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