new value stack system to handle the futur types (long long and floats)
[tinycc/miki.git] / tcc.c
blob2a1f2519833aaa7479d04e3c2c0f850e69813c56
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <math.h>
25 #ifndef CONFIG_TCC_STATIC
26 #include <dlfcn.h>
27 #endif
29 //#define DEBUG
30 /* preprocessor debug */
31 //#define PP_DEBUG
33 /* these sizes are dummy for unix, because malloc() does not use
34 memory when the pages are not used */
35 #define TEXT_SIZE (4*1024*1024)
36 #define DATA_SIZE (4*1024*1024)
38 #define INCLUDE_STACK_SIZE 32
39 #define IFDEF_STACK_SIZE 64
40 #define VSTACK_SIZE 64
41 #define STRING_MAX_SIZE 1024
42 #define INCLUDE_PATHS_MAX 32
44 #define TOK_HASH_SIZE 521
45 #define TOK_ALLOC_INCR 256 /* must be a power of two */
46 #define SYM_HASH_SIZE 263
48 /* token symbol management */
49 typedef struct TokenSym {
50 struct TokenSym *hash_next;
51 int tok; /* token number */
52 int len;
53 char str[1];
54 } TokenSym;
56 /* constant value */
57 typedef union CValue {
58 long double ld;
59 double d;
60 float f;
61 int i;
62 unsigned int ui;
63 struct TokenSym *ts;
64 int tab[1];
65 } CValue;
67 /* value on stack */
68 typedef struct SValue {
69 int t;
70 int c;
71 } SValue;
73 /* symbol management */
74 typedef struct Sym {
75 int v; /* symbol token */
76 int t; /* associated type */
77 int c; /* associated number */
78 struct Sym *next; /* next related symbol */
79 struct Sym *prev; /* prev symbol in stack */
80 struct Sym *hash_next; /* next symbol in hash table */
81 } Sym;
83 typedef struct SymStack {
84 struct Sym *top;
85 struct Sym *hash[SYM_HASH_SIZE];
86 } SymStack;
88 /* relocation entry (currently only used for functions or variables */
89 typedef struct Reloc {
90 int type; /* type of relocation */
91 int addr; /* address of relocation */
92 struct Reloc *next; /* next relocation */
93 } Reloc;
95 #define RELOC_ADDR32 1 /* 32 bits relocation */
96 #define RELOC_REL32 2 /* 32 bits relative relocation */
99 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
100 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
101 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
103 #define FUNC_NEW 1 /* ansi function prototype */
104 #define FUNC_OLD 2 /* old function prototype */
105 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
107 /* field 'Sym.t' for macros */
108 #define MACRO_OBJ 0 /* object like macro */
109 #define MACRO_FUNC 1 /* function like macro */
111 /* type_decl() types */
112 #define TYPE_ABSTRACT 1 /* type without variable */
113 #define TYPE_DIRECT 2 /* type with variable */
115 typedef struct {
116 FILE *file;
117 char *filename;
118 int line_num;
119 } IncludeFile;
121 /* parser */
122 FILE *file;
123 int line_num;
124 int ch, ch1, tok, tok1;
125 CValue tokc, tok1c;
127 /* loc : local variable index
128 glo : global variable index
129 ind : output code ptr
130 rsym: return symbol
131 prog: output code
132 anon_sym: anonymous symbol index
134 int rsym, anon_sym,
135 prog, ind, loc, glo, const_wanted;
136 int global_expr; /* true if compound literals must be allocated
137 globally (used during initializers parsing */
138 int func_vt, func_vc; /* current function return type (used by
139 return instruction) */
140 int tok_ident;
141 TokenSym **table_ident;
142 TokenSym *hash_ident[TOK_HASH_SIZE];
143 char token_buf[STRING_MAX_SIZE + 1];
144 char *filename, *funcname;
145 /* contains global symbols which remain between each translation unit */
146 SymStack extern_stack;
147 SymStack define_stack, global_stack, local_stack, label_stack;
149 SValue vstack[VSTACK_SIZE], *vtop;
150 int *macro_ptr, *macro_ptr_allocated;
151 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
152 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
153 char *include_paths[INCLUDE_PATHS_MAX];
154 int nb_include_paths;
156 /* use GNU C extensions */
157 int gnu_ext = 1;
159 /* use Tiny C extensions */
160 int tcc_ext = 1;
162 /* The current value can be: */
163 #define VT_VALMASK 0x000f
164 #define VT_CONST 0x000a /* constant in vc
165 (must be first non register value) */
166 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
167 #define VT_LOCAL 0x000c /* offset on stack */
168 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
169 #define VT_JMP 0x000e /* value is the consequence of jmp true */
170 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
171 #define VT_LVAL 0x0010 /* var is an lvalue */
172 #define VT_LVALN -17 /* ~VT_LVAL */
173 #define VT_FORWARD 0x0020 /* value is forward reference
174 (only used for functions) */
175 /* storage */
176 #define VT_EXTERN 0x00000040 /* extern definition */
177 #define VT_STATIC 0x00000080 /* static variable */
178 #define VT_TYPEDEF 0x00000100 /* typedef definition */
180 /* types */
181 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
183 #define VT_BTYPE_SHIFT 9
184 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
185 #define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */
186 #define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */
187 #define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */
188 #define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */
189 #define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */
190 #define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */
191 #define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */
192 #define VT_FLOAT (8 << VT_BTYPE_SHIFT) /* IEEE float */
193 #define VT_DOUBLE (9 << VT_BTYPE_SHIFT) /* IEEE double */
194 #define VT_LDOUBLE (10 << VT_BTYPE_SHIFT) /* IEEE long double */
195 #define VT_BOOL (11 << VT_BTYPE_SHIFT) /* ISOC99 boolean type */
196 #define VT_LLONG (12 << VT_BTYPE_SHIFT) /* 64 bit integer */
197 #define VT_LONG (13 << VT_BTYPE_SHIFT) /* long integer (NEVER
198 USED as type, only
199 during parsing) */
200 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
201 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
202 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
203 #define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
205 #define VT_TYPE 0xfffffe00 /* type mask */
207 /* token values */
209 /* warning: the following compare tokens depend on i386 asm code */
210 #define TOK_ULT 0x92
211 #define TOK_UGE 0x93
212 #define TOK_EQ 0x94
213 #define TOK_NE 0x95
214 #define TOK_ULE 0x96
215 #define TOK_UGT 0x97
216 #define TOK_LT 0x9c
217 #define TOK_GE 0x9d
218 #define TOK_LE 0x9e
219 #define TOK_GT 0x9f
221 #define TOK_LAND 0xa0
222 #define TOK_LOR 0xa1
224 #define TOK_DEC 0xa2
225 #define TOK_MID 0xa3 /* inc/dec, to void constant */
226 #define TOK_INC 0xa4
227 #define TOK_ARROW 0xa7
228 #define TOK_DOTS 0xa8 /* three dots */
229 #define TOK_SHR 0xa9 /* unsigned shift right */
230 #define TOK_UDIV 0xb0 /* unsigned division */
231 #define TOK_UMOD 0xb1 /* unsigned modulo */
232 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
233 #define TOK_NUM 0xb3 /* number in tokc */
234 #define TOK_CCHAR 0xb4 /* char constant in tokc */
235 #define TOK_STR 0xb5 /* pointer to string in tokc */
236 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
237 #define TOK_LCHAR 0xb7
238 #define TOK_LSTR 0xb8
239 #define TOK_CFLOAT 0xb9 /* float constant */
240 #define TOK_CDOUBLE 0xc0 /* double constant */
241 #define TOK_CLDOUBLE 0xc1 /* long double constant */
243 #define TOK_SHL 0x01 /* shift left */
244 #define TOK_SAR 0x02 /* signed shift right */
246 /* assignement operators : normal operator or 0x80 */
247 #define TOK_A_MOD 0xa5
248 #define TOK_A_AND 0xa6
249 #define TOK_A_MUL 0xaa
250 #define TOK_A_ADD 0xab
251 #define TOK_A_SUB 0xad
252 #define TOK_A_DIV 0xaf
253 #define TOK_A_XOR 0xde
254 #define TOK_A_OR 0xfc
255 #define TOK_A_SHL 0x81
256 #define TOK_A_SAR 0x82
258 /* all identificators and strings have token above that */
259 #define TOK_IDENT 256
261 enum {
262 TOK_INT = TOK_IDENT,
263 TOK_VOID,
264 TOK_CHAR,
265 TOK_IF,
266 TOK_ELSE,
267 TOK_WHILE,
268 TOK_BREAK,
269 TOK_RETURN,
270 TOK_FOR,
271 TOK_EXTERN,
272 TOK_STATIC,
273 TOK_UNSIGNED,
274 TOK_GOTO,
275 TOK_DO,
276 TOK_CONTINUE,
277 TOK_SWITCH,
278 TOK_CASE,
280 /* ignored types Must have contiguous values */
281 TOK_CONST,
282 TOK_VOLATILE,
283 TOK_LONG,
284 TOK_REGISTER,
285 TOK_SIGNED,
286 TOK_AUTO,
287 TOK_INLINE,
288 TOK_RESTRICT,
290 /* unsupported type */
291 TOK_FLOAT,
292 TOK_DOUBLE,
293 TOK_BOOL,
295 TOK_SHORT,
296 TOK_STRUCT,
297 TOK_UNION,
298 TOK_TYPEDEF,
299 TOK_DEFAULT,
300 TOK_ENUM,
301 TOK_SIZEOF,
303 /* preprocessor only */
304 TOK_UIDENT, /* first "user" ident (not keyword) */
305 TOK_DEFINE = TOK_UIDENT,
306 TOK_INCLUDE,
307 TOK_IFDEF,
308 TOK_IFNDEF,
309 TOK_ELIF,
310 TOK_ENDIF,
311 TOK_DEFINED,
312 TOK_UNDEF,
313 TOK_ERROR,
314 TOK_LINE,
315 TOK___LINE__,
316 TOK___FILE__,
317 TOK___DATE__,
318 TOK___TIME__,
319 TOK___VA_ARGS__,
321 /* special identifiers */
322 TOK___FUNC__,
323 TOK_MAIN,
326 /* XXX: need to define this to use them in non ISOC99 context */
327 extern float strtof (const char *__nptr, char **__endptr);
328 extern long double strtold (const char *__nptr, char **__endptr);
330 void sum(int l);
331 void next(void);
332 void next_nomacro(void);
333 int expr_const(void);
334 void expr_eq(void);
335 void expr(void);
336 void decl(int l);
337 void decl_initializer(int t, int c, int first, int size_only);
338 int decl_initializer_alloc(int t, int has_init);
339 int gv(void);
340 void move_reg(int r, int s);
341 void save_reg(int r);
342 void vpop(void);
343 void vswap(void);
344 void vdup(void);
345 int get_reg(int rc);
347 void macro_subst(int **tok_str, int *tok_len,
348 Sym **nested_list, int *macro_str);
349 int save_reg_forced(int r);
350 void gen_op(int op);
351 void gen_cast(int t);
352 void vstore(void);
353 int type_size(int t, int *a);
354 int pointed_type(int t);
355 int pointed_size(int t);
356 int ist(void);
357 int type_decl(int *v, int t, int td);
358 void error(const char *fmt, ...);
359 void vset(int t, int v);
361 #include "i386-gen.c"
363 #ifdef CONFIG_TCC_STATIC
365 #define RTLD_LAZY 0x001
366 #define RTLD_NOW 0x002
367 #define RTLD_GLOBAL 0x100
369 /* dummy function for profiling */
370 void *dlopen(const char *filename, int flag)
372 return NULL;
375 const char *dlerror(void)
377 return "error";
380 typedef struct TCCSyms {
381 char *str;
382 void *ptr;
383 } TCCSyms;
385 #define TCCSYM(a) { #a, &a, },
387 /* add the symbol you want here if no dynamic linking is done */
388 static TCCSyms tcc_syms[] = {
389 TCCSYM(printf)
390 TCCSYM(fprintf)
391 TCCSYM(fopen)
392 TCCSYM(fclose)
393 { NULL, NULL },
396 void *dlsym(void *handle, char *symbol)
398 TCCSyms *p;
399 p = tcc_syms;
400 while (p->str != NULL) {
401 if (!strcmp(p->str, symbol))
402 return p->ptr;
403 p++;
405 return NULL;
408 #endif
410 static inline int isid(int c)
412 return (c >= 'a' && c <= 'z') ||
413 (c >= 'A' && c <= 'Z') ||
414 c == '_';
417 static inline int isnum(int c)
419 return c >= '0' & c <= '9';
422 static inline int toup(int c)
424 if (ch >= 'a' && ch <= 'z')
425 return ch - 'a' + 'A';
426 else
427 return ch;
430 void printline(void)
432 IncludeFile *f;
433 for(f = include_stack; f < include_stack_ptr; f++)
434 fprintf(stderr, "In file included from %s:%d:\n",
435 f->filename, f->line_num);
436 fprintf(stderr, "%s:%d: ", filename, line_num);
439 void error(const char *fmt, ...)
441 va_list ap;
442 va_start(ap, fmt);
443 printline();
444 vfprintf(stderr, fmt, ap);
445 fprintf(stderr, "\n");
446 exit(1);
447 va_end(ap);
450 void expect(const char *msg)
452 error("%s expected", msg);
455 void warning(const char *msg)
457 printline();
458 fprintf(stderr, "warning: %s\n", msg);
461 void skip(int c)
463 if (tok != c)
464 error("'%c' expected", c);
465 next();
468 void test_lvalue(void)
470 if (!(vtop->t & VT_LVAL))
471 expect("lvalue");
474 TokenSym *tok_alloc(char *str, int len)
476 TokenSym *ts, **pts, **ptable;
477 int h, i;
479 if (len <= 0)
480 len = strlen(str);
481 h = 1;
482 for(i=0;i<len;i++)
483 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
485 pts = &hash_ident[h];
486 while (1) {
487 ts = *pts;
488 if (!ts)
489 break;
490 if (ts->len == len && !memcmp(ts->str, str, len))
491 return ts;
492 pts = &(ts->hash_next);
495 if (tok_ident >= SYM_FIRST_ANOM)
496 error("memory full");
498 /* expand token table if needed */
499 i = tok_ident - TOK_IDENT;
500 if ((i % TOK_ALLOC_INCR) == 0) {
501 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
502 if (!ptable)
503 error("memory full");
504 table_ident = ptable;
507 ts = malloc(sizeof(TokenSym) + len);
508 if (!ts)
509 error("memory full");
510 table_ident[i] = ts;
511 ts->tok = tok_ident++;
512 ts->len = len;
513 ts->hash_next = NULL;
514 memcpy(ts->str, str, len + 1);
515 *pts = ts;
516 return ts;
519 void add_char(char **pp, int c)
521 char *p;
522 p = *pp;
523 if (c == '\'' || c == '\"' || c == '\\') {
524 /* XXX: could be more precise if char or string */
525 *p++ = '\\';
527 if (c >= 32 && c <= 126) {
528 *p++ = c;
529 } else {
530 *p++ = '\\';
531 if (c == '\n') {
532 *p++ = 'n';
533 } else {
534 *p++ = '0' + ((c >> 6) & 7);
535 *p++ = '0' + ((c >> 3) & 7);
536 *p++ = '0' + (c & 7);
539 *pp = p;
542 /* XXX: buffer overflow */
543 char *get_tok_str(int v, CValue *cv)
545 static char buf[STRING_MAX_SIZE + 1];
546 TokenSym *ts;
547 char *p;
548 int i;
550 if (v == TOK_NUM) {
551 sprintf(buf, "%u", cv->ui);
552 return buf;
553 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
554 p = buf;
555 *p++ = '\'';
556 add_char(&p, cv->i);
557 *p++ = '\'';
558 *p = '\0';
559 return buf;
560 } else if (v == TOK_STR || v == TOK_LSTR) {
561 ts = cv->ts;
562 p = buf;
563 *p++ = '\"';
564 for(i=0;i<ts->len;i++)
565 add_char(&p, ts->str[i]);
566 *p++ = '\"';
567 *p = '\0';
568 return buf;
569 } else if (v < TOK_IDENT) {
570 p = buf;
571 *p++ = v;
572 *p = '\0';
573 return buf;
574 } else if (v < tok_ident) {
575 return table_ident[v - TOK_IDENT]->str;
576 } else {
577 /* should never happen */
578 return NULL;
582 /* push, without hashing */
583 Sym *sym_push2(Sym **ps, int v, int t, int c)
585 Sym *s;
586 s = malloc(sizeof(Sym));
587 if (!s)
588 error("memory full");
589 s->v = v;
590 s->t = t;
591 s->c = c;
592 s->next = NULL;
593 /* add in stack */
594 s->prev = *ps;
595 *ps = s;
596 return s;
599 /* find a symbol and return its associated structure. 's' is the top
600 of the symbol stack */
601 Sym *sym_find2(Sym *s, int v)
603 while (s) {
604 if (s->v == v)
605 return s;
606 s = s->prev;
608 return NULL;
611 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
613 /* find a symbol and return its associated structure. 'st' is the
614 symbol stack */
615 Sym *sym_find1(SymStack *st, int v)
617 Sym *s;
619 s = st->hash[HASH_SYM(v)];
620 while (s) {
621 if (s->v == v)
622 return s;
623 s = s->hash_next;
625 return 0;
628 Sym *sym_push1(SymStack *st, int v, int t, int c)
630 Sym *s, **ps;
631 s = sym_push2(&st->top, v, t, c);
632 /* add in hash table */
633 if (v) {
634 ps = &st->hash[HASH_SYM(v)];
635 s->hash_next = *ps;
636 *ps = s;
638 return s;
641 /* find a symbol in the right symbol space */
642 Sym *sym_find(int v)
644 Sym *s;
645 s = sym_find1(&local_stack, v);
646 if (!s)
647 s = sym_find1(&global_stack, v);
648 return s;
651 /* push a given symbol on the symbol stack */
652 Sym *sym_push(int v, int t, int c)
654 if (local_stack.top)
655 return sym_push1(&local_stack, v, t, c);
656 else
657 return sym_push1(&global_stack, v, t, c);
660 /* pop symbols until top reaches 'b' */
661 void sym_pop(SymStack *st, Sym *b)
663 Sym *s, *ss;
665 s = st->top;
666 while(s != b) {
667 ss = s->prev;
668 /* free hash table entry, except if symbol was freed (only
669 used for #undef symbols) */
670 if (s->v)
671 st->hash[HASH_SYM(s->v)] = s->hash_next;
672 free(s);
673 s = ss;
675 st->top = b;
678 /* undefined a hashed symbol (used for #undef). Its name is set to
679 zero */
680 void sym_undef(SymStack *st, Sym *s)
682 Sym **ss;
683 ss = &st->hash[HASH_SYM(s->v)];
684 while (*ss != NULL) {
685 if (*ss == s)
686 break;
687 ss = &(*ss)->hash_next;
689 *ss = s->hash_next;
690 s->v = 0;
693 /* no need to put that inline */
694 int handle_eof(void)
696 if (include_stack_ptr == include_stack)
697 return -1;
698 /* pop include stack */
699 fclose(file);
700 free(filename);
701 include_stack_ptr--;
702 file = include_stack_ptr->file;
703 filename = include_stack_ptr->filename;
704 line_num = include_stack_ptr->line_num;
705 return 0;
708 /* read next char from current input file */
709 static inline void inp(void)
711 redo:
712 /* faster than fgetc */
713 ch1 = getc_unlocked(file);
714 if (ch1 == -1) {
715 if (handle_eof() < 0)
716 return;
717 else
718 goto redo;
720 if (ch1 == '\n')
721 line_num++;
722 // printf("ch1=%c 0x%x\n", ch1, ch1);
725 /* input with '\\n' handling */
726 static inline void minp(void)
728 redo:
729 ch = ch1;
730 inp();
731 if (ch == '\\' && ch1 == '\n') {
732 inp();
733 goto redo;
735 //printf("ch=%c 0x%x\n", ch, ch);
739 /* same as minp, but also skip comments */
740 void cinp(void)
742 int c;
744 if (ch1 == '/') {
745 inp();
746 if (ch1 == '/') {
747 /* single line C++ comments */
748 inp();
749 while (ch1 != '\n' && ch1 != -1)
750 inp();
751 inp();
752 ch = ' '; /* return space */
753 } else if (ch1 == '*') {
754 /* C comments */
755 inp();
756 while (ch1 != -1) {
757 c = ch1;
758 inp();
759 if (c == '*' && ch1 == '/') {
760 inp();
761 ch = ' '; /* return space */
762 break;
765 } else {
766 ch = '/';
768 } else {
769 minp();
773 void skip_spaces(void)
775 while (ch == ' ' || ch == '\t')
776 cinp();
779 /* skip block of text until #else, #elif or #endif. skip also pairs of
780 #if/#endif */
781 void preprocess_skip()
783 int a;
784 a = 0;
785 while (1) {
786 while (ch != '\n') {
787 if (ch == -1)
788 expect("#endif");
789 cinp();
791 cinp();
792 skip_spaces();
793 if (ch == '#') {
794 cinp();
795 next_nomacro();
796 if (a == 0 &&
797 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
798 break;
799 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
800 a++;
801 else if (tok == TOK_ENDIF)
802 a--;
807 /* return the number of additionnal 'ints' necessary to store the
808 token */
809 static inline int tok_ext_size(int t)
811 switch(t) {
812 /* 4 bytes */
813 case TOK_NUM:
814 case TOK_CCHAR:
815 case TOK_LCHAR:
816 case TOK_STR:
817 case TOK_LSTR:
818 case TOK_CFLOAT:
819 return 1;
820 case TOK_CDOUBLE:
821 return 2;
822 case TOK_CLDOUBLE:
823 return LDOUBLE_SIZE / 4;
824 default:
825 return 0;
829 void tok_add(int **tok_str, int *tok_len, int t)
831 int len, *str;
832 len = *tok_len;
833 str = *tok_str;
834 if ((len & 63) == 0) {
835 str = realloc(str, (len + 64) * sizeof(int));
836 if (!str)
837 return;
838 *tok_str = str;
840 str[len++] = t;
841 *tok_len = len;
844 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
846 int n, i;
848 tok_add(tok_str, tok_len, t);
849 n = tok_ext_size(t);
850 for(i=0;i<n;i++)
851 tok_add(tok_str, tok_len, cv->tab[i]);
854 /* get a token from an integer array and increment pointer accordingly */
855 int tok_get(int **tok_str, CValue *cv)
857 int *p, t, n, i;
859 p = *tok_str;
860 t = *p++;
861 n = tok_ext_size(t);
862 for(i=0;i<n;i++)
863 cv->tab[i] = *p++;
864 *tok_str = p;
865 return t;
868 /* eval an expression for #if/#elif */
869 int expr_preprocess(void)
871 int *str, len, c, t;
873 str = NULL;
874 len = 0;
875 while (1) {
876 skip_spaces();
877 if (ch == '\n')
878 break;
879 next(); /* do macro subst */
880 if (tok == TOK_DEFINED) {
881 next_nomacro();
882 t = tok;
883 if (t == '(')
884 next_nomacro();
885 c = sym_find1(&define_stack, tok) != 0;
886 if (t == '(')
887 next_nomacro();
888 tok = TOK_NUM;
889 tokc.i = c;
890 } else if (tok >= TOK_IDENT) {
891 /* if undefined macro */
892 tok = TOK_NUM;
893 tokc.i = 0;
895 tok_add2(&str, &len, tok, &tokc);
897 tok_add(&str, &len, -1); /* simulate end of file */
898 tok_add(&str, &len, 0);
899 /* now evaluate C constant expression */
900 macro_ptr = str;
901 next();
902 c = expr_const();
903 macro_ptr = NULL;
904 free(str);
905 return c != 0;
908 #if defined(DEBUG)
909 void tok_print(int *str)
911 int t;
912 CValue cval;
914 while (1) {
915 t = tok_get(&str, &cval);
916 if (!t)
917 break;
918 printf(" %s", get_tok_str(t, &cval));
920 printf("\n");
922 #endif
924 /* XXX: should be more factorized */
925 void define_symbol(char *sym)
927 TokenSym *ts;
928 int *str, len;
929 CValue cval;
931 ts = tok_alloc(sym, 0);
932 str = NULL;
933 len = 0;
934 cval.i = 1;
935 tok_add2(&str, &len, TOK_NUM, &cval);
936 tok_add(&str, &len, 0);
937 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
940 void preprocess(void)
942 int size, i, c, v, t, *str, len;
943 char buf[1024], *q, *p;
944 char buf1[1024];
945 FILE *f;
946 Sym **ps, *first, *s;
948 cinp();
949 next_nomacro();
950 redo:
951 if (tok == TOK_DEFINE) {
952 next_nomacro();
953 v = tok;
954 /* XXX: should check if same macro (ANSI) */
955 first = NULL;
956 t = MACRO_OBJ;
957 /* '(' must be just after macro definition for MACRO_FUNC */
958 if (ch == '(') {
959 next_nomacro();
960 next_nomacro();
961 ps = &first;
962 while (tok != ')') {
963 if (tok == TOK_DOTS)
964 tok = TOK___VA_ARGS__;
965 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
966 *ps = s;
967 ps = &s->next;
968 next_nomacro();
969 if (tok != ',')
970 break;
971 next_nomacro();
973 t = MACRO_FUNC;
975 str = NULL;
976 len = 0;
977 while (1) {
978 skip_spaces();
979 if (ch == '\n' || ch == -1)
980 break;
981 next_nomacro();
982 tok_add2(&str, &len, tok, &tokc);
984 tok_add(&str, &len, 0);
985 #ifdef PP_DEBUG
986 printf("define %s %d: ", get_tok_str(v, 0), t);
987 tok_print(str);
988 #endif
989 s = sym_push1(&define_stack, v, t, (int)str);
990 s->next = first;
991 } else if (tok == TOK_UNDEF) {
992 next_nomacro();
993 s = sym_find1(&define_stack, tok);
994 /* undefine symbol by putting an invalid name */
995 if (s)
996 sym_undef(&define_stack, s);
997 } else if (tok == TOK_INCLUDE) {
998 skip_spaces();
999 if (ch == '<') {
1000 c = '>';
1001 goto read_name;
1002 } else if (ch == '\"') {
1003 c = ch;
1004 read_name:
1005 minp();
1006 q = buf;
1007 while (ch != c && ch != '\n' && ch != -1) {
1008 if ((q - buf) < sizeof(buf) - 1)
1009 *q++ = ch;
1010 minp();
1012 *q = '\0';
1013 } else {
1014 next();
1015 if (tok != TOK_STR)
1016 error("#include syntax error");
1017 /* XXX: buffer overflow */
1018 strcpy(buf, get_tok_str(tok, &tokc));
1019 c = '\"';
1021 /* eat all spaces and comments after include */
1022 /* XXX: slightly incorrect */
1023 while (ch1 != '\n' && ch1 != -1)
1024 inp();
1026 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1027 error("memory full");
1028 if (c == '\"') {
1029 /* first search in current dir if "header.h" */
1030 /* XXX: buffer overflow */
1031 size = 0;
1032 p = strrchr(filename, '/');
1033 if (p)
1034 size = p + 1 - filename;
1035 memcpy(buf1, filename, size);
1036 buf1[size] = '\0';
1037 strcat(buf1, buf);
1038 f = fopen(buf1, "r");
1039 if (f)
1040 goto found;
1042 /* now search in standard include path */
1043 for(i=nb_include_paths - 1;i>=0;i--) {
1044 strcpy(buf1, include_paths[i]);
1045 strcat(buf1, "/");
1046 strcat(buf1, buf);
1047 f = fopen(buf1, "r");
1048 if (f)
1049 goto found;
1051 error("include file '%s' not found", buf1);
1052 f = NULL;
1053 found:
1054 /* push current file in stack */
1055 /* XXX: fix current line init */
1056 include_stack_ptr->file = file;
1057 include_stack_ptr->filename = filename;
1058 include_stack_ptr->line_num = line_num;
1059 include_stack_ptr++;
1060 file = f;
1061 filename = strdup(buf1);
1062 line_num = 1;
1063 } else if (tok == TOK_IFNDEF) {
1064 c = 1;
1065 goto do_ifdef;
1066 } else if (tok == TOK_IF) {
1067 c = expr_preprocess();
1068 goto do_if;
1069 } else if (tok == TOK_IFDEF) {
1070 c = 0;
1071 do_ifdef:
1072 next_nomacro();
1073 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1074 do_if:
1075 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1076 error("memory full");
1077 *ifdef_stack_ptr++ = c;
1078 goto test_skip;
1079 } else if (tok == TOK_ELSE) {
1080 if (ifdef_stack_ptr == ifdef_stack ||
1081 (ifdef_stack_ptr[-1] & 2))
1082 error("#else after #else");
1083 c = (ifdef_stack_ptr[-1] ^= 3);
1084 goto test_skip;
1085 } else if (tok == TOK_ELIF) {
1086 if (ifdef_stack_ptr == ifdef_stack ||
1087 ifdef_stack_ptr[-1] > 1)
1088 error("#elif after #else");
1089 c = expr_preprocess();
1090 ifdef_stack_ptr[-1] = c;
1091 test_skip:
1092 if (!(c & 1)) {
1093 preprocess_skip();
1094 goto redo;
1096 } else if (tok == TOK_ENDIF) {
1097 if (ifdef_stack_ptr == ifdef_stack)
1098 expect("#if");
1099 ifdef_stack_ptr--;
1100 } else if (tok == TOK_LINE) {
1101 next();
1102 if (tok != TOK_NUM)
1103 error("#line");
1104 line_num = tokc.i;
1105 skip_spaces();
1106 if (ch != '\n') {
1107 next();
1108 if (tok != TOK_STR)
1109 error("#line");
1110 /* XXX: potential memory leak */
1111 filename = strdup(get_tok_str(tok, &tokc));
1113 } else if (tok == TOK_ERROR) {
1114 error("#error");
1116 /* ignore other preprocess commands or #! for C scripts */
1117 while (ch != '\n' && ch != -1)
1118 cinp();
1121 /* read a number in base b */
1122 int getn(b)
1124 int n, t;
1125 n = 0;
1126 while (1) {
1127 if (ch >= 'a' & ch <= 'f')
1128 t = ch - 'a' + 10;
1129 else if (ch >= 'A' & ch <= 'F')
1130 t = ch - 'A' + 10;
1131 else if (isnum(ch))
1132 t = ch - '0';
1133 else
1134 break;
1135 if (t < 0 | t >= b)
1136 break;
1137 n = n * b + t;
1138 cinp();
1140 return n;
1143 /* read a character for string or char constant and eval escape codes */
1144 int getq()
1146 int c;
1148 c = ch;
1149 minp();
1150 if (c == '\\') {
1151 if (isnum(ch)) {
1152 /* at most three octal digits */
1153 c = ch - '0';
1154 minp();
1155 if (isnum(ch)) {
1156 c = c * 8 + ch - '0';
1157 minp();
1158 if (isnum(ch)) {
1159 c = c * 8 + ch - '0';
1160 minp();
1163 return c;
1164 } else if (ch == 'x') {
1165 minp();
1166 return getn(16);
1167 } else {
1168 if (ch == 'a')
1169 c = '\a';
1170 else if (ch == 'b')
1171 c = '\b';
1172 else if (ch == 'f')
1173 c = '\f';
1174 else if (ch == 'n')
1175 c = '\n';
1176 else if (ch == 'r')
1177 c = '\r';
1178 else if (ch == 't')
1179 c = '\t';
1180 else if (ch == 'v')
1181 c = '\v';
1182 else if (ch == 'e' && gnu_ext)
1183 c = 27;
1184 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1185 c = ch;
1186 else
1187 error("invalid escaped char");
1188 minp();
1191 return c;
1194 /* we use 64 bit numbers */
1195 #define BN_SIZE 2
1197 /* bn = (bn << shift) | or_val */
1198 void bn_lshift(unsigned int *bn, int shift, int or_val)
1200 int i;
1201 unsigned int v;
1202 for(i=0;i<BN_SIZE;i++) {
1203 v = bn[i];
1204 bn[i] = (v << shift) | or_val;
1205 or_val = v >> (32 - shift);
1209 void bn_zero(unsigned int *bn)
1211 int i;
1212 for(i=0;i<BN_SIZE;i++) {
1213 bn[i] = 0;
1217 void parse_number(void)
1219 int b, t, shift, frac_bits, s, exp_val;
1220 char *q;
1221 unsigned int n, n1;
1222 unsigned int bn[BN_SIZE];
1223 CValue cval;
1224 double d;
1226 /* number */
1227 q = token_buf;
1228 t = ch;
1229 cinp();
1230 *q++ = t;
1231 b = 10;
1232 if (t == '.') {
1233 /* special dot handling */
1234 if (ch >= '0' && ch <= '9') {
1235 goto float_frac_parse;
1236 } else if (ch == '.') {
1237 cinp();
1238 if (ch != '.')
1239 expect("'.'");
1240 cinp();
1241 tok = TOK_DOTS;
1242 } else {
1243 /* dots */
1244 tok = t;
1246 return;
1247 } else if (t == '0') {
1248 if (ch == 'x' || ch == 'X') {
1249 q--;
1250 cinp();
1251 b = 16;
1252 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1253 q--;
1254 cinp();
1255 b = 2;
1258 /* parse all digits. cannot check octal numbers at this stage
1259 because of floating point constants */
1260 while (1) {
1261 if (ch >= 'a' & ch <= 'f')
1262 t = ch - 'a' + 10;
1263 else if (ch >= 'A' & ch <= 'F')
1264 t = ch - 'A' + 10;
1265 else if (isnum(ch))
1266 t = ch - '0';
1267 else
1268 break;
1269 if (t >= b)
1270 break;
1271 if (q >= token_buf + STRING_MAX_SIZE) {
1272 num_too_long:
1273 error("number too long");
1275 *q++ = ch;
1276 cinp();
1278 if (ch == '.' ||
1279 ((ch == 'e' || ch == 'E') && b == 10) ||
1280 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1281 if (b != 10) {
1282 /* NOTE: strtox should support that for hexa numbers, but
1283 non ISOC99 libcs do not support it, so we prefer to do
1284 it by hand */
1285 /* hexadecimal or binary floats */
1286 /* XXX: handle overflows */
1287 *q = '\0';
1288 if (b == 16)
1289 shift = 4;
1290 else
1291 shift = 2;
1292 bn_zero(bn);
1293 q = token_buf;
1294 while (1) {
1295 t = *q++;
1296 if (t == '\0') {
1297 break;
1298 } else if (t >= 'a') {
1299 t = t - 'a' + 10;
1300 } else if (t >= 'A') {
1301 t = t - 'A' + 10;
1302 } else {
1303 t = t - '0';
1305 bn_lshift(bn, shift, t);
1307 frac_bits = 0;
1308 if (ch == '.') {
1309 cinp();
1310 while (1) {
1311 t = ch;
1312 if (t >= 'a' && t <= 'f') {
1313 t = t - 'a' + 10;
1314 } else if (t >= 'A' && t <= 'F') {
1315 t = t - 'A' + 10;
1316 } else if (t >= '0' && t <= '9') {
1317 t = t - '0';
1318 } else {
1319 break;
1321 if (t >= b)
1322 error("invalid digit");
1323 bn_lshift(bn, shift, t);
1324 frac_bits += shift;
1325 cinp();
1328 if (ch != 'p' && ch != 'P')
1329 error("exponent expected");
1330 cinp();
1331 s = 1;
1332 exp_val = 0;
1333 if (ch == '+') {
1334 cinp();
1335 } else if (ch == '-') {
1336 s = -1;
1337 cinp();
1339 if (ch < '0' || ch > '9')
1340 error("exponent digits expected");
1341 while (ch >= '0' && ch <= '9') {
1342 exp_val = exp_val * 10 + ch - '0';
1343 cinp();
1345 exp_val = exp_val * s;
1346 printf("num=%08x %08x %d %d\n", bn[1], bn[0], frac_bits, exp_val);
1348 /* now we can generate the number */
1349 /* XXX: should patch directly float number */
1350 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1351 d = ldexp(d, exp_val - frac_bits);
1352 t = toup(ch);
1353 if (t == 'F') {
1354 cinp();
1355 tok = TOK_CFLOAT;
1356 /* float : should handle overflow */
1357 cval.f = (float)d;
1358 } else if (t == 'L') {
1359 cinp();
1360 tok = TOK_CLDOUBLE;
1361 /* XXX: not large enough */
1362 cval.ld = (long double)d;
1363 } else {
1364 tok = TOK_CDOUBLE;
1365 cval.d = d;
1367 } else {
1368 /* decimal floats */
1369 if (ch == '.') {
1370 if (q >= token_buf + STRING_MAX_SIZE)
1371 goto num_too_long;
1372 *q++ = ch;
1373 cinp();
1374 float_frac_parse:
1375 while (ch >= '0' && ch <= '9') {
1376 if (q >= token_buf + STRING_MAX_SIZE)
1377 goto num_too_long;
1378 *q++ = ch;
1379 cinp();
1382 if (ch == 'e' || ch == 'E') {
1383 if (q >= token_buf + STRING_MAX_SIZE)
1384 goto num_too_long;
1385 *q++ = ch;
1386 cinp();
1387 if (ch == '-' || ch == '+') {
1388 if (q >= token_buf + STRING_MAX_SIZE)
1389 goto num_too_long;
1390 *q++ = ch;
1391 cinp();
1393 if (ch < '0' || ch > '9')
1394 error("exponent digits expected");
1395 while (ch >= '0' && ch <= '9') {
1396 if (q >= token_buf + STRING_MAX_SIZE)
1397 goto num_too_long;
1398 *q++ = ch;
1399 cinp();
1402 *q = '\0';
1403 t = toup(ch);
1404 errno = 0;
1405 if (t == 'F') {
1406 cinp();
1407 tok = TOK_CFLOAT;
1408 cval.f = strtof(token_buf, NULL);
1409 } else if (t == 'L') {
1410 cinp();
1411 tok = TOK_CLDOUBLE;
1412 cval.ld = strtold(token_buf, NULL);
1413 } else {
1414 tok = TOK_CDOUBLE;
1415 cval.d = strtod(token_buf, NULL);
1418 } else {
1419 /* integer number */
1420 *q = '\0';
1421 q = token_buf;
1422 if (b == 10 && *q == '0') {
1423 b = 8;
1424 q++;
1426 n = 0;
1427 while(1) {
1428 t = *q++;
1429 /* no need for checks except for base 10 / 8 errors */
1430 if (t == '\0') {
1431 break;
1432 } else if (t >= 'a') {
1433 t = t - 'a' + 10;
1434 } else if (t >= 'A') {
1435 t = t - 'A' + 10;
1436 } else {
1437 t = t - '0';
1438 if (t >= b)
1439 error("invalid digit");
1441 n1 = n;
1442 n = n * b + t;
1443 /* detect overflow */
1444 if (n < n1)
1445 error("integer constant overflow");
1447 tokc.ui = n;
1448 tok = TOK_NUM;
1449 /* XXX: add unsigned constant support (ANSI) */
1450 while (ch == 'L' || ch == 'l' || ch == 'U' || ch == 'u')
1451 cinp();
1456 /* return next token without macro substitution */
1457 void next_nomacro1(void)
1459 int b;
1460 char *q;
1461 TokenSym *ts;
1463 /* skip spaces */
1464 while(1) {
1465 while (ch == '\n') {
1466 cinp();
1467 while (ch == ' ' || ch == 9)
1468 cinp();
1469 if (ch == '#') {
1470 /* preprocessor command if # at start of line after
1471 spaces */
1472 preprocess();
1475 if (ch != ' ' && ch != '\t' && ch != '\f')
1476 break;
1477 cinp();
1479 if (isid(ch)) {
1480 q = token_buf;
1481 *q++ = ch;
1482 cinp();
1483 if (q[-1] == 'L') {
1484 if (ch == '\'') {
1485 tok = TOK_LCHAR;
1486 goto char_const;
1488 if (ch == '\"') {
1489 tok = TOK_LSTR;
1490 goto str_const;
1493 while (isid(ch) || isnum(ch)) {
1494 if (q >= token_buf + STRING_MAX_SIZE)
1495 error("ident too long");
1496 *q++ = ch;
1497 cinp();
1499 *q = '\0';
1500 ts = tok_alloc(token_buf, q - token_buf);
1501 tok = ts->tok;
1502 } else if (isnum(ch) || ch == '.') {
1503 parse_number();
1504 } else if (ch == '\'') {
1505 tok = TOK_CCHAR;
1506 char_const:
1507 minp();
1508 tokc.i = getq();
1509 if (ch != '\'')
1510 expect("\'");
1511 minp();
1512 } else if (ch == '\"') {
1513 tok = TOK_STR;
1514 str_const:
1515 minp();
1516 q = token_buf;
1517 while (ch != '\"') {
1518 b = getq();
1519 if (ch == -1)
1520 error("unterminated string");
1521 if (q >= token_buf + STRING_MAX_SIZE)
1522 error("string too long");
1523 *q++ = b;
1525 *q = '\0';
1526 tokc.ts = tok_alloc(token_buf, q - token_buf);
1527 minp();
1528 } else {
1529 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1530 /* two chars */
1531 tok = ch;
1532 cinp();
1533 while (*q) {
1534 if (*q == tok && q[1] == ch) {
1535 cinp();
1536 tok = q[2] & 0xff;
1537 /* three chars tests */
1538 if (tok == TOK_SHL | tok == TOK_SAR) {
1539 if (ch == '=') {
1540 tok = tok | 0x80;
1541 cinp();
1543 } else if (tok == TOK_DOTS) {
1544 if (ch != '.')
1545 error("parse error");
1546 cinp();
1548 return;
1550 q = q + 3;
1552 /* single char substitutions */
1553 if (tok == '<')
1554 tok = TOK_LT;
1555 else if (tok == '>')
1556 tok = TOK_GT;
1560 /* return next token without macro substitution. Can read input from
1561 macro_ptr buffer */
1562 void next_nomacro()
1564 if (macro_ptr) {
1565 tok = *macro_ptr;
1566 if (tok)
1567 tok = tok_get(&macro_ptr, &tokc);
1568 } else {
1569 next_nomacro1();
1573 /* substitute args in macro_str and return allocated string */
1574 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1576 int *st, last_tok, t, notfirst, *str, len;
1577 Sym *s;
1578 TokenSym *ts;
1579 CValue cval;
1581 str = NULL;
1582 len = 0;
1583 last_tok = 0;
1584 while(1) {
1585 t = tok_get(&macro_str, &cval);
1586 if (!t)
1587 break;
1588 if (t == '#') {
1589 /* stringize */
1590 t = tok_get(&macro_str, &cval);
1591 if (!t)
1592 break;
1593 s = sym_find2(args, t);
1594 if (s) {
1595 token_buf[0] = '\0';
1596 st = (int *)s->c;
1597 /* XXX: buffer overflow */
1598 notfirst = 0;
1599 while (*st) {
1600 if (notfirst)
1601 strcat(token_buf, " ");
1602 t = tok_get(&st, &cval);
1603 strcat(token_buf, get_tok_str(t, &cval));
1604 notfirst = 1;
1606 #ifdef PP_DEBUG
1607 printf("stringize: %s\n", token_buf);
1608 #endif
1609 /* add string */
1610 ts = tok_alloc(token_buf, 0);
1611 cval.ts = ts;
1612 tok_add2(&str, &len, TOK_STR, &cval);
1613 } else {
1614 tok_add2(&str, &len, t, &cval);
1616 } else if (t >= TOK_IDENT) {
1617 s = sym_find2(args, t);
1618 if (s) {
1619 st = (int *)s->c;
1620 /* if '##' is present before or after , no arg substitution */
1621 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1622 while (*st)
1623 tok_add(&str, &len, *st++);
1624 } else {
1625 macro_subst(&str, &len, nested_list, st);
1627 } else {
1628 tok_add(&str, &len, t);
1630 } else {
1631 tok_add2(&str, &len, t, &cval);
1633 last_tok = t;
1635 tok_add(&str, &len, 0);
1636 return str;
1639 /* handle the '##' operator */
1640 int *macro_twosharps(int *macro_str)
1642 TokenSym *ts;
1643 int *macro_str1, macro_str1_len, *macro_ptr1;
1644 int t;
1645 char *p;
1646 CValue cval;
1648 macro_str1 = NULL;
1649 macro_str1_len = 0;
1650 tok = 0;
1651 while (1) {
1652 next_nomacro();
1653 if (tok == 0)
1654 break;
1655 while (*macro_ptr == TOK_TWOSHARPS) {
1656 macro_ptr++;
1657 macro_ptr1 = macro_ptr;
1658 t = *macro_ptr;
1659 if (t) {
1660 t = tok_get(&macro_ptr, &cval);
1661 /* XXX: we handle only most common cases:
1662 ident + ident or ident + number */
1663 if (tok >= TOK_IDENT &&
1664 (t >= TOK_IDENT || t == TOK_NUM)) {
1665 /* XXX: buffer overflow */
1666 p = get_tok_str(tok, &tokc);
1667 strcpy(token_buf, p);
1668 p = get_tok_str(t, &cval);
1669 strcat(token_buf, p);
1670 ts = tok_alloc(token_buf, 0);
1671 tok = ts->tok; /* modify current token */
1672 } else {
1673 /* cannot merge tokens: skip '##' */
1674 macro_ptr = macro_ptr1;
1675 break;
1679 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
1681 tok_add(&macro_str1, &macro_str1_len, 0);
1682 return macro_str1;
1687 /* do macro substitution of macro_str and add result to
1688 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1689 substituted. 'nested_list' is the list of all macros we got inside
1690 to avoid recursing. */
1691 void macro_subst(int **tok_str, int *tok_len,
1692 Sym **nested_list, int *macro_str)
1694 Sym *s, *args, *sa, *sa1;
1695 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
1696 int mstr_allocated, *macro_str1;
1697 CValue cval;
1699 saved_macro_ptr = macro_ptr;
1700 macro_ptr = macro_str;
1701 macro_str1 = NULL;
1702 if (macro_str) {
1703 /* first scan for '##' operator handling */
1704 macro_str1 = macro_twosharps(macro_str);
1705 macro_ptr = macro_str1;
1708 while (1) {
1709 next_nomacro();
1710 if (tok == 0)
1711 break;
1712 /* special macros */
1713 if (tok == TOK___LINE__) {
1714 cval.i = line_num;
1715 tok_add2(tok_str, tok_len, TOK_NUM, &cval);
1716 } else if (tok == TOK___FILE__) {
1717 cval.ts = tok_alloc(filename, 0);
1718 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1719 } else if (tok == TOK___DATE__) {
1720 cval.ts = tok_alloc("Jan 1 1970", 0);
1721 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1722 } else if (tok == TOK___TIME__) {
1723 cval.ts = tok_alloc("00:00:00", 0);
1724 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1725 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
1726 /* if symbol is a macro, prepare substitution */
1727 /* if nested substitution, do nothing */
1728 if (sym_find2(*nested_list, tok))
1729 goto no_subst;
1730 mstr = (int *)s->c;
1731 mstr_allocated = 0;
1732 if (s->t == MACRO_FUNC) {
1733 /* NOTE: we do not use next_nomacro to avoid eating the
1734 next token. XXX: find better solution */
1735 if (macro_ptr) {
1736 t = *macro_ptr;
1737 } else {
1738 while (ch == ' ' || ch == '\t' || ch == '\n')
1739 cinp();
1740 t = ch;
1742 if (t != '(') /* no macro subst */
1743 goto no_subst;
1745 /* argument macro */
1746 next_nomacro();
1747 next_nomacro();
1748 args = NULL;
1749 sa = s->next;
1750 while (tok != ')' && sa) {
1751 len = 0;
1752 str = NULL;
1753 parlevel = 0;
1754 while ((parlevel > 0 ||
1755 (tok != ')' &&
1756 (tok != ',' ||
1757 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
1758 tok != -1) {
1759 if (tok == '(')
1760 parlevel++;
1761 else if (tok == ')')
1762 parlevel--;
1763 tok_add2(&str, &len, tok, &tokc);
1764 next_nomacro();
1766 tok_add(&str, &len, 0);
1767 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
1768 if (tok != ',')
1769 break;
1770 next_nomacro();
1771 sa = sa->next;
1773 if (tok != ')')
1774 expect(")");
1775 /* now subst each arg */
1776 mstr = macro_arg_subst(nested_list, mstr, args);
1777 /* free memory */
1778 sa = args;
1779 while (sa) {
1780 sa1 = sa->prev;
1781 free((int *)sa->c);
1782 free(sa);
1783 sa = sa1;
1785 mstr_allocated = 1;
1787 sym_push2(nested_list, s->v, 0, 0);
1788 macro_subst(tok_str, tok_len, nested_list, mstr);
1789 /* pop nested defined symbol */
1790 sa1 = *nested_list;
1791 *nested_list = sa1->prev;
1792 free(sa1);
1793 if (mstr_allocated)
1794 free(mstr);
1795 } else {
1796 no_subst:
1797 /* no need to add if reading input stream */
1798 if (!macro_str)
1799 return;
1800 tok_add2(tok_str, tok_len, tok, &tokc);
1802 /* only replace one macro while parsing input stream */
1803 if (!macro_str)
1804 return;
1806 macro_ptr = saved_macro_ptr;
1807 if (macro_str1)
1808 free(macro_str1);
1811 /* return next token with macro substitution */
1812 void next(void)
1814 int len, *ptr;
1815 Sym *nested_list;
1817 /* special 'ungettok' case for label parsing */
1818 if (tok1) {
1819 tok = tok1;
1820 tokc = tok1c;
1821 tok1 = 0;
1822 } else {
1823 redo:
1824 if (!macro_ptr) {
1825 /* if not reading from macro substuted string, then try to substitute */
1826 len = 0;
1827 ptr = NULL;
1828 nested_list = NULL;
1829 macro_subst(&ptr, &len, &nested_list, NULL);
1830 if (ptr) {
1831 tok_add(&ptr, &len, 0);
1832 macro_ptr = ptr;
1833 macro_ptr_allocated = ptr;
1834 goto redo;
1836 if (tok == 0)
1837 goto redo;
1838 } else {
1839 next_nomacro();
1840 if (tok == 0) {
1841 /* end of macro string: free it */
1842 free(macro_ptr_allocated);
1843 macro_ptr = NULL;
1844 goto redo;
1848 #if defined(DEBUG)
1849 printf("token = %s\n", get_tok_str(tok, tokc));
1850 #endif
1853 void swap(int *p, int *q)
1855 int t;
1856 t = *p;
1857 *p = *q;
1858 *q = t;
1861 void vset(int t, int v)
1863 if (vtop >= vstack + VSTACK_SIZE)
1864 error("memory full");
1865 /* cannot let cpu flags if other instruction are generated */
1866 /* XXX: VT_JMP test too ? */
1867 if ((vtop->t & VT_VALMASK) == VT_CMP)
1868 gv();
1869 vtop++;
1870 vtop->t = t;
1871 vtop->c = v;
1874 void vpop(void)
1876 vtop--;
1879 void vswap(void)
1881 SValue tmp;
1883 tmp = vtop[0];
1884 vtop[0] = vtop[-1];
1885 vtop[-1] = tmp;
1888 void vdup(void)
1890 if (vtop >= vstack + VSTACK_SIZE)
1891 error("memory full");
1892 vtop++;
1893 *vtop = vtop[-1];
1896 int save_reg_forced(int r)
1898 int i, l, t;
1899 SValue *p;
1901 /* store register */
1902 loc = (loc - 4) & -3;
1903 store(r, VT_LOCAL, loc);
1904 l = loc;
1906 /* modify all stack values */
1907 for(p=vstack;p<=vtop;p++) {
1908 i = p->t & VT_VALMASK;
1909 if (i == r) {
1910 if (p->t & VT_LVAL)
1911 t = VT_LLOCAL;
1912 else
1913 t = VT_LOCAL;
1914 p->t = (p->t & VT_TYPE) | VT_LVAL | t;
1915 p->c = l;
1918 return l;
1921 /* save r to memory. and mark it as being free */
1922 void save_reg(int r)
1924 int i;
1925 SValue *p;
1927 /* modify all stack values */
1928 for(p=vstack;p<=vtop;p++) {
1929 i = p->t & VT_VALMASK;
1930 if (i == r) {
1931 save_reg_forced(r);
1932 break;
1937 /* find a free register of class 'rc'. If none, save one register */
1938 int get_reg(int rc)
1940 int r, i;
1941 SValue *p;
1943 /* find a free register */
1944 for(r=0;r<NB_REGS;r++) {
1945 if (reg_classes[r] & rc) {
1946 for(p=vstack;p<=vtop;p++) {
1947 i = p->t & VT_VALMASK;
1948 if (i == r)
1949 goto notfound;
1951 return r;
1953 notfound: ;
1956 /* no register left : free the first one on the stack (very
1957 important to start from the bottom to ensure that we don't
1958 spill registers used in gen_op()) */
1959 for(p=vstack;p<=vtop;p++) {
1960 r = p->t & VT_VALMASK;
1961 if (r < VT_CONST && (reg_classes[r] & rc)) {
1962 save_reg(r);
1963 break;
1966 return r;
1969 void save_regs()
1971 int r;
1972 SValue *p;
1974 for(p=vstack;p<=vtop;p++) {
1975 r = p->t & VT_VALMASK;
1976 if (r < VT_CONST) {
1977 save_reg(r);
1982 /* move register 's' to 'r', and flush previous value of r to memory
1983 if needed */
1984 void move_reg(int r, int s)
1986 if (r != s) {
1987 save_reg(r);
1988 load(r, s, 0);
1992 /* convert a (vtop->t, vtop->c) in register. lvalues are converted as
1993 values. Cannot be used if cannot be converted to register value
1994 (such as structures). */
1995 int gv(void)
1997 int r, bit_pos, bit_size, rc;
1999 /* NOTE: get_reg can modify vstack[] */
2000 if (vtop->t & VT_BITFIELD) {
2001 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2002 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2003 /* remove bit field info to avoid loops */
2004 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2005 /* generate shifts */
2006 vset(VT_CONST, 32 - (bit_pos + bit_size));
2007 gen_op(TOK_SHL);
2008 vset(VT_CONST, 32 - bit_size);
2009 /* NOTE: transformed to SHR if unsigned */
2010 gen_op(TOK_SAR);
2011 r = gv();
2012 } else {
2013 r = vtop->t & VT_VALMASK;
2014 if (r >= VT_CONST || (vtop->t & VT_LVAL)) {
2015 if ((vtop->t & VT_BTYPE) == VT_FLOAT ||
2016 (vtop->t & VT_BTYPE) == VT_DOUBLE)
2017 rc = REG_CLASS_FLOAT;
2018 else
2019 rc = REG_CLASS_INT;
2020 r = get_reg(rc);
2022 load(r, vtop->t, vtop->c);
2023 vtop->t = (vtop->t & VT_TYPE) | r;
2025 return r;
2028 /* handle constant optimizations and various machine independant opt */
2029 void gen_opc(int op)
2031 int fc, c1, c2, n;
2032 SValue *v1, *v2;
2034 v1 = vtop - 1;
2035 v2 = vtop;
2036 /* currently, we cannot do computations with forward symbols */
2037 c1 = (v1->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2038 c2 = (v2->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2039 if (c1 && c2) {
2040 fc = v2->c;
2041 switch(op) {
2042 case '+': v1->c += fc; break;
2043 case '-': v1->c -= fc; break;
2044 case '&': v1->c &= fc; break;
2045 case '^': v1->c ^= fc; break;
2046 case '|': v1->c |= fc; break;
2047 case '*': v1->c *= fc; break;
2048 case TOK_PDIV:
2049 case '/': v1->c /= fc; break; /* XXX: zero case ? */
2050 case '%': v1->c %= fc; break; /* XXX: zero case ? */
2051 case TOK_UDIV: v1->c = (unsigned)v1->c / fc; break; /* XXX: zero case ? */
2052 case TOK_UMOD: v1->c = (unsigned)v1->c % fc; break; /* XXX: zero case ? */
2053 case TOK_SHL: v1->c <<= fc; break;
2054 case TOK_SHR: v1->c = (unsigned)v1->c >> fc; break;
2055 case TOK_SAR: v1->c >>= fc; break;
2056 /* tests */
2057 case TOK_ULT: v1->c = (unsigned)v1->c < (unsigned)fc; break;
2058 case TOK_UGE: v1->c = (unsigned)v1->c >= (unsigned)fc; break;
2059 case TOK_EQ: v1->c = v1->c == fc; break;
2060 case TOK_NE: v1->c = v1->c != fc; break;
2061 case TOK_ULE: v1->c = (unsigned)v1->c <= (unsigned)fc; break;
2062 case TOK_UGT: v1->c = (unsigned)v1->c > (unsigned)fc; break;
2063 case TOK_LT: v1->c = v1->c < fc; break;
2064 case TOK_GE: v1->c = v1->c >= fc; break;
2065 case TOK_LE: v1->c = v1->c <= fc; break;
2066 case TOK_GT: v1->c = v1->c > fc; break;
2067 /* logical */
2068 case TOK_LAND: v1->c = v1->c && fc; break;
2069 case TOK_LOR: v1->c = v1->c || fc; break;
2070 default:
2071 goto general_case;
2073 vtop--;
2074 } else {
2075 /* if commutative ops, put c2 as constant */
2076 if (c1 && (op == '+' || op == '&' || op == '^' ||
2077 op == '|' || op == '*')) {
2078 vswap();
2079 swap(&c1, &c2);
2081 fc = vtop->c;
2082 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2083 op == TOK_PDIV) &&
2084 fc == 1) ||
2085 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2086 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2087 fc == 0) ||
2088 (op == '&' &&
2089 fc == -1))) {
2090 /* nothing to do */
2091 vtop--;
2092 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2093 /* try to use shifts instead of muls or divs */
2094 if (fc > 0 && (fc & (fc - 1)) == 0) {
2095 n = -1;
2096 while (fc) {
2097 fc >>= 1;
2098 n++;
2100 vtop->c = n;
2101 if (op == '*')
2102 op = TOK_SHL;
2103 else if (op == TOK_PDIV)
2104 op = TOK_SAR;
2105 else
2106 op = TOK_SHR;
2108 goto general_case;
2109 } else {
2110 general_case:
2111 /* call low level op generator */
2112 /* XXX: remove explicit registers */
2113 gen_opi(op);
2118 int pointed_size(int t)
2120 return type_size(pointed_type(t), &t);
2123 /* true if float/double/long double type */
2124 static inline int is_float(int t)
2126 int bt;
2127 bt = t & VT_BTYPE;
2128 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
2131 /* generic gen_op: handles types problems */
2132 void gen_op(int op)
2134 int u, t1, t2, bt1, bt2, t;
2136 t1 = vtop[-1].t;
2137 t2 = vtop[0].t;
2138 bt1 = t1 & VT_BTYPE;
2139 bt2 = t2 & VT_BTYPE;
2141 if (is_float(bt1) || is_float(bt2)) {
2142 /* compute bigger type and do implicit casts */
2143 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2144 t = VT_LDOUBLE;
2145 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2146 t = VT_DOUBLE;
2147 } else {
2148 t = VT_FLOAT;
2150 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2151 op < TOK_EQ || op > TOK_GT)
2152 error("invalid operands for binary operation");
2153 if (bt1 != t) {
2154 vswap();
2155 gen_cast(t);
2156 vswap();
2158 if (bt2 != t) {
2159 gen_cast(t);
2161 gen_opf(op);
2162 if (op >= TOK_EQ && op <= TOK_GT) {
2163 /* the result is an int */
2164 vtop->t = (vtop->t & ~VT_TYPE) | VT_INT;
2165 } else {
2166 vtop->t = (vtop->t & ~VT_TYPE) | t;
2168 } else if (op == '+' || op == '-') {
2169 if ((t1 & VT_BTYPE) == VT_PTR &&
2170 (t2 & VT_BTYPE) == VT_PTR) {
2171 if (op != '-')
2172 error("invalid type");
2173 /* XXX: check that types are compatible */
2174 u = pointed_size(t1);
2175 gen_opc(op);
2176 /* set to integer type */
2177 vtop->t = (vtop->t & ~VT_TYPE) | VT_INT;
2178 vset(VT_CONST, u);
2179 gen_op(TOK_PDIV);
2180 } else if ((t1 & VT_BTYPE) == VT_PTR ||
2181 (t2 & VT_BTYPE) == VT_PTR) {
2182 if ((t2 & VT_BTYPE) == VT_PTR) {
2183 vswap();
2184 swap(&t1, &t2);
2186 /* stack-4 contains pointer, stack-2 value to add */
2187 vset(VT_CONST, pointed_size(vtop[-1].t));
2188 gen_op('*');
2189 gen_opc(op);
2190 /* put again type if gen_opc() swaped operands */
2191 vtop->t = (vtop->t & ~VT_TYPE) | (t1 & VT_TYPE);
2192 } else {
2193 gen_opc(op);
2195 } else {
2196 /* XXX: test types and compute returned value */
2197 if ((t1 | t2) & VT_UNSIGNED ||
2198 (t1 & VT_BTYPE) == VT_PTR ||
2199 (t2 & VT_BTYPE) == VT_PTR) {
2200 if (op == TOK_SAR)
2201 op = TOK_SHR;
2202 else if (op == '/')
2203 op = TOK_UDIV;
2204 else if (op == '%')
2205 op = TOK_UMOD;
2206 else if (op == TOK_LT)
2207 op = TOK_ULT;
2208 else if (op == TOK_GT)
2209 op = TOK_UGT;
2210 else if (op == TOK_LE)
2211 op = TOK_ULE;
2212 else if (op == TOK_GE)
2213 op = TOK_UGE;
2215 gen_opc(op);
2219 /* cast 'vtop' to 't' type */
2220 void gen_cast(int t)
2222 int r, bits, bt, vbt;
2224 r = vtop->t & VT_VALMASK;
2225 if (!(t & VT_LVAL)) {
2226 /* if not lvalue, then we convert now */
2227 bt = t & VT_BTYPE;
2228 vbt = vtop->t & VT_BTYPE;
2229 if (bt != vbt) {
2230 if (is_float(bt)) {
2231 /* need to generate value and do explicit cast */
2232 gv();
2233 gen_cvtf(bt);
2234 } else if (bt == VT_BOOL) {
2235 vset(VT_CONST, 0);
2236 gen_op(TOK_NE);
2237 } else if (bt == VT_BYTE || bt == VT_SHORT) {
2238 if (bt == VT_BYTE)
2239 bits = 8;
2240 else
2241 bits = 16;
2242 if (t & VT_UNSIGNED) {
2243 vset(VT_CONST, (1 << bits) - 1);
2244 gen_op('&');
2245 } else {
2246 bits = 32 - bits;
2247 vset(VT_CONST, bits);
2248 gen_op(TOK_SHL);
2249 vset(VT_CONST, bits);
2250 gen_op(TOK_SAR);
2255 vtop->t = (vtop->t & ~VT_TYPE) | t;
2258 /* return type size. Put alignment at 'a' */
2259 int type_size(int t, int *a)
2261 Sym *s;
2262 int bt;
2264 bt = t & VT_BTYPE;
2265 if (bt == VT_STRUCT) {
2266 /* struct/union */
2267 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2268 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
2269 return s->c;
2270 } else if (bt == VT_PTR) {
2271 if (t & VT_ARRAY) {
2272 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2273 return type_size(s->t, a) * s->c;
2274 } else {
2275 *a = PTR_SIZE;
2276 return PTR_SIZE;
2278 } else if (bt == VT_LDOUBLE) {
2279 *a = LDOUBLE_ALIGN;
2280 return LDOUBLE_SIZE;
2281 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
2282 *a = 8;
2283 return 8;
2284 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
2285 *a = 4;
2286 return 4;
2287 } else if (bt == VT_SHORT) {
2288 *a = 2;
2289 return 2;
2290 } else {
2291 /* char, void, function, _Bool */
2292 *a = 1;
2293 return 1;
2297 /* return the pointed type of t */
2298 int pointed_type(int t)
2300 Sym *s;
2301 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2302 return s->t | (t & ~VT_TYPE);
2305 int mk_pointer(int t)
2307 int p;
2308 p = anon_sym++;
2309 sym_push(p, t, -1);
2310 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
2313 /* store vtop in lvalue pushed on stack */
2314 void vstore(void)
2316 int ft, fc, r, t, size, align, bit_size, bit_pos;
2317 GFuncContext gf;
2319 ft = vtop[-1].t;
2320 if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
2321 /* if structure, only generate pointer */
2322 /* structure assignment : generate memcpy */
2323 /* XXX: optimize if small size */
2325 vdup();
2326 gfunc_start(&gf);
2327 /* type size */
2328 size = type_size(vtop->t, &align);
2329 vset(VT_CONST, size);
2330 gfunc_param(&gf);
2331 /* source */
2332 vtop->t &= ~VT_LVAL;
2333 gfunc_param(&gf);
2334 /* destination */
2335 vswap();
2336 vtop->t &= ~VT_LVAL;
2337 gfunc_param(&gf);
2339 save_regs();
2340 vset(VT_CONST, (int)&memcpy);
2341 gfunc_call(&gf);
2342 /* leave source on stack */
2343 } else if (ft & VT_BITFIELD) {
2344 /* bitfield store handling */
2345 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
2346 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2347 /* remove bit field info to avoid loops */
2348 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2350 /* duplicate destination */
2351 vdup();
2352 vtop[-1] = vtop[-2];
2354 /* mask and shift source */
2355 vset(VT_CONST, (1 << bit_size) - 1);
2356 gen_op('&');
2357 vset(VT_CONST, bit_pos);
2358 gen_op(TOK_SHL);
2359 /* load destination, mask and or with source */
2360 vswap();
2361 vset(VT_CONST, ~(((1 << bit_size) - 1) << bit_pos));
2362 gen_op('&');
2363 gen_op('|');
2364 /* store result */
2365 vstore();
2366 } else {
2367 /* generate cast if needed implicit cast for bool */
2368 if ((ft & VT_BTYPE) == VT_BOOL) {
2369 gen_cast(VT_BOOL);
2371 r = gv(); /* generate value */
2372 ft = vtop[-1].t;
2373 fc = vtop[-1].c;
2374 /* if lvalue was saved on stack, must read it */
2375 if ((ft & VT_VALMASK) == VT_LLOCAL) {
2376 t = get_reg(REG_CLASS_INT);
2377 load(t, VT_LOCAL | VT_LVAL, fc);
2378 ft = (ft & ~VT_VALMASK) | t;
2380 store(r, ft, fc);
2381 vtop--;
2382 vtop->t = (ft & VT_TYPE) | r;
2383 vtop->c = 0;
2387 /* post defines POST/PRE add. c is the token ++ or -- */
2388 void inc(int post, int c)
2390 int r, r1;
2392 test_lvalue();
2393 if (post)
2394 vdup(); /* room for returned value */
2395 vdup(); /* save lvalue */
2396 r = gv();
2397 if (post) {
2398 /* duplicate value */
2399 /* XXX: handle floats */
2400 r1 = get_reg(REG_CLASS_INT);
2401 load(r1, r, 0); /* move r to r1 */
2402 /* duplicates value */
2403 vtop[-2].t = (vtop->t & VT_TYPE) | r1;
2404 vtop[-2].c = 0;
2406 /* add constant */
2407 vset(VT_CONST, c - TOK_MID);
2408 gen_op('+');
2409 vstore(); /* store value */
2410 if (post)
2411 vpop(); /* if post op, return saved value */
2414 /* enum/struct/union declaration */
2415 int struct_decl(int u)
2417 int a, t, b, v, size, align, maxalign, c, offset;
2418 int bit_size, bit_pos, bsize, bt, lbit_pos;
2419 Sym *s, *ss, **ps;
2421 a = tok; /* save decl type */
2422 next();
2423 if (tok != '{') {
2424 v = tok;
2425 next();
2426 /* struct already defined ? return it */
2427 /* XXX: check consistency */
2428 if (s = sym_find(v | SYM_STRUCT)) {
2429 if (s->t != a)
2430 error("invalid type");
2431 goto do_decl;
2433 } else {
2434 v = anon_sym++;
2436 s = sym_push(v | SYM_STRUCT, a, 0);
2437 /* put struct/union/enum name in type */
2438 do_decl:
2439 u = u | (v << VT_STRUCT_SHIFT);
2441 if (tok == '{') {
2442 next();
2443 if (s->c)
2444 error("struct/union/enum already defined");
2445 /* cannot be empty */
2446 c = 0;
2447 maxalign = 0;
2448 ps = &s->next;
2449 bit_pos = 0;
2450 offset = 0;
2451 while (1) {
2452 if (a == TOK_ENUM) {
2453 v = tok;
2454 next();
2455 if (tok == '=') {
2456 next();
2457 c = expr_const();
2459 /* enum symbols have static storage */
2460 sym_push(v, VT_CONST | VT_STATIC, c);
2461 if (tok == ',')
2462 next();
2463 c++;
2464 } else {
2465 b = ist();
2466 while (1) {
2467 bit_size = -1;
2468 v = 0;
2469 if (tok != ':') {
2470 t = type_decl(&v, b, TYPE_DIRECT);
2471 if ((t & VT_BTYPE) == VT_FUNC ||
2472 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
2473 error("invalid type for '%s'", get_tok_str(v, 0));
2474 } else {
2475 t = b;
2477 if (tok == ':') {
2478 next();
2479 bit_size = expr_const();
2480 /* XXX: handle v = 0 case for messages */
2481 if (bit_size < 0)
2482 error("negative width in bit-field '%s'",
2483 get_tok_str(v, 0));
2484 if (v && bit_size == 0)
2485 error("zero width for bit-field '%s'",
2486 get_tok_str(v, 0));
2488 size = type_size(t, &align);
2489 lbit_pos = 0;
2490 if (bit_size >= 0) {
2491 bt = t & VT_BTYPE;
2492 if (bt != VT_INT &&
2493 bt != VT_BYTE &&
2494 bt != VT_SHORT)
2495 error("bitfields must have scalar type");
2496 bsize = size * 8;
2497 if (bit_size > bsize) {
2498 error("width of '%s' exceeds its type",
2499 get_tok_str(v, 0));
2500 } else if (bit_size == bsize) {
2501 /* no need for bit fields */
2502 bit_pos = 0;
2503 } else if (bit_size == 0) {
2504 /* XXX: what to do if only padding in a
2505 structure ? */
2506 /* zero size: means to pad */
2507 if (bit_pos > 0)
2508 bit_pos = bsize;
2509 } else {
2510 /* we do not have enough room ? */
2511 if ((bit_pos + bit_size) > bsize)
2512 bit_pos = 0;
2513 lbit_pos = bit_pos;
2514 /* XXX: handle LSB first */
2515 t |= VT_BITFIELD |
2516 (bit_pos << VT_STRUCT_SHIFT) |
2517 (bit_size << (VT_STRUCT_SHIFT + 6));
2518 bit_pos += bit_size;
2520 } else {
2521 bit_pos = 0;
2523 if (v) {
2524 /* add new memory data only if starting
2525 bit field */
2526 if (lbit_pos == 0) {
2527 if (a == TOK_STRUCT) {
2528 c = (c + align - 1) & -align;
2529 offset = c;
2530 c += size;
2531 } else {
2532 offset = 0;
2533 if (size > c)
2534 c = size;
2536 if (align > maxalign)
2537 maxalign = align;
2539 #if 0
2540 printf("add field %s offset=%d",
2541 get_tok_str(v, 0), offset);
2542 if (t & VT_BITFIELD) {
2543 printf(" pos=%d size=%d",
2544 (t >> VT_STRUCT_SHIFT) & 0x3f,
2545 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
2547 printf("\n");
2548 #endif
2549 ss = sym_push(v | SYM_FIELD, t, offset);
2550 *ps = ss;
2551 ps = &ss->next;
2553 if (tok == ';' || tok == -1)
2554 break;
2555 skip(',');
2557 skip(';');
2559 if (tok == '}')
2560 break;
2562 skip('}');
2563 /* size for struct/union, dummy for enum */
2564 s->c = (c + maxalign - 1) & -maxalign;
2566 return u;
2569 /* return 0 if no type declaration. otherwise, return the basic type
2570 and skip it.
2571 XXX: A '2' is ored to ensure non zero return if int type.
2573 int ist(void)
2575 int t, u;
2576 Sym *s;
2578 t = 0;
2579 while(1) {
2580 switch(tok) {
2581 /* basic types */
2582 case TOK_CHAR:
2583 u = VT_BYTE;
2584 basic_type:
2585 next();
2586 basic_type1:
2587 if ((t & VT_BTYPE) != 0)
2588 error("too many basic types %x", t);
2589 t |= u;
2590 break;
2591 case TOK_VOID:
2592 u = VT_VOID;
2593 goto basic_type;
2594 case TOK_SHORT:
2595 u = VT_SHORT;
2596 goto basic_type;
2597 case TOK_INT:
2598 next();
2599 break;
2600 case TOK_LONG:
2601 next();
2602 if ((t & VT_BTYPE) == VT_DOUBLE) {
2603 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
2604 } else if ((t & VT_BTYPE) == VT_LONG) {
2605 t = (t & ~VT_BTYPE) | VT_LLONG;
2606 } else {
2607 u = VT_LONG;
2608 goto basic_type1;
2610 break;
2611 case TOK_BOOL:
2612 u = VT_BOOL;
2613 goto basic_type;
2614 case TOK_FLOAT:
2615 u = VT_FLOAT;
2616 goto basic_type;
2617 case TOK_DOUBLE:
2618 next();
2619 if ((t & VT_BTYPE) == VT_LONG) {
2620 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
2621 } else {
2622 u = VT_DOUBLE;
2623 goto basic_type1;
2625 break;
2626 case TOK_ENUM:
2627 u = struct_decl(VT_ENUM);
2628 goto basic_type1;
2629 case TOK_STRUCT:
2630 case TOK_UNION:
2631 u = struct_decl(VT_STRUCT);
2632 goto basic_type1;
2634 /* type modifiers */
2635 case TOK_CONST:
2636 case TOK_VOLATILE:
2637 case TOK_REGISTER:
2638 case TOK_SIGNED:
2639 case TOK_AUTO:
2640 case TOK_INLINE:
2641 case TOK_RESTRICT:
2642 next();
2643 break;
2644 case TOK_UNSIGNED:
2645 t |= VT_UNSIGNED;
2646 next();
2647 break;
2649 /* storage */
2650 case TOK_EXTERN:
2651 t |= VT_EXTERN;
2652 next();
2653 break;
2654 case TOK_STATIC:
2655 t |= VT_STATIC;
2656 next();
2657 break;
2658 case TOK_TYPEDEF:
2659 t |= VT_TYPEDEF;
2660 next();
2661 break;
2662 default:
2663 s = sym_find(tok);
2664 if (!s || !(s->t & VT_TYPEDEF))
2665 goto the_end;
2666 t |= (s->t & ~VT_TYPEDEF);
2667 next();
2668 break;
2670 t |= 2;
2672 the_end:
2673 /* long is never used as type */
2674 if ((t & VT_BTYPE) == VT_LONG)
2675 t = (t & ~VT_BTYPE) | VT_INT;
2676 return t;
2679 int post_type(int t)
2681 int p, n, pt, l, t1;
2682 Sym **plast, *s, *first;
2684 if (tok == '(') {
2685 /* function declaration */
2686 next();
2687 l = 0;
2688 first = NULL;
2689 plast = &first;
2690 while (tok != ')') {
2691 /* read param name and compute offset */
2692 if (l != FUNC_OLD) {
2693 if (!(pt = ist())) {
2694 if (l) {
2695 error("invalid type");
2696 } else {
2697 l = FUNC_OLD;
2698 goto old_proto;
2701 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
2702 break;
2703 l = FUNC_NEW;
2704 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
2705 } else {
2706 old_proto:
2707 n = tok;
2708 pt = VT_INT;
2709 next();
2711 /* array must be transformed to pointer according to ANSI C */
2712 pt &= ~VT_ARRAY;
2713 s = sym_push(n | SYM_FIELD, pt, 0);
2714 *plast = s;
2715 plast = &s->next;
2716 if (tok == ',') {
2717 next();
2718 if (l == FUNC_NEW && tok == TOK_DOTS) {
2719 l = FUNC_ELLIPSIS;
2720 next();
2721 break;
2725 skip(')');
2726 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2727 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2728 /* we push a anonymous symbol which will contain the function prototype */
2729 p = anon_sym++;
2730 s = sym_push(p, t, l);
2731 s->next = first;
2732 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
2733 } else if (tok == '[') {
2734 /* array definition */
2735 next();
2736 n = -1;
2737 if (tok != ']') {
2738 n = expr_const();
2739 if (n < 0)
2740 error("invalid array size");
2742 skip(']');
2743 /* parse next post type */
2744 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2745 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2747 /* we push a anonymous symbol which will contain the array
2748 element type */
2749 p = anon_sym++;
2750 sym_push(p, t, n);
2751 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
2753 return t;
2756 /* Read a type declaration (except basic type), and return the
2757 type. If v is true, then also put variable name in 'vtop->c' */
2758 int type_decl(int *v, int t, int td)
2760 int u, p;
2761 Sym *s;
2763 t = t & -3; /* suppress the ored '2' */
2764 while (tok == '*') {
2765 next();
2766 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
2767 next();
2768 t = mk_pointer(t);
2771 /* recursive type */
2772 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2773 if (tok == '(') {
2774 next();
2775 u = type_decl(v, 0, td);
2776 skip(')');
2777 } else {
2778 u = 0;
2779 /* type identifier */
2780 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
2781 *v = tok;
2782 next();
2783 } else {
2784 if (!(td & TYPE_ABSTRACT))
2785 expect("identifier");
2786 *v = 0;
2789 /* append t at the end of u */
2790 t = post_type(t);
2791 if (!u)
2792 return t;
2793 p = u;
2794 while(1) {
2795 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
2796 p = s->t;
2797 if (!p) {
2798 s->t = t;
2799 break;
2802 return u;
2805 /* define a new external reference to a function 'v' of type 'u' */
2806 Sym *external_sym(int v, int u)
2808 Sym *s;
2809 s = sym_find(v);
2810 if (!s) {
2811 /* push forward reference */
2812 s = sym_push1(&global_stack,
2813 v, u | VT_CONST | VT_FORWARD, 0);
2815 return s;
2818 void indir(void)
2820 if (vtop->t & VT_LVAL)
2821 gv();
2822 if ((vtop->t & VT_BTYPE) != VT_PTR)
2823 expect("pointer");
2824 vtop->t = pointed_type(vtop->t);
2825 if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */
2826 vtop->t |= VT_LVAL;
2829 void unary(void)
2831 int n, t, ft, fc, p, align, size;
2832 Sym *s;
2833 GFuncContext gf;
2835 if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
2836 vset(VT_CONST | VT_INT, tokc.i);
2837 next();
2838 } else if (tok == TOK_CFLOAT) {
2839 /* currently, cannot do more */
2840 vset(VT_CONST | VT_FLOAT, 0);
2841 next();
2842 } else if (tok == TOK_CDOUBLE) {
2843 /* currently, cannot do more */
2844 vset(VT_CONST | VT_DOUBLE, 0);
2845 next();
2846 } else if (tok == TOK_CLDOUBLE) {
2847 /* currently, cannot do more */
2848 vset(VT_CONST | VT_LDOUBLE, 0);
2849 next();
2850 } else if (tok == TOK___FUNC__) {
2851 /* special function name identifier */
2852 /* generate (char *) type */
2853 vset(VT_CONST | mk_pointer(VT_BYTE), glo);
2854 strcpy((void *)glo, funcname);
2855 glo += strlen(funcname) + 1;
2856 next();
2857 } else if (tok == TOK_LSTR) {
2858 t = VT_INT;
2859 goto str_init;
2860 } else if (tok == TOK_STR) {
2861 /* string parsing */
2862 t = VT_BYTE;
2863 str_init:
2864 type_size(t, &align);
2865 glo = (glo + align - 1) & -align;
2866 fc = glo;
2867 /* we must declare it as an array first to use initializer parser */
2868 t = VT_CONST | VT_ARRAY | mk_pointer(t);
2869 decl_initializer(t, glo, 1, 0);
2870 glo += type_size(t, &align);
2871 /* put it as pointer */
2872 vset(t & ~VT_ARRAY, fc);
2873 } else {
2874 t = tok;
2875 next();
2876 if (t == '(') {
2877 /* cast ? */
2878 if (t = ist()) {
2879 ft = type_decl(&n, t, TYPE_ABSTRACT);
2880 skip(')');
2881 /* check ISOC99 compound literal */
2882 if (tok == '{') {
2883 /* data is allocated locally by default */
2884 if (global_expr)
2885 ft |= VT_CONST;
2886 else
2887 ft |= VT_LOCAL;
2888 /* all except arrays are lvalues */
2889 if (!(ft & VT_ARRAY))
2890 ft |= VT_LVAL;
2891 fc = decl_initializer_alloc(ft, 1);
2892 vset(ft, fc);
2893 } else {
2894 unary();
2895 gen_cast(ft);
2897 } else {
2898 expr();
2899 skip(')');
2901 } else if (t == '*') {
2902 unary();
2903 indir();
2904 } else if (t == '&') {
2905 unary();
2906 /* functions names must be treated as function pointers,
2907 except for unary '&' and sizeof. Since we consider that
2908 functions are not lvalues, we only have to handle it
2909 there and in function calls. */
2910 if ((vtop->t & VT_BTYPE) != VT_FUNC)
2911 test_lvalue();
2912 vtop->t = mk_pointer(vtop->t & VT_LVALN);
2913 } else
2914 if (t == '!') {
2915 unary();
2916 if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST)
2917 vtop->c = !vtop->c;
2918 else if ((vtop->t & VT_VALMASK) == VT_CMP)
2919 vtop->c = vtop->c ^ 1;
2920 else
2921 vset(VT_JMP, gtst(1, 0));
2922 } else
2923 if (t == '~') {
2924 unary();
2925 vset(VT_CONST, -1);
2926 gen_op('^');
2927 } else
2928 if (t == '+') {
2929 unary();
2930 } else
2931 if (t == TOK_SIZEOF) {
2932 if (tok == '(') {
2933 next();
2934 if (t = ist())
2935 t = type_decl(&n, t, TYPE_ABSTRACT);
2936 else {
2937 /* XXX: some code could be generated: add eval
2938 flag */
2939 expr();
2940 t = vtop->t;
2941 vpop();
2943 skip(')');
2944 } else {
2945 unary();
2946 t = vtop->t;
2947 vpop();
2949 vset(VT_CONST, type_size(t, &t));
2950 } else
2951 if (t == TOK_INC || t == TOK_DEC) {
2952 unary();
2953 inc(0, t);
2954 } else if (t == '-') {
2955 vset(VT_CONST, 0);
2956 unary();
2957 gen_op('-');
2958 } else
2960 s = sym_find(t);
2961 if (!s) {
2962 if (tok != '(')
2963 error("'%s' undeclared", get_tok_str(t, 0));
2964 /* for simple function calls, we tolerate undeclared
2965 external reference */
2966 p = anon_sym++;
2967 sym_push1(&global_stack, p, 0, FUNC_OLD);
2968 /* int() function */
2969 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
2971 vset(s->t, s->c);
2972 /* if forward reference, we must point to s */
2973 if (vtop->t & VT_FORWARD)
2974 vtop->c = (int)s;
2978 /* post operations */
2979 while (1) {
2980 if (tok == TOK_INC | tok == TOK_DEC) {
2981 inc(1, tok);
2982 next();
2983 } else if (tok == '.' | tok == TOK_ARROW) {
2984 /* field */
2985 if (tok == TOK_ARROW)
2986 indir();
2987 test_lvalue();
2988 vtop->t &= VT_LVALN;
2989 next();
2990 /* expect pointer on structure */
2991 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
2992 expect("struct or union");
2993 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2994 /* find field */
2995 tok |= SYM_FIELD;
2996 while (s = s->next) {
2997 if (s->v == tok)
2998 break;
3000 if (!s)
3001 error("field not found");
3002 /* add field offset to pointer */
3003 vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; /* change type to int */
3004 vset(VT_CONST, s->c);
3005 gen_op('+');
3006 /* change type to field type, and set to lvalue */
3007 vtop->t = (vtop->t & ~VT_TYPE) | s->t;
3008 /* an array is never an lvalue */
3009 if (!(vtop->t & VT_ARRAY))
3010 vtop->t |= VT_LVAL;
3011 next();
3012 } else if (tok == '[') {
3013 next();
3014 expr();
3015 gen_op('+');
3016 indir();
3017 skip(']');
3018 } else if (tok == '(') {
3019 int rett, retc;
3021 /* function call */
3022 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
3023 /* pointer test (no array accepted) */
3024 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
3025 vtop->t = pointed_type(vtop->t);
3026 if ((vtop->t & VT_BTYPE) != VT_FUNC)
3027 goto error_func;
3028 } else {
3029 error_func:
3030 expect("function pointer");
3032 } else {
3033 vtop->t &= ~VT_LVAL; /* no lvalue */
3036 /* get return type */
3037 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
3038 save_regs(); /* save used temporary registers */
3039 gfunc_start(&gf);
3040 next();
3041 #ifdef INVERT_FUNC_PARAMS
3043 int *str, len, parlevel, *saved_macro_ptr;
3044 Sym *args, *s1;
3046 /* read each argument and store it on a stack */
3047 /* XXX: merge it with macro args ? */
3048 args = NULL;
3049 while (tok != ')') {
3050 len = 0;
3051 str = NULL;
3052 parlevel = 0;
3053 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
3054 tok != -1) {
3055 if (tok == '(')
3056 parlevel++;
3057 else if (tok == ')')
3058 parlevel--;
3059 tok_add2(&str, &len, tok, &tokc);
3060 next();
3062 tok_add(&str, &len, -1); /* end of file added */
3063 tok_add(&str, &len, 0);
3064 sym_push2(&args, 0, 0, (int)str);
3065 if (tok != ',')
3066 break;
3067 next();
3069 if (tok != ')')
3070 expect(")");
3072 /* now generate code in reverse order by reading the stack */
3073 saved_macro_ptr = macro_ptr;
3074 while (args) {
3075 macro_ptr = (int *)args->c;
3076 next();
3077 expr_eq();
3078 if (tok != -1)
3079 expect("',' or ')'");
3080 gfunc_param(&gf);
3081 s1 = args->prev;
3082 free((int *)args->c);
3083 free(args);
3084 args = s1;
3086 macro_ptr = saved_macro_ptr;
3087 /* restore token */
3088 tok = ')';
3090 #endif
3091 /* compute first implicit argument if a structure is returned */
3092 if ((s->t & VT_BTYPE) == VT_STRUCT) {
3093 /* get some space for the returned structure */
3094 size = type_size(s->t, &align);
3095 loc = (loc - size) & -align;
3096 rett = s->t | VT_LOCAL | VT_LVAL;
3097 /* pass it as 'int' to avoid structure arg passing
3098 problems */
3099 vset(VT_INT | VT_LOCAL, loc);
3100 retc = vtop->c;
3101 gfunc_param(&gf);
3102 } else {
3103 rett = s->t | FUNC_RET_REG; /* return in register */
3104 retc = 0;
3106 #ifndef INVERT_FUNC_PARAMS
3107 while (tok != ')') {
3108 expr_eq();
3109 gfunc_param(&gf);
3110 if (tok == ',')
3111 next();
3113 #endif
3114 skip(')');
3115 gfunc_call(&gf);
3116 /* return value */
3117 vset(rett, retc);
3118 } else {
3119 break;
3124 int is_compatible_types(int t1, int t2)
3126 Sym *s1, *s2;
3127 int bt1, bt2;
3129 t1 &= VT_TYPE;
3130 t2 &= VT_TYPE;
3131 bt1 = t1 & VT_BTYPE;
3132 bt2 = t2 & VT_BTYPE;
3133 if (bt1 == VT_PTR) {
3134 t1 = pointed_type(t1);
3135 /* if function, then convert implicitely to function pointer */
3136 if (bt2 != VT_FUNC) {
3137 if (bt2 != VT_PTR)
3138 return 0;
3139 t2 = pointed_type(t2);
3141 /* void matches everything */
3142 t1 &= VT_TYPE;
3143 t2 &= VT_TYPE;
3144 if (t1 == VT_VOID || t2 == VT_VOID)
3145 return 1;
3146 return is_compatible_types(t1, t2);
3147 } else if (bt1 == VT_STRUCT) {
3148 return (t2 == t1);
3149 } else if (bt1 == VT_FUNC) {
3150 if (bt2 != VT_FUNC)
3151 return 0;
3152 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3153 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3154 if (!is_compatible_types(s1->t, s2->t))
3155 return 0;
3156 /* XXX: not complete */
3157 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3158 return 1;
3159 if (s1->c != s2->c)
3160 return 0;
3161 while (s1 != NULL) {
3162 if (s2 == NULL)
3163 return 0;
3164 if (!is_compatible_types(s1->t, s2->t))
3165 return 0;
3166 s1 = s1->next;
3167 s2 = s2->next;
3169 if (s2)
3170 return 0;
3171 return 1;
3172 } else {
3173 /* XXX: not complete */
3174 return 1;
3178 int check_assign_types(int t1, int t2)
3180 t1 &= VT_TYPE;
3181 t2 &= VT_TYPE;
3182 if ((t1 & VT_BTYPE) == VT_PTR &&
3183 (t2 & VT_BTYPE) == VT_FUNC) {
3184 return is_compatible_types(pointed_type(t1), t2);
3185 } else {
3186 return is_compatible_types(t1, t2);
3191 void uneq(void)
3193 int t;
3195 unary();
3196 if (tok == '=' ||
3197 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
3198 tok == TOK_A_XOR || tok == TOK_A_OR ||
3199 tok == TOK_A_SHL || tok == TOK_A_SAR) {
3200 test_lvalue();
3201 t = tok;
3202 next();
3203 if (t == '=') {
3204 expr_eq();
3205 if (!check_assign_types(vtop[-1].t, vtop[0].t))
3206 warning("incompatible types");
3207 } else {
3208 vdup();
3209 expr_eq();
3210 gen_op(t & 0x7f);
3212 vstore();
3216 void sum(int l)
3218 int t;
3220 if (l == 0)
3221 uneq();
3222 else {
3223 sum(--l);
3224 while ((l == 0 & (tok == '*' | tok == '/' | tok == '%')) |
3225 (l == 1 & (tok == '+' | tok == '-')) |
3226 (l == 2 & (tok == TOK_SHL | tok == TOK_SAR)) |
3227 (l == 3 & ((tok >= TOK_ULE & tok <= TOK_GT) |
3228 tok == TOK_ULT | tok == TOK_UGE)) |
3229 (l == 4 & (tok == TOK_EQ | tok == TOK_NE)) |
3230 (l == 5 & tok == '&') |
3231 (l == 6 & tok == '^') |
3232 (l == 7 & tok == '|') |
3233 (l == 8 & tok == TOK_LAND) |
3234 (l == 9 & tok == TOK_LOR)) {
3235 t = tok;
3236 next();
3237 sum(l);
3238 gen_op(t);
3243 /* only used if non constant */
3244 void eand(void)
3246 int t;
3248 sum(8);
3249 t = 0;
3250 while (1) {
3251 if (tok != TOK_LAND) {
3252 if (t) {
3253 t = gtst(1, t);
3254 vset(VT_JMPI, t);
3256 break;
3258 t = gtst(1, t);
3259 next();
3260 sum(8);
3264 void eor(void)
3266 int t;
3268 eand();
3269 t = 0;
3270 while (1) {
3271 if (tok != TOK_LOR) {
3272 if (t) {
3273 t = gtst(0, t);
3274 vset(VT_JMP, t);
3276 break;
3278 t = gtst(0, t);
3279 next();
3280 eand();
3284 /* XXX: better constant handling */
3285 void expr_eq(void)
3287 int t, u, c, r1, r2;
3289 if (const_wanted) {
3290 sum(10);
3291 if (tok == '?') {
3292 c = vtop->c;
3293 vpop();
3294 next();
3295 expr();
3296 t = vtop->c;
3297 vpop();
3298 skip(':');
3299 expr_eq();
3300 if (c)
3301 vtop->c = t;
3303 } else {
3304 eor();
3305 if (tok == '?') {
3306 next();
3307 t = gtst(1, 0);
3309 expr();
3310 r1 = gv();
3311 vpop();
3312 skip(':');
3313 u = gjmp(0);
3315 gsym(t);
3316 expr_eq();
3317 r2 = gv();
3318 move_reg(r1, r2);
3319 vtop->t = (vtop->t & VT_TYPE) | r1;
3320 gsym(u);
3325 void expr(void)
3327 while (1) {
3328 expr_eq();
3329 if (tok != ',')
3330 break;
3331 vpop();
3332 next();
3336 int expr_const(void)
3338 int a, c;
3339 a = const_wanted;
3340 const_wanted = 1;
3341 expr_eq();
3342 if ((vtop->t & (VT_CONST | VT_LVAL)) != VT_CONST)
3343 expect("constant");
3344 const_wanted = a;
3345 c = vtop->c;
3346 vpop();
3347 return c;
3350 /* return the label token if current token is a label, otherwise
3351 return zero */
3352 int is_label(void)
3354 int t;
3355 CValue c;
3357 /* fast test first */
3358 if (tok < TOK_UIDENT)
3359 return 0;
3360 /* no need to save tokc since we expect an identifier */
3361 t = tok;
3362 c = tokc;
3363 next();
3364 if (tok == ':') {
3365 next();
3366 return t;
3367 } else {
3368 /* XXX: may not work in all cases (macros ?) */
3369 tok1 = tok;
3370 tok1c = tokc;
3371 tok = t;
3372 tokc = c;
3373 return 0;
3377 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
3379 int a, b, c, d;
3380 Sym *s;
3382 if (tok == TOK_IF) {
3383 /* if test */
3384 next();
3385 skip('(');
3386 expr();
3387 skip(')');
3388 a = gtst(1, 0);
3389 block(bsym, csym, case_sym, def_sym, case_reg);
3390 c = tok;
3391 if (c == TOK_ELSE) {
3392 next();
3393 d = gjmp(0);
3394 gsym(a);
3395 block(bsym, csym, case_sym, def_sym, case_reg);
3396 gsym(d); /* patch else jmp */
3397 } else
3398 gsym(a);
3399 } else if (tok == TOK_WHILE) {
3400 next();
3401 d = ind;
3402 skip('(');
3403 expr();
3404 skip(')');
3405 a = gtst(1, 0);
3406 b = 0;
3407 block(&a, &b, case_sym, def_sym, case_reg);
3408 oad(0xe9, d - ind - 5); /* jmp */
3409 gsym(a);
3410 gsym_addr(b, d);
3411 } else if (tok == '{') {
3412 next();
3413 /* declarations */
3414 s = local_stack.top;
3415 while (tok != '}') {
3416 decl(VT_LOCAL);
3417 if (tok != '}')
3418 block(bsym, csym, case_sym, def_sym, case_reg);
3420 /* pop locally defined symbols */
3421 sym_pop(&local_stack, s);
3422 next();
3423 } else if (tok == TOK_RETURN) {
3424 next();
3425 if (tok != ';') {
3426 expr();
3427 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
3428 /* if returning structure, must copy it to implicit
3429 first pointer arg location */
3430 vset(mk_pointer(func_vt) | VT_LOCAL | VT_LVAL, func_vc);
3431 indir();
3432 vswap();
3433 /* copy structure value to pointer */
3434 vstore();
3435 } else {
3436 /* move return value to standard return register */
3437 move_reg(FUNC_RET_REG, gv());
3439 vpop();
3441 skip(';');
3442 rsym = gjmp(rsym); /* jmp */
3443 } else if (tok == TOK_BREAK) {
3444 /* compute jump */
3445 if (!bsym)
3446 error("cannot break");
3447 *bsym = gjmp(*bsym);
3448 next();
3449 skip(';');
3450 } else if (tok == TOK_CONTINUE) {
3451 /* compute jump */
3452 if (!csym)
3453 error("cannot continue");
3454 *csym = gjmp(*csym);
3455 next();
3456 skip(';');
3457 } else if (tok == TOK_FOR) {
3458 int e;
3459 next();
3460 skip('(');
3461 if (tok != ';') {
3462 expr();
3463 vpop();
3465 skip(';');
3466 d = ind;
3467 c = ind;
3468 a = 0;
3469 b = 0;
3470 if (tok != ';') {
3471 expr();
3472 a = gtst(1, 0);
3474 skip(';');
3475 if (tok != ')') {
3476 e = gjmp(0);
3477 c = ind;
3478 expr();
3479 vpop();
3480 oad(0xe9, d - ind - 5); /* jmp */
3481 gsym(e);
3483 skip(')');
3484 block(&a, &b, case_sym, def_sym, case_reg);
3485 oad(0xe9, c - ind - 5); /* jmp */
3486 gsym(a);
3487 gsym_addr(b, c);
3488 } else
3489 if (tok == TOK_DO) {
3490 next();
3491 a = 0;
3492 b = 0;
3493 d = ind;
3494 block(&a, &b, case_sym, def_sym, case_reg);
3495 skip(TOK_WHILE);
3496 skip('(');
3497 gsym(b);
3498 expr();
3499 c = gtst(0, 0);
3500 gsym_addr(c, d);
3501 skip(')');
3502 gsym(a);
3503 skip(';');
3504 } else
3505 if (tok == TOK_SWITCH) {
3506 next();
3507 skip('(');
3508 expr();
3509 case_reg = gv();
3510 vpop();
3511 skip(')');
3512 a = 0;
3513 b = gjmp(0); /* jump to first case */
3514 c = 0;
3515 block(&a, csym, &b, &c, case_reg);
3516 /* if no default, jmp after switch */
3517 if (c == 0)
3518 c = ind;
3519 /* default label */
3520 gsym_addr(b, c);
3521 /* break label */
3522 gsym(a);
3523 } else
3524 if (tok == TOK_CASE) {
3525 next();
3526 a = expr_const();
3527 if (!case_sym)
3528 expect("switch");
3529 /* since a case is like a label, we must skip it with a jmp */
3530 b = gjmp(0);
3531 gsym(*case_sym);
3532 vset(case_reg, 0);
3533 vset(VT_CONST, a);
3534 gen_op(TOK_EQ);
3535 *case_sym = gtst(1, 0);
3536 gsym(b);
3537 skip(':');
3538 block(bsym, csym, case_sym, def_sym, case_reg);
3539 } else
3540 if (tok == TOK_DEFAULT) {
3541 next();
3542 skip(':');
3543 if (!def_sym)
3544 expect("switch");
3545 if (*def_sym)
3546 error("too many 'default'");
3547 *def_sym = ind;
3548 block(bsym, csym, case_sym, def_sym, case_reg);
3549 } else
3550 if (tok == TOK_GOTO) {
3551 next();
3552 s = sym_find1(&label_stack, tok);
3553 /* put forward definition if needed */
3554 if (!s)
3555 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
3556 /* label already defined */
3557 if (s->t & VT_FORWARD)
3558 s->c = gjmp(s->c); /* jmp xxx */
3559 else
3560 oad(0xe9, s->c - ind - 5); /* jmp xxx */
3561 next();
3562 skip(';');
3563 } else {
3564 b = is_label();
3565 if (b) {
3566 /* label case */
3567 s = sym_find1(&label_stack, b);
3568 if (s) {
3569 if (!(s->t & VT_FORWARD))
3570 error("multiple defined label");
3571 gsym(s->c);
3572 s->c = ind;
3573 s->t = 0;
3574 } else {
3575 sym_push1(&label_stack, b, 0, ind);
3577 /* we accept this, but it is a mistake */
3578 if (tok == '}')
3579 warning("deprecated use of label at end of compound statement");
3580 else
3581 block(bsym, csym, case_sym, def_sym, case_reg);
3582 } else {
3583 /* expression case */
3584 if (tok != ';') {
3585 expr();
3586 vpop();
3588 skip(';');
3593 /* t is the array or struct type. c is the array or struct
3594 address. cur_index/cur_field is the pointer to the current
3595 value. 'size_only' is true if only size info is needed (only used
3596 in arrays) */
3597 void decl_designator(int t, int c,
3598 int *cur_index, Sym **cur_field,
3599 int size_only)
3601 Sym *s, *f;
3602 int notfirst, index, align, l;
3604 notfirst = 0;
3605 if (gnu_ext && (l = is_label()) != 0)
3606 goto struct_field;
3608 while (tok == '[' || tok == '.') {
3609 if (tok == '[') {
3610 if (!(t & VT_ARRAY))
3611 expect("array type");
3612 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3613 next();
3614 index = expr_const();
3615 if (index < 0 || (s->c >= 0 && index >= s->c))
3616 expect("invalid index");
3617 skip(']');
3618 if (!notfirst)
3619 *cur_index = index;
3620 t = pointed_type(t);
3621 c += index * type_size(t, &align);
3622 } else {
3623 next();
3624 l = tok;
3625 next();
3626 struct_field:
3627 if ((t & VT_BTYPE) != VT_STRUCT)
3628 expect("struct/union type");
3629 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3630 l |= SYM_FIELD;
3631 f = s->next;
3632 while (f) {
3633 if (f->v == l)
3634 break;
3635 f = f->next;
3637 if (!f)
3638 expect("field");
3639 if (!notfirst)
3640 *cur_field = f;
3641 t = f->t | (t & ~VT_TYPE);
3642 c += f->c;
3644 notfirst = 1;
3646 if (notfirst) {
3647 if (tok == '=') {
3648 next();
3649 } else {
3650 if (!gnu_ext)
3651 expect("=");
3653 } else {
3654 if (t & VT_ARRAY) {
3655 index = *cur_index;
3656 t = pointed_type(t);
3657 c += index * type_size(t, &align);
3658 } else {
3659 f = *cur_field;
3660 if (!f)
3661 error("too many field init");
3662 t = f->t | (t & ~VT_TYPE);
3663 c += f->c;
3666 decl_initializer(t, c, 0, size_only);
3669 /* store a value or an expression directly in global data or in local array */
3671 void init_putv(int t, int c, int v, int is_expr)
3673 int saved_global_expr;
3675 if ((t & VT_VALMASK) == VT_CONST) {
3676 if (is_expr) {
3677 /* compound literals must be allocated globally in this case */
3678 saved_global_expr = global_expr;
3679 global_expr = 1;
3680 v = expr_const();
3681 global_expr = saved_global_expr;
3683 if ((t & VT_BTYPE) == VT_BYTE)
3684 *(char *)c = v;
3685 else if ((t & VT_BTYPE) == VT_SHORT)
3686 *(short *)c = v;
3687 else
3688 *(int *)c = v;
3689 } else {
3690 vset(t, c);
3691 if (is_expr)
3692 expr_eq();
3693 else
3694 vset(VT_CONST, v);
3695 vstore();
3696 vpop();
3700 /* put zeros for variable based init */
3701 void init_putz(int t, int c, int size)
3703 GFuncContext gf;
3705 if ((t & VT_VALMASK) == VT_CONST) {
3706 /* nothing to do because global are already set to zero */
3707 } else {
3708 gfunc_start(&gf);
3709 vset(VT_CONST, size);
3710 gfunc_param(&gf);
3711 vset(VT_CONST, 0);
3712 gfunc_param(&gf);
3713 vset(VT_LOCAL, c);
3714 gfunc_param(&gf);
3715 vset(VT_CONST, (int)&memset);
3716 gfunc_call(&gf);
3720 /* 't' contains the type and storage info. c is the address of the
3721 object. 'first' is true if array '{' must be read (multi dimension
3722 implicit array init handling). 'size_only' is true if size only
3723 evaluation is wanted (only for arrays). */
3724 void decl_initializer(int t, int c, int first, int size_only)
3726 int index, array_length, n, no_oblock, nb, parlevel, i;
3727 int t1, size1, align1;
3728 Sym *s, *f;
3729 TokenSym *ts;
3731 if (t & VT_ARRAY) {
3732 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3733 n = s->c;
3734 array_length = 0;
3735 t1 = pointed_type(t);
3736 size1 = type_size(t1, &align1);
3738 no_oblock = 1;
3739 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
3740 tok == '{') {
3741 skip('{');
3742 no_oblock = 0;
3745 /* only parse strings here if correct type (otherwise: handle
3746 them as ((w)char *) expressions */
3747 if ((tok == TOK_LSTR &&
3748 (t1 & VT_BTYPE) == VT_INT) ||
3749 (tok == TOK_STR &&
3750 (t1 & VT_BTYPE) == VT_BYTE)) {
3751 /* XXX: move multiple string parsing in parser ? */
3752 while (tok == TOK_STR || tok == TOK_LSTR) {
3753 ts = tokc.ts;
3754 /* compute maximum number of chars wanted */
3755 nb = ts->len;
3756 if (n >= 0 && nb > (n - array_length))
3757 nb = n - array_length;
3758 if (!size_only) {
3759 if (ts->len > nb)
3760 warning("initializer-string for array is too long");
3761 for(i=0;i<nb;i++) {
3762 init_putv(t1, c + (array_length + i) * size1,
3763 ts->str[i], 0);
3766 array_length += nb;
3767 next();
3769 /* only add trailing zero if enough storage (no
3770 warning in this case since it is standard) */
3771 if (n < 0 || array_length < n) {
3772 if (!size_only) {
3773 init_putv(t1, c + (array_length * size1), 0, 0);
3775 array_length++;
3777 } else {
3778 index = 0;
3779 while (tok != '}') {
3780 decl_designator(t, c, &index, NULL, size_only);
3781 if (n >= 0 && index >= n)
3782 error("index too large");
3783 /* must put zero in holes (note that doing it that way
3784 ensures that it even works with designators) */
3785 if (!size_only && array_length < index) {
3786 init_putz(t1, c + array_length * size1,
3787 (index - array_length) * size1);
3789 index++;
3790 if (index > array_length)
3791 array_length = index;
3792 /* special test for multi dimensional arrays (may not
3793 be strictly correct if designators are used at the
3794 same time) */
3795 if (index >= n && no_oblock)
3796 break;
3797 if (tok == '}')
3798 break;
3799 skip(',');
3802 if (!no_oblock)
3803 skip('}');
3804 /* put zeros at the end */
3805 if (!size_only && n >= 0 && array_length < n) {
3806 init_putz(t1, c + array_length * size1,
3807 (n - array_length) * size1);
3809 /* patch type size if needed */
3810 if (n < 0)
3811 s->c = array_length;
3812 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
3813 /* XXX: union needs only one init */
3814 next();
3815 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3816 f = s->next;
3817 array_length = 0;
3818 index = 0;
3819 n = s->c;
3820 while (tok != '}') {
3821 decl_designator(t, c, NULL, &f, size_only);
3822 /* fill with zero between fields */
3823 index = f->c;
3824 if (!size_only && array_length < index) {
3825 init_putz(t, c + array_length,
3826 index - array_length);
3828 index = index + type_size(f->t, &align1);
3829 if (index > array_length)
3830 array_length = index;
3831 if (tok == '}')
3832 break;
3833 skip(',');
3834 f = f->next;
3836 /* put zeros at the end */
3837 if (!size_only && array_length < n) {
3838 init_putz(t, c + array_length,
3839 n - array_length);
3841 skip('}');
3842 } else if (tok == '{') {
3843 next();
3844 decl_initializer(t, c, first, size_only);
3845 skip('}');
3846 } else if (size_only) {
3847 /* just skip expression */
3848 parlevel = 0;
3849 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
3850 tok != -1) {
3851 if (tok == '(')
3852 parlevel++;
3853 else if (tok == ')')
3854 parlevel--;
3855 next();
3857 } else {
3858 init_putv(t, c, 0, 1);
3862 /* parse an initializer for type 't' if 'has_init' is true, and
3863 allocate space in local or global data space. The allocated address
3864 in returned */
3865 int decl_initializer_alloc(int t, int has_init)
3867 int size, align, addr, tok1;
3868 int *init_str, init_len, level, *saved_macro_ptr;
3870 size = type_size(t, &align);
3871 /* If unknown size, we must evaluate it before
3872 evaluating initializers because
3873 initializers can generate global data too
3874 (e.g. string pointers or ISOC99 compound
3875 literals). It also simplifies local
3876 initializers handling */
3877 init_len = 0;
3878 init_str = NULL;
3879 saved_macro_ptr = NULL; /* avoid warning */
3880 tok1 = 0;
3881 if (size < 0) {
3882 if (!has_init)
3883 error("unknown type size");
3884 /* get all init string */
3885 level = 0;
3886 while (level > 0 || (tok != ',' && tok != ';')) {
3887 if (tok < 0)
3888 error("unexpect end of file in initializer");
3889 tok_add2(&init_str, &init_len, tok, &tokc);
3890 if (tok == '{')
3891 level++;
3892 else if (tok == '}') {
3893 if (level == 0)
3894 break;
3895 level--;
3897 next();
3899 tok1 = tok;
3900 tok_add(&init_str, &init_len, -1);
3901 tok_add(&init_str, &init_len, 0);
3903 /* compute size */
3904 saved_macro_ptr = macro_ptr;
3905 macro_ptr = init_str;
3906 next();
3907 decl_initializer(t, 0, 1, 1);
3908 /* prepare second initializer parsing */
3909 macro_ptr = init_str;
3910 next();
3912 /* if still unknown size, error */
3913 size = type_size(t, &align);
3914 if (size < 0)
3915 error("unknown type size");
3917 if ((t & VT_VALMASK) == VT_LOCAL) {
3918 loc = (loc - size) & -align;
3919 addr = loc;
3920 } else {
3921 glo = (glo + align - 1) & -align;
3922 addr = glo;
3923 /* very important to increment global
3924 pointer at this time because
3925 initializers themselves can create new
3926 initializers */
3927 glo += size;
3929 if (has_init) {
3930 decl_initializer(t, addr, 1, 0);
3931 /* restore parse state if needed */
3932 if (init_str) {
3933 free(init_str);
3934 macro_ptr = saved_macro_ptr;
3935 tok = tok1;
3938 return addr;
3942 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3943 void decl(int l)
3945 int *a, t, b, v, u, addr, has_init, size, align;
3946 Sym *sym;
3948 while (1) {
3949 b = ist();
3950 if (!b) {
3951 /* skip redundant ';' */
3952 /* XXX: find more elegant solution */
3953 if (tok == ';') {
3954 next();
3955 continue;
3957 /* special test for old K&R protos without explicit int
3958 type. Only accepted when defining global data */
3959 if (l == VT_LOCAL || tok < TOK_DEFINE)
3960 break;
3961 b = VT_INT;
3963 if (((b & VT_BTYPE) == VT_ENUM ||
3964 (b & VT_BTYPE) == VT_STRUCT) &&
3965 tok == ';') {
3966 /* we accept no variable after */
3967 next();
3968 continue;
3970 while (1) { /* iterate thru each declaration */
3971 t = type_decl(&v, b, TYPE_DIRECT);
3972 if (tok == '{') {
3973 if (l == VT_LOCAL)
3974 error("cannot use local functions");
3975 if (!(t & VT_FUNC))
3976 expect("function definition");
3977 /* patch forward references */
3978 if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
3979 greloc_patch(sym, ind);
3980 sym->t = VT_CONST | t;
3981 } else {
3982 /* put function address */
3983 sym_push1(&global_stack, v, VT_CONST | t, ind);
3985 funcname = get_tok_str(v, 0);
3986 /* push a dummy symbol to enable local sym storage */
3987 sym_push1(&local_stack, 0, 0, 0);
3988 /* define parameters */
3989 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3990 /* XXX: the following is x86 dependant -> move it to
3991 x86 code gen */
3992 addr = 8;
3993 /* if the function returns a structure, then add an
3994 implicit pointer parameter */
3995 func_vt = sym->t;
3996 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
3997 func_vc = addr;
3998 addr += 4;
4000 while (sym = sym->next) {
4001 u = sym->t;
4002 sym_push(sym->v & ~SYM_FIELD,
4003 u | VT_LOCAL | VT_LVAL,
4004 addr);
4005 if ((u & VT_BTYPE) == VT_STRUCT) {
4006 #ifdef FUNC_STRUCT_PARAM_AS_PTR
4007 /* structs are passed as pointer */
4008 size = 4;
4009 #else
4010 /* structs are directly put on stack (x86
4011 like) */
4012 size = type_size(u, &align);
4013 size = (size + 3) & ~3;
4014 #endif
4015 } else {
4016 /* XXX: size will be different someday */
4017 size = 4;
4019 addr += size;
4021 loc = 0;
4022 o(0xe58955); /* push %ebp, mov %esp, %ebp */
4023 a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
4024 rsym = 0;
4025 block(0, 0, 0, 0, 0);
4026 gsym(rsym);
4027 o(0xc3c9); /* leave, ret */
4028 *a = (-loc + 3) & -4; /* align local size to word &
4029 save local variables */
4030 sym_pop(&label_stack, NULL); /* reset label stack */
4031 sym_pop(&local_stack, NULL); /* reset local stack */
4032 funcname = ""; /* for safety */
4033 func_vt = VT_VOID; /* for safety */
4034 break;
4035 } else {
4036 if (b & VT_TYPEDEF) {
4037 /* save typedefed type */
4038 /* XXX: test storage specifiers ? */
4039 sym_push(v, t | VT_TYPEDEF, 0);
4040 } else if ((t & VT_BTYPE) == VT_FUNC) {
4041 /* external function definition */
4042 external_sym(v, t);
4043 } else {
4044 /* not lvalue if array */
4045 if (!(t & VT_ARRAY))
4046 t |= VT_LVAL;
4047 if (b & VT_EXTERN) {
4048 /* external variable */
4049 external_sym(v, t);
4050 } else {
4051 u = l;
4052 if (t & VT_STATIC)
4053 u = VT_CONST;
4054 u |= t;
4055 has_init = (tok == '=');
4056 if (has_init)
4057 next();
4058 addr = decl_initializer_alloc(u, has_init);
4059 if (l == VT_CONST) {
4060 /* global scope: see if already defined */
4061 sym = sym_find(v);
4062 if (!sym)
4063 goto do_def;
4064 if (!is_compatible_types(sym->t, u))
4065 error("incompatible types for redefinition of '%s'",
4066 get_tok_str(v, 0));
4067 if (!(sym->t & VT_FORWARD))
4068 error("redefinition of '%s'", get_tok_str(v, 0));
4069 greloc_patch(sym, addr);
4070 } else {
4071 do_def:
4072 sym_push(v, u, addr);
4076 if (tok != ',') {
4077 skip(';');
4078 break;
4080 next();
4086 /* put all global symbols in the extern stack and do all the
4087 resolving which can be done without using external symbols from DLLs */
4088 /* XXX: could try to verify types, but would not to save them in
4089 extern_stack too */
4090 void resolve_global_syms(void)
4092 Sym *s, *s1, *ext_sym;
4093 Reloc **p;
4095 s = global_stack.top;
4096 while (s != NULL) {
4097 s1 = s->prev;
4098 /* do not save static or typedefed symbols or types */
4099 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
4100 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
4101 (s->v < SYM_FIRST_ANOM)) {
4102 ext_sym = sym_find1(&extern_stack, s->v);
4103 if (!ext_sym) {
4104 /* if the symbol do not exist, we simply save it */
4105 sym_push1(&extern_stack, s->v, s->t, s->c);
4106 } else if (ext_sym->t & VT_FORWARD) {
4107 /* external symbol already exists, but only as forward
4108 definition */
4109 if (!(s->t & VT_FORWARD)) {
4110 /* s is not forward, so we can relocate all symbols */
4111 greloc_patch(ext_sym, s->c);
4112 } else {
4113 /* the two symbols are forward: merge them */
4114 p = (Reloc **)&ext_sym->c;
4115 while (*p != NULL)
4116 p = &(*p)->next;
4117 *p = (Reloc *)s->c;
4119 } else {
4120 /* external symbol already exists and is defined :
4121 patch all references to it */
4122 if (!(s->t & VT_FORWARD))
4123 error("'%s' defined twice", get_tok_str(s->v, 0));
4124 greloc_patch(s, ext_sym->c);
4127 s = s1;
4131 /* compile a C file. Return non zero if errors. */
4132 int tcc_compile_file(const char *filename1)
4134 Sym *define_start;
4136 filename = (char *)filename1;
4138 line_num = 1;
4139 funcname = "";
4140 file = fopen(filename, "r");
4141 if (!file)
4142 error("file '%s' not found", filename);
4143 include_stack_ptr = include_stack;
4144 ifdef_stack_ptr = ifdef_stack;
4146 vtop = vstack - 1;
4147 anon_sym = SYM_FIRST_ANOM;
4149 define_start = define_stack.top;
4150 inp();
4151 ch = '\n'; /* needed to parse correctly first preprocessor command */
4152 next();
4153 decl(VT_CONST);
4154 if (tok != -1)
4155 expect("declaration");
4156 fclose(file);
4158 /* reset define stack, but leave -Dsymbols (may be incorrect if
4159 they are undefined) */
4160 sym_pop(&define_stack, define_start);
4162 resolve_global_syms();
4164 sym_pop(&global_stack, NULL);
4166 return 0;
4169 /* open a dynamic library so that its symbol are available for
4170 compiled programs */
4171 void open_dll(char *libname)
4173 char buf[1024];
4174 void *h;
4176 snprintf(buf, sizeof(buf), "lib%s.so", libname);
4177 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
4178 if (!h)
4179 error((char *)dlerror());
4182 void resolve_extern_syms(void)
4184 Sym *s, *s1;
4185 char *str;
4186 int addr;
4188 s = extern_stack.top;
4189 while (s != NULL) {
4190 s1 = s->prev;
4191 if (s->t & VT_FORWARD) {
4192 /* if there is at least one relocation to do, then find it
4193 and patch it */
4194 if (s->c) {
4195 str = get_tok_str(s->v, 0);
4196 addr = (int)dlsym(NULL, str);
4197 if (!addr)
4198 error("unresolved external reference '%s'", str);
4199 greloc_patch(s, addr);
4202 s = s1;
4206 /* output a binary file (for testing) */
4207 void build_exe(char *filename)
4209 FILE *f;
4210 f = fopen(filename, "w");
4211 fwrite((void *)prog, 1, ind - prog, f);
4212 fclose(f);
4215 int main(int argc, char **argv)
4217 Sym *s;
4218 int (*t)();
4219 char *p, *r, *outfile;
4220 int optind;
4222 include_paths[0] = "/usr/include";
4223 include_paths[1] = "/usr/lib/tcc";
4224 include_paths[2] = "/usr/local/lib/tcc";
4225 nb_include_paths = 3;
4227 /* add all tokens */
4228 tok_ident = TOK_IDENT;
4229 p = "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0";
4230 while (*p) {
4231 r = p;
4232 while (*r++);
4233 tok_alloc(p, r - p - 1);
4234 p = r;
4237 /* standard defines */
4238 define_symbol("__STDC__");
4239 #ifdef __i386__
4240 define_symbol("__i386__");
4241 #endif
4242 /* tiny C specific defines */
4243 define_symbol("__TINYC__");
4245 glo = (int)malloc(DATA_SIZE);
4246 memset((void *)glo, 0, DATA_SIZE);
4247 prog = (int)malloc(TEXT_SIZE);
4248 ind = prog;
4250 optind = 1;
4251 outfile = NULL;
4252 while (1) {
4253 if (optind >= argc) {
4254 show_help:
4255 printf("tcc version 0.9.2 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
4256 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile] infile [infile_args...]\n");
4257 return 1;
4259 r = argv[optind];
4260 if (r[0] != '-')
4261 break;
4262 optind++;
4263 if (r[1] == 'I') {
4264 if (nb_include_paths >= INCLUDE_PATHS_MAX)
4265 error("too many include paths");
4266 include_paths[nb_include_paths++] = r + 2;
4267 } else if (r[1] == 'D') {
4268 define_symbol(r + 2);
4269 } else if (r[1] == 'l') {
4270 open_dll(r + 2);
4271 } else if (r[1] == 'i') {
4272 if (optind >= argc)
4273 goto show_help;
4274 tcc_compile_file(argv[optind++]);
4275 } else if (r[1] == 'o') {
4276 /* currently, only for testing, so not documented */
4277 if (optind >= argc)
4278 goto show_help;
4279 outfile = argv[optind++];
4280 } else {
4281 fprintf(stderr, "invalid option -- '%s'\n", r);
4282 exit(1);
4286 tcc_compile_file(argv[optind]);
4288 resolve_extern_syms();
4290 if (outfile) {
4291 build_exe(outfile);
4292 return 0;
4293 } else {
4294 s = sym_find1(&extern_stack, TOK_MAIN);
4295 if (!s || (s->t & VT_FORWARD))
4296 error("main() not defined");
4297 t = (int (*)())s->c;
4298 return (*t)(argc - optind, argv + optind);