3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
9 * 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
10 * によって公表されている GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
14 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
26 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
36 * @(#) $Id: parser.cpp,v 1.2 2012/06/17 00:24:19 suikan Exp $
41 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/parser.cpp,v 1.2 2012/06/17 00:24:19 suikan Exp $
43 #include "base/defs.h"
44 #include "base/parser.h"
55 Token & Token::trim(void)
57 string::iterator scope;
61 while(*scope == ' ' || *scope == '\t' || *scope == '\r' || *scope == '\n')
63 erase(begin(), scope);
71 } while(*scope == ' ' || *scope == '\t' || *scope == '\r' || *scope == '\n');
80 * 文字列リテラルの展開 (ダブルクォートの取り除き + エスケープシーケンスの展開)
82 Token & Token::chopLiteral(void)
84 if(type != STRINGLITERAL)
87 string::iterator scope;
93 if(src[0] != '"' || src[src.length()-1] != '"')
96 src = src.substr(1, src.length()-2);
99 while(scope != src.end())
103 //リテラルの末尾が\で終わることはないのでチェックしない
107 case '"': work += '"'; break;
108 case 't': work += '\t'; break;
109 case 'r': work += '\r'; break;
110 case 'n': work += '\n'; break;
111 case 'b': work += '\b'; break;
112 case '\\': work += '\\'; break;
114 ExceptionMessage("Illegal escape sequence [\\%]","エスケープシーケンス[\\%]は不正です") << *scope << throwException;
124 value = this->length();
129 /* 区切り文字 (一文字だけで意味を成す文字) */
130 const char * Parser::Punctuator =
133 /* 演算子 (特殊文字からなる文字) */
134 const char * Parser::Operator =
137 Token Parser::lastErrorToken;
143 inline int Parser::getChar(void)
145 int work = current->stream->get();
152 if(PutBackCount == 0)
154 if(LogBuffer != 0 && isenabled(LOGGING))
155 *LogBuffer += static_cast<char>(work);
157 PutBackCount --; //すでに読み込んでいる
165 inline void Parser::putBack(int ch)
174 current->stream->putback(ch);
180 Parser::~Parser(void)
182 list<tagFile *>::iterator scope;
184 /* 最後までパースしてないなら、とりあえずスタックに入れておく */
186 fileStack.push_front(current);
189 scope = fileStack.begin();
190 while(scope != fileStack.end())
192 if((*scope)->stream != 0 && (*scope)->stream != &cin)
193 delete (*scope)->stream; //ストリームの破棄
194 delete (*scope); //構造体のデータ領域の破棄
206 * 識別子の切出し (識別子 = [a-zA-Z_][0-9a-zA-Z_]*)
208 bool Parser::getIdentifier(Token & token,int ch)
214 token += static_cast<char>(ch);
216 } while( (ch >='a' && ch <= 'z') || (ch >='A' && ch <= 'Z') || (ch == '_') || (ch >= '0' && ch <= '9') );
219 putBack(static_cast<char>(ch));
221 token.type = Token::IDENTIFIER;
229 bool Parser::parseDirectives(Token & token, int ch, bool allow_space)
232 map<string, ParseUnit *>::iterator scope;
236 token += static_cast<char>(ch);
238 } while(ch == ' ' || ch == '\t');
240 if(ch >= '0' && ch <= '9')
242 //GNU-cpp lineディレクティブ 対策
243 directive.assign("line");
254 if(directive.compare("line") == 0)
258 getToken(token, Token::INTEGER);
259 setCurrentLine(token.value -1);
261 getToken(token, Token::STRINGLITERAL);
266 token.assign("Unknown");
268 setStreamIdentifier(token);
274 if(directive.compare("pragma") == 0)
280 if((scope = Directive::container().find(directive)) != Directive::container().end())
282 (*scope).second->body(directive, *Container, *this, string(""));
285 if(!TokenStack.empty())
288 token = TokenStack.front();
289 TokenStack.pop_front();
290 } while(!TokenStack.empty() && !allow_space && token.type == Token::SPACE);
298 if(directive.compare("include") == 0)
300 cerr << getStreamLocation() << Message(": Configurator found 'include' directive\nKernel configuration file must be preprocessed.\n",": #includeディレクティブを発見しました\n カーネル構成ファイルはCプリプロセッサを通過させる必要があります\n");
301 ExceptionMessage("Illegal kernel configuration file","不正なカーネル構成ファイル").throwException();
311 * ・スペース, タブ ・#で始まって改行まで ・C言語のコメントブロック
312 * ・2連のスラッシュ(//)から改行まで
315 bool Parser::getWhitespace(Token & token, int ch, bool allow_space)
319 token.type = Token::SPACE;
331 while( ((ch = getChar()) != '/') || (prev!='*'))
333 token += static_cast<char>(ch);
336 token += static_cast<char>(ch);
343 token += static_cast<char>(ch);
344 } while( (ch = getChar()) != '\n' );
347 /* ただ'/'で始まっただけでした */
350 return getOperator(token, '/');;
356 /* ディレクティブが無効 or そんなディレクティブは知らない */
357 if(! (isenabled(DIRECTIVE) && parseDirectives(token, ch, allow_space)) )
362 token += static_cast<char>(ch);
375 token += static_cast<char>(ch);
377 } while((ch == ' ') || (ch == '\n') || (ch == '\r') || (ch == '\t'));
378 putBack(static_cast<char>(ch));
385 * 整数値の切出し (8/10/16進, 正数/負数)
388 bool Parser::getInteger(Token & token, int ch)
396 if(ch < '0' || ch >'9')
398 putBack(static_cast<char>(ch));
404 token.type = Token::INTEGER;
409 token += static_cast<char>(ch);
411 if(ch == 'x' || ch == 'X')
413 token += static_cast<char>(ch);
415 while((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
417 token += static_cast<char>(ch);
418 if((ch -= '0') >= 10)
420 ch = ch + '0' - 'A' + 10;
422 ch = ch - ('a' - 'A');
424 token.value = token.value * 16 + ch;
429 while(ch >= '0' && ch <= '7')
431 token += static_cast<char>(ch);
432 token.value = token.value * 8 + ch - '0';
439 token += static_cast<char>(ch);
440 token.value = token.value * 10 + ch - '0';
442 } while(ch >= '0' && ch <= '9');
448 bool unsigned_suffix = false;
449 bool long_suffix = false;
451 int first_longsuffix;
453 if(ch == 'u' || ch == 'U')
455 unsigned_suffix = true;
456 token += static_cast<char>(ch);
460 if(ch == 'i' || ch == 'I') //i8, i16, i32, i64
464 const signed char suffix_list[10] = { -1, '6', -1, '2', -1, -1, '4', -1, 0, -1}; //8, 16, 32, 64のみを受理
468 if(first >= '0' && first <= '9')
470 if(suffix_list[first - '0'] > 0)
473 if(second == suffix_list[first - '0'])
476 if(suffix_list[first - '0'] == 0)
487 token += static_cast<char>(ch);
488 token += static_cast<char>(first);
490 token += static_cast<char>(second);
495 if(ch == 'l' || ch == 'L')
497 first_longsuffix = ch;
500 token += static_cast<char>(ch);
502 if(ch == first_longsuffix)
504 token += static_cast<char>(ch);
509 if(!unsigned_suffix && (ch == 'u' || ch == 'U'))
511 token += static_cast<char>(ch);
518 token.value = - token.value;
521 putBack(static_cast<char>(ch));
528 * オペレータ(特殊文字の組合せからなるトークン)の切出し
530 bool Parser::getOperator(Token & token, int ch)
534 /* chがオペレータ文字であるかどうか確かめる */
535 for(work = Operator;*work != '\x0' && *work != ch;work++);
539 /* 後続する文字もオペレータ文字であるかどうか確かめる */
541 token += static_cast<char>(ch);
543 for(work = Operator;*work != '\x0' && *work != ch;work++);
544 } while(*work != '\x0');
547 token.type = Token::OPERATOR;
553 * 文字列リテラル (ダブルクォートで括られた文字)
556 * VisualStudio6.0でコンパイルした場合、改行がLFのファイルに対してtellg後に
557 * getするとEOFが返るため、同処理をコメントアウトしておく。
559 bool Parser::getStringLiteral(Token & token, int delimitor)
567 token.type = Token::STRINGLITERAL;
569 token += static_cast<char>(ch);
571 while(!current->stream->bad() && !current->stream->eof())
575 token += static_cast<char>(ch);
578 if(ch == delimitor && prev != '\\')
582 //いったん閉じて再オープンして、リテラル開始の " の次に移動
584 ExceptionMessage(ExceptionMessage::FATAL, "Unterminated string literal appeared.","閉じられていない文字リテラルを検出しました").throwException();
592 enum Token::tagTokenType Parser::getToken(Token & token, bool allow_space)
599 token.type = Token::ERROR;
603 if(!TokenStack.empty())
606 token = TokenStack.front();
607 TokenStack.pop_front();
608 } while(!TokenStack.empty() && !allow_space && token.type == Token::SPACE);
610 if(!allow_space && token.type != Token::SPACE)
615 if(current == NULL || current->stream == NULL || current->stream->bad())
617 token.assign("<End of stream>");
618 return (token.type = Token::EOS);
626 //ファイルスタックから次のストリームを取る
627 if(!fileStack.empty())
629 if(current->stream != &cin)
630 delete current->stream;
633 current = *fileStack.begin();
634 fileStack.pop_front();
637 token.assign("<End of stream>");
638 return (token.type = Token::EOS);
642 //First(whitespaces) is [ \n\t\r/#]
643 if( (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r') || (ch == '/') || (isHeadofLine && ch == '#'))
648 if(getWhitespace(token, ch, allow_space))
649 if((token == Token::SPACE && allow_space) || !(token == Token::SPACE || token == Token::ERROR))
657 isHeadofLine = false;
659 token.line = current->line;
661 //First(identifier) is [a-zA-Z_]
662 if( (ch >='a' && ch <= 'z') || (ch >='A' && ch <= 'Z') || (ch == '_') )
663 if(getIdentifier(token, ch))
664 return Token::IDENTIFIER;
666 //First(integer) is [\-0-9]
667 if( (ch >='0' && ch <='9') || (ch == '-') )
668 if(getInteger(token,ch))
669 return Token::INTEGER;
671 //First(string) is ["']
672 if( ch == '"' || ch == '\'')
673 if(getStringLiteral(token,ch))
674 return Token::STRINGLITERAL;
677 if(getOperator(token,ch))
678 return Token::OPERATOR;
682 while(*work != '\x0')
683 if( *(work++) == ch )
685 token += static_cast<char>(ch);
686 return (token.type = Token::PUNCTUATOR);
689 token += static_cast<char>(ch);
690 token.type = Token::UNKNOWN;
691 return Token::UNKNOWN;
696 * トークン用 ストリームオペレータ (主にテスト目的)
698 ostream & operator << (ostream & out, Token & src)
702 case Token::IDENTIFIER:
703 out << "<IDENTIFIER:["; break;
705 out << "<INTEGER:["; break;
706 case Token::STRINGLITERAL:
707 out << "<STRINGLITERAL:["; break;
709 out << "<STRING:["; break;
710 case Token::OPERATOR:
711 out << "<OPERATOR:["; break;
712 case Token::PUNCTUATOR:
713 out << "<PUNCTUATOR:["; break;
714 case Token::RESERVEDWORD:
715 out << "<RESERVEDWORD:["; break;
717 out << "<SPECIAL:["; break;
719 out << "<SPACE:["; break;
721 out << "<UNKNOWN>"; return out;
723 out << "<ERROR>"; return out;
728 return out << static_cast<string &>(src) << "]("<<src.value<<")>";
734 void Parser::getToken(const char * term) throw(Exception)
739 ExceptionMessage("Internal: GetToken received an empty string as reserved word.","内部エラー: GetTokenに空文字列が渡されました").throwException();
741 getToken(token, false);
742 if(token.compare(term) != 0) {
743 lastErrorToken = token;
744 ExceptionMessage("Token [%] should be replaced by [%]","字句[%]は[%]であるべきです") << token << term << throwException;
748 void Parser::getToken(const char * first, const char * second, const char * third, const char * fourth) throw(Exception)
759 string Parser::getStreamLocation(void)
761 list<tagFile *>::iterator scope;
769 ::sprintf(buffer, ":%d", current->line);
770 location += current->identifier;
773 if(!fileStack.empty())
775 location += " (included at ";
777 scope = fileStack.begin();
778 while(scope != fileStack.end())
780 ::sprintf(buffer, ":%d, ", (*scope)->line);
781 location += (*scope)->identifier;
788 location.erase(location.size()-2);
795 void Parser::pushStream(const std::string & filename, std::string strid)
800 fileStack.push_front(current);
802 fin = new fstream(filename.c_str(),ios::in);
806 if(strid.size() == 0)
809 current = new tagFile;
810 current->stream = fin;
811 current->identifier = strid;
815 ExceptionMessage("File operation failure : [%]","ファイル操作に失敗しました [%]") << filename << throwException;
820 void Parser::pushStdStream(std::string strid)
822 stringstream * work = new stringstream;
826 //標準入力の情報をすべて取り込む (エラー対処用に seekg/tellg を使いたい)
828 cin.read(buffer, 1024);
829 count = cin.gcount();
830 work->write(buffer, count);
834 fileStack.push_front(current);
836 current = new tagFile;
837 current->stream = work;
838 current->identifier = strid;
842 string * Parser::setLogBuffer(string * buffer)
844 string * old = LogBuffer;
850 streampos Parser::getLogBufferPos(int offset)
856 pos = LogBuffer->size();
857 pos += static_cast<streampos>(offset - PutBackCount);
861 #ifdef CALL_EXTERNAL_PROGRAM
862 void Parser::doPreProcess(const char * cmd)
869 stringstream * stream;
871 if(current == NULL || current->stream == NULL)
872 ExceptionMessage("No stream specified for processing","処理対象となるストリームが設定されていません").throwException();
875 /* 今のストリームの内容をすべてテンポラリに書き出す */
877 strcpy(buffer,"cfgXXXXXX");
880 tempfilename.assign(buffer);
881 tempfile.open(tempfilename.c_str(),ios::out);
883 if(!tempfile.is_open())
884 ExceptionMessage("Failed to open a temporary file","テンポラリファイルの作成に失敗しました").throwException();
887 current->stream->read(buffer, 1024);
888 count = current->stream->gcount();
889 tempfile.write(buffer, count);
896 preprocessname = tempfilename;
897 originalname = current->identifier;
899 if(current->stream != &cin)
900 delete current->stream;
901 stream = new stringstream;
902 current->stream = stream;
905 /* プリプロセッサの起動 & 出力の取り込み */
907 work = string(cmd) + " " + tempfilename;
908 VerboseMessage(" Start the external preprocessor [%]\n"," 外部プログラムを起動します [%]\n") << work;
910 FILE * pipe = popen(work.c_str(),"r");
911 while(feof(pipe) == 0)
912 stream->put((char)fgetc(pipe));
915 remove(tempfilename.c_str());
919 void Parser::doPreProcess(const char * cmd)
921 #endif /* CALL_EXTERNAL_PROGRAM */
924 ParseUnit::ParseUnit(void * _container, const char * name)
926 map<string, ParseUnit *> * container;
929 string::size_type i,j;
932 container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
935 j = work.find_first_of(',', i);
936 apiname = work.substr(i, j-i);
938 if(container->find(apiname) != container->end())
939 ExceptionMessage("Multiple registration of [%]\n","[%]が重複して登録されようとしています") << apiname << throwException;
940 (*container)[apiname] = this;
942 }while(j != string::npos);
945 void ParseUnit::printList(void * _container)
948 map<string, ParseUnit *> * container;
949 map<string, ParseUnit *>::iterator scope;
951 container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
952 if(container->empty())
954 cerr << " " << Message("None of element registed\n", "登録されている要素はありません\n");
959 scope = container->begin();
960 while(scope != container->end())
962 cerr << '[' << (*scope).first << "] ";
977 Token & ParseUnit::parseParameter(Parser & p)
983 result.type = Token::ERROR;
990 if(token == Token::PUNCTUATOR)
992 if(token.compare("(") == 0)
994 else if(token.compare(")") == 0)
999 ExceptionMessage("')' appeared before '('.","対応しない閉じ括弧があります").throwException();
1002 if(result == Token::ERROR)
1006 result.type = Token::STRING;
1018 int ParseUnit::parseParameters(Parser & p, Directory * container, int min, int max)
1028 Token & token = parseParameter(p);
1029 if(token.type == Token::ERROR)
1032 if(token == Token::INTEGER)
1033 container->addChild(new Directory(token.value));
1035 container->addChild(new Directory((string &)token));
1039 }while(work.compare(",")==0 && count < max);
1042 ExceptionMessage("Too few parameters [%/%]","パラメータの数が少なすぎます [%/%]") << count << min << throwException;
1048 int ParseUnit::parseParameters(Parser & p, Directory * container, const char * paramlist)
1054 string::size_type head,tail;
1056 list.assign(paramlist);
1060 tail = list.find_first_of(',');
1061 key = list.substr(head,tail-head);
1065 if(head == string::npos)
1066 ExceptionMessage("Too many parameters","パラメータの数が多すぎます").throwException();
1068 Token & token = parseParameter(p);
1069 if(token.type == Token::ERROR)
1072 if(token == Token::INTEGER)
1073 container->addChild(key,new Directory(token.value));
1075 container->addChild(key,new Directory((string &)token));
1077 if(tail != string::npos)
1080 tail = list.find_first_of(',',head);
1081 key = list.substr(head,tail != string::npos ? tail-head : string::npos);
1086 }while(work.compare(",")==0);
1088 if(tail != string::npos)
1089 ExceptionMessage("Too few parameters","パラメータの数が少なすぎます").throwException();
1096 Directory * StaticAPI::last = NULL;
1098 map<std::string, class ParseUnit *> & StaticAPI::container(void)
1100 static map<std::string, class ParseUnit *> _container;
1104 Directory * StaticAPI::allocate(Directory & container, const Token & token, const char * id, bool regist)
1106 static unsigned int assignment_count = 0;
1109 if(!(token == Token::IDENTIFIER || token == Token::INTEGER))
1110 ExceptionMessage("Given token(%) is not suitable for an object identifier.","オブジェクトの識別名として利用できない字句(%)が指定されました") << token << throwException;
1112 if(regist && (token == Token::INTEGER && token.value <= 0))
1113 ExceptionMessage("Cannot assign an ID number less or equal to 0.","0以下のID番号を設定することはできません").throwException();
1116 node = container.findChild(id);
1119 Directory::iterator scope;
1121 scope = node->begin();
1122 while(scope != node->end())
1124 if((*scope).first.compare(token) == 0)
1125 ExceptionMessage("Identifier % is already used.","識別名%はすでに利用されています") << token << throwException;
1129 node = container.addChild(id);
1131 node = node->addChild(token);
1132 (*node)["#order"] = assignment_count++;
1134 if(token == Token::IDENTIFIER)
1138 Directory * scope = container.openChild("/","identifier",token.c_str(),NULL);
1139 if(*scope == Directory::INTEGER)
1140 *node = scope->toInteger();
1143 *node = token.value;
1151 map<std::string, class ParseUnit *> & Directive::container(void)
1153 static map<std::string, class ParseUnit *> _container;
1159 ParserComponent::ParserComponent(void) throw() : Component(PARSER)
1162 ParserComponent::~ParserComponent(void) throw()
1165 void ParserComponent::parseOption(Directory & container)
1167 if(findOption("h", "help"))
1170 "Static API parser\n"
1171 " -s, --source=filename : Specify the source file\n"
1172 " -idir ,--ignore-directive : Ignore directives\n"
1173 " -iapi ,--ignore-api : Ignore unknown static api\n"
1174 " -t, --through : Get unprocessed APIs through\n"
1175 " --print-api : Show registered static api list\n",
1177 " -s, --source=ファイル名 : 入力ファイル名を指定します\n"
1178 " -idir ,--ignore-directive : ディレクティブの解析を行いません\n"
1179 " -iapi, --ignore-api : 登録されていないAPIを無視します\n"
1180 " -t, --through : 処理しなかったAPIを通過させます\n"
1181 " --print-api : 登録されているAPIの一覧を表示します\n");
1185 if(findOption("-print-api"))
1187 cerr << Message("List of Registerd Static API\n","静的API 一覧\n");
1188 StaticAPI::printList();
1192 checkOption("idir", "ignore-directive");
1193 checkOption("iapi", "ignore-api");
1194 checkOption("t", "through");
1196 if(checkOption("s","source") || checkOption(DEFAULT_PARAMETER))
1197 activateComponent();
1200 bool ParserComponent::parseStaticAPI(Parser & p, Directory & container, Token token, const string domain)
1202 bool isParseErrorOccured = false;
1203 map<string, ParseUnit *>::iterator api;
1204 Directory * node = NULL;
1206 if(token.type != Token::IDENTIFIER)
1209 StaticAPI::clearLastObject();
1210 node = container[PARSERESULT].addChild();
1213 node->addChild("api",new Directory(token));
1214 node->addChild("begin",new Directory((long)p.getLogBufferPos(-(int)token.size()-1)));
1216 node->addChild("domain", new Directory(domain));
1218 api = StaticAPI::container().find(token);
1219 if(api == StaticAPI::container().end())
1221 if(ignoreUnknownAPI)
1223 cerr << Message("%: Unknown static api % was ignored. (skipped)\n","%: 非登録のAPI % は無視されます\n") << p.getStreamLocation() << token;
1226 }while(token.compare(";") != 0);
1227 node->addChild("end",new Directory((long)p.getLogBufferPos()));
1231 ExceptionMessage("Static API [%] is not registered in the configurator", "静的API[%]は未登録です") << token << throwException;
1234 DebugMessage(" StaticAPI [%]\n") << (*api).first;
1238 (*api).second->body(token, container, p, domain);
1243 node->addChild("end",new Directory((long)p.getLogBufferPos()));
1246 catch(Exception & e)
1250 work = p.getStreamLocation() + Message(":[Error] ",":[エラー] ").str() + e.getDetails();
1251 isParseErrorOccured = true;
1253 StaticAPI::dropLastObject();
1257 token = p.getLastErrorToken();
1258 while (token != Token::ERROR && token != Token::EOS)
1263 //読み出したトークンが静的APIと同じ名前なら きっとセミコロン忘れ
1264 api = StaticAPI::container().find(token);
1265 if(api != StaticAPI::container().end())
1267 cerr << Message("<The following error must be occured by lack of ';' at the end of previous line>\n","<次のエラーは直前行の';'忘れによる可能性が高いです>\n");
1268 offset = -(int)token.size();
1276 node->addChild("end",new Directory((long)p.getLogBufferPos(offset)));
1279 cerr << work << '\n';
1281 ExceptionMessage("Fatal error on Static API parsing","静的APIの構文解析に失敗しました").throwException();
1288 * 処理できなかったAPIを標準出力に吐き出す
1290 void ParserComponent::throughConfigurationFile(string & log, Directory & container)
1293 string::size_type pos;
1294 string::size_type begin;
1295 string::size_type end;
1300 node = container[PARSERESULT].getFirstChild();
1303 begin = static_cast<string::size_type>((*node)["begin"].toInteger());
1304 end = static_cast<string::size_type>((*node)["end"].toInteger());
1307 cout << log.substr(pos, begin - pos);
1309 if(node->toInteger() == 0)
1311 cout << log.substr(begin, end - begin);
1314 for(pos = begin; pos < end; ++pos)
1315 if( log.at(pos) == '\n' )
1318 node = node->getNext();
1321 if(end < log.size())
1322 cout << log.substr(end);
1324 ExceptionMessage("","").throwException();
1328 void ParserComponent::body(Directory & container)
1331 Parser p(container);
1333 OptionParameter::OptionItem item;
1334 unsigned int itemcount = 0;
1339 if(findOption("idir","ignore-directive"))
1340 p.disable(Parser::DIRECTIVE);
1342 ignoreUnknownAPI = findOption("iapi", "ignore-api");
1344 if(findOption("t","through"))
1346 p.setLogBuffer(&logbuffer);
1347 ignoreUnknownAPI = true;
1351 item = getOption("s", "source");
1352 item.mergeItem(getOption(DEFAULT_PARAMETER));
1353 if(item.countParameter() == 0)
1355 p.pushStdStream(Message("Standard Input","標準入力").str());
1356 VerboseMessage("Starting parse with standard input\n","標準入力からの字句解析を開始しました\n");
1361 if(item.hasParameter())
1363 VerboseMessage("Starting parse with file[%]\n","ファイル[%]の字句解析を開始しました\n") << item[itemcount];
1364 p.pushStream(item[itemcount]);
1367 this->parse(p, container);
1369 if(p.getToken(token) != Token::EOS)
1370 ExceptionMessage("Buffer has remaining tokens, parsing is not yet finished", "パースが中断されました").throwException();
1373 ExceptionMessage("Total % failures found in this configuration.","%個の障害があります") << failCount << throwException;
1375 VerboseMessage("Parse finished\n","字句解析は正常に終了しました\n");
1377 } while(++itemcount < item.countParameter());
1379 if(findOption("t","through"))
1380 throughConfigurationFile(logbuffer,container);
1382 container[PARSERESULT].erase();
1384 catch(Exception & e)
1388 work = p.getStreamLocation() + Message(":[Error] ",":[エラー] ").str() + e.getDetails();
1389 ExceptionMessage(work.c_str()).throwException();
1393 // オプションノードから割付方法を取得する
1394 enum Common::tagAssignmentOrder Common::parseOrder(Directory * node)
1403 scope = node->getFirstChild();
1406 string param = scope->toString();
1407 if(param.compare("alphabetic") == 0 || param.compare("ALPHABETIC") == 0)
1408 i = (i & 0xf0) | ALPHABETIC;
1409 else if(param.compare("fcfs") == 0 || param.compare("FCFS") == 0)
1410 i = (i & 0xf0) | FCFS;
1411 else if(param.compare("reverse") == 0 || param.compare("REVERSE") == 0)
1414 scope = scope->getNext();
1418 return static_cast<enum tagAssignmentOrder>(i);
1421 // オプションノードから割付方法を取得する
1422 enum Common::tagAssignmentOrder Common::parseOrder(OptionParameter::OptionItem item)
1427 for(i=0;i<item.countParameter();++i)
1428 node.addChild(item[i]);
1430 return parseOrder(&node);
1434 // (他の場所からも使うのでここに移動)
1435 int Common::assignID(Directory & container, const char * category, const char * top, enum tagAssignmentOrder order)
1437 Directory * node = 0;
1438 Directory * scope = 0;
1439 Directory * work = 0;
1441 map<int, Directory *> sorter;
1442 map<int, Directory *>::iterator p_sorter;
1446 node = container.findChild(top,category,NULL);
1450 for(i=1;i< (signed int) node->size() + 32; i++)
1455 scope = node->getFirstChild();
1458 if( *scope == Directory::INTEGER )
1459 idpool.erase(*scope);
1463 work = container.openChild("/","identifier",scope->getKey().c_str(),NULL);
1464 if( *work == Directory::INTEGER)
1466 VerboseMessage("Assigning the same ID (%) since the name (%[%]) is duplicated\n","ID番号(%)を異種同名のオブジェクト(%[%])に割り当てます.\n") << work->toInteger() << scope->getKey() << category;
1467 idpool.erase(*scope = work->toInteger());
1474 sorter[i++] = scope;
1476 case REVERSE_ALPHABETIC:
1477 sorter[i--] = scope;
1481 sorter[scope->openChild("#order")->toInteger()] = scope;
1484 sorter[-scope->openChild("#order")->toInteger()] = scope;
1489 scope = scope->getNext();
1493 p_sorter = sorter.begin();
1494 while(p_sorter != sorter.end())
1496 scope = (*p_sorter).second;
1497 if( !(*scope == Directory::INTEGER) )
1499 i = *(idpool.begin());
1500 idpool.erase(idpool.begin());
1502 work = container.openChild("/","identifier",scope->getKey().c_str(),NULL);
1510 if(node->size() != 0 && VerboseMessage::getVerbose())
1512 VerboseMessage("Object ID assignment list [%]\n","オブジェクトID割付表 [%]\n") << category;
1515 scope = node->getFirstChild();
1518 sorter[scope->toInteger()] = scope;
1519 scope = scope->getNext();
1522 p_sorter = sorter.begin();
1523 while(p_sorter != sorter.end())
1525 VerboseMessage(" % : %\n") << setw(3) << (*p_sorter).first << (*p_sorter).second->getKey();
1531 if((signed)node->size()+1 != *(idpool.begin()))
1532 ExceptionMessage("Discontinuous % ID assignment occured","不連続なオブジェクトID(%)") << category << throwException;
1534 return node->size();