X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.lex;h=7f64c9768f10698a667e50bfcae03054f6117145;hb=73345d09819099037a195686d80bf9f8e0c99370;hp=23ee5a102f2bdba229f7acf7b93a1c03a0ba1100;hpb=20bae27b1c4b37bba7f4ec5aa92d78fbc23188f4;p=fw%2Fsdcc diff --git a/src/SDCC.lex b/src/SDCC.lex index 23ee5a10..7f64c976 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -22,144 +22,106 @@ what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ -D [0-9] -L [a-zA-Z_] -H [a-fA-F0-9] -E [Ee][+-]?{D}+ -FS (f|F|l|L) -IS (u|U|l|L)* -%{ +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +FS (f|F|l|L) +IS (u|U|l|L)* +%{ #include #include #include #include "common.h" #include "newalloc.h" - -char *stringLiteral(); -char *currFname; - -extern int lineno ; -extern char *filename ; -extern char *fullSrcFileName ; -int yylineno = 1 ; -void count() ; -void comment(); -int process_pragma(char *); -#undef yywrap +#include "dbuf.h" -int yywrap YY_PROTO((void)) -{ - return(1); -} #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\ - check_type(yytext)) -char *asmbuff=NULL; -int asmbuffSize=0; -char *asmp ; -extern int check_type (); - extern int isTargetKeyword (); -extern int checkCurrFile (char *); -extern int processPragma (char *); -extern int printListing (int ); -struct optimize save_optimize ; -struct options save_options ; - - enum { - P_SAVE = 1, - P_RESTORE , - P_NOINDUCTION, - P_NOINVARIANT, - P_INDUCTION , - P_STACKAUTO , - P_NOJTBOUND , - P_NOOVERLAY , - P_NOGCSE , - P_CALLEE_SAVES, - P_EXCLUDE , - P_LOOPREV - }; + check_type()) +extern int lineno, column; +extern char *filename; + +/* global definitions */ +char *currFname; +int mylineno = 1; + +/* local definitions */ +static struct dbuf_s asmbuff; + +/* forward declarations */ +static char *stringLiteral(void); +static void count(void); +static int process_pragma(char *); +static int check_type(void); +static int isTargetKeyword(char *s); +static int checkCurrFile(char *s); %} + %x asm %% -"_asm" { - count(); - asmp = asmbuff = Safe_realloc (asmbuff, INITIAL_INLINEASM); - asmbuffSize=INITIAL_INLINEASM; - BEGIN(asm) ; +"_asm" { + count(); + assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL); + dbuf_init(&asmbuff, INITIAL_INLINEASM); + BEGIN(asm); } -"_endasm" { +"_endasm" { count(); - *asmp = '\0'; - yylval.yyinline = Safe_calloc (1, strlen(asmbuff)+1); - strcpy(yylval.yyinline,asmbuff); + yylval.yyinline = dbuf_c_str(&asmbuff); + dbuf_detach(&asmbuff); BEGIN(INITIAL); return (INLINEASM); } -. { - if (asmp-asmbuff >= asmbuffSize-2) { - // increase the buffersize with 50% - int size=asmp-asmbuff; - asmbuffSize=asmbuffSize*3/2; - asmbuff = Safe_realloc (asmbuff, asmbuffSize); - asmp=asmbuff+size; - } - *asmp++ = yytext[0]; +\n { + count(); + dbuf_append(&asmbuff, yytext, 1); } -\n { - count(); - if (asmp-asmbuff >= asmbuffSize-3) { - // increase the buffersize with 50% - int size=asmp-asmbuff; - asmbuffSize=asmbuffSize*3/2; - asmbuff = Safe_realloc (asmbuff, asmbuffSize); - asmp=asmbuff+size; - } - *asmp++ = '\n' ; +. { + dbuf_append(&asmbuff, yytext, 1); } -"/*" { comment(); } -"at" { count(); TKEYWORD(AT) ; } -"auto" { count(); return(AUTO); } -"bit" { count(); TKEYWORD(BIT) ; } +"at" { count(); TKEYWORD(AT); } +"auto" { count(); return(AUTO); } +"bit" { count(); TKEYWORD(BIT); } "break" { count(); return(BREAK); } "case" { count(); return(CASE); } "char" { count(); return(CHAR); } "code" { count(); TKEYWORD(CODE); } "const" { count(); return(CONST); } "continue" { count(); return(CONTINUE); } -"critical" { count(); TKEYWORD(CRITICAL); } -"data" { count(); TKEYWORD(DATA); } +"critical" { count(); TKEYWORD(CRITICAL); } +"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(); TKEYWORD(XDATA); } +"eeprom" { count(); TKEYWORD(EEPROM); } "float" { count(); return(FLOAT); } -"flash" { count(); TKEYWORD(CODE);} +"flash" { count(); TKEYWORD(CODE); } "for" { count(); return(FOR); } -"goto" { count(); return(GOTO); } -"idata" { count(); TKEYWORD(IDATA);} +"goto" { count(); return(GOTO); } +"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);} +"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);} +"reentrant" { count(); TKEYWORD(REENTRANT); } "register" { count(); return(REGISTER); } "return" { count(); return(RETURN); } -"sfr" { count(); TKEYWORD(SFR) ; } -"sbit" { count(); TKEYWORD(SBIT) ; } +"sfr" { count(); TKEYWORD(SFR); } +"sbit" { count(); TKEYWORD(SBIT); } "short" { count(); return(SHORT); } "signed" { count(); return(SIGNED); } "sizeof" { count(); return(SIZEOF); } -"sram" { count(); TKEYWORD(XDATA);} +"sram" { count(); TKEYWORD(XDATA); } "static" { count(); return(STATIC); } "struct" { count(); return(STRUCT); } "switch" { count(); return(SWITCH); } @@ -172,36 +134,29 @@ struct options save_options ; "_naked" { count(); TKEYWORD(NAKED); } "while" { count(); return(WHILE); } "xdata" { count(); TKEYWORD(XDATA); } -"_data" { count(); TKEYWORD(_NEAR); } -"_code" { count(); TKEYWORD(_CODE); } -"_eeprom" { count(); TKEYWORD(_EEPROM); } -"_flash" { count(); TKEYWORD(_CODE); } -"_generic" { count(); TKEYWORD(_GENERIC); } -"_near" { count(); TKEYWORD(_NEAR); } -"_sram" { count(); TKEYWORD(_XDATA);} -"_xdata" { count(); TKEYWORD(_XDATA);} -"_pdata" { count(); TKEYWORD(_PDATA); } -"_idata" { count(); TKEYWORD(_IDATA); } -"..." { count(); return(VAR_ARGS);} +"..." { count(); return(VAR_ARGS); } +"__typeof" { count(); return TYPEOF; } +"_JavaNative" { count(); TKEYWORD(JAVANATIVE); } +"_overlay" { count(); TKEYWORD(OVERLAY); } {L}({L}|{D})* { count(); return(check_type()); } 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); } +'(\\.|[^\\'])+' { 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);} +{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(); 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); } @@ -214,12 +169,12 @@ struct options save_options ; "==" { 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(']'); } @@ -237,351 +192,505 @@ struct options save_options ; "^" { count(); return('^'); } "|" { count(); return('|'); } "?" { count(); return('?'); } -^#line.*"\n" { count(); checkCurrFile(yytext); } -^#pragma.*"\n" { count(); process_pragma(yytext); } +^#pragma.*"\n" { 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(); } -. { count() ; } +\\ { + int ch = input(); + if (ch != '\n') { + /* that could have been removed by the preprocessor anyway */ + werror (W_STRAY_BACKSLASH, column); + unput(ch); + } +} +. { count(); } %% - -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 (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); - + 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(*tptr)) + return 0; + s = tptr; + /* now see if we have a file name */ - while (*s != '\"' && *s) - s++ ; - + 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) { - yylineno = lNum ; - return 0; + if (!*s) { + lineno = mylineno = lNum; + return 0; } - + /* if we have a filename then check */ /* if it is "standard in" if yes then */ /* get the currentfile name info */ s++ ; - if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) { - yylineno = lNum - 2; - currFname = fullSrcFileName ; - } else { - char *sb = s; - /* mark the end of the filename */ - while (*s != '"') s++; - *s = '\0'; - currFname = Safe_calloc(1,strlen(sb)+1); - strcpy(currFname,sb); - yylineno = lNum - 2; + /* 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; } filename = currFname ; return 0; } - -void comment() -{ - char c, c1; - -loop: - while ((c = input()) != '*' && c != 0) - if ( c == '\n') - yylineno++ ; - - if ((c1 = input()) != '/' && c != 0) { - if ( c1 == '\n' ) - yylineno++ ; - - unput(c1); - goto loop; - } - -} - - int column = 0; -int plineIdx=0; +int plineIdx =0; -void count() +static void count(void) { - int i; - for (i = 0; yytext[i] != '\0'; i++) { - if (yytext[i] == '\n') { - column = 0; - lineno = ++yylineno ; - } - else - if (yytext[i] == '\t') - column += 8 - (column % 8); - else - column++; - } - - /* ECHO; */ + int i; + for (i = 0; yytext[i] != '\0'; i++) { + if (yytext[i] == '\n') { + column = 0; + lineno = ++mylineno; + } + else + if (yytext[i] == '\t') + column += 8 - (column % 8); + else + column++; + } + /* ECHO; */ } -int check_type() +static int check_type(void) { - /* check if it is in the typedef table */ - if (findSym(TypedefTab,NULL,yytext)) { - strcpy(yylval.yychar,yytext); - return (TYPE_NAME) ; - } - else { - strcpy (yylval.yychar,yytext); - return(IDENTIFIER); - } -} + symbol *sym = findSym(SymbolTab, NULL, yytext); -char strLitBuff[2048] ; + /* check if it is in the table as a typedef */ + if (!ignoreTypedefType && sym && IS_SPEC (sym->etype) + && SPEC_TYPEDEF (sym->etype)) { + strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX); + return (TYPE_NAME); + } + else { + strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX); + 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 */ -char *stringLiteral () - +static char *stringLiteral(void) { -int ch; -char *str = strLitBuff ; +#define STR_BUF_CHUNCK_LEN 1024 + int ch; + static struct dbuf_s dbuf; + char buf[2]; + + if (dbuf.alloc == 0) + dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN); + else + dbuf_set_size(&dbuf, 0); + + 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 */ + 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 */ + + 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) { + case '\\': + if ((ch = input()) != '\n') { + werror(W_STRAY_BACKSLASH, column); + unput(ch); + } + else { + lineno = ++mylineno; + column = 0; + } + break; + + case '\n': + mylineno++; + break; + } + } -*str++ = '\"' ; -/* put into the buffer till we hit the */ -/* first \" */ + if (!ch) + goto out; -while (1) - { - ch = input() ; + if (ch != '\"') { + unput(ch); + goto out; + } + break; - if (!ch) - break ; /* end of input */ + default: + buf[0] = ch; + dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */ + } + } - /* if it is a \ then everything allowed */ +out: + return (char *)dbuf_c_str(&dbuf); +} - if (ch == '\\') - { - *str++ = ch ; /* backslash in place */ - *str++ = input() ; /* following char in place */ - continue ; /* carry on */ - } - /* if new line we have a new line break */ - if (ch == '\n') - break ; +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 */ +}; - /* 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 */ - if (ch == '\"') - { - *str++ = ch ; /* Pass end of this string or substring to evaluator */ +/* SAVE/RESTORE stack */ +#define SAVE_RESTORE_SIZE 128 - while ((ch = input()) && isspace(ch)) ; +STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE) +STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE) - if (!ch) - break ; +/* + * cloneXxx functions should be updated every time a new set is + * added to the options or optimize structure! + */ - if (ch != '\"') - { - unput(ch) ; - break ; - } - } +static struct options *cloneOptions(struct options *opt) +{ + struct options *new_opt; - *str++ = ch; /* Put next substring introducer into output string */ - } + new_opt = Safe_malloc(sizeof (struct options)); -*str = '\0'; + /* clone scalar values */ + *new_opt = *opt; -return strLitBuff ; + /* clone sets */ + new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet); + new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet); + /* not implemented yet: */ + /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */ + + return new_opt; } -void doPragma (int op, char *cp) +static struct optimize *cloneOptimize(struct optimize *opt) { - switch (op) { - case P_SAVE: - memcpy(&save_options,&options,sizeof(options)); - memcpy(&save_optimize,&optimize,sizeof(optimize)); - break; - case P_RESTORE: - memcpy(&options,&save_options,sizeof(options)); - memcpy(&optimize,&save_optimize,sizeof(optimize)); - break; - case P_NOINDUCTION: - optimize.loopInduction = 0 ; - break; - case P_NOINVARIANT: - optimize.loopInvariant = 0 ; - break; - case P_INDUCTION: - optimize.loopInduction = 1 ; - break; - case P_STACKAUTO: - options.stackAuto = 1; - break; - case P_NOJTBOUND: - optimize.noJTabBoundary = 1; - break; - case P_NOGCSE: - optimize.global_cse = 0; - break; - case P_NOOVERLAY: - options.noOverlay = 1; - break; - case P_CALLEE_SAVES: - { - int i=0; - /* append to the functions already listed - in callee-saves */ - for (; options.calleeSaves[i] ;i++); - parseWithComma(&options.calleeSaves[i],strdup(cp)); - } - break; - case P_EXCLUDE: - parseWithComma(options.excludeRegs,strdup(cp)); - break; - case P_LOOPREV: - optimize.noLoopReverse = 1; - break; - } + struct optimize *new_opt; + + new_opt = Safe_malloc(sizeof (struct options)); + + /* clone scalar values */ + *new_opt = *opt; + + return new_opt; } -int process_pragma(char *s) +static void copyAndFreeOptions(struct options *dest, struct options *src) { - char *cp ; - /* find the pragma */ - while (strncmp(s,"#pragma",7)) - s++; - s += 7; - - /* look for the directive */ - while(isspace(*s)) s++; - - cp = s; - /* look for the end of the directive */ - while ((! isspace(*s)) && - (*s != '\n')) - s++ ; - - /* First give the port a chance */ - if (port->process_pragma && !port->process_pragma(cp)) - return 0; - - /* now compare and do what needs to be done */ - if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) { - doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE)); - return 0; - } + /* delete dest sets */ + deleteSet(&dest->calleeSavesSet); + deleteSet(&dest->excludeRegsSet); + /* not implemented yet: */ + /* deleteSet(&dest->olaysSet); */ - if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) { - doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE)); - return 0; - } + /* dopy src to dest */ + *dest = *src; - if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) { - doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ; - return 0; - } + Safe_free(src); +} - if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) { - doPragma (P_NOINVARIANT,NULL) ; - return 0; - } +static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src) +{ + /* dopy src to dest */ + *dest = *src; - if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) { - doPragma (P_INDUCTION,NULL) ; - return 0; - } + Safe_free(src); +} - if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) { - doPragma (P_STACKAUTO,NULL); - return 0; +static void doPragma(int op, char *cp) +{ + switch (op) { + case P_SAVE: + { + STACK_PUSH(options_stack, cloneOptions(&options)); + STACK_PUSH(optimize_stack, cloneOptimize(&optimize)); } + break; - if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) { - doPragma (P_NOJTBOUND,NULL); - return 0; - } + case P_RESTORE: + { + struct options *optionsp; + struct optimize *optimizep; - if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) { - doPragma (P_NOGCSE,NULL); - return 0; - } + optionsp = STACK_POP(options_stack); + copyAndFreeOptions(&options, optionsp); - if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) { - doPragma (P_NOOVERLAY,NULL); - return 0; - } - - if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) { - doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES)); - return 0; - } - - if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) { - doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE)); - return 0; + optimizep = STACK_POP(optimize_stack); + copyAndFreeOptimize(&optimize, optimizep); } + break; + + case P_NOINDUCTION: + optimize.loopInduction = 0; + break; + + case P_NOINVARIANT: + optimize.loopInvariant = 0; + break; + + case P_INDUCTION: + optimize.loopInduction = 1; + break; + + case P_STACKAUTO: + options.stackAuto = 1; + break; + + case P_NOJTBOUND: + optimize.noJTabBoundary = 1; + break; - if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) { - doPragma(P_EXCLUDE,NULL); - return 0; + case P_NOGCSE: + optimize.global_cse = 0; + break; + + case P_NOOVERLAY: + options.noOverlay = 1; + break; + + case P_LESSPEDANTIC: + options.lessPedantic = 1; + break; + + case P_CALLEE_SAVES: + /* append to the functions already listed + in callee-saves */ + setParseWithComma(&options.calleeSavesSet, cp); + break; + + case P_EXCLUDE: + { + deleteSet(&options.excludeRegsSet); + setParseWithComma(&options.excludeRegsSet, cp); } + break; + + case P_NOIV: + options.noiv = 1; + break; + + case P_LOOPREV: + optimize.noLoopReverse = 1; + break; + + case P_OVERLAY_: + break; /* notyet */ + } +} + +static int process_pragma(char *s) +{ +#define NELEM(x) (sizeof (x) / sizeof (x)[0]) +#define PRAGMA_STR "#pragma" +#define PRAGMA_LEN ((sizeof PRAGMA_STR) - 1) - werror(W_UNKNOWN_PRAGMA,cp); + static struct pragma_s + { + const char *name; + enum pragma_id id; + char deprecated; + } pragma_tbl[] = { + { "save", P_SAVE, 0 }, + { "restore", P_RESTORE, 0 }, + { "noinduction", P_NOINDUCTION, 0 }, + { "noinvariant", P_NOINVARIANT, 0 }, + { "noloopreverse", P_LOOPREV, 0 }, + { "induction", P_INDUCTION, 0 }, + { "stackauto", P_STACKAUTO, 0 }, + { "nojtbound", P_NOJTBOUND, 0 }, + { "nogcse", P_NOGCSE, 0 }, + { "nooverlay", P_NOOVERLAY, 0 }, + { "callee_saves", P_CALLEE_SAVES, 0 }, + { "exclude", P_EXCLUDE, 0 }, + { "noiv", P_NOIV, 0 }, + { "overlay", P_OVERLAY_, 0 }, + { "less_pedantic", P_LESSPEDANTIC, 0 }, + + /* + * The following lines are deprecated pragmas, + * only for bacward compatibility. + * They should be removed in next major release after 1.4.0 + */ + + { "SAVE", P_SAVE, 1 }, + { "RESTORE", P_RESTORE, 1 }, + { "NOINDUCTION", P_NOINDUCTION, 1 }, + { "NOINVARIANT", P_NOINVARIANT, 1 }, + { "NOLOOPREVERSE", P_LOOPREV, 1 }, + { "INDUCTION", P_INDUCTION, 1 }, + { "STACKAUTO", P_STACKAUTO, 1 }, + { "NOJTBOUND", P_NOJTBOUND, 1 }, + { "NOGCSE", P_NOGCSE, 1 }, + { "NOOVERLAY", P_NOOVERLAY, 1 }, + { "CALLEE-SAVES", P_CALLEE_SAVES, 1 }, + { "EXCLUDE", P_EXCLUDE, 1 }, + { "NOIV", P_NOIV, 1 }, + { "OVERLAY", P_OVERLAY_, 1 }, + { "LESS_PEDANTIC", P_LESSPEDANTIC, 1 }, + }; + char *cp; + int i; + + /* find the pragma */ + while (strncmp(s, PRAGMA_STR, PRAGMA_LEN)) + s++; + s += PRAGMA_LEN; + + /* look for the directive */ + while(isspace(*s)) + s++; + + cp = s; + /* look for the end of the directive */ + while ((!isspace(*s)) && (*s != '\n')) + s++ ; + + /* First give the port a chance */ + if (port->process_pragma && !port->process_pragma(cp)) return 0; + + 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); + + if (strncmp(cp, pragma_tbl[i].name, len) == 0) + { + if (pragma_tbl[i].deprecated != 0) + werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name); + + doPragma(pragma_tbl[i].id, cp + len); + return 0; + } + } + + werror(W_UNKNOWN_PRAGMA, cp); + return 0; } /* will return 1 if the string is a part of a target specific keyword */ -int isTargetKeyword(char *s) +static int isTargetKeyword(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; + for (i = 0 ; port->keywords[i] ; i++ ) { + if (strcmp(port->keywords[i],s) == 0) + return 1; + } + return 0; } -extern int fatalError; +int yywrap(void) +{ + if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack)) + werror(W_SAVE_RESTORE); + + return 1; +} int yyerror(char *s) { - fflush(stdout); - - if (yylineno && filename) - fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n", - filename,yylineno, - s,yytext,column); - fatalError++; - return 0; + 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; }