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