fixed assignment of const struct in struct
[tinycc.git] / tcc.c
blob30a355555cb7391f3ea62973c76e4dfe205282c0
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #endif
38 #ifndef WIN32
39 #include <sys/time.h>
40 #include <sys/ucontext.h>
41 #endif
42 #include "elf.h"
43 #include "stab.h"
44 #ifndef CONFIG_TCC_STATIC
45 #include <dlfcn.h>
46 #endif
48 #include "libtcc.h"
50 /* parser debug */
51 //#define PARSE_DEBUG
52 /* preprocessor debug */
53 //#define PP_DEBUG
54 /* include file debug */
55 //#define INC_DEBUG
57 //#define MEM_DEBUG
59 /* assembler debug */
60 //#define ASM_DEBUG
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
64 //#define TCC_TARGET_ARM /* ARMv4 code generator */
66 /* default target is I386 */
67 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM)
68 #define TCC_TARGET_I386
69 #endif
71 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM)
72 #define CONFIG_TCC_BCHECK /* enable bound checking code */
73 #endif
75 /* define it to include assembler support */
76 #if !defined(TCC_TARGET_ARM)
77 #define CONFIG_TCC_ASM
78 #endif
80 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
81 executables or dlls */
82 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
84 #define INCLUDE_STACK_SIZE 32
85 #define IFDEF_STACK_SIZE 64
86 #define VSTACK_SIZE 64
87 #define STRING_MAX_SIZE 1024
89 #define TOK_HASH_SIZE 2048 /* must be a power of two */
90 #define TOK_ALLOC_INCR 512 /* must be a power of two */
91 #define TOK_STR_ALLOC_INCR_BITS 6
92 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
93 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
95 /* token symbol management */
96 typedef struct TokenSym {
97 struct TokenSym *hash_next;
98 struct Sym *sym_define; /* direct pointer to define */
99 struct Sym *sym_label; /* direct pointer to label */
100 struct Sym *sym_struct; /* direct pointer to structure */
101 struct Sym *sym_identifier; /* direct pointer to identifier */
102 int tok; /* token number */
103 int len;
104 char str[1];
105 } TokenSym;
107 typedef struct CString {
108 int size; /* size in bytes */
109 void *data; /* either 'char *' or 'int *' */
110 int size_allocated;
111 void *data_allocated; /* if non NULL, data has been malloced */
112 } CString;
114 /* type definition */
115 typedef struct CType {
116 int t;
117 struct Sym *ref;
118 } CType;
120 /* constant value */
121 typedef union CValue {
122 long double ld;
123 double d;
124 float f;
125 int i;
126 unsigned int ui;
127 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
128 long long ll;
129 unsigned long long ull;
130 struct CString *cstr;
131 void *ptr;
132 int tab[1];
133 } CValue;
135 /* value on stack */
136 typedef struct SValue {
137 CType type; /* type */
138 unsigned short r; /* register + flags */
139 unsigned short r2; /* second register, used for 'long long'
140 type. If not used, set to VT_CONST */
141 CValue c; /* constant, if VT_CONST */
142 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
143 } SValue;
145 /* symbol management */
146 typedef struct Sym {
147 int v; /* symbol token */
148 int r; /* associated register */
149 int c; /* associated number */
150 CType type; /* associated type */
151 struct Sym *next; /* next related symbol */
152 struct Sym *prev; /* prev symbol in stack */
153 struct Sym *prev_tok; /* previous symbol for this token */
154 } Sym;
156 /* section definition */
157 /* XXX: use directly ELF structure for parameters ? */
158 /* special flag to indicate that the section should not be linked to
159 the other ones */
160 #define SHF_PRIVATE 0x80000000
162 typedef struct Section {
163 unsigned long data_offset; /* current data offset */
164 unsigned char *data; /* section data */
165 unsigned long data_allocated; /* used for realloc() handling */
166 int sh_name; /* elf section name (only used during output) */
167 int sh_num; /* elf section number */
168 int sh_type; /* elf section type */
169 int sh_flags; /* elf section flags */
170 int sh_info; /* elf section info */
171 int sh_addralign; /* elf section alignment */
172 int sh_entsize; /* elf entry size */
173 unsigned long sh_size; /* section size (only used during output) */
174 unsigned long sh_addr; /* address at which the section is relocated */
175 unsigned long sh_offset; /* address at which the section is relocated */
176 int nb_hashed_syms; /* used to resize the hash table */
177 struct Section *link; /* link to another section */
178 struct Section *reloc; /* corresponding section for relocation, if any */
179 struct Section *hash; /* hash table for symbols */
180 struct Section *next;
181 char name[1]; /* section name */
182 } Section;
184 typedef struct DLLReference {
185 int level;
186 char name[1];
187 } DLLReference;
189 /* GNUC attribute definition */
190 typedef struct AttributeDef {
191 int aligned;
192 Section *section;
193 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
194 } AttributeDef;
196 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
197 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
198 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
200 /* stored in 'Sym.c' field */
201 #define FUNC_NEW 1 /* ansi function prototype */
202 #define FUNC_OLD 2 /* old function prototype */
203 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
205 /* stored in 'Sym.r' field */
206 #define FUNC_CDECL 0 /* standard c call */
207 #define FUNC_STDCALL 1 /* pascal c call */
209 /* field 'Sym.t' for macros */
210 #define MACRO_OBJ 0 /* object like macro */
211 #define MACRO_FUNC 1 /* function like macro */
213 /* field 'Sym.r' for C labels */
214 #define LABEL_DEFINED 0 /* label is defined */
215 #define LABEL_FORWARD 1 /* label is forward defined */
216 #define LABEL_DECLARED 2 /* label is declared but never used */
218 /* type_decl() types */
219 #define TYPE_ABSTRACT 1 /* type without variable */
220 #define TYPE_DIRECT 2 /* type with variable */
222 #define IO_BUF_SIZE 8192
224 typedef struct BufferedFile {
225 uint8_t *buf_ptr;
226 uint8_t *buf_end;
227 int fd;
228 int line_num; /* current line number - here to simplify code */
229 int ifndef_macro; /* #ifndef macro / #endif search */
230 int ifndef_macro_saved; /* saved ifndef_macro */
231 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
232 char inc_type; /* type of include */
233 char inc_filename[512]; /* filename specified by the user */
234 char filename[1024]; /* current filename - here to simplify code */
235 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
236 } BufferedFile;
238 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
239 #define CH_EOF (-1) /* end of file */
241 /* parsing state (used to save parser state to reparse part of the
242 source several times) */
243 typedef struct ParseState {
244 int *macro_ptr;
245 int line_num;
246 int tok;
247 CValue tokc;
248 } ParseState;
250 /* used to record tokens */
251 typedef struct TokenString {
252 int *str;
253 int len;
254 int allocated_len;
255 int last_line_num;
256 } TokenString;
258 /* include file cache, used to find files faster and also to eliminate
259 inclusion if the include file is protected by #ifndef ... #endif */
260 typedef struct CachedInclude {
261 int ifndef_macro;
262 char type; /* '"' or '>' to give include type */
263 char filename[1]; /* path specified in #include */
264 } CachedInclude;
266 /* parser */
267 static struct BufferedFile *file;
268 static int ch, tok;
269 static CValue tokc;
270 static CString tokcstr; /* current parsed string, if any */
271 /* additional informations about token */
272 static int tok_flags;
273 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
274 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
275 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
277 static int *macro_ptr, *macro_ptr_allocated;
278 static int *unget_saved_macro_ptr;
279 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
280 static int unget_buffer_enabled;
281 static int parse_flags;
282 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
283 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
284 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
285 token. line feed is also
286 returned at eof */
288 static Section *text_section, *data_section, *bss_section; /* predefined sections */
289 static Section *cur_text_section; /* current section where function code is
290 generated */
291 /* bound check related sections */
292 static Section *bounds_section; /* contains global data bound description */
293 static Section *lbounds_section; /* contains local data bound description */
294 /* symbol sections */
295 static Section *symtab_section, *strtab_section;
297 /* debug sections */
298 static Section *stab_section, *stabstr_section;
300 /* loc : local variable index
301 ind : output code index
302 rsym: return symbol
303 anon_sym: anonymous symbol index
305 static int rsym, anon_sym, ind, loc;
306 /* expression generation modifiers */
307 static int const_wanted; /* true if constant wanted */
308 static int nocode_wanted; /* true if no code generation wanted for an expression */
309 static int global_expr; /* true if compound literals must be allocated
310 globally (used during initializers parsing */
311 static CType func_vt; /* current function return type (used by return
312 instruction) */
313 static int func_vc;
314 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
315 static int tok_ident;
316 static TokenSym **table_ident;
317 static TokenSym *hash_ident[TOK_HASH_SIZE];
318 static char token_buf[STRING_MAX_SIZE + 1];
319 static char *funcname;
320 static Sym *global_stack, *local_stack;
321 static Sym *define_stack;
322 static Sym *global_label_stack, *local_label_stack;
324 static SValue vstack[VSTACK_SIZE], *vtop;
325 /* some predefined types */
326 static CType char_pointer_type, func_old_type, int_type;
327 /* true if isid(c) || isnum(c) */
328 static unsigned char isidnum_table[256];
330 /* compile with debug symbol (and use them if error during execution) */
331 static int do_debug = 0;
333 /* compile with built-in memory and bounds checker */
334 static int do_bounds_check = 0;
336 /* display benchmark infos */
337 #if !defined(LIBTCC)
338 static int do_bench = 0;
339 #endif
340 static int total_lines;
341 static int total_bytes;
343 /* use GNU C extensions */
344 static int gnu_ext = 1;
346 /* use Tiny C extensions */
347 static int tcc_ext = 1;
349 /* max number of callers shown if error */
350 static int num_callers = 6;
351 static const char **rt_bound_error_msg;
353 /* XXX: get rid of this ASAP */
354 static struct TCCState *tcc_state;
356 /* give the path of the tcc libraries */
357 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
359 struct TCCState {
360 int output_type;
362 BufferedFile **include_stack_ptr;
363 int *ifdef_stack_ptr;
365 /* include file handling */
366 char **include_paths;
367 int nb_include_paths;
368 char **sysinclude_paths;
369 int nb_sysinclude_paths;
370 CachedInclude **cached_includes;
371 int nb_cached_includes;
373 char **library_paths;
374 int nb_library_paths;
376 /* array of all loaded dlls (including those referenced by loaded
377 dlls) */
378 DLLReference **loaded_dlls;
379 int nb_loaded_dlls;
381 /* sections */
382 Section **sections;
383 int nb_sections; /* number of sections, including first dummy section */
385 /* got handling */
386 Section *got;
387 Section *plt;
388 unsigned long *got_offsets;
389 int nb_got_offsets;
390 /* give the correspondance from symtab indexes to dynsym indexes */
391 int *symtab_to_dynsym;
393 /* temporary dynamic symbol sections (for dll loading) */
394 Section *dynsymtab_section;
395 /* exported dynamic symbol section */
396 Section *dynsym;
398 int nostdinc; /* if true, no standard headers are added */
399 int nostdlib; /* if true, no standard libraries are added */
401 /* if true, static linking is performed */
402 int static_link;
404 /* if true, all symbols are exported */
405 int rdynamic;
407 /* if true, only link in referenced objects from archive */
408 int alacarte_link;
410 /* C language options */
411 int char_is_unsigned;
413 /* warning switches */
414 int warn_write_strings;
415 int warn_unsupported;
416 int warn_error;
417 int warn_none;
418 int warn_implicit_function_declaration;
420 /* error handling */
421 void *error_opaque;
422 void (*error_func)(void *opaque, const char *msg);
423 int error_set_jmp_enabled;
424 jmp_buf error_jmp_buf;
425 int nb_errors;
427 /* tiny assembler state */
428 Sym *asm_labels;
430 /* see include_stack_ptr */
431 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
433 /* see ifdef_stack_ptr */
434 int ifdef_stack[IFDEF_STACK_SIZE];
437 /* The current value can be: */
438 #define VT_VALMASK 0x00ff
439 #define VT_CONST 0x00f0 /* constant in vc
440 (must be first non register value) */
441 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
442 #define VT_LOCAL 0x00f2 /* offset on stack */
443 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
444 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
445 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
446 #define VT_LVAL 0x0100 /* var is an lvalue */
447 #define VT_SYM 0x0200 /* a symbol value is added */
448 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
449 char/short stored in integer registers) */
450 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
451 dereferencing value */
452 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
453 bounding function call point is in vc */
454 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
455 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
456 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
457 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
459 /* types */
460 #define VT_INT 0 /* integer type */
461 #define VT_BYTE 1 /* signed byte type */
462 #define VT_SHORT 2 /* short type */
463 #define VT_VOID 3 /* void type */
464 #define VT_PTR 4 /* pointer */
465 #define VT_ENUM 5 /* enum definition */
466 #define VT_FUNC 6 /* function type */
467 #define VT_STRUCT 7 /* struct/union definition */
468 #define VT_FLOAT 8 /* IEEE float */
469 #define VT_DOUBLE 9 /* IEEE double */
470 #define VT_LDOUBLE 10 /* IEEE long double */
471 #define VT_BOOL 11 /* ISOC99 boolean type */
472 #define VT_LLONG 12 /* 64 bit integer */
473 #define VT_LONG 13 /* long integer (NEVER USED as type, only
474 during parsing) */
475 #define VT_BTYPE 0x000f /* mask for basic type */
476 #define VT_UNSIGNED 0x0010 /* unsigned type */
477 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
478 #define VT_BITFIELD 0x0040 /* bitfield modifier */
479 #define VT_CONSTANT 0x0800 /* const modifier */
480 #define VT_VOLATILE 0x1000 /* volatile modifier */
481 #define VT_SIGNED 0x2000 /* signed type */
483 /* storage */
484 #define VT_EXTERN 0x00000080 /* extern definition */
485 #define VT_STATIC 0x00000100 /* static variable */
486 #define VT_TYPEDEF 0x00000200 /* typedef definition */
487 #define VT_INLINE 0x00000400 /* inline definition */
489 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
491 /* type mask (except storage) */
492 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
493 #define VT_TYPE (~(VT_STORAGE))
495 /* token values */
497 /* warning: the following compare tokens depend on i386 asm code */
498 #define TOK_ULT 0x92
499 #define TOK_UGE 0x93
500 #define TOK_EQ 0x94
501 #define TOK_NE 0x95
502 #define TOK_ULE 0x96
503 #define TOK_UGT 0x97
504 #define TOK_LT 0x9c
505 #define TOK_GE 0x9d
506 #define TOK_LE 0x9e
507 #define TOK_GT 0x9f
509 #define TOK_LAND 0xa0
510 #define TOK_LOR 0xa1
512 #define TOK_DEC 0xa2
513 #define TOK_MID 0xa3 /* inc/dec, to void constant */
514 #define TOK_INC 0xa4
515 #define TOK_UDIV 0xb0 /* unsigned division */
516 #define TOK_UMOD 0xb1 /* unsigned modulo */
517 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
518 #define TOK_CINT 0xb3 /* number in tokc */
519 #define TOK_CCHAR 0xb4 /* char constant in tokc */
520 #define TOK_STR 0xb5 /* pointer to string in tokc */
521 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
522 #define TOK_LCHAR 0xb7
523 #define TOK_LSTR 0xb8
524 #define TOK_CFLOAT 0xb9 /* float constant */
525 #define TOK_LINENUM 0xba /* line number info */
526 #define TOK_CDOUBLE 0xc0 /* double constant */
527 #define TOK_CLDOUBLE 0xc1 /* long double constant */
528 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
529 #define TOK_ADDC1 0xc3 /* add with carry generation */
530 #define TOK_ADDC2 0xc4 /* add with carry use */
531 #define TOK_SUBC1 0xc5 /* add with carry generation */
532 #define TOK_SUBC2 0xc6 /* add with carry use */
533 #define TOK_CUINT 0xc8 /* unsigned int constant */
534 #define TOK_CLLONG 0xc9 /* long long constant */
535 #define TOK_CULLONG 0xca /* unsigned long long constant */
536 #define TOK_ARROW 0xcb
537 #define TOK_DOTS 0xcc /* three dots */
538 #define TOK_SHR 0xcd /* unsigned shift right */
539 #define TOK_PPNUM 0xce /* preprocessor number */
541 #define TOK_SHL 0x01 /* shift left */
542 #define TOK_SAR 0x02 /* signed shift right */
544 /* assignement operators : normal operator or 0x80 */
545 #define TOK_A_MOD 0xa5
546 #define TOK_A_AND 0xa6
547 #define TOK_A_MUL 0xaa
548 #define TOK_A_ADD 0xab
549 #define TOK_A_SUB 0xad
550 #define TOK_A_DIV 0xaf
551 #define TOK_A_XOR 0xde
552 #define TOK_A_OR 0xfc
553 #define TOK_A_SHL 0x81
554 #define TOK_A_SAR 0x82
556 #ifndef offsetof
557 #define offsetof(type, field) ((size_t) &((type *)0)->field)
558 #endif
560 #ifndef countof
561 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
562 #endif
564 /* WARNING: the content of this string encodes token numbers */
565 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";
567 #define TOK_EOF (-1) /* end of file */
568 #define TOK_LINEFEED 10 /* line feed */
570 /* all identificators and strings have token above that */
571 #define TOK_IDENT 256
573 /* only used for i386 asm opcodes definitions */
574 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
576 #define DEF_BWL(x) \
577 DEF(TOK_ASM_ ## x ## b, #x "b") \
578 DEF(TOK_ASM_ ## x ## w, #x "w") \
579 DEF(TOK_ASM_ ## x ## l, #x "l") \
580 DEF(TOK_ASM_ ## x, #x)
582 #define DEF_WL(x) \
583 DEF(TOK_ASM_ ## x ## w, #x "w") \
584 DEF(TOK_ASM_ ## x ## l, #x "l") \
585 DEF(TOK_ASM_ ## x, #x)
587 #define DEF_FP1(x) \
588 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
589 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
590 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
591 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
593 #define DEF_FP(x) \
594 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
595 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
596 DEF_FP1(x)
598 #define DEF_ASMTEST(x) \
599 DEF_ASM(x ## o) \
600 DEF_ASM(x ## no) \
601 DEF_ASM(x ## b) \
602 DEF_ASM(x ## c) \
603 DEF_ASM(x ## nae) \
604 DEF_ASM(x ## nb) \
605 DEF_ASM(x ## nc) \
606 DEF_ASM(x ## ae) \
607 DEF_ASM(x ## e) \
608 DEF_ASM(x ## z) \
609 DEF_ASM(x ## ne) \
610 DEF_ASM(x ## nz) \
611 DEF_ASM(x ## be) \
612 DEF_ASM(x ## na) \
613 DEF_ASM(x ## nbe) \
614 DEF_ASM(x ## a) \
615 DEF_ASM(x ## s) \
616 DEF_ASM(x ## ns) \
617 DEF_ASM(x ## p) \
618 DEF_ASM(x ## pe) \
619 DEF_ASM(x ## np) \
620 DEF_ASM(x ## po) \
621 DEF_ASM(x ## l) \
622 DEF_ASM(x ## nge) \
623 DEF_ASM(x ## nl) \
624 DEF_ASM(x ## ge) \
625 DEF_ASM(x ## le) \
626 DEF_ASM(x ## ng) \
627 DEF_ASM(x ## nle) \
628 DEF_ASM(x ## g)
630 #define TOK_ASM_int TOK_INT
632 enum {
633 TOK_LAST = TOK_IDENT - 1,
634 #define DEF(id, str) id,
635 #include "tcctok.h"
636 #undef DEF
639 static const char tcc_keywords[] =
640 #define DEF(id, str) str "\0"
641 #include "tcctok.h"
642 #undef DEF
645 #define TOK_UIDENT TOK_DEFINE
647 #ifdef WIN32
648 #define snprintf _snprintf
649 #define vsnprintf _vsnprintf
650 #endif
652 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
653 /* currently incorrect */
654 long double strtold(const char *nptr, char **endptr)
656 return (long double)strtod(nptr, endptr);
658 float strtof(const char *nptr, char **endptr)
660 return (float)strtod(nptr, endptr);
662 #else
663 /* XXX: need to define this to use them in non ISOC99 context */
664 extern float strtof (const char *__nptr, char **__endptr);
665 extern long double strtold (const char *__nptr, char **__endptr);
666 #endif
668 static char *pstrcpy(char *buf, int buf_size, const char *s);
669 static char *pstrcat(char *buf, int buf_size, const char *s);
671 static void next(void);
672 static void next_nomacro(void);
673 static void parse_expr_type(CType *type);
674 static void expr_type(CType *type);
675 static void unary_type(CType *type);
676 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
677 int case_reg, int is_expr);
678 static int expr_const(void);
679 static void expr_eq(void);
680 static void gexpr(void);
681 static void decl(int l);
682 static void decl_initializer(CType *type, Section *sec, unsigned long c,
683 int first, int size_only);
684 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
685 int has_init, int v, int scope);
686 int gv(int rc);
687 void gv2(int rc1, int rc2);
688 void move_reg(int r, int s);
689 void save_regs(int n);
690 void save_reg(int r);
691 void vpop(void);
692 void vswap(void);
693 void vdup(void);
694 int get_reg(int rc);
695 int get_reg_ex(int rc,int rc2);
697 static void macro_subst(TokenString *tok_str, Sym **nested_list,
698 const int *macro_str, int can_read_stream);
699 int save_reg_forced(int r);
700 void gen_op(int op);
701 void force_charshort_cast(int t);
702 static void gen_cast(CType *type);
703 void vstore(void);
704 static Sym *sym_find(int v);
705 static Sym *sym_push(int v, CType *type, int r, int c);
707 /* type handling */
708 static int type_size(CType *type, int *a);
709 static inline CType *pointed_type(CType *type);
710 static int pointed_size(CType *type);
711 static int lvalue_type(int t);
712 static int parse_btype(CType *type, AttributeDef *ad);
713 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
714 static int is_compatible_types(CType *type1, CType *type2);
716 int ieee_finite(double d);
717 void error(const char *fmt, ...);
718 void vpushi(int v);
719 void vrott(int n);
720 static void vpush_global_sym(CType *type, int v);
721 void vset(CType *type, int r, int v);
722 void type_to_str(char *buf, int buf_size,
723 CType *type, const char *varstr);
724 char *get_tok_str(int v, CValue *cv);
725 static Sym *get_sym_ref(CType *type, Section *sec,
726 unsigned long offset, unsigned long size);
727 static Sym *external_global_sym(int v, CType *type, int r);
729 /* section generation */
730 static void section_realloc(Section *sec, unsigned long new_size);
731 static void *section_ptr_add(Section *sec, unsigned long size);
732 static void put_extern_sym(Sym *sym, Section *section,
733 unsigned long value, unsigned long size);
734 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
735 static int put_elf_str(Section *s, const char *sym);
736 static int put_elf_sym(Section *s,
737 unsigned long value, unsigned long size,
738 int info, int other, int shndx, const char *name);
739 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
740 int info, int sh_num, const char *name);
741 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
742 int type, int symbol);
743 static void put_stabs(const char *str, int type, int other, int desc,
744 unsigned long value);
745 static void put_stabs_r(const char *str, int type, int other, int desc,
746 unsigned long value, Section *sec, int sym_index);
747 static void put_stabn(int type, int other, int desc, int value);
748 static void put_stabd(int type, int other, int desc);
749 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
751 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
752 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
753 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
755 /* tccasm.c */
757 #ifdef CONFIG_TCC_ASM
759 typedef struct ExprValue {
760 uint32_t v;
761 Sym *sym;
762 } ExprValue;
764 #define MAX_ASM_OPERANDS 30
766 typedef struct ASMOperand {
767 int id; /* GCC 3 optionnal identifier (0 if number only supported */
768 char *constraint;
769 char asm_str[16]; /* computed asm string for operand */
770 SValue *vt; /* C value of the expression */
771 int ref_index; /* if >= 0, gives reference to a output constraint */
772 int priority; /* priority, used to assign registers */
773 int reg; /* if >= 0, register number used for this operand */
774 int is_llong; /* true if double register value */
775 } ASMOperand;
777 static void asm_expr(TCCState *s1, ExprValue *pe);
778 static int asm_int_expr(TCCState *s1);
779 static int find_constraint(ASMOperand *operands, int nb_operands,
780 const char *name, const char **pp);
782 static int tcc_assemble(TCCState *s1, int do_preprocess);
784 #endif
786 static void asm_instr(void);
788 /* true if float/double/long double type */
789 static inline int is_float(int t)
791 int bt;
792 bt = t & VT_BTYPE;
793 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
796 #ifdef TCC_TARGET_I386
797 #include "i386-gen.c"
798 #endif
800 #ifdef TCC_TARGET_ARM
801 #include "arm-gen.c"
802 #endif
804 #ifdef CONFIG_TCC_STATIC
806 #define RTLD_LAZY 0x001
807 #define RTLD_NOW 0x002
808 #define RTLD_GLOBAL 0x100
809 #define RTLD_DEFAULT NULL
811 /* dummy function for profiling */
812 void *dlopen(const char *filename, int flag)
814 return NULL;
817 const char *dlerror(void)
819 return "error";
822 typedef struct TCCSyms {
823 char *str;
824 void *ptr;
825 } TCCSyms;
827 #define TCCSYM(a) { #a, &a, },
829 /* add the symbol you want here if no dynamic linking is done */
830 static TCCSyms tcc_syms[] = {
831 TCCSYM(printf)
832 TCCSYM(fprintf)
833 TCCSYM(fopen)
834 TCCSYM(fclose)
835 { NULL, NULL },
838 void *dlsym(void *handle, const char *symbol)
840 TCCSyms *p;
841 p = tcc_syms;
842 while (p->str != NULL) {
843 if (!strcmp(p->str, symbol))
844 return p->ptr;
845 p++;
847 return NULL;
850 #endif
852 /********************************************************/
854 /* we use our own 'finite' function to avoid potential problems with
855 non standard math libs */
856 /* XXX: endianness dependent */
857 int ieee_finite(double d)
859 int *p = (int *)&d;
860 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
863 /* copy a string and truncate it. */
864 static char *pstrcpy(char *buf, int buf_size, const char *s)
866 char *q, *q_end;
867 int c;
869 if (buf_size > 0) {
870 q = buf;
871 q_end = buf + buf_size - 1;
872 while (q < q_end) {
873 c = *s++;
874 if (c == '\0')
875 break;
876 *q++ = c;
878 *q = '\0';
880 return buf;
883 /* strcat and truncate. */
884 static char *pstrcat(char *buf, int buf_size, const char *s)
886 int len;
887 len = strlen(buf);
888 if (len < buf_size)
889 pstrcpy(buf + len, buf_size - len, s);
890 return buf;
893 /* memory management */
894 #ifdef MEM_DEBUG
895 int mem_cur_size;
896 int mem_max_size;
897 #endif
899 static inline void tcc_free(void *ptr)
901 #ifdef MEM_DEBUG
902 mem_cur_size -= malloc_usable_size(ptr);
903 #endif
904 free(ptr);
907 static void *tcc_malloc(unsigned long size)
909 void *ptr;
910 ptr = malloc(size);
911 if (!ptr && size)
912 error("memory full");
913 #ifdef MEM_DEBUG
914 mem_cur_size += malloc_usable_size(ptr);
915 if (mem_cur_size > mem_max_size)
916 mem_max_size = mem_cur_size;
917 #endif
918 return ptr;
921 static void *tcc_mallocz(unsigned long size)
923 void *ptr;
924 ptr = tcc_malloc(size);
925 memset(ptr, 0, size);
926 return ptr;
929 static inline void *tcc_realloc(void *ptr, unsigned long size)
931 void *ptr1;
932 #ifdef MEM_DEBUG
933 mem_cur_size -= malloc_usable_size(ptr);
934 #endif
935 ptr1 = realloc(ptr, size);
936 #ifdef MEM_DEBUG
937 /* NOTE: count not correct if alloc error, but not critical */
938 mem_cur_size += malloc_usable_size(ptr1);
939 if (mem_cur_size > mem_max_size)
940 mem_max_size = mem_cur_size;
941 #endif
942 return ptr1;
945 static char *tcc_strdup(const char *str)
947 char *ptr;
948 ptr = tcc_malloc(strlen(str) + 1);
949 strcpy(ptr, str);
950 return ptr;
953 #define free(p) use_tcc_free(p)
954 #define malloc(s) use_tcc_malloc(s)
955 #define realloc(p, s) use_tcc_realloc(p, s)
957 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
959 int nb, nb_alloc;
960 void **pp;
962 nb = *nb_ptr;
963 pp = *ptab;
964 /* every power of two we double array size */
965 if ((nb & (nb - 1)) == 0) {
966 if (!nb)
967 nb_alloc = 1;
968 else
969 nb_alloc = nb * 2;
970 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
971 if (!pp)
972 error("memory full");
973 *ptab = pp;
975 pp[nb++] = data;
976 *nb_ptr = nb;
979 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
981 Section *sec;
983 sec = tcc_mallocz(sizeof(Section) + strlen(name));
984 strcpy(sec->name, name);
985 sec->sh_type = sh_type;
986 sec->sh_flags = sh_flags;
987 switch(sh_type) {
988 case SHT_HASH:
989 case SHT_REL:
990 case SHT_DYNSYM:
991 case SHT_SYMTAB:
992 case SHT_DYNAMIC:
993 sec->sh_addralign = 4;
994 break;
995 case SHT_STRTAB:
996 sec->sh_addralign = 1;
997 break;
998 default:
999 sec->sh_addralign = 32; /* default conservative alignment */
1000 break;
1003 /* only add section if not private */
1004 if (!(sh_flags & SHF_PRIVATE)) {
1005 sec->sh_num = s1->nb_sections;
1006 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1008 return sec;
1011 static void free_section(Section *s)
1013 tcc_free(s->data);
1014 tcc_free(s);
1017 /* realloc section and set its content to zero */
1018 static void section_realloc(Section *sec, unsigned long new_size)
1020 unsigned long size;
1021 unsigned char *data;
1023 size = sec->data_allocated;
1024 if (size == 0)
1025 size = 1;
1026 while (size < new_size)
1027 size = size * 2;
1028 data = tcc_realloc(sec->data, size);
1029 if (!data)
1030 error("memory full");
1031 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1032 sec->data = data;
1033 sec->data_allocated = size;
1036 /* reserve at least 'size' bytes in section 'sec' from
1037 sec->data_offset. */
1038 static void *section_ptr_add(Section *sec, unsigned long size)
1040 unsigned long offset, offset1;
1042 offset = sec->data_offset;
1043 offset1 = offset + size;
1044 if (offset1 > sec->data_allocated)
1045 section_realloc(sec, offset1);
1046 sec->data_offset = offset1;
1047 return sec->data + offset;
1050 /* return a reference to a section, and create it if it does not
1051 exists */
1052 Section *find_section(TCCState *s1, const char *name)
1054 Section *sec;
1055 int i;
1056 for(i = 1; i < s1->nb_sections; i++) {
1057 sec = s1->sections[i];
1058 if (!strcmp(name, sec->name))
1059 return sec;
1061 /* sections are created as PROGBITS */
1062 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1065 /* update sym->c so that it points to an external symbol in section
1066 'section' with value 'value' */
1067 static void put_extern_sym(Sym *sym, Section *section,
1068 unsigned long value, unsigned long size)
1070 int sym_type, sym_bind, sh_num, info;
1071 Elf32_Sym *esym;
1072 const char *name;
1074 if (section)
1075 sh_num = section->sh_num;
1076 else
1077 sh_num = SHN_UNDEF;
1078 if (!sym->c) {
1079 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1080 sym_type = STT_FUNC;
1081 else
1082 sym_type = STT_OBJECT;
1083 if (sym->type.t & VT_STATIC)
1084 sym_bind = STB_LOCAL;
1085 else
1086 sym_bind = STB_GLOBAL;
1088 name = get_tok_str(sym->v, NULL);
1089 #ifdef CONFIG_TCC_BCHECK
1090 if (do_bounds_check) {
1091 char buf[32];
1093 /* XXX: avoid doing that for statics ? */
1094 /* if bound checking is activated, we change some function
1095 names by adding the "__bound" prefix */
1096 switch(sym->v) {
1097 #if 0
1098 /* XXX: we rely only on malloc hooks */
1099 case TOK_malloc:
1100 case TOK_free:
1101 case TOK_realloc:
1102 case TOK_memalign:
1103 case TOK_calloc:
1104 #endif
1105 case TOK_memcpy:
1106 case TOK_memmove:
1107 case TOK_memset:
1108 case TOK_strlen:
1109 case TOK_strcpy:
1110 strcpy(buf, "__bound_");
1111 strcat(buf, name);
1112 name = buf;
1113 break;
1116 #endif
1117 info = ELF32_ST_INFO(sym_bind, sym_type);
1118 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1119 } else {
1120 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1121 esym->st_value = value;
1122 esym->st_size = size;
1123 esym->st_shndx = sh_num;
1127 /* add a new relocation entry to symbol 'sym' in section 's' */
1128 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1130 if (!sym->c)
1131 put_extern_sym(sym, NULL, 0, 0);
1132 /* now we can add ELF relocation info */
1133 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1136 static inline int isid(int c)
1138 return (c >= 'a' && c <= 'z') ||
1139 (c >= 'A' && c <= 'Z') ||
1140 c == '_';
1143 static inline int isnum(int c)
1145 return c >= '0' && c <= '9';
1148 static inline int isoct(int c)
1150 return c >= '0' && c <= '7';
1153 static inline int toup(int c)
1155 if (c >= 'a' && c <= 'z')
1156 return c - 'a' + 'A';
1157 else
1158 return c;
1161 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1163 int len;
1164 len = strlen(buf);
1165 vsnprintf(buf + len, buf_size - len, fmt, ap);
1168 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1170 va_list ap;
1171 va_start(ap, fmt);
1172 strcat_vprintf(buf, buf_size, fmt, ap);
1173 va_end(ap);
1176 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1178 char buf[2048];
1179 BufferedFile **f;
1181 buf[0] = '\0';
1182 if (file) {
1183 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1184 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1185 (*f)->filename, (*f)->line_num);
1186 if (file->line_num > 0) {
1187 strcat_printf(buf, sizeof(buf),
1188 "%s:%d: ", file->filename, file->line_num);
1189 } else {
1190 strcat_printf(buf, sizeof(buf),
1191 "%s: ", file->filename);
1193 } else {
1194 strcat_printf(buf, sizeof(buf),
1195 "tcc: ");
1197 if (is_warning)
1198 strcat_printf(buf, sizeof(buf), "warning: ");
1199 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1201 if (!s1->error_func) {
1202 /* default case: stderr */
1203 fprintf(stderr, "%s\n", buf);
1204 } else {
1205 s1->error_func(s1->error_opaque, buf);
1207 if (!is_warning || s1->warn_error)
1208 s1->nb_errors++;
1211 #ifdef LIBTCC
1212 void tcc_set_error_func(TCCState *s, void *error_opaque,
1213 void (*error_func)(void *opaque, const char *msg))
1215 s->error_opaque = error_opaque;
1216 s->error_func = error_func;
1218 #endif
1220 /* error without aborting current compilation */
1221 void error_noabort(const char *fmt, ...)
1223 TCCState *s1 = tcc_state;
1224 va_list ap;
1226 va_start(ap, fmt);
1227 error1(s1, 0, fmt, ap);
1228 va_end(ap);
1231 void error(const char *fmt, ...)
1233 TCCState *s1 = tcc_state;
1234 va_list ap;
1236 va_start(ap, fmt);
1237 error1(s1, 0, fmt, ap);
1238 va_end(ap);
1239 /* better than nothing: in some cases, we accept to handle errors */
1240 if (s1->error_set_jmp_enabled) {
1241 longjmp(s1->error_jmp_buf, 1);
1242 } else {
1243 /* XXX: eliminate this someday */
1244 exit(1);
1248 void expect(const char *msg)
1250 error("%s expected", msg);
1253 void warning(const char *fmt, ...)
1255 TCCState *s1 = tcc_state;
1256 va_list ap;
1258 if (s1->warn_none)
1259 return;
1261 va_start(ap, fmt);
1262 error1(s1, 1, fmt, ap);
1263 va_end(ap);
1266 void skip(int c)
1268 if (tok != c)
1269 error("'%c' expected", c);
1270 next();
1273 static void test_lvalue(void)
1275 if (!(vtop->r & VT_LVAL))
1276 expect("lvalue");
1279 /* allocate a new token */
1280 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1282 TokenSym *ts, **ptable;
1283 int i;
1285 if (tok_ident >= SYM_FIRST_ANOM)
1286 error("memory full");
1288 /* expand token table if needed */
1289 i = tok_ident - TOK_IDENT;
1290 if ((i % TOK_ALLOC_INCR) == 0) {
1291 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1292 if (!ptable)
1293 error("memory full");
1294 table_ident = ptable;
1297 ts = tcc_malloc(sizeof(TokenSym) + len);
1298 table_ident[i] = ts;
1299 ts->tok = tok_ident++;
1300 ts->sym_define = NULL;
1301 ts->sym_label = NULL;
1302 ts->sym_struct = NULL;
1303 ts->sym_identifier = NULL;
1304 ts->len = len;
1305 ts->hash_next = NULL;
1306 memcpy(ts->str, str, len);
1307 ts->str[len] = '\0';
1308 *pts = ts;
1309 return ts;
1312 #define TOK_HASH_INIT 1
1313 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1315 /* find a token and add it if not found */
1316 static TokenSym *tok_alloc(const char *str, int len)
1318 TokenSym *ts, **pts;
1319 int i;
1320 unsigned int h;
1322 h = TOK_HASH_INIT;
1323 for(i=0;i<len;i++)
1324 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1325 h &= (TOK_HASH_SIZE - 1);
1327 pts = &hash_ident[h];
1328 for(;;) {
1329 ts = *pts;
1330 if (!ts)
1331 break;
1332 if (ts->len == len && !memcmp(ts->str, str, len))
1333 return ts;
1334 pts = &(ts->hash_next);
1336 return tok_alloc_new(pts, str, len);
1339 /* CString handling */
1341 static void cstr_realloc(CString *cstr, int new_size)
1343 int size;
1344 void *data;
1346 size = cstr->size_allocated;
1347 if (size == 0)
1348 size = 8; /* no need to allocate a too small first string */
1349 while (size < new_size)
1350 size = size * 2;
1351 data = tcc_realloc(cstr->data_allocated, size);
1352 if (!data)
1353 error("memory full");
1354 cstr->data_allocated = data;
1355 cstr->size_allocated = size;
1356 cstr->data = data;
1359 /* add a byte */
1360 static void cstr_ccat(CString *cstr, int ch)
1362 int size;
1363 size = cstr->size + 1;
1364 if (size > cstr->size_allocated)
1365 cstr_realloc(cstr, size);
1366 ((unsigned char *)cstr->data)[size - 1] = ch;
1367 cstr->size = size;
1370 static void cstr_cat(CString *cstr, const char *str)
1372 int c;
1373 for(;;) {
1374 c = *str;
1375 if (c == '\0')
1376 break;
1377 cstr_ccat(cstr, c);
1378 str++;
1382 /* add a wide char */
1383 static void cstr_wccat(CString *cstr, int ch)
1385 int size;
1386 size = cstr->size + sizeof(int);
1387 if (size > cstr->size_allocated)
1388 cstr_realloc(cstr, size);
1389 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1390 cstr->size = size;
1393 static void cstr_new(CString *cstr)
1395 memset(cstr, 0, sizeof(CString));
1398 /* free string and reset it to NULL */
1399 static void cstr_free(CString *cstr)
1401 tcc_free(cstr->data_allocated);
1402 cstr_new(cstr);
1405 #define cstr_reset(cstr) cstr_free(cstr)
1407 static CString *cstr_dup(CString *cstr1)
1409 CString *cstr;
1410 int size;
1412 cstr = tcc_malloc(sizeof(CString));
1413 size = cstr1->size;
1414 cstr->size = size;
1415 cstr->size_allocated = size;
1416 cstr->data_allocated = tcc_malloc(size);
1417 cstr->data = cstr->data_allocated;
1418 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1419 return cstr;
1422 /* XXX: unicode ? */
1423 static void add_char(CString *cstr, int c)
1425 if (c == '\'' || c == '\"' || c == '\\') {
1426 /* XXX: could be more precise if char or string */
1427 cstr_ccat(cstr, '\\');
1429 if (c >= 32 && c <= 126) {
1430 cstr_ccat(cstr, c);
1431 } else {
1432 cstr_ccat(cstr, '\\');
1433 if (c == '\n') {
1434 cstr_ccat(cstr, 'n');
1435 } else {
1436 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1437 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1438 cstr_ccat(cstr, '0' + (c & 7));
1443 /* XXX: buffer overflow */
1444 /* XXX: float tokens */
1445 char *get_tok_str(int v, CValue *cv)
1447 static char buf[STRING_MAX_SIZE + 1];
1448 static CString cstr_buf;
1449 CString *cstr;
1450 unsigned char *q;
1451 char *p;
1452 int i, len;
1454 /* NOTE: to go faster, we give a fixed buffer for small strings */
1455 cstr_reset(&cstr_buf);
1456 cstr_buf.data = buf;
1457 cstr_buf.size_allocated = sizeof(buf);
1458 p = buf;
1460 switch(v) {
1461 case TOK_CINT:
1462 case TOK_CUINT:
1463 /* XXX: not quite exact, but only useful for testing */
1464 sprintf(p, "%u", cv->ui);
1465 break;
1466 case TOK_CLLONG:
1467 case TOK_CULLONG:
1468 /* XXX: not quite exact, but only useful for testing */
1469 sprintf(p, "%Lu", cv->ull);
1470 break;
1471 case TOK_CCHAR:
1472 case TOK_LCHAR:
1473 cstr_ccat(&cstr_buf, '\'');
1474 add_char(&cstr_buf, cv->i);
1475 cstr_ccat(&cstr_buf, '\'');
1476 cstr_ccat(&cstr_buf, '\0');
1477 break;
1478 case TOK_PPNUM:
1479 cstr = cv->cstr;
1480 len = cstr->size - 1;
1481 for(i=0;i<len;i++)
1482 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1483 cstr_ccat(&cstr_buf, '\0');
1484 break;
1485 case TOK_STR:
1486 case TOK_LSTR:
1487 cstr = cv->cstr;
1488 cstr_ccat(&cstr_buf, '\"');
1489 if (v == TOK_STR) {
1490 len = cstr->size - 1;
1491 for(i=0;i<len;i++)
1492 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1493 } else {
1494 len = (cstr->size / sizeof(int)) - 1;
1495 for(i=0;i<len;i++)
1496 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1498 cstr_ccat(&cstr_buf, '\"');
1499 cstr_ccat(&cstr_buf, '\0');
1500 break;
1501 case TOK_LT:
1502 v = '<';
1503 goto addv;
1504 case TOK_GT:
1505 v = '>';
1506 goto addv;
1507 case TOK_A_SHL:
1508 return strcpy(p, "<<=");
1509 case TOK_A_SAR:
1510 return strcpy(p, ">>=");
1511 default:
1512 if (v < TOK_IDENT) {
1513 /* search in two bytes table */
1514 q = tok_two_chars;
1515 while (*q) {
1516 if (q[2] == v) {
1517 *p++ = q[0];
1518 *p++ = q[1];
1519 *p = '\0';
1520 return buf;
1522 q += 3;
1524 addv:
1525 *p++ = v;
1526 *p = '\0';
1527 } else if (v < tok_ident) {
1528 return table_ident[v - TOK_IDENT]->str;
1529 } else if (v >= SYM_FIRST_ANOM) {
1530 /* special name for anonymous symbol */
1531 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1532 } else {
1533 /* should never happen */
1534 return NULL;
1536 break;
1538 return cstr_buf.data;
1541 /* push, without hashing */
1542 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1544 Sym *s;
1545 s = tcc_malloc(sizeof(Sym));
1546 s->v = v;
1547 s->type.t = t;
1548 s->c = c;
1549 s->next = NULL;
1550 /* add in stack */
1551 s->prev = *ps;
1552 *ps = s;
1553 return s;
1556 /* find a symbol and return its associated structure. 's' is the top
1557 of the symbol stack */
1558 static Sym *sym_find2(Sym *s, int v)
1560 while (s) {
1561 if (s->v == v)
1562 return s;
1563 s = s->prev;
1565 return NULL;
1568 /* structure lookup */
1569 static inline Sym *struct_find(int v)
1571 v -= TOK_IDENT;
1572 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1573 return NULL;
1574 return table_ident[v]->sym_struct;
1577 /* find an identifier */
1578 static inline Sym *sym_find(int v)
1580 v -= TOK_IDENT;
1581 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1582 return NULL;
1583 return table_ident[v]->sym_identifier;
1586 /* push a given symbol on the symbol stack */
1587 static Sym *sym_push(int v, CType *type, int r, int c)
1589 Sym *s, **ps;
1590 TokenSym *ts;
1592 if (local_stack)
1593 ps = &local_stack;
1594 else
1595 ps = &global_stack;
1596 s = sym_push2(ps, v, type->t, c);
1597 s->type.ref = type->ref;
1598 s->r = r;
1599 /* don't record fields or anonymous symbols */
1600 /* XXX: simplify */
1601 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1602 /* record symbol in token array */
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 s->prev_tok = *ps;
1609 *ps = s;
1611 return s;
1614 /* push a global identifier */
1615 static Sym *global_identifier_push(int v, int t, int c)
1617 Sym *s, **ps;
1618 s = sym_push2(&global_stack, v, t, c);
1619 /* don't record anonymous symbol */
1620 if (v < SYM_FIRST_ANOM) {
1621 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1622 /* modify the top most local identifier, so that
1623 sym_identifier will point to 's' when popped */
1624 while (*ps != NULL)
1625 ps = &(*ps)->prev_tok;
1626 s->prev_tok = NULL;
1627 *ps = s;
1629 return s;
1632 /* pop symbols until top reaches 'b' */
1633 static void sym_pop(Sym **ptop, Sym *b)
1635 Sym *s, *ss, **ps;
1636 TokenSym *ts;
1637 int v;
1639 s = *ptop;
1640 while(s != b) {
1641 ss = s->prev;
1642 v = s->v;
1643 /* remove symbol in token array */
1644 /* XXX: simplify */
1645 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1646 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1647 if (v & SYM_STRUCT)
1648 ps = &ts->sym_struct;
1649 else
1650 ps = &ts->sym_identifier;
1651 *ps = s->prev_tok;
1653 tcc_free(s);
1654 s = ss;
1656 *ptop = b;
1659 /* I/O layer */
1661 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1663 int fd;
1664 BufferedFile *bf;
1666 fd = open(filename, O_RDONLY);
1667 if (fd < 0)
1668 return NULL;
1669 bf = tcc_malloc(sizeof(BufferedFile));
1670 if (!bf) {
1671 close(fd);
1672 return NULL;
1674 bf->fd = fd;
1675 bf->buf_ptr = bf->buffer;
1676 bf->buf_end = bf->buffer;
1677 bf->buffer[0] = CH_EOB; /* put eob symbol */
1678 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1679 bf->line_num = 1;
1680 bf->ifndef_macro = 0;
1681 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1682 // printf("opening '%s'\n", filename);
1683 return bf;
1686 void tcc_close(BufferedFile *bf)
1688 total_lines += bf->line_num;
1689 close(bf->fd);
1690 tcc_free(bf);
1693 /* fill input buffer and peek next char */
1694 static int tcc_peekc_slow(BufferedFile *bf)
1696 int len;
1697 /* only tries to read if really end of buffer */
1698 if (bf->buf_ptr >= bf->buf_end) {
1699 if (bf->fd != -1) {
1700 #if defined(PARSE_DEBUG)
1701 len = 8;
1702 #else
1703 len = IO_BUF_SIZE;
1704 #endif
1705 len = read(bf->fd, bf->buffer, len);
1706 if (len < 0)
1707 len = 0;
1708 } else {
1709 len = 0;
1711 total_bytes += len;
1712 bf->buf_ptr = bf->buffer;
1713 bf->buf_end = bf->buffer + len;
1714 *bf->buf_end = CH_EOB;
1716 if (bf->buf_ptr < bf->buf_end) {
1717 return bf->buf_ptr[0];
1718 } else {
1719 bf->buf_ptr = bf->buf_end;
1720 return CH_EOF;
1724 /* return the current character, handling end of block if necessary
1725 (but not stray) */
1726 static int handle_eob(void)
1728 return tcc_peekc_slow(file);
1731 /* read next char from current input file and handle end of input buffer */
1732 static inline void inp(void)
1734 ch = *(++(file->buf_ptr));
1735 /* end of buffer/file handling */
1736 if (ch == CH_EOB)
1737 ch = handle_eob();
1740 /* handle '\[\r]\n' */
1741 static void handle_stray(void)
1743 while (ch == '\\') {
1744 inp();
1745 if (ch == '\n') {
1746 file->line_num++;
1747 inp();
1748 } else if (ch == '\r') {
1749 inp();
1750 if (ch != '\n')
1751 goto fail;
1752 file->line_num++;
1753 inp();
1754 } else {
1755 fail:
1756 error("stray '\\' in program");
1761 /* skip the stray and handle the \\n case. Output an error if
1762 incorrect char after the stray */
1763 static int handle_stray1(uint8_t *p)
1765 int c;
1767 if (p >= file->buf_end) {
1768 file->buf_ptr = p;
1769 c = handle_eob();
1770 p = file->buf_ptr;
1771 if (c == '\\')
1772 goto parse_stray;
1773 } else {
1774 parse_stray:
1775 file->buf_ptr = p;
1776 ch = *p;
1777 handle_stray();
1778 p = file->buf_ptr;
1779 c = *p;
1781 return c;
1784 /* handle just the EOB case, but not stray */
1785 #define PEEKC_EOB(c, p)\
1787 p++;\
1788 c = *p;\
1789 if (c == '\\') {\
1790 file->buf_ptr = p;\
1791 c = handle_eob();\
1792 p = file->buf_ptr;\
1796 /* handle the complicated stray case */
1797 #define PEEKC(c, p)\
1799 p++;\
1800 c = *p;\
1801 if (c == '\\') {\
1802 c = handle_stray1(p);\
1803 p = file->buf_ptr;\
1807 /* input with '\[\r]\n' handling. Note that this function cannot
1808 handle other characters after '\', so you cannot call it inside
1809 strings or comments */
1810 static void minp(void)
1812 inp();
1813 if (ch == '\\')
1814 handle_stray();
1818 /* single line C++ comments */
1819 static uint8_t *parse_line_comment(uint8_t *p)
1821 int c;
1823 p++;
1824 for(;;) {
1825 c = *p;
1826 if (c == '\n' || c == CH_EOF) {
1827 break;
1828 } else if (c == '\\') {
1829 PEEKC_EOB(c, p);
1830 if (c == '\n') {
1831 file->line_num++;
1832 PEEKC_EOB(c, p);
1833 } else if (c == '\r') {
1834 PEEKC_EOB(c, p);
1835 if (c == '\n') {
1836 file->line_num++;
1837 PEEKC_EOB(c, p);
1840 } else {
1841 p++;
1844 return p;
1847 /* C comments */
1848 static uint8_t *parse_comment(uint8_t *p)
1850 int c;
1852 p++;
1853 for(;;) {
1854 /* fast skip loop */
1855 for(;;) {
1856 c = *p;
1857 if (c == '\n' || c == '*' || c == '\\')
1858 break;
1859 p++;
1860 c = *p;
1861 if (c == '\n' || c == '*' || c == '\\')
1862 break;
1863 p++;
1865 /* now we can handle all the cases */
1866 if (c == '\n') {
1867 file->line_num++;
1868 p++;
1869 } else if (c == '*') {
1870 p++;
1871 for(;;) {
1872 c = *p;
1873 if (c == '*') {
1874 p++;
1875 } else if (c == '/') {
1876 goto end_of_comment;
1877 } else if (c == '\\') {
1878 file->buf_ptr = p;
1879 c = handle_eob();
1880 p = file->buf_ptr;
1881 if (c == '\\') {
1882 /* skip '\[\r]\n', otherwise just skip the stray */
1883 while (c == '\\') {
1884 PEEKC_EOB(c, p);
1885 if (c == '\n') {
1886 file->line_num++;
1887 PEEKC_EOB(c, p);
1888 } else if (c == '\r') {
1889 PEEKC_EOB(c, p);
1890 if (c == '\n') {
1891 file->line_num++;
1892 PEEKC_EOB(c, p);
1894 } else {
1895 goto after_star;
1899 } else {
1900 break;
1903 after_star: ;
1904 } else {
1905 /* stray, eob or eof */
1906 file->buf_ptr = p;
1907 c = handle_eob();
1908 p = file->buf_ptr;
1909 if (c == CH_EOF) {
1910 error("unexpected end of file in comment");
1911 } else if (c == '\\') {
1912 p++;
1916 end_of_comment:
1917 p++;
1918 return p;
1921 #define cinp minp
1923 /* space exlcuding newline */
1924 static inline int is_space(int ch)
1926 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1929 static inline void skip_spaces(void)
1931 while (is_space(ch))
1932 cinp();
1935 /* parse a string without interpreting escapes */
1936 static uint8_t *parse_pp_string(uint8_t *p,
1937 int sep, CString *str)
1939 int c;
1940 p++;
1941 for(;;) {
1942 c = *p;
1943 if (c == sep) {
1944 break;
1945 } else if (c == '\\') {
1946 file->buf_ptr = p;
1947 c = handle_eob();
1948 p = file->buf_ptr;
1949 if (c == CH_EOF) {
1950 unterminated_string:
1951 /* XXX: indicate line number of start of string */
1952 error("missing terminating %c character", sep);
1953 } else if (c == '\\') {
1954 /* escape : just skip \[\r]\n */
1955 PEEKC_EOB(c, p);
1956 if (c == '\n') {
1957 file->line_num++;
1958 p++;
1959 } else if (c == '\r') {
1960 PEEKC_EOB(c, p);
1961 if (c != '\n')
1962 expect("'\n' after '\r'");
1963 file->line_num++;
1964 p++;
1965 } else if (c == CH_EOF) {
1966 goto unterminated_string;
1967 } else {
1968 if (str) {
1969 cstr_ccat(str, '\\');
1970 cstr_ccat(str, c);
1972 p++;
1975 } else if (c == '\n') {
1976 file->line_num++;
1977 goto add_char;
1978 } else if (c == '\r') {
1979 PEEKC_EOB(c, p);
1980 if (c != '\n') {
1981 cstr_ccat(str, '\r');
1982 } else {
1983 file->line_num++;
1984 goto add_char;
1986 } else {
1987 add_char:
1988 if (str)
1989 cstr_ccat(str, c);
1990 p++;
1993 p++;
1994 return p;
1997 /* skip block of text until #else, #elif or #endif. skip also pairs of
1998 #if/#endif */
1999 void preprocess_skip(void)
2001 int a, start_of_line, c;
2002 uint8_t *p;
2004 p = file->buf_ptr;
2005 start_of_line = 1;
2006 a = 0;
2007 for(;;) {
2008 redo_no_start:
2009 c = *p;
2010 switch(c) {
2011 case ' ':
2012 case '\t':
2013 case '\f':
2014 case '\v':
2015 case '\r':
2016 p++;
2017 goto redo_no_start;
2018 case '\n':
2019 start_of_line = 1;
2020 file->line_num++;
2021 p++;
2022 goto redo_no_start;
2023 case '\\':
2024 file->buf_ptr = p;
2025 c = handle_eob();
2026 if (c == CH_EOF) {
2027 expect("#endif");
2028 } else if (c == '\\') {
2029 /* XXX: incorrect: should not give an error */
2030 ch = file->buf_ptr[0];
2031 handle_stray();
2033 p = file->buf_ptr;
2034 goto redo_no_start;
2035 /* skip strings */
2036 case '\"':
2037 case '\'':
2038 p = parse_pp_string(p, c, NULL);
2039 break;
2040 /* skip comments */
2041 case '/':
2042 file->buf_ptr = p;
2043 ch = *p;
2044 minp();
2045 p = file->buf_ptr;
2046 if (ch == '*') {
2047 p = parse_comment(p);
2048 } else if (ch == '/') {
2049 p = parse_line_comment(p);
2051 break;
2053 case '#':
2054 p++;
2055 if (start_of_line) {
2056 file->buf_ptr = p;
2057 next_nomacro();
2058 p = file->buf_ptr;
2059 if (a == 0 &&
2060 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2061 goto the_end;
2062 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2063 a++;
2064 else if (tok == TOK_ENDIF)
2065 a--;
2067 break;
2068 default:
2069 p++;
2070 break;
2072 start_of_line = 0;
2074 the_end: ;
2075 file->buf_ptr = p;
2078 /* ParseState handling */
2080 /* XXX: currently, no include file info is stored. Thus, we cannot display
2081 accurate messages if the function or data definition spans multiple
2082 files */
2084 /* save current parse state in 's' */
2085 void save_parse_state(ParseState *s)
2087 s->line_num = file->line_num;
2088 s->macro_ptr = macro_ptr;
2089 s->tok = tok;
2090 s->tokc = tokc;
2093 /* restore parse state from 's' */
2094 void restore_parse_state(ParseState *s)
2096 file->line_num = s->line_num;
2097 macro_ptr = s->macro_ptr;
2098 tok = s->tok;
2099 tokc = s->tokc;
2102 /* return the number of additional 'ints' necessary to store the
2103 token */
2104 static inline int tok_ext_size(int t)
2106 switch(t) {
2107 /* 4 bytes */
2108 case TOK_CINT:
2109 case TOK_CUINT:
2110 case TOK_CCHAR:
2111 case TOK_LCHAR:
2112 case TOK_STR:
2113 case TOK_LSTR:
2114 case TOK_CFLOAT:
2115 case TOK_LINENUM:
2116 case TOK_PPNUM:
2117 return 1;
2118 case TOK_CDOUBLE:
2119 case TOK_CLLONG:
2120 case TOK_CULLONG:
2121 return 2;
2122 case TOK_CLDOUBLE:
2123 return LDOUBLE_SIZE / 4;
2124 default:
2125 return 0;
2129 /* token string handling */
2131 static inline void tok_str_new(TokenString *s)
2133 s->str = NULL;
2134 s->len = 0;
2135 s->allocated_len = 0;
2136 s->last_line_num = -1;
2139 static void tok_str_free(int *str)
2141 const int *p;
2142 CString *cstr;
2143 int t;
2145 p = str;
2146 for(;;) {
2147 t = *p;
2148 /* NOTE: we test zero separately so that GCC can generate a
2149 table for the following switch */
2150 if (t == 0)
2151 break;
2152 switch(t) {
2153 case TOK_CINT:
2154 case TOK_CUINT:
2155 case TOK_CCHAR:
2156 case TOK_LCHAR:
2157 case TOK_CFLOAT:
2158 case TOK_LINENUM:
2159 p += 2;
2160 break;
2161 case TOK_PPNUM:
2162 case TOK_STR:
2163 case TOK_LSTR:
2164 /* XXX: use a macro to be portable on 64 bit ? */
2165 cstr = (CString *)p[1];
2166 cstr_free(cstr);
2167 tcc_free(cstr);
2168 p += 2;
2169 break;
2170 case TOK_CDOUBLE:
2171 case TOK_CLLONG:
2172 case TOK_CULLONG:
2173 p += 3;
2174 break;
2175 case TOK_CLDOUBLE:
2176 p += 1 + (LDOUBLE_SIZE / 4);
2177 break;
2178 default:
2179 p++;
2180 break;
2183 tcc_free(str);
2186 static int *tok_str_realloc(TokenString *s)
2188 int *str, len;
2190 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2191 str = tcc_realloc(s->str, len * sizeof(int));
2192 if (!str)
2193 error("memory full");
2194 s->allocated_len = len;
2195 s->str = str;
2196 return str;
2199 static void tok_str_add(TokenString *s, int t)
2201 int len, *str;
2203 len = s->len;
2204 str = s->str;
2205 if (len >= s->allocated_len)
2206 str = tok_str_realloc(s);
2207 str[len++] = t;
2208 s->len = len;
2211 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2213 int len, *str;
2215 len = s->len;
2216 str = s->str;
2218 /* allocate space for worst case */
2219 if (len + TOK_MAX_SIZE > s->allocated_len)
2220 str = tok_str_realloc(s);
2221 str[len++] = t;
2222 switch(t) {
2223 case TOK_CINT:
2224 case TOK_CUINT:
2225 case TOK_CCHAR:
2226 case TOK_LCHAR:
2227 case TOK_CFLOAT:
2228 case TOK_LINENUM:
2229 str[len++] = cv->tab[0];
2230 break;
2231 case TOK_PPNUM:
2232 case TOK_STR:
2233 case TOK_LSTR:
2234 str[len++] = (int)cstr_dup(cv->cstr);
2235 break;
2236 case TOK_CDOUBLE:
2237 case TOK_CLLONG:
2238 case TOK_CULLONG:
2239 #if LDOUBLE_SIZE == 8
2240 case TOK_CLDOUBLE:
2241 #endif
2242 str[len++] = cv->tab[0];
2243 str[len++] = cv->tab[1];
2244 break;
2245 #if LDOUBLE_SIZE == 12
2246 case TOK_CLDOUBLE:
2247 str[len++] = cv->tab[0];
2248 str[len++] = cv->tab[1];
2249 str[len++] = cv->tab[2];
2250 #elif LDOUBLE_SIZE != 8
2251 #error add long double size support
2252 #endif
2253 break;
2254 default:
2255 break;
2257 s->len = len;
2260 /* add the current parse token in token string 's' */
2261 static void tok_str_add_tok(TokenString *s)
2263 CValue cval;
2265 /* save line number info */
2266 if (file->line_num != s->last_line_num) {
2267 s->last_line_num = file->line_num;
2268 cval.i = s->last_line_num;
2269 tok_str_add2(s, TOK_LINENUM, &cval);
2271 tok_str_add2(s, tok, &tokc);
2274 #if LDOUBLE_SIZE == 12
2275 #define LDOUBLE_GET(p, cv) \
2276 cv.tab[0] = p[0]; \
2277 cv.tab[1] = p[1]; \
2278 cv.tab[2] = p[2];
2279 #elif LDOUBLE_SIZE == 8
2280 #define LDOUBLE_GET(p, cv) \
2281 cv.tab[0] = p[0]; \
2282 cv.tab[1] = p[1];
2283 #else
2284 #error add long double size support
2285 #endif
2288 /* get a token from an integer array and increment pointer
2289 accordingly. we code it as a macro to avoid pointer aliasing. */
2290 #define TOK_GET(t, p, cv) \
2292 t = *p++; \
2293 switch(t) { \
2294 case TOK_CINT: \
2295 case TOK_CUINT: \
2296 case TOK_CCHAR: \
2297 case TOK_LCHAR: \
2298 case TOK_CFLOAT: \
2299 case TOK_LINENUM: \
2300 case TOK_STR: \
2301 case TOK_LSTR: \
2302 case TOK_PPNUM: \
2303 cv.tab[0] = *p++; \
2304 break; \
2305 case TOK_CDOUBLE: \
2306 case TOK_CLLONG: \
2307 case TOK_CULLONG: \
2308 cv.tab[0] = p[0]; \
2309 cv.tab[1] = p[1]; \
2310 p += 2; \
2311 break; \
2312 case TOK_CLDOUBLE: \
2313 LDOUBLE_GET(p, cv); \
2314 p += LDOUBLE_SIZE / 4; \
2315 break; \
2316 default: \
2317 break; \
2321 /* defines handling */
2322 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2324 Sym *s;
2326 s = sym_push2(&define_stack, v, macro_type, (int)str);
2327 s->next = first_arg;
2328 table_ident[v - TOK_IDENT]->sym_define = s;
2331 /* undefined a define symbol. Its name is just set to zero */
2332 static void define_undef(Sym *s)
2334 int v;
2335 v = s->v;
2336 if (v >= TOK_IDENT && v < tok_ident)
2337 table_ident[v - TOK_IDENT]->sym_define = NULL;
2338 s->v = 0;
2341 static inline Sym *define_find(int v)
2343 v -= TOK_IDENT;
2344 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2345 return NULL;
2346 return table_ident[v]->sym_define;
2349 /* free define stack until top reaches 'b' */
2350 static void free_defines(Sym *b)
2352 Sym *top, *top1;
2353 int v;
2355 top = define_stack;
2356 while (top != b) {
2357 top1 = top->prev;
2358 /* do not free args or predefined defines */
2359 if (top->c)
2360 tok_str_free((int *)top->c);
2361 v = top->v;
2362 if (v >= TOK_IDENT && v < tok_ident)
2363 table_ident[v - TOK_IDENT]->sym_define = NULL;
2364 tcc_free(top);
2365 top = top1;
2367 define_stack = b;
2370 /* label lookup */
2371 static Sym *label_find(int v)
2373 v -= TOK_IDENT;
2374 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2375 return NULL;
2376 return table_ident[v]->sym_label;
2379 static Sym *label_push(Sym **ptop, int v, int flags)
2381 Sym *s, **ps;
2382 s = sym_push2(ptop, v, 0, 0);
2383 s->r = flags;
2384 ps = &table_ident[v - TOK_IDENT]->sym_label;
2385 if (ptop == &global_label_stack) {
2386 /* modify the top most local identifier, so that
2387 sym_identifier will point to 's' when popped */
2388 while (*ps != NULL)
2389 ps = &(*ps)->prev_tok;
2391 s->prev_tok = *ps;
2392 *ps = s;
2393 return s;
2396 /* pop labels until element last is reached. Look if any labels are
2397 undefined. Define symbols if '&&label' was used. */
2398 static void label_pop(Sym **ptop, Sym *slast)
2400 Sym *s, *s1;
2401 for(s = *ptop; s != slast; s = s1) {
2402 s1 = s->prev;
2403 if (s->r == LABEL_DECLARED) {
2404 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2405 } else if (s->r == LABEL_FORWARD) {
2406 error("label '%s' used but not defined",
2407 get_tok_str(s->v, NULL));
2408 } else {
2409 if (s->c) {
2410 /* define corresponding symbol. A size of
2411 1 is put. */
2412 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2415 /* remove label */
2416 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2417 tcc_free(s);
2419 *ptop = slast;
2422 /* eval an expression for #if/#elif */
2423 static int expr_preprocess(void)
2425 int c, t;
2426 TokenString str;
2428 tok_str_new(&str);
2429 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2430 next(); /* do macro subst */
2431 if (tok == TOK_DEFINED) {
2432 next_nomacro();
2433 t = tok;
2434 if (t == '(')
2435 next_nomacro();
2436 c = define_find(tok) != 0;
2437 if (t == '(')
2438 next_nomacro();
2439 tok = TOK_CINT;
2440 tokc.i = c;
2441 } else if (tok >= TOK_IDENT) {
2442 /* if undefined macro */
2443 tok = TOK_CINT;
2444 tokc.i = 0;
2446 tok_str_add_tok(&str);
2448 tok_str_add(&str, -1); /* simulate end of file */
2449 tok_str_add(&str, 0);
2450 /* now evaluate C constant expression */
2451 macro_ptr = str.str;
2452 next();
2453 c = expr_const();
2454 macro_ptr = NULL;
2455 tok_str_free(str.str);
2456 return c != 0;
2459 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2460 static void tok_print(int *str)
2462 int t;
2463 CValue cval;
2465 while (1) {
2466 TOK_GET(t, str, cval);
2467 if (!t)
2468 break;
2469 printf(" %s", get_tok_str(t, &cval));
2471 printf("\n");
2473 #endif
2475 /* parse after #define */
2476 static void parse_define(void)
2478 Sym *s, *first, **ps;
2479 int v, t, varg, is_vaargs, c;
2480 TokenString str;
2482 v = tok;
2483 if (v < TOK_IDENT)
2484 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2485 /* XXX: should check if same macro (ANSI) */
2486 first = NULL;
2487 t = MACRO_OBJ;
2488 /* '(' must be just after macro definition for MACRO_FUNC */
2489 c = file->buf_ptr[0];
2490 if (c == '\\')
2491 c = handle_stray1(file->buf_ptr);
2492 if (c == '(') {
2493 next_nomacro();
2494 next_nomacro();
2495 ps = &first;
2496 while (tok != ')') {
2497 varg = tok;
2498 next_nomacro();
2499 is_vaargs = 0;
2500 if (varg == TOK_DOTS) {
2501 varg = TOK___VA_ARGS__;
2502 is_vaargs = 1;
2503 } else if (tok == TOK_DOTS && gnu_ext) {
2504 is_vaargs = 1;
2505 next_nomacro();
2507 if (varg < TOK_IDENT)
2508 error("badly punctuated parameter list");
2509 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2510 *ps = s;
2511 ps = &s->next;
2512 if (tok != ',')
2513 break;
2514 next_nomacro();
2516 t = MACRO_FUNC;
2518 tok_str_new(&str);
2519 next_nomacro();
2520 /* EOF testing necessary for '-D' handling */
2521 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2522 tok_str_add2(&str, tok, &tokc);
2523 next_nomacro();
2525 tok_str_add(&str, 0);
2526 #ifdef PP_DEBUG
2527 printf("define %s %d: ", get_tok_str(v, NULL), t);
2528 tok_print(str.str);
2529 #endif
2530 define_push(v, t, str.str, first);
2533 /* XXX: use a token or a hash table to accelerate matching ? */
2534 static CachedInclude *search_cached_include(TCCState *s1,
2535 int type, const char *filename)
2537 CachedInclude *e;
2538 int i;
2540 for(i = 0;i < s1->nb_cached_includes; i++) {
2541 e = s1->cached_includes[i];
2542 if (e->type == type && !strcmp(e->filename, filename))
2543 return e;
2545 return NULL;
2548 static inline void add_cached_include(TCCState *s1, int type,
2549 const char *filename, int ifndef_macro)
2551 CachedInclude *e;
2553 if (search_cached_include(s1, type, filename))
2554 return;
2555 #ifdef INC_DEBUG
2556 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2557 #endif
2558 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2559 if (!e)
2560 return;
2561 e->type = type;
2562 strcpy(e->filename, filename);
2563 e->ifndef_macro = ifndef_macro;
2564 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2567 /* is_bof is true if first non space token at beginning of file */
2568 static void preprocess(int is_bof)
2570 TCCState *s1 = tcc_state;
2571 int size, i, c, n, saved_parse_flags;
2572 char buf[1024], *q, *p;
2573 char buf1[1024];
2574 BufferedFile *f;
2575 Sym *s;
2576 CachedInclude *e;
2578 saved_parse_flags = parse_flags;
2579 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2580 PARSE_FLAG_LINEFEED;
2581 next_nomacro();
2582 redo:
2583 switch(tok) {
2584 case TOK_DEFINE:
2585 next_nomacro();
2586 parse_define();
2587 break;
2588 case TOK_UNDEF:
2589 next_nomacro();
2590 s = define_find(tok);
2591 /* undefine symbol by putting an invalid name */
2592 if (s)
2593 define_undef(s);
2594 break;
2595 case TOK_INCLUDE:
2596 ch = file->buf_ptr[0];
2597 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2598 skip_spaces();
2599 if (ch == '<') {
2600 c = '>';
2601 goto read_name;
2602 } else if (ch == '\"') {
2603 c = ch;
2604 read_name:
2605 /* XXX: better stray handling */
2606 minp();
2607 q = buf;
2608 while (ch != c && ch != '\n' && ch != CH_EOF) {
2609 if ((q - buf) < sizeof(buf) - 1)
2610 *q++ = ch;
2611 minp();
2613 *q = '\0';
2614 minp();
2615 #if 0
2616 /* eat all spaces and comments after include */
2617 /* XXX: slightly incorrect */
2618 while (ch1 != '\n' && ch1 != CH_EOF)
2619 inp();
2620 #endif
2621 } else {
2622 /* computed #include : either we have only strings or
2623 we have anything enclosed in '<>' */
2624 next();
2625 buf[0] = '\0';
2626 if (tok == TOK_STR) {
2627 while (tok != TOK_LINEFEED) {
2628 if (tok != TOK_STR) {
2629 include_syntax:
2630 error("'#include' expects \"FILENAME\" or <FILENAME>");
2632 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2633 next();
2635 c = '\"';
2636 } else {
2637 int len;
2638 while (tok != TOK_LINEFEED) {
2639 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2640 next();
2642 len = strlen(buf);
2643 /* check syntax and remove '<>' */
2644 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2645 goto include_syntax;
2646 memmove(buf, buf + 1, len - 2);
2647 buf[len - 2] = '\0';
2648 c = '>';
2652 e = search_cached_include(s1, c, buf);
2653 if (e && define_find(e->ifndef_macro)) {
2654 /* no need to parse the include because the 'ifndef macro'
2655 is defined */
2656 #ifdef INC_DEBUG
2657 printf("%s: skipping %s\n", file->filename, buf);
2658 #endif
2659 } else {
2660 if (c == '\"') {
2661 /* first search in current dir if "header.h" */
2662 size = 0;
2663 p = strrchr(file->filename, '/');
2664 if (p)
2665 size = p + 1 - file->filename;
2666 if (size > sizeof(buf1) - 1)
2667 size = sizeof(buf1) - 1;
2668 memcpy(buf1, file->filename, size);
2669 buf1[size] = '\0';
2670 pstrcat(buf1, sizeof(buf1), buf);
2671 f = tcc_open(s1, buf1);
2672 if (f)
2673 goto found;
2675 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2676 error("#include recursion too deep");
2677 /* now search in all the include paths */
2678 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2679 for(i = 0; i < n; i++) {
2680 const char *path;
2681 if (i < s1->nb_include_paths)
2682 path = s1->include_paths[i];
2683 else
2684 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2685 pstrcpy(buf1, sizeof(buf1), path);
2686 pstrcat(buf1, sizeof(buf1), "/");
2687 pstrcat(buf1, sizeof(buf1), buf);
2688 f = tcc_open(s1, buf1);
2689 if (f)
2690 goto found;
2692 error("include file '%s' not found", buf);
2693 f = NULL;
2694 found:
2695 #ifdef INC_DEBUG
2696 printf("%s: including %s\n", file->filename, buf1);
2697 #endif
2698 f->inc_type = c;
2699 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2700 /* push current file in stack */
2701 /* XXX: fix current line init */
2702 *s1->include_stack_ptr++ = file;
2703 file = f;
2704 /* add include file debug info */
2705 if (do_debug) {
2706 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2708 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2709 ch = file->buf_ptr[0];
2710 goto the_end;
2712 break;
2713 case TOK_IFNDEF:
2714 c = 1;
2715 goto do_ifdef;
2716 case TOK_IF:
2717 c = expr_preprocess();
2718 goto do_if;
2719 case TOK_IFDEF:
2720 c = 0;
2721 do_ifdef:
2722 next_nomacro();
2723 if (tok < TOK_IDENT)
2724 error("invalid argument for '#if%sdef'", c ? "n" : "");
2725 if (is_bof) {
2726 if (c) {
2727 #ifdef INC_DEBUG
2728 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2729 #endif
2730 file->ifndef_macro = tok;
2733 c = (define_find(tok) != 0) ^ c;
2734 do_if:
2735 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2736 error("memory full");
2737 *s1->ifdef_stack_ptr++ = c;
2738 goto test_skip;
2739 case TOK_ELSE:
2740 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2741 error("#else without matching #if");
2742 if (s1->ifdef_stack_ptr[-1] & 2)
2743 error("#else after #else");
2744 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2745 goto test_skip;
2746 case TOK_ELIF:
2747 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2748 error("#elif without matching #if");
2749 c = s1->ifdef_stack_ptr[-1];
2750 if (c > 1)
2751 error("#elif after #else");
2752 /* last #if/#elif expression was true: we skip */
2753 if (c == 1)
2754 goto skip;
2755 c = expr_preprocess();
2756 s1->ifdef_stack_ptr[-1] = c;
2757 test_skip:
2758 if (!(c & 1)) {
2759 skip:
2760 preprocess_skip();
2761 is_bof = 0;
2762 goto redo;
2764 break;
2765 case TOK_ENDIF:
2766 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2767 error("#endif without matching #if");
2768 s1->ifdef_stack_ptr--;
2769 /* '#ifndef macro' was at the start of file. Now we check if
2770 an '#endif' is exactly at the end of file */
2771 if (file->ifndef_macro &&
2772 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2773 file->ifndef_macro_saved = file->ifndef_macro;
2774 /* need to set to zero to avoid false matches if another
2775 #ifndef at middle of file */
2776 file->ifndef_macro = 0;
2777 while (tok != TOK_LINEFEED)
2778 next_nomacro();
2779 tok_flags |= TOK_FLAG_ENDIF;
2780 goto the_end;
2782 break;
2783 case TOK_LINE:
2784 next();
2785 if (tok != TOK_CINT)
2786 error("#line");
2787 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2788 next();
2789 if (tok != TOK_LINEFEED) {
2790 if (tok != TOK_STR)
2791 error("#line");
2792 pstrcpy(file->filename, sizeof(file->filename),
2793 (char *)tokc.cstr->data);
2795 break;
2796 case TOK_ERROR:
2797 case TOK_WARNING:
2798 c = tok;
2799 ch = file->buf_ptr[0];
2800 skip_spaces();
2801 q = buf;
2802 while (ch != '\n' && ch != CH_EOF) {
2803 if ((q - buf) < sizeof(buf) - 1)
2804 *q++ = ch;
2805 minp();
2807 *q = '\0';
2808 if (c == TOK_ERROR)
2809 error("#error %s", buf);
2810 else
2811 warning("#warning %s", buf);
2812 break;
2813 case TOK_PRAGMA:
2814 /* ignored */
2815 break;
2816 default:
2817 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2818 /* '!' is ignored to allow C scripts. numbers are ignored
2819 to emulate cpp behaviour */
2820 } else {
2821 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2823 break;
2825 /* ignore other preprocess commands or #! for C scripts */
2826 while (tok != TOK_LINEFEED)
2827 next_nomacro();
2828 the_end:
2829 parse_flags = saved_parse_flags;
2832 /* evaluate escape codes in a string. */
2833 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2835 int c, n;
2836 const uint8_t *p;
2838 p = buf;
2839 for(;;) {
2840 c = *p;
2841 if (c == '\0')
2842 break;
2843 if (c == '\\') {
2844 p++;
2845 /* escape */
2846 c = *p;
2847 switch(c) {
2848 case '0': case '1': case '2': case '3':
2849 case '4': case '5': case '6': case '7':
2850 /* at most three octal digits */
2851 n = c - '0';
2852 p++;
2853 c = *p;
2854 if (isoct(c)) {
2855 n = n * 8 + c - '0';
2856 p++;
2857 c = *p;
2858 if (isoct(c)) {
2859 n = n * 8 + c - '0';
2860 p++;
2863 c = n;
2864 goto add_char_nonext;
2865 case 'x':
2866 p++;
2867 n = 0;
2868 for(;;) {
2869 c = *p;
2870 if (c >= 'a' && c <= 'f')
2871 c = c - 'a' + 10;
2872 else if (c >= 'A' && c <= 'F')
2873 c = c - 'A' + 10;
2874 else if (isnum(c))
2875 c = c - '0';
2876 else
2877 break;
2878 n = n * 16 + c;
2879 p++;
2881 c = n;
2882 goto add_char_nonext;
2883 case 'a':
2884 c = '\a';
2885 break;
2886 case 'b':
2887 c = '\b';
2888 break;
2889 case 'f':
2890 c = '\f';
2891 break;
2892 case 'n':
2893 c = '\n';
2894 break;
2895 case 'r':
2896 c = '\r';
2897 break;
2898 case 't':
2899 c = '\t';
2900 break;
2901 case 'v':
2902 c = '\v';
2903 break;
2904 case 'e':
2905 if (!gnu_ext)
2906 goto invalid_escape;
2907 c = 27;
2908 break;
2909 case '\'':
2910 case '\"':
2911 case '\\':
2912 case '?':
2913 break;
2914 default:
2915 invalid_escape:
2916 if (c >= '!' && c <= '~')
2917 warning("unknown escape sequence: \'\\%c\'", c);
2918 else
2919 warning("unknown escape sequence: \'\\x%x\'", c);
2920 break;
2923 p++;
2924 add_char_nonext:
2925 if (!is_long)
2926 cstr_ccat(outstr, c);
2927 else
2928 cstr_wccat(outstr, c);
2930 /* add a trailing '\0' */
2931 if (!is_long)
2932 cstr_ccat(outstr, '\0');
2933 else
2934 cstr_wccat(outstr, '\0');
2937 /* we use 64 bit numbers */
2938 #define BN_SIZE 2
2940 /* bn = (bn << shift) | or_val */
2941 void bn_lshift(unsigned int *bn, int shift, int or_val)
2943 int i;
2944 unsigned int v;
2945 for(i=0;i<BN_SIZE;i++) {
2946 v = bn[i];
2947 bn[i] = (v << shift) | or_val;
2948 or_val = v >> (32 - shift);
2952 void bn_zero(unsigned int *bn)
2954 int i;
2955 for(i=0;i<BN_SIZE;i++) {
2956 bn[i] = 0;
2960 /* parse number in null terminated string 'p' and return it in the
2961 current token */
2962 void parse_number(const char *p)
2964 int b, t, shift, frac_bits, s, exp_val, ch;
2965 char *q;
2966 unsigned int bn[BN_SIZE];
2967 double d;
2969 /* number */
2970 q = token_buf;
2971 ch = *p++;
2972 t = ch;
2973 ch = *p++;
2974 *q++ = t;
2975 b = 10;
2976 if (t == '.') {
2977 goto float_frac_parse;
2978 } else if (t == '0') {
2979 if (ch == 'x' || ch == 'X') {
2980 q--;
2981 ch = *p++;
2982 b = 16;
2983 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2984 q--;
2985 ch = *p++;
2986 b = 2;
2989 /* parse all digits. cannot check octal numbers at this stage
2990 because of floating point constants */
2991 while (1) {
2992 if (ch >= 'a' && ch <= 'f')
2993 t = ch - 'a' + 10;
2994 else if (ch >= 'A' && ch <= 'F')
2995 t = ch - 'A' + 10;
2996 else if (isnum(ch))
2997 t = ch - '0';
2998 else
2999 break;
3000 if (t >= b)
3001 break;
3002 if (q >= token_buf + STRING_MAX_SIZE) {
3003 num_too_long:
3004 error("number too long");
3006 *q++ = ch;
3007 ch = *p++;
3009 if (ch == '.' ||
3010 ((ch == 'e' || ch == 'E') && b == 10) ||
3011 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3012 if (b != 10) {
3013 /* NOTE: strtox should support that for hexa numbers, but
3014 non ISOC99 libcs do not support it, so we prefer to do
3015 it by hand */
3016 /* hexadecimal or binary floats */
3017 /* XXX: handle overflows */
3018 *q = '\0';
3019 if (b == 16)
3020 shift = 4;
3021 else
3022 shift = 2;
3023 bn_zero(bn);
3024 q = token_buf;
3025 while (1) {
3026 t = *q++;
3027 if (t == '\0') {
3028 break;
3029 } else if (t >= 'a') {
3030 t = t - 'a' + 10;
3031 } else if (t >= 'A') {
3032 t = t - 'A' + 10;
3033 } else {
3034 t = t - '0';
3036 bn_lshift(bn, shift, t);
3038 frac_bits = 0;
3039 if (ch == '.') {
3040 ch = *p++;
3041 while (1) {
3042 t = ch;
3043 if (t >= 'a' && t <= 'f') {
3044 t = t - 'a' + 10;
3045 } else if (t >= 'A' && t <= 'F') {
3046 t = t - 'A' + 10;
3047 } else if (t >= '0' && t <= '9') {
3048 t = t - '0';
3049 } else {
3050 break;
3052 if (t >= b)
3053 error("invalid digit");
3054 bn_lshift(bn, shift, t);
3055 frac_bits += shift;
3056 ch = *p++;
3059 if (ch != 'p' && ch != 'P')
3060 expect("exponent");
3061 ch = *p++;
3062 s = 1;
3063 exp_val = 0;
3064 if (ch == '+') {
3065 ch = *p++;
3066 } else if (ch == '-') {
3067 s = -1;
3068 ch = *p++;
3070 if (ch < '0' || ch > '9')
3071 expect("exponent digits");
3072 while (ch >= '0' && ch <= '9') {
3073 exp_val = exp_val * 10 + ch - '0';
3074 ch = *p++;
3076 exp_val = exp_val * s;
3078 /* now we can generate the number */
3079 /* XXX: should patch directly float number */
3080 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3081 d = ldexp(d, exp_val - frac_bits);
3082 t = toup(ch);
3083 if (t == 'F') {
3084 ch = *p++;
3085 tok = TOK_CFLOAT;
3086 /* float : should handle overflow */
3087 tokc.f = (float)d;
3088 } else if (t == 'L') {
3089 ch = *p++;
3090 tok = TOK_CLDOUBLE;
3091 /* XXX: not large enough */
3092 tokc.ld = (long double)d;
3093 } else {
3094 tok = TOK_CDOUBLE;
3095 tokc.d = d;
3097 } else {
3098 /* decimal floats */
3099 if (ch == '.') {
3100 if (q >= token_buf + STRING_MAX_SIZE)
3101 goto num_too_long;
3102 *q++ = ch;
3103 ch = *p++;
3104 float_frac_parse:
3105 while (ch >= '0' && ch <= '9') {
3106 if (q >= token_buf + STRING_MAX_SIZE)
3107 goto num_too_long;
3108 *q++ = ch;
3109 ch = *p++;
3112 if (ch == 'e' || ch == 'E') {
3113 if (q >= token_buf + STRING_MAX_SIZE)
3114 goto num_too_long;
3115 *q++ = ch;
3116 ch = *p++;
3117 if (ch == '-' || ch == '+') {
3118 if (q >= token_buf + STRING_MAX_SIZE)
3119 goto num_too_long;
3120 *q++ = ch;
3121 ch = *p++;
3123 if (ch < '0' || ch > '9')
3124 expect("exponent digits");
3125 while (ch >= '0' && ch <= '9') {
3126 if (q >= token_buf + STRING_MAX_SIZE)
3127 goto num_too_long;
3128 *q++ = ch;
3129 ch = *p++;
3132 *q = '\0';
3133 t = toup(ch);
3134 errno = 0;
3135 if (t == 'F') {
3136 ch = *p++;
3137 tok = TOK_CFLOAT;
3138 tokc.f = strtof(token_buf, NULL);
3139 } else if (t == 'L') {
3140 ch = *p++;
3141 tok = TOK_CLDOUBLE;
3142 tokc.ld = strtold(token_buf, NULL);
3143 } else {
3144 tok = TOK_CDOUBLE;
3145 tokc.d = strtod(token_buf, NULL);
3148 } else {
3149 unsigned long long n, n1;
3150 int lcount, ucount;
3152 /* integer number */
3153 *q = '\0';
3154 q = token_buf;
3155 if (b == 10 && *q == '0') {
3156 b = 8;
3157 q++;
3159 n = 0;
3160 while(1) {
3161 t = *q++;
3162 /* no need for checks except for base 10 / 8 errors */
3163 if (t == '\0') {
3164 break;
3165 } else if (t >= 'a') {
3166 t = t - 'a' + 10;
3167 } else if (t >= 'A') {
3168 t = t - 'A' + 10;
3169 } else {
3170 t = t - '0';
3171 if (t >= b)
3172 error("invalid digit");
3174 n1 = n;
3175 n = n * b + t;
3176 /* detect overflow */
3177 /* XXX: this test is not reliable */
3178 if (n < n1)
3179 error("integer constant overflow");
3182 /* XXX: not exactly ANSI compliant */
3183 if ((n & 0xffffffff00000000LL) != 0) {
3184 if ((n >> 63) != 0)
3185 tok = TOK_CULLONG;
3186 else
3187 tok = TOK_CLLONG;
3188 } else if (n > 0x7fffffff) {
3189 tok = TOK_CUINT;
3190 } else {
3191 tok = TOK_CINT;
3193 lcount = 0;
3194 ucount = 0;
3195 for(;;) {
3196 t = toup(ch);
3197 if (t == 'L') {
3198 if (lcount >= 2)
3199 error("three 'l's in integer constant");
3200 lcount++;
3201 if (lcount == 2) {
3202 if (tok == TOK_CINT)
3203 tok = TOK_CLLONG;
3204 else if (tok == TOK_CUINT)
3205 tok = TOK_CULLONG;
3207 ch = *p++;
3208 } else if (t == 'U') {
3209 if (ucount >= 1)
3210 error("two 'u's in integer constant");
3211 ucount++;
3212 if (tok == TOK_CINT)
3213 tok = TOK_CUINT;
3214 else if (tok == TOK_CLLONG)
3215 tok = TOK_CULLONG;
3216 ch = *p++;
3217 } else {
3218 break;
3221 if (tok == TOK_CINT || tok == TOK_CUINT)
3222 tokc.ui = n;
3223 else
3224 tokc.ull = n;
3229 #define PARSE2(c1, tok1, c2, tok2) \
3230 case c1: \
3231 PEEKC(c, p); \
3232 if (c == c2) { \
3233 p++; \
3234 tok = tok2; \
3235 } else { \
3236 tok = tok1; \
3238 break;
3240 /* return next token without macro substitution */
3241 static inline void next_nomacro1(void)
3243 int t, c, is_long;
3244 TokenSym *ts;
3245 uint8_t *p, *p1;
3246 unsigned int h;
3248 p = file->buf_ptr;
3249 redo_no_start:
3250 c = *p;
3251 switch(c) {
3252 case ' ':
3253 case '\t':
3254 case '\f':
3255 case '\v':
3256 case '\r':
3257 p++;
3258 goto redo_no_start;
3260 case '\\':
3261 /* first look if it is in fact an end of buffer */
3262 if (p >= file->buf_end) {
3263 file->buf_ptr = p;
3264 handle_eob();
3265 p = file->buf_ptr;
3266 if (p >= file->buf_end)
3267 goto parse_eof;
3268 else
3269 goto redo_no_start;
3270 } else {
3271 file->buf_ptr = p;
3272 ch = *p;
3273 handle_stray();
3274 p = file->buf_ptr;
3275 goto redo_no_start;
3277 parse_eof:
3279 TCCState *s1 = tcc_state;
3280 if (parse_flags & PARSE_FLAG_LINEFEED) {
3281 tok = TOK_LINEFEED;
3282 } else if (s1->include_stack_ptr == s1->include_stack ||
3283 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3284 /* no include left : end of file. */
3285 tok = TOK_EOF;
3286 } else {
3287 /* pop include file */
3289 /* test if previous '#endif' was after a #ifdef at
3290 start of file */
3291 if (tok_flags & TOK_FLAG_ENDIF) {
3292 #ifdef INC_DEBUG
3293 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3294 #endif
3295 add_cached_include(s1, file->inc_type, file->inc_filename,
3296 file->ifndef_macro_saved);
3299 /* add end of include file debug info */
3300 if (do_debug) {
3301 put_stabd(N_EINCL, 0, 0);
3303 /* pop include stack */
3304 tcc_close(file);
3305 s1->include_stack_ptr--;
3306 file = *s1->include_stack_ptr;
3307 p = file->buf_ptr;
3308 goto redo_no_start;
3311 break;
3313 case '\n':
3314 if (parse_flags & PARSE_FLAG_LINEFEED) {
3315 tok = TOK_LINEFEED;
3316 } else {
3317 file->line_num++;
3318 tok_flags |= TOK_FLAG_BOL;
3319 p++;
3320 goto redo_no_start;
3322 break;
3324 case '#':
3325 /* XXX: simplify */
3326 PEEKC(c, p);
3327 if ((tok_flags & TOK_FLAG_BOL) &&
3328 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3329 file->buf_ptr = p;
3330 preprocess(tok_flags & TOK_FLAG_BOF);
3331 p = file->buf_ptr;
3332 goto redo_no_start;
3333 } else {
3334 if (c == '#') {
3335 p++;
3336 tok = TOK_TWOSHARPS;
3337 } else {
3338 tok = '#';
3341 break;
3343 case 'a': case 'b': case 'c': case 'd':
3344 case 'e': case 'f': case 'g': case 'h':
3345 case 'i': case 'j': case 'k': case 'l':
3346 case 'm': case 'n': case 'o': case 'p':
3347 case 'q': case 'r': case 's': case 't':
3348 case 'u': case 'v': case 'w': case 'x':
3349 case 'y': case 'z':
3350 case 'A': case 'B': case 'C': case 'D':
3351 case 'E': case 'F': case 'G': case 'H':
3352 case 'I': case 'J': case 'K':
3353 case 'M': case 'N': case 'O': case 'P':
3354 case 'Q': case 'R': case 'S': case 'T':
3355 case 'U': case 'V': case 'W': case 'X':
3356 case 'Y': case 'Z':
3357 case '_':
3358 parse_ident_fast:
3359 p1 = p;
3360 h = TOK_HASH_INIT;
3361 h = TOK_HASH_FUNC(h, c);
3362 p++;
3363 for(;;) {
3364 c = *p;
3365 if (!isidnum_table[c])
3366 break;
3367 h = TOK_HASH_FUNC(h, c);
3368 p++;
3370 if (c != '\\') {
3371 TokenSym **pts;
3372 int len;
3374 /* fast case : no stray found, so we have the full token
3375 and we have already hashed it */
3376 len = p - p1;
3377 h &= (TOK_HASH_SIZE - 1);
3378 pts = &hash_ident[h];
3379 for(;;) {
3380 ts = *pts;
3381 if (!ts)
3382 break;
3383 if (ts->len == len && !memcmp(ts->str, p1, len))
3384 goto token_found;
3385 pts = &(ts->hash_next);
3387 ts = tok_alloc_new(pts, p1, len);
3388 token_found: ;
3389 } else {
3390 /* slower case */
3391 cstr_reset(&tokcstr);
3393 while (p1 < p) {
3394 cstr_ccat(&tokcstr, *p1);
3395 p1++;
3397 p--;
3398 PEEKC(c, p);
3399 parse_ident_slow:
3400 while (isidnum_table[c]) {
3401 cstr_ccat(&tokcstr, c);
3402 PEEKC(c, p);
3404 ts = tok_alloc(tokcstr.data, tokcstr.size);
3406 tok = ts->tok;
3407 break;
3408 case 'L':
3409 t = p[1];
3410 if (t != '\\' && t != '\'' && t != '\"') {
3411 /* fast case */
3412 goto parse_ident_fast;
3413 } else {
3414 PEEKC(c, p);
3415 if (c == '\'' || c == '\"') {
3416 is_long = 1;
3417 goto str_const;
3418 } else {
3419 cstr_reset(&tokcstr);
3420 cstr_ccat(&tokcstr, 'L');
3421 goto parse_ident_slow;
3424 break;
3425 case '0': case '1': case '2': case '3':
3426 case '4': case '5': case '6': case '7':
3427 case '8': case '9':
3429 cstr_reset(&tokcstr);
3430 /* after the first digit, accept digits, alpha, '.' or sign if
3431 prefixed by 'eEpP' */
3432 parse_num:
3433 for(;;) {
3434 t = c;
3435 cstr_ccat(&tokcstr, c);
3436 PEEKC(c, p);
3437 if (!(isnum(c) || isid(c) || c == '.' ||
3438 ((c == '+' || c == '-') &&
3439 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3440 break;
3442 /* We add a trailing '\0' to ease parsing */
3443 cstr_ccat(&tokcstr, '\0');
3444 tokc.cstr = &tokcstr;
3445 tok = TOK_PPNUM;
3446 break;
3447 case '.':
3448 /* special dot handling because it can also start a number */
3449 PEEKC(c, p);
3450 if (isnum(c)) {
3451 cstr_reset(&tokcstr);
3452 cstr_ccat(&tokcstr, '.');
3453 goto parse_num;
3454 } else if (c == '.') {
3455 PEEKC(c, p);
3456 if (c != '.')
3457 expect("'.'");
3458 PEEKC(c, p);
3459 tok = TOK_DOTS;
3460 } else {
3461 tok = '.';
3463 break;
3464 case '\'':
3465 case '\"':
3466 is_long = 0;
3467 str_const:
3469 CString str;
3470 int sep;
3472 sep = c;
3474 /* parse the string */
3475 cstr_new(&str);
3476 p = parse_pp_string(p, sep, &str);
3477 cstr_ccat(&str, '\0');
3479 /* eval the escape (should be done as TOK_PPNUM) */
3480 cstr_reset(&tokcstr);
3481 parse_escape_string(&tokcstr, str.data, is_long);
3482 cstr_free(&str);
3484 if (sep == '\'') {
3485 int char_size;
3486 /* XXX: make it portable */
3487 if (!is_long)
3488 char_size = 1;
3489 else
3490 char_size = sizeof(int);
3491 if (tokcstr.size <= char_size)
3492 error("empty character constant");
3493 if (tokcstr.size > 2 * char_size)
3494 warning("multi-character character constant");
3495 if (!is_long) {
3496 tokc.i = *(int8_t *)tokcstr.data;
3497 tok = TOK_CCHAR;
3498 } else {
3499 tokc.i = *(int *)tokcstr.data;
3500 tok = TOK_LCHAR;
3502 } else {
3503 tokc.cstr = &tokcstr;
3504 if (!is_long)
3505 tok = TOK_STR;
3506 else
3507 tok = TOK_LSTR;
3510 break;
3512 case '<':
3513 PEEKC(c, p);
3514 if (c == '=') {
3515 p++;
3516 tok = TOK_LE;
3517 } else if (c == '<') {
3518 PEEKC(c, p);
3519 if (c == '=') {
3520 p++;
3521 tok = TOK_A_SHL;
3522 } else {
3523 tok = TOK_SHL;
3525 } else {
3526 tok = TOK_LT;
3528 break;
3530 case '>':
3531 PEEKC(c, p);
3532 if (c == '=') {
3533 p++;
3534 tok = TOK_GE;
3535 } else if (c == '>') {
3536 PEEKC(c, p);
3537 if (c == '=') {
3538 p++;
3539 tok = TOK_A_SAR;
3540 } else {
3541 tok = TOK_SAR;
3543 } else {
3544 tok = TOK_GT;
3546 break;
3548 case '&':
3549 PEEKC(c, p);
3550 if (c == '&') {
3551 p++;
3552 tok = TOK_LAND;
3553 } else if (c == '=') {
3554 p++;
3555 tok = TOK_A_AND;
3556 } else {
3557 tok = '&';
3559 break;
3561 case '|':
3562 PEEKC(c, p);
3563 if (c == '|') {
3564 p++;
3565 tok = TOK_LOR;
3566 } else if (c == '=') {
3567 p++;
3568 tok = TOK_A_OR;
3569 } else {
3570 tok = '|';
3572 break;
3574 case '+':
3575 PEEKC(c, p);
3576 if (c == '+') {
3577 p++;
3578 tok = TOK_INC;
3579 } else if (c == '=') {
3580 p++;
3581 tok = TOK_A_ADD;
3582 } else {
3583 tok = '+';
3585 break;
3587 case '-':
3588 PEEKC(c, p);
3589 if (c == '-') {
3590 p++;
3591 tok = TOK_DEC;
3592 } else if (c == '=') {
3593 p++;
3594 tok = TOK_A_SUB;
3595 } else if (c == '>') {
3596 p++;
3597 tok = TOK_ARROW;
3598 } else {
3599 tok = '-';
3601 break;
3603 PARSE2('!', '!', '=', TOK_NE)
3604 PARSE2('=', '=', '=', TOK_EQ)
3605 PARSE2('*', '*', '=', TOK_A_MUL)
3606 PARSE2('%', '%', '=', TOK_A_MOD)
3607 PARSE2('^', '^', '=', TOK_A_XOR)
3609 /* comments or operator */
3610 case '/':
3611 PEEKC(c, p);
3612 if (c == '*') {
3613 p = parse_comment(p);
3614 goto redo_no_start;
3615 } else if (c == '/') {
3616 p = parse_line_comment(p);
3617 goto redo_no_start;
3618 } else if (c == '=') {
3619 p++;
3620 tok = TOK_A_DIV;
3621 } else {
3622 tok = '/';
3624 break;
3626 /* simple tokens */
3627 case '(':
3628 case ')':
3629 case '[':
3630 case ']':
3631 case '{':
3632 case '}':
3633 case ',':
3634 case ';':
3635 case ':':
3636 case '?':
3637 case '~':
3638 case '$': /* only used in assembler */
3639 tok = c;
3640 p++;
3641 break;
3642 default:
3643 error("unrecognized character \\x%02x", c);
3644 break;
3646 file->buf_ptr = p;
3647 tok_flags = 0;
3648 #if defined(PARSE_DEBUG)
3649 printf("token = %s\n", get_tok_str(tok, &tokc));
3650 #endif
3653 /* return next token without macro substitution. Can read input from
3654 macro_ptr buffer */
3655 static void next_nomacro(void)
3657 if (macro_ptr) {
3658 redo:
3659 tok = *macro_ptr;
3660 if (tok) {
3661 TOK_GET(tok, macro_ptr, tokc);
3662 if (tok == TOK_LINENUM) {
3663 file->line_num = tokc.i;
3664 goto redo;
3667 } else {
3668 next_nomacro1();
3672 /* substitute args in macro_str and return allocated string */
3673 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3675 int *st, last_tok, t, notfirst;
3676 Sym *s;
3677 CValue cval;
3678 TokenString str;
3679 CString cstr;
3681 tok_str_new(&str);
3682 last_tok = 0;
3683 while(1) {
3684 TOK_GET(t, macro_str, cval);
3685 if (!t)
3686 break;
3687 if (t == '#') {
3688 /* stringize */
3689 TOK_GET(t, macro_str, cval);
3690 if (!t)
3691 break;
3692 s = sym_find2(args, t);
3693 if (s) {
3694 cstr_new(&cstr);
3695 st = (int *)s->c;
3696 notfirst = 0;
3697 while (*st) {
3698 if (notfirst)
3699 cstr_ccat(&cstr, ' ');
3700 TOK_GET(t, st, cval);
3701 cstr_cat(&cstr, get_tok_str(t, &cval));
3702 notfirst = 1;
3704 cstr_ccat(&cstr, '\0');
3705 #ifdef PP_DEBUG
3706 printf("stringize: %s\n", (char *)cstr.data);
3707 #endif
3708 /* add string */
3709 cval.cstr = &cstr;
3710 tok_str_add2(&str, TOK_STR, &cval);
3711 cstr_free(&cstr);
3712 } else {
3713 tok_str_add2(&str, t, &cval);
3715 } else if (t >= TOK_IDENT) {
3716 s = sym_find2(args, t);
3717 if (s) {
3718 st = (int *)s->c;
3719 /* if '##' is present before or after, no arg substitution */
3720 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3721 /* special case for var arg macros : ## eats the
3722 ',' if empty VA_ARGS variable. */
3723 /* XXX: test of the ',' is not 100%
3724 reliable. should fix it to avoid security
3725 problems */
3726 if (gnu_ext && s->type.t &&
3727 last_tok == TOK_TWOSHARPS &&
3728 str.len >= 2 && str.str[str.len - 2] == ',') {
3729 if (*st == 0) {
3730 /* suppress ',' '##' */
3731 str.len -= 2;
3732 } else {
3733 /* suppress '##' and add variable */
3734 str.len--;
3735 goto add_var;
3737 } else {
3738 int t1;
3739 add_var:
3740 for(;;) {
3741 TOK_GET(t1, st, cval);
3742 if (!t1)
3743 break;
3744 tok_str_add2(&str, t1, &cval);
3747 } else {
3748 /* NOTE: the stream cannot be read when macro
3749 substituing an argument */
3750 macro_subst(&str, nested_list, st, 0);
3752 } else {
3753 tok_str_add(&str, t);
3755 } else {
3756 tok_str_add2(&str, t, &cval);
3758 last_tok = t;
3760 tok_str_add(&str, 0);
3761 return str.str;
3764 static char const ab_month_name[12][4] =
3766 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3767 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3770 /* do macro substitution of current token with macro 's' and add
3771 result to (tok_str,tok_len). 'nested_list' is the list of all
3772 macros we got inside to avoid recursing. Return non zero if no
3773 substitution needs to be done */
3774 static int macro_subst_tok(TokenString *tok_str,
3775 Sym **nested_list, Sym *s, int can_read_stream)
3777 Sym *args, *sa, *sa1;
3778 int mstr_allocated, parlevel, *mstr, t;
3779 TokenString str;
3780 char *cstrval;
3781 CValue cval;
3782 CString cstr;
3784 /* if symbol is a macro, prepare substitution */
3786 /* special macros */
3787 if (tok == TOK___LINE__) {
3788 cval.i = file->line_num;
3789 tok_str_add2(tok_str, TOK_CINT, &cval);
3790 } else if (tok == TOK___FILE__) {
3791 cstrval = file->filename;
3792 goto add_cstr;
3793 tok_str_add2(tok_str, TOK_STR, &cval);
3794 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3795 time_t ti;
3796 struct tm *tm;
3797 char buf[64];
3799 time(&ti);
3800 tm = localtime(&ti);
3801 if (tok == TOK___DATE__) {
3802 snprintf(buf, sizeof(buf), "%s %2d %d",
3803 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3804 } else {
3805 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3806 tm->tm_hour, tm->tm_min, tm->tm_sec);
3808 cstrval = buf;
3809 add_cstr:
3810 cstr_new(&cstr);
3811 cstr_cat(&cstr, cstrval);
3812 cstr_ccat(&cstr, '\0');
3813 cval.cstr = &cstr;
3814 tok_str_add2(tok_str, TOK_STR, &cval);
3815 cstr_free(&cstr);
3816 } else {
3817 mstr = (int *)s->c;
3818 mstr_allocated = 0;
3819 if (s->type.t == MACRO_FUNC) {
3820 /* NOTE: we do not use next_nomacro to avoid eating the
3821 next token. XXX: find better solution */
3822 if (macro_ptr) {
3823 t = *macro_ptr;
3824 if (t == 0 && can_read_stream) {
3825 /* end of macro stream: we must look at the token
3826 after in the file */
3827 macro_ptr = NULL;
3828 goto parse_stream;
3830 } else {
3831 parse_stream:
3832 /* XXX: incorrect with comments */
3833 ch = file->buf_ptr[0];
3834 while (is_space(ch) || ch == '\n')
3835 cinp();
3836 t = ch;
3838 if (t != '(') /* no macro subst */
3839 return -1;
3841 /* argument macro */
3842 next_nomacro();
3843 next_nomacro();
3844 args = NULL;
3845 sa = s->next;
3846 /* NOTE: empty args are allowed, except if no args */
3847 for(;;) {
3848 /* handle '()' case */
3849 if (!args && !sa && tok == ')')
3850 break;
3851 if (!sa)
3852 error("macro '%s' used with too many args",
3853 get_tok_str(s->v, 0));
3854 tok_str_new(&str);
3855 parlevel = 0;
3856 /* NOTE: non zero sa->t indicates VA_ARGS */
3857 while ((parlevel > 0 ||
3858 (tok != ')' &&
3859 (tok != ',' || sa->type.t))) &&
3860 tok != -1) {
3861 if (tok == '(')
3862 parlevel++;
3863 else if (tok == ')')
3864 parlevel--;
3865 tok_str_add2(&str, tok, &tokc);
3866 next_nomacro();
3868 tok_str_add(&str, 0);
3869 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3870 sa = sa->next;
3871 if (tok == ')') {
3872 /* special case for gcc var args: add an empty
3873 var arg argument if it is omitted */
3874 if (sa && sa->type.t && gnu_ext)
3875 continue;
3876 else
3877 break;
3879 if (tok != ',')
3880 expect(",");
3881 next_nomacro();
3883 if (sa) {
3884 error("macro '%s' used with too few args",
3885 get_tok_str(s->v, 0));
3888 /* now subst each arg */
3889 mstr = macro_arg_subst(nested_list, mstr, args);
3890 /* free memory */
3891 sa = args;
3892 while (sa) {
3893 sa1 = sa->prev;
3894 tok_str_free((int *)sa->c);
3895 tcc_free(sa);
3896 sa = sa1;
3898 mstr_allocated = 1;
3900 sym_push2(nested_list, s->v, 0, 0);
3901 macro_subst(tok_str, nested_list, mstr, 1);
3902 /* pop nested defined symbol */
3903 sa1 = *nested_list;
3904 *nested_list = sa1->prev;
3905 tcc_free(sa1);
3906 if (mstr_allocated)
3907 tok_str_free(mstr);
3909 return 0;
3912 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3913 return the resulting string (which must be freed). */
3914 static inline int *macro_twosharps(const int *macro_str)
3916 TokenSym *ts;
3917 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3918 int t;
3919 const char *p1, *p2;
3920 CValue cval;
3921 TokenString macro_str1;
3922 CString cstr;
3924 start_macro_ptr = macro_str;
3925 /* we search the first '##' */
3926 for(;;) {
3927 macro_ptr1 = macro_str;
3928 TOK_GET(t, macro_str, cval);
3929 /* nothing more to do if end of string */
3930 if (t == 0)
3931 return NULL;
3932 if (*macro_str == TOK_TWOSHARPS)
3933 break;
3936 /* we saw '##', so we need more processing to handle it */
3937 cstr_new(&cstr);
3938 tok_str_new(&macro_str1);
3939 tok = t;
3940 tokc = cval;
3942 /* add all tokens seen so far */
3943 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3944 TOK_GET(t, ptr, cval);
3945 tok_str_add2(&macro_str1, t, &cval);
3947 saved_macro_ptr = macro_ptr;
3948 /* XXX: get rid of the use of macro_ptr here */
3949 macro_ptr = (int *)macro_str;
3950 for(;;) {
3951 while (*macro_ptr == TOK_TWOSHARPS) {
3952 macro_ptr++;
3953 macro_ptr1 = macro_ptr;
3954 t = *macro_ptr;
3955 if (t) {
3956 TOK_GET(t, macro_ptr, cval);
3957 /* We concatenate the two tokens if we have an
3958 identifier or a preprocessing number */
3959 cstr_reset(&cstr);
3960 p1 = get_tok_str(tok, &tokc);
3961 cstr_cat(&cstr, p1);
3962 p2 = get_tok_str(t, &cval);
3963 cstr_cat(&cstr, p2);
3964 cstr_ccat(&cstr, '\0');
3966 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3967 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3968 if (tok == TOK_PPNUM) {
3969 /* if number, then create a number token */
3970 /* NOTE: no need to allocate because
3971 tok_str_add2() does it */
3972 tokc.cstr = &cstr;
3973 } else {
3974 /* if identifier, we must do a test to
3975 validate we have a correct identifier */
3976 if (t == TOK_PPNUM) {
3977 const char *p;
3978 int c;
3980 p = p2;
3981 for(;;) {
3982 c = *p;
3983 if (c == '\0')
3984 break;
3985 p++;
3986 if (!isnum(c) && !isid(c))
3987 goto error_pasting;
3990 ts = tok_alloc(cstr.data, strlen(cstr.data));
3991 tok = ts->tok; /* modify current token */
3993 } else {
3994 const char *str = cstr.data;
3995 const unsigned char *q;
3997 /* we look for a valid token */
3998 /* XXX: do more extensive checks */
3999 if (!strcmp(str, ">>=")) {
4000 tok = TOK_A_SAR;
4001 } else if (!strcmp(str, "<<=")) {
4002 tok = TOK_A_SHL;
4003 } else if (strlen(str) == 2) {
4004 /* search in two bytes table */
4005 q = tok_two_chars;
4006 for(;;) {
4007 if (!*q)
4008 goto error_pasting;
4009 if (q[0] == str[0] && q[1] == str[1])
4010 break;
4011 q += 3;
4013 tok = q[2];
4014 } else {
4015 error_pasting:
4016 /* NOTE: because get_tok_str use a static buffer,
4017 we must save it */
4018 cstr_reset(&cstr);
4019 p1 = get_tok_str(tok, &tokc);
4020 cstr_cat(&cstr, p1);
4021 cstr_ccat(&cstr, '\0');
4022 p2 = get_tok_str(t, &cval);
4023 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4024 /* cannot merge tokens: just add them separately */
4025 tok_str_add2(&macro_str1, tok, &tokc);
4026 /* XXX: free associated memory ? */
4027 tok = t;
4028 tokc = cval;
4033 tok_str_add2(&macro_str1, tok, &tokc);
4034 next_nomacro();
4035 if (tok == 0)
4036 break;
4038 macro_ptr = (int *)saved_macro_ptr;
4039 cstr_free(&cstr);
4040 tok_str_add(&macro_str1, 0);
4041 return macro_str1.str;
4045 /* do macro substitution of macro_str and add result to
4046 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4047 inside to avoid recursing. */
4048 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4049 const int *macro_str, int can_read_stream)
4051 Sym *s;
4052 int *saved_macro_ptr, *macro_str1;
4053 const int *ptr;
4054 int t, ret;
4055 CValue cval;
4057 /* first scan for '##' operator handling */
4058 ptr = macro_str;
4059 macro_str1 = macro_twosharps(ptr);
4060 if (macro_str1)
4061 ptr = macro_str1;
4062 while (1) {
4063 /* NOTE: ptr == NULL can only happen if tokens are read from
4064 file stream due to a macro function call */
4065 if (ptr == NULL)
4066 break;
4067 TOK_GET(t, ptr, cval);
4068 if (t == 0)
4069 break;
4070 s = define_find(t);
4071 if (s != NULL) {
4072 /* if nested substitution, do nothing */
4073 if (sym_find2(*nested_list, t))
4074 goto no_subst;
4075 saved_macro_ptr = macro_ptr;
4076 macro_ptr = (int *)ptr;
4077 tok = t;
4078 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4079 ptr = (int *)macro_ptr;
4080 macro_ptr = saved_macro_ptr;
4081 if (ret != 0)
4082 goto no_subst;
4083 } else {
4084 no_subst:
4085 tok_str_add2(tok_str, t, &cval);
4088 if (macro_str1)
4089 tok_str_free(macro_str1);
4092 /* return next token with macro substitution */
4093 static void next(void)
4095 Sym *nested_list, *s;
4096 TokenString str;
4098 redo:
4099 next_nomacro();
4100 if (!macro_ptr) {
4101 /* if not reading from macro substituted string, then try
4102 to substitute macros */
4103 if (tok >= TOK_IDENT &&
4104 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4105 s = define_find(tok);
4106 if (s) {
4107 /* we have a macro: we try to substitute */
4108 tok_str_new(&str);
4109 nested_list = NULL;
4110 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4111 /* substitution done, NOTE: maybe empty */
4112 tok_str_add(&str, 0);
4113 macro_ptr = str.str;
4114 macro_ptr_allocated = str.str;
4115 goto redo;
4119 } else {
4120 if (tok == 0) {
4121 /* end of macro or end of unget buffer */
4122 if (unget_buffer_enabled) {
4123 macro_ptr = unget_saved_macro_ptr;
4124 unget_buffer_enabled = 0;
4125 } else {
4126 /* end of macro string: free it */
4127 tok_str_free(macro_ptr_allocated);
4128 macro_ptr = NULL;
4130 goto redo;
4134 /* convert preprocessor tokens into C tokens */
4135 if (tok == TOK_PPNUM &&
4136 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4137 parse_number((char *)tokc.cstr->data);
4141 /* push back current token and set current token to 'last_tok'. Only
4142 identifier case handled for labels. */
4143 static inline void unget_tok(int last_tok)
4145 int i, n;
4146 int *q;
4147 unget_saved_macro_ptr = macro_ptr;
4148 unget_buffer_enabled = 1;
4149 q = unget_saved_buffer;
4150 macro_ptr = q;
4151 *q++ = tok;
4152 n = tok_ext_size(tok) - 1;
4153 for(i=0;i<n;i++)
4154 *q++ = tokc.tab[i];
4155 *q = 0; /* end of token string */
4156 tok = last_tok;
4160 void swap(int *p, int *q)
4162 int t;
4163 t = *p;
4164 *p = *q;
4165 *q = t;
4168 void vsetc(CType *type, int r, CValue *vc)
4170 int v;
4172 if (vtop >= vstack + VSTACK_SIZE)
4173 error("memory full");
4174 /* cannot let cpu flags if other instruction are generated. Also
4175 avoid leaving VT_JMP anywhere except on the top of the stack
4176 because it would complicate the code generator. */
4177 if (vtop >= vstack) {
4178 v = vtop->r & VT_VALMASK;
4179 if (v == VT_CMP || (v & ~1) == VT_JMP)
4180 gv(RC_INT);
4182 vtop++;
4183 vtop->type = *type;
4184 vtop->r = r;
4185 vtop->r2 = VT_CONST;
4186 vtop->c = *vc;
4189 /* push integer constant */
4190 void vpushi(int v)
4192 CValue cval;
4193 cval.i = v;
4194 vsetc(&int_type, VT_CONST, &cval);
4197 /* Return a static symbol pointing to a section */
4198 static Sym *get_sym_ref(CType *type, Section *sec,
4199 unsigned long offset, unsigned long size)
4201 int v;
4202 Sym *sym;
4204 v = anon_sym++;
4205 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4206 sym->type.ref = type->ref;
4207 sym->r = VT_CONST | VT_SYM;
4208 put_extern_sym(sym, sec, offset, size);
4209 return sym;
4212 /* push a reference to a section offset by adding a dummy symbol */
4213 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4215 CValue cval;
4217 cval.ul = 0;
4218 vsetc(type, VT_CONST | VT_SYM, &cval);
4219 vtop->sym = get_sym_ref(type, sec, offset, size);
4222 /* define a new external reference to a symbol 'v' of type 'u' */
4223 static Sym *external_global_sym(int v, CType *type, int r)
4225 Sym *s;
4227 s = sym_find(v);
4228 if (!s) {
4229 /* push forward reference */
4230 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4231 s->type.ref = type->ref;
4232 s->r = r | VT_CONST | VT_SYM;
4234 return s;
4237 /* define a new external reference to a symbol 'v' of type 'u' */
4238 static Sym *external_sym(int v, CType *type, int r)
4240 Sym *s;
4242 s = sym_find(v);
4243 if (!s) {
4244 /* push forward reference */
4245 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4246 s->type.t |= VT_EXTERN;
4247 } else {
4248 if (!is_compatible_types(&s->type, type))
4249 error("incompatible types for redefinition of '%s'",
4250 get_tok_str(v, NULL));
4252 return s;
4255 /* push a reference to global symbol v */
4256 static void vpush_global_sym(CType *type, int v)
4258 Sym *sym;
4259 CValue cval;
4261 sym = external_global_sym(v, type, 0);
4262 cval.ul = 0;
4263 vsetc(type, VT_CONST | VT_SYM, &cval);
4264 vtop->sym = sym;
4267 void vset(CType *type, int r, int v)
4269 CValue cval;
4271 cval.i = v;
4272 vsetc(type, r, &cval);
4275 void vseti(int r, int v)
4277 CType type;
4278 type.t = VT_INT;
4279 vset(&type, r, v);
4282 void vswap(void)
4284 SValue tmp;
4286 tmp = vtop[0];
4287 vtop[0] = vtop[-1];
4288 vtop[-1] = tmp;
4291 void vpushv(SValue *v)
4293 if (vtop >= vstack + VSTACK_SIZE)
4294 error("memory full");
4295 vtop++;
4296 *vtop = *v;
4299 void vdup(void)
4301 vpushv(vtop);
4304 /* save r to the memory stack, and mark it as being free */
4305 void save_reg(int r)
4307 int l, saved, size, align;
4308 SValue *p, sv;
4309 CType *type;
4311 /* modify all stack values */
4312 saved = 0;
4313 l = 0;
4314 for(p=vstack;p<=vtop;p++) {
4315 if ((p->r & VT_VALMASK) == r ||
4316 (p->r2 & VT_VALMASK) == r) {
4317 /* must save value on stack if not already done */
4318 if (!saved) {
4319 /* NOTE: must reload 'r' because r might be equal to r2 */
4320 r = p->r & VT_VALMASK;
4321 /* store register in the stack */
4322 type = &p->type;
4323 if ((p->r & VT_LVAL) ||
4324 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4325 type = &int_type;
4326 size = type_size(type, &align);
4327 loc = (loc - size) & -align;
4328 sv.type.t = type->t;
4329 sv.r = VT_LOCAL | VT_LVAL;
4330 sv.c.ul = loc;
4331 store(r, &sv);
4332 #ifdef TCC_TARGET_I386
4333 /* x86 specific: need to pop fp register ST0 if saved */
4334 if (r == TREG_ST0) {
4335 o(0xd9dd); /* fstp %st(1) */
4337 #endif
4338 /* special long long case */
4339 if ((type->t & VT_BTYPE) == VT_LLONG) {
4340 sv.c.ul += 4;
4341 store(p->r2, &sv);
4343 l = loc;
4344 saved = 1;
4346 /* mark that stack entry as being saved on the stack */
4347 if (p->r & VT_LVAL) {
4348 /* also clear the bounded flag because the
4349 relocation address of the function was stored in
4350 p->c.ul */
4351 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4352 } else {
4353 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4355 p->r2 = VT_CONST;
4356 p->c.ul = l;
4361 /* find a register of class 'rc2' with at most one reference on stack.
4362 * If none, call get_reg(rc) */
4363 int get_reg_ex(int rc, int rc2)
4365 int r;
4366 SValue *p;
4368 for(r=0;r<NB_REGS;r++) {
4369 if (reg_classes[r] & rc2) {
4370 int n;
4371 n=0;
4372 for(p = vstack; p <= vtop; p++) {
4373 if ((p->r & VT_VALMASK) == r ||
4374 (p->r2 & VT_VALMASK) == r)
4375 n++;
4377 if (n <= 1)
4378 return r;
4381 return get_reg(rc);
4384 /* find a free register of class 'rc'. If none, save one register */
4385 int get_reg(int rc)
4387 int r;
4388 SValue *p;
4390 /* find a free register */
4391 for(r=0;r<NB_REGS;r++) {
4392 if (reg_classes[r] & rc) {
4393 for(p=vstack;p<=vtop;p++) {
4394 if ((p->r & VT_VALMASK) == r ||
4395 (p->r2 & VT_VALMASK) == r)
4396 goto notfound;
4398 return r;
4400 notfound: ;
4403 /* no register left : free the first one on the stack (VERY
4404 IMPORTANT to start from the bottom to ensure that we don't
4405 spill registers used in gen_opi()) */
4406 for(p=vstack;p<=vtop;p++) {
4407 r = p->r & VT_VALMASK;
4408 if (r < VT_CONST && (reg_classes[r] & rc))
4409 goto save_found;
4410 /* also look at second register (if long long) */
4411 r = p->r2 & VT_VALMASK;
4412 if (r < VT_CONST && (reg_classes[r] & rc)) {
4413 save_found:
4414 save_reg(r);
4415 return r;
4418 /* Should never comes here */
4419 return -1;
4422 /* save registers up to (vtop - n) stack entry */
4423 void save_regs(int n)
4425 int r;
4426 SValue *p, *p1;
4427 p1 = vtop - n;
4428 for(p = vstack;p <= p1; p++) {
4429 r = p->r & VT_VALMASK;
4430 if (r < VT_CONST) {
4431 save_reg(r);
4436 /* move register 's' to 'r', and flush previous value of r to memory
4437 if needed */
4438 void move_reg(int r, int s)
4440 SValue sv;
4442 if (r != s) {
4443 save_reg(r);
4444 sv.type.t = VT_INT;
4445 sv.r = s;
4446 sv.c.ul = 0;
4447 load(r, &sv);
4451 /* get address of vtop (vtop MUST BE an lvalue) */
4452 void gaddrof(void)
4454 vtop->r &= ~VT_LVAL;
4455 /* tricky: if saved lvalue, then we can go back to lvalue */
4456 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4457 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4460 #ifdef CONFIG_TCC_BCHECK
4461 /* generate lvalue bound code */
4462 void gbound(void)
4464 int lval_type;
4465 CType type1;
4467 vtop->r &= ~VT_MUSTBOUND;
4468 /* if lvalue, then use checking code before dereferencing */
4469 if (vtop->r & VT_LVAL) {
4470 /* if not VT_BOUNDED value, then make one */
4471 if (!(vtop->r & VT_BOUNDED)) {
4472 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4473 /* must save type because we must set it to int to get pointer */
4474 type1 = vtop->type;
4475 vtop->type.t = VT_INT;
4476 gaddrof();
4477 vpushi(0);
4478 gen_bounded_ptr_add();
4479 vtop->r |= lval_type;
4480 vtop->type = type1;
4482 /* then check for dereferencing */
4483 gen_bounded_ptr_deref();
4486 #endif
4488 /* store vtop a register belonging to class 'rc'. lvalues are
4489 converted to values. Cannot be used if cannot be converted to
4490 register value (such as structures). */
4491 int gv(int rc)
4493 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4494 unsigned long long ll;
4496 /* NOTE: get_reg can modify vstack[] */
4497 if (vtop->type.t & VT_BITFIELD) {
4498 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4499 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4500 /* remove bit field info to avoid loops */
4501 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4502 /* generate shifts */
4503 vpushi(32 - (bit_pos + bit_size));
4504 gen_op(TOK_SHL);
4505 vpushi(32 - bit_size);
4506 /* NOTE: transformed to SHR if unsigned */
4507 gen_op(TOK_SAR);
4508 r = gv(rc);
4509 } else {
4510 if (is_float(vtop->type.t) &&
4511 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4512 Sym *sym;
4513 int *ptr;
4514 unsigned long offset;
4516 /* XXX: unify with initializers handling ? */
4517 /* CPUs usually cannot use float constants, so we store them
4518 generically in data segment */
4519 size = type_size(&vtop->type, &align);
4520 offset = (data_section->data_offset + align - 1) & -align;
4521 data_section->data_offset = offset;
4522 /* XXX: not portable yet */
4523 ptr = section_ptr_add(data_section, size);
4524 size = size >> 2;
4525 for(i=0;i<size;i++)
4526 ptr[i] = vtop->c.tab[i];
4527 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4528 vtop->r |= VT_LVAL | VT_SYM;
4529 vtop->sym = sym;
4530 vtop->c.ul = 0;
4532 #ifdef CONFIG_TCC_BCHECK
4533 if (vtop->r & VT_MUSTBOUND)
4534 gbound();
4535 #endif
4537 r = vtop->r & VT_VALMASK;
4538 /* need to reload if:
4539 - constant
4540 - lvalue (need to dereference pointer)
4541 - already a register, but not in the right class */
4542 if (r >= VT_CONST ||
4543 (vtop->r & VT_LVAL) ||
4544 !(reg_classes[r] & rc) ||
4545 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4546 !(reg_classes[vtop->r2] & rc))) {
4547 r = get_reg(rc);
4548 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4549 /* two register type load : expand to two words
4550 temporarily */
4551 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4552 /* load constant */
4553 ll = vtop->c.ull;
4554 vtop->c.ui = ll; /* first word */
4555 load(r, vtop);
4556 vtop->r = r; /* save register value */
4557 vpushi(ll >> 32); /* second word */
4558 } else if (r >= VT_CONST ||
4559 (vtop->r & VT_LVAL)) {
4560 /* load from memory */
4561 load(r, vtop);
4562 vdup();
4563 vtop[-1].r = r; /* save register value */
4564 /* increment pointer to get second word */
4565 vtop->type.t = VT_INT;
4566 gaddrof();
4567 vpushi(4);
4568 gen_op('+');
4569 vtop->r |= VT_LVAL;
4570 } else {
4571 /* move registers */
4572 load(r, vtop);
4573 vdup();
4574 vtop[-1].r = r; /* save register value */
4575 vtop->r = vtop[-1].r2;
4577 /* allocate second register */
4578 rc2 = RC_INT;
4579 if (rc == RC_IRET)
4580 rc2 = RC_LRET;
4581 r2 = get_reg(rc2);
4582 load(r2, vtop);
4583 vpop();
4584 /* write second register */
4585 vtop->r2 = r2;
4586 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4587 int t1, t;
4588 /* lvalue of scalar type : need to use lvalue type
4589 because of possible cast */
4590 t = vtop->type.t;
4591 t1 = t;
4592 /* compute memory access type */
4593 if (vtop->r & VT_LVAL_BYTE)
4594 t = VT_BYTE;
4595 else if (vtop->r & VT_LVAL_SHORT)
4596 t = VT_SHORT;
4597 if (vtop->r & VT_LVAL_UNSIGNED)
4598 t |= VT_UNSIGNED;
4599 vtop->type.t = t;
4600 load(r, vtop);
4601 /* restore wanted type */
4602 vtop->type.t = t1;
4603 } else {
4604 /* one register type load */
4605 load(r, vtop);
4608 vtop->r = r;
4610 return r;
4613 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4614 void gv2(int rc1, int rc2)
4616 int v;
4618 /* generate more generic register first. But VT_JMP or VT_CMP
4619 values must be generated first in all cases to avoid possible
4620 reload errors */
4621 v = vtop[0].r & VT_VALMASK;
4622 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4623 vswap();
4624 gv(rc1);
4625 vswap();
4626 gv(rc2);
4627 /* test if reload is needed for first register */
4628 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4629 vswap();
4630 gv(rc1);
4631 vswap();
4633 } else {
4634 gv(rc2);
4635 vswap();
4636 gv(rc1);
4637 vswap();
4638 /* test if reload is needed for first register */
4639 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4640 gv(rc2);
4645 /* expand long long on stack in two int registers */
4646 void lexpand(void)
4648 int u;
4650 u = vtop->type.t & VT_UNSIGNED;
4651 gv(RC_INT);
4652 vdup();
4653 vtop[0].r = vtop[-1].r2;
4654 vtop[0].r2 = VT_CONST;
4655 vtop[-1].r2 = VT_CONST;
4656 vtop[0].type.t = VT_INT | u;
4657 vtop[-1].type.t = VT_INT | u;
4660 /* build a long long from two ints */
4661 void lbuild(int t)
4663 gv2(RC_INT, RC_INT);
4664 vtop[-1].r2 = vtop[0].r;
4665 vtop[-1].type.t = t;
4666 vpop();
4669 /* rotate n first stack elements to the bottom
4670 I1 ... In -> I2 ... In I1 [top is right]
4672 void vrotb(int n)
4674 int i;
4675 SValue tmp;
4677 tmp = vtop[-n + 1];
4678 for(i=-n+1;i!=0;i++)
4679 vtop[i] = vtop[i+1];
4680 vtop[0] = tmp;
4683 /* rotate n first stack elements to the top
4684 I1 ... In -> In I1 ... I(n-1) [top is right]
4686 void vrott(int n)
4688 int i;
4689 SValue tmp;
4691 tmp = vtop[0];
4692 for(i = 0;i < n - 1; i++)
4693 vtop[-i] = vtop[-i - 1];
4694 vtop[-n + 1] = tmp;
4697 /* pop stack value */
4698 void vpop(void)
4700 int v;
4701 v = vtop->r & VT_VALMASK;
4702 #ifdef TCC_TARGET_I386
4703 /* for x86, we need to pop the FP stack */
4704 if (v == TREG_ST0 && !nocode_wanted) {
4705 o(0xd9dd); /* fstp %st(1) */
4706 } else
4707 #endif
4708 if (v == VT_JMP || v == VT_JMPI) {
4709 /* need to put correct jump if && or || without test */
4710 gsym(vtop->c.ul);
4712 vtop--;
4715 /* convert stack entry to register and duplicate its value in another
4716 register */
4717 void gv_dup(void)
4719 int rc, t, r, r1;
4720 SValue sv;
4722 t = vtop->type.t;
4723 if ((t & VT_BTYPE) == VT_LLONG) {
4724 lexpand();
4725 gv_dup();
4726 vswap();
4727 vrotb(3);
4728 gv_dup();
4729 vrotb(4);
4730 /* stack: H L L1 H1 */
4731 lbuild(t);
4732 vrotb(3);
4733 vrotb(3);
4734 vswap();
4735 lbuild(t);
4736 vswap();
4737 } else {
4738 /* duplicate value */
4739 rc = RC_INT;
4740 sv.type.t = VT_INT;
4741 if (is_float(t)) {
4742 rc = RC_FLOAT;
4743 sv.type.t = t;
4745 r = gv(rc);
4746 r1 = get_reg(rc);
4747 sv.r = r;
4748 sv.c.ul = 0;
4749 load(r1, &sv); /* move r to r1 */
4750 vdup();
4751 /* duplicates value */
4752 vtop->r = r1;
4756 /* generate CPU independent (unsigned) long long operations */
4757 void gen_opl(int op)
4759 int t, a, b, op1, c, i;
4760 int func;
4761 SValue tmp;
4763 switch(op) {
4764 case '/':
4765 case TOK_PDIV:
4766 func = TOK___divdi3;
4767 goto gen_func;
4768 case TOK_UDIV:
4769 func = TOK___udivdi3;
4770 goto gen_func;
4771 case '%':
4772 func = TOK___moddi3;
4773 goto gen_func;
4774 case TOK_UMOD:
4775 func = TOK___umoddi3;
4776 gen_func:
4777 /* call generic long long function */
4778 vpush_global_sym(&func_old_type, func);
4779 vrott(3);
4780 gfunc_call(2);
4781 vpushi(0);
4782 vtop->r = REG_IRET;
4783 vtop->r2 = REG_LRET;
4784 break;
4785 case '^':
4786 case '&':
4787 case '|':
4788 case '*':
4789 case '+':
4790 case '-':
4791 t = vtop->type.t;
4792 vswap();
4793 lexpand();
4794 vrotb(3);
4795 lexpand();
4796 /* stack: L1 H1 L2 H2 */
4797 tmp = vtop[0];
4798 vtop[0] = vtop[-3];
4799 vtop[-3] = tmp;
4800 tmp = vtop[-2];
4801 vtop[-2] = vtop[-3];
4802 vtop[-3] = tmp;
4803 vswap();
4804 /* stack: H1 H2 L1 L2 */
4805 if (op == '*') {
4806 vpushv(vtop - 1);
4807 vpushv(vtop - 1);
4808 gen_op(TOK_UMULL);
4809 lexpand();
4810 /* stack: H1 H2 L1 L2 ML MH */
4811 for(i=0;i<4;i++)
4812 vrotb(6);
4813 /* stack: ML MH H1 H2 L1 L2 */
4814 tmp = vtop[0];
4815 vtop[0] = vtop[-2];
4816 vtop[-2] = tmp;
4817 /* stack: ML MH H1 L2 H2 L1 */
4818 gen_op('*');
4819 vrotb(3);
4820 vrotb(3);
4821 gen_op('*');
4822 /* stack: ML MH M1 M2 */
4823 gen_op('+');
4824 gen_op('+');
4825 } else if (op == '+' || op == '-') {
4826 /* XXX: add non carry method too (for MIPS or alpha) */
4827 if (op == '+')
4828 op1 = TOK_ADDC1;
4829 else
4830 op1 = TOK_SUBC1;
4831 gen_op(op1);
4832 /* stack: H1 H2 (L1 op L2) */
4833 vrotb(3);
4834 vrotb(3);
4835 gen_op(op1 + 1); /* TOK_xxxC2 */
4836 } else {
4837 gen_op(op);
4838 /* stack: H1 H2 (L1 op L2) */
4839 vrotb(3);
4840 vrotb(3);
4841 /* stack: (L1 op L2) H1 H2 */
4842 gen_op(op);
4843 /* stack: (L1 op L2) (H1 op H2) */
4845 /* stack: L H */
4846 lbuild(t);
4847 break;
4848 case TOK_SAR:
4849 case TOK_SHR:
4850 case TOK_SHL:
4851 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4852 t = vtop[-1].type.t;
4853 vswap();
4854 lexpand();
4855 vrotb(3);
4856 /* stack: L H shift */
4857 c = (int)vtop->c.i;
4858 /* constant: simpler */
4859 /* NOTE: all comments are for SHL. the other cases are
4860 done by swaping words */
4861 vpop();
4862 if (op != TOK_SHL)
4863 vswap();
4864 if (c >= 32) {
4865 /* stack: L H */
4866 vpop();
4867 if (c > 32) {
4868 vpushi(c - 32);
4869 gen_op(op);
4871 if (op != TOK_SAR) {
4872 vpushi(0);
4873 } else {
4874 gv_dup();
4875 vpushi(31);
4876 gen_op(TOK_SAR);
4878 vswap();
4879 } else {
4880 vswap();
4881 gv_dup();
4882 /* stack: H L L */
4883 vpushi(c);
4884 gen_op(op);
4885 vswap();
4886 vpushi(32 - c);
4887 if (op == TOK_SHL)
4888 gen_op(TOK_SHR);
4889 else
4890 gen_op(TOK_SHL);
4891 vrotb(3);
4892 /* stack: L L H */
4893 vpushi(c);
4894 if (op == TOK_SHL)
4895 gen_op(TOK_SHL);
4896 else
4897 gen_op(TOK_SHR);
4898 gen_op('|');
4900 if (op != TOK_SHL)
4901 vswap();
4902 lbuild(t);
4903 } else {
4904 /* XXX: should provide a faster fallback on x86 ? */
4905 switch(op) {
4906 case TOK_SAR:
4907 func = TOK___sardi3;
4908 goto gen_func;
4909 case TOK_SHR:
4910 func = TOK___shrdi3;
4911 goto gen_func;
4912 case TOK_SHL:
4913 func = TOK___shldi3;
4914 goto gen_func;
4917 break;
4918 default:
4919 /* compare operations */
4920 t = vtop->type.t;
4921 vswap();
4922 lexpand();
4923 vrotb(3);
4924 lexpand();
4925 /* stack: L1 H1 L2 H2 */
4926 tmp = vtop[-1];
4927 vtop[-1] = vtop[-2];
4928 vtop[-2] = tmp;
4929 /* stack: L1 L2 H1 H2 */
4930 /* compare high */
4931 op1 = op;
4932 /* when values are equal, we need to compare low words. since
4933 the jump is inverted, we invert the test too. */
4934 if (op1 == TOK_LT)
4935 op1 = TOK_LE;
4936 else if (op1 == TOK_GT)
4937 op1 = TOK_GE;
4938 else if (op1 == TOK_ULT)
4939 op1 = TOK_ULE;
4940 else if (op1 == TOK_UGT)
4941 op1 = TOK_UGE;
4942 a = 0;
4943 b = 0;
4944 gen_op(op1);
4945 if (op1 != TOK_NE) {
4946 a = gtst(1, 0);
4948 if (op != TOK_EQ) {
4949 /* generate non equal test */
4950 /* XXX: NOT PORTABLE yet */
4951 if (a == 0) {
4952 b = gtst(0, 0);
4953 } else {
4954 #if defined(TCC_TARGET_I386)
4955 b = psym(0x850f, 0);
4956 #elif defined(TCC_TARGET_ARM)
4957 b = ind;
4958 o(0x1A000000 | encbranch(ind, 0, 1));
4959 #else
4960 #error not supported
4961 #endif
4964 /* compare low. Always unsigned */
4965 op1 = op;
4966 if (op1 == TOK_LT)
4967 op1 = TOK_ULT;
4968 else if (op1 == TOK_LE)
4969 op1 = TOK_ULE;
4970 else if (op1 == TOK_GT)
4971 op1 = TOK_UGT;
4972 else if (op1 == TOK_GE)
4973 op1 = TOK_UGE;
4974 gen_op(op1);
4975 a = gtst(1, a);
4976 gsym(b);
4977 vseti(VT_JMPI, a);
4978 break;
4982 /* handle integer constant optimizations and various machine
4983 independent opt */
4984 void gen_opic(int op)
4986 int fc, c1, c2, n;
4987 SValue *v1, *v2;
4989 v1 = vtop - 1;
4990 v2 = vtop;
4991 /* currently, we cannot do computations with forward symbols */
4992 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4993 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4994 if (c1 && c2) {
4995 fc = v2->c.i;
4996 switch(op) {
4997 case '+': v1->c.i += fc; break;
4998 case '-': v1->c.i -= fc; break;
4999 case '&': v1->c.i &= fc; break;
5000 case '^': v1->c.i ^= fc; break;
5001 case '|': v1->c.i |= fc; break;
5002 case '*': v1->c.i *= fc; break;
5004 case TOK_PDIV:
5005 case '/':
5006 case '%':
5007 case TOK_UDIV:
5008 case TOK_UMOD:
5009 /* if division by zero, generate explicit division */
5010 if (fc == 0) {
5011 if (const_wanted)
5012 error("division by zero in constant");
5013 goto general_case;
5015 switch(op) {
5016 default: v1->c.i /= fc; break;
5017 case '%': v1->c.i %= fc; break;
5018 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5019 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5021 break;
5022 case TOK_SHL: v1->c.i <<= fc; break;
5023 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5024 case TOK_SAR: v1->c.i >>= fc; break;
5025 /* tests */
5026 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5027 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5028 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5029 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5030 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5031 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5032 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5033 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5034 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5035 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5036 /* logical */
5037 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5038 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5039 default:
5040 goto general_case;
5042 vtop--;
5043 } else {
5044 /* if commutative ops, put c2 as constant */
5045 if (c1 && (op == '+' || op == '&' || op == '^' ||
5046 op == '|' || op == '*')) {
5047 vswap();
5048 swap(&c1, &c2);
5050 fc = vtop->c.i;
5051 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5052 op == TOK_PDIV) &&
5053 fc == 1) ||
5054 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5055 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5056 fc == 0) ||
5057 (op == '&' &&
5058 fc == -1))) {
5059 /* nothing to do */
5060 vtop--;
5061 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5062 /* try to use shifts instead of muls or divs */
5063 if (fc > 0 && (fc & (fc - 1)) == 0) {
5064 n = -1;
5065 while (fc) {
5066 fc >>= 1;
5067 n++;
5069 vtop->c.i = n;
5070 if (op == '*')
5071 op = TOK_SHL;
5072 else if (op == TOK_PDIV)
5073 op = TOK_SAR;
5074 else
5075 op = TOK_SHR;
5077 goto general_case;
5078 } else if (c2 && (op == '+' || op == '-') &&
5079 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5080 (VT_CONST | VT_SYM)) {
5081 /* symbol + constant case */
5082 if (op == '-')
5083 fc = -fc;
5084 vtop--;
5085 vtop->c.i += fc;
5086 } else {
5087 general_case:
5088 if (!nocode_wanted) {
5089 /* call low level op generator */
5090 gen_opi(op);
5091 } else {
5092 vtop--;
5098 /* generate a floating point operation with constant propagation */
5099 void gen_opif(int op)
5101 int c1, c2;
5102 SValue *v1, *v2;
5103 long double f1, f2;
5105 v1 = vtop - 1;
5106 v2 = vtop;
5107 /* currently, we cannot do computations with forward symbols */
5108 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5109 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5110 if (c1 && c2) {
5111 if (v1->type.t == VT_FLOAT) {
5112 f1 = v1->c.f;
5113 f2 = v2->c.f;
5114 } else if (v1->type.t == VT_DOUBLE) {
5115 f1 = v1->c.d;
5116 f2 = v2->c.d;
5117 } else {
5118 f1 = v1->c.ld;
5119 f2 = v2->c.ld;
5122 /* NOTE: we only do constant propagation if finite number (not
5123 NaN or infinity) (ANSI spec) */
5124 if (!ieee_finite(f1) || !ieee_finite(f2))
5125 goto general_case;
5127 switch(op) {
5128 case '+': f1 += f2; break;
5129 case '-': f1 -= f2; break;
5130 case '*': f1 *= f2; break;
5131 case '/':
5132 if (f2 == 0.0) {
5133 if (const_wanted)
5134 error("division by zero in constant");
5135 goto general_case;
5137 f1 /= f2;
5138 break;
5139 /* XXX: also handles tests ? */
5140 default:
5141 goto general_case;
5143 /* XXX: overflow test ? */
5144 if (v1->type.t == VT_FLOAT) {
5145 v1->c.f = f1;
5146 } else if (v1->type.t == VT_DOUBLE) {
5147 v1->c.d = f1;
5148 } else {
5149 v1->c.ld = f1;
5151 vtop--;
5152 } else {
5153 general_case:
5154 if (!nocode_wanted) {
5155 gen_opf(op);
5156 } else {
5157 vtop--;
5162 static int pointed_size(CType *type)
5164 int align;
5165 return type_size(pointed_type(type), &align);
5168 static inline int is_null_pointer(SValue *p)
5170 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5171 return 0;
5172 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5173 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5176 static inline int is_integer_btype(int bt)
5178 return (bt == VT_BYTE || bt == VT_SHORT ||
5179 bt == VT_INT || bt == VT_LLONG);
5182 /* check types for comparison or substraction of pointers */
5183 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5185 CType *type1, *type2, tmp_type1, tmp_type2;
5186 int bt1, bt2;
5188 /* null pointers are accepted for all comparisons as gcc */
5189 if (is_null_pointer(p1) || is_null_pointer(p2))
5190 return;
5191 type1 = &p1->type;
5192 type2 = &p2->type;
5193 bt1 = type1->t & VT_BTYPE;
5194 bt2 = type2->t & VT_BTYPE;
5195 /* accept comparison between pointer and integer with a warning */
5196 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5197 warning("comparison between pointer and integer");
5198 return;
5201 /* both must be pointers or implicit function pointers */
5202 if (bt1 == VT_PTR) {
5203 type1 = pointed_type(type1);
5204 } else if (bt1 != VT_FUNC)
5205 goto invalid_operands;
5207 if (bt2 == VT_PTR) {
5208 type2 = pointed_type(type2);
5209 } else if (bt2 != VT_FUNC) {
5210 invalid_operands:
5211 error("invalid operands to binary %s", get_tok_str(op, NULL));
5213 if ((type1->t & VT_BTYPE) == VT_VOID ||
5214 (type2->t & VT_BTYPE) == VT_VOID)
5215 return;
5216 tmp_type1 = *type1;
5217 tmp_type2 = *type2;
5218 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5219 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5220 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5221 /* gcc-like error if '-' is used */
5222 if (op == '-')
5223 goto invalid_operands;
5224 else
5225 warning("comparison of distinct pointer types lacks a cast");
5229 /* generic gen_op: handles types problems */
5230 void gen_op(int op)
5232 int u, t1, t2, bt1, bt2, t;
5233 CType type1;
5235 t1 = vtop[-1].type.t;
5236 t2 = vtop[0].type.t;
5237 bt1 = t1 & VT_BTYPE;
5238 bt2 = t2 & VT_BTYPE;
5240 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5241 /* at least one operand is a pointer */
5242 /* relationnal op: must be both pointers */
5243 if (op >= TOK_ULT && op <= TOK_GT) {
5244 check_comparison_pointer_types(vtop - 1, vtop, op);
5245 /* pointers are handled are unsigned */
5246 t = VT_INT | VT_UNSIGNED;
5247 goto std_op;
5249 /* if both pointers, then it must be the '-' op */
5250 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5251 if (op != '-')
5252 error("cannot use pointers here");
5253 check_comparison_pointer_types(vtop - 1, vtop, op);
5254 /* XXX: check that types are compatible */
5255 u = pointed_size(&vtop[-1].type);
5256 gen_opic(op);
5257 /* set to integer type */
5258 vtop->type.t = VT_INT;
5259 vpushi(u);
5260 gen_op(TOK_PDIV);
5261 } else {
5262 /* exactly one pointer : must be '+' or '-'. */
5263 if (op != '-' && op != '+')
5264 error("cannot use pointers here");
5265 /* Put pointer as first operand */
5266 if (bt2 == VT_PTR) {
5267 vswap();
5268 swap(&t1, &t2);
5270 type1 = vtop[-1].type;
5271 /* XXX: cast to int ? (long long case) */
5272 vpushi(pointed_size(&vtop[-1].type));
5273 gen_op('*');
5274 #ifdef CONFIG_TCC_BCHECK
5275 /* if evaluating constant expression, no code should be
5276 generated, so no bound check */
5277 if (do_bounds_check && !const_wanted) {
5278 /* if bounded pointers, we generate a special code to
5279 test bounds */
5280 if (op == '-') {
5281 vpushi(0);
5282 vswap();
5283 gen_op('-');
5285 gen_bounded_ptr_add();
5286 } else
5287 #endif
5289 gen_opic(op);
5291 /* put again type if gen_opic() swaped operands */
5292 vtop->type = type1;
5294 } else if (is_float(bt1) || is_float(bt2)) {
5295 /* compute bigger type and do implicit casts */
5296 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5297 t = VT_LDOUBLE;
5298 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5299 t = VT_DOUBLE;
5300 } else {
5301 t = VT_FLOAT;
5303 /* floats can only be used for a few operations */
5304 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5305 (op < TOK_ULT || op > TOK_GT))
5306 error("invalid operands for binary operation");
5307 goto std_op;
5308 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5309 /* cast to biggest op */
5310 t = VT_LLONG;
5311 /* convert to unsigned if it does not fit in a long long */
5312 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5313 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5314 t |= VT_UNSIGNED;
5315 goto std_op;
5316 } else {
5317 /* integer operations */
5318 t = VT_INT;
5319 /* convert to unsigned if it does not fit in an integer */
5320 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5321 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5322 t |= VT_UNSIGNED;
5323 std_op:
5324 /* XXX: currently, some unsigned operations are explicit, so
5325 we modify them here */
5326 if (t & VT_UNSIGNED) {
5327 if (op == TOK_SAR)
5328 op = TOK_SHR;
5329 else if (op == '/')
5330 op = TOK_UDIV;
5331 else if (op == '%')
5332 op = TOK_UMOD;
5333 else if (op == TOK_LT)
5334 op = TOK_ULT;
5335 else if (op == TOK_GT)
5336 op = TOK_UGT;
5337 else if (op == TOK_LE)
5338 op = TOK_ULE;
5339 else if (op == TOK_GE)
5340 op = TOK_UGE;
5342 vswap();
5343 type1.t = t;
5344 gen_cast(&type1);
5345 vswap();
5346 /* special case for shifts and long long: we keep the shift as
5347 an integer */
5348 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5349 type1.t = VT_INT;
5350 gen_cast(&type1);
5351 if (is_float(t))
5352 gen_opif(op);
5353 else if ((t & VT_BTYPE) == VT_LLONG)
5354 gen_opl(op);
5355 else
5356 gen_opic(op);
5357 if (op >= TOK_ULT && op <= TOK_GT) {
5358 /* relationnal op: the result is an int */
5359 vtop->type.t = VT_INT;
5360 } else {
5361 vtop->type.t = t;
5366 /* generic itof for unsigned long long case */
5367 void gen_cvt_itof1(int t)
5369 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5370 (VT_LLONG | VT_UNSIGNED)) {
5372 if (t == VT_FLOAT)
5373 vpush_global_sym(&func_old_type, TOK___ulltof);
5374 else if (t == VT_DOUBLE)
5375 vpush_global_sym(&func_old_type, TOK___ulltod);
5376 else
5377 vpush_global_sym(&func_old_type, TOK___ulltold);
5378 vrott(2);
5379 gfunc_call(1);
5380 vpushi(0);
5381 vtop->r = REG_FRET;
5382 } else {
5383 gen_cvt_itof(t);
5387 /* generic ftoi for unsigned long long case */
5388 void gen_cvt_ftoi1(int t)
5390 int st;
5392 if (t == (VT_LLONG | VT_UNSIGNED)) {
5393 /* not handled natively */
5394 st = vtop->type.t & VT_BTYPE;
5395 if (st == VT_FLOAT)
5396 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5397 else if (st == VT_DOUBLE)
5398 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5399 else
5400 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5401 vrott(2);
5402 gfunc_call(1);
5403 vpushi(0);
5404 vtop->r = REG_IRET;
5405 vtop->r2 = REG_LRET;
5406 } else {
5407 gen_cvt_ftoi(t);
5411 /* force char or short cast */
5412 void force_charshort_cast(int t)
5414 int bits, dbt;
5415 dbt = t & VT_BTYPE;
5416 /* XXX: add optimization if lvalue : just change type and offset */
5417 if (dbt == VT_BYTE)
5418 bits = 8;
5419 else
5420 bits = 16;
5421 if (t & VT_UNSIGNED) {
5422 vpushi((1 << bits) - 1);
5423 gen_op('&');
5424 } else {
5425 bits = 32 - bits;
5426 vpushi(bits);
5427 gen_op(TOK_SHL);
5428 vpushi(bits);
5429 gen_op(TOK_SAR);
5433 /* cast 'vtop' to 'type' */
5434 static void gen_cast(CType *type)
5436 int sbt, dbt, sf, df, c;
5438 /* special delayed cast for char/short */
5439 /* XXX: in some cases (multiple cascaded casts), it may still
5440 be incorrect */
5441 if (vtop->r & VT_MUSTCAST) {
5442 vtop->r &= ~VT_MUSTCAST;
5443 force_charshort_cast(vtop->type.t);
5446 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5447 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5449 if (sbt != dbt && !nocode_wanted) {
5450 sf = is_float(sbt);
5451 df = is_float(dbt);
5452 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5453 if (sf && df) {
5454 /* convert from fp to fp */
5455 if (c) {
5456 /* constant case: we can do it now */
5457 /* XXX: in ISOC, cannot do it if error in convert */
5458 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5459 vtop->c.f = (float)vtop->c.d;
5460 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5461 vtop->c.f = (float)vtop->c.ld;
5462 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5463 vtop->c.d = (double)vtop->c.f;
5464 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5465 vtop->c.d = (double)vtop->c.ld;
5466 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5467 vtop->c.ld = (long double)vtop->c.f;
5468 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5469 vtop->c.ld = (long double)vtop->c.d;
5470 } else {
5471 /* non constant case: generate code */
5472 gen_cvt_ftof(dbt);
5474 } else if (df) {
5475 /* convert int to fp */
5476 if (c) {
5477 switch(sbt) {
5478 case VT_LLONG | VT_UNSIGNED:
5479 case VT_LLONG:
5480 /* XXX: add const cases for long long */
5481 goto do_itof;
5482 case VT_INT | VT_UNSIGNED:
5483 switch(dbt) {
5484 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5485 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5486 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5488 break;
5489 default:
5490 switch(dbt) {
5491 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5492 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5493 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5495 break;
5497 } else {
5498 do_itof:
5499 #if !defined(TCC_TARGET_ARM)
5500 gen_cvt_itof1(dbt);
5501 #else
5502 gen_cvt_itof(dbt);
5503 #endif
5505 } else if (sf) {
5506 /* convert fp to int */
5507 /* we handle char/short/etc... with generic code */
5508 if (dbt != (VT_INT | VT_UNSIGNED) &&
5509 dbt != (VT_LLONG | VT_UNSIGNED) &&
5510 dbt != VT_LLONG)
5511 dbt = VT_INT;
5512 if (c) {
5513 switch(dbt) {
5514 case VT_LLONG | VT_UNSIGNED:
5515 case VT_LLONG:
5516 /* XXX: add const cases for long long */
5517 goto do_ftoi;
5518 case VT_INT | VT_UNSIGNED:
5519 switch(sbt) {
5520 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5521 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5522 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5524 break;
5525 default:
5526 /* int case */
5527 switch(sbt) {
5528 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5529 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5530 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5532 break;
5534 } else {
5535 do_ftoi:
5536 gen_cvt_ftoi1(dbt);
5538 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5539 /* additional cast for char/short/bool... */
5540 vtop->type.t = dbt;
5541 gen_cast(type);
5543 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5544 if ((sbt & VT_BTYPE) != VT_LLONG) {
5545 /* scalar to long long */
5546 if (c) {
5547 if (sbt == (VT_INT | VT_UNSIGNED))
5548 vtop->c.ll = vtop->c.ui;
5549 else
5550 vtop->c.ll = vtop->c.i;
5551 } else {
5552 /* machine independent conversion */
5553 gv(RC_INT);
5554 /* generate high word */
5555 if (sbt == (VT_INT | VT_UNSIGNED)) {
5556 vpushi(0);
5557 gv(RC_INT);
5558 } else {
5559 gv_dup();
5560 vpushi(31);
5561 gen_op(TOK_SAR);
5563 /* patch second register */
5564 vtop[-1].r2 = vtop->r;
5565 vpop();
5568 } else if (dbt == VT_BOOL) {
5569 /* scalar to bool */
5570 vpushi(0);
5571 gen_op(TOK_NE);
5572 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5573 (dbt & VT_BTYPE) == VT_SHORT) {
5574 force_charshort_cast(dbt);
5575 } else if ((dbt & VT_BTYPE) == VT_INT) {
5576 /* scalar to int */
5577 if (sbt == VT_LLONG) {
5578 /* from long long: just take low order word */
5579 lexpand();
5580 vpop();
5582 /* if lvalue and single word type, nothing to do because
5583 the lvalue already contains the real type size (see
5584 VT_LVAL_xxx constants) */
5587 vtop->type = *type;
5590 /* return type size. Put alignment at 'a' */
5591 static int type_size(CType *type, int *a)
5593 Sym *s;
5594 int bt;
5596 bt = type->t & VT_BTYPE;
5597 if (bt == VT_STRUCT) {
5598 /* struct/union */
5599 s = type->ref;
5600 *a = s->r;
5601 return s->c;
5602 } else if (bt == VT_PTR) {
5603 if (type->t & VT_ARRAY) {
5604 s = type->ref;
5605 return type_size(&s->type, a) * s->c;
5606 } else {
5607 *a = PTR_SIZE;
5608 return PTR_SIZE;
5610 } else if (bt == VT_LDOUBLE) {
5611 *a = LDOUBLE_ALIGN;
5612 return LDOUBLE_SIZE;
5613 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5614 *a = 4; /* XXX: i386 specific */
5615 return 8;
5616 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5617 *a = 4;
5618 return 4;
5619 } else if (bt == VT_SHORT) {
5620 *a = 2;
5621 return 2;
5622 } else {
5623 /* char, void, function, _Bool */
5624 *a = 1;
5625 return 1;
5629 /* return the pointed type of t */
5630 static inline CType *pointed_type(CType *type)
5632 return &type->ref->type;
5635 /* modify type so that its it is a pointer to type. */
5636 static void mk_pointer(CType *type)
5638 Sym *s;
5639 s = sym_push(SYM_FIELD, type, 0, -1);
5640 type->t = VT_PTR | (type->t & ~VT_TYPE);
5641 type->ref = s;
5644 /* compare function types. OLD functions match any new functions */
5645 static int is_compatible_func(CType *type1, CType *type2)
5647 Sym *s1, *s2;
5649 s1 = type1->ref;
5650 s2 = type2->ref;
5651 if (!is_compatible_types(&s1->type, &s2->type))
5652 return 0;
5653 /* XXX: not complete */
5654 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5655 return 1;
5656 if (s1->c != s2->c)
5657 return 0;
5658 while (s1 != NULL) {
5659 if (s2 == NULL)
5660 return 0;
5661 if (!is_compatible_types(&s1->type, &s2->type))
5662 return 0;
5663 s1 = s1->next;
5664 s2 = s2->next;
5666 if (s2)
5667 return 0;
5668 return 1;
5671 /* return true if type1 and type2 are exactly the same (including
5672 qualifiers).
5674 - enums are not checked as gcc __builtin_types_compatible_p ()
5676 static int is_compatible_types(CType *type1, CType *type2)
5678 int bt1, t1, t2;
5680 t1 = type1->t & VT_TYPE;
5681 t2 = type2->t & VT_TYPE;
5682 /* XXX: bitfields ? */
5683 if (t1 != t2)
5684 return 0;
5685 /* test more complicated cases */
5686 bt1 = t1 & VT_BTYPE;
5687 if (bt1 == VT_PTR) {
5688 type1 = pointed_type(type1);
5689 type2 = pointed_type(type2);
5690 return is_compatible_types(type1, type2);
5691 } else if (bt1 == VT_STRUCT) {
5692 return (type1->ref == type2->ref);
5693 } else if (bt1 == VT_FUNC) {
5694 return is_compatible_func(type1, type2);
5695 } else {
5696 return 1;
5700 /* print a type. If 'varstr' is not NULL, then the variable is also
5701 printed in the type */
5702 /* XXX: union */
5703 /* XXX: add array and function pointers */
5704 void type_to_str(char *buf, int buf_size,
5705 CType *type, const char *varstr)
5707 int bt, v, t;
5708 Sym *s, *sa;
5709 char buf1[256];
5710 const char *tstr;
5712 t = type->t & VT_TYPE;
5713 bt = t & VT_BTYPE;
5714 buf[0] = '\0';
5715 if (t & VT_CONSTANT)
5716 pstrcat(buf, buf_size, "const ");
5717 if (t & VT_VOLATILE)
5718 pstrcat(buf, buf_size, "volatile ");
5719 if (t & VT_UNSIGNED)
5720 pstrcat(buf, buf_size, "unsigned ");
5721 switch(bt) {
5722 case VT_VOID:
5723 tstr = "void";
5724 goto add_tstr;
5725 case VT_BOOL:
5726 tstr = "_Bool";
5727 goto add_tstr;
5728 case VT_BYTE:
5729 tstr = "char";
5730 goto add_tstr;
5731 case VT_SHORT:
5732 tstr = "short";
5733 goto add_tstr;
5734 case VT_INT:
5735 tstr = "int";
5736 goto add_tstr;
5737 case VT_LONG:
5738 tstr = "long";
5739 goto add_tstr;
5740 case VT_LLONG:
5741 tstr = "long long";
5742 goto add_tstr;
5743 case VT_FLOAT:
5744 tstr = "float";
5745 goto add_tstr;
5746 case VT_DOUBLE:
5747 tstr = "double";
5748 goto add_tstr;
5749 case VT_LDOUBLE:
5750 tstr = "long double";
5751 add_tstr:
5752 pstrcat(buf, buf_size, tstr);
5753 break;
5754 case VT_ENUM:
5755 case VT_STRUCT:
5756 if (bt == VT_STRUCT)
5757 tstr = "struct ";
5758 else
5759 tstr = "enum ";
5760 pstrcat(buf, buf_size, tstr);
5761 v = type->ref->v & ~SYM_STRUCT;
5762 if (v >= SYM_FIRST_ANOM)
5763 pstrcat(buf, buf_size, "<anonymous>");
5764 else
5765 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5766 break;
5767 case VT_FUNC:
5768 s = type->ref;
5769 type_to_str(buf, buf_size, &s->type, varstr);
5770 pstrcat(buf, buf_size, "(");
5771 sa = s->next;
5772 while (sa != NULL) {
5773 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5774 pstrcat(buf, buf_size, buf1);
5775 sa = sa->next;
5776 if (sa)
5777 pstrcat(buf, buf_size, ", ");
5779 pstrcat(buf, buf_size, ")");
5780 goto no_var;
5781 case VT_PTR:
5782 s = type->ref;
5783 pstrcpy(buf1, sizeof(buf1), "*");
5784 if (varstr)
5785 pstrcat(buf1, sizeof(buf1), varstr);
5786 type_to_str(buf, buf_size, &s->type, buf1);
5787 goto no_var;
5789 if (varstr) {
5790 pstrcat(buf, buf_size, " ");
5791 pstrcat(buf, buf_size, varstr);
5793 no_var: ;
5796 /* verify type compatibility to store vtop in 'dt' type, and generate
5797 casts if needed. */
5798 static void gen_assign_cast(CType *dt)
5800 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5801 char buf1[256], buf2[256];
5802 int dbt, sbt;
5804 st = &vtop->type; /* source type */
5805 dbt = dt->t & VT_BTYPE;
5806 sbt = st->t & VT_BTYPE;
5807 if (dt->t & VT_CONSTANT)
5808 warning("assignment of read-only location");
5809 switch(dbt) {
5810 case VT_PTR:
5811 /* special cases for pointers */
5812 /* '0' can also be a pointer */
5813 if (is_null_pointer(vtop))
5814 goto type_ok;
5815 /* accept implicit pointer to integer cast with warning */
5816 if (is_integer_btype(sbt)) {
5817 warning("assignment makes pointer from integer without a cast");
5818 goto type_ok;
5820 type1 = pointed_type(dt);
5821 /* a function is implicitely a function pointer */
5822 if (sbt == VT_FUNC) {
5823 if ((type1->t & VT_BTYPE) != VT_VOID &&
5824 !is_compatible_types(pointed_type(dt), st))
5825 goto error;
5826 else
5827 goto type_ok;
5829 if (sbt != VT_PTR)
5830 goto error;
5831 type2 = pointed_type(st);
5832 if ((type1->t & VT_BTYPE) == VT_VOID ||
5833 (type2->t & VT_BTYPE) == VT_VOID) {
5834 /* void * can match anything */
5835 } else {
5836 /* exact type match, except for unsigned */
5837 tmp_type1 = *type1;
5838 tmp_type2 = *type2;
5839 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5840 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5841 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5842 goto error;
5844 /* check const and volatile */
5845 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5846 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5847 warning("assignment discards qualifiers from pointer target type");
5848 break;
5849 case VT_BYTE:
5850 case VT_SHORT:
5851 case VT_INT:
5852 case VT_LLONG:
5853 if (sbt == VT_PTR || sbt == VT_FUNC) {
5854 warning("assignment makes integer from pointer without a cast");
5856 /* XXX: more tests */
5857 break;
5858 case VT_STRUCT:
5859 tmp_type1 = *dt;
5860 tmp_type2 = *st;
5861 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
5862 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
5863 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5864 error:
5865 type_to_str(buf1, sizeof(buf1), st, NULL);
5866 type_to_str(buf2, sizeof(buf2), dt, NULL);
5867 error("cannot cast '%s' to '%s'", buf1, buf2);
5869 break;
5871 type_ok:
5872 gen_cast(dt);
5875 /* store vtop in lvalue pushed on stack */
5876 void vstore(void)
5878 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5880 ft = vtop[-1].type.t;
5881 sbt = vtop->type.t & VT_BTYPE;
5882 dbt = ft & VT_BTYPE;
5883 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5884 (sbt == VT_INT && dbt == VT_SHORT)) {
5885 /* optimize char/short casts */
5886 delayed_cast = VT_MUSTCAST;
5887 vtop->type.t = ft & VT_TYPE;
5888 /* XXX: factorize */
5889 if (ft & VT_CONSTANT)
5890 warning("assignment of read-only location");
5891 } else {
5892 delayed_cast = 0;
5893 gen_assign_cast(&vtop[-1].type);
5896 if (sbt == VT_STRUCT) {
5897 /* if structure, only generate pointer */
5898 /* structure assignment : generate memcpy */
5899 /* XXX: optimize if small size */
5900 if (!nocode_wanted) {
5901 size = type_size(&vtop->type, &align);
5903 vpush_global_sym(&func_old_type, TOK_memcpy);
5905 /* destination */
5906 vpushv(vtop - 2);
5907 vtop->type.t = VT_INT;
5908 gaddrof();
5909 /* source */
5910 vpushv(vtop - 2);
5911 vtop->type.t = VT_INT;
5912 gaddrof();
5913 /* type size */
5914 vpushi(size);
5915 gfunc_call(3);
5917 vswap();
5918 vpop();
5919 } else {
5920 vswap();
5921 vpop();
5923 /* leave source on stack */
5924 } else if (ft & VT_BITFIELD) {
5925 /* bitfield store handling */
5926 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5927 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5928 /* remove bit field info to avoid loops */
5929 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5931 /* duplicate destination */
5932 vdup();
5933 vtop[-1] = vtop[-2];
5935 /* mask and shift source */
5936 vpushi((1 << bit_size) - 1);
5937 gen_op('&');
5938 vpushi(bit_pos);
5939 gen_op(TOK_SHL);
5940 /* load destination, mask and or with source */
5941 vswap();
5942 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5943 gen_op('&');
5944 gen_op('|');
5945 /* store result */
5946 vstore();
5947 } else {
5948 #ifdef CONFIG_TCC_BCHECK
5949 /* bound check case */
5950 if (vtop[-1].r & VT_MUSTBOUND) {
5951 vswap();
5952 gbound();
5953 vswap();
5955 #endif
5956 if (!nocode_wanted) {
5957 rc = RC_INT;
5958 if (is_float(ft))
5959 rc = RC_FLOAT;
5960 r = gv(rc); /* generate value */
5961 /* if lvalue was saved on stack, must read it */
5962 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5963 SValue sv;
5964 t = get_reg(RC_INT);
5965 sv.type.t = VT_INT;
5966 sv.r = VT_LOCAL | VT_LVAL;
5967 sv.c.ul = vtop[-1].c.ul;
5968 load(t, &sv);
5969 vtop[-1].r = t | VT_LVAL;
5971 store(r, vtop - 1);
5972 /* two word case handling : store second register at word + 4 */
5973 if ((ft & VT_BTYPE) == VT_LLONG) {
5974 vswap();
5975 /* convert to int to increment easily */
5976 vtop->type.t = VT_INT;
5977 gaddrof();
5978 vpushi(4);
5979 gen_op('+');
5980 vtop->r |= VT_LVAL;
5981 vswap();
5982 /* XXX: it works because r2 is spilled last ! */
5983 store(vtop->r2, vtop - 1);
5986 vswap();
5987 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5988 vtop->r |= delayed_cast;
5992 /* post defines POST/PRE add. c is the token ++ or -- */
5993 void inc(int post, int c)
5995 test_lvalue();
5996 vdup(); /* save lvalue */
5997 if (post) {
5998 gv_dup(); /* duplicate value */
5999 vrotb(3);
6000 vrotb(3);
6002 /* add constant */
6003 vpushi(c - TOK_MID);
6004 gen_op('+');
6005 vstore(); /* store value */
6006 if (post)
6007 vpop(); /* if post op, return saved value */
6010 /* Parse GNUC __attribute__ extension. Currently, the following
6011 extensions are recognized:
6012 - aligned(n) : set data/function alignment.
6013 - section(x) : generate data/code in this section.
6014 - unused : currently ignored, but may be used someday.
6016 static void parse_attribute(AttributeDef *ad)
6018 int t, n;
6020 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6021 next();
6022 skip('(');
6023 skip('(');
6024 while (tok != ')') {
6025 if (tok < TOK_IDENT)
6026 expect("attribute name");
6027 t = tok;
6028 next();
6029 switch(t) {
6030 case TOK_SECTION1:
6031 case TOK_SECTION2:
6032 skip('(');
6033 if (tok != TOK_STR)
6034 expect("section name");
6035 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6036 next();
6037 skip(')');
6038 break;
6039 case TOK_ALIGNED1:
6040 case TOK_ALIGNED2:
6041 if (tok == '(') {
6042 next();
6043 n = expr_const();
6044 if (n <= 0 || (n & (n - 1)) != 0)
6045 error("alignment must be a positive power of two");
6046 skip(')');
6047 } else {
6048 n = MAX_ALIGN;
6050 ad->aligned = n;
6051 break;
6052 case TOK_UNUSED1:
6053 case TOK_UNUSED2:
6054 /* currently, no need to handle it because tcc does not
6055 track unused objects */
6056 break;
6057 case TOK_NORETURN1:
6058 case TOK_NORETURN2:
6059 /* currently, no need to handle it because tcc does not
6060 track unused objects */
6061 break;
6062 case TOK_CDECL1:
6063 case TOK_CDECL2:
6064 case TOK_CDECL3:
6065 ad->func_call = FUNC_CDECL;
6066 break;
6067 case TOK_STDCALL1:
6068 case TOK_STDCALL2:
6069 case TOK_STDCALL3:
6070 ad->func_call = FUNC_STDCALL;
6071 break;
6072 default:
6073 if (tcc_state->warn_unsupported)
6074 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6075 /* skip parameters */
6076 /* XXX: skip parenthesis too */
6077 if (tok == '(') {
6078 next();
6079 while (tok != ')' && tok != -1)
6080 next();
6081 next();
6083 break;
6085 if (tok != ',')
6086 break;
6087 next();
6089 skip(')');
6090 skip(')');
6094 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6095 static void struct_decl(CType *type, int u)
6097 int a, v, size, align, maxalign, c, offset;
6098 int bit_size, bit_pos, bsize, bt, lbit_pos;
6099 Sym *s, *ss, **ps;
6100 AttributeDef ad;
6101 CType type1, btype;
6103 a = tok; /* save decl type */
6104 next();
6105 if (tok != '{') {
6106 v = tok;
6107 next();
6108 /* struct already defined ? return it */
6109 if (v < TOK_IDENT)
6110 expect("struct/union/enum name");
6111 s = struct_find(v);
6112 if (s) {
6113 if (s->type.t != a)
6114 error("invalid type");
6115 goto do_decl;
6117 } else {
6118 v = anon_sym++;
6120 type1.t = a;
6121 /* we put an undefined size for struct/union */
6122 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6123 s->r = 0; /* default alignment is zero as gcc */
6124 /* put struct/union/enum name in type */
6125 do_decl:
6126 type->t = u;
6127 type->ref = s;
6129 if (tok == '{') {
6130 next();
6131 if (s->c != -1)
6132 error("struct/union/enum already defined");
6133 /* cannot be empty */
6134 c = 0;
6135 /* non empty enums are not allowed */
6136 if (a == TOK_ENUM) {
6137 for(;;) {
6138 v = tok;
6139 if (v < TOK_UIDENT)
6140 expect("identifier");
6141 next();
6142 if (tok == '=') {
6143 next();
6144 c = expr_const();
6146 /* enum symbols have static storage */
6147 ss = sym_push(v, &int_type, VT_CONST, c);
6148 ss->type.t |= VT_STATIC;
6149 if (tok != ',')
6150 break;
6151 next();
6152 c++;
6153 /* NOTE: we accept a trailing comma */
6154 if (tok == '}')
6155 break;
6157 skip('}');
6158 } else {
6159 maxalign = 1;
6160 ps = &s->next;
6161 bit_pos = 0;
6162 offset = 0;
6163 while (tok != '}') {
6164 parse_btype(&btype, &ad);
6165 while (1) {
6166 bit_size = -1;
6167 v = 0;
6168 type1 = btype;
6169 if (tok != ':') {
6170 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6171 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6172 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6173 error("invalid type for '%s'",
6174 get_tok_str(v, NULL));
6176 if (tok == ':') {
6177 next();
6178 bit_size = expr_const();
6179 /* XXX: handle v = 0 case for messages */
6180 if (bit_size < 0)
6181 error("negative width in bit-field '%s'",
6182 get_tok_str(v, NULL));
6183 if (v && bit_size == 0)
6184 error("zero width for bit-field '%s'",
6185 get_tok_str(v, NULL));
6187 size = type_size(&type1, &align);
6188 lbit_pos = 0;
6189 if (bit_size >= 0) {
6190 bt = type1.t & VT_BTYPE;
6191 if (bt != VT_INT &&
6192 bt != VT_BYTE &&
6193 bt != VT_SHORT &&
6194 bt != VT_ENUM)
6195 error("bitfields must have scalar type");
6196 bsize = size * 8;
6197 if (bit_size > bsize) {
6198 error("width of '%s' exceeds its type",
6199 get_tok_str(v, NULL));
6200 } else if (bit_size == bsize) {
6201 /* no need for bit fields */
6202 bit_pos = 0;
6203 } else if (bit_size == 0) {
6204 /* XXX: what to do if only padding in a
6205 structure ? */
6206 /* zero size: means to pad */
6207 if (bit_pos > 0)
6208 bit_pos = bsize;
6209 } else {
6210 /* we do not have enough room ? */
6211 if ((bit_pos + bit_size) > bsize)
6212 bit_pos = 0;
6213 lbit_pos = bit_pos;
6214 /* XXX: handle LSB first */
6215 type1.t |= VT_BITFIELD |
6216 (bit_pos << VT_STRUCT_SHIFT) |
6217 (bit_size << (VT_STRUCT_SHIFT + 6));
6218 bit_pos += bit_size;
6220 } else {
6221 bit_pos = 0;
6223 if (v) {
6224 /* add new memory data only if starting
6225 bit field */
6226 if (lbit_pos == 0) {
6227 if (a == TOK_STRUCT) {
6228 c = (c + align - 1) & -align;
6229 offset = c;
6230 c += size;
6231 } else {
6232 offset = 0;
6233 if (size > c)
6234 c = size;
6236 if (align > maxalign)
6237 maxalign = align;
6239 #if 0
6240 printf("add field %s offset=%d",
6241 get_tok_str(v, NULL), offset);
6242 if (type1.t & VT_BITFIELD) {
6243 printf(" pos=%d size=%d",
6244 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6245 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6247 printf("\n");
6248 #endif
6249 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6250 *ps = ss;
6251 ps = &ss->next;
6253 if (tok == ';' || tok == TOK_EOF)
6254 break;
6255 skip(',');
6257 skip(';');
6259 skip('}');
6260 /* store size and alignment */
6261 s->c = (c + maxalign - 1) & -maxalign;
6262 s->r = maxalign;
6267 /* return 0 if no type declaration. otherwise, return the basic type
6268 and skip it.
6270 static int parse_btype(CType *type, AttributeDef *ad)
6272 int t, u, type_found, typespec_found;
6273 Sym *s;
6274 CType type1;
6276 memset(ad, 0, sizeof(AttributeDef));
6277 type_found = 0;
6278 typespec_found = 0;
6279 t = 0;
6280 while(1) {
6281 switch(tok) {
6282 case TOK_EXTENSION:
6283 /* currently, we really ignore extension */
6284 next();
6285 continue;
6287 /* basic types */
6288 case TOK_CHAR:
6289 u = VT_BYTE;
6290 basic_type:
6291 next();
6292 basic_type1:
6293 if ((t & VT_BTYPE) != 0)
6294 error("too many basic types");
6295 t |= u;
6296 typespec_found = 1;
6297 break;
6298 case TOK_VOID:
6299 u = VT_VOID;
6300 goto basic_type;
6301 case TOK_SHORT:
6302 u = VT_SHORT;
6303 goto basic_type;
6304 case TOK_INT:
6305 next();
6306 typespec_found = 1;
6307 break;
6308 case TOK_LONG:
6309 next();
6310 if ((t & VT_BTYPE) == VT_DOUBLE) {
6311 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6312 } else if ((t & VT_BTYPE) == VT_LONG) {
6313 t = (t & ~VT_BTYPE) | VT_LLONG;
6314 } else {
6315 u = VT_LONG;
6316 goto basic_type1;
6318 break;
6319 case TOK_BOOL:
6320 u = VT_BOOL;
6321 goto basic_type;
6322 case TOK_FLOAT:
6323 u = VT_FLOAT;
6324 goto basic_type;
6325 case TOK_DOUBLE:
6326 next();
6327 if ((t & VT_BTYPE) == VT_LONG) {
6328 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6329 } else {
6330 u = VT_DOUBLE;
6331 goto basic_type1;
6333 break;
6334 case TOK_ENUM:
6335 struct_decl(&type1, VT_ENUM);
6336 basic_type2:
6337 u = type1.t;
6338 type->ref = type1.ref;
6339 goto basic_type1;
6340 case TOK_STRUCT:
6341 case TOK_UNION:
6342 struct_decl(&type1, VT_STRUCT);
6343 goto basic_type2;
6345 /* type modifiers */
6346 case TOK_CONST1:
6347 case TOK_CONST2:
6348 case TOK_CONST3:
6349 t |= VT_CONSTANT;
6350 next();
6351 break;
6352 case TOK_VOLATILE1:
6353 case TOK_VOLATILE2:
6354 case TOK_VOLATILE3:
6355 t |= VT_VOLATILE;
6356 next();
6357 break;
6358 case TOK_SIGNED1:
6359 case TOK_SIGNED2:
6360 case TOK_SIGNED3:
6361 typespec_found = 1;
6362 t |= VT_SIGNED;
6363 next();
6364 break;
6365 case TOK_REGISTER:
6366 case TOK_AUTO:
6367 case TOK_RESTRICT1:
6368 case TOK_RESTRICT2:
6369 case TOK_RESTRICT3:
6370 next();
6371 break;
6372 case TOK_UNSIGNED:
6373 t |= VT_UNSIGNED;
6374 next();
6375 typespec_found = 1;
6376 break;
6378 /* storage */
6379 case TOK_EXTERN:
6380 t |= VT_EXTERN;
6381 next();
6382 break;
6383 case TOK_STATIC:
6384 t |= VT_STATIC;
6385 next();
6386 break;
6387 case TOK_TYPEDEF:
6388 t |= VT_TYPEDEF;
6389 next();
6390 break;
6391 case TOK_INLINE1:
6392 case TOK_INLINE2:
6393 case TOK_INLINE3:
6394 t |= VT_INLINE;
6395 next();
6396 break;
6398 /* GNUC attribute */
6399 case TOK_ATTRIBUTE1:
6400 case TOK_ATTRIBUTE2:
6401 parse_attribute(ad);
6402 break;
6403 /* GNUC typeof */
6404 case TOK_TYPEOF1:
6405 case TOK_TYPEOF2:
6406 case TOK_TYPEOF3:
6407 next();
6408 parse_expr_type(&type1);
6409 goto basic_type2;
6410 default:
6411 if (typespec_found)
6412 goto the_end;
6413 s = sym_find(tok);
6414 if (!s || !(s->type.t & VT_TYPEDEF))
6415 goto the_end;
6416 t |= (s->type.t & ~VT_TYPEDEF);
6417 type->ref = s->type.ref;
6418 next();
6419 break;
6421 type_found = 1;
6423 the_end:
6424 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6425 error("signed and unsigned modifier");
6426 if (tcc_state->char_is_unsigned) {
6427 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6428 t |= VT_UNSIGNED;
6430 t &= ~VT_SIGNED;
6432 /* long is never used as type */
6433 if ((t & VT_BTYPE) == VT_LONG)
6434 t = (t & ~VT_BTYPE) | VT_INT;
6435 type->t = t;
6436 return type_found;
6439 /* convert a function parameter type (array to pointer and function to
6440 function pointer) */
6441 static inline void convert_parameter_type(CType *pt)
6443 /* array must be transformed to pointer according to ANSI C */
6444 pt->t &= ~VT_ARRAY;
6445 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6446 mk_pointer(pt);
6450 static void post_type(CType *type, AttributeDef *ad)
6452 int n, l, t1;
6453 Sym **plast, *s, *first;
6454 AttributeDef ad1;
6455 CType pt;
6457 if (tok == '(') {
6458 /* function declaration */
6459 next();
6460 l = 0;
6461 first = NULL;
6462 plast = &first;
6463 while (tok != ')') {
6464 /* read param name and compute offset */
6465 if (l != FUNC_OLD) {
6466 if (!parse_btype(&pt, &ad1)) {
6467 if (l) {
6468 error("invalid type");
6469 } else {
6470 l = FUNC_OLD;
6471 goto old_proto;
6474 l = FUNC_NEW;
6475 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6476 break;
6477 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6478 if ((pt.t & VT_BTYPE) == VT_VOID)
6479 error("parameter declared as void");
6480 } else {
6481 old_proto:
6482 n = tok;
6483 pt.t = VT_INT;
6484 next();
6486 convert_parameter_type(&pt);
6487 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6488 *plast = s;
6489 plast = &s->next;
6490 if (tok == ',') {
6491 next();
6492 if (l == FUNC_NEW && tok == TOK_DOTS) {
6493 l = FUNC_ELLIPSIS;
6494 next();
6495 break;
6499 /* if no parameters, then old type prototype */
6500 if (l == 0)
6501 l = FUNC_OLD;
6502 skip(')');
6503 t1 = type->t & VT_STORAGE;
6504 /* NOTE: const is ignored in returned type as it has a special
6505 meaning in gcc / C++ */
6506 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6507 post_type(type, ad);
6508 /* we push a anonymous symbol which will contain the function prototype */
6509 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6510 s->next = first;
6511 type->t = t1 | VT_FUNC;
6512 type->ref = s;
6513 } else if (tok == '[') {
6514 /* array definition */
6515 next();
6516 n = -1;
6517 if (tok != ']') {
6518 n = expr_const();
6519 if (n < 0)
6520 error("invalid array size");
6522 skip(']');
6523 /* parse next post type */
6524 t1 = type->t & VT_STORAGE;
6525 type->t &= ~VT_STORAGE;
6526 post_type(type, ad);
6528 /* we push a anonymous symbol which will contain the array
6529 element type */
6530 s = sym_push(SYM_FIELD, type, 0, n);
6531 type->t = t1 | VT_ARRAY | VT_PTR;
6532 type->ref = s;
6536 /* Parse a type declaration (except basic type), and return the type
6537 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6538 expected. 'type' should contain the basic type. 'ad' is the
6539 attribute definition of the basic type. It can be modified by
6540 type_decl().
6542 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6544 Sym *s;
6545 CType type1, *type2;
6546 int qualifiers;
6548 while (tok == '*') {
6549 qualifiers = 0;
6550 redo:
6551 next();
6552 switch(tok) {
6553 case TOK_CONST1:
6554 case TOK_CONST2:
6555 case TOK_CONST3:
6556 qualifiers |= VT_CONSTANT;
6557 goto redo;
6558 case TOK_VOLATILE1:
6559 case TOK_VOLATILE2:
6560 case TOK_VOLATILE3:
6561 qualifiers |= VT_VOLATILE;
6562 goto redo;
6563 case TOK_RESTRICT1:
6564 case TOK_RESTRICT2:
6565 case TOK_RESTRICT3:
6566 goto redo;
6568 mk_pointer(type);
6569 type->t |= qualifiers;
6572 /* XXX: clarify attribute handling */
6573 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6574 parse_attribute(ad);
6576 /* recursive type */
6577 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6578 type1.t = 0; /* XXX: same as int */
6579 if (tok == '(') {
6580 next();
6581 /* XXX: this is not correct to modify 'ad' at this point, but
6582 the syntax is not clear */
6583 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6584 parse_attribute(ad);
6585 type_decl(&type1, ad, v, td);
6586 skip(')');
6587 } else {
6588 /* type identifier */
6589 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6590 *v = tok;
6591 next();
6592 } else {
6593 if (!(td & TYPE_ABSTRACT))
6594 expect("identifier");
6595 *v = 0;
6598 post_type(type, ad);
6599 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6600 parse_attribute(ad);
6601 if (!type1.t)
6602 return;
6603 /* append type at the end of type1 */
6604 type2 = &type1;
6605 for(;;) {
6606 s = type2->ref;
6607 type2 = &s->type;
6608 if (!type2->t) {
6609 *type2 = *type;
6610 break;
6613 *type = type1;
6616 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6617 static int lvalue_type(int t)
6619 int bt, r;
6620 r = VT_LVAL;
6621 bt = t & VT_BTYPE;
6622 if (bt == VT_BYTE || bt == VT_BOOL)
6623 r |= VT_LVAL_BYTE;
6624 else if (bt == VT_SHORT)
6625 r |= VT_LVAL_SHORT;
6626 else
6627 return r;
6628 if (t & VT_UNSIGNED)
6629 r |= VT_LVAL_UNSIGNED;
6630 return r;
6633 /* indirection with full error checking and bound check */
6634 static void indir(void)
6636 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6637 expect("pointer");
6638 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6639 gv(RC_INT);
6640 vtop->type = *pointed_type(&vtop->type);
6641 /* an array is never an lvalue */
6642 if (!(vtop->type.t & VT_ARRAY)) {
6643 vtop->r |= lvalue_type(vtop->type.t);
6644 /* if bound checking, the referenced pointer must be checked */
6645 if (do_bounds_check)
6646 vtop->r |= VT_MUSTBOUND;
6650 /* pass a parameter to a function and do type checking and casting */
6651 static void gfunc_param_typed(Sym *func, Sym *arg)
6653 int func_type;
6654 CType type;
6656 func_type = func->c;
6657 if (func_type == FUNC_OLD ||
6658 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6659 /* default casting : only need to convert float to double */
6660 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6661 type.t = VT_DOUBLE;
6662 gen_cast(&type);
6664 } else if (arg == NULL) {
6665 error("too many arguments to function");
6666 } else {
6667 type = arg->type;
6668 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6669 gen_assign_cast(&type);
6673 /* parse an expression of the form '(type)' or '(expr)' and return its
6674 type */
6675 static void parse_expr_type(CType *type)
6677 int n;
6678 AttributeDef ad;
6680 skip('(');
6681 if (parse_btype(type, &ad)) {
6682 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6683 } else {
6684 expr_type(type);
6686 skip(')');
6689 static void parse_type(CType *type)
6691 AttributeDef ad;
6692 int n;
6694 if (!parse_btype(type, &ad)) {
6695 expect("type");
6697 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6700 static void vpush_tokc(int t)
6702 CType type;
6703 type.t = t;
6704 vsetc(&type, VT_CONST, &tokc);
6707 static void unary(void)
6709 int n, t, align, size, r;
6710 CType type;
6711 Sym *s;
6712 AttributeDef ad;
6714 /* XXX: GCC 2.95.3 does not generate a table although it should be
6715 better here */
6716 tok_next:
6717 switch(tok) {
6718 case TOK_EXTENSION:
6719 next();
6720 goto tok_next;
6721 case TOK_CINT:
6722 case TOK_CCHAR:
6723 case TOK_LCHAR:
6724 vpushi(tokc.i);
6725 next();
6726 break;
6727 case TOK_CUINT:
6728 vpush_tokc(VT_INT | VT_UNSIGNED);
6729 next();
6730 break;
6731 case TOK_CLLONG:
6732 vpush_tokc(VT_LLONG);
6733 next();
6734 break;
6735 case TOK_CULLONG:
6736 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6737 next();
6738 break;
6739 case TOK_CFLOAT:
6740 vpush_tokc(VT_FLOAT);
6741 next();
6742 break;
6743 case TOK_CDOUBLE:
6744 vpush_tokc(VT_DOUBLE);
6745 next();
6746 break;
6747 case TOK_CLDOUBLE:
6748 vpush_tokc(VT_LDOUBLE);
6749 next();
6750 break;
6751 case TOK___FUNCTION__:
6752 if (!gnu_ext)
6753 goto tok_identifier;
6754 /* fall thru */
6755 case TOK___FUNC__:
6757 void *ptr;
6758 int len;
6759 /* special function name identifier */
6760 len = strlen(funcname) + 1;
6761 /* generate char[len] type */
6762 type.t = VT_BYTE;
6763 mk_pointer(&type);
6764 type.t |= VT_ARRAY;
6765 type.ref->c = len;
6766 vpush_ref(&type, data_section, data_section->data_offset, len);
6767 ptr = section_ptr_add(data_section, len);
6768 memcpy(ptr, funcname, len);
6769 next();
6771 break;
6772 case TOK_LSTR:
6773 t = VT_INT;
6774 goto str_init;
6775 case TOK_STR:
6776 /* string parsing */
6777 t = VT_BYTE;
6778 str_init:
6779 if (tcc_state->warn_write_strings)
6780 t |= VT_CONSTANT;
6781 type.t = t;
6782 mk_pointer(&type);
6783 type.t |= VT_ARRAY;
6784 memset(&ad, 0, sizeof(AttributeDef));
6785 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6786 break;
6787 case '(':
6788 next();
6789 /* cast ? */
6790 if (parse_btype(&type, &ad)) {
6791 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6792 skip(')');
6793 /* check ISOC99 compound literal */
6794 if (tok == '{') {
6795 /* data is allocated locally by default */
6796 if (global_expr)
6797 r = VT_CONST;
6798 else
6799 r = VT_LOCAL;
6800 /* all except arrays are lvalues */
6801 if (!(type.t & VT_ARRAY))
6802 r |= lvalue_type(type.t);
6803 memset(&ad, 0, sizeof(AttributeDef));
6804 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6805 } else {
6806 unary();
6807 gen_cast(&type);
6809 } else if (tok == '{') {
6810 /* save all registers */
6811 save_regs(0);
6812 /* statement expression : we do not accept break/continue
6813 inside as GCC does */
6814 block(NULL, NULL, NULL, NULL, 0, 1);
6815 skip(')');
6816 } else {
6817 gexpr();
6818 skip(')');
6820 break;
6821 case '*':
6822 next();
6823 unary();
6824 indir();
6825 break;
6826 case '&':
6827 next();
6828 unary();
6829 /* functions names must be treated as function pointers,
6830 except for unary '&' and sizeof. Since we consider that
6831 functions are not lvalues, we only have to handle it
6832 there and in function calls. */
6833 /* arrays can also be used although they are not lvalues */
6834 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6835 !(vtop->type.t & VT_ARRAY))
6836 test_lvalue();
6837 mk_pointer(&vtop->type);
6838 gaddrof();
6839 break;
6840 case '!':
6841 next();
6842 unary();
6843 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6844 vtop->c.i = !vtop->c.i;
6845 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6846 vtop->c.i = vtop->c.i ^ 1;
6847 else
6848 vseti(VT_JMP, gtst(1, 0));
6849 break;
6850 case '~':
6851 next();
6852 unary();
6853 vpushi(-1);
6854 gen_op('^');
6855 break;
6856 case '+':
6857 next();
6858 /* in order to force cast, we add zero */
6859 unary();
6860 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6861 error("pointer not accepted for unary plus");
6862 vpushi(0);
6863 gen_op('+');
6864 break;
6865 case TOK_SIZEOF:
6866 case TOK_ALIGNOF1:
6867 case TOK_ALIGNOF2:
6868 t = tok;
6869 next();
6870 if (tok == '(') {
6871 parse_expr_type(&type);
6872 } else {
6873 unary_type(&type);
6875 size = type_size(&type, &align);
6876 if (t == TOK_SIZEOF) {
6877 if (size < 0)
6878 error("sizeof applied to an incomplete type");
6879 vpushi(size);
6880 } else {
6881 vpushi(align);
6883 break;
6885 case TOK_builtin_types_compatible_p:
6887 CType type1, type2;
6888 next();
6889 skip('(');
6890 parse_type(&type1);
6891 skip(',');
6892 parse_type(&type2);
6893 skip(')');
6894 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6895 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6896 vpushi(is_compatible_types(&type1, &type2));
6898 break;
6899 case TOK_builtin_constant_p:
6901 int saved_nocode_wanted, res;
6902 next();
6903 skip('(');
6904 saved_nocode_wanted = nocode_wanted;
6905 nocode_wanted = 1;
6906 gexpr();
6907 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6908 vpop();
6909 nocode_wanted = saved_nocode_wanted;
6910 skip(')');
6911 vpushi(res);
6913 break;
6914 case TOK_INC:
6915 case TOK_DEC:
6916 t = tok;
6917 next();
6918 unary();
6919 inc(0, t);
6920 break;
6921 case '-':
6922 next();
6923 vpushi(0);
6924 unary();
6925 gen_op('-');
6926 break;
6927 case TOK_LAND:
6928 if (!gnu_ext)
6929 goto tok_identifier;
6930 next();
6931 /* allow to take the address of a label */
6932 if (tok < TOK_UIDENT)
6933 expect("label identifier");
6934 s = label_find(tok);
6935 if (!s) {
6936 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6937 } else {
6938 if (s->r == LABEL_DECLARED)
6939 s->r = LABEL_FORWARD;
6941 if (!s->type.t) {
6942 s->type.t = VT_VOID;
6943 mk_pointer(&s->type);
6944 s->type.t |= VT_STATIC;
6946 vset(&s->type, VT_CONST | VT_SYM, 0);
6947 vtop->sym = s;
6948 next();
6949 break;
6950 default:
6951 tok_identifier:
6952 t = tok;
6953 next();
6954 if (t < TOK_UIDENT)
6955 expect("identifier");
6956 s = sym_find(t);
6957 if (!s) {
6958 if (tok != '(')
6959 error("'%s' undeclared", get_tok_str(t, NULL));
6960 /* for simple function calls, we tolerate undeclared
6961 external reference to int() function */
6962 if (tcc_state->warn_implicit_function_declaration)
6963 warning("implicit declaration of function '%s'",
6964 get_tok_str(t, NULL));
6965 s = external_global_sym(t, &func_old_type, 0);
6967 vset(&s->type, s->r, s->c);
6968 /* if forward reference, we must point to s */
6969 if (vtop->r & VT_SYM) {
6970 vtop->sym = s;
6971 vtop->c.ul = 0;
6973 break;
6976 /* post operations */
6977 while (1) {
6978 if (tok == TOK_INC || tok == TOK_DEC) {
6979 inc(1, tok);
6980 next();
6981 } else if (tok == '.' || tok == TOK_ARROW) {
6982 /* field */
6983 if (tok == TOK_ARROW)
6984 indir();
6985 test_lvalue();
6986 gaddrof();
6987 next();
6988 /* expect pointer on structure */
6989 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6990 expect("struct or union");
6991 s = vtop->type.ref;
6992 /* find field */
6993 tok |= SYM_FIELD;
6994 while ((s = s->next) != NULL) {
6995 if (s->v == tok)
6996 break;
6998 if (!s)
6999 error("field not found");
7000 /* add field offset to pointer */
7001 vtop->type = char_pointer_type; /* change type to 'char *' */
7002 vpushi(s->c);
7003 gen_op('+');
7004 /* change type to field type, and set to lvalue */
7005 vtop->type = s->type;
7006 /* an array is never an lvalue */
7007 if (!(vtop->type.t & VT_ARRAY)) {
7008 vtop->r |= lvalue_type(vtop->type.t);
7009 /* if bound checking, the referenced pointer must be checked */
7010 if (do_bounds_check)
7011 vtop->r |= VT_MUSTBOUND;
7013 next();
7014 } else if (tok == '[') {
7015 next();
7016 gexpr();
7017 gen_op('+');
7018 indir();
7019 skip(']');
7020 } else if (tok == '(') {
7021 SValue ret;
7022 Sym *sa;
7023 int nb_args;
7025 /* function call */
7026 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7027 /* pointer test (no array accepted) */
7028 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7029 vtop->type = *pointed_type(&vtop->type);
7030 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7031 goto error_func;
7032 } else {
7033 error_func:
7034 expect("function pointer");
7036 } else {
7037 vtop->r &= ~VT_LVAL; /* no lvalue */
7039 /* get return type */
7040 s = vtop->type.ref;
7041 next();
7042 sa = s->next; /* first parameter */
7043 nb_args = 0;
7044 /* compute first implicit argument if a structure is returned */
7045 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7046 /* get some space for the returned structure */
7047 size = type_size(&s->type, &align);
7048 loc = (loc - size) & -align;
7049 ret.type = s->type;
7050 ret.r = VT_LOCAL | VT_LVAL;
7051 /* pass it as 'int' to avoid structure arg passing
7052 problems */
7053 vseti(VT_LOCAL, loc);
7054 ret.c = vtop->c;
7055 nb_args++;
7056 } else {
7057 ret.type = s->type;
7058 ret.r2 = VT_CONST;
7059 /* return in register */
7060 if (is_float(ret.type.t)) {
7061 ret.r = REG_FRET;
7062 } else {
7063 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7064 ret.r2 = REG_LRET;
7065 ret.r = REG_IRET;
7067 ret.c.i = 0;
7069 if (tok != ')') {
7070 for(;;) {
7071 expr_eq();
7072 gfunc_param_typed(s, sa);
7073 nb_args++;
7074 if (sa)
7075 sa = sa->next;
7076 if (tok == ')')
7077 break;
7078 skip(',');
7081 if (sa)
7082 error("too few arguments to function");
7083 skip(')');
7084 if (!nocode_wanted) {
7085 gfunc_call(nb_args);
7086 } else {
7087 vtop -= (nb_args + 1);
7089 /* return value */
7090 vsetc(&ret.type, ret.r, &ret.c);
7091 vtop->r2 = ret.r2;
7092 } else {
7093 break;
7098 static void uneq(void)
7100 int t;
7102 unary();
7103 if (tok == '=' ||
7104 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7105 tok == TOK_A_XOR || tok == TOK_A_OR ||
7106 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7107 test_lvalue();
7108 t = tok;
7109 next();
7110 if (t == '=') {
7111 expr_eq();
7112 } else {
7113 vdup();
7114 expr_eq();
7115 gen_op(t & 0x7f);
7117 vstore();
7121 static void expr_prod(void)
7123 int t;
7125 uneq();
7126 while (tok == '*' || tok == '/' || tok == '%') {
7127 t = tok;
7128 next();
7129 uneq();
7130 gen_op(t);
7134 static void expr_sum(void)
7136 int t;
7138 expr_prod();
7139 while (tok == '+' || tok == '-') {
7140 t = tok;
7141 next();
7142 expr_prod();
7143 gen_op(t);
7147 static void expr_shift(void)
7149 int t;
7151 expr_sum();
7152 while (tok == TOK_SHL || tok == TOK_SAR) {
7153 t = tok;
7154 next();
7155 expr_sum();
7156 gen_op(t);
7160 static void expr_cmp(void)
7162 int t;
7164 expr_shift();
7165 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7166 tok == TOK_ULT || tok == TOK_UGE) {
7167 t = tok;
7168 next();
7169 expr_shift();
7170 gen_op(t);
7174 static void expr_cmpeq(void)
7176 int t;
7178 expr_cmp();
7179 while (tok == TOK_EQ || tok == TOK_NE) {
7180 t = tok;
7181 next();
7182 expr_cmp();
7183 gen_op(t);
7187 static void expr_and(void)
7189 expr_cmpeq();
7190 while (tok == '&') {
7191 next();
7192 expr_cmpeq();
7193 gen_op('&');
7197 static void expr_xor(void)
7199 expr_and();
7200 while (tok == '^') {
7201 next();
7202 expr_and();
7203 gen_op('^');
7207 static void expr_or(void)
7209 expr_xor();
7210 while (tok == '|') {
7211 next();
7212 expr_xor();
7213 gen_op('|');
7217 /* XXX: fix this mess */
7218 static void expr_land_const(void)
7220 expr_or();
7221 while (tok == TOK_LAND) {
7222 next();
7223 expr_or();
7224 gen_op(TOK_LAND);
7228 /* XXX: fix this mess */
7229 static void expr_lor_const(void)
7231 expr_land_const();
7232 while (tok == TOK_LOR) {
7233 next();
7234 expr_land_const();
7235 gen_op(TOK_LOR);
7239 /* only used if non constant */
7240 static void expr_land(void)
7242 int t;
7244 expr_or();
7245 if (tok == TOK_LAND) {
7246 t = 0;
7247 for(;;) {
7248 t = gtst(1, t);
7249 if (tok != TOK_LAND) {
7250 vseti(VT_JMPI, t);
7251 break;
7253 next();
7254 expr_or();
7259 static void expr_lor(void)
7261 int t;
7263 expr_land();
7264 if (tok == TOK_LOR) {
7265 t = 0;
7266 for(;;) {
7267 t = gtst(0, t);
7268 if (tok != TOK_LOR) {
7269 vseti(VT_JMP, t);
7270 break;
7272 next();
7273 expr_land();
7278 /* XXX: better constant handling */
7279 static void expr_eq(void)
7281 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7282 SValue sv;
7283 CType type, type1, type2;
7285 if (const_wanted) {
7286 int c1, c;
7287 expr_lor_const();
7288 if (tok == '?') {
7289 c = vtop->c.i;
7290 vpop();
7291 next();
7292 if (tok == ':' && gnu_ext) {
7293 c1 = c;
7294 } else {
7295 gexpr();
7296 c1 = vtop->c.i;
7297 vpop();
7299 skip(':');
7300 expr_eq();
7301 if (c)
7302 vtop->c.i = c1;
7304 } else {
7305 expr_lor();
7306 if (tok == '?') {
7307 next();
7308 if (vtop != vstack) {
7309 /* needed to avoid having different registers saved in
7310 each branch */
7311 if (is_float(vtop->type.t))
7312 rc = RC_FLOAT;
7313 else
7314 rc = RC_INT;
7315 gv(rc);
7316 save_regs(1);
7318 if (tok == ':' && gnu_ext) {
7319 gv_dup();
7320 tt = gtst(1, 0);
7321 } else {
7322 tt = gtst(1, 0);
7323 gexpr();
7325 type1 = vtop->type;
7326 sv = *vtop; /* save value to handle it later */
7327 vtop--; /* no vpop so that FP stack is not flushed */
7328 skip(':');
7329 u = gjmp(0);
7330 gsym(tt);
7331 expr_eq();
7332 type2 = vtop->type;
7334 t1 = type1.t;
7335 bt1 = t1 & VT_BTYPE;
7336 t2 = type2.t;
7337 bt2 = t2 & VT_BTYPE;
7338 /* cast operands to correct type according to ISOC rules */
7339 if (is_float(bt1) || is_float(bt2)) {
7340 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7341 type.t = VT_LDOUBLE;
7342 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7343 type.t = VT_DOUBLE;
7344 } else {
7345 type.t = VT_FLOAT;
7347 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7348 /* cast to biggest op */
7349 type.t = VT_LLONG;
7350 /* convert to unsigned if it does not fit in a long long */
7351 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7352 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7353 type.t |= VT_UNSIGNED;
7354 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7355 /* XXX: test pointer compatibility */
7356 type = type1;
7357 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7358 /* XXX: test structure compatibility */
7359 type = type1;
7360 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7361 /* NOTE: as an extension, we accept void on only one side */
7362 type.t = VT_VOID;
7363 } else {
7364 /* integer operations */
7365 type.t = VT_INT;
7366 /* convert to unsigned if it does not fit in an integer */
7367 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7368 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7369 type.t |= VT_UNSIGNED;
7372 /* now we convert second operand */
7373 gen_cast(&type);
7374 rc = RC_INT;
7375 if (is_float(type.t)) {
7376 rc = RC_FLOAT;
7377 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7378 /* for long longs, we use fixed registers to avoid having
7379 to handle a complicated move */
7380 rc = RC_IRET;
7383 r2 = gv(rc);
7384 /* this is horrible, but we must also convert first
7385 operand */
7386 tt = gjmp(0);
7387 gsym(u);
7388 /* put again first value and cast it */
7389 *vtop = sv;
7390 gen_cast(&type);
7391 r1 = gv(rc);
7392 move_reg(r2, r1);
7393 vtop->r = r2;
7394 gsym(tt);
7399 static void gexpr(void)
7401 while (1) {
7402 expr_eq();
7403 if (tok != ',')
7404 break;
7405 vpop();
7406 next();
7410 /* parse an expression and return its type without any side effect. */
7411 static void expr_type(CType *type)
7413 int saved_nocode_wanted;
7415 saved_nocode_wanted = nocode_wanted;
7416 nocode_wanted = 1;
7417 gexpr();
7418 *type = vtop->type;
7419 vpop();
7420 nocode_wanted = saved_nocode_wanted;
7423 /* parse a unary expression and return its type without any side
7424 effect. */
7425 static void unary_type(CType *type)
7427 int a;
7429 a = nocode_wanted;
7430 nocode_wanted = 1;
7431 unary();
7432 *type = vtop->type;
7433 vpop();
7434 nocode_wanted = a;
7437 /* parse a constant expression and return value in vtop. */
7438 static void expr_const1(void)
7440 int a;
7441 a = const_wanted;
7442 const_wanted = 1;
7443 expr_eq();
7444 const_wanted = a;
7447 /* parse an integer constant and return its value. */
7448 static int expr_const(void)
7450 int c;
7451 expr_const1();
7452 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7453 expect("constant expression");
7454 c = vtop->c.i;
7455 vpop();
7456 return c;
7459 /* return the label token if current token is a label, otherwise
7460 return zero */
7461 static int is_label(void)
7463 int last_tok;
7465 /* fast test first */
7466 if (tok < TOK_UIDENT)
7467 return 0;
7468 /* no need to save tokc because tok is an identifier */
7469 last_tok = tok;
7470 next();
7471 if (tok == ':') {
7472 next();
7473 return last_tok;
7474 } else {
7475 unget_tok(last_tok);
7476 return 0;
7480 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7481 int case_reg, int is_expr)
7483 int a, b, c, d;
7484 Sym *s;
7486 /* generate line number info */
7487 if (do_debug &&
7488 (last_line_num != file->line_num || last_ind != ind)) {
7489 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7490 last_ind = ind;
7491 last_line_num = file->line_num;
7494 if (is_expr) {
7495 /* default return value is (void) */
7496 vpushi(0);
7497 vtop->type.t = VT_VOID;
7500 if (tok == TOK_IF) {
7501 /* if test */
7502 next();
7503 skip('(');
7504 gexpr();
7505 skip(')');
7506 a = gtst(1, 0);
7507 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7508 c = tok;
7509 if (c == TOK_ELSE) {
7510 next();
7511 d = gjmp(0);
7512 gsym(a);
7513 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7514 gsym(d); /* patch else jmp */
7515 } else
7516 gsym(a);
7517 } else if (tok == TOK_WHILE) {
7518 next();
7519 d = ind;
7520 skip('(');
7521 gexpr();
7522 skip(')');
7523 a = gtst(1, 0);
7524 b = 0;
7525 block(&a, &b, case_sym, def_sym, case_reg, 0);
7526 gjmp_addr(d);
7527 gsym(a);
7528 gsym_addr(b, d);
7529 } else if (tok == '{') {
7530 Sym *llabel;
7532 next();
7533 /* record local declaration stack position */
7534 s = local_stack;
7535 llabel = local_label_stack;
7536 /* handle local labels declarations */
7537 if (tok == TOK_LABEL) {
7538 next();
7539 for(;;) {
7540 if (tok < TOK_UIDENT)
7541 expect("label identifier");
7542 label_push(&local_label_stack, tok, LABEL_DECLARED);
7543 next();
7544 if (tok == ',') {
7545 next();
7546 } else {
7547 skip(';');
7548 break;
7552 while (tok != '}') {
7553 decl(VT_LOCAL);
7554 if (tok != '}') {
7555 if (is_expr)
7556 vpop();
7557 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7560 /* pop locally defined labels */
7561 label_pop(&local_label_stack, llabel);
7562 /* pop locally defined symbols */
7563 sym_pop(&local_stack, s);
7564 next();
7565 } else if (tok == TOK_RETURN) {
7566 next();
7567 if (tok != ';') {
7568 gexpr();
7569 gen_assign_cast(&func_vt);
7570 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7571 CType type;
7572 /* if returning structure, must copy it to implicit
7573 first pointer arg location */
7574 type = func_vt;
7575 mk_pointer(&type);
7576 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7577 indir();
7578 vswap();
7579 /* copy structure value to pointer */
7580 vstore();
7581 } else if (is_float(func_vt.t)) {
7582 gv(RC_FRET);
7583 } else {
7584 gv(RC_IRET);
7586 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7588 skip(';');
7589 rsym = gjmp(rsym); /* jmp */
7590 } else if (tok == TOK_BREAK) {
7591 /* compute jump */
7592 if (!bsym)
7593 error("cannot break");
7594 *bsym = gjmp(*bsym);
7595 next();
7596 skip(';');
7597 } else if (tok == TOK_CONTINUE) {
7598 /* compute jump */
7599 if (!csym)
7600 error("cannot continue");
7601 *csym = gjmp(*csym);
7602 next();
7603 skip(';');
7604 } else if (tok == TOK_FOR) {
7605 int e;
7606 next();
7607 skip('(');
7608 if (tok != ';') {
7609 gexpr();
7610 vpop();
7612 skip(';');
7613 d = ind;
7614 c = ind;
7615 a = 0;
7616 b = 0;
7617 if (tok != ';') {
7618 gexpr();
7619 a = gtst(1, 0);
7621 skip(';');
7622 if (tok != ')') {
7623 e = gjmp(0);
7624 c = ind;
7625 gexpr();
7626 vpop();
7627 gjmp_addr(d);
7628 gsym(e);
7630 skip(')');
7631 block(&a, &b, case_sym, def_sym, case_reg, 0);
7632 gjmp_addr(c);
7633 gsym(a);
7634 gsym_addr(b, c);
7635 } else
7636 if (tok == TOK_DO) {
7637 next();
7638 a = 0;
7639 b = 0;
7640 d = ind;
7641 block(&a, &b, case_sym, def_sym, case_reg, 0);
7642 skip(TOK_WHILE);
7643 skip('(');
7644 gsym(b);
7645 gexpr();
7646 c = gtst(0, 0);
7647 gsym_addr(c, d);
7648 skip(')');
7649 gsym(a);
7650 skip(';');
7651 } else
7652 if (tok == TOK_SWITCH) {
7653 next();
7654 skip('(');
7655 gexpr();
7656 /* XXX: other types than integer */
7657 case_reg = gv(RC_INT);
7658 vpop();
7659 skip(')');
7660 a = 0;
7661 b = gjmp(0); /* jump to first case */
7662 c = 0;
7663 block(&a, csym, &b, &c, case_reg, 0);
7664 /* if no default, jmp after switch */
7665 if (c == 0)
7666 c = ind;
7667 /* default label */
7668 gsym_addr(b, c);
7669 /* break label */
7670 gsym(a);
7671 } else
7672 if (tok == TOK_CASE) {
7673 int v1, v2;
7674 if (!case_sym)
7675 expect("switch");
7676 next();
7677 v1 = expr_const();
7678 v2 = v1;
7679 if (gnu_ext && tok == TOK_DOTS) {
7680 next();
7681 v2 = expr_const();
7682 if (v2 < v1)
7683 warning("empty case range");
7685 /* since a case is like a label, we must skip it with a jmp */
7686 b = gjmp(0);
7687 gsym(*case_sym);
7688 vseti(case_reg, 0);
7689 vpushi(v1);
7690 if (v1 == v2) {
7691 gen_op(TOK_EQ);
7692 *case_sym = gtst(1, 0);
7693 } else {
7694 gen_op(TOK_GE);
7695 *case_sym = gtst(1, 0);
7696 vseti(case_reg, 0);
7697 vpushi(v2);
7698 gen_op(TOK_LE);
7699 *case_sym = gtst(1, *case_sym);
7701 gsym(b);
7702 skip(':');
7703 is_expr = 0;
7704 goto block_after_label;
7705 } else
7706 if (tok == TOK_DEFAULT) {
7707 next();
7708 skip(':');
7709 if (!def_sym)
7710 expect("switch");
7711 if (*def_sym)
7712 error("too many 'default'");
7713 *def_sym = ind;
7714 is_expr = 0;
7715 goto block_after_label;
7716 } else
7717 if (tok == TOK_GOTO) {
7718 next();
7719 if (tok == '*' && gnu_ext) {
7720 /* computed goto */
7721 next();
7722 gexpr();
7723 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7724 expect("pointer");
7725 ggoto();
7726 } else if (tok >= TOK_UIDENT) {
7727 s = label_find(tok);
7728 /* put forward definition if needed */
7729 if (!s) {
7730 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7731 } else {
7732 if (s->r == LABEL_DECLARED)
7733 s->r = LABEL_FORWARD;
7735 /* label already defined */
7736 if (s->r & LABEL_FORWARD)
7737 s->next = (void *)gjmp((long)s->next);
7738 else
7739 gjmp_addr((long)s->next);
7740 next();
7741 } else {
7742 expect("label identifier");
7744 skip(';');
7745 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7746 asm_instr();
7747 } else {
7748 b = is_label();
7749 if (b) {
7750 /* label case */
7751 s = label_find(b);
7752 if (s) {
7753 if (s->r == LABEL_DEFINED)
7754 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7755 gsym((long)s->next);
7756 s->r = LABEL_DEFINED;
7757 } else {
7758 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7760 s->next = (void *)ind;
7761 /* we accept this, but it is a mistake */
7762 block_after_label:
7763 if (tok == '}') {
7764 warning("deprecated use of label at end of compound statement");
7765 } else {
7766 if (is_expr)
7767 vpop();
7768 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7770 } else {
7771 /* expression case */
7772 if (tok != ';') {
7773 if (is_expr) {
7774 vpop();
7775 gexpr();
7776 } else {
7777 gexpr();
7778 vpop();
7781 skip(';');
7786 /* t is the array or struct type. c is the array or struct
7787 address. cur_index/cur_field is the pointer to the current
7788 value. 'size_only' is true if only size info is needed (only used
7789 in arrays) */
7790 static void decl_designator(CType *type, Section *sec, unsigned long c,
7791 int *cur_index, Sym **cur_field,
7792 int size_only)
7794 Sym *s, *f;
7795 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7796 CType type1;
7798 notfirst = 0;
7799 elem_size = 0;
7800 nb_elems = 1;
7801 if (gnu_ext && (l = is_label()) != 0)
7802 goto struct_field;
7803 while (tok == '[' || tok == '.') {
7804 if (tok == '[') {
7805 if (!(type->t & VT_ARRAY))
7806 expect("array type");
7807 s = type->ref;
7808 next();
7809 index = expr_const();
7810 if (index < 0 || (s->c >= 0 && index >= s->c))
7811 expect("invalid index");
7812 if (tok == TOK_DOTS && gnu_ext) {
7813 next();
7814 index_last = expr_const();
7815 if (index_last < 0 ||
7816 (s->c >= 0 && index_last >= s->c) ||
7817 index_last < index)
7818 expect("invalid index");
7819 } else {
7820 index_last = index;
7822 skip(']');
7823 if (!notfirst)
7824 *cur_index = index_last;
7825 type = pointed_type(type);
7826 elem_size = type_size(type, &align);
7827 c += index * elem_size;
7828 /* NOTE: we only support ranges for last designator */
7829 nb_elems = index_last - index + 1;
7830 if (nb_elems != 1) {
7831 notfirst = 1;
7832 break;
7834 } else {
7835 next();
7836 l = tok;
7837 next();
7838 struct_field:
7839 if ((type->t & VT_BTYPE) != VT_STRUCT)
7840 expect("struct/union type");
7841 s = type->ref;
7842 l |= SYM_FIELD;
7843 f = s->next;
7844 while (f) {
7845 if (f->v == l)
7846 break;
7847 f = f->next;
7849 if (!f)
7850 expect("field");
7851 if (!notfirst)
7852 *cur_field = f;
7853 /* XXX: fix this mess by using explicit storage field */
7854 type1 = f->type;
7855 type1.t |= (type->t & ~VT_TYPE);
7856 type = &type1;
7857 c += f->c;
7859 notfirst = 1;
7861 if (notfirst) {
7862 if (tok == '=') {
7863 next();
7864 } else {
7865 if (!gnu_ext)
7866 expect("=");
7868 } else {
7869 if (type->t & VT_ARRAY) {
7870 index = *cur_index;
7871 type = pointed_type(type);
7872 c += index * type_size(type, &align);
7873 } else {
7874 f = *cur_field;
7875 if (!f)
7876 error("too many field init");
7877 /* XXX: fix this mess by using explicit storage field */
7878 type1 = f->type;
7879 type1.t |= (type->t & ~VT_TYPE);
7880 type = &type1;
7881 c += f->c;
7884 decl_initializer(type, sec, c, 0, size_only);
7886 /* XXX: make it more general */
7887 if (!size_only && nb_elems > 1) {
7888 unsigned long c_end;
7889 uint8_t *src, *dst;
7890 int i;
7892 if (!sec)
7893 error("range init not supported yet for dynamic storage");
7894 c_end = c + nb_elems * elem_size;
7895 if (c_end > sec->data_allocated)
7896 section_realloc(sec, c_end);
7897 src = sec->data + c;
7898 dst = src;
7899 for(i = 1; i < nb_elems; i++) {
7900 dst += elem_size;
7901 memcpy(dst, src, elem_size);
7906 #define EXPR_VAL 0
7907 #define EXPR_CONST 1
7908 #define EXPR_ANY 2
7910 /* store a value or an expression directly in global data or in local array */
7911 static void init_putv(CType *type, Section *sec, unsigned long c,
7912 int v, int expr_type)
7914 int saved_global_expr, bt, bit_pos, bit_size;
7915 void *ptr;
7916 unsigned long long bit_mask;
7917 CType dtype;
7919 switch(expr_type) {
7920 case EXPR_VAL:
7921 vpushi(v);
7922 break;
7923 case EXPR_CONST:
7924 /* compound literals must be allocated globally in this case */
7925 saved_global_expr = global_expr;
7926 global_expr = 1;
7927 expr_const1();
7928 global_expr = saved_global_expr;
7929 /* NOTE: symbols are accepted */
7930 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7931 error("initializer element is not constant");
7932 break;
7933 case EXPR_ANY:
7934 expr_eq();
7935 break;
7938 dtype = *type;
7939 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7941 if (sec) {
7942 /* XXX: not portable */
7943 /* XXX: generate error if incorrect relocation */
7944 gen_assign_cast(&dtype);
7945 bt = type->t & VT_BTYPE;
7946 ptr = sec->data + c;
7947 /* XXX: make code faster ? */
7948 if (!(type->t & VT_BITFIELD)) {
7949 bit_pos = 0;
7950 bit_size = 32;
7951 bit_mask = -1LL;
7952 } else {
7953 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7954 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7955 bit_mask = (1LL << bit_size) - 1;
7957 if ((vtop->r & VT_SYM) &&
7958 (bt == VT_BYTE ||
7959 bt == VT_SHORT ||
7960 bt == VT_DOUBLE ||
7961 bt == VT_LDOUBLE ||
7962 bt == VT_LLONG ||
7963 (bt == VT_INT && bit_size != 32)))
7964 error("initializer element is not computable at load time");
7965 switch(bt) {
7966 case VT_BYTE:
7967 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7968 break;
7969 case VT_SHORT:
7970 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7971 break;
7972 case VT_DOUBLE:
7973 *(double *)ptr = vtop->c.d;
7974 break;
7975 case VT_LDOUBLE:
7976 *(long double *)ptr = vtop->c.ld;
7977 break;
7978 case VT_LLONG:
7979 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7980 break;
7981 default:
7982 if (vtop->r & VT_SYM) {
7983 greloc(sec, vtop->sym, c, R_DATA_32);
7985 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7986 break;
7988 vtop--;
7989 } else {
7990 vset(&dtype, VT_LOCAL, c);
7991 vswap();
7992 vstore();
7993 vpop();
7997 /* put zeros for variable based init */
7998 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8000 if (sec) {
8001 /* nothing to do because globals are already set to zero */
8002 } else {
8003 vpush_global_sym(&func_old_type, TOK_memset);
8004 vseti(VT_LOCAL, c);
8005 vpushi(0);
8006 vpushi(size);
8007 gfunc_call(3);
8011 /* 't' contains the type and storage info. 'c' is the offset of the
8012 object in section 'sec'. If 'sec' is NULL, it means stack based
8013 allocation. 'first' is true if array '{' must be read (multi
8014 dimension implicit array init handling). 'size_only' is true if
8015 size only evaluation is wanted (only for arrays). */
8016 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8017 int first, int size_only)
8019 int index, array_length, n, no_oblock, nb, parlevel, i;
8020 int size1, align1, expr_type;
8021 Sym *s, *f;
8022 CType *t1;
8024 if (type->t & VT_ARRAY) {
8025 s = type->ref;
8026 n = s->c;
8027 array_length = 0;
8028 t1 = pointed_type(type);
8029 size1 = type_size(t1, &align1);
8031 no_oblock = 1;
8032 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8033 tok == '{') {
8034 skip('{');
8035 no_oblock = 0;
8038 /* only parse strings here if correct type (otherwise: handle
8039 them as ((w)char *) expressions */
8040 if ((tok == TOK_LSTR &&
8041 (t1->t & VT_BTYPE) == VT_INT) ||
8042 (tok == TOK_STR &&
8043 (t1->t & VT_BTYPE) == VT_BYTE)) {
8044 while (tok == TOK_STR || tok == TOK_LSTR) {
8045 int cstr_len, ch;
8046 CString *cstr;
8048 cstr = tokc.cstr;
8049 /* compute maximum number of chars wanted */
8050 if (tok == TOK_STR)
8051 cstr_len = cstr->size;
8052 else
8053 cstr_len = cstr->size / sizeof(int);
8054 cstr_len--;
8055 nb = cstr_len;
8056 if (n >= 0 && nb > (n - array_length))
8057 nb = n - array_length;
8058 if (!size_only) {
8059 if (cstr_len > nb)
8060 warning("initializer-string for array is too long");
8061 /* in order to go faster for common case (char
8062 string in global variable, we handle it
8063 specifically */
8064 if (sec && tok == TOK_STR && size1 == 1) {
8065 memcpy(sec->data + c + array_length, cstr->data, nb);
8066 } else {
8067 for(i=0;i<nb;i++) {
8068 if (tok == TOK_STR)
8069 ch = ((unsigned char *)cstr->data)[i];
8070 else
8071 ch = ((int *)cstr->data)[i];
8072 init_putv(t1, sec, c + (array_length + i) * size1,
8073 ch, EXPR_VAL);
8077 array_length += nb;
8078 next();
8080 /* only add trailing zero if enough storage (no
8081 warning in this case since it is standard) */
8082 if (n < 0 || array_length < n) {
8083 if (!size_only) {
8084 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8086 array_length++;
8088 } else {
8089 index = 0;
8090 while (tok != '}') {
8091 decl_designator(type, sec, c, &index, NULL, size_only);
8092 if (n >= 0 && index >= n)
8093 error("index too large");
8094 /* must put zero in holes (note that doing it that way
8095 ensures that it even works with designators) */
8096 if (!size_only && array_length < index) {
8097 init_putz(t1, sec, c + array_length * size1,
8098 (index - array_length) * size1);
8100 index++;
8101 if (index > array_length)
8102 array_length = index;
8103 /* special test for multi dimensional arrays (may not
8104 be strictly correct if designators are used at the
8105 same time) */
8106 if (index >= n && no_oblock)
8107 break;
8108 if (tok == '}')
8109 break;
8110 skip(',');
8113 if (!no_oblock)
8114 skip('}');
8115 /* put zeros at the end */
8116 if (!size_only && n >= 0 && array_length < n) {
8117 init_putz(t1, sec, c + array_length * size1,
8118 (n - array_length) * size1);
8120 /* patch type size if needed */
8121 if (n < 0)
8122 s->c = array_length;
8123 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8124 (sec || !first || tok == '{')) {
8125 int par_count;
8127 /* NOTE: the previous test is a specific case for automatic
8128 struct/union init */
8129 /* XXX: union needs only one init */
8131 /* XXX: this test is incorrect for local initializers
8132 beginning with ( without {. It would be much more difficult
8133 to do it correctly (ideally, the expression parser should
8134 be used in all cases) */
8135 par_count = 0;
8136 if (tok == '(') {
8137 AttributeDef ad1;
8138 CType type1;
8139 next();
8140 while (tok == '(') {
8141 par_count++;
8142 next();
8144 if (!parse_btype(&type1, &ad1))
8145 expect("cast");
8146 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8147 #if 0
8148 if (!is_assignable_types(type, &type1))
8149 error("invalid type for cast");
8150 #endif
8151 skip(')');
8153 no_oblock = 1;
8154 if (first || tok == '{') {
8155 skip('{');
8156 no_oblock = 0;
8158 s = type->ref;
8159 f = s->next;
8160 array_length = 0;
8161 index = 0;
8162 n = s->c;
8163 while (tok != '}') {
8164 decl_designator(type, sec, c, NULL, &f, size_only);
8165 index = f->c;
8166 if (!size_only && array_length < index) {
8167 init_putz(type, sec, c + array_length,
8168 index - array_length);
8170 index = index + type_size(&f->type, &align1);
8171 if (index > array_length)
8172 array_length = index;
8173 f = f->next;
8174 if (no_oblock && f == NULL)
8175 break;
8176 if (tok == '}')
8177 break;
8178 skip(',');
8180 /* put zeros at the end */
8181 if (!size_only && array_length < n) {
8182 init_putz(type, sec, c + array_length,
8183 n - array_length);
8185 if (!no_oblock)
8186 skip('}');
8187 while (par_count) {
8188 skip(')');
8189 par_count--;
8191 } else if (tok == '{') {
8192 next();
8193 decl_initializer(type, sec, c, first, size_only);
8194 skip('}');
8195 } else if (size_only) {
8196 /* just skip expression */
8197 parlevel = 0;
8198 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8199 tok != -1) {
8200 if (tok == '(')
8201 parlevel++;
8202 else if (tok == ')')
8203 parlevel--;
8204 next();
8206 } else {
8207 /* currently, we always use constant expression for globals
8208 (may change for scripting case) */
8209 expr_type = EXPR_CONST;
8210 if (!sec)
8211 expr_type = EXPR_ANY;
8212 init_putv(type, sec, c, 0, expr_type);
8216 /* parse an initializer for type 't' if 'has_init' is non zero, and
8217 allocate space in local or global data space ('r' is either
8218 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8219 variable 'v' of scope 'scope' is declared before initializers are
8220 parsed. If 'v' is zero, then a reference to the new object is put
8221 in the value stack. If 'has_init' is 2, a special parsing is done
8222 to handle string constants. */
8223 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8224 int has_init, int v, int scope)
8226 int size, align, addr, data_offset;
8227 int level;
8228 ParseState saved_parse_state;
8229 TokenString init_str;
8230 Section *sec;
8232 size = type_size(type, &align);
8233 /* If unknown size, we must evaluate it before
8234 evaluating initializers because
8235 initializers can generate global data too
8236 (e.g. string pointers or ISOC99 compound
8237 literals). It also simplifies local
8238 initializers handling */
8239 tok_str_new(&init_str);
8240 if (size < 0) {
8241 if (!has_init)
8242 error("unknown type size");
8243 /* get all init string */
8244 if (has_init == 2) {
8245 /* only get strings */
8246 while (tok == TOK_STR || tok == TOK_LSTR) {
8247 tok_str_add_tok(&init_str);
8248 next();
8250 } else {
8251 level = 0;
8252 while (level > 0 || (tok != ',' && tok != ';')) {
8253 if (tok < 0)
8254 error("unexpected end of file in initializer");
8255 tok_str_add_tok(&init_str);
8256 if (tok == '{')
8257 level++;
8258 else if (tok == '}') {
8259 if (level == 0)
8260 break;
8261 level--;
8263 next();
8266 tok_str_add(&init_str, -1);
8267 tok_str_add(&init_str, 0);
8269 /* compute size */
8270 save_parse_state(&saved_parse_state);
8272 macro_ptr = init_str.str;
8273 next();
8274 decl_initializer(type, NULL, 0, 1, 1);
8275 /* prepare second initializer parsing */
8276 macro_ptr = init_str.str;
8277 next();
8279 /* if still unknown size, error */
8280 size = type_size(type, &align);
8281 if (size < 0)
8282 error("unknown type size");
8284 /* take into account specified alignment if bigger */
8285 if (ad->aligned > align)
8286 align = ad->aligned;
8287 if ((r & VT_VALMASK) == VT_LOCAL) {
8288 sec = NULL;
8289 if (do_bounds_check && (type->t & VT_ARRAY))
8290 loc--;
8291 loc = (loc - size) & -align;
8292 addr = loc;
8293 /* handles bounds */
8294 /* XXX: currently, since we do only one pass, we cannot track
8295 '&' operators, so we add only arrays */
8296 if (do_bounds_check && (type->t & VT_ARRAY)) {
8297 unsigned long *bounds_ptr;
8298 /* add padding between regions */
8299 loc--;
8300 /* then add local bound info */
8301 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8302 bounds_ptr[0] = addr;
8303 bounds_ptr[1] = size;
8305 if (v) {
8306 /* local variable */
8307 sym_push(v, type, r, addr);
8308 } else {
8309 /* push local reference */
8310 vset(type, r, addr);
8312 } else {
8313 Sym *sym;
8315 sym = NULL;
8316 if (v && scope == VT_CONST) {
8317 /* see if the symbol was already defined */
8318 sym = sym_find(v);
8319 if (sym) {
8320 if (!is_compatible_types(&sym->type, type))
8321 error("incompatible types for redefinition of '%s'",
8322 get_tok_str(v, NULL));
8323 if (sym->type.t & VT_EXTERN) {
8324 /* if the variable is extern, it was not allocated */
8325 sym->type.t &= ~VT_EXTERN;
8326 } else {
8327 /* we accept several definitions of the same
8328 global variable. this is tricky, because we
8329 must play with the SHN_COMMON type of the symbol */
8330 /* XXX: should check if the variable was already
8331 initialized. It is incorrect to initialized it
8332 twice */
8333 /* no init data, we won't add more to the symbol */
8334 if (!has_init)
8335 goto no_alloc;
8340 /* allocate symbol in corresponding section */
8341 sec = ad->section;
8342 if (!sec) {
8343 if (has_init)
8344 sec = data_section;
8346 if (sec) {
8347 data_offset = sec->data_offset;
8348 data_offset = (data_offset + align - 1) & -align;
8349 addr = data_offset;
8350 /* very important to increment global pointer at this time
8351 because initializers themselves can create new initializers */
8352 data_offset += size;
8353 /* add padding if bound check */
8354 if (do_bounds_check)
8355 data_offset++;
8356 sec->data_offset = data_offset;
8357 /* allocate section space to put the data */
8358 if (sec->sh_type != SHT_NOBITS &&
8359 data_offset > sec->data_allocated)
8360 section_realloc(sec, data_offset);
8361 } else {
8362 addr = 0; /* avoid warning */
8365 if (v) {
8366 if (scope == VT_CONST) {
8367 if (!sym)
8368 goto do_def;
8369 } else {
8370 do_def:
8371 sym = sym_push(v, type, r | VT_SYM, 0);
8373 /* update symbol definition */
8374 if (sec) {
8375 put_extern_sym(sym, sec, addr, size);
8376 } else {
8377 Elf32_Sym *esym;
8378 /* put a common area */
8379 put_extern_sym(sym, NULL, align, size);
8380 /* XXX: find a nicer way */
8381 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8382 esym->st_shndx = SHN_COMMON;
8384 } else {
8385 CValue cval;
8387 /* push global reference */
8388 sym = get_sym_ref(type, sec, addr, size);
8389 cval.ul = 0;
8390 vsetc(type, VT_CONST | VT_SYM, &cval);
8391 vtop->sym = sym;
8394 /* handles bounds now because the symbol must be defined
8395 before for the relocation */
8396 if (do_bounds_check) {
8397 unsigned long *bounds_ptr;
8399 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8400 /* then add global bound info */
8401 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8402 bounds_ptr[0] = 0; /* relocated */
8403 bounds_ptr[1] = size;
8406 if (has_init) {
8407 decl_initializer(type, sec, addr, 1, 0);
8408 /* restore parse state if needed */
8409 if (init_str.str) {
8410 tok_str_free(init_str.str);
8411 restore_parse_state(&saved_parse_state);
8414 no_alloc: ;
8417 void put_func_debug(Sym *sym)
8419 char buf[512];
8421 /* stabs info */
8422 /* XXX: we put here a dummy type */
8423 snprintf(buf, sizeof(buf), "%s:%c1",
8424 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8425 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8426 cur_text_section, sym->c);
8427 last_ind = 0;
8428 last_line_num = 0;
8431 /* not finished : try to put some local vars in registers */
8432 //#define CONFIG_REG_VARS
8434 #ifdef CONFIG_REG_VARS
8435 void add_var_ref(int t)
8437 printf("%s:%d: &%s\n",
8438 file->filename, file->line_num,
8439 get_tok_str(t, NULL));
8442 /* first pass on a function with heuristic to extract variable usage
8443 and pointer references to local variables for register allocation */
8444 void analyse_function(void)
8446 int level, t;
8448 for(;;) {
8449 if (tok == -1)
8450 break;
8451 /* any symbol coming after '&' is considered as being a
8452 variable whose reference is taken. It is highly unaccurate
8453 but it is difficult to do better without a complete parse */
8454 if (tok == '&') {
8455 next();
8456 /* if '& number', then no need to examine next tokens */
8457 if (tok == TOK_CINT ||
8458 tok == TOK_CUINT ||
8459 tok == TOK_CLLONG ||
8460 tok == TOK_CULLONG) {
8461 continue;
8462 } else if (tok >= TOK_UIDENT) {
8463 /* if '& ident [' or '& ident ->', then ident address
8464 is not needed */
8465 t = tok;
8466 next();
8467 if (tok != '[' && tok != TOK_ARROW)
8468 add_var_ref(t);
8469 } else {
8470 level = 0;
8471 while (tok != '}' && tok != ';' &&
8472 !((tok == ',' || tok == ')') && level == 0)) {
8473 if (tok >= TOK_UIDENT) {
8474 add_var_ref(tok);
8475 } else if (tok == '(') {
8476 level++;
8477 } else if (tok == ')') {
8478 level--;
8480 next();
8483 } else {
8484 next();
8488 #endif
8490 /* parse an old style function declaration list */
8491 /* XXX: check multiple parameter */
8492 static void func_decl_list(Sym *func_sym)
8494 AttributeDef ad;
8495 int v;
8496 Sym *s;
8497 CType btype, type;
8499 /* parse each declaration */
8500 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8501 if (!parse_btype(&btype, &ad))
8502 expect("declaration list");
8503 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8504 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8505 tok == ';') {
8506 /* we accept no variable after */
8507 } else {
8508 for(;;) {
8509 type = btype;
8510 type_decl(&type, &ad, &v, TYPE_DIRECT);
8511 /* find parameter in function parameter list */
8512 s = func_sym->next;
8513 while (s != NULL) {
8514 if ((s->v & ~SYM_FIELD) == v)
8515 goto found;
8516 s = s->next;
8518 error("declaration for parameter '%s' but no such parameter",
8519 get_tok_str(v, NULL));
8520 found:
8521 /* check that no storage specifier except 'register' was given */
8522 if (type.t & VT_STORAGE)
8523 error("storage class specified for '%s'", get_tok_str(v, NULL));
8524 convert_parameter_type(&type);
8525 /* we can add the type (NOTE: it could be local to the function) */
8526 s->type = type;
8527 /* accept other parameters */
8528 if (tok == ',')
8529 next();
8530 else
8531 break;
8534 skip(';');
8538 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8539 static void decl(int l)
8541 int v, has_init, r;
8542 CType type, btype;
8543 Sym *sym;
8544 AttributeDef ad;
8546 while (1) {
8547 if (!parse_btype(&btype, &ad)) {
8548 /* skip redundant ';' */
8549 /* XXX: find more elegant solution */
8550 if (tok == ';') {
8551 next();
8552 continue;
8554 /* special test for old K&R protos without explicit int
8555 type. Only accepted when defining global data */
8556 if (l == VT_LOCAL || tok < TOK_DEFINE)
8557 break;
8558 btype.t = VT_INT;
8560 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8561 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8562 tok == ';') {
8563 /* we accept no variable after */
8564 next();
8565 continue;
8567 while (1) { /* iterate thru each declaration */
8568 type = btype;
8569 type_decl(&type, &ad, &v, TYPE_DIRECT);
8570 #if 0
8572 char buf[500];
8573 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8574 printf("type = '%s'\n", buf);
8576 #endif
8577 if ((type.t & VT_BTYPE) == VT_FUNC) {
8578 /* if old style function prototype, we accept a
8579 declaration list */
8580 sym = type.ref;
8581 if (sym->c == FUNC_OLD)
8582 func_decl_list(sym);
8585 if (tok == '{') {
8586 #ifdef CONFIG_REG_VARS
8587 TokenString func_str;
8588 ParseState saved_parse_state;
8589 int block_level;
8590 #endif
8592 if (l == VT_LOCAL)
8593 error("cannot use local functions");
8594 if (!(type.t & VT_FUNC))
8595 expect("function definition");
8597 /* reject abstract declarators in function definition */
8598 sym = type.ref;
8599 while ((sym = sym->next) != NULL)
8600 if (!(sym->v & ~SYM_FIELD))
8601 expect("identifier");
8603 /* XXX: cannot do better now: convert extern line to static inline */
8604 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8605 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8607 #ifdef CONFIG_REG_VARS
8608 /* parse all function code and record it */
8610 tok_str_new(&func_str);
8612 block_level = 0;
8613 for(;;) {
8614 int t;
8615 if (tok == -1)
8616 error("unexpected end of file");
8617 tok_str_add_tok(&func_str);
8618 t = tok;
8619 next();
8620 if (t == '{') {
8621 block_level++;
8622 } else if (t == '}') {
8623 block_level--;
8624 if (block_level == 0)
8625 break;
8628 tok_str_add(&func_str, -1);
8629 tok_str_add(&func_str, 0);
8631 save_parse_state(&saved_parse_state);
8633 macro_ptr = func_str.str;
8634 next();
8635 analyse_function();
8636 #endif
8638 /* compute text section */
8639 cur_text_section = ad.section;
8640 if (!cur_text_section)
8641 cur_text_section = text_section;
8642 ind = cur_text_section->data_offset;
8643 funcname = get_tok_str(v, NULL);
8644 sym = sym_find(v);
8645 if (sym) {
8646 /* if symbol is already defined, then put complete type */
8647 sym->type = type;
8648 } else {
8649 /* put function symbol */
8650 sym = global_identifier_push(v, type.t, 0);
8651 sym->type.ref = type.ref;
8653 /* NOTE: we patch the symbol size later */
8654 put_extern_sym(sym, cur_text_section, ind, 0);
8655 func_ind = ind;
8656 sym->r = VT_SYM | VT_CONST;
8657 /* put debug symbol */
8658 if (do_debug)
8659 put_func_debug(sym);
8660 /* push a dummy symbol to enable local sym storage */
8661 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8662 gfunc_prolog(&type);
8663 loc = 0;
8664 rsym = 0;
8665 #ifdef CONFIG_REG_VARS
8666 macro_ptr = func_str.str;
8667 next();
8668 #endif
8669 block(NULL, NULL, NULL, NULL, 0, 0);
8670 gsym(rsym);
8671 gfunc_epilog();
8672 cur_text_section->data_offset = ind;
8673 label_pop(&global_label_stack, NULL);
8674 sym_pop(&local_stack, NULL); /* reset local stack */
8675 /* end of function */
8676 /* patch symbol size */
8677 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8678 ind - func_ind;
8679 if (do_debug) {
8680 put_stabn(N_FUN, 0, 0, ind - func_ind);
8682 funcname = ""; /* for safety */
8683 func_vt.t = VT_VOID; /* for safety */
8684 ind = 0; /* for safety */
8686 #ifdef CONFIG_REG_VARS
8687 tok_str_free(func_str.str);
8688 restore_parse_state(&saved_parse_state);
8689 #endif
8690 break;
8691 } else {
8692 if (btype.t & VT_TYPEDEF) {
8693 /* save typedefed type */
8694 /* XXX: test storage specifiers ? */
8695 sym = sym_push(v, &type, 0, 0);
8696 sym->type.t |= VT_TYPEDEF;
8697 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8698 /* external function definition */
8699 external_sym(v, &type, 0);
8700 } else {
8701 /* not lvalue if array */
8702 r = 0;
8703 if (!(type.t & VT_ARRAY))
8704 r |= lvalue_type(type.t);
8705 has_init = (tok == '=');
8706 if ((btype.t & VT_EXTERN) ||
8707 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8708 !has_init && l == VT_CONST && type.ref->c < 0)) {
8709 /* external variable */
8710 /* NOTE: as GCC, uninitialized global static
8711 arrays of null size are considered as
8712 extern */
8713 external_sym(v, &type, r);
8714 } else {
8715 if (type.t & VT_STATIC)
8716 r |= VT_CONST;
8717 else
8718 r |= l;
8719 if (has_init)
8720 next();
8721 decl_initializer_alloc(&type, &ad, r,
8722 has_init, v, l);
8725 if (tok != ',') {
8726 skip(';');
8727 break;
8729 next();
8735 /* better than nothing, but needs extension to handle '-E' option
8736 correctly too */
8737 static void preprocess_init(TCCState *s1)
8739 s1->include_stack_ptr = s1->include_stack;
8740 /* XXX: move that before to avoid having to initialize
8741 file->ifdef_stack_ptr ? */
8742 s1->ifdef_stack_ptr = s1->ifdef_stack;
8743 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8745 /* XXX: not ANSI compliant: bound checking says error */
8746 vtop = vstack - 1;
8749 /* compile the C file opened in 'file'. Return non zero if errors. */
8750 static int tcc_compile(TCCState *s1)
8752 Sym *define_start;
8753 char buf[512];
8754 volatile int section_sym;
8756 #ifdef INC_DEBUG
8757 printf("%s: **** new file\n", file->filename);
8758 #endif
8759 preprocess_init(s1);
8761 funcname = "";
8762 anon_sym = SYM_FIRST_ANOM;
8764 /* file info: full path + filename */
8765 section_sym = 0; /* avoid warning */
8766 if (do_debug) {
8767 section_sym = put_elf_sym(symtab_section, 0, 0,
8768 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8769 text_section->sh_num, NULL);
8770 getcwd(buf, sizeof(buf));
8771 pstrcat(buf, sizeof(buf), "/");
8772 put_stabs_r(buf, N_SO, 0, 0,
8773 text_section->data_offset, text_section, section_sym);
8774 put_stabs_r(file->filename, N_SO, 0, 0,
8775 text_section->data_offset, text_section, section_sym);
8777 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8778 symbols can be safely used */
8779 put_elf_sym(symtab_section, 0, 0,
8780 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8781 SHN_ABS, file->filename);
8783 /* define some often used types */
8784 int_type.t = VT_INT;
8786 char_pointer_type.t = VT_BYTE;
8787 mk_pointer(&char_pointer_type);
8789 func_old_type.t = VT_FUNC;
8790 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8792 #if 0
8793 /* define 'void *alloca(unsigned int)' builtin function */
8795 Sym *s1;
8797 p = anon_sym++;
8798 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8799 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8800 s1->next = NULL;
8801 sym->next = s1;
8802 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8804 #endif
8806 define_start = define_stack;
8808 if (setjmp(s1->error_jmp_buf) == 0) {
8809 s1->nb_errors = 0;
8810 s1->error_set_jmp_enabled = 1;
8812 ch = file->buf_ptr[0];
8813 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8814 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8815 next();
8816 decl(VT_CONST);
8817 if (tok != TOK_EOF)
8818 expect("declaration");
8820 /* end of translation unit info */
8821 if (do_debug) {
8822 put_stabs_r(NULL, N_SO, 0, 0,
8823 text_section->data_offset, text_section, section_sym);
8826 s1->error_set_jmp_enabled = 0;
8828 /* reset define stack, but leave -Dsymbols (may be incorrect if
8829 they are undefined) */
8830 free_defines(define_start);
8832 sym_pop(&global_stack, NULL);
8834 return s1->nb_errors != 0 ? -1 : 0;
8837 #ifdef LIBTCC
8838 int tcc_compile_string(TCCState *s, const char *str)
8840 BufferedFile bf1, *bf = &bf1;
8841 int ret, len;
8842 char *buf;
8844 /* init file structure */
8845 bf->fd = -1;
8846 /* XXX: avoid copying */
8847 len = strlen(str);
8848 buf = tcc_malloc(len + 1);
8849 if (!buf)
8850 return -1;
8851 memcpy(buf, str, len);
8852 buf[len] = CH_EOB;
8853 bf->buf_ptr = buf;
8854 bf->buf_end = buf + len;
8855 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8856 bf->line_num = 1;
8857 file = bf;
8859 ret = tcc_compile(s);
8861 tcc_free(buf);
8863 /* currently, no need to close */
8864 return ret;
8866 #endif
8868 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8869 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8871 BufferedFile bf1, *bf = &bf1;
8873 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8874 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8875 /* default value */
8876 if (!value)
8877 value = "1";
8878 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8880 /* init file structure */
8881 bf->fd = -1;
8882 bf->buf_ptr = bf->buffer;
8883 bf->buf_end = bf->buffer + strlen(bf->buffer);
8884 *bf->buf_end = CH_EOB;
8885 bf->filename[0] = '\0';
8886 bf->line_num = 1;
8887 file = bf;
8889 s1->include_stack_ptr = s1->include_stack;
8891 /* parse with define parser */
8892 ch = file->buf_ptr[0];
8893 next_nomacro();
8894 parse_define();
8895 file = NULL;
8898 /* undefine a preprocessor symbol */
8899 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8901 TokenSym *ts;
8902 Sym *s;
8903 ts = tok_alloc(sym, strlen(sym));
8904 s = define_find(ts->tok);
8905 /* undefine symbol by putting an invalid name */
8906 if (s)
8907 define_undef(s);
8910 #ifdef CONFIG_TCC_ASM
8912 #ifdef TCC_TARGET_I386
8913 #include "i386-asm.c"
8914 #endif
8915 #include "tccasm.c"
8917 #else
8918 static void asm_instr(void)
8920 error("inline asm() not supported");
8922 #endif
8924 #include "tccelf.c"
8926 /* print the position in the source file of PC value 'pc' by reading
8927 the stabs debug information */
8928 static void rt_printline(unsigned long wanted_pc)
8930 Stab_Sym *sym, *sym_end;
8931 char func_name[128], last_func_name[128];
8932 unsigned long func_addr, last_pc, pc;
8933 const char *incl_files[INCLUDE_STACK_SIZE];
8934 int incl_index, len, last_line_num, i;
8935 const char *str, *p;
8937 fprintf(stderr, "0x%08lx:", wanted_pc);
8939 func_name[0] = '\0';
8940 func_addr = 0;
8941 incl_index = 0;
8942 last_func_name[0] = '\0';
8943 last_pc = 0xffffffff;
8944 last_line_num = 1;
8945 sym = (Stab_Sym *)stab_section->data + 1;
8946 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8947 while (sym < sym_end) {
8948 switch(sym->n_type) {
8949 /* function start or end */
8950 case N_FUN:
8951 if (sym->n_strx == 0) {
8952 /* we test if between last line and end of function */
8953 pc = sym->n_value + func_addr;
8954 if (wanted_pc >= last_pc && wanted_pc < pc)
8955 goto found;
8956 func_name[0] = '\0';
8957 func_addr = 0;
8958 } else {
8959 str = stabstr_section->data + sym->n_strx;
8960 p = strchr(str, ':');
8961 if (!p) {
8962 pstrcpy(func_name, sizeof(func_name), str);
8963 } else {
8964 len = p - str;
8965 if (len > sizeof(func_name) - 1)
8966 len = sizeof(func_name) - 1;
8967 memcpy(func_name, str, len);
8968 func_name[len] = '\0';
8970 func_addr = sym->n_value;
8972 break;
8973 /* line number info */
8974 case N_SLINE:
8975 pc = sym->n_value + func_addr;
8976 if (wanted_pc >= last_pc && wanted_pc < pc)
8977 goto found;
8978 last_pc = pc;
8979 last_line_num = sym->n_desc;
8980 /* XXX: slow! */
8981 strcpy(last_func_name, func_name);
8982 break;
8983 /* include files */
8984 case N_BINCL:
8985 str = stabstr_section->data + sym->n_strx;
8986 add_incl:
8987 if (incl_index < INCLUDE_STACK_SIZE) {
8988 incl_files[incl_index++] = str;
8990 break;
8991 case N_EINCL:
8992 if (incl_index > 1)
8993 incl_index--;
8994 break;
8995 case N_SO:
8996 if (sym->n_strx == 0) {
8997 incl_index = 0; /* end of translation unit */
8998 } else {
8999 str = stabstr_section->data + sym->n_strx;
9000 /* do not add path */
9001 len = strlen(str);
9002 if (len > 0 && str[len - 1] != '/')
9003 goto add_incl;
9005 break;
9007 sym++;
9010 /* second pass: we try symtab symbols (no line number info) */
9011 incl_index = 0;
9013 Elf32_Sym *sym, *sym_end;
9014 int type;
9016 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9017 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9018 sym < sym_end;
9019 sym++) {
9020 type = ELF32_ST_TYPE(sym->st_info);
9021 if (type == STT_FUNC) {
9022 if (wanted_pc >= sym->st_value &&
9023 wanted_pc < sym->st_value + sym->st_size) {
9024 pstrcpy(last_func_name, sizeof(last_func_name),
9025 strtab_section->data + sym->st_name);
9026 goto found;
9031 /* did not find any info: */
9032 fprintf(stderr, " ???\n");
9033 return;
9034 found:
9035 if (last_func_name[0] != '\0') {
9036 fprintf(stderr, " %s()", last_func_name);
9038 if (incl_index > 0) {
9039 fprintf(stderr, " (%s:%d",
9040 incl_files[incl_index - 1], last_line_num);
9041 for(i = incl_index - 2; i >= 0; i--)
9042 fprintf(stderr, ", included from %s", incl_files[i]);
9043 fprintf(stderr, ")");
9045 fprintf(stderr, "\n");
9048 #ifndef WIN32
9050 #ifdef __i386__
9052 /* fix for glibc 2.1 */
9053 #ifndef REG_EIP
9054 #define REG_EIP EIP
9055 #define REG_EBP EBP
9056 #endif
9058 /* return the PC at frame level 'level'. Return non zero if not found */
9059 static int rt_get_caller_pc(unsigned long *paddr,
9060 ucontext_t *uc, int level)
9062 unsigned long fp;
9063 int i;
9065 if (level == 0) {
9066 #ifdef __FreeBSD__
9067 *paddr = uc->uc_mcontext.mc_eip;
9068 #else
9069 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9070 #endif
9071 return 0;
9072 } else {
9073 #ifdef __FreeBSD__
9074 fp = uc->uc_mcontext.mc_ebp;
9075 #else
9076 fp = uc->uc_mcontext.gregs[REG_EBP];
9077 #endif
9078 for(i=1;i<level;i++) {
9079 /* XXX: check address validity with program info */
9080 if (fp <= 0x1000 || fp >= 0xc0000000)
9081 return -1;
9082 fp = ((unsigned long *)fp)[0];
9084 *paddr = ((unsigned long *)fp)[1];
9085 return 0;
9088 #else
9090 #warning add arch specific rt_get_caller_pc()
9092 static int rt_get_caller_pc(unsigned long *paddr,
9093 ucontext_t *uc, int level)
9095 return -1;
9097 #endif
9099 /* emit a run time error at position 'pc' */
9100 void rt_error(ucontext_t *uc, const char *fmt, ...)
9102 va_list ap;
9103 unsigned long pc;
9104 int i;
9106 va_start(ap, fmt);
9107 fprintf(stderr, "Runtime error: ");
9108 vfprintf(stderr, fmt, ap);
9109 fprintf(stderr, "\n");
9110 for(i=0;i<num_callers;i++) {
9111 if (rt_get_caller_pc(&pc, uc, i) < 0)
9112 break;
9113 if (i == 0)
9114 fprintf(stderr, "at ");
9115 else
9116 fprintf(stderr, "by ");
9117 rt_printline(pc);
9119 exit(255);
9120 va_end(ap);
9123 /* signal handler for fatal errors */
9124 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9126 ucontext_t *uc = puc;
9128 switch(signum) {
9129 case SIGFPE:
9130 switch(siginf->si_code) {
9131 case FPE_INTDIV:
9132 case FPE_FLTDIV:
9133 rt_error(uc, "division by zero");
9134 break;
9135 default:
9136 rt_error(uc, "floating point exception");
9137 break;
9139 break;
9140 case SIGBUS:
9141 case SIGSEGV:
9142 if (rt_bound_error_msg && *rt_bound_error_msg)
9143 rt_error(uc, *rt_bound_error_msg);
9144 else
9145 rt_error(uc, "dereferencing invalid pointer");
9146 break;
9147 case SIGILL:
9148 rt_error(uc, "illegal instruction");
9149 break;
9150 case SIGABRT:
9151 rt_error(uc, "abort() called");
9152 break;
9153 default:
9154 rt_error(uc, "caught signal %d", signum);
9155 break;
9157 exit(255);
9159 #endif
9161 /* do all relocations (needed before using tcc_get_symbol()) */
9162 int tcc_relocate(TCCState *s1)
9164 Section *s;
9165 int i;
9167 s1->nb_errors = 0;
9169 tcc_add_runtime(s1);
9171 build_got_entries(s1);
9173 relocate_common_syms();
9175 /* compute relocation address : section are relocated in place. We
9176 also alloc the bss space */
9177 for(i = 1; i < s1->nb_sections; i++) {
9178 s = s1->sections[i];
9179 if (s->sh_flags & SHF_ALLOC) {
9180 if (s->sh_type == SHT_NOBITS)
9181 s->data = tcc_mallocz(s->data_offset);
9182 s->sh_addr = (unsigned long)s->data;
9186 relocate_syms(s1, 1);
9188 if (s1->nb_errors != 0)
9189 return -1;
9191 /* relocate each section */
9192 for(i = 1; i < s1->nb_sections; i++) {
9193 s = s1->sections[i];
9194 if (s->reloc)
9195 relocate_section(s1, s);
9197 return 0;
9200 /* launch the compiled program with the given arguments */
9201 int tcc_run(TCCState *s1, int argc, char **argv)
9203 int (*prog_main)(int, char **);
9205 if (tcc_relocate(s1) < 0)
9206 return -1;
9208 prog_main = tcc_get_symbol_err(s1, "main");
9210 if (do_debug) {
9211 #ifdef WIN32
9212 error("debug mode currently not available for Windows");
9213 #else
9214 struct sigaction sigact;
9215 /* install TCC signal handlers to print debug info on fatal
9216 runtime errors */
9217 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9218 sigact.sa_sigaction = sig_error;
9219 sigemptyset(&sigact.sa_mask);
9220 sigaction(SIGFPE, &sigact, NULL);
9221 sigaction(SIGILL, &sigact, NULL);
9222 sigaction(SIGSEGV, &sigact, NULL);
9223 sigaction(SIGBUS, &sigact, NULL);
9224 sigaction(SIGABRT, &sigact, NULL);
9225 #endif
9228 #ifdef CONFIG_TCC_BCHECK
9229 if (do_bounds_check) {
9230 void (*bound_init)(void);
9232 /* set error function */
9233 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9234 "__bound_error_msg");
9236 /* XXX: use .init section so that it also work in binary ? */
9237 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9238 bound_init();
9240 #endif
9241 return (*prog_main)(argc, argv);
9244 TCCState *tcc_new(void)
9246 const char *p, *r;
9247 TCCState *s;
9248 TokenSym *ts;
9249 int i, c;
9251 s = tcc_mallocz(sizeof(TCCState));
9252 if (!s)
9253 return NULL;
9254 tcc_state = s;
9255 s->output_type = TCC_OUTPUT_MEMORY;
9257 /* init isid table */
9258 for(i=0;i<256;i++)
9259 isidnum_table[i] = isid(i) || isnum(i);
9261 /* add all tokens */
9262 table_ident = NULL;
9263 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9265 tok_ident = TOK_IDENT;
9266 p = tcc_keywords;
9267 while (*p) {
9268 r = p;
9269 for(;;) {
9270 c = *r++;
9271 if (c == '\0')
9272 break;
9274 ts = tok_alloc(p, r - p - 1);
9275 p = r;
9278 /* we add dummy defines for some special macros to speed up tests
9279 and to have working defined() */
9280 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9281 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9282 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9283 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9285 /* standard defines */
9286 tcc_define_symbol(s, "__STDC__", NULL);
9287 #if defined(TCC_TARGET_I386)
9288 tcc_define_symbol(s, "__i386__", NULL);
9289 #endif
9290 #if defined(TCC_TARGET_ARM)
9291 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9292 tcc_define_symbol(s, "__arm_elf__", NULL);
9293 tcc_define_symbol(s, "__arm_elf", NULL);
9294 tcc_define_symbol(s, "arm_elf", NULL);
9295 tcc_define_symbol(s, "__arm__", NULL);
9296 tcc_define_symbol(s, "__arm", NULL);
9297 tcc_define_symbol(s, "arm", NULL);
9298 tcc_define_symbol(s, "__APCS_32__", NULL);
9299 #endif
9300 #if defined(linux)
9301 tcc_define_symbol(s, "__linux__", NULL);
9302 tcc_define_symbol(s, "linux", NULL);
9303 #endif
9304 /* tiny C specific defines */
9305 tcc_define_symbol(s, "__TINYC__", NULL);
9307 /* tiny C & gcc defines */
9308 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9309 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9310 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9312 /* default library paths */
9313 tcc_add_library_path(s, "/usr/local/lib");
9314 tcc_add_library_path(s, "/usr/lib");
9315 tcc_add_library_path(s, "/lib");
9317 /* no section zero */
9318 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9320 /* create standard sections */
9321 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9322 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9323 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9325 /* symbols are always generated for linking stage */
9326 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9327 ".strtab",
9328 ".hashtab", SHF_PRIVATE);
9329 strtab_section = symtab_section->link;
9331 /* private symbol table for dynamic symbols */
9332 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9333 ".dynstrtab",
9334 ".dynhashtab", SHF_PRIVATE);
9335 s->alacarte_link = 1;
9337 #ifdef CHAR_IS_UNSIGNED
9338 s->char_is_unsigned = 1;
9339 #endif
9340 return s;
9343 void tcc_delete(TCCState *s1)
9345 int i, n;
9347 /* free -D defines */
9348 free_defines(NULL);
9350 /* free tokens */
9351 n = tok_ident - TOK_IDENT;
9352 for(i = 0; i < n; i++)
9353 tcc_free(table_ident[i]);
9354 tcc_free(table_ident);
9356 /* free all sections */
9358 free_section(symtab_section->hash);
9360 free_section(s1->dynsymtab_section->hash);
9361 free_section(s1->dynsymtab_section->link);
9362 free_section(s1->dynsymtab_section);
9364 for(i = 1; i < s1->nb_sections; i++)
9365 free_section(s1->sections[i]);
9366 tcc_free(s1->sections);
9368 /* free loaded dlls array */
9369 for(i = 0; i < s1->nb_loaded_dlls; i++)
9370 tcc_free(s1->loaded_dlls[i]);
9371 tcc_free(s1->loaded_dlls);
9373 /* library paths */
9374 for(i = 0; i < s1->nb_library_paths; i++)
9375 tcc_free(s1->library_paths[i]);
9376 tcc_free(s1->library_paths);
9378 /* cached includes */
9379 for(i = 0; i < s1->nb_cached_includes; i++)
9380 tcc_free(s1->cached_includes[i]);
9381 tcc_free(s1->cached_includes);
9383 for(i = 0; i < s1->nb_include_paths; i++)
9384 tcc_free(s1->include_paths[i]);
9385 tcc_free(s1->include_paths);
9387 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9388 tcc_free(s1->sysinclude_paths[i]);
9389 tcc_free(s1->sysinclude_paths);
9391 tcc_free(s1);
9394 int tcc_add_include_path(TCCState *s1, const char *pathname)
9396 char *pathname1;
9398 pathname1 = tcc_strdup(pathname);
9399 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9400 return 0;
9403 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9405 char *pathname1;
9407 pathname1 = tcc_strdup(pathname);
9408 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9409 return 0;
9412 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9414 const char *ext, *filename1;
9415 Elf32_Ehdr ehdr;
9416 int fd, ret;
9417 BufferedFile *saved_file;
9419 /* find source file type with extension */
9420 filename1 = strrchr(filename, '/');
9421 if (filename1)
9422 filename1++;
9423 else
9424 filename1 = filename;
9425 ext = strrchr(filename1, '.');
9426 if (ext)
9427 ext++;
9429 /* open the file */
9430 saved_file = file;
9431 file = tcc_open(s1, filename);
9432 if (!file) {
9433 if (flags & AFF_PRINT_ERROR) {
9434 error_noabort("file '%s' not found", filename);
9436 ret = -1;
9437 goto fail1;
9440 if (!ext || !strcmp(ext, "c")) {
9441 /* C file assumed */
9442 ret = tcc_compile(s1);
9443 } else
9444 #ifdef CONFIG_TCC_ASM
9445 if (!strcmp(ext, "S")) {
9446 /* preprocessed assembler */
9447 ret = tcc_assemble(s1, 1);
9448 } else if (!strcmp(ext, "s")) {
9449 /* non preprocessed assembler */
9450 ret = tcc_assemble(s1, 0);
9451 } else
9452 #endif
9454 fd = file->fd;
9455 /* assume executable format: auto guess file type */
9456 ret = read(fd, &ehdr, sizeof(ehdr));
9457 lseek(fd, 0, SEEK_SET);
9458 if (ret <= 0) {
9459 error_noabort("could not read header");
9460 goto fail;
9461 } else if (ret != sizeof(ehdr)) {
9462 goto try_load_script;
9465 if (ehdr.e_ident[0] == ELFMAG0 &&
9466 ehdr.e_ident[1] == ELFMAG1 &&
9467 ehdr.e_ident[2] == ELFMAG2 &&
9468 ehdr.e_ident[3] == ELFMAG3) {
9469 file->line_num = 0; /* do not display line number if error */
9470 if (ehdr.e_type == ET_REL) {
9471 ret = tcc_load_object_file(s1, fd, 0);
9472 } else if (ehdr.e_type == ET_DYN) {
9473 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9474 void *h;
9475 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9476 if (h)
9477 ret = 0;
9478 else
9479 ret = -1;
9480 } else {
9481 ret = tcc_load_dll(s1, fd, filename,
9482 (flags & AFF_REFERENCED_DLL) != 0);
9484 } else {
9485 error_noabort("unrecognized ELF file");
9486 goto fail;
9488 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9489 file->line_num = 0; /* do not display line number if error */
9490 ret = tcc_load_archive(s1, fd);
9491 } else {
9492 /* as GNU ld, consider it is an ld script if not recognized */
9493 try_load_script:
9494 ret = tcc_load_ldscript(s1);
9495 if (ret < 0) {
9496 error_noabort("unrecognized file type");
9497 goto fail;
9501 the_end:
9502 tcc_close(file);
9503 fail1:
9504 file = saved_file;
9505 return ret;
9506 fail:
9507 ret = -1;
9508 goto the_end;
9511 int tcc_add_file(TCCState *s, const char *filename)
9513 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9516 int tcc_add_library_path(TCCState *s, const char *pathname)
9518 char *pathname1;
9520 pathname1 = tcc_strdup(pathname);
9521 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9522 return 0;
9525 /* find and load a dll. Return non zero if not found */
9526 /* XXX: add '-rpath' option support ? */
9527 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9529 char buf[1024];
9530 int i;
9532 for(i = 0; i < s->nb_library_paths; i++) {
9533 snprintf(buf, sizeof(buf), "%s/%s",
9534 s->library_paths[i], filename);
9535 if (tcc_add_file_internal(s, buf, flags) == 0)
9536 return 0;
9538 return -1;
9541 /* the library name is the same as the argument of the '-l' option */
9542 int tcc_add_library(TCCState *s, const char *libraryname)
9544 char buf[1024];
9545 int i;
9547 /* first we look for the dynamic library if not static linking */
9548 if (!s->static_link) {
9549 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9550 if (tcc_add_dll(s, buf, 0) == 0)
9551 return 0;
9554 /* then we look for the static library */
9555 for(i = 0; i < s->nb_library_paths; i++) {
9556 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9557 s->library_paths[i], libraryname);
9558 if (tcc_add_file_internal(s, buf, 0) == 0)
9559 return 0;
9561 return -1;
9564 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9566 add_elf_sym(symtab_section, val, 0,
9567 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9568 SHN_ABS, name);
9569 return 0;
9572 int tcc_set_output_type(TCCState *s, int output_type)
9574 char buf[1024];
9576 s->output_type = output_type;
9578 if (!s->nostdinc) {
9579 /* default include paths */
9580 /* XXX: reverse order needed if -isystem support */
9581 tcc_add_sysinclude_path(s, "/usr/local/include");
9582 tcc_add_sysinclude_path(s, "/usr/include");
9583 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9584 tcc_add_sysinclude_path(s, buf);
9587 /* if bound checking, then add corresponding sections */
9588 #ifdef CONFIG_TCC_BCHECK
9589 if (do_bounds_check) {
9590 /* define symbol */
9591 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9592 /* create bounds sections */
9593 bounds_section = new_section(s, ".bounds",
9594 SHT_PROGBITS, SHF_ALLOC);
9595 lbounds_section = new_section(s, ".lbounds",
9596 SHT_PROGBITS, SHF_ALLOC);
9598 #endif
9600 if (s->char_is_unsigned) {
9601 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9604 /* add debug sections */
9605 if (do_debug) {
9606 /* stab symbols */
9607 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9608 stab_section->sh_entsize = sizeof(Stab_Sym);
9609 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9610 put_elf_str(stabstr_section, "");
9611 stab_section->link = stabstr_section;
9612 /* put first entry */
9613 put_stabs("", 0, 0, 0, 0);
9616 /* add libc crt1/crti objects */
9617 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9618 !s->nostdlib) {
9619 if (output_type != TCC_OUTPUT_DLL)
9620 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9621 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9623 return 0;
9626 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9627 #define FD_INVERT 0x0002 /* invert value before storing */
9629 typedef struct FlagDef {
9630 uint16_t offset;
9631 uint16_t flags;
9632 const char *name;
9633 } FlagDef;
9635 static const FlagDef warning_defs[] = {
9636 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9637 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9638 { offsetof(TCCState, warn_error), 0, "error" },
9639 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9640 "implicit-function-declaration" },
9643 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9644 const char *name, int value)
9646 int i;
9647 const FlagDef *p;
9648 const char *r;
9650 r = name;
9651 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9652 r += 3;
9653 value = !value;
9655 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9656 if (!strcmp(r, p->name))
9657 goto found;
9659 return -1;
9660 found:
9661 if (p->flags & FD_INVERT)
9662 value = !value;
9663 *(int *)((uint8_t *)s + p->offset) = value;
9664 return 0;
9668 /* set/reset a warning */
9669 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9671 int i;
9672 const FlagDef *p;
9674 if (!strcmp(warning_name, "all")) {
9675 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9676 if (p->flags & WD_ALL)
9677 *(int *)((uint8_t *)s + p->offset) = 1;
9679 return 0;
9680 } else {
9681 return set_flag(s, warning_defs, countof(warning_defs),
9682 warning_name, value);
9686 static const FlagDef flag_defs[] = {
9687 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9688 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9691 /* set/reset a flag */
9692 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9694 return set_flag(s, flag_defs, countof(flag_defs),
9695 flag_name, value);
9698 #if !defined(LIBTCC)
9700 /* extract the basename of a file */
9701 static const char *tcc_basename(const char *name)
9703 const char *p;
9704 p = strrchr(name, '/');
9705 #ifdef WIN32
9706 if (!p)
9707 p = strrchr(name, '\\');
9708 #endif
9709 if (!p)
9710 p = name;
9711 else
9712 p++;
9713 return p;
9716 static int64_t getclock_us(void)
9718 #ifdef WIN32
9719 struct _timeb tb;
9720 _ftime(&tb);
9721 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9722 #else
9723 struct timeval tv;
9724 gettimeofday(&tv, NULL);
9725 return tv.tv_sec * 1000000LL + tv.tv_usec;
9726 #endif
9729 void help(void)
9731 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9732 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9733 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9734 " [infile1 infile2...] [-run infile args...]\n"
9735 "\n"
9736 "General options:\n"
9737 " -v display current version\n"
9738 " -c compile only - generate an object file\n"
9739 " -o outfile set output filename\n"
9740 " -Bdir set tcc internal library path\n"
9741 " -bench output compilation statistics\n"
9742 " -run run compiled source\n"
9743 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9744 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9745 " -w disable all warnings\n"
9746 "Preprocessor options:\n"
9747 " -Idir add include path 'dir'\n"
9748 " -Dsym[=val] define 'sym' with value 'val'\n"
9749 " -Usym undefine 'sym'\n"
9750 "Linker options:\n"
9751 " -Ldir add library path 'dir'\n"
9752 " -llib link with dynamic or static library 'lib'\n"
9753 " -shared generate a shared library\n"
9754 " -static static linking\n"
9755 " -rdynamic export all global symbols to dynamic linker\n"
9756 " -r relocatable output\n"
9757 "Debugger options:\n"
9758 " -g generate runtime debug info\n"
9759 #ifdef CONFIG_TCC_BCHECK
9760 " -b compile with built-in memory and bounds checker (implies -g)\n"
9761 #endif
9762 " -bt N show N callers in stack traces\n"
9766 #define TCC_OPTION_HAS_ARG 0x0001
9767 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9769 typedef struct TCCOption {
9770 const char *name;
9771 uint16_t index;
9772 uint16_t flags;
9773 } TCCOption;
9775 enum {
9776 TCC_OPTION_HELP,
9777 TCC_OPTION_I,
9778 TCC_OPTION_D,
9779 TCC_OPTION_U,
9780 TCC_OPTION_L,
9781 TCC_OPTION_B,
9782 TCC_OPTION_l,
9783 TCC_OPTION_bench,
9784 TCC_OPTION_bt,
9785 TCC_OPTION_b,
9786 TCC_OPTION_g,
9787 TCC_OPTION_c,
9788 TCC_OPTION_static,
9789 TCC_OPTION_shared,
9790 TCC_OPTION_o,
9791 TCC_OPTION_r,
9792 TCC_OPTION_W,
9793 TCC_OPTION_O,
9794 TCC_OPTION_m,
9795 TCC_OPTION_f,
9796 TCC_OPTION_nostdinc,
9797 TCC_OPTION_nostdlib,
9798 TCC_OPTION_print_search_dirs,
9799 TCC_OPTION_rdynamic,
9800 TCC_OPTION_run,
9801 TCC_OPTION_v,
9802 TCC_OPTION_w,
9805 static const TCCOption tcc_options[] = {
9806 { "h", TCC_OPTION_HELP, 0 },
9807 { "?", TCC_OPTION_HELP, 0 },
9808 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9809 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9810 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9811 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9812 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9813 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9814 { "bench", TCC_OPTION_bench, 0 },
9815 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9816 #ifdef CONFIG_TCC_BCHECK
9817 { "b", TCC_OPTION_b, 0 },
9818 #endif
9819 { "g", TCC_OPTION_g, 0 },
9820 { "c", TCC_OPTION_c, 0 },
9821 { "static", TCC_OPTION_static, 0 },
9822 { "shared", TCC_OPTION_shared, 0 },
9823 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9824 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9825 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9826 { "r", TCC_OPTION_r, 0 },
9827 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9828 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9829 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9830 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9831 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9832 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9833 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9834 { "v", TCC_OPTION_v, 0 },
9835 { "w", TCC_OPTION_w, 0 },
9836 { NULL },
9839 /* convert 'str' into an array of space separated strings */
9840 static int expand_args(char ***pargv, const char *str)
9842 const char *s1;
9843 char **argv, *arg;
9844 int argc, len;
9846 argc = 0;
9847 argv = NULL;
9848 for(;;) {
9849 while (is_space(*str))
9850 str++;
9851 if (*str == '\0')
9852 break;
9853 s1 = str;
9854 while (*str != '\0' && !is_space(*str))
9855 str++;
9856 len = str - s1;
9857 arg = tcc_malloc(len + 1);
9858 memcpy(arg, s1, len);
9859 arg[len] = '\0';
9860 dynarray_add((void ***)&argv, &argc, arg);
9862 *pargv = argv;
9863 return argc;
9866 static char **files;
9867 static int nb_files, nb_libraries;
9868 static int multiple_files;
9869 static int print_search_dirs;
9870 static int output_type;
9871 static int reloc_output;
9872 static const char *outfile;
9874 int parse_args(TCCState *s, int argc, char **argv)
9876 int optind;
9877 const TCCOption *popt;
9878 const char *optarg, *p1, *r1;
9879 char *r;
9881 optind = 0;
9882 while (1) {
9883 if (optind >= argc) {
9884 if (nb_files == 0 && !print_search_dirs)
9885 goto show_help;
9886 else
9887 break;
9889 r = argv[optind++];
9890 if (r[0] != '-') {
9891 /* add a new file */
9892 dynarray_add((void ***)&files, &nb_files, r);
9893 if (!multiple_files) {
9894 optind--;
9895 /* argv[0] will be this file */
9896 break;
9898 } else {
9899 /* find option in table (match only the first chars */
9900 popt = tcc_options;
9901 for(;;) {
9902 p1 = popt->name;
9903 if (p1 == NULL)
9904 error("invalid option -- '%s'", r);
9905 r1 = r + 1;
9906 for(;;) {
9907 if (*p1 == '\0')
9908 goto option_found;
9909 if (*r1 != *p1)
9910 break;
9911 p1++;
9912 r1++;
9914 popt++;
9916 option_found:
9917 if (popt->flags & TCC_OPTION_HAS_ARG) {
9918 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9919 optarg = r1;
9920 } else {
9921 if (optind >= argc)
9922 error("argument to '%s' is missing", r);
9923 optarg = argv[optind++];
9925 } else {
9926 if (*r1 != '\0')
9927 goto show_help;
9928 optarg = NULL;
9931 switch(popt->index) {
9932 case TCC_OPTION_HELP:
9933 show_help:
9934 help();
9935 exit(1);
9936 case TCC_OPTION_I:
9937 if (tcc_add_include_path(s, optarg) < 0)
9938 error("too many include paths");
9939 break;
9940 case TCC_OPTION_D:
9942 char *sym, *value;
9943 sym = (char *)optarg;
9944 value = strchr(sym, '=');
9945 if (value) {
9946 *value = '\0';
9947 value++;
9949 tcc_define_symbol(s, sym, value);
9951 break;
9952 case TCC_OPTION_U:
9953 tcc_undefine_symbol(s, optarg);
9954 break;
9955 case TCC_OPTION_L:
9956 tcc_add_library_path(s, optarg);
9957 break;
9958 case TCC_OPTION_B:
9959 /* set tcc utilities path (mainly for tcc development) */
9960 tcc_lib_path = optarg;
9961 break;
9962 case TCC_OPTION_l:
9963 dynarray_add((void ***)&files, &nb_files, r);
9964 nb_libraries++;
9965 break;
9966 case TCC_OPTION_bench:
9967 do_bench = 1;
9968 break;
9969 case TCC_OPTION_bt:
9970 num_callers = atoi(optarg);
9971 break;
9972 #ifdef CONFIG_TCC_BCHECK
9973 case TCC_OPTION_b:
9974 do_bounds_check = 1;
9975 do_debug = 1;
9976 break;
9977 #endif
9978 case TCC_OPTION_g:
9979 do_debug = 1;
9980 break;
9981 case TCC_OPTION_c:
9982 multiple_files = 1;
9983 output_type = TCC_OUTPUT_OBJ;
9984 break;
9985 case TCC_OPTION_static:
9986 s->static_link = 1;
9987 break;
9988 case TCC_OPTION_shared:
9989 output_type = TCC_OUTPUT_DLL;
9990 break;
9991 case TCC_OPTION_o:
9992 multiple_files = 1;
9993 outfile = optarg;
9994 break;
9995 case TCC_OPTION_r:
9996 /* generate a .o merging several output files */
9997 reloc_output = 1;
9998 output_type = TCC_OUTPUT_OBJ;
9999 break;
10000 case TCC_OPTION_nostdinc:
10001 s->nostdinc = 1;
10002 break;
10003 case TCC_OPTION_nostdlib:
10004 s->nostdlib = 1;
10005 break;
10006 case TCC_OPTION_print_search_dirs:
10007 print_search_dirs = 1;
10008 break;
10009 case TCC_OPTION_run:
10011 int argc1;
10012 char **argv1;
10013 argc1 = expand_args(&argv1, optarg);
10014 if (argc1 > 0) {
10015 parse_args(s, argc1, argv1);
10017 multiple_files = 0;
10018 output_type = TCC_OUTPUT_MEMORY;
10020 break;
10021 case TCC_OPTION_v:
10022 printf("tcc version %s\n", TCC_VERSION);
10023 exit(0);
10024 case TCC_OPTION_f:
10025 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10026 goto unsupported_option;
10027 break;
10028 case TCC_OPTION_W:
10029 if (tcc_set_warning(s, optarg, 1) < 0 &&
10030 s->warn_unsupported)
10031 goto unsupported_option;
10032 break;
10033 case TCC_OPTION_w:
10034 s->warn_none = 1;
10035 break;
10036 case TCC_OPTION_rdynamic:
10037 s->rdynamic = 1;
10038 break;
10039 default:
10040 if (s->warn_unsupported) {
10041 unsupported_option:
10042 warning("unsupported option '%s'", r);
10044 break;
10048 return optind;
10051 int main(int argc, char **argv)
10053 int i;
10054 TCCState *s;
10055 int nb_objfiles, ret, optind;
10056 char objfilename[1024];
10057 int64_t start_time = 0;
10059 s = tcc_new();
10060 output_type = TCC_OUTPUT_EXE;
10061 outfile = NULL;
10062 multiple_files = 1;
10063 files = NULL;
10064 nb_files = 0;
10065 nb_libraries = 0;
10066 reloc_output = 0;
10067 print_search_dirs = 0;
10069 optind = parse_args(s, argc - 1, argv + 1) + 1;
10071 if (print_search_dirs) {
10072 /* enough for Linux kernel */
10073 printf("install: %s/\n", tcc_lib_path);
10074 return 0;
10077 nb_objfiles = nb_files - nb_libraries;
10079 /* if outfile provided without other options, we output an
10080 executable */
10081 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10082 output_type = TCC_OUTPUT_EXE;
10084 /* check -c consistency : only single file handled. XXX: checks file type */
10085 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10086 /* accepts only a single input file */
10087 if (nb_objfiles != 1)
10088 error("cannot specify multiple files with -c");
10089 if (nb_libraries != 0)
10090 error("cannot specify libraries with -c");
10093 /* compute default outfile name */
10094 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10095 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10096 char *ext;
10097 /* strip path */
10098 pstrcpy(objfilename, sizeof(objfilename) - 1,
10099 tcc_basename(files[0]));
10100 /* add .o extension */
10101 ext = strrchr(objfilename, '.');
10102 if (!ext)
10103 goto default_outfile;
10104 strcpy(ext + 1, "o");
10105 } else {
10106 default_outfile:
10107 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10109 outfile = objfilename;
10112 if (do_bench) {
10113 start_time = getclock_us();
10116 tcc_set_output_type(s, output_type);
10118 /* compile or add each files or library */
10119 for(i = 0;i < nb_files; i++) {
10120 const char *filename;
10122 filename = files[i];
10123 if (filename[0] == '-') {
10124 if (tcc_add_library(s, filename + 2) < 0)
10125 error("cannot find %s", filename);
10126 } else {
10127 if (tcc_add_file(s, filename) < 0) {
10128 ret = 1;
10129 goto the_end;
10134 /* free all files */
10135 tcc_free(files);
10137 if (do_bench) {
10138 double total_time;
10139 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10140 if (total_time < 0.001)
10141 total_time = 0.001;
10142 if (total_bytes < 1)
10143 total_bytes = 1;
10144 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10145 tok_ident - TOK_IDENT, total_lines, total_bytes,
10146 total_time, (int)(total_lines / total_time),
10147 total_bytes / total_time / 1000000.0);
10150 if (s->output_type != TCC_OUTPUT_MEMORY) {
10151 tcc_output_file(s, outfile);
10152 ret = 0;
10153 } else {
10154 ret = tcc_run(s, argc - optind, argv + optind);
10156 the_end:
10157 /* XXX: cannot do it with bound checking because of the malloc hooks */
10158 if (!do_bounds_check)
10159 tcc_delete(s);
10161 #ifdef MEM_DEBUG
10162 if (do_bench) {
10163 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10165 #endif
10166 return ret;
10169 #endif