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