X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.lex;h=0fc43d00445ed1bd3f5881bb047b091f04423282;hb=31264d72ca126a7ad645192145c94daf4d72e2a7;hp=d27496983af877116d40853c61f5e2e6bef9b4bf;hpb=0a5bc62ebb4a2123b3d20d40a49bd363a75d0ff9;p=fw%2Fsdcc diff --git a/src/SDCC.lex b/src/SDCC.lex index d2749698..0fc43d00 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -1,29 +1,30 @@ /*----------------------------------------------------------------------- - SDCC.lex - lexical analyser for use with sdcc ( a freeware compiler for - 8/16 bit microcontrollers) + SDCC.lex - lexical analyser for use with sdcc (free open source + compiler for 8/16 bit microcontrollers) Written by : Sandeep Dutta . sandeep.dutta@usa.net (1997) - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ +B [0-1] D [0-9] -L [a-zA-Z_] +L [a-zA-Z_$] H [a-fA-F0-9] E [Ee][+-]?{D}+ FS (f|F|l|L) @@ -35,93 +36,140 @@ IS (u|U|l|L)* #include #include "common.h" #include "newalloc.h" -#include "dbuf.h" +#include "dbuf_string.h" #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\ check_type()) -extern int lineno, column; +#define TKEYWORDSDCC(token) return (options.std_sdcc && isTargetKeyword(yytext)\ + ? token : check_type()) + +#define TKEYWORD99(token) return (options.std_c99 ? token : check_type()) + extern char *filename; +extern int lineno; +int column = 0; /* current column */ /* global definitions */ -char *currFname; -int mylineno = 1; +char *lexFilename; +int lexLineno = 1; /* local definitions */ -static struct dbuf_s asmbuff; +static struct dbuf_s asmbuff; /* reusable _asm buffer */ /* forward declarations */ -static char *stringLiteral(void); +int yyerror(char *s); +static const char *stringLiteral(void); static void count(void); -static int process_pragma(char *); +static void count_char(int); +static int process_pragma(const char *); static int check_type(void); -static int isTargetKeyword(char *s); -static int checkCurrFile(char *s); +static int isTargetKeyword(const char *s); +static int checkCurrFile(const char *s); %} %x asm %% -"_asm" { +_?"_asm" { count(); - assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL); - dbuf_init(&asmbuff, INITIAL_INLINEASM); + if (!options.std_sdcc && yytext[1] != '_') + return check_type(); + if (asmbuff.buf == NULL) + dbuf_init(&asmbuff, INITIAL_INLINEASM); + else + dbuf_set_length(&asmbuff, 0); + BEGIN(asm); } -"_endasm" { +_?"_endasm" { count(); - yylval.yyinline = dbuf_c_str(&asmbuff); - dbuf_detach(&asmbuff); - BEGIN(INITIAL); - return (INLINEASM); + if (!options.std_sdcc && yytext[1] != '_') + { + dbuf_append_str(&asmbuff, yytext); + } + else + { + yylval.yyinline = dbuf_c_str(&asmbuff); + BEGIN(INITIAL); + return (INLINEASM); + } } \n { count(); - dbuf_append(&asmbuff, yytext, 1); + dbuf_append_char(&asmbuff, *yytext); } . { - dbuf_append(&asmbuff, yytext, 1); + dbuf_append_char(&asmbuff, *yytext); } -"at" { count(); TKEYWORD(AT) ; } -"auto" { count(); return(AUTO); } -"bit" { count(); TKEYWORD(BIT) ; } +"at" { count(); TKEYWORDSDCC(AT); } +"__at" { count(); TKEYWORD(AT); } +"auto" { count(); return(AUTO); } +"bit" { count(); TKEYWORDSDCC(BIT); } +"__bit" { count(); TKEYWORD(BIT); } "break" { count(); return(BREAK); } "case" { count(); return(CASE); } "char" { count(); return(CHAR); } -"code" { count(); TKEYWORD(CODE); } +"code" { count(); TKEYWORDSDCC(CODE); } +"__code" { count(); TKEYWORD(CODE); } "const" { count(); return(CONST); } "continue" { count(); return(CONTINUE); } -"critical" { count(); TKEYWORD(CRITICAL); } -"data" { count(); TKEYWORD(DATA); } +"critical" { count(); TKEYWORDSDCC(CRITICAL); } +"__critical" { count(); TKEYWORD(CRITICAL); } +"data" { count(); TKEYWORDSDCC(DATA); } +"__data" { count(); TKEYWORD(DATA); } "default" { count(); return(DEFAULT); } "do" { count(); return(DO); } "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); } "else" { count(); return(ELSE); } "enum" { count(); return(ENUM); } "extern" { count(); return(EXTERN); } -"far" { count(); TKEYWORD(XDATA); } -"eeprom" { count(); TKEYWORD(EEPROM); } +"far" { count(); TKEYWORDSDCC(XDATA); } +"__far" { count(); TKEYWORD(XDATA); } +"eeprom" { count(); TKEYWORDSDCC(EEPROM); } +"__eeprom" { count(); TKEYWORD(EEPROM); } "float" { count(); return(FLOAT); } -"flash" { count(); TKEYWORD(CODE);} +"fixed16x16" { count(); TKEYWORDSDCC(FIXED16X16); } +"__fixed16x16" { count(); TKEYWORD(FIXED16X16); } +"flash" { count(); TKEYWORDSDCC(CODE); } +"__flash" { count(); TKEYWORD(CODE); } "for" { count(); return(FOR); } -"goto" { count(); return(GOTO); } -"idata" { count(); TKEYWORD(IDATA);} +"goto" { count(); return(GOTO); } +"idata" { count(); TKEYWORDSDCC(IDATA); } +"__idata" { count(); TKEYWORD(IDATA); } "if" { count(); return(IF); } "int" { count(); return(INT); } -"interrupt" { count(); return(INTERRUPT);} -"nonbanked" { count(); TKEYWORD(NONBANKED);} -"banked" { count(); TKEYWORD(BANKED);} -"long" { count(); return(LONG); } -"near" { count(); TKEYWORD(DATA);} -"pdata" { count(); TKEYWORD(PDATA); } -"reentrant" { count(); TKEYWORD(REENTRANT);} +"interrupt" { count(); TKEYWORDSDCC(INTERRUPT); } +"__interrupt" { count(); TKEYWORD(INTERRUPT); } +"nonbanked" { count(); TKEYWORDSDCC(NONBANKED); } +"__nonbanked" { count(); TKEYWORD(NONBANKED); } +"banked" { count(); TKEYWORDSDCC(BANKED); } +"__banked" { count(); TKEYWORD(BANKED); } +"long" { count(); return(LONG); } +"near" { count(); TKEYWORDSDCC(DATA); } +"__near" { count(); TKEYWORD(DATA); } +"pdata" { count(); TKEYWORDSDCC(PDATA); } +"__pdata" { count(); TKEYWORD(PDATA); } +"reentrant" { count(); TKEYWORDSDCC(REENTRANT); } +"__reentrant" { count(); TKEYWORD(REENTRANT); } +"shadowregs" { count(); TKEYWORDSDCC(SHADOWREGS); } +"__shadowregs" { count(); TKEYWORD(SHADOWREGS); } +"wparam" { count(); TKEYWORDSDCC(WPARAM); } +"__wparam" { count(); TKEYWORD(WPARAM); } "register" { count(); return(REGISTER); } "return" { count(); return(RETURN); } -"sfr" { count(); TKEYWORD(SFR) ; } -"sbit" { count(); TKEYWORD(SBIT) ; } +"sfr" { count(); TKEYWORDSDCC(SFR); } +"__sfr" { count(); TKEYWORD(SFR); } +"sfr16" { count(); TKEYWORDSDCC(SFR16); } +"__sfr16" { count(); TKEYWORD(SFR16); } +"sfr32" { count(); TKEYWORDSDCC(SFR32); } +"__sfr32" { count(); TKEYWORD(SFR32); } +"sbit" { count(); TKEYWORDSDCC(SBIT); } +"__sbit" { count(); TKEYWORD(SBIT); } "short" { count(); return(SHORT); } "signed" { count(); return(SIGNED); } "sizeof" { count(); return(SIZEOF); } -"sram" { count(); TKEYWORD(XDATA);} +"sram" { count(); TKEYWORDSDCC(XDATA); } +"__sram" { count(); TKEYWORD(XDATA); } "static" { count(); return(STATIC); } "struct" { count(); return(STRUCT); } "switch" { count(); return(SWITCH); } @@ -130,33 +178,55 @@ static int checkCurrFile(char *s); "unsigned" { count(); return(UNSIGNED); } "void" { count(); return(VOID); } "volatile" { count(); return(VOLATILE); } -"using" { count(); TKEYWORD(USING); } -"_naked" { count(); TKEYWORD(NAKED); } +"using" { count(); TKEYWORDSDCC(USING); } +"__using" { count(); TKEYWORD(USING); } +"_naked" { count(); TKEYWORDSDCC(NAKED); } +"__naked" { count(); TKEYWORD(NAKED); } "while" { count(); return(WHILE); } -"xdata" { count(); TKEYWORD(XDATA); } -"..." { count(); return(VAR_ARGS);} -"__typeof" { count(); return TYPEOF;} -"_JavaNative" { count(); TKEYWORD(JAVANATIVE);} -"_overlay" { count(); TKEYWORD(OVERLAY);} -{L}({L}|{D})* { count(); return(check_type()); } +"xdata" { count(); TKEYWORDSDCC(XDATA); } +"__xdata" { count(); TKEYWORD(XDATA); } +"..." { count(); return(VAR_ARGS); } +"__typeof" { count(); return TYPEOF; } +"_JavaNative" { count(); TKEYWORD(JAVANATIVE); } +"_overlay" { count(); TKEYWORDSDCC(OVERLAY); } +"__overlay" { count(); TKEYWORD(OVERLAY); } +"inline" { count(); TKEYWORD99(INLINE); } +"restrict" { count(); TKEYWORD99(RESTRICT); } +{L}({L}|{D})* { + if (!options.dollars_in_ident && strchr(yytext, '$')) + { + yyerror("stray '$' in program"); + } + count(); + return(check_type()); +} +0[bB]{B}+{IS}? { + if (!options.std_sdcc) + { + yyerror("binary (0b) constants are not allowed in ISO C"); + } + count(); + yylval.val = constVal(yytext); + return(CONSTANT); +} 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); } -0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); } -{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); } -'(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */} +0[0-7]*{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); } +[1-9]{D}*{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); } +'(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ } {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } -{D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } -\" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);} -">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); } -"<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; } -"+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; } -"-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; } -"*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; } -"/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; } -"%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; } -"&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; } -"^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; } -"|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; } +{D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } +\" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); } +">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); } +"<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN); } +"+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN); } +"-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN); } +"*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN); } +"/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN); } +"%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN); } +"&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN); } +"^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN); } +"|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN); } ">>" { count(); return(RIGHT_OP); } "<<" { count(); return(LEFT_OP); } "++" { count(); return(INC_OP); } @@ -169,12 +239,12 @@ static int checkCurrFile(char *s); "==" { count(); return(EQ_OP); } "!=" { count(); return(NE_OP); } ";" { count(); return(';'); } -"{" { count(); NestLevel++ ; return('{'); } -"}" { count(); NestLevel--; return('}'); } +"{" { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); } +"}" { count(); NestLevel--; return('}'); } "," { count(); return(','); } ":" { count(); return(':'); } "=" { count(); return('='); } -"(" { count(); return('('); } +"(" { count(); ignoreTypedefType = 0; return('('); } ")" { count(); return(')'); } "[" { count(); return('['); } "]" { count(); return(']'); } @@ -192,218 +262,314 @@ static int checkCurrFile(char *s); "^" { count(); return('^'); } "|" { count(); return('|'); } "?" { count(); return('?'); } -^#line.*"\n" { count(); checkCurrFile(yytext); } -^#pragma.*"\n" { count(); process_pragma(yytext); } +^#pragma.*$ { count(); process_pragma(yytext); } +^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); } -^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); } -^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); } -"\r\n" { count(); } -"\n" { count(); } +^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); } +^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); } +"\r\n" { count(); } +"\n" { count(); } [ \t\v\f] { count(); } \\ { int ch = input(); - if (ch != '\n') { - /* that could have been removed by the preprocessor anyway */ - werror (W_STRAY_BACKSLASH, column); - unput(ch); - } + + if (ch == '\n') + count_char(ch); + else + { + /* that could have been removed by the preprocessor anyway */ + werror (W_STRAY_BACKSLASH, column); + unput(ch); + } } -. { count() ; } +. { count(); } %% -static int checkCurrFile (char *s) +/* flex 2.5.31 undefines yytext_ptr, so we have to define it again */ +#ifndef yytext_ptr +#define yytext_ptr yytext +#endif + + +static int checkCurrFile (const char *s) { - char lineNum[10] ; - int lNum ; - char *tptr ; - - /* first check if this is a #line */ - if ( strncmp(s,"#line",5) ) - return 0 ; - - /* get to the line number */ - while (!isdigit(*s)) - s++ ; - tptr = lineNum ; - while (isdigit(*s)) - *tptr++ = *s++ ; - *tptr = '\0'; - sscanf(lineNum,"%d",&lNum); - - /* now see if we have a file name */ - while (*s != '\"' && *s) - s++ ; - - /* if we don't have a filename then */ - /* set the current line number to */ - /* line number if printFlag is on */ - if (!*s) { - lineno = mylineno = lNum ; + int lNum; + char *tptr; + + /* skip '#' character */ + if (*s++ != '#') + return 0; + + /* check if this is a #line + this is not standard and can be removed in the future */ +#define LINE_STR "line" +#define LINE_LEN ((sizeof LINE_STR) - 1) + + if (strncmp(s, LINE_STR, LINE_LEN) == 0) + s += LINE_LEN; + + /* get the line number */ + lNum = strtol(s, &tptr, 10); + if (tptr == s || !isspace((unsigned char)*tptr)) + return 0; + s = tptr; + + /* adjust the line number */ + lineno = lexLineno = lNum; + + /* now see if we have a file name */ + while (*s != '"' && *s) + ++s; + + if (!*s) + { + /* no file name: return */ return 0; } - - /* if we have a filename then check */ - /* if it is "standard in" if yes then */ - /* get the currentfile name info */ - s++ ; - - /* in c1mode fullSrcFileName is NULL */ - if ( fullSrcFileName && - strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) { - lineno = mylineno = lNum; - currFname = fullSrcFileName ; - } else { - char *sb = s; - /* mark the end of the filename */ - while (*s != '"') s++; - *s = '\0'; - currFname = strdup (sb); - lineno = mylineno = lNum; + + /* skip the double quote */ + ++s; + + /* get the file name and see if it is different from current one. + in c1mode fullSrcFileName is NULL */ + if (fullSrcFileName && + strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0 && fullSrcFileName[strlen(fullSrcFileName) - 1] == '"') + { + lexFilename = fullSrcFileName; } - filename = currFname ; - return 0; + else + { + const char *sb = s; + char *tmpFname; + + /* find the end of the file name */ + while (*s && *s != '"') + ++s; + + tmpFname = Safe_malloc(s - sb + 1); + memcpy(tmpFname, sb, s - sb); + tmpFname[s - sb] = '\0'; + + lexFilename = Safe_malloc(s - sb + 1); + copyStr(lexFilename, tmpFname); + } + filename = lexFilename; + + return 0; } - -int column = 0; -int plineIdx =0; -static void count(void) +static void count_char(int ch) { - int i; - for (i = 0; yytext[i] != '\0'; i++) { - if (yytext[i] == '\n') { + switch (ch) + { + case '\n': column = 0; - lineno = ++mylineno ; + lineno = ++lexLineno; + break; + + case '\t': + column += 8 - (column % 8); + break; + + default: + ++column; + break; } - else - if (yytext[i] == '\t') - column += 8 - (column % 8); - else - column++; - } - /* ECHO; */ +} + +static void count(void) +{ + const char *p; + + for (p = yytext; *p; ++p) + count_char(*p); } static int check_type(void) { - /* check if it is in the typedef table */ - if (findSym(TypedefTab,NULL,yytext)) { - strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX); - return (TYPE_NAME) ; - } - else { - strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX); - return(IDENTIFIER); - } + symbol *sym = findSym(SymbolTab, NULL, yytext); + + strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX); + + /* check if it is in the table as a typedef */ + if (!ignoreTypedefType && sym && IS_SPEC (sym->etype) + && SPEC_TYPEDEF (sym->etype) && findSym(TypedefTab, NULL, yytext)) + return (TYPE_NAME); + else + return(IDENTIFIER); } /* * Change by JTV 2001-05-19 to not concantenate strings - * to support ANSI hex and octal escape sequences in string liteals + * to support ANSI hex and octal escape sequences in string literals */ -static char *stringLiteral(void) +static const char *stringLiteral(void) { #define STR_BUF_CHUNCK_LEN 1024 int ch; - static struct dbuf_s dbuf; - char buf[2]; + static struct dbuf_s dbuf; /* reusable string literal buffer */ if (dbuf.alloc == 0) dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN); else - dbuf_set_size(&dbuf, 0); + dbuf_set_length(&dbuf, 0); + dbuf_append_char(&dbuf, '"'); - dbuf_append(&dbuf, "\"", 1); /* put into the buffer till we hit the first \" */ - while ((ch = input()) != 0) { - switch (ch) { - case '\\': - /* if it is a \ then escape char's are allowed */ + for (; ; ) + { ch = input(); - if (ch == '\n') { - /* \ is a continuator */ - lineno = ++mylineno; - column = 0; - } - else { - buf[0] = '\\'; - buf[1] = ch; - dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */ - } - break; /* carry on */ + count_char(ch); + if (ch == EOF) + break; - case '\n': - /* if new line we have a new line break, which is illegal */ - werror(W_NEWLINE_IN_STRING); - dbuf_append(&dbuf, "\n", 1); - lineno = ++mylineno; - column = 0; - break; - - case '"': - /* if this is a quote then we have work to do */ - /* find the next non whitespace character */ - /* if that is a double quote then carry on */ - dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */ - while ((ch = input()) && (isspace(ch) || ch == '\\')) { - switch (ch) { + switch (ch) + { case '\\': - if ((ch = input()) != '\n') { - werror(W_STRAY_BACKSLASH, column); - unput(ch); - } - else { - lineno = ++mylineno; - column = 0; - } - break; + /* if it is a \ then escape char's are allowed */ + ch = input(); + count_char(ch); + if (ch == '\n') + { + /* \ is a continuator */ + } + else + { + char buf[2]; + + if (ch == EOF) + goto out; + + buf[0] = '\\'; + buf[1] = ch; + dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */ + } + break; /* carry on */ case '\n': - mylineno++; + /* if new line we have a new line break, which is illegal */ + werror(W_NEWLINE_IN_STRING); + dbuf_append_char(&dbuf, '\n'); break; - } - } - - if (!ch) - goto out; - if (ch != '\"') { - unput(ch) ; - goto out; - } - break; + case '"': + /* if this is a quote then we have work to do */ + /* find the next non whitespace character */ + /* if that is a double quote then carry on */ + dbuf_append_char(&dbuf, '"'); /* Pass end of this string or substring to evaluator */ + while ((ch = input()) && (isspace(ch) || ch == '\\' || ch == '#')) + { + switch (ch) + { + case '\\': + count_char(ch); + if ((ch = input()) != '\n') + { + werror(W_STRAY_BACKSLASH, column); + if (ch != EOF) + unput(ch); + else + count_char(ch); + } + else + count_char(ch); + break; + + case '\n': + count_char(ch); + break; + + case '#': + if (column == 0) + { + /* # at the beginning of the line: collect the entire line */ + struct dbuf_s linebuf; + const char *line; + + count_char(ch); + + dbuf_init(&linebuf, STR_BUF_CHUNCK_LEN); + dbuf_append_char(&linebuf, '#'); + + while ((ch = input()) != EOF && ch != '\n') + dbuf_append_char(&linebuf, (char)ch); + + if (ch == '\n') + count_char(ch); + + line = dbuf_c_str(&linebuf); + + /* process the line */ + if (startsWith(line, "#pragma")) + process_pragma(line); + else + checkCurrFile(line); + + dbuf_destroy(&linebuf); + } + else + { + unput(ch); + goto out; + } + + default: + count_char(ch); + break; + } + } + + if (ch == EOF) + goto out; + + if (ch != '"') + { + unput(ch); + goto out; + } + count_char(ch); + break; - default: - buf[0] = ch; - dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */ + default: + dbuf_append_char(&dbuf, (char)ch); /* Put next substring introducer into output string */ + } } - } out: - return (char *)dbuf_c_str(&dbuf); + return dbuf_c_str(&dbuf); } -enum pragma_id { - P_SAVE = 1, - P_RESTORE , - P_NOINDUCTION, - P_NOINVARIANT, - P_INDUCTION , - P_STACKAUTO , - P_NOJTBOUND , - P_NOOVERLAY , - P_LESSPEDANTIC, - P_NOGCSE , - P_CALLEE_SAVES, - P_EXCLUDE , - P_NOIV , - P_LOOPREV , - P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */ - /* cross-compiling for MINGW32 with gcc 3.2 */ +enum { + P_SAVE = 1, + P_RESTORE, + P_NOINDUCTION, + P_NOINVARIANT, + P_INDUCTION, + P_STACKAUTO, + P_NOJTBOUND, + P_NOOVERLAY, + P_LESSPEDANTIC, + P_NOGCSE, + P_CALLEE_SAVES, + P_EXCLUDE, + P_NOIV, + P_LOOPREV, + P_OVERLAY_, /* I had a strange conflict with P_OVERLAY while */ + /* cross-compiling for MINGW32 with gcc 3.2 */ + P_DISABLEWARN, + P_OPTCODESPEED, + P_OPTCODESIZE, + P_OPTCODEBALANCED, + P_STD_C89, + P_STD_C99, + P_STD_SDCC89, + P_STD_SDCC99, + P_CODESEG, + P_CONSTSEG }; @@ -412,6 +578,7 @@ enum pragma_id { STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE) STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE) +STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE) /* * cloneXxx functions should be updated every time a new set is @@ -440,7 +607,7 @@ static struct optimize *cloneOptimize(struct optimize *opt) { struct optimize *new_opt; - new_opt = Safe_malloc(sizeof (struct options)); + new_opt = Safe_malloc(sizeof (struct optimize)); /* clone scalar values */ *new_opt = *opt; @@ -448,6 +615,18 @@ static struct optimize *cloneOptimize(struct optimize *opt) return new_opt; } +static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val) +{ + struct SDCCERRG *new_val; + + new_val = Safe_malloc(sizeof (struct SDCCERRG)); + + /* clone scalar values */ + *new_val = *val; + + return new_val; +} + static void copyAndFreeOptions(struct options *dest, struct options *src) { /* delete dest sets */ @@ -456,7 +635,7 @@ static void copyAndFreeOptions(struct options *dest, struct options *src) /* not implemented yet: */ /* deleteSet(&dest->olaysSet); */ - /* dopy src to dest */ + /* copy src to dest */ *dest = *src; Safe_free(src); @@ -464,167 +643,488 @@ static void copyAndFreeOptions(struct options *dest, struct options *src) static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src) { - /* dopy src to dest */ + /* copy src to dest */ *dest = *src; Safe_free(src); } -static void doPragma(int op, char *cp) +static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src) { - switch (op) { - case P_SAVE: - { - STACK_PUSH(options_stack, cloneOptions(&options)); - STACK_PUSH(optimize_stack, cloneOptimize(&optimize)); - } - break; + /* copy src to dest */ + *dest = *src; + + Safe_free(src); +} + +/* + * returns 1 if the pragma was processed, 0 if not + */ +static int doPragma(int id, const char *name, const char *cp) +{ + struct pragma_token_s token; + int err = 0; + int processed = 1; - case P_RESTORE: + init_pragma_token(&token); + + switch (id) { - struct options *optionsp; - struct optimize *optimizep; + case P_SAVE: + { + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } - optionsp = STACK_POP(options_stack); - copyAndFreeOptions(&options, optionsp); + STACK_PUSH(options_stack, cloneOptions(&options)); + STACK_PUSH(optimize_stack, cloneOptimize(&optimize)); + STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG)); + } + break; - optimizep = STACK_POP(optimize_stack); - copyAndFreeOptimize(&optimize, optimizep); - } - break; + case P_RESTORE: + { + struct options *optionsp; + struct optimize *optimizep; + struct SDCCERRG *sdccerrgp; + + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } - case P_NOINDUCTION: - optimize.loopInduction = 0 ; - break; + optionsp = STACK_POP(options_stack); + copyAndFreeOptions(&options, optionsp); - case P_NOINVARIANT: - optimize.loopInvariant = 0 ; - break; + optimizep = STACK_POP(optimize_stack); + copyAndFreeOptimize(&optimize, optimizep); - case P_INDUCTION: - optimize.loopInduction = 1 ; - break; + sdccerrgp = STACK_POP(SDCCERRG_stack); + copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp); + } + break; - case P_STACKAUTO: - options.stackAuto = 1; - break; + case P_NOINDUCTION: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } - case P_NOJTBOUND: - optimize.noJTabBoundary = 1; - break; + optimize.loopInduction = 0; + break; - case P_NOGCSE: - optimize.global_cse = 0; - break; + case P_NOINVARIANT: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } - case P_NOOVERLAY: - options.noOverlay = 1; - break; + optimize.loopInvariant = 0; + break; - case P_LESSPEDANTIC: - options.lessPedantic = 1; - break; + case P_INDUCTION: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } - case P_CALLEE_SAVES: - /* append to the functions already listed - in callee-saves */ - setParseWithComma(&options.calleeSavesSet, cp); - break; + optimize.loopInduction = 1; + break; - case P_EXCLUDE: - { - deleteSet(&options.excludeRegsSet); - setParseWithComma(&options.excludeRegsSet, cp); + case P_STACKAUTO: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.stackAuto = 1; + break; + + case P_NOJTBOUND: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.noJTabBoundary = 1; + break; + + case P_NOGCSE: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.global_cse = 0; + break; + + case P_NOOVERLAY: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.noOverlay = 1; + break; + + case P_LESSPEDANTIC: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.lessPedantic = 1; + setErrorLogLevel(ERROR_LEVEL_WARNING); + break; + + case P_CALLEE_SAVES: + /* append to the functions already listed + in callee-saves */ + setParseWithComma(&options.calleeSavesSet, cp); + err = -1; + break; + + case P_EXCLUDE: + { + deleteSet(&options.excludeRegsSet); + setParseWithComma(&options.excludeRegsSet, cp); + err = -1; + } + break; + + case P_NOIV: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.noiv = 1; + break; + + case P_LOOPREV: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.noLoopReverse = 1; + break; + + case P_OVERLAY_: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + break; /* notyet */ + + case P_DISABLEWARN: + { + int warn; + + cp = get_pragma_token(cp, &token); + if (TOKEN_INT != token.type) + { + err = 1; + break; + } + warn = token.val.int_val; + + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + if (warn < MAX_ERROR_WARNING) + setWarningDisabled(warn); + } + break; + + case P_OPTCODESPEED: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.codeSpeed = 1; + optimize.codeSize = 0; + break; + + case P_OPTCODESIZE: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.codeSpeed = 0; + optimize.codeSize = 1; + break; + + case P_OPTCODEBALANCED: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + optimize.codeSpeed = 0; + optimize.codeSize = 0; + break; + + case P_STD_C89: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.std_c99 = 0; + options.std_sdcc = 0; + break; + + case P_STD_C99: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.std_c99 = 1; + options.std_sdcc = 0; + break; + + case P_STD_SDCC89: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.std_c99 = 0; + options.std_sdcc = 1; + break; + + case P_STD_SDCC99: + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + options.std_c99 = 1; + options.std_sdcc = 1; + break; + + case P_CODESEG: + case P_CONSTSEG: + { + struct dbuf_s segname; + + cp = get_pragma_token(cp, &token); + if (token.type == TOKEN_EOL) + { + err = 1; + break; + } + + dbuf_init(&segname, 16); + dbuf_printf(&segname, "%-8s(CODE)", get_pragma_string(&token)); + + cp = get_pragma_token(cp, &token); + if (token.type != TOKEN_EOL) + { + dbuf_destroy(&segname); + err = 1; + break; + } + + if (id == P_CODESEG) + options.code_seg = dbuf_detach(&segname); + else + options.const_seg = dbuf_detach(&segname); + } + break; + + default: + processed = 0; + break; } - break; - case P_NOIV: - options.noiv = 1; - break; + get_pragma_token(cp, &token); - case P_LOOPREV: - optimize.noLoopReverse = 1; - break; + if (1 == err || (0 == err && token.type != TOKEN_EOL)) + werror(W_BAD_PRAGMA_ARGUMENTS, name); - case P_OVERLAY_: - break; /* notyet */ - } + free_pragma_token(&token); + return processed; } -static int process_pragma(char *s) +static struct pragma_s pragma_tbl[] = { + { "save", P_SAVE, 0, doPragma }, + { "restore", P_RESTORE, 0, doPragma }, + { "noinduction", P_NOINDUCTION, 0, doPragma }, + { "noinvariant", P_NOINVARIANT, 0, doPragma }, + { "noloopreverse", P_LOOPREV, 0, doPragma }, + { "induction", P_INDUCTION, 0, doPragma }, + { "stackauto", P_STACKAUTO, 0, doPragma }, + { "nojtbound", P_NOJTBOUND, 0, doPragma }, + { "nogcse", P_NOGCSE, 0, doPragma }, + { "nooverlay", P_NOOVERLAY, 0, doPragma }, + { "callee_saves", P_CALLEE_SAVES, 0, doPragma }, + { "exclude", P_EXCLUDE, 0, doPragma }, + { "noiv", P_NOIV, 0, doPragma }, + { "overlay", P_OVERLAY_, 0, doPragma }, + { "less_pedantic", P_LESSPEDANTIC, 0, doPragma }, + { "disable_warning",P_DISABLEWARN, 0, doPragma }, + { "opt_code_speed", P_OPTCODESPEED, 0, doPragma }, + { "opt_code_size", P_OPTCODESIZE, 0, doPragma }, + { "opt_code_balanced", P_OPTCODEBALANCED, 0, doPragma }, + { "std_c89", P_STD_C89, 0, doPragma }, + { "std_c99", P_STD_C99, 0, doPragma }, + { "std_sdcc89", P_STD_SDCC89, 0, doPragma }, + { "std_sdcc99", P_STD_SDCC99, 0, doPragma }, + { "codeseg", P_CODESEG, 0, doPragma }, + { "constseg", P_CONSTSEG, 0, doPragma }, + { NULL, 0, 0, NULL }, +}; + +/* + * returns 1 if the pragma was processed, 0 if not + */ +int +process_pragma_tbl(const struct pragma_s *pragma_tbl, const char *s) { -#define NELEM(x) (sizeof (x) / sizeof (x)[0]) -#define PRAGMA "#pragma" - - static struct pragma_s { - const char *name; - enum pragma_id id; - } pragma_tbl[] = { - { "SAVE", P_SAVE }, - { "RESTORE", P_RESTORE }, - { "NOINDUCTION", P_NOINDUCTION }, - { "NOINVARIANT", P_NOINVARIANT }, - { "NOLOOPREVERSE", P_LOOPREV }, - { "INDUCTION", P_INDUCTION }, - { "STACKAUTO", P_STACKAUTO }, - { "NOJTBOUND", P_NOJTBOUND }, - { "NOGCSE", P_NOGCSE }, - { "NOOVERLAY", P_NOOVERLAY }, - { "CALLEE-SAVES", P_CALLEE_SAVES }, - { "EXCLUDE", P_EXCLUDE }, - { "NOIV", P_NOIV }, - { "OVERLAY", P_OVERLAY_ }, - { "LESS_PEDANTIC", P_LESSPEDANTIC }, - }; - char *cp ; + struct pragma_token_s token; int i; + int ret = 0; - /* find the pragma */ - while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1)) - s++; - s += (sizeof PRAGMA) - 1; - - /* look for the directive */ - while(isspace(*s)) + init_pragma_token(&token); + + s = get_pragma_token(s, &token); + + /* skip separating whitespace */ + while ('\n' != *s && isspace((unsigned char)*s)) s++; - cp = s; - /* look for the end of the directive */ - while ((!isspace(*s)) && (*s != '\n')) - s++ ; + for (i = 0; NULL != pragma_tbl[i].name; ++i) + { + /* now compare and do what needs to be done */ + if (strcmp(get_pragma_string(&token), pragma_tbl[i].name) == 0) + { + if (pragma_tbl[i].deprecated != 0) + werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name); - /* First give the port a chance */ - if (port->process_pragma && !port->process_pragma(cp)) - return 0; + ret = (*pragma_tbl[i].func)(pragma_tbl[i].id, pragma_tbl[i].name, s); + break; + } + } - for (i = 0; i < NELEM(pragma_tbl); i++) { - /* now compare and do what needs to be done */ - size_t len = strlen(pragma_tbl[i].name); + free_pragma_token(&token); + return ret; +} - if (strncmp(cp, pragma_tbl[i].name, len) == 0) { - doPragma(pragma_tbl[i].id, cp + len); - return 0; +static int process_pragma(const char *s) +{ + struct pragma_token_s token; + + init_pragma_token(&token); + + s = get_pragma_token(s, &token); + if (0 != strcmp("#pragma", get_pragma_string(&token))) + { + /* Oops, womething went totally wrong - internal error */ + wassertl(0, "pragma parser internal error"); } - } - werror(W_UNKNOWN_PRAGMA,cp); - return 0; + /* skip spaces */ + while ('\n' != *s && isspace((unsigned char)*s)) + ++s; + + /* First give the port a chance */ + if (port->process_pragma && port->process_pragma(s)) + return 1; + + if (process_pragma_tbl(pragma_tbl, s)) + { + return 1; + } + else + { + werror(W_UNKNOWN_PRAGMA, s); + return 0; + } } /* will return 1 if the string is a part of a target specific keyword */ -static int isTargetKeyword(char *s) +static int isTargetKeyword(const char *s) { - int i; - - if (port->keywords == NULL) - return 0; - for ( i = 0 ; port->keywords[i] ; i++ ) { - if (strcmp(port->keywords[i],s) == 0) - return 1; - } - + int i; + + if (port->keywords == NULL) return 0; + + if (s[0] == '_' && s[1] == '_') + { + /* Keywords in the port's array have either 0 or 1 underscore, */ + /* so skip over the appropriate number of chars when comparing */ + for (i = 0 ; port->keywords[i] ; i++ ) + { + if (port->keywords[i][0] == '_' && + strcmp(port->keywords[i],s+1) == 0) + return 1; + else if (strcmp(port->keywords[i],s+2) == 0) + return 1; + } + } + else + { + for (i = 0 ; port->keywords[i] ; i++ ) + { + if (strcmp(port->keywords[i],s) == 0) + return 1; + } + } + + return 0; } int yywrap(void) @@ -637,20 +1137,15 @@ int yywrap(void) int yyerror(char *s) { - fflush(stdout); - - if (mylineno && filename) { - if(options.vc_err_style) - fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n", - filename,mylineno, - s,yytext,column); - else - fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n", - filename,mylineno, - s,yytext,column); - fatalError++; - } else { - /* this comes from an empy file, no problem */ - } - return 0; + fflush(stdout); + + if(options.vc_err_style) + fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n", + lexFilename, lexLineno, s, yytext, column); + else + fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n", + lexFilename, lexLineno, s ,yytext, column); + fatalError++; + + return 0; }