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 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
216 #define yytext_ptr yytext
220 static int checkCurrFile (char *s)
226 /* first check if this is a #line */
227 if ( strncmp(s,"#line",5) )
230 /* get to the line number */
237 sscanf(lineNum,"%d",&lNum);
239 /* now see if we have a file name */
240 while (*s != '\"' && *s)
243 /* if we don't have a filename then */
244 /* set the current line number to */
245 /* line number if printFlag is on */
247 lineno = mylineno = lNum ;
251 /* if we have a filename then check */
252 /* if it is "standard in" if yes then */
253 /* get the currentfile name info */
256 /* in c1mode fullSrcFileName is NULL */
257 if ( fullSrcFileName &&
258 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
259 lineno = mylineno = lNum;
260 currFname = fullSrcFileName ;
263 /* mark the end of the filename */
264 while (*s != '"') s++;
266 currFname = strdup (sb);
267 lineno = mylineno = lNum;
269 filename = currFname ;
276 static void count(void)
279 for (i = 0; yytext[i] != '\0'; i++) {
280 if (yytext[i] == '\n') {
282 lineno = ++mylineno ;
285 if (yytext[i] == '\t')
286 column += 8 - (column % 8);
293 static int check_type(void)
295 /* check if it is in the typedef table */
296 if (findSym(TypedefTab,NULL,yytext)) {
297 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
301 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
307 * Change by JTV 2001-05-19 to not concantenate strings
308 * to support ANSI hex and octal escape sequences in string liteals
311 static char *stringLiteral(void)
313 #define STR_BUF_CHUNCK_LEN 1024
315 static struct dbuf_s dbuf;
319 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
321 dbuf_set_size(&dbuf, 0);
324 dbuf_append(&dbuf, "\"", 1);
325 /* put into the buffer till we hit the first \" */
327 while ((ch = input()) != 0) {
330 /* if it is a \ then escape char's are allowed */
333 /* \<newline> is a continuator */
340 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
342 break; /* carry on */
345 /* if new line we have a new line break, which is illegal */
346 werror(W_NEWLINE_IN_STRING);
347 dbuf_append(&dbuf, "\n", 1);
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 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
357 while ((ch = input()) && (isspace(ch) || ch == '\\')) {
360 if ((ch = input()) != '\n') {
361 werror(W_STRAY_BACKSLASH, column);
387 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
392 return (char *)dbuf_c_str(&dbuf);
411 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
412 /* cross-compiling for MINGW32 with gcc 3.2 */
416 /* SAVE/RESTORE stack */
417 #define SAVE_RESTORE_SIZE 128
419 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
420 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
423 * cloneXxx functions should be updated every time a new set is
424 * added to the options or optimize structure!
427 static struct options *cloneOptions(struct options *opt)
429 struct options *new_opt;
431 new_opt = Safe_malloc(sizeof (struct options));
433 /* clone scalar values */
437 new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
438 new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
439 /* not implemented yet: */
440 /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
445 static struct optimize *cloneOptimize(struct optimize *opt)
447 struct optimize *new_opt;
449 new_opt = Safe_malloc(sizeof (struct options));
451 /* clone scalar values */
457 static void copyAndFreeOptions(struct options *dest, struct options *src)
459 /* delete dest sets */
460 deleteSet(&dest->calleeSavesSet);
461 deleteSet(&dest->excludeRegsSet);
462 /* not implemented yet: */
463 /* deleteSet(&dest->olaysSet); */
465 /* dopy src to dest */
471 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
473 /* dopy src to dest */
479 static void doPragma(int op, char *cp)
484 STACK_PUSH(options_stack, cloneOptions(&options));
485 STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
491 struct options *optionsp;
492 struct optimize *optimizep;
494 optionsp = STACK_POP(options_stack);
495 copyAndFreeOptions(&options, optionsp);
497 optimizep = STACK_POP(optimize_stack);
498 copyAndFreeOptimize(&optimize, optimizep);
503 optimize.loopInduction = 0 ;
507 optimize.loopInvariant = 0 ;
511 optimize.loopInduction = 1 ;
515 options.stackAuto = 1;
519 optimize.noJTabBoundary = 1;
523 optimize.global_cse = 0;
527 options.noOverlay = 1;
531 options.lessPedantic = 1;
535 /* append to the functions already listed
537 setParseWithComma(&options.calleeSavesSet, cp);
542 deleteSet(&options.excludeRegsSet);
543 setParseWithComma(&options.excludeRegsSet, cp);
552 optimize.noLoopReverse = 1;
560 static int process_pragma(char *s)
562 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
563 #define PRAGMA "#pragma"
565 static struct pragma_s {
570 { "RESTORE", P_RESTORE },
571 { "NOINDUCTION", P_NOINDUCTION },
572 { "NOINVARIANT", P_NOINVARIANT },
573 { "NOLOOPREVERSE", P_LOOPREV },
574 { "INDUCTION", P_INDUCTION },
575 { "STACKAUTO", P_STACKAUTO },
576 { "NOJTBOUND", P_NOJTBOUND },
577 { "NOGCSE", P_NOGCSE },
578 { "NOOVERLAY", P_NOOVERLAY },
579 { "CALLEE-SAVES", P_CALLEE_SAVES },
580 { "EXCLUDE", P_EXCLUDE },
582 { "OVERLAY", P_OVERLAY_ },
583 { "LESS_PEDANTIC", P_LESSPEDANTIC },
588 /* find the pragma */
589 while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
591 s += (sizeof PRAGMA) - 1;
593 /* look for the directive */
598 /* look for the end of the directive */
599 while ((!isspace(*s)) && (*s != '\n'))
602 /* First give the port a chance */
603 if (port->process_pragma && !port->process_pragma(cp))
606 for (i = 0; i < NELEM(pragma_tbl); i++) {
607 /* now compare and do what needs to be done */
608 size_t len = strlen(pragma_tbl[i].name);
610 if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
611 doPragma(pragma_tbl[i].id, cp + len);
616 werror(W_UNKNOWN_PRAGMA,cp);
620 /* will return 1 if the string is a part
621 of a target specific keyword */
622 static int isTargetKeyword(char *s)
626 if (port->keywords == NULL)
628 for ( i = 0 ; port->keywords[i] ; i++ ) {
629 if (strcmp(port->keywords[i],s) == 0)
638 if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
639 werror(W_SAVE_RESTORE);
648 if (mylineno && filename) {
649 if(options.vc_err_style)
650 fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
654 fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n",
659 /* this comes from an empy file, no problem */