lots of progress in AVR
[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     
38 char *stringLiteral();
39 char *currFname;
40
41 extern int lineno                       ;
42 extern char *filename ;
43 extern char *fullSrcFileName ;
44 int   yylineno = 1               ;
45 void count()                     ;
46 void comment();
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[MAX_INLINEASM]                     ;
57 char *asmp ;
58 extern int check_type           ();
59  extern int isTargetKeyword     ();
60 extern int checkCurrFile        (char *);
61 extern int processPragma        (char *);
62 extern int printListing         (int   );
63 struct optimize save_optimize ;
64 struct options  save_options  ;
65
66  enum {
67      P_SAVE = 1,
68      P_RESTORE ,
69      P_NOINDUCTION,
70      P_NOINVARIANT,
71      P_INDUCTION ,
72      P_STACKAUTO ,
73      P_NOJTBOUND ,
74      P_NOOVERLAY ,
75      P_NOGCSE    ,
76      P_CALLEE_SAVES,
77      P_EXCLUDE   ,
78      P_LOOPREV
79  };
80
81 %}
82 %x asm
83 %%
84 "_asm"        {  count(); asmp = asmbuff ;BEGIN(asm) ;}
85 <asm>"_endasm" { count()                ; 
86                   *asmp = '\0'                          ; 
87                   strcpy(yylval.yyinline,asmbuff)               ; 
88                   BEGIN(INITIAL)        ;
89                   return (INLINEASM)                    ; }
90 <asm>.         { *asmp++ = yytext[0]    ; }
91 <asm>\n        { count(); *asmp++ = '\n' ;}
92 "/*"           { comment(); }
93 "at"           { count(); TKEYWORD(AT)  ; }
94 "auto"         { count(); return(AUTO); }
95 "bit"          { count(); TKEYWORD(BIT) ; }
96 "break"        { count(); return(BREAK); }
97 "case"         { count(); return(CASE); }
98 "char"         { count(); return(CHAR); }
99 "code"         { count(); TKEYWORD(CODE); }
100 "const"        { count(); return(CONST); }
101 "continue"     { count(); return(CONTINUE); }
102 "critical"     { count(); TKEYWORD(CRITICAL); } 
103 "data"         { count(); TKEYWORD(DATA);   }
104 "default"      { count(); return(DEFAULT); }
105 "do"           { count(); return(DO); }
106 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
107 "else"         { count(); return(ELSE); }
108 "enum"         { count(); return(ENUM); }
109 "extern"       { count(); return(EXTERN); }
110 "far"          { count(); TKEYWORD(XDATA);  }
111 "eeprom"       { count(); TKEYWORD(EEPROM);  }
112 "float"        { count(); return(FLOAT); }
113 "flash"        { count(); TKEYWORD(CODE);}
114 "for"          { count(); return(FOR); }
115 "goto"         { count(); return(GOTO); }
116 "idata"        { count(); TKEYWORD(IDATA);}
117 "if"           { count(); return(IF); }
118 "int"          { count(); return(INT); }
119 "interrupt"    { count(); return(INTERRUPT);}
120 "long"         { count(); return(LONG); }
121 "near"         { count(); TKEYWORD(DATA);}
122 "pdata"        { count(); TKEYWORD(PDATA); }
123 "reentrant"    { count(); TKEYWORD(REENTRANT);}
124 "register"     { count(); return(REGISTER); }
125 "return"       { count(); return(RETURN); }
126 "sfr"          { count(); TKEYWORD(SFR) ; }
127 "sbit"         { count(); TKEYWORD(SBIT)        ; }
128 "short"        { count(); return(SHORT); }
129 "signed"       { count(); return(SIGNED); }
130 "sizeof"       { count(); return(SIZEOF); }
131 "sram"         { count(); TKEYWORD(XDATA);}
132 "static"       { count(); return(STATIC); }
133 "struct"       { count(); return(STRUCT); }
134 "switch"       { count(); return(SWITCH); }
135 "typedef"      { count(); return(TYPEDEF); }
136 "union"        { count(); return(UNION); }
137 "unsigned"     { count(); return(UNSIGNED); }
138 "void"         { count(); return(VOID); }
139 "volatile"     { count(); return(VOLATILE); }
140 "using"        { count(); TKEYWORD(USING); }
141 "while"        { count(); return(WHILE); }
142 "xdata"        { count(); TKEYWORD(XDATA); }
143 "_data"        { count(); TKEYWORD(_NEAR); }
144 "_code"        { count(); TKEYWORD(_CODE); }
145 "_eeprom"      { count(); TKEYWORD(_EEPROM); }
146 "_flash"       { count(); TKEYWORD(_CODE); }
147 "_generic"     { count(); TKEYWORD(_GENERIC); }
148 "_near"        { count(); TKEYWORD(_NEAR); }
149 "_sram"        { count(); TKEYWORD(_XDATA);}
150 "_xdata"       { count(); TKEYWORD(_XDATA);}
151 "_pdata"       { count(); TKEYWORD(_PDATA); }
152 "_idata"       { count(); TKEYWORD(_IDATA); }
153 "..."          { count(); return(VAR_ARGS);}
154 {L}({L}|{D})*  { count(); return(check_type()); }
155 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
156 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
157 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
158 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
159 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
160 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
161 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
162 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
163 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
164 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
165 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
166 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
167 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
168 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
169 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
170 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
171 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
172 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
173 ">>"           { count(); return(RIGHT_OP); }
174 "<<"           { count(); return(LEFT_OP); }
175 "++"           { count(); return(INC_OP); }
176 "--"           { count(); return(DEC_OP); }
177 "->"           { count(); return(PTR_OP); }
178 "&&"           { count(); return(AND_OP); }
179 "||"           { count(); return(OR_OP); }
180 "<="           { count(); return(LE_OP); }
181 ">="           { count(); return(GE_OP); }
182 "=="           { count(); return(EQ_OP); }
183 "!="           { count(); return(NE_OP); }
184 ";"            { count(); return(';'); }
185 "{"            { count(); NestLevel++ ;  return('{'); }
186 "}"            { count(); NestLevel--; 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 "~"            { count(); return('~'); }
198 "-"            { count(); return('-'); }
199 "+"            { count(); return('+'); }
200 "*"            { count(); return('*'); }
201 "/"            { count(); return('/'); }
202 "%"            { count(); return('%'); }
203 "<"            { count(); return('<'); }
204 ">"            { count(); return('>'); }
205 "^"            { count(); return('^'); }
206 "|"            { count(); return('|'); }
207 "?"            { count(); return('?'); }
208 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
209 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
210
211 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
212 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
213 "\r\n"             { count(); }
214 "\n"               { count(); }
215 [ \t\v\f]      { count(); }
216 .                          { count()    ; }
217 %%
218    
219 int checkCurrFile ( char *s)
220 {
221     char lineNum[10]                    ;
222     int  lNum                           ;
223     char *tptr                          ;
224        
225     /* first check if this is a #line */
226     if ( strncmp(s,"#line",5) )
227         return  0                               ;
228     
229     /* get to the line number */
230     while (!isdigit(*s))
231         s++ ;
232     tptr = lineNum ;
233     while (isdigit(*s))
234         *tptr++ = *s++ ;
235     *tptr = '\0'; 
236     sscanf(lineNum,"%d",&lNum);
237     
238     /* now see if we have a file name */
239     while (*s != '\"' && *s) 
240         s++ ;
241     
242     /* if we don't have a filename then */
243     /* set the current line number to   */
244     /* line number if printFlag is on   */
245     if (!*s) {          
246         yylineno = lNum ;
247         return 0;
248     }
249     
250     /* if we have a filename then check */
251     /* if it is "standard in" if yes then */
252     /* get the currentfile name info    */
253     s++ ;
254
255     if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
256             yylineno = lNum - 2;                                        
257             currFname = fullSrcFileName ;
258     }  else {
259         char *sb = s;
260         /* mark the end of the filename */
261         while (*s != '"') s++;
262         *s = '\0';
263         ALLOC_ATOMIC(currFname,strlen(sb)+1);
264         strcpy(currFname,sb);
265         yylineno = lNum - 2;
266     }
267     filename = currFname ;
268     return 0;
269 }
270     
271 void comment()
272 {
273         char c, c1;
274
275 loop:
276         while ((c = input()) != '*' && c != 0)
277                 if ( c == '\n')
278                         yylineno++ ;
279
280         if ((c1 = input()) != '/' && c != 0)  {
281                 if ( c1 == '\n' )
282                         yylineno++ ;
283
284                 unput(c1);
285                 goto loop;
286    }
287
288 }
289    
290    
291
292 int column = 0;
293 int plineIdx=0;
294
295 void count()
296 {
297         int i;
298         for (i = 0; yytext[i] != '\0'; i++)   {                         
299                 if (yytext[i] == '\n')      {         
300                    column = 0;
301                    lineno = ++yylineno ;
302                 }
303                 else 
304                         if (yytext[i] == '\t')
305                                 column += 8 - (column % 8);
306                         else
307                                 column++;
308    }
309          
310    /* ECHO; */
311 }
312
313 int check_type()
314 {
315         /* check if it is in the typedef table */
316         if (findSym(TypedefTab,NULL,yytext)) {
317                 strcpy(yylval.yychar,yytext);
318                 return (TYPE_NAME) ;
319         }
320         else   {
321                 strcpy (yylval.yychar,yytext);
322                 return(IDENTIFIER);
323         }
324 }
325
326 char strLitBuff[2048]                   ;
327
328 char *stringLiteral ()
329 {
330        int ch;
331        char *str = strLitBuff                   ;
332        
333        *str++ = '\"'                    ;
334        /* put into the buffer till we hit the */
335        /* first \" */
336        while (1) {
337
338           ch = input()                  ;
339           if (!ch)          break       ; /* end of input */
340           /* if it is a \ then everything allowed */
341           if (ch == '\\') {
342              *str++ = ch     ; /* backslash in place */
343              *str++ = input()           ; /* following char in place */
344              continue                   ;      /* carry on */
345              }
346              
347          /* if new line we have a new line break */
348          if (ch == '\n') break          ;
349          
350          /* if this is a quote then we have work to do */
351          /* find the next non whitespace character     */
352          /* if that is a double quote then carry on    */
353          if (ch == '\"') {
354          
355              while ((ch = input()) && isspace(ch)) ;
356              if (!ch) break             ; 
357              if (ch != '\"') {
358                   unput(ch)                     ;
359                   break                 ;
360                   }
361                   
362                   continue              ;
363         }
364         *str++  = ch;     
365      }  
366      *str++ = '\"'                      ;
367      *str = '\0';
368      return strLitBuff                  ;
369 }
370
371 void doPragma (int op, char *cp)
372 {
373     switch (op) {
374     case P_SAVE:
375         memcpy(&save_options,&options,sizeof(options));
376         memcpy(&save_optimize,&optimize,sizeof(optimize));
377         break;
378     case P_RESTORE:
379         memcpy(&options,&save_options,sizeof(options));
380         memcpy(&optimize,&save_optimize,sizeof(optimize));
381         break;
382     case P_NOINDUCTION:
383         optimize.loopInduction = 0 ;
384         break;
385     case P_NOINVARIANT:
386         optimize.loopInvariant = 0 ;
387         break;
388     case P_INDUCTION:
389         optimize.loopInduction = 1 ;
390         break;
391     case P_STACKAUTO:
392         options.stackAuto = 1;
393         break;
394     case P_NOJTBOUND:
395         optimize.noJTabBoundary = 1;
396         break;
397     case P_NOGCSE:
398         optimize.global_cse = 0;
399         break;
400     case P_NOOVERLAY:
401         options.noOverlay = 1;
402         break;
403     case P_CALLEE_SAVES:
404         {
405             int i=0;
406             /* append to the functions already listed
407                in callee-saves */
408             for (; options.calleeSaves[i] ;i++);
409             parseWithComma(&options.calleeSaves[i],strdup(cp));
410         }
411         break;
412     case P_EXCLUDE:
413         parseWithComma(options.excludeRegs,strdup(cp));
414         break;
415     case P_LOOPREV:
416         optimize.noLoopReverse = 1;
417         break;
418     }
419 }
420
421 int process_pragma(char *s)
422 {
423     char *cp ;
424     /* find the pragma */
425     while (strncmp(s,"#pragma",7))
426         s++;
427     s += 7;
428     
429     /* look for the directive */
430     while(isspace(*s)) s++;
431
432     cp = s;
433     /* look for the end of the directive */
434     while ((! isspace(*s)) && 
435            (*s != '\n')) 
436         s++ ;    
437
438     /* now compare and do what needs to be done */
439     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
440         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
441         return 0;
442     }
443
444     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
445         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
446         return 0;
447     }
448
449     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
450         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
451         return 0;
452     }
453
454     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
455         doPragma (P_NOINVARIANT,NULL)   ;
456         return 0;
457     }
458
459     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
460         doPragma (P_INDUCTION,NULL)     ;
461         return 0;
462     }
463
464     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
465         doPragma (P_STACKAUTO,NULL);
466         return 0;
467     }
468
469     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
470         doPragma (P_NOJTBOUND,NULL);
471         return 0;
472     }
473
474     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
475         doPragma (P_NOGCSE,NULL);
476         return 0;
477     }
478
479     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
480         doPragma (P_NOOVERLAY,NULL);
481         return 0;
482     }
483     
484     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
485         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
486         return 0;
487     }
488     
489     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
490         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
491         return 0;
492     }
493
494     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
495         doPragma(P_EXCLUDE,NULL);
496         return 0;
497     }
498
499     werror(W_UNKNOWN_PRAGMA,cp);
500     return 0;
501 }
502
503 /* will return 1 if the string is a part
504    of a target specific keyword */
505 int isTargetKeyword(char *s)
506 {
507     int i;
508     
509     if (port->keywords == NULL)
510         return 0;
511     for ( i = 0 ; port->keywords[i] ; i++ ) {
512         if (strcmp(port->keywords[i],s) == 0)
513             return 1;
514     }
515     
516     return 0;
517 }