* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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.h"
39
40 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
41                                 check_type())
42
43 #define TKEYWORDSDCC(token) return (options.std_sdcc && isTargetKeyword(yytext)\
44                                     ? token : check_type())
45
46 #define TKEYWORD99(token) return (options.std_c99 ? token : check_type())
47
48 extern int lineno, column;
49 extern char *filename;
50
51 /* global definitions */
52 char *currFname;
53 int mylineno = 1;
54
55 /* local definitions */
56 static struct dbuf_s asmbuff;
57
58 /* forward declarations */
59 static char *stringLiteral(void);
60 static void count(void);
61 static int process_pragma(char *);
62 static int check_type(void);
63 static int isTargetKeyword(char *s);
64 static int checkCurrFile(char *s);
65 %}
66
67 %x asm
68 %%
69 _?"_asm"         {
70   count();
71   if (!options.std_sdcc && yytext[1] != '_')
72     return check_type();
73   assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
74   dbuf_init(&asmbuff, INITIAL_INLINEASM);
75   BEGIN(asm);
76 }
77 <asm>_?"_endasm" {
78   count();
79   if (!options.std_sdcc && yytext[1] != '_')
80     {
81       dbuf_append(&asmbuff, yytext, strlen(yytext));
82     }
83   else
84     {
85       yylval.yyinline = dbuf_c_str(&asmbuff);
86       dbuf_detach(&asmbuff);
87       BEGIN(INITIAL);
88       return (INLINEASM);
89     }
90 }
91 <asm>\n        {
92   count();
93   dbuf_append(&asmbuff, yytext, 1);
94 }
95 <asm>.         {
96   dbuf_append(&asmbuff, yytext, 1);
97 }
98 "at"           { count(); TKEYWORDSDCC(AT); }
99 "__at"         { count(); TKEYWORD(AT); }
100 "auto"         { count(); return(AUTO); }
101 "bit"          { count(); TKEYWORDSDCC(BIT); }
102 "__bit"        { count(); TKEYWORD(BIT); }
103 "break"        { count(); return(BREAK); }
104 "case"         { count(); return(CASE); }
105 "char"         { count(); return(CHAR); }
106 "code"         { count(); TKEYWORDSDCC(CODE); }
107 "__code"       { count(); TKEYWORD(CODE); }
108 "const"        { count(); return(CONST); }
109 "continue"     { count(); return(CONTINUE); }
110 "critical"     { count(); TKEYWORDSDCC(CRITICAL); }
111 "__critical"   { count(); TKEYWORD(CRITICAL); }
112 "data"         { count(); TKEYWORDSDCC(DATA); }
113 "__data"       { count(); TKEYWORD(DATA); }
114 "default"      { count(); return(DEFAULT); }
115 "do"           { count(); return(DO); }
116 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
117 "else"         { count(); return(ELSE); }
118 "enum"         { count(); return(ENUM); }
119 "extern"       { count(); return(EXTERN); }
120 "far"          { count(); TKEYWORDSDCC(XDATA); }
121 "__far"        { count(); TKEYWORD(XDATA); }
122 "eeprom"       { count(); TKEYWORDSDCC(EEPROM); }
123 "__eeprom"     { count(); TKEYWORD(EEPROM); }
124 "float"        { count(); return(FLOAT); }
125 "fixed16x16"   { count(); TKEYWORDSDCC(FIXED16X16); }
126 "__fixed16x16"   { count(); TKEYWORD(FIXED16X16); }
127 "flash"        { count(); TKEYWORDSDCC(CODE); }
128 "__flash"      { count(); TKEYWORD(CODE); }
129 "for"          { count(); return(FOR); }
130 "goto"         { count(); return(GOTO); }
131 "idata"        { count(); TKEYWORDSDCC(IDATA); }
132 "__idata"      { count(); TKEYWORD(IDATA); }
133 "if"           { count(); return(IF); }
134 "int"          { count(); return(INT); }
135 "interrupt"    { count(); TKEYWORDSDCC(INTERRUPT); }
136 "__interrupt"  { count(); TKEYWORD(INTERRUPT); }
137 "nonbanked"    { count(); TKEYWORDSDCC(NONBANKED); }
138 "__nonbanked"  { count(); TKEYWORD(NONBANKED); }
139 "banked"       { count(); TKEYWORDSDCC(BANKED); }
140 "__banked"     { count(); TKEYWORD(BANKED); }
141 "long"         { count(); return(LONG); }
142 "near"         { count(); TKEYWORDSDCC(DATA); }
143 "__near"       { count(); TKEYWORD(DATA); }
144 "pdata"        { count(); TKEYWORDSDCC(PDATA); }
145 "__pdata"      { count(); TKEYWORD(PDATA); }
146 "reentrant"    { count(); TKEYWORDSDCC(REENTRANT); }
147 "__reentrant"  { count(); TKEYWORD(REENTRANT); }
148 "shadowregs"   { count(); TKEYWORDSDCC(SHADOWREGS); }
149 "__shadowregs" { count(); TKEYWORD(SHADOWREGS); }
150 "wparam"       { count(); TKEYWORDSDCC(WPARAM); }
151 "__wparam"     { count(); TKEYWORD(WPARAM); }
152 "register"     { count(); return(REGISTER); }
153 "return"       { count(); return(RETURN); }
154 "sfr"          { count(); TKEYWORDSDCC(SFR); }
155 "__sfr"        { count(); TKEYWORD(SFR); }
156 "sfr16"        { count(); TKEYWORDSDCC(SFR16); }
157 "__sfr16"      { count(); TKEYWORD(SFR16); }
158 "sfr32"        { count(); TKEYWORDSDCC(SFR32); }
159 "__sfr32"      { count(); TKEYWORD(SFR32); }
160 "sbit"         { count(); TKEYWORDSDCC(SBIT); }
161 "__sbit"       { count(); TKEYWORD(SBIT); }
162 "short"        { count(); return(SHORT); }
163 "signed"       { count(); return(SIGNED); }
164 "sizeof"       { count(); return(SIZEOF); }
165 "sram"         { count(); TKEYWORDSDCC(XDATA); }
166 "__sram"       { count(); TKEYWORD(XDATA); }
167 "static"       { count(); return(STATIC); }
168 "struct"       { count(); return(STRUCT); }
169 "switch"       { count(); return(SWITCH); }
170 "typedef"      { count(); return(TYPEDEF); }
171 "union"        { count(); return(UNION); }
172 "unsigned"     { count(); return(UNSIGNED); }
173 "void"         { count(); return(VOID); }
174 "volatile"     { count(); return(VOLATILE); }
175 "using"        { count(); TKEYWORDSDCC(USING); }
176 "__using"      { count(); TKEYWORD(USING); }
177 "_naked"       { count(); TKEYWORDSDCC(NAKED); }
178 "__naked"      { count(); TKEYWORD(NAKED); }
179 "while"        { count(); return(WHILE); }
180 "xdata"        { count(); TKEYWORDSDCC(XDATA); }
181 "__xdata"      { count(); TKEYWORD(XDATA); }
182 "..."          { count(); return(VAR_ARGS); }
183 "__typeof"     { count(); return TYPEOF; }
184 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE); }
185 "_overlay"     { count(); TKEYWORDSDCC(OVERLAY); }
186 "__overlay"    { count(); TKEYWORD(OVERLAY); }
187 "inline"       { count(); TKEYWORD99(INLINE); }
188 "restrict"     { count(); TKEYWORD99(RESTRICT); }
189 {L}({L}|{D})*  { count(); return(check_type()); }
190 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
191 0[0-7]*{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
192 [1-9]{D}*{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
193 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ }
194 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
195 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
196 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
197 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
198 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
199 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN); }
200 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN); }
201 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN); }
202 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN); }
203 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN); }
204 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN); }
205 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN); }
206 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN); }
207 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN); }
208 ">>"           { count(); return(RIGHT_OP); }
209 "<<"           { count(); return(LEFT_OP); }
210 "++"           { count(); return(INC_OP); }
211 "--"           { count(); return(DEC_OP); }
212 "->"           { count(); return(PTR_OP); }
213 "&&"           { count(); return(AND_OP); }
214 "||"           { count(); return(OR_OP); }
215 "<="           { count(); return(LE_OP); }
216 ">="           { count(); return(GE_OP); }
217 "=="           { count(); return(EQ_OP); }
218 "!="           { count(); return(NE_OP); }
219 ";"            { count(); return(';'); }
220 "{"            { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
221 "}"            { count(); NestLevel--; return('}'); }
222 ","            { count(); return(','); }
223 ":"            { count(); return(':'); }
224 "="            { count(); return('='); }
225 "("            { count(); ignoreTypedefType = 0; return('('); }
226 ")"            { count(); return(')'); }
227 "["            { count(); return('['); }
228 "]"            { count(); return(']'); }
229 "."            { count(); return('.'); }
230 "&"            { count(); return('&'); }
231 "!"            { count(); return('!'); }
232 "~"            { count(); return('~'); }
233 "-"            { count(); return('-'); }
234 "+"            { count(); return('+'); }
235 "*"            { count(); return('*'); }
236 "/"            { count(); return('/'); }
237 "%"            { count(); return('%'); }
238 "<"            { count(); return('<'); }
239 ">"            { count(); return('>'); }
240 "^"            { count(); return('^'); }
241 "|"            { count(); return('|'); }
242 "?"            { count(); return('?'); }
243 ^#pragma.*"\n" { count(); process_pragma(yytext); }
244 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
245
246 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
247 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
248 "\r\n"         { count(); }
249 "\n"           { count(); }
250 [ \t\v\f]      { count(); }
251 \\ {
252   int ch = input();
253   if (ch != '\n') {
254     /* that could have been removed by the preprocessor anyway */
255     werror (W_STRAY_BACKSLASH, column);
256     unput(ch);
257   }
258 }
259 .              { count(); }
260 %%
261
262 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
263 #ifndef yytext_ptr
264 #define yytext_ptr yytext
265 #endif
266
267
268 static int checkCurrFile (char *s)
269 {
270     int  lNum;
271     char *tptr;
272
273     /* skip '#' character */
274     if (*s++ != '#')
275       return 0;
276
277     /* check if this is a #line
278        this is not standard and can be removed in the future */
279 #define LINE_STR  "line"
280 #define LINE_LEN  ((sizeof LINE_STR) - 1)
281
282     if (strncmp(s, LINE_STR, LINE_LEN) == 0)
283       s += LINE_LEN;
284
285     /* get the line number */
286     lNum = strtol(s, &tptr, 10);
287     if (tptr == s || !isspace((unsigned char)*tptr))
288       return 0;
289     s = tptr;
290
291     /* now see if we have a file name */
292     while (*s != '\"' && *s)
293       s++;
294
295     /* if we don't have a filename then */
296     /* set the current line number to   */
297     /* line number if printFlag is on   */
298     if (!*s) {
299       lineno = mylineno = lNum;
300       return 0;
301     }
302
303     /* if we have a filename then check */
304     /* if it is "standard in" if yes then */
305     /* get the currentfile name info    */
306     s++ ;
307
308     /* in c1mode fullSrcFileName is NULL */
309     if (fullSrcFileName &&
310          strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
311       lineno = mylineno = lNum;
312       currFname = fullSrcFileName;
313     } else {
314         char *sb = s;
315         /* mark the end of the filename */
316         while (*s != '"') s++;
317         *s = '\0';
318         currFname = strdup (sb);
319         lineno = mylineno = lNum;
320     }
321     filename = currFname ;
322     return 0;
323 }
324
325 int column = 0;
326 int plineIdx =0;
327
328 static void count(void)
329 {
330   int i;
331   for (i = 0; yytext[i] != '\0'; i++) {
332     if (yytext[i] == '\n') {
333       column = 0;
334       lineno = ++mylineno;
335     }
336     else
337       if (yytext[i] == '\t')
338         column += 8 - (column % 8);
339       else
340         column++;
341   }
342   /* ECHO; */
343 }
344
345 static int check_type(void)
346 {
347   symbol *sym = findSym(SymbolTab, NULL, yytext);
348
349   /* check if it is in the table as a typedef */
350   if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
351       && SPEC_TYPEDEF (sym->etype)) {
352     strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
353     return (TYPE_NAME);
354   }
355   else {
356     strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
357     return(IDENTIFIER);
358   }
359 }
360
361 /*
362  * Change by JTV 2001-05-19 to not concantenate strings
363  * to support ANSI hex and octal escape sequences in string literals
364  */
365
366 static char *stringLiteral(void)
367 {
368 #define STR_BUF_CHUNCK_LEN  1024
369   int ch;
370   static struct dbuf_s dbuf;
371   char buf[2];
372
373   if (dbuf.alloc == 0)
374     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
375   else
376     dbuf_set_size(&dbuf, 0);
377
378   dbuf_append(&dbuf, "\"", 1);
379   /* put into the buffer till we hit the first \" */
380
381   while ((ch = input()) != 0) {
382     switch (ch) {
383     case '\\':
384       /* if it is a \ then escape char's are allowed */
385       ch = input();
386       if (ch == '\n') {
387         /* \<newline> is a continuator */
388         lineno = ++mylineno;
389         column = 0;
390       }
391       else {
392         buf[0] = '\\';
393         buf[1] = ch;
394         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
395       }
396       break; /* carry on */
397
398     case '\n':
399       /* if new line we have a new line break, which is illegal */
400       werror(W_NEWLINE_IN_STRING);
401       dbuf_append(&dbuf, "\n", 1);
402       lineno = ++mylineno;
403       column = 0;
404       break;
405
406     case '"':
407       /* if this is a quote then we have work to do */
408       /* find the next non whitespace character     */
409       /* if that is a double quote then carry on    */
410       dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
411       while ((ch = input()) && (isspace(ch) || ch == '\\')) {
412         switch (ch) {
413         case '\\':
414           if ((ch = input()) != '\n') {
415             werror(W_STRAY_BACKSLASH, column);
416             unput(ch);
417           }
418           else {
419             lineno = ++mylineno;
420             column = 0;
421           }
422           break;
423
424         case '\n':
425           mylineno++;
426           break;
427         }
428       }
429
430       if (!ch)
431         goto out;
432
433       if (ch != '\"') {
434         unput(ch);
435         goto out;
436       }
437       break;
438
439     default:
440       buf[0] = ch;
441       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
442     }
443   }
444
445 out:
446   return (char *)dbuf_c_str(&dbuf);
447 }
448
449
450 enum pragma_id {
451      P_SAVE = 1,
452      P_RESTORE,
453      P_NOINDUCTION,
454      P_NOINVARIANT,
455      P_INDUCTION,
456      P_STACKAUTO,
457      P_NOJTBOUND,
458      P_NOOVERLAY,
459      P_LESSPEDANTIC,
460      P_NOGCSE,
461      P_CALLEE_SAVES,
462      P_EXCLUDE,
463      P_NOIV,
464      P_LOOPREV,
465      P_OVERLAY_,     /* I had a strange conflict with P_OVERLAY while */
466                      /* cross-compiling for MINGW32 with gcc 3.2 */
467      P_DISABLEWARN,
468      P_OPTCODESPEED,
469      P_OPTCODESIZE,
470      P_OPTCODEBALANCED,
471      P_STD_C89,
472      P_STD_C99,
473      P_STD_SDCC89,
474      P_STD_SDCC99,
475      P_CODESEG,
476      P_CONSTSEG
477 };
478
479
480 /* SAVE/RESTORE stack */
481 #define SAVE_RESTORE_SIZE 128
482
483 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
484 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
485 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
486
487 /*
488  * cloneXxx functions should be updated every time a new set is
489  * added to the options or optimize structure!
490  */
491
492 static struct options *cloneOptions(struct options *opt)
493 {
494   struct options *new_opt;
495
496   new_opt = Safe_malloc(sizeof (struct options));
497
498   /* clone scalar values */
499   *new_opt = *opt;
500
501   /* clone sets */
502   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
503   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
504   /* not implemented yet: */
505   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
506
507   return new_opt;
508 }
509
510 static struct optimize *cloneOptimize(struct optimize *opt)
511 {
512   struct optimize *new_opt;
513
514   new_opt = Safe_malloc(sizeof (struct optimize));
515
516   /* clone scalar values */
517   *new_opt = *opt;
518
519   return new_opt;
520 }
521
522 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
523 {
524   struct SDCCERRG *new_val;
525
526   new_val = Safe_malloc(sizeof (struct SDCCERRG));
527
528   /* clone scalar values */
529   *new_val = *val;
530
531   return new_val;
532 }
533
534 static void copyAndFreeOptions(struct options *dest, struct options *src)
535 {
536   /* delete dest sets */
537   deleteSet(&dest->calleeSavesSet);
538   deleteSet(&dest->excludeRegsSet);
539   /* not implemented yet: */
540   /* deleteSet(&dest->olaysSet); */
541
542   /* copy src to dest */
543   *dest = *src;
544
545   Safe_free(src);
546 }
547
548 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
549 {
550   /* copy src to dest */
551   *dest = *src;
552
553   Safe_free(src);
554 }
555
556 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
557 {
558   /* copy src to dest */
559   *dest = *src;
560
561   Safe_free(src);
562 }
563
564 static void doPragma(int op, char *cp)
565 {
566   int i;
567
568   switch (op) {
569   case P_SAVE:
570     {
571       STACK_PUSH(options_stack, cloneOptions(&options));
572       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
573       STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
574     }
575     break;
576
577   case P_RESTORE:
578     {
579       struct options *optionsp;
580       struct optimize *optimizep;
581       struct SDCCERRG *sdccerrgp;
582
583       optionsp = STACK_POP(options_stack);
584       copyAndFreeOptions(&options, optionsp);
585
586       optimizep = STACK_POP(optimize_stack);
587       copyAndFreeOptimize(&optimize, optimizep);
588
589       sdccerrgp = STACK_POP(SDCCERRG_stack);
590       copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
591     }
592     break;
593
594   case P_NOINDUCTION:
595     optimize.loopInduction = 0;
596     break;
597
598   case P_NOINVARIANT:
599     optimize.loopInvariant = 0;
600     break;
601
602   case P_INDUCTION:
603     optimize.loopInduction = 1;
604     break;
605
606   case P_STACKAUTO:
607     options.stackAuto = 1;
608     break;
609
610   case P_NOJTBOUND:
611     optimize.noJTabBoundary = 1;
612     break;
613
614   case P_NOGCSE:
615     optimize.global_cse = 0;
616     break;
617
618   case P_NOOVERLAY:
619     options.noOverlay = 1;
620     break;
621
622   case P_LESSPEDANTIC:
623     options.lessPedantic = 1;
624     setErrorLogLevel(ERROR_LEVEL_WARNING);
625     break;
626
627   case P_CALLEE_SAVES:
628     /* append to the functions already listed
629        in callee-saves */
630     setParseWithComma(&options.calleeSavesSet, cp);
631     break;
632
633   case P_EXCLUDE:
634     {
635       deleteSet(&options.excludeRegsSet);
636       setParseWithComma(&options.excludeRegsSet, cp);
637     }
638     break;
639
640   case P_NOIV:
641     options.noiv = 1;
642     break;
643
644   case P_LOOPREV:
645     optimize.noLoopReverse = 1;
646     break;
647
648   case P_OVERLAY_:
649     break; /* notyet */
650
651   case P_DISABLEWARN:
652     if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
653       {
654         setWarningDisabled(i);
655       }
656     break;
657   
658   case P_OPTCODESPEED:
659     optimize.codeSpeed = 1;
660     optimize.codeSize = 0;
661     break;
662
663   case P_OPTCODESIZE:
664     optimize.codeSpeed = 0;
665     optimize.codeSize = 1;
666     break;
667
668   case P_OPTCODEBALANCED:
669     optimize.codeSpeed = 0;
670     optimize.codeSize = 0;
671     break;
672   
673   case P_STD_C89:
674     options.std_c99 = 0;
675     options.std_sdcc = 0;
676     break;
677   
678   case P_STD_C99:
679     options.std_c99 = 1;
680     options.std_sdcc = 0;
681     break;
682   
683   case P_STD_SDCC89:
684     options.std_c99 = 0;
685     options.std_sdcc = 1;
686     break;
687   
688   case P_STD_SDCC99:
689     options.std_c99 = 1;
690     options.std_sdcc = 1;
691     break;
692
693   case P_CODESEG:
694     {
695       char str[9];
696       char *segname = Safe_malloc(15);
697       sscanf(cp, " %8s", str);
698       str[8] = '\0';
699       sprintf(segname, "%-8.8s(CODE)", str);
700       options.code_seg = segname;
701     }
702     break;
703
704   case P_CONSTSEG:
705     {
706       char str[9];
707       char *segname = Safe_malloc(15);
708       sscanf(cp, " %8s", str);
709       str[8] = '\0';
710       sprintf(segname, "%-8.8s(CODE)", str);
711       options.const_seg = segname;
712     }
713     break;
714   }
715 }
716
717 static int process_pragma(char *s)
718 {
719 #define NELEM(x)    (sizeof (x) / sizeof (x)[0])
720 #define PRAGMA_STR  "#pragma"
721 #define PRAGMA_LEN  ((sizeof PRAGMA_STR) - 1)
722
723   static struct pragma_s
724     {
725       const char *name;
726       enum pragma_id id;
727       char deprecated;
728     } pragma_tbl[] = {
729     { "save",           P_SAVE,         0 },
730     { "restore",        P_RESTORE,      0 },
731     { "noinduction",    P_NOINDUCTION,  0 },
732     { "noinvariant",    P_NOINVARIANT,  0 },
733     { "noloopreverse",  P_LOOPREV,      0 },
734     { "induction",      P_INDUCTION,    0 },
735     { "stackauto",      P_STACKAUTO,    0 },
736     { "nojtbound",      P_NOJTBOUND,    0 },
737     { "nogcse",         P_NOGCSE,       0 },
738     { "nooverlay",      P_NOOVERLAY,    0 },
739     { "callee_saves",   P_CALLEE_SAVES, 0 },
740     { "exclude",        P_EXCLUDE,      0 },
741     { "noiv",           P_NOIV,         0 },
742     { "overlay",        P_OVERLAY_,     0 },
743     { "less_pedantic",  P_LESSPEDANTIC, 0 },
744     { "disable_warning",P_DISABLEWARN,  0 },
745     { "opt_code_speed", P_OPTCODESPEED, 0 },
746     { "opt_code_size",  P_OPTCODESIZE,  0 },
747     { "opt_code_balanced",  P_OPTCODEBALANCED,  0 },
748     { "std_c89",        P_STD_C89,      0 },
749     { "std_c99",        P_STD_C99,      0 },
750     { "std_sdcc89",     P_STD_SDCC89,   0 },
751     { "std_sdcc99",     P_STD_SDCC99,   0 },
752     { "codeseg",        P_CODESEG,      0 },
753     { "constseg",       P_CONSTSEG,     0 },
754
755     /*
756      * The following lines are deprecated pragmas,
757      * only for bacward compatibility.
758      * They should be removed in next major release after 1.4.0
759      */
760
761     { "SAVE",           P_SAVE,         1 },
762     { "RESTORE",        P_RESTORE,      1 },
763     { "NOINDUCTION",    P_NOINDUCTION,  1 },
764     { "NOINVARIANT",    P_NOINVARIANT,  1 },
765     { "NOLOOPREVERSE",  P_LOOPREV,      1 },
766     { "INDUCTION",      P_INDUCTION,    1 },
767     { "STACKAUTO",      P_STACKAUTO,    1 },
768     { "NOJTBOUND",      P_NOJTBOUND,    1 },
769     { "NOGCSE",         P_NOGCSE,       1 },
770     { "NOOVERLAY",      P_NOOVERLAY,    1 },
771     { "CALLEE-SAVES",   P_CALLEE_SAVES, 1 },
772     { "EXCLUDE",        P_EXCLUDE,      1 },
773     { "NOIV",           P_NOIV,         1 },
774     { "OVERLAY",        P_OVERLAY_,     1 },
775     { "LESS_PEDANTIC",  P_LESSPEDANTIC, 1 },
776   };
777   char *cp;
778   int i;
779
780   /* find the pragma */
781   while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
782     s++;
783   s += PRAGMA_LEN;
784
785   /* look for the directive */
786   while(isspace((unsigned char)*s))
787     s++;
788
789   cp = s;
790   /* look for the end of the directive */
791   while ((!isspace((unsigned char)*s)) && (*s != '\n'))
792     s++ ;
793
794   /* skip separating whitespace */
795   while (isspace((unsigned char)*s) && (*s != '\n'))
796     s++;
797
798   /* First give the port a chance */
799   if (port->process_pragma && !port->process_pragma(cp))
800     return 0;
801
802   for (i = 0; i < NELEM(pragma_tbl); i++)
803     {
804       /* now compare and do what needs to be done */
805       size_t len = strlen(pragma_tbl[i].name);
806
807       if (strncmp(cp, pragma_tbl[i].name, len) == 0)
808         {
809           if (pragma_tbl[i].deprecated != 0)
810             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
811
812           doPragma(pragma_tbl[i].id, s);
813           return 0;
814         }
815     }
816
817   werror(W_UNKNOWN_PRAGMA, cp);
818   return 0;
819 }
820
821 /* will return 1 if the string is a part
822    of a target specific keyword */
823 static int isTargetKeyword(char *s)
824 {
825   int i;
826
827   if (port->keywords == NULL)
828     return 0;
829   
830   if (s[0] == '_' && s[1] == '_')
831     {
832       /* Keywords in the port's array have either 0 or 1 underscore, */
833       /* so skip over the appropriate number of chars when comparing */
834       for (i = 0 ; port->keywords[i] ; i++ )
835         {
836           if (port->keywords[i][0] == '_' &&
837               strcmp(port->keywords[i],s+1) == 0)
838             return 1;
839           else if (strcmp(port->keywords[i],s+2) == 0)
840             return 1;
841         }
842     }
843   else
844     {
845       for (i = 0 ; port->keywords[i] ; i++ )
846         {
847           if (strcmp(port->keywords[i],s) == 0)
848             return 1;
849         }
850     }
851
852   return 0;
853 }
854
855 int yywrap(void)
856 {
857   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
858     werror(W_SAVE_RESTORE);
859
860   return 1;
861 }
862
863 int yyerror(char *s)
864 {
865   fflush(stdout);
866
867   if (mylineno && filename) {
868     if(options.vc_err_style)
869       fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
870         filename, mylineno, s, yytext, column);
871     else
872       fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
873         filename, mylineno, s ,yytext, column);
874     fatalError++;
875   } else {
876     /* this comes from an empy file, no problem */
877   }
878   return 0;
879 }