OSDN Git Service

b575734f2251729e26297427bed7b309ad3b2f10
[trx-305dsp/dsp.git] / trx305 / kernel / cfg / jsp / jsp_parser.cpp
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
13  *  利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  * 
31  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: jsp_parser.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/jsp/jsp_parser.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
40
41 #include <stdarg.h>
42
43 #include "jsp/jsp_defs.h"
44 #include "base/parser.h"
45 #include "base/mpstrstream.h"
46 #include "jsp/jsp_common.h"
47
48 #include <set>
49 #include <map>
50 #include <cctype>
51 #include <algorithm>
52 #include <iomanip>
53
54 using namespace ToppersJsp;
55 using namespace std;
56
57 class CoreParser : public ParserComponent
58 {
59 protected:
60     virtual void parseOption(Directory &);
61             void outputContainer(Directory & container) throw();
62             void assignID(Directory & container) throw();
63
64 public:
65     CoreParser(void);
66     virtual bool parse(Parser & p, Directory & container);
67 } instance_of_Parser;
68
69 CoreParser::CoreParser(void)
70 {
71     setBanner("=== TOPPERS/JSP Kernel Configurator ver.9.4 (for JSP rel 1.4) ===");
72 }
73
74 void CoreParser::parseOption(Directory & container)
75 {
76     ParserComponent::parseOption(container);
77
78     if(findOption("h","help"))
79     {
80         cerr << Message(
81             "  -obj, --dump-object=filename : Dump the object tree into the file specified\n"
82             "  -ao, --assign-order=order : Specify the order of automatic ID assignment\n"
83             "    You can use three terms below as ordering rule.\n"
84             "     alphabetic (in alphabetic order)\n"
85             "     fcfs       (in arrival order [as default])\n"
86             "     reverse    (reverse the order)\n"
87             "  -var, --variable-id : Prepare ID-variable for storing its identifier number\n",
88             "  -obj, --dump-object=ファイル名 : 指定したファイルにオブジェクト情報を出力します\n"
89             "  -ao, --assign-order=順序 : 自動ID割当の割当順序を指定します\n"
90             "    割当順序は次の3つの組合せで指定します.\n"
91             "     alphabetic (ABC順), fcfs (宣言順 [デフォルト]), reverse (逆順)\n"
92             "  -var, --variable-id : ID番号を格納する変数を用意します");
93         return;
94     }
95
96     checkOption("D","dump");
97     checkOption("cpu","cpu");
98     checkOption("system","system");
99     checkOption("var","variable-id");
100 }
101
102 namespace {
103     int displayHandler(Directory & container, const char * category, const char * format)
104     {
105         Directory * node  = 0;
106         Directory * scope = 0;
107
108         node = container.findChild(OBJECTTREE,category,NULL);
109         if(node == 0 || node->size() == 0)
110         return 0;
111
112         VerboseMessage("Handler assignment list [%]\n","ハンドラ割付表 [%]\n") << category;
113
114         scope = node->getFirstChild();
115         while(scope != 0)
116         {
117         VerboseMessage::getStream() << scope->format(format);
118         scope = scope->getNext();
119         }
120
121         return node->size();
122     }
123
124     //マクロ化されたtoupperを関数化する (STL-algorithm用)
125     int toupper_function(int c)
126     { return toupper(c); }
127 }
128 /*
129  *  outputContainer - デバッグ時 or ダンプ指定時にオブジェクト情報を所定のファイル形式で出力する
130  */
131 void CoreParser::outputContainer(Directory & container) throw()
132 {
133     try {
134
135         if(findOption("D","dump") || findOption("debug","debug")) {
136             fstream file("container.txt", ios::out);
137             container.drawTree(&file);
138             file.close();
139         }
140
141         if(findOption("Dx","dump-xml") || findOption("debug","debug")) {
142             fstream file("container.xml", ios::out);
143             container.drawTree_byXML(&file);
144             file.close();
145         }
146     }
147     catch (...) {
148     }
149 }
150
151 /*
152  *  assignID - オブジェクトに対してIDを割り付ける
153  *             取り込んだオブジェクト名をユーザに提示する
154  */
155 void CoreParser::assignID(Directory & container) throw()
156 {
157     multimap<int, const char *> sorter;
158     multimap<int, const char *>::iterator scope;
159     enum Common::tagAssignmentOrder order = Common::FCFS;
160
161     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" TASK].size(), TASK));
162     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" SEMAPHORE].size(), SEMAPHORE));
163     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" EVENTFLAG].size(), EVENTFLAG));
164     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" DATAQUEUE].size(), DATAQUEUE));
165     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" MAILBOX].size(), MAILBOX));
166     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" FIXEDSIZEMEMORYPOOL].size(), FIXEDSIZEMEMORYPOOL));
167     sorter.insert(pair<int, const char *>(container[OBJECTTREE "/" CYCLICHANDLER].size(), CYCLICHANDLER));
168
169     order = Common::parseOrder(getOption("ao", "assign-order"));
170     scope = sorter.begin();
171     while(scope != sorter.end())
172     {
173         if( (*scope).first != 0 )
174             Common::assignID(container, (*scope).second, OBJECTTREE, order);
175         ++ scope;
176     }
177
178     displayHandler(container, INTERRUPTHANDLER, "  $@ : $(inthdr)\n");
179     displayHandler(container, EXCEPTIONHANDLER, "  $@ : $(exchdr)\n");
180     displayHandler(container, INITIALIZER, "  $@ : $(inirtn)($(exinf))\n");
181     displayHandler(container, TERMINATOR, "  $@ : $(terrtn)($(exinf))\n");
182 }
183
184
185 bool CoreParser::parse(Parser & p, Directory & container)
186 {
187     Token token;
188     string work;
189     bool isParseErrorOccured;
190
191     if(findOption("cpu","cpu", &work))
192         container["/cpu"] = work;
193     
194     try{
195         isParseErrorOccured = false;
196         do {
197             p.getToken(token);
198             if(token == Token::IDENTIFIER)
199             {
200                     /* エラーが起きても極力続けたいので、
201                         起きたことだけ覚えておいてどんどん続ける */
202                 try 
203                 {   this->parseStaticAPI(p, container, token);  }
204                 catch(...)
205                 {   isParseErrorOccured = true;                 }
206
207             }
208         }while(token != Token::EOS);
209
210         p.setLogBuffer(NULL);
211
212         if(isParseErrorOccured)
213             ExceptionMessage(ExceptionMessage::FATAL,"The configuration process was aborted due to occurence of parse error","構文解析に失敗したため処理を中断します").throwException();
214
215         if(container[OBJECTTREE "/" TASK].size() == 0)
216             ExceptionMessage("Kernel requires one or more task objects.","タスクオブジェクトがありません").throwException();
217
218             /* ID割付 & オブジェクト名表示 */
219         assignID(container);
220
221             /* オブジェクト情報をファイルに出力 */
222         outputContainer(container);
223
224         return true;
225     }
226     catch(Exception &)
227     {
228             /* 例外を投げなおす前に 現在のオブジェクト情報を格納する */
229         outputContainer(container);
230         throw;
231     }
232 }
233
234 /* ======================================================================== */
235
236 DECLARE_DIRECTIVE(assigner,"assign_id")
237 {
238     Token name;
239     Token value;
240
241     p.getToken(name, Token::IDENTIFIER);
242     p.getToken(value, Token::INTEGER);
243
244     if(value.value <= 0)
245         ExceptionMessage("Cannot assign an ID number less or equal to 0.","0以下のID番号を設定することはできません").throwException();
246
247     *container.openChild("/","identifier",name.c_str(),NULL) = value.value;
248 }
249
250 DECLARE_DIRECTIVE(parameter,"parameter")
251 {
252     Token token;
253     string key;
254     string::size_type i,j;
255
256     do {
257         p.getToken(token);
258         if(!(token == Token::STRINGLITERAL))
259             ExceptionMessage("parameter pragma requires additional parameter put in '\"...\"'","parameterプラグマには\"...\"で括られた追加パラメータが必要です").throwException();
260
261         token.chopLiteral();
262
263         if(token[0] == '-')
264         {
265             i = token.find_first_of('=');
266             j = token.find_first_not_of('-');
267             if(i == j || j == string::npos)
268                 ExceptionMessage(ExceptionMessage::FATAL,"Wrong option [%]","不正なオプション [%]") << token << throwException;
269
270             if(i != string::npos)
271             {
272                 key = DEFAULT_PARAMETER;
273                 *container.openChild(string("/Parameter/") + token.substr(1, i-1)) = token.substr(i+1);
274             }
275             else
276             {
277                 key = token.substr(1);
278                 *container.openChild(string("/Parameter/") + key) = string("");
279             }
280         }else
281             *container.openChild(string("/Parameter/") + key) = token;
282
283         p.getToken(token);
284     } while(token.compare(",") == 0);
285
286     p.putBack(token);
287 }
288
289
290 /* ======================================================================== */
291 class ConfigurationFileGenerator : public Component
292 {
293 protected:
294     bool backward_compatible;
295     bool libstyle_include;
296     bool restrict_zero;
297     bool def_prototype;
298
299     enum tagDefinition { HEADER=1, TNUM=2, BUFFER=4, DEFINITION=8, CONTROLBLOCK=16, SHORT_ID=32, TNUMNO=64, INIT=128, PROTOTYPE=256, INITLIST=512 };
300     void createObjectDefinition(MultipartStream *, Directory &, int, ...);
301
302     virtual void parseOption(Directory &);
303     virtual void body(Directory &);
304     virtual void onFatalExit(Directory &);
305
306 public:
307     ConfigurationFileGenerator(void) : Component(CODEGENERATOR) {};
308 } instance_of_Configurator;
309
310
311
312 namespace {
313
314         //ファイル名の取得
315     string get_filename(string category, string _default) throw(Exception)
316     {
317         string result(_default);
318         OptionParameter::OptionItem item = getOptionParameter()[category];
319
320         if(item.isValid()) {
321             if(item.countParameter() == 1)
322                 result = item[0];
323             else
324                 ExceptionMessage("-% should have just ONE filename.","-%オプションに指定できるファイルは1つのみ") << category << throwException;
325         }
326
327         if(result.empty())
328             ExceptionMessage("-% has illegal file name.","-%オプションに渡されたファイル名は不正") << category << throwException;
329         
330         return result;
331     }
332
333         // カーネル構成ファイルの生成
334     KernelCfg * createKernelCfg(void)
335     {
336         KernelCfg * cfg;
337
338         cfg = KernelCfg::createInstance(get_filename("kernel_cfg","kernel_cfg.c"));
339         cfg->disableOutput();       //処理が完了するまで出力させない
340
341             //基本的なオブジェクトの格納場所はここで指定しておく
342         cfg->createPart("header")
343             .createPart("include")
344             .createPart(IDENTIFIER_VARIABLE)
345             .createPart(TASK)
346             .createPart(SEMAPHORE)
347             .createPart(EVENTFLAG)
348             .createPart(DATAQUEUE)
349             .createPart(MAILBOX)
350             .createPart(FIXEDSIZEMEMORYPOOL)
351             .createPart(CYCLICHANDLER)
352             .createPart(INTERRUPTHANDLER)
353             .createPart(EXCEPTIONHANDLER)
354             .createPart(INITIALIZER)
355             .createPart(OBJECT_INITIALIZER)
356             .createPart("others");
357
358             //カーネル構成ファイル生成イベントの実行
359         KernelCfg::CreationEvent ev;
360         ev.file = cfg;
361         Event<KernelCfg::CreationEvent>::raise(ev);
362
363             //エラーチェック
364         if(ev.file == 0)
365             ExceptionMessage("Internal error : kernel_cfg event handler eliminates the instance.","内部エラー : kernel_cfgのハンドラがインスタンスを削除した") << throwException;
366         if(RuntimeObjectTable::getInstance(typeid(KernelCfg)) != ev.file)
367             ExceptionMessage("Internal error : kernel_cfg event handler creates the illegal instance.","内部エラー : kernel_cfgのハンドラが不正なインスタンスを生成した") << throwException;
368
369         return ev.file; //cfgではダメ
370     }
371
372         //ファイル名から衝突回避用の名前を生成する
373     string convert_filename_to_definition(string filename)
374     {
375         string result;
376         string::iterator scope;
377
378         scope = filename.begin();
379         while(scope != filename.end()) {
380             if(isalnum(*scope))
381                 result += static_cast<char>(toupper(*scope));
382             else
383                 result += '_';
384             ++ scope;
385         }
386
387         return result;
388     }
389
390         //自動ID割付結果ファイルの生成
391     KernelID * createKernelID(void)
392     {
393         KernelID * id = 0;
394
395         id = KernelID::createInstance(get_filename("kernel_id","kernel_id.h"));
396         id->disableOutput();
397
398             //基本的なオブジェクトの格納場所はここで指定しておく
399         id-> createPart("__header__")
400             .createPart("body")
401             .createPart("__footer__");
402
403             //ファイル生成イベントの実行
404         KernelID::CreationEvent ev;
405         ev.file = id;
406         Event<KernelID::CreationEvent>::raise(ev);
407
408             //エラーチェック
409         if(ev.file == 0)
410             ExceptionMessage("Internal error : kernel_id event handler eliminates the instance.","内部エラー : kernel_idのハンドラがインスタンスを削除した") << throwException;
411         if(RuntimeObjectTable::getInstance(typeid(KernelID)) != ev.file)
412             ExceptionMessage("Internal error : kernel_id event handler creates the illegal instance.","内部エラー : kernel_idのハンドラが不正なインスタンスを生成した") << throwException;
413
414             //多重インクルード回避用定義の追加
415         string defname = convert_filename_to_definition(id->getFilename());
416         id->movePart("__header__");
417         (*id)   // << get_agreement(id->getFilename())      //文言の付与
418                 << "#ifndef " << defname << '\n'        //#ifndef KERNELID_H
419                 << "#define " << defname << "\n\n";     //#define KERNELID_H
420         
421         id->movePart("__footer__");
422         (*id)   << "\n#endif /* " << defname << " */\n\n";          //#endif /* KERNELID_H */
423
424         return ev.file; //idではダメ
425     }
426
427         //登録されている文字の最大長を得る
428     unsigned int countLongestSymbolName(const std::map<std::string, int> & identifiers) throw()
429     {
430         unsigned int max_length = 0;
431         std::map<std::string, int>::const_iterator scope;
432
433             // もっとも長い名前を持つシンボル名を検索
434         scope = identifiers.begin();
435         while(scope != identifiers.end()) {
436             if(max_length < scope->first.size())
437                 max_length = scope->first.size();
438             ++ scope;
439         }
440
441         return max_length;
442     }
443
444         //自動ID割付結果出力 (これまでとの互換モード)
445     void serializeIdentifiers_defineStyle(KernelID * out, std::map<std::string, int> & identifier_pool)
446     {
447         std::map<std::string, int>::const_iterator scope;
448         string::size_type max_length;
449
450         (*out) << "\t/* object identifier deifnition */\n\n";
451
452             // もっとも長い名前を持つシンボル名を検索
453         max_length = countLongestSymbolName(identifier_pool);
454
455         scope = identifier_pool.begin();
456         while(scope != identifier_pool.end()) {
457             (*out)  << "#define " << scope->first 
458                     << string(max_length - scope->first.size() + 4, ' ')    //値をそろえる
459                     << setw(3)
460                     << scope->second << '\n';
461             ++ scope;
462         }
463     }
464
465         //自動ID割付結果出力 (定数変数格納方式)
466     void serializeIdentifiers_variableStyle(KernelID * id, std::map<std::string, int> & identifier) throw(Exception)
467     {
468         std::map<std::string, int>::const_iterator scope;
469         string::size_type max_length;
470         KernelCfg * cfg = getRuntimeObjectInstance(KernelCfg);
471
472             /* kernel_id.hに出力 */
473
474         (*id) << "#ifdef __cplusplus\n"
475                  "#define KERNELID_EXPORT extern \"C\"\n"
476                  "#else\n"
477                  "#define KERNELID_EXPORT extern\n"
478                  "#endif\n\n";
479
480             // もっとも長い名前を持つシンボル名を検索
481         max_length = countLongestSymbolName(identifier);
482
483         scope = identifier.begin();
484         while(scope != identifier.end()) {
485             (*id) << "KERNELID_EXPORT const int "
486                   << scope->first
487                   << ";\n";
488
489             ++ scope;
490         }
491
492         (*id) << "\n#undef KERNELID_EXPORT\n\n";
493
494             /* kernel_cfg.cに定数定義を出力 */
495
496         cfg->movePart(IDENTIFIER_VARIABLE);
497         (*cfg) << "\t/* Identifier storage variables */\n";
498         scope = identifier.begin();
499         while(scope != identifier.end()) {
500             (*cfg) << "const int " 
501                   << scope->first
502                   << string(max_length - scope->first.size() + 4, ' ')
503                   << " = "
504                   << scope->second << ";\n";
505             ++ scope;
506         }
507     }
508
509         //自動ID割付結果出力 (併用方式 - (toppers-dev 28))
510     void serializeIdentifiers_blendedStyle(KernelID * id, std::map<std::string, int> & identifier) throw(Exception)
511     {
512         /* kernel_id.hへの出力は従来と同じ */
513         serializeIdentifiers_defineStyle(id, identifier);
514
515             /* kernel_cfg.cに定数定義を出力 */
516
517         std::map<std::string, int>::const_iterator scope;
518         string::size_type max_length;
519         KernelCfg * cfg = getRuntimeObjectInstance(KernelCfg);
520
521         max_length = countLongestSymbolName(identifier);
522
523         cfg->movePart(IDENTIFIER_VARIABLE);
524         (*cfg) << "\t/* Identifier storage variables */\n";
525         scope = identifier.begin();
526         while(scope != identifier.end()) {
527             (*cfg) << "const int " 
528                   << scope->first
529                   << "_id"
530                   << string(max_length - scope->first.size() + 1, ' ')
531                   << " = "
532                   << scope->second << ";\n";
533             ++ scope;
534         }
535     }
536
537         //自動ID割付結果の出力
538     void serializeIdentifiers(bool varid_style = false) throw(Exception)
539     {
540         KernelID * out = getRuntimeObjectInstance(KernelID);
541         std::map<std::string, int> identifier_pool;
542
543             //識別子プールを生成
544         {
545             Directory * scope = Singleton<Directory>::getInstance()->findChild("/identifier")->getFirstChild();
546             while(scope != 0)
547             {
548                 identifier_pool[scope->getKey()] = scope->toInteger();
549                 scope = scope->getNext();
550             }
551         }
552
553             //割付結果の出力
554         out->movePart("body");
555         if(varid_style) {
556             serializeIdentifiers_blendedStyle(out, identifier_pool);
557 //            serializeIdentifiers_variableStyle(out, identifier_pool);
558         }
559         else {
560             serializeIdentifiers_defineStyle(out, identifier_pool);
561         }
562
563         out->enableOutput();
564     }
565
566     void serializeConfiguration_headerPart(KernelCfg & out) throw(Exception)
567     {
568         const bool backward_compatible = getOptionParameter()["1.3"].isValid();
569         
570             //頭の部分の出力
571         out.movePart("header");
572
573         out // << get_agreement(out.getFilename())          //文言の添付
574             << "/* Configured with ["                   //コンフィギュレーションオプションを出力しておく
575             << getOptionParameter().getCommandLine() 
576             << "] */\n\n";
577
578             //1.4以降はkernel_cfg.hを使用
579         if(!backward_compatible)
580             out << "#include " << conv_includefile("kernel_cfg.h") << '\n';
581
582             //kernel_id.hのinclude (kernel_idはダブルクォートでくくる)
583         out << "#include \"" << dynamic_cast<KernelID *>(RuntimeObjectTable::getInstance(typeid(KernelID)))->getFilename() <<"\"\n" 
584             << '\n';
585
586
587             //CFG_INT/EXCHDR_ENTRY
588             // Q: "<<"があったりなかったりするのはなぜ? A: 2行目から5行目まではelseブロックで出力している内容とまったく同じ。こうすればコンパイラによってはシュリンクされて一つになるし、可読性も悪くならない。
589         if(backward_compatible) {
590             out << "#if TKERNEL_PRVER >= 0x1040\n"
591                 << "#error \"This configuration file has no compatibility with"
592                 << " TOPPERS/JSP rel 1.4 or later version.\"\n"
593                    "#elif TKERNEL_PRVER >= 0x1011\n"
594                 << "#define CFG_INTHDR_ENTRY(inthdr) INTHDR_ENTRY(inthdr)\n"
595                    "#define CFG_EXCHDR_ENTRY(exchdr) EXCHDR_ENTRY(exchdr)\n"
596                    "#define CFG_INT_ENTRY(inthdr) INT_ENTRY(inthdr)\n"
597                    "#define CFG_EXC_ENTRY(exchdr) EXC_ENTRY(exchdr)\n"
598                 << "#else\n"
599                 << "#define CFG_INTHDR_ENTRY(inthdr) INTHDR_ENTRY(ENTRY(inthdr), inthdr)\n"
600                    "#define CFG_EXCHDR_ENTRY(exchdr) EXCHDR_ENTRY(ENTRY(exchdr), exchdr)\n"
601                    "#define CFG_INT_ENTRY(inthdr) ENTRY(inthdr)\n"
602                    "#define CFG_EXC_ENTRY(exchdr) ENTRY(exchdr)\n"
603                 << "#endif\n\n";
604         }
605         else {
606             out << "#if TKERNEL_PRVER >= 0x1040\n"
607                 << "#define CFG_INTHDR_ENTRY(inthdr) INTHDR_ENTRY(inthdr)\n"
608                    "#define CFG_EXCHDR_ENTRY(exchdr) EXCHDR_ENTRY(exchdr)\n"
609                    "#define CFG_INT_ENTRY(inthdr) INT_ENTRY(inthdr)\n"
610                    "#define CFG_EXC_ENTRY(exchdr) EXC_ENTRY(exchdr)\n"
611                 << "#else\n"
612                 << "#error \"This configuration file has no compatibility with"
613                 << " TOPPERS/JSP rel 1.3 or earlier.\"\n"
614                 << "#endif\n\n";
615         }
616
617             //__EMPTY_LABELマクロの出力
618         if(!getOptionParameter()["z"].isValid()) {
619             
620             string zeromacro;
621
622             if(getOptionParameter()["ZERO"].isValid())
623                 zeromacro = getOptionParameter()["ZERO"][0];
624             else
625                 zeromacro.assign("x y[0]");
626
627             out <<  "#ifndef __EMPTY_LABEL\n"
628                     "#define __EMPTY_LABEL(x,y) " << zeromacro << "\n"
629                     "#endif\n\n";
630         }
631
632             /* PRIDのチェック */
633         out << "#if TKERNEL_PRID != 0x0001u /* TOPPERS/JSP */\n"
634                "#error \"You can not use this configuration file without TOPPERS/JSP\"\n"
635                "#endif\n\n";
636     }
637 }
638
639 void ConfigurationFileGenerator::parseOption(Directory & parameter)
640 {
641     string work;
642
643     if(findOption("h","help"))
644     {
645         cerr << endl << Message(
646             "Kernel configuration file generator\n"
647             "  -id, --kernel_id=filename  : Specify the name of ID assignment file\n"
648             "  -cfg,--kernel_cfg=filename : Specify the name of kernel configuration file\n"
649             "  -il, --include-libstyle    : Use #include <...> style for kernel headers\n"
650             "  -oproto, --output-prototype: Output task prototype definitions in kernel_cfg\n"
651             "  -z, --nonzero              : Do not output __EMPTY_LABEL macro and related definitions\n"
652             "  -1.3  : Generates kernel_cfg.c for TOPPERS/JSP rel 1.3\n",
653             "カーネル構成ファイルの生成\n"
654             "  -id, --kernel_id=ファイル名  : ID割当ファイルの名前を指定します\n"
655             "  -cfg,--kernel_cfg=ファイル名 : カーネル構成ファイルの名前を指定します\n"
656             "  -il, --include-libstyle      : カーネルのヘッダファイルを<...>の形で出力します\n"
657             "  -oproto, --output-prototype  : タスク本体などの定義をkernel_cfg.cに生成します\n"
658             "  -z, --nonzero                : __EMPTY_LABELマクロの使用を制限します\n"
659             "  -1.3  : TOPPERS/JSP rel 1.3 用のコンフィギュレーションファイルを生成します\n");
660         return;
661     }
662
663     checkOption("cfg","cfg");
664     checkOption("id","id");
665
666         /*
667          *  カーネルコンフィギュレーション結果のファイル (kernel_cfg.c) の初期設定
668          */
669
670     createKernelCfg();
671
672         /*
673          *  ID割付結果のファイル (kernel_id.h) の初期設定
674          */
675
676     createKernelID();
677
678         /* その他オプション */
679     restrict_zero = findOption("z","zero");
680     def_prototype = findOption("oproto","output-prototype");
681     libstyle_include = findOption("il","include-libstyle");
682     backward_compatible = findOption("1.3","1.3");
683     
684     checkOption("mcfg","minimize-cfg");
685     checkOption("ZERO","ZERO");
686     checkOption("obj", "dump-object");
687     checkOption("ext");
688
689     activateComponent();
690 }
691
692 void ConfigurationFileGenerator::onFatalExit(Directory & container)
693 {
694         //例外で異常終了したら、ファイルを生成しない
695     dynamic_cast<MultipartStream *>(RuntimeObjectTable::getInstance(typeid(KernelCfg)))->disableOutput();
696     dynamic_cast<MultipartStream *>(RuntimeObjectTable::getInstance(typeid(KernelID)))->disableOutput();
697 }
698
699 void ConfigurationFileGenerator::createObjectDefinition(MultipartStream * out, Directory & container, int flag, ...)
700 {
701     Directory * scope;
702     const char * buffer;
703     string work;
704
705     map<int, Directory *> sorter;
706     map<int, Directory *>::iterator psorter;
707
708     va_list vl;
709     int i;
710
711     Directory & id = container[string(PREFIX "/") + container.getKey().c_str()];
712
713     if(container.size() == 0 && findOption("mcfg","minimize-cfg"))
714     {
715         if(!getOptionParameter().find("ext"))
716             ExceptionMessage("Use of the extended option --minimize-cfg. Please use -ext option together.","--minimizeオプションは拡張機能です。使用するには-extを指定してください。").throwException();
717         return;
718     }
719     va_start(vl, flag);
720
721
722         //必要な情報の作成
723     work = string(va_arg(vl, const char *));
724     id["id"]  = work;
725     transform(work.begin(), work.end(), work.begin(), toupper_function);
726     id["ID"]  = work;
727     
728
729     if((flag & SHORT_ID) != 0)
730     {
731         work = string(va_arg(vl, const char *));
732         id["sid"]  = work;
733     for(i=0; i<(signed)work.size(); i++) {
734       if (work[i] >= 'a' && work[i] <= 'z')
735         work[i] = work[i] - 'a' + 'A';
736     }
737         id["SID"]  = work;
738     }else
739     {
740         id["sid"] = id["id"].toString();
741         id["SID"] = id["ID"].toString();
742     }
743
744     if(!backward_compatible)
745         id["symbolprefix"] = "_kernel_";
746
747     work = container.getKey();
748     id["name"] = work;
749     out->movePart(work);
750
751         //オブジェクト初期化関数を追加
752     if((flag & INIT) != 0 && container.size() != 0)
753         container["/" OBJECT_INITIALIZER].addChild(new Directory(work));
754
755     (*out) << "\n\t/* " << (Message("Object initializer [%]","オブジェクト初期化ブロック [%]") << work) << " */\n\n";
756
757     if(((flag & HEADER) != 0) && backward_compatible)
758         (*out) << "#include " << conv_includefile(work) << "\n\n";
759
760     if((flag & TNUM) != 0)
761     {
762         (*out) << id.format("#define TNUM_$(ID)ID ") << container.size() << "\n\n";
763         (*out) << id.format("const ID $(symbolprefix,)tmax_$(id)id = (TMIN_$(ID)ID + TNUM_$(ID)ID - 1);\n\n");
764     }
765
766     if((flag & TNUMNO) != 0)
767     {
768         (*out) << id.format("#define TNUM_$(ID)NO ") << container.size() << "\n\n";
769         (*out) << id.format("const UINT $(symbolprefix,)tnum_$(id)no = TNUM_$(ID)NO;\n\n");
770     }
771
772         /* ID順にソート (この時点で連番が確定しているはずなので,チェックはしない) */
773     if((flag & (BUFFER|DEFINITION)) != 0)
774     {
775         const bool is_identifier = (flag & TNUMNO) == 0;
776
777         i = 0;
778         scope = container.getFirstChild();
779         while(scope != 0)
780         {
781             if(is_identifier)
782                 sorter[scope->toInteger(i++)] = scope;
783             else
784                 sorter[i++] = scope;
785
786             scope = scope->getNext();
787         }
788     }
789
790         //プロトタイプ定義の出力
791     if((flag & PROTOTYPE) != 0)
792     {
793         buffer = va_arg(vl, const char *);
794
795         if(def_prototype)
796         {
797             set<string> func;
798             set<string>::iterator pfunc;
799
800             scope = container.getFirstChild();
801             while(scope != NULL)
802             {
803                 func.insert(scope->format(buffer));
804                 scope = scope->getNext();
805             }
806
807             pfunc = func.begin();
808             while(pfunc != func.end())
809             {
810                 (*out) << (*pfunc) << '\n';
811                 ++ pfunc;
812             }
813         }
814     }
815
816         //バッファの作成
817     if((flag & BUFFER) != 0 && container.size() != 0)
818     {
819         buffer = va_arg(vl, const char *);
820         psorter = sorter.begin();
821         while(psorter != sorter.end())
822         {
823             (*out) << (*psorter).second->format(buffer) << '\n';
824             ++ psorter;
825         }
826         (*out) << '\n';
827     }
828
829         //定義ブロック(xINIB)の出力
830     if((flag & DEFINITION) != 0)
831     {
832         buffer = va_arg(vl, const char *);
833         if(container.size() != 0)
834         {
835             (*out) << id.format("const $(SID)INIB $(symbolprefix,)$(sid)inib_table[TNUM_$(ID)") << ( (flag & TNUMNO) != 0  ? "NO" : "ID") << "] = {\n";
836             psorter = sorter.begin();
837             while(psorter != sorter.end())
838             {
839                 (*out) << "\t{" << (*psorter).second->format(buffer) << '}';
840                 ++ psorter;
841                 if(psorter != sorter.end())
842                     (*out) << ',';
843                 (*out) << '\n';
844             }
845             (*out) << "};\n\n";
846         }else
847             if( !restrict_zero )
848                 (*out) << id.format("__EMPTY_LABEL(const $(SID)INIB, $(symbolprefix,)$(sid)inib_table);\n");
849     }
850
851     if((flag & INITLIST) != 0)
852     {
853         Directory * node;
854
855             /* 宣言順でID番号をソート */
856         sorter.clear();
857         node = container.getFirstChild();
858         while(node != NULL)
859         {
860             sorter.insert(pair<int,Directory*>(node->findChild("#order")->toInteger(), node));
861             node = node->getNext();
862         }
863
864         *out << id.format("const ID $(symbolprefix,)$(sid)order_table[TNUM_$(ID)ID] = {");
865         psorter = sorter.begin();
866         while(psorter != sorter.end())
867         {
868             *out << psorter->second->toInteger();
869             ++ psorter;
870             if(psorter != sorter.end())
871                 *out << ',';
872         }
873         *out << "};\n\n";
874     }
875
876         //制御ブロック(xCB)の出力
877     if((flag & CONTROLBLOCK) != 0)
878     {
879         if(container.size() != 0)
880             (*out) << id.format("$(SID)CB $(symbolprefix,)$(sid)cb_table[TNUM_$(ID)ID];\n\n");
881         else
882             if( !restrict_zero )
883                 (*out) << id.format("__EMPTY_LABEL($(SID)CB, $(symbolprefix,)$(sid)cb_table);\n\n");
884     }
885 }
886
887 void ConfigurationFileGenerator::body(Directory & container)
888 {
889     Directory * scope;
890     KernelCfg * out;
891     string work;
892     const bool varid_style = findOption("var","variable-id");
893
894         /* kernel_id.hの出力 */
895     serializeIdentifiers(varid_style);
896
897         /* kernel_cfg.cの出力 */
898     out = dynamic_cast<KernelCfg *>(RuntimeObjectTable::getInstance(typeid(KernelCfg)));
899     if(out == 0) {
900         ExceptionMessage("[Internal error] The stream buffer of kernel_cfg disappeared.","[内部エラー] ファイルストリームが開けません (kernel_cfg.c)").throwException();
901         return;
902     }
903
904         /* 頭の定義部分の作成 */
905     serializeConfiguration_headerPart(*out);
906
907         /* INCLUDE */
908     out->movePart(INCLUDEFILE);
909     scope = container(OBJECTTREE "/" INCLUDEFILE)->getFirstChild();
910     (*out) << "\t/* " << Message("User specified include files","ユーザ定義のインクルードファイル") << "*/\n";
911     while(scope != 0)
912     {
913         (*out) << "#include " << scope->toString() << '\n';
914         scope = scope->getNext();
915     }
916     (*out) << '\n';
917
918         /* TASK */
919     work.assign("$(tskatr), (VP_INT)($(exinf)), (FP)($(task)), INT_PRIORITY($(itskpri)), __TROUND_STK_UNIT($(stksz)), __stack_$@, $(texatr), (FP)($(texrtn))");
920     if(container["/cpu"].toString().compare("nios32") == 0)
921         work += ", $(hi_limit), $(lo_limit)";
922     createObjectDefinition(out, container[OBJECTTREE "/" TASK], HEADER|TNUM|SHORT_ID|BUFFER|DEFINITION|CONTROLBLOCK|INIT|PROTOTYPE|INITLIST,"tsk", "t", "void $(task)(VP_INT exinf);", "static __STK_UNIT __stack_$@[__TCOUNT_STK_UNIT($(stksz))];",work.c_str());
923
924         /* SEMAPHORE */
925     createObjectDefinition(out, container[OBJECTTREE "/" SEMAPHORE], HEADER|TNUM|DEFINITION|CONTROLBLOCK|INIT,"sem", "$(sematr), $(isemcnt), $(maxsem)");
926
927         /* EVENTFLAG */
928     createObjectDefinition(out, container[OBJECTTREE "/" EVENTFLAG], HEADER|TNUM|DEFINITION|CONTROLBLOCK|INIT,"flg", "$(flgatr), $(iflgptn)");
929
930         /* DATAQUEUE */
931     createObjectDefinition(out, container[OBJECTTREE "/" DATAQUEUE], HEADER|TNUM|BUFFER|DEFINITION|CONTROLBLOCK|INIT,"dtq", "#if ($(dtqcnt)) > 0\n  static VP_INT __dataqueue_$@[$(dtqcnt)];\n#else\n  #define __dataqueue_$@ NULL\n#endif","$(dtqatr), $(dtqcnt), __dataqueue_$@");
932
933         /* MAILBOX */
934     createObjectDefinition(out, container[OBJECTTREE "/" MAILBOX], HEADER|TNUM|DEFINITION|CONTROLBLOCK|INIT,"mbx","$(mbxatr), $(maxmpri)");
935
936         /* FIXEDSIZEMEMORYPOOL */
937     createObjectDefinition(out, container[OBJECTTREE "/" FIXEDSIZEMEMORYPOOL], HEADER|TNUM|BUFFER|DEFINITION|CONTROLBLOCK|INIT,"mpf","static __MPF_UNIT __fixedsize_memorypool_$@[__TCOUNT_MPF_UNIT($(blksz)) * (($(blkcnt)))];","$(mpfatr), __TROUND_MPF_UNIT($(blksz)), __fixedsize_memorypool_$@, (VP)((VB *)__fixedsize_memorypool_$@ + sizeof(__fixedsize_memorypool_$@))");
938
939         /* CYCLICHANDLER */
940     createObjectDefinition(out, container[OBJECTTREE "/" CYCLICHANDLER], HEADER|TNUM|DEFINITION|CONTROLBLOCK|INIT|PROTOTYPE,"cyc","void $(cychdr)(VP_INT exinf);","$(cycatr),$(exinf),(FP)($(cychdr)),$(cyctim),$(cycphs)");
941
942         /* INTERRUPTHANDLER */
943     createObjectDefinition(out, container[OBJECTTREE "/" INTERRUPTHANDLER], HEADER|BUFFER|TNUMNO|DEFINITION|INIT|PROTOTYPE,"inh","void $(inthdr)(void);","CFG_INTHDR_ENTRY($(inthdr));","$@,$(inhatr),(FP)CFG_INT_ENTRY($(inthdr))");
944
945         /* EXCEPTIONHANDLER */
946     createObjectDefinition(out, container[OBJECTTREE "/" EXCEPTIONHANDLER], HEADER|BUFFER|TNUMNO|DEFINITION|INIT|PROTOTYPE,"exc","void $(exchdr)(VP p_excinf);","CFG_EXCHDR_ENTRY($(exchdr));","$@,$(excatr),(FP)CFG_EXC_ENTRY($(exchdr))");
947
948
949         /* オブジェクト初期化ルーチン */
950     out->movePart(OBJECT_INITIALIZER);
951     (*out) << "\t/* " << Message("Object initialization routine","オブジェクト初期化ルーチン") << " */\n\n";
952     (*out) << "void\n" << conv_kernelobject("object_initialize") << "(void)\n{\n";
953     scope = container["/" OBJECT_INITIALIZER].getFirstChild();
954     while(scope != 0)
955     {
956         (*out) << '\t' << conv_kernelobject(scope->toString() + "_initialize") << "();\n";
957         scope = scope->getNext();
958     }
959     (*out) << "}\n\n";
960
961
962         /* 初期化ハンドラ */
963     out->movePart(INITIALIZER);
964     (*out) << "\t/* " << Message("Initialization handler","初期化ハンドラ起動ルーチン") << " */\n\n";
965     (*out) << "void\n" << conv_kernelobject("call_inirtn") << "(void)\n{\n";
966     scope = container[OBJECTTREE "/" INITIALIZER].getFirstChild();
967     while(scope != 0)
968     {
969         (*out) << scope->format("\t$(inirtn)( (VP_INT)($(exinf)) );\n");
970         scope = scope->getNext();
971     }
972     (*out) << "}\n\n";
973
974         /* 終了ハンドラ */
975     scope = container[OBJECTTREE "/"  TERMINATOR].getLastChild();
976     if(!backward_compatible) {
977         (*out) << "void\n" << conv_kernelobject("call_terrtn") << "(void)\n{\n";
978         while(scope != 0)
979         {
980             (*out) << scope->format("\t$(terrtn)( (VP_INT)($(exinf)) );\n");
981             scope = scope->getPrev();
982         }
983         (*out) << "}\n\n";
984     }
985     else {
986         if(scope->size() != 0)
987             ExceptionMessage("VATT_TER is not supported for TOPPERS/JSP rel 1.3 or earlier.",
988                              "VATT_TERはTOPPERS/JSP rel 1.3以前ではサポートされません").throwException();
989     }
990
991     out->movePart("others");
992     (*out) << "TMEVTN   " << conv_kernelobject("tmevt_heap") << "[TNUM_TSKID + TNUM_CYCID];\n\n";
993
994     container["/object_initializer"].erase();
995
996     string filename;
997     if(findOption("obj","dump-object",&filename))
998     {
999         if(filename.empty())
1000             filename.assign("kernel_obj.dat");
1001
1002         fstream f(filename.c_str(),ios::out|ios::binary);
1003         if(f.is_open())
1004         {
1005             container[OBJECTTREE].Store(&f);
1006             f.close();
1007         }else
1008             ExceptionMessage(" Failed to open the file % for storing object definitions"," オブジェクト情報を格納するためのファイル(%)が開けません") << filename << throwException;
1009     }
1010
1011     out->enableOutput();
1012 }
1013
1014
1015 /* ======================================================================== */
1016