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