c7bb9181c0d6ff9a0a45fe88a0dd6ff30d4c013f
[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 #define TKEYWORDSDCC(token) return (options.std_sdcc && isTargetKeyword(yytext)\
44                                     ? token : check_type())
45
46 #define TKEYWORD99(token) return (options.std_c99 ? token : check_type())
47
48 extern int lineno, column;
49 extern char *filename;
50
51 /* global definitions */
52 char *currFname;
53 int mylineno = 1;
54
55 /* local definitions */
56 static struct dbuf_s asmbuff;
57
58 /* forward declarations */
59 static char *stringLiteral(void);
60 static void count(void);
61 static int process_pragma(char *);
62 static int check_type(void);
63 static int isTargetKeyword(char *s);
64 static int checkCurrFile(char *s);
65 %}
66
67 %x asm
68 %%
69 _?"_asm"         {
70   count();
71   if (!options.std_sdcc && yytext[1] != '_')
72     return check_type();
73   assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
74   dbuf_init(&asmbuff, INITIAL_INLINEASM);
75   BEGIN(asm);
76 }
77 <asm>_?"_endasm" {
78   count();
79   if (!options.std_sdcc && yytext[1] != '_')
80     {
81       dbuf_append(&asmbuff, yytext, strlen(yytext));
82     }
83   else
84     {
85       yylval.yyinline = dbuf_c_str(&asmbuff);
86       dbuf_detach(&asmbuff);
87       BEGIN(INITIAL);
88       return (INLINEASM);
89     }
90 }
91 <asm>\n        {
92   count();
93   dbuf_append(&asmbuff, yytext, 1);
94 }
95 <asm>.         {
96   dbuf_append(&asmbuff, yytext, 1);
97 }
98 "at"           { count(); TKEYWORDSDCC(AT); }
99 "__at"         { count(); TKEYWORD(AT); }
100 "auto"         { count(); return(AUTO); }
101 "bit"          { count(); TKEYWORDSDCC(BIT); }
102 "__bit"        { count(); TKEYWORD(BIT); }
103 "break"        { count(); return(BREAK); }
104 "case"         { count(); return(CASE); }
105 "char"         { count(); return(CHAR); }
106 "code"         { count(); TKEYWORDSDCC(CODE); }
107 "__code"       { count(); TKEYWORD(CODE); }
108 "const"        { count(); return(CONST); }
109 "continue"     { count(); return(CONTINUE); }
110 "critical"     { count(); TKEYWORDSDCC(CRITICAL); }
111 "__critical"   { count(); TKEYWORD(CRITICAL); }
112 "data"         { count(); TKEYWORDSDCC(DATA); }
113 "__data"       { count(); TKEYWORD(DATA); }
114 "default"      { count(); return(DEFAULT); }
115 "do"           { count(); return(DO); }
116 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
117 "else"         { count(); return(ELSE); }
118 "enum"         { count(); return(ENUM); }
119 "extern"       { count(); return(EXTERN); }
120 "far"          { count(); TKEYWORDSDCC(XDATA); }
121 "__far"        { count(); TKEYWORD(XDATA); }
122 "eeprom"       { count(); TKEYWORDSDCC(EEPROM); }
123 "__eeprom"     { count(); TKEYWORD(EEPROM); }
124 "float"        { count(); return(FLOAT); }
125 "flash"        { count(); TKEYWORDSDCC(CODE); }
126 "__flash"      { count(); TKEYWORD(CODE); }
127 "for"          { count(); return(FOR); }
128 "goto"         { count(); return(GOTO); }
129 "idata"        { count(); TKEYWORDSDCC(IDATA); }
130 "__idata"      { count(); TKEYWORD(IDATA); }
131 "if"           { count(); return(IF); }
132 "int"          { count(); return(INT); }
133 "interrupt"    { count(); TKEYWORDSDCC(INTERRUPT); }
134 "__interrupt"  { count(); TKEYWORD(INTERRUPT); }
135 "nonbanked"    { count(); TKEYWORDSDCC(NONBANKED); }
136 "__nonbanked"  { count(); TKEYWORD(NONBANKED); }
137 "banked"       { count(); TKEYWORDSDCC(BANKED); }
138 "__banked"     { count(); TKEYWORD(BANKED); }
139 "long"         { count(); return(LONG); }
140 "near"         { count(); TKEYWORDSDCC(DATA); }
141 "__near"       { count(); TKEYWORD(DATA); }
142 "pdata"        { count(); TKEYWORDSDCC(PDATA); }
143 "__pdata"      { count(); TKEYWORD(PDATA); }
144 "reentrant"    { count(); TKEYWORDSDCC(REENTRANT); }
145 "__reentrant"  { count(); TKEYWORD(REENTRANT); }
146 "shadowregs"   { count(); TKEYWORDSDCC(SHADOWREGS); }
147 "__shadowregs" { count(); TKEYWORD(SHADOWREGS); }
148 "wparam"       { count(); TKEYWORDSDCC(WPARAM); }
149 "__wparam"     { count(); TKEYWORD(WPARAM); }
150 "register"     { count(); return(REGISTER); }
151 "return"       { count(); return(RETURN); }
152 "sfr"          { count(); TKEYWORDSDCC(SFR); }
153 "__sfr"        { count(); TKEYWORD(SFR); }
154 "sfr16"        { count(); TKEYWORDSDCC(SFR16); }
155 "__sfr16"      { count(); TKEYWORD(SFR16); }
156 "sfr32"        { count(); TKEYWORDSDCC(SFR32); }
157 "__sfr32"      { count(); TKEYWORD(SFR32); }
158 "sbit"         { count(); TKEYWORDSDCC(SBIT); }
159 "__sbit"       { count(); TKEYWORD(SBIT); }
160 "short"        { count(); return(SHORT); }
161 "signed"       { count(); return(SIGNED); }
162 "sizeof"       { count(); return(SIZEOF); }
163 "sram"         { count(); TKEYWORDSDCC(XDATA); }
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(); TKEYWORDSDCC(USING); }
174 "__using"      { count(); TKEYWORD(USING); }
175 "_naked"       { count(); TKEYWORDSDCC(NAKED); }
176 "__naked"      { count(); TKEYWORD(NAKED); }
177 "while"        { count(); return(WHILE); }
178 "xdata"        { count(); TKEYWORDSDCC(XDATA); }
179 "__xdata"      { count(); TKEYWORD(XDATA); }
180 "..."          { count(); return(VAR_ARGS); }
181 "__typeof"     { count(); return TYPEOF; }
182 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE); }
183 "_overlay"     { count(); TKEYWORDSDCC(OVERLAY); }
184 "__overlay"    { count(); TKEYWORD(OVERLAY); }
185 "inline"       { count(); TKEYWORD99(INLINE); }
186 "restrict"     { count(); TKEYWORD99(RESTRICT); }
187 {L}({L}|{D})*  { count(); return(check_type()); }
188 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
189 0[0-7]*{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
190 [1-9]{D}*{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
191 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ }
192 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
193 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
194 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
195 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
196 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
197 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN); }
198 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN); }
199 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN); }
200 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN); }
201 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN); }
202 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN); }
203 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN); }
204 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN); }
205 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN); }
206 ">>"           { count(); return(RIGHT_OP); }
207 "<<"           { count(); return(LEFT_OP); }
208 "++"           { count(); return(INC_OP); }
209 "--"           { count(); return(DEC_OP); }
210 "->"           { count(); return(PTR_OP); }
211 "&&"           { count(); return(AND_OP); }
212 "||"           { count(); return(OR_OP); }
213 "<="           { count(); return(LE_OP); }
214 ">="           { count(); return(GE_OP); }
215 "=="           { count(); return(EQ_OP); }
216 "!="           { count(); return(NE_OP); }
217 ";"            { count(); return(';'); }
218 "{"            { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
219 "}"            { count(); NestLevel--; return('}'); }
220 ","            { count(); return(','); }
221 ":"            { count(); return(':'); }
222 "="            { count(); return('='); }
223 "("            { count(); ignoreTypedefType = 0; 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 "%"            { count(); return('%'); }
236 "<"            { count(); return('<'); }
237 ">"            { count(); return('>'); }
238 "^"            { count(); return('^'); }
239 "|"            { count(); return('|'); }
240 "?"            { count(); return('?'); }
241 ^#pragma.*"\n" { count(); process_pragma(yytext); }
242 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
243
244 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
245 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
246 "\r\n"         { count(); }
247 "\n"           { count(); }
248 [ \t\v\f]      { count(); }
249 \\ {
250   int ch = input();
251   if (ch != '\n') {
252     /* that could have been removed by the preprocessor anyway */
253     werror (W_STRAY_BACKSLASH, column);
254     unput(ch);
255   }
256 }
257 .              { count(); }
258 %%
259
260 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
261 #ifndef yytext_ptr
262 #define yytext_ptr yytext
263 #endif
264
265
266 static int checkCurrFile (char *s)
267 {
268     int  lNum;
269     char *tptr;
270
271     /* skip '#' character */
272     if (*s++ != '#')
273       return 0;
274
275     /* check if this is a #line
276        this is not standard and can be removed in the future */
277 #define LINE_STR  "line"
278 #define LINE_LEN  ((sizeof LINE_STR) - 1)
279
280     if (strncmp(s, LINE_STR, LINE_LEN) == 0)
281       s += LINE_LEN;
282
283     /* get the line number */
284     lNum = strtol(s, &tptr, 10);
285     if (tptr == s || !isspace(*tptr))
286       return 0;
287     s = tptr;
288
289     /* now see if we have a file name */
290     while (*s != '\"' && *s)
291       s++;
292
293     /* if we don't have a filename then */
294     /* set the current line number to   */
295     /* line number if printFlag is on   */
296     if (!*s) {
297       lineno = mylineno = lNum;
298       return 0;
299     }
300
301     /* if we have a filename then check */
302     /* if it is "standard in" if yes then */
303     /* get the currentfile name info    */
304     s++ ;
305
306     /* in c1mode fullSrcFileName is NULL */
307     if (fullSrcFileName &&
308          strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
309       lineno = mylineno = lNum;
310       currFname = fullSrcFileName;
311     } else {
312         char *sb = s;
313         /* mark the end of the filename */
314         while (*s != '"') s++;
315         *s = '\0';
316         currFname = strdup (sb);
317         lineno = mylineno = lNum;
318     }
319     filename = currFname ;
320     return 0;
321 }
322
323 int column = 0;
324 int plineIdx =0;
325
326 static void count(void)
327 {
328   int i;
329   for (i = 0; yytext[i] != '\0'; i++) {
330     if (yytext[i] == '\n') {
331       column = 0;
332       lineno = ++mylineno;
333     }
334     else
335       if (yytext[i] == '\t')
336         column += 8 - (column % 8);
337       else
338         column++;
339   }
340   /* ECHO; */
341 }
342
343 static int check_type(void)
344 {
345   symbol *sym = findSym(SymbolTab, NULL, yytext);
346
347   /* check if it is in the table as a typedef */
348   if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
349       && SPEC_TYPEDEF (sym->etype)) {
350     strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
351     return (TYPE_NAME);
352   }
353   else {
354     strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
355     return(IDENTIFIER);
356   }
357 }
358
359 /*
360  * Change by JTV 2001-05-19 to not concantenate strings
361  * to support ANSI hex and octal escape sequences in string literals
362  */
363
364 static char *stringLiteral(void)
365 {
366 #define STR_BUF_CHUNCK_LEN  1024
367   int ch;
368   static struct dbuf_s dbuf;
369   char buf[2];
370
371   if (dbuf.alloc == 0)
372     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
373   else
374     dbuf_set_size(&dbuf, 0);
375
376   dbuf_append(&dbuf, "\"", 1);
377   /* put into the buffer till we hit the first \" */
378
379   while ((ch = input()) != 0) {
380     switch (ch) {
381     case '\\':
382       /* if it is a \ then escape char's are allowed */
383       ch = input();
384       if (ch == '\n') {
385         /* \<newline> is a continuator */
386         lineno = ++mylineno;
387         column = 0;
388       }
389       else {
390         buf[0] = '\\';
391         buf[1] = ch;
392         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
393       }
394       break; /* carry on */
395
396     case '\n':
397       /* if new line we have a new line break, which is illegal */
398       werror(W_NEWLINE_IN_STRING);
399       dbuf_append(&dbuf, "\n", 1);
400       lineno = ++mylineno;
401       column = 0;
402       break;
403
404     case '"':
405       /* if this is a quote then we have work to do */
406       /* find the next non whitespace character     */
407       /* if that is a double quote then carry on    */
408       dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
409       while ((ch = input()) && (isspace(ch) || ch == '\\')) {
410         switch (ch) {
411         case '\\':
412           if ((ch = input()) != '\n') {
413             werror(W_STRAY_BACKSLASH, column);
414             unput(ch);
415           }
416           else {
417             lineno = ++mylineno;
418             column = 0;
419           }
420           break;
421
422         case '\n':
423           mylineno++;
424           break;
425         }
426       }
427
428       if (!ch)
429         goto out;
430
431       if (ch != '\"') {
432         unput(ch);
433         goto out;
434       }
435       break;
436
437     default:
438       buf[0] = ch;
439       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
440     }
441   }
442
443 out:
444   return (char *)dbuf_c_str(&dbuf);
445 }
446
447
448 enum pragma_id {
449      P_SAVE = 1,
450      P_RESTORE,
451      P_NOINDUCTION,
452      P_NOINVARIANT,
453      P_INDUCTION,
454      P_STACKAUTO,
455      P_NOJTBOUND,
456      P_NOOVERLAY,
457      P_LESSPEDANTIC,
458      P_NOGCSE,
459      P_CALLEE_SAVES,
460      P_EXCLUDE,
461      P_NOIV,
462      P_LOOPREV,
463      P_OVERLAY_,     /* I had a strange conflict with P_OVERLAY while */
464                      /* cross-compiling for MINGW32 with gcc 3.2 */
465      P_DISABLEWARN,
466      P_OPTCODESPEED,
467      P_OPTCODESIZE,
468      P_OPTCODEBALANCED,
469      P_STD_C89,
470      P_STD_C99,
471      P_STD_SDCC89,
472      P_STD_SDCC99
473 };
474
475
476 /* SAVE/RESTORE stack */
477 #define SAVE_RESTORE_SIZE 128
478
479 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
480 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
481 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
482
483 /*
484  * cloneXxx functions should be updated every time a new set is
485  * added to the options or optimize structure!
486  */
487
488 static struct options *cloneOptions(struct options *opt)
489 {
490   struct options *new_opt;
491
492   new_opt = Safe_malloc(sizeof (struct options));
493
494   /* clone scalar values */
495   *new_opt = *opt;
496
497   /* clone sets */
498   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
499   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
500   /* not implemented yet: */
501   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
502
503   return new_opt;
504 }
505
506 static struct optimize *cloneOptimize(struct optimize *opt)
507 {
508   struct optimize *new_opt;
509
510   new_opt = Safe_malloc(sizeof (struct optimize));
511
512   /* clone scalar values */
513   *new_opt = *opt;
514
515   return new_opt;
516 }
517
518 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
519 {
520   struct SDCCERRG *new_val;
521
522   new_val = Safe_malloc(sizeof (struct SDCCERRG));
523
524   /* clone scalar values */
525   *new_val = *val;
526
527   return new_val;
528 }
529
530 static void copyAndFreeOptions(struct options *dest, struct options *src)
531 {
532   /* delete dest sets */
533   deleteSet(&dest->calleeSavesSet);
534   deleteSet(&dest->excludeRegsSet);
535   /* not implemented yet: */
536   /* deleteSet(&dest->olaysSet); */
537
538   /* copy src to dest */
539   *dest = *src;
540
541   Safe_free(src);
542 }
543
544 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
545 {
546   /* copy src to dest */
547   *dest = *src;
548
549   Safe_free(src);
550 }
551
552 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
553 {
554   /* copy src to dest */
555   *dest = *src;
556
557   Safe_free(src);
558 }
559
560 static void doPragma(int op, char *cp)
561 {
562   int i;
563
564   switch (op) {
565   case P_SAVE:
566     {
567       STACK_PUSH(options_stack, cloneOptions(&options));
568       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
569       STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
570     }
571     break;
572
573   case P_RESTORE:
574     {
575       struct options *optionsp;
576       struct optimize *optimizep;
577       struct SDCCERRG *sdccerrgp;
578
579       optionsp = STACK_POP(options_stack);
580       copyAndFreeOptions(&options, optionsp);
581
582       optimizep = STACK_POP(optimize_stack);
583       copyAndFreeOptimize(&optimize, optimizep);
584
585       sdccerrgp = STACK_POP(SDCCERRG_stack);
586       copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
587     }
588     break;
589
590   case P_NOINDUCTION:
591     optimize.loopInduction = 0;
592     break;
593
594   case P_NOINVARIANT:
595     optimize.loopInvariant = 0;
596     break;
597
598   case P_INDUCTION:
599     optimize.loopInduction = 1;
600     break;
601
602   case P_STACKAUTO:
603     options.stackAuto = 1;
604     break;
605
606   case P_NOJTBOUND:
607     optimize.noJTabBoundary = 1;
608     break;
609
610   case P_NOGCSE:
611     optimize.global_cse = 0;
612     break;
613
614   case P_NOOVERLAY:
615     options.noOverlay = 1;
616     break;
617
618   case P_LESSPEDANTIC:
619     options.lessPedantic = 1;
620     setErrorLogLevel(ERROR_LEVEL_WARNING);
621     break;
622
623   case P_CALLEE_SAVES:
624     /* append to the functions already listed
625        in callee-saves */
626     setParseWithComma(&options.calleeSavesSet, cp);
627     break;
628
629   case P_EXCLUDE:
630     {
631       deleteSet(&options.excludeRegsSet);
632       setParseWithComma(&options.excludeRegsSet, cp);
633     }
634     break;
635
636   case P_NOIV:
637     options.noiv = 1;
638     break;
639
640   case P_LOOPREV:
641     optimize.noLoopReverse = 1;
642     break;
643
644   case P_OVERLAY_:
645     break; /* notyet */
646
647   case P_DISABLEWARN:
648     if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
649       {
650         setWarningDisabled(i);
651       }
652     break;
653   
654   case P_OPTCODESPEED:
655     optimize.codeSpeed = 1;
656     optimize.codeSize = 0;
657     break;
658
659   case P_OPTCODESIZE:
660     optimize.codeSpeed = 0;
661     optimize.codeSize = 1;
662     break;
663
664   case P_OPTCODEBALANCED:
665     optimize.codeSpeed = 0;
666     optimize.codeSize = 0;
667     break;
668   
669   case P_STD_C89:
670     options.std_c99 = 0;
671     options.std_sdcc = 0;
672     break;
673   
674   case P_STD_C99:
675     options.std_c99 = 1;
676     options.std_sdcc = 0;
677     break;
678   
679   case P_STD_SDCC89:
680     options.std_c99 = 0;
681     options.std_sdcc = 1;
682     break;
683   
684   case P_STD_SDCC99:
685     options.std_c99 = 1;
686     options.std_sdcc = 1;
687     break;
688   }
689 }
690
691 static int process_pragma(char *s)
692 {
693 #define NELEM(x)    (sizeof (x) / sizeof (x)[0])
694 #define PRAGMA_STR  "#pragma"
695 #define PRAGMA_LEN  ((sizeof PRAGMA_STR) - 1)
696
697   static struct pragma_s
698     {
699       const char *name;
700       enum pragma_id id;
701       char deprecated;
702     } pragma_tbl[] = {
703     { "save",           P_SAVE,         0 },
704     { "restore",        P_RESTORE,      0 },
705     { "noinduction",    P_NOINDUCTION,  0 },
706     { "noinvariant",    P_NOINVARIANT,  0 },
707     { "noloopreverse",  P_LOOPREV,      0 },
708     { "induction",      P_INDUCTION,    0 },
709     { "stackauto",      P_STACKAUTO,    0 },
710     { "nojtbound",      P_NOJTBOUND,    0 },
711     { "nogcse",         P_NOGCSE,       0 },
712     { "nooverlay",      P_NOOVERLAY,    0 },
713     { "callee_saves",   P_CALLEE_SAVES, 0 },
714     { "exclude",        P_EXCLUDE,      0 },
715     { "noiv",           P_NOIV,         0 },
716     { "overlay",        P_OVERLAY_,     0 },
717     { "less_pedantic",  P_LESSPEDANTIC, 0 },
718     { "disable_warning",P_DISABLEWARN,  0 },
719     { "opt_code_speed", P_OPTCODESPEED, 0 },
720     { "opt_code_size",  P_OPTCODESIZE,  0 },
721     { "opt_code_balanced",  P_OPTCODEBALANCED,  0 },
722     { "std_c89",        P_STD_C89, 0 },
723     { "std_c99",        P_STD_C99, 0 },
724     { "std_sdcc89",     P_STD_SDCC89, 0 },
725     { "std_sdcc99",     P_STD_SDCC99, 0 },
726
727     /*
728      * The following lines are deprecated pragmas,
729      * only for bacward compatibility.
730      * They should be removed in next major release after 1.4.0
731      */
732
733     { "SAVE",           P_SAVE,         1 },
734     { "RESTORE",        P_RESTORE,      1 },
735     { "NOINDUCTION",    P_NOINDUCTION,  1 },
736     { "NOINVARIANT",    P_NOINVARIANT,  1 },
737     { "NOLOOPREVERSE",  P_LOOPREV,      1 },
738     { "INDUCTION",      P_INDUCTION,    1 },
739     { "STACKAUTO",      P_STACKAUTO,    1 },
740     { "NOJTBOUND",      P_NOJTBOUND,    1 },
741     { "NOGCSE",         P_NOGCSE,       1 },
742     { "NOOVERLAY",      P_NOOVERLAY,    1 },
743     { "CALLEE-SAVES",   P_CALLEE_SAVES, 1 },
744     { "EXCLUDE",        P_EXCLUDE,      1 },
745     { "NOIV",           P_NOIV,         1 },
746     { "OVERLAY",        P_OVERLAY_,     1 },
747     { "LESS_PEDANTIC",  P_LESSPEDANTIC, 1 },
748   };
749   char *cp;
750   int i;
751
752   /* find the pragma */
753   while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
754     s++;
755   s += PRAGMA_LEN;
756
757   /* look for the directive */
758   while(isspace(*s))
759     s++;
760
761   cp = s;
762   /* look for the end of the directive */
763   while ((!isspace(*s)) && (*s != '\n'))
764     s++ ;
765
766   /* skip separating whitespace */
767   while (isspace(*s) && (*s != '\n'))
768     s++;
769
770   /* First give the port a chance */
771   if (port->process_pragma && !port->process_pragma(cp))
772     return 0;
773
774   for (i = 0; i < NELEM(pragma_tbl); i++)
775     {
776       /* now compare and do what needs to be done */
777       size_t len = strlen(pragma_tbl[i].name);
778
779       if (strncmp(cp, pragma_tbl[i].name, len) == 0)
780         {
781           if (pragma_tbl[i].deprecated != 0)
782             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
783
784           doPragma(pragma_tbl[i].id, s);
785           return 0;
786         }
787     }
788
789   werror(W_UNKNOWN_PRAGMA, cp);
790   return 0;
791 }
792
793 /* will return 1 if the string is a part
794    of a target specific keyword */
795 static int isTargetKeyword(char *s)
796 {
797   int i;
798
799   if (port->keywords == NULL)
800     return 0;
801   
802   if (s[0] == '_' && s[1] == '_')
803     {
804       /* Keywords in the port's array have either 0 or 1 underscore, */
805       /* so skip over the appropriate number of chars when comparing */
806       for (i = 0 ; port->keywords[i] ; i++ )
807         {
808           if (port->keywords[i][0] == '_' &&
809               strcmp(port->keywords[i],s+1) == 0)
810             return 1;
811           else if (strcmp(port->keywords[i],s+2) == 0)
812             return 1;
813         }
814     }
815   else
816     {
817       for (i = 0 ; port->keywords[i] ; i++ )
818         {
819           if (strcmp(port->keywords[i],s) == 0)
820             return 1;
821         }
822     }
823
824   return 0;
825 }
826
827 int yywrap(void)
828 {
829   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
830     werror(W_SAVE_RESTORE);
831
832   return 1;
833 }
834
835 int yyerror(char *s)
836 {
837   fflush(stdout);
838
839   if (mylineno && filename) {
840     if(options.vc_err_style)
841       fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
842         filename, mylineno, s, yytext, column);
843     else
844       fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
845         filename, mylineno, s ,yytext, column);
846     fatalError++;
847   } else {
848     /* this comes from an empy file, no problem */
849   }
850   return 0;
851 }