some progress on escape sequences
[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 "_naked"       { count(); TKEYWORD(NAKED); }
173 "while"        { count(); return(WHILE); }
174 "xdata"        { count(); TKEYWORD(XDATA); }
175 "_data"        { count(); TKEYWORD(_NEAR); }
176 "_code"        { count(); TKEYWORD(_CODE); }
177 "_eeprom"      { count(); TKEYWORD(_EEPROM); }
178 "_flash"       { count(); TKEYWORD(_CODE); }
179 "_generic"     { count(); TKEYWORD(_GENERIC); }
180 "_near"        { count(); TKEYWORD(_NEAR); }
181 "_sram"        { count(); TKEYWORD(_XDATA);}
182 "_xdata"       { count(); TKEYWORD(_XDATA);}
183 "_pdata"       { count(); TKEYWORD(_PDATA); }
184 "_idata"       { count(); TKEYWORD(_IDATA); }
185 "..."          { count(); return(VAR_ARGS);}
186 {L}({L}|{D})*  { count(); return(check_type()); }
187 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
188 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
189 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
190 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
191 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
192 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
193 {D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
194 \"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
195 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
196 "<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
197 "+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
198 "-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
199 "*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
200 "/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
201 "%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
202 "&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
203 "^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
204 "|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
205 ">>"           { count(); return(RIGHT_OP); }
206 "<<"           { count(); return(LEFT_OP); }
207 "++"           { count(); return(INC_OP); }
208 "--"           { count(); return(DEC_OP); }
209 "->"           { count(); return(PTR_OP); }
210 "&&"           { count(); return(AND_OP); }
211 "||"           { count(); return(OR_OP); }
212 "<="           { count(); return(LE_OP); }
213 ">="           { count(); return(GE_OP); }
214 "=="           { count(); return(EQ_OP); }
215 "!="           { count(); return(NE_OP); }
216 ";"            { count(); return(';'); }
217 "{"            { count(); NestLevel++ ;  return('{'); }
218 "}"            { count(); NestLevel--; 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 "?"            { count(); return('?'); }
240 ^#line.*"\n"       { count(); checkCurrFile(yytext); }
241 ^#pragma.*"\n"   { count(); process_pragma(yytext); }
242
243 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
244 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
245 "\r\n"             { count(); }
246 "\n"               { count(); }
247 [ \t\v\f]      { count(); }
248 .                          { count()    ; }
249 %%
250    
251 int checkCurrFile ( char *s)
252 {
253     char lineNum[10]                    ;
254     int  lNum                           ;
255     char *tptr                          ;
256        
257     /* first check if this is a #line */
258     if ( strncmp(s,"#line",5) )
259         return  0                               ;
260     
261     /* get to the line number */
262     while (!isdigit(*s))
263         s++ ;
264     tptr = lineNum ;
265     while (isdigit(*s))
266         *tptr++ = *s++ ;
267     *tptr = '\0'; 
268     sscanf(lineNum,"%d",&lNum);
269     
270     /* now see if we have a file name */
271     while (*s != '\"' && *s) 
272         s++ ;
273     
274     /* if we don't have a filename then */
275     /* set the current line number to   */
276     /* line number if printFlag is on   */
277     if (!*s) {          
278         yylineno = lNum ;
279         return 0;
280     }
281     
282     /* if we have a filename then check */
283     /* if it is "standard in" if yes then */
284     /* get the currentfile name info    */
285     s++ ;
286
287     if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
288             yylineno = lNum - 2;                                        
289             currFname = fullSrcFileName ;
290     }  else {
291         char *sb = s;
292         /* mark the end of the filename */
293         while (*s != '"') s++;
294         *s = '\0';
295         currFname = Safe_calloc(1,strlen(sb)+1);
296         strcpy(currFname,sb);
297         yylineno = lNum - 2;
298     }
299     filename = currFname ;
300     return 0;
301 }
302     
303 void comment()
304 {
305   char c, c1;
306   
307  loop:
308   while ((c = input()) != '*' && c)
309     if ( c == '\n')
310       yylineno++ ;
311   
312   if (c && (c1 = input()) != '/') {
313     unput(c1);
314     goto loop;
315   }
316 }
317    
318    
319
320 int column = 0;
321 int plineIdx=0;
322
323 void count()
324 {
325         int i;
326         for (i = 0; yytext[i] != '\0'; i++)   {                         
327                 if (yytext[i] == '\n')      {         
328                    column = 0;
329                    lineno = ++yylineno ;
330                 }
331                 else 
332                         if (yytext[i] == '\t')
333                                 column += 8 - (column % 8);
334                         else
335                                 column++;
336    }
337          
338    /* ECHO; */
339 }
340
341 int check_type()
342 {
343         /* check if it is in the typedef table */
344         if (findSym(TypedefTab,NULL,yytext)) {
345                 strcpy(yylval.yychar,yytext);
346                 return (TYPE_NAME) ;
347         }
348         else   {
349                 strcpy (yylval.yychar,yytext);
350                 return(IDENTIFIER);
351         }
352 }
353
354 char strLitBuff[2048]                   ;
355
356 /*
357  * Change by JTV 2001-05-19 to not concantenate strings
358  * to support ANSI hex and octal escape sequences in string liteals 
359  */
360
361 char *stringLiteral () {
362   int ch;
363   char *str = strLitBuff;
364   
365   *str++ = '\"';
366   /* put into the buffer till we hit the first \" */
367   
368   while (1) {
369     ch = input();
370     
371     if (!ch)
372       break; /* end of input */
373     
374     /* if it is a \ then escape char's are allowed */
375     if (ch == '\\') {
376       *str++ = ch; /* backslash in place */
377       *str++=input(); /* get the escape char, no check */
378       continue; /* carry on */
379     }
380     
381     /* if new line we have a new line break */
382     if (ch == '\n') {
383       yylineno++;
384       continue;
385     }
386     
387     /* if this is a quote then we have work to do */
388     /* find the next non whitespace character     */
389     /* if that is a double quote then carry on    */
390     if (ch == '\"') {
391       *str++  = ch ; /* Pass end of this string or substring to evaluator */
392       
393       while ((ch = input()) && (isspace(ch) || ch=='\\')) {
394         switch (ch) {
395         case '\\':
396           werror (W_STRAY_BACKSLASH, filename, yylineno);
397           break;
398         case '\n':
399           yylineno++;
400           break;
401         }
402       }
403
404       if (!ch) 
405         break; 
406       
407       if (ch != '\"') {
408         unput(ch) ;
409         break ;
410       }
411     }
412     *str++  = ch; /* Put next substring introducer into output string */
413   }  
414   *str = '\0';
415   
416   return strLitBuff;
417 }
418
419 void doPragma (int op, char *cp)
420 {
421     switch (op) {
422     case P_SAVE:
423         memcpy(&save_options,&options,sizeof(options));
424         memcpy(&save_optimize,&optimize,sizeof(optimize));
425         break;
426     case P_RESTORE:
427         memcpy(&options,&save_options,sizeof(options));
428         memcpy(&optimize,&save_optimize,sizeof(optimize));
429         break;
430     case P_NOINDUCTION:
431         optimize.loopInduction = 0 ;
432         break;
433     case P_NOINVARIANT:
434         optimize.loopInvariant = 0 ;
435         break;
436     case P_INDUCTION:
437         optimize.loopInduction = 1 ;
438         break;
439     case P_STACKAUTO:
440         options.stackAuto = 1;
441         break;
442     case P_NOJTBOUND:
443         optimize.noJTabBoundary = 1;
444         break;
445     case P_NOGCSE:
446         optimize.global_cse = 0;
447         break;
448     case P_NOOVERLAY:
449         options.noOverlay = 1;
450         break;
451     case P_CALLEE_SAVES:
452         {
453             int i=0;
454             /* append to the functions already listed
455                in callee-saves */
456             for (; options.calleeSaves[i] ;i++);
457             parseWithComma(&options.calleeSaves[i],strdup(cp));
458         }
459         break;
460     case P_EXCLUDE:
461         parseWithComma(options.excludeRegs,strdup(cp));
462         break;
463     case P_LOOPREV:
464         optimize.noLoopReverse = 1;
465         break;
466     }
467 }
468
469 int process_pragma(char *s)
470 {
471     char *cp ;
472     /* find the pragma */
473     while (strncmp(s,"#pragma",7))
474         s++;
475     s += 7;
476     
477     /* look for the directive */
478     while(isspace(*s)) s++;
479
480     cp = s;
481     /* look for the end of the directive */
482     while ((! isspace(*s)) && 
483            (*s != '\n')) 
484         s++ ;    
485
486     /* First give the port a chance */
487     if (port->process_pragma && !port->process_pragma(cp))
488         return 0;
489
490     /* now compare and do what needs to be done */
491     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
492         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
493         return 0;
494     }
495
496     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
497         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
498         return 0;
499     }
500
501     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
502         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
503         return 0;
504     }
505
506     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
507         doPragma (P_NOINVARIANT,NULL)   ;
508         return 0;
509     }
510
511     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
512         doPragma (P_INDUCTION,NULL)     ;
513         return 0;
514     }
515
516     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
517         doPragma (P_STACKAUTO,NULL);
518         return 0;
519     }
520
521     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
522         doPragma (P_NOJTBOUND,NULL);
523         return 0;
524     }
525
526     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
527         doPragma (P_NOGCSE,NULL);
528         return 0;
529     }
530
531     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
532         doPragma (P_NOOVERLAY,NULL);
533         return 0;
534     }
535     
536     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
537         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
538         return 0;
539     }
540     
541     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
542         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
543         return 0;
544     }
545
546     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
547         doPragma(P_EXCLUDE,NULL);
548         return 0;
549     }
550
551     werror(W_UNKNOWN_PRAGMA,cp);
552     return 0;
553 }
554
555 /* will return 1 if the string is a part
556    of a target specific keyword */
557 int isTargetKeyword(char *s)
558 {
559     int i;
560     
561     if (port->keywords == NULL)
562         return 0;
563     for ( i = 0 ; port->keywords[i] ; i++ ) {
564         if (strcmp(port->keywords[i],s) == 0)
565             return 1;
566     }
567     
568     return 0;
569 }
570
571 extern int fatalError;
572
573 int yyerror(char *s)
574 {
575    fflush(stdout);
576
577    if (yylineno && filename)
578         fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",
579                 filename,yylineno,
580                 s,yytext,column);
581    fatalError++;
582    return 0;
583 }