* src/SDCC.lex (doPragma): added pragma disable_warning <nnn>
[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{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
144 {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 };
421
422
423 /* SAVE/RESTORE stack */
424 #define SAVE_RESTORE_SIZE 128
425
426 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
427 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
428
429 /*
430  * cloneXxx functions should be updated every time a new set is
431  * added to the options or optimize structure!
432  */
433
434 static struct options *cloneOptions(struct options *opt)
435 {
436   struct options *new_opt;
437
438   new_opt = Safe_malloc(sizeof (struct options));
439
440   /* clone scalar values */
441   *new_opt = *opt;
442
443   /* clone sets */
444   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
445   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
446   /* not implemented yet: */
447   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
448
449   return new_opt;
450 }
451
452 static struct optimize *cloneOptimize(struct optimize *opt)
453 {
454   struct optimize *new_opt;
455
456   new_opt = Safe_malloc(sizeof (struct options));
457
458   /* clone scalar values */
459   *new_opt = *opt;
460
461   return new_opt;
462 }
463
464 static void copyAndFreeOptions(struct options *dest, struct options *src)
465 {
466   /* delete dest sets */
467   deleteSet(&dest->calleeSavesSet);
468   deleteSet(&dest->excludeRegsSet);
469   /* not implemented yet: */
470   /* deleteSet(&dest->olaysSet); */
471
472   /* dopy src to dest */
473   *dest = *src;
474
475   Safe_free(src);
476 }
477
478 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
479 {
480   /* dopy src to dest */
481   *dest = *src;
482
483   Safe_free(src);
484 }
485
486 static void doPragma(int op, char *cp)
487 {
488   int i;
489
490   switch (op) {
491   case P_SAVE:
492     {
493       STACK_PUSH(options_stack, cloneOptions(&options));
494       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
495     }
496     break;
497
498   case P_RESTORE:
499     {
500       struct options *optionsp;
501       struct optimize *optimizep;
502
503       optionsp = STACK_POP(options_stack);
504       copyAndFreeOptions(&options, optionsp);
505
506       optimizep = STACK_POP(optimize_stack);
507       copyAndFreeOptimize(&optimize, optimizep);
508     }
509     break;
510
511   case P_NOINDUCTION:
512     optimize.loopInduction = 0;
513     break;
514
515   case P_NOINVARIANT:
516     optimize.loopInvariant = 0;
517     break;
518
519   case P_INDUCTION:
520     optimize.loopInduction = 1;
521     break;
522
523   case P_STACKAUTO:
524     options.stackAuto = 1;
525     break;
526
527   case P_NOJTBOUND:
528     optimize.noJTabBoundary = 1;
529     break;
530
531   case P_NOGCSE:
532     optimize.global_cse = 0;
533     break;
534
535   case P_NOOVERLAY:
536     options.noOverlay = 1;
537     break;
538
539   case P_LESSPEDANTIC:
540     options.lessPedantic = 1;
541     break;
542
543   case P_CALLEE_SAVES:
544     /* append to the functions already listed
545        in callee-saves */
546     setParseWithComma(&options.calleeSavesSet, cp);
547     break;
548
549   case P_EXCLUDE:
550     {
551       deleteSet(&options.excludeRegsSet);
552       setParseWithComma(&options.excludeRegsSet, cp);
553     }
554     break;
555
556   case P_NOIV:
557     options.noiv = 1;
558     break;
559
560   case P_LOOPREV:
561     optimize.noLoopReverse = 1;
562     break;
563
564   case P_OVERLAY_:
565     break; /* notyet */
566
567   case P_DISABLEWARN:
568     if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
569       {
570         setWarningDisabled(i);
571       }
572     break;
573   }
574 }
575
576 static int process_pragma(char *s)
577 {
578 #define NELEM(x)    (sizeof (x) / sizeof (x)[0])
579 #define PRAGMA_STR  "#pragma"
580 #define PRAGMA_LEN  ((sizeof PRAGMA_STR) - 1)
581
582   static struct pragma_s
583     {
584       const char *name;
585       enum pragma_id id;
586       char deprecated;
587     } pragma_tbl[] = {
588     { "save",           P_SAVE,         0 },
589     { "restore",        P_RESTORE,      0 },
590     { "noinduction",    P_NOINDUCTION,  0 },
591     { "noinvariant",    P_NOINVARIANT,  0 },
592     { "noloopreverse",  P_LOOPREV,      0 },
593     { "induction",      P_INDUCTION,    0 },
594     { "stackauto",      P_STACKAUTO,    0 },
595     { "nojtbound",      P_NOJTBOUND,    0 },
596     { "nogcse",         P_NOGCSE,       0 },
597     { "nooverlay",      P_NOOVERLAY,    0 },
598     { "callee_saves",   P_CALLEE_SAVES, 0 },
599     { "exclude",        P_EXCLUDE,      0 },
600     { "noiv",           P_NOIV,         0 },
601     { "overlay",        P_OVERLAY_,     0 },
602     { "less_pedantic",  P_LESSPEDANTIC, 0 },
603     { "disable_warning",P_DISABLEWARN,  0 },
604
605     /*
606      * The following lines are deprecated pragmas,
607      * only for bacward compatibility.
608      * They should be removed in next major release after 1.4.0
609      */
610
611     { "SAVE",           P_SAVE,         1 },
612     { "RESTORE",        P_RESTORE,      1 },
613     { "NOINDUCTION",    P_NOINDUCTION,  1 },
614     { "NOINVARIANT",    P_NOINVARIANT,  1 },
615     { "NOLOOPREVERSE",  P_LOOPREV,      1 },
616     { "INDUCTION",      P_INDUCTION,    1 },
617     { "STACKAUTO",      P_STACKAUTO,    1 },
618     { "NOJTBOUND",      P_NOJTBOUND,    1 },
619     { "NOGCSE",         P_NOGCSE,       1 },
620     { "NOOVERLAY",      P_NOOVERLAY,    1 },
621     { "CALLEE-SAVES",   P_CALLEE_SAVES, 1 },
622     { "EXCLUDE",        P_EXCLUDE,      1 },
623     { "NOIV",           P_NOIV,         1 },
624     { "OVERLAY",        P_OVERLAY_,     1 },
625     { "LESS_PEDANTIC",  P_LESSPEDANTIC, 1 },
626   };
627   char *cp;
628   int i;
629
630   /* find the pragma */
631   while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
632     s++;
633   s += PRAGMA_LEN;
634
635   /* look for the directive */
636   while(isspace(*s))
637     s++;
638
639   cp = s;
640   /* look for the end of the directive */
641   while ((!isspace(*s)) && (*s != '\n'))
642     s++ ;
643
644   /* First give the port a chance */
645   if (port->process_pragma && !port->process_pragma(cp))
646     return 0;
647
648   for (i = 0; i < NELEM(pragma_tbl); i++)
649     {
650       /* now compare and do what needs to be done */
651       size_t len = strlen(pragma_tbl[i].name);
652
653       if (strncmp(cp, pragma_tbl[i].name, len) == 0)
654         {
655           if (pragma_tbl[i].deprecated != 0)
656             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
657
658           doPragma(pragma_tbl[i].id, cp + len);
659           return 0;
660         }
661     }
662
663   werror(W_UNKNOWN_PRAGMA, cp);
664   return 0;
665 }
666
667 /* will return 1 if the string is a part
668    of a target specific keyword */
669 static int isTargetKeyword(char *s)
670 {
671   int i;
672
673   if (port->keywords == NULL)
674     return 0;
675   for (i = 0 ; port->keywords[i] ; i++ ) {
676     if (strcmp(port->keywords[i],s) == 0)
677       return 1;
678   }
679
680     return 0;
681 }
682
683 int yywrap(void)
684 {
685   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
686     werror(W_SAVE_RESTORE);
687
688   return 1;
689 }
690
691 int yyerror(char *s)
692 {
693   fflush(stdout);
694
695   if (mylineno && filename) {
696     if(options.vc_err_style)
697       fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
698         filename, mylineno, s, yytext, column);
699     else
700       fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
701         filename, mylineno, s ,yytext, column);
702     fatalError++;
703   } else {
704     /* this comes from an empy file, no problem */
705   }
706   return 0;
707 }