* as/mcs51/lkarea.c (lnkarea, lnkarea2): improved BSEG size calculation,
[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      P_CODESEG,
474      P_CONSTSEG
475 };
476
477
478 /* SAVE/RESTORE stack */
479 #define SAVE_RESTORE_SIZE 128
480
481 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
482 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
483 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
484
485 /*
486  * cloneXxx functions should be updated every time a new set is
487  * added to the options or optimize structure!
488  */
489
490 static struct options *cloneOptions(struct options *opt)
491 {
492   struct options *new_opt;
493
494   new_opt = Safe_malloc(sizeof (struct options));
495
496   /* clone scalar values */
497   *new_opt = *opt;
498
499   /* clone sets */
500   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
501   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
502   /* not implemented yet: */
503   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
504
505   return new_opt;
506 }
507
508 static struct optimize *cloneOptimize(struct optimize *opt)
509 {
510   struct optimize *new_opt;
511
512   new_opt = Safe_malloc(sizeof (struct optimize));
513
514   /* clone scalar values */
515   *new_opt = *opt;
516
517   return new_opt;
518 }
519
520 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
521 {
522   struct SDCCERRG *new_val;
523
524   new_val = Safe_malloc(sizeof (struct SDCCERRG));
525
526   /* clone scalar values */
527   *new_val = *val;
528
529   return new_val;
530 }
531
532 static void copyAndFreeOptions(struct options *dest, struct options *src)
533 {
534   /* delete dest sets */
535   deleteSet(&dest->calleeSavesSet);
536   deleteSet(&dest->excludeRegsSet);
537   /* not implemented yet: */
538   /* deleteSet(&dest->olaysSet); */
539
540   /* copy src to dest */
541   *dest = *src;
542
543   Safe_free(src);
544 }
545
546 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
547 {
548   /* copy src to dest */
549   *dest = *src;
550
551   Safe_free(src);
552 }
553
554 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
555 {
556   /* copy src to dest */
557   *dest = *src;
558
559   Safe_free(src);
560 }
561
562 static void doPragma(int op, char *cp)
563 {
564   int i;
565
566   switch (op) {
567   case P_SAVE:
568     {
569       STACK_PUSH(options_stack, cloneOptions(&options));
570       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
571       STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
572     }
573     break;
574
575   case P_RESTORE:
576     {
577       struct options *optionsp;
578       struct optimize *optimizep;
579       struct SDCCERRG *sdccerrgp;
580
581       optionsp = STACK_POP(options_stack);
582       copyAndFreeOptions(&options, optionsp);
583
584       optimizep = STACK_POP(optimize_stack);
585       copyAndFreeOptimize(&optimize, optimizep);
586
587       sdccerrgp = STACK_POP(SDCCERRG_stack);
588       copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
589     }
590     break;
591
592   case P_NOINDUCTION:
593     optimize.loopInduction = 0;
594     break;
595
596   case P_NOINVARIANT:
597     optimize.loopInvariant = 0;
598     break;
599
600   case P_INDUCTION:
601     optimize.loopInduction = 1;
602     break;
603
604   case P_STACKAUTO:
605     options.stackAuto = 1;
606     break;
607
608   case P_NOJTBOUND:
609     optimize.noJTabBoundary = 1;
610     break;
611
612   case P_NOGCSE:
613     optimize.global_cse = 0;
614     break;
615
616   case P_NOOVERLAY:
617     options.noOverlay = 1;
618     break;
619
620   case P_LESSPEDANTIC:
621     options.lessPedantic = 1;
622     setErrorLogLevel(ERROR_LEVEL_WARNING);
623     break;
624
625   case P_CALLEE_SAVES:
626     /* append to the functions already listed
627        in callee-saves */
628     setParseWithComma(&options.calleeSavesSet, cp);
629     break;
630
631   case P_EXCLUDE:
632     {
633       deleteSet(&options.excludeRegsSet);
634       setParseWithComma(&options.excludeRegsSet, cp);
635     }
636     break;
637
638   case P_NOIV:
639     options.noiv = 1;
640     break;
641
642   case P_LOOPREV:
643     optimize.noLoopReverse = 1;
644     break;
645
646   case P_OVERLAY_:
647     break; /* notyet */
648
649   case P_DISABLEWARN:
650     if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
651       {
652         setWarningDisabled(i);
653       }
654     break;
655   
656   case P_OPTCODESPEED:
657     optimize.codeSpeed = 1;
658     optimize.codeSize = 0;
659     break;
660
661   case P_OPTCODESIZE:
662     optimize.codeSpeed = 0;
663     optimize.codeSize = 1;
664     break;
665
666   case P_OPTCODEBALANCED:
667     optimize.codeSpeed = 0;
668     optimize.codeSize = 0;
669     break;
670   
671   case P_STD_C89:
672     options.std_c99 = 0;
673     options.std_sdcc = 0;
674     break;
675   
676   case P_STD_C99:
677     options.std_c99 = 1;
678     options.std_sdcc = 0;
679     break;
680   
681   case P_STD_SDCC89:
682     options.std_c99 = 0;
683     options.std_sdcc = 1;
684     break;
685   
686   case P_STD_SDCC99:
687     options.std_c99 = 1;
688     options.std_sdcc = 1;
689     break;
690
691   case P_CODESEG:
692     {
693       char str[9];
694       char *segname = Safe_malloc(15);
695       sscanf(cp, " %8s", str);
696       str[8] = '\0';
697       sprintf(segname, "%-8.8s(CODE)", str);
698       options.code_seg = segname;
699     }
700     break;
701
702   case P_CONSTSEG:
703     {
704       char str[9];
705       char *segname = Safe_malloc(15);
706       sscanf(cp, " %8s", str);
707       str[8] = '\0';
708       sprintf(segname, "%-8.8s(CODE)", str);
709       options.const_seg = segname;
710     }
711     break;
712   }
713 }
714
715 static int process_pragma(char *s)
716 {
717 #define NELEM(x)    (sizeof (x) / sizeof (x)[0])
718 #define PRAGMA_STR  "#pragma"
719 #define PRAGMA_LEN  ((sizeof PRAGMA_STR) - 1)
720
721   static struct pragma_s
722     {
723       const char *name;
724       enum pragma_id id;
725       char deprecated;
726     } pragma_tbl[] = {
727     { "save",           P_SAVE,         0 },
728     { "restore",        P_RESTORE,      0 },
729     { "noinduction",    P_NOINDUCTION,  0 },
730     { "noinvariant",    P_NOINVARIANT,  0 },
731     { "noloopreverse",  P_LOOPREV,      0 },
732     { "induction",      P_INDUCTION,    0 },
733     { "stackauto",      P_STACKAUTO,    0 },
734     { "nojtbound",      P_NOJTBOUND,    0 },
735     { "nogcse",         P_NOGCSE,       0 },
736     { "nooverlay",      P_NOOVERLAY,    0 },
737     { "callee_saves",   P_CALLEE_SAVES, 0 },
738     { "exclude",        P_EXCLUDE,      0 },
739     { "noiv",           P_NOIV,         0 },
740     { "overlay",        P_OVERLAY_,     0 },
741     { "less_pedantic",  P_LESSPEDANTIC, 0 },
742     { "disable_warning",P_DISABLEWARN,  0 },
743     { "opt_code_speed", P_OPTCODESPEED, 0 },
744     { "opt_code_size",  P_OPTCODESIZE,  0 },
745     { "opt_code_balanced",  P_OPTCODEBALANCED,  0 },
746     { "std_c89",        P_STD_C89,      0 },
747     { "std_c99",        P_STD_C99,      0 },
748     { "std_sdcc89",     P_STD_SDCC89,   0 },
749     { "std_sdcc99",     P_STD_SDCC99,   0 },
750     { "codeseg",        P_CODESEG,      0 },
751     { "constseg",       P_CONSTSEG,     0 },
752
753     /*
754      * The following lines are deprecated pragmas,
755      * only for bacward compatibility.
756      * They should be removed in next major release after 1.4.0
757      */
758
759     { "SAVE",           P_SAVE,         1 },
760     { "RESTORE",        P_RESTORE,      1 },
761     { "NOINDUCTION",    P_NOINDUCTION,  1 },
762     { "NOINVARIANT",    P_NOINVARIANT,  1 },
763     { "NOLOOPREVERSE",  P_LOOPREV,      1 },
764     { "INDUCTION",      P_INDUCTION,    1 },
765     { "STACKAUTO",      P_STACKAUTO,    1 },
766     { "NOJTBOUND",      P_NOJTBOUND,    1 },
767     { "NOGCSE",         P_NOGCSE,       1 },
768     { "NOOVERLAY",      P_NOOVERLAY,    1 },
769     { "CALLEE-SAVES",   P_CALLEE_SAVES, 1 },
770     { "EXCLUDE",        P_EXCLUDE,      1 },
771     { "NOIV",           P_NOIV,         1 },
772     { "OVERLAY",        P_OVERLAY_,     1 },
773     { "LESS_PEDANTIC",  P_LESSPEDANTIC, 1 },
774   };
775   char *cp;
776   int i;
777
778   /* find the pragma */
779   while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
780     s++;
781   s += PRAGMA_LEN;
782
783   /* look for the directive */
784   while(isspace(*s))
785     s++;
786
787   cp = s;
788   /* look for the end of the directive */
789   while ((!isspace(*s)) && (*s != '\n'))
790     s++ ;
791
792   /* skip separating whitespace */
793   while (isspace(*s) && (*s != '\n'))
794     s++;
795
796   /* First give the port a chance */
797   if (port->process_pragma && !port->process_pragma(cp))
798     return 0;
799
800   for (i = 0; i < NELEM(pragma_tbl); i++)
801     {
802       /* now compare and do what needs to be done */
803       size_t len = strlen(pragma_tbl[i].name);
804
805       if (strncmp(cp, pragma_tbl[i].name, len) == 0)
806         {
807           if (pragma_tbl[i].deprecated != 0)
808             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
809
810           doPragma(pragma_tbl[i].id, s);
811           return 0;
812         }
813     }
814
815   werror(W_UNKNOWN_PRAGMA, cp);
816   return 0;
817 }
818
819 /* will return 1 if the string is a part
820    of a target specific keyword */
821 static int isTargetKeyword(char *s)
822 {
823   int i;
824
825   if (port->keywords == NULL)
826     return 0;
827   
828   if (s[0] == '_' && s[1] == '_')
829     {
830       /* Keywords in the port's array have either 0 or 1 underscore, */
831       /* so skip over the appropriate number of chars when comparing */
832       for (i = 0 ; port->keywords[i] ; i++ )
833         {
834           if (port->keywords[i][0] == '_' &&
835               strcmp(port->keywords[i],s+1) == 0)
836             return 1;
837           else if (strcmp(port->keywords[i],s+2) == 0)
838             return 1;
839         }
840     }
841   else
842     {
843       for (i = 0 ; port->keywords[i] ; i++ )
844         {
845           if (strcmp(port->keywords[i],s) == 0)
846             return 1;
847         }
848     }
849
850   return 0;
851 }
852
853 int yywrap(void)
854 {
855   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
856     werror(W_SAVE_RESTORE);
857
858   return 1;
859 }
860
861 int yyerror(char *s)
862 {
863   fflush(stdout);
864
865   if (mylineno && filename) {
866     if(options.vc_err_style)
867       fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
868         filename, mylineno, s, yytext, column);
869     else
870       fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
871         filename, mylineno, s ,yytext, column);
872     fatalError++;
873   } else {
874     /* this comes from an empy file, no problem */
875   }
876   return 0;
877 }