1/*===- ScriptScanner.ll ---------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===*/ 9 10%{ 11/* C/C++ Declarations */ 12 13#include <mcld/Script/ScriptScanner.h> 14#include <mcld/Script/ScriptFile.h> 15#include <mcld/Support/MsgHandling.h> 16#include <llvm/ADT/StringRef.h> 17#include <string> 18 19typedef mcld::ScriptParser::token token; 20typedef mcld::ScriptParser::token_type token_type; 21 22#define yyterminate() return token::END 23#define YY_NO_UNISTD_H 24%} 25 26/* Flex Declarations and Options */ 27%option c++ 28%option batch 29%option noyywrap 30%option nounput 31%option stack 32 33%{ 34#define YY_USER_ACTION yylloc->columns(yyleng); 35%} 36 37/* abbrev. of RE @ref binutils ld/ldlex.l */ 38FILENAMECHAR1 [_a-zA-Z\/\.\\\$\_\~] 39SYMBOLCHARN [_a-zA-Z\/\.\\\$\_\~0-9] 40NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\~] 41WILDCHAR [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\,\~\?\*\^\!] 42WS [ \t\r] 43 44/* Start conditions */ 45%s LDSCRIPT 46%s EXPRESSION 47 48%% /* Regular Expressions */ 49 50 /* code to place at the beginning of yylex() */ 51%{ 52 /* reset location */ 53 yylloc->step(); 54 55 /* determine the initial parser state */ 56 if (m_Kind == ScriptFile::Unknown) { 57 m_Kind = pScriptFile.getKind(); 58 switch (pScriptFile.getKind()) { 59 case ScriptFile::LDScript: 60 case ScriptFile::Expression: 61 return token::LINKER_SCRIPT; 62 case ScriptFile::VersionScript: 63 case ScriptFile::DynamicList: 64 default: 65 assert(0 && "Unsupported script type!"); 66 break; 67 } 68 } 69%} 70 71 /* Entry Point */ 72<LDSCRIPT>"ENTRY" { return token::ENTRY; } 73 /* File Commands */ 74<LDSCRIPT>"INCLUDE" { return token::INCLUDE; } 75<LDSCRIPT>"INPUT" { return token::INPUT; } 76<LDSCRIPT>"GROUP" { return token::GROUP; } 77<LDSCRIPT>"AS_NEEDED" { return token::AS_NEEDED; } 78<LDSCRIPT>"OUTPUT" { return token::OUTPUT; } 79<LDSCRIPT>"SEARCH_DIR" { return token::SEARCH_DIR; } 80<LDSCRIPT>"STARTUP" { return token::STARTUP; } 81 /* Format Commands */ 82<LDSCRIPT>"OUTPUT_FORMAT" { return token::OUTPUT_FORMAT; } 83<LDSCRIPT>"TARGET" { return token::TARGET; } 84 /* Misc Commands */ 85<LDSCRIPT>"ASSERT" { return token::ASSERT; } 86<LDSCRIPT>"EXTERN" { return token::EXTERN; } 87<LDSCRIPT>"FORCE_COMMON_ALLOCATION" { return token::FORCE_COMMON_ALLOCATION; } 88<LDSCRIPT>"INHIBIT_COMMON_ALLOCATION" { return token::INHIBIT_COMMON_ALLOCATION; } 89<LDSCRIPT>"INSERT" { return token::INSERT; } 90<LDSCRIPT>"NOCROSSREFS" { return token::NOCROSSREFS; } 91<LDSCRIPT>"OUTPUT_ARCH" { return token::OUTPUT_ARCH; } 92<LDSCRIPT>"LD_FEATURE" { return token::LD_FEATURE; } 93 /* Assignemnts */ 94<LDSCRIPT,EXPRESSION>"HIDDEN" { return token::HIDDEN; } 95<LDSCRIPT,EXPRESSION>"PROVIDE" { return token::PROVIDE; } 96<LDSCRIPT,EXPRESSION>"PROVIDE_HIDDEN" { return token::PROVIDE_HIDDEN; } 97 /* SECTIONS Command */ 98<LDSCRIPT>"SECTIONS" { return token::SECTIONS; } 99 /* MEMORY Command */ 100<LDSCRIPT>"MEMORY" { return token::MEMORY; } 101 /* PHDRS Command */ 102<LDSCRIPT>"PHDRS" { return token::PHDRS; } 103 /* Builtin Functions */ 104<EXPRESSION>"ABSOLUTE" { return token::ABSOLUTE; } 105<EXPRESSION>"ADDR" { return token::ADDR; } 106<LDSCRIPT,EXPRESSION>"ALIGN" { return token::ALIGN; } 107<EXPRESSION>"ALIGNOF" { return token::ALIGNOF; } 108<EXPRESSION>"BLOCK" { return token::BLOCK; } 109<EXPRESSION>"DATA_SEGMENT_ALIGN" { return token::DATA_SEGMENT_ALIGN; } 110<EXPRESSION>"DATA_SEGMENT_END" { return token::DATA_SEGMENT_END; } 111<EXPRESSION>"DATA_SEGMENT_RELRO_END" { return token::DATA_SEGMENT_RELRO_END; } 112<EXPRESSION>"DEFINED" { return token::DEFINED; } 113<EXPRESSION>"LENGTH" { return token::LENGTH; } 114<EXPRESSION>"LOADADDR" { return token::LOADADDR; } 115<EXPRESSION>"MAX" { return token::MAX; } 116<EXPRESSION>"MIN" { return token::MIN; } 117<EXPRESSION>"NEXT" { return token::NEXT; } 118<EXPRESSION>"ORIGIN" { return token::ORIGIN; } 119<EXPRESSION>"SEGMENT_START" { return token::SEGMENT_START; } 120<EXPRESSION>"SIZEOF" { return token::SIZEOF; } 121<EXPRESSION>"SIZEOF_HEADERS" { return token::SIZEOF_HEADERS; } 122<EXPRESSION>"CONSTANT" { return token::CONSTANT; } 123 /* Symbolic Constants */ 124<EXPRESSION>"MAXPAGESIZE" { return token::MAXPAGESIZE; } 125<EXPRESSION>"COMMONPAGESIZE" { return token::COMMONPAGESIZE; } 126 /* Input Section Description */ 127<LDSCRIPT>"EXCLUDE_FILE" { return token::EXCLUDE_FILE; } 128<LDSCRIPT>"KEEP" { return token::KEEP; } 129<LDSCRIPT>"SORT" { return token::SORT_BY_NAME; } 130<LDSCRIPT>"SORT_BY_NAME" { return token::SORT_BY_NAME; } 131<LDSCRIPT>"SORT_BY_ALIGNMENT" { return token::SORT_BY_ALIGNMENT; } 132<LDSCRIPT>"SORT_NONE" { return token::SORT_NONE; } 133<LDSCRIPT>"SORT_BY_INIT_PRIORITY" { return token::SORT_BY_INIT_PRIORITY; } 134 /* Output Section Data */ 135<LDSCRIPT>"BYTE" { return token::BYTE; } 136<LDSCRIPT>"SHORT" { return token::SHORT; } 137<LDSCRIPT>"LONG" { return token::LONG; } 138<LDSCRIPT>"QUAD" { return token::QUAD; } 139<LDSCRIPT>"SQUAD" { return token::SQUAD; } 140<LDSCRIPT>"FILL" { return token::FILL; } 141 /* Output Section Discarding */ 142<LDSCRIPT>"DISCARD" { return token::DISCARD; } 143 /* Output Section Keywords */ 144<LDSCRIPT>"CREATE_OBJECT_SYMBOLS" { return token::CREATE_OBJECT_SYMBOLS; } 145<LDSCRIPT>"CONSTRUCTORS" { return token::CONSTRUCTORS; } 146 /* Output Section Attributes */ 147 /* Output Section Type */ 148<LDSCRIPT,EXPRESSION>"NOLOAD" { return token::NOLOAD; } 149<LDSCRIPT,EXPRESSION>"DSECT" { return token::DSECT; } 150<LDSCRIPT,EXPRESSION>"COPY" { return token::COPY; } 151<LDSCRIPT,EXPRESSION>"INFO" { return token::INFO; } 152<LDSCRIPT,EXPRESSION>"OVERLAY" { return token::OVERLAY; } 153 /* Output Section LMA */ 154<LDSCRIPT>"AT" { return token::AT; } 155 /* Forced Input Alignment */ 156<LDSCRIPT>"SUBALIGN" { return token::SUBALIGN; } 157 /* Output Section Constraint */ 158<LDSCRIPT>"ONLY_IF_RO" { return token::ONLY_IF_RO; } 159<LDSCRIPT>"ONLY_IF_RW" { return token::ONLY_IF_RW; } 160 /* Operators */ 161<LDSCRIPT,EXPRESSION>"<<" { return token::LSHIFT; } 162<LDSCRIPT,EXPRESSION>">>" { return token::RSHIFT; } 163<LDSCRIPT,EXPRESSION>"==" { return token::EQ; } 164<LDSCRIPT,EXPRESSION>"!=" { return token::NE; } 165<LDSCRIPT,EXPRESSION>"<=" { return token::LE; } 166<LDSCRIPT,EXPRESSION>">=" { return token::GE; } 167<LDSCRIPT,EXPRESSION>"&&" { return token::LOGICAL_AND; } 168<LDSCRIPT,EXPRESSION>"||" { return token::LOGICAL_OR; } 169<LDSCRIPT,EXPRESSION>"+=" { return token::ADD_ASSIGN; } 170<LDSCRIPT,EXPRESSION>"-=" { return token::SUB_ASSIGN; } 171<LDSCRIPT,EXPRESSION>"*=" { return token::MUL_ASSIGN; } 172<LDSCRIPT,EXPRESSION>"/=" { return token::DIV_ASSIGN; } 173<LDSCRIPT,EXPRESSION>"&=" { return token::AND_ASSIGN; } 174<LDSCRIPT,EXPRESSION>"|=" { return token::OR_ASSIGN; } 175<LDSCRIPT,EXPRESSION>"<<=" { return token::LS_ASSIGN; } 176<LDSCRIPT,EXPRESSION>">>=" { return token::RS_ASSIGN; } 177<LDSCRIPT,EXPRESSION>"," { return static_cast<token_type>(*yytext); } 178<LDSCRIPT,EXPRESSION>"=" { return static_cast<token_type>(*yytext); } 179<LDSCRIPT,EXPRESSION>"?" { return static_cast<token_type>(*yytext); } 180<LDSCRIPT,EXPRESSION>":" { return static_cast<token_type>(*yytext); } 181<LDSCRIPT,EXPRESSION>"|" { return static_cast<token_type>(*yytext); } 182<LDSCRIPT,EXPRESSION>"^" { return static_cast<token_type>(*yytext); } 183<LDSCRIPT,EXPRESSION>"&" { return static_cast<token_type>(*yytext); } 184<LDSCRIPT,EXPRESSION>"<" { return static_cast<token_type>(*yytext); } 185<LDSCRIPT,EXPRESSION>">" { return static_cast<token_type>(*yytext); } 186<LDSCRIPT,EXPRESSION>"+" { return static_cast<token_type>(*yytext); } 187<LDSCRIPT,EXPRESSION>"-" { return static_cast<token_type>(*yytext); } 188<LDSCRIPT,EXPRESSION>"*" { return static_cast<token_type>(*yytext); } 189<LDSCRIPT,EXPRESSION>"/" { return static_cast<token_type>(*yytext); } 190<LDSCRIPT,EXPRESSION>"%" { return static_cast<token_type>(*yytext); } 191<LDSCRIPT,EXPRESSION>"!" { return static_cast<token_type>(*yytext); } 192<LDSCRIPT,EXPRESSION>"~" { return static_cast<token_type>(*yytext); } 193<LDSCRIPT,EXPRESSION>";" { return static_cast<token_type>(*yytext); } 194<LDSCRIPT,EXPRESSION>"(" { return static_cast<token_type>(*yytext); } 195<LDSCRIPT,EXPRESSION>")" { return static_cast<token_type>(*yytext); } 196<LDSCRIPT,EXPRESSION>"{" { return static_cast<token_type>(*yytext); } 197<LDSCRIPT,EXPRESSION>"}" { return static_cast<token_type>(*yytext); } 198 199 /* Numbers */ 200<LDSCRIPT,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? { 201 llvm::StringRef str(yytext, yyleng); 202 switch (str.back()) { 203 case 'k': 204 case 'K': 205 str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer); 206 yylval->integer *= 1024; 207 break; 208 case 'm': 209 case 'M': 210 str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer); 211 yylval->integer *= 1024 * 1024; 212 break; 213 default: 214 str.getAsInteger(0, yylval->integer); 215 break; 216 } 217 return token::INTEGER; 218} 219 220 /* Expression string */ 221<EXPRESSION>{FILENAMECHAR1}{SYMBOLCHARN}* { 222 const std::string& str = pScriptFile.createParserStr(yytext, yyleng); 223 yylval->string = &str; 224 return token::STRING; 225} 226 227 /* String */ 228<LDSCRIPT>{FILENAMECHAR1}{NOCFILENAMECHAR}* { 229 const std::string& str = pScriptFile.createParserStr(yytext, yyleng); 230 yylval->string = &str; 231 return token::STRING; 232} 233 234<LDSCRIPT,EXPRESSION>\"(\\.|[^\\"])*\" { 235 /*" c string literal */ 236 const std::string& str = pScriptFile.createParserStr(yytext, yyleng); 237 yylval->string = &str; 238 return token::STRING; 239} 240 241 /* -l namespec */ 242<LDSCRIPT>"-l"{FILENAMECHAR1}{NOCFILENAMECHAR}* { 243 const std::string& str = pScriptFile.createParserStr(yytext + 2, yyleng - 2); 244 yylval->string = &str; 245 return token::LNAMESPEC; 246} 247 248 /* WILDCHAR String */ 249<LDSCRIPT>{WILDCHAR}* { 250 if (yytext[0] == '/' && yytext[1] == '*') { 251 yyless (2); 252 enterComments(*yylloc); 253 } else { 254 const std::string& str = pScriptFile.createParserStr(yytext, yyleng); 255 yylval->string = &str; 256 return token::STRING; 257 } 258} 259 260 /* gobble up C comments */ 261<LDSCRIPT,EXPRESSION>"/*" { 262 enterComments(*yylloc); 263 yylloc->step(); 264} 265 266 /* gobble up white-spaces */ 267<LDSCRIPT,EXPRESSION>{WS}+ { 268 yylloc->step(); 269} 270 271 /* gobble up end-of-lines */ 272<LDSCRIPT,EXPRESSION>\n { 273 yylloc->lines(1); 274 yylloc->step(); 275} 276 277%% /* Additional Code */ 278 279namespace mcld { 280 281ScriptScanner::ScriptScanner(std::istream* yyin, std::ostream* yyout) 282 : yyFlexLexer(yyin, yyout), m_Kind(ScriptFile::Unknown) 283{ 284} 285 286ScriptScanner::~ScriptScanner() 287{ 288} 289 290void ScriptScanner::enterComments(ScriptParser::location_type& pLocation) 291{ 292 const int start_line = pLocation.begin.line; 293 const int start_col = pLocation.begin.column; 294 295 int ch = 0; 296 297 while (true) { 298 ch = yyinput(); 299 pLocation.columns(1); 300 301 while (ch != '*' && ch != EOF) { 302 if (ch == '\n') { 303 pLocation.lines(1); 304 } 305 306 ch = yyinput(); 307 pLocation.columns(1); 308 } 309 310 if (ch == '*') { 311 ch = yyinput(); 312 pLocation.columns(1); 313 314 while (ch == '*') { 315 ch = yyinput(); 316 pLocation.columns(1); 317 } 318 319 if (ch == '/') 320 break; 321 } 322 323 if (ch == '\n') 324 pLocation.lines(1); 325 326 if (ch == EOF) { 327 error(diag::err_unterminated_comment) << pLocation.begin.filename 328 << start_line 329 << start_col; 330 break; 331 } 332 } 333} 334 335void ScriptScanner::setLexState(ScriptFile::Kind pKind) 336{ 337 /* push the state into the top of stach */ 338 m_StateStack.push(pKind); 339 340 switch (pKind) { 341 case ScriptFile::LDScript: 342 BEGIN(LDSCRIPT); 343 break; 344 case ScriptFile::Expression: 345 BEGIN(EXPRESSION); 346 break; 347 case ScriptFile::VersionScript: 348 case ScriptFile::DynamicList: 349 default: 350 assert(0 && "Unsupported script type!"); 351 break; 352 } 353} 354 355void ScriptScanner::popLexState() 356{ 357 /* pop the last state */ 358 m_StateStack.pop(); 359 360 /* resume the appropriate state */ 361 if (!m_StateStack.empty()) { 362 switch (m_StateStack.top()) { 363 case ScriptFile::LDScript: 364 BEGIN(LDSCRIPT); 365 break; 366 case ScriptFile::Expression: 367 BEGIN(EXPRESSION); 368 break; 369 case ScriptFile::VersionScript: 370 case ScriptFile::DynamicList: 371 default: 372 assert(0 && "Unsupported script type!"); 373 break; 374 } 375 } 376} 377 378} /* namespace of mcld */ 379 380#ifdef yylex 381#undef yylex 382#endif 383 384int yyFlexLexer::yylex() 385{ 386 return 0; 387} 388 389