* Added z80 blurb.
[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     /* First give the port a chance */
439     if (port->process_pragma && !port->process_pragma(cp))
440         return 0;
441
442     /* now compare and do what needs to be done */
443     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
444         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
445         return 0;
446     }
447
448     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
449         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
450         return 0;
451     }
452
453     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
454         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
455         return 0;
456     }
457
458     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
459         doPragma (P_NOINVARIANT,NULL)   ;
460         return 0;
461     }
462
463     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
464         doPragma (P_INDUCTION,NULL)     ;
465         return 0;
466     }
467
468     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
469         doPragma (P_STACKAUTO,NULL);
470         return 0;
471     }
472
473     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
474         doPragma (P_NOJTBOUND,NULL);
475         return 0;
476     }
477
478     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
479         doPragma (P_NOGCSE,NULL);
480         return 0;
481     }
482
483     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
484         doPragma (P_NOOVERLAY,NULL);
485         return 0;
486     }
487     
488     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
489         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
490         return 0;
491     }
492     
493     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
494         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
495         return 0;
496     }
497
498     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
499         doPragma(P_EXCLUDE,NULL);
500         return 0;
501     }
502
503     werror(W_UNKNOWN_PRAGMA,cp);
504     return 0;
505 }
506
507 /* will return 1 if the string is a part
508    of a target specific keyword */
509 int isTargetKeyword(char *s)
510 {
511     int i;
512     
513     if (port->keywords == NULL)
514         return 0;
515     for ( i = 0 ; port->keywords[i] ; i++ ) {
516         if (strcmp(port->keywords[i],s) == 0)
517             return 1;
518     }
519     
520     return 0;
521 }