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)
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
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.
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.
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 -------------------------------------------------------------------------*/
40 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
43 extern int lineno, column;
44 extern char *filename;
46 /* global definitions */
50 /* local definitions */
51 static struct dbuf_s asmbuff;
53 /* forward declarations */
54 static char *stringLiteral(void);
55 static void count(void);
56 static int process_pragma(char *);
57 static int check_type(void);
58 static int isTargetKeyword(char *s);
59 static int checkCurrFile(char *s);
66 assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
67 dbuf_init(&asmbuff, INITIAL_INLINEASM);
72 yylval.yyinline = dbuf_c_str(&asmbuff);
73 dbuf_detach(&asmbuff);
79 dbuf_append(&asmbuff, yytext, 1);
82 dbuf_append(&asmbuff, yytext, 1);
84 "at" { count(); TKEYWORD(AT) ; }
85 "auto" { count(); return(AUTO); }
86 "bit" { count(); TKEYWORD(BIT) ; }
87 "break" { count(); return(BREAK); }
88 "case" { count(); return(CASE); }
89 "char" { count(); return(CHAR); }
90 "code" { count(); TKEYWORD(CODE); }
91 "const" { count(); return(CONST); }
92 "continue" { count(); return(CONTINUE); }
93 "critical" { count(); TKEYWORD(CRITICAL); }
94 "data" { count(); TKEYWORD(DATA); }
95 "default" { count(); return(DEFAULT); }
96 "do" { count(); return(DO); }
97 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
98 "else" { count(); return(ELSE); }
99 "enum" { count(); return(ENUM); }
100 "extern" { count(); return(EXTERN); }
101 "far" { count(); TKEYWORD(XDATA); }
102 "eeprom" { count(); TKEYWORD(EEPROM); }
103 "float" { count(); return(FLOAT); }
104 "flash" { count(); TKEYWORD(CODE);}
105 "for" { count(); return(FOR); }
106 "goto" { count(); return(GOTO); }
107 "idata" { count(); TKEYWORD(IDATA);}
108 "if" { count(); return(IF); }
109 "int" { count(); return(INT); }
110 "interrupt" { count(); return(INTERRUPT);}
111 "nonbanked" { count(); TKEYWORD(NONBANKED);}
112 "banked" { count(); TKEYWORD(BANKED);}
113 "long" { count(); return(LONG); }
114 "near" { count(); TKEYWORD(DATA);}
115 "pdata" { count(); TKEYWORD(PDATA); }
116 "reentrant" { count(); TKEYWORD(REENTRANT);}
117 "register" { count(); return(REGISTER); }
118 "return" { count(); return(RETURN); }
119 "sfr" { count(); TKEYWORD(SFR) ; }
120 "sbit" { count(); TKEYWORD(SBIT) ; }
121 "short" { count(); return(SHORT); }
122 "signed" { count(); return(SIGNED); }
123 "sizeof" { count(); return(SIZEOF); }
124 "sram" { count(); TKEYWORD(XDATA);}
125 "static" { count(); return(STATIC); }
126 "struct" { count(); return(STRUCT); }
127 "switch" { count(); return(SWITCH); }
128 "typedef" { count(); return(TYPEDEF); }
129 "union" { count(); return(UNION); }
130 "unsigned" { count(); return(UNSIGNED); }
131 "void" { count(); return(VOID); }
132 "volatile" { count(); return(VOLATILE); }
133 "using" { count(); TKEYWORD(USING); }
134 "_naked" { count(); TKEYWORD(NAKED); }
135 "while" { count(); return(WHILE); }
136 "xdata" { count(); TKEYWORD(XDATA); }
137 "..." { count(); return(VAR_ARGS);}
138 "__typeof" { count(); return TYPEOF;}
139 "_JavaNative" { count(); TKEYWORD(JAVANATIVE);}
140 "_overlay" { count(); TKEYWORD(OVERLAY);}
141 {L}({L}|{D})* { count(); return(check_type()); }
142 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
143 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
144 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
145 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
146 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
147 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
148 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
149 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
150 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
151 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
152 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
153 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
154 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
155 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
156 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
157 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
158 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
159 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
160 ">>" { count(); return(RIGHT_OP); }
161 "<<" { count(); return(LEFT_OP); }
162 "++" { count(); return(INC_OP); }
163 "--" { count(); return(DEC_OP); }
164 "->" { count(); return(PTR_OP); }
165 "&&" { count(); return(AND_OP); }
166 "||" { count(); return(OR_OP); }
167 "<=" { count(); return(LE_OP); }
168 ">=" { count(); return(GE_OP); }
169 "==" { count(); return(EQ_OP); }
170 "!=" { count(); return(NE_OP); }
171 ";" { count(); return(';'); }
172 "{" { count(); NestLevel++ ; return('{'); }
173 "}" { count(); NestLevel--; return('}'); }
174 "," { count(); return(','); }
175 ":" { count(); return(':'); }
176 "=" { count(); return('='); }
177 "(" { count(); return('('); }
178 ")" { count(); return(')'); }
179 "[" { count(); return('['); }
180 "]" { count(); return(']'); }
181 "." { count(); return('.'); }
182 "&" { count(); return('&'); }
183 "!" { count(); return('!'); }
184 "~" { count(); return('~'); }
185 "-" { count(); return('-'); }
186 "+" { count(); 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 ^#line.*"\n" { count(); checkCurrFile(yytext); }
196 ^#pragma.*"\n" { count(); process_pragma(yytext); }
198 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
199 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
202 [ \t\v\f] { count(); }
206 /* that could have been removed by the preprocessor anyway */
207 werror (W_STRAY_BACKSLASH, column);
214 static int checkCurrFile (char *s)
220 /* first check if this is a #line */
221 if ( strncmp(s,"#line",5) )
224 /* get to the line number */
231 sscanf(lineNum,"%d",&lNum);
233 /* now see if we have a file name */
234 while (*s != '\"' && *s)
237 /* if we don't have a filename then */
238 /* set the current line number to */
239 /* line number if printFlag is on */
241 lineno = mylineno = lNum ;
245 /* if we have a filename then check */
246 /* if it is "standard in" if yes then */
247 /* get the currentfile name info */
250 /* in c1mode fullSrcFileName is NULL */
251 if ( fullSrcFileName &&
252 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
253 lineno = mylineno = lNum;
254 currFname = fullSrcFileName ;
257 /* mark the end of the filename */
258 while (*s != '"') s++;
260 currFname = strdup (sb);
261 lineno = mylineno = lNum;
263 filename = currFname ;
270 static void count(void)
273 for (i = 0; yytext[i] != '\0'; i++) {
274 if (yytext[i] == '\n') {
276 lineno = ++mylineno ;
279 if (yytext[i] == '\t')
280 column += 8 - (column % 8);
287 static int check_type(void)
289 /* check if it is in the typedef table */
290 if (findSym(TypedefTab,NULL,yytext)) {
291 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
295 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
301 * Change by JTV 2001-05-19 to not concantenate strings
302 * to support ANSI hex and octal escape sequences in string liteals
305 static char *stringLiteral(void)
307 #define STR_BUF_CHUNCK_LEN 1024
309 static struct dbuf_s dbuf;
313 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
315 dbuf_set_size(&dbuf, 0);
318 dbuf_append(&dbuf, "\"", 1);
319 /* put into the buffer till we hit the first \" */
321 while ((ch = input()) != 0) {
324 /* if it is a \ then escape char's are allowed */
327 /* \<newline> is a continuator */
334 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
336 break; /* carry on */
339 /* if new line we have a new line break, which is illegal */
340 werror(W_NEWLINE_IN_STRING);
341 dbuf_append(&dbuf, "\n", 1);
347 /* if this is a quote then we have work to do */
348 /* find the next non whitespace character */
349 /* if that is a double quote then carry on */
350 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
351 while ((ch = input()) && (isspace(ch) || ch == '\\')) {
354 if ((ch = input()) != '\n') {
355 werror(W_STRAY_BACKSLASH, column);
381 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
386 return (char *)dbuf_c_str(&dbuf);
405 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
406 /* cross-compiling for MINGW32 with gcc 3.2 */
410 /* SAVE/RESTORE stack */
411 #define SAVE_RESTORE_SIZE 128
413 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
414 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
417 * cloneXxx functions should be updated every time a new set is
418 * added to the options or optimize structure!
421 static struct options *cloneOptions(struct options *opt)
423 struct options *new_opt;
425 new_opt = Safe_malloc(sizeof (struct options));
427 /* clone scalar values */
431 new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
432 new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
433 /* not implemented yet: */
434 /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
439 static struct optimize *cloneOptimize(struct optimize *opt)
441 struct optimize *new_opt;
443 new_opt = Safe_malloc(sizeof (struct options));
445 /* clone scalar values */
451 static void copyAndFreeOptions(struct options *dest, struct options *src)
453 /* delete dest sets */
454 deleteSet(&dest->calleeSavesSet);
455 deleteSet(&dest->excludeRegsSet);
456 /* not implemented yet: */
457 /* deleteSet(&dest->olaysSet); */
459 /* dopy src to dest */
465 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
467 /* dopy src to dest */
473 static void doPragma(int op, char *cp)
478 STACK_PUSH(options_stack, cloneOptions(&options));
479 STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
485 struct options *optionsp;
486 struct optimize *optimizep;
488 optionsp = STACK_POP(options_stack);
489 copyAndFreeOptions(&options, optionsp);
491 optimizep = STACK_POP(optimize_stack);
492 copyAndFreeOptimize(&optimize, optimizep);
497 optimize.loopInduction = 0 ;
501 optimize.loopInvariant = 0 ;
505 optimize.loopInduction = 1 ;
509 options.stackAuto = 1;
513 optimize.noJTabBoundary = 1;
517 optimize.global_cse = 0;
521 options.noOverlay = 1;
525 options.lessPedantic = 1;
529 /* append to the functions already listed
531 setParseWithComma(&options.calleeSavesSet, cp);
536 deleteSet(&options.excludeRegsSet);
537 setParseWithComma(&options.excludeRegsSet, cp);
546 optimize.noLoopReverse = 1;
554 static int process_pragma(char *s)
556 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
557 #define PRAGMA "#pragma"
559 static struct pragma_s {
564 { "RESTORE", P_RESTORE },
565 { "NOINDUCTION", P_NOINDUCTION },
566 { "NOINVARIANT", P_NOINVARIANT },
567 { "NOLOOPREVERSE", P_LOOPREV },
568 { "INDUCTION", P_INDUCTION },
569 { "STACKAUTO", P_STACKAUTO },
570 { "NOJTBOUND", P_NOJTBOUND },
571 { "NOGCSE", P_NOGCSE },
572 { "NOOVERLAY", P_NOOVERLAY },
573 { "CALLEE-SAVES", P_CALLEE_SAVES },
574 { "EXCLUDE", P_EXCLUDE },
576 { "OVERLAY", P_OVERLAY_ },
577 { "LESS_PEDANTIC", P_LESSPEDANTIC },
582 /* find the pragma */
583 while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
585 s += (sizeof PRAGMA) - 1;
587 /* look for the directive */
592 /* look for the end of the directive */
593 while ((!isspace(*s)) && (*s != '\n'))
596 /* First give the port a chance */
597 if (port->process_pragma && !port->process_pragma(cp))
600 for (i = 0; i < NELEM(pragma_tbl); i++) {
601 /* now compare and do what needs to be done */
602 size_t len = strlen(pragma_tbl[i].name);
604 if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
605 doPragma(pragma_tbl[i].id, cp + len);
610 werror(W_UNKNOWN_PRAGMA,cp);
614 /* will return 1 if the string is a part
615 of a target specific keyword */
616 static int isTargetKeyword(char *s)
620 if (port->keywords == NULL)
622 for ( i = 0 ; port->keywords[i] ; i++ ) {
623 if (strcmp(port->keywords[i],s) == 0)
632 if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
633 werror(W_SAVE_RESTORE);
642 if (mylineno && filename) {
643 if(options.vc_err_style)
644 fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
648 fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n",
653 /* this comes from an empy file, no problem */