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 char *stringLiteral();
43 extern int lineno, column;
44 extern char *filename ;
47 int process_pragma(char *);
50 int yywrap YY_PROTO((void))
54 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
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 ;
71 asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
72 asmbuffSize=INITIAL_INLINEASM;
78 yylval.yyinline = strdup (asmbuff);
83 if (asmp-asmbuff >= asmbuffSize-2) {
84 // increase the buffersize with 50%
85 int size=asmp-asmbuff;
86 asmbuffSize=asmbuffSize*3/2;
87 asmbuff = realloc (asmbuff, asmbuffSize);
94 if (asmp-asmbuff >= asmbuffSize-3) {
95 // increase the buffersize with 50%
96 int size=asmp-asmbuff;
97 asmbuffSize=asmbuffSize*3/2;
98 asmbuff = realloc (asmbuff, asmbuffSize);
103 "at" { count(); TKEYWORD(AT) ; }
104 "auto" { count(); return(AUTO); }
105 "bit" { count(); TKEYWORD(BIT) ; }
106 "break" { count(); return(BREAK); }
107 "case" { count(); return(CASE); }
108 "char" { count(); return(CHAR); }
109 "code" { count(); TKEYWORD(CODE); }
110 "const" { count(); return(CONST); }
111 "continue" { count(); return(CONTINUE); }
112 "critical" { count(); TKEYWORD(CRITICAL); }
113 "data" { count(); TKEYWORD(DATA); }
114 "default" { count(); return(DEFAULT); }
115 "do" { count(); return(DO); }
116 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
117 "else" { count(); return(ELSE); }
118 "enum" { count(); return(ENUM); }
119 "extern" { count(); return(EXTERN); }
120 "far" { count(); TKEYWORD(XDATA); }
121 "eeprom" { count(); TKEYWORD(EEPROM); }
122 "float" { count(); return(FLOAT); }
123 "flash" { count(); TKEYWORD(CODE);}
124 "for" { count(); return(FOR); }
125 "goto" { count(); return(GOTO); }
126 "idata" { count(); TKEYWORD(IDATA);}
127 "if" { count(); return(IF); }
128 "int" { count(); return(INT); }
129 "interrupt" { count(); return(INTERRUPT);}
130 "nonbanked" { count(); TKEYWORD(NONBANKED);}
131 "banked" { count(); TKEYWORD(BANKED);}
132 "long" { count(); return(LONG); }
133 "near" { count(); TKEYWORD(DATA);}
134 "pdata" { count(); TKEYWORD(PDATA); }
135 "reentrant" { count(); TKEYWORD(REENTRANT);}
136 "register" { count(); return(REGISTER); }
137 "return" { count(); return(RETURN); }
138 "sfr" { count(); TKEYWORD(SFR) ; }
139 "sbit" { count(); TKEYWORD(SBIT) ; }
140 "short" { count(); return(SHORT); }
141 "signed" { count(); return(SIGNED); }
142 "sizeof" { count(); return(SIZEOF); }
143 "sram" { count(); TKEYWORD(XDATA);}
144 "static" { count(); return(STATIC); }
145 "struct" { count(); return(STRUCT); }
146 "switch" { count(); return(SWITCH); }
147 "typedef" { count(); return(TYPEDEF); }
148 "union" { count(); return(UNION); }
149 "unsigned" { count(); return(UNSIGNED); }
150 "void" { count(); return(VOID); }
151 "volatile" { count(); return(VOLATILE); }
152 "using" { count(); TKEYWORD(USING); }
153 "_naked" { count(); TKEYWORD(NAKED); }
154 "while" { count(); return(WHILE); }
155 "xdata" { count(); TKEYWORD(XDATA); }
156 "..." { count(); return(VAR_ARGS);}
157 "__typeof" { count(); return TYPEOF;}
158 "_JavaNative" { count(); TKEYWORD(JAVANATIVE);}
159 "_overlay" { count(); TKEYWORD(OVERLAY);}
160 {L}({L}|{D})* { count(); return(check_type()); }
161 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
162 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
163 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
164 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
165 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
166 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
167 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
168 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
169 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
170 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
171 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
172 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
173 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
174 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
175 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
176 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
177 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
178 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
179 ">>" { count(); return(RIGHT_OP); }
180 "<<" { count(); return(LEFT_OP); }
181 "++" { count(); return(INC_OP); }
182 "--" { count(); return(DEC_OP); }
183 "->" { count(); return(PTR_OP); }
184 "&&" { count(); return(AND_OP); }
185 "||" { count(); return(OR_OP); }
186 "<=" { count(); return(LE_OP); }
187 ">=" { count(); return(GE_OP); }
188 "==" { count(); return(EQ_OP); }
189 "!=" { count(); return(NE_OP); }
190 ";" { count(); return(';'); }
191 "{" { count(); NestLevel++ ; return('{'); }
192 "}" { count(); NestLevel--; 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 "^" { count(); return('^'); }
212 "|" { count(); return('|'); }
213 "?" { count(); return('?'); }
214 ^#line.*"\n" { count(); checkCurrFile(yytext); }
215 ^#pragma.*"\n" { count(); process_pragma(yytext); }
217 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
218 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
221 [ \t\v\f] { count(); }
225 // that could have been removed by the preprocessor anyway
226 werror (W_STRAY_BACKSLASH, column);
233 int checkCurrFile ( char *s)
239 /* first check if this is a #line */
240 if ( strncmp(s,"#line",5) )
243 /* get to the line number */
250 sscanf(lineNum,"%d",&lNum);
252 /* now see if we have a file name */
253 while (*s != '\"' && *s)
256 /* if we don't have a filename then */
257 /* set the current line number to */
258 /* line number if printFlag is on */
260 lineno = yylineno = lNum ;
264 /* if we have a filename then check */
265 /* if it is "standard in" if yes then */
266 /* get the currentfile name info */
269 /* in c1mode fullSrcFileName is NULL */
270 if ( fullSrcFileName &&
271 strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
272 lineno = yylineno = lNum;
273 currFname = fullSrcFileName ;
276 /* mark the end of the filename */
277 while (*s != '"') s++;
279 currFname = strdup (sb);
280 lineno = yylineno = lNum;
282 filename = currFname ;
292 for (i = 0; yytext[i] != '\0'; i++) {
293 if (yytext[i] == '\n') {
295 lineno = ++yylineno ;
298 if (yytext[i] == '\t')
299 column += 8 - (column % 8);
308 /* check if it is in the typedef table */
309 if (findSym(TypedefTab,NULL,yytext)) {
310 strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
314 strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
320 * Change by JTV 2001-05-19 to not concantenate strings
321 * to support ANSI hex and octal escape sequences in string liteals
324 char *stringLiteral()
326 #define STR_BUF_CHUNCK_LEN 1024
328 static struct dbuf_s dbuf;
332 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
334 dbuf_set_size(&dbuf, 0);
337 dbuf_append(&dbuf, "\"", 1);
338 /* put into the buffer till we hit the first \" */
340 while ((ch = input()) != 0) {
343 /* if it is a \ then escape char's are allowed */
346 /* \<newline> is a continuator */
353 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
355 break; /* carry on */
358 /* if new line we have a new line break, which is illegal */
359 werror(W_NEWLINE_IN_STRING);
360 dbuf_append(&dbuf, "\n", 1);
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 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
370 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
373 if ((ch = input()) != '\n') {
374 werror(W_STRAY_BACKSLASH, column);
400 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
405 return (char *)dbuf_c_str(&dbuf);
424 P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
425 /* cross-compiling for MINGW32 with gcc 3.2 */
429 /* SAVE/RESTORE stack */
430 #define SAVE_RESTORE_SIZE 128
432 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
433 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
436 void doPragma (int op, char *cp)
441 struct options *optionsp;
442 struct optimize *optimizep;
444 optionsp = Safe_malloc(sizeof (struct options));
446 STACK_PUSH(options_stack, optionsp);
448 optimizep = Safe_malloc(sizeof (struct optimize));
449 *optimizep = optimize;
450 STACK_PUSH(optimize_stack, optimizep);
456 struct options *optionsp;
457 struct optimize *optimizep;
459 optionsp = STACK_POP(options_stack);
463 optimizep = STACK_POP(optimize_stack);
464 optimize = *optimizep;
465 Safe_free(optimizep);
470 optimize.loopInduction = 0 ;
474 optimize.loopInvariant = 0 ;
478 optimize.loopInduction = 1 ;
482 options.stackAuto = 1;
486 optimize.noJTabBoundary = 1;
490 optimize.global_cse = 0;
494 options.noOverlay = 1;
498 options.lessPedantic = 1;
504 /* append to the functions already listed
506 for (; options.calleeSaves[i] ;i++);
507 parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
512 parseWithComma(options.excludeRegs, Safe_strdup(cp));
520 optimize.noLoopReverse = 1;
528 int process_pragma(char *s)
530 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
531 #define PRAGMA "#pragma"
533 static struct pragma_s {
538 { "RESTORE", P_RESTORE },
539 { "NOINDUCTION", P_NOINDUCTION },
540 { "NOINVARIANT", P_NOINVARIANT },
541 { "NOLOOPREVERSE", P_LOOPREV },
542 { "INDUCTION", P_INDUCTION },
543 { "STACKAUTO", P_STACKAUTO },
544 { "NOJTBOUND", P_NOJTBOUND },
545 { "NOGCSE", P_NOGCSE },
546 { "NOOVERLAY", P_NOOVERLAY },
547 { "CALLEE-SAVES", P_CALLEE_SAVES },
548 { "EXCLUDE", P_EXCLUDE },
550 { "OVERLAY", P_OVERLAY_ },
551 { "LESS_PEDANTIC", P_LESSPEDANTIC },
556 /* find the pragma */
557 while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
559 s += (sizeof PRAGMA) - 1;
561 /* look for the directive */
566 /* look for the end of the directive */
567 while ((!isspace(*s)) && (*s != '\n'))
570 /* First give the port a chance */
571 if (port->process_pragma && !port->process_pragma(cp))
574 for (i = 0; i < NELEM(pragma_tbl); i++) {
575 /* now compare and do what needs to be done */
576 size_t len = strlen(pragma_tbl[i].name);
578 if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
579 doPragma(pragma_tbl[i].id, cp + len);
584 werror(W_UNKNOWN_PRAGMA,cp);
588 /* will return 1 if the string is a part
589 of a target specific keyword */
590 int isTargetKeyword(char *s)
594 if (port->keywords == NULL)
596 for ( i = 0 ; port->keywords[i] ; i++ ) {
597 if (strcmp(port->keywords[i],s) == 0)
604 extern int fatalError;
610 if (yylineno && filename) {
611 fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
616 // this comes from an empy file, no problem