* src/mcs51/gen.c (genNearPointerGet, genNearPointerSet): fixed bug 1938300
[fw/sdcc] / src / SDCC.lex
1 /*-----------------------------------------------------------------------
2   SDCC.lex - lexical analyser for use with sdcc (free open source
3   compiler for 8/16 bit microcontrollers)
4   Written by : Sandeep Dutta . sandeep.dutta@usa.net (1997)
5
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20   In other words, you are welcome to use, share and improve this program.
21   You are forbidden to forbid anyone else to use, share and improve
22   what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 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 char *filename;
49 extern int lineno;
50 int column = 0;         /* current column */
51
52 /* global definitions */
53 char *lexFilename;
54 int lexLineno = 1;
55
56 /* local definitions */
57 static struct dbuf_s asmbuff; /* reusable _asm buffer */
58
59 /* forward declarations */
60 int yyerror(char *s);
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})*  {
195   if (!options.dollars_in_ident && strchr(yytext, '$'))
196     {
197       yyerror("stray '$' in program");
198     }
199   count();
200   return(check_type());
201 }
202 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
203 0[0-7]*{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
204 [1-9]{D}*{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
205 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ }
206 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
207 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
208 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
209 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
210 ">>="          { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
211 "<<="          { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN); }
212 "+="           { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN); }
213 "-="           { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN); }
214 "*="           { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN); }
215 "/="           { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN); }
216 "%="           { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN); }
217 "&="           { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN); }
218 "^="           { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN); }
219 "|="           { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN); }
220 ">>"           { count(); return(RIGHT_OP); }
221 "<<"           { count(); return(LEFT_OP); }
222 "++"           { count(); return(INC_OP); }
223 "--"           { count(); return(DEC_OP); }
224 "->"           { count(); return(PTR_OP); }
225 "&&"           { count(); return(AND_OP); }
226 "||"           { count(); return(OR_OP); }
227 "<="           { count(); return(LE_OP); }
228 ">="           { count(); return(GE_OP); }
229 "=="           { count(); return(EQ_OP); }
230 "!="           { count(); return(NE_OP); }
231 ";"            { count(); return(';'); }
232 "{"            { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
233 "}"            { count(); NestLevel--; return('}'); }
234 ","            { count(); return(','); }
235 ":"            { count(); return(':'); }
236 "="            { count(); return('='); }
237 "("            { count(); ignoreTypedefType = 0; return('('); }
238 ")"            { count(); return(')'); }
239 "["            { count(); 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 ^#pragma.*$    { count(); process_pragma(yytext); }
256 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
257
258 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
259 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
260 "\r\n"         { count(); }
261 "\n"           { count(); }
262 [ \t\v\f]      { count(); }
263 \\ {
264   int ch = input();
265
266   if (ch == '\n')
267     count_char(ch);
268   else
269     {
270       /* that could have been removed by the preprocessor anyway */
271       werror (W_STRAY_BACKSLASH, column);
272       unput(ch);
273     }
274 }
275 .              { count(); }
276 %%
277
278 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
279 #ifndef yytext_ptr
280 #define yytext_ptr yytext
281 #endif
282
283
284 static int checkCurrFile (const char *s)
285 {
286   int  lNum;
287   char *tptr;
288
289   /* skip '#' character */
290   if (*s++ != '#')
291     return 0;
292
293   /* check if this is a #line
294     this is not standard and can be removed in the future */
295 #define LINE_STR  "line"
296 #define LINE_LEN  ((sizeof LINE_STR) - 1)
297
298   if (strncmp(s, LINE_STR, LINE_LEN) == 0)
299     s += LINE_LEN;
300
301   /* get the line number */
302   lNum = strtol(s, &tptr, 10);
303   if (tptr == s || !isspace((unsigned char)*tptr))
304     return 0;
305   s = tptr;
306
307   /* adjust the line number */
308   lineno = lexLineno = lNum;
309
310   /* now see if we have a file name */
311   while (*s != '"' && *s)
312     ++s;
313
314   if (!*s)
315     {
316       /* no file name: return */
317       return 0;
318     }
319
320   /* skip the double quote */
321   ++s;
322
323   /* get the file name and see if it is different from current one.
324      in c1mode fullSrcFileName is NULL */
325   if (fullSrcFileName &&
326     strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0 && fullSrcFileName[strlen(fullSrcFileName) - 1] == '"')
327     {
328       lexFilename = fullSrcFileName;
329     }
330   else
331     {
332       const char *sb = s;
333       char *tmpFname;
334
335       /* find the end of the file name */
336       while (*s && *s != '"')
337         ++s;
338
339       tmpFname = Safe_malloc(s - sb + 1);
340       memcpy(tmpFname, sb, s - sb);
341       tmpFname[s - sb] = '\0';
342
343       lexFilename = Safe_malloc(s - sb + 1);
344       copyStr(lexFilename, tmpFname);
345     }
346   filename = lexFilename;
347
348   return 0;
349 }
350
351 static void count_char(int ch)
352 {
353   switch (ch)
354     {
355     case '\n':
356       column = 0;
357       lineno = ++lexLineno;
358       break;
359
360     case '\t':
361       column += 8 - (column % 8);
362       break;
363
364     default:
365       ++column;
366       break;
367     }
368 }
369
370 static void count(void)
371 {
372   const char *p;
373
374   for (p = yytext; *p; ++p)
375     count_char(*p);
376 }
377
378 static int check_type(void)
379 {
380   symbol *sym = findSym(SymbolTab, NULL, yytext);
381
382   strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
383
384   /* check if it is in the table as a typedef */
385   if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
386       && SPEC_TYPEDEF (sym->etype) && findSym(TypedefTab, NULL, yytext))
387     return (TYPE_NAME);
388   else
389     return(IDENTIFIER);
390 }
391
392 /*
393  * Change by JTV 2001-05-19 to not concantenate strings
394  * to support ANSI hex and octal escape sequences in string literals
395  */
396
397 static const char *stringLiteral(void)
398 {
399 #define STR_BUF_CHUNCK_LEN  1024
400   int ch;
401   static struct dbuf_s dbuf;  /* reusable string literal buffer */
402
403   if (dbuf.alloc == 0)
404     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
405   else
406     dbuf_set_length(&dbuf, 0);
407
408   dbuf_append_char(&dbuf, '"');
409
410   /* put into the buffer till we hit the first \" */
411
412   for (; ; )
413     {
414       ch = input();
415       count_char(ch);
416       if (ch == EOF)
417         break;
418
419       switch (ch)
420         {
421         case '\\':
422           /* if it is a \ then escape char's are allowed */
423           ch = input();
424           count_char(ch);
425           if (ch == '\n')
426             {
427               /* \<newline> is a continuator */
428             }
429           else
430             {
431               char buf[2];
432
433               if (ch == EOF)
434                 goto out;
435
436               buf[0] = '\\';
437               buf[1] = ch;
438               dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
439             }
440           break; /* carry on */
441
442         case '\n':
443           /* if new line we have a new line break, which is illegal */
444           werror(W_NEWLINE_IN_STRING);
445           dbuf_append_char(&dbuf, '\n');
446           break;
447
448         case '"':
449           /* if this is a quote then we have work to do */
450           /* find the next non whitespace character     */
451           /* if that is a double quote then carry on    */
452           dbuf_append_char(&dbuf, '"');  /* Pass end of this string or substring to evaluator */
453           while ((ch = input()) && (isspace(ch) || ch == '\\' || ch == '#'))
454             {
455               switch (ch)
456                 {
457                 case '\\':
458                   count_char(ch);
459                   if ((ch = input()) != '\n')
460                     {
461                       werror(W_STRAY_BACKSLASH, column);
462                       if (ch != EOF)
463                         unput(ch);
464                       else
465                         count_char(ch);
466                     }
467                   else
468                     count_char(ch);
469                   break;
470
471                 case '\n':
472                   count_char(ch);
473                   break;
474
475                 case '#':
476                   if (column == 0)
477                     {
478                       /* # at the beginning of the line: collect the entire line */
479                       struct dbuf_s linebuf;
480                       const char *line;
481
482                       count_char(ch);
483
484                       dbuf_init(&linebuf, STR_BUF_CHUNCK_LEN);
485                       dbuf_append_char(&linebuf, '#');
486
487                       while ((ch = input()) != EOF && ch != '\n')
488                         dbuf_append_char(&linebuf, (char)ch);
489
490                       if (ch == '\n')
491                         count_char(ch);
492
493                       line = dbuf_c_str(&linebuf);
494
495                       /* process the line */
496                       if (startsWith(line, "#pragma"))
497                         process_pragma(line);
498                       else
499                         checkCurrFile(line);
500
501                       dbuf_destroy(&linebuf);
502                     }
503                   else
504                     {
505                       unput(ch);
506                       goto out;
507                     }
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 }