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