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