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