fixed bug #825944 - defined yytext_ptr to make it compile with flex 2.5.31
[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++ ;  return('{'); }
173 "}"            { count(); NestLevel--; return('}'); }
174 ","            { count(); return(','); }
175 ":"            { count(); return(':'); }
176 "="            { count(); return('='); }
177 "("            { count(); 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 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
196 ^#pragma.*"\n"   { count(); process_pragma(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     char lineNum[10]                    ;
223     int  lNum                           ;
224     char *tptr                          ;
225        
226     /* first check if this is a #line */
227     if ( strncmp(s,"#line",5) )
228         return  0                               ;
229     
230     /* get to the line number */
231     while (!isdigit(*s))
232         s++ ;
233     tptr = lineNum ;
234     while (isdigit(*s))
235         *tptr++ = *s++ ;
236     *tptr = '\0'; 
237     sscanf(lineNum,"%d",&lNum);
238     
239     /* now see if we have a file name */
240     while (*s != '\"' && *s) 
241         s++ ;
242     
243     /* if we don't have a filename then */
244     /* set the current line number to   */
245     /* line number if printFlag is on   */
246     if (!*s) {          
247       lineno = mylineno = lNum ;
248       return 0;
249     }
250     
251     /* if we have a filename then check */
252     /* if it is "standard in" if yes then */
253     /* get the currentfile name info    */
254     s++ ;
255
256     /* in c1mode fullSrcFileName is NULL */
257     if ( fullSrcFileName &&
258          strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
259       lineno = mylineno = lNum;                                 
260       currFname = fullSrcFileName ;
261     }  else {
262         char *sb = s;
263         /* mark the end of the filename */
264         while (*s != '"') s++;
265         *s = '\0';
266         currFname = strdup (sb);
267         lineno = mylineno = lNum;
268     }
269     filename = currFname ;
270     return 0;
271 }
272     
273 int column = 0;
274 int plineIdx =0;
275
276 static void count(void)
277 {
278   int i;
279   for (i = 0; yytext[i] != '\0'; i++)   {                               
280     if (yytext[i] == '\n')      {         
281       column = 0;
282       lineno = ++mylineno ;
283     }
284     else 
285       if (yytext[i] == '\t')
286         column += 8 - (column % 8);
287       else
288         column++;
289   }
290   /* ECHO; */
291 }
292
293 static int check_type(void)
294 {
295         /* check if it is in the typedef table */
296         if (findSym(TypedefTab,NULL,yytext)) {
297                 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
298                 return (TYPE_NAME) ;
299         }
300         else   {
301                 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
302                 return(IDENTIFIER);
303         }
304 }
305
306 /*
307  * Change by JTV 2001-05-19 to not concantenate strings
308  * to support ANSI hex and octal escape sequences in string liteals 
309  */
310
311 static char *stringLiteral(void)
312 {
313 #define STR_BUF_CHUNCK_LEN  1024
314   int ch;
315   static struct dbuf_s dbuf;
316   char buf[2];
317
318   if (dbuf.alloc == 0)
319     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
320   else
321     dbuf_set_size(&dbuf, 0);
322
323
324   dbuf_append(&dbuf, "\"", 1);
325   /* put into the buffer till we hit the first \" */
326
327   while ((ch = input()) != 0) {
328     switch (ch) {
329     case '\\':
330       /* if it is a \ then escape char's are allowed */
331       ch = input();
332       if (ch == '\n') {
333         /* \<newline> is a continuator */
334         lineno = ++mylineno;
335         column = 0;
336       }
337       else {
338         buf[0] = '\\';
339         buf[1] = ch;
340         dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
341       }
342       break; /* carry on */
343
344     case '\n':
345       /* if new line we have a new line break, which is illegal */
346       werror(W_NEWLINE_IN_STRING);
347       dbuf_append(&dbuf, "\n", 1);
348       lineno = ++mylineno;
349       column = 0;
350       break;
351
352     case '"':
353       /* if this is a quote then we have work to do */
354       /* find the next non whitespace character     */
355       /* if that is a double quote then carry on    */
356       dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
357       while ((ch = input()) && (isspace(ch) || ch == '\\')) {
358         switch (ch) {
359         case '\\':
360           if ((ch = input()) != '\n') {
361             werror(W_STRAY_BACKSLASH, column);
362             unput(ch);
363           }
364           else {
365             lineno = ++mylineno;
366             column = 0;
367           }
368           break;
369
370         case '\n':
371           mylineno++;
372           break;
373         }
374       }
375
376       if (!ch) 
377         goto out;
378
379       if (ch != '\"') {
380         unput(ch) ;
381         goto out;
382       }
383       break;
384
385     default:
386       buf[0] = ch;
387       dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
388     }
389   }
390
391 out:
392   return (char *)dbuf_c_str(&dbuf);
393 }
394
395
396 enum pragma_id {
397      P_SAVE = 1,
398      P_RESTORE ,
399      P_NOINDUCTION,
400      P_NOINVARIANT,
401      P_INDUCTION ,
402      P_STACKAUTO ,
403      P_NOJTBOUND ,
404      P_NOOVERLAY ,
405      P_LESSPEDANTIC,
406      P_NOGCSE    ,
407      P_CALLEE_SAVES,
408      P_EXCLUDE   ,
409      P_NOIV      ,
410      P_LOOPREV   ,
411      P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
412                      /* cross-compiling for MINGW32 with gcc 3.2 */
413 };
414
415
416 /* SAVE/RESTORE stack */
417 #define SAVE_RESTORE_SIZE 128
418
419 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
420 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
421
422 /*
423  * cloneXxx functions should be updated every time a new set is
424  * added to the options or optimize structure!
425  */
426
427 static struct options *cloneOptions(struct options *opt)
428 {
429   struct options *new_opt;
430
431   new_opt = Safe_malloc(sizeof (struct options));
432
433   /* clone scalar values */
434   *new_opt = *opt;
435
436   /* clone sets */
437   new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
438   new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
439   /* not implemented yet: */
440   /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
441
442   return new_opt;
443 }
444
445 static struct optimize *cloneOptimize(struct optimize *opt)
446 {
447   struct optimize *new_opt;
448
449   new_opt = Safe_malloc(sizeof (struct options));
450
451   /* clone scalar values */
452   *new_opt = *opt;
453
454   return new_opt;
455 }
456
457 static void copyAndFreeOptions(struct options *dest, struct options *src)
458 {
459   /* delete dest sets */
460   deleteSet(&dest->calleeSavesSet);
461   deleteSet(&dest->excludeRegsSet);
462   /* not implemented yet: */
463   /* deleteSet(&dest->olaysSet); */
464
465   /* dopy src to dest */
466   *dest = *src;
467
468   Safe_free(src);
469 }
470
471 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
472 {
473   /* dopy src to dest */
474   *dest = *src;
475
476   Safe_free(src);
477 }
478
479 static void doPragma(int op, char *cp)
480 {
481   switch (op) {
482   case P_SAVE:
483     {
484       STACK_PUSH(options_stack, cloneOptions(&options));
485       STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
486     }
487     break;
488
489   case P_RESTORE:
490     {
491       struct options *optionsp;
492       struct optimize *optimizep;
493
494       optionsp = STACK_POP(options_stack);
495       copyAndFreeOptions(&options, optionsp);
496
497       optimizep = STACK_POP(optimize_stack);
498       copyAndFreeOptimize(&optimize, optimizep);
499     }
500     break;
501
502   case P_NOINDUCTION:
503     optimize.loopInduction = 0 ;
504     break;
505
506   case P_NOINVARIANT:
507     optimize.loopInvariant = 0 ;
508     break;
509
510   case P_INDUCTION:
511     optimize.loopInduction = 1 ;
512     break;
513
514   case P_STACKAUTO:
515     options.stackAuto = 1;
516     break;
517
518   case P_NOJTBOUND:
519     optimize.noJTabBoundary = 1;
520     break;
521
522   case P_NOGCSE:
523     optimize.global_cse = 0;
524     break;
525
526   case P_NOOVERLAY:
527     options.noOverlay = 1;
528     break;
529
530   case P_LESSPEDANTIC:
531     options.lessPedantic = 1;
532     break;
533
534   case P_CALLEE_SAVES:
535     /* append to the functions already listed
536        in callee-saves */
537     setParseWithComma(&options.calleeSavesSet, cp);
538     break;
539
540   case P_EXCLUDE:
541     {
542       deleteSet(&options.excludeRegsSet);
543       setParseWithComma(&options.excludeRegsSet, cp);
544     }
545     break;
546
547   case P_NOIV:
548     options.noiv = 1;
549     break;
550
551   case P_LOOPREV:
552     optimize.noLoopReverse = 1;
553     break;
554
555   case P_OVERLAY_:
556     break; /* notyet */
557   }
558 }
559
560 static int process_pragma(char *s)
561 {
562 #define NELEM(x)  (sizeof (x) / sizeof (x)[0])
563 #define PRAGMA    "#pragma"
564
565   static struct pragma_s {
566     const char *name;
567     enum pragma_id id;
568   } pragma_tbl[] = {
569     { "SAVE",           P_SAVE },
570     { "RESTORE",        P_RESTORE },
571     { "NOINDUCTION",    P_NOINDUCTION },
572     { "NOINVARIANT",    P_NOINVARIANT },
573     { "NOLOOPREVERSE",  P_LOOPREV },
574     { "INDUCTION",      P_INDUCTION },
575     { "STACKAUTO",      P_STACKAUTO },
576     { "NOJTBOUND",      P_NOJTBOUND },
577     { "NOGCSE",         P_NOGCSE },
578     { "NOOVERLAY",      P_NOOVERLAY },
579     { "CALLEE-SAVES",   P_CALLEE_SAVES },
580     { "EXCLUDE",        P_EXCLUDE },
581     { "NOIV",           P_NOIV },
582     { "OVERLAY",        P_OVERLAY_ },
583     { "LESS_PEDANTIC",  P_LESSPEDANTIC },
584   };
585   char *cp ;
586   int i;
587
588   /* find the pragma */
589   while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
590     s++;
591   s += (sizeof PRAGMA) - 1;
592     
593   /* look for the directive */
594   while(isspace(*s))
595     s++;
596
597   cp = s;
598   /* look for the end of the directive */
599   while ((!isspace(*s)) && (*s != '\n')) 
600     s++ ;    
601
602   /* First give the port a chance */
603   if (port->process_pragma && !port->process_pragma(cp))
604     return 0;
605
606   for (i = 0; i < NELEM(pragma_tbl); i++) {
607     /* now compare and do what needs to be done */
608     size_t len = strlen(pragma_tbl[i].name);
609
610     if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
611       doPragma(pragma_tbl[i].id, cp + len);
612       return 0;
613     }
614   }
615
616   werror(W_UNKNOWN_PRAGMA,cp);
617   return 0;
618 }
619
620 /* will return 1 if the string is a part
621    of a target specific keyword */
622 static int isTargetKeyword(char *s)
623 {
624     int i;
625     
626     if (port->keywords == NULL)
627         return 0;
628     for ( i = 0 ; port->keywords[i] ; i++ ) {
629         if (strcmp(port->keywords[i],s) == 0)
630             return 1;
631     }
632     
633     return 0;
634 }
635
636 int yywrap(void)
637 {
638   if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
639     werror(W_SAVE_RESTORE);
640
641   return 1;
642 }
643
644 int yyerror(char *s)
645 {
646    fflush(stdout);
647
648    if (mylineno && filename) {
649          if(options.vc_err_style)
650                 fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
651                         filename,mylineno,
652                         s,yytext,column);
653           else
654                 fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n",
655                         filename,mylineno,
656                         s,yytext,column);
657      fatalError++;
658    } else {
659      /* this comes from an empy file, no problem */
660    }
661    return 0;
662 }