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