* src/SDCC.lex: (stringLiteral) fixed bug #1351710
[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(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(&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 "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   char buf[2];
376
377   if (dbuf.alloc == 0)
378     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
379   else
380     dbuf_set_size(&dbuf, 0);
381
382   dbuf_append(&dbuf, "\"", 1);
383   /* put into the buffer till we hit the first \" */
384
385   while ((ch = input()) != 0) {
386     switch (ch) {
387     case '\\':
388       /* if it is a \ then escape char's are allowed */
389       ch = input();
390       if (ch == '\n') {
391         /* \<newline> is a continuator */
392         lineno = ++mylineno;
393         column = 0;
394       }
395       else {
396         buf[0] = '\\';
397         buf[1] = ch;
398         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
399       }
400       break; /* carry on */
401
402     case '\n':
403       /* if new line we have a new line break, which is illegal */
404       werror(W_NEWLINE_IN_STRING);
405       dbuf_append(&dbuf, "\n", 1);
406       lineno = ++mylineno;
407       column = 0;
408       break;
409
410     case '"':
411       /* if this is a quote then we have work to do */
412       /* find the next non whitespace character     */
413       /* if that is a double quote then carry on    */
414       dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
415       while ((ch = input()) && (isspace(ch) || ch == '\\' || ch == '#')) {
416         switch (ch) {
417         case '\\':
418           if ((ch = input()) != '\n') {
419             werror(W_STRAY_BACKSLASH, column);
420             unput(ch);
421           }
422           else {
423             lineno = ++mylineno;
424             column = 0;
425           }
426           break;
427
428         case '\n':
429           lineno = ++mylineno;
430           column = 0;
431           break;
432
433         case '#':
434           if (0 == column) {
435             /* # at the beginning of the line: collect the entire line */
436             struct dbuf_s linebuf;
437             const char *line;
438             
439             dbuf_init(&linebuf, STR_BUF_CHUNCK_LEN);
440             dbuf_append(&linebuf, "#", 1);
441
442             while ((ch = input()) && ch != '\n') {
443               buf[0] = ch;
444               dbuf_append(&linebuf, buf, 1);
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       buf[0] = ch;
476       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
477     }
478   }
479
480 out:
481   return (char *)dbuf_c_str(&dbuf);
482 }
483
484
485 enum {
486      P_SAVE = 1,
487      P_RESTORE,
488      P_NOINDUCTION,
489      P_NOINVARIANT,
490      P_INDUCTION,
491      P_STACKAUTO,
492      P_NOJTBOUND,
493      P_NOOVERLAY,
494      P_LESSPEDANTIC,
495      P_NOGCSE,
496      P_CALLEE_SAVES,
497      P_EXCLUDE,
498      P_NOIV,
499      P_LOOPREV,
500      P_OVERLAY_,     /* I had a strange conflict with P_OVERLAY while */
501                      /* cross-compiling for MINGW32 with gcc 3.2 */
502      P_DISABLEWARN,
503      P_OPTCODESPEED,
504      P_OPTCODESIZE,
505      P_OPTCODEBALANCED,
506      P_STD_C89,
507      P_STD_C99,
508      P_STD_SDCC89,
509      P_STD_SDCC99,
510      P_CODESEG,
511      P_CONSTSEG
512 };
513
514
515 /* SAVE/RESTORE stack */
516 #define SAVE_RESTORE_SIZE 128
517
518 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
519 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
520 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
521
522 /*
523  * cloneXxx functions should be updated every time a new set is
524  * added to the options or optimize structure!
525  */
526
527 static struct options *cloneOptions(struct options *opt)
528 {
529   struct options *new_opt;
530
531   new_opt = Safe_malloc(sizeof (struct options));
532
533   /* clone scalar values */
534   *new_opt = *opt;
535
536   /* clone sets */
537   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
538   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
539   /* not implemented yet: */
540   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
541
542   return new_opt;
543 }
544
545 static struct optimize *cloneOptimize(struct optimize *opt)
546 {
547   struct optimize *new_opt;
548
549   new_opt = Safe_malloc(sizeof (struct optimize));
550
551   /* clone scalar values */
552   *new_opt = *opt;
553
554   return new_opt;
555 }
556
557 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
558 {
559   struct SDCCERRG *new_val;
560
561   new_val = Safe_malloc(sizeof (struct SDCCERRG));
562
563   /* clone scalar values */
564   *new_val = *val;
565
566   return new_val;
567 }
568
569 static void copyAndFreeOptions(struct options *dest, struct options *src)
570 {
571   /* delete dest sets */
572   deleteSet(&dest->calleeSavesSet);
573   deleteSet(&dest->excludeRegsSet);
574   /* not implemented yet: */
575   /* deleteSet(&dest->olaysSet); */
576
577   /* copy src to dest */
578   *dest = *src;
579
580   Safe_free(src);
581 }
582
583 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
584 {
585   /* copy src to dest */
586   *dest = *src;
587
588   Safe_free(src);
589 }
590
591 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
592 {
593   /* copy src to dest */
594   *dest = *src;
595
596   Safe_free(src);
597 }
598
599 /*
600  * returns 1 if the pragma was processed, 0 if not
601  */
602 static int doPragma(int id, const char *name, const char *cp)
603 {
604   struct pragma_token_s token;
605   int err = 0;
606   int processed = 1;
607
608   init_pragma_token(&token);
609
610   switch (id) 
611     {
612     case P_SAVE:
613       {
614         cp = get_pragma_token(cp, &token);
615         if (TOKEN_EOL != token.type)
616           {
617             err = 1;
618             break;
619           }
620
621         STACK_PUSH(options_stack, cloneOptions(&options));
622         STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
623         STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
624       }
625       break;
626
627     case P_RESTORE:
628       {
629         struct options *optionsp;
630         struct optimize *optimizep;
631         struct SDCCERRG *sdccerrgp;
632
633         cp = get_pragma_token(cp, &token);
634         if (TOKEN_EOL != token.type)
635           {
636             err = 1;
637             break;
638           }
639
640         optionsp = STACK_POP(options_stack);
641         copyAndFreeOptions(&options, optionsp);
642
643         optimizep = STACK_POP(optimize_stack);
644         copyAndFreeOptimize(&optimize, optimizep);
645
646         sdccerrgp = STACK_POP(SDCCERRG_stack);
647         copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
648       }
649       break;
650
651     case P_NOINDUCTION:
652       cp = get_pragma_token(cp, &token);
653       if (TOKEN_EOL != token.type)
654         {
655           err = 1;
656           break;
657         }
658
659       optimize.loopInduction = 0;
660       break;
661
662     case P_NOINVARIANT:
663       cp = get_pragma_token(cp, &token);
664       if (TOKEN_EOL != token.type)
665         {
666           err = 1;
667           break;
668         }
669
670       optimize.loopInvariant = 0;
671       break;
672
673     case P_INDUCTION:
674       cp = get_pragma_token(cp, &token);
675       if (TOKEN_EOL != token.type)
676         {
677           err = 1;
678           break;
679         }
680
681       optimize.loopInduction = 1;
682       break;
683
684     case P_STACKAUTO:
685       cp = get_pragma_token(cp, &token);
686       if (TOKEN_EOL != token.type)
687         {
688           err = 1;
689           break;
690         }
691
692       options.stackAuto = 1;
693       break;
694
695     case P_NOJTBOUND:
696       cp = get_pragma_token(cp, &token);
697       if (TOKEN_EOL != token.type)
698         {
699           err = 1;
700           break;
701         }
702
703       optimize.noJTabBoundary = 1;
704       break;
705
706     case P_NOGCSE:
707       cp = get_pragma_token(cp, &token);
708       if (TOKEN_EOL != token.type)
709         {
710           err = 1;
711           break;
712         }
713
714       optimize.global_cse = 0;
715       break;
716
717     case P_NOOVERLAY:
718       cp = get_pragma_token(cp, &token);
719       if (TOKEN_EOL != token.type)
720         {
721           err = 1;
722           break;
723         }
724
725       options.noOverlay = 1;
726       break;
727
728     case P_LESSPEDANTIC:
729       cp = get_pragma_token(cp, &token);
730       if (TOKEN_EOL != token.type)
731         {
732           err = 1;
733           break;
734         }
735
736       options.lessPedantic = 1;
737       setErrorLogLevel(ERROR_LEVEL_WARNING);
738       break;
739
740     case P_CALLEE_SAVES:
741       /* append to the functions already listed
742          in callee-saves */
743       setParseWithComma(&options.calleeSavesSet, cp);
744       err = -1;
745       break;
746
747     case P_EXCLUDE:
748       {
749         deleteSet(&options.excludeRegsSet);
750         setParseWithComma(&options.excludeRegsSet, cp);
751         err = -1;
752       }
753       break;
754
755     case P_NOIV:
756       cp = get_pragma_token(cp, &token);
757       if (TOKEN_EOL != token.type)
758         {
759           err = 1;
760           break;
761         }
762
763       options.noiv = 1;
764       break;
765
766     case P_LOOPREV:
767       cp = get_pragma_token(cp, &token);
768       if (TOKEN_EOL != token.type)
769         {
770           err = 1;
771           break;
772         }
773
774       optimize.noLoopReverse = 1;
775       break;
776
777     case P_OVERLAY_:
778       cp = get_pragma_token(cp, &token);
779       if (TOKEN_EOL != token.type)
780         {
781           err = 1;
782           break;
783         }
784
785       break; /* notyet */
786
787     case P_DISABLEWARN:
788       {
789         int warn;
790
791         cp = get_pragma_token(cp, &token);
792         if (TOKEN_INT != token.type)
793           {
794             err = 1;
795             break;
796           }
797         warn = token.val.int_val;
798
799         cp = get_pragma_token(cp, &token);
800         if (TOKEN_EOL != token.type)
801           {
802             err = 1;
803             break;
804           }
805
806         if (warn < MAX_ERROR_WARNING)
807           setWarningDisabled(warn);
808       }
809       break;
810
811     case P_OPTCODESPEED:
812       cp = get_pragma_token(cp, &token);
813       if (TOKEN_EOL != token.type)
814         {
815           err = 1;
816           break;
817         }
818
819       optimize.codeSpeed = 1;
820       optimize.codeSize = 0;
821       break;
822
823     case P_OPTCODESIZE:
824       cp = get_pragma_token(cp, &token);
825       if (TOKEN_EOL != token.type)
826         {
827           err = 1;
828           break;
829         }
830
831       optimize.codeSpeed = 0;
832       optimize.codeSize = 1;
833       break;
834
835     case P_OPTCODEBALANCED:
836       cp = get_pragma_token(cp, &token);
837       if (TOKEN_EOL != token.type)
838         {
839           err = 1;
840           break;
841         }
842
843       optimize.codeSpeed = 0;
844       optimize.codeSize = 0;
845       break;
846
847     case P_STD_C89:
848       cp = get_pragma_token(cp, &token);
849       if (TOKEN_EOL != token.type)
850         {
851           err = 1;
852           break;
853         }
854
855       options.std_c99 = 0;
856       options.std_sdcc = 0;
857       break;
858
859     case P_STD_C99:
860       cp = get_pragma_token(cp, &token);
861       if (TOKEN_EOL != token.type)
862         {
863           err = 1;
864           break;
865         }
866
867       options.std_c99 = 1;
868       options.std_sdcc = 0;
869       break;
870
871     case P_STD_SDCC89:
872       cp = get_pragma_token(cp, &token);
873       if (TOKEN_EOL != token.type)
874         {
875           err = 1;
876           break;
877         }
878
879       options.std_c99 = 0;
880       options.std_sdcc = 1;
881       break;
882
883     case P_STD_SDCC99:
884       cp = get_pragma_token(cp, &token);
885       if (TOKEN_EOL != token.type)
886         {
887           err = 1;
888           break;
889         }
890
891       options.std_c99 = 1;
892       options.std_sdcc = 1;
893       break;
894
895     case P_CODESEG:
896       {
897         const char *segname;
898
899         cp = get_pragma_token(cp, &token);
900         if (token.type == TOKEN_EOL)
901           {
902             err = 1;
903             break;
904           }
905         segname = get_pragma_string(&token);
906
907         cp = get_pragma_token(cp, &token);
908         if (token.type != TOKEN_EOL)
909           {
910             err = 1;
911             break;
912           }
913
914         if (strlen(segname) > 8)
915           {
916             err = 1;
917             break;
918           }
919         else
920           {
921             dbuf_append(&token.dbuf, "(CODE)", (sizeof "(CODE)") - 1);
922             options.code_seg = Safe_strdup(get_pragma_string(&token));
923           }
924       }
925       break;
926
927     case P_CONSTSEG:
928       {
929         const char *segname;
930
931         cp = get_pragma_token(cp, &token);
932         if (token.type == TOKEN_EOL)
933           {
934             err = 1;
935             break;
936           }
937         segname = get_pragma_string(&token);
938
939         cp = get_pragma_token(cp, &token);
940         if (token.type != TOKEN_EOL)
941           {
942             err = 1;
943             break;
944           }
945
946         if (strlen(segname) > 8)
947           {
948             err = 1;
949             break;
950           }
951         else
952           {
953             dbuf_append(&token.dbuf, "(CODE)", (sizeof "(CODE)") - 1);
954             options.code_seg = Safe_strdup(get_pragma_string(&token));
955           }
956       }
957       break;
958
959     default:
960       processed = 0;
961       break;
962     }
963
964   get_pragma_token(cp, &token);
965
966   if (1 == err || (0 == err && token.type != TOKEN_EOL))
967     werror(W_BAD_PRAGMA_ARGUMENTS, name);
968
969   free_pragma_token(&token);
970   return processed;
971 }
972
973 static struct pragma_s pragma_tbl[] = {
974   { "save",           P_SAVE,         0, doPragma },
975   { "restore",        P_RESTORE,      0, doPragma },
976   { "noinduction",    P_NOINDUCTION,  0, doPragma },
977   { "noinvariant",    P_NOINVARIANT,  0, doPragma },
978   { "noloopreverse",  P_LOOPREV,      0, doPragma },
979   { "induction",      P_INDUCTION,    0, doPragma },
980   { "stackauto",      P_STACKAUTO,    0, doPragma },
981   { "nojtbound",      P_NOJTBOUND,    0, doPragma },
982   { "nogcse",         P_NOGCSE,       0, doPragma },
983   { "nooverlay",      P_NOOVERLAY,    0, doPragma },
984   { "callee_saves",   P_CALLEE_SAVES, 0, doPragma },
985   { "exclude",        P_EXCLUDE,      0, doPragma },
986   { "noiv",           P_NOIV,         0, doPragma },
987   { "overlay",        P_OVERLAY_,     0, doPragma },
988   { "less_pedantic",  P_LESSPEDANTIC, 0, doPragma },
989   { "disable_warning",P_DISABLEWARN,  0, doPragma },
990   { "opt_code_speed", P_OPTCODESPEED, 0, doPragma },
991   { "opt_code_size",  P_OPTCODESIZE,  0, doPragma },
992   { "opt_code_balanced", P_OPTCODEBALANCED, 0, doPragma },
993   { "std_c89",        P_STD_C89,      0, doPragma },
994   { "std_c99",        P_STD_C99,      0, doPragma },
995   { "std_sdcc89",     P_STD_SDCC89,   0, doPragma },
996   { "std_sdcc99",     P_STD_SDCC99,   0, doPragma },
997   { "codeseg",        P_CODESEG,      0, doPragma },
998   { "constseg",       P_CONSTSEG,     0, doPragma },
999   { NULL,             0,              0, NULL },
1000 };
1001
1002 /*
1003  * returns 1 if the pragma was processed, 0 if not
1004  */
1005 int
1006 process_pragma_tbl(const struct pragma_s *pragma_tbl, const char *s)
1007 {
1008   struct pragma_token_s token;
1009   int i;
1010   int ret = 0;
1011
1012   init_pragma_token(&token);
1013
1014   s = get_pragma_token(s, &token);
1015
1016   /* skip separating whitespace */
1017   while ('\n' != *s && isspace((unsigned char)*s))
1018     s++;
1019
1020   for (i = 0; NULL != pragma_tbl[i].name; ++i)
1021     {
1022       /* now compare and do what needs to be done */
1023       if (strcmp(get_pragma_string(&token), pragma_tbl[i].name) == 0)
1024         {
1025           if (pragma_tbl[i].deprecated != 0)
1026             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
1027
1028           ret = (*pragma_tbl[i].func)(pragma_tbl[i].id, pragma_tbl[i].name, s);
1029           break;
1030         }
1031     }
1032
1033   free_pragma_token(&token);
1034   return ret;
1035 }
1036
1037 static int process_pragma(const char *s)
1038 {
1039   struct pragma_token_s token;
1040
1041   init_pragma_token(&token);
1042
1043   s = get_pragma_token(s, &token);
1044   if (0 != strcmp("#pragma", get_pragma_string(&token)))
1045     {
1046       /* Oops, womething went totally wrong - internal error */
1047       wassertl(0, "pragma parser internal error");
1048     }
1049
1050   /* skip spaces */
1051   while ('\n' != *s && isspace((unsigned char)*s))
1052     ++s;
1053
1054   /* First give the port a chance */
1055   if (port->process_pragma && port->process_pragma(s))
1056     return 1;
1057
1058   if (process_pragma_tbl(pragma_tbl, s))
1059     {
1060       return 1;
1061     }
1062   else
1063     {
1064       werror(W_UNKNOWN_PRAGMA, s);
1065       return 0;
1066     }
1067 }
1068
1069 /* will return 1 if the string is a part
1070    of a target specific keyword */
1071 static int isTargetKeyword(const char *s)
1072 {
1073   int i;
1074
1075   if (port->keywords == NULL)
1076     return 0;
1077
1078   if (s[0] == '_' && s[1] == '_')
1079     {
1080       /* Keywords in the port's array have either 0 or 1 underscore, */
1081       /* so skip over the appropriate number of chars when comparing */
1082       for (i = 0 ; port->keywords[i] ; i++ )
1083         {
1084           if (port->keywords[i][0] == '_' &&
1085               strcmp(port->keywords[i],s+1) == 0)
1086             return 1;
1087           else if (strcmp(port->keywords[i],s+2) == 0)
1088             return 1;
1089         }
1090     }
1091   else
1092     {
1093       for (i = 0 ; port->keywords[i] ; i++ )
1094         {
1095           if (strcmp(port->keywords[i],s) == 0)
1096             return 1;
1097         }
1098     }
1099
1100   return 0;
1101 }
1102
1103 int yywrap(void)
1104 {
1105   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
1106     werror(W_SAVE_RESTORE);
1107
1108   return 1;
1109 }
1110
1111 int yyerror(char *s)
1112 {
1113   fflush(stdout);
1114
1115   if(options.vc_err_style)
1116     fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
1117       filename, mylineno, s, yytext, column);
1118   else
1119     fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
1120       filename, mylineno, s ,yytext, column);
1121   fatalError++;
1122
1123   return 0;
1124 }