* src/SDCC.lex, src/SDCCmain.c: fixed bug #1631895:
[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_string.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(const char *);
62 static int check_type(void);
63 static int isTargetKeyword(const char *s);
64 static int checkCurrFile(const 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_str(&asmbuff, 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_char(&asmbuff, *yytext);
94 }
95 <asm>.         {
96   dbuf_append_char(&asmbuff, *yytext);
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 "fixed16x16"   { count(); TKEYWORDSDCC(FIXED16X16); }
126 "__fixed16x16"   { count(); TKEYWORD(FIXED16X16); }
127 "flash"        { count(); TKEYWORDSDCC(CODE); }
128 "__flash"      { count(); TKEYWORD(CODE); }
129 "for"          { count(); return(FOR); }
130 "goto"         { count(); return(GOTO); }
131 "idata"        { count(); TKEYWORDSDCC(IDATA); }
132 "__idata"      { count(); TKEYWORD(IDATA); }
133 "if"           { count(); return(IF); }
134 "int"          { count(); return(INT); }
135 "interrupt"    { count(); TKEYWORDSDCC(INTERRUPT); }
136 "__interrupt"  { count(); TKEYWORD(INTERRUPT); }
137 "nonbanked"    { count(); TKEYWORDSDCC(NONBANKED); }
138 "__nonbanked"  { count(); TKEYWORD(NONBANKED); }
139 "banked"       { count(); TKEYWORDSDCC(BANKED); }
140 "__banked"     { count(); TKEYWORD(BANKED); }
141 "long"         { count(); return(LONG); }
142 "near"         { count(); TKEYWORDSDCC(DATA); }
143 "__near"       { count(); TKEYWORD(DATA); }
144 "pdata"        { count(); TKEYWORDSDCC(PDATA); }
145 "__pdata"      { count(); TKEYWORD(PDATA); }
146 "reentrant"    { count(); TKEYWORDSDCC(REENTRANT); }
147 "__reentrant"  { count(); TKEYWORD(REENTRANT); }
148 "shadowregs"   { count(); TKEYWORDSDCC(SHADOWREGS); }
149 "__shadowregs" { count(); TKEYWORD(SHADOWREGS); }
150 "wparam"       { count(); TKEYWORDSDCC(WPARAM); }
151 "__wparam"     { count(); TKEYWORD(WPARAM); }
152 "register"     { count(); return(REGISTER); }
153 "return"       { count(); return(RETURN); }
154 "sfr"          { count(); TKEYWORDSDCC(SFR); }
155 "__sfr"        { count(); TKEYWORD(SFR); }
156 "sfr16"        { count(); TKEYWORDSDCC(SFR16); }
157 "__sfr16"      { count(); TKEYWORD(SFR16); }
158 "sfr32"        { count(); TKEYWORDSDCC(SFR32); }
159 "__sfr32"      { count(); TKEYWORD(SFR32); }
160 "sbit"         { count(); TKEYWORDSDCC(SBIT); }
161 "__sbit"       { count(); TKEYWORD(SBIT); }
162 "short"        { count(); return(SHORT); }
163 "signed"       { count(); return(SIGNED); }
164 "sizeof"       { count(); return(SIZEOF); }
165 "sram"         { count(); TKEYWORDSDCC(XDATA); }
166 "__sram"       { count(); TKEYWORD(XDATA); }
167 "static"       { count(); return(STATIC); }
168 "struct"       { count(); return(STRUCT); }
169 "switch"       { count(); return(SWITCH); }
170 "typedef"      { count(); return(TYPEDEF); }
171 "union"        { count(); return(UNION); }
172 "unsigned"     { count(); return(UNSIGNED); }
173 "void"         { count(); return(VOID); }
174 "volatile"     { count(); return(VOLATILE); }
175 "using"        { count(); TKEYWORDSDCC(USING); }
176 "__using"      { count(); TKEYWORD(USING); }
177 "_naked"       { count(); TKEYWORDSDCC(NAKED); }
178 "__naked"      { count(); TKEYWORD(NAKED); }
179 "while"        { count(); return(WHILE); }
180 "xdata"        { count(); TKEYWORDSDCC(XDATA); }
181 "__xdata"      { count(); TKEYWORD(XDATA); }
182 "..."          { count(); return(VAR_ARGS); }
183 "__typeof"     { count(); return TYPEOF; }
184 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE); }
185 "_overlay"     { count(); TKEYWORDSDCC(OVERLAY); }
186 "__overlay"    { count(); TKEYWORD(OVERLAY); }
187 "inline"       { count(); TKEYWORD99(INLINE); }
188 "restrict"     { count(); TKEYWORD99(RESTRICT); }
189 {L}({L}|{D})*  { count(); return(check_type()); }
190 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
191 0[0-7]*{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
192 [1-9]{D}*{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
193 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ }
194 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
195 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
196 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
197 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
198 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
199 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN); }
200 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN); }
201 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN); }
202 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN); }
203 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN); }
204 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN); }
205 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN); }
206 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN); }
207 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN); }
208 ">>"           { count(); return(RIGHT_OP); }
209 "<<"           { count(); return(LEFT_OP); }
210 "++"           { count(); return(INC_OP); }
211 "--"           { count(); return(DEC_OP); }
212 "->"           { count(); return(PTR_OP); }
213 "&&"           { count(); return(AND_OP); }
214 "||"           { count(); return(OR_OP); }
215 "<="           { count(); return(LE_OP); }
216 ">="           { count(); return(GE_OP); }
217 "=="           { count(); return(EQ_OP); }
218 "!="           { count(); return(NE_OP); }
219 ";"            { count(); return(';'); }
220 "{"            { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
221 "}"            { count(); NestLevel--; return('}'); }
222 ","            { count(); return(','); }
223 ":"            { count(); return(':'); }
224 "="            { count(); return('='); }
225 "("            { count(); ignoreTypedefType = 0; 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 "|"            { count(); return('|'); }
242 "?"            { count(); return('?'); }
243 ^#pragma.*$    { count(); process_pragma(yytext); }
244 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
245
246 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
247 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
248 "\r\n"         { count(); }
249 "\n"           { count(); }
250 [ \t\v\f]      { count(); }
251 \\ {
252   int ch = input();
253   if (ch != '\n') {
254     /* that could have been removed by the preprocessor anyway */
255     werror (W_STRAY_BACKSLASH, column);
256     unput(ch);
257   }
258 }
259 .              { count(); }
260 %%
261
262 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
263 #ifndef yytext_ptr
264 #define yytext_ptr yytext
265 #endif
266
267
268 static int checkCurrFile (const char *s)
269 {
270     int  lNum;
271     char *tptr;
272
273     /* skip '#' character */
274     if (*s++ != '#')
275       return 0;
276
277     /* check if this is a #line
278        this is not standard and can be removed in the future */
279 #define LINE_STR  "line"
280 #define LINE_LEN  ((sizeof LINE_STR) - 1)
281
282     if (strncmp(s, LINE_STR, LINE_LEN) == 0)
283       s += LINE_LEN;
284
285     /* get the line number */
286     lNum = strtol(s, &tptr, 10);
287     if (tptr == s || !isspace((unsigned char)*tptr))
288       return 0;
289     s = tptr;
290
291     /* now see if we have a file name */
292     while (*s != '"' && *s)
293       ++s;
294
295     /* if we don't have a filename then */
296     /* set the current line number to   */
297     /* line number if printFlag is on   */
298     if (!*s) {
299       lineno = mylineno = lNum;
300       return 0;
301     }
302
303     /* if we have a filename then check */
304     /* if it is "standard in" if yes then */
305     /* get the currentfile name info    */
306     ++s;
307
308     /* in c1mode fullSrcFileName is NULL */
309     if (fullSrcFileName &&
310          strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
311       lineno = mylineno = lNum;
312       currFname = fullSrcFileName;
313     }
314     else {
315       const char *sb = s;
316
317       /* find the end of the filename */
318       while (*s && *s != '"')
319         ++s;
320       currFname = Safe_malloc(s - sb + 1);
321       memcpy(currFname, sb, s - sb);
322       currFname[s - sb] = '\0';
323       lineno = mylineno = lNum;
324     }
325     filename = currFname ;
326     return 0;
327 }
328
329 int column = 0;
330 int plineIdx =0;
331
332 static void count(void)
333 {
334   int i;
335   for (i = 0; yytext[i] != '\0'; i++) {
336     if (yytext[i] == '\n') {
337       column = 0;
338       lineno = ++mylineno;
339     }
340     else
341       if (yytext[i] == '\t')
342         column += 8 - (column % 8);
343       else
344         column++;
345   }
346   /* ECHO; */
347 }
348
349 static int check_type(void)
350 {
351   symbol *sym = findSym(SymbolTab, NULL, yytext);
352
353   /* check if it is in the table as a typedef */
354   if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
355       && SPEC_TYPEDEF (sym->etype)) {
356     strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
357     return (TYPE_NAME);
358   }
359   else {
360     strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
361     return(IDENTIFIER);
362   }
363 }
364
365 /*
366  * Change by JTV 2001-05-19 to not concantenate strings
367  * to support ANSI hex and octal escape sequences in string literals
368  */
369
370 static char *stringLiteral(void)
371 {
372 #define STR_BUF_CHUNCK_LEN  1024
373   int ch;
374   static struct dbuf_s dbuf;
375
376   if (dbuf.alloc == 0)
377     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
378   else
379     dbuf_set_length(&dbuf, 0);
380
381   dbuf_append_char(&dbuf, '"');
382   /* put into the buffer till we hit the first \" */
383
384   while ((ch = input()) != 0) {
385     switch (ch) {
386     case '\\':
387       /* if it is a \ then escape char's are allowed */
388       ch = input();
389       if (ch == '\n') {
390         /* \<newline> is a continuator */
391         lineno = ++mylineno;
392         column = 0;
393       }
394       else {
395         char buf[2];
396
397         buf[0] = '\\';
398         buf[1] = ch;
399         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
400       }
401       break; /* carry on */
402
403     case '\n':
404       /* if new line we have a new line break, which is illegal */
405       werror(W_NEWLINE_IN_STRING);
406       dbuf_append_char(&dbuf, '\n');
407       lineno = ++mylineno;
408       column = 0;
409       break;
410
411     case '"':
412       /* if this is a quote then we have work to do */
413       /* find the next non whitespace character     */
414       /* if that is a double quote then carry on    */
415       dbuf_append_char(&dbuf, '"');  /* Pass end of this string or substring to evaluator */
416       while ((ch = input()) && (isspace(ch) || ch == '\\' || ch == '#')) {
417         switch (ch) {
418         case '\\':
419           if ((ch = input()) != '\n') {
420             werror(W_STRAY_BACKSLASH, column);
421             unput(ch);
422           }
423           else {
424             lineno = ++mylineno;
425             column = 0;
426           }
427           break;
428
429         case '\n':
430           lineno = ++mylineno;
431           column = 0;
432           break;
433
434         case '#':
435           if (0 == column) {
436             /* # at the beginning of the line: collect the entire line */
437             struct dbuf_s linebuf;
438             const char *line;
439             
440             dbuf_init(&linebuf, STR_BUF_CHUNCK_LEN);
441             dbuf_append_char(&linebuf, '#');
442
443             while ((ch = input()) && ch != '\n') {
444               dbuf_append_char(&linebuf, (char)ch);
445             }
446
447             if (ch == '\n') {
448               lineno = ++mylineno;
449               column = 0;
450             }
451
452             line = dbuf_c_str(&linebuf);
453
454             /* process the line */
455             if (startsWith(line, "#pragma"))
456               process_pragma(line);
457             else
458               checkCurrFile(line);
459
460             dbuf_destroy(&linebuf);
461           }
462         }
463       }
464
465       if (!ch)
466         goto out;
467
468       if (ch != '"') {
469         unput(ch);
470         goto out;
471       }
472       break;
473
474     default:
475       dbuf_append_char(&dbuf, (char)ch);  /* Put next substring introducer into output string */
476     }
477   }
478
479 out:
480   return (char *)dbuf_c_str(&dbuf);
481 }
482
483
484 enum {
485      P_SAVE = 1,
486      P_RESTORE,
487      P_NOINDUCTION,
488      P_NOINVARIANT,
489      P_INDUCTION,
490      P_STACKAUTO,
491      P_NOJTBOUND,
492      P_NOOVERLAY,
493      P_LESSPEDANTIC,
494      P_NOGCSE,
495      P_CALLEE_SAVES,
496      P_EXCLUDE,
497      P_NOIV,
498      P_LOOPREV,
499      P_OVERLAY_,     /* I had a strange conflict with P_OVERLAY while */
500                      /* cross-compiling for MINGW32 with gcc 3.2 */
501      P_DISABLEWARN,
502      P_OPTCODESPEED,
503      P_OPTCODESIZE,
504      P_OPTCODEBALANCED,
505      P_STD_C89,
506      P_STD_C99,
507      P_STD_SDCC89,
508      P_STD_SDCC99,
509      P_CODESEG,
510      P_CONSTSEG
511 };
512
513
514 /* SAVE/RESTORE stack */
515 #define SAVE_RESTORE_SIZE 128
516
517 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
518 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
519 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
520
521 /*
522  * cloneXxx functions should be updated every time a new set is
523  * added to the options or optimize structure!
524  */
525
526 static struct options *cloneOptions(struct options *opt)
527 {
528   struct options *new_opt;
529
530   new_opt = Safe_malloc(sizeof (struct options));
531
532   /* clone scalar values */
533   *new_opt = *opt;
534
535   /* clone sets */
536   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
537   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
538   /* not implemented yet: */
539   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
540
541   return new_opt;
542 }
543
544 static struct optimize *cloneOptimize(struct optimize *opt)
545 {
546   struct optimize *new_opt;
547
548   new_opt = Safe_malloc(sizeof (struct optimize));
549
550   /* clone scalar values */
551   *new_opt = *opt;
552
553   return new_opt;
554 }
555
556 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
557 {
558   struct SDCCERRG *new_val;
559
560   new_val = Safe_malloc(sizeof (struct SDCCERRG));
561
562   /* clone scalar values */
563   *new_val = *val;
564
565   return new_val;
566 }
567
568 static void copyAndFreeOptions(struct options *dest, struct options *src)
569 {
570   /* delete dest sets */
571   deleteSet(&dest->calleeSavesSet);
572   deleteSet(&dest->excludeRegsSet);
573   /* not implemented yet: */
574   /* deleteSet(&dest->olaysSet); */
575
576   /* copy src to dest */
577   *dest = *src;
578
579   Safe_free(src);
580 }
581
582 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
583 {
584   /* copy src to dest */
585   *dest = *src;
586
587   Safe_free(src);
588 }
589
590 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
591 {
592   /* copy src to dest */
593   *dest = *src;
594
595   Safe_free(src);
596 }
597
598 /*
599  * returns 1 if the pragma was processed, 0 if not
600  */
601 static int doPragma(int id, const char *name, const char *cp)
602 {
603   struct pragma_token_s token;
604   int err = 0;
605   int processed = 1;
606
607   init_pragma_token(&token);
608
609   switch (id) 
610     {
611     case P_SAVE:
612       {
613         cp = get_pragma_token(cp, &token);
614         if (TOKEN_EOL != token.type)
615           {
616             err = 1;
617             break;
618           }
619
620         STACK_PUSH(options_stack, cloneOptions(&options));
621         STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
622         STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
623       }
624       break;
625
626     case P_RESTORE:
627       {
628         struct options *optionsp;
629         struct optimize *optimizep;
630         struct SDCCERRG *sdccerrgp;
631
632         cp = get_pragma_token(cp, &token);
633         if (TOKEN_EOL != token.type)
634           {
635             err = 1;
636             break;
637           }
638
639         optionsp = STACK_POP(options_stack);
640         copyAndFreeOptions(&options, optionsp);
641
642         optimizep = STACK_POP(optimize_stack);
643         copyAndFreeOptimize(&optimize, optimizep);
644
645         sdccerrgp = STACK_POP(SDCCERRG_stack);
646         copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
647       }
648       break;
649
650     case P_NOINDUCTION:
651       cp = get_pragma_token(cp, &token);
652       if (TOKEN_EOL != token.type)
653         {
654           err = 1;
655           break;
656         }
657
658       optimize.loopInduction = 0;
659       break;
660
661     case P_NOINVARIANT:
662       cp = get_pragma_token(cp, &token);
663       if (TOKEN_EOL != token.type)
664         {
665           err = 1;
666           break;
667         }
668
669       optimize.loopInvariant = 0;
670       break;
671
672     case P_INDUCTION:
673       cp = get_pragma_token(cp, &token);
674       if (TOKEN_EOL != token.type)
675         {
676           err = 1;
677           break;
678         }
679
680       optimize.loopInduction = 1;
681       break;
682
683     case P_STACKAUTO:
684       cp = get_pragma_token(cp, &token);
685       if (TOKEN_EOL != token.type)
686         {
687           err = 1;
688           break;
689         }
690
691       options.stackAuto = 1;
692       break;
693
694     case P_NOJTBOUND:
695       cp = get_pragma_token(cp, &token);
696       if (TOKEN_EOL != token.type)
697         {
698           err = 1;
699           break;
700         }
701
702       optimize.noJTabBoundary = 1;
703       break;
704
705     case P_NOGCSE:
706       cp = get_pragma_token(cp, &token);
707       if (TOKEN_EOL != token.type)
708         {
709           err = 1;
710           break;
711         }
712
713       optimize.global_cse = 0;
714       break;
715
716     case P_NOOVERLAY:
717       cp = get_pragma_token(cp, &token);
718       if (TOKEN_EOL != token.type)
719         {
720           err = 1;
721           break;
722         }
723
724       options.noOverlay = 1;
725       break;
726
727     case P_LESSPEDANTIC:
728       cp = get_pragma_token(cp, &token);
729       if (TOKEN_EOL != token.type)
730         {
731           err = 1;
732           break;
733         }
734
735       options.lessPedantic = 1;
736       setErrorLogLevel(ERROR_LEVEL_WARNING);
737       break;
738
739     case P_CALLEE_SAVES:
740       /* append to the functions already listed
741          in callee-saves */
742       setParseWithComma(&options.calleeSavesSet, cp);
743       err = -1;
744       break;
745
746     case P_EXCLUDE:
747       {
748         deleteSet(&options.excludeRegsSet);
749         setParseWithComma(&options.excludeRegsSet, cp);
750         err = -1;
751       }
752       break;
753
754     case P_NOIV:
755       cp = get_pragma_token(cp, &token);
756       if (TOKEN_EOL != token.type)
757         {
758           err = 1;
759           break;
760         }
761
762       options.noiv = 1;
763       break;
764
765     case P_LOOPREV:
766       cp = get_pragma_token(cp, &token);
767       if (TOKEN_EOL != token.type)
768         {
769           err = 1;
770           break;
771         }
772
773       optimize.noLoopReverse = 1;
774       break;
775
776     case P_OVERLAY_:
777       cp = get_pragma_token(cp, &token);
778       if (TOKEN_EOL != token.type)
779         {
780           err = 1;
781           break;
782         }
783
784       break; /* notyet */
785
786     case P_DISABLEWARN:
787       {
788         int warn;
789
790         cp = get_pragma_token(cp, &token);
791         if (TOKEN_INT != token.type)
792           {
793             err = 1;
794             break;
795           }
796         warn = token.val.int_val;
797
798         cp = get_pragma_token(cp, &token);
799         if (TOKEN_EOL != token.type)
800           {
801             err = 1;
802             break;
803           }
804
805         if (warn < MAX_ERROR_WARNING)
806           setWarningDisabled(warn);
807       }
808       break;
809
810     case P_OPTCODESPEED:
811       cp = get_pragma_token(cp, &token);
812       if (TOKEN_EOL != token.type)
813         {
814           err = 1;
815           break;
816         }
817
818       optimize.codeSpeed = 1;
819       optimize.codeSize = 0;
820       break;
821
822     case P_OPTCODESIZE:
823       cp = get_pragma_token(cp, &token);
824       if (TOKEN_EOL != token.type)
825         {
826           err = 1;
827           break;
828         }
829
830       optimize.codeSpeed = 0;
831       optimize.codeSize = 1;
832       break;
833
834     case P_OPTCODEBALANCED:
835       cp = get_pragma_token(cp, &token);
836       if (TOKEN_EOL != token.type)
837         {
838           err = 1;
839           break;
840         }
841
842       optimize.codeSpeed = 0;
843       optimize.codeSize = 0;
844       break;
845
846     case P_STD_C89:
847       cp = get_pragma_token(cp, &token);
848       if (TOKEN_EOL != token.type)
849         {
850           err = 1;
851           break;
852         }
853
854       options.std_c99 = 0;
855       options.std_sdcc = 0;
856       break;
857
858     case P_STD_C99:
859       cp = get_pragma_token(cp, &token);
860       if (TOKEN_EOL != token.type)
861         {
862           err = 1;
863           break;
864         }
865
866       options.std_c99 = 1;
867       options.std_sdcc = 0;
868       break;
869
870     case P_STD_SDCC89:
871       cp = get_pragma_token(cp, &token);
872       if (TOKEN_EOL != token.type)
873         {
874           err = 1;
875           break;
876         }
877
878       options.std_c99 = 0;
879       options.std_sdcc = 1;
880       break;
881
882     case P_STD_SDCC99:
883       cp = get_pragma_token(cp, &token);
884       if (TOKEN_EOL != token.type)
885         {
886           err = 1;
887           break;
888         }
889
890       options.std_c99 = 1;
891       options.std_sdcc = 1;
892       break;
893
894     case P_CODESEG:
895     case P_CONSTSEG:
896       {
897         struct dbuf_s segname;
898
899         cp = get_pragma_token(cp, &token);
900         if (token.type == TOKEN_EOL)
901           {
902             err = 1;
903             break;
904           }
905
906         dbuf_init(&segname, 16);
907         dbuf_printf(&segname, "%-8s(CODE)", get_pragma_string(&token));
908
909         cp = get_pragma_token(cp, &token);
910         if (token.type != TOKEN_EOL)
911           {
912             dbuf_destroy(&segname);
913             err = 1;
914             break;
915           }
916
917         if (id == P_CODESEG)
918           options.code_seg = dbuf_detach(&segname);
919         else
920           options.const_seg = dbuf_detach(&segname);
921       }
922       break;
923
924     default:
925       processed = 0;
926       break;
927     }
928
929   get_pragma_token(cp, &token);
930
931   if (1 == err || (0 == err && token.type != TOKEN_EOL))
932     werror(W_BAD_PRAGMA_ARGUMENTS, name);
933
934   free_pragma_token(&token);
935   return processed;
936 }
937
938 static struct pragma_s pragma_tbl[] = {
939   { "save",           P_SAVE,         0, doPragma },
940   { "restore",        P_RESTORE,      0, doPragma },
941   { "noinduction",    P_NOINDUCTION,  0, doPragma },
942   { "noinvariant",    P_NOINVARIANT,  0, doPragma },
943   { "noloopreverse",  P_LOOPREV,      0, doPragma },
944   { "induction",      P_INDUCTION,    0, doPragma },
945   { "stackauto",      P_STACKAUTO,    0, doPragma },
946   { "nojtbound",      P_NOJTBOUND,    0, doPragma },
947   { "nogcse",         P_NOGCSE,       0, doPragma },
948   { "nooverlay",      P_NOOVERLAY,    0, doPragma },
949   { "callee_saves",   P_CALLEE_SAVES, 0, doPragma },
950   { "exclude",        P_EXCLUDE,      0, doPragma },
951   { "noiv",           P_NOIV,         0, doPragma },
952   { "overlay",        P_OVERLAY_,     0, doPragma },
953   { "less_pedantic",  P_LESSPEDANTIC, 0, doPragma },
954   { "disable_warning",P_DISABLEWARN,  0, doPragma },
955   { "opt_code_speed", P_OPTCODESPEED, 0, doPragma },
956   { "opt_code_size",  P_OPTCODESIZE,  0, doPragma },
957   { "opt_code_balanced", P_OPTCODEBALANCED, 0, doPragma },
958   { "std_c89",        P_STD_C89,      0, doPragma },
959   { "std_c99",        P_STD_C99,      0, doPragma },
960   { "std_sdcc89",     P_STD_SDCC89,   0, doPragma },
961   { "std_sdcc99",     P_STD_SDCC99,   0, doPragma },
962   { "codeseg",        P_CODESEG,      0, doPragma },
963   { "constseg",       P_CONSTSEG,     0, doPragma },
964   { NULL,             0,              0, NULL },
965 };
966
967 /*
968  * returns 1 if the pragma was processed, 0 if not
969  */
970 int
971 process_pragma_tbl(const struct pragma_s *pragma_tbl, const char *s)
972 {
973   struct pragma_token_s token;
974   int i;
975   int ret = 0;
976
977   init_pragma_token(&token);
978
979   s = get_pragma_token(s, &token);
980
981   /* skip separating whitespace */
982   while ('\n' != *s && isspace((unsigned char)*s))
983     s++;
984
985   for (i = 0; NULL != pragma_tbl[i].name; ++i)
986     {
987       /* now compare and do what needs to be done */
988       if (strcmp(get_pragma_string(&token), pragma_tbl[i].name) == 0)
989         {
990           if (pragma_tbl[i].deprecated != 0)
991             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
992
993           ret = (*pragma_tbl[i].func)(pragma_tbl[i].id, pragma_tbl[i].name, s);
994           break;
995         }
996     }
997
998   free_pragma_token(&token);
999   return ret;
1000 }
1001
1002 static int process_pragma(const char *s)
1003 {
1004   struct pragma_token_s token;
1005
1006   init_pragma_token(&token);
1007
1008   s = get_pragma_token(s, &token);
1009   if (0 != strcmp("#pragma", get_pragma_string(&token)))
1010     {
1011       /* Oops, womething went totally wrong - internal error */
1012       wassertl(0, "pragma parser internal error");
1013     }
1014
1015   /* skip spaces */
1016   while ('\n' != *s && isspace((unsigned char)*s))
1017     ++s;
1018
1019   /* First give the port a chance */
1020   if (port->process_pragma && port->process_pragma(s))
1021     return 1;
1022
1023   if (process_pragma_tbl(pragma_tbl, s))
1024     {
1025       return 1;
1026     }
1027   else
1028     {
1029       werror(W_UNKNOWN_PRAGMA, s);
1030       return 0;
1031     }
1032 }
1033
1034 /* will return 1 if the string is a part
1035    of a target specific keyword */
1036 static int isTargetKeyword(const char *s)
1037 {
1038   int i;
1039
1040   if (port->keywords == NULL)
1041     return 0;
1042
1043   if (s[0] == '_' && s[1] == '_')
1044     {
1045       /* Keywords in the port's array have either 0 or 1 underscore, */
1046       /* so skip over the appropriate number of chars when comparing */
1047       for (i = 0 ; port->keywords[i] ; i++ )
1048         {
1049           if (port->keywords[i][0] == '_' &&
1050               strcmp(port->keywords[i],s+1) == 0)
1051             return 1;
1052           else if (strcmp(port->keywords[i],s+2) == 0)
1053             return 1;
1054         }
1055     }
1056   else
1057     {
1058       for (i = 0 ; port->keywords[i] ; i++ )
1059         {
1060           if (strcmp(port->keywords[i],s) == 0)
1061             return 1;
1062         }
1063     }
1064
1065   return 0;
1066 }
1067
1068 int yywrap(void)
1069 {
1070   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
1071     werror(W_SAVE_RESTORE);
1072
1073   return 1;
1074 }
1075
1076 int yyerror(char *s)
1077 {
1078   fflush(stdout);
1079
1080   if(options.vc_err_style)
1081     fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
1082       filename, mylineno, s, yytext, column);
1083   else
1084     fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
1085       filename, mylineno, s ,yytext, column);
1086   fatalError++;
1087
1088   return 0;
1089 }