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