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