* src/ds390/gen.c: fix deps by replacing <common.h> with "common.h"
[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     
39 char *stringLiteral();
40 char *currFname;
41
42 extern int lineno, column;
43 extern char *filename ;
44 extern char *fullSrcFileName ;
45 int   yylineno = 1               ;
46 void count()                     ;
47 int process_pragma(char *);
48 #undef yywrap
49
50 int yywrap YY_PROTO((void))
51 {
52    return(1);
53 }
54 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
55                                 check_type(yytext))
56 char *asmbuff=NULL;
57 int asmbuffSize=0;
58 char *asmp ;
59 extern int check_type           ();
60  extern int isTargetKeyword     ();
61 extern int checkCurrFile        (char *);
62 extern int processPragma        (char *);
63 extern int printListing         (int   );
64 struct optimize save_optimize ;
65 struct options  save_options  ;
66
67  enum {
68      P_SAVE = 1,
69      P_RESTORE ,
70      P_NOINDUCTION,
71      P_NOINVARIANT,
72      P_INDUCTION ,
73      P_STACKAUTO ,
74      P_NOJTBOUND ,
75      P_NOOVERLAY ,
76      P_NOGCSE    ,
77      P_CALLEE_SAVES,
78      P_EXCLUDE   ,
79      P_LOOPREV   ,
80      P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
81                      /* cross-compiling for MINGW32 with gcc 3.2 */
82  };
83
84 %}
85 %x asm
86 %%
87 "_asm"         {  
88   count(); 
89   asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
90   asmbuffSize=INITIAL_INLINEASM;
91   BEGIN(asm) ;
92 }
93 <asm>"_endasm" { 
94   count();
95   *asmp = '\0';
96   yylval.yyinline = malloc (strlen(asmbuff)+1);
97   strcpy(yylval.yyinline,asmbuff);
98   BEGIN(INITIAL);
99   return (INLINEASM);
100 }
101 <asm>.         { 
102   if (asmp-asmbuff >= asmbuffSize-2) {
103     // increase the buffersize with 50%
104     int size=asmp-asmbuff;
105     asmbuffSize=asmbuffSize*3/2;
106     asmbuff = realloc (asmbuff, asmbuffSize); 
107     asmp=asmbuff+size;
108   }
109   *asmp++ = yytext[0];
110 }
111 <asm>\n        { 
112   count(); 
113   if (asmp-asmbuff >= asmbuffSize-3) {
114     // increase the buffersize with 50%
115     int size=asmp-asmbuff;
116     asmbuffSize=asmbuffSize*3/2;
117     asmbuff = realloc (asmbuff, asmbuffSize); 
118     asmp=asmbuff+size;
119   }
120   *asmp++ = '\n' ;
121 }
122 "at"           { count(); TKEYWORD(AT)  ; }
123 "auto"         { count(); return(AUTO); }
124 "bit"          { count(); TKEYWORD(BIT) ; }
125 "break"        { count(); return(BREAK); }
126 "case"         { count(); return(CASE); }
127 "char"         { count(); return(CHAR); }
128 "code"         { count(); TKEYWORD(CODE); }
129 "const"        { count(); return(CONST); }
130 "continue"     { count(); return(CONTINUE); }
131 "critical"     { count(); TKEYWORD(CRITICAL); } 
132 "data"         { count(); TKEYWORD(DATA);   }
133 "default"      { count(); return(DEFAULT); }
134 "do"           { count(); return(DO); }
135 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
136 "else"         { count(); return(ELSE); }
137 "enum"         { count(); return(ENUM); }
138 "extern"       { count(); return(EXTERN); }
139 "far"          { count(); TKEYWORD(XDATA);  }
140 "eeprom"       { count(); TKEYWORD(EEPROM);  }
141 "float"        { count(); return(FLOAT); }
142 "flash"        { count(); TKEYWORD(CODE);}
143 "for"          { count(); return(FOR); }
144 "goto"         { count(); return(GOTO); }
145 "idata"        { count(); TKEYWORD(IDATA);}
146 "if"           { count(); return(IF); }
147 "int"          { count(); return(INT); }
148 "interrupt"    { count(); return(INTERRUPT);}
149 "nonbanked"    { count(); TKEYWORD(NONBANKED);}
150 "banked"       { count(); TKEYWORD(BANKED);}
151 "long"         { count(); return(LONG); }
152 "near"         { count(); TKEYWORD(DATA);}
153 "pdata"        { count(); TKEYWORD(PDATA); }
154 "reentrant"    { count(); TKEYWORD(REENTRANT);}
155 "register"     { count(); return(REGISTER); }
156 "return"       { count(); return(RETURN); }
157 "sfr"          { count(); TKEYWORD(SFR) ; }
158 "sbit"         { count(); TKEYWORD(SBIT)        ; }
159 "short"        { count(); return(SHORT); }
160 "signed"       { count(); return(SIGNED); }
161 "sizeof"       { count(); return(SIZEOF); }
162 "sram"         { count(); TKEYWORD(XDATA);}
163 "static"       { count(); return(STATIC); }
164 "struct"       { count(); return(STRUCT); }
165 "switch"       { count(); return(SWITCH); }
166 "typedef"      { count(); return(TYPEDEF); }
167 "union"        { count(); return(UNION); }
168 "unsigned"     { count(); return(UNSIGNED); }
169 "void"         { count(); return(VOID); }
170 "volatile"     { count(); return(VOLATILE); }
171 "using"        { count(); TKEYWORD(USING); }
172 "_naked"       { count(); TKEYWORD(NAKED); }
173 "while"        { count(); return(WHILE); }
174 "xdata"        { count(); TKEYWORD(XDATA); }
175 "..."          { count(); return(VAR_ARGS);}
176 "__typeof"     { count(); return TYPEOF;}
177 "_JavaNative"  { count(); TKEYWORD(JAVANATIVE);}
178 "_overlay"     { count(); TKEYWORD(OVERLAY);}
179 {L}({L}|{D})*  { count(); return(check_type()); }
180 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
181 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
182 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
183 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
184 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
185 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
186 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
187 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
188 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
189 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
190 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
191 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
192 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
193 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
194 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
195 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
196 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
197 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
198 ">>"           { count(); return(RIGHT_OP); }
199 "<<"           { count(); return(LEFT_OP); }
200 "++"           { count(); return(INC_OP); }
201 "--"           { count(); return(DEC_OP); }
202 "->"           { count(); return(PTR_OP); }
203 "&&"           { count(); return(AND_OP); }
204 "||"           { count(); return(OR_OP); }
205 "<="           { count(); return(LE_OP); }
206 ">="           { count(); return(GE_OP); }
207 "=="           { count(); return(EQ_OP); }
208 "!="           { count(); return(NE_OP); }
209 ";"            { count(); return(';'); }
210 "{"            { count(); NestLevel++ ;  return('{'); }
211 "}"            { count(); NestLevel--; return('}'); }
212 ","            { count(); return(','); }
213 ":"            { count(); return(':'); }
214 "="            { count(); return('='); }
215 "("            { count(); return('('); }
216 ")"            { count(); return(')'); }
217 "["            { count(); return('['); }
218 "]"            { count(); return(']'); }
219 "."            { count(); return('.'); }
220 "&"            { count(); return('&'); }
221 "!"            { count(); return('!'); }
222 "~"            { count(); return('~'); }
223 "-"            { count(); return('-'); }
224 "+"            { count(); return('+'); }
225 "*"            { count(); return('*'); }
226 "/"            { count(); return('/'); }
227 "%"            { count(); return('%'); }
228 "<"            { count(); return('<'); }
229 ">"            { count(); return('>'); }
230 "^"            { count(); return('^'); }
231 "|"            { count(); return('|'); }
232 "?"            { count(); return('?'); }
233 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
234 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
235
236 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
237 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
238 "\r\n"             { count(); }
239 "\n"               { count(); }
240 [ \t\v\f]      { count(); }
241 \\ {
242   char ch=input();
243   if (ch!='\n') {
244     // that could have been removed by the preprocessor anyway
245     werror (W_STRAY_BACKSLASH, column);
246     unput(ch);
247   }
248 }
249 .                          { count()    ; }
250 %%
251
252 int checkCurrFile ( char *s)
253 {
254     char lineNum[10]                    ;
255     int  lNum                           ;
256     char *tptr                          ;
257        
258     /* first check if this is a #line */
259     if ( strncmp(s,"#line",5) )
260         return  0                               ;
261     
262     /* get to the line number */
263     while (!isdigit(*s))
264         s++ ;
265     tptr = lineNum ;
266     while (isdigit(*s))
267         *tptr++ = *s++ ;
268     *tptr = '\0'; 
269     sscanf(lineNum,"%d",&lNum);
270     
271     /* now see if we have a file name */
272     while (*s != '\"' && *s) 
273         s++ ;
274     
275     /* if we don't have a filename then */
276     /* set the current line number to   */
277     /* line number if printFlag is on   */
278     if (!*s) {          
279       lineno = yylineno = lNum ;
280       return 0;
281     }
282     
283     /* if we have a filename then check */
284     /* if it is "standard in" if yes then */
285     /* get the currentfile name info    */
286     s++ ;
287
288     if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
289       lineno = yylineno = lNum;                                 
290       currFname = fullSrcFileName ;
291     }  else {
292         char *sb = s;
293         /* mark the end of the filename */
294         while (*s != '"') s++;
295         *s = '\0';
296         currFname = malloc (strlen(sb)+1);
297         strcpy(currFname,sb);
298         lineno = yylineno = lNum;
299     }
300     filename = currFname ;
301     return 0;
302 }
303     
304 int column = 0;
305 int plineIdx=0;
306
307 void count()
308 {
309   int i;
310   for (i = 0; yytext[i] != '\0'; i++)   {                               
311     if (yytext[i] == '\n')      {         
312       column = 0;
313       lineno = ++yylineno ;
314     }
315     else 
316       if (yytext[i] == '\t')
317         column += 8 - (column % 8);
318       else
319         column++;
320   }
321   /* ECHO; */
322 }
323
324 int check_type()
325 {
326         /* check if it is in the typedef table */
327         if (findSym(TypedefTab,NULL,yytext)) {
328                 strcpy(yylval.yychar,yytext);
329                 return (TYPE_NAME) ;
330         }
331         else   {
332                 strcpy (yylval.yychar,yytext);
333                 return(IDENTIFIER);
334         }
335 }
336
337 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
338
339 /*
340  * Change by JTV 2001-05-19 to not concantenate strings
341  * to support ANSI hex and octal escape sequences in string liteals 
342  */
343
344 char *stringLiteral () {
345   int ch;
346   char *str = strLitBuff;
347   
348   *str++ = '\"';
349   /* put into the buffer till we hit the first \" */
350   
351   while (1) {
352     ch = input();
353     
354     if (!ch)
355       break; /* end of input */
356     
357     /* if it is a \ then escape char's are allowed */
358     if (ch == '\\') {
359       ch=input();
360       if (ch=='\n') {
361         /* \<newline> is a continuator */
362         lineno=++yylineno;
363         column=0;
364         continue;
365       }
366       *str++ = '\\'; /* backslash in place */
367       *str++ = ch; /* get the escape char, no further check */
368       continue; /* carry on */
369     }
370     
371     /* if new line we have a new line break, which is illegal */
372     if (ch == '\n') {
373       werror (W_NEWLINE_IN_STRING);
374       *str++ = '\n';
375       lineno=++yylineno;
376       column=0;
377       continue;
378     }
379     
380     /* if this is a quote then we have work to do */
381     /* find the next non whitespace character     */
382     /* if that is a double quote then carry on    */
383     if (ch == '\"') {
384       *str++  = ch ; /* Pass end of this string or substring to evaluator */
385       while ((ch = input()) && (isspace(ch) || ch=='\\')) {
386         switch (ch) {
387         case '\\':
388           if ((ch=input())!='\n') {
389             werror (W_STRAY_BACKSLASH, column);
390             unput(ch);
391           } else {
392             lineno=++yylineno;
393             column=0;
394           }
395           break;
396         case '\n':
397           yylineno++;
398           break;
399         }
400       }
401
402       if (!ch) 
403         break; 
404
405       if (ch != '\"') {
406         unput(ch) ;
407         break ;
408       }
409     }
410     *str++  = ch; /* Put next substring introducer into output string */
411   }  
412   *str = '\0';
413   
414   return strLitBuff;
415 }
416
417 void doPragma (int op, char *cp)
418 {
419     switch (op) {
420     case P_SAVE:
421         memcpy(&save_options,&options,sizeof(options));
422         memcpy(&save_optimize,&optimize,sizeof(optimize));
423         break;
424     case P_RESTORE:
425         memcpy(&options,&save_options,sizeof(options));
426         memcpy(&optimize,&save_optimize,sizeof(optimize));
427         break;
428     case P_NOINDUCTION:
429         optimize.loopInduction = 0 ;
430         break;
431     case P_NOINVARIANT:
432         optimize.loopInvariant = 0 ;
433         break;
434     case P_INDUCTION:
435         optimize.loopInduction = 1 ;
436         break;
437     case P_STACKAUTO:
438         options.stackAuto = 1;
439         break;
440     case P_NOJTBOUND:
441         optimize.noJTabBoundary = 1;
442         break;
443     case P_NOGCSE:
444         optimize.global_cse = 0;
445         break;
446     case P_NOOVERLAY:
447         options.noOverlay = 1;
448         break;
449     case P_CALLEE_SAVES:
450         {
451             int i=0;
452             /* append to the functions already listed
453                in callee-saves */
454             for (; options.calleeSaves[i] ;i++);
455             parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
456         }
457         break;
458     case P_EXCLUDE:
459         parseWithComma(options.excludeRegs, Safe_strdup(cp));
460         break;
461     case P_LOOPREV:
462         optimize.noLoopReverse = 1;
463         break;
464     case P_OVERLAY_:
465         break; /* notyet */
466     }
467 }
468
469 int process_pragma(char *s)
470 {
471     char *cp ;
472     /* find the pragma */
473     while (strncmp(s,"#pragma",7))
474         s++;
475     s += 7;
476     
477     /* look for the directive */
478     while(isspace(*s)) s++;
479
480     cp = s;
481     /* look for the end of the directive */
482     while ((! isspace(*s)) && 
483            (*s != '\n')) 
484         s++ ;    
485
486     /* First give the port a chance */
487     if (port->process_pragma && !port->process_pragma(cp))
488         return 0;
489
490     /* now compare and do what needs to be done */
491     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
492         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
493         return 0;
494     }
495
496     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
497         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
498         return 0;
499     }
500
501     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
502         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
503         return 0;
504     }
505
506     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
507         doPragma (P_NOINVARIANT,NULL)   ;
508         return 0;
509     }
510
511     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
512         doPragma (P_INDUCTION,NULL)     ;
513         return 0;
514     }
515
516     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
517         doPragma (P_STACKAUTO,NULL);
518         return 0;
519     }
520
521     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
522         doPragma (P_NOJTBOUND,NULL);
523         return 0;
524     }
525
526     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
527         doPragma (P_NOGCSE,NULL);
528         return 0;
529     }
530
531     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
532         doPragma (P_NOOVERLAY,NULL);
533         return 0;
534     }
535     
536     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
537         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
538         return 0;
539     }
540     
541     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
542         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
543         return 0;
544     }
545
546     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
547         doPragma(P_LOOPREV,NULL);
548         return 0;
549     }
550
551     werror(W_UNKNOWN_PRAGMA,cp);
552     return 0;
553 }
554
555 /* will return 1 if the string is a part
556    of a target specific keyword */
557 int isTargetKeyword(char *s)
558 {
559     int i;
560     
561     if (port->keywords == NULL)
562         return 0;
563     for ( i = 0 ; port->keywords[i] ; i++ ) {
564         if (strcmp(port->keywords[i],s) == 0)
565             return 1;
566     }
567     
568     return 0;
569 }
570
571 extern int fatalError;
572
573 int yyerror(char *s)
574 {
575    fflush(stdout);
576
577    if (yylineno && filename) {
578      fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
579              filename,yylineno,
580              s,yytext,column);
581      fatalError++;
582    } else {
583      // this comes from an empy file, no problem
584    }
585    return 0;
586 }