fixed some warnings, introduced with changes made 15.06.1003
[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 %option noyywrap
26
27 D        [0-9]
28 L        [a-zA-Z_]
29 H        [a-fA-F0-9]
30 E        [Ee][+-]?{D}+
31 FS       (f|F|l|L)
32 IS       (u|U|l|L)*
33 %{
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "common.h"
39 #include "newalloc.h"
40 #include "dbuf.h"
41
42 static char *stringLiteral(void);
43 char *currFname;
44
45 extern int lineno, column;
46 extern char *filename;
47 int  mylineno = 1;
48 static void count(void);
49 static int process_pragma(char *);
50 #undef yywrap
51
52 #ifndef YYPROTO
53
54 #ifdef YY_USE_PROTOS
55 #define YY_PROTO(proto) proto
56 #else
57 #define YY_PROTO(proto) ()
58 #endif
59
60 #endif
61
62 int yywrap YY_PROTO((void))
63 {
64    return(1);
65 }
66
67 static void yyunput (int, char *);
68
69 static void my_unput(char c)
70 {
71   yyunput(c, (yytext_ptr));
72 }
73
74 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
75                                 check_type())
76 char *asmbuff=NULL;
77 int asmbuffSize=0;
78 char *asmp ;
79 static int check_type(void);
80 static int isTargetKeyword(char *s);
81 static int checkCurrFile (char *s);
82 //extern int processPragma      (char *);
83 //extern int printListing               (int   );
84 struct optimize save_optimize;
85 struct options  save_options;
86 %}
87
88 %x asm
89 %%
90 "_asm"         {  
91   count(); 
92   asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
93   asmbuffSize=INITIAL_INLINEASM;
94   BEGIN(asm) ;
95 }
96 <asm>"_endasm" { 
97   count();
98   *asmp = '\0';
99   yylval.yyinline = strdup (asmbuff);
100   BEGIN(INITIAL);
101   return (INLINEASM);
102 }
103 <asm>.         { 
104   if (asmp-asmbuff >= asmbuffSize-2) {
105     // increase the buffersize with 50%
106     int size=asmp-asmbuff;
107     asmbuffSize=asmbuffSize*3/2;
108     asmbuff = realloc (asmbuff, asmbuffSize); 
109     asmp=asmbuff+size;
110   }
111   *asmp++ = yytext[0];
112 }
113 <asm>\n        { 
114   count(); 
115   if (asmp-asmbuff >= asmbuffSize-3) {
116     // increase the buffersize with 50%
117     int size=asmp-asmbuff;
118     asmbuffSize=asmbuffSize*3/2;
119     asmbuff = realloc (asmbuff, asmbuffSize); 
120     asmp=asmbuff+size;
121   }
122   *asmp++ = '\n' ;
123 }
124 "at"           { count(); TKEYWORD(AT)  ; }
125 "auto"         { count(); return(AUTO); }
126 "bit"          { count(); TKEYWORD(BIT) ; }
127 "break"        { count(); return(BREAK); }
128 "case"         { count(); return(CASE); }
129 "char"         { count(); return(CHAR); }
130 "code"         { count(); TKEYWORD(CODE); }
131 "const"        { count(); return(CONST); }
132 "continue"     { count(); return(CONTINUE); }
133 "critical"     { count(); TKEYWORD(CRITICAL); } 
134 "data"         { count(); TKEYWORD(DATA);   }
135 "default"      { count(); return(DEFAULT); }
136 "do"           { count(); return(DO); }
137 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
138 "else"         { count(); return(ELSE); }
139 "enum"         { count(); return(ENUM); }
140 "extern"       { count(); return(EXTERN); }
141 "far"          { count(); TKEYWORD(XDATA);  }
142 "eeprom"       { count(); TKEYWORD(EEPROM);  }
143 "float"        { count(); return(FLOAT); }
144 "flash"        { count(); TKEYWORD(CODE);}
145 "for"          { count(); return(FOR); }
146 "goto"         { count(); return(GOTO); }
147 "idata"        { count(); TKEYWORD(IDATA);}
148 "if"           { count(); return(IF); }
149 "int"          { count(); return(INT); }
150 "interrupt"    { count(); return(INTERRUPT);}
151 "nonbanked"    { count(); TKEYWORD(NONBANKED);}
152 "banked"       { count(); TKEYWORD(BANKED);}
153 "long"         { count(); return(LONG); }
154 "near"         { count(); TKEYWORD(DATA);}
155 "pdata"        { count(); TKEYWORD(PDATA); }
156 "reentrant"    { count(); TKEYWORD(REENTRANT);}
157 "register"     { count(); return(REGISTER); }
158 "return"       { count(); return(RETURN); }
159 "sfr"          { count(); TKEYWORD(SFR) ; }
160 "sbit"         { count(); TKEYWORD(SBIT)        ; }
161 "short"        { count(); return(SHORT); }
162 "signed"       { count(); return(SIGNED); }
163 "sizeof"       { count(); return(SIZEOF); }
164 "sram"         { count(); TKEYWORD(XDATA);}
165 "static"       { count(); return(STATIC); }
166 "struct"       { count(); return(STRUCT); }
167 "switch"       { count(); return(SWITCH); }
168 "typedef"      { count(); return(TYPEDEF); }
169 "union"        { count(); return(UNION); }
170 "unsigned"     { count(); return(UNSIGNED); }
171 "void"         { count(); return(VOID); }
172 "volatile"     { count(); return(VOLATILE); }
173 "using"        { count(); TKEYWORD(USING); }
174 "_naked"       { count(); TKEYWORD(NAKED); }
175 "while"        { count(); return(WHILE); }
176 "xdata"        { count(); TKEYWORD(XDATA); }
177 "..."          { count(); return(VAR_ARGS);}
178 "__typeof"     { count(); return TYPEOF;}
179 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE);}
180 "_overlay"     { count(); TKEYWORD(OVERLAY);}
181 {L}({L}|{D})*  { count(); return(check_type()); }
182 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
183 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
184 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
185 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
186 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
187 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
188 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
189 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
190 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
191 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
192 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
193 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
194 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
195 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
196 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
197 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
198 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
199 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
200 ">>"           { count(); return(RIGHT_OP); }
201 "<<"           { count(); return(LEFT_OP); }
202 "++"           { count(); return(INC_OP); }
203 "--"           { count(); return(DEC_OP); }
204 "->"           { count(); return(PTR_OP); }
205 "&&"           { count(); return(AND_OP); }
206 "||"           { count(); return(OR_OP); }
207 "<="           { count(); return(LE_OP); }
208 ">="           { count(); return(GE_OP); }
209 "=="           { count(); return(EQ_OP); }
210 "!="           { count(); return(NE_OP); }
211 ";"            { count(); return(';'); }
212 "{"            { count(); NestLevel++ ;  return('{'); }
213 "}"            { count(); NestLevel--; 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 "?"            { count(); return('?'); }
235 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
236 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
237
238 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
239 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
240 "\r\n"             { count(); }
241 "\n"               { count(); }
242 [ \t\v\f]      { count(); }
243 \\ {
244   char ch=input();
245   if (ch!='\n') {
246     // that could have been removed by the preprocessor anyway
247     werror (W_STRAY_BACKSLASH, column);
248     my_unput(ch);
249   }
250 }
251 .                          { count()    ; }
252 %%
253
254 static int checkCurrFile (char *s)
255 {
256     char lineNum[10]                    ;
257     int  lNum                           ;
258     char *tptr                          ;
259        
260     /* first check if this is a #line */
261     if ( strncmp(s,"#line",5) )
262         return  0                               ;
263     
264     /* get to the line number */
265     while (!isdigit(*s))
266         s++ ;
267     tptr = lineNum ;
268     while (isdigit(*s))
269         *tptr++ = *s++ ;
270     *tptr = '\0'; 
271     sscanf(lineNum,"%d",&lNum);
272     
273     /* now see if we have a file name */
274     while (*s != '\"' && *s) 
275         s++ ;
276     
277     /* if we don't have a filename then */
278     /* set the current line number to   */
279     /* line number if printFlag is on   */
280     if (!*s) {          
281       lineno = mylineno = lNum ;
282       return 0;
283     }
284     
285     /* if we have a filename then check */
286     /* if it is "standard in" if yes then */
287     /* get the currentfile name info    */
288     s++ ;
289
290     /* in c1mode fullSrcFileName is NULL */
291     if ( fullSrcFileName &&
292          strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
293       lineno = mylineno = lNum;                                 
294       currFname = fullSrcFileName ;
295     }  else {
296         char *sb = s;
297         /* mark the end of the filename */
298         while (*s != '"') s++;
299         *s = '\0';
300         currFname = strdup (sb);
301         lineno = mylineno = lNum;
302     }
303     filename = currFname ;
304     return 0;
305 }
306     
307 int column = 0;
308 int plineIdx =0;
309
310 static void count(void)
311 {
312   int i;
313   for (i = 0; yytext[i] != '\0'; i++)   {                               
314     if (yytext[i] == '\n')      {         
315       column = 0;
316       lineno = ++mylineno ;
317     }
318     else 
319       if (yytext[i] == '\t')
320         column += 8 - (column % 8);
321       else
322         column++;
323   }
324   /* ECHO; */
325 }
326
327 static int check_type(void)
328 {
329         /* check if it is in the typedef table */
330         if (findSym(TypedefTab,NULL,yytext)) {
331                 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
332                 return (TYPE_NAME) ;
333         }
334         else   {
335                 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
336                 return(IDENTIFIER);
337         }
338 }
339
340 /*
341  * Change by JTV 2001-05-19 to not concantenate strings
342  * to support ANSI hex and octal escape sequences in string liteals 
343  */
344
345 static char *stringLiteral(void)
346 {
347 #define STR_BUF_CHUNCK_LEN  1024
348   int ch;
349   static struct dbuf_s dbuf;
350   char buf[2];
351
352   if (dbuf.alloc == 0)
353     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
354   else
355     dbuf_set_size(&dbuf, 0);
356
357
358   dbuf_append(&dbuf, "\"", 1);
359   /* put into the buffer till we hit the first \" */
360
361   while ((ch = input()) != 0) {
362     switch (ch) {
363     case '\\':
364       /* if it is a \ then escape char's are allowed */
365       ch = input();
366       if (ch == '\n') {
367         /* \<newline> is a continuator */
368         lineno = ++mylineno;
369         column = 0;
370       }
371       else {
372         buf[0] = '\\';
373         buf[1] = ch;
374         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
375       }
376       break; /* carry on */
377
378     case '\n':
379       /* if new line we have a new line break, which is illegal */
380       werror(W_NEWLINE_IN_STRING);
381       dbuf_append(&dbuf, "\n", 1);
382       lineno = ++mylineno;
383       column = 0;
384       break;
385
386     case '"':
387       /* if this is a quote then we have work to do */
388       /* find the next non whitespace character     */
389       /* if that is a double quote then carry on    */
390       dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
391       while ((ch = input()) && (isspace(ch) || ch=='\\')) {
392         switch (ch) {
393         case '\\':
394           if ((ch = input()) != '\n') {
395             werror(W_STRAY_BACKSLASH, column);
396             my_unput(ch);
397           }
398           else {
399             lineno = ++mylineno;
400             column = 0;
401           }
402           break;
403
404         case '\n':
405           mylineno++;
406           break;
407         }
408       }
409
410       if (!ch) 
411         goto out;
412
413       if (ch != '\"') {
414         my_unput(ch) ;
415         goto out;
416       }
417       break;
418
419     default:
420       buf[0] = ch;
421       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
422     }
423   }
424
425 out:
426   return (char *)dbuf_c_str(&dbuf);
427 }
428
429
430 enum pragma_id {
431      P_SAVE = 1,
432      P_RESTORE ,
433      P_NOINDUCTION,
434      P_NOINVARIANT,
435      P_INDUCTION ,
436      P_STACKAUTO ,
437      P_NOJTBOUND ,
438      P_NOOVERLAY ,
439      P_LESSPEDANTIC,
440      P_NOGCSE    ,
441      P_CALLEE_SAVES,
442      P_EXCLUDE   ,
443      P_NOIV      ,
444      P_LOOPREV   ,
445      P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
446                      /* cross-compiling for MINGW32 with gcc 3.2 */
447 };
448
449
450 /* SAVE/RESTORE stack */
451 #define SAVE_RESTORE_SIZE 128
452
453 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
454 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
455
456 /*
457  * cloneXxx functions should be updated every time a new set is
458  * added to the options or optimize structure!
459  */
460
461 static struct options *cloneOptions(struct options *opt)
462 {
463   struct options *new_opt;
464
465   new_opt = Safe_malloc(sizeof (struct options));
466
467   /* clone scalar values */
468   *new_opt = *opt;
469
470   /* clone sets */
471   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
472   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
473   /* not implemented yet: */
474   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
475
476   return new_opt;
477 }
478
479 static struct optimize *cloneOptimize(struct optimize *opt)
480 {
481   struct optimize *new_opt;
482
483   new_opt = Safe_malloc(sizeof (struct options));
484
485   /* clone scalar values */
486   *new_opt = *opt;
487
488   return new_opt;
489 }
490
491 static void copyAndFreeOptions(struct options *dest, struct options *src)
492 {
493   /* delete dest sets */
494   deleteSet(&dest->calleeSavesSet);
495   deleteSet(&dest->excludeRegsSet);
496   /* not implemented yet: */
497   /* deleteSet(&dest->olaysSet); */
498
499   /* dopy src to dest */
500   *dest = *src;
501
502   Safe_free(src);
503 }
504
505 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
506 {
507   /* dopy src to dest */
508   *dest = *src;
509
510   Safe_free(src);
511 }
512
513 static void doPragma(int op, char *cp)
514 {
515   switch (op) {
516   case P_SAVE:
517     {
518       STACK_PUSH(options_stack, cloneOptions(&options));
519       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
520     }
521     break;
522
523   case P_RESTORE:
524     {
525       struct options *optionsp;
526       struct optimize *optimizep;
527
528       optionsp = STACK_POP(options_stack);
529       copyAndFreeOptions(&options, optionsp);
530
531       optimizep = STACK_POP(optimize_stack);
532       copyAndFreeOptimize(&optimize, optimizep);
533     }
534     break;
535
536   case P_NOINDUCTION:
537     optimize.loopInduction = 0 ;
538     break;
539
540   case P_NOINVARIANT:
541     optimize.loopInvariant = 0 ;
542     break;
543
544   case P_INDUCTION:
545     optimize.loopInduction = 1 ;
546     break;
547
548   case P_STACKAUTO:
549     options.stackAuto = 1;
550     break;
551
552   case P_NOJTBOUND:
553     optimize.noJTabBoundary = 1;
554     break;
555
556   case P_NOGCSE:
557     optimize.global_cse = 0;
558     break;
559
560   case P_NOOVERLAY:
561     options.noOverlay = 1;
562     break;
563
564   case P_LESSPEDANTIC:
565     options.lessPedantic = 1;
566     break;
567
568   case P_CALLEE_SAVES:
569     /* append to the functions already listed
570        in callee-saves */
571     setParseWithComma(&options.calleeSavesSet, cp);
572     break;
573
574   case P_EXCLUDE:
575     {
576       deleteSet(&options.excludeRegsSet);
577       setParseWithComma(&options.excludeRegsSet, cp);
578     }
579     break;
580
581   case P_NOIV:
582     options.noiv = 1;
583     break;
584
585   case P_LOOPREV:
586     optimize.noLoopReverse = 1;
587     break;
588
589   case P_OVERLAY_:
590     break; /* notyet */
591   }
592 }
593
594 static int process_pragma(char *s)
595 {
596 #define NELEM(x)  (sizeof (x) / sizeof (x)[0])
597 #define PRAGMA    "#pragma"
598
599   static struct pragma_s {
600     const char *name;
601     enum pragma_id id;
602   } pragma_tbl[] = {
603     { "SAVE",           P_SAVE },
604     { "RESTORE",        P_RESTORE },
605     { "NOINDUCTION",    P_NOINDUCTION },
606     { "NOINVARIANT",    P_NOINVARIANT },
607     { "NOLOOPREVERSE",  P_LOOPREV },
608     { "INDUCTION",      P_INDUCTION },
609     { "STACKAUTO",      P_STACKAUTO },
610     { "NOJTBOUND",      P_NOJTBOUND },
611     { "NOGCSE",         P_NOGCSE },
612     { "NOOVERLAY",      P_NOOVERLAY },
613     { "CALLEE-SAVES",   P_CALLEE_SAVES },
614     { "EXCLUDE",        P_EXCLUDE },
615     { "NOIV",           P_NOIV },
616     { "OVERLAY",        P_OVERLAY_ },
617     { "LESS_PEDANTIC",  P_LESSPEDANTIC },
618   };
619   char *cp ;
620   int i;
621
622   /* find the pragma */
623   while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
624     s++;
625   s += (sizeof PRAGMA) - 1;
626     
627   /* look for the directive */
628   while(isspace(*s))
629     s++;
630
631   cp = s;
632   /* look for the end of the directive */
633   while ((!isspace(*s)) && (*s != '\n')) 
634     s++ ;    
635
636   /* First give the port a chance */
637   if (port->process_pragma && !port->process_pragma(cp))
638     return 0;
639
640   for (i = 0; i < NELEM(pragma_tbl); i++) {
641     /* now compare and do what needs to be done */
642     size_t len = strlen(pragma_tbl[i].name);
643
644     if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
645       doPragma(pragma_tbl[i].id, cp + len);
646       return 0;
647     }
648   }
649
650   werror(W_UNKNOWN_PRAGMA,cp);
651   return 0;
652 }
653
654 /* will return 1 if the string is a part
655    of a target specific keyword */
656 static int isTargetKeyword(char *s)
657 {
658     int i;
659     
660     if (port->keywords == NULL)
661         return 0;
662     for ( i = 0 ; port->keywords[i] ; i++ ) {
663         if (strcmp(port->keywords[i],s) == 0)
664             return 1;
665     }
666     
667     return 0;
668 }
669
670 int yyerror(char *s)
671 {
672    fflush(stdout);
673
674    if (mylineno && filename) {
675          if(options.vc_err_style)
676                 fprintf(stdout,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
677                         filename,mylineno,
678                         s,yytext,column);
679           else
680                 fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
681                         filename,mylineno,
682                         s,yytext,column);
683      fatalError++;
684    } else {
685      /* this comes from an empy file, no problem */
686    }
687    return 0;
688 }