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