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