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