/*===- 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 #include 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 */ "ENTRY" { return token::ENTRY; } /* File Commands */ "INCLUDE" { return token::INCLUDE; } "INPUT" { return token::INPUT; } "GROUP" { return token::GROUP; } "AS_NEEDED" { return token::AS_NEEDED; } "OUTPUT" { return token::OUTPUT; } "SEARCH_DIR" { return token::SEARCH_DIR; } "STARTUP" { return token::STARTUP; } /* Format Commands */ "OUTPUT_FORMAT" { return token::OUTPUT_FORMAT; } "TARGET" { return token::TARGET; } /* Misc Commands */ "ASSERT" { return token::ASSERT; } "EXTERN" { return token::EXTERN; } "FORCE_COMMON_ALLOCATION" { return token::FORCE_COMMON_ALLOCATION; } "INHIBIT_COMMON_ALLOCATION" { return token::INHIBIT_COMMON_ALLOCATION; } "INSERT" { return token::INSERT; } "NOCROSSREFS" { return token::NOCROSSREFS; } "OUTPUT_ARCH" { return token::OUTPUT_ARCH; } "LD_FEATURE" { return token::LD_FEATURE; } /* Assignemnts */ "HIDDEN" { return token::HIDDEN; } "PROVIDE" { return token::PROVIDE; } "PROVIDE_HIDDEN" { return token::PROVIDE_HIDDEN; } /* SECTIONS Command */ "SECTIONS" { return token::SECTIONS; } /* MEMORY Command */ "MEMORY" { return token::MEMORY; } /* PHDRS Command */ "PHDRS" { return token::PHDRS; } /* Builtin Functions */ "ABSOLUTE" { return token::ABSOLUTE; } "ADDR" { return token::ADDR; } "ALIGN" { return token::ALIGN; } "ALIGNOF" { return token::ALIGNOF; } "BLOCK" { return token::BLOCK; } "DATA_SEGMENT_ALIGN" { return token::DATA_SEGMENT_ALIGN; } "DATA_SEGMENT_END" { return token::DATA_SEGMENT_END; } "DATA_SEGMENT_RELRO_END" { return token::DATA_SEGMENT_RELRO_END; } "DEFINED" { return token::DEFINED; } "LENGTH" { return token::LENGTH; } "LOADADDR" { return token::LOADADDR; } "MAX" { return token::MAX; } "MIN" { return token::MIN; } "NEXT" { return token::NEXT; } "ORIGIN" { return token::ORIGIN; } "SEGMENT_START" { return token::SEGMENT_START; } "SIZEOF" { return token::SIZEOF; } "SIZEOF_HEADERS" { return token::SIZEOF_HEADERS; } "CONSTANT" { return token::CONSTANT; } /* Symbolic Constants */ "MAXPAGESIZE" { return token::MAXPAGESIZE; } "COMMONPAGESIZE" { return token::COMMONPAGESIZE; } /* Input Section Description */ "EXCLUDE_FILE" { return token::EXCLUDE_FILE; } "KEEP" { return token::KEEP; } "SORT" { return token::SORT_BY_NAME; } "SORT_BY_NAME" { return token::SORT_BY_NAME; } "SORT_BY_ALIGNMENT" { return token::SORT_BY_ALIGNMENT; } "SORT_NONE" { return token::SORT_NONE; } "SORT_BY_INIT_PRIORITY" { return token::SORT_BY_INIT_PRIORITY; } /* Output Section Data */ "BYTE" { return token::BYTE; } "SHORT" { return token::SHORT; } "LONG" { return token::LONG; } "QUAD" { return token::QUAD; } "SQUAD" { return token::SQUAD; } "FILL" { return token::FILL; } /* Output Section Discarding */ "DISCARD" { return token::DISCARD; } /* Output Section Keywords */ "CREATE_OBJECT_SYMBOLS" { return token::CREATE_OBJECT_SYMBOLS; } "CONSTRUCTORS" { return token::CONSTRUCTORS; } /* Output Section Attributes */ /* Output Section Type */ "NOLOAD" { return token::NOLOAD; } "DSECT" { return token::DSECT; } "COPY" { return token::COPY; } "INFO" { return token::INFO; } "OVERLAY" { return token::OVERLAY; } /* Output Section LMA */ "AT" { return token::AT; } /* Forced Input Alignment */ "SUBALIGN" { return token::SUBALIGN; } /* Output Section Constraint */ "ONLY_IF_RO" { return token::ONLY_IF_RO; } "ONLY_IF_RW" { return token::ONLY_IF_RW; } /* Operators */ "<<" { return token::LSHIFT; } ">>" { return token::RSHIFT; } "==" { return token::EQ; } "!=" { return token::NE; } "<=" { return token::LE; } ">=" { return token::GE; } "&&" { return token::LOGICAL_AND; } "||" { return token::LOGICAL_OR; } "+=" { return token::ADD_ASSIGN; } "-=" { return token::SUB_ASSIGN; } "*=" { return token::MUL_ASSIGN; } "/=" { return token::DIV_ASSIGN; } "&=" { return token::AND_ASSIGN; } "|=" { return token::OR_ASSIGN; } "<<=" { return token::LS_ASSIGN; } ">>=" { return token::RS_ASSIGN; } "," { return static_cast(*yytext); } "=" { return static_cast(*yytext); } "?" { return static_cast(*yytext); } ":" { return static_cast(*yytext); } "|" { return static_cast(*yytext); } "^" { return static_cast(*yytext); } "&" { return static_cast(*yytext); } "<" { return static_cast(*yytext); } ">" { return static_cast(*yytext); } "+" { return static_cast(*yytext); } "-" { return static_cast(*yytext); } "*" { return static_cast(*yytext); } "/" { return static_cast(*yytext); } "%" { return static_cast(*yytext); } "!" { return static_cast(*yytext); } "~" { return static_cast(*yytext); } ";" { return static_cast(*yytext); } "(" { return static_cast(*yytext); } ")" { return static_cast(*yytext); } "{" { return static_cast(*yytext); } "}" { return static_cast(*yytext); } /* Numbers */ ((("$"|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 */ {FILENAMECHAR1}{SYMBOLCHARN}* { const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } /* String */ {FILENAMECHAR1}{NOCFILENAMECHAR}* { const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } \"(\\.|[^\\"])*\" { /*" c string literal */ const std::string& str = pScriptFile.createParserStr(yytext, yyleng); yylval->string = &str; return token::STRING; } /* -l namespec */ "-l"{FILENAMECHAR1}{NOCFILENAMECHAR}* { const std::string& str = pScriptFile.createParserStr(yytext + 2, yyleng - 2); yylval->string = &str; return token::LNAMESPEC; } /* WILDCHAR String */ {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 */ "/*" { enterComments(*yylloc); yylloc->step(); } /* gobble up white-spaces */ {WS}+ { yylloc->step(); } /* gobble up end-of-lines */ \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; }