Fixed octal and hex escape sequences in character and string constants
[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 /*
332  * Change by JTV 2001-05-19 to not concantenate strings
333  * to support ANSI hex and octal escape sequences in string liteals 
334  */
335
336 char *stringLiteral ()
337
338 {
339 int ch;
340 char *str = strLitBuff                  ;
341
342 *str++ = '\"'                   ;
343 /* put into the buffer till we hit the */
344 /* first \" */
345
346 while (1) 
347   {
348   ch = input()                  ;
349
350   if (!ch)
351     break       ; /* end of input */
352
353   /* if it is a \ then everything allowed */
354
355   if (ch == '\\') 
356     {
357     *str++ = ch     ; /* backslash in place */
358     *str++ = input()            ; /* following char in place */
359     continue                    ;      /* carry on */
360     }
361
362   /* if new line we have a new line break */
363   if (ch == '\n') 
364     break               ;
365
366   /* if this is a quote then we have work to do */
367   /* find the next non whitespace character     */
368   /* if that is a double quote then carry on    */
369
370   if (ch == '\"') 
371     {
372     *str++  = ch ;      /* Pass end of this string or substring to evaluator */
373
374     while ((ch = input()) && isspace(ch)) ;
375
376     if (!ch) 
377       break ; 
378
379     if (ch != '\"') 
380       {
381       unput(ch) ;
382       break ;
383       }
384     }
385
386   *str++  = ch;       /* Put next substring introducer into output string */
387   }  
388
389 *str = '\0';
390
391 return strLitBuff                       ;
392 }
393
394 void doPragma (int op, char *cp)
395 {
396     switch (op) {
397     case P_SAVE:
398         memcpy(&save_options,&options,sizeof(options));
399         memcpy(&save_optimize,&optimize,sizeof(optimize));
400         break;
401     case P_RESTORE:
402         memcpy(&options,&save_options,sizeof(options));
403         memcpy(&optimize,&save_optimize,sizeof(optimize));
404         break;
405     case P_NOINDUCTION:
406         optimize.loopInduction = 0 ;
407         break;
408     case P_NOINVARIANT:
409         optimize.loopInvariant = 0 ;
410         break;
411     case P_INDUCTION:
412         optimize.loopInduction = 1 ;
413         break;
414     case P_STACKAUTO:
415         options.stackAuto = 1;
416         break;
417     case P_NOJTBOUND:
418         optimize.noJTabBoundary = 1;
419         break;
420     case P_NOGCSE:
421         optimize.global_cse = 0;
422         break;
423     case P_NOOVERLAY:
424         options.noOverlay = 1;
425         break;
426     case P_CALLEE_SAVES:
427         {
428             int i=0;
429             /* append to the functions already listed
430                in callee-saves */
431             for (; options.calleeSaves[i] ;i++);
432             parseWithComma(&options.calleeSaves[i],strdup(cp));
433         }
434         break;
435     case P_EXCLUDE:
436         parseWithComma(options.excludeRegs,strdup(cp));
437         break;
438     case P_LOOPREV:
439         optimize.noLoopReverse = 1;
440         break;
441     }
442 }
443
444 int process_pragma(char *s)
445 {
446     char *cp ;
447     /* find the pragma */
448     while (strncmp(s,"#pragma",7))
449         s++;
450     s += 7;
451     
452     /* look for the directive */
453     while(isspace(*s)) s++;
454
455     cp = s;
456     /* look for the end of the directive */
457     while ((! isspace(*s)) && 
458            (*s != '\n')) 
459         s++ ;    
460
461     /* First give the port a chance */
462     if (port->process_pragma && !port->process_pragma(cp))
463         return 0;
464
465     /* now compare and do what needs to be done */
466     if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
467         doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
468         return 0;
469     }
470
471     if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
472         doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
473         return 0;
474     }
475
476     if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
477         doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
478         return 0;
479     }
480
481     if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
482         doPragma (P_NOINVARIANT,NULL)   ;
483         return 0;
484     }
485
486     if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
487         doPragma (P_INDUCTION,NULL)     ;
488         return 0;
489     }
490
491     if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
492         doPragma (P_STACKAUTO,NULL);
493         return 0;
494     }
495
496     if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
497         doPragma (P_NOJTBOUND,NULL);
498         return 0;
499     }
500
501     if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
502         doPragma (P_NOGCSE,NULL);
503         return 0;
504     }
505
506     if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
507         doPragma (P_NOOVERLAY,NULL);
508         return 0;
509     }
510     
511     if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
512         doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
513         return 0;
514     }
515     
516     if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
517         doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
518         return 0;
519     }
520
521     if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
522         doPragma(P_EXCLUDE,NULL);
523         return 0;
524     }
525
526     werror(W_UNKNOWN_PRAGMA,cp);
527     return 0;
528 }
529
530 /* will return 1 if the string is a part
531    of a target specific keyword */
532 int isTargetKeyword(char *s)
533 {
534     int i;
535     
536     if (port->keywords == NULL)
537         return 0;
538     for ( i = 0 ; port->keywords[i] ; i++ ) {
539         if (strcmp(port->keywords[i],s) == 0)
540             return 1;
541     }
542     
543     return 0;
544 }
545
546 extern int fatalError;
547
548 int yyerror(char *s)
549 {
550    fflush(stdout);
551
552    if (yylineno && filename)
553         fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",
554                 filename,yylineno,
555                 s,yytext,column);
556    fatalError++;
557    return 0;
558 }