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 -------------------------------------------------------------------------*/
39 char *stringLiteral();
42 extern int lineno, column;
43 extern char *filename ;
44 extern char *fullSrcFileName ;
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 ;
87 asmp = asmbuff = Safe_realloc (asmbuff, INITIAL_INLINEASM);
88 asmbuffSize=INITIAL_INLINEASM;
94 yylval.yyinline = Safe_alloc (strlen(asmbuff)+1);
95 strcpy(yylval.yyinline,asmbuff);
100 if (asmp-asmbuff >= asmbuffSize-2) {
101 // increase the buffersize with 50%
102 int size=asmp-asmbuff;
103 asmbuffSize=asmbuffSize*3/2;
104 asmbuff = Safe_realloc (asmbuff, asmbuffSize);
111 if (asmp-asmbuff >= asmbuffSize-3) {
112 // increase the buffersize with 50%
113 int size=asmp-asmbuff;
114 asmbuffSize=asmbuffSize*3/2;
115 asmbuff = Safe_realloc (asmbuff, asmbuffSize);
120 "at" { count(); TKEYWORD(AT) ; }
121 "auto" { count(); return(AUTO); }
122 "bit" { count(); TKEYWORD(BIT) ; }
123 "break" { count(); return(BREAK); }
124 "case" { count(); return(CASE); }
125 "char" { count(); return(CHAR); }
126 "code" { count(); TKEYWORD(CODE); }
127 "const" { count(); return(CONST); }
128 "continue" { count(); return(CONTINUE); }
129 "critical" { count(); TKEYWORD(CRITICAL); }
130 "data" { count(); TKEYWORD(DATA); }
131 "default" { count(); return(DEFAULT); }
132 "do" { count(); return(DO); }
133 "double" { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
134 "else" { count(); return(ELSE); }
135 "enum" { count(); return(ENUM); }
136 "extern" { count(); return(EXTERN); }
137 "far" { count(); TKEYWORD(XDATA); }
138 "eeprom" { count(); TKEYWORD(EEPROM); }
139 "float" { count(); return(FLOAT); }
140 "flash" { count(); TKEYWORD(CODE);}
141 "for" { count(); return(FOR); }
142 "goto" { count(); return(GOTO); }
143 "idata" { count(); TKEYWORD(IDATA);}
144 "if" { count(); return(IF); }
145 "int" { count(); return(INT); }
146 "interrupt" { count(); return(INTERRUPT);}
147 "nonbanked" { count(); TKEYWORD(NONBANKED);}
148 "banked" { count(); TKEYWORD(BANKED);}
149 "long" { count(); return(LONG); }
150 "near" { count(); TKEYWORD(DATA);}
151 "pdata" { count(); TKEYWORD(PDATA); }
152 "reentrant" { count(); TKEYWORD(REENTRANT);}
153 "register" { count(); return(REGISTER); }
154 "return" { count(); return(RETURN); }
155 "sfr" { count(); TKEYWORD(SFR) ; }
156 "sbit" { count(); TKEYWORD(SBIT) ; }
157 "short" { count(); return(SHORT); }
158 "signed" { count(); return(SIGNED); }
159 "sizeof" { count(); return(SIZEOF); }
160 "sram" { count(); TKEYWORD(XDATA);}
161 "static" { count(); return(STATIC); }
162 "struct" { count(); return(STRUCT); }
163 "switch" { count(); return(SWITCH); }
164 "typedef" { count(); return(TYPEDEF); }
165 "union" { count(); return(UNION); }
166 "unsigned" { count(); return(UNSIGNED); }
167 "void" { count(); return(VOID); }
168 "volatile" { count(); return(VOLATILE); }
169 "using" { count(); TKEYWORD(USING); }
170 "_naked" { count(); TKEYWORD(NAKED); }
171 "while" { count(); return(WHILE); }
172 "xdata" { count(); TKEYWORD(XDATA); }
173 "..." { count(); return(VAR_ARGS);}
174 {L}({L}|{D})* { count(); return(check_type()); }
175 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
176 0{D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
177 {D}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
178 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
179 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
180 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
181 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
182 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
183 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
184 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; }
185 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; }
186 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; }
187 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; }
188 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; }
189 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; }
190 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; }
191 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; }
192 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; }
193 ">>" { count(); return(RIGHT_OP); }
194 "<<" { count(); return(LEFT_OP); }
195 "++" { count(); return(INC_OP); }
196 "--" { count(); return(DEC_OP); }
197 "->" { count(); return(PTR_OP); }
198 "&&" { count(); return(AND_OP); }
199 "||" { count(); return(OR_OP); }
200 "<=" { count(); return(LE_OP); }
201 ">=" { count(); return(GE_OP); }
202 "==" { count(); return(EQ_OP); }
203 "!=" { count(); return(NE_OP); }
204 ";" { count(); return(';'); }
205 "{" { count(); NestLevel++ ; return('{'); }
206 "}" { count(); NestLevel--; return('}'); }
207 "," { count(); return(','); }
208 ":" { count(); return(':'); }
209 "=" { count(); return('='); }
210 "(" { count(); return('('); }
211 ")" { count(); return(')'); }
212 "[" { count(); return('['); }
213 "]" { count(); return(']'); }
214 "." { count(); return('.'); }
215 "&" { count(); return('&'); }
216 "!" { count(); return('!'); }
217 "~" { count(); return('~'); }
218 "-" { count(); return('-'); }
219 "+" { count(); return('+'); }
220 "*" { count(); return('*'); }
221 "/" { count(); return('/'); }
222 "%" { count(); return('%'); }
223 "<" { count(); return('<'); }
224 ">" { count(); return('>'); }
225 "^" { count(); return('^'); }
226 "|" { count(); return('|'); }
227 "?" { count(); return('?'); }
228 ^#line.*"\n" { count(); checkCurrFile(yytext); }
229 ^#pragma.*"\n" { count(); process_pragma(yytext); }
231 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
232 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
235 [ \t\v\f] { count(); }
239 // that could have been removed by the preprocessor anyway
240 werror (W_STRAY_BACKSLASH, column);
247 int checkCurrFile ( char *s)
253 /* first check if this is a #line */
254 if ( strncmp(s,"#line",5) )
257 /* get to the line number */
264 sscanf(lineNum,"%d",&lNum);
266 /* now see if we have a file name */
267 while (*s != '\"' && *s)
270 /* if we don't have a filename then */
271 /* set the current line number to */
272 /* line number if printFlag is on */
274 lineno = yylineno = lNum ;
278 /* if we have a filename then check */
279 /* if it is "standard in" if yes then */
280 /* get the currentfile name info */
283 if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
284 lineno = yylineno = lNum;
285 currFname = fullSrcFileName ;
288 /* mark the end of the filename */
289 while (*s != '"') s++;
291 currFname = Safe_alloc (strlen(sb)+1);
292 strcpy(currFname,sb);
293 lineno = yylineno = lNum;
295 filename = currFname ;
305 for (i = 0; yytext[i] != '\0'; i++) {
306 if (yytext[i] == '\n') {
308 lineno = ++yylineno ;
311 if (yytext[i] == '\t')
312 column += 8 - (column % 8);
321 /* check if it is in the typedef table */
322 if (findSym(TypedefTab,NULL,yytext)) {
323 strcpy(yylval.yychar,yytext);
327 strcpy (yylval.yychar,yytext);
332 char strLitBuff[2048]; // TODO: this is asking for the next bug :)
335 * Change by JTV 2001-05-19 to not concantenate strings
336 * to support ANSI hex and octal escape sequences in string liteals
339 char *stringLiteral () {
341 char *str = strLitBuff;
344 /* put into the buffer till we hit the first \" */
350 break; /* end of input */
352 /* if it is a \ then escape char's are allowed */
356 /* \<newline> is a continuator */
361 *str++ = '\\'; /* backslash in place */
362 *str++ = ch; /* get the escape char, no further check */
363 continue; /* carry on */
366 /* if new line we have a new line break, which is illegal */
368 werror (W_NEWLINE_IN_STRING);
375 /* if this is a quote then we have work to do */
376 /* find the next non whitespace character */
377 /* if that is a double quote then carry on */
379 *str++ = ch ; /* Pass end of this string or substring to evaluator */
380 while ((ch = input()) && (isspace(ch) || ch=='\\')) {
383 if ((ch=input())!='\n') {
384 werror (W_STRAY_BACKSLASH, column);
405 *str++ = ch; /* Put next substring introducer into output string */
412 void doPragma (int op, char *cp)
416 memcpy(&save_options,&options,sizeof(options));
417 memcpy(&save_optimize,&optimize,sizeof(optimize));
420 memcpy(&options,&save_options,sizeof(options));
421 memcpy(&optimize,&save_optimize,sizeof(optimize));
424 optimize.loopInduction = 0 ;
427 optimize.loopInvariant = 0 ;
430 optimize.loopInduction = 1 ;
433 options.stackAuto = 1;
436 optimize.noJTabBoundary = 1;
439 optimize.global_cse = 0;
442 options.noOverlay = 1;
447 /* append to the functions already listed
449 for (; options.calleeSaves[i] ;i++);
450 parseWithComma(&options.calleeSaves[i],strdup(cp));
454 parseWithComma(options.excludeRegs,strdup(cp));
457 optimize.noLoopReverse = 1;
462 int process_pragma(char *s)
465 /* find the pragma */
466 while (strncmp(s,"#pragma",7))
470 /* look for the directive */
471 while(isspace(*s)) s++;
474 /* look for the end of the directive */
475 while ((! isspace(*s)) &&
479 /* First give the port a chance */
480 if (port->process_pragma && !port->process_pragma(cp))
483 /* now compare and do what needs to be done */
484 if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
485 doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
489 if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
490 doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
494 if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
495 doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
499 if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
500 doPragma (P_NOINVARIANT,NULL) ;
504 if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
505 doPragma (P_INDUCTION,NULL) ;
509 if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
510 doPragma (P_STACKAUTO,NULL);
514 if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
515 doPragma (P_NOJTBOUND,NULL);
519 if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
520 doPragma (P_NOGCSE,NULL);
524 if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
525 doPragma (P_NOOVERLAY,NULL);
529 if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
530 doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
534 if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
535 doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
539 if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
540 doPragma(P_LOOPREV,NULL);
544 werror(W_UNKNOWN_PRAGMA,cp);
548 /* will return 1 if the string is a part
549 of a target specific keyword */
550 int isTargetKeyword(char *s)
554 if (port->keywords == NULL)
556 for ( i = 0 ; port->keywords[i] ; i++ ) {
557 if (strcmp(port->keywords[i],s) == 0)
564 extern int fatalError;
570 if (yylineno && filename)
571 fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",