1 /*-----------------------------------------------------------------------
2 SDCC.lex - lexical analyser for use with sdcc ( a freeware compiler for
3 8/16 bit microcontrollers)
4 Written by : Sandeep Dutta . sandeep.dutta@usa.net (1997)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
39 char *stringLiteral();
42 extern int lineno, column;
43 extern char *filename ;
46 int process_pragma(char *);
49 int yywrap YY_PROTO((void))
53 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
58 extern int check_type ();
59 extern int isTargetKeyword ();
60 extern int checkCurrFile (char *);
61 extern int processPragma (char *);
62 extern int printListing (int );
63 struct optimize save_optimize ;
64 struct options save_options ;
80 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
81 /* cross-compiling for MINGW32 with gcc 3.2 */
89 asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
90 asmbuffSize=INITIAL_INLINEASM;
96 yylval.yyinline = strdup (asmbuff);
101 if (asmp-asmbuff >= asmbuffSize-2) {
102 // increase the buffersize with 50%
103 int size=asmp-asmbuff;
104 asmbuffSize=asmbuffSize*3/2;
105 asmbuff = realloc (asmbuff, asmbuffSize);
112 if (asmp-asmbuff >= asmbuffSize-3) {
113 // increase the buffersize with 50%
114 int size=asmp-asmbuff;
115 asmbuffSize=asmbuffSize*3/2;
116 asmbuff = realloc (asmbuff, asmbuffSize);
121 "at" { count(); TKEYWORD(AT) ; }
122 "auto" { count(); return(AUTO); }
123 "bit" { count(); TKEYWORD(BIT) ; }
124 "break" { count(); return(BREAK); }
125 "case" { count(); return(CASE); }
126 "char" { count(); return(CHAR); }
127 "code" { count(); TKEYWORD(CODE); }
128 "const" { count(); return(CONST); }
129 "continue" { count(); return(CONTINUE); }
130 "critical" { count(); TKEYWORD(CRITICAL); }
131 "data" { count(); TKEYWORD(DATA); }
132 "default" { count(); return(DEFAULT); }
133 "do" { count(); return(DO); }
134 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
135 "else" { count(); return(ELSE); }
136 "enum" { count(); return(ENUM); }
137 "extern" { count(); return(EXTERN); }
138 "far" { count(); TKEYWORD(XDATA); }
139 "eeprom" { count(); TKEYWORD(EEPROM); }
140 "float" { count(); return(FLOAT); }
141 "flash" { count(); TKEYWORD(CODE);}
142 "for" { count(); return(FOR); }
143 "goto" { count(); return(GOTO); }
144 "idata" { count(); TKEYWORD(IDATA);}
145 "if" { count(); return(IF); }
146 "int" { count(); return(INT); }
147 "interrupt" { count(); return(INTERRUPT);}
148 "nonbanked" { count(); TKEYWORD(NONBANKED);}
149 "banked" { count(); TKEYWORD(BANKED);}
150 "long" { count(); return(LONG); }
151 "near" { count(); TKEYWORD(DATA);}
152 "pdata" { count(); TKEYWORD(PDATA); }
153 "reentrant" { count(); TKEYWORD(REENTRANT);}
154 "register" { count(); return(REGISTER); }
155 "return" { count(); return(RETURN); }
156 "sfr" { count(); TKEYWORD(SFR) ; }
157 "sbit" { count(); TKEYWORD(SBIT) ; }
158 "short" { count(); return(SHORT); }
159 "signed" { count(); return(SIGNED); }
160 "sizeof" { count(); return(SIZEOF); }
161 "sram" { count(); TKEYWORD(XDATA);}
162 "static" { count(); return(STATIC); }
163 "struct" { count(); return(STRUCT); }
164 "switch" { count(); return(SWITCH); }
165 "typedef" { count(); return(TYPEDEF); }
166 "union" { count(); return(UNION); }
167 "unsigned" { count(); return(UNSIGNED); }
168 "void" { count(); return(VOID); }
169 "volatile" { count(); return(VOLATILE); }
170 "using" { count(); TKEYWORD(USING); }
171 "_naked" { count(); TKEYWORD(NAKED); }
172 "while" { count(); return(WHILE); }
173 "xdata" { count(); TKEYWORD(XDATA); }
174 "..." { count(); return(VAR_ARGS);}
175 "__typeof" { count(); return TYPEOF;}
176 "_JavaNative" { count(); TKEYWORD(JAVANATIVE);}
177 "_overlay" { count(); TKEYWORD(OVERLAY);}
178 {L}({L}|{D})* { count(); return(check_type()); }
179 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
180 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
181 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
182 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
183 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
184 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
185 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
186 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
187 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
188 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
189 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
190 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
191 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
192 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
193 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
194 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
195 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
196 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
197 ">>" { count(); return(RIGHT_OP); }
198 "<<" { count(); return(LEFT_OP); }
199 "++" { count(); return(INC_OP); }
200 "--" { count(); return(DEC_OP); }
201 "->" { count(); return(PTR_OP); }
202 "&&" { count(); return(AND_OP); }
203 "||" { count(); return(OR_OP); }
204 "<=" { count(); return(LE_OP); }
205 ">=" { count(); return(GE_OP); }
206 "==" { count(); return(EQ_OP); }
207 "!=" { count(); return(NE_OP); }
208 ";" { count(); return(';'); }
209 "{" { count(); NestLevel++ ; return('{'); }
210 "}" { count(); NestLevel--; return('}'); }
211 "," { count(); return(','); }
212 ":" { count(); return(':'); }
213 "=" { count(); return('='); }
214 "(" { count(); return('('); }
215 ")" { count(); return(')'); }
216 "[" { count(); return('['); }
217 "]" { count(); return(']'); }
218 "." { count(); return('.'); }
219 "&" { count(); return('&'); }
220 "!" { count(); return('!'); }
221 "~" { count(); return('~'); }
222 "-" { count(); return('-'); }
223 "+" { count(); return('+'); }
224 "*" { count(); return('*'); }
225 "/" { count(); return('/'); }
226 "%" { count(); return('%'); }
227 "<" { count(); return('<'); }
228 ">" { count(); return('>'); }
229 "^" { count(); return('^'); }
230 "|" { count(); return('|'); }
231 "?" { count(); return('?'); }
232 ^#line.*"\n" { count(); checkCurrFile(yytext); }
233 ^#pragma.*"\n" { count(); process_pragma(yytext); }
235 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
236 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
239 [ \t\v\f] { count(); }
243 // that could have been removed by the preprocessor anyway
244 werror (W_STRAY_BACKSLASH, column);
251 int checkCurrFile ( char *s)
257 /* first check if this is a #line */
258 if ( strncmp(s,"#line",5) )
261 /* get to the line number */
268 sscanf(lineNum,"%d",&lNum);
270 /* now see if we have a file name */
271 while (*s != '\"' && *s)
274 /* if we don't have a filename then */
275 /* set the current line number to */
276 /* line number if printFlag is on */
278 lineno = yylineno = lNum ;
282 /* if we have a filename then check */
283 /* if it is "standard in" if yes then */
284 /* get the currentfile name info */
287 /* in c1mode fullSrcFileName is NULL */
288 if ( fullSrcFileName &&
289 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
290 lineno = yylineno = lNum;
291 currFname = fullSrcFileName ;
294 /* mark the end of the filename */
295 while (*s != '"') s++;
297 currFname = strdup (sb);
298 lineno = yylineno = lNum;
300 filename = currFname ;
310 for (i = 0; yytext[i] != '\0'; i++) {
311 if (yytext[i] == '\n') {
313 lineno = ++yylineno ;
316 if (yytext[i] == '\t')
317 column += 8 - (column % 8);
326 /* check if it is in the typedef table */
327 if (findSym(TypedefTab,NULL,yytext)) {
328 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
332 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
337 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
340 * Change by JTV 2001-05-19 to not concantenate strings
341 * to support ANSI hex and octal escape sequences in string liteals
344 char *stringLiteral () {
346 char *str = strLitBuff;
349 /* put into the buffer till we hit the first \" */
355 break; /* end of input */
357 /* if it is a \ then escape char's are allowed */
361 /* \<newline> is a continuator */
366 *str++ = '\\'; /* backslash in place */
367 *str++ = ch; /* get the escape char, no further check */
368 continue; /* carry on */
371 /* if new line we have a new line break, which is illegal */
373 werror (W_NEWLINE_IN_STRING);
380 /* if this is a quote then we have work to do */
381 /* find the next non whitespace character */
382 /* if that is a double quote then carry on */
384 *str++ = ch ; /* Pass end of this string or substring to evaluator */
385 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
388 if ((ch=input())!='\n') {
389 werror (W_STRAY_BACKSLASH, column);
410 *str++ = ch; /* Put next substring introducer into output string */
414 /* If we aren't going to fix it, at least trap it. */
415 if (strlen(strLitBuff) >= sizeof(strLitBuff))
417 fprintf(stderr, "Internal error: strLitBuff overflowed.\n");
424 void doPragma (int op, char *cp)
428 memcpy(&save_options,&options,sizeof(options));
429 memcpy(&save_optimize,&optimize,sizeof(optimize));
432 memcpy(&options,&save_options,sizeof(options));
433 memcpy(&optimize,&save_optimize,sizeof(optimize));
436 optimize.loopInduction = 0 ;
439 optimize.loopInvariant = 0 ;
442 optimize.loopInduction = 1 ;
445 options.stackAuto = 1;
448 optimize.noJTabBoundary = 1;
451 optimize.global_cse = 0;
454 options.noOverlay = 1;
459 /* append to the functions already listed
461 for (; options.calleeSaves[i] ;i++);
462 parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
466 parseWithComma(options.excludeRegs, Safe_strdup(cp));
472 optimize.noLoopReverse = 1;
479 int process_pragma(char *s)
482 /* find the pragma */
483 while (strncmp(s,"#pragma",7))
487 /* look for the directive */
488 while(isspace(*s)) s++;
491 /* look for the end of the directive */
492 while ((! isspace(*s)) &&
496 /* First give the port a chance */
497 if (port->process_pragma && !port->process_pragma(cp))
500 /* now compare and do what needs to be done */
501 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
502 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
506 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
507 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
511 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
512 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
516 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
517 doPragma (P_NOINVARIANT,NULL) ;
521 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
522 doPragma (P_INDUCTION,NULL) ;
526 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
527 doPragma (P_STACKAUTO,NULL);
531 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
532 doPragma (P_NOJTBOUND,NULL);
536 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
537 doPragma (P_NOGCSE,NULL);
541 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
542 doPragma (P_NOOVERLAY,NULL);
546 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
547 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
551 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
552 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
556 if (strncmp(cp,PRAGMA_NOIV,strlen(PRAGMA_NOIV)) == 0) {
557 doPragma(P_NOIV,cp+strlen(PRAGMA_NOIV));
561 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
562 doPragma(P_LOOPREV,NULL);
566 werror(W_UNKNOWN_PRAGMA,cp);
570 /* will return 1 if the string is a part
571 of a target specific keyword */
572 int isTargetKeyword(char *s)
576 if (port->keywords == NULL)
578 for ( i = 0 ; port->keywords[i] ; i++ ) {
579 if (strcmp(port->keywords[i],s) == 0)
586 extern int fatalError;
592 if (yylineno && filename) {
593 fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
598 // this comes from an empy file, no problem