X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.lex;h=d27496983af877116d40853c61f5e2e6bef9b4bf;hb=5f4c7aeda2b5672d87d0805103a394b62e3904c2;hp=365d56f27498e162b65761eccb9af0d863f11418;hpb=7bcf5c2d729ccd9c2bcd05b5f8033b1507707a74;p=fw%2Fsdcc diff --git a/src/SDCC.lex b/src/SDCC.lex index 365d56f2..d2749698 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -22,103 +22,65 @@ 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) ; } @@ -172,22 +134,15 @@ 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);} +"__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); } @@ -245,10 +200,18 @@ struct options save_options ; "\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); + } +} . { count() ; } %% - -int checkCurrFile ( char *s) + +static int checkCurrFile (char *s) { char lineNum[10] ; int lNum ; @@ -275,8 +238,8 @@ int checkCurrFile ( char *s) /* set the current line number to */ /* line number if printFlag is on */ if (!*s) { - yylineno = lNum ; - return 0; + lineno = mylineno = lNum ; + return 0; } /* if we have a filename then check */ @@ -284,51 +247,33 @@ int checkCurrFile ( char *s) /* get the currentfile name info */ s++ ; - if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) { - yylineno = lNum - 2; - currFname = fullSrcFileName ; + /* 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 = Safe_calloc(1,strlen(sb)+1); - strcpy(currFname,sb); - yylineno = lNum - 2; + currFname = strdup (sb); + lineno = mylineno = lNum; } filename = currFname ; return 0; } -void comment() -{ - char c, c1; - - loop: - while ((c = input()) != '*' && c) { - if ( c == '\n') { - lineno=++yylineno; - } - } - - if (c && (c1 = input()) != '/') { - 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 ; + lineno = ++mylineno ; } else if (yytext[i] == '\t') @@ -339,238 +284,336 @@ void count() /* 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); + strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX); return (TYPE_NAME) ; } else { - strcpy (yylval.yychar,yytext); + strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX); return(IDENTIFIER); } } -char strLitBuff[2048]; // TODO: this is asking for the next bug :) - /* * Change by JTV 2001-05-19 to not concantenate strings * to support ANSI hex and octal escape sequences in string liteals */ -char *stringLiteral () { +static char *stringLiteral(void) +{ +#define STR_BUF_CHUNCK_LEN 1024 int ch; - char *str = strLitBuff; - - *str++ = '\"'; + 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 (1) { - ch = input(); - - if (!ch) - break; /* end of input */ - - /* if it is a \ then escape char's are allowed */ - if (ch == '\\') { - ch=input(); - if (ch=='\r') { - // input() translates \n into \r\n - if ((ch=input())!='\n') { - unput (ch); - } - /* \ is a continuator */ - lineno=++yylineno; - continue; + + 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; } - *str++ = '\\'; /* backslash in place */ - *str++ = ch; /* get the escape char, no further check */ - continue; /* carry on */ - } - - /* if new line we have a new line break, which is illegal */ - if (ch == '\r') { - // input() translates \n into \r\n - if ((ch=input())!='\n') { - unput (ch); + else { + buf[0] = '\\'; + buf[1] = ch; + dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */ } - werror (W_NEWLINE_IN_STRING); - *str++ = '\n'; - lineno=++yylineno; - continue; - } - - /* 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 */ - while ((ch = input()) && (isspace(ch) || ch=='\\')) { - switch (ch) { - case '\\': - //werror (W_STRAY_BACKSLASH) - break; - case '\n': - yylineno++; - break; - } + 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; + } } if (!ch) - break; - + goto out; + if (ch != '\"') { - unput(ch) ; - break ; + unput(ch) ; + goto out; } + break; + + default: + buf[0] = ch; + dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */ } - *str++ = ch; /* Put next substring introducer into output string */ - } - *str = '\0'; - - return strLitBuff; + } + +out: + return (char *)dbuf_c_str(&dbuf); } -void doPragma (int op, char *cp) + +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 */ +}; + + +/* SAVE/RESTORE stack */ +#define SAVE_RESTORE_SIZE 128 + +STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE) +STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE) + +/* + * cloneXxx functions should be updated every time a new set is + * added to the options or optimize structure! + */ + +static struct options *cloneOptions(struct options *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 options *new_opt; + + new_opt = Safe_malloc(sizeof (struct options)); + + /* clone scalar values */ + *new_opt = *opt; + + /* 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; } -int process_pragma(char *s) +static struct optimize *cloneOptimize(struct optimize *opt) { - char *cp ; - /* find the pragma */ - while (strncmp(s,"#pragma",7)) - s++; - s += 7; - - /* look for the directive */ - while(isspace(*s)) s++; + struct optimize *new_opt; - cp = s; - /* look for the end of the directive */ - while ((! isspace(*s)) && - (*s != '\n')) - s++ ; + new_opt = Safe_malloc(sizeof (struct options)); - /* First give the port a chance */ - if (port->process_pragma && !port->process_pragma(cp)) - return 0; + /* clone scalar values */ + *new_opt = *opt; - /* 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; - } + return new_opt; +} - if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) { - doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE)); - return 0; - } +static void copyAndFreeOptions(struct options *dest, struct options *src) +{ + /* delete dest sets */ + deleteSet(&dest->calleeSavesSet); + deleteSet(&dest->excludeRegsSet); + /* not implemented yet: */ + /* deleteSet(&dest->olaysSet); */ - if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) { - doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ; - return 0; - } + /* dopy src to dest */ + *dest = *src; - if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) { - doPragma (P_NOINVARIANT,NULL) ; - return 0; - } + Safe_free(src); +} - if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) { - doPragma (P_INDUCTION,NULL) ; - return 0; - } +static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src) +{ + /* dopy src to dest */ + *dest = *src; - if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) { - doPragma (P_STACKAUTO,NULL); - return 0; - } + Safe_free(src); +} - if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) { - doPragma (P_NOJTBOUND,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_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) { - doPragma (P_NOGCSE,NULL); - return 0; - } + case P_RESTORE: + { + struct options *optionsp; + struct optimize *optimizep; - if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) { - doPragma (P_NOOVERLAY,NULL); - return 0; + optionsp = STACK_POP(options_stack); + copyAndFreeOptions(&options, optionsp); + + optimizep = STACK_POP(optimize_stack); + copyAndFreeOptimize(&optimize, optimizep); } - - if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) { - doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES)); - return 0; + 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_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 "#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 ; + int i; + + /* find the pragma */ + while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1)) + s++; + s += (sizeof PRAGMA) - 1; - if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) { - doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE)); - return 0; - } + /* look for the directive */ + while(isspace(*s)) + s++; - if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) { - doPragma(P_EXCLUDE,NULL); - return 0; - } + cp = s; + /* look for the end of the directive */ + while ((!isspace(*s)) && (*s != '\n')) + s++ ; - werror(W_UNKNOWN_PRAGMA,cp); + /* 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) { + 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; @@ -584,16 +627,30 @@ int isTargetKeyword(char *s) 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++; + 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; }