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