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 ;
47 int process_pragma(char *);
50 int yywrap YY_PROTO((void))
54 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
59 extern int check_type ();
60 extern int isTargetKeyword ();
61 extern int checkCurrFile (char *);
62 extern int processPragma (char *);
63 extern int printListing (int );
64 struct optimize save_optimize ;
65 struct options save_options ;
87 asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
88 asmbuffSize=INITIAL_INLINEASM;
94 yylval.yyinline = malloc (strlen(asmbuff)+1);
95 strcpy(yylval.yyinline,asmbuff);
100 if (asmp-asmbuff >= asmbuffSize-2) {
101 // increase the buffersize with 50%
102 int size=asmp-asmbuff;
103 asmbuffSize=asmbuffSize*3/2;
104 asmbuff = realloc (asmbuff, asmbuffSize);
111 if (asmp-asmbuff >= asmbuffSize-3) {
112 // increase the buffersize with 50%
113 int size=asmp-asmbuff;
114 asmbuffSize=asmbuffSize*3/2;
115 asmbuff = realloc (asmbuff, asmbuffSize);
120 "at" { count(); TKEYWORD(AT) ; }
121 "auto" { count(); return(AUTO); }
122 "bit" { count(); TKEYWORD(BIT) ; }
123 "break" { count(); return(BREAK); }
124 "case" { count(); return(CASE); }
125 "char" { count(); return(CHAR); }
126 "code" { count(); TKEYWORD(CODE); }
127 "const" { count(); return(CONST); }
128 "continue" { count(); return(CONTINUE); }
129 "critical" { count(); TKEYWORD(CRITICAL); }
130 "data" { count(); TKEYWORD(DATA); }
131 "default" { count(); return(DEFAULT); }
132 "do" { count(); return(DO); }
133 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
134 "else" { count(); return(ELSE); }
135 "enum" { count(); return(ENUM); }
136 "extern" { count(); return(EXTERN); }
137 "far" { count(); TKEYWORD(XDATA); }
138 "eeprom" { count(); TKEYWORD(EEPROM); }
139 "float" { count(); return(FLOAT); }
140 "flash" { count(); TKEYWORD(CODE);}
141 "for" { count(); return(FOR); }
142 "goto" { count(); return(GOTO); }
143 "idata" { count(); TKEYWORD(IDATA);}
144 "if" { count(); return(IF); }
145 "int" { count(); return(INT); }
146 "interrupt" { count(); return(INTERRUPT);}
147 "nonbanked" { count(); TKEYWORD(NONBANKED);}
148 "banked" { count(); TKEYWORD(BANKED);}
149 "long" { count(); return(LONG); }
150 "near" { count(); TKEYWORD(DATA);}
151 "pdata" { count(); TKEYWORD(PDATA); }
152 "reentrant" { count(); TKEYWORD(REENTRANT);}
153 "register" { count(); return(REGISTER); }
154 "return" { count(); return(RETURN); }
155 "sfr" { count(); TKEYWORD(SFR) ; }
156 "sbit" { count(); TKEYWORD(SBIT) ; }
157 "short" { count(); return(SHORT); }
158 "signed" { count(); return(SIGNED); }
159 "sizeof" { count(); return(SIZEOF); }
160 "sram" { count(); TKEYWORD(XDATA);}
161 "static" { count(); return(STATIC); }
162 "struct" { count(); return(STRUCT); }
163 "switch" { count(); return(SWITCH); }
164 "typedef" { count(); return(TYPEDEF); }
165 "union" { count(); return(UNION); }
166 "unsigned" { count(); return(UNSIGNED); }
167 "void" { count(); return(VOID); }
168 "volatile" { count(); return(VOLATILE); }
169 "using" { count(); TKEYWORD(USING); }
170 "_naked" { count(); TKEYWORD(NAKED); }
171 "while" { count(); return(WHILE); }
172 "xdata" { count(); TKEYWORD(XDATA); }
173 "..." { count(); return(VAR_ARGS);}
174 "__typeof" { count(); return TYPEOF;}
175 {L}({L}|{D})* { count(); return(check_type()); }
176 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
177 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
178 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
179 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
180 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
181 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
182 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
183 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
184 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
185 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
186 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
187 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
188 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
189 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
190 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
191 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
192 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
193 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
194 ">>" { count(); return(RIGHT_OP); }
195 "<<" { count(); return(LEFT_OP); }
196 "++" { count(); return(INC_OP); }
197 "--" { count(); return(DEC_OP); }
198 "->" { count(); return(PTR_OP); }
199 "&&" { count(); return(AND_OP); }
200 "||" { count(); return(OR_OP); }
201 "<=" { count(); return(LE_OP); }
202 ">=" { count(); return(GE_OP); }
203 "==" { count(); return(EQ_OP); }
204 "!=" { count(); return(NE_OP); }
205 ";" { count(); return(';'); }
206 "{" { count(); NestLevel++ ; return('{'); }
207 "}" { count(); NestLevel--; return('}'); }
208 "," { count(); return(','); }
209 ":" { count(); return(':'); }
210 "=" { count(); 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 ^#line.*"\n" { count(); checkCurrFile(yytext); }
230 ^#pragma.*"\n" { count(); process_pragma(yytext); }
232 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
233 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
236 [ \t\v\f] { count(); }
240 // that could have been removed by the preprocessor anyway
241 werror (W_STRAY_BACKSLASH, column);
248 int checkCurrFile ( char *s)
254 /* first check if this is a #line */
255 if ( strncmp(s,"#line",5) )
258 /* get to the line number */
265 sscanf(lineNum,"%d",&lNum);
267 /* now see if we have a file name */
268 while (*s != '\"' && *s)
271 /* if we don't have a filename then */
272 /* set the current line number to */
273 /* line number if printFlag is on */
275 lineno = yylineno = lNum ;
279 /* if we have a filename then check */
280 /* if it is "standard in" if yes then */
281 /* get the currentfile name info */
284 if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
285 lineno = yylineno = lNum;
286 currFname = fullSrcFileName ;
289 /* mark the end of the filename */
290 while (*s != '"') s++;
292 currFname = malloc (strlen(sb)+1);
293 strcpy(currFname,sb);
294 lineno = yylineno = lNum;
296 filename = currFname ;
306 for (i = 0; yytext[i] != '\0'; i++) {
307 if (yytext[i] == '\n') {
309 lineno = ++yylineno ;
312 if (yytext[i] == '\t')
313 column += 8 - (column % 8);
322 /* check if it is in the typedef table */
323 if (findSym(TypedefTab,NULL,yytext)) {
324 strcpy(yylval.yychar,yytext);
328 strcpy (yylval.yychar,yytext);
333 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
336 * Change by JTV 2001-05-19 to not concantenate strings
337 * to support ANSI hex and octal escape sequences in string liteals
340 char *stringLiteral () {
342 char *str = strLitBuff;
345 /* put into the buffer till we hit the first \" */
351 break; /* end of input */
353 /* if it is a \ then escape char's are allowed */
357 /* \<newline> is a continuator */
362 *str++ = '\\'; /* backslash in place */
363 *str++ = ch; /* get the escape char, no further check */
364 continue; /* carry on */
367 /* if new line we have a new line break, which is illegal */
369 werror (W_NEWLINE_IN_STRING);
376 /* if this is a quote then we have work to do */
377 /* find the next non whitespace character */
378 /* if that is a double quote then carry on */
380 *str++ = ch ; /* Pass end of this string or substring to evaluator */
381 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
384 if ((ch=input())!='\n') {
385 werror (W_STRAY_BACKSLASH, column);
406 *str++ = ch; /* Put next substring introducer into output string */
413 void doPragma (int op, char *cp)
417 memcpy(&save_options,&options,sizeof(options));
418 memcpy(&save_optimize,&optimize,sizeof(optimize));
421 memcpy(&options,&save_options,sizeof(options));
422 memcpy(&optimize,&save_optimize,sizeof(optimize));
425 optimize.loopInduction = 0 ;
428 optimize.loopInvariant = 0 ;
431 optimize.loopInduction = 1 ;
434 options.stackAuto = 1;
437 optimize.noJTabBoundary = 1;
440 optimize.global_cse = 0;
443 options.noOverlay = 1;
448 /* append to the functions already listed
450 for (; options.calleeSaves[i] ;i++);
451 parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
455 parseWithComma(options.excludeRegs, Safe_strdup(cp));
458 optimize.noLoopReverse = 1;
463 int process_pragma(char *s)
466 /* find the pragma */
467 while (strncmp(s,"#pragma",7))
471 /* look for the directive */
472 while(isspace(*s)) s++;
475 /* look for the end of the directive */
476 while ((! isspace(*s)) &&
480 /* First give the port a chance */
481 if (port->process_pragma && !port->process_pragma(cp))
484 /* now compare and do what needs to be done */
485 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
486 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
490 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
491 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
495 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
496 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
500 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
501 doPragma (P_NOINVARIANT,NULL) ;
505 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
506 doPragma (P_INDUCTION,NULL) ;
510 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
511 doPragma (P_STACKAUTO,NULL);
515 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
516 doPragma (P_NOJTBOUND,NULL);
520 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
521 doPragma (P_NOGCSE,NULL);
525 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
526 doPragma (P_NOOVERLAY,NULL);
530 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
531 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
535 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
536 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
540 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
541 doPragma(P_LOOPREV,NULL);
545 werror(W_UNKNOWN_PRAGMA,cp);
549 /* will return 1 if the string is a part
550 of a target specific keyword */
551 int isTargetKeyword(char *s)
555 if (port->keywords == NULL)
557 for ( i = 0 ; port->keywords[i] ; i++ ) {
558 if (strcmp(port->keywords[i],s) == 0)
565 extern int fatalError;
571 if (yylineno && filename)
572 fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",