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