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 -------------------------------------------------------------------------*/
40 char *stringLiteral();
43 extern int lineno, column;
44 extern char *filename ;
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 ;
82 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
83 /* cross-compiling for MINGW32 with gcc 3.2 */
91 asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
92 asmbuffSize=INITIAL_INLINEASM;
98 yylval.yyinline = strdup (asmbuff);
103 if (asmp-asmbuff >= asmbuffSize-2) {
104 // increase the buffersize with 50%
105 int size=asmp-asmbuff;
106 asmbuffSize=asmbuffSize*3/2;
107 asmbuff = realloc (asmbuff, asmbuffSize);
114 if (asmp-asmbuff >= asmbuffSize-3) {
115 // increase the buffersize with 50%
116 int size=asmp-asmbuff;
117 asmbuffSize=asmbuffSize*3/2;
118 asmbuff = realloc (asmbuff, asmbuffSize);
123 "at" { count(); TKEYWORD(AT) ; }
124 "auto" { count(); return(AUTO); }
125 "bit" { count(); TKEYWORD(BIT) ; }
126 "break" { count(); return(BREAK); }
127 "case" { count(); return(CASE); }
128 "char" { count(); return(CHAR); }
129 "code" { count(); TKEYWORD(CODE); }
130 "const" { count(); return(CONST); }
131 "continue" { count(); return(CONTINUE); }
132 "critical" { count(); TKEYWORD(CRITICAL); }
133 "data" { count(); TKEYWORD(DATA); }
134 "default" { count(); return(DEFAULT); }
135 "do" { count(); return(DO); }
136 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
137 "else" { count(); return(ELSE); }
138 "enum" { count(); return(ENUM); }
139 "extern" { count(); return(EXTERN); }
140 "far" { count(); TKEYWORD(XDATA); }
141 "eeprom" { count(); TKEYWORD(EEPROM); }
142 "float" { count(); return(FLOAT); }
143 "flash" { count(); TKEYWORD(CODE);}
144 "for" { count(); return(FOR); }
145 "goto" { count(); return(GOTO); }
146 "idata" { count(); TKEYWORD(IDATA);}
147 "if" { count(); return(IF); }
148 "int" { count(); return(INT); }
149 "interrupt" { count(); return(INTERRUPT);}
150 "nonbanked" { count(); TKEYWORD(NONBANKED);}
151 "banked" { count(); TKEYWORD(BANKED);}
152 "long" { count(); return(LONG); }
153 "near" { count(); TKEYWORD(DATA);}
154 "pdata" { count(); TKEYWORD(PDATA); }
155 "reentrant" { count(); TKEYWORD(REENTRANT);}
156 "register" { count(); return(REGISTER); }
157 "return" { count(); return(RETURN); }
158 "sfr" { count(); TKEYWORD(SFR) ; }
159 "sbit" { count(); TKEYWORD(SBIT) ; }
160 "short" { count(); return(SHORT); }
161 "signed" { count(); return(SIGNED); }
162 "sizeof" { count(); return(SIZEOF); }
163 "sram" { count(); TKEYWORD(XDATA);}
164 "static" { count(); return(STATIC); }
165 "struct" { count(); return(STRUCT); }
166 "switch" { count(); return(SWITCH); }
167 "typedef" { count(); return(TYPEDEF); }
168 "union" { count(); return(UNION); }
169 "unsigned" { count(); return(UNSIGNED); }
170 "void" { count(); return(VOID); }
171 "volatile" { count(); return(VOLATILE); }
172 "using" { count(); TKEYWORD(USING); }
173 "_naked" { count(); TKEYWORD(NAKED); }
174 "while" { count(); return(WHILE); }
175 "xdata" { count(); TKEYWORD(XDATA); }
176 "..." { count(); return(VAR_ARGS);}
177 "__typeof" { count(); return TYPEOF;}
178 "_JavaNative" { count(); TKEYWORD(JAVANATIVE);}
179 "_overlay" { count(); TKEYWORD(OVERLAY);}
180 {L}({L}|{D})* { count(); return(check_type()); }
181 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
182 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
183 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
184 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
185 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
186 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
187 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
188 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
189 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
190 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
191 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
192 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
193 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
194 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
195 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
196 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
197 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
198 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
199 ">>" { count(); return(RIGHT_OP); }
200 "<<" { count(); return(LEFT_OP); }
201 "++" { count(); return(INC_OP); }
202 "--" { count(); return(DEC_OP); }
203 "->" { count(); return(PTR_OP); }
204 "&&" { count(); return(AND_OP); }
205 "||" { count(); return(OR_OP); }
206 "<=" { count(); return(LE_OP); }
207 ">=" { count(); return(GE_OP); }
208 "==" { count(); return(EQ_OP); }
209 "!=" { count(); return(NE_OP); }
210 ";" { count(); return(';'); }
211 "{" { count(); NestLevel++ ; return('{'); }
212 "}" { count(); NestLevel--; 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 "|" { count(); return('|'); }
233 "?" { count(); return('?'); }
234 ^#line.*"\n" { count(); checkCurrFile(yytext); }
235 ^#pragma.*"\n" { count(); process_pragma(yytext); }
237 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
238 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
241 [ \t\v\f] { count(); }
245 // that could have been removed by the preprocessor anyway
246 werror (W_STRAY_BACKSLASH, column);
253 int checkCurrFile ( char *s)
259 /* first check if this is a #line */
260 if ( strncmp(s,"#line",5) )
263 /* get to the line number */
270 sscanf(lineNum,"%d",&lNum);
272 /* now see if we have a file name */
273 while (*s != '\"' && *s)
276 /* if we don't have a filename then */
277 /* set the current line number to */
278 /* line number if printFlag is on */
280 lineno = yylineno = lNum ;
284 /* if we have a filename then check */
285 /* if it is "standard in" if yes then */
286 /* get the currentfile name info */
289 /* in c1mode fullSrcFileName is NULL */
290 if ( fullSrcFileName &&
291 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
292 lineno = yylineno = lNum;
293 currFname = fullSrcFileName ;
296 /* mark the end of the filename */
297 while (*s != '"') s++;
299 currFname = strdup (sb);
300 lineno = yylineno = lNum;
302 filename = currFname ;
312 for (i = 0; yytext[i] != '\0'; i++) {
313 if (yytext[i] == '\n') {
315 lineno = ++yylineno ;
318 if (yytext[i] == '\t')
319 column += 8 - (column % 8);
328 /* check if it is in the typedef table */
329 if (findSym(TypedefTab,NULL,yytext)) {
330 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
334 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
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 #define STR_BUF_CHUNCK_LEN 1024
348 static struct dbuf_s dbuf;
352 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
354 dbuf_set_size(&dbuf, 0);
357 dbuf_append(&dbuf, "\"", 1);
358 /* put into the buffer till we hit the first \" */
360 while ((ch = input()) != 0) {
363 /* if it is a \ then escape char's are allowed */
366 /* \<newline> is a continuator */
373 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
375 break; /* carry on */
378 /* if new line we have a new line break, which is illegal */
379 werror(W_NEWLINE_IN_STRING);
380 dbuf_append(&dbuf, "\n", 1);
386 /* if this is a quote then we have work to do */
387 /* find the next non whitespace character */
388 /* if that is a double quote then carry on */
389 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
390 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
393 if ((ch = input()) != '\n') {
394 werror(W_STRAY_BACKSLASH, column);
420 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
425 return (char *)dbuf_c_str(&dbuf);
428 void doPragma (int op, char *cp)
432 memcpy(&save_options,&options,sizeof(options));
433 memcpy(&save_optimize,&optimize,sizeof(optimize));
436 memcpy(&options,&save_options,sizeof(options));
437 memcpy(&optimize,&save_optimize,sizeof(optimize));
440 optimize.loopInduction = 0 ;
443 optimize.loopInvariant = 0 ;
446 optimize.loopInduction = 1 ;
449 options.stackAuto = 1;
452 optimize.noJTabBoundary = 1;
455 optimize.global_cse = 0;
458 options.noOverlay = 1;
461 options.lessPedantic = 1;
466 /* append to the functions already listed
468 for (; options.calleeSaves[i] ;i++);
469 parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
473 parseWithComma(options.excludeRegs, Safe_strdup(cp));
479 optimize.noLoopReverse = 1;
486 int process_pragma(char *s)
489 /* find the pragma */
490 while (strncmp(s,"#pragma",7))
494 /* look for the directive */
495 while(isspace(*s)) s++;
498 /* look for the end of the directive */
499 while ((! isspace(*s)) &&
503 /* First give the port a chance */
504 if (port->process_pragma && !port->process_pragma(cp))
507 /* now compare and do what needs to be done */
508 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
509 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
513 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
514 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
518 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
519 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
523 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
524 doPragma (P_NOINVARIANT,NULL) ;
528 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
529 doPragma (P_INDUCTION,NULL) ;
533 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
534 doPragma (P_STACKAUTO,NULL);
538 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
539 doPragma (P_NOJTBOUND,NULL);
543 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
544 doPragma (P_NOGCSE,NULL);
548 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
549 doPragma (P_NOOVERLAY,NULL);
553 if (strncmp(cp,PRAGMA_LESSPEDANTIC,strlen(PRAGMA_LESSPEDANTIC)) == 0) {
554 doPragma(P_LESSPEDANTIC,cp+strlen(PRAGMA_LESSPEDANTIC));
558 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
559 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
563 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
564 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
568 if (strncmp(cp,PRAGMA_NOIV,strlen(PRAGMA_NOIV)) == 0) {
569 doPragma(P_NOIV,cp+strlen(PRAGMA_NOIV));
573 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
574 doPragma(P_LOOPREV,NULL);
578 werror(W_UNKNOWN_PRAGMA,cp);
582 /* will return 1 if the string is a part
583 of a target specific keyword */
584 int isTargetKeyword(char *s)
588 if (port->keywords == NULL)
590 for ( i = 0 ; port->keywords[i] ; i++ ) {
591 if (strcmp(port->keywords[i],s) == 0)
598 extern int fatalError;
604 if (yylineno && filename) {
605 fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
610 // this comes from an empy file, no problem