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 #define TKEYWORDSDCC(token) return (options.std_sdcc && isTargetKeyword(yytext)\
44 ? token : check_type())
46 #define TKEYWORD99(token) return (options.std_c99 ? token : check_type())
48 extern int lineno, column;
49 extern char *filename;
51 /* global definitions */
55 /* local definitions */
56 static struct dbuf_s asmbuff;
58 /* forward declarations */
59 static char *stringLiteral(void);
60 static void count(void);
61 static int process_pragma(char *);
62 static int check_type(void);
63 static int isTargetKeyword(char *s);
64 static int checkCurrFile(char *s);
71 if (!options.std_sdcc && yytext[1] != '_')
73 assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
74 dbuf_init(&asmbuff, INITIAL_INLINEASM);
79 if (!options.std_sdcc && yytext[1] != '_')
81 dbuf_append(&asmbuff, yytext, strlen(yytext));
85 yylval.yyinline = dbuf_c_str(&asmbuff);
86 dbuf_detach(&asmbuff);
93 dbuf_append(&asmbuff, yytext, 1);
96 dbuf_append(&asmbuff, yytext, 1);
98 "at" { count(); TKEYWORDSDCC(AT); }
99 "__at" { count(); TKEYWORD(AT); }
100 "auto" { count(); return(AUTO); }
101 "bit" { count(); TKEYWORDSDCC(BIT); }
102 "__bit" { count(); TKEYWORD(BIT); }
103 "break" { count(); return(BREAK); }
104 "case" { count(); return(CASE); }
105 "char" { count(); return(CHAR); }
106 "code" { count(); TKEYWORDSDCC(CODE); }
107 "__code" { count(); TKEYWORD(CODE); }
108 "const" { count(); return(CONST); }
109 "continue" { count(); return(CONTINUE); }
110 "critical" { count(); TKEYWORDSDCC(CRITICAL); }
111 "__critical" { count(); TKEYWORD(CRITICAL); }
112 "data" { count(); TKEYWORDSDCC(DATA); }
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(); TKEYWORDSDCC(XDATA); }
121 "__far" { count(); TKEYWORD(XDATA); }
122 "eeprom" { count(); TKEYWORDSDCC(EEPROM); }
123 "__eeprom" { count(); TKEYWORD(EEPROM); }
124 "float" { count(); return(FLOAT); }
125 "flash" { count(); TKEYWORDSDCC(CODE); }
126 "__flash" { count(); TKEYWORD(CODE); }
127 "for" { count(); return(FOR); }
128 "goto" { count(); return(GOTO); }
129 "idata" { count(); TKEYWORDSDCC(IDATA); }
130 "__idata" { count(); TKEYWORD(IDATA); }
131 "if" { count(); return(IF); }
132 "int" { count(); return(INT); }
133 "interrupt" { count(); TKEYWORDSDCC(INTERRUPT); }
134 "__interrupt" { count(); TKEYWORD(INTERRUPT); }
135 "nonbanked" { count(); TKEYWORDSDCC(NONBANKED); }
136 "__nonbanked" { count(); TKEYWORD(NONBANKED); }
137 "banked" { count(); TKEYWORDSDCC(BANKED); }
138 "__banked" { count(); TKEYWORD(BANKED); }
139 "long" { count(); return(LONG); }
140 "near" { count(); TKEYWORDSDCC(DATA); }
141 "__near" { count(); TKEYWORD(DATA); }
142 "pdata" { count(); TKEYWORDSDCC(PDATA); }
143 "__pdata" { count(); TKEYWORD(PDATA); }
144 "reentrant" { count(); TKEYWORDSDCC(REENTRANT); }
145 "__reentrant" { count(); TKEYWORD(REENTRANT); }
146 "shadowregs" { count(); TKEYWORDSDCC(SHADOWREGS); }
147 "__shadowregs" { count(); TKEYWORD(SHADOWREGS); }
148 "wparam" { count(); TKEYWORDSDCC(WPARAM); }
149 "__wparam" { count(); TKEYWORD(WPARAM); }
150 "register" { count(); return(REGISTER); }
151 "return" { count(); return(RETURN); }
152 "sfr" { count(); TKEYWORDSDCC(SFR); }
153 "__sfr" { count(); TKEYWORD(SFR); }
154 "sbit" { count(); TKEYWORDSDCC(SBIT); }
155 "__sbit" { count(); TKEYWORD(SBIT); }
156 "short" { count(); return(SHORT); }
157 "signed" { count(); return(SIGNED); }
158 "sizeof" { count(); return(SIZEOF); }
159 "sram" { count(); TKEYWORDSDCC(XDATA); }
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(); TKEYWORDSDCC(USING); }
170 "__using" { count(); TKEYWORD(USING); }
171 "_naked" { count(); TKEYWORDSDCC(NAKED); }
172 "__naked" { count(); TKEYWORD(NAKED); }
173 "while" { count(); return(WHILE); }
174 "xdata" { count(); TKEYWORDSDCC(XDATA); }
175 "__xdata" { count(); TKEYWORD(XDATA); }
176 "..." { count(); return(VAR_ARGS); }
177 "__typeof" { count(); return TYPEOF; }
178 "_JavaNative" { count(); TKEYWORD(JAVANATIVE); }
179 "_overlay" { count(); TKEYWORDSDCC(OVERLAY); }
180 "__overlay" { count(); TKEYWORD(OVERLAY); }
181 "inline" { count(); TKEYWORD99(INLINE); }
182 "restrict" { count(); TKEYWORD99(RESTRICT); }
183 {L}({L}|{D})* { count(); return(check_type()); }
184 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
185 0[0-7]*{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
186 [1-9]{D}*{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
187 '(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */ }
188 {D}+{E}{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
189 {D}*"."{D}+({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
190 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
191 \" { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
192 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
193 "<<=" { count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN); }
194 "+=" { count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN); }
195 "-=" { count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN); }
196 "*=" { count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN); }
197 "/=" { count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN); }
198 "%=" { count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN); }
199 "&=" { count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN); }
200 "^=" { count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN); }
201 "|=" { count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN); }
202 ">>" { count(); return(RIGHT_OP); }
203 "<<" { count(); return(LEFT_OP); }
204 "++" { count(); return(INC_OP); }
205 "--" { count(); return(DEC_OP); }
206 "->" { count(); return(PTR_OP); }
207 "&&" { count(); return(AND_OP); }
208 "||" { count(); return(OR_OP); }
209 "<=" { count(); return(LE_OP); }
210 ">=" { count(); return(GE_OP); }
211 "==" { count(); return(EQ_OP); }
212 "!=" { count(); return(NE_OP); }
213 ";" { count(); return(';'); }
214 "{" { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
215 "}" { count(); NestLevel--; return('}'); }
216 "," { count(); return(','); }
217 ":" { count(); return(':'); }
218 "=" { count(); return('='); }
219 "(" { count(); ignoreTypedefType = 0; 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 "+" { count(); return('+'); }
229 "*" { count(); return('*'); }
230 "/" { count(); return('/'); }
231 "%" { count(); return('%'); }
232 "<" { count(); return('<'); }
233 ">" { count(); return('>'); }
234 "^" { count(); return('^'); }
235 "|" { count(); return('|'); }
236 "?" { count(); return('?'); }
237 ^#pragma.*"\n" { count(); process_pragma(yytext); }
238 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
240 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
241 ^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
244 [ \t\v\f] { count(); }
248 /* that could have been removed by the preprocessor anyway */
249 werror (W_STRAY_BACKSLASH, column);
256 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
258 #define yytext_ptr yytext
262 static int checkCurrFile (char *s)
267 /* skip '#' character */
271 /* check if this is a #line
272 this is not standard and can be removed in the future */
273 #define LINE_STR "line"
274 #define LINE_LEN ((sizeof LINE_STR) - 1)
276 if (strncmp(s, LINE_STR, LINE_LEN) == 0)
279 /* get the line number */
280 lNum = strtol(s, &tptr, 10);
281 if (tptr == s || !isspace(*tptr))
285 /* now see if we have a file name */
286 while (*s != '\"' && *s)
289 /* if we don't have a filename then */
290 /* set the current line number to */
291 /* line number if printFlag is on */
293 lineno = mylineno = lNum;
297 /* if we have a filename then check */
298 /* if it is "standard in" if yes then */
299 /* get the currentfile name info */
302 /* in c1mode fullSrcFileName is NULL */
303 if (fullSrcFileName &&
304 strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
305 lineno = mylineno = lNum;
306 currFname = fullSrcFileName;
309 /* mark the end of the filename */
310 while (*s != '"') s++;
312 currFname = strdup (sb);
313 lineno = mylineno = lNum;
315 filename = currFname ;
322 static void count(void)
325 for (i = 0; yytext[i] != '\0'; i++) {
326 if (yytext[i] == '\n') {
331 if (yytext[i] == '\t')
332 column += 8 - (column % 8);
339 static int check_type(void)
341 symbol *sym = findSym(SymbolTab, NULL, yytext);
343 /* check if it is in the table as a typedef */
344 if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
345 && SPEC_TYPEDEF (sym->etype)) {
346 strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
350 strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
356 * Change by JTV 2001-05-19 to not concantenate strings
357 * to support ANSI hex and octal escape sequences in string literals
360 static char *stringLiteral(void)
362 #define STR_BUF_CHUNCK_LEN 1024
364 static struct dbuf_s dbuf;
368 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
370 dbuf_set_size(&dbuf, 0);
372 dbuf_append(&dbuf, "\"", 1);
373 /* put into the buffer till we hit the first \" */
375 while ((ch = input()) != 0) {
378 /* if it is a \ then escape char's are allowed */
381 /* \<newline> is a continuator */
388 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
390 break; /* carry on */
393 /* if new line we have a new line break, which is illegal */
394 werror(W_NEWLINE_IN_STRING);
395 dbuf_append(&dbuf, "\n", 1);
401 /* if this is a quote then we have work to do */
402 /* find the next non whitespace character */
403 /* if that is a double quote then carry on */
404 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
405 while ((ch = input()) && (isspace(ch) || ch == '\\')) {
408 if ((ch = input()) != '\n') {
409 werror(W_STRAY_BACKSLASH, column);
435 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
440 return (char *)dbuf_c_str(&dbuf);
459 P_OVERLAY_, /* I had a strange conflict with P_OVERLAY while */
460 /* cross-compiling for MINGW32 with gcc 3.2 */
472 /* SAVE/RESTORE stack */
473 #define SAVE_RESTORE_SIZE 128
475 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
476 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
477 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
480 * cloneXxx functions should be updated every time a new set is
481 * added to the options or optimize structure!
484 static struct options *cloneOptions(struct options *opt)
486 struct options *new_opt;
488 new_opt = Safe_malloc(sizeof (struct options));
490 /* clone scalar values */
494 new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
495 new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
496 /* not implemented yet: */
497 /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
502 static struct optimize *cloneOptimize(struct optimize *opt)
504 struct optimize *new_opt;
506 new_opt = Safe_malloc(sizeof (struct optimize));
508 /* clone scalar values */
514 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
516 struct SDCCERRG *new_val;
518 new_val = Safe_malloc(sizeof (struct SDCCERRG));
520 /* clone scalar values */
526 static void copyAndFreeOptions(struct options *dest, struct options *src)
528 /* delete dest sets */
529 deleteSet(&dest->calleeSavesSet);
530 deleteSet(&dest->excludeRegsSet);
531 /* not implemented yet: */
532 /* deleteSet(&dest->olaysSet); */
534 /* copy src to dest */
540 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
542 /* copy src to dest */
548 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
550 /* copy src to dest */
556 static void doPragma(int op, char *cp)
563 STACK_PUSH(options_stack, cloneOptions(&options));
564 STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
565 STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
571 struct options *optionsp;
572 struct optimize *optimizep;
573 struct SDCCERRG *sdccerrgp;
575 optionsp = STACK_POP(options_stack);
576 copyAndFreeOptions(&options, optionsp);
578 optimizep = STACK_POP(optimize_stack);
579 copyAndFreeOptimize(&optimize, optimizep);
581 sdccerrgp = STACK_POP(SDCCERRG_stack);
582 copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
587 optimize.loopInduction = 0;
591 optimize.loopInvariant = 0;
595 optimize.loopInduction = 1;
599 options.stackAuto = 1;
603 optimize.noJTabBoundary = 1;
607 optimize.global_cse = 0;
611 options.noOverlay = 1;
615 options.lessPedantic = 1;
616 setErrorLogLevel(ERROR_LEVEL_WARNING);
620 /* append to the functions already listed
622 setParseWithComma(&options.calleeSavesSet, cp);
627 deleteSet(&options.excludeRegsSet);
628 setParseWithComma(&options.excludeRegsSet, cp);
637 optimize.noLoopReverse = 1;
644 if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
646 setWarningDisabled(i);
651 optimize.codeSpeed = 1;
652 optimize.codeSize = 0;
656 optimize.codeSpeed = 0;
657 optimize.codeSize = 1;
660 case P_OPTCODEBALANCED:
661 optimize.codeSpeed = 0;
662 optimize.codeSize = 0;
667 options.std_sdcc = 0;
672 options.std_sdcc = 0;
677 options.std_sdcc = 1;
682 options.std_sdcc = 1;
687 static int process_pragma(char *s)
689 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
690 #define PRAGMA_STR "#pragma"
691 #define PRAGMA_LEN ((sizeof PRAGMA_STR) - 1)
693 static struct pragma_s
699 { "save", P_SAVE, 0 },
700 { "restore", P_RESTORE, 0 },
701 { "noinduction", P_NOINDUCTION, 0 },
702 { "noinvariant", P_NOINVARIANT, 0 },
703 { "noloopreverse", P_LOOPREV, 0 },
704 { "induction", P_INDUCTION, 0 },
705 { "stackauto", P_STACKAUTO, 0 },
706 { "nojtbound", P_NOJTBOUND, 0 },
707 { "nogcse", P_NOGCSE, 0 },
708 { "nooverlay", P_NOOVERLAY, 0 },
709 { "callee_saves", P_CALLEE_SAVES, 0 },
710 { "exclude", P_EXCLUDE, 0 },
711 { "noiv", P_NOIV, 0 },
712 { "overlay", P_OVERLAY_, 0 },
713 { "less_pedantic", P_LESSPEDANTIC, 0 },
714 { "disable_warning",P_DISABLEWARN, 0 },
715 { "opt_code_speed", P_OPTCODESPEED, 0 },
716 { "opt_code_size", P_OPTCODESIZE, 0 },
717 { "opt_code_balanced", P_OPTCODEBALANCED, 0 },
718 { "std_c89", P_STD_C89, 0 },
719 { "std_c99", P_STD_C99, 0 },
720 { "std_sdcc89", P_STD_SDCC89, 0 },
721 { "std_sdcc99", P_STD_SDCC99, 0 },
724 * The following lines are deprecated pragmas,
725 * only for bacward compatibility.
726 * They should be removed in next major release after 1.4.0
729 { "SAVE", P_SAVE, 1 },
730 { "RESTORE", P_RESTORE, 1 },
731 { "NOINDUCTION", P_NOINDUCTION, 1 },
732 { "NOINVARIANT", P_NOINVARIANT, 1 },
733 { "NOLOOPREVERSE", P_LOOPREV, 1 },
734 { "INDUCTION", P_INDUCTION, 1 },
735 { "STACKAUTO", P_STACKAUTO, 1 },
736 { "NOJTBOUND", P_NOJTBOUND, 1 },
737 { "NOGCSE", P_NOGCSE, 1 },
738 { "NOOVERLAY", P_NOOVERLAY, 1 },
739 { "CALLEE-SAVES", P_CALLEE_SAVES, 1 },
740 { "EXCLUDE", P_EXCLUDE, 1 },
741 { "NOIV", P_NOIV, 1 },
742 { "OVERLAY", P_OVERLAY_, 1 },
743 { "LESS_PEDANTIC", P_LESSPEDANTIC, 1 },
748 /* find the pragma */
749 while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
753 /* look for the directive */
758 /* look for the end of the directive */
759 while ((!isspace(*s)) && (*s != '\n'))
762 /* skip separating whitespace */
763 while (isspace(*s) && (*s != '\n'))
766 /* First give the port a chance */
767 if (port->process_pragma && !port->process_pragma(cp))
770 for (i = 0; i < NELEM(pragma_tbl); i++)
772 /* now compare and do what needs to be done */
773 size_t len = strlen(pragma_tbl[i].name);
775 if (strncmp(cp, pragma_tbl[i].name, len) == 0)
777 if (pragma_tbl[i].deprecated != 0)
778 werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
780 doPragma(pragma_tbl[i].id, s);
785 werror(W_UNKNOWN_PRAGMA, cp);
789 /* will return 1 if the string is a part
790 of a target specific keyword */
791 static int isTargetKeyword(char *s)
795 if (port->keywords == NULL)
798 if (s[0] == '_' && s[1] == '_')
800 /* Keywords in the port's array have either 0 or 1 underscore, */
801 /* so skip over the appropriate number of chars when comparing */
802 for (i = 0 ; port->keywords[i] ; i++ )
804 if (port->keywords[i][0] == '_' &&
805 strcmp(port->keywords[i],s+1) == 0)
807 else if (strcmp(port->keywords[i],s+2) == 0)
813 for (i = 0 ; port->keywords[i] ; i++ )
815 if (strcmp(port->keywords[i],s) == 0)
825 if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
826 werror(W_SAVE_RESTORE);
835 if (mylineno && filename) {
836 if(options.vc_err_style)
837 fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
838 filename, mylineno, s, yytext, column);
840 fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
841 filename, mylineno, s ,yytext, column);
844 /* this comes from an empy file, no problem */