struct syntax fix
[tinycc.git] / tcc.c
blobd5e3b7968d5c869947d07606747a7dd05f919022
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 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 #define _GNU_SOURCE
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <math.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <setjmp.h>
32 #ifdef WIN32
33 #include <sys/timeb.h>
34 #endif
35 #ifndef WIN32
36 #include <sys/time.h>
37 #include <sys/ucontext.h>
38 #endif
39 #include "elf.h"
40 #include "stab.h"
41 #ifndef CONFIG_TCC_STATIC
42 #include <dlfcn.h>
43 #endif
45 #include "libtcc.h"
47 /* parser debug */
48 //#define PARSE_DEBUG
49 /* preprocessor debug */
50 //#define PP_DEBUG
51 /* include file debug */
52 //#define INC_DEBUG
54 //#define MEM_DEBUG
56 /* assembler debug */
57 //#define ASM_DEBUG
59 /* target selection */
60 //#define TCC_TARGET_I386 /* i386 code generator */
62 /* default target is I386 */
63 #if !defined(TCC_TARGET_I386)
64 #define TCC_TARGET_I386
65 #endif
67 #if !defined(WIN32) && !defined(TCC_UCLIBC)
68 #define CONFIG_TCC_BCHECK /* enable bound checking code */
69 #endif
71 /* define it to include assembler support */
72 #define CONFIG_TCC_ASM
74 #ifndef CONFIG_TCC_PREFIX
75 #define CONFIG_TCC_PREFIX "/usr/local"
76 #endif
78 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
79 executables or dlls */
80 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
82 #define INCLUDE_STACK_SIZE 32
83 #define IFDEF_STACK_SIZE 64
84 #define VSTACK_SIZE 64
85 #define STRING_MAX_SIZE 1024
87 #define TOK_HASH_SIZE 2048 /* must be a power of two */
88 #define TOK_ALLOC_INCR 512 /* must be a power of two */
89 #define TOK_STR_ALLOC_INCR_BITS 6
90 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
91 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
93 /* token symbol management */
94 typedef struct TokenSym {
95 struct TokenSym *hash_next;
96 struct Sym *sym_define; /* direct pointer to define */
97 struct Sym *sym_label; /* direct pointer to label */
98 struct Sym *sym_struct; /* direct pointer to structure */
99 struct Sym *sym_identifier; /* direct pointer to identifier */
100 int tok; /* token number */
101 int len;
102 char str[1];
103 } TokenSym;
105 typedef struct CString {
106 int size; /* size in bytes */
107 void *data; /* either 'char *' or 'int *' */
108 int size_allocated;
109 void *data_allocated; /* if non NULL, data has been malloced */
110 } CString;
112 /* type definition */
113 typedef struct CType {
114 int t;
115 struct Sym *ref;
116 } CType;
118 /* constant value */
119 typedef union CValue {
120 long double ld;
121 double d;
122 float f;
123 int i;
124 unsigned int ui;
125 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
126 long long ll;
127 unsigned long long ull;
128 struct CString *cstr;
129 void *ptr;
130 int tab[1];
131 } CValue;
133 /* value on stack */
134 typedef struct SValue {
135 CType type; /* type */
136 unsigned short r; /* register + flags */
137 unsigned short r2; /* second register, used for 'long long'
138 type. If not used, set to VT_CONST */
139 CValue c; /* constant, if VT_CONST */
140 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
141 } SValue;
143 /* symbol management */
144 typedef struct Sym {
145 int v; /* symbol token */
146 int r; /* associated register */
147 int c; /* associated number */
148 CType type; /* associated type */
149 struct Sym *next; /* next related symbol */
150 struct Sym *prev; /* prev symbol in stack */
151 struct Sym *prev_tok; /* previous symbol for this token */
152 } Sym;
154 /* section definition */
155 /* XXX: use directly ELF structure for parameters ? */
156 /* special flag to indicate that the section should not be linked to
157 the other ones */
158 #define SHF_PRIVATE 0x80000000
160 typedef struct Section {
161 unsigned long data_offset; /* current data offset */
162 unsigned char *data; /* section data */
163 unsigned long data_allocated; /* used for realloc() handling */
164 int sh_name; /* elf section name (only used during output) */
165 int sh_num; /* elf section number */
166 int sh_type; /* elf section type */
167 int sh_flags; /* elf section flags */
168 int sh_info; /* elf section info */
169 int sh_addralign; /* elf section alignment */
170 int sh_entsize; /* elf entry size */
171 unsigned long sh_size; /* section size (only used during output) */
172 unsigned long sh_addr; /* address at which the section is relocated */
173 unsigned long sh_offset; /* address at which the section is relocated */
174 int nb_hashed_syms; /* used to resize the hash table */
175 struct Section *link; /* link to another section */
176 struct Section *reloc; /* corresponding section for relocation, if any */
177 struct Section *hash; /* hash table for symbols */
178 struct Section *next;
179 char name[64]; /* section name */
180 } Section;
182 typedef struct DLLReference {
183 int level;
184 char name[1];
185 } DLLReference;
187 /* GNUC attribute definition */
188 typedef struct AttributeDef {
189 int aligned;
190 Section *section;
191 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
192 } AttributeDef;
194 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
195 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
196 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
198 /* stored in 'Sym.c' field */
199 #define FUNC_NEW 1 /* ansi function prototype */
200 #define FUNC_OLD 2 /* old function prototype */
201 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
203 /* stored in 'Sym.r' field */
204 #define FUNC_CDECL 0 /* standard c call */
205 #define FUNC_STDCALL 1 /* pascal c call */
207 /* field 'Sym.t' for macros */
208 #define MACRO_OBJ 0 /* object like macro */
209 #define MACRO_FUNC 1 /* function like macro */
211 /* field 'Sym.r' for C labels */
212 #define LABEL_DEFINED 0 /* label is defined */
213 #define LABEL_FORWARD 1 /* label is forward defined */
214 #define LABEL_DECLARED 2 /* label is declared but never used */
216 /* type_decl() types */
217 #define TYPE_ABSTRACT 1 /* type without variable */
218 #define TYPE_DIRECT 2 /* type with variable */
220 #define IO_BUF_SIZE 8192
222 typedef struct BufferedFile {
223 uint8_t *buf_ptr;
224 uint8_t *buf_end;
225 int fd;
226 int line_num; /* current line number - here to simply code */
227 int ifndef_macro; /* #ifndef macro / #endif search */
228 int ifndef_macro_saved; /* saved ifndef_macro */
229 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
230 char inc_type; /* type of include */
231 char inc_filename[512]; /* filename specified by the user */
232 char filename[1024]; /* current filename - here to simplify code */
233 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
234 } BufferedFile;
236 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
237 #define CH_EOF (-1) /* end of file */
239 /* parsing state (used to save parser state to reparse part of the
240 source several times) */
241 typedef struct ParseState {
242 int *macro_ptr;
243 int line_num;
244 int tok;
245 CValue tokc;
246 } ParseState;
248 /* used to record tokens */
249 typedef struct TokenString {
250 int *str;
251 int len;
252 int allocated_len;
253 int last_line_num;
254 } TokenString;
256 /* include file cache, used to find files faster and also to eliminate
257 inclusion if the include file is protected by #ifndef ... #endif */
258 typedef struct CachedInclude {
259 int ifndef_macro;
260 char type; /* '"' or '>' to give include type */
261 char filename[1]; /* path specified in #include */
262 } CachedInclude;
264 /* parser */
265 static struct BufferedFile *file;
266 static int ch, tok;
267 static CValue tokc;
268 static CString tokcstr; /* current parsed string, if any */
269 /* additionnal informations about token */
270 static int tok_flags;
271 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
272 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
273 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
275 static int *macro_ptr, *macro_ptr_allocated;
276 static int *unget_saved_macro_ptr;
277 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
278 static int unget_buffer_enabled;
279 static int parse_flags;
280 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
281 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
282 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
283 token. line feed is also
284 returned at eof */
286 static Section *text_section, *data_section, *bss_section; /* predefined sections */
287 static Section *cur_text_section; /* current section where function code is
288 generated */
289 /* bound check related sections */
290 static Section *bounds_section; /* contains global data bound description */
291 static Section *lbounds_section; /* contains local data bound description */
292 /* symbol sections */
293 static Section *symtab_section, *strtab_section;
295 /* debug sections */
296 static Section *stab_section, *stabstr_section;
298 /* loc : local variable index
299 ind : output code index
300 rsym: return symbol
301 anon_sym: anonymous symbol index
303 static int rsym, anon_sym, ind, loc;
304 /* expression generation modifiers */
305 static int const_wanted; /* true if constant wanted */
306 static int nocode_wanted; /* true if no code generation wanted for an expression */
307 static int global_expr; /* true if compound literals must be allocated
308 globally (used during initializers parsing */
309 static CType func_vt; /* current function return type (used by return
310 instruction) */
311 static int func_vc;
312 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
313 static int tok_ident;
314 static TokenSym **table_ident;
315 static TokenSym *hash_ident[TOK_HASH_SIZE];
316 static char token_buf[STRING_MAX_SIZE + 1];
317 static char *funcname;
318 static Sym *global_stack, *local_stack;
319 static Sym *define_stack;
320 static Sym *global_label_stack, *local_label_stack;
322 static SValue vstack[VSTACK_SIZE], *vtop;
323 /* some predefined types */
324 static CType char_pointer_type, func_old_type, int_type;
325 /* true if isid(c) || isnum(c) */
326 static unsigned char isidnum_table[256];
328 /* compile with debug symbol (and use them if error during execution) */
329 static int do_debug = 0;
331 /* compile with built-in memory and bounds checker */
332 static int do_bounds_check = 0;
334 /* display benchmark infos */
335 static int do_bench = 0;
336 static int total_lines;
337 static int total_bytes;
339 /* use GNU C extensions */
340 static int gnu_ext = 1;
342 /* use Tiny C extensions */
343 static int tcc_ext = 1;
345 /* max number of callers shown if error */
346 static int num_callers = 6;
347 static const char **rt_bound_error_msg;
349 /* XXX: suppress that ASAP */
350 static struct TCCState *tcc_state;
352 /* give the path of the tcc libraries */
353 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
355 struct TCCState {
356 int output_type;
358 BufferedFile **include_stack_ptr;
359 int *ifdef_stack_ptr;
361 /* include file handling */
362 char **include_paths;
363 int nb_include_paths;
364 char **sysinclude_paths;
365 int nb_sysinclude_paths;
366 CachedInclude **cached_includes;
367 int nb_cached_includes;
369 char **library_paths;
370 int nb_library_paths;
372 /* array of all loaded dlls (including those referenced by loaded
373 dlls) */
374 DLLReference **loaded_dlls;
375 int nb_loaded_dlls;
377 /* sections */
378 Section **sections;
379 int nb_sections; /* number of sections, including first dummy section */
381 /* got handling */
382 Section *got;
383 Section *plt;
384 unsigned long *got_offsets;
385 int nb_got_offsets;
386 /* give the correspondance from symtab indexes to dynsym indexes */
387 int *symtab_to_dynsym;
389 /* temporary dynamic symbol sections (for dll loading) */
390 Section *dynsymtab_section;
391 /* exported dynamic symbol section */
392 Section *dynsym;
394 /* if true, no standard headers are added */
395 int nostdinc;
397 /* if true, static linking is performed */
398 int static_link;
400 /* error handling */
401 void *error_opaque;
402 void (*error_func)(void *opaque, const char *msg);
403 int error_set_jmp_enabled;
404 jmp_buf error_jmp_buf;
405 int nb_errors;
407 /* tiny assembler state */
408 Sym *asm_labels;
410 /* see include_stack_ptr */
411 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
413 /* see ifdef_stack_ptr */
414 int ifdef_stack[IFDEF_STACK_SIZE];
417 /* The current value can be: */
418 #define VT_VALMASK 0x00ff
419 #define VT_CONST 0x00f0 /* constant in vc
420 (must be first non register value) */
421 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
422 #define VT_LOCAL 0x00f2 /* offset on stack */
423 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
424 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
425 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
426 #define VT_LVAL 0x0100 /* var is an lvalue */
427 #define VT_SYM 0x0200 /* a symbol value is added */
428 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
429 char/short stored in integer registers) */
430 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
431 dereferencing value */
432 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
433 bounding function call point is in vc */
434 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
435 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
436 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
437 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
439 /* types */
440 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
442 #define VT_INT 0 /* integer type */
443 #define VT_BYTE 1 /* signed byte type */
444 #define VT_SHORT 2 /* short type */
445 #define VT_VOID 3 /* void type */
446 #define VT_PTR 4 /* pointer */
447 #define VT_ENUM 5 /* enum definition */
448 #define VT_FUNC 6 /* function type */
449 #define VT_STRUCT 7 /* struct/union definition */
450 #define VT_FLOAT 8 /* IEEE float */
451 #define VT_DOUBLE 9 /* IEEE double */
452 #define VT_LDOUBLE 10 /* IEEE long double */
453 #define VT_BOOL 11 /* ISOC99 boolean type */
454 #define VT_LLONG 12 /* 64 bit integer */
455 #define VT_LONG 13 /* long integer (NEVER USED as type, only
456 during parsing) */
457 #define VT_BTYPE 0x000f /* mask for basic type */
458 #define VT_UNSIGNED 0x0010 /* unsigned type */
459 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
460 #define VT_BITFIELD 0x0040 /* bitfield modifier */
462 /* storage */
463 #define VT_EXTERN 0x00000080 /* extern definition */
464 #define VT_STATIC 0x00000100 /* static variable */
465 #define VT_TYPEDEF 0x00000200 /* typedef definition */
466 #define VT_INLINE 0x00000400 /* inline definition */
468 /* type mask (except storage) */
469 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
470 #define VT_TYPE (~(VT_STORAGE))
472 /* token values */
474 /* warning: the following compare tokens depend on i386 asm code */
475 #define TOK_ULT 0x92
476 #define TOK_UGE 0x93
477 #define TOK_EQ 0x94
478 #define TOK_NE 0x95
479 #define TOK_ULE 0x96
480 #define TOK_UGT 0x97
481 #define TOK_LT 0x9c
482 #define TOK_GE 0x9d
483 #define TOK_LE 0x9e
484 #define TOK_GT 0x9f
486 #define TOK_LAND 0xa0
487 #define TOK_LOR 0xa1
489 #define TOK_DEC 0xa2
490 #define TOK_MID 0xa3 /* inc/dec, to void constant */
491 #define TOK_INC 0xa4
492 #define TOK_UDIV 0xb0 /* unsigned division */
493 #define TOK_UMOD 0xb1 /* unsigned modulo */
494 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
495 #define TOK_CINT 0xb3 /* number in tokc */
496 #define TOK_CCHAR 0xb4 /* char constant in tokc */
497 #define TOK_STR 0xb5 /* pointer to string in tokc */
498 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
499 #define TOK_LCHAR 0xb7
500 #define TOK_LSTR 0xb8
501 #define TOK_CFLOAT 0xb9 /* float constant */
502 #define TOK_LINENUM 0xba /* line number info */
503 #define TOK_CDOUBLE 0xc0 /* double constant */
504 #define TOK_CLDOUBLE 0xc1 /* long double constant */
505 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
506 #define TOK_ADDC1 0xc3 /* add with carry generation */
507 #define TOK_ADDC2 0xc4 /* add with carry use */
508 #define TOK_SUBC1 0xc5 /* add with carry generation */
509 #define TOK_SUBC2 0xc6 /* add with carry use */
510 #define TOK_CUINT 0xc8 /* unsigned int constant */
511 #define TOK_CLLONG 0xc9 /* long long constant */
512 #define TOK_CULLONG 0xca /* unsigned long long constant */
513 #define TOK_ARROW 0xcb
514 #define TOK_DOTS 0xcc /* three dots */
515 #define TOK_SHR 0xcd /* unsigned shift right */
516 #define TOK_PPNUM 0xce /* preprocessor number */
518 #define TOK_SHL 0x01 /* shift left */
519 #define TOK_SAR 0x02 /* signed shift right */
521 /* assignement operators : normal operator or 0x80 */
522 #define TOK_A_MOD 0xa5
523 #define TOK_A_AND 0xa6
524 #define TOK_A_MUL 0xaa
525 #define TOK_A_ADD 0xab
526 #define TOK_A_SUB 0xad
527 #define TOK_A_DIV 0xaf
528 #define TOK_A_XOR 0xde
529 #define TOK_A_OR 0xfc
530 #define TOK_A_SHL 0x81
531 #define TOK_A_SAR 0x82
533 /* WARNING: the content of this string encodes token numbers */
534 static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
536 #define TOK_EOF (-1) /* end of file */
537 #define TOK_LINEFEED 10 /* line feed */
539 /* all identificators and strings have token above that */
540 #define TOK_IDENT 256
542 /* only used for i386 asm opcodes definitions */
543 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
545 #define DEF_BWL(x) \
546 DEF(TOK_ASM_ ## x ## b, #x "b") \
547 DEF(TOK_ASM_ ## x ## w, #x "w") \
548 DEF(TOK_ASM_ ## x ## l, #x "l") \
549 DEF(TOK_ASM_ ## x, #x)
551 #define DEF_WL(x) \
552 DEF(TOK_ASM_ ## x ## w, #x "w") \
553 DEF(TOK_ASM_ ## x ## l, #x "l") \
554 DEF(TOK_ASM_ ## x, #x)
556 #define DEF_FP1(x) \
557 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
558 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
559 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
560 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
562 #define DEF_FP(x) \
563 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
564 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
565 DEF_FP1(x)
567 #define DEF_ASMTEST(x) \
568 DEF_ASM(x ## o) \
569 DEF_ASM(x ## no) \
570 DEF_ASM(x ## b) \
571 DEF_ASM(x ## c) \
572 DEF_ASM(x ## nae) \
573 DEF_ASM(x ## nb) \
574 DEF_ASM(x ## nc) \
575 DEF_ASM(x ## ae) \
576 DEF_ASM(x ## e) \
577 DEF_ASM(x ## z) \
578 DEF_ASM(x ## ne) \
579 DEF_ASM(x ## nz) \
580 DEF_ASM(x ## be) \
581 DEF_ASM(x ## na) \
582 DEF_ASM(x ## nbe) \
583 DEF_ASM(x ## a) \
584 DEF_ASM(x ## s) \
585 DEF_ASM(x ## ns) \
586 DEF_ASM(x ## p) \
587 DEF_ASM(x ## pe) \
588 DEF_ASM(x ## np) \
589 DEF_ASM(x ## po) \
590 DEF_ASM(x ## l) \
591 DEF_ASM(x ## nge) \
592 DEF_ASM(x ## nl) \
593 DEF_ASM(x ## ge) \
594 DEF_ASM(x ## le) \
595 DEF_ASM(x ## ng) \
596 DEF_ASM(x ## nle) \
597 DEF_ASM(x ## g)
599 #define TOK_ASM_int TOK_INT
601 enum {
602 TOK_LAST = TOK_IDENT - 1,
603 #define DEF(id, str) id,
604 #include "tcctok.h"
605 #undef DEF
608 static const char tcc_keywords[] =
609 #define DEF(id, str) str "\0"
610 #include "tcctok.h"
611 #undef DEF
614 #define TOK_UIDENT TOK_DEFINE
616 #ifdef WIN32
617 #define snprintf _snprintf
618 #define vsnprintf _vsnprintf
619 #endif
621 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
622 /* currently incorrect */
623 long double strtold(const char *nptr, char **endptr)
625 return (long double)strtod(nptr, endptr);
627 float strtof(const char *nptr, char **endptr)
629 return (float)strtod(nptr, endptr);
631 #else
632 /* XXX: need to define this to use them in non ISOC99 context */
633 extern float strtof (const char *__nptr, char **__endptr);
634 extern long double strtold (const char *__nptr, char **__endptr);
635 #endif
637 static char *pstrcpy(char *buf, int buf_size, const char *s);
638 static char *pstrcat(char *buf, int buf_size, const char *s);
640 static void next(void);
641 static void next_nomacro(void);
642 static void parse_expr_type(CType *type);
643 static void expr_type(CType *type);
644 static void unary_type(CType *type);
645 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
646 int case_reg, int is_expr);
647 static int expr_const(void);
648 static void expr_eq(void);
649 static void gexpr(void);
650 static void decl(int l);
651 static void decl_initializer(CType *type, Section *sec, unsigned long c,
652 int first, int size_only);
653 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
654 int has_init, int v, int scope);
655 int gv(int rc);
656 void gv2(int rc1, int rc2);
657 void move_reg(int r, int s);
658 void save_regs(int n);
659 void save_reg(int r);
660 void vpop(void);
661 void vswap(void);
662 void vdup(void);
663 int get_reg(int rc);
665 static void macro_subst(TokenString *tok_str,
666 Sym **nested_list, const int *macro_str);
667 int save_reg_forced(int r);
668 void gen_op(int op);
669 void force_charshort_cast(int t);
670 static void gen_cast(CType *type);
671 void vstore(void);
672 static Sym *sym_find(int v);
673 static Sym *sym_push(int v, CType *type, int r, int c);
675 /* type handling */
676 static int type_size(CType *type, int *a);
677 static inline CType *pointed_type(CType *type);
678 static int pointed_size(CType *type);
679 static int lvalue_type(int t);
680 static int is_compatible_types(CType *type1, CType *type2);
681 static int parse_btype(CType *type, AttributeDef *ad);
682 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
684 void error(const char *fmt, ...);
685 void vpushi(int v);
686 void vset(CType *type, int r, int v);
687 void type_to_str(char *buf, int buf_size,
688 CType *type, const char *varstr);
689 char *get_tok_str(int v, CValue *cv);
690 static Sym *get_sym_ref(CType *type, Section *sec,
691 unsigned long offset, unsigned long size);
692 static Sym *external_global_sym(int v, CType *type, int r);
694 /* section generation */
695 static void section_realloc(Section *sec, unsigned long new_size);
696 static void *section_ptr_add(Section *sec, unsigned long size);
697 static void put_extern_sym(Sym *sym, Section *section,
698 unsigned long value, unsigned long size);
699 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
700 static int put_elf_str(Section *s, const char *sym);
701 static int put_elf_sym(Section *s,
702 unsigned long value, unsigned long size,
703 int info, int other, int shndx, const char *name);
704 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
705 int info, int sh_num, const char *name);
706 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
707 int type, int symbol);
708 static void put_stabs(const char *str, int type, int other, int desc,
709 unsigned long value);
710 static void put_stabs_r(const char *str, int type, int other, int desc,
711 unsigned long value, Section *sec, int sym_index);
712 static void put_stabn(int type, int other, int desc, int value);
713 static void put_stabd(int type, int other, int desc);
714 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
716 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
717 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
718 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
720 /* tccasm.c */
722 #ifdef CONFIG_TCC_ASM
724 typedef struct ExprValue {
725 uint32_t v;
726 Sym *sym;
727 } ExprValue;
729 #define MAX_ASM_OPERANDS 30
731 typedef struct ASMOperand {
732 int id; /* GCC 3 optionnal identifier (0 if number only supported */
733 char *constraint;
734 char asm_str[16]; /* computed asm string for operand */
735 SValue *vt; /* C value of the expression */
736 int ref_index; /* if >= 0, gives reference to a output constraint */
737 int priority; /* priority, used to assign registers */
738 int reg; /* if >= 0, register number used for this operand */
739 } ASMOperand;
741 static void asm_expr(TCCState *s1, ExprValue *pe);
742 static int asm_int_expr(TCCState *s1);
743 static int find_constraint(ASMOperand *operands, int nb_operands,
744 const char *name, const char **pp);
746 static int tcc_assemble(TCCState *s1, int do_preprocess);
748 #endif
750 static void asm_instr(void);
752 /* true if float/double/long double type */
753 static inline int is_float(int t)
755 int bt;
756 bt = t & VT_BTYPE;
757 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
760 #ifdef TCC_TARGET_I386
761 #include "i386-gen.c"
762 #endif
764 #ifdef CONFIG_TCC_STATIC
766 #define RTLD_LAZY 0x001
767 #define RTLD_NOW 0x002
768 #define RTLD_GLOBAL 0x100
769 #define RTLD_DEFAULT NULL
771 /* dummy function for profiling */
772 void *dlopen(const char *filename, int flag)
774 return NULL;
777 const char *dlerror(void)
779 return "error";
782 typedef struct TCCSyms {
783 char *str;
784 void *ptr;
785 } TCCSyms;
787 #define TCCSYM(a) { #a, &a, },
789 /* add the symbol you want here if no dynamic linking is done */
790 static TCCSyms tcc_syms[] = {
791 TCCSYM(printf)
792 TCCSYM(fprintf)
793 TCCSYM(fopen)
794 TCCSYM(fclose)
795 { NULL, NULL },
798 void *dlsym(void *handle, const char *symbol)
800 TCCSyms *p;
801 p = tcc_syms;
802 while (p->str != NULL) {
803 if (!strcmp(p->str, symbol))
804 return p->ptr;
805 p++;
807 return NULL;
810 #endif
812 /********************************************************/
814 /* we use our own 'finite' function to avoid potential problems with
815 non standard math libs */
816 /* XXX: endianness dependant */
817 int ieee_finite(double d)
819 int *p = (int *)&d;
820 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
823 /* copy a string and truncate it. */
824 static char *pstrcpy(char *buf, int buf_size, const char *s)
826 char *q, *q_end;
827 int c;
829 if (buf_size > 0) {
830 q = buf;
831 q_end = buf + buf_size - 1;
832 while (q < q_end) {
833 c = *s++;
834 if (c == '\0')
835 break;
836 *q++ = c;
838 *q = '\0';
840 return buf;
843 /* strcat and truncate. */
844 static char *pstrcat(char *buf, int buf_size, const char *s)
846 int len;
847 len = strlen(buf);
848 if (len < buf_size)
849 pstrcpy(buf + len, buf_size - len, s);
850 return buf;
853 /* memory management */
854 #ifdef MEM_DEBUG
855 int mem_cur_size;
856 int mem_max_size;
857 #endif
859 static inline void tcc_free(void *ptr)
861 #ifdef MEM_DEBUG
862 mem_cur_size -= malloc_usable_size(ptr);
863 #endif
864 free(ptr);
867 static void *tcc_malloc(unsigned long size)
869 void *ptr;
870 ptr = malloc(size);
871 if (!ptr && size)
872 error("memory full");
873 #ifdef MEM_DEBUG
874 mem_cur_size += malloc_usable_size(ptr);
875 if (mem_cur_size > mem_max_size)
876 mem_max_size = mem_cur_size;
877 #endif
878 return ptr;
881 static void *tcc_mallocz(unsigned long size)
883 void *ptr;
884 ptr = tcc_malloc(size);
885 memset(ptr, 0, size);
886 return ptr;
889 static inline void *tcc_realloc(void *ptr, unsigned long size)
891 void *ptr1;
892 #ifdef MEM_DEBUG
893 mem_cur_size -= malloc_usable_size(ptr);
894 #endif
895 ptr1 = realloc(ptr, size);
896 #ifdef MEM_DEBUG
897 /* NOTE: count not correct if alloc error, but not critical */
898 mem_cur_size += malloc_usable_size(ptr1);
899 if (mem_cur_size > mem_max_size)
900 mem_max_size = mem_cur_size;
901 #endif
902 return ptr1;
905 static char *tcc_strdup(const char *str)
907 char *ptr;
908 ptr = tcc_malloc(strlen(str) + 1);
909 strcpy(ptr, str);
910 return ptr;
913 #define free(p) use_tcc_free(p)
914 #define malloc(s) use_tcc_malloc(s)
915 #define realloc(p, s) use_tcc_realloc(p, s)
917 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
919 int nb, nb_alloc;
920 void **pp;
922 nb = *nb_ptr;
923 pp = *ptab;
924 /* every power of two we double array size */
925 if ((nb & (nb - 1)) == 0) {
926 if (!nb)
927 nb_alloc = 1;
928 else
929 nb_alloc = nb * 2;
930 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
931 if (!pp)
932 error("memory full");
933 *ptab = pp;
935 pp[nb++] = data;
936 *nb_ptr = nb;
939 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
941 Section *sec;
943 sec = tcc_mallocz(sizeof(Section));
944 pstrcpy(sec->name, sizeof(sec->name), name);
945 sec->sh_type = sh_type;
946 sec->sh_flags = sh_flags;
947 switch(sh_type) {
948 case SHT_HASH:
949 case SHT_REL:
950 case SHT_DYNSYM:
951 case SHT_SYMTAB:
952 case SHT_DYNAMIC:
953 sec->sh_addralign = 4;
954 break;
955 case SHT_STRTAB:
956 sec->sh_addralign = 1;
957 break;
958 default:
959 sec->sh_addralign = 32; /* default conservative alignment */
960 break;
963 /* only add section if not private */
964 if (!(sh_flags & SHF_PRIVATE)) {
965 sec->sh_num = s1->nb_sections;
966 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
968 return sec;
971 static void free_section(Section *s)
973 tcc_free(s->data);
974 tcc_free(s);
977 /* realloc section and set its content to zero */
978 static void section_realloc(Section *sec, unsigned long new_size)
980 unsigned long size;
981 unsigned char *data;
983 size = sec->data_allocated;
984 if (size == 0)
985 size = 1;
986 while (size < new_size)
987 size = size * 2;
988 data = tcc_realloc(sec->data, size);
989 if (!data)
990 error("memory full");
991 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
992 sec->data = data;
993 sec->data_allocated = size;
996 /* reserve at least 'size' bytes in section 'sec' from
997 sec->data_offset. */
998 static void *section_ptr_add(Section *sec, unsigned long size)
1000 unsigned long offset, offset1;
1002 offset = sec->data_offset;
1003 offset1 = offset + size;
1004 if (offset1 > sec->data_allocated)
1005 section_realloc(sec, offset1);
1006 sec->data_offset = offset1;
1007 return sec->data + offset;
1010 /* return a reference to a section, and create it if it does not
1011 exists */
1012 Section *find_section(TCCState *s1, const char *name)
1014 Section *sec;
1015 int i;
1016 for(i = 1; i < s1->nb_sections; i++) {
1017 sec = s1->sections[i];
1018 if (!strcmp(name, sec->name))
1019 return sec;
1021 /* sections are created as PROGBITS */
1022 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1025 /* update sym->c so that it points to an external symbol in section
1026 'section' with value 'value' */
1027 static void put_extern_sym(Sym *sym, Section *section,
1028 unsigned long value, unsigned long size)
1030 int sym_type, sym_bind, sh_num, info;
1031 Elf32_Sym *esym;
1032 const char *name;
1034 if (section)
1035 sh_num = section->sh_num;
1036 else
1037 sh_num = SHN_UNDEF;
1038 if (!sym->c) {
1039 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1040 sym_type = STT_FUNC;
1041 else
1042 sym_type = STT_OBJECT;
1043 if (sym->type.t & VT_STATIC)
1044 sym_bind = STB_LOCAL;
1045 else
1046 sym_bind = STB_GLOBAL;
1048 name = get_tok_str(sym->v, NULL);
1049 #ifdef CONFIG_TCC_BCHECK
1050 if (do_bounds_check) {
1051 char buf[32];
1053 /* XXX: avoid doing that for statics ? */
1054 /* if bound checking is activated, we change some function
1055 names by adding the "__bound" prefix */
1056 switch(sym->v) {
1057 #if 0
1058 /* XXX: we rely only on malloc hooks */
1059 case TOK_malloc:
1060 case TOK_free:
1061 case TOK_realloc:
1062 case TOK_memalign:
1063 case TOK_calloc:
1064 #endif
1065 case TOK_memcpy:
1066 case TOK_memmove:
1067 case TOK_memset:
1068 case TOK_strlen:
1069 case TOK_strcpy:
1070 strcpy(buf, "__bound_");
1071 strcat(buf, name);
1072 name = buf;
1073 break;
1076 #endif
1077 info = ELF32_ST_INFO(sym_bind, sym_type);
1078 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1079 } else {
1080 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1081 esym->st_value = value;
1082 esym->st_size = size;
1083 esym->st_shndx = sh_num;
1087 /* add a new relocation entry to symbol 'sym' in section 's' */
1088 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1090 if (!sym->c)
1091 put_extern_sym(sym, NULL, 0, 0);
1092 /* now we can add ELF relocation info */
1093 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1096 static inline int isid(int c)
1098 return (c >= 'a' && c <= 'z') ||
1099 (c >= 'A' && c <= 'Z') ||
1100 c == '_';
1103 static inline int isnum(int c)
1105 return c >= '0' && c <= '9';
1108 static inline int isoct(int c)
1110 return c >= '0' && c <= '7';
1113 static inline int toup(int c)
1115 if (c >= 'a' && c <= 'z')
1116 return c - 'a' + 'A';
1117 else
1118 return c;
1121 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1123 int len;
1124 len = strlen(buf);
1125 vsnprintf(buf + len, buf_size - len, fmt, ap);
1128 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1130 va_list ap;
1131 va_start(ap, fmt);
1132 strcat_vprintf(buf, buf_size, fmt, ap);
1133 va_end(ap);
1136 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1138 char buf[2048];
1139 BufferedFile **f;
1141 buf[0] = '\0';
1142 if (file) {
1143 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1144 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1145 (*f)->filename, (*f)->line_num);
1146 if (file->line_num > 0) {
1147 strcat_printf(buf, sizeof(buf),
1148 "%s:%d: ", file->filename, file->line_num);
1149 } else {
1150 strcat_printf(buf, sizeof(buf),
1151 "%s: ", file->filename);
1153 } else {
1154 strcat_printf(buf, sizeof(buf),
1155 "tcc: ");
1157 if (is_warning)
1158 strcat_printf(buf, sizeof(buf), "warning: ");
1159 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1161 if (!s1->error_func) {
1162 /* default case: stderr */
1163 fprintf(stderr, "%s\n", buf);
1164 } else {
1165 s1->error_func(s1->error_opaque, buf);
1167 if (!is_warning)
1168 s1->nb_errors++;
1171 #ifdef LIBTCC
1172 void tcc_set_error_func(TCCState *s, void *error_opaque,
1173 void (*error_func)(void *opaque, const char *msg))
1175 s->error_opaque = error_opaque;
1176 s->error_func = error_func;
1178 #endif
1180 /* error without aborting current compilation */
1181 void error_noabort(const char *fmt, ...)
1183 TCCState *s1 = tcc_state;
1184 va_list ap;
1186 va_start(ap, fmt);
1187 error1(s1, 0, fmt, ap);
1188 va_end(ap);
1191 void error(const char *fmt, ...)
1193 TCCState *s1 = tcc_state;
1194 va_list ap;
1196 va_start(ap, fmt);
1197 error1(s1, 0, fmt, ap);
1198 va_end(ap);
1199 /* better than nothing: in some cases, we accept to handle errors */
1200 if (s1->error_set_jmp_enabled) {
1201 longjmp(s1->error_jmp_buf, 1);
1202 } else {
1203 /* XXX: suppress it someday */
1204 exit(1);
1208 void expect(const char *msg)
1210 error("%s expected", msg);
1213 void warning(const char *fmt, ...)
1215 TCCState *s1 = tcc_state;
1216 va_list ap;
1218 va_start(ap, fmt);
1219 error1(s1, 1, fmt, ap);
1220 va_end(ap);
1223 void skip(int c)
1225 if (tok != c)
1226 error("'%c' expected", c);
1227 next();
1230 static void test_lvalue(void)
1232 if (!(vtop->r & VT_LVAL))
1233 expect("lvalue");
1236 /* allocate a new token */
1237 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1239 TokenSym *ts, **ptable;
1240 int i;
1242 if (tok_ident >= SYM_FIRST_ANOM)
1243 error("memory full");
1245 /* expand token table if needed */
1246 i = tok_ident - TOK_IDENT;
1247 if ((i % TOK_ALLOC_INCR) == 0) {
1248 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1249 if (!ptable)
1250 error("memory full");
1251 table_ident = ptable;
1254 ts = tcc_malloc(sizeof(TokenSym) + len);
1255 table_ident[i] = ts;
1256 ts->tok = tok_ident++;
1257 ts->sym_define = NULL;
1258 ts->sym_label = NULL;
1259 ts->sym_struct = NULL;
1260 ts->sym_identifier = NULL;
1261 ts->len = len;
1262 ts->hash_next = NULL;
1263 memcpy(ts->str, str, len);
1264 ts->str[len] = '\0';
1265 *pts = ts;
1266 return ts;
1269 #define TOK_HASH_INIT 1
1270 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1272 /* find a token and add it if not found */
1273 static TokenSym *tok_alloc(const char *str, int len)
1275 TokenSym *ts, **pts;
1276 int i;
1277 unsigned int h;
1279 h = TOK_HASH_INIT;
1280 for(i=0;i<len;i++)
1281 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1282 h &= (TOK_HASH_SIZE - 1);
1284 pts = &hash_ident[h];
1285 for(;;) {
1286 ts = *pts;
1287 if (!ts)
1288 break;
1289 if (ts->len == len && !memcmp(ts->str, str, len))
1290 return ts;
1291 pts = &(ts->hash_next);
1293 return tok_alloc_new(pts, str, len);
1296 /* CString handling */
1298 static void cstr_realloc(CString *cstr, int new_size)
1300 int size;
1301 void *data;
1303 size = cstr->size_allocated;
1304 if (size == 0)
1305 size = 8; /* no need to allocate a too small first string */
1306 while (size < new_size)
1307 size = size * 2;
1308 data = tcc_realloc(cstr->data_allocated, size);
1309 if (!data)
1310 error("memory full");
1311 cstr->data_allocated = data;
1312 cstr->size_allocated = size;
1313 cstr->data = data;
1316 /* add a byte */
1317 static void cstr_ccat(CString *cstr, int ch)
1319 int size;
1320 size = cstr->size + 1;
1321 if (size > cstr->size_allocated)
1322 cstr_realloc(cstr, size);
1323 ((unsigned char *)cstr->data)[size - 1] = ch;
1324 cstr->size = size;
1327 static void cstr_cat(CString *cstr, const char *str)
1329 int c;
1330 for(;;) {
1331 c = *str;
1332 if (c == '\0')
1333 break;
1334 cstr_ccat(cstr, c);
1335 str++;
1339 /* add a wide char */
1340 static void cstr_wccat(CString *cstr, int ch)
1342 int size;
1343 size = cstr->size + sizeof(int);
1344 if (size > cstr->size_allocated)
1345 cstr_realloc(cstr, size);
1346 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1347 cstr->size = size;
1350 static void cstr_new(CString *cstr)
1352 memset(cstr, 0, sizeof(CString));
1355 /* free string and reset it to NULL */
1356 static void cstr_free(CString *cstr)
1358 tcc_free(cstr->data_allocated);
1359 cstr_new(cstr);
1362 #define cstr_reset(cstr) cstr_free(cstr)
1364 static CString *cstr_dup(CString *cstr1)
1366 CString *cstr;
1367 int size;
1369 cstr = tcc_malloc(sizeof(CString));
1370 size = cstr1->size;
1371 cstr->size = size;
1372 cstr->size_allocated = size;
1373 cstr->data_allocated = tcc_malloc(size);
1374 cstr->data = cstr->data_allocated;
1375 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1376 return cstr;
1379 /* XXX: unicode ? */
1380 static void add_char(CString *cstr, int c)
1382 if (c == '\'' || c == '\"' || c == '\\') {
1383 /* XXX: could be more precise if char or string */
1384 cstr_ccat(cstr, '\\');
1386 if (c >= 32 && c <= 126) {
1387 cstr_ccat(cstr, c);
1388 } else {
1389 cstr_ccat(cstr, '\\');
1390 if (c == '\n') {
1391 cstr_ccat(cstr, 'n');
1392 } else {
1393 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1394 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1395 cstr_ccat(cstr, '0' + (c & 7));
1400 /* XXX: buffer overflow */
1401 /* XXX: float tokens */
1402 char *get_tok_str(int v, CValue *cv)
1404 static char buf[STRING_MAX_SIZE + 1];
1405 static CString cstr_buf;
1406 CString *cstr;
1407 unsigned char *q;
1408 char *p;
1409 int i, len;
1411 /* NOTE: to go faster, we give a fixed buffer for small strings */
1412 cstr_reset(&cstr_buf);
1413 cstr_buf.data = buf;
1414 cstr_buf.size_allocated = sizeof(buf);
1415 p = buf;
1417 switch(v) {
1418 case TOK_CINT:
1419 case TOK_CUINT:
1420 /* XXX: not quite exact, but only useful for testing */
1421 sprintf(p, "%u", cv->ui);
1422 break;
1423 case TOK_CLLONG:
1424 case TOK_CULLONG:
1425 /* XXX: not quite exact, but only useful for testing */
1426 sprintf(p, "%Lu", cv->ull);
1427 break;
1428 case TOK_CCHAR:
1429 case TOK_LCHAR:
1430 cstr_ccat(&cstr_buf, '\'');
1431 add_char(&cstr_buf, cv->i);
1432 cstr_ccat(&cstr_buf, '\'');
1433 cstr_ccat(&cstr_buf, '\0');
1434 break;
1435 case TOK_PPNUM:
1436 cstr = cv->cstr;
1437 len = cstr->size - 1;
1438 for(i=0;i<len;i++)
1439 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1440 cstr_ccat(&cstr_buf, '\0');
1441 break;
1442 case TOK_STR:
1443 case TOK_LSTR:
1444 cstr = cv->cstr;
1445 cstr_ccat(&cstr_buf, '\"');
1446 if (v == TOK_STR) {
1447 len = cstr->size - 1;
1448 for(i=0;i<len;i++)
1449 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1450 } else {
1451 len = (cstr->size / sizeof(int)) - 1;
1452 for(i=0;i<len;i++)
1453 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1455 cstr_ccat(&cstr_buf, '\"');
1456 cstr_ccat(&cstr_buf, '\0');
1457 break;
1458 case TOK_LT:
1459 v = '<';
1460 goto addv;
1461 case TOK_GT:
1462 v = '>';
1463 goto addv;
1464 case TOK_A_SHL:
1465 return strcpy(p, "<<=");
1466 case TOK_A_SAR:
1467 return strcpy(p, ">>=");
1468 default:
1469 if (v < TOK_IDENT) {
1470 /* search in two bytes table */
1471 q = tok_two_chars;
1472 while (*q) {
1473 if (q[2] == v) {
1474 *p++ = q[0];
1475 *p++ = q[1];
1476 *p = '\0';
1477 return buf;
1479 q += 3;
1481 addv:
1482 *p++ = v;
1483 *p = '\0';
1484 } else if (v < tok_ident) {
1485 return table_ident[v - TOK_IDENT]->str;
1486 } else if (v >= SYM_FIRST_ANOM) {
1487 /* special name for anonymous symbol */
1488 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1489 } else {
1490 /* should never happen */
1491 return NULL;
1493 break;
1495 return cstr_buf.data;
1498 /* push, without hashing */
1499 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1501 Sym *s;
1502 s = tcc_malloc(sizeof(Sym));
1503 s->v = v;
1504 s->type.t = t;
1505 s->c = c;
1506 s->next = NULL;
1507 /* add in stack */
1508 s->prev = *ps;
1509 *ps = s;
1510 return s;
1513 /* find a symbol and return its associated structure. 's' is the top
1514 of the symbol stack */
1515 static Sym *sym_find2(Sym *s, int v)
1517 while (s) {
1518 if (s->v == v)
1519 return s;
1520 s = s->prev;
1522 return NULL;
1525 /* structure lookup */
1526 static inline Sym *struct_find(int v)
1528 v -= TOK_IDENT;
1529 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1530 return NULL;
1531 return table_ident[v]->sym_struct;
1534 /* find an identifier */
1535 static inline Sym *sym_find(int v)
1537 v -= TOK_IDENT;
1538 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1539 return NULL;
1540 return table_ident[v]->sym_identifier;
1543 /* push a given symbol on the symbol stack */
1544 static Sym *sym_push(int v, CType *type, int r, int c)
1546 Sym *s, **ps;
1547 TokenSym *ts;
1549 if (local_stack)
1550 ps = &local_stack;
1551 else
1552 ps = &global_stack;
1553 s = sym_push2(ps, v, type->t, c);
1554 s->type.ref = type->ref;
1555 s->r = r;
1556 /* don't record fields or anonymous symbols */
1557 /* XXX: simplify */
1558 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1559 /* record symbol in token array */
1560 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1561 if (v & SYM_STRUCT)
1562 ps = &ts->sym_struct;
1563 else
1564 ps = &ts->sym_identifier;
1565 s->prev_tok = *ps;
1566 *ps = s;
1568 return s;
1571 /* push a global identifier */
1572 static Sym *global_identifier_push(int v, int t, int c)
1574 Sym *s, **ps;
1575 s = sym_push2(&global_stack, v, t, c);
1576 /* don't record anonymous symbol */
1577 if (v < SYM_FIRST_ANOM) {
1578 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1579 /* modify the top most local identifier, so that
1580 sym_identifier will point to 's' when popped */
1581 while (*ps != NULL)
1582 ps = &(*ps)->prev_tok;
1583 s->prev_tok = NULL;
1584 *ps = s;
1586 return s;
1589 /* pop symbols until top reaches 'b' */
1590 static void sym_pop(Sym **ptop, Sym *b)
1592 Sym *s, *ss, **ps;
1593 TokenSym *ts;
1594 int v;
1596 s = *ptop;
1597 while(s != b) {
1598 ss = s->prev;
1599 v = s->v;
1600 /* remove symbol in token array */
1601 /* XXX: simplify */
1602 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1603 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1604 if (v & SYM_STRUCT)
1605 ps = &ts->sym_struct;
1606 else
1607 ps = &ts->sym_identifier;
1608 *ps = s->prev_tok;
1610 tcc_free(s);
1611 s = ss;
1613 *ptop = b;
1616 /* I/O layer */
1618 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1620 int fd;
1621 BufferedFile *bf;
1623 fd = open(filename, O_RDONLY);
1624 if (fd < 0)
1625 return NULL;
1626 bf = tcc_malloc(sizeof(BufferedFile));
1627 if (!bf) {
1628 close(fd);
1629 return NULL;
1631 bf->fd = fd;
1632 bf->buf_ptr = bf->buffer;
1633 bf->buf_end = bf->buffer;
1634 bf->buffer[0] = CH_EOB; /* put eob symbol */
1635 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1636 bf->line_num = 1;
1637 bf->ifndef_macro = 0;
1638 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1639 // printf("opening '%s'\n", filename);
1640 return bf;
1643 void tcc_close(BufferedFile *bf)
1645 total_lines += bf->line_num;
1646 close(bf->fd);
1647 tcc_free(bf);
1650 /* fill input buffer and peek next char */
1651 static int tcc_peekc_slow(BufferedFile *bf)
1653 int len;
1654 /* only tries to read if really end of buffer */
1655 if (bf->buf_ptr >= bf->buf_end) {
1656 if (bf->fd != -1) {
1657 #if defined(PARSE_DEBUG)
1658 len = 8;
1659 #else
1660 len = IO_BUF_SIZE;
1661 #endif
1662 len = read(bf->fd, bf->buffer, len);
1663 if (len < 0)
1664 len = 0;
1665 } else {
1666 len = 0;
1668 total_bytes += len;
1669 bf->buf_ptr = bf->buffer;
1670 bf->buf_end = bf->buffer + len;
1671 *bf->buf_end = CH_EOB;
1673 if (bf->buf_ptr < bf->buf_end) {
1674 return bf->buf_ptr[0];
1675 } else {
1676 bf->buf_ptr = bf->buf_end;
1677 return CH_EOF;
1681 /* return the current character, handling end of block if necessary
1682 (but not stray) */
1683 static int handle_eob(void)
1685 return tcc_peekc_slow(file);
1688 /* read next char from current input file and handle end of input buffer */
1689 static inline void inp(void)
1691 ch = *(++(file->buf_ptr));
1692 /* end of buffer/file handling */
1693 if (ch == CH_EOB)
1694 ch = handle_eob();
1697 /* handle '\[\r]\n' */
1698 static void handle_stray(void)
1700 while (ch == '\\') {
1701 inp();
1702 if (ch == '\n') {
1703 file->line_num++;
1704 inp();
1705 } else if (ch == '\r') {
1706 inp();
1707 if (ch != '\n')
1708 goto fail;
1709 file->line_num++;
1710 inp();
1711 } else {
1712 fail:
1713 error("stray '\\' in program");
1718 /* skip the stray and handle the \\n case. Output an error if
1719 incorrect char after the stray */
1720 static int handle_stray1(uint8_t *p)
1722 int c;
1724 if (p >= file->buf_end) {
1725 file->buf_ptr = p;
1726 c = handle_eob();
1727 p = file->buf_ptr;
1728 if (c == '\\')
1729 goto parse_stray;
1730 } else {
1731 parse_stray:
1732 file->buf_ptr = p;
1733 ch = *p;
1734 handle_stray();
1735 p = file->buf_ptr;
1736 c = *p;
1738 return c;
1741 /* handle the complicated stray case */
1742 #define PEEKC(c, p)\
1744 p++;\
1745 c = *p;\
1746 if (c == '\\') {\
1747 c = handle_stray1(p);\
1748 p = file->buf_ptr;\
1752 /* input with '\[\r]\n' handling. Note that this function cannot
1753 handle other characters after '\', so you cannot call it inside
1754 strings or comments */
1755 static void minp(void)
1757 inp();
1758 if (ch == '\\')
1759 handle_stray();
1763 static void parse_line_comment(void)
1765 /* single line C++ comments */
1766 /* XXX: accept '\\\n' ? */
1767 inp();
1768 while (ch != '\n' && ch != CH_EOF)
1769 inp();
1772 static void parse_comment(void)
1774 uint8_t *p;
1775 int c;
1777 /* C comments */
1778 p = file->buf_ptr;
1779 p++;
1780 for(;;) {
1781 /* fast skip loop */
1782 for(;;) {
1783 c = *p;
1784 if (c == '\n' || c == '*' || c == '\\')
1785 break;
1786 p++;
1787 c = *p;
1788 if (c == '\n' || c == '*' || c == '\\')
1789 break;
1790 p++;
1792 /* now we can handle all the cases */
1793 if (c == '\n') {
1794 file->line_num++;
1795 p++;
1796 } else if (c == '*') {
1797 p++;
1798 for(;;) {
1799 c = *p;
1800 if (c == '*') {
1801 p++;
1802 } else if (c == '/') {
1803 goto end_of_comment;
1804 } else if (c == '\\') {
1805 file->buf_ptr = p;
1806 c = handle_eob();
1807 if (c == '\\') {
1808 /* skip '\\n', but if '\' followed but another
1809 char, behave asif a stray was parsed */
1810 ch = file->buf_ptr[0];
1811 while (ch == '\\') {
1812 inp();
1813 if (ch == '\n') {
1814 file->line_num++;
1815 inp();
1816 } else if (ch == '\r') {
1817 inp();
1818 if (ch == '\n') {
1819 file->line_num++;
1820 inp();
1822 } else {
1823 p = file->buf_ptr;
1824 break;
1828 p = file->buf_ptr;
1829 } else {
1830 break;
1833 } else {
1834 /* stray, eob or eof */
1835 file->buf_ptr = p;
1836 c = handle_eob();
1837 p = file->buf_ptr;
1838 if (c == CH_EOF) {
1839 error("unexpected end of file in comment");
1840 } else if (c == '\\') {
1841 p++;
1845 end_of_comment:
1846 p++;
1847 file->buf_ptr = p;
1848 ch = *p;
1851 #define cinp minp
1853 /* space exlcuding newline */
1854 static inline int is_space(int ch)
1856 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1859 static inline void skip_spaces(void)
1861 while (is_space(ch))
1862 cinp();
1865 /* skip block of text until #else, #elif or #endif. skip also pairs of
1866 #if/#endif */
1867 void preprocess_skip(void)
1869 int a, start_of_line, sep, c;
1870 uint8_t *p;
1872 p = file->buf_ptr;
1873 start_of_line = 1;
1874 a = 0;
1875 for(;;) {
1876 redo_no_start:
1877 c = *p;
1878 switch(c) {
1879 case ' ':
1880 case '\t':
1881 case '\f':
1882 case '\v':
1883 case '\r':
1884 p++;
1885 goto redo_no_start;
1886 case '\n':
1887 start_of_line = 1;
1888 file->line_num++;
1889 p++;
1890 goto redo_no_start;
1891 case '\\':
1892 file->buf_ptr = p;
1893 c = handle_eob();
1894 if (c == CH_EOF) {
1895 expect("#endif");
1896 } else if (c == '\\') {
1897 /* XXX: incorrect: should not give an error */
1898 ch = file->buf_ptr[0];
1899 handle_stray();
1901 p = file->buf_ptr;
1902 goto redo_no_start;
1903 /* skip strings */
1904 case '\"':
1905 case '\'':
1906 sep = c;
1907 p++;
1908 for(;;) {
1909 c = *p;
1910 if (c == sep) {
1911 break;
1912 } else if (c == '\\') {
1913 file->buf_ptr = p;
1914 c = handle_eob();
1915 p = file->buf_ptr;
1916 if (c == CH_EOF) {
1917 /* XXX: better error message */
1918 error("unterminated string");
1919 } else if (c == '\\') {
1920 /* ignore next char */
1921 p++;
1922 c = *p;
1923 if (c == '\\') {
1924 file->buf_ptr = p;
1925 c = handle_eob();
1926 p = file->buf_ptr;
1928 if (c == '\n')
1929 file->line_num++;
1930 else if (c != CH_EOF)
1931 p++;
1933 } else if (c == '\n') {
1934 file->line_num++;
1935 p++;
1936 } else {
1937 p++;
1940 p++;
1941 break;
1942 /* skip comments */
1943 case '/':
1944 file->buf_ptr = p;
1945 ch = *p;
1946 minp();
1947 if (ch == '*') {
1948 parse_comment();
1949 } else if (ch == '/') {
1950 parse_line_comment();
1952 p = file->buf_ptr;
1953 break;
1955 case '#':
1956 p++;
1957 if (start_of_line) {
1958 file->buf_ptr = p;
1959 next_nomacro();
1960 p = file->buf_ptr;
1961 if (a == 0 &&
1962 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1963 goto the_end;
1964 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1965 a++;
1966 else if (tok == TOK_ENDIF)
1967 a--;
1969 break;
1970 default:
1971 p++;
1972 break;
1974 start_of_line = 0;
1976 the_end: ;
1977 file->buf_ptr = p;
1980 /* ParseState handling */
1982 /* XXX: currently, no include file info is stored. Thus, we cannot display
1983 accurate messages if the function or data definition spans multiple
1984 files */
1986 /* save current parse state in 's' */
1987 void save_parse_state(ParseState *s)
1989 s->line_num = file->line_num;
1990 s->macro_ptr = macro_ptr;
1991 s->tok = tok;
1992 s->tokc = tokc;
1995 /* restore parse state from 's' */
1996 void restore_parse_state(ParseState *s)
1998 file->line_num = s->line_num;
1999 macro_ptr = s->macro_ptr;
2000 tok = s->tok;
2001 tokc = s->tokc;
2004 /* return the number of additionnal 'ints' necessary to store the
2005 token */
2006 static inline int tok_ext_size(int t)
2008 switch(t) {
2009 /* 4 bytes */
2010 case TOK_CINT:
2011 case TOK_CUINT:
2012 case TOK_CCHAR:
2013 case TOK_LCHAR:
2014 case TOK_STR:
2015 case TOK_LSTR:
2016 case TOK_CFLOAT:
2017 case TOK_LINENUM:
2018 case TOK_PPNUM:
2019 return 1;
2020 case TOK_CDOUBLE:
2021 case TOK_CLLONG:
2022 case TOK_CULLONG:
2023 return 2;
2024 case TOK_CLDOUBLE:
2025 return LDOUBLE_SIZE / 4;
2026 default:
2027 return 0;
2031 /* token string handling */
2033 static inline void tok_str_new(TokenString *s)
2035 s->str = NULL;
2036 s->len = 0;
2037 s->allocated_len = 0;
2038 s->last_line_num = -1;
2041 static void tok_str_free(int *str)
2043 const int *p;
2044 CString *cstr;
2045 int t;
2047 p = str;
2048 for(;;) {
2049 t = *p;
2050 /* NOTE: we test zero separately so that GCC can generate a
2051 table for the following switch */
2052 if (t == 0)
2053 break;
2054 switch(t) {
2055 case TOK_CINT:
2056 case TOK_CUINT:
2057 case TOK_CCHAR:
2058 case TOK_LCHAR:
2059 case TOK_CFLOAT:
2060 case TOK_LINENUM:
2061 p += 2;
2062 break;
2063 case TOK_PPNUM:
2064 case TOK_STR:
2065 case TOK_LSTR:
2066 /* XXX: use a macro to be portable on 64 bit ? */
2067 cstr = (CString *)p[1];
2068 cstr_free(cstr);
2069 tcc_free(cstr);
2070 p += 2;
2071 break;
2072 case TOK_CDOUBLE:
2073 case TOK_CLLONG:
2074 case TOK_CULLONG:
2075 p += 3;
2076 break;
2077 case TOK_CLDOUBLE:
2078 p += 1 + (LDOUBLE_SIZE / 4);
2079 break;
2080 default:
2081 p++;
2082 break;
2085 tcc_free(str);
2088 static int *tok_str_realloc(TokenString *s)
2090 int *str, len;
2092 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2093 str = tcc_realloc(s->str, len * sizeof(int));
2094 if (!str)
2095 error("memory full");
2096 s->allocated_len = len;
2097 s->str = str;
2098 return str;
2101 static void tok_str_add(TokenString *s, int t)
2103 int len, *str;
2105 len = s->len;
2106 str = s->str;
2107 if (len >= s->allocated_len)
2108 str = tok_str_realloc(s);
2109 str[len++] = t;
2110 s->len = len;
2113 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2115 int len, *str;
2117 len = s->len;
2118 str = s->str;
2120 /* allocate space for worst case */
2121 if (len + TOK_MAX_SIZE > s->allocated_len)
2122 str = tok_str_realloc(s);
2123 str[len++] = t;
2124 switch(t) {
2125 case TOK_CINT:
2126 case TOK_CUINT:
2127 case TOK_CCHAR:
2128 case TOK_LCHAR:
2129 case TOK_CFLOAT:
2130 case TOK_LINENUM:
2131 str[len++] = cv->tab[0];
2132 break;
2133 case TOK_PPNUM:
2134 case TOK_STR:
2135 case TOK_LSTR:
2136 str[len++] = (int)cstr_dup(cv->cstr);
2137 break;
2138 case TOK_CDOUBLE:
2139 case TOK_CLLONG:
2140 case TOK_CULLONG:
2141 str[len++] = cv->tab[0];
2142 str[len++] = cv->tab[1];
2143 break;
2144 case TOK_CLDOUBLE:
2145 #if LDOUBLE_SIZE == 12
2146 str[len++] = cv->tab[0];
2147 str[len++] = cv->tab[1];
2148 str[len++] = cv->tab[2];
2149 #else
2150 #error add long double size support
2151 #endif
2152 break;
2153 default:
2154 break;
2156 s->len = len;
2159 /* add the current parse token in token string 's' */
2160 static void tok_str_add_tok(TokenString *s)
2162 CValue cval;
2164 /* save line number info */
2165 if (file->line_num != s->last_line_num) {
2166 s->last_line_num = file->line_num;
2167 cval.i = s->last_line_num;
2168 tok_str_add2(s, TOK_LINENUM, &cval);
2170 tok_str_add2(s, tok, &tokc);
2173 #if LDOUBLE_SIZE == 12
2174 #define LDOUBLE_GET(p, cv) \
2175 cv.tab[0] = p[0]; \
2176 cv.tab[1] = p[1]; \
2177 cv.tab[2] = p[2];
2178 #else
2179 #error add long double size support
2180 #endif
2183 /* get a token from an integer array and increment pointer
2184 accordingly. we code it as a macro to avoid pointer aliasing. */
2185 #define TOK_GET(t, p, cv) \
2187 t = *p++; \
2188 switch(t) { \
2189 case TOK_CINT: \
2190 case TOK_CUINT: \
2191 case TOK_CCHAR: \
2192 case TOK_LCHAR: \
2193 case TOK_CFLOAT: \
2194 case TOK_LINENUM: \
2195 case TOK_STR: \
2196 case TOK_LSTR: \
2197 case TOK_PPNUM: \
2198 cv.tab[0] = *p++; \
2199 break; \
2200 case TOK_CDOUBLE: \
2201 case TOK_CLLONG: \
2202 case TOK_CULLONG: \
2203 cv.tab[0] = p[0]; \
2204 cv.tab[1] = p[1]; \
2205 p += 2; \
2206 break; \
2207 case TOK_CLDOUBLE: \
2208 LDOUBLE_GET(p, cv); \
2209 p += LDOUBLE_SIZE / 4; \
2210 break; \
2211 default: \
2212 break; \
2216 /* defines handling */
2217 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2219 Sym *s;
2221 s = sym_push2(&define_stack, v, macro_type, (int)str);
2222 s->next = first_arg;
2223 table_ident[v - TOK_IDENT]->sym_define = s;
2226 /* undefined a define symbol. Its name is just set to zero */
2227 static void define_undef(Sym *s)
2229 int v;
2230 v = s->v;
2231 if (v >= TOK_IDENT && v < tok_ident)
2232 table_ident[v - TOK_IDENT]->sym_define = NULL;
2233 s->v = 0;
2236 static inline Sym *define_find(int v)
2238 v -= TOK_IDENT;
2239 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2240 return NULL;
2241 return table_ident[v]->sym_define;
2244 /* free define stack until top reaches 'b' */
2245 static void free_defines(Sym *b)
2247 Sym *top, *top1;
2248 int v;
2250 top = define_stack;
2251 while (top != b) {
2252 top1 = top->prev;
2253 /* do not free args or predefined defines */
2254 if (top->c)
2255 tok_str_free((int *)top->c);
2256 v = top->v;
2257 if (v >= TOK_IDENT && v < tok_ident)
2258 table_ident[v - TOK_IDENT]->sym_define = NULL;
2259 tcc_free(top);
2260 top = top1;
2262 define_stack = b;
2265 /* label lookup */
2266 static Sym *label_find(int v)
2268 v -= TOK_IDENT;
2269 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2270 return NULL;
2271 return table_ident[v]->sym_label;
2274 static Sym *label_push(Sym **ptop, int v, int flags)
2276 Sym *s, **ps;
2277 s = sym_push2(ptop, v, 0, 0);
2278 s->r = flags;
2279 ps = &table_ident[v - TOK_IDENT]->sym_label;
2280 if (ptop == &global_label_stack) {
2281 /* modify the top most local identifier, so that
2282 sym_identifier will point to 's' when popped */
2283 while (*ps != NULL)
2284 ps = &(*ps)->prev_tok;
2286 s->prev_tok = *ps;
2287 *ps = s;
2288 return s;
2291 /* pop labels until element last is reached. Look if any labels are
2292 undefined. Define symbols if '&&label' was used. */
2293 static void label_pop(Sym **ptop, Sym *slast)
2295 Sym *s, *s1;
2296 for(s = *ptop; s != slast; s = s1) {
2297 s1 = s->prev;
2298 if (s->r == LABEL_DECLARED) {
2299 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2300 } else if (s->r == LABEL_FORWARD) {
2301 error("label '%s' used but not defined",
2302 get_tok_str(s->v, NULL));
2303 } else {
2304 if (s->c) {
2305 /* define corresponding symbol. A size of
2306 1 is put. */
2307 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2310 /* remove label */
2311 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2312 tcc_free(s);
2314 *ptop = slast;
2317 /* eval an expression for #if/#elif */
2318 static int expr_preprocess(void)
2320 int c, t;
2321 TokenString str;
2323 tok_str_new(&str);
2324 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2325 next(); /* do macro subst */
2326 if (tok == TOK_DEFINED) {
2327 next_nomacro();
2328 t = tok;
2329 if (t == '(')
2330 next_nomacro();
2331 c = define_find(tok) != 0;
2332 if (t == '(')
2333 next_nomacro();
2334 tok = TOK_CINT;
2335 tokc.i = c;
2336 } else if (tok >= TOK_IDENT) {
2337 /* if undefined macro */
2338 tok = TOK_CINT;
2339 tokc.i = 0;
2341 tok_str_add_tok(&str);
2343 tok_str_add(&str, -1); /* simulate end of file */
2344 tok_str_add(&str, 0);
2345 /* now evaluate C constant expression */
2346 macro_ptr = str.str;
2347 next();
2348 c = expr_const();
2349 macro_ptr = NULL;
2350 tok_str_free(str.str);
2351 return c != 0;
2354 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2355 static void tok_print(int *str)
2357 int t;
2358 CValue cval;
2360 while (1) {
2361 TOK_GET(t, str, cval);
2362 if (!t)
2363 break;
2364 printf(" %s", get_tok_str(t, &cval));
2366 printf("\n");
2368 #endif
2370 /* parse after #define */
2371 static void parse_define(void)
2373 Sym *s, *first, **ps;
2374 int v, t, varg, is_vaargs, c;
2375 TokenString str;
2377 v = tok;
2378 if (v < TOK_IDENT)
2379 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2380 /* XXX: should check if same macro (ANSI) */
2381 first = NULL;
2382 t = MACRO_OBJ;
2383 /* '(' must be just after macro definition for MACRO_FUNC */
2384 c = file->buf_ptr[0];
2385 if (c == '\\')
2386 c = handle_stray1(file->buf_ptr);
2387 if (c == '(') {
2388 next_nomacro();
2389 next_nomacro();
2390 ps = &first;
2391 while (tok != ')') {
2392 varg = tok;
2393 next_nomacro();
2394 is_vaargs = 0;
2395 if (varg == TOK_DOTS) {
2396 varg = TOK___VA_ARGS__;
2397 is_vaargs = 1;
2398 } else if (tok == TOK_DOTS && gnu_ext) {
2399 is_vaargs = 1;
2400 next_nomacro();
2402 if (varg < TOK_IDENT)
2403 error("badly punctuated parameter list");
2404 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2405 *ps = s;
2406 ps = &s->next;
2407 if (tok != ',')
2408 break;
2409 next_nomacro();
2411 t = MACRO_FUNC;
2413 tok_str_new(&str);
2414 next_nomacro();
2415 /* EOF testing necessary for '-D' handling */
2416 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2417 tok_str_add2(&str, tok, &tokc);
2418 next_nomacro();
2420 tok_str_add(&str, 0);
2421 #ifdef PP_DEBUG
2422 printf("define %s %d: ", get_tok_str(v, NULL), t);
2423 tok_print(str.str);
2424 #endif
2425 define_push(v, t, str.str, first);
2428 /* XXX: use a token or a hash table to accelerate matching ? */
2429 static CachedInclude *search_cached_include(TCCState *s1,
2430 int type, const char *filename)
2432 CachedInclude *e;
2433 int i;
2435 for(i = 0;i < s1->nb_cached_includes; i++) {
2436 e = s1->cached_includes[i];
2437 if (e->type == type && !strcmp(e->filename, filename))
2438 return e;
2440 return NULL;
2443 static inline void add_cached_include(TCCState *s1, int type,
2444 const char *filename, int ifndef_macro)
2446 CachedInclude *e;
2448 if (search_cached_include(s1, type, filename))
2449 return;
2450 #ifdef INC_DEBUG
2451 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2452 #endif
2453 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2454 if (!e)
2455 return;
2456 e->type = type;
2457 strcpy(e->filename, filename);
2458 e->ifndef_macro = ifndef_macro;
2459 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2462 /* is_bof is true if first non space token at beginning of file */
2463 static void preprocess(int is_bof)
2465 TCCState *s1 = tcc_state;
2466 int size, i, c, n, saved_parse_flags;
2467 char buf[1024], *q, *p;
2468 char buf1[1024];
2469 BufferedFile *f;
2470 Sym *s;
2471 CachedInclude *e;
2473 saved_parse_flags = parse_flags;
2474 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2475 PARSE_FLAG_LINEFEED;
2476 next_nomacro();
2477 redo:
2478 switch(tok) {
2479 case TOK_DEFINE:
2480 next_nomacro();
2481 parse_define();
2482 break;
2483 case TOK_UNDEF:
2484 next_nomacro();
2485 s = define_find(tok);
2486 /* undefine symbol by putting an invalid name */
2487 if (s)
2488 define_undef(s);
2489 break;
2490 case TOK_INCLUDE:
2491 ch = file->buf_ptr[0];
2492 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2493 skip_spaces();
2494 if (ch == '<') {
2495 c = '>';
2496 goto read_name;
2497 } else if (ch == '\"') {
2498 c = ch;
2499 read_name:
2500 /* XXX: better stray handling */
2501 minp();
2502 q = buf;
2503 while (ch != c && ch != '\n' && ch != CH_EOF) {
2504 if ((q - buf) < sizeof(buf) - 1)
2505 *q++ = ch;
2506 minp();
2508 *q = '\0';
2509 minp();
2510 #if 0
2511 /* eat all spaces and comments after include */
2512 /* XXX: slightly incorrect */
2513 while (ch1 != '\n' && ch1 != CH_EOF)
2514 inp();
2515 #endif
2516 } else {
2517 /* computed #include : either we have only strings or
2518 we have anything enclosed in '<>' */
2519 next();
2520 buf[0] = '\0';
2521 if (tok == TOK_STR) {
2522 while (tok != TOK_LINEFEED) {
2523 if (tok != TOK_STR) {
2524 include_syntax:
2525 error("'#include' expects \"FILENAME\" or <FILENAME>");
2527 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2528 next();
2530 c = '\"';
2531 } else {
2532 int len;
2533 while (tok != TOK_LINEFEED) {
2534 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2535 next();
2537 len = strlen(buf);
2538 /* check syntax and remove '<>' */
2539 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2540 goto include_syntax;
2541 memmove(buf, buf + 1, len - 2);
2542 buf[len - 2] = '\0';
2543 c = '>';
2547 e = search_cached_include(s1, c, buf);
2548 if (e && define_find(e->ifndef_macro)) {
2549 /* no need to parse the include because the 'ifndef macro'
2550 is defined */
2551 #ifdef INC_DEBUG
2552 printf("%s: skipping %s\n", file->filename, buf);
2553 #endif
2554 } else {
2555 if (c == '\"') {
2556 /* first search in current dir if "header.h" */
2557 size = 0;
2558 p = strrchr(file->filename, '/');
2559 if (p)
2560 size = p + 1 - file->filename;
2561 if (size > sizeof(buf1) - 1)
2562 size = sizeof(buf1) - 1;
2563 memcpy(buf1, file->filename, size);
2564 buf1[size] = '\0';
2565 pstrcat(buf1, sizeof(buf1), buf);
2566 f = tcc_open(s1, buf1);
2567 if (f)
2568 goto found;
2570 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2571 error("#include recursion too deep");
2572 /* now search in all the include paths */
2573 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2574 for(i = 0; i < n; i++) {
2575 const char *path;
2576 if (i < s1->nb_include_paths)
2577 path = s1->include_paths[i];
2578 else
2579 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2580 pstrcpy(buf1, sizeof(buf1), path);
2581 pstrcat(buf1, sizeof(buf1), "/");
2582 pstrcat(buf1, sizeof(buf1), buf);
2583 f = tcc_open(s1, buf1);
2584 if (f)
2585 goto found;
2587 error("include file '%s' not found", buf);
2588 f = NULL;
2589 found:
2590 #ifdef INC_DEBUG
2591 printf("%s: including %s\n", file->filename, buf1);
2592 #endif
2593 f->inc_type = c;
2594 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2595 /* push current file in stack */
2596 /* XXX: fix current line init */
2597 *s1->include_stack_ptr++ = file;
2598 file = f;
2599 /* add include file debug info */
2600 if (do_debug) {
2601 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2603 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2604 ch = file->buf_ptr[0];
2605 goto the_end;
2607 break;
2608 case TOK_IFNDEF:
2609 c = 1;
2610 goto do_ifdef;
2611 case TOK_IF:
2612 c = expr_preprocess();
2613 goto do_if;
2614 case TOK_IFDEF:
2615 c = 0;
2616 do_ifdef:
2617 next_nomacro();
2618 if (tok < TOK_IDENT)
2619 error("invalid argument for '#if%sdef'", c ? "n" : "");
2620 if (is_bof) {
2621 if (c) {
2622 #ifdef INC_DEBUG
2623 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2624 #endif
2625 file->ifndef_macro = tok;
2628 c = (define_find(tok) != 0) ^ c;
2629 do_if:
2630 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2631 error("memory full");
2632 *s1->ifdef_stack_ptr++ = c;
2633 goto test_skip;
2634 case TOK_ELSE:
2635 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2636 error("#else without matching #if");
2637 if (s1->ifdef_stack_ptr[-1] & 2)
2638 error("#else after #else");
2639 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2640 goto test_skip;
2641 case TOK_ELIF:
2642 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2643 error("#elif without matching #if");
2644 c = s1->ifdef_stack_ptr[-1];
2645 if (c > 1)
2646 error("#elif after #else");
2647 /* last #if/#elif expression was true: we skip */
2648 if (c == 1)
2649 goto skip;
2650 c = expr_preprocess();
2651 s1->ifdef_stack_ptr[-1] = c;
2652 test_skip:
2653 if (!(c & 1)) {
2654 skip:
2655 preprocess_skip();
2656 is_bof = 0;
2657 goto redo;
2659 break;
2660 case TOK_ENDIF:
2661 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2662 error("#endif without matching #if");
2663 s1->ifdef_stack_ptr--;
2664 /* '#ifndef macro' was at the start of file. Now we check if
2665 an '#endif' is exactly at the end of file */
2666 if (file->ifndef_macro &&
2667 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2668 file->ifndef_macro_saved = file->ifndef_macro;
2669 /* need to set to zero to avoid false matches if another
2670 #ifndef at middle of file */
2671 file->ifndef_macro = 0;
2672 while (tok != TOK_LINEFEED)
2673 next_nomacro();
2674 tok_flags |= TOK_FLAG_ENDIF;
2675 goto the_end;
2677 break;
2678 case TOK_LINE:
2679 next();
2680 if (tok != TOK_CINT)
2681 error("#line");
2682 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2683 next();
2684 if (tok != TOK_LINEFEED) {
2685 if (tok != TOK_STR)
2686 error("#line");
2687 pstrcpy(file->filename, sizeof(file->filename),
2688 (char *)tokc.cstr->data);
2690 break;
2691 case TOK_ERROR:
2692 case TOK_WARNING:
2693 c = tok;
2694 ch = file->buf_ptr[0];
2695 skip_spaces();
2696 q = buf;
2697 while (ch != '\n' && ch != CH_EOF) {
2698 if ((q - buf) < sizeof(buf) - 1)
2699 *q++ = ch;
2700 minp();
2702 *q = '\0';
2703 if (c == TOK_ERROR)
2704 error("#error %s", buf);
2705 else
2706 warning("#warning %s", buf);
2707 break;
2708 case TOK_PRAGMA:
2709 /* ignored */
2710 break;
2711 default:
2712 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2713 /* '!' is ignored to allow C scripts. numbers are ignored
2714 to emulate cpp behaviour */
2715 } else {
2716 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2718 break;
2720 /* ignore other preprocess commands or #! for C scripts */
2721 while (tok != TOK_LINEFEED)
2722 next_nomacro();
2723 the_end:
2724 parse_flags = saved_parse_flags;
2727 /* read a number in base b */
2728 static int getn(int b)
2730 int n, t;
2731 n = 0;
2732 while (1) {
2733 if (ch >= 'a' && ch <= 'f')
2734 t = ch - 'a' + 10;
2735 else if (ch >= 'A' && ch <= 'F')
2736 t = ch - 'A' + 10;
2737 else if (isnum(ch))
2738 t = ch - '0';
2739 else
2740 break;
2741 if (t < 0 || t >= b)
2742 break;
2743 n = n * b + t;
2744 inp();
2746 return n;
2749 /* read a character for string or char constant and eval escape codes */
2750 static int getq(void)
2752 int c;
2754 redo:
2755 c = ch;
2756 inp();
2757 if (c == '\\') {
2758 switch(ch) {
2759 case '0': case '1': case '2': case '3':
2760 case '4': case '5': case '6': case '7':
2761 /* at most three octal digits */
2762 c = ch - '0';
2763 inp();
2764 if (isoct(ch)) {
2765 c = c * 8 + ch - '0';
2766 inp();
2767 if (isoct(ch)) {
2768 c = c * 8 + ch - '0';
2769 inp();
2772 return c;
2773 case 'x':
2774 inp();
2775 return getn(16);
2776 case 'a':
2777 c = '\a';
2778 break;
2779 case 'b':
2780 c = '\b';
2781 break;
2782 case 'f':
2783 c = '\f';
2784 break;
2785 case 'n':
2786 c = '\n';
2787 break;
2788 case 'r':
2789 c = '\r';
2790 break;
2791 case 't':
2792 c = '\t';
2793 break;
2794 case 'v':
2795 c = '\v';
2796 break;
2797 case 'e':
2798 if (!gnu_ext)
2799 goto invalid_escape;
2800 c = 27;
2801 break;
2802 case '\'':
2803 case '\"':
2804 case '\\':
2805 case '?':
2806 c = ch;
2807 break;
2808 case '\n':
2809 inp();
2810 goto redo;
2811 case '\r':
2812 inp();
2813 if (ch != '\n')
2814 goto invalid_escape;
2815 inp();
2816 goto redo;
2817 default:
2818 invalid_escape:
2819 error("invalid escaped char");
2821 inp();
2822 } else if (c == '\r' && ch == '\n') {
2823 inp();
2824 c = '\n';
2826 return c;
2829 /* we use 64 bit numbers */
2830 #define BN_SIZE 2
2832 /* bn = (bn << shift) | or_val */
2833 void bn_lshift(unsigned int *bn, int shift, int or_val)
2835 int i;
2836 unsigned int v;
2837 for(i=0;i<BN_SIZE;i++) {
2838 v = bn[i];
2839 bn[i] = (v << shift) | or_val;
2840 or_val = v >> (32 - shift);
2844 void bn_zero(unsigned int *bn)
2846 int i;
2847 for(i=0;i<BN_SIZE;i++) {
2848 bn[i] = 0;
2852 /* parse number in null terminated string 'p' and return it in the
2853 current token */
2854 void parse_number(const char *p)
2856 int b, t, shift, frac_bits, s, exp_val, ch;
2857 char *q;
2858 unsigned int bn[BN_SIZE];
2859 double d;
2861 /* number */
2862 q = token_buf;
2863 ch = *p++;
2864 t = ch;
2865 ch = *p++;
2866 *q++ = t;
2867 b = 10;
2868 if (t == '.') {
2869 goto float_frac_parse;
2870 } else if (t == '0') {
2871 if (ch == 'x' || ch == 'X') {
2872 q--;
2873 ch = *p++;
2874 b = 16;
2875 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2876 q--;
2877 ch = *p++;
2878 b = 2;
2881 /* parse all digits. cannot check octal numbers at this stage
2882 because of floating point constants */
2883 while (1) {
2884 if (ch >= 'a' && ch <= 'f')
2885 t = ch - 'a' + 10;
2886 else if (ch >= 'A' && ch <= 'F')
2887 t = ch - 'A' + 10;
2888 else if (isnum(ch))
2889 t = ch - '0';
2890 else
2891 break;
2892 if (t >= b)
2893 break;
2894 if (q >= token_buf + STRING_MAX_SIZE) {
2895 num_too_long:
2896 error("number too long");
2898 *q++ = ch;
2899 ch = *p++;
2901 if (ch == '.' ||
2902 ((ch == 'e' || ch == 'E') && b == 10) ||
2903 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2904 if (b != 10) {
2905 /* NOTE: strtox should support that for hexa numbers, but
2906 non ISOC99 libcs do not support it, so we prefer to do
2907 it by hand */
2908 /* hexadecimal or binary floats */
2909 /* XXX: handle overflows */
2910 *q = '\0';
2911 if (b == 16)
2912 shift = 4;
2913 else
2914 shift = 2;
2915 bn_zero(bn);
2916 q = token_buf;
2917 while (1) {
2918 t = *q++;
2919 if (t == '\0') {
2920 break;
2921 } else if (t >= 'a') {
2922 t = t - 'a' + 10;
2923 } else if (t >= 'A') {
2924 t = t - 'A' + 10;
2925 } else {
2926 t = t - '0';
2928 bn_lshift(bn, shift, t);
2930 frac_bits = 0;
2931 if (ch == '.') {
2932 ch = *p++;
2933 while (1) {
2934 t = ch;
2935 if (t >= 'a' && t <= 'f') {
2936 t = t - 'a' + 10;
2937 } else if (t >= 'A' && t <= 'F') {
2938 t = t - 'A' + 10;
2939 } else if (t >= '0' && t <= '9') {
2940 t = t - '0';
2941 } else {
2942 break;
2944 if (t >= b)
2945 error("invalid digit");
2946 bn_lshift(bn, shift, t);
2947 frac_bits += shift;
2948 ch = *p++;
2951 if (ch != 'p' && ch != 'P')
2952 expect("exponent");
2953 ch = *p++;
2954 s = 1;
2955 exp_val = 0;
2956 if (ch == '+') {
2957 ch = *p++;
2958 } else if (ch == '-') {
2959 s = -1;
2960 ch = *p++;
2962 if (ch < '0' || ch > '9')
2963 expect("exponent digits");
2964 while (ch >= '0' && ch <= '9') {
2965 exp_val = exp_val * 10 + ch - '0';
2966 ch = *p++;
2968 exp_val = exp_val * s;
2970 /* now we can generate the number */
2971 /* XXX: should patch directly float number */
2972 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2973 d = ldexp(d, exp_val - frac_bits);
2974 t = toup(ch);
2975 if (t == 'F') {
2976 ch = *p++;
2977 tok = TOK_CFLOAT;
2978 /* float : should handle overflow */
2979 tokc.f = (float)d;
2980 } else if (t == 'L') {
2981 ch = *p++;
2982 tok = TOK_CLDOUBLE;
2983 /* XXX: not large enough */
2984 tokc.ld = (long double)d;
2985 } else {
2986 tok = TOK_CDOUBLE;
2987 tokc.d = d;
2989 } else {
2990 /* decimal floats */
2991 if (ch == '.') {
2992 if (q >= token_buf + STRING_MAX_SIZE)
2993 goto num_too_long;
2994 *q++ = ch;
2995 ch = *p++;
2996 float_frac_parse:
2997 while (ch >= '0' && ch <= '9') {
2998 if (q >= token_buf + STRING_MAX_SIZE)
2999 goto num_too_long;
3000 *q++ = ch;
3001 ch = *p++;
3004 if (ch == 'e' || ch == 'E') {
3005 if (q >= token_buf + STRING_MAX_SIZE)
3006 goto num_too_long;
3007 *q++ = ch;
3008 ch = *p++;
3009 if (ch == '-' || ch == '+') {
3010 if (q >= token_buf + STRING_MAX_SIZE)
3011 goto num_too_long;
3012 *q++ = ch;
3013 ch = *p++;
3015 if (ch < '0' || ch > '9')
3016 expect("exponent digits");
3017 while (ch >= '0' && ch <= '9') {
3018 if (q >= token_buf + STRING_MAX_SIZE)
3019 goto num_too_long;
3020 *q++ = ch;
3021 ch = *p++;
3024 *q = '\0';
3025 t = toup(ch);
3026 errno = 0;
3027 if (t == 'F') {
3028 ch = *p++;
3029 tok = TOK_CFLOAT;
3030 tokc.f = strtof(token_buf, NULL);
3031 } else if (t == 'L') {
3032 ch = *p++;
3033 tok = TOK_CLDOUBLE;
3034 tokc.ld = strtold(token_buf, NULL);
3035 } else {
3036 tok = TOK_CDOUBLE;
3037 tokc.d = strtod(token_buf, NULL);
3040 } else {
3041 unsigned long long n, n1;
3042 int lcount, ucount;
3044 /* integer number */
3045 *q = '\0';
3046 q = token_buf;
3047 if (b == 10 && *q == '0') {
3048 b = 8;
3049 q++;
3051 n = 0;
3052 while(1) {
3053 t = *q++;
3054 /* no need for checks except for base 10 / 8 errors */
3055 if (t == '\0') {
3056 break;
3057 } else if (t >= 'a') {
3058 t = t - 'a' + 10;
3059 } else if (t >= 'A') {
3060 t = t - 'A' + 10;
3061 } else {
3062 t = t - '0';
3063 if (t >= b)
3064 error("invalid digit");
3066 n1 = n;
3067 n = n * b + t;
3068 /* detect overflow */
3069 /* XXX: this test is not reliable */
3070 if (n < n1)
3071 error("integer constant overflow");
3074 /* XXX: not exactly ANSI compliant */
3075 if ((n & 0xffffffff00000000LL) != 0) {
3076 if ((n >> 63) != 0)
3077 tok = TOK_CULLONG;
3078 else
3079 tok = TOK_CLLONG;
3080 } else if (n > 0x7fffffff) {
3081 tok = TOK_CUINT;
3082 } else {
3083 tok = TOK_CINT;
3085 lcount = 0;
3086 ucount = 0;
3087 for(;;) {
3088 t = toup(ch);
3089 if (t == 'L') {
3090 if (lcount >= 2)
3091 error("three 'l's in integer constant");
3092 lcount++;
3093 if (lcount == 2) {
3094 if (tok == TOK_CINT)
3095 tok = TOK_CLLONG;
3096 else if (tok == TOK_CUINT)
3097 tok = TOK_CULLONG;
3099 ch = *p++;
3100 } else if (t == 'U') {
3101 if (ucount >= 1)
3102 error("two 'u's in integer constant");
3103 ucount++;
3104 if (tok == TOK_CINT)
3105 tok = TOK_CUINT;
3106 else if (tok == TOK_CLLONG)
3107 tok = TOK_CULLONG;
3108 ch = *p++;
3109 } else {
3110 break;
3113 if (tok == TOK_CINT || tok == TOK_CUINT)
3114 tokc.ui = n;
3115 else
3116 tokc.ull = n;
3121 #define PARSE2(c1, tok1, c2, tok2) \
3122 case c1: \
3123 PEEKC(c, p); \
3124 if (c == c2) { \
3125 p++; \
3126 tok = tok2; \
3127 } else { \
3128 tok = tok1; \
3130 break;
3132 /* return next token without macro substitution */
3133 static inline void next_nomacro1(void)
3135 int b, t, c;
3136 TokenSym *ts;
3137 uint8_t *p, *p1;
3138 unsigned int h;
3140 p = file->buf_ptr;
3141 redo_no_start:
3142 c = *p;
3143 switch(c) {
3144 case ' ':
3145 case '\t':
3146 case '\f':
3147 case '\v':
3148 case '\r':
3149 p++;
3150 goto redo_no_start;
3152 case '\\':
3153 /* first look if it is in fact an end of buffer */
3154 if (p >= file->buf_end) {
3155 file->buf_ptr = p;
3156 handle_eob();
3157 p = file->buf_ptr;
3158 if (p >= file->buf_end)
3159 goto parse_eof;
3160 else
3161 goto redo_no_start;
3162 } else {
3163 file->buf_ptr = p;
3164 ch = *p;
3165 handle_stray();
3166 p = file->buf_ptr;
3167 goto redo_no_start;
3169 parse_eof:
3171 TCCState *s1 = tcc_state;
3172 if (parse_flags & PARSE_FLAG_LINEFEED) {
3173 tok = TOK_LINEFEED;
3174 } else if (s1->include_stack_ptr == s1->include_stack ||
3175 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3176 /* no include left : end of file. */
3177 tok = TOK_EOF;
3178 } else {
3179 /* pop include file */
3181 /* test if previous '#endif' was after a #ifdef at
3182 start of file */
3183 if (tok_flags & TOK_FLAG_ENDIF) {
3184 #ifdef INC_DEBUG
3185 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3186 #endif
3187 add_cached_include(s1, file->inc_type, file->inc_filename,
3188 file->ifndef_macro_saved);
3191 /* add end of include file debug info */
3192 if (do_debug) {
3193 put_stabd(N_EINCL, 0, 0);
3195 /* pop include stack */
3196 tcc_close(file);
3197 s1->include_stack_ptr--;
3198 file = *s1->include_stack_ptr;
3199 p = file->buf_ptr;
3200 goto redo_no_start;
3203 break;
3205 case '\n':
3206 if (parse_flags & PARSE_FLAG_LINEFEED) {
3207 tok = TOK_LINEFEED;
3208 } else {
3209 file->line_num++;
3210 tok_flags |= TOK_FLAG_BOL;
3211 p++;
3212 goto redo_no_start;
3214 break;
3216 case '#':
3217 /* XXX: simplify */
3218 PEEKC(c, p);
3219 if ((tok_flags & TOK_FLAG_BOL) &&
3220 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3221 file->buf_ptr = p;
3222 preprocess(tok_flags & TOK_FLAG_BOF);
3223 p = file->buf_ptr;
3224 goto redo_no_start;
3225 } else {
3226 if (c == '#') {
3227 p++;
3228 tok = TOK_TWOSHARPS;
3229 } else {
3230 tok = '#';
3233 break;
3235 case 'a': case 'b': case 'c': case 'd':
3236 case 'e': case 'f': case 'g': case 'h':
3237 case 'i': case 'j': case 'k': case 'l':
3238 case 'm': case 'n': case 'o': case 'p':
3239 case 'q': case 'r': case 's': case 't':
3240 case 'u': case 'v': case 'w': case 'x':
3241 case 'y': case 'z':
3242 case 'A': case 'B': case 'C': case 'D':
3243 case 'E': case 'F': case 'G': case 'H':
3244 case 'I': case 'J': case 'K':
3245 case 'M': case 'N': case 'O': case 'P':
3246 case 'Q': case 'R': case 'S': case 'T':
3247 case 'U': case 'V': case 'W': case 'X':
3248 case 'Y': case 'Z':
3249 case '_':
3250 parse_ident_fast:
3251 p1 = p;
3252 h = TOK_HASH_INIT;
3253 h = TOK_HASH_FUNC(h, c);
3254 p++;
3255 for(;;) {
3256 c = *p;
3257 if (!isidnum_table[c])
3258 break;
3259 h = TOK_HASH_FUNC(h, c);
3260 p++;
3262 if (c != '\\') {
3263 TokenSym **pts;
3264 int len;
3266 /* fast case : no stray found, so we have the full token
3267 and we have already hashed it */
3268 len = p - p1;
3269 h &= (TOK_HASH_SIZE - 1);
3270 pts = &hash_ident[h];
3271 for(;;) {
3272 ts = *pts;
3273 if (!ts)
3274 break;
3275 if (ts->len == len && !memcmp(ts->str, p1, len))
3276 goto token_found;
3277 pts = &(ts->hash_next);
3279 ts = tok_alloc_new(pts, p1, len);
3280 token_found: ;
3281 } else {
3282 /* slower case */
3283 cstr_reset(&tokcstr);
3285 while (p1 < p) {
3286 cstr_ccat(&tokcstr, *p1);
3287 p1++;
3289 p--;
3290 PEEKC(c, p);
3291 parse_ident_slow:
3292 while (isidnum_table[c]) {
3293 cstr_ccat(&tokcstr, c);
3294 PEEKC(c, p);
3296 ts = tok_alloc(tokcstr.data, tokcstr.size);
3298 tok = ts->tok;
3299 break;
3300 case 'L':
3301 t = p[1];
3302 if (t != '\\' && t != '\'' && t != '\"') {
3303 /* fast case */
3304 goto parse_ident_fast;
3305 } else {
3306 PEEKC(c, p);
3307 if (c == '\'') {
3308 tok = TOK_LCHAR;
3309 goto char_const;
3310 } else if (c == '\"') {
3311 tok = TOK_LSTR;
3312 goto str_const;
3313 } else {
3314 cstr_reset(&tokcstr);
3315 cstr_ccat(&tokcstr, 'L');
3316 goto parse_ident_slow;
3319 break;
3320 case '0': case '1': case '2': case '3':
3321 case '4': case '5': case '6': case '7':
3322 case '8': case '9':
3324 cstr_reset(&tokcstr);
3325 /* after the first digit, accept digits, alpha, '.' or sign if
3326 prefixed by 'eEpP' */
3327 parse_num:
3328 for(;;) {
3329 t = c;
3330 cstr_ccat(&tokcstr, c);
3331 PEEKC(c, p);
3332 if (!(isnum(c) || isid(c) || c == '.' ||
3333 ((c == '+' || c == '-') &&
3334 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3335 break;
3337 /* We add a trailing '\0' to ease parsing */
3338 cstr_ccat(&tokcstr, '\0');
3339 tokc.cstr = &tokcstr;
3340 tok = TOK_PPNUM;
3341 break;
3342 case '.':
3343 /* special dot handling because it can also start a number */
3344 PEEKC(c, p);
3345 if (isnum(c)) {
3346 cstr_reset(&tokcstr);
3347 cstr_ccat(&tokcstr, '.');
3348 goto parse_num;
3349 } else if (c == '.') {
3350 PEEKC(c, p);
3351 if (c != '.')
3352 expect("'.'");
3353 PEEKC(c, p);
3354 tok = TOK_DOTS;
3355 } else {
3356 tok = '.';
3358 break;
3359 case '\'':
3360 tok = TOK_CCHAR;
3361 char_const:
3362 file->buf_ptr = p;
3363 inp();
3364 b = getq();
3365 /* this cast is needed if >= 128 */
3366 if (tok == TOK_CCHAR)
3367 b = (char)b;
3368 tokc.i = b;
3369 if (ch != '\'')
3370 error("unterminated character constant");
3371 p = file->buf_ptr;
3372 p++;
3373 break;
3374 case '\"':
3375 tok = TOK_STR;
3376 str_const:
3377 file->buf_ptr = p;
3378 inp();
3379 cstr_reset(&tokcstr);
3380 while (ch != '\"') {
3381 b = getq();
3382 if (ch == CH_EOF)
3383 error("unterminated string");
3384 if (tok == TOK_STR)
3385 cstr_ccat(&tokcstr, b);
3386 else
3387 cstr_wccat(&tokcstr, b);
3389 if (tok == TOK_STR)
3390 cstr_ccat(&tokcstr, '\0');
3391 else
3392 cstr_wccat(&tokcstr, '\0');
3393 tokc.cstr = &tokcstr;
3394 p = file->buf_ptr;
3395 p++;
3396 break;
3398 case '<':
3399 PEEKC(c, p);
3400 if (c == '=') {
3401 p++;
3402 tok = TOK_LE;
3403 } else if (c == '<') {
3404 PEEKC(c, p);
3405 if (c == '=') {
3406 p++;
3407 tok = TOK_A_SHL;
3408 } else {
3409 tok = TOK_SHL;
3411 } else {
3412 tok = TOK_LT;
3414 break;
3416 case '>':
3417 PEEKC(c, p);
3418 if (c == '=') {
3419 p++;
3420 tok = TOK_GE;
3421 } else if (c == '>') {
3422 PEEKC(c, p);
3423 if (c == '=') {
3424 p++;
3425 tok = TOK_A_SAR;
3426 } else {
3427 tok = TOK_SAR;
3429 } else {
3430 tok = TOK_GT;
3432 break;
3434 case '&':
3435 PEEKC(c, p);
3436 if (c == '&') {
3437 p++;
3438 tok = TOK_LAND;
3439 } else if (c == '=') {
3440 p++;
3441 tok = TOK_A_AND;
3442 } else {
3443 tok = '&';
3445 break;
3447 case '|':
3448 PEEKC(c, p);
3449 if (c == '|') {
3450 p++;
3451 tok = TOK_LOR;
3452 } else if (c == '=') {
3453 p++;
3454 tok = TOK_A_OR;
3455 } else {
3456 tok = '|';
3458 break;
3460 case '+':
3461 PEEKC(c, p);
3462 if (c == '+') {
3463 p++;
3464 tok = TOK_INC;
3465 } else if (c == '=') {
3466 p++;
3467 tok = TOK_A_ADD;
3468 } else {
3469 tok = '+';
3471 break;
3473 case '-':
3474 PEEKC(c, p);
3475 if (c == '-') {
3476 p++;
3477 tok = TOK_DEC;
3478 } else if (c == '=') {
3479 p++;
3480 tok = TOK_A_SUB;
3481 } else if (c == '>') {
3482 p++;
3483 tok = TOK_ARROW;
3484 } else {
3485 tok = '-';
3487 break;
3489 PARSE2('!', '!', '=', TOK_NE)
3490 PARSE2('=', '=', '=', TOK_EQ)
3491 PARSE2('*', '*', '=', TOK_A_MUL)
3492 PARSE2('%', '%', '=', TOK_A_MOD)
3493 PARSE2('^', '^', '=', TOK_A_XOR)
3495 /* comments or operator */
3496 case '/':
3497 PEEKC(c, p);
3498 if (c == '*') {
3499 file->buf_ptr = p;
3500 parse_comment();
3501 p = file->buf_ptr;
3502 goto redo_no_start;
3503 } else if (c == '/') {
3504 file->buf_ptr = p;
3505 parse_line_comment();
3506 p = file->buf_ptr;
3507 goto redo_no_start;
3508 } else if (c == '=') {
3509 p++;
3510 tok = TOK_A_DIV;
3511 } else {
3512 tok = '/';
3514 break;
3516 /* simple tokens */
3517 case '(':
3518 case ')':
3519 case '[':
3520 case ']':
3521 case '{':
3522 case '}':
3523 case ',':
3524 case ';':
3525 case ':':
3526 case '?':
3527 case '~':
3528 case '$': /* only used in assembler */
3529 tok = c;
3530 p++;
3531 break;
3532 default:
3533 error("unrecognized character \\x%02x", c);
3534 break;
3536 file->buf_ptr = p;
3537 tok_flags = 0;
3538 #if defined(PARSE_DEBUG)
3539 printf("token = %s\n", get_tok_str(tok, &tokc));
3540 #endif
3543 /* return next token without macro substitution. Can read input from
3544 macro_ptr buffer */
3545 static void next_nomacro(void)
3547 if (macro_ptr) {
3548 redo:
3549 tok = *macro_ptr;
3550 if (tok) {
3551 TOK_GET(tok, macro_ptr, tokc);
3552 if (tok == TOK_LINENUM) {
3553 file->line_num = tokc.i;
3554 goto redo;
3557 } else {
3558 next_nomacro1();
3562 /* substitute args in macro_str and return allocated string */
3563 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3565 int *st, last_tok, t, notfirst;
3566 Sym *s;
3567 CValue cval;
3568 TokenString str;
3569 CString cstr;
3571 tok_str_new(&str);
3572 last_tok = 0;
3573 while(1) {
3574 TOK_GET(t, macro_str, cval);
3575 if (!t)
3576 break;
3577 if (t == '#') {
3578 /* stringize */
3579 TOK_GET(t, macro_str, cval);
3580 if (!t)
3581 break;
3582 s = sym_find2(args, t);
3583 if (s) {
3584 cstr_new(&cstr);
3585 st = (int *)s->c;
3586 notfirst = 0;
3587 while (*st) {
3588 if (notfirst)
3589 cstr_ccat(&cstr, ' ');
3590 TOK_GET(t, st, cval);
3591 cstr_cat(&cstr, get_tok_str(t, &cval));
3592 notfirst = 1;
3594 cstr_ccat(&cstr, '\0');
3595 #ifdef PP_DEBUG
3596 printf("stringize: %s\n", (char *)cstr.data);
3597 #endif
3598 /* add string */
3599 cval.cstr = &cstr;
3600 tok_str_add2(&str, TOK_STR, &cval);
3601 cstr_free(&cstr);
3602 } else {
3603 tok_str_add2(&str, t, &cval);
3605 } else if (t >= TOK_IDENT) {
3606 s = sym_find2(args, t);
3607 if (s) {
3608 st = (int *)s->c;
3609 /* if '##' is present before or after, no arg substitution */
3610 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3611 /* special case for var arg macros : ## eats the
3612 ',' if empty VA_ARGS variable. */
3613 /* XXX: test of the ',' is not 100%
3614 reliable. should fix it to avoid security
3615 problems */
3616 if (gnu_ext && s->type.t &&
3617 last_tok == TOK_TWOSHARPS &&
3618 str.len >= 2 && str.str[str.len - 2] == ',') {
3619 if (*st == 0) {
3620 /* suppress ',' '##' */
3621 str.len -= 2;
3622 } else {
3623 /* suppress '##' and add variable */
3624 str.len--;
3625 goto add_var;
3627 } else {
3628 int t1;
3629 add_var:
3630 for(;;) {
3631 TOK_GET(t1, st, cval);
3632 if (!t1)
3633 break;
3634 tok_str_add2(&str, t1, &cval);
3637 } else {
3638 macro_subst(&str, nested_list, st);
3640 } else {
3641 tok_str_add(&str, t);
3643 } else {
3644 tok_str_add2(&str, t, &cval);
3646 last_tok = t;
3648 tok_str_add(&str, 0);
3649 return str.str;
3652 /* do macro substitution of current token with macro 's' and add
3653 result to (tok_str,tok_len). 'nested_list' is the list of all
3654 macros we got inside to avoid recursing. Return non zero if no
3655 substitution needs to be done */
3656 static int macro_subst_tok(TokenString *tok_str,
3657 Sym **nested_list, Sym *s)
3659 Sym *args, *sa, *sa1;
3660 int mstr_allocated, parlevel, *mstr, t;
3661 TokenString str;
3662 char *cstrval;
3663 CValue cval;
3664 CString cstr;
3666 /* if symbol is a macro, prepare substitution */
3668 /* special macros */
3669 if (tok == TOK___LINE__) {
3670 cval.i = file->line_num;
3671 tok_str_add2(tok_str, TOK_CINT, &cval);
3672 } else if (tok == TOK___FILE__) {
3673 cstrval = file->filename;
3674 goto add_cstr;
3675 tok_str_add2(tok_str, TOK_STR, &cval);
3676 } else if (tok == TOK___DATE__) {
3677 cstrval = "Jan 1 2002";
3678 goto add_cstr;
3679 } else if (tok == TOK___TIME__) {
3680 cstrval = "00:00:00";
3681 add_cstr:
3682 cstr_new(&cstr);
3683 cstr_cat(&cstr, cstrval);
3684 cstr_ccat(&cstr, '\0');
3685 cval.cstr = &cstr;
3686 tok_str_add2(tok_str, TOK_STR, &cval);
3687 cstr_free(&cstr);
3688 } else {
3689 mstr = (int *)s->c;
3690 mstr_allocated = 0;
3691 if (s->type.t == MACRO_FUNC) {
3692 /* NOTE: we do not use next_nomacro to avoid eating the
3693 next token. XXX: find better solution */
3694 if (macro_ptr) {
3695 t = *macro_ptr;
3696 } else {
3697 /* XXX: incorrect with comments */
3698 ch = file->buf_ptr[0];
3699 while (is_space(ch) || ch == '\n')
3700 cinp();
3701 t = ch;
3703 if (t != '(') /* no macro subst */
3704 return -1;
3706 /* argument macro */
3707 next_nomacro();
3708 next_nomacro();
3709 args = NULL;
3710 sa = s->next;
3711 /* NOTE: empty args are allowed, except if no args */
3712 for(;;) {
3713 /* handle '()' case */
3714 if (!args && tok == ')')
3715 break;
3716 if (!sa)
3717 error("macro '%s' used with too many args",
3718 get_tok_str(s->v, 0));
3719 tok_str_new(&str);
3720 parlevel = 0;
3721 /* NOTE: non zero sa->t indicates VA_ARGS */
3722 while ((parlevel > 0 ||
3723 (tok != ')' &&
3724 (tok != ',' || sa->type.t))) &&
3725 tok != -1) {
3726 if (tok == '(')
3727 parlevel++;
3728 else if (tok == ')')
3729 parlevel--;
3730 tok_str_add2(&str, tok, &tokc);
3731 next_nomacro();
3733 tok_str_add(&str, 0);
3734 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3735 sa = sa->next;
3736 if (tok == ')') {
3737 /* special case for gcc var args: add an empty
3738 var arg argument if it is omitted */
3739 if (sa && sa->type.t && gnu_ext)
3740 continue;
3741 else
3742 break;
3744 if (tok != ',')
3745 expect(",");
3746 next_nomacro();
3748 if (sa) {
3749 error("macro '%s' used with too few args",
3750 get_tok_str(s->v, 0));
3753 /* now subst each arg */
3754 mstr = macro_arg_subst(nested_list, mstr, args);
3755 /* free memory */
3756 sa = args;
3757 while (sa) {
3758 sa1 = sa->prev;
3759 tok_str_free((int *)sa->c);
3760 tcc_free(sa);
3761 sa = sa1;
3763 mstr_allocated = 1;
3765 sym_push2(nested_list, s->v, 0, 0);
3766 macro_subst(tok_str, nested_list, mstr);
3767 /* pop nested defined symbol */
3768 sa1 = *nested_list;
3769 *nested_list = sa1->prev;
3770 tcc_free(sa1);
3771 if (mstr_allocated)
3772 tok_str_free(mstr);
3774 return 0;
3777 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3778 return the resulting string (which must be freed). */
3779 static inline int *macro_twosharps(const int *macro_str)
3781 TokenSym *ts;
3782 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3783 int t;
3784 const char *p1, *p2;
3785 CValue cval;
3786 TokenString macro_str1;
3787 CString cstr;
3789 start_macro_ptr = macro_str;
3790 /* we search the first '##' */
3791 for(;;) {
3792 macro_ptr1 = macro_str;
3793 TOK_GET(t, macro_str, cval);
3794 /* nothing more to do if end of string */
3795 if (t == 0)
3796 return NULL;
3797 if (*macro_str == TOK_TWOSHARPS)
3798 break;
3801 /* we saw '##', so we need more processing to handle it */
3802 cstr_new(&cstr);
3803 tok_str_new(&macro_str1);
3804 tok = t;
3805 tokc = cval;
3807 /* add all tokens seen so far */
3808 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3809 TOK_GET(t, ptr, cval);
3810 tok_str_add2(&macro_str1, t, &cval);
3812 saved_macro_ptr = macro_ptr;
3813 /* XXX: suppress the use of macro_ptr here */
3814 macro_ptr = (int *)macro_str;
3815 for(;;) {
3816 while (*macro_ptr == TOK_TWOSHARPS) {
3817 macro_ptr++;
3818 macro_ptr1 = macro_ptr;
3819 t = *macro_ptr;
3820 if (t) {
3821 TOK_GET(t, macro_ptr, cval);
3822 /* We concatenate the two tokens if we have an
3823 identifier or a preprocessing number */
3824 cstr_reset(&cstr);
3825 p1 = get_tok_str(tok, &tokc);
3826 cstr_cat(&cstr, p1);
3827 p2 = get_tok_str(t, &cval);
3828 cstr_cat(&cstr, p2);
3829 cstr_ccat(&cstr, '\0');
3831 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3832 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3833 if (tok == TOK_PPNUM) {
3834 /* if number, then create a number token */
3835 /* NOTE: no need to allocate because
3836 tok_str_add2() does it */
3837 tokc.cstr = &cstr;
3838 } else {
3839 /* if identifier, we must do a test to
3840 validate we have a correct identifier */
3841 if (t == TOK_PPNUM) {
3842 const char *p;
3843 int c;
3845 p = p2;
3846 for(;;) {
3847 c = *p;
3848 if (c == '\0')
3849 break;
3850 p++;
3851 if (!isnum(c) && !isid(c))
3852 goto error_pasting;
3855 ts = tok_alloc(cstr.data, strlen(cstr.data));
3856 tok = ts->tok; /* modify current token */
3858 } else {
3859 const char *str = cstr.data;
3860 const unsigned char *q;
3862 /* we look for a valid token */
3863 /* XXX: do more extensive checks */
3864 if (!strcmp(str, ">>=")) {
3865 tok = TOK_A_SAR;
3866 } else if (!strcmp(str, "<<=")) {
3867 tok = TOK_A_SHL;
3868 } else if (strlen(str) == 2) {
3869 /* search in two bytes table */
3870 q = tok_two_chars;
3871 for(;;) {
3872 if (!*q)
3873 goto error_pasting;
3874 if (q[0] == str[0] && q[1] == str[1])
3875 break;
3876 q += 3;
3878 tok = q[2];
3879 } else {
3880 error_pasting:
3881 /* NOTE: because get_tok_str use a static buffer,
3882 we must save it */
3883 cstr_reset(&cstr);
3884 p1 = get_tok_str(tok, &tokc);
3885 cstr_cat(&cstr, p1);
3886 cstr_ccat(&cstr, '\0');
3887 p2 = get_tok_str(t, &cval);
3888 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3889 /* cannot merge tokens: just add them separately */
3890 tok_str_add2(&macro_str1, tok, &tokc);
3891 /* XXX: free associated memory ? */
3892 tok = t;
3893 tokc = cval;
3898 tok_str_add2(&macro_str1, tok, &tokc);
3899 next_nomacro();
3900 if (tok == 0)
3901 break;
3903 macro_ptr = (int *)saved_macro_ptr;
3904 cstr_free(&cstr);
3905 tok_str_add(&macro_str1, 0);
3906 return macro_str1.str;
3910 /* do macro substitution of macro_str and add result to
3911 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3912 inside to avoid recursing. */
3913 static void macro_subst(TokenString *tok_str,
3914 Sym **nested_list, const int *macro_str)
3916 Sym *s;
3917 int *saved_macro_ptr, *macro_str1;
3918 const int *ptr;
3919 int t, ret;
3920 CValue cval;
3922 /* first scan for '##' operator handling */
3923 ptr = macro_str;
3924 macro_str1 = macro_twosharps(ptr);
3925 if (macro_str1)
3926 ptr = macro_str1;
3927 while (1) {
3928 TOK_GET(t, ptr, cval);
3929 if (t == 0)
3930 break;
3931 s = define_find(t);
3932 if (s != NULL) {
3933 /* if nested substitution, do nothing */
3934 if (sym_find2(*nested_list, t))
3935 goto no_subst;
3936 saved_macro_ptr = macro_ptr;
3937 macro_ptr = (int *)ptr;
3938 tok = t;
3939 ret = macro_subst_tok(tok_str, nested_list, s);
3940 ptr = (int *)macro_ptr;
3941 macro_ptr = saved_macro_ptr;
3942 if (ret != 0)
3943 goto no_subst;
3944 } else {
3945 no_subst:
3946 tok_str_add2(tok_str, t, &cval);
3949 if (macro_str1)
3950 tok_str_free(macro_str1);
3953 /* return next token with macro substitution */
3954 static void next(void)
3956 Sym *nested_list, *s;
3957 TokenString str;
3959 redo:
3960 next_nomacro();
3961 if (!macro_ptr) {
3962 /* if not reading from macro substituted string, then try
3963 to substitute macros */
3964 if (tok >= TOK_IDENT &&
3965 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3966 s = define_find(tok);
3967 if (s) {
3968 /* we have a macro: we try to substitute */
3969 tok_str_new(&str);
3970 nested_list = NULL;
3971 if (macro_subst_tok(&str, &nested_list, s) == 0) {
3972 /* substitution done, NOTE: maybe empty */
3973 tok_str_add(&str, 0);
3974 macro_ptr = str.str;
3975 macro_ptr_allocated = str.str;
3976 goto redo;
3980 } else {
3981 if (tok == 0) {
3982 /* end of macro or end of unget buffer */
3983 if (unget_buffer_enabled) {
3984 macro_ptr = unget_saved_macro_ptr;
3985 unget_buffer_enabled = 0;
3986 } else {
3987 /* end of macro string: free it */
3988 tok_str_free(macro_ptr_allocated);
3989 macro_ptr = NULL;
3991 goto redo;
3995 /* convert preprocessor tokens into C tokens */
3996 if (tok == TOK_PPNUM &&
3997 (parse_flags & PARSE_FLAG_TOK_NUM)) {
3998 parse_number((char *)tokc.cstr->data);
4002 /* push back current token and set current token to 'last_tok'. Only
4003 identifier case handled for labels. */
4004 static inline void unget_tok(int last_tok)
4006 int i, n;
4007 int *q;
4008 unget_saved_macro_ptr = macro_ptr;
4009 unget_buffer_enabled = 1;
4010 q = unget_saved_buffer;
4011 macro_ptr = q;
4012 *q++ = tok;
4013 n = tok_ext_size(tok) - 1;
4014 for(i=0;i<n;i++)
4015 *q++ = tokc.tab[i];
4016 *q = 0; /* end of token string */
4017 tok = last_tok;
4021 void swap(int *p, int *q)
4023 int t;
4024 t = *p;
4025 *p = *q;
4026 *q = t;
4029 void vsetc(CType *type, int r, CValue *vc)
4031 int v;
4033 if (vtop >= vstack + VSTACK_SIZE)
4034 error("memory full");
4035 /* cannot let cpu flags if other instruction are generated. Also
4036 avoid leaving VT_JMP anywhere except on the top of the stack
4037 because it would complicate the code generator. */
4038 if (vtop >= vstack) {
4039 v = vtop->r & VT_VALMASK;
4040 if (v == VT_CMP || (v & ~1) == VT_JMP)
4041 gv(RC_INT);
4043 vtop++;
4044 vtop->type = *type;
4045 vtop->r = r;
4046 vtop->r2 = VT_CONST;
4047 vtop->c = *vc;
4050 /* push integer constant */
4051 void vpushi(int v)
4053 CValue cval;
4054 cval.i = v;
4055 vsetc(&int_type, VT_CONST, &cval);
4058 /* Return a static symbol pointing to a section */
4059 static Sym *get_sym_ref(CType *type, Section *sec,
4060 unsigned long offset, unsigned long size)
4062 int v;
4063 Sym *sym;
4065 v = anon_sym++;
4066 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4067 sym->type.ref = type->ref;
4068 sym->r = VT_CONST | VT_SYM;
4069 put_extern_sym(sym, sec, offset, size);
4070 return sym;
4073 /* push a reference to a section offset by adding a dummy symbol */
4074 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4076 CValue cval;
4078 cval.ul = 0;
4079 vsetc(type, VT_CONST | VT_SYM, &cval);
4080 vtop->sym = get_sym_ref(type, sec, offset, size);
4083 /* define a new external reference to a symbol 'v' of type 'u' */
4084 static Sym *external_global_sym(int v, CType *type, int r)
4086 Sym *s;
4088 s = sym_find(v);
4089 if (!s) {
4090 /* push forward reference */
4091 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4092 s->type.ref = type->ref;
4093 s->r = r | VT_CONST | VT_SYM;
4095 return s;
4098 /* define a new external reference to a symbol 'v' of type 'u' */
4099 static Sym *external_sym(int v, CType *type, int r)
4101 Sym *s;
4103 s = sym_find(v);
4104 if (!s) {
4105 /* push forward reference */
4106 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4107 s->type.t |= VT_EXTERN;
4108 } else {
4109 if (!is_compatible_types(&s->type, type))
4110 error("incompatible types for redefinition of '%s'",
4111 get_tok_str(v, NULL));
4113 return s;
4116 /* push a reference to global symbol v */
4117 static void vpush_global_sym(CType *type, int v)
4119 Sym *sym;
4120 CValue cval;
4122 sym = external_global_sym(v, type, 0);
4123 cval.ul = 0;
4124 vsetc(type, VT_CONST | VT_SYM, &cval);
4125 vtop->sym = sym;
4128 void vset(CType *type, int r, int v)
4130 CValue cval;
4132 cval.i = v;
4133 vsetc(type, r, &cval);
4136 void vseti(int r, int v)
4138 CType type;
4139 type.t = VT_INT;
4140 vset(&type, r, v);
4143 void vswap(void)
4145 SValue tmp;
4147 tmp = vtop[0];
4148 vtop[0] = vtop[-1];
4149 vtop[-1] = tmp;
4152 void vpushv(SValue *v)
4154 if (vtop >= vstack + VSTACK_SIZE)
4155 error("memory full");
4156 vtop++;
4157 *vtop = *v;
4160 void vdup(void)
4162 vpushv(vtop);
4165 /* save r to the memory stack, and mark it as being free */
4166 void save_reg(int r)
4168 int l, saved, size, align;
4169 SValue *p, sv;
4170 CType *type;
4172 /* modify all stack values */
4173 saved = 0;
4174 l = 0;
4175 for(p=vstack;p<=vtop;p++) {
4176 if ((p->r & VT_VALMASK) == r ||
4177 (p->r2 & VT_VALMASK) == r) {
4178 /* must save value on stack if not already done */
4179 if (!saved) {
4180 /* NOTE: must reload 'r' because r might be equal to r2 */
4181 r = p->r & VT_VALMASK;
4182 /* store register in the stack */
4183 type = &p->type;
4184 if ((p->r & VT_LVAL) ||
4185 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4186 type = &int_type;
4187 size = type_size(type, &align);
4188 loc = (loc - size) & -align;
4189 sv.type.t = type->t;
4190 sv.r = VT_LOCAL | VT_LVAL;
4191 sv.c.ul = loc;
4192 store(r, &sv);
4193 #ifdef TCC_TARGET_I386
4194 /* x86 specific: need to pop fp register ST0 if saved */
4195 if (r == TREG_ST0) {
4196 o(0xd9dd); /* fstp %st(1) */
4198 #endif
4199 /* special long long case */
4200 if ((type->t & VT_BTYPE) == VT_LLONG) {
4201 sv.c.ul += 4;
4202 store(p->r2, &sv);
4204 l = loc;
4205 saved = 1;
4207 /* mark that stack entry as being saved on the stack */
4208 if (p->r & VT_LVAL) {
4209 /* also suppress the bounded flag because the
4210 relocation address of the function was stored in
4211 p->c.ul */
4212 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4213 } else {
4214 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4216 p->r2 = VT_CONST;
4217 p->c.ul = l;
4222 /* find a free register of class 'rc'. If none, save one register */
4223 int get_reg(int rc)
4225 int r;
4226 SValue *p;
4228 /* find a free register */
4229 for(r=0;r<NB_REGS;r++) {
4230 if (reg_classes[r] & rc) {
4231 for(p=vstack;p<=vtop;p++) {
4232 if ((p->r & VT_VALMASK) == r ||
4233 (p->r2 & VT_VALMASK) == r)
4234 goto notfound;
4236 return r;
4238 notfound: ;
4241 /* no register left : free the first one on the stack (VERY
4242 IMPORTANT to start from the bottom to ensure that we don't
4243 spill registers used in gen_opi()) */
4244 for(p=vstack;p<=vtop;p++) {
4245 r = p->r & VT_VALMASK;
4246 if (r < VT_CONST && (reg_classes[r] & rc))
4247 goto save_found;
4248 /* also look at second register (if long long) */
4249 r = p->r2 & VT_VALMASK;
4250 if (r < VT_CONST && (reg_classes[r] & rc)) {
4251 save_found:
4252 save_reg(r);
4253 return r;
4256 /* Should never comes here */
4257 return -1;
4260 /* save registers up to (vtop - n) stack entry */
4261 void save_regs(int n)
4263 int r;
4264 SValue *p, *p1;
4265 p1 = vtop - n;
4266 for(p = vstack;p <= p1; p++) {
4267 r = p->r & VT_VALMASK;
4268 if (r < VT_CONST) {
4269 save_reg(r);
4274 /* move register 's' to 'r', and flush previous value of r to memory
4275 if needed */
4276 void move_reg(int r, int s)
4278 SValue sv;
4280 if (r != s) {
4281 save_reg(r);
4282 sv.type.t = VT_INT;
4283 sv.r = s;
4284 sv.c.ul = 0;
4285 load(r, &sv);
4289 /* get address of vtop (vtop MUST BE an lvalue) */
4290 void gaddrof(void)
4292 vtop->r &= ~VT_LVAL;
4293 /* tricky: if saved lvalue, then we can go back to lvalue */
4294 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4295 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4298 #ifdef CONFIG_TCC_BCHECK
4299 /* generate lvalue bound code */
4300 void gbound(void)
4302 int lval_type;
4303 CType type1;
4305 vtop->r &= ~VT_MUSTBOUND;
4306 /* if lvalue, then use checking code before dereferencing */
4307 if (vtop->r & VT_LVAL) {
4308 /* if not VT_BOUNDED value, then make one */
4309 if (!(vtop->r & VT_BOUNDED)) {
4310 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4311 /* must save type because we must set it to int to get pointer */
4312 type1 = vtop->type;
4313 vtop->type.t = VT_INT;
4314 gaddrof();
4315 vpushi(0);
4316 gen_bounded_ptr_add();
4317 vtop->r |= lval_type;
4318 vtop->type = type1;
4320 /* then check for dereferencing */
4321 gen_bounded_ptr_deref();
4324 #endif
4326 /* store vtop a register belonging to class 'rc'. lvalues are
4327 converted to values. Cannot be used if cannot be converted to
4328 register value (such as structures). */
4329 int gv(int rc)
4331 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4332 unsigned long long ll;
4334 /* NOTE: get_reg can modify vstack[] */
4335 if (vtop->type.t & VT_BITFIELD) {
4336 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4337 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4338 /* remove bit field info to avoid loops */
4339 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4340 /* generate shifts */
4341 vpushi(32 - (bit_pos + bit_size));
4342 gen_op(TOK_SHL);
4343 vpushi(32 - bit_size);
4344 /* NOTE: transformed to SHR if unsigned */
4345 gen_op(TOK_SAR);
4346 r = gv(rc);
4347 } else {
4348 if (is_float(vtop->type.t) &&
4349 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4350 Sym *sym;
4351 int *ptr;
4352 unsigned long offset;
4354 /* XXX: unify with initializers handling ? */
4355 /* CPUs usually cannot use float constants, so we store them
4356 generically in data segment */
4357 size = type_size(&vtop->type, &align);
4358 offset = (data_section->data_offset + align - 1) & -align;
4359 data_section->data_offset = offset;
4360 /* XXX: not portable yet */
4361 ptr = section_ptr_add(data_section, size);
4362 size = size >> 2;
4363 for(i=0;i<size;i++)
4364 ptr[i] = vtop->c.tab[i];
4365 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4366 vtop->r |= VT_LVAL | VT_SYM;
4367 vtop->sym = sym;
4368 vtop->c.ul = 0;
4370 #ifdef CONFIG_TCC_BCHECK
4371 if (vtop->r & VT_MUSTBOUND)
4372 gbound();
4373 #endif
4375 r = vtop->r & VT_VALMASK;
4376 /* need to reload if:
4377 - constant
4378 - lvalue (need to dereference pointer)
4379 - already a register, but not in the right class */
4380 if (r >= VT_CONST ||
4381 (vtop->r & VT_LVAL) ||
4382 !(reg_classes[r] & rc) ||
4383 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4384 !(reg_classes[vtop->r2] & rc))) {
4385 r = get_reg(rc);
4386 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4387 /* two register type load : expand to two words
4388 temporarily */
4389 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4390 /* load constant */
4391 ll = vtop->c.ull;
4392 vtop->c.ui = ll; /* first word */
4393 load(r, vtop);
4394 vtop->r = r; /* save register value */
4395 vpushi(ll >> 32); /* second word */
4396 } else if (r >= VT_CONST ||
4397 (vtop->r & VT_LVAL)) {
4398 /* load from memory */
4399 load(r, vtop);
4400 vdup();
4401 vtop[-1].r = r; /* save register value */
4402 /* increment pointer to get second word */
4403 vtop->type.t = VT_INT;
4404 gaddrof();
4405 vpushi(4);
4406 gen_op('+');
4407 vtop->r |= VT_LVAL;
4408 } else {
4409 /* move registers */
4410 load(r, vtop);
4411 vdup();
4412 vtop[-1].r = r; /* save register value */
4413 vtop->r = vtop[-1].r2;
4415 /* allocate second register */
4416 rc2 = RC_INT;
4417 if (rc == RC_IRET)
4418 rc2 = RC_LRET;
4419 r2 = get_reg(rc2);
4420 load(r2, vtop);
4421 vpop();
4422 /* write second register */
4423 vtop->r2 = r2;
4424 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4425 int t1, t;
4426 /* lvalue of scalar type : need to use lvalue type
4427 because of possible cast */
4428 t = vtop->type.t;
4429 t1 = t;
4430 /* compute memory access type */
4431 if (vtop->r & VT_LVAL_BYTE)
4432 t = VT_BYTE;
4433 else if (vtop->r & VT_LVAL_SHORT)
4434 t = VT_SHORT;
4435 if (vtop->r & VT_LVAL_UNSIGNED)
4436 t |= VT_UNSIGNED;
4437 vtop->type.t = t;
4438 load(r, vtop);
4439 /* restore wanted type */
4440 vtop->type.t = t1;
4441 } else {
4442 /* one register type load */
4443 load(r, vtop);
4446 vtop->r = r;
4448 return r;
4451 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4452 void gv2(int rc1, int rc2)
4454 int v;
4456 /* generate more generic register first. But VT_JMP or VT_CMP
4457 values must be generated first in all cases to avoid possible
4458 reload errors */
4459 v = vtop[0].r & VT_VALMASK;
4460 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4461 vswap();
4462 gv(rc1);
4463 vswap();
4464 gv(rc2);
4465 /* test if reload is needed for first register */
4466 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4467 vswap();
4468 gv(rc1);
4469 vswap();
4471 } else {
4472 gv(rc2);
4473 vswap();
4474 gv(rc1);
4475 vswap();
4476 /* test if reload is needed for first register */
4477 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4478 gv(rc2);
4483 /* expand long long on stack in two int registers */
4484 void lexpand(void)
4486 int u;
4488 u = vtop->type.t & VT_UNSIGNED;
4489 gv(RC_INT);
4490 vdup();
4491 vtop[0].r = vtop[-1].r2;
4492 vtop[0].r2 = VT_CONST;
4493 vtop[-1].r2 = VT_CONST;
4494 vtop[0].type.t = VT_INT | u;
4495 vtop[-1].type.t = VT_INT | u;
4498 /* build a long long from two ints */
4499 void lbuild(int t)
4501 gv2(RC_INT, RC_INT);
4502 vtop[-1].r2 = vtop[0].r;
4503 vtop[-1].type.t = t;
4504 vpop();
4507 /* rotate n first stack elements to the bottom */
4508 void vrotb(int n)
4510 int i;
4511 SValue tmp;
4513 tmp = vtop[-n + 1];
4514 for(i=-n+1;i!=0;i++)
4515 vtop[i] = vtop[i+1];
4516 vtop[0] = tmp;
4519 /* pop stack value */
4520 void vpop(void)
4522 int v;
4523 v = vtop->r & VT_VALMASK;
4524 #ifdef TCC_TARGET_I386
4525 /* for x86, we need to pop the FP stack */
4526 if (v == TREG_ST0 && !nocode_wanted) {
4527 o(0xd9dd); /* fstp %st(1) */
4528 } else
4529 #endif
4530 if (v == VT_JMP || v == VT_JMPI) {
4531 /* need to put correct jump if && or || without test */
4532 gsym(vtop->c.ul);
4534 vtop--;
4537 /* convert stack entry to register and duplicate its value in another
4538 register */
4539 void gv_dup(void)
4541 int rc, t, r, r1;
4542 SValue sv;
4544 t = vtop->type.t;
4545 if ((t & VT_BTYPE) == VT_LLONG) {
4546 lexpand();
4547 gv_dup();
4548 vswap();
4549 vrotb(3);
4550 gv_dup();
4551 vrotb(4);
4552 /* stack: H L L1 H1 */
4553 lbuild(t);
4554 vrotb(3);
4555 vrotb(3);
4556 vswap();
4557 lbuild(t);
4558 vswap();
4559 } else {
4560 /* duplicate value */
4561 rc = RC_INT;
4562 sv.type.t = VT_INT;
4563 if (is_float(t)) {
4564 rc = RC_FLOAT;
4565 sv.type.t = t;
4567 r = gv(rc);
4568 r1 = get_reg(rc);
4569 sv.r = r;
4570 sv.c.ul = 0;
4571 load(r1, &sv); /* move r to r1 */
4572 vdup();
4573 /* duplicates value */
4574 vtop->r = r1;
4578 /* generate CPU independent (unsigned) long long operations */
4579 void gen_opl(int op)
4581 int t, a, b, op1, c, i;
4582 int func;
4583 GFuncContext gf;
4584 SValue tmp;
4586 switch(op) {
4587 case '/':
4588 case TOK_PDIV:
4589 func = TOK___divdi3;
4590 goto gen_func;
4591 case TOK_UDIV:
4592 func = TOK___udivdi3;
4593 goto gen_func;
4594 case '%':
4595 func = TOK___moddi3;
4596 goto gen_func;
4597 case TOK_UMOD:
4598 func = TOK___umoddi3;
4599 gen_func:
4600 /* call generic long long function */
4601 gfunc_start(&gf, FUNC_CDECL);
4602 gfunc_param(&gf);
4603 gfunc_param(&gf);
4604 vpush_global_sym(&func_old_type, func);
4605 gfunc_call(&gf);
4606 vpushi(0);
4607 vtop->r = REG_IRET;
4608 vtop->r2 = REG_LRET;
4609 break;
4610 case '^':
4611 case '&':
4612 case '|':
4613 case '*':
4614 case '+':
4615 case '-':
4616 t = vtop->type.t;
4617 vswap();
4618 lexpand();
4619 vrotb(3);
4620 lexpand();
4621 /* stack: L1 H1 L2 H2 */
4622 tmp = vtop[0];
4623 vtop[0] = vtop[-3];
4624 vtop[-3] = tmp;
4625 tmp = vtop[-2];
4626 vtop[-2] = vtop[-3];
4627 vtop[-3] = tmp;
4628 vswap();
4629 /* stack: H1 H2 L1 L2 */
4630 if (op == '*') {
4631 vpushv(vtop - 1);
4632 vpushv(vtop - 1);
4633 gen_op(TOK_UMULL);
4634 lexpand();
4635 /* stack: H1 H2 L1 L2 ML MH */
4636 for(i=0;i<4;i++)
4637 vrotb(6);
4638 /* stack: ML MH H1 H2 L1 L2 */
4639 tmp = vtop[0];
4640 vtop[0] = vtop[-2];
4641 vtop[-2] = tmp;
4642 /* stack: ML MH H1 L2 H2 L1 */
4643 gen_op('*');
4644 vrotb(3);
4645 vrotb(3);
4646 gen_op('*');
4647 /* stack: ML MH M1 M2 */
4648 gen_op('+');
4649 gen_op('+');
4650 } else if (op == '+' || op == '-') {
4651 /* XXX: add non carry method too (for MIPS or alpha) */
4652 if (op == '+')
4653 op1 = TOK_ADDC1;
4654 else
4655 op1 = TOK_SUBC1;
4656 gen_op(op1);
4657 /* stack: H1 H2 (L1 op L2) */
4658 vrotb(3);
4659 vrotb(3);
4660 gen_op(op1 + 1); /* TOK_xxxC2 */
4661 } else {
4662 gen_op(op);
4663 /* stack: H1 H2 (L1 op L2) */
4664 vrotb(3);
4665 vrotb(3);
4666 /* stack: (L1 op L2) H1 H2 */
4667 gen_op(op);
4668 /* stack: (L1 op L2) (H1 op H2) */
4670 /* stack: L H */
4671 lbuild(t);
4672 break;
4673 case TOK_SAR:
4674 case TOK_SHR:
4675 case TOK_SHL:
4676 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4677 t = vtop[-1].type.t;
4678 vswap();
4679 lexpand();
4680 vrotb(3);
4681 /* stack: L H shift */
4682 c = (int)vtop->c.i;
4683 /* constant: simpler */
4684 /* NOTE: all comments are for SHL. the other cases are
4685 done by swaping words */
4686 vpop();
4687 if (op != TOK_SHL)
4688 vswap();
4689 if (c >= 32) {
4690 /* stack: L H */
4691 vpop();
4692 if (c > 32) {
4693 vpushi(c - 32);
4694 gen_op(op);
4696 if (op != TOK_SAR) {
4697 vpushi(0);
4698 } else {
4699 gv_dup();
4700 vpushi(31);
4701 gen_op(TOK_SAR);
4703 vswap();
4704 } else {
4705 vswap();
4706 gv_dup();
4707 /* stack: H L L */
4708 vpushi(c);
4709 gen_op(op);
4710 vswap();
4711 vpushi(32 - c);
4712 if (op == TOK_SHL)
4713 gen_op(TOK_SHR);
4714 else
4715 gen_op(TOK_SHL);
4716 vrotb(3);
4717 /* stack: L L H */
4718 vpushi(c);
4719 if (op == TOK_SHL)
4720 gen_op(TOK_SHL);
4721 else
4722 gen_op(TOK_SHR);
4723 gen_op('|');
4725 if (op != TOK_SHL)
4726 vswap();
4727 lbuild(t);
4728 } else {
4729 /* XXX: should provide a faster fallback on x86 ? */
4730 switch(op) {
4731 case TOK_SAR:
4732 func = TOK___sardi3;
4733 goto gen_func;
4734 case TOK_SHR:
4735 func = TOK___shrdi3;
4736 goto gen_func;
4737 case TOK_SHL:
4738 func = TOK___shldi3;
4739 goto gen_func;
4742 break;
4743 default:
4744 /* compare operations */
4745 t = vtop->type.t;
4746 vswap();
4747 lexpand();
4748 vrotb(3);
4749 lexpand();
4750 /* stack: L1 H1 L2 H2 */
4751 tmp = vtop[-1];
4752 vtop[-1] = vtop[-2];
4753 vtop[-2] = tmp;
4754 /* stack: L1 L2 H1 H2 */
4755 /* compare high */
4756 op1 = op;
4757 /* when values are equal, we need to compare low words. since
4758 the jump is inverted, we invert the test too. */
4759 if (op1 == TOK_LT)
4760 op1 = TOK_LE;
4761 else if (op1 == TOK_GT)
4762 op1 = TOK_GE;
4763 else if (op1 == TOK_ULT)
4764 op1 = TOK_ULE;
4765 else if (op1 == TOK_UGT)
4766 op1 = TOK_UGE;
4767 a = 0;
4768 b = 0;
4769 gen_op(op1);
4770 if (op1 != TOK_NE) {
4771 a = gtst(1, 0);
4773 if (op != TOK_EQ) {
4774 /* generate non equal test */
4775 /* XXX: NOT PORTABLE yet */
4776 if (a == 0) {
4777 b = gtst(0, 0);
4778 } else {
4779 #ifdef TCC_TARGET_I386
4780 b = psym(0x850f, 0);
4781 #else
4782 error("not implemented");
4783 #endif
4786 /* compare low. Always unsigned */
4787 op1 = op;
4788 if (op1 == TOK_LT)
4789 op1 = TOK_ULT;
4790 else if (op1 == TOK_LE)
4791 op1 = TOK_ULE;
4792 else if (op1 == TOK_GT)
4793 op1 = TOK_UGT;
4794 else if (op1 == TOK_GE)
4795 op1 = TOK_UGE;
4796 gen_op(op1);
4797 a = gtst(1, a);
4798 gsym(b);
4799 vseti(VT_JMPI, a);
4800 break;
4804 /* handle integer constant optimizations and various machine
4805 independant opt */
4806 void gen_opic(int op)
4808 int fc, c1, c2, n;
4809 SValue *v1, *v2;
4811 v1 = vtop - 1;
4812 v2 = vtop;
4813 /* currently, we cannot do computations with forward symbols */
4814 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4815 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4816 if (c1 && c2) {
4817 fc = v2->c.i;
4818 switch(op) {
4819 case '+': v1->c.i += fc; break;
4820 case '-': v1->c.i -= fc; break;
4821 case '&': v1->c.i &= fc; break;
4822 case '^': v1->c.i ^= fc; break;
4823 case '|': v1->c.i |= fc; break;
4824 case '*': v1->c.i *= fc; break;
4826 case TOK_PDIV:
4827 case '/':
4828 case '%':
4829 case TOK_UDIV:
4830 case TOK_UMOD:
4831 /* if division by zero, generate explicit division */
4832 if (fc == 0) {
4833 if (const_wanted)
4834 error("division by zero in constant");
4835 goto general_case;
4837 switch(op) {
4838 default: v1->c.i /= fc; break;
4839 case '%': v1->c.i %= fc; break;
4840 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4841 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4843 break;
4844 case TOK_SHL: v1->c.i <<= fc; break;
4845 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4846 case TOK_SAR: v1->c.i >>= fc; break;
4847 /* tests */
4848 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4849 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4850 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4851 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4852 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4853 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4854 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4855 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4856 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4857 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4858 /* logical */
4859 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4860 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4861 default:
4862 goto general_case;
4864 vtop--;
4865 } else {
4866 /* if commutative ops, put c2 as constant */
4867 if (c1 && (op == '+' || op == '&' || op == '^' ||
4868 op == '|' || op == '*')) {
4869 vswap();
4870 swap(&c1, &c2);
4872 fc = vtop->c.i;
4873 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4874 op == TOK_PDIV) &&
4875 fc == 1) ||
4876 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4877 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4878 fc == 0) ||
4879 (op == '&' &&
4880 fc == -1))) {
4881 /* nothing to do */
4882 vtop--;
4883 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4884 /* try to use shifts instead of muls or divs */
4885 if (fc > 0 && (fc & (fc - 1)) == 0) {
4886 n = -1;
4887 while (fc) {
4888 fc >>= 1;
4889 n++;
4891 vtop->c.i = n;
4892 if (op == '*')
4893 op = TOK_SHL;
4894 else if (op == TOK_PDIV)
4895 op = TOK_SAR;
4896 else
4897 op = TOK_SHR;
4899 goto general_case;
4900 } else if (c2 && (op == '+' || op == '-') &&
4901 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4902 (VT_CONST | VT_SYM)) {
4903 /* symbol + constant case */
4904 if (op == '-')
4905 fc = -fc;
4906 vtop--;
4907 vtop->c.i += fc;
4908 } else {
4909 general_case:
4910 if (!nocode_wanted) {
4911 /* call low level op generator */
4912 gen_opi(op);
4913 } else {
4914 vtop--;
4920 /* generate a floating point operation with constant propagation */
4921 void gen_opif(int op)
4923 int c1, c2;
4924 SValue *v1, *v2;
4925 long double f1, f2;
4927 v1 = vtop - 1;
4928 v2 = vtop;
4929 /* currently, we cannot do computations with forward symbols */
4930 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4931 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4932 if (c1 && c2) {
4933 if (v1->type.t == VT_FLOAT) {
4934 f1 = v1->c.f;
4935 f2 = v2->c.f;
4936 } else if (v1->type.t == VT_DOUBLE) {
4937 f1 = v1->c.d;
4938 f2 = v2->c.d;
4939 } else {
4940 f1 = v1->c.ld;
4941 f2 = v2->c.ld;
4944 /* NOTE: we only do constant propagation if finite number (not
4945 NaN or infinity) (ANSI spec) */
4946 if (!ieee_finite(f1) || !ieee_finite(f2))
4947 goto general_case;
4949 switch(op) {
4950 case '+': f1 += f2; break;
4951 case '-': f1 -= f2; break;
4952 case '*': f1 *= f2; break;
4953 case '/':
4954 if (f2 == 0.0) {
4955 if (const_wanted)
4956 error("division by zero in constant");
4957 goto general_case;
4959 f1 /= f2;
4960 break;
4961 /* XXX: also handles tests ? */
4962 default:
4963 goto general_case;
4965 /* XXX: overflow test ? */
4966 if (v1->type.t == VT_FLOAT) {
4967 v1->c.f = f1;
4968 } else if (v1->type.t == VT_DOUBLE) {
4969 v1->c.d = f1;
4970 } else {
4971 v1->c.ld = f1;
4973 vtop--;
4974 } else {
4975 general_case:
4976 if (!nocode_wanted) {
4977 gen_opf(op);
4978 } else {
4979 vtop--;
4984 static int pointed_size(CType *type)
4986 int align;
4987 return type_size(pointed_type(type), &align);
4990 #if 0
4991 void check_pointer_types(SValue *p1, SValue *p2)
4993 char buf1[256], buf2[256];
4994 int t1, t2;
4995 t1 = p1->t;
4996 t2 = p2->t;
4997 if (!is_compatible_types(t1, t2)) {
4998 type_to_str(buf1, sizeof(buf1), t1, NULL);
4999 type_to_str(buf2, sizeof(buf2), t2, NULL);
5000 error("incompatible pointers '%s' and '%s'", buf1, buf2);
5003 #endif
5005 /* generic gen_op: handles types problems */
5006 void gen_op(int op)
5008 int u, t1, t2, bt1, bt2, t;
5009 CType type1;
5011 t1 = vtop[-1].type.t;
5012 t2 = vtop[0].type.t;
5013 bt1 = t1 & VT_BTYPE;
5014 bt2 = t2 & VT_BTYPE;
5016 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5017 /* at least one operand is a pointer */
5018 /* relationnal op: must be both pointers */
5019 if (op >= TOK_ULT && op <= TOK_GT) {
5020 // check_pointer_types(vtop, vtop - 1);
5021 /* pointers are handled are unsigned */
5022 t = VT_INT | VT_UNSIGNED;
5023 goto std_op;
5025 /* if both pointers, then it must be the '-' op */
5026 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5027 if (op != '-')
5028 error("cannot use pointers here");
5029 // check_pointer_types(vtop - 1, vtop);
5030 /* XXX: check that types are compatible */
5031 u = pointed_size(&vtop[-1].type);
5032 gen_opic(op);
5033 /* set to integer type */
5034 vtop->type.t = VT_INT;
5035 vpushi(u);
5036 gen_op(TOK_PDIV);
5037 } else {
5038 /* exactly one pointer : must be '+' or '-'. */
5039 if (op != '-' && op != '+')
5040 error("cannot use pointers here");
5041 /* Put pointer as first operand */
5042 if (bt2 == VT_PTR) {
5043 vswap();
5044 swap(&t1, &t2);
5046 type1 = vtop[-1].type;
5047 /* XXX: cast to int ? (long long case) */
5048 vpushi(pointed_size(&vtop[-1].type));
5049 gen_op('*');
5050 #ifdef CONFIG_TCC_BCHECK
5051 /* if evaluating constant expression, no code should be
5052 generated, so no bound check */
5053 if (do_bounds_check && !const_wanted) {
5054 /* if bounded pointers, we generate a special code to
5055 test bounds */
5056 if (op == '-') {
5057 vpushi(0);
5058 vswap();
5059 gen_op('-');
5061 gen_bounded_ptr_add();
5062 } else
5063 #endif
5065 gen_opic(op);
5067 /* put again type if gen_opic() swaped operands */
5068 vtop->type = type1;
5070 } else if (is_float(bt1) || is_float(bt2)) {
5071 /* compute bigger type and do implicit casts */
5072 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5073 t = VT_LDOUBLE;
5074 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5075 t = VT_DOUBLE;
5076 } else {
5077 t = VT_FLOAT;
5079 /* floats can only be used for a few operations */
5080 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5081 (op < TOK_ULT || op > TOK_GT))
5082 error("invalid operands for binary operation");
5083 goto std_op;
5084 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5085 /* cast to biggest op */
5086 t = VT_LLONG;
5087 /* convert to unsigned if it does not fit in a long long */
5088 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5089 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5090 t |= VT_UNSIGNED;
5091 goto std_op;
5092 } else {
5093 /* integer operations */
5094 t = VT_INT;
5095 /* convert to unsigned if it does not fit in an integer */
5096 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5097 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5098 t |= VT_UNSIGNED;
5099 std_op:
5100 /* XXX: currently, some unsigned operations are explicit, so
5101 we modify them here */
5102 if (t & VT_UNSIGNED) {
5103 if (op == TOK_SAR)
5104 op = TOK_SHR;
5105 else if (op == '/')
5106 op = TOK_UDIV;
5107 else if (op == '%')
5108 op = TOK_UMOD;
5109 else if (op == TOK_LT)
5110 op = TOK_ULT;
5111 else if (op == TOK_GT)
5112 op = TOK_UGT;
5113 else if (op == TOK_LE)
5114 op = TOK_ULE;
5115 else if (op == TOK_GE)
5116 op = TOK_UGE;
5118 vswap();
5119 type1.t = t;
5120 gen_cast(&type1);
5121 vswap();
5122 /* special case for shifts and long long: we keep the shift as
5123 an integer */
5124 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5125 type1.t = VT_INT;
5126 gen_cast(&type1);
5127 if (is_float(t))
5128 gen_opif(op);
5129 else if ((t & VT_BTYPE) == VT_LLONG)
5130 gen_opl(op);
5131 else
5132 gen_opic(op);
5133 if (op >= TOK_ULT && op <= TOK_GT) {
5134 /* relationnal op: the result is an int */
5135 vtop->type.t = VT_INT;
5136 } else {
5137 vtop->type.t = t;
5142 /* generic itof for unsigned long long case */
5143 void gen_cvt_itof1(int t)
5145 GFuncContext gf;
5147 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5148 (VT_LLONG | VT_UNSIGNED)) {
5150 gfunc_start(&gf, FUNC_CDECL);
5151 gfunc_param(&gf);
5152 if (t == VT_FLOAT)
5153 vpush_global_sym(&func_old_type, TOK___ulltof);
5154 else if (t == VT_DOUBLE)
5155 vpush_global_sym(&func_old_type, TOK___ulltod);
5156 else
5157 vpush_global_sym(&func_old_type, TOK___ulltold);
5158 gfunc_call(&gf);
5159 vpushi(0);
5160 vtop->r = REG_FRET;
5161 } else {
5162 gen_cvt_itof(t);
5166 /* generic ftoi for unsigned long long case */
5167 void gen_cvt_ftoi1(int t)
5169 GFuncContext gf;
5170 int st;
5172 if (t == (VT_LLONG | VT_UNSIGNED)) {
5173 /* not handled natively */
5174 gfunc_start(&gf, FUNC_CDECL);
5175 st = vtop->type.t & VT_BTYPE;
5176 gfunc_param(&gf);
5177 if (st == VT_FLOAT)
5178 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5179 else if (st == VT_DOUBLE)
5180 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5181 else
5182 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5183 gfunc_call(&gf);
5184 vpushi(0);
5185 vtop->r = REG_IRET;
5186 vtop->r2 = REG_LRET;
5187 } else {
5188 gen_cvt_ftoi(t);
5192 /* force char or short cast */
5193 void force_charshort_cast(int t)
5195 int bits, dbt;
5196 dbt = t & VT_BTYPE;
5197 /* XXX: add optimization if lvalue : just change type and offset */
5198 if (dbt == VT_BYTE)
5199 bits = 8;
5200 else
5201 bits = 16;
5202 if (t & VT_UNSIGNED) {
5203 vpushi((1 << bits) - 1);
5204 gen_op('&');
5205 } else {
5206 bits = 32 - bits;
5207 vpushi(bits);
5208 gen_op(TOK_SHL);
5209 vpushi(bits);
5210 gen_op(TOK_SAR);
5214 /* cast 'vtop' to 'type' */
5215 static void gen_cast(CType *type)
5217 int sbt, dbt, sf, df, c;
5219 /* special delayed cast for char/short */
5220 /* XXX: in some cases (multiple cascaded casts), it may still
5221 be incorrect */
5222 if (vtop->r & VT_MUSTCAST) {
5223 vtop->r &= ~VT_MUSTCAST;
5224 force_charshort_cast(vtop->type.t);
5227 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5228 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5230 if (sbt != dbt && !nocode_wanted) {
5231 sf = is_float(sbt);
5232 df = is_float(dbt);
5233 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5234 if (sf && df) {
5235 /* convert from fp to fp */
5236 if (c) {
5237 /* constant case: we can do it now */
5238 /* XXX: in ISOC, cannot do it if error in convert */
5239 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5240 vtop->c.f = (float)vtop->c.d;
5241 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5242 vtop->c.f = (float)vtop->c.ld;
5243 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5244 vtop->c.d = (double)vtop->c.f;
5245 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5246 vtop->c.d = (double)vtop->c.ld;
5247 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5248 vtop->c.ld = (long double)vtop->c.f;
5249 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5250 vtop->c.ld = (long double)vtop->c.d;
5251 } else {
5252 /* non constant case: generate code */
5253 gen_cvt_ftof(dbt);
5255 } else if (df) {
5256 /* convert int to fp */
5257 if (c) {
5258 switch(sbt) {
5259 case VT_LLONG | VT_UNSIGNED:
5260 case VT_LLONG:
5261 /* XXX: add const cases for long long */
5262 goto do_itof;
5263 case VT_INT | VT_UNSIGNED:
5264 switch(dbt) {
5265 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5266 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5267 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5269 break;
5270 default:
5271 switch(dbt) {
5272 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5273 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5274 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5276 break;
5278 } else {
5279 do_itof:
5280 gen_cvt_itof1(dbt);
5282 } else if (sf) {
5283 /* convert fp to int */
5284 /* we handle char/short/etc... with generic code */
5285 if (dbt != (VT_INT | VT_UNSIGNED) &&
5286 dbt != (VT_LLONG | VT_UNSIGNED) &&
5287 dbt != VT_LLONG)
5288 dbt = VT_INT;
5289 if (c) {
5290 switch(dbt) {
5291 case VT_LLONG | VT_UNSIGNED:
5292 case VT_LLONG:
5293 /* XXX: add const cases for long long */
5294 goto do_ftoi;
5295 case VT_INT | VT_UNSIGNED:
5296 switch(sbt) {
5297 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5298 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5299 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5301 break;
5302 default:
5303 /* int case */
5304 switch(sbt) {
5305 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5306 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5307 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5309 break;
5311 } else {
5312 do_ftoi:
5313 gen_cvt_ftoi1(dbt);
5315 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5316 /* additionnal cast for char/short/bool... */
5317 vtop->type.t = dbt;
5318 gen_cast(type);
5320 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5321 if ((sbt & VT_BTYPE) != VT_LLONG) {
5322 /* scalar to long long */
5323 if (c) {
5324 if (sbt == (VT_INT | VT_UNSIGNED))
5325 vtop->c.ll = vtop->c.ui;
5326 else
5327 vtop->c.ll = vtop->c.i;
5328 } else {
5329 /* machine independant conversion */
5330 gv(RC_INT);
5331 /* generate high word */
5332 if (sbt == (VT_INT | VT_UNSIGNED)) {
5333 vpushi(0);
5334 gv(RC_INT);
5335 } else {
5336 gv_dup();
5337 vpushi(31);
5338 gen_op(TOK_SAR);
5340 /* patch second register */
5341 vtop[-1].r2 = vtop->r;
5342 vpop();
5345 } else if (dbt == VT_BOOL) {
5346 /* scalar to bool */
5347 vpushi(0);
5348 gen_op(TOK_NE);
5349 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5350 (dbt & VT_BTYPE) == VT_SHORT) {
5351 force_charshort_cast(dbt);
5352 } else if ((dbt & VT_BTYPE) == VT_INT) {
5353 /* scalar to int */
5354 if (sbt == VT_LLONG) {
5355 /* from long long: just take low order word */
5356 lexpand();
5357 vpop();
5359 /* if lvalue and single word type, nothing to do because
5360 the lvalue already contains the real type size (see
5361 VT_LVAL_xxx constants) */
5364 vtop->type = *type;
5367 /* return type size. Put alignment at 'a' */
5368 static int type_size(CType *type, int *a)
5370 Sym *s;
5371 int bt;
5373 bt = type->t & VT_BTYPE;
5374 if (bt == VT_STRUCT) {
5375 /* struct/union */
5376 s = type->ref;
5377 *a = s->r;
5378 return s->c;
5379 } else if (bt == VT_PTR) {
5380 if (type->t & VT_ARRAY) {
5381 s = type->ref;
5382 return type_size(&s->type, a) * s->c;
5383 } else {
5384 *a = PTR_SIZE;
5385 return PTR_SIZE;
5387 } else if (bt == VT_LDOUBLE) {
5388 *a = LDOUBLE_ALIGN;
5389 return LDOUBLE_SIZE;
5390 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5391 *a = 4; /* XXX: i386 specific */
5392 return 8;
5393 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5394 *a = 4;
5395 return 4;
5396 } else if (bt == VT_SHORT) {
5397 *a = 2;
5398 return 2;
5399 } else {
5400 /* char, void, function, _Bool */
5401 *a = 1;
5402 return 1;
5406 /* return the pointed type of t */
5407 static inline CType *pointed_type(CType *type)
5409 return &type->ref->type;
5412 /* modify type so that its it is a pointer to type. */
5413 static void mk_pointer(CType *type)
5415 Sym *s;
5416 s = sym_push(SYM_FIELD, type, 0, -1);
5417 type->t = VT_PTR | (type->t & ~VT_TYPE);
5418 type->ref = s;
5421 static int is_compatible_types(CType *type1, CType *type2)
5423 Sym *s1, *s2;
5424 int bt1, bt2, t1, t2;
5426 t1 = type1->t & VT_TYPE;
5427 t2 = type2->t & VT_TYPE;
5428 bt1 = t1 & VT_BTYPE;
5429 bt2 = t2 & VT_BTYPE;
5430 if (bt1 == VT_PTR) {
5431 type1 = pointed_type(type1);
5432 /* if function, then convert implicitely to function pointer */
5433 if (bt2 != VT_FUNC) {
5434 if (bt2 != VT_PTR)
5435 return 0;
5436 type2 = pointed_type(type2);
5438 /* void matches everything */
5439 /* XXX: not fully compliant */
5440 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
5441 return 1;
5442 return is_compatible_types(type1, type2);
5443 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5444 return (type1->ref == type2->ref);
5445 } else if (bt1 == VT_FUNC) {
5446 if (bt2 != VT_FUNC)
5447 return 0;
5448 s1 = type1->ref;
5449 s2 = type2->ref;
5450 if (!is_compatible_types(&s1->type, &s2->type))
5451 return 0;
5452 /* XXX: not complete */
5453 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5454 return 1;
5455 if (s1->c != s2->c)
5456 return 0;
5457 while (s1 != NULL) {
5458 if (s2 == NULL)
5459 return 0;
5460 if (!is_compatible_types(&s1->type, &s2->type))
5461 return 0;
5462 s1 = s1->next;
5463 s2 = s2->next;
5465 if (s2)
5466 return 0;
5467 return 1;
5468 } else {
5469 /* XXX: not complete */
5470 return 1;
5474 /* print a type. If 'varstr' is not NULL, then the variable is also
5475 printed in the type */
5476 /* XXX: union */
5477 /* XXX: add array and function pointers */
5478 void type_to_str(char *buf, int buf_size,
5479 CType *type, const char *varstr)
5481 int bt, v, t;
5482 Sym *s, *sa;
5483 char buf1[256];
5484 const char *tstr;
5486 t = type->t & VT_TYPE;
5487 bt = t & VT_BTYPE;
5488 buf[0] = '\0';
5489 if (t & VT_UNSIGNED)
5490 pstrcat(buf, buf_size, "unsigned ");
5491 switch(bt) {
5492 case VT_VOID:
5493 tstr = "void";
5494 goto add_tstr;
5495 case VT_BOOL:
5496 tstr = "_Bool";
5497 goto add_tstr;
5498 case VT_BYTE:
5499 tstr = "char";
5500 goto add_tstr;
5501 case VT_SHORT:
5502 tstr = "short";
5503 goto add_tstr;
5504 case VT_INT:
5505 tstr = "int";
5506 goto add_tstr;
5507 case VT_LONG:
5508 tstr = "long";
5509 goto add_tstr;
5510 case VT_LLONG:
5511 tstr = "long long";
5512 goto add_tstr;
5513 case VT_FLOAT:
5514 tstr = "float";
5515 goto add_tstr;
5516 case VT_DOUBLE:
5517 tstr = "double";
5518 goto add_tstr;
5519 case VT_LDOUBLE:
5520 tstr = "long double";
5521 add_tstr:
5522 pstrcat(buf, buf_size, tstr);
5523 break;
5524 case VT_ENUM:
5525 case VT_STRUCT:
5526 if (bt == VT_STRUCT)
5527 tstr = "struct ";
5528 else
5529 tstr = "enum ";
5530 pstrcat(buf, buf_size, tstr);
5531 v = type->ref->v & ~SYM_STRUCT;
5532 if (v >= SYM_FIRST_ANOM)
5533 pstrcat(buf, buf_size, "<anonymous>");
5534 else
5535 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5536 break;
5537 case VT_FUNC:
5538 s = type->ref;
5539 type_to_str(buf, buf_size, &s->type, varstr);
5540 pstrcat(buf, buf_size, "(");
5541 sa = s->next;
5542 while (sa != NULL) {
5543 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5544 pstrcat(buf, buf_size, buf1);
5545 sa = sa->next;
5546 if (sa)
5547 pstrcat(buf, buf_size, ", ");
5549 pstrcat(buf, buf_size, ")");
5550 goto no_var;
5551 case VT_PTR:
5552 s = type->ref;
5553 pstrcpy(buf1, sizeof(buf1), "*");
5554 if (varstr)
5555 pstrcat(buf1, sizeof(buf1), varstr);
5556 type_to_str(buf, buf_size, &s->type, buf1);
5557 goto no_var;
5559 if (varstr) {
5560 pstrcat(buf, buf_size, " ");
5561 pstrcat(buf, buf_size, varstr);
5563 no_var: ;
5566 /* verify type compatibility to store vtop in 'dt' type, and generate
5567 casts if needed. */
5568 static void gen_assign_cast(CType *dt)
5570 CType *st;
5571 char buf1[256], buf2[256];
5572 int dbt, sbt;
5574 st = &vtop->type; /* source type */
5575 dbt = dt->t & VT_BTYPE;
5576 sbt = st->t & VT_BTYPE;
5577 if (dbt == VT_PTR) {
5578 /* special cases for pointers */
5579 /* a function is implicitely a function pointer */
5580 if (sbt == VT_FUNC) {
5581 if (!is_compatible_types(pointed_type(dt), st))
5582 goto error;
5583 else
5584 goto type_ok;
5586 /* '0' can also be a pointer */
5587 if (sbt == VT_INT &&
5588 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5589 vtop->c.i == 0)
5590 goto type_ok;
5591 /* accept implicit pointer to integer cast with warning */
5592 if (sbt == VT_BYTE || sbt == VT_SHORT ||
5593 sbt == VT_INT || sbt == VT_LLONG) {
5594 warning("assignment makes pointer from integer without a cast");
5595 goto type_ok;
5597 } else if (dbt == VT_BYTE || dbt == VT_SHORT ||
5598 dbt == VT_INT || dbt == VT_LLONG) {
5599 if (sbt == VT_PTR || sbt == VT_FUNC) {
5600 warning("assignment makes integer from pointer without a cast");
5601 goto type_ok;
5604 if (!is_compatible_types(dt, st)) {
5605 error:
5606 type_to_str(buf1, sizeof(buf1), st, NULL);
5607 type_to_str(buf2, sizeof(buf2), dt, NULL);
5608 error("cannot cast '%s' to '%s'", buf1, buf2);
5610 type_ok:
5611 gen_cast(dt);
5614 /* store vtop in lvalue pushed on stack */
5615 void vstore(void)
5617 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5618 GFuncContext gf;
5620 ft = vtop[-1].type.t;
5621 sbt = vtop->type.t & VT_BTYPE;
5622 dbt = ft & VT_BTYPE;
5623 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5624 (sbt == VT_INT && dbt == VT_SHORT)) {
5625 /* optimize char/short casts */
5626 delayed_cast = VT_MUSTCAST;
5627 vtop->type.t = ft & VT_TYPE;
5628 } else {
5629 delayed_cast = 0;
5630 gen_assign_cast(&vtop[-1].type);
5633 if (sbt == VT_STRUCT) {
5634 /* if structure, only generate pointer */
5635 /* structure assignment : generate memcpy */
5636 /* XXX: optimize if small size */
5637 if (!nocode_wanted) {
5638 vdup();
5639 gfunc_start(&gf, FUNC_CDECL);
5640 /* type size */
5641 size = type_size(&vtop->type, &align);
5642 vpushi(size);
5643 gfunc_param(&gf);
5644 /* source */
5645 vtop->type.t = VT_INT;
5646 gaddrof();
5647 gfunc_param(&gf);
5648 /* destination */
5649 vswap();
5650 vtop->type.t = VT_INT;
5651 gaddrof();
5652 gfunc_param(&gf);
5654 save_regs(0);
5655 vpush_global_sym(&func_old_type, TOK_memcpy);
5656 gfunc_call(&gf);
5657 } else {
5658 vswap();
5659 vpop();
5661 /* leave source on stack */
5662 } else if (ft & VT_BITFIELD) {
5663 /* bitfield store handling */
5664 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5665 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5666 /* remove bit field info to avoid loops */
5667 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5669 /* duplicate destination */
5670 vdup();
5671 vtop[-1] = vtop[-2];
5673 /* mask and shift source */
5674 vpushi((1 << bit_size) - 1);
5675 gen_op('&');
5676 vpushi(bit_pos);
5677 gen_op(TOK_SHL);
5678 /* load destination, mask and or with source */
5679 vswap();
5680 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5681 gen_op('&');
5682 gen_op('|');
5683 /* store result */
5684 vstore();
5685 } else {
5686 #ifdef CONFIG_TCC_BCHECK
5687 /* bound check case */
5688 if (vtop[-1].r & VT_MUSTBOUND) {
5689 vswap();
5690 gbound();
5691 vswap();
5693 #endif
5694 if (!nocode_wanted) {
5695 rc = RC_INT;
5696 if (is_float(ft))
5697 rc = RC_FLOAT;
5698 r = gv(rc); /* generate value */
5699 /* if lvalue was saved on stack, must read it */
5700 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5701 SValue sv;
5702 t = get_reg(RC_INT);
5703 sv.type.t = VT_INT;
5704 sv.r = VT_LOCAL | VT_LVAL;
5705 sv.c.ul = vtop[-1].c.ul;
5706 load(t, &sv);
5707 vtop[-1].r = t | VT_LVAL;
5709 store(r, vtop - 1);
5710 /* two word case handling : store second register at word + 4 */
5711 if ((ft & VT_BTYPE) == VT_LLONG) {
5712 vswap();
5713 /* convert to int to increment easily */
5714 vtop->type.t = VT_INT;
5715 gaddrof();
5716 vpushi(4);
5717 gen_op('+');
5718 vtop->r |= VT_LVAL;
5719 vswap();
5720 /* XXX: it works because r2 is spilled last ! */
5721 store(vtop->r2, vtop - 1);
5724 vswap();
5725 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5726 vtop->r |= delayed_cast;
5730 /* post defines POST/PRE add. c is the token ++ or -- */
5731 void inc(int post, int c)
5733 test_lvalue();
5734 vdup(); /* save lvalue */
5735 if (post) {
5736 gv_dup(); /* duplicate value */
5737 vrotb(3);
5738 vrotb(3);
5740 /* add constant */
5741 vpushi(c - TOK_MID);
5742 gen_op('+');
5743 vstore(); /* store value */
5744 if (post)
5745 vpop(); /* if post op, return saved value */
5748 /* Parse GNUC __attribute__ extension. Currently, the following
5749 extensions are recognized:
5750 - aligned(n) : set data/function alignment.
5751 - section(x) : generate data/code in this section.
5752 - unused : currently ignored, but may be used someday.
5754 static void parse_attribute(AttributeDef *ad)
5756 int t, n;
5758 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5759 next();
5760 skip('(');
5761 skip('(');
5762 while (tok != ')') {
5763 if (tok < TOK_IDENT)
5764 expect("attribute name");
5765 t = tok;
5766 next();
5767 switch(t) {
5768 case TOK_SECTION1:
5769 case TOK_SECTION2:
5770 skip('(');
5771 if (tok != TOK_STR)
5772 expect("section name");
5773 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5774 next();
5775 skip(')');
5776 break;
5777 case TOK_ALIGNED1:
5778 case TOK_ALIGNED2:
5779 if (tok == '(') {
5780 next();
5781 n = expr_const();
5782 if (n <= 0 || (n & (n - 1)) != 0)
5783 error("alignment must be a positive power of two");
5784 skip(')');
5785 } else {
5786 n = MAX_ALIGN;
5788 ad->aligned = n;
5789 break;
5790 case TOK_UNUSED1:
5791 case TOK_UNUSED2:
5792 /* currently, no need to handle it because tcc does not
5793 track unused objects */
5794 break;
5795 case TOK_NORETURN1:
5796 case TOK_NORETURN2:
5797 /* currently, no need to handle it because tcc does not
5798 track unused objects */
5799 break;
5800 case TOK_CDECL1:
5801 case TOK_CDECL2:
5802 case TOK_CDECL3:
5803 ad->func_call = FUNC_CDECL;
5804 break;
5805 case TOK_STDCALL1:
5806 case TOK_STDCALL2:
5807 case TOK_STDCALL3:
5808 ad->func_call = FUNC_STDCALL;
5809 break;
5810 default:
5811 // warning("'%s' attribute ignored", get_tok_str(t, NULL));
5812 /* skip parameters */
5813 /* XXX: skip parenthesis too */
5814 if (tok == '(') {
5815 next();
5816 while (tok != ')' && tok != -1)
5817 next();
5818 next();
5820 break;
5822 if (tok != ',')
5823 break;
5824 next();
5826 skip(')');
5827 skip(')');
5831 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5832 static void struct_decl(CType *type, int u)
5834 int a, v, size, align, maxalign, c, offset;
5835 int bit_size, bit_pos, bsize, bt, lbit_pos;
5836 Sym *s, *ss, **ps;
5837 AttributeDef ad;
5838 CType type1, btype;
5840 a = tok; /* save decl type */
5841 next();
5842 if (tok != '{') {
5843 v = tok;
5844 next();
5845 /* struct already defined ? return it */
5846 if (v < TOK_IDENT)
5847 expect("struct/union/enum name");
5848 s = struct_find(v);
5849 if (s) {
5850 if (s->type.t != a)
5851 error("invalid type");
5852 goto do_decl;
5854 } else {
5855 v = anon_sym++;
5857 type1.t = a;
5858 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5859 /* put struct/union/enum name in type */
5860 do_decl:
5861 type->t = u;
5862 type->ref = s;
5864 if (tok == '{') {
5865 next();
5866 if (s->c)
5867 error("struct/union/enum already defined");
5868 /* cannot be empty */
5869 c = 0;
5870 /* non empty enums are not allowed */
5871 if (a == TOK_ENUM) {
5872 for(;;) {
5873 v = tok;
5874 if (v < TOK_UIDENT)
5875 expect("identifier");
5876 next();
5877 if (tok == '=') {
5878 next();
5879 c = expr_const();
5881 /* enum symbols have static storage */
5882 ss = sym_push(v, &int_type, VT_CONST, c);
5883 ss->type.t |= VT_STATIC;
5884 if (tok != ',')
5885 break;
5886 next();
5887 c++;
5888 /* NOTE: we accept a trailing comma */
5889 if (tok == '}')
5890 break;
5892 skip('}');
5893 } else {
5894 maxalign = 1;
5895 ps = &s->next;
5896 bit_pos = 0;
5897 offset = 0;
5898 while (tok != '}') {
5899 parse_btype(&btype, &ad);
5900 while (1) {
5901 bit_size = -1;
5902 v = 0;
5903 type1 = btype;
5904 if (tok != ':') {
5905 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5906 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5907 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
5908 error("invalid type for '%s'",
5909 get_tok_str(v, NULL));
5911 if (tok == ':') {
5912 next();
5913 bit_size = expr_const();
5914 /* XXX: handle v = 0 case for messages */
5915 if (bit_size < 0)
5916 error("negative width in bit-field '%s'",
5917 get_tok_str(v, NULL));
5918 if (v && bit_size == 0)
5919 error("zero width for bit-field '%s'",
5920 get_tok_str(v, NULL));
5922 size = type_size(&type1, &align);
5923 lbit_pos = 0;
5924 if (bit_size >= 0) {
5925 bt = type1.t & VT_BTYPE;
5926 if (bt != VT_INT &&
5927 bt != VT_BYTE &&
5928 bt != VT_SHORT &&
5929 bt != VT_ENUM)
5930 error("bitfields must have scalar type");
5931 bsize = size * 8;
5932 if (bit_size > bsize) {
5933 error("width of '%s' exceeds its type",
5934 get_tok_str(v, NULL));
5935 } else if (bit_size == bsize) {
5936 /* no need for bit fields */
5937 bit_pos = 0;
5938 } else if (bit_size == 0) {
5939 /* XXX: what to do if only padding in a
5940 structure ? */
5941 /* zero size: means to pad */
5942 if (bit_pos > 0)
5943 bit_pos = bsize;
5944 } else {
5945 /* we do not have enough room ? */
5946 if ((bit_pos + bit_size) > bsize)
5947 bit_pos = 0;
5948 lbit_pos = bit_pos;
5949 /* XXX: handle LSB first */
5950 type1.t |= VT_BITFIELD |
5951 (bit_pos << VT_STRUCT_SHIFT) |
5952 (bit_size << (VT_STRUCT_SHIFT + 6));
5953 bit_pos += bit_size;
5955 } else {
5956 bit_pos = 0;
5958 if (v) {
5959 /* add new memory data only if starting
5960 bit field */
5961 if (lbit_pos == 0) {
5962 if (a == TOK_STRUCT) {
5963 c = (c + align - 1) & -align;
5964 offset = c;
5965 c += size;
5966 } else {
5967 offset = 0;
5968 if (size > c)
5969 c = size;
5971 if (align > maxalign)
5972 maxalign = align;
5974 #if 0
5975 printf("add field %s offset=%d",
5976 get_tok_str(v, NULL), offset);
5977 if (type1.t & VT_BITFIELD) {
5978 printf(" pos=%d size=%d",
5979 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
5980 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
5982 printf("\n");
5983 #endif
5984 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
5985 *ps = ss;
5986 ps = &ss->next;
5988 if (tok == ';' || tok == TOK_EOF)
5989 break;
5990 skip(',');
5992 skip(';');
5994 skip('}');
5995 /* store size and alignment */
5996 s->c = (c + maxalign - 1) & -maxalign;
5997 s->r = maxalign;
6002 /* return 0 if no type declaration. otherwise, return the basic type
6003 and skip it.
6005 static int parse_btype(CType *type, AttributeDef *ad)
6007 int t, u, type_found;
6008 Sym *s;
6009 CType type1;
6011 memset(ad, 0, sizeof(AttributeDef));
6012 type_found = 0;
6013 t = 0;
6014 while(1) {
6015 switch(tok) {
6016 case TOK_EXTENSION:
6017 /* currently, we really ignore extension */
6018 next();
6019 continue;
6021 /* basic types */
6022 case TOK_CHAR:
6023 u = VT_BYTE;
6024 basic_type:
6025 next();
6026 basic_type1:
6027 if ((t & VT_BTYPE) != 0)
6028 error("too many basic types");
6029 t |= u;
6030 break;
6031 case TOK_VOID:
6032 u = VT_VOID;
6033 goto basic_type;
6034 case TOK_SHORT:
6035 u = VT_SHORT;
6036 goto basic_type;
6037 case TOK_INT:
6038 next();
6039 break;
6040 case TOK_LONG:
6041 next();
6042 if ((t & VT_BTYPE) == VT_DOUBLE) {
6043 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6044 } else if ((t & VT_BTYPE) == VT_LONG) {
6045 t = (t & ~VT_BTYPE) | VT_LLONG;
6046 } else {
6047 u = VT_LONG;
6048 goto basic_type1;
6050 break;
6051 case TOK_BOOL:
6052 u = VT_BOOL;
6053 goto basic_type;
6054 case TOK_FLOAT:
6055 u = VT_FLOAT;
6056 goto basic_type;
6057 case TOK_DOUBLE:
6058 next();
6059 if ((t & VT_BTYPE) == VT_LONG) {
6060 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6061 } else {
6062 u = VT_DOUBLE;
6063 goto basic_type1;
6065 break;
6066 case TOK_ENUM:
6067 struct_decl(&type1, VT_ENUM);
6068 basic_type2:
6069 u = type1.t;
6070 type->ref = type1.ref;
6071 goto basic_type1;
6072 case TOK_STRUCT:
6073 case TOK_UNION:
6074 struct_decl(&type1, VT_STRUCT);
6075 goto basic_type2;
6077 /* type modifiers */
6078 case TOK_CONST1:
6079 case TOK_CONST2:
6080 case TOK_CONST3:
6081 case TOK_VOLATILE1:
6082 case TOK_VOLATILE2:
6083 case TOK_VOLATILE3:
6084 case TOK_REGISTER:
6085 case TOK_SIGNED1:
6086 case TOK_SIGNED2:
6087 case TOK_SIGNED3:
6088 case TOK_AUTO:
6089 case TOK_RESTRICT1:
6090 case TOK_RESTRICT2:
6091 case TOK_RESTRICT3:
6092 next();
6093 break;
6094 case TOK_UNSIGNED:
6095 t |= VT_UNSIGNED;
6096 next();
6097 break;
6099 /* storage */
6100 case TOK_EXTERN:
6101 t |= VT_EXTERN;
6102 next();
6103 break;
6104 case TOK_STATIC:
6105 t |= VT_STATIC;
6106 next();
6107 break;
6108 case TOK_TYPEDEF:
6109 t |= VT_TYPEDEF;
6110 next();
6111 break;
6112 case TOK_INLINE1:
6113 case TOK_INLINE2:
6114 case TOK_INLINE3:
6115 t |= VT_INLINE;
6116 next();
6117 break;
6119 /* GNUC attribute */
6120 case TOK_ATTRIBUTE1:
6121 case TOK_ATTRIBUTE2:
6122 parse_attribute(ad);
6123 break;
6124 /* GNUC typeof */
6125 case TOK_TYPEOF1:
6126 case TOK_TYPEOF2:
6127 case TOK_TYPEOF3:
6128 next();
6129 parse_expr_type(&type1);
6130 goto basic_type2;
6131 default:
6132 s = sym_find(tok);
6133 if (!s || !(s->type.t & VT_TYPEDEF))
6134 goto the_end;
6135 t |= (s->type.t & ~VT_TYPEDEF);
6136 type->ref = s->type.ref;
6137 next();
6138 break;
6140 type_found = 1;
6142 the_end:
6143 /* long is never used as type */
6144 if ((t & VT_BTYPE) == VT_LONG)
6145 t = (t & ~VT_BTYPE) | VT_INT;
6146 type->t = t;
6147 return type_found;
6150 static void post_type(CType *type, AttributeDef *ad)
6152 int n, l, t1;
6153 Sym **plast, *s, *first;
6154 AttributeDef ad1;
6155 CType pt;
6157 if (tok == '(') {
6158 /* function declaration */
6159 next();
6160 l = 0;
6161 first = NULL;
6162 plast = &first;
6163 while (tok != ')') {
6164 /* read param name and compute offset */
6165 if (l != FUNC_OLD) {
6166 if (!parse_btype(&pt, &ad1)) {
6167 if (l) {
6168 error("invalid type");
6169 } else {
6170 l = FUNC_OLD;
6171 goto old_proto;
6174 l = FUNC_NEW;
6175 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6176 break;
6177 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6178 if ((pt.t & VT_BTYPE) == VT_VOID)
6179 error("parameter declared as void");
6180 } else {
6181 old_proto:
6182 n = tok;
6183 pt.t = VT_INT;
6184 next();
6186 /* array must be transformed to pointer according to ANSI C */
6187 pt.t &= ~VT_ARRAY;
6188 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6189 *plast = s;
6190 plast = &s->next;
6191 if (tok == ',') {
6192 next();
6193 if (l == FUNC_NEW && tok == TOK_DOTS) {
6194 l = FUNC_ELLIPSIS;
6195 next();
6196 break;
6200 /* if no parameters, then old type prototype */
6201 if (l == 0)
6202 l = FUNC_OLD;
6203 skip(')');
6204 t1 = type->t & VT_STORAGE;
6205 type->t &= ~VT_STORAGE;
6206 post_type(type, ad);
6207 /* we push a anonymous symbol which will contain the function prototype */
6208 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6209 s->next = first;
6210 type->t = t1 | VT_FUNC;
6211 type->ref = s;
6212 } else if (tok == '[') {
6213 /* array definition */
6214 next();
6215 n = -1;
6216 if (tok != ']') {
6217 n = expr_const();
6218 if (n < 0)
6219 error("invalid array size");
6221 skip(']');
6222 /* parse next post type */
6223 t1 = type->t & VT_STORAGE;
6224 type->t &= ~VT_STORAGE;
6225 post_type(type, ad);
6227 /* we push a anonymous symbol which will contain the array
6228 element type */
6229 s = sym_push(SYM_FIELD, type, 0, n);
6230 type->t = t1 | VT_ARRAY | VT_PTR;
6231 type->ref = s;
6235 /* Parse a type declaration (except basic type), and return the type
6236 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6237 expected. 'type' should contain the basic type. 'ad' is the
6238 attribute definition of the basic type. It can be modified by
6239 type_decl().
6241 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6243 Sym *s;
6244 CType type1, *type2;
6246 while (tok == '*') {
6247 next();
6248 redo:
6249 switch(tok) {
6250 case TOK_CONST1:
6251 case TOK_CONST2:
6252 case TOK_CONST3:
6253 case TOK_VOLATILE1:
6254 case TOK_VOLATILE2:
6255 case TOK_VOLATILE3:
6256 case TOK_RESTRICT1:
6257 case TOK_RESTRICT2:
6258 case TOK_RESTRICT3:
6259 next();
6260 goto redo;
6262 mk_pointer(type);
6265 /* XXX: clarify attribute handling */
6266 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6267 parse_attribute(ad);
6269 /* recursive type */
6270 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6271 type1.t = 0; /* XXX: same as int */
6272 if (tok == '(') {
6273 next();
6274 /* XXX: this is not correct to modify 'ad' at this point, but
6275 the syntax is not clear */
6276 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6277 parse_attribute(ad);
6278 type_decl(&type1, ad, v, td);
6279 skip(')');
6280 } else {
6281 /* type identifier */
6282 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6283 *v = tok;
6284 next();
6285 } else {
6286 if (!(td & TYPE_ABSTRACT))
6287 expect("identifier");
6288 *v = 0;
6291 post_type(type, ad);
6292 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6293 parse_attribute(ad);
6294 if (!type1.t)
6295 return;
6296 /* append type at the end of type1 */
6297 type2 = &type1;
6298 for(;;) {
6299 s = type2->ref;
6300 type2 = &s->type;
6301 if (!type2->t) {
6302 *type2 = *type;
6303 break;
6306 *type = type1;
6309 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6310 static int lvalue_type(int t)
6312 int bt, r;
6313 r = VT_LVAL;
6314 bt = t & VT_BTYPE;
6315 if (bt == VT_BYTE)
6316 r |= VT_LVAL_BYTE;
6317 else if (bt == VT_SHORT)
6318 r |= VT_LVAL_SHORT;
6319 else
6320 return r;
6321 if (t & VT_UNSIGNED)
6322 r |= VT_LVAL_UNSIGNED;
6323 return r;
6326 /* indirection with full error checking and bound check */
6327 static void indir(void)
6329 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6330 expect("pointer");
6331 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6332 gv(RC_INT);
6333 vtop->type = *pointed_type(&vtop->type);
6334 /* an array is never an lvalue */
6335 if (!(vtop->type.t & VT_ARRAY)) {
6336 vtop->r |= lvalue_type(vtop->type.t);
6337 /* if bound checking, the referenced pointer must be checked */
6338 if (do_bounds_check)
6339 vtop->r |= VT_MUSTBOUND;
6343 /* pass a parameter to a function and do type checking and casting */
6344 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
6346 int func_type;
6347 CType type;
6349 func_type = func->c;
6350 if (func_type == FUNC_OLD ||
6351 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6352 /* default casting : only need to convert float to double */
6353 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6354 type.t = VT_DOUBLE;
6355 gen_cast(&type);
6357 } else if (arg == NULL) {
6358 error("too many arguments to function");
6359 } else {
6360 gen_assign_cast(&arg->type);
6362 if (!nocode_wanted) {
6363 gfunc_param(gf);
6364 } else {
6365 vpop();
6369 /* parse an expression of the form '(type)' or '(expr)' and return its
6370 type */
6371 static void parse_expr_type(CType *type)
6373 int n;
6374 AttributeDef ad;
6376 skip('(');
6377 if (parse_btype(type, &ad)) {
6378 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6379 } else {
6380 expr_type(type);
6382 skip(')');
6385 static void vpush_tokc(int t)
6387 CType type;
6388 type.t = t;
6389 vsetc(&type, VT_CONST, &tokc);
6392 static void unary(void)
6394 int n, t, align, size, r;
6395 CType type;
6396 Sym *s;
6397 GFuncContext gf;
6398 AttributeDef ad;
6400 /* XXX: GCC 2.95.3 does not generate a table although it should be
6401 better here */
6402 tok_next:
6403 switch(tok) {
6404 case TOK_EXTENSION:
6405 next();
6406 goto tok_next;
6407 case TOK_CINT:
6408 case TOK_CCHAR:
6409 case TOK_LCHAR:
6410 vpushi(tokc.i);
6411 next();
6412 break;
6413 case TOK_CUINT:
6414 vpush_tokc(VT_INT | VT_UNSIGNED);
6415 next();
6416 break;
6417 case TOK_CLLONG:
6418 vpush_tokc(VT_LLONG);
6419 next();
6420 break;
6421 case TOK_CULLONG:
6422 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6423 next();
6424 break;
6425 case TOK_CFLOAT:
6426 vpush_tokc(VT_FLOAT);
6427 next();
6428 break;
6429 case TOK_CDOUBLE:
6430 vpush_tokc(VT_DOUBLE);
6431 next();
6432 break;
6433 case TOK_CLDOUBLE:
6434 vpush_tokc(VT_LDOUBLE);
6435 next();
6436 break;
6437 case TOK___FUNCTION__:
6438 if (!gnu_ext)
6439 goto tok_identifier;
6440 /* fall thru */
6441 case TOK___FUNC__:
6443 void *ptr;
6444 int len;
6445 /* special function name identifier */
6446 len = strlen(funcname) + 1;
6447 /* generate char[len] type */
6448 type.t = VT_BYTE;
6449 mk_pointer(&type);
6450 type.t |= VT_ARRAY;
6451 type.ref->c = len;
6452 vpush_ref(&type, data_section, data_section->data_offset, len);
6453 ptr = section_ptr_add(data_section, len);
6454 memcpy(ptr, funcname, len);
6455 next();
6457 break;
6458 case TOK_LSTR:
6459 t = VT_INT;
6460 goto str_init;
6461 case TOK_STR:
6462 /* string parsing */
6463 t = VT_BYTE;
6464 str_init:
6465 type.t = t;
6466 mk_pointer(&type);
6467 type.t |= VT_ARRAY;
6468 memset(&ad, 0, sizeof(AttributeDef));
6469 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6470 break;
6471 case '(':
6472 next();
6473 /* cast ? */
6474 if (parse_btype(&type, &ad)) {
6475 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6476 skip(')');
6477 /* check ISOC99 compound literal */
6478 if (tok == '{') {
6479 /* data is allocated locally by default */
6480 if (global_expr)
6481 r = VT_CONST;
6482 else
6483 r = VT_LOCAL;
6484 /* all except arrays are lvalues */
6485 if (!(type.t & VT_ARRAY))
6486 r |= lvalue_type(type.t);
6487 memset(&ad, 0, sizeof(AttributeDef));
6488 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6489 } else {
6490 unary();
6491 gen_cast(&type);
6493 } else if (tok == '{') {
6494 /* save all registers */
6495 save_regs(0);
6496 /* statement expression : we do not accept break/continue
6497 inside as GCC does */
6498 block(NULL, NULL, NULL, NULL, 0, 1);
6499 skip(')');
6500 } else {
6501 gexpr();
6502 skip(')');
6504 break;
6505 case '*':
6506 next();
6507 unary();
6508 indir();
6509 break;
6510 case '&':
6511 next();
6512 unary();
6513 /* functions names must be treated as function pointers,
6514 except for unary '&' and sizeof. Since we consider that
6515 functions are not lvalues, we only have to handle it
6516 there and in function calls. */
6517 /* arrays can also be used although they are not lvalues */
6518 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6519 !(vtop->type.t & VT_ARRAY))
6520 test_lvalue();
6521 mk_pointer(&vtop->type);
6522 gaddrof();
6523 break;
6524 case '!':
6525 next();
6526 unary();
6527 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6528 vtop->c.i = !vtop->c.i;
6529 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6530 vtop->c.i = vtop->c.i ^ 1;
6531 else
6532 vseti(VT_JMP, gtst(1, 0));
6533 break;
6534 case '~':
6535 next();
6536 unary();
6537 vpushi(-1);
6538 gen_op('^');
6539 break;
6540 case '+':
6541 next();
6542 /* in order to force cast, we add zero */
6543 unary();
6544 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6545 error("pointer not accepted for unary plus");
6546 vpushi(0);
6547 gen_op('+');
6548 break;
6549 case TOK_SIZEOF:
6550 case TOK_ALIGNOF1:
6551 case TOK_ALIGNOF2:
6552 t = tok;
6553 next();
6554 if (tok == '(') {
6555 parse_expr_type(&type);
6556 } else {
6557 unary_type(&type);
6559 size = type_size(&type, &align);
6560 if (t == TOK_SIZEOF)
6561 vpushi(size);
6562 else
6563 vpushi(align);
6564 break;
6566 case TOK_INC:
6567 case TOK_DEC:
6568 t = tok;
6569 next();
6570 unary();
6571 inc(0, t);
6572 break;
6573 case '-':
6574 next();
6575 vpushi(0);
6576 unary();
6577 gen_op('-');
6578 break;
6579 case TOK_LAND:
6580 if (!gnu_ext)
6581 goto tok_identifier;
6582 next();
6583 /* allow to take the address of a label */
6584 if (tok < TOK_UIDENT)
6585 expect("label identifier");
6586 s = label_find(tok);
6587 if (!s) {
6588 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6589 } else {
6590 if (s->r == LABEL_DECLARED)
6591 s->r = LABEL_FORWARD;
6593 if (!s->type.t) {
6594 s->type.t = VT_VOID;
6595 mk_pointer(&s->type);
6596 s->type.t |= VT_STATIC;
6598 vset(&s->type, VT_CONST | VT_SYM, 0);
6599 vtop->sym = s;
6600 next();
6601 break;
6602 default:
6603 tok_identifier:
6604 t = tok;
6605 next();
6606 if (t < TOK_UIDENT)
6607 expect("identifier");
6608 s = sym_find(t);
6609 if (!s) {
6610 if (tok != '(')
6611 error("'%s' undeclared", get_tok_str(t, NULL));
6612 /* for simple function calls, we tolerate undeclared
6613 external reference to int() function */
6614 s = external_global_sym(t, &func_old_type, 0);
6616 vset(&s->type, s->r, s->c);
6617 /* if forward reference, we must point to s */
6618 if (vtop->r & VT_SYM) {
6619 vtop->sym = s;
6620 vtop->c.ul = 0;
6622 break;
6625 /* post operations */
6626 while (1) {
6627 if (tok == TOK_INC || tok == TOK_DEC) {
6628 inc(1, tok);
6629 next();
6630 } else if (tok == '.' || tok == TOK_ARROW) {
6631 /* field */
6632 if (tok == TOK_ARROW)
6633 indir();
6634 test_lvalue();
6635 gaddrof();
6636 next();
6637 /* expect pointer on structure */
6638 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6639 expect("struct or union");
6640 s = vtop->type.ref;
6641 /* find field */
6642 tok |= SYM_FIELD;
6643 while ((s = s->next) != NULL) {
6644 if (s->v == tok)
6645 break;
6647 if (!s)
6648 error("field not found");
6649 /* add field offset to pointer */
6650 vtop->type = char_pointer_type; /* change type to 'char *' */
6651 vpushi(s->c);
6652 gen_op('+');
6653 /* change type to field type, and set to lvalue */
6654 vtop->type = s->type;
6655 /* an array is never an lvalue */
6656 if (!(vtop->type.t & VT_ARRAY)) {
6657 vtop->r |= lvalue_type(vtop->type.t);
6658 /* if bound checking, the referenced pointer must be checked */
6659 if (do_bounds_check)
6660 vtop->r |= VT_MUSTBOUND;
6662 next();
6663 } else if (tok == '[') {
6664 next();
6665 gexpr();
6666 gen_op('+');
6667 indir();
6668 skip(']');
6669 } else if (tok == '(') {
6670 SValue ret;
6671 Sym *sa;
6673 /* function call */
6674 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6675 /* pointer test (no array accepted) */
6676 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6677 vtop->type = *pointed_type(&vtop->type);
6678 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6679 goto error_func;
6680 } else {
6681 error_func:
6682 expect("function pointer");
6684 } else {
6685 vtop->r &= ~VT_LVAL; /* no lvalue */
6687 /* get return type */
6688 s = vtop->type.ref;
6689 if (!nocode_wanted) {
6690 save_regs(0); /* save used temporary registers */
6691 gfunc_start(&gf, s->r);
6693 next();
6694 sa = s->next; /* first parameter */
6695 #ifdef INVERT_FUNC_PARAMS
6697 int parlevel;
6698 Sym *args, *s1;
6699 ParseState saved_parse_state;
6700 TokenString str;
6702 /* read each argument and store it on a stack */
6703 args = NULL;
6704 if (tok != ')') {
6705 for(;;) {
6706 tok_str_new(&str);
6707 parlevel = 0;
6708 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6709 tok != TOK_EOF) {
6710 if (tok == '(')
6711 parlevel++;
6712 else if (tok == ')')
6713 parlevel--;
6714 tok_str_add_tok(&str);
6715 next();
6717 tok_str_add(&str, -1); /* end of file added */
6718 tok_str_add(&str, 0);
6719 s1 = sym_push2(&args, 0, 0, (int)str.str);
6720 s1->next = sa; /* add reference to argument */
6721 if (sa)
6722 sa = sa->next;
6723 if (tok == ')')
6724 break;
6725 skip(',');
6729 /* now generate code in reverse order by reading the stack */
6730 save_parse_state(&saved_parse_state);
6731 while (args) {
6732 macro_ptr = (int *)args->c;
6733 next();
6734 expr_eq();
6735 if (tok != -1)
6736 expect("',' or ')'");
6737 gfunc_param_typed(&gf, s, args->next);
6738 s1 = args->prev;
6739 tok_str_free((int *)args->c);
6740 tcc_free(args);
6741 args = s1;
6743 restore_parse_state(&saved_parse_state);
6745 #endif
6746 /* compute first implicit argument if a structure is returned */
6747 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6748 /* get some space for the returned structure */
6749 size = type_size(&s->type, &align);
6750 loc = (loc - size) & -align;
6751 ret.type = s->type;
6752 ret.r = VT_LOCAL | VT_LVAL;
6753 /* pass it as 'int' to avoid structure arg passing
6754 problems */
6755 vseti(VT_LOCAL, loc);
6756 ret.c = vtop->c;
6757 if (!nocode_wanted)
6758 gfunc_param(&gf);
6759 else
6760 vtop--;
6761 } else {
6762 ret.type = s->type;
6763 ret.r2 = VT_CONST;
6764 /* return in register */
6765 if (is_float(ret.type.t)) {
6766 ret.r = REG_FRET;
6767 } else {
6768 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6769 ret.r2 = REG_LRET;
6770 ret.r = REG_IRET;
6772 ret.c.i = 0;
6774 #ifndef INVERT_FUNC_PARAMS
6775 if (tok != ')') {
6776 for(;;) {
6777 expr_eq();
6778 gfunc_param_typed(&gf, s, sa);
6779 if (sa)
6780 sa = sa->next;
6781 if (tok == ')')
6782 break;
6783 skip(',');
6786 #endif
6787 if (sa)
6788 error("too few arguments to function");
6789 skip(')');
6790 if (!nocode_wanted)
6791 gfunc_call(&gf);
6792 else
6793 vtop--;
6794 /* return value */
6795 vsetc(&ret.type, ret.r, &ret.c);
6796 vtop->r2 = ret.r2;
6797 } else {
6798 break;
6803 static void uneq(void)
6805 int t;
6807 unary();
6808 if (tok == '=' ||
6809 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6810 tok == TOK_A_XOR || tok == TOK_A_OR ||
6811 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6812 test_lvalue();
6813 t = tok;
6814 next();
6815 if (t == '=') {
6816 expr_eq();
6817 } else {
6818 vdup();
6819 expr_eq();
6820 gen_op(t & 0x7f);
6822 vstore();
6826 static void expr_prod(void)
6828 int t;
6830 uneq();
6831 while (tok == '*' || tok == '/' || tok == '%') {
6832 t = tok;
6833 next();
6834 uneq();
6835 gen_op(t);
6839 static void expr_sum(void)
6841 int t;
6843 expr_prod();
6844 while (tok == '+' || tok == '-') {
6845 t = tok;
6846 next();
6847 expr_prod();
6848 gen_op(t);
6852 static void expr_shift(void)
6854 int t;
6856 expr_sum();
6857 while (tok == TOK_SHL || tok == TOK_SAR) {
6858 t = tok;
6859 next();
6860 expr_sum();
6861 gen_op(t);
6865 static void expr_cmp(void)
6867 int t;
6869 expr_shift();
6870 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
6871 tok == TOK_ULT || tok == TOK_UGE) {
6872 t = tok;
6873 next();
6874 expr_shift();
6875 gen_op(t);
6879 static void expr_cmpeq(void)
6881 int t;
6883 expr_cmp();
6884 while (tok == TOK_EQ || tok == TOK_NE) {
6885 t = tok;
6886 next();
6887 expr_cmp();
6888 gen_op(t);
6892 static void expr_and(void)
6894 expr_cmpeq();
6895 while (tok == '&') {
6896 next();
6897 expr_cmpeq();
6898 gen_op('&');
6902 static void expr_xor(void)
6904 expr_and();
6905 while (tok == '^') {
6906 next();
6907 expr_and();
6908 gen_op('^');
6912 static void expr_or(void)
6914 expr_xor();
6915 while (tok == '|') {
6916 next();
6917 expr_xor();
6918 gen_op('|');
6922 /* XXX: suppress this mess */
6923 static void expr_land_const(void)
6925 expr_or();
6926 while (tok == TOK_LAND) {
6927 next();
6928 expr_or();
6929 gen_op(TOK_LAND);
6933 /* XXX: suppress this mess */
6934 static void expr_lor_const(void)
6936 expr_land_const();
6937 while (tok == TOK_LOR) {
6938 next();
6939 expr_land_const();
6940 gen_op(TOK_LOR);
6944 /* only used if non constant */
6945 static void expr_land(void)
6947 int t;
6949 expr_or();
6950 if (tok == TOK_LAND) {
6951 t = 0;
6952 for(;;) {
6953 t = gtst(1, t);
6954 if (tok != TOK_LAND) {
6955 vseti(VT_JMPI, t);
6956 break;
6958 next();
6959 expr_or();
6964 static void expr_lor(void)
6966 int t;
6968 expr_land();
6969 if (tok == TOK_LOR) {
6970 t = 0;
6971 for(;;) {
6972 t = gtst(0, t);
6973 if (tok != TOK_LOR) {
6974 vseti(VT_JMP, t);
6975 break;
6977 next();
6978 expr_land();
6983 /* XXX: better constant handling */
6984 static void expr_eq(void)
6986 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
6987 SValue sv;
6988 CType type, type1, type2;
6990 if (const_wanted) {
6991 int c1, c;
6992 expr_lor_const();
6993 if (tok == '?') {
6994 c = vtop->c.i;
6995 vpop();
6996 next();
6997 if (tok == ':' && gnu_ext) {
6998 c1 = c;
6999 } else {
7000 gexpr();
7001 c1 = vtop->c.i;
7002 vpop();
7004 skip(':');
7005 expr_eq();
7006 if (c)
7007 vtop->c.i = c1;
7009 } else {
7010 expr_lor();
7011 if (tok == '?') {
7012 next();
7013 if (vtop != vstack) {
7014 /* needed to avoid having different registers saved in
7015 each branch */
7016 if (is_float(vtop->type.t))
7017 rc = RC_FLOAT;
7018 else
7019 rc = RC_INT;
7020 gv(rc);
7021 save_regs(1);
7023 if (tok == ':' && gnu_ext) {
7024 gv_dup();
7025 tt = gtst(1, 0);
7026 } else {
7027 tt = gtst(1, 0);
7028 gexpr();
7030 type1 = vtop->type;
7031 sv = *vtop; /* save value to handle it later */
7032 vtop--; /* no vpop so that FP stack is not flushed */
7033 skip(':');
7034 u = gjmp(0);
7035 gsym(tt);
7036 expr_eq();
7037 type2 = vtop->type;
7039 t1 = type1.t;
7040 bt1 = t1 & VT_BTYPE;
7041 t2 = type2.t;
7042 bt2 = t2 & VT_BTYPE;
7043 /* cast operands to correct type according to ISOC rules */
7044 if (is_float(bt1) || is_float(bt2)) {
7045 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7046 type.t = VT_LDOUBLE;
7047 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7048 type.t = VT_DOUBLE;
7049 } else {
7050 type.t = VT_FLOAT;
7052 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7053 /* cast to biggest op */
7054 type.t = VT_LLONG;
7055 /* convert to unsigned if it does not fit in a long long */
7056 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7057 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7058 type.t |= VT_UNSIGNED;
7059 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7060 /* XXX: test pointer compatibility */
7061 type = type1;
7062 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7063 /* XXX: test structure compatibility */
7064 type = type1;
7065 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7066 /* NOTE: as an extension, we accept void on only one side */
7067 type.t = VT_VOID;
7068 } else {
7069 /* integer operations */
7070 type.t = VT_INT;
7071 /* convert to unsigned if it does not fit in an integer */
7072 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7073 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7074 type.t |= VT_UNSIGNED;
7077 /* now we convert second operand */
7078 gen_cast(&type);
7079 rc = RC_INT;
7080 if (is_float(type.t)) {
7081 rc = RC_FLOAT;
7082 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7083 /* for long longs, we use fixed registers to avoid having
7084 to handle a complicated move */
7085 rc = RC_IRET;
7088 r2 = gv(rc);
7089 /* this is horrible, but we must also convert first
7090 operand */
7091 tt = gjmp(0);
7092 gsym(u);
7093 /* put again first value and cast it */
7094 *vtop = sv;
7095 gen_cast(&type);
7096 r1 = gv(rc);
7097 move_reg(r2, r1);
7098 vtop->r = r2;
7099 gsym(tt);
7104 static void gexpr(void)
7106 while (1) {
7107 expr_eq();
7108 if (tok != ',')
7109 break;
7110 vpop();
7111 next();
7115 /* parse an expression and return its type without any side effect. */
7116 static void expr_type(CType *type)
7118 int a;
7120 a = nocode_wanted;
7121 nocode_wanted = 1;
7122 gexpr();
7123 *type = vtop->type;
7124 vpop();
7125 nocode_wanted = a;
7128 /* parse a unary expression and return its type without any side
7129 effect. */
7130 static void unary_type(CType *type)
7132 int a;
7134 a = nocode_wanted;
7135 nocode_wanted = 1;
7136 unary();
7137 *type = vtop->type;
7138 vpop();
7139 nocode_wanted = a;
7142 /* parse a constant expression and return value in vtop. */
7143 static void expr_const1(void)
7145 int a;
7146 a = const_wanted;
7147 const_wanted = 1;
7148 expr_eq();
7149 const_wanted = a;
7152 /* parse an integer constant and return its value. */
7153 static int expr_const(void)
7155 int c;
7156 expr_const1();
7157 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7158 expect("constant expression");
7159 c = vtop->c.i;
7160 vpop();
7161 return c;
7164 /* return the label token if current token is a label, otherwise
7165 return zero */
7166 static int is_label(void)
7168 int last_tok;
7170 /* fast test first */
7171 if (tok < TOK_UIDENT)
7172 return 0;
7173 /* no need to save tokc because tok is an identifier */
7174 last_tok = tok;
7175 next();
7176 if (tok == ':') {
7177 next();
7178 return last_tok;
7179 } else {
7180 unget_tok(last_tok);
7181 return 0;
7185 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7186 int case_reg, int is_expr)
7188 int a, b, c, d;
7189 Sym *s;
7191 /* generate line number info */
7192 if (do_debug &&
7193 (last_line_num != file->line_num || last_ind != ind)) {
7194 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7195 last_ind = ind;
7196 last_line_num = file->line_num;
7199 if (is_expr) {
7200 /* default return value is (void) */
7201 vpushi(0);
7202 vtop->type.t = VT_VOID;
7205 if (tok == TOK_IF) {
7206 /* if test */
7207 next();
7208 skip('(');
7209 gexpr();
7210 skip(')');
7211 a = gtst(1, 0);
7212 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7213 c = tok;
7214 if (c == TOK_ELSE) {
7215 next();
7216 d = gjmp(0);
7217 gsym(a);
7218 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7219 gsym(d); /* patch else jmp */
7220 } else
7221 gsym(a);
7222 } else if (tok == TOK_WHILE) {
7223 next();
7224 d = ind;
7225 skip('(');
7226 gexpr();
7227 skip(')');
7228 a = gtst(1, 0);
7229 b = 0;
7230 block(&a, &b, case_sym, def_sym, case_reg, 0);
7231 gjmp_addr(d);
7232 gsym(a);
7233 gsym_addr(b, d);
7234 } else if (tok == '{') {
7235 Sym *llabel;
7237 next();
7238 /* record local declaration stack position */
7239 s = local_stack;
7240 llabel = local_label_stack;
7241 /* handle local labels declarations */
7242 if (tok == TOK_LABEL) {
7243 next();
7244 for(;;) {
7245 if (tok < TOK_UIDENT)
7246 expect("label identifier");
7247 label_push(&local_label_stack, tok, LABEL_DECLARED);
7248 next();
7249 if (tok == ',') {
7250 next();
7251 } else {
7252 skip(';');
7253 break;
7257 while (tok != '}') {
7258 decl(VT_LOCAL);
7259 if (tok != '}') {
7260 if (is_expr)
7261 vpop();
7262 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7265 /* pop locally defined labels */
7266 label_pop(&local_label_stack, llabel);
7267 /* pop locally defined symbols */
7268 sym_pop(&local_stack, s);
7269 next();
7270 } else if (tok == TOK_RETURN) {
7271 next();
7272 if (tok != ';') {
7273 gexpr();
7274 gen_assign_cast(&func_vt);
7275 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7276 CType type;
7277 /* if returning structure, must copy it to implicit
7278 first pointer arg location */
7279 type = func_vt;
7280 mk_pointer(&type);
7281 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7282 indir();
7283 vswap();
7284 /* copy structure value to pointer */
7285 vstore();
7286 } else if (is_float(func_vt.t)) {
7287 gv(RC_FRET);
7288 } else {
7289 gv(RC_IRET);
7291 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7293 skip(';');
7294 rsym = gjmp(rsym); /* jmp */
7295 } else if (tok == TOK_BREAK) {
7296 /* compute jump */
7297 if (!bsym)
7298 error("cannot break");
7299 *bsym = gjmp(*bsym);
7300 next();
7301 skip(';');
7302 } else if (tok == TOK_CONTINUE) {
7303 /* compute jump */
7304 if (!csym)
7305 error("cannot continue");
7306 *csym = gjmp(*csym);
7307 next();
7308 skip(';');
7309 } else if (tok == TOK_FOR) {
7310 int e;
7311 next();
7312 skip('(');
7313 if (tok != ';') {
7314 gexpr();
7315 vpop();
7317 skip(';');
7318 d = ind;
7319 c = ind;
7320 a = 0;
7321 b = 0;
7322 if (tok != ';') {
7323 gexpr();
7324 a = gtst(1, 0);
7326 skip(';');
7327 if (tok != ')') {
7328 e = gjmp(0);
7329 c = ind;
7330 gexpr();
7331 vpop();
7332 gjmp_addr(d);
7333 gsym(e);
7335 skip(')');
7336 block(&a, &b, case_sym, def_sym, case_reg, 0);
7337 gjmp_addr(c);
7338 gsym(a);
7339 gsym_addr(b, c);
7340 } else
7341 if (tok == TOK_DO) {
7342 next();
7343 a = 0;
7344 b = 0;
7345 d = ind;
7346 block(&a, &b, case_sym, def_sym, case_reg, 0);
7347 skip(TOK_WHILE);
7348 skip('(');
7349 gsym(b);
7350 gexpr();
7351 c = gtst(0, 0);
7352 gsym_addr(c, d);
7353 skip(')');
7354 gsym(a);
7355 skip(';');
7356 } else
7357 if (tok == TOK_SWITCH) {
7358 next();
7359 skip('(');
7360 gexpr();
7361 /* XXX: other types than integer */
7362 case_reg = gv(RC_INT);
7363 vpop();
7364 skip(')');
7365 a = 0;
7366 b = gjmp(0); /* jump to first case */
7367 c = 0;
7368 block(&a, csym, &b, &c, case_reg, 0);
7369 /* if no default, jmp after switch */
7370 if (c == 0)
7371 c = ind;
7372 /* default label */
7373 gsym_addr(b, c);
7374 /* break label */
7375 gsym(a);
7376 } else
7377 if (tok == TOK_CASE) {
7378 int v1, v2;
7379 if (!case_sym)
7380 expect("switch");
7381 next();
7382 v1 = expr_const();
7383 v2 = v1;
7384 if (gnu_ext && tok == TOK_DOTS) {
7385 next();
7386 v2 = expr_const();
7387 if (v2 < v1)
7388 warning("empty case range");
7390 /* since a case is like a label, we must skip it with a jmp */
7391 b = gjmp(0);
7392 gsym(*case_sym);
7393 vseti(case_reg, 0);
7394 vpushi(v1);
7395 if (v1 == v2) {
7396 gen_op(TOK_EQ);
7397 *case_sym = gtst(1, 0);
7398 } else {
7399 gen_op(TOK_GE);
7400 *case_sym = gtst(1, 0);
7401 vseti(case_reg, 0);
7402 vpushi(v2);
7403 gen_op(TOK_LE);
7404 *case_sym = gtst(1, *case_sym);
7406 gsym(b);
7407 skip(':');
7408 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7409 } else
7410 if (tok == TOK_DEFAULT) {
7411 next();
7412 skip(':');
7413 if (!def_sym)
7414 expect("switch");
7415 if (*def_sym)
7416 error("too many 'default'");
7417 *def_sym = ind;
7418 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7419 } else
7420 if (tok == TOK_GOTO) {
7421 next();
7422 if (tok == '*' && gnu_ext) {
7423 /* computed goto */
7424 next();
7425 gexpr();
7426 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7427 expect("pointer");
7428 ggoto();
7429 } else if (tok >= TOK_UIDENT) {
7430 s = label_find(tok);
7431 /* put forward definition if needed */
7432 if (!s) {
7433 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7434 } else {
7435 if (s->r == LABEL_DECLARED)
7436 s->r = LABEL_FORWARD;
7438 /* label already defined */
7439 if (s->r & LABEL_FORWARD)
7440 s->next = (void *)gjmp((long)s->next);
7441 else
7442 gjmp_addr((long)s->next);
7443 next();
7444 } else {
7445 expect("label identifier");
7447 skip(';');
7448 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7449 asm_instr();
7450 } else {
7451 b = is_label();
7452 if (b) {
7453 /* label case */
7454 s = label_find(b);
7455 if (s) {
7456 if (s->r == LABEL_DEFINED)
7457 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7458 gsym((long)s->next);
7459 s->r = LABEL_DEFINED;
7460 } else {
7461 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7463 s->next = (void *)ind;
7464 /* we accept this, but it is a mistake */
7465 if (tok == '}') {
7466 warning("deprecated use of label at end of compound statement");
7467 } else {
7468 if (is_expr)
7469 vpop();
7470 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7472 } else {
7473 /* expression case */
7474 if (tok != ';') {
7475 if (is_expr) {
7476 vpop();
7477 gexpr();
7478 } else {
7479 gexpr();
7480 vpop();
7483 skip(';');
7488 /* t is the array or struct type. c is the array or struct
7489 address. cur_index/cur_field is the pointer to the current
7490 value. 'size_only' is true if only size info is needed (only used
7491 in arrays) */
7492 static void decl_designator(CType *type, Section *sec, unsigned long c,
7493 int *cur_index, Sym **cur_field,
7494 int size_only)
7496 Sym *s, *f;
7497 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7498 CType type1;
7500 notfirst = 0;
7501 elem_size = 0;
7502 nb_elems = 1;
7503 if (gnu_ext && (l = is_label()) != 0)
7504 goto struct_field;
7505 while (tok == '[' || tok == '.') {
7506 if (tok == '[') {
7507 if (!(type->t & VT_ARRAY))
7508 expect("array type");
7509 s = type->ref;
7510 next();
7511 index = expr_const();
7512 if (index < 0 || (s->c >= 0 && index >= s->c))
7513 expect("invalid index");
7514 if (tok == TOK_DOTS && gnu_ext) {
7515 next();
7516 index_last = expr_const();
7517 if (index_last < 0 ||
7518 (s->c >= 0 && index_last >= s->c) ||
7519 index_last < index)
7520 expect("invalid index");
7521 } else {
7522 index_last = index;
7524 skip(']');
7525 if (!notfirst)
7526 *cur_index = index_last;
7527 type = pointed_type(type);
7528 elem_size = type_size(type, &align);
7529 c += index * elem_size;
7530 /* NOTE: we only support ranges for last designator */
7531 nb_elems = index_last - index + 1;
7532 if (nb_elems != 1) {
7533 notfirst = 1;
7534 break;
7536 } else {
7537 next();
7538 l = tok;
7539 next();
7540 struct_field:
7541 if ((type->t & VT_BTYPE) != VT_STRUCT)
7542 expect("struct/union type");
7543 s = type->ref;
7544 l |= SYM_FIELD;
7545 f = s->next;
7546 while (f) {
7547 if (f->v == l)
7548 break;
7549 f = f->next;
7551 if (!f)
7552 expect("field");
7553 if (!notfirst)
7554 *cur_field = f;
7555 /* XXX: suppress this mess by using explicit storage field */
7556 type1 = f->type;
7557 type1.t |= (type->t & ~VT_TYPE);
7558 type = &type1;
7559 c += f->c;
7561 notfirst = 1;
7563 if (notfirst) {
7564 if (tok == '=') {
7565 next();
7566 } else {
7567 if (!gnu_ext)
7568 expect("=");
7570 } else {
7571 if (type->t & VT_ARRAY) {
7572 index = *cur_index;
7573 type = pointed_type(type);
7574 c += index * type_size(type, &align);
7575 } else {
7576 f = *cur_field;
7577 if (!f)
7578 error("too many field init");
7579 /* XXX: suppress this mess by using explicit storage field */
7580 type1 = f->type;
7581 type1.t |= (type->t & ~VT_TYPE);
7582 type = &type1;
7583 c += f->c;
7586 decl_initializer(type, sec, c, 0, size_only);
7588 /* XXX: make it more general */
7589 if (!size_only && nb_elems > 1) {
7590 unsigned long c_end;
7591 uint8_t *src, *dst;
7592 int i;
7594 if (!sec)
7595 error("range init not supported yet for dynamic storage");
7596 c_end = c + nb_elems * elem_size;
7597 if (c_end > sec->data_allocated)
7598 section_realloc(sec, c_end);
7599 src = sec->data + c;
7600 dst = src;
7601 for(i = 1; i < nb_elems; i++) {
7602 dst += elem_size;
7603 memcpy(dst, src, elem_size);
7608 #define EXPR_VAL 0
7609 #define EXPR_CONST 1
7610 #define EXPR_ANY 2
7612 /* store a value or an expression directly in global data or in local array */
7613 static void init_putv(CType *type, Section *sec, unsigned long c,
7614 int v, int expr_type)
7616 int saved_global_expr, bt, bit_pos, bit_size;
7617 void *ptr;
7618 unsigned long long bit_mask;
7620 switch(expr_type) {
7621 case EXPR_VAL:
7622 vpushi(v);
7623 break;
7624 case EXPR_CONST:
7625 /* compound literals must be allocated globally in this case */
7626 saved_global_expr = global_expr;
7627 global_expr = 1;
7628 expr_const1();
7629 global_expr = saved_global_expr;
7630 /* NOTE: symbols are accepted */
7631 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7632 error("initializer element is not constant");
7633 break;
7634 case EXPR_ANY:
7635 expr_eq();
7636 break;
7639 if (sec) {
7640 /* XXX: not portable */
7641 /* XXX: generate error if incorrect relocation */
7642 gen_assign_cast(type);
7643 bt = type->t & VT_BTYPE;
7644 ptr = sec->data + c;
7645 /* XXX: make code faster ? */
7646 if (!(type->t & VT_BITFIELD)) {
7647 bit_pos = 0;
7648 bit_size = 32;
7649 bit_mask = -1LL;
7650 } else {
7651 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7652 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7653 bit_mask = (1LL << bit_size) - 1;
7655 if ((vtop->r & VT_SYM) &&
7656 (bt == VT_BYTE ||
7657 bt == VT_SHORT ||
7658 bt == VT_DOUBLE ||
7659 bt == VT_LDOUBLE ||
7660 bt == VT_LLONG ||
7661 (bt == VT_INT && bit_size != 32)))
7662 error("initializer element is not computable at load time");
7663 switch(bt) {
7664 case VT_BYTE:
7665 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7666 break;
7667 case VT_SHORT:
7668 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7669 break;
7670 case VT_DOUBLE:
7671 *(double *)ptr = vtop->c.d;
7672 break;
7673 case VT_LDOUBLE:
7674 *(long double *)ptr = vtop->c.ld;
7675 break;
7676 case VT_LLONG:
7677 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7678 break;
7679 default:
7680 if (vtop->r & VT_SYM) {
7681 greloc(sec, vtop->sym, c, R_DATA_32);
7683 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7684 break;
7686 vtop--;
7687 } else {
7688 vset(type, VT_LOCAL, c);
7689 vswap();
7690 vstore();
7691 vpop();
7695 /* put zeros for variable based init */
7696 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7698 GFuncContext gf;
7700 if (sec) {
7701 /* nothing to do because globals are already set to zero */
7702 } else {
7703 gfunc_start(&gf, FUNC_CDECL);
7704 vpushi(size);
7705 gfunc_param(&gf);
7706 vpushi(0);
7707 gfunc_param(&gf);
7708 vseti(VT_LOCAL, c);
7709 gfunc_param(&gf);
7710 vpush_global_sym(&func_old_type, TOK_memset);
7711 gfunc_call(&gf);
7715 /* 't' contains the type and storage info. 'c' is the offset of the
7716 object in section 'sec'. If 'sec' is NULL, it means stack based
7717 allocation. 'first' is true if array '{' must be read (multi
7718 dimension implicit array init handling). 'size_only' is true if
7719 size only evaluation is wanted (only for arrays). */
7720 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7721 int first, int size_only)
7723 int index, array_length, n, no_oblock, nb, parlevel, i;
7724 int size1, align1, expr_type;
7725 Sym *s, *f;
7726 CType *t1;
7728 if (type->t & VT_ARRAY) {
7729 s = type->ref;
7730 n = s->c;
7731 array_length = 0;
7732 t1 = pointed_type(type);
7733 size1 = type_size(t1, &align1);
7735 no_oblock = 1;
7736 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7737 tok == '{') {
7738 skip('{');
7739 no_oblock = 0;
7742 /* only parse strings here if correct type (otherwise: handle
7743 them as ((w)char *) expressions */
7744 if ((tok == TOK_LSTR &&
7745 (t1->t & VT_BTYPE) == VT_INT) ||
7746 (tok == TOK_STR &&
7747 (t1->t & VT_BTYPE) == VT_BYTE)) {
7748 while (tok == TOK_STR || tok == TOK_LSTR) {
7749 int cstr_len, ch;
7750 CString *cstr;
7752 cstr = tokc.cstr;
7753 /* compute maximum number of chars wanted */
7754 if (tok == TOK_STR)
7755 cstr_len = cstr->size;
7756 else
7757 cstr_len = cstr->size / sizeof(int);
7758 cstr_len--;
7759 nb = cstr_len;
7760 if (n >= 0 && nb > (n - array_length))
7761 nb = n - array_length;
7762 if (!size_only) {
7763 if (cstr_len > nb)
7764 warning("initializer-string for array is too long");
7765 /* in order to go faster for common case (char
7766 string in global variable, we handle it
7767 specifically */
7768 if (sec && tok == TOK_STR && size1 == 1) {
7769 memcpy(sec->data + c + array_length, cstr->data, nb);
7770 } else {
7771 for(i=0;i<nb;i++) {
7772 if (tok == TOK_STR)
7773 ch = ((unsigned char *)cstr->data)[i];
7774 else
7775 ch = ((int *)cstr->data)[i];
7776 init_putv(t1, sec, c + (array_length + i) * size1,
7777 ch, EXPR_VAL);
7781 array_length += nb;
7782 next();
7784 /* only add trailing zero if enough storage (no
7785 warning in this case since it is standard) */
7786 if (n < 0 || array_length < n) {
7787 if (!size_only) {
7788 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7790 array_length++;
7792 } else {
7793 index = 0;
7794 while (tok != '}') {
7795 decl_designator(type, sec, c, &index, NULL, size_only);
7796 if (n >= 0 && index >= n)
7797 error("index too large");
7798 /* must put zero in holes (note that doing it that way
7799 ensures that it even works with designators) */
7800 if (!size_only && array_length < index) {
7801 init_putz(t1, sec, c + array_length * size1,
7802 (index - array_length) * size1);
7804 index++;
7805 if (index > array_length)
7806 array_length = index;
7807 /* special test for multi dimensional arrays (may not
7808 be strictly correct if designators are used at the
7809 same time) */
7810 if (index >= n && no_oblock)
7811 break;
7812 if (tok == '}')
7813 break;
7814 skip(',');
7817 if (!no_oblock)
7818 skip('}');
7819 /* put zeros at the end */
7820 if (!size_only && n >= 0 && array_length < n) {
7821 init_putz(t1, sec, c + array_length * size1,
7822 (n - array_length) * size1);
7824 /* patch type size if needed */
7825 if (n < 0)
7826 s->c = array_length;
7827 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
7828 (sec || !first || tok == '{')) {
7829 int par_count;
7831 /* NOTE: the previous test is a specific case for automatic
7832 struct/union init */
7833 /* XXX: union needs only one init */
7835 /* XXX: this test is incorrect for local initializers
7836 beginning with ( without {. It would be much more difficult
7837 to do it correctly (ideally, the expression parser should
7838 be used in all cases) */
7839 par_count = 0;
7840 if (tok == '(') {
7841 AttributeDef ad1;
7842 CType type1;
7843 next();
7844 while (tok == '(') {
7845 par_count++;
7846 next();
7848 if (!parse_btype(&type1, &ad1))
7849 expect("cast");
7850 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
7851 if (!is_compatible_types(type, &type1))
7852 error("invalid type for cast");
7853 skip(')');
7855 no_oblock = 1;
7856 if (first || tok == '{') {
7857 skip('{');
7858 no_oblock = 0;
7860 s = type->ref;
7861 f = s->next;
7862 array_length = 0;
7863 index = 0;
7864 n = s->c;
7865 while (tok != '}') {
7866 decl_designator(type, sec, c, NULL, &f, size_only);
7867 index = f->c;
7868 if (!size_only && array_length < index) {
7869 init_putz(type, sec, c + array_length,
7870 index - array_length);
7872 index = index + type_size(&f->type, &align1);
7873 if (index > array_length)
7874 array_length = index;
7875 f = f->next;
7876 if (no_oblock && f == NULL)
7877 break;
7878 if (tok == '}')
7879 break;
7880 skip(',');
7882 /* put zeros at the end */
7883 if (!size_only && array_length < n) {
7884 init_putz(type, sec, c + array_length,
7885 n - array_length);
7887 if (!no_oblock)
7888 skip('}');
7889 while (par_count) {
7890 skip(')');
7891 par_count--;
7893 } else if (tok == '{') {
7894 next();
7895 decl_initializer(type, sec, c, first, size_only);
7896 skip('}');
7897 } else if (size_only) {
7898 /* just skip expression */
7899 parlevel = 0;
7900 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7901 tok != -1) {
7902 if (tok == '(')
7903 parlevel++;
7904 else if (tok == ')')
7905 parlevel--;
7906 next();
7908 } else {
7909 /* currently, we always use constant expression for globals
7910 (may change for scripting case) */
7911 expr_type = EXPR_CONST;
7912 if (!sec)
7913 expr_type = EXPR_ANY;
7914 init_putv(type, sec, c, 0, expr_type);
7918 /* parse an initializer for type 't' if 'has_init' is non zero, and
7919 allocate space in local or global data space ('r' is either
7920 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7921 variable 'v' of scope 'scope' is declared before initializers are
7922 parsed. If 'v' is zero, then a reference to the new object is put
7923 in the value stack. If 'has_init' is 2, a special parsing is done
7924 to handle string constants. */
7925 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
7926 int has_init, int v, int scope)
7928 int size, align, addr, data_offset;
7929 int level;
7930 ParseState saved_parse_state;
7931 TokenString init_str;
7932 Section *sec;
7934 size = type_size(type, &align);
7935 /* If unknown size, we must evaluate it before
7936 evaluating initializers because
7937 initializers can generate global data too
7938 (e.g. string pointers or ISOC99 compound
7939 literals). It also simplifies local
7940 initializers handling */
7941 tok_str_new(&init_str);
7942 if (size < 0) {
7943 if (!has_init)
7944 error("unknown type size");
7945 /* get all init string */
7946 if (has_init == 2) {
7947 /* only get strings */
7948 while (tok == TOK_STR || tok == TOK_LSTR) {
7949 tok_str_add_tok(&init_str);
7950 next();
7952 } else {
7953 level = 0;
7954 while (level > 0 || (tok != ',' && tok != ';')) {
7955 if (tok < 0)
7956 error("unexpected end of file in initializer");
7957 tok_str_add_tok(&init_str);
7958 if (tok == '{')
7959 level++;
7960 else if (tok == '}') {
7961 if (level == 0)
7962 break;
7963 level--;
7965 next();
7968 tok_str_add(&init_str, -1);
7969 tok_str_add(&init_str, 0);
7971 /* compute size */
7972 save_parse_state(&saved_parse_state);
7974 macro_ptr = init_str.str;
7975 next();
7976 decl_initializer(type, NULL, 0, 1, 1);
7977 /* prepare second initializer parsing */
7978 macro_ptr = init_str.str;
7979 next();
7981 /* if still unknown size, error */
7982 size = type_size(type, &align);
7983 if (size < 0)
7984 error("unknown type size");
7986 /* take into account specified alignment if bigger */
7987 if (ad->aligned > align)
7988 align = ad->aligned;
7989 if ((r & VT_VALMASK) == VT_LOCAL) {
7990 sec = NULL;
7991 if (do_bounds_check && (type->t & VT_ARRAY))
7992 loc--;
7993 loc = (loc - size) & -align;
7994 addr = loc;
7995 /* handles bounds */
7996 /* XXX: currently, since we do only one pass, we cannot track
7997 '&' operators, so we add only arrays */
7998 if (do_bounds_check && (type->t & VT_ARRAY)) {
7999 unsigned long *bounds_ptr;
8000 /* add padding between regions */
8001 loc--;
8002 /* then add local bound info */
8003 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8004 bounds_ptr[0] = addr;
8005 bounds_ptr[1] = size;
8007 if (v) {
8008 /* local variable */
8009 sym_push(v, type, r, addr);
8010 } else {
8011 /* push local reference */
8012 vset(type, r, addr);
8014 } else {
8015 Sym *sym;
8017 sym = NULL;
8018 if (v && scope == VT_CONST) {
8019 /* see if the symbol was already defined */
8020 sym = sym_find(v);
8021 if (sym) {
8022 if (!is_compatible_types(&sym->type, type))
8023 error("incompatible types for redefinition of '%s'",
8024 get_tok_str(v, NULL));
8025 if (sym->type.t & VT_EXTERN) {
8026 /* if the variable is extern, it was not allocated */
8027 sym->type.t &= ~VT_EXTERN;
8028 } else {
8029 /* we accept several definitions of the same
8030 global variable. this is tricky, because we
8031 must play with the SHN_COMMON type of the symbol */
8032 /* XXX: should check if the variable was already
8033 initialized. It is incorrect to initialized it
8034 twice */
8035 /* no init data, we won't add more to the symbol */
8036 if (!has_init)
8037 goto no_alloc;
8042 /* allocate symbol in corresponding section */
8043 sec = ad->section;
8044 if (!sec) {
8045 if (has_init)
8046 sec = data_section;
8048 if (sec) {
8049 data_offset = sec->data_offset;
8050 data_offset = (data_offset + align - 1) & -align;
8051 addr = data_offset;
8052 /* very important to increment global pointer at this time
8053 because initializers themselves can create new initializers */
8054 data_offset += size;
8055 /* add padding if bound check */
8056 if (do_bounds_check)
8057 data_offset++;
8058 sec->data_offset = data_offset;
8059 /* allocate section space to put the data */
8060 if (sec->sh_type != SHT_NOBITS &&
8061 data_offset > sec->data_allocated)
8062 section_realloc(sec, data_offset);
8063 } else {
8064 addr = 0; /* avoid warning */
8067 if (v) {
8068 if (scope == VT_CONST) {
8069 if (!sym)
8070 goto do_def;
8071 } else {
8072 do_def:
8073 sym = sym_push(v, type, r | VT_SYM, 0);
8075 /* update symbol definition */
8076 if (sec) {
8077 put_extern_sym(sym, sec, addr, size);
8078 } else {
8079 Elf32_Sym *esym;
8080 /* put a common area */
8081 put_extern_sym(sym, NULL, align, size);
8082 /* XXX: find a nicer way */
8083 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8084 esym->st_shndx = SHN_COMMON;
8086 } else {
8087 CValue cval;
8089 /* push global reference */
8090 sym = get_sym_ref(type, sec, addr, size);
8091 cval.ul = 0;
8092 vsetc(type, VT_CONST | VT_SYM, &cval);
8093 vtop->sym = sym;
8096 /* handles bounds now because the symbol must be defined
8097 before for the relocation */
8098 if (do_bounds_check) {
8099 unsigned long *bounds_ptr;
8101 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8102 /* then add global bound info */
8103 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8104 bounds_ptr[0] = 0; /* relocated */
8105 bounds_ptr[1] = size;
8108 if (has_init) {
8109 decl_initializer(type, sec, addr, 1, 0);
8110 /* restore parse state if needed */
8111 if (init_str.str) {
8112 tok_str_free(init_str.str);
8113 restore_parse_state(&saved_parse_state);
8116 no_alloc: ;
8119 void put_func_debug(Sym *sym)
8121 char buf[512];
8123 /* stabs info */
8124 /* XXX: we put here a dummy type */
8125 snprintf(buf, sizeof(buf), "%s:%c1",
8126 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8127 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8128 cur_text_section, sym->c);
8129 last_ind = 0;
8130 last_line_num = 0;
8133 /* not finished : try to put some local vars in registers */
8134 //#define CONFIG_REG_VARS
8136 #ifdef CONFIG_REG_VARS
8137 void add_var_ref(int t)
8139 printf("%s:%d: &%s\n",
8140 file->filename, file->line_num,
8141 get_tok_str(t, NULL));
8144 /* first pass on a function with heuristic to extract variable usage
8145 and pointer references to local variables for register allocation */
8146 void analyse_function(void)
8148 int level, t;
8150 for(;;) {
8151 if (tok == -1)
8152 break;
8153 /* any symbol coming after '&' is considered as being a
8154 variable whose reference is taken. It is highly unaccurate
8155 but it is difficult to do better without a complete parse */
8156 if (tok == '&') {
8157 next();
8158 /* if '& number', then no need to examine next tokens */
8159 if (tok == TOK_CINT ||
8160 tok == TOK_CUINT ||
8161 tok == TOK_CLLONG ||
8162 tok == TOK_CULLONG) {
8163 continue;
8164 } else if (tok >= TOK_UIDENT) {
8165 /* if '& ident [' or '& ident ->', then ident address
8166 is not needed */
8167 t = tok;
8168 next();
8169 if (tok != '[' && tok != TOK_ARROW)
8170 add_var_ref(t);
8171 } else {
8172 level = 0;
8173 while (tok != '}' && tok != ';' &&
8174 !((tok == ',' || tok == ')') && level == 0)) {
8175 if (tok >= TOK_UIDENT) {
8176 add_var_ref(tok);
8177 } else if (tok == '(') {
8178 level++;
8179 } else if (tok == ')') {
8180 level--;
8182 next();
8185 } else {
8186 next();
8190 #endif
8192 /* parse an old style function declaration list */
8193 /* XXX: check multiple parameter */
8194 static void func_decl_list(Sym *func_sym)
8196 AttributeDef ad;
8197 int v;
8198 Sym *s;
8199 CType btype, type;
8201 /* parse each declaration */
8202 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8203 if (!parse_btype(&btype, &ad))
8204 expect("declaration list");
8205 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8206 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8207 tok == ';') {
8208 /* we accept no variable after */
8209 } else {
8210 for(;;) {
8211 type = btype;
8212 type_decl(&type, &ad, &v, TYPE_DIRECT);
8213 /* find parameter in function parameter list */
8214 s = func_sym->next;
8215 while (s != NULL) {
8216 if ((s->v & ~SYM_FIELD) == v)
8217 goto found;
8218 s = s->next;
8220 error("declaration for parameter '%s' but no such parameter",
8221 get_tok_str(v, NULL));
8222 found:
8223 /* check that no storage specifier except 'register' was given */
8224 if (type.t & VT_STORAGE)
8225 error("storage class specified for '%s'", get_tok_str(v, NULL));
8226 /* array must be transformed to pointer according to ANSI C */
8227 type.t &= ~VT_ARRAY;
8228 /* we can add the type (NOTE: it could be local to the function) */
8229 s->type = type;
8230 /* accept other parameters */
8231 if (tok == ',')
8232 next();
8233 else
8234 break;
8237 skip(';');
8241 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8242 static void decl(int l)
8244 int v, has_init, r;
8245 CType type, btype;
8246 Sym *sym;
8247 AttributeDef ad;
8249 while (1) {
8250 if (!parse_btype(&btype, &ad)) {
8251 /* skip redundant ';' */
8252 /* XXX: find more elegant solution */
8253 if (tok == ';') {
8254 next();
8255 continue;
8257 /* special test for old K&R protos without explicit int
8258 type. Only accepted when defining global data */
8259 if (l == VT_LOCAL || tok < TOK_DEFINE)
8260 break;
8261 btype.t = VT_INT;
8263 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8264 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8265 tok == ';') {
8266 /* we accept no variable after */
8267 next();
8268 continue;
8270 while (1) { /* iterate thru each declaration */
8271 type = btype;
8272 type_decl(&type, &ad, &v, TYPE_DIRECT);
8273 #if 0
8275 char buf[500];
8276 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8277 printf("type = '%s'\n", buf);
8279 #endif
8280 if ((type.t & VT_BTYPE) == VT_FUNC) {
8281 /* if old style function prototype, we accept a
8282 declaration list */
8283 sym = type.ref;
8284 if (sym->c == FUNC_OLD)
8285 func_decl_list(sym);
8288 if (tok == '{') {
8289 #ifdef CONFIG_REG_VARS
8290 TokenString func_str;
8291 ParseState saved_parse_state;
8292 int block_level;
8293 #endif
8295 if (l == VT_LOCAL)
8296 error("cannot use local functions");
8297 if (!(type.t & VT_FUNC))
8298 expect("function definition");
8299 /* XXX: cannot do better now: convert extern line to static inline */
8300 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8301 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8303 #ifdef CONFIG_REG_VARS
8304 /* parse all function code and record it */
8306 tok_str_new(&func_str);
8308 block_level = 0;
8309 for(;;) {
8310 int t;
8311 if (tok == -1)
8312 error("unexpected end of file");
8313 tok_str_add_tok(&func_str);
8314 t = tok;
8315 next();
8316 if (t == '{') {
8317 block_level++;
8318 } else if (t == '}') {
8319 block_level--;
8320 if (block_level == 0)
8321 break;
8324 tok_str_add(&func_str, -1);
8325 tok_str_add(&func_str, 0);
8327 save_parse_state(&saved_parse_state);
8329 macro_ptr = func_str.str;
8330 next();
8331 analyse_function();
8332 #endif
8334 /* compute text section */
8335 cur_text_section = ad.section;
8336 if (!cur_text_section)
8337 cur_text_section = text_section;
8338 ind = cur_text_section->data_offset;
8339 funcname = get_tok_str(v, NULL);
8340 sym = sym_find(v);
8341 if (sym) {
8342 /* if symbol is already defined, then put complete type */
8343 sym->type = type;
8344 } else {
8345 /* put function symbol */
8346 sym = global_identifier_push(v, type.t, 0);
8347 sym->type.ref = type.ref;
8349 /* NOTE: we patch the symbol size later */
8350 put_extern_sym(sym, cur_text_section, ind, 0);
8351 func_ind = ind;
8352 sym->r = VT_SYM | VT_CONST;
8353 /* put debug symbol */
8354 if (do_debug)
8355 put_func_debug(sym);
8356 /* push a dummy symbol to enable local sym storage */
8357 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8358 gfunc_prolog(&type);
8359 loc = 0;
8360 rsym = 0;
8361 #ifdef CONFIG_REG_VARS
8362 macro_ptr = func_str.str;
8363 next();
8364 #endif
8365 block(NULL, NULL, NULL, NULL, 0, 0);
8366 gsym(rsym);
8367 gfunc_epilog();
8368 cur_text_section->data_offset = ind;
8369 label_pop(&global_label_stack, NULL);
8370 sym_pop(&local_stack, NULL); /* reset local stack */
8371 /* end of function */
8372 /* patch symbol size */
8373 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8374 ind - func_ind;
8375 if (do_debug) {
8376 put_stabn(N_FUN, 0, 0, ind - func_ind);
8378 funcname = ""; /* for safety */
8379 func_vt.t = VT_VOID; /* for safety */
8380 ind = 0; /* for safety */
8382 #ifdef CONFIG_REG_VARS
8383 tok_str_free(func_str.str);
8384 restore_parse_state(&saved_parse_state);
8385 #endif
8386 break;
8387 } else {
8388 if (btype.t & VT_TYPEDEF) {
8389 /* save typedefed type */
8390 /* XXX: test storage specifiers ? */
8391 sym = sym_push(v, &type, 0, 0);
8392 sym->type.t |= VT_TYPEDEF;
8393 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8394 /* external function definition */
8395 external_sym(v, &type, 0);
8396 } else {
8397 /* not lvalue if array */
8398 r = 0;
8399 if (!(type.t & VT_ARRAY))
8400 r |= lvalue_type(type.t);
8401 has_init = (tok == '=');
8402 if ((btype.t & VT_EXTERN) ||
8403 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8404 !has_init && l == VT_CONST && type.ref->c < 0)) {
8405 /* external variable */
8406 /* NOTE: as GCC, uninitialized global static
8407 arrays of null size are considered as
8408 extern */
8409 external_sym(v, &type, r);
8410 } else {
8411 if (type.t & VT_STATIC)
8412 r |= VT_CONST;
8413 else
8414 r |= l;
8415 if (has_init)
8416 next();
8417 decl_initializer_alloc(&type, &ad, r,
8418 has_init, v, l);
8421 if (tok != ',') {
8422 skip(';');
8423 break;
8425 next();
8431 /* better than nothing, but needs extension to handle '-E' option
8432 correctly too */
8433 static void preprocess_init(TCCState *s1)
8435 s1->include_stack_ptr = s1->include_stack;
8436 /* XXX: move that before to avoid having to initialize
8437 file->ifdef_stack_ptr ? */
8438 s1->ifdef_stack_ptr = s1->ifdef_stack;
8439 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8441 /* XXX: not ANSI compliant: bound checking says error */
8442 vtop = vstack - 1;
8445 /* compile the C file opened in 'file'. Return non zero if errors. */
8446 static int tcc_compile(TCCState *s1)
8448 Sym *define_start;
8449 char buf[512];
8450 volatile int section_sym;
8452 #ifdef INC_DEBUG
8453 printf("%s: **** new file\n", file->filename);
8454 #endif
8455 preprocess_init(s1);
8457 funcname = "";
8458 anon_sym = SYM_FIRST_ANOM;
8460 /* file info: full path + filename */
8461 section_sym = 0; /* avoid warning */
8462 if (do_debug) {
8463 section_sym = put_elf_sym(symtab_section, 0, 0,
8464 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8465 text_section->sh_num, NULL);
8466 getcwd(buf, sizeof(buf));
8467 pstrcat(buf, sizeof(buf), "/");
8468 put_stabs_r(buf, N_SO, 0, 0,
8469 text_section->data_offset, text_section, section_sym);
8470 put_stabs_r(file->filename, N_SO, 0, 0,
8471 text_section->data_offset, text_section, section_sym);
8473 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8474 symbols can be safely used */
8475 put_elf_sym(symtab_section, 0, 0,
8476 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8477 SHN_ABS, file->filename);
8479 /* define some often used types */
8480 int_type.t = VT_INT;
8482 char_pointer_type.t = VT_BYTE;
8483 mk_pointer(&char_pointer_type);
8485 func_old_type.t = VT_FUNC;
8486 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8488 #if 0
8489 /* define 'void *alloca(unsigned int)' builtin function */
8491 Sym *s1;
8493 p = anon_sym++;
8494 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8495 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8496 s1->next = NULL;
8497 sym->next = s1;
8498 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8500 #endif
8502 define_start = define_stack;
8504 if (setjmp(s1->error_jmp_buf) == 0) {
8505 s1->nb_errors = 0;
8506 s1->error_set_jmp_enabled = 1;
8508 ch = file->buf_ptr[0];
8509 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8510 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8511 next();
8512 decl(VT_CONST);
8513 if (tok != -1)
8514 expect("declaration");
8516 /* end of translation unit info */
8517 if (do_debug) {
8518 put_stabs_r(NULL, N_SO, 0, 0,
8519 text_section->data_offset, text_section, section_sym);
8522 s1->error_set_jmp_enabled = 0;
8524 /* reset define stack, but leave -Dsymbols (may be incorrect if
8525 they are undefined) */
8526 free_defines(define_start);
8528 sym_pop(&global_stack, NULL);
8530 return s1->nb_errors != 0 ? -1 : 0;
8533 #ifdef LIBTCC
8534 int tcc_compile_string(TCCState *s, const char *str)
8536 BufferedFile bf1, *bf = &bf1;
8537 int ret, len;
8538 char *buf;
8540 /* init file structure */
8541 bf->fd = -1;
8542 /* XXX: avoid copying */
8543 len = strlen(str);
8544 buf = tcc_malloc(len + 1);
8545 if (!buf)
8546 return -1;
8547 memcpy(buf, str, len);
8548 buf[len] = CH_EOB;
8549 bf->buf_ptr = buf;
8550 bf->buf_end = buf + len;
8551 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8552 bf->line_num = 1;
8553 file = bf;
8555 ret = tcc_compile(s);
8557 tcc_free(buf);
8559 /* currently, no need to close */
8560 return ret;
8562 #endif
8564 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8565 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8567 BufferedFile bf1, *bf = &bf1;
8569 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8570 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8571 /* default value */
8572 if (!value)
8573 value = "1";
8574 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8576 /* init file structure */
8577 bf->fd = -1;
8578 bf->buf_ptr = bf->buffer;
8579 bf->buf_end = bf->buffer + strlen(bf->buffer);
8580 *bf->buf_end = CH_EOB;
8581 bf->filename[0] = '\0';
8582 bf->line_num = 1;
8583 file = bf;
8585 s1->include_stack_ptr = s1->include_stack;
8587 /* parse with define parser */
8588 ch = file->buf_ptr[0];
8589 next_nomacro();
8590 parse_define();
8591 file = NULL;
8594 /* undefine a preprocessor symbol */
8595 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8597 TokenSym *ts;
8598 Sym *s;
8599 ts = tok_alloc(sym, strlen(sym));
8600 s = define_find(ts->tok);
8601 /* undefine symbol by putting an invalid name */
8602 if (s)
8603 define_undef(s);
8606 #ifdef CONFIG_TCC_ASM
8608 #include "i386-asm.c"
8609 #include "tccasm.c"
8611 #else
8612 static void asm_instr(void)
8614 error("inline asm() not supported");
8616 #endif
8618 #include "tccelf.c"
8620 /* print the position in the source file of PC value 'pc' by reading
8621 the stabs debug information */
8622 static void rt_printline(unsigned long wanted_pc)
8624 Stab_Sym *sym, *sym_end;
8625 char func_name[128], last_func_name[128];
8626 unsigned long func_addr, last_pc, pc;
8627 const char *incl_files[INCLUDE_STACK_SIZE];
8628 int incl_index, len, last_line_num, i;
8629 const char *str, *p;
8631 fprintf(stderr, "0x%08lx:", wanted_pc);
8633 func_name[0] = '\0';
8634 func_addr = 0;
8635 incl_index = 0;
8636 last_func_name[0] = '\0';
8637 last_pc = 0xffffffff;
8638 last_line_num = 1;
8639 sym = (Stab_Sym *)stab_section->data + 1;
8640 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8641 while (sym < sym_end) {
8642 switch(sym->n_type) {
8643 /* function start or end */
8644 case N_FUN:
8645 if (sym->n_strx == 0) {
8646 /* we test if between last line and end of function */
8647 pc = sym->n_value + func_addr;
8648 if (wanted_pc >= last_pc && wanted_pc < pc)
8649 goto found;
8650 func_name[0] = '\0';
8651 func_addr = 0;
8652 } else {
8653 str = stabstr_section->data + sym->n_strx;
8654 p = strchr(str, ':');
8655 if (!p) {
8656 pstrcpy(func_name, sizeof(func_name), str);
8657 } else {
8658 len = p - str;
8659 if (len > sizeof(func_name) - 1)
8660 len = sizeof(func_name) - 1;
8661 memcpy(func_name, str, len);
8662 func_name[len] = '\0';
8664 func_addr = sym->n_value;
8666 break;
8667 /* line number info */
8668 case N_SLINE:
8669 pc = sym->n_value + func_addr;
8670 if (wanted_pc >= last_pc && wanted_pc < pc)
8671 goto found;
8672 last_pc = pc;
8673 last_line_num = sym->n_desc;
8674 /* XXX: slow! */
8675 strcpy(last_func_name, func_name);
8676 break;
8677 /* include files */
8678 case N_BINCL:
8679 str = stabstr_section->data + sym->n_strx;
8680 add_incl:
8681 if (incl_index < INCLUDE_STACK_SIZE) {
8682 incl_files[incl_index++] = str;
8684 break;
8685 case N_EINCL:
8686 if (incl_index > 1)
8687 incl_index--;
8688 break;
8689 case N_SO:
8690 if (sym->n_strx == 0) {
8691 incl_index = 0; /* end of translation unit */
8692 } else {
8693 str = stabstr_section->data + sym->n_strx;
8694 /* do not add path */
8695 len = strlen(str);
8696 if (len > 0 && str[len - 1] != '/')
8697 goto add_incl;
8699 break;
8701 sym++;
8704 /* second pass: we try symtab symbols (no line number info) */
8705 incl_index = 0;
8707 Elf32_Sym *sym, *sym_end;
8708 int type;
8710 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8711 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8712 sym < sym_end;
8713 sym++) {
8714 type = ELF32_ST_TYPE(sym->st_info);
8715 if (type == STT_FUNC) {
8716 if (wanted_pc >= sym->st_value &&
8717 wanted_pc < sym->st_value + sym->st_size) {
8718 pstrcpy(last_func_name, sizeof(last_func_name),
8719 strtab_section->data + sym->st_name);
8720 goto found;
8725 /* did not find any info: */
8726 fprintf(stderr, " ???\n");
8727 return;
8728 found:
8729 if (last_func_name[0] != '\0') {
8730 fprintf(stderr, " %s()", last_func_name);
8732 if (incl_index > 0) {
8733 fprintf(stderr, " (%s:%d",
8734 incl_files[incl_index - 1], last_line_num);
8735 for(i = incl_index - 2; i >= 0; i--)
8736 fprintf(stderr, ", included from %s", incl_files[i]);
8737 fprintf(stderr, ")");
8739 fprintf(stderr, "\n");
8742 #ifndef WIN32
8744 #ifdef __i386__
8746 /* fix for glibc 2.1 */
8747 #ifndef REG_EIP
8748 #define REG_EIP EIP
8749 #define REG_EBP EBP
8750 #endif
8752 /* return the PC at frame level 'level'. Return non zero if not found */
8753 static int rt_get_caller_pc(unsigned long *paddr,
8754 ucontext_t *uc, int level)
8756 unsigned long fp;
8757 int i;
8759 if (level == 0) {
8760 #ifdef __FreeBSD__
8761 *paddr = uc->uc_mcontext.mc_eip;
8762 #else
8763 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8764 #endif
8765 return 0;
8766 } else {
8767 #ifdef __FreeBSD__
8768 fp = uc->uc_mcontext.mc_ebp;
8769 #else
8770 fp = uc->uc_mcontext.gregs[REG_EBP];
8771 #endif
8772 for(i=1;i<level;i++) {
8773 /* XXX: check address validity with program info */
8774 if (fp <= 0x1000 || fp >= 0xc0000000)
8775 return -1;
8776 fp = ((unsigned long *)fp)[0];
8778 *paddr = ((unsigned long *)fp)[1];
8779 return 0;
8782 #else
8783 #error add arch specific rt_get_caller_pc()
8784 #endif
8786 /* emit a run time error at position 'pc' */
8787 void rt_error(ucontext_t *uc, const char *fmt, ...)
8789 va_list ap;
8790 unsigned long pc;
8791 int i;
8793 va_start(ap, fmt);
8794 fprintf(stderr, "Runtime error: ");
8795 vfprintf(stderr, fmt, ap);
8796 fprintf(stderr, "\n");
8797 for(i=0;i<num_callers;i++) {
8798 if (rt_get_caller_pc(&pc, uc, i) < 0)
8799 break;
8800 if (i == 0)
8801 fprintf(stderr, "at ");
8802 else
8803 fprintf(stderr, "by ");
8804 rt_printline(pc);
8806 exit(255);
8807 va_end(ap);
8810 /* signal handler for fatal errors */
8811 static void sig_error(int signum, siginfo_t *siginf, void *puc)
8813 ucontext_t *uc = puc;
8815 switch(signum) {
8816 case SIGFPE:
8817 switch(siginf->si_code) {
8818 case FPE_INTDIV:
8819 case FPE_FLTDIV:
8820 rt_error(uc, "division by zero");
8821 break;
8822 default:
8823 rt_error(uc, "floating point exception");
8824 break;
8826 break;
8827 case SIGBUS:
8828 case SIGSEGV:
8829 if (rt_bound_error_msg && *rt_bound_error_msg)
8830 rt_error(uc, *rt_bound_error_msg);
8831 else
8832 rt_error(uc, "dereferencing invalid pointer");
8833 break;
8834 case SIGILL:
8835 rt_error(uc, "illegal instruction");
8836 break;
8837 case SIGABRT:
8838 rt_error(uc, "abort() called");
8839 break;
8840 default:
8841 rt_error(uc, "caught signal %d", signum);
8842 break;
8844 exit(255);
8846 #endif
8848 /* do all relocations (needed before using tcc_get_symbol()) */
8849 int tcc_relocate(TCCState *s1)
8851 Section *s;
8852 int i;
8854 s1->nb_errors = 0;
8856 tcc_add_runtime(s1);
8858 relocate_common_syms();
8860 /* compute relocation address : section are relocated in place. We
8861 also alloc the bss space */
8862 for(i = 1; i < s1->nb_sections; i++) {
8863 s = s1->sections[i];
8864 if (s->sh_flags & SHF_ALLOC) {
8865 if (s->sh_type == SHT_NOBITS)
8866 s->data = tcc_mallocz(s->data_offset);
8867 s->sh_addr = (unsigned long)s->data;
8871 relocate_syms(s1, 1);
8873 if (s1->nb_errors != 0)
8874 return -1;
8876 /* relocate each section */
8877 for(i = 1; i < s1->nb_sections; i++) {
8878 s = s1->sections[i];
8879 if (s->reloc)
8880 relocate_section(s1, s);
8882 return 0;
8885 /* launch the compiled program with the given arguments */
8886 int tcc_run(TCCState *s1, int argc, char **argv)
8888 int (*prog_main)(int, char **);
8890 if (tcc_relocate(s1) < 0)
8891 return -1;
8893 prog_main = tcc_get_symbol(s1, "main");
8895 if (do_debug) {
8896 #ifdef WIN32
8897 error("debug mode currently not available for Windows");
8898 #else
8899 struct sigaction sigact;
8900 /* install TCC signal handlers to print debug info on fatal
8901 runtime errors */
8902 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
8903 sigact.sa_sigaction = sig_error;
8904 sigemptyset(&sigact.sa_mask);
8905 sigaction(SIGFPE, &sigact, NULL);
8906 sigaction(SIGILL, &sigact, NULL);
8907 sigaction(SIGSEGV, &sigact, NULL);
8908 sigaction(SIGBUS, &sigact, NULL);
8909 sigaction(SIGABRT, &sigact, NULL);
8910 #endif
8913 #ifdef CONFIG_TCC_BCHECK
8914 if (do_bounds_check) {
8915 void (*bound_init)(void);
8917 /* set error function */
8918 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8920 /* XXX: use .init section so that it also work in binary ? */
8921 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8922 bound_init();
8924 #endif
8925 return (*prog_main)(argc, argv);
8928 TCCState *tcc_new(void)
8930 const char *p, *r;
8931 TCCState *s;
8932 TokenSym *ts;
8933 int i, c;
8935 s = tcc_mallocz(sizeof(TCCState));
8936 if (!s)
8937 return NULL;
8938 tcc_state = s;
8939 s->output_type = TCC_OUTPUT_MEMORY;
8941 /* init isid table */
8942 for(i=0;i<256;i++)
8943 isidnum_table[i] = isid(i) || isnum(i);
8945 /* add all tokens */
8946 table_ident = NULL;
8947 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
8949 tok_ident = TOK_IDENT;
8950 p = tcc_keywords;
8951 while (*p) {
8952 r = p;
8953 for(;;) {
8954 c = *r++;
8955 if (c == '\0')
8956 break;
8958 ts = tok_alloc(p, r - p - 1);
8959 p = r;
8962 /* we add dummy defines for some special macros to speed up tests
8963 and to have working defined() */
8964 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
8965 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
8966 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
8967 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
8969 /* standard defines */
8970 tcc_define_symbol(s, "__STDC__", NULL);
8971 #if defined(TCC_TARGET_I386)
8972 tcc_define_symbol(s, "__i386__", NULL);
8973 #endif
8974 #if defined(linux)
8975 tcc_define_symbol(s, "__linux__", NULL);
8976 tcc_define_symbol(s, "linux", NULL);
8977 #endif
8978 /* tiny C specific defines */
8979 tcc_define_symbol(s, "__TINYC__", NULL);
8981 /* tiny C & gcc defines */
8982 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
8983 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
8984 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
8986 /* default library paths */
8987 tcc_add_library_path(s, "/usr/local/lib");
8988 tcc_add_library_path(s, "/usr/lib");
8989 tcc_add_library_path(s, "/lib");
8991 /* no section zero */
8992 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
8994 /* create standard sections */
8995 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8996 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8997 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8999 /* symbols are always generated for linking stage */
9000 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9001 ".strtab",
9002 ".hashtab", SHF_PRIVATE);
9003 strtab_section = symtab_section->link;
9005 /* private symbol table for dynamic symbols */
9006 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9007 ".dynstrtab",
9008 ".dynhashtab", SHF_PRIVATE);
9009 return s;
9012 void tcc_delete(TCCState *s1)
9014 int i, n;
9016 /* free -D defines */
9017 free_defines(NULL);
9019 /* free tokens */
9020 n = tok_ident - TOK_IDENT;
9021 for(i = 0; i < n; i++)
9022 tcc_free(table_ident[i]);
9023 tcc_free(table_ident);
9025 /* free all sections */
9027 free_section(symtab_section->hash);
9029 free_section(s1->dynsymtab_section->hash);
9030 free_section(s1->dynsymtab_section->link);
9031 free_section(s1->dynsymtab_section);
9033 for(i = 1; i < s1->nb_sections; i++)
9034 free_section(s1->sections[i]);
9035 tcc_free(s1->sections);
9037 /* free loaded dlls array */
9038 for(i = 0; i < s1->nb_loaded_dlls; i++)
9039 tcc_free(s1->loaded_dlls[i]);
9040 tcc_free(s1->loaded_dlls);
9042 /* library paths */
9043 for(i = 0; i < s1->nb_library_paths; i++)
9044 tcc_free(s1->library_paths[i]);
9045 tcc_free(s1->library_paths);
9047 /* cached includes */
9048 for(i = 0; i < s1->nb_cached_includes; i++)
9049 tcc_free(s1->cached_includes[i]);
9050 tcc_free(s1->cached_includes);
9052 for(i = 0; i < s1->nb_include_paths; i++)
9053 tcc_free(s1->include_paths[i]);
9054 tcc_free(s1->include_paths);
9056 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9057 tcc_free(s1->sysinclude_paths[i]);
9058 tcc_free(s1->sysinclude_paths);
9060 tcc_free(s1);
9063 int tcc_add_include_path(TCCState *s1, const char *pathname)
9065 char *pathname1;
9067 pathname1 = tcc_strdup(pathname);
9068 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9069 return 0;
9072 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9074 char *pathname1;
9076 pathname1 = tcc_strdup(pathname);
9077 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9078 return 0;
9081 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9083 const char *ext, *filename1;
9084 Elf32_Ehdr ehdr;
9085 int fd, ret;
9086 BufferedFile *saved_file;
9088 /* find source file type with extension */
9089 filename1 = strrchr(filename, '/');
9090 if (filename1)
9091 filename1++;
9092 else
9093 filename1 = filename;
9094 ext = strrchr(filename1, '.');
9095 if (ext)
9096 ext++;
9098 /* open the file */
9099 saved_file = file;
9100 file = tcc_open(s1, filename);
9101 if (!file) {
9102 if (flags & AFF_PRINT_ERROR) {
9103 error_noabort("file '%s' not found", filename);
9105 ret = -1;
9106 goto fail1;
9109 if (!ext || !strcmp(ext, "c")) {
9110 /* C file assumed */
9111 ret = tcc_compile(s1);
9112 } else
9113 #ifdef CONFIG_TCC_ASM
9114 if (!strcmp(ext, "S")) {
9115 /* preprocessed assembler */
9116 ret = tcc_assemble(s1, 1);
9117 } else if (!strcmp(ext, "s")) {
9118 /* non preprocessed assembler */
9119 ret = tcc_assemble(s1, 0);
9120 } else
9121 #endif
9123 fd = file->fd;
9124 /* assume executable format: auto guess file type */
9125 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9126 error_noabort("could not read header");
9127 goto fail;
9129 lseek(fd, 0, SEEK_SET);
9131 if (ehdr.e_ident[0] == ELFMAG0 &&
9132 ehdr.e_ident[1] == ELFMAG1 &&
9133 ehdr.e_ident[2] == ELFMAG2 &&
9134 ehdr.e_ident[3] == ELFMAG3) {
9135 file->line_num = 0; /* do not display line number if error */
9136 if (ehdr.e_type == ET_REL) {
9137 ret = tcc_load_object_file(s1, fd, 0);
9138 } else if (ehdr.e_type == ET_DYN) {
9139 ret = tcc_load_dll(s1, fd, filename,
9140 (flags & AFF_REFERENCED_DLL) != 0);
9141 } else {
9142 error_noabort("unrecognized ELF file");
9143 goto fail;
9145 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9146 file->line_num = 0; /* do not display line number if error */
9147 ret = tcc_load_archive(s1, fd);
9148 } else {
9149 /* as GNU ld, consider it is an ld script if not recognized */
9150 ret = tcc_load_ldscript(s1);
9151 if (ret < 0) {
9152 error_noabort("unrecognized file type");
9153 goto fail;
9157 the_end:
9158 tcc_close(file);
9159 fail1:
9160 file = saved_file;
9161 return ret;
9162 fail:
9163 ret = -1;
9164 goto the_end;
9167 int tcc_add_file(TCCState *s, const char *filename)
9169 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9172 int tcc_add_library_path(TCCState *s, const char *pathname)
9174 char *pathname1;
9176 pathname1 = tcc_strdup(pathname);
9177 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9178 return 0;
9181 /* find and load a dll. Return non zero if not found */
9182 /* XXX: add '-rpath' option support ? */
9183 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9185 char buf[1024];
9186 int i;
9188 for(i = 0; i < s->nb_library_paths; i++) {
9189 snprintf(buf, sizeof(buf), "%s/%s",
9190 s->library_paths[i], filename);
9191 if (tcc_add_file_internal(s, buf, flags) == 0)
9192 return 0;
9194 return -1;
9197 /* the library name is the same as the argument of the '-l' option */
9198 int tcc_add_library(TCCState *s, const char *libraryname)
9200 char buf[1024];
9201 int i;
9202 void *h;
9204 /* first we look for the dynamic library if not static linking */
9205 if (!s->static_link) {
9206 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9207 /* if we output to memory, then we simply we dlopen(). */
9208 if (s->output_type == TCC_OUTPUT_MEMORY) {
9209 /* Since the libc is already loaded, we don't need to load it again */
9210 if (!strcmp(libraryname, "c"))
9211 return 0;
9212 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9213 if (h)
9214 return 0;
9215 } else {
9216 if (tcc_add_dll(s, buf, 0) == 0)
9217 return 0;
9221 /* then we look for the static library */
9222 for(i = 0; i < s->nb_library_paths; i++) {
9223 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9224 s->library_paths[i], libraryname);
9225 if (tcc_add_file_internal(s, buf, 0) == 0)
9226 return 0;
9228 return -1;
9231 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9233 add_elf_sym(symtab_section, val, 0,
9234 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9235 SHN_ABS, name);
9236 return 0;
9239 int tcc_set_output_type(TCCState *s, int output_type)
9241 char buf[1024];
9243 s->output_type = output_type;
9245 if (!s->nostdinc) {
9246 /* default include paths */
9247 /* XXX: reverse order needed if -isystem support */
9248 tcc_add_sysinclude_path(s, "/usr/local/include");
9249 tcc_add_sysinclude_path(s, "/usr/include");
9250 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9251 tcc_add_sysinclude_path(s, buf);
9254 /* if bound checking, then add corresponding sections */
9255 #ifdef CONFIG_TCC_BCHECK
9256 if (do_bounds_check) {
9257 /* define symbol */
9258 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9259 /* create bounds sections */
9260 bounds_section = new_section(s, ".bounds",
9261 SHT_PROGBITS, SHF_ALLOC);
9262 lbounds_section = new_section(s, ".lbounds",
9263 SHT_PROGBITS, SHF_ALLOC);
9265 #endif
9267 /* add debug sections */
9268 if (do_debug) {
9269 /* stab symbols */
9270 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9271 stab_section->sh_entsize = sizeof(Stab_Sym);
9272 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9273 put_elf_str(stabstr_section, "");
9274 stab_section->link = stabstr_section;
9275 /* put first entry */
9276 put_stabs("", 0, 0, 0, 0);
9279 /* add libc crt1/crti objects */
9280 if (output_type == TCC_OUTPUT_EXE ||
9281 output_type == TCC_OUTPUT_DLL) {
9282 if (output_type != TCC_OUTPUT_DLL)
9283 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9284 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9286 return 0;
9289 #if !defined(LIBTCC)
9291 static int64_t getclock_us(void)
9293 #ifdef WIN32
9294 struct _timeb tb;
9295 _ftime(&tb);
9296 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9297 #else
9298 struct timeval tv;
9299 gettimeofday(&tv, NULL);
9300 return tv.tv_sec * 1000000LL + tv.tv_usec;
9301 #endif
9304 void help(void)
9306 printf("tcc version 0.9.16 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
9307 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9308 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9309 " [--] infile1 [infile2... --] [infile_args...]\n"
9310 "\n"
9311 "General options:\n"
9312 " -c compile only - generate an object file\n"
9313 " -o outfile set output filename\n"
9314 " -- allows multiples input files if no -o option given. Also\n"
9315 " separate input files from runtime arguments\n"
9316 " -Bdir set tcc internal library path\n"
9317 " -bench output compilation statistics\n"
9318 "Preprocessor options:\n"
9319 " -Idir add include path 'dir'\n"
9320 " -Dsym[=val] define 'sym' with value 'val'\n"
9321 " -Usym undefine 'sym'\n"
9322 "Linker options:\n"
9323 " -Ldir add library path 'dir'\n"
9324 " -llib link with dynamic or static library 'lib'\n"
9325 " -shared generate a shared library\n"
9326 " -static static linking\n"
9327 " -r relocatable output\n"
9328 "Debugger options:\n"
9329 " -g generate runtime debug info\n"
9330 #ifdef CONFIG_TCC_BCHECK
9331 " -b compile with built-in memory and bounds checker (implies -g)\n"
9332 #endif
9333 " -bt N show N callers in stack traces\n"
9337 #define TCC_OPTION_HAS_ARG 0x0001
9338 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9340 typedef struct TCCOption {
9341 const char *name;
9342 uint16_t index;
9343 uint16_t flags;
9344 } TCCOption;
9346 enum {
9347 TCC_OPTION_HELP,
9348 TCC_OPTION_MARKER,
9349 TCC_OPTION_I,
9350 TCC_OPTION_D,
9351 TCC_OPTION_U,
9352 TCC_OPTION_L,
9353 TCC_OPTION_B,
9354 TCC_OPTION_l,
9355 TCC_OPTION_bench,
9356 TCC_OPTION_bt,
9357 TCC_OPTION_b,
9358 TCC_OPTION_g,
9359 TCC_OPTION_c,
9360 TCC_OPTION_static,
9361 TCC_OPTION_shared,
9362 TCC_OPTION_o,
9363 TCC_OPTION_r,
9364 TCC_OPTION_W,
9365 TCC_OPTION_O,
9366 TCC_OPTION_m,
9367 TCC_OPTION_f,
9368 TCC_OPTION_nostdinc,
9369 TCC_OPTION_print_search_dirs,
9370 TCC_OPTION_rdynamic,
9373 static const TCCOption tcc_options[] = {
9374 { "h", TCC_OPTION_HELP, 0 },
9375 { "?", TCC_OPTION_HELP, 0 },
9376 { "-", TCC_OPTION_MARKER, 0 },
9377 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9378 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9379 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9380 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9381 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9382 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9383 { "bench", TCC_OPTION_bench, 0 },
9384 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9385 #ifdef CONFIG_TCC_BCHECK
9386 { "b", TCC_OPTION_b, 0 },
9387 #endif
9388 { "g", TCC_OPTION_g, 0 },
9389 { "c", TCC_OPTION_c, 0 },
9390 { "static", TCC_OPTION_static, 0 },
9391 { "shared", TCC_OPTION_shared, 0 },
9392 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9393 { "rdynamic", TCC_OPTION_rdynamic, 0 }, /* currently ignored */
9394 { "r", TCC_OPTION_r, 0 },
9395 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9396 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9397 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9398 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9399 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9400 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9401 { NULL },
9404 int main(int argc, char **argv)
9406 char *r;
9407 int optind, output_type, multiple_files, i, reloc_output;
9408 TCCState *s;
9409 char **files;
9410 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9411 char objfilename[1024];
9412 int64_t start_time = 0;
9413 const TCCOption *popt;
9414 const char *optarg, *p1, *r1, *outfile;
9415 int print_search_dirs;
9417 s = tcc_new();
9418 output_type = TCC_OUTPUT_MEMORY;
9420 optind = 1;
9421 outfile = NULL;
9422 multiple_files = 0;
9423 dminus = 0;
9424 files = NULL;
9425 nb_files = 0;
9426 nb_libraries = 0;
9427 reloc_output = 0;
9428 print_search_dirs = 0;
9429 while (1) {
9430 if (optind >= argc) {
9431 if (nb_files == 0 && !print_search_dirs)
9432 goto show_help;
9433 else
9434 break;
9436 r = argv[optind++];
9437 if (r[0] != '-') {
9438 /* add a new file */
9439 dynarray_add((void ***)&files, &nb_files, r);
9440 if (!multiple_files) {
9441 optind--;
9442 /* argv[0] will be this file */
9443 break;
9445 } else {
9446 /* find option in table (match only the first chars */
9447 popt = tcc_options;
9448 for(;;) {
9449 p1 = popt->name;
9450 if (p1 == NULL)
9451 error("invalid option -- '%s'", r);
9452 r1 = r + 1;
9453 for(;;) {
9454 if (*p1 == '\0')
9455 goto option_found;
9456 if (*r1 != *p1)
9457 break;
9458 p1++;
9459 r1++;
9461 popt++;
9463 option_found:
9464 if (popt->flags & TCC_OPTION_HAS_ARG) {
9465 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9466 optarg = r1;
9467 } else {
9468 if (optind >= argc)
9469 error("argument to '%s' is missing", r);
9470 optarg = argv[optind++];
9472 } else {
9473 if (*r1 != '\0')
9474 goto show_help;
9475 optarg = NULL;
9478 switch(popt->index) {
9479 case TCC_OPTION_HELP:
9480 show_help:
9481 help();
9482 return 1;
9483 case TCC_OPTION_MARKER:
9484 /* '--' enables multiple files input and also ends several
9485 file input */
9486 if (dminus && multiple_files) {
9487 optind--; /* argv[0] will be '--' */
9488 goto end_parse;
9490 dminus = 1;
9491 multiple_files = 1;
9492 case TCC_OPTION_I:
9493 if (tcc_add_include_path(s, optarg) < 0)
9494 error("too many include paths");
9495 break;
9496 case TCC_OPTION_D:
9498 char *sym, *value;
9499 sym = (char *)optarg;
9500 value = strchr(sym, '=');
9501 if (value) {
9502 *value = '\0';
9503 value++;
9505 tcc_define_symbol(s, sym, value);
9507 break;
9508 case TCC_OPTION_U:
9509 tcc_undefine_symbol(s, optarg);
9510 break;
9511 case TCC_OPTION_L:
9512 tcc_add_library_path(s, optarg);
9513 break;
9514 case TCC_OPTION_B:
9515 /* set tcc utilities path (mainly for tcc development) */
9516 tcc_lib_path = optarg;
9517 break;
9518 case TCC_OPTION_l:
9519 dynarray_add((void ***)&files, &nb_files, r);
9520 nb_libraries++;
9521 break;
9522 case TCC_OPTION_bench:
9523 do_bench = 1;
9524 break;
9525 case TCC_OPTION_bt:
9526 num_callers = atoi(optarg);
9527 break;
9528 #ifdef CONFIG_TCC_BCHECK
9529 case TCC_OPTION_b:
9530 do_bounds_check = 1;
9531 do_debug = 1;
9532 break;
9533 #endif
9534 case TCC_OPTION_g:
9535 do_debug = 1;
9536 break;
9537 case TCC_OPTION_c:
9538 multiple_files = 1;
9539 output_type = TCC_OUTPUT_OBJ;
9540 break;
9541 case TCC_OPTION_static:
9542 s->static_link = 1;
9543 break;
9544 case TCC_OPTION_shared:
9545 output_type = TCC_OUTPUT_DLL;
9546 break;
9547 case TCC_OPTION_o:
9548 multiple_files = 1;
9549 outfile = optarg;
9550 break;
9551 case TCC_OPTION_r:
9552 /* generate a .o merging several output files */
9553 reloc_output = 1;
9554 output_type = TCC_OUTPUT_OBJ;
9555 break;
9556 case TCC_OPTION_nostdinc:
9557 s->nostdinc = 1;
9558 break;
9559 case TCC_OPTION_print_search_dirs:
9560 print_search_dirs = 1;
9561 break;
9562 default:
9563 break;
9567 end_parse:
9568 if (print_search_dirs) {
9569 /* enough for Linux kernel */
9570 printf("install: %s/\n", tcc_lib_path);
9571 return 0;
9574 nb_objfiles = nb_files - nb_libraries;
9576 /* if outfile provided without other options, we output an
9577 executable */
9578 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9579 output_type = TCC_OUTPUT_EXE;
9581 /* check -c consistency : only single file handled. XXX: checks file type */
9582 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9583 /* accepts only a single input file */
9584 if (nb_objfiles != 1)
9585 error("cannot specify multiple files with -c");
9586 if (nb_libraries != 0)
9587 error("cannot specify libraries with -c");
9590 /* compute default outfile name */
9591 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9592 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9593 char *ext;
9594 /* add .o extension */
9595 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
9596 ext = strrchr(objfilename, '.');
9597 if (!ext)
9598 goto default_outfile;
9599 strcpy(ext + 1, "o");
9600 } else {
9601 default_outfile:
9602 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9604 outfile = objfilename;
9607 if (do_bench) {
9608 start_time = getclock_us();
9611 tcc_set_output_type(s, output_type);
9613 /* compile or add each files or library */
9614 for(i = 0;i < nb_files; i++) {
9615 const char *filename;
9617 filename = files[i];
9618 if (filename[0] == '-') {
9619 if (tcc_add_library(s, filename + 2) < 0)
9620 error("cannot find %s", filename);
9621 } else {
9622 if (tcc_add_file(s, filename) < 0) {
9623 ret = 1;
9624 goto the_end;
9629 /* free all files */
9630 tcc_free(files);
9632 if (do_bench) {
9633 double total_time;
9634 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9635 if (total_time < 0.001)
9636 total_time = 0.001;
9637 if (total_bytes < 1)
9638 total_bytes = 1;
9639 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9640 tok_ident - TOK_IDENT, total_lines, total_bytes,
9641 total_time, (int)(total_lines / total_time),
9642 total_bytes / total_time / 1000000.0);
9645 if (s->output_type != TCC_OUTPUT_MEMORY) {
9646 tcc_output_file(s, outfile);
9647 ret = 0;
9648 } else {
9649 ret = tcc_run(s, argc - optind, argv + optind);
9651 the_end:
9652 /* XXX: cannot do it with bound checking because of the malloc hooks */
9653 if (!do_bounds_check)
9654 tcc_delete(s);
9656 #ifdef MEM_DEBUG
9657 if (do_bench) {
9658 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9660 #endif
9661 return ret;
9664 #endif