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