* src/SDCCglue.h: make tmpfileNameSet available for preOutName
[fw/sdcc] / src / SDCC.lex
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)
5   
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
9    later version.
10    
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.
15    
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.
19     
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 -------------------------------------------------------------------------*/
24
25 D        [0-9]
26 L        [a-zA-Z_]
27 H        [a-fA-F0-9]
28 E        [Ee][+-]?{D}+
29 FS       (f|F|l|L)
30 IS       (u|U|l|L)*
31 %{
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "common.h"
37 #include "newalloc.h"
38     
39 char *stringLiteral();
40 char *currFname;
41
42 extern int lineno, column;
43 extern char *filename ;
44 int   yylineno = 1               ;
45 void count()                     ;
46 int process_pragma(char *);
47 #undef yywrap
48
49 int yywrap YY_PROTO((void))
50 {
51    return(1);
52 }
53 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
54                                 check_type(yytext))
55 char *asmbuff=NULL;
56 int asmbuffSize=0;
57 char *asmp ;
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  ;
65
66  enum {
67      P_SAVE = 1,
68      P_RESTORE ,
69      P_NOINDUCTION,
70      P_NOINVARIANT,
71      P_INDUCTION ,
72      P_STACKAUTO ,
73      P_NOJTBOUND ,
74      P_NOOVERLAY ,
75      P_NOGCSE    ,
76      P_CALLEE_SAVES,
77      P_EXCLUDE   ,
78      P_NOIV      ,
79      P_LOOPREV   ,
80      P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
81                      /* cross-compiling for MINGW32 with gcc 3.2 */
82  };
83
84 %}
85 %x asm
86 %%
87 "_asm"         {  
88   count(); 
89   asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
90   asmbuffSize=INITIAL_INLINEASM;
91   BEGIN(asm) ;
92 }
93 <asm>"_endasm" { 
94   count();
95   *asmp = '\0';
96   yylval.yyinline = malloc (strlen(asmbuff)+1);
97   strcpy(yylval.yyinline,asmbuff);
98   BEGIN(INITIAL);
99   return (INLINEASM);
100 }
101 <asm>.         { 
102   if (asmp-asmbuff >= asmbuffSize-2) {
103     // increase the buffersize with 50%
104     int size=asmp-asmbuff;
105     asmbuffSize=asmbuffSize*3/2;
106     asmbuff = realloc (asmbuff, asmbuffSize); 
107     asmp=asmbuff+size;
108   }
109   *asmp++ = yytext[0];
110 }
111 <asm>\n        { 
112   count(); 
113   if (asmp-asmbuff >= asmbuffSize-3) {
114     // increase the buffersize with 50%
115     int size=asmp-asmbuff;
116     asmbuffSize=asmbuffSize*3/2;
117     asmbuff = realloc (asmbuff, asmbuffSize); 
118     asmp=asmbuff+size;
119   }
120   *asmp++ = '\n' ;
121 }
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 "..."          { count(); return(VAR_ARGS);}
176 "__typeof"     { count(); return TYPEOF;}
177 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE);}
178 "_overlay"     { count(); TKEYWORD(OVERLAY);}
179 {L}({L}|{D})*  { count(); return(check_type()); }
180 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
181 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
182 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
183 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
184 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
185 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
186 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
187 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
188 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
189 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
190 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
191 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
192 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
193 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
194 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
195 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
196 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
197 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
198 ">>"           { count(); return(RIGHT_OP); }
199 "<<"           { count(); return(LEFT_OP); }
200 "++"           { count(); return(INC_OP); }
201 "--"           { count(); return(DEC_OP); }
202 "->"           { count(); return(PTR_OP); }
203 "&&"           { count(); return(AND_OP); }
204 "||"           { count(); return(OR_OP); }
205 "<="           { count(); return(LE_OP); }
206 ">="           { count(); return(GE_OP); }
207 "=="           { count(); return(EQ_OP); }
208 "!="           { count(); return(NE_OP); }
209 ";"            { count(); return(';'); }
210 "{"            { count(); NestLevel++ ;  return('{'); }
211 "}"            { count(); NestLevel--; 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 "?"            { count(); return('?'); }
233 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
234 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
235
236 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
237 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
238 "\r\n"             { count(); }
239 "\n"               { count(); }
240 [ \t\v\f]      { count(); }
241 \\ {
242   char ch=input();
243   if (ch!='\n') {
244     // that could have been removed by the preprocessor anyway
245     werror (W_STRAY_BACKSLASH, column);
246     unput(ch);
247   }
248 }
249 .                          { count()    ; }
250 %%
251
252 int checkCurrFile ( char *s)
253 {
254     char lineNum[10]                    ;
255     int  lNum                           ;
256     char *tptr                          ;
257        
258     /* first check if this is a #line */
259     if ( strncmp(s,"#line",5) )
260         return  0                               ;
261     
262     /* get to the line number */
263     while (!isdigit(*s))
264         s++ ;
265     tptr = lineNum ;
266     while (isdigit(*s))
267         *tptr++ = *s++ ;
268     *tptr = '\0'; 
269     sscanf(lineNum,"%d",&lNum);
270     
271     /* now see if we have a file name */
272     while (*s != '\"' && *s) 
273         s++ ;
274     
275     /* if we don't have a filename then */
276     /* set the current line number to   */
277     /* line number if printFlag is on   */
278     if (!*s) {          
279       lineno = yylineno = lNum ;
280       return 0;
281     }
282     
283     /* if we have a filename then check */
284     /* if it is "standard in" if yes then */
285     /* get the currentfile name info    */
286     s++ ;
287
288     /* in c1mode fullSrcFileName is NULL */
289     if ( fullSrcFileName &&
290          strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
291       lineno = yylineno = lNum;                                 
292       currFname = fullSrcFileName ;
293     }  else {
294         char *sb = s;
295         /* mark the end of the filename */
296         while (*s != '"') s++;
297         *s = '\0';
298         currFname = malloc (strlen(sb)+1);
299         strcpy(currFname,sb);
300         lineno = yylineno = lNum;
301     }
302     filename = currFname ;
303     return 0;
304 }
305     
306 int column = 0;
307 int plineIdx=0;
308
309 void count()
310 {
311   int i;
312   for (i = 0; yytext[i] != '\0'; i++)   {                               
313     if (yytext[i] == '\n')      {         
314       column = 0;
315       lineno = ++yylineno ;
316     }
317     else 
318       if (yytext[i] == '\t')
319         column += 8 - (column % 8);
320       else
321         column++;
322   }
323   /* ECHO; */
324 }
325
326 int check_type()
327 {
328         /* check if it is in the typedef table */
329         if (findSym(TypedefTab,NULL,yytext)) {
330                 strcpy(yylval.yychar,yytext);
331                 return (TYPE_NAME) ;
332         }
333         else   {
334                 strcpy (yylval.yychar,yytext);
335                 return(IDENTIFIER);
336         }
337 }
338
339 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
340
341 /*
342  * Change by JTV 2001-05-19 to not concantenate strings
343  * to support ANSI hex and octal escape sequences in string liteals 
344  */
345
346 char *stringLiteral () {
347   int ch;
348   char *str = strLitBuff;
349   
350   *str++ = '\"';
351   /* put into the buffer till we hit the first \" */
352   
353   while (1) {
354     ch = input();
355     
356     if (!ch)
357       break; /* end of input */
358     
359     /* if it is a \ then escape char's are allowed */
360     if (ch == '\\') {
361       ch=input();
362       if (ch=='\n') {
363         /* \<newline> is a continuator */
364         lineno=++yylineno;
365         column=0;
366         continue;
367       }
368       *str++ = '\\'; /* backslash in place */
369       *str++ = ch; /* get the escape char, no further check */
370       continue; /* carry on */
371     }
372     
373     /* if new line we have a new line break, which is illegal */
374     if (ch == '\n') {
375       werror (W_NEWLINE_IN_STRING);
376       *str++ = '\n';
377       lineno=++yylineno;
378       column=0;
379       continue;
380     }
381     
382     /* if this is a quote then we have work to do */
383     /* find the next non whitespace character     */
384     /* if that is a double quote then carry on    */
385     if (ch == '\"') {
386       *str++  = ch ; /* Pass end of this string or substring to evaluator */
387       while ((ch = input()) && (isspace(ch) || ch=='\\')) {
388         switch (ch) {
389         case '\\':
390           if ((ch=input())!='\n') {
391             werror (W_STRAY_BACKSLASH, column);
392             unput(ch);
393           } else {
394             lineno=++yylineno;
395             column=0;
396           }
397           break;
398         case '\n':
399           yylineno++;
400           break;
401         }
402       }
403
404       if (!ch) 
405         break; 
406
407       if (ch != '\"') {
408         unput(ch) ;
409         break ;
410       }
411     }
412     *str++  = ch; /* Put next substring introducer into output string */
413   }  
414   *str = '\0';
415   
416   return strLitBuff;
417 }
418
419 void doPragma (int op, char *cp)
420 {
421     switch (op) {
422     case P_SAVE:
423         memcpy(&save_options,&options,sizeof(options));
424         memcpy(&save_optimize,&optimize,sizeof(optimize));
425         break;
426     case P_RESTORE:
427         memcpy(&options,&save_options,sizeof(options));
428         memcpy(&optimize,&save_optimize,sizeof(optimize));
429         break;
430     case P_NOINDUCTION:
431         optimize.loopInduction = 0 ;
432         break;
433     case P_NOINVARIANT:
434         optimize.loopInvariant = 0 ;
435         break;
436     case P_INDUCTION:
437         optimize.loopInduction = 1 ;
438         break;
439     case P_STACKAUTO:
440         options.stackAuto = 1;
441         break;
442     case P_NOJTBOUND:
443         optimize.noJTabBoundary = 1;
444         break;
445     case P_NOGCSE:
446         optimize.global_cse = 0;
447         break;
448     case P_NOOVERLAY:
449         options.noOverlay = 1;
450         break;
451     case P_CALLEE_SAVES:
452         {
453             int i=0;
454             /* append to the functions already listed
455                in callee-saves */
456             for (; options.calleeSaves[i] ;i++);
457             parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
458         }
459         break;
460     case P_EXCLUDE:
461         parseWithComma(options.excludeRegs, Safe_strdup(cp));
462         break;
463     case P_NOIV:
464         options.noiv = 1;
465         break;
466     case P_LOOPREV:
467         optimize.noLoopReverse = 1;
468         break;
469     case P_OVERLAY_:
470         break; /* notyet */
471     }
472 }
473
474 int process_pragma(char *s)
475 {
476     char *cp ;
477     /* find the pragma */
478     while (strncmp(s,"#pragma",7))
479         s++;
480     s += 7;
481     
482     /* look for the directive */
483     while(isspace(*s)) s++;
484
485     cp = s;
486     /* look for the end of the directive */
487     while ((! isspace(*s)) && 
488            (*s != '\n')) 
489         s++ ;    
490
491     /* First give the port a chance */
492     if (port->process_pragma && !port->process_pragma(cp))
493         return 0;
494
495     /* now compare and do what needs to be done */
496     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
497         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
498         return 0;
499     }
500
501     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
502         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
503         return 0;
504     }
505
506     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
507         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
508         return 0;
509     }
510
511     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
512         doPragma (P_NOINVARIANT,NULL)   ;
513         return 0;
514     }
515
516     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
517         doPragma (P_INDUCTION,NULL)     ;
518         return 0;
519     }
520
521     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
522         doPragma (P_STACKAUTO,NULL);
523         return 0;
524     }
525
526     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
527         doPragma (P_NOJTBOUND,NULL);
528         return 0;
529     }
530
531     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
532         doPragma (P_NOGCSE,NULL);
533         return 0;
534     }
535
536     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
537         doPragma (P_NOOVERLAY,NULL);
538         return 0;
539     }
540     
541     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
542         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
543         return 0;
544     }
545     
546     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
547         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
548         return 0;
549     }
550
551     if (strncmp(cp,PRAGMA_NOIV,strlen(PRAGMA_NOIV)) == 0) {
552         doPragma(P_NOIV,cp+strlen(PRAGMA_NOIV));
553         return 0;
554     }
555
556     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
557         doPragma(P_LOOPREV,NULL);
558         return 0;
559     }
560
561     werror(W_UNKNOWN_PRAGMA,cp);
562     return 0;
563 }
564
565 /* will return 1 if the string is a part
566    of a target specific keyword */
567 int isTargetKeyword(char *s)
568 {
569     int i;
570     
571     if (port->keywords == NULL)
572         return 0;
573     for ( i = 0 ; port->keywords[i] ; i++ ) {
574         if (strcmp(port->keywords[i],s) == 0)
575             return 1;
576     }
577     
578     return 0;
579 }
580
581 extern int fatalError;
582
583 int yyerror(char *s)
584 {
585    fflush(stdout);
586
587    if (yylineno && filename) {
588      fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
589              filename,yylineno,
590              s,yytext,column);
591      fatalError++;
592    } else {
593      // this comes from an empy file, no problem
594    }
595    return 0;
596 }