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 ;
44 extern char *fullSrcFileName ;
48 int process_pragma(char *);
51 int yywrap YY_PROTO((void))
55 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
60 extern int check_type ();
61 extern int isTargetKeyword ();
62 extern int checkCurrFile (char *);
63 extern int processPragma (char *);
64 extern int printListing (int );
65 struct optimize save_optimize ;
66 struct options save_options ;
88 asmp = asmbuff = Safe_realloc (asmbuff, INITIAL_INLINEASM);
89 asmbuffSize=INITIAL_INLINEASM;
95 yylval.yyinline = Safe_calloc (1, strlen(asmbuff)+1);
96 strcpy(yylval.yyinline,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 = Safe_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 = Safe_realloc (asmbuff, asmbuffSize);
122 "at" { count(); TKEYWORD(AT) ; }
123 "auto" { count(); return(AUTO); }
124 "bit" { count(); TKEYWORD(BIT) ; }
125 "break" { count(); return(BREAK); }
126 "case" { count(); return(CASE); }
127 "char" { count(); return(CHAR); }
128 "code" { count(); TKEYWORD(CODE); }
129 "const" { count(); return(CONST); }
130 "continue" { count(); return(CONTINUE); }
131 "critical" { count(); TKEYWORD(CRITICAL); }
132 "data" { count(); TKEYWORD(DATA); }
133 "default" { count(); return(DEFAULT); }
134 "do" { count(); return(DO); }
135 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
136 "else" { count(); return(ELSE); }
137 "enum" { count(); return(ENUM); }
138 "extern" { count(); return(EXTERN); }
139 "far" { count(); TKEYWORD(XDATA); }
140 "eeprom" { count(); TKEYWORD(EEPROM); }
141 "float" { count(); return(FLOAT); }
142 "flash" { count(); TKEYWORD(CODE);}
143 "for" { count(); return(FOR); }
144 "goto" { count(); return(GOTO); }
145 "idata" { count(); TKEYWORD(IDATA);}
146 "if" { count(); return(IF); }
147 "int" { count(); return(INT); }
148 "interrupt" { count(); return(INTERRUPT);}
149 "nonbanked" { count(); TKEYWORD(NONBANKED);}
150 "banked" { count(); TKEYWORD(BANKED);}
151 "long" { count(); return(LONG); }
152 "near" { count(); TKEYWORD(DATA);}
153 "pdata" { count(); TKEYWORD(PDATA); }
154 "reentrant" { count(); TKEYWORD(REENTRANT);}
155 "register" { count(); return(REGISTER); }
156 "return" { count(); return(RETURN); }
157 "sfr" { count(); TKEYWORD(SFR) ; }
158 "sbit" { count(); TKEYWORD(SBIT) ; }
159 "short" { count(); return(SHORT); }
160 "signed" { count(); return(SIGNED); }
161 "sizeof" { count(); return(SIZEOF); }
162 "sram" { count(); TKEYWORD(XDATA);}
163 "static" { count(); return(STATIC); }
164 "struct" { count(); return(STRUCT); }
165 "switch" { count(); return(SWITCH); }
166 "typedef" { count(); return(TYPEDEF); }
167 "union" { count(); return(UNION); }
168 "unsigned" { count(); return(UNSIGNED); }
169 "void" { count(); return(VOID); }
170 "volatile" { count(); return(VOLATILE); }
171 "using" { count(); TKEYWORD(USING); }
172 "_naked" { count(); TKEYWORD(NAKED); }
173 "while" { count(); return(WHILE); }
174 "xdata" { count(); TKEYWORD(XDATA); }
175 "_data" { count(); TKEYWORD(_NEAR); }
176 "_code" { count(); TKEYWORD(_CODE); }
177 "_eeprom" { count(); TKEYWORD(_EEPROM); }
178 "_flash" { count(); TKEYWORD(_CODE); }
179 "_generic" { count(); TKEYWORD(_GENERIC); }
180 "_near" { count(); TKEYWORD(_NEAR); }
181 "_sram" { count(); TKEYWORD(_XDATA);}
182 "_xdata" { count(); TKEYWORD(_XDATA);}
183 "_pdata" { count(); TKEYWORD(_PDATA); }
184 "_idata" { count(); TKEYWORD(_IDATA); }
185 "..." { count(); return(VAR_ARGS);}
186 {L}({L}|{D})* { count(); return(check_type()); }
187 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
188 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
189 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
190 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
191 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
192 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
193 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
194 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
195 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
196 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
197 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
198 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
199 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
200 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
201 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
202 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
203 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
204 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
205 ">>" { count(); return(RIGHT_OP); }
206 "<<" { count(); return(LEFT_OP); }
207 "++" { count(); return(INC_OP); }
208 "--" { count(); return(DEC_OP); }
209 "->" { count(); return(PTR_OP); }
210 "&&" { count(); return(AND_OP); }
211 "||" { count(); return(OR_OP); }
212 "<=" { count(); return(LE_OP); }
213 ">=" { count(); return(GE_OP); }
214 "==" { count(); return(EQ_OP); }
215 "!=" { count(); return(NE_OP); }
216 ";" { count(); return(';'); }
217 "{" { count(); NestLevel++ ; return('{'); }
218 "}" { count(); NestLevel--; 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 "*" { count(); return('*'); }
233 "/" { count(); return('/'); }
234 "%" { count(); return('%'); }
235 "<" { count(); return('<'); }
236 ">" { count(); return('>'); }
237 "^" { count(); return('^'); }
238 "|" { count(); return('|'); }
239 "?" { count(); return('?'); }
240 ^#line.*"\n" { count(); checkCurrFile(yytext); }
241 ^#pragma.*"\n" { count(); process_pragma(yytext); }
243 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
244 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
247 [ \t\v\f] { count(); }
251 werror (W_STRAY_BACKSLASH, column);
258 int checkCurrFile ( char *s)
264 /* first check if this is a #line */
265 if ( strncmp(s,"#line",5) )
268 /* get to the line number */
275 sscanf(lineNum,"%d",&lNum);
277 /* now see if we have a file name */
278 while (*s != '\"' && *s)
281 /* if we don't have a filename then */
282 /* set the current line number to */
283 /* line number if printFlag is on */
289 /* if we have a filename then check */
290 /* if it is "standard in" if yes then */
291 /* get the currentfile name info */
294 if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
296 currFname = fullSrcFileName ;
299 /* mark the end of the filename */
300 while (*s != '"') s++;
302 currFname = Safe_calloc(1,strlen(sb)+1);
303 strcpy(currFname,sb);
306 filename = currFname ;
315 while ((c = input()) != '*' && c) {
321 if (c && (c1 = input()) != '/') {
335 for (i = 0; yytext[i] != '\0'; i++) {
336 if (yytext[i] == '\n') {
338 lineno = ++yylineno ;
341 if (yytext[i] == '\t')
342 column += 8 - (column % 8);
351 /* check if it is in the typedef table */
352 if (findSym(TypedefTab,NULL,yytext)) {
353 strcpy(yylval.yychar,yytext);
357 strcpy (yylval.yychar,yytext);
362 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
365 * Change by JTV 2001-05-19 to not concantenate strings
366 * to support ANSI hex and octal escape sequences in string liteals
369 char *stringLiteral () {
371 char *str = strLitBuff;
374 /* put into the buffer till we hit the first \" */
380 break; /* end of input */
382 /* if it is a \ then escape char's are allowed */
386 // input() translates \n into \r\n
387 if ((ch=input())!='\n') {
390 /* \<newline> is a continuator */
394 *str++ = '\\'; /* backslash in place */
395 *str++ = ch; /* get the escape char, no further check */
396 continue; /* carry on */
399 /* if new line we have a new line break, which is illegal */
401 // input() translates \n into \r\n
402 if ((ch=input())!='\n') {
405 werror (W_NEWLINE_IN_STRING);
411 /* if this is a quote then we have work to do */
412 /* find the next non whitespace character */
413 /* if that is a double quote then carry on */
415 *str++ = ch ; /* Pass end of this string or substring to evaluator */
416 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
419 if ((ch=input())!='\n') {
420 werror (W_STRAY_BACKSLASH, column);
438 *str++ = ch; /* Put next substring introducer into output string */
445 void doPragma (int op, char *cp)
449 memcpy(&save_options,&options,sizeof(options));
450 memcpy(&save_optimize,&optimize,sizeof(optimize));
453 memcpy(&options,&save_options,sizeof(options));
454 memcpy(&optimize,&save_optimize,sizeof(optimize));
457 optimize.loopInduction = 0 ;
460 optimize.loopInvariant = 0 ;
463 optimize.loopInduction = 1 ;
466 options.stackAuto = 1;
469 optimize.noJTabBoundary = 1;
472 optimize.global_cse = 0;
475 options.noOverlay = 1;
480 /* append to the functions already listed
482 for (; options.calleeSaves[i] ;i++);
483 parseWithComma(&options.calleeSaves[i],strdup(cp));
487 parseWithComma(options.excludeRegs,strdup(cp));
490 optimize.noLoopReverse = 1;
495 int process_pragma(char *s)
498 /* find the pragma */
499 while (strncmp(s,"#pragma",7))
503 /* look for the directive */
504 while(isspace(*s)) s++;
507 /* look for the end of the directive */
508 while ((! isspace(*s)) &&
512 /* First give the port a chance */
513 if (port->process_pragma && !port->process_pragma(cp))
516 /* now compare and do what needs to be done */
517 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
518 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
522 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
523 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
527 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
528 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
532 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
533 doPragma (P_NOINVARIANT,NULL) ;
537 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
538 doPragma (P_INDUCTION,NULL) ;
542 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
543 doPragma (P_STACKAUTO,NULL);
547 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
548 doPragma (P_NOJTBOUND,NULL);
552 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
553 doPragma (P_NOGCSE,NULL);
557 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
558 doPragma (P_NOOVERLAY,NULL);
562 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
563 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
567 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
568 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
572 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
573 doPragma(P_EXCLUDE,NULL);
577 werror(W_UNKNOWN_PRAGMA,cp);
581 /* will return 1 if the string is a part
582 of a target specific keyword */
583 int isTargetKeyword(char *s)
587 if (port->keywords == NULL)
589 for ( i = 0 ; port->keywords[i] ; i++ ) {
590 if (strcmp(port->keywords[i],s) == 0)
597 extern int fatalError;
603 if (yylineno && filename)
604 fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",