new #pragma LESS_PEDANTIC
[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 #include "dbuf.h"
39
40 char *stringLiteral();
41 char *currFname;
42
43 extern int lineno, column;
44 extern char *filename ;
45 int   yylineno = 1               ;
46 void count()                     ;
47 int process_pragma(char *);
48 #undef yywrap
49
50 int yywrap YY_PROTO((void))
51 {
52    return(1);
53 }
54 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
55                                 check_type(yytext))
56 char *asmbuff=NULL;
57 int asmbuffSize=0;
58 char *asmp ;
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  ;
66
67  enum {
68      P_SAVE = 1,
69      P_RESTORE ,
70      P_NOINDUCTION,
71      P_NOINVARIANT,
72      P_INDUCTION ,
73      P_STACKAUTO ,
74      P_NOJTBOUND ,
75      P_NOOVERLAY ,
76      P_LESSPEDANTIC,
77      P_NOGCSE    ,
78      P_CALLEE_SAVES,
79      P_EXCLUDE   ,
80      P_NOIV      ,
81      P_LOOPREV   ,
82      P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
83                      /* cross-compiling for MINGW32 with gcc 3.2 */
84  };
85
86 %}
87 %x asm
88 %%
89 "_asm"         {  
90   count(); 
91   asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
92   asmbuffSize=INITIAL_INLINEASM;
93   BEGIN(asm) ;
94 }
95 <asm>"_endasm" { 
96   count();
97   *asmp = '\0';
98   yylval.yyinline = strdup (asmbuff);
99   BEGIN(INITIAL);
100   return (INLINEASM);
101 }
102 <asm>.         { 
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); 
108     asmp=asmbuff+size;
109   }
110   *asmp++ = yytext[0];
111 }
112 <asm>\n        { 
113   count(); 
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); 
119     asmp=asmbuff+size;
120   }
121   *asmp++ = '\n' ;
122 }
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); }
236
237 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
238 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
239 "\r\n"             { count(); }
240 "\n"               { count(); }
241 [ \t\v\f]      { count(); }
242 \\ {
243   char ch=input();
244   if (ch!='\n') {
245     // that could have been removed by the preprocessor anyway
246     werror (W_STRAY_BACKSLASH, column);
247     unput(ch);
248   }
249 }
250 .                          { count()    ; }
251 %%
252
253 int checkCurrFile ( char *s)
254 {
255     char lineNum[10]                    ;
256     int  lNum                           ;
257     char *tptr                          ;
258        
259     /* first check if this is a #line */
260     if ( strncmp(s,"#line",5) )
261         return  0                               ;
262     
263     /* get to the line number */
264     while (!isdigit(*s))
265         s++ ;
266     tptr = lineNum ;
267     while (isdigit(*s))
268         *tptr++ = *s++ ;
269     *tptr = '\0'; 
270     sscanf(lineNum,"%d",&lNum);
271     
272     /* now see if we have a file name */
273     while (*s != '\"' && *s) 
274         s++ ;
275     
276     /* if we don't have a filename then */
277     /* set the current line number to   */
278     /* line number if printFlag is on   */
279     if (!*s) {          
280       lineno = yylineno = lNum ;
281       return 0;
282     }
283     
284     /* if we have a filename then check */
285     /* if it is "standard in" if yes then */
286     /* get the currentfile name info    */
287     s++ ;
288
289     /* in c1mode fullSrcFileName is NULL */
290     if ( fullSrcFileName &&
291          strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
292       lineno = yylineno = lNum;                                 
293       currFname = fullSrcFileName ;
294     }  else {
295         char *sb = s;
296         /* mark the end of the filename */
297         while (*s != '"') s++;
298         *s = '\0';
299         currFname = strdup (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                 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
331                 return (TYPE_NAME) ;
332         }
333         else   {
334                 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
335                 return(IDENTIFIER);
336         }
337 }
338
339 /*
340  * Change by JTV 2001-05-19 to not concantenate strings
341  * to support ANSI hex and octal escape sequences in string liteals 
342  */
343
344 char *stringLiteral()
345 {
346 #define STR_BUF_CHUNCK_LEN  1024
347   int ch;
348   static struct dbuf_s dbuf;
349   char buf[2];
350
351   if (dbuf.alloc == 0)
352     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
353   else
354     dbuf_set_size(&dbuf, 0);
355
356
357   dbuf_append(&dbuf, "\"", 1);
358   /* put into the buffer till we hit the first \" */
359
360   while ((ch = input()) != 0) {
361     switch (ch) {
362     case '\\':
363       /* if it is a \ then escape char's are allowed */
364       ch = input();
365       if (ch == '\n') {
366         /* \<newline> is a continuator */
367         lineno = ++yylineno;
368         column = 0;
369       }
370       else {
371         buf[0] = '\\';
372         buf[1] = ch;
373         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
374       }
375       break; /* carry on */
376
377     case '\n':
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);
381       lineno = ++yylineno;
382       column = 0;
383       break;
384
385     case '"':
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=='\\')) {
391         switch (ch) {
392         case '\\':
393           if ((ch = input()) != '\n') {
394             werror(W_STRAY_BACKSLASH, column);
395             unput(ch);
396           }
397           else {
398             lineno = ++yylineno;
399             column = 0;
400           }
401           break;
402
403         case '\n':
404           yylineno++;
405           break;
406         }
407       }
408
409       if (!ch) 
410         goto out;
411
412       if (ch != '\"') {
413         unput(ch) ;
414         goto out;
415       }
416       break;
417
418     default:
419       buf[0] = ch;
420       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
421     }
422   }
423
424 out:
425   return (char *)dbuf_c_str(&dbuf);
426 }
427
428 void doPragma (int op, char *cp)
429 {
430     switch (op) {
431     case P_SAVE:
432         memcpy(&save_options,&options,sizeof(options));
433         memcpy(&save_optimize,&optimize,sizeof(optimize));
434         break;
435     case P_RESTORE:
436         memcpy(&options,&save_options,sizeof(options));
437         memcpy(&optimize,&save_optimize,sizeof(optimize));
438         break;
439     case P_NOINDUCTION:
440         optimize.loopInduction = 0 ;
441         break;
442     case P_NOINVARIANT:
443         optimize.loopInvariant = 0 ;
444         break;
445     case P_INDUCTION:
446         optimize.loopInduction = 1 ;
447         break;
448     case P_STACKAUTO:
449         options.stackAuto = 1;
450         break;
451     case P_NOJTBOUND:
452         optimize.noJTabBoundary = 1;
453         break;
454     case P_NOGCSE:
455         optimize.global_cse = 0;
456         break;
457     case P_NOOVERLAY:
458         options.noOverlay = 1;
459         break;
460     case P_LESSPEDANTIC:
461         options.lessPedantic = 1;
462         break;
463     case P_CALLEE_SAVES:
464         {
465             int i=0;
466             /* append to the functions already listed
467                in callee-saves */
468             for (; options.calleeSaves[i] ;i++);
469             parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
470         }
471         break;
472     case P_EXCLUDE:
473         parseWithComma(options.excludeRegs, Safe_strdup(cp));
474         break;
475     case P_NOIV:
476         options.noiv = 1;
477         break;
478     case P_LOOPREV:
479         optimize.noLoopReverse = 1;
480         break;
481     case P_OVERLAY_:
482         break; /* notyet */
483     }
484 }
485
486 int process_pragma(char *s)
487 {
488     char *cp ;
489     /* find the pragma */
490     while (strncmp(s,"#pragma",7))
491         s++;
492     s += 7;
493     
494     /* look for the directive */
495     while(isspace(*s)) s++;
496
497     cp = s;
498     /* look for the end of the directive */
499     while ((! isspace(*s)) && 
500            (*s != '\n')) 
501         s++ ;    
502
503     /* First give the port a chance */
504     if (port->process_pragma && !port->process_pragma(cp))
505         return 0;
506
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));
510         return 0;
511     }
512
513     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
514         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
515         return 0;
516     }
517
518     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
519         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
520         return 0;
521     }
522
523     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
524         doPragma (P_NOINVARIANT,NULL)   ;
525         return 0;
526     }
527
528     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
529         doPragma (P_INDUCTION,NULL)     ;
530         return 0;
531     }
532
533     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
534         doPragma (P_STACKAUTO,NULL);
535         return 0;
536     }
537
538     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
539         doPragma (P_NOJTBOUND,NULL);
540         return 0;
541     }
542
543     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
544         doPragma (P_NOGCSE,NULL);
545         return 0;
546     }
547
548     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
549         doPragma (P_NOOVERLAY,NULL);
550         return 0;
551     }
552     
553     if (strncmp(cp,PRAGMA_LESSPEDANTIC,strlen(PRAGMA_LESSPEDANTIC)) == 0) {
554         doPragma(P_LESSPEDANTIC,cp+strlen(PRAGMA_LESSPEDANTIC));
555         return 0;
556     }
557     
558     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
559         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
560         return 0;
561     }
562     
563     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
564         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
565         return 0;
566     }
567
568     if (strncmp(cp,PRAGMA_NOIV,strlen(PRAGMA_NOIV)) == 0) {
569         doPragma(P_NOIV,cp+strlen(PRAGMA_NOIV));
570         return 0;
571     }
572
573     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
574         doPragma(P_LOOPREV,NULL);
575         return 0;
576     }
577
578     werror(W_UNKNOWN_PRAGMA,cp);
579     return 0;
580 }
581
582 /* will return 1 if the string is a part
583    of a target specific keyword */
584 int isTargetKeyword(char *s)
585 {
586     int i;
587     
588     if (port->keywords == NULL)
589         return 0;
590     for ( i = 0 ; port->keywords[i] ; i++ ) {
591         if (strcmp(port->keywords[i],s) == 0)
592             return 1;
593     }
594     
595     return 0;
596 }
597
598 extern int fatalError;
599
600 int yyerror(char *s)
601 {
602    fflush(stdout);
603
604    if (yylineno && filename) {
605      fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
606              filename,yylineno,
607              s,yytext,column);
608      fatalError++;
609    } else {
610      // this comes from an empy file, no problem
611    }
612    return 0;
613 }