blob: 97bff76904332ac12bd27b0eca82cc2c26c9132d [file] [log] [blame]
/*===- 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;
}