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 optimize save_optimize;
52 static struct options save_options;
53 static struct dbuf_s asmbuff;
55 /* forward declarations */
56 static char *stringLiteral(void);
57 static void count(void);
58 static int process_pragma(char *);
59 static int check_type(void);
60 static int isTargetKeyword(char *s);
61 static int checkCurrFile(char *s);
68 assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
69 dbuf_init(&asmbuff, INITIAL_INLINEASM);
74 yylval.yyinline = dbuf_c_str(&asmbuff);
75 dbuf_detach(&asmbuff);
81 dbuf_append(&asmbuff, yytext, 1);
84 dbuf_append(&asmbuff, yytext, 1);
86 "at" { count(); TKEYWORD(AT) ; }
87 "auto" { count(); return(AUTO); }
88 "bit" { count(); TKEYWORD(BIT) ; }
89 "break" { count(); return(BREAK); }
90 "case" { count(); return(CASE); }
91 "char" { count(); return(CHAR); }
92 "code" { count(); TKEYWORD(CODE); }
93 "const" { count(); return(CONST); }
94 "continue" { count(); return(CONTINUE); }
95 "critical" { count(); TKEYWORD(CRITICAL); }
96 "data" { count(); TKEYWORD(DATA); }
97 "default" { count(); return(DEFAULT); }
98 "do" { count(); return(DO); }
99 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
100 "else" { count(); return(ELSE); }
101 "enum" { count(); return(ENUM); }
102 "extern" { count(); return(EXTERN); }
103 "far" { count(); TKEYWORD(XDATA); }
104 "eeprom" { count(); TKEYWORD(EEPROM); }
105 "float" { count(); return(FLOAT); }
106 "flash" { count(); TKEYWORD(CODE);}
107 "for" { count(); return(FOR); }
108 "goto" { count(); return(GOTO); }
109 "idata" { count(); TKEYWORD(IDATA);}
110 "if" { count(); return(IF); }
111 "int" { count(); return(INT); }
112 "interrupt" { count(); return(INTERRUPT);}
113 "nonbanked" { count(); TKEYWORD(NONBANKED);}
114 "banked" { count(); TKEYWORD(BANKED);}
115 "long" { count(); return(LONG); }
116 "near" { count(); TKEYWORD(DATA);}
117 "pdata" { count(); TKEYWORD(PDATA); }
118 "reentrant" { count(); TKEYWORD(REENTRANT);}
119 "register" { count(); return(REGISTER); }
120 "return" { count(); return(RETURN); }
121 "sfr" { count(); TKEYWORD(SFR) ; }
122 "sbit" { count(); TKEYWORD(SBIT) ; }
123 "short" { count(); return(SHORT); }
124 "signed" { count(); return(SIGNED); }
125 "sizeof" { count(); return(SIZEOF); }
126 "sram" { count(); TKEYWORD(XDATA);}
127 "static" { count(); return(STATIC); }
128 "struct" { count(); return(STRUCT); }
129 "switch" { count(); return(SWITCH); }
130 "typedef" { count(); return(TYPEDEF); }
131 "union" { count(); return(UNION); }
132 "unsigned" { count(); return(UNSIGNED); }
133 "void" { count(); return(VOID); }
134 "volatile" { count(); return(VOLATILE); }
135 "using" { count(); TKEYWORD(USING); }
136 "_naked" { count(); TKEYWORD(NAKED); }
137 "while" { count(); return(WHILE); }
138 "xdata" { count(); TKEYWORD(XDATA); }
139 "..." { count(); return(VAR_ARGS);}
140 "__typeof" { count(); return TYPEOF;}
141 "_JavaNative" { count(); TKEYWORD(JAVANATIVE);}
142 "_overlay" { count(); TKEYWORD(OVERLAY);}
143 {L}({L}|{D})* { count(); return(check_type()); }
144 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
145 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
146 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
147 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
148 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
149 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
150 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
151 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
152 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
153 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
154 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
155 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
156 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
157 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
158 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
159 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
160 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
161 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
162 ">>" { count(); return(RIGHT_OP); }
163 "<<" { count(); return(LEFT_OP); }
164 "++" { count(); return(INC_OP); }
165 "--" { count(); return(DEC_OP); }
166 "->" { count(); return(PTR_OP); }
167 "&&" { count(); return(AND_OP); }
168 "||" { count(); return(OR_OP); }
169 "<=" { count(); return(LE_OP); }
170 ">=" { count(); return(GE_OP); }
171 "==" { count(); return(EQ_OP); }
172 "!=" { count(); return(NE_OP); }
173 ";" { count(); return(';'); }
174 "{" { count(); NestLevel++ ; return('{'); }
175 "}" { count(); NestLevel--; 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 "|" { count(); return('|'); }
196 "?" { count(); return('?'); }
197 ^#line.*"\n" { count(); checkCurrFile(yytext); }
198 ^#pragma.*"\n" { count(); process_pragma(yytext); }
200 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
201 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
204 [ \t\v\f] { count(); }
208 /* that could have been removed by the preprocessor anyway */
209 werror (W_STRAY_BACKSLASH, column);
216 static int checkCurrFile (char *s)
222 /* first check if this is a #line */
223 if ( strncmp(s,"#line",5) )
226 /* get to the line number */
233 sscanf(lineNum,"%d",&lNum);
235 /* now see if we have a file name */
236 while (*s != '\"' && *s)
239 /* if we don't have a filename then */
240 /* set the current line number to */
241 /* line number if printFlag is on */
243 lineno = mylineno = lNum ;
247 /* if we have a filename then check */
248 /* if it is "standard in" if yes then */
249 /* get the currentfile name info */
252 /* in c1mode fullSrcFileName is NULL */
253 if ( fullSrcFileName &&
254 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
255 lineno = mylineno = lNum;
256 currFname = fullSrcFileName ;
259 /* mark the end of the filename */
260 while (*s != '"') s++;
262 currFname = strdup (sb);
263 lineno = mylineno = lNum;
265 filename = currFname ;
272 static void count(void)
275 for (i = 0; yytext[i] != '\0'; i++) {
276 if (yytext[i] == '\n') {
278 lineno = ++mylineno ;
281 if (yytext[i] == '\t')
282 column += 8 - (column % 8);
289 static int check_type(void)
291 /* check if it is in the typedef table */
292 if (findSym(TypedefTab,NULL,yytext)) {
293 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
297 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
303 * Change by JTV 2001-05-19 to not concantenate strings
304 * to support ANSI hex and octal escape sequences in string liteals
307 static char *stringLiteral(void)
309 #define STR_BUF_CHUNCK_LEN 1024
311 static struct dbuf_s dbuf;
315 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
317 dbuf_set_size(&dbuf, 0);
320 dbuf_append(&dbuf, "\"", 1);
321 /* put into the buffer till we hit the first \" */
323 while ((ch = input()) != 0) {
326 /* if it is a \ then escape char's are allowed */
329 /* \<newline> is a continuator */
336 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
338 break; /* carry on */
341 /* if new line we have a new line break, which is illegal */
342 werror(W_NEWLINE_IN_STRING);
343 dbuf_append(&dbuf, "\n", 1);
349 /* if this is a quote then we have work to do */
350 /* find the next non whitespace character */
351 /* if that is a double quote then carry on */
352 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
353 while ((ch = input()) && (isspace(ch) || ch == '\\')) {
356 if ((ch = input()) != '\n') {
357 werror(W_STRAY_BACKSLASH, column);
383 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
388 return (char *)dbuf_c_str(&dbuf);
407 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
408 /* cross-compiling for MINGW32 with gcc 3.2 */
412 /* SAVE/RESTORE stack */
413 #define SAVE_RESTORE_SIZE 128
415 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
416 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
419 * cloneXxx functions should be updated every time a new set is
420 * added to the options or optimize structure!
423 static struct options *cloneOptions(struct options *opt)
425 struct options *new_opt;
427 new_opt = Safe_malloc(sizeof (struct options));
429 /* clone scalar values */
433 new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
434 new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
435 /* not implemented yet: */
436 /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
441 static struct optimize *cloneOptimize(struct optimize *opt)
443 struct optimize *new_opt;
445 new_opt = Safe_malloc(sizeof (struct options));
447 /* clone scalar values */
453 static void copyAndFreeOptions(struct options *dest, struct options *src)
455 /* delete dest sets */
456 deleteSet(&dest->calleeSavesSet);
457 deleteSet(&dest->excludeRegsSet);
458 /* not implemented yet: */
459 /* deleteSet(&dest->olaysSet); */
461 /* dopy src to dest */
467 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
469 /* dopy src to dest */
475 static void doPragma(int op, char *cp)
480 STACK_PUSH(options_stack, cloneOptions(&options));
481 STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
487 struct options *optionsp;
488 struct optimize *optimizep;
490 optionsp = STACK_POP(options_stack);
491 copyAndFreeOptions(&options, optionsp);
493 optimizep = STACK_POP(optimize_stack);
494 copyAndFreeOptimize(&optimize, optimizep);
499 optimize.loopInduction = 0 ;
503 optimize.loopInvariant = 0 ;
507 optimize.loopInduction = 1 ;
511 options.stackAuto = 1;
515 optimize.noJTabBoundary = 1;
519 optimize.global_cse = 0;
523 options.noOverlay = 1;
527 options.lessPedantic = 1;
531 /* append to the functions already listed
533 setParseWithComma(&options.calleeSavesSet, cp);
538 deleteSet(&options.excludeRegsSet);
539 setParseWithComma(&options.excludeRegsSet, cp);
548 optimize.noLoopReverse = 1;
556 static int process_pragma(char *s)
558 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
559 #define PRAGMA "#pragma"
561 static struct pragma_s {
566 { "RESTORE", P_RESTORE },
567 { "NOINDUCTION", P_NOINDUCTION },
568 { "NOINVARIANT", P_NOINVARIANT },
569 { "NOLOOPREVERSE", P_LOOPREV },
570 { "INDUCTION", P_INDUCTION },
571 { "STACKAUTO", P_STACKAUTO },
572 { "NOJTBOUND", P_NOJTBOUND },
573 { "NOGCSE", P_NOGCSE },
574 { "NOOVERLAY", P_NOOVERLAY },
575 { "CALLEE-SAVES", P_CALLEE_SAVES },
576 { "EXCLUDE", P_EXCLUDE },
578 { "OVERLAY", P_OVERLAY_ },
579 { "LESS_PEDANTIC", P_LESSPEDANTIC },
584 /* find the pragma */
585 while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
587 s += (sizeof PRAGMA) - 1;
589 /* look for the directive */
594 /* look for the end of the directive */
595 while ((!isspace(*s)) && (*s != '\n'))
598 /* First give the port a chance */
599 if (port->process_pragma && !port->process_pragma(cp))
602 for (i = 0; i < NELEM(pragma_tbl); i++) {
603 /* now compare and do what needs to be done */
604 size_t len = strlen(pragma_tbl[i].name);
606 if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
607 doPragma(pragma_tbl[i].id, cp + len);
612 werror(W_UNKNOWN_PRAGMA,cp);
616 /* will return 1 if the string is a part
617 of a target specific keyword */
618 static int isTargetKeyword(char *s)
622 if (port->keywords == NULL)
624 for ( i = 0 ; port->keywords[i] ; i++ ) {
625 if (strcmp(port->keywords[i],s) == 0)
634 if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
635 werror(W_SAVE_RESTORE);
644 if (mylineno && filename) {
645 if(options.vc_err_style)
646 fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
650 fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n",
655 /* this comes from an empy file, no problem */