create/append dump files on a per session base
[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                       ;
43 extern char *filename ;
44 extern char *fullSrcFileName ;
45 int   yylineno = 1               ;
46 void count()                     ;
47 void comment();
48 int process_pragma(char *);
49 #undef yywrap
50
51 int yywrap YY_PROTO((void))
52 {
53    return(1);
54 }
55 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
56                                 check_type(yytext))
57 char *asmbuff=NULL;
58 int asmbuffSize=0;
59 char *asmp ;
60 extern int check_type           ();
61  extern int isTargetKeyword     ();
62 extern int checkCurrFile        (char *);
63 extern int processPragma        (char *);
64 extern int printListing         (int   );
65 struct optimize save_optimize ;
66 struct options  save_options  ;
67
68  enum {
69      P_SAVE = 1,
70      P_RESTORE ,
71      P_NOINDUCTION,
72      P_NOINVARIANT,
73      P_INDUCTION ,
74      P_STACKAUTO ,
75      P_NOJTBOUND ,
76      P_NOOVERLAY ,
77      P_NOGCSE    ,
78      P_CALLEE_SAVES,
79      P_EXCLUDE   ,
80      P_LOOPREV
81  };
82
83 %}
84 %x asm
85 %%
86 "_asm"         {  
87   count(); 
88   asmp = asmbuff = Safe_realloc (asmbuff, INITIAL_INLINEASM);
89   asmbuffSize=INITIAL_INLINEASM;
90   BEGIN(asm) ;
91 }
92 <asm>"_endasm" { 
93   count();
94   *asmp = '\0';
95   yylval.yyinline = Safe_calloc (1, 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     asmbuffSize=asmbuffSize*3/2;
104     asmbuff = Safe_realloc (asmbuff, asmbuffSize); 
105   }
106   *asmp++ = yytext[0];
107 }
108 <asm>\n        { 
109   count(); 
110   if (asmp-asmbuff >= asmbuffSize-3) {
111     // increase the buffersize with 50%
112     asmbuffSize=asmbuffSize*3/2;
113     asmbuff = Safe_realloc (asmbuff, asmbuffSize); 
114   }
115   *asmp++ = '\n' ;
116 }
117 "/*"           { comment(); }
118 "at"           { count(); TKEYWORD(AT)  ; }
119 "auto"         { count(); return(AUTO); }
120 "bit"          { count(); TKEYWORD(BIT) ; }
121 "break"        { count(); return(BREAK); }
122 "case"         { count(); return(CASE); }
123 "char"         { count(); return(CHAR); }
124 "code"         { count(); TKEYWORD(CODE); }
125 "const"        { count(); return(CONST); }
126 "continue"     { count(); return(CONTINUE); }
127 "critical"     { count(); TKEYWORD(CRITICAL); } 
128 "data"         { count(); TKEYWORD(DATA);   }
129 "default"      { count(); return(DEFAULT); }
130 "do"           { count(); return(DO); }
131 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
132 "else"         { count(); return(ELSE); }
133 "enum"         { count(); return(ENUM); }
134 "extern"       { count(); return(EXTERN); }
135 "far"          { count(); TKEYWORD(XDATA);  }
136 "eeprom"       { count(); TKEYWORD(EEPROM);  }
137 "float"        { count(); return(FLOAT); }
138 "flash"        { count(); TKEYWORD(CODE);}
139 "for"          { count(); return(FOR); }
140 "goto"         { count(); return(GOTO); }
141 "idata"        { count(); TKEYWORD(IDATA);}
142 "if"           { count(); return(IF); }
143 "int"          { count(); return(INT); }
144 "interrupt"    { count(); return(INTERRUPT);}
145 "nonbanked"    { count(); TKEYWORD(NONBANKED);}
146 "banked"       { count(); TKEYWORD(BANKED);}
147 "long"         { count(); return(LONG); }
148 "near"         { count(); TKEYWORD(DATA);}
149 "pdata"        { count(); TKEYWORD(PDATA); }
150 "reentrant"    { count(); TKEYWORD(REENTRANT);}
151 "register"     { count(); return(REGISTER); }
152 "return"       { count(); return(RETURN); }
153 "sfr"          { count(); TKEYWORD(SFR) ; }
154 "sbit"         { count(); TKEYWORD(SBIT)        ; }
155 "short"        { count(); return(SHORT); }
156 "signed"       { count(); return(SIGNED); }
157 "sizeof"       { count(); return(SIZEOF); }
158 "sram"         { count(); TKEYWORD(XDATA);}
159 "static"       { count(); return(STATIC); }
160 "struct"       { count(); return(STRUCT); }
161 "switch"       { count(); return(SWITCH); }
162 "typedef"      { count(); return(TYPEDEF); }
163 "union"        { count(); return(UNION); }
164 "unsigned"     { count(); return(UNSIGNED); }
165 "void"         { count(); return(VOID); }
166 "volatile"     { count(); return(VOLATILE); }
167 "using"        { count(); TKEYWORD(USING); }
168 "while"        { count(); return(WHILE); }
169 "xdata"        { count(); TKEYWORD(XDATA); }
170 "_data"        { count(); TKEYWORD(_NEAR); }
171 "_code"        { count(); TKEYWORD(_CODE); }
172 "_eeprom"      { count(); TKEYWORD(_EEPROM); }
173 "_flash"       { count(); TKEYWORD(_CODE); }
174 "_generic"     { count(); TKEYWORD(_GENERIC); }
175 "_near"        { count(); TKEYWORD(_NEAR); }
176 "_sram"        { count(); TKEYWORD(_XDATA);}
177 "_xdata"       { count(); TKEYWORD(_XDATA);}
178 "_pdata"       { count(); TKEYWORD(_PDATA); }
179 "_idata"       { count(); TKEYWORD(_IDATA); }
180 "..."          { count(); return(VAR_ARGS);}
181 {L}({L}|{D})*  { count(); return(check_type()); }
182 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
183 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
184 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
185 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
186 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
187 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
188 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
189 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
190 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
191 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
192 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
193 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
194 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
195 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
196 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
197 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
198 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
199 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
200 ">>"           { count(); return(RIGHT_OP); }
201 "<<"           { count(); return(LEFT_OP); }
202 "++"           { count(); return(INC_OP); }
203 "--"           { count(); return(DEC_OP); }
204 "->"           { count(); return(PTR_OP); }
205 "&&"           { count(); return(AND_OP); }
206 "||"           { count(); return(OR_OP); }
207 "<="           { count(); return(LE_OP); }
208 ">="           { count(); return(GE_OP); }
209 "=="           { count(); return(EQ_OP); }
210 "!="           { count(); return(NE_OP); }
211 ";"            { count(); return(';'); }
212 "{"            { count(); NestLevel++ ;  return('{'); }
213 "}"            { count(); NestLevel--; 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 "|"            { count(); return('|'); }
234 "?"            { count(); return('?'); }
235 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
236 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
237
238 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
239 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
240 "\r\n"             { count(); }
241 "\n"               { count(); }
242 [ \t\v\f]      { count(); }
243 .                          { count()    ; }
244 %%
245    
246 int checkCurrFile ( char *s)
247 {
248     char lineNum[10]                    ;
249     int  lNum                           ;
250     char *tptr                          ;
251        
252     /* first check if this is a #line */
253     if ( strncmp(s,"#line",5) )
254         return  0                               ;
255     
256     /* get to the line number */
257     while (!isdigit(*s))
258         s++ ;
259     tptr = lineNum ;
260     while (isdigit(*s))
261         *tptr++ = *s++ ;
262     *tptr = '\0'; 
263     sscanf(lineNum,"%d",&lNum);
264     
265     /* now see if we have a file name */
266     while (*s != '\"' && *s) 
267         s++ ;
268     
269     /* if we don't have a filename then */
270     /* set the current line number to   */
271     /* line number if printFlag is on   */
272     if (!*s) {          
273         yylineno = lNum ;
274         return 0;
275     }
276     
277     /* if we have a filename then check */
278     /* if it is "standard in" if yes then */
279     /* get the currentfile name info    */
280     s++ ;
281
282     if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
283             yylineno = lNum - 2;                                        
284             currFname = fullSrcFileName ;
285     }  else {
286         char *sb = s;
287         /* mark the end of the filename */
288         while (*s != '"') s++;
289         *s = '\0';
290         currFname = Safe_calloc(1,strlen(sb)+1);
291         strcpy(currFname,sb);
292         yylineno = lNum - 2;
293     }
294     filename = currFname ;
295     return 0;
296 }
297     
298 void comment()
299 {
300         char c, c1;
301
302 loop:
303         while ((c = input()) != '*' && c != 0)
304                 if ( c == '\n')
305                         yylineno++ ;
306
307         if ((c1 = input()) != '/' && c != 0)  {
308                 if ( c1 == '\n' )
309                         yylineno++ ;
310
311                 unput(c1);
312                 goto loop;
313    }
314
315 }
316    
317    
318
319 int column = 0;
320 int plineIdx=0;
321
322 void count()
323 {
324         int i;
325         for (i = 0; yytext[i] != '\0'; i++)   {                         
326                 if (yytext[i] == '\n')      {         
327                    column = 0;
328                    lineno = ++yylineno ;
329                 }
330                 else 
331                         if (yytext[i] == '\t')
332                                 column += 8 - (column % 8);
333                         else
334                                 column++;
335    }
336          
337    /* ECHO; */
338 }
339
340 int check_type()
341 {
342         /* check if it is in the typedef table */
343         if (findSym(TypedefTab,NULL,yytext)) {
344                 strcpy(yylval.yychar,yytext);
345                 return (TYPE_NAME) ;
346         }
347         else   {
348                 strcpy (yylval.yychar,yytext);
349                 return(IDENTIFIER);
350         }
351 }
352
353 char strLitBuff[2048]                   ;
354
355 /*
356  * Change by JTV 2001-05-19 to not concantenate strings
357  * to support ANSI hex and octal escape sequences in string liteals 
358  */
359
360 char *stringLiteral ()
361
362 {
363 int ch;
364 char *str = strLitBuff                  ;
365
366 *str++ = '\"'                   ;
367 /* put into the buffer till we hit the */
368 /* first \" */
369
370 while (1) 
371   {
372   ch = input()                  ;
373
374   if (!ch)
375     break       ; /* end of input */
376
377   /* if it is a \ then everything allowed */
378
379   if (ch == '\\') 
380     {
381     *str++ = ch     ; /* backslash in place */
382     *str++ = input()            ; /* following char in place */
383     continue                    ;      /* carry on */
384     }
385
386   /* if new line we have a new line break */
387   if (ch == '\n') 
388     break               ;
389
390   /* if this is a quote then we have work to do */
391   /* find the next non whitespace character     */
392   /* if that is a double quote then carry on    */
393
394   if (ch == '\"') 
395     {
396     *str++  = ch ;      /* Pass end of this string or substring to evaluator */
397
398     while ((ch = input()) && isspace(ch)) ;
399
400     if (!ch) 
401       break ; 
402
403     if (ch != '\"') 
404       {
405       unput(ch) ;
406       break ;
407       }
408     }
409
410   *str++  = ch;       /* Put next substring introducer into output string */
411   }  
412
413 *str = '\0';
414
415 return strLitBuff                       ;
416 }
417
418 void doPragma (int op, char *cp)
419 {
420     switch (op) {
421     case P_SAVE:
422         memcpy(&save_options,&options,sizeof(options));
423         memcpy(&save_optimize,&optimize,sizeof(optimize));
424         break;
425     case P_RESTORE:
426         memcpy(&options,&save_options,sizeof(options));
427         memcpy(&optimize,&save_optimize,sizeof(optimize));
428         break;
429     case P_NOINDUCTION:
430         optimize.loopInduction = 0 ;
431         break;
432     case P_NOINVARIANT:
433         optimize.loopInvariant = 0 ;
434         break;
435     case P_INDUCTION:
436         optimize.loopInduction = 1 ;
437         break;
438     case P_STACKAUTO:
439         options.stackAuto = 1;
440         break;
441     case P_NOJTBOUND:
442         optimize.noJTabBoundary = 1;
443         break;
444     case P_NOGCSE:
445         optimize.global_cse = 0;
446         break;
447     case P_NOOVERLAY:
448         options.noOverlay = 1;
449         break;
450     case P_CALLEE_SAVES:
451         {
452             int i=0;
453             /* append to the functions already listed
454                in callee-saves */
455             for (; options.calleeSaves[i] ;i++);
456             parseWithComma(&options.calleeSaves[i],strdup(cp));
457         }
458         break;
459     case P_EXCLUDE:
460         parseWithComma(options.excludeRegs,strdup(cp));
461         break;
462     case P_LOOPREV:
463         optimize.noLoopReverse = 1;
464         break;
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_EXCLUDE,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 }