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