/*===- ScriptScanner.ll ---------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===*/ %{ /* C/C++ Declarations */ #include "mcld/Script/ScriptScanner.h" #include "mcld/Script/ScriptFile.h" #include "mcld/Support/MsgHandling.h" #include <llvm/ADT/StringRef.h> #include <string> typedef mcld::ScriptParser::token token; typedef mcld::ScriptParser::token_type token_type; #define yyterminate() return token::END #define YY_NO_UNISTD_H %} %{ #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-register" #endif %} /* Flex Declarations and Options */ %option c++ %option batch %option noyywrap %option nounput %option stack %{ #define YY_USER_ACTION yylloc->columns(yyleng); %} /* abbrev. of RE @ref binutils ld/ldlex.l */ FILENAMECHAR1 [_a-zA-Z\/\.\\\$\_\~] SYMBOLCHARN [_a-zA-Z\/\.\\\$\_\~0-9] NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\~] WILDCHAR [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\,\~\?\*\^\!] WS [ \t\r] /* Start conditions */ %s LDSCRIPT %s EXPRESSION %% /* Regular Expressions */ /* code to place at the beginning of yylex() */ %{ /* reset location */ yylloc->step(); /* determine the initial parser state */ if (m_Kind == ScriptFile::Unknown) { m_Kind = pScriptFile.getKind(); switch (pScriptFile.getKind()) { case ScriptFile::LDScript: case ScriptFile::Expression: return token::LINKER_SCRIPT; case ScriptFile::VersionScript: case ScriptFile::DynamicList: default: assert(0 && "Unsupported script type!"); break; } } %} /* Entry Point */ <LDSCRIPT>"ENTRY" { return token::ENTRY; } /* File Commands */ <LDSCRIPT>"INCLUDE" { return token::INCLUDE; } <LDSCRIPT>"INPUT" { return token::INPUT; } <LDSCRIPT>"GROUP" { return token::GROUP; } <LDSCRIPT>"AS_NEEDED" { return token::AS_NEEDED; } <LDSCRIPT>"OUTPUT" { return token::OUTPUT; } <LDSCRIPT>"SEARCH_DIR" { return token::SEARCH_DIR; } <LDSCRIPT>"STARTUP" { return token::STARTUP; } /* Format Commands */ <LDSCRIPT>"OUTPUT_FORMAT" { return token::OUTPUT_FORMAT; } <LDSCRIPT>"TARGET" { return token::TARGET; } /* Misc Commands */ <LDSCRIPT>"ASSERT" { return token::ASSERT; } <LDSCRIPT>"EXTERN" { return token::EXTERN; } <LDSCRIPT>"FORCE_COMMON_ALLOCATION" { return token::FORCE_COMMON_ALLOCATION; } <LDSCRIPT>"INHIBIT_COMMON_ALLOCATION" { return token::INHIBIT_COMMON_ALLOCATION; } <LDSCRIPT>"INSERT" { return token::INSERT; } <LDSCRIPT>"NOCROSSREFS" { return token::NOCROSSREFS; } <LDSCRIPT>"OUTPUT_ARCH" { return token::OUTPUT_ARCH; } <LDSCRIPT>"LD_FEATURE" { return token::LD_FEATURE; } /* Assignemnts */ <LDSCRIPT,EXPRESSION>"HIDDEN" { return token::HIDDEN; } <LDSCRIPT,EXPRESSION>"PROVIDE" { return token::PROVIDE; } <LDSCRIPT,EXPRESSION>"PROVIDE_HIDDEN" { return token::PROVIDE_HIDDEN; } /* SECTIONS Command */ <LDSCRIPT>"SECTIONS" { return token::SECTIONS; } /* MEMORY Command */ <LDSCRIPT>"MEMORY" { return token::MEMORY; } /* PHDRS Command */ <LDSCRIPT>"PHDRS" { return token::PHDRS; } /* Builtin Functions */ <EXPRESSION>"ABSOLUTE" { return token::ABSOLUTE; } <EXPRESSION>"ADDR" { return token::ADDR; } <LDSCRIPT,EXPRESSION>"ALIGN" { return token::ALIGN; } <EXPRESSION>"ALIGNOF" { return token::ALIGNOF; } <EXPRESSION>"BLOCK" { return token::BLOCK; } <EXPRESSION>"DATA_SEGMENT_ALIGN" { return token::DATA_SEGMENT_ALIGN; } <EXPRESSION>"DATA_SEGMENT_END" { return token::DATA_SEGMENT_END; } <EXPRESSION>"DATA_SEGMENT_RELRO_END" { return token::DATA_SEGMENT_RELRO_END; } <EXPRESSION>"DEFINED" { return token::DEFINED; } <EXPRESSION>"LENGTH" { return token::LENGTH; } <EXPRESSION>"LOADADDR" { return token::LOADADDR; } <EXPRESSION>"MAX" { return token::MAX; } <EXPRESSION>"MIN" { return token::MIN; } <EXPRESSION>"NEXT" { return token::NEXT; } <EXPRESSION>"ORIGIN" { return token::ORIGIN; } <EXPRESSION>"SEGMENT_START" { return token::SEGMENT_START; } <EXPRESSION>"SIZEOF" { return token::SIZEOF; } <EXPRESSION>"SIZEOF_HEADERS" { return token::SIZEOF_HEADERS; } <EXPRESSION>"CONSTANT" { return token::CONSTANT; } /* Symbolic Constants */ <EXPRESSION>"MAXPAGESIZE" { return token::MAXPAGESIZE; } <EXPRESSION>"COMMONPAGESIZE" { return token::COMMONPAGESIZE; } /* Input Section Description */ <LDSCRIPT>"EXCLUDE_FILE" { return token::EXCLUDE_FILE; } <LDSCRIPT>"KEEP" { return token::KEEP; } <LDSCRIPT>"SORT" { return token::SORT_BY_NAME; } <LDSCRIPT>"SORT_BY_NAME" { return token::SORT_BY_NAME; } <LDSCRIPT>"SORT_BY_ALIGNMENT" { return token::SORT_BY_ALIGNMENT; } <LDSCRIPT>"SORT_NONE" { return token::SORT_NONE; } <LDSCRIPT>"SORT_BY_INIT_PRIORITY" { return token::SORT_BY_INIT_PRIORITY; } /* Output Section Data */ <LDSCRIPT>"BYTE" { return token::BYTE; } <LDSCRIPT>"SHORT" { return token::SHORT; } <LDSCRIPT>"LONG" { return token::LONG; } <LDSCRIPT>"QUAD" { return token::QUAD; } <LDSCRIPT>"SQUAD" { return token::SQUAD; } <LDSCRIPT>"FILL" { return token::FILL; } /* Output Section Discarding */ <LDSCRIPT>"DISCARD" { return token::DISCARD; } /* Output Section Keywords */ <LDSCRIPT>"CREATE_OBJECT_SYMBOLS" { return token::CREATE_OBJECT_SYMBOLS; } <LDSCRIPT>"CONSTRUCTORS" { return token::CONSTRUCTORS; } /* Output Section Attributes */ /* Output Section Type */ <LDSCRIPT,EXPRESSION>"NOLOAD" { return token::NOLOAD; } <LDSCRIPT,EXPRESSION>"DSECT" { return token::DSECT; } <LDSCRIPT,EXPRESSION>"COPY" { return token::COPY; } <LDSCRIPT,EXPRESSION>"INFO" { return token::INFO; } <LDSCRIPT,EXPRESSION>"OVERLAY" { return token::OVERLAY; } /* Output Section LMA */ <LDSCRIPT>"AT" { return token::AT; } /* Forced Input Alignment */ <LDSCRIPT>"SUBALIGN" { return token::SUBALIGN; } /* Output Section Constraint */ <LDSCRIPT>"ONLY_IF_RO" { return token::ONLY_IF_RO; } <LDSCRIPT>"ONLY_IF_RW" { return token::ONLY_IF_RW; } /* Operators */ <LDSCRIPT,EXPRESSION>"<<" { return token::LSHIFT; } <LDSCRIPT,EXPRESSION>">>" { return token::RSHIFT; } <LDSCRIPT,EXPRESSION>"==" { return token::EQ; } <LDSCRIPT,EXPRESSION>"!=" { return token::NE; } <LDSCRIPT,EXPRESSION>"<=" { return token::LE; } <LDSCRIPT,EXPRESSION>">=" { return token::GE; } <LDSCRIPT,EXPRESSION>"&&" { return token::LOGICAL_AND; } <LDSCRIPT,EXPRESSION>"||" { return token::LOGICAL_OR; } <LDSCRIPT,EXPRESSION>"+=" { return token::ADD_ASSIGN; } <LDSCRIPT,EXPRESSION>"-=" { return token::SUB_ASSIGN; } <LDSCRIPT,EXPRESSION>"*=" { return token::MUL_ASSIGN; } <LDSCRIPT,EXPRESSION>"/=" { return token::DIV_ASSIGN; } <LDSCRIPT,EXPRESSION>"&=" { return token::AND_ASSIGN; } <LDSCRIPT,EXPRESSION>"|=" { return token::OR_ASSIGN; } <LDSCRIPT,EXPRESSION>"<<=" { return token::LS_ASSIGN; } <LDSCRIPT,EXPRESSION>">>=" { return token::RS_ASSIGN; } <LDSCRIPT,EXPRESSION>"," { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"=" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"?" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>":" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"|" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"^" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"&" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"<" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>">" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"+" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"-" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"*" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"/" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"%" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"!" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"~" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>";" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"(" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>")" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"{" { return static_cast<token_type>(*yytext); } <LDSCRIPT,EXPRESSION>"}" { return static_cast<token_type>(*yytext); } /* Numbers */ <LDSCRIPT,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? { llvm::StringRef str(yytext, yyleng); switch (str.back()) { case 'k': case 'K': str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer); yylval->integer *= 1024; break; case 'm': case 'M': str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer); yylval->integer *= 1024 * 1024; break; default: str.getAsInteger(0, yylval->integer); break; } return token::INTEGER; } /* Expression string */ <EXPRESSION>{FILENAMECHAR1}{SYMBOLCHARN}* { const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } /* String */ <LDSCRIPT>{FILENAMECHAR1}{NOCFILENAMECHAR}* { const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } <LDSCRIPT,EXPRESSION>\"(\\.|[^\\"])*\" { /*" c string literal */ const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } /* -l namespec */ <LDSCRIPT>"-l"{FILENAMECHAR1}{NOCFILENAMECHAR}* { const std::string& str = pScriptFile.createParserStr(yytext + 2, yyleng - 2); yylval->string = &str; return token::LNAMESPEC; } /* WILDCHAR String */ <LDSCRIPT>{WILDCHAR}* { if (yytext[0] == '/' && yytext[1] == '*') { yyless (2); enterComments(*yylloc); } else { const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } } /* gobble up C comments */ <LDSCRIPT,EXPRESSION>"/*" { enterComments(*yylloc); yylloc->step(); } /* gobble up white-spaces */ <LDSCRIPT,EXPRESSION>{WS}+ { yylloc->step(); } /* gobble up end-of-lines */ <LDSCRIPT,EXPRESSION>\n { yylloc->lines(1); yylloc->step(); } %% /* Additional Code */ namespace mcld { ScriptScanner::ScriptScanner(std::istream* yyin, std::ostream* yyout) : yyFlexLexer(yyin, yyout), m_Kind(ScriptFile::Unknown) { } ScriptScanner::~ScriptScanner() { } void ScriptScanner::enterComments(ScriptParser::location_type& pLocation) { const int start_line = pLocation.begin.line; const int start_col = pLocation.begin.column; int ch = 0; while (true) { ch = yyinput(); pLocation.columns(1); while (ch != '*' && ch != EOF) { if (ch == '\n') { pLocation.lines(1); } ch = yyinput(); pLocation.columns(1); } if (ch == '*') { ch = yyinput(); pLocation.columns(1); while (ch == '*') { ch = yyinput(); pLocation.columns(1); } if (ch == '/') break; } if (ch == '\n') pLocation.lines(1); if (ch == EOF) { error(diag::err_unterminated_comment) << pLocation.begin.filename << start_line << start_col; break; } } } void ScriptScanner::setLexState(ScriptFile::Kind pKind) { /* push the state into the top of stach */ m_StateStack.push(pKind); switch (pKind) { case ScriptFile::LDScript: BEGIN(LDSCRIPT); break; case ScriptFile::Expression: BEGIN(EXPRESSION); break; case ScriptFile::VersionScript: case ScriptFile::DynamicList: default: assert(0 && "Unsupported script type!"); break; } } void ScriptScanner::popLexState() { /* pop the last state */ m_StateStack.pop(); /* resume the appropriate state */ if (!m_StateStack.empty()) { switch (m_StateStack.top()) { case ScriptFile::LDScript: BEGIN(LDSCRIPT); break; case ScriptFile::Expression: BEGIN(EXPRESSION); break; case ScriptFile::VersionScript: case ScriptFile::DynamicList: default: assert(0 && "Unsupported script type!"); break; } } } } /* namespace mcld */ #ifdef __clang__ #pragma clang diagnostic pop #endif #ifdef yylex #undef yylex #endif int yyFlexLexer::yylex() { return 0; }