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 "shadowregs" { count(); TKEYWORD(SHADOWREGS); }
118 "wparam" { count(); TKEYWORD(WPARAM); }
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[0-7]*{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
146 [1-9]{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++ ; ignoreTypedefType = 0; return('{'); }
175 "}" { count(); NestLevel--; return('}'); }
176 "," { count(); return(','); }
177 ":" { count(); return(':'); }
178 "=" { count(); return('='); }
179 "(" { count(); ignoreTypedefType = 0; 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 ^#pragma.*"\n" { count(); process_pragma(yytext); }
198 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(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 /* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
218 #define yytext_ptr yytext
222 static int checkCurrFile (char *s)
227 /* skip '#' character */
231 /* check if this is a #line
232 this is not standard and can be removed in the future */
233 #define LINE_STR "line"
234 #define LINE_LEN ((sizeof LINE_STR) - 1)
236 if (strncmp(s, LINE_STR, LINE_LEN) == 0)
239 /* get the line number */
240 lNum = strtol(s, &tptr, 10);
241 if (tptr == s || !isspace(*tptr))
245 /* now see if we have a file name */
246 while (*s != '\"' && *s)
249 /* if we don't have a filename then */
250 /* set the current line number to */
251 /* line number if printFlag is on */
253 lineno = mylineno = lNum;
257 /* if we have a filename then check */
258 /* if it is "standard in" if yes then */
259 /* get the currentfile name info */
262 /* in c1mode fullSrcFileName is NULL */
263 if (fullSrcFileName &&
264 strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
265 lineno = mylineno = lNum;
266 currFname = fullSrcFileName;
269 /* mark the end of the filename */
270 while (*s != '"') s++;
272 currFname = strdup (sb);
273 lineno = mylineno = lNum;
275 filename = currFname ;
282 static void count(void)
285 for (i = 0; yytext[i] != '\0'; i++) {
286 if (yytext[i] == '\n') {
291 if (yytext[i] == '\t')
292 column += 8 - (column % 8);
299 static int check_type(void)
301 symbol *sym = findSym(SymbolTab, NULL, yytext);
303 /* check if it is in the table as a typedef */
304 if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
305 && SPEC_TYPEDEF (sym->etype)) {
306 strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
310 strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
316 * Change by JTV 2001-05-19 to not concantenate strings
317 * to support ANSI hex and octal escape sequences in string literals
320 static char *stringLiteral(void)
322 #define STR_BUF_CHUNCK_LEN 1024
324 static struct dbuf_s dbuf;
328 dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
330 dbuf_set_size(&dbuf, 0);
332 dbuf_append(&dbuf, "\"", 1);
333 /* put into the buffer till we hit the first \" */
335 while ((ch = input()) != 0) {
338 /* if it is a \ then escape char's are allowed */
341 /* \<newline> is a continuator */
348 dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
350 break; /* carry on */
353 /* if new line we have a new line break, which is illegal */
354 werror(W_NEWLINE_IN_STRING);
355 dbuf_append(&dbuf, "\n", 1);
361 /* if this is a quote then we have work to do */
362 /* find the next non whitespace character */
363 /* if that is a double quote then carry on */
364 dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
365 while ((ch = input()) && (isspace(ch) || ch == '\\')) {
368 if ((ch = input()) != '\n') {
369 werror(W_STRAY_BACKSLASH, column);
395 dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
400 return (char *)dbuf_c_str(&dbuf);
419 P_OVERLAY_, /* I had a strange conflict with P_OVERLAY while */
420 /* cross-compiling for MINGW32 with gcc 3.2 */
428 /* SAVE/RESTORE stack */
429 #define SAVE_RESTORE_SIZE 128
431 STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
432 STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
433 STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
436 * cloneXxx functions should be updated every time a new set is
437 * added to the options or optimize structure!
440 static struct options *cloneOptions(struct options *opt)
442 struct options *new_opt;
444 new_opt = Safe_malloc(sizeof (struct options));
446 /* clone scalar values */
450 new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
451 new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
452 /* not implemented yet: */
453 /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
458 static struct optimize *cloneOptimize(struct optimize *opt)
460 struct optimize *new_opt;
462 new_opt = Safe_malloc(sizeof (struct optimize));
464 /* clone scalar values */
470 static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
472 struct SDCCERRG *new_val;
474 new_val = Safe_malloc(sizeof (struct SDCCERRG));
476 /* clone scalar values */
482 static void copyAndFreeOptions(struct options *dest, struct options *src)
484 /* delete dest sets */
485 deleteSet(&dest->calleeSavesSet);
486 deleteSet(&dest->excludeRegsSet);
487 /* not implemented yet: */
488 /* deleteSet(&dest->olaysSet); */
490 /* copy src to dest */
496 static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
498 /* copy src to dest */
504 static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
506 /* copy src to dest */
512 static void doPragma(int op, char *cp)
519 STACK_PUSH(options_stack, cloneOptions(&options));
520 STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
521 STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
527 struct options *optionsp;
528 struct optimize *optimizep;
529 struct SDCCERRG *sdccerrgp;
531 optionsp = STACK_POP(options_stack);
532 copyAndFreeOptions(&options, optionsp);
534 optimizep = STACK_POP(optimize_stack);
535 copyAndFreeOptimize(&optimize, optimizep);
537 sdccerrgp = STACK_POP(SDCCERRG_stack);
538 copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
543 optimize.loopInduction = 0;
547 optimize.loopInvariant = 0;
551 optimize.loopInduction = 1;
555 options.stackAuto = 1;
559 optimize.noJTabBoundary = 1;
563 optimize.global_cse = 0;
567 options.noOverlay = 1;
571 options.lessPedantic = 1;
572 setErrorLogLevel(ERROR_LEVEL_WARNING);
576 /* append to the functions already listed
578 setParseWithComma(&options.calleeSavesSet, cp);
583 deleteSet(&options.excludeRegsSet);
584 setParseWithComma(&options.excludeRegsSet, cp);
593 optimize.noLoopReverse = 1;
600 if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
602 setWarningDisabled(i);
607 optimize.codeSpeed = 1;
608 optimize.codeSize = 0;
612 optimize.codeSpeed = 0;
613 optimize.codeSize = 1;
616 case P_OPTCODEBALANCED:
617 optimize.codeSpeed = 0;
618 optimize.codeSize = 0;
624 static int process_pragma(char *s)
626 #define NELEM(x) (sizeof (x) / sizeof (x)[0])
627 #define PRAGMA_STR "#pragma"
628 #define PRAGMA_LEN ((sizeof PRAGMA_STR) - 1)
630 static struct pragma_s
636 { "save", P_SAVE, 0 },
637 { "restore", P_RESTORE, 0 },
638 { "noinduction", P_NOINDUCTION, 0 },
639 { "noinvariant", P_NOINVARIANT, 0 },
640 { "noloopreverse", P_LOOPREV, 0 },
641 { "induction", P_INDUCTION, 0 },
642 { "stackauto", P_STACKAUTO, 0 },
643 { "nojtbound", P_NOJTBOUND, 0 },
644 { "nogcse", P_NOGCSE, 0 },
645 { "nooverlay", P_NOOVERLAY, 0 },
646 { "callee_saves", P_CALLEE_SAVES, 0 },
647 { "exclude", P_EXCLUDE, 0 },
648 { "noiv", P_NOIV, 0 },
649 { "overlay", P_OVERLAY_, 0 },
650 { "less_pedantic", P_LESSPEDANTIC, 0 },
651 { "disable_warning",P_DISABLEWARN, 0 },
652 { "opt_code_speed", P_OPTCODESPEED, 0 },
653 { "opt_code_size", P_OPTCODESIZE, 0 },
654 { "opt_code_balanced", P_OPTCODEBALANCED, 0 },
657 * The following lines are deprecated pragmas,
658 * only for bacward compatibility.
659 * They should be removed in next major release after 1.4.0
662 { "SAVE", P_SAVE, 1 },
663 { "RESTORE", P_RESTORE, 1 },
664 { "NOINDUCTION", P_NOINDUCTION, 1 },
665 { "NOINVARIANT", P_NOINVARIANT, 1 },
666 { "NOLOOPREVERSE", P_LOOPREV, 1 },
667 { "INDUCTION", P_INDUCTION, 1 },
668 { "STACKAUTO", P_STACKAUTO, 1 },
669 { "NOJTBOUND", P_NOJTBOUND, 1 },
670 { "NOGCSE", P_NOGCSE, 1 },
671 { "NOOVERLAY", P_NOOVERLAY, 1 },
672 { "CALLEE-SAVES", P_CALLEE_SAVES, 1 },
673 { "EXCLUDE", P_EXCLUDE, 1 },
674 { "NOIV", P_NOIV, 1 },
675 { "OVERLAY", P_OVERLAY_, 1 },
676 { "LESS_PEDANTIC", P_LESSPEDANTIC, 1 },
681 /* find the pragma */
682 while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
686 /* look for the directive */
691 /* look for the end of the directive */
692 while ((!isspace(*s)) && (*s != '\n'))
695 /* First give the port a chance */
696 if (port->process_pragma && !port->process_pragma(cp))
699 for (i = 0; i < NELEM(pragma_tbl); i++)
701 /* now compare and do what needs to be done */
702 size_t len = strlen(pragma_tbl[i].name);
704 if (strncmp(cp, pragma_tbl[i].name, len) == 0)
706 if (pragma_tbl[i].deprecated != 0)
707 werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
709 doPragma(pragma_tbl[i].id, cp + len);
714 werror(W_UNKNOWN_PRAGMA, cp);
718 /* will return 1 if the string is a part
719 of a target specific keyword */
720 static int isTargetKeyword(char *s)
724 if (port->keywords == NULL)
726 for (i = 0 ; port->keywords[i] ; i++ ) {
727 if (strcmp(port->keywords[i],s) == 0)
736 if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
737 werror(W_SAVE_RESTORE);
746 if (mylineno && filename) {
747 if(options.vc_err_style)
748 fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
749 filename, mylineno, s, yytext, column);
751 fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
752 filename, mylineno, s ,yytext, column);
755 /* this comes from an empy file, no problem */