mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
672 lines
22 KiB
Text
672 lines
22 KiB
Text
/* ###
|
|
* IP: GHIDRA
|
|
* NOTE: flex skeletons are NOT bound by flex's BSD license
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
%{
|
|
#include "slgh_compile.hh"
|
|
#include "slghparse.tab.hh"
|
|
#define yywrap() 1
|
|
#define YY_SKIP_YYWRAP
|
|
|
|
/* If we are building don't include unistd.h */
|
|
/* flex provides us with this macro for turning it off */
|
|
#ifdef _WIN32
|
|
#define YY_NO_UNISTD_H
|
|
static int isatty (int fildes) { return 0; }
|
|
#endif
|
|
|
|
struct FileStreamState {
|
|
YY_BUFFER_STATE lastbuffer; // Last lex buffer corresponding to the stream
|
|
FILE *file; // The NEW file stream
|
|
};
|
|
|
|
extern SleighCompile *slgh;
|
|
int4 last_preproc; // lex state before last preprocessing erasure
|
|
int4 actionon; // whether '&' '|' and '^' are treated as actionon in pattern section
|
|
int4 withsection = 0; // whether we are between the 'with' keyword and its open brace '{'
|
|
vector<FileStreamState> filebuffers;
|
|
vector<int4> ifstack;
|
|
int4 negative_if = -1;
|
|
|
|
void preproc_error(const string &err)
|
|
|
|
{
|
|
slgh->reportError((const Location *)0, err);
|
|
cerr << "Terminating due to error in preprocessing" << endl;
|
|
exit(1);
|
|
}
|
|
|
|
void check_to_endofline(istream &s)
|
|
|
|
{ // Make sure there is nothing to the end of the line
|
|
s >> ws;
|
|
if (!s.eof())
|
|
if (s.peek() != '#')
|
|
preproc_error("Extra characters in preprocessor directive");
|
|
}
|
|
|
|
string read_identifier(istream &s)
|
|
|
|
{ // Read a proper identifier from the stream
|
|
s >> ws; // Skip any whitespace
|
|
string res;
|
|
while(!s.eof()) {
|
|
char tok = s.peek();
|
|
if (isalnum(tok) || (tok == '_')) {
|
|
s >> tok;
|
|
res += tok;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void preprocess_string(istream &s,string &res)
|
|
|
|
{ // Grab string surrounded by double quotes from stream or call preprocess_error
|
|
int4 val;
|
|
|
|
s >> ws; // Skip any whitespace
|
|
val = s.get();
|
|
if (val != '\"')
|
|
preproc_error("Expecting double quoted string");
|
|
val = s.get();
|
|
while((val != '\"')&&(val>=0)) {
|
|
res += (char)val;
|
|
val = s.get();
|
|
}
|
|
if (val != '\"')
|
|
preproc_error("Missing terminating double quote");
|
|
}
|
|
|
|
extern int4 preprocess_if(istream &s); // Forward declaration for recursion
|
|
|
|
int4 read_defined_operator(istream &s)
|
|
|
|
{ // We have seen a -defined- keyword in an if or elif
|
|
// Read macro name used as input, return 1 if it is defined
|
|
char tok = ' ';
|
|
string macroname;
|
|
|
|
s >> ws >> tok;
|
|
if (tok != '(')
|
|
preproc_error("Badly formed \"defined\" operator");
|
|
macroname = read_identifier(s);
|
|
int4 res = slgh->getPreprocValue(macroname,macroname) ? 1 : 0;
|
|
s >> ws >> tok;
|
|
if (tok != ')')
|
|
preproc_error("Badly formed \"defined\" operator");
|
|
return res;
|
|
}
|
|
|
|
int4 read_boolean_clause(istream &s)
|
|
|
|
{ // We have seen an if or elif
|
|
// return 1 if condition is true or else 0
|
|
s >> ws;
|
|
if (s.peek()=='(') { // Parenthetical expression spawns recursion
|
|
int4 val = s.get();
|
|
int4 res = preprocess_if(s);
|
|
s >> ws;
|
|
val = s.get();
|
|
if (val != ')')
|
|
preproc_error("Unbalanced parentheses");
|
|
return res;
|
|
}
|
|
// Otherwise we must have a normal comparison operator
|
|
string lhs,rhs,comp;
|
|
|
|
if (s.peek()=='\"') // Read left-hand side string
|
|
preprocess_string(s,lhs);
|
|
else {
|
|
lhs = read_identifier(s);
|
|
if (lhs == "defined")
|
|
return read_defined_operator(s);
|
|
if (!slgh->getPreprocValue(lhs,lhs))
|
|
preproc_error("Could not find preprocessor macro "+lhs);
|
|
}
|
|
|
|
char tok;
|
|
s >> tok; // Read comparison symbol
|
|
comp += tok;
|
|
s >> tok;
|
|
comp += tok;
|
|
|
|
s >> ws;
|
|
if (s.peek()=='\"') // Read right-hand side string
|
|
preprocess_string(s,rhs);
|
|
else {
|
|
rhs = read_identifier(s);
|
|
if (!slgh->getPreprocValue(rhs,rhs))
|
|
preproc_error("Could not find preprocessor macro "+rhs);
|
|
}
|
|
|
|
if (comp == "==")
|
|
return (lhs == rhs) ? 1 : 0;
|
|
else if (comp=="!=")
|
|
return (lhs != rhs) ? 1 : 0;
|
|
else
|
|
preproc_error("Syntax error in condition");
|
|
return 0;
|
|
}
|
|
|
|
int4 preprocess_if(istream &s)
|
|
|
|
{
|
|
int4 res = read_boolean_clause(s);
|
|
s >> ws;
|
|
while((!s.eof())&&(s.peek()!=')')) {
|
|
string boolop;
|
|
char tok;
|
|
s >> tok;
|
|
boolop += tok;
|
|
s >> tok;
|
|
boolop += tok;
|
|
int4 res2 = read_boolean_clause(s);
|
|
if (boolop == "&&")
|
|
res = res & res2;
|
|
else if (boolop == "||")
|
|
res = res | res2;
|
|
else if (boolop == "^^")
|
|
res = res ^ res2;
|
|
else
|
|
preproc_error("Syntax error in expression");
|
|
s >> ws;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void expand_preprocmacros(string &str)
|
|
|
|
{
|
|
string::size_type pos;
|
|
string::size_type lastpos = 0;
|
|
pos = str.find("$(",lastpos);
|
|
if (pos == string::npos)
|
|
return;
|
|
string res;
|
|
for(;;) {
|
|
if (pos == string::npos) {
|
|
res += str.substr(lastpos);
|
|
str = res;
|
|
return;
|
|
}
|
|
else {
|
|
res += str.substr(lastpos,(pos-lastpos));
|
|
string::size_type endpos = str.find(')',pos+2);
|
|
if (endpos == string::npos) {
|
|
preproc_error("Unterminated macro in string");
|
|
break;
|
|
}
|
|
string macro = str.substr(pos+2, endpos - (pos+2));
|
|
string value;
|
|
if (!slgh->getPreprocValue(macro,value)) {
|
|
preproc_error("Unknown preprocessing macro "+macro);
|
|
break;
|
|
}
|
|
res += value;
|
|
lastpos = endpos + 1;
|
|
}
|
|
pos = str.find("$(",lastpos);
|
|
}
|
|
}
|
|
|
|
int4 preprocess(int4 cur_state,int4 blank_state)
|
|
|
|
{
|
|
string str(yytext);
|
|
string::size_type pos = str.find('#');
|
|
if (pos != string::npos)
|
|
str.erase(pos);
|
|
istringstream s(str);
|
|
string type;
|
|
|
|
if (cur_state != blank_state)
|
|
last_preproc = cur_state;
|
|
|
|
s.get(); // Skip the preprocessor marker
|
|
s >> type;
|
|
if (type == "include") {
|
|
if (negative_if == -1) { // Not in the middle of a false if clause
|
|
filebuffers.push_back(FileStreamState()); // Save state of current file
|
|
filebuffers.back().lastbuffer = YY_CURRENT_BUFFER;
|
|
filebuffers.back().file = (FILE *)0;
|
|
s >> ws;
|
|
string fname;
|
|
preprocess_string(s,fname);
|
|
expand_preprocmacros(fname);
|
|
slgh->parseFromNewFile(fname);
|
|
fname = slgh->grabCurrentFilePath();
|
|
yyin = fopen(fname.c_str(),"r");
|
|
if (yyin == (FILE *)0)
|
|
preproc_error("Could not open included file "+fname);
|
|
filebuffers.back().file = yyin;
|
|
yy_switch_to_buffer( yy_create_buffer(yyin, YY_BUF_SIZE) );
|
|
check_to_endofline(s);
|
|
}
|
|
}
|
|
else if (type == "define") {
|
|
if (negative_if == -1) {
|
|
string varname;
|
|
string value;
|
|
varname = read_identifier(s); // Get name of variable being defined
|
|
s >> ws;
|
|
if (s.peek() == '\"')
|
|
preprocess_string(s,value);
|
|
else
|
|
value = read_identifier(s);
|
|
if (varname.size()==0)
|
|
preproc_error("Error in preprocessor definition");
|
|
slgh->setPreprocValue(varname,value);
|
|
check_to_endofline(s);
|
|
}
|
|
}
|
|
else if (type == "undef") {
|
|
if (negative_if == -1) {
|
|
string varname;
|
|
varname = read_identifier(s); // Name of variable to undefine
|
|
if (varname.size()==0)
|
|
preproc_error("Error in preprocessor undef");
|
|
slgh->undefinePreprocValue(varname);
|
|
check_to_endofline(s);
|
|
}
|
|
}
|
|
else if (type=="ifdef") {
|
|
string varname;
|
|
varname = read_identifier(s);
|
|
if (varname.size()==0)
|
|
preproc_error("Error in preprocessor ifdef");
|
|
string value;
|
|
int4 truth = (slgh->getPreprocValue(varname,value)) ? 1 : 0;
|
|
ifstack.push_back(truth);
|
|
check_to_endofline(s);
|
|
}
|
|
else if (type=="ifndef") {
|
|
string varname;
|
|
varname = read_identifier(s);
|
|
if (varname.size()==0)
|
|
preproc_error("Error in preprocessor ifndef");
|
|
string value;
|
|
int4 truth = (slgh->getPreprocValue(varname,value)) ? 0 : 1; // flipped from ifdef
|
|
ifstack.push_back(truth);
|
|
check_to_endofline(s);
|
|
}
|
|
else if (type=="if") {
|
|
int4 truth = preprocess_if(s);
|
|
if (!s.eof())
|
|
preproc_error("Unbalanced parentheses");
|
|
ifstack.push_back(truth);
|
|
}
|
|
else if (type=="elif") {
|
|
if (ifstack.empty())
|
|
preproc_error("elif without preceding if");
|
|
if ((ifstack.back()&2)!=0) // We have already seen an else clause
|
|
preproc_error("elif follows else");
|
|
if ((ifstack.back()&4)!=0) // We have already seen a true elif clause
|
|
ifstack.back() = 4; // don't include any other elif clause
|
|
else if ((ifstack.back()&1)!=0) // Last clause was a true if
|
|
ifstack.back() = 4; // don't include this elif
|
|
else {
|
|
int4 truth = preprocess_if(s);
|
|
if (!s.eof())
|
|
preproc_error("Unbalanced parentheses");
|
|
if (truth==0)
|
|
ifstack.back() = 0;
|
|
else
|
|
ifstack.back() = 5;
|
|
}
|
|
}
|
|
else if (type=="endif") {
|
|
if (ifstack.empty())
|
|
preproc_error("preprocessing endif without matching if");
|
|
ifstack.pop_back();
|
|
check_to_endofline(s);
|
|
}
|
|
else if (type=="else") {
|
|
if (ifstack.empty())
|
|
preproc_error("preprocessing else without matching if");
|
|
if ((ifstack.back()&2)!=0)
|
|
preproc_error("second else for one if");
|
|
if ((ifstack.back()&4)!=0) // Seen a true elif clause before
|
|
ifstack.back() = 6;
|
|
else if (ifstack.back()==0)
|
|
ifstack.back() = 3;
|
|
else
|
|
ifstack.back() = 2;
|
|
check_to_endofline(s);
|
|
}
|
|
else
|
|
preproc_error("Unknown preprocessing directive: "+type);
|
|
|
|
if (negative_if >= 0) { // We were in a false state
|
|
if (negative_if+1 < ifstack.size())
|
|
return blank_state; // false state is still deep in stack
|
|
else // false state is popped off or is current and changed
|
|
negative_if = -1;
|
|
}
|
|
if (ifstack.empty()) return last_preproc;
|
|
if ((ifstack.back()&1)==0) {
|
|
negative_if = ifstack.size()-1;
|
|
return blank_state;
|
|
}
|
|
return last_preproc;
|
|
}
|
|
|
|
void preproc_macroexpand(void)
|
|
|
|
{
|
|
filebuffers.push_back(FileStreamState());
|
|
filebuffers.back().lastbuffer = YY_CURRENT_BUFFER;
|
|
filebuffers.back().file = (FILE *)0;
|
|
string macro(yytext);
|
|
macro.erase(0,2);
|
|
macro.erase(macro.size()-1,1);
|
|
string value;
|
|
if (!slgh->getPreprocValue(macro,value))
|
|
preproc_error("Unknown preprocessing macro "+macro);
|
|
yy_switch_to_buffer( yy_scan_string( value.c_str() ) );
|
|
slgh->parsePreprocMacro();
|
|
}
|
|
|
|
int4 find_symbol(void) {
|
|
string * newstring = new string(yytext);
|
|
SleighSymbol *sym = slgh->findSymbol(*newstring);
|
|
if (sym == (SleighSymbol *)0) {
|
|
yylval.str = newstring;
|
|
return STRING;
|
|
}
|
|
delete newstring;
|
|
switch(sym->getType()) {
|
|
case SleighSymbol::section_symbol:
|
|
yylval.sectionsym = (SectionSymbol *)sym;
|
|
return SECTIONSYM;
|
|
case SleighSymbol::space_symbol:
|
|
yylval.spacesym = (SpaceSymbol *)sym;
|
|
return SPACESYM;
|
|
case SleighSymbol::token_symbol:
|
|
yylval.tokensym = (TokenSymbol *)sym;
|
|
return TOKENSYM;
|
|
case SleighSymbol::userop_symbol:
|
|
yylval.useropsym = (UserOpSymbol *)sym;
|
|
return USEROPSYM;
|
|
case SleighSymbol::value_symbol:
|
|
yylval.valuesym = (ValueSymbol *)sym;
|
|
return VALUESYM;
|
|
case SleighSymbol::valuemap_symbol:
|
|
yylval.valuemapsym = (ValueMapSymbol *)sym;
|
|
return VALUEMAPSYM;
|
|
case SleighSymbol::name_symbol:
|
|
yylval.namesym = (NameSymbol *)sym;
|
|
return NAMESYM;
|
|
case SleighSymbol::varnode_symbol:
|
|
yylval.varsym = (VarnodeSymbol *)sym;
|
|
return VARSYM;
|
|
case SleighSymbol::bitrange_symbol:
|
|
yylval.bitsym = (BitrangeSymbol *)sym;
|
|
return BITSYM;
|
|
case SleighSymbol::varnodelist_symbol:
|
|
yylval.varlistsym = (VarnodeListSymbol *)sym;
|
|
return VARLISTSYM;
|
|
case SleighSymbol::operand_symbol:
|
|
yylval.operandsym = (OperandSymbol *)sym;
|
|
return OPERANDSYM;
|
|
case SleighSymbol::start_symbol:
|
|
yylval.startsym = (StartSymbol *)sym;
|
|
return STARTSYM;
|
|
case SleighSymbol::end_symbol:
|
|
yylval.endsym = (EndSymbol *)sym;
|
|
return ENDSYM;
|
|
case SleighSymbol::subtable_symbol:
|
|
yylval.subtablesym = (SubtableSymbol *)sym;
|
|
return SUBTABLESYM;
|
|
case SleighSymbol::macro_symbol:
|
|
yylval.macrosym = (MacroSymbol *)sym;
|
|
return MACROSYM;
|
|
case SleighSymbol::label_symbol:
|
|
yylval.labelsym = (LabelSymbol *)sym;
|
|
return LABELSYM;
|
|
case SleighSymbol::epsilon_symbol:
|
|
yylval.specsym = (SpecificSymbol *)sym;
|
|
return SPECSYM;
|
|
case SleighSymbol::context_symbol:
|
|
yylval.contextsym = (ContextSymbol *)sym;
|
|
return CONTEXTSYM;
|
|
case SleighSymbol::dummy_symbol:
|
|
break;
|
|
}
|
|
return -1; // Should never reach here
|
|
}
|
|
|
|
int4 scan_number(char *numtext,YYSTYPE *lval,bool signednum)
|
|
|
|
{
|
|
uintb val;
|
|
if (numtext[0] == '0' && numtext[1] == 'b') {
|
|
val = 0;
|
|
numtext += 2;
|
|
while ((*numtext) != 0) {
|
|
val <<= 1;
|
|
if (*numtext == '1') {
|
|
val |= 1;
|
|
}
|
|
++numtext;
|
|
}
|
|
} else {
|
|
istringstream s(numtext);
|
|
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
s >> val;
|
|
if (!s)
|
|
return BADINTEGER;
|
|
}
|
|
if (signednum) {
|
|
lval->big = new intb(val);
|
|
return INTB;
|
|
}
|
|
lval->i = new uintb(val);
|
|
return INTEGER;
|
|
}
|
|
|
|
%}
|
|
|
|
%x defblock
|
|
%x macroblock
|
|
%x print
|
|
%x pattern
|
|
%x sem
|
|
%x preproc
|
|
%%
|
|
|
|
^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(INITIAL,preproc) ); }
|
|
\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
[(),\-] { yylval.ch = yytext[0]; return yytext[0]; }
|
|
\: { BEGIN(print); slgh->calcContextLayout(); yylval.ch = yytext[0]; return yytext[0]; }
|
|
\{ { BEGIN(sem); yylval.ch = yytext[0]; return yytext[0]; }
|
|
#.*$
|
|
[\r\ \t\v]+
|
|
\n { slgh->nextLine(); }
|
|
macro { BEGIN(macroblock); return MACRO_KEY; }
|
|
define { BEGIN(defblock); return DEFINE_KEY; }
|
|
attach { BEGIN(defblock); slgh->calcContextLayout(); return ATTACH_KEY; }
|
|
with { BEGIN(pattern); withsection = 1; slgh->calcContextLayout(); return WITH_KEY; }
|
|
[a-zA-Z_.][a-zA-Z0-9_.]* { return find_symbol(); }
|
|
. { return yytext[0]; }
|
|
|
|
<macroblock>^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(macroblock,preproc) ); }
|
|
<macroblock>\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
<macroblock>[(),] { yylval.ch = yytext[0]; return yytext[0]; }
|
|
<macroblock>\{ { BEGIN(sem); return yytext[0]; }
|
|
<macroblock>[a-zA-Z_.][a-zA-Z0-9_.]* { yylval.str = new string(yytext); return STRING; }
|
|
<macroblock>[\r\ \t\v]+
|
|
<macroblock>\n { slgh->nextLine(); }
|
|
<macroblock>. { return yytext[0]; }
|
|
|
|
<defblock>^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(defblock,preproc) ); }
|
|
<defblock>\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
<defblock>[(),=:\[\]] { yylval.ch = yytext[0]; return yytext[0]; }
|
|
<defblock>\; { BEGIN(INITIAL); yylval.ch = yytext[0]; return yytext[0]; }
|
|
<defblock>space { return SPACE_KEY; }
|
|
<defblock>type { return TYPE_KEY; }
|
|
<defblock>ram_space { return RAM_KEY; }
|
|
<defblock>default { return DEFAULT_KEY; }
|
|
<defblock>register_space { return REGISTER_KEY; }
|
|
<defblock>token { return TOKEN_KEY; }
|
|
<defblock>context { return CONTEXT_KEY; }
|
|
<defblock>bitrange { return BITRANGE_KEY; }
|
|
<defblock>signed { return SIGNED_KEY; }
|
|
<defblock>noflow { return NOFLOW_KEY; }
|
|
<defblock>hex { return HEX_KEY; }
|
|
<defblock>dec { return DEC_KEY; }
|
|
<defblock>endian { return ENDIAN_KEY; }
|
|
<defblock>alignment { return ALIGN_KEY; }
|
|
<defblock>big { return BIG_KEY; }
|
|
<defblock>little { return LITTLE_KEY; }
|
|
<defblock>size { return SIZE_KEY; }
|
|
<defblock>wordsize { return WORDSIZE_KEY; }
|
|
<defblock>offset { return OFFSET_KEY; }
|
|
<defblock>names { return NAMES_KEY; }
|
|
<defblock>values { return VALUES_KEY; }
|
|
<defblock>variables { return VARIABLES_KEY; }
|
|
<defblock>pcodeop { return PCODEOP_KEY; }
|
|
<defblock>#.*$
|
|
<defblock>[a-zA-Z_.][a-zA-Z0-9_.]* { return find_symbol(); }
|
|
<defblock>[0-9]|[1-9][0-9]+ { return scan_number(yytext,&yylval,false); }
|
|
<defblock>0x[0-9a-fA-F]+ { return scan_number(yytext,&yylval,false); }
|
|
<defblock>0b[01]+ { return scan_number(yytext,&yylval,false); }
|
|
<defblock>\"([^\"]|\"\")*\" { yylval.str = new string(yytext+1,strlen(yytext)-2); return STRING; }
|
|
<defblock>[\r\ \t\v]+
|
|
<defblock>\n { slgh->nextLine(); }
|
|
<defblock>. { return yytext[0]; }
|
|
|
|
|
|
<print>^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(print,preproc) ); }
|
|
<print>\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
<print>[~!@#$%&*()\-=+\[\]{}|;:<>?,/0-9] { yylval.ch = yytext[0]; return CHAR; }
|
|
<print>\^ { yylval.ch = '^'; return '^'; }
|
|
<print>is { BEGIN(pattern); actionon=0; return IS_KEY; }
|
|
<print>[a-zA-Z_.][a-zA-Z0-9_.]* { yylval.str = new string(yytext); return SYMBOLSTRING; }
|
|
<print>\"([^\"]|\"\")*\" { yylval.str = new string(yytext+1,strlen(yytext)-2); return STRING; }
|
|
<print>[\r\ \t\v]+ { yylval.ch = ' '; return ' '; }
|
|
<print>\n { slgh->nextLine(); return ' '; }
|
|
<print>. { return yytext[0]; }
|
|
|
|
<pattern>^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(pattern,preproc) ); }
|
|
<pattern>\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
<pattern>\{ { BEGIN((withsection==1) ? INITIAL:sem); withsection=0; yylval.ch = yytext[0]; return yytext[0]; }
|
|
<pattern>unimpl { BEGIN(INITIAL); return OP_UNIMPL; }
|
|
<pattern>globalset { return GLOBALSET_KEY; }
|
|
<pattern>\>\> { return OP_RIGHT; }
|
|
<pattern>\<\< { return OP_LEFT; }
|
|
<pattern>\!\= { return OP_NOTEQUAL; }
|
|
<pattern>\<\= { return OP_LESSEQUAL; }
|
|
<pattern>\>\= { return OP_GREATEQUAL; }
|
|
<pattern>\$and { return OP_AND; }
|
|
<pattern>\$or { return OP_OR; }
|
|
<pattern>\$xor { return OP_XOR; }
|
|
<pattern>\.\.\. { return ELLIPSIS_KEY; }
|
|
<pattern>\[ { actionon = 1; yylval.ch = yytext[0]; return yytext[0]; }
|
|
<pattern>\] { actionon = 0; yylval.ch = yytext[0]; return yytext[0]; }
|
|
<pattern>\& { yylval.ch = yytext[0]; return (actionon==0) ? yytext[0] : OP_AND; }
|
|
<pattern>\| { yylval.ch = yytext[0]; return (actionon==0) ? yytext[0] : OP_OR; }
|
|
<pattern>\^ { return OP_XOR; }
|
|
<pattern>[=(),:;+\-*/~<>] { yylval.ch = yytext[0]; return yytext[0]; }
|
|
<pattern>#.*$
|
|
<pattern>[a-zA-Z_.][a-zA-Z0-9_.]* { return find_symbol(); }
|
|
<pattern>[0-9]|[1-9][0-9]+ { return scan_number(yytext,&yylval,true); }
|
|
<pattern>0x[0-9a-fA-F]+ { return scan_number(yytext,&yylval,true); }
|
|
<pattern>0b[01]+ { return scan_number(yytext,&yylval,true); }
|
|
<pattern>[\r\ \t\v]+
|
|
<pattern>\n { slgh->nextLine(); }
|
|
<pattern>. { return yytext[0]; }
|
|
|
|
<sem>^@[^\n]*\n? { slgh->nextLine(); BEGIN( preprocess(sem,preproc) ); }
|
|
<sem>\$\([a-zA-Z0-9_.][a-zA-Z0-9_.]*\) { preproc_macroexpand(); }
|
|
<sem>\} { BEGIN(INITIAL); yylval.ch = yytext[0]; return yytext[0]; }
|
|
<sem>\|\| { return OP_BOOL_OR; }
|
|
<sem>\&\& { return OP_BOOL_AND; }
|
|
<sem>\^\^ { return OP_BOOL_XOR; }
|
|
<sem>\>\> { return OP_RIGHT; }
|
|
<sem>\<\< { return OP_LEFT; }
|
|
<sem>\=\= { return OP_EQUAL; }
|
|
<sem>\!\= { return OP_NOTEQUAL; }
|
|
<sem>\<\= { return OP_LESSEQUAL; }
|
|
<sem>\>\= { return OP_GREATEQUAL; }
|
|
<sem>s\/ { return OP_SDIV; }
|
|
<sem>s\% { return OP_SREM; }
|
|
<sem>s\>\> { return OP_SRIGHT; }
|
|
<sem>s\< { return OP_SLESS; }
|
|
<sem>s\> { return OP_SGREAT; }
|
|
<sem>s\<\= { return OP_SLESSEQUAL; }
|
|
<sem>s\>\= { return OP_SGREATEQUAL; }
|
|
<sem>f\+ { return OP_FADD; }
|
|
<sem>f\- { return OP_FSUB; }
|
|
<sem>f\* { return OP_FMULT; }
|
|
<sem>f\/ { return OP_FDIV; }
|
|
<sem>f\=\= { return OP_FEQUAL; }
|
|
<sem>f\!\= { return OP_FNOTEQUAL; }
|
|
<sem>f\< { return OP_FLESS; }
|
|
<sem>f\> { return OP_FGREAT; }
|
|
<sem>f\<\= { return OP_FLESSEQUAL; }
|
|
<sem>f\>\= { return OP_FGREATEQUAL; }
|
|
<sem>zext { return OP_ZEXT; }
|
|
<sem>carry { return OP_CARRY; }
|
|
<sem>borrow { return OP_BORROW; }
|
|
<sem>sext { return OP_SEXT; }
|
|
<sem>scarry { return OP_SCARRY; }
|
|
<sem>sborrow { return OP_SBORROW; }
|
|
<sem>nan { return OP_NAN; }
|
|
<sem>abs { return OP_ABS; }
|
|
<sem>sqrt { return OP_SQRT; }
|
|
<sem>ceil { return OP_CEIL; }
|
|
<sem>floor { return OP_FLOOR; }
|
|
<sem>round { return OP_ROUND; }
|
|
<sem>int2float { return OP_INT2FLOAT; }
|
|
<sem>float2float { return OP_FLOAT2FLOAT; }
|
|
<sem>trunc { return OP_TRUNC; }
|
|
<sem>cpool { return OP_CPOOLREF; }
|
|
<sem>newobject { return OP_NEW; }
|
|
<sem>popcount { return OP_POPCOUNT; }
|
|
<sem>if { return IF_KEY; }
|
|
<sem>goto { return GOTO_KEY; }
|
|
<sem>call { return CALL_KEY; }
|
|
<sem>return { return RETURN_KEY; }
|
|
<sem>delayslot { return DELAYSLOT_KEY; }
|
|
<sem>crossbuild { return CROSSBUILD_KEY; }
|
|
<sem>export { return EXPORT_KEY; }
|
|
<sem>build { return BUILD_KEY; }
|
|
<sem>local { return LOCAL_KEY; }
|
|
<sem>[=(),:\[\];!&|^+\-*/%~<>] { yylval.ch = yytext[0]; return yytext[0]; }
|
|
<sem>#.*$
|
|
<sem>[a-zA-Z_.][a-zA-Z0-9_.]* { return find_symbol(); }
|
|
<sem>[0-9]|[1-9][0-9]+ { return scan_number(yytext,&yylval,false); }
|
|
<sem>0x[0-9a-fA-F]+ { return scan_number(yytext,&yylval,false); }
|
|
<sem>0b[01]+ { return scan_number(yytext,&yylval,false); }
|
|
<sem>[\r\ \t\v]+
|
|
<sem>\n { slgh->nextLine(); }
|
|
<sem>. { return yytext[0]; }
|
|
|
|
<preproc>^@.*\n? { slgh->nextLine(); BEGIN( preprocess(preproc,preproc) ); }
|
|
<preproc>^.*\n { slgh->nextLine(); }
|
|
|
|
<<EOF>> { yy_delete_buffer( YY_CURRENT_BUFFER );
|
|
if (filebuffers.empty())
|
|
yyterminate();
|
|
yy_switch_to_buffer( filebuffers.back().lastbuffer );
|
|
FILE *curfile = filebuffers.back().file;
|
|
if (curfile != (FILE *)0)
|
|
fclose(curfile);
|
|
filebuffers.pop_back();
|
|
slgh->parseFileFinished();
|
|
}
|