source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/jsp/jsp_parser.cpp@ 363

Last change on this file since 363 was 363, checked in by ykominami, 5 years ago

add tags/jsp-1.4.4-full-UTF8

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