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