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