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();
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 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 */
282 /* if we have a filename then check */
283 /* if it is "standard in" if yes then */
284 /* get the currentfile name info */
287 if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
289 currFname = fullSrcFileName ;
292 /* mark the end of the filename */
293 while (*s != '"') s++;
295 currFname = Safe_calloc(1,strlen(sb)+1);
296 strcpy(currFname,sb);
299 filename = currFname ;
308 while ((c = input()) != '*' && c) {
314 if (c && (c1 = input()) != '/') {
328 for (i = 0; yytext[i] != '\0'; i++) {
329 if (yytext[i] == '\n') {
331 lineno = ++yylineno ;
334 if (yytext[i] == '\t')
335 column += 8 - (column % 8);
344 /* check if it is in the typedef table */
345 if (findSym(TypedefTab,NULL,yytext)) {
346 strcpy(yylval.yychar,yytext);
350 strcpy (yylval.yychar,yytext);
355 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
358 * Change by JTV 2001-05-19 to not concantenate strings
359 * to support ANSI hex and octal escape sequences in string liteals
362 char *stringLiteral () {
364 char *str = strLitBuff;
367 /* put into the buffer till we hit the first \" */
373 break; /* end of input */
375 /* if it is a \ then escape char's are allowed */
379 // input() translates \n into \r\n
380 if ((ch=input())!='\n') {
383 /* \<newline> is a continuator */
387 *str++ = '\\'; /* backslash in place */
388 *str++ = ch; /* get the escape char, no further check */
389 continue; /* carry on */
392 /* if new line we have a new line break, which is illegal */
394 // input() translates \n into \r\n
395 if ((ch=input())!='\n') {
398 werror (W_NEWLINE_IN_STRING);
404 /* if this is a quote then we have work to do */
405 /* find the next non whitespace character */
406 /* if that is a double quote then carry on */
408 *str++ = ch ; /* Pass end of this string or substring to evaluator */
409 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
412 //werror (W_STRAY_BACKSLASH)
428 *str++ = ch; /* Put next substring introducer into output string */
435 void doPragma (int op, char *cp)
439 memcpy(&save_options,&options,sizeof(options));
440 memcpy(&save_optimize,&optimize,sizeof(optimize));
443 memcpy(&options,&save_options,sizeof(options));
444 memcpy(&optimize,&save_optimize,sizeof(optimize));
447 optimize.loopInduction = 0 ;
450 optimize.loopInvariant = 0 ;
453 optimize.loopInduction = 1 ;
456 options.stackAuto = 1;
459 optimize.noJTabBoundary = 1;
462 optimize.global_cse = 0;
465 options.noOverlay = 1;
470 /* append to the functions already listed
472 for (; options.calleeSaves[i] ;i++);
473 parseWithComma(&options.calleeSaves[i],strdup(cp));
477 parseWithComma(options.excludeRegs,strdup(cp));
480 optimize.noLoopReverse = 1;
485 int process_pragma(char *s)
488 /* find the pragma */
489 while (strncmp(s,"#pragma",7))
493 /* look for the directive */
494 while(isspace(*s)) s++;
497 /* look for the end of the directive */
498 while ((! isspace(*s)) &&
502 /* First give the port a chance */
503 if (port->process_pragma && !port->process_pragma(cp))
506 /* now compare and do what needs to be done */
507 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
508 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
512 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
513 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
517 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
518 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
522 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
523 doPragma (P_NOINVARIANT,NULL) ;
527 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
528 doPragma (P_INDUCTION,NULL) ;
532 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
533 doPragma (P_STACKAUTO,NULL);
537 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
538 doPragma (P_NOJTBOUND,NULL);
542 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
543 doPragma (P_NOGCSE,NULL);
547 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
548 doPragma (P_NOOVERLAY,NULL);
552 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
553 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
557 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
558 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
562 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
563 doPragma(P_EXCLUDE,NULL);
567 werror(W_UNKNOWN_PRAGMA,cp);
571 /* will return 1 if the string is a part
572 of a target specific keyword */
573 int isTargetKeyword(char *s)
577 if (port->keywords == NULL)
579 for ( i = 0 ; port->keywords[i] ; i++ ) {
580 if (strcmp(port->keywords[i],s) == 0)
587 extern int fatalError;
593 if (yylineno && filename)
594 fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",