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