added -funsigned-char, -fsigned-char and -Wimplicit-function-declaration
[tinycc.git] / tcc.c
blob1eee2ce9bcb104011c4ab92f86fc04821fa1ce04
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 if (!is_compatible_types(dt, st)) {
5860 error:
5861 type_to_str(buf1, sizeof(buf1), st, NULL);
5862 type_to_str(buf2, sizeof(buf2), dt, NULL);
5863 error("cannot cast '%s' to '%s'", buf1, buf2);
5865 break;
5867 type_ok:
5868 gen_cast(dt);
5871 /* store vtop in lvalue pushed on stack */
5872 void vstore(void)
5874 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5876 ft = vtop[-1].type.t;
5877 sbt = vtop->type.t & VT_BTYPE;
5878 dbt = ft & VT_BTYPE;
5879 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5880 (sbt == VT_INT && dbt == VT_SHORT)) {
5881 /* optimize char/short casts */
5882 delayed_cast = VT_MUSTCAST;
5883 vtop->type.t = ft & VT_TYPE;
5884 /* XXX: factorize */
5885 if (ft & VT_CONSTANT)
5886 warning("assignment of read-only location");
5887 } else {
5888 delayed_cast = 0;
5889 gen_assign_cast(&vtop[-1].type);
5892 if (sbt == VT_STRUCT) {
5893 /* if structure, only generate pointer */
5894 /* structure assignment : generate memcpy */
5895 /* XXX: optimize if small size */
5896 if (!nocode_wanted) {
5897 size = type_size(&vtop->type, &align);
5899 vpush_global_sym(&func_old_type, TOK_memcpy);
5901 /* destination */
5902 vpushv(vtop - 2);
5903 vtop->type.t = VT_INT;
5904 gaddrof();
5905 /* source */
5906 vpushv(vtop - 2);
5907 vtop->type.t = VT_INT;
5908 gaddrof();
5909 /* type size */
5910 vpushi(size);
5911 gfunc_call(3);
5913 vswap();
5914 vpop();
5915 } else {
5916 vswap();
5917 vpop();
5919 /* leave source on stack */
5920 } else if (ft & VT_BITFIELD) {
5921 /* bitfield store handling */
5922 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5923 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5924 /* remove bit field info to avoid loops */
5925 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5927 /* duplicate destination */
5928 vdup();
5929 vtop[-1] = vtop[-2];
5931 /* mask and shift source */
5932 vpushi((1 << bit_size) - 1);
5933 gen_op('&');
5934 vpushi(bit_pos);
5935 gen_op(TOK_SHL);
5936 /* load destination, mask and or with source */
5937 vswap();
5938 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5939 gen_op('&');
5940 gen_op('|');
5941 /* store result */
5942 vstore();
5943 } else {
5944 #ifdef CONFIG_TCC_BCHECK
5945 /* bound check case */
5946 if (vtop[-1].r & VT_MUSTBOUND) {
5947 vswap();
5948 gbound();
5949 vswap();
5951 #endif
5952 if (!nocode_wanted) {
5953 rc = RC_INT;
5954 if (is_float(ft))
5955 rc = RC_FLOAT;
5956 r = gv(rc); /* generate value */
5957 /* if lvalue was saved on stack, must read it */
5958 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5959 SValue sv;
5960 t = get_reg(RC_INT);
5961 sv.type.t = VT_INT;
5962 sv.r = VT_LOCAL | VT_LVAL;
5963 sv.c.ul = vtop[-1].c.ul;
5964 load(t, &sv);
5965 vtop[-1].r = t | VT_LVAL;
5967 store(r, vtop - 1);
5968 /* two word case handling : store second register at word + 4 */
5969 if ((ft & VT_BTYPE) == VT_LLONG) {
5970 vswap();
5971 /* convert to int to increment easily */
5972 vtop->type.t = VT_INT;
5973 gaddrof();
5974 vpushi(4);
5975 gen_op('+');
5976 vtop->r |= VT_LVAL;
5977 vswap();
5978 /* XXX: it works because r2 is spilled last ! */
5979 store(vtop->r2, vtop - 1);
5982 vswap();
5983 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5984 vtop->r |= delayed_cast;
5988 /* post defines POST/PRE add. c is the token ++ or -- */
5989 void inc(int post, int c)
5991 test_lvalue();
5992 vdup(); /* save lvalue */
5993 if (post) {
5994 gv_dup(); /* duplicate value */
5995 vrotb(3);
5996 vrotb(3);
5998 /* add constant */
5999 vpushi(c - TOK_MID);
6000 gen_op('+');
6001 vstore(); /* store value */
6002 if (post)
6003 vpop(); /* if post op, return saved value */
6006 /* Parse GNUC __attribute__ extension. Currently, the following
6007 extensions are recognized:
6008 - aligned(n) : set data/function alignment.
6009 - section(x) : generate data/code in this section.
6010 - unused : currently ignored, but may be used someday.
6012 static void parse_attribute(AttributeDef *ad)
6014 int t, n;
6016 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6017 next();
6018 skip('(');
6019 skip('(');
6020 while (tok != ')') {
6021 if (tok < TOK_IDENT)
6022 expect("attribute name");
6023 t = tok;
6024 next();
6025 switch(t) {
6026 case TOK_SECTION1:
6027 case TOK_SECTION2:
6028 skip('(');
6029 if (tok != TOK_STR)
6030 expect("section name");
6031 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6032 next();
6033 skip(')');
6034 break;
6035 case TOK_ALIGNED1:
6036 case TOK_ALIGNED2:
6037 if (tok == '(') {
6038 next();
6039 n = expr_const();
6040 if (n <= 0 || (n & (n - 1)) != 0)
6041 error("alignment must be a positive power of two");
6042 skip(')');
6043 } else {
6044 n = MAX_ALIGN;
6046 ad->aligned = n;
6047 break;
6048 case TOK_UNUSED1:
6049 case TOK_UNUSED2:
6050 /* currently, no need to handle it because tcc does not
6051 track unused objects */
6052 break;
6053 case TOK_NORETURN1:
6054 case TOK_NORETURN2:
6055 /* currently, no need to handle it because tcc does not
6056 track unused objects */
6057 break;
6058 case TOK_CDECL1:
6059 case TOK_CDECL2:
6060 case TOK_CDECL3:
6061 ad->func_call = FUNC_CDECL;
6062 break;
6063 case TOK_STDCALL1:
6064 case TOK_STDCALL2:
6065 case TOK_STDCALL3:
6066 ad->func_call = FUNC_STDCALL;
6067 break;
6068 default:
6069 if (tcc_state->warn_unsupported)
6070 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6071 /* skip parameters */
6072 /* XXX: skip parenthesis too */
6073 if (tok == '(') {
6074 next();
6075 while (tok != ')' && tok != -1)
6076 next();
6077 next();
6079 break;
6081 if (tok != ',')
6082 break;
6083 next();
6085 skip(')');
6086 skip(')');
6090 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6091 static void struct_decl(CType *type, int u)
6093 int a, v, size, align, maxalign, c, offset;
6094 int bit_size, bit_pos, bsize, bt, lbit_pos;
6095 Sym *s, *ss, **ps;
6096 AttributeDef ad;
6097 CType type1, btype;
6099 a = tok; /* save decl type */
6100 next();
6101 if (tok != '{') {
6102 v = tok;
6103 next();
6104 /* struct already defined ? return it */
6105 if (v < TOK_IDENT)
6106 expect("struct/union/enum name");
6107 s = struct_find(v);
6108 if (s) {
6109 if (s->type.t != a)
6110 error("invalid type");
6111 goto do_decl;
6113 } else {
6114 v = anon_sym++;
6116 type1.t = a;
6117 /* we put an undefined size for struct/union */
6118 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6119 s->r = 0; /* default alignment is zero as gcc */
6120 /* put struct/union/enum name in type */
6121 do_decl:
6122 type->t = u;
6123 type->ref = s;
6125 if (tok == '{') {
6126 next();
6127 if (s->c != -1)
6128 error("struct/union/enum already defined");
6129 /* cannot be empty */
6130 c = 0;
6131 /* non empty enums are not allowed */
6132 if (a == TOK_ENUM) {
6133 for(;;) {
6134 v = tok;
6135 if (v < TOK_UIDENT)
6136 expect("identifier");
6137 next();
6138 if (tok == '=') {
6139 next();
6140 c = expr_const();
6142 /* enum symbols have static storage */
6143 ss = sym_push(v, &int_type, VT_CONST, c);
6144 ss->type.t |= VT_STATIC;
6145 if (tok != ',')
6146 break;
6147 next();
6148 c++;
6149 /* NOTE: we accept a trailing comma */
6150 if (tok == '}')
6151 break;
6153 skip('}');
6154 } else {
6155 maxalign = 1;
6156 ps = &s->next;
6157 bit_pos = 0;
6158 offset = 0;
6159 while (tok != '}') {
6160 parse_btype(&btype, &ad);
6161 while (1) {
6162 bit_size = -1;
6163 v = 0;
6164 type1 = btype;
6165 if (tok != ':') {
6166 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6167 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6168 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6169 error("invalid type for '%s'",
6170 get_tok_str(v, NULL));
6172 if (tok == ':') {
6173 next();
6174 bit_size = expr_const();
6175 /* XXX: handle v = 0 case for messages */
6176 if (bit_size < 0)
6177 error("negative width in bit-field '%s'",
6178 get_tok_str(v, NULL));
6179 if (v && bit_size == 0)
6180 error("zero width for bit-field '%s'",
6181 get_tok_str(v, NULL));
6183 size = type_size(&type1, &align);
6184 lbit_pos = 0;
6185 if (bit_size >= 0) {
6186 bt = type1.t & VT_BTYPE;
6187 if (bt != VT_INT &&
6188 bt != VT_BYTE &&
6189 bt != VT_SHORT &&
6190 bt != VT_ENUM)
6191 error("bitfields must have scalar type");
6192 bsize = size * 8;
6193 if (bit_size > bsize) {
6194 error("width of '%s' exceeds its type",
6195 get_tok_str(v, NULL));
6196 } else if (bit_size == bsize) {
6197 /* no need for bit fields */
6198 bit_pos = 0;
6199 } else if (bit_size == 0) {
6200 /* XXX: what to do if only padding in a
6201 structure ? */
6202 /* zero size: means to pad */
6203 if (bit_pos > 0)
6204 bit_pos = bsize;
6205 } else {
6206 /* we do not have enough room ? */
6207 if ((bit_pos + bit_size) > bsize)
6208 bit_pos = 0;
6209 lbit_pos = bit_pos;
6210 /* XXX: handle LSB first */
6211 type1.t |= VT_BITFIELD |
6212 (bit_pos << VT_STRUCT_SHIFT) |
6213 (bit_size << (VT_STRUCT_SHIFT + 6));
6214 bit_pos += bit_size;
6216 } else {
6217 bit_pos = 0;
6219 if (v) {
6220 /* add new memory data only if starting
6221 bit field */
6222 if (lbit_pos == 0) {
6223 if (a == TOK_STRUCT) {
6224 c = (c + align - 1) & -align;
6225 offset = c;
6226 c += size;
6227 } else {
6228 offset = 0;
6229 if (size > c)
6230 c = size;
6232 if (align > maxalign)
6233 maxalign = align;
6235 #if 0
6236 printf("add field %s offset=%d",
6237 get_tok_str(v, NULL), offset);
6238 if (type1.t & VT_BITFIELD) {
6239 printf(" pos=%d size=%d",
6240 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6241 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6243 printf("\n");
6244 #endif
6245 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6246 *ps = ss;
6247 ps = &ss->next;
6249 if (tok == ';' || tok == TOK_EOF)
6250 break;
6251 skip(',');
6253 skip(';');
6255 skip('}');
6256 /* store size and alignment */
6257 s->c = (c + maxalign - 1) & -maxalign;
6258 s->r = maxalign;
6263 /* return 0 if no type declaration. otherwise, return the basic type
6264 and skip it.
6266 static int parse_btype(CType *type, AttributeDef *ad)
6268 int t, u, type_found, typespec_found;
6269 Sym *s;
6270 CType type1;
6272 memset(ad, 0, sizeof(AttributeDef));
6273 type_found = 0;
6274 typespec_found = 0;
6275 t = 0;
6276 while(1) {
6277 switch(tok) {
6278 case TOK_EXTENSION:
6279 /* currently, we really ignore extension */
6280 next();
6281 continue;
6283 /* basic types */
6284 case TOK_CHAR:
6285 u = VT_BYTE;
6286 basic_type:
6287 next();
6288 basic_type1:
6289 if ((t & VT_BTYPE) != 0)
6290 error("too many basic types");
6291 t |= u;
6292 typespec_found = 1;
6293 break;
6294 case TOK_VOID:
6295 u = VT_VOID;
6296 goto basic_type;
6297 case TOK_SHORT:
6298 u = VT_SHORT;
6299 goto basic_type;
6300 case TOK_INT:
6301 next();
6302 typespec_found = 1;
6303 break;
6304 case TOK_LONG:
6305 next();
6306 if ((t & VT_BTYPE) == VT_DOUBLE) {
6307 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6308 } else if ((t & VT_BTYPE) == VT_LONG) {
6309 t = (t & ~VT_BTYPE) | VT_LLONG;
6310 } else {
6311 u = VT_LONG;
6312 goto basic_type1;
6314 break;
6315 case TOK_BOOL:
6316 u = VT_BOOL;
6317 goto basic_type;
6318 case TOK_FLOAT:
6319 u = VT_FLOAT;
6320 goto basic_type;
6321 case TOK_DOUBLE:
6322 next();
6323 if ((t & VT_BTYPE) == VT_LONG) {
6324 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6325 } else {
6326 u = VT_DOUBLE;
6327 goto basic_type1;
6329 break;
6330 case TOK_ENUM:
6331 struct_decl(&type1, VT_ENUM);
6332 basic_type2:
6333 u = type1.t;
6334 type->ref = type1.ref;
6335 goto basic_type1;
6336 case TOK_STRUCT:
6337 case TOK_UNION:
6338 struct_decl(&type1, VT_STRUCT);
6339 goto basic_type2;
6341 /* type modifiers */
6342 case TOK_CONST1:
6343 case TOK_CONST2:
6344 case TOK_CONST3:
6345 t |= VT_CONSTANT;
6346 next();
6347 break;
6348 case TOK_VOLATILE1:
6349 case TOK_VOLATILE2:
6350 case TOK_VOLATILE3:
6351 t |= VT_VOLATILE;
6352 next();
6353 break;
6354 case TOK_SIGNED1:
6355 case TOK_SIGNED2:
6356 case TOK_SIGNED3:
6357 typespec_found = 1;
6358 t |= VT_SIGNED;
6359 next();
6360 break;
6361 case TOK_REGISTER:
6362 case TOK_AUTO:
6363 case TOK_RESTRICT1:
6364 case TOK_RESTRICT2:
6365 case TOK_RESTRICT3:
6366 next();
6367 break;
6368 case TOK_UNSIGNED:
6369 t |= VT_UNSIGNED;
6370 next();
6371 typespec_found = 1;
6372 break;
6374 /* storage */
6375 case TOK_EXTERN:
6376 t |= VT_EXTERN;
6377 next();
6378 break;
6379 case TOK_STATIC:
6380 t |= VT_STATIC;
6381 next();
6382 break;
6383 case TOK_TYPEDEF:
6384 t |= VT_TYPEDEF;
6385 next();
6386 break;
6387 case TOK_INLINE1:
6388 case TOK_INLINE2:
6389 case TOK_INLINE3:
6390 t |= VT_INLINE;
6391 next();
6392 break;
6394 /* GNUC attribute */
6395 case TOK_ATTRIBUTE1:
6396 case TOK_ATTRIBUTE2:
6397 parse_attribute(ad);
6398 break;
6399 /* GNUC typeof */
6400 case TOK_TYPEOF1:
6401 case TOK_TYPEOF2:
6402 case TOK_TYPEOF3:
6403 next();
6404 parse_expr_type(&type1);
6405 goto basic_type2;
6406 default:
6407 if (typespec_found)
6408 goto the_end;
6409 s = sym_find(tok);
6410 if (!s || !(s->type.t & VT_TYPEDEF))
6411 goto the_end;
6412 t |= (s->type.t & ~VT_TYPEDEF);
6413 type->ref = s->type.ref;
6414 next();
6415 break;
6417 type_found = 1;
6419 the_end:
6420 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6421 error("signed and unsigned modifier");
6422 if (tcc_state->char_is_unsigned) {
6423 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6424 t |= VT_UNSIGNED;
6426 t &= ~VT_SIGNED;
6428 /* long is never used as type */
6429 if ((t & VT_BTYPE) == VT_LONG)
6430 t = (t & ~VT_BTYPE) | VT_INT;
6431 type->t = t;
6432 return type_found;
6435 /* convert a function parameter type (array to pointer and function to
6436 function pointer) */
6437 static inline void convert_parameter_type(CType *pt)
6439 /* array must be transformed to pointer according to ANSI C */
6440 pt->t &= ~VT_ARRAY;
6441 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6442 mk_pointer(pt);
6446 static void post_type(CType *type, AttributeDef *ad)
6448 int n, l, t1;
6449 Sym **plast, *s, *first;
6450 AttributeDef ad1;
6451 CType pt;
6453 if (tok == '(') {
6454 /* function declaration */
6455 next();
6456 l = 0;
6457 first = NULL;
6458 plast = &first;
6459 while (tok != ')') {
6460 /* read param name and compute offset */
6461 if (l != FUNC_OLD) {
6462 if (!parse_btype(&pt, &ad1)) {
6463 if (l) {
6464 error("invalid type");
6465 } else {
6466 l = FUNC_OLD;
6467 goto old_proto;
6470 l = FUNC_NEW;
6471 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6472 break;
6473 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6474 if ((pt.t & VT_BTYPE) == VT_VOID)
6475 error("parameter declared as void");
6476 } else {
6477 old_proto:
6478 n = tok;
6479 pt.t = VT_INT;
6480 next();
6482 convert_parameter_type(&pt);
6483 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6484 *plast = s;
6485 plast = &s->next;
6486 if (tok == ',') {
6487 next();
6488 if (l == FUNC_NEW && tok == TOK_DOTS) {
6489 l = FUNC_ELLIPSIS;
6490 next();
6491 break;
6495 /* if no parameters, then old type prototype */
6496 if (l == 0)
6497 l = FUNC_OLD;
6498 skip(')');
6499 t1 = type->t & VT_STORAGE;
6500 /* NOTE: const is ignored in returned type as it has a special
6501 meaning in gcc / C++ */
6502 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6503 post_type(type, ad);
6504 /* we push a anonymous symbol which will contain the function prototype */
6505 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6506 s->next = first;
6507 type->t = t1 | VT_FUNC;
6508 type->ref = s;
6509 } else if (tok == '[') {
6510 /* array definition */
6511 next();
6512 n = -1;
6513 if (tok != ']') {
6514 n = expr_const();
6515 if (n < 0)
6516 error("invalid array size");
6518 skip(']');
6519 /* parse next post type */
6520 t1 = type->t & VT_STORAGE;
6521 type->t &= ~VT_STORAGE;
6522 post_type(type, ad);
6524 /* we push a anonymous symbol which will contain the array
6525 element type */
6526 s = sym_push(SYM_FIELD, type, 0, n);
6527 type->t = t1 | VT_ARRAY | VT_PTR;
6528 type->ref = s;
6532 /* Parse a type declaration (except basic type), and return the type
6533 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6534 expected. 'type' should contain the basic type. 'ad' is the
6535 attribute definition of the basic type. It can be modified by
6536 type_decl().
6538 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6540 Sym *s;
6541 CType type1, *type2;
6542 int qualifiers;
6544 while (tok == '*') {
6545 qualifiers = 0;
6546 redo:
6547 next();
6548 switch(tok) {
6549 case TOK_CONST1:
6550 case TOK_CONST2:
6551 case TOK_CONST3:
6552 qualifiers |= VT_CONSTANT;
6553 goto redo;
6554 case TOK_VOLATILE1:
6555 case TOK_VOLATILE2:
6556 case TOK_VOLATILE3:
6557 qualifiers |= VT_VOLATILE;
6558 goto redo;
6559 case TOK_RESTRICT1:
6560 case TOK_RESTRICT2:
6561 case TOK_RESTRICT3:
6562 goto redo;
6564 mk_pointer(type);
6565 type->t |= qualifiers;
6568 /* XXX: clarify attribute handling */
6569 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6570 parse_attribute(ad);
6572 /* recursive type */
6573 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6574 type1.t = 0; /* XXX: same as int */
6575 if (tok == '(') {
6576 next();
6577 /* XXX: this is not correct to modify 'ad' at this point, but
6578 the syntax is not clear */
6579 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6580 parse_attribute(ad);
6581 type_decl(&type1, ad, v, td);
6582 skip(')');
6583 } else {
6584 /* type identifier */
6585 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6586 *v = tok;
6587 next();
6588 } else {
6589 if (!(td & TYPE_ABSTRACT))
6590 expect("identifier");
6591 *v = 0;
6594 post_type(type, ad);
6595 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6596 parse_attribute(ad);
6597 if (!type1.t)
6598 return;
6599 /* append type at the end of type1 */
6600 type2 = &type1;
6601 for(;;) {
6602 s = type2->ref;
6603 type2 = &s->type;
6604 if (!type2->t) {
6605 *type2 = *type;
6606 break;
6609 *type = type1;
6612 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6613 static int lvalue_type(int t)
6615 int bt, r;
6616 r = VT_LVAL;
6617 bt = t & VT_BTYPE;
6618 if (bt == VT_BYTE || bt == VT_BOOL)
6619 r |= VT_LVAL_BYTE;
6620 else if (bt == VT_SHORT)
6621 r |= VT_LVAL_SHORT;
6622 else
6623 return r;
6624 if (t & VT_UNSIGNED)
6625 r |= VT_LVAL_UNSIGNED;
6626 return r;
6629 /* indirection with full error checking and bound check */
6630 static void indir(void)
6632 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6633 expect("pointer");
6634 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6635 gv(RC_INT);
6636 vtop->type = *pointed_type(&vtop->type);
6637 /* an array is never an lvalue */
6638 if (!(vtop->type.t & VT_ARRAY)) {
6639 vtop->r |= lvalue_type(vtop->type.t);
6640 /* if bound checking, the referenced pointer must be checked */
6641 if (do_bounds_check)
6642 vtop->r |= VT_MUSTBOUND;
6646 /* pass a parameter to a function and do type checking and casting */
6647 static void gfunc_param_typed(Sym *func, Sym *arg)
6649 int func_type;
6650 CType type;
6652 func_type = func->c;
6653 if (func_type == FUNC_OLD ||
6654 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6655 /* default casting : only need to convert float to double */
6656 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6657 type.t = VT_DOUBLE;
6658 gen_cast(&type);
6660 } else if (arg == NULL) {
6661 error("too many arguments to function");
6662 } else {
6663 type = arg->type;
6664 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6665 gen_assign_cast(&type);
6669 /* parse an expression of the form '(type)' or '(expr)' and return its
6670 type */
6671 static void parse_expr_type(CType *type)
6673 int n;
6674 AttributeDef ad;
6676 skip('(');
6677 if (parse_btype(type, &ad)) {
6678 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6679 } else {
6680 expr_type(type);
6682 skip(')');
6685 static void parse_type(CType *type)
6687 AttributeDef ad;
6688 int n;
6690 if (!parse_btype(type, &ad)) {
6691 expect("type");
6693 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6696 static void vpush_tokc(int t)
6698 CType type;
6699 type.t = t;
6700 vsetc(&type, VT_CONST, &tokc);
6703 static void unary(void)
6705 int n, t, align, size, r;
6706 CType type;
6707 Sym *s;
6708 AttributeDef ad;
6710 /* XXX: GCC 2.95.3 does not generate a table although it should be
6711 better here */
6712 tok_next:
6713 switch(tok) {
6714 case TOK_EXTENSION:
6715 next();
6716 goto tok_next;
6717 case TOK_CINT:
6718 case TOK_CCHAR:
6719 case TOK_LCHAR:
6720 vpushi(tokc.i);
6721 next();
6722 break;
6723 case TOK_CUINT:
6724 vpush_tokc(VT_INT | VT_UNSIGNED);
6725 next();
6726 break;
6727 case TOK_CLLONG:
6728 vpush_tokc(VT_LLONG);
6729 next();
6730 break;
6731 case TOK_CULLONG:
6732 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6733 next();
6734 break;
6735 case TOK_CFLOAT:
6736 vpush_tokc(VT_FLOAT);
6737 next();
6738 break;
6739 case TOK_CDOUBLE:
6740 vpush_tokc(VT_DOUBLE);
6741 next();
6742 break;
6743 case TOK_CLDOUBLE:
6744 vpush_tokc(VT_LDOUBLE);
6745 next();
6746 break;
6747 case TOK___FUNCTION__:
6748 if (!gnu_ext)
6749 goto tok_identifier;
6750 /* fall thru */
6751 case TOK___FUNC__:
6753 void *ptr;
6754 int len;
6755 /* special function name identifier */
6756 len = strlen(funcname) + 1;
6757 /* generate char[len] type */
6758 type.t = VT_BYTE;
6759 mk_pointer(&type);
6760 type.t |= VT_ARRAY;
6761 type.ref->c = len;
6762 vpush_ref(&type, data_section, data_section->data_offset, len);
6763 ptr = section_ptr_add(data_section, len);
6764 memcpy(ptr, funcname, len);
6765 next();
6767 break;
6768 case TOK_LSTR:
6769 t = VT_INT;
6770 goto str_init;
6771 case TOK_STR:
6772 /* string parsing */
6773 t = VT_BYTE;
6774 str_init:
6775 if (tcc_state->warn_write_strings)
6776 t |= VT_CONSTANT;
6777 type.t = t;
6778 mk_pointer(&type);
6779 type.t |= VT_ARRAY;
6780 memset(&ad, 0, sizeof(AttributeDef));
6781 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6782 break;
6783 case '(':
6784 next();
6785 /* cast ? */
6786 if (parse_btype(&type, &ad)) {
6787 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6788 skip(')');
6789 /* check ISOC99 compound literal */
6790 if (tok == '{') {
6791 /* data is allocated locally by default */
6792 if (global_expr)
6793 r = VT_CONST;
6794 else
6795 r = VT_LOCAL;
6796 /* all except arrays are lvalues */
6797 if (!(type.t & VT_ARRAY))
6798 r |= lvalue_type(type.t);
6799 memset(&ad, 0, sizeof(AttributeDef));
6800 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6801 } else {
6802 unary();
6803 gen_cast(&type);
6805 } else if (tok == '{') {
6806 /* save all registers */
6807 save_regs(0);
6808 /* statement expression : we do not accept break/continue
6809 inside as GCC does */
6810 block(NULL, NULL, NULL, NULL, 0, 1);
6811 skip(')');
6812 } else {
6813 gexpr();
6814 skip(')');
6816 break;
6817 case '*':
6818 next();
6819 unary();
6820 indir();
6821 break;
6822 case '&':
6823 next();
6824 unary();
6825 /* functions names must be treated as function pointers,
6826 except for unary '&' and sizeof. Since we consider that
6827 functions are not lvalues, we only have to handle it
6828 there and in function calls. */
6829 /* arrays can also be used although they are not lvalues */
6830 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6831 !(vtop->type.t & VT_ARRAY))
6832 test_lvalue();
6833 mk_pointer(&vtop->type);
6834 gaddrof();
6835 break;
6836 case '!':
6837 next();
6838 unary();
6839 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6840 vtop->c.i = !vtop->c.i;
6841 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6842 vtop->c.i = vtop->c.i ^ 1;
6843 else
6844 vseti(VT_JMP, gtst(1, 0));
6845 break;
6846 case '~':
6847 next();
6848 unary();
6849 vpushi(-1);
6850 gen_op('^');
6851 break;
6852 case '+':
6853 next();
6854 /* in order to force cast, we add zero */
6855 unary();
6856 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6857 error("pointer not accepted for unary plus");
6858 vpushi(0);
6859 gen_op('+');
6860 break;
6861 case TOK_SIZEOF:
6862 case TOK_ALIGNOF1:
6863 case TOK_ALIGNOF2:
6864 t = tok;
6865 next();
6866 if (tok == '(') {
6867 parse_expr_type(&type);
6868 } else {
6869 unary_type(&type);
6871 size = type_size(&type, &align);
6872 if (t == TOK_SIZEOF) {
6873 if (size < 0)
6874 error("sizeof applied to an incomplete type");
6875 vpushi(size);
6876 } else {
6877 vpushi(align);
6879 break;
6881 case TOK_builtin_types_compatible_p:
6883 CType type1, type2;
6884 next();
6885 skip('(');
6886 parse_type(&type1);
6887 skip(',');
6888 parse_type(&type2);
6889 skip(')');
6890 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6891 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6892 vpushi(is_compatible_types(&type1, &type2));
6894 break;
6895 case TOK_builtin_constant_p:
6897 int saved_nocode_wanted, res;
6898 next();
6899 skip('(');
6900 saved_nocode_wanted = nocode_wanted;
6901 nocode_wanted = 1;
6902 gexpr();
6903 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6904 vpop();
6905 nocode_wanted = saved_nocode_wanted;
6906 skip(')');
6907 vpushi(res);
6909 break;
6910 case TOK_INC:
6911 case TOK_DEC:
6912 t = tok;
6913 next();
6914 unary();
6915 inc(0, t);
6916 break;
6917 case '-':
6918 next();
6919 vpushi(0);
6920 unary();
6921 gen_op('-');
6922 break;
6923 case TOK_LAND:
6924 if (!gnu_ext)
6925 goto tok_identifier;
6926 next();
6927 /* allow to take the address of a label */
6928 if (tok < TOK_UIDENT)
6929 expect("label identifier");
6930 s = label_find(tok);
6931 if (!s) {
6932 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6933 } else {
6934 if (s->r == LABEL_DECLARED)
6935 s->r = LABEL_FORWARD;
6937 if (!s->type.t) {
6938 s->type.t = VT_VOID;
6939 mk_pointer(&s->type);
6940 s->type.t |= VT_STATIC;
6942 vset(&s->type, VT_CONST | VT_SYM, 0);
6943 vtop->sym = s;
6944 next();
6945 break;
6946 default:
6947 tok_identifier:
6948 t = tok;
6949 next();
6950 if (t < TOK_UIDENT)
6951 expect("identifier");
6952 s = sym_find(t);
6953 if (!s) {
6954 if (tok != '(')
6955 error("'%s' undeclared", get_tok_str(t, NULL));
6956 /* for simple function calls, we tolerate undeclared
6957 external reference to int() function */
6958 if (tcc_state->warn_implicit_function_declaration)
6959 warning("implicit declaration of function '%s'",
6960 get_tok_str(t, NULL));
6961 s = external_global_sym(t, &func_old_type, 0);
6963 vset(&s->type, s->r, s->c);
6964 /* if forward reference, we must point to s */
6965 if (vtop->r & VT_SYM) {
6966 vtop->sym = s;
6967 vtop->c.ul = 0;
6969 break;
6972 /* post operations */
6973 while (1) {
6974 if (tok == TOK_INC || tok == TOK_DEC) {
6975 inc(1, tok);
6976 next();
6977 } else if (tok == '.' || tok == TOK_ARROW) {
6978 /* field */
6979 if (tok == TOK_ARROW)
6980 indir();
6981 test_lvalue();
6982 gaddrof();
6983 next();
6984 /* expect pointer on structure */
6985 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6986 expect("struct or union");
6987 s = vtop->type.ref;
6988 /* find field */
6989 tok |= SYM_FIELD;
6990 while ((s = s->next) != NULL) {
6991 if (s->v == tok)
6992 break;
6994 if (!s)
6995 error("field not found");
6996 /* add field offset to pointer */
6997 vtop->type = char_pointer_type; /* change type to 'char *' */
6998 vpushi(s->c);
6999 gen_op('+');
7000 /* change type to field type, and set to lvalue */
7001 vtop->type = s->type;
7002 /* an array is never an lvalue */
7003 if (!(vtop->type.t & VT_ARRAY)) {
7004 vtop->r |= lvalue_type(vtop->type.t);
7005 /* if bound checking, the referenced pointer must be checked */
7006 if (do_bounds_check)
7007 vtop->r |= VT_MUSTBOUND;
7009 next();
7010 } else if (tok == '[') {
7011 next();
7012 gexpr();
7013 gen_op('+');
7014 indir();
7015 skip(']');
7016 } else if (tok == '(') {
7017 SValue ret;
7018 Sym *sa;
7019 int nb_args;
7021 /* function call */
7022 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7023 /* pointer test (no array accepted) */
7024 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7025 vtop->type = *pointed_type(&vtop->type);
7026 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7027 goto error_func;
7028 } else {
7029 error_func:
7030 expect("function pointer");
7032 } else {
7033 vtop->r &= ~VT_LVAL; /* no lvalue */
7035 /* get return type */
7036 s = vtop->type.ref;
7037 next();
7038 sa = s->next; /* first parameter */
7039 nb_args = 0;
7040 /* compute first implicit argument if a structure is returned */
7041 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7042 /* get some space for the returned structure */
7043 size = type_size(&s->type, &align);
7044 loc = (loc - size) & -align;
7045 ret.type = s->type;
7046 ret.r = VT_LOCAL | VT_LVAL;
7047 /* pass it as 'int' to avoid structure arg passing
7048 problems */
7049 vseti(VT_LOCAL, loc);
7050 ret.c = vtop->c;
7051 nb_args++;
7052 } else {
7053 ret.type = s->type;
7054 ret.r2 = VT_CONST;
7055 /* return in register */
7056 if (is_float(ret.type.t)) {
7057 ret.r = REG_FRET;
7058 } else {
7059 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7060 ret.r2 = REG_LRET;
7061 ret.r = REG_IRET;
7063 ret.c.i = 0;
7065 if (tok != ')') {
7066 for(;;) {
7067 expr_eq();
7068 gfunc_param_typed(s, sa);
7069 nb_args++;
7070 if (sa)
7071 sa = sa->next;
7072 if (tok == ')')
7073 break;
7074 skip(',');
7077 if (sa)
7078 error("too few arguments to function");
7079 skip(')');
7080 if (!nocode_wanted) {
7081 gfunc_call(nb_args);
7082 } else {
7083 vtop -= (nb_args + 1);
7085 /* return value */
7086 vsetc(&ret.type, ret.r, &ret.c);
7087 vtop->r2 = ret.r2;
7088 } else {
7089 break;
7094 static void uneq(void)
7096 int t;
7098 unary();
7099 if (tok == '=' ||
7100 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7101 tok == TOK_A_XOR || tok == TOK_A_OR ||
7102 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7103 test_lvalue();
7104 t = tok;
7105 next();
7106 if (t == '=') {
7107 expr_eq();
7108 } else {
7109 vdup();
7110 expr_eq();
7111 gen_op(t & 0x7f);
7113 vstore();
7117 static void expr_prod(void)
7119 int t;
7121 uneq();
7122 while (tok == '*' || tok == '/' || tok == '%') {
7123 t = tok;
7124 next();
7125 uneq();
7126 gen_op(t);
7130 static void expr_sum(void)
7132 int t;
7134 expr_prod();
7135 while (tok == '+' || tok == '-') {
7136 t = tok;
7137 next();
7138 expr_prod();
7139 gen_op(t);
7143 static void expr_shift(void)
7145 int t;
7147 expr_sum();
7148 while (tok == TOK_SHL || tok == TOK_SAR) {
7149 t = tok;
7150 next();
7151 expr_sum();
7152 gen_op(t);
7156 static void expr_cmp(void)
7158 int t;
7160 expr_shift();
7161 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7162 tok == TOK_ULT || tok == TOK_UGE) {
7163 t = tok;
7164 next();
7165 expr_shift();
7166 gen_op(t);
7170 static void expr_cmpeq(void)
7172 int t;
7174 expr_cmp();
7175 while (tok == TOK_EQ || tok == TOK_NE) {
7176 t = tok;
7177 next();
7178 expr_cmp();
7179 gen_op(t);
7183 static void expr_and(void)
7185 expr_cmpeq();
7186 while (tok == '&') {
7187 next();
7188 expr_cmpeq();
7189 gen_op('&');
7193 static void expr_xor(void)
7195 expr_and();
7196 while (tok == '^') {
7197 next();
7198 expr_and();
7199 gen_op('^');
7203 static void expr_or(void)
7205 expr_xor();
7206 while (tok == '|') {
7207 next();
7208 expr_xor();
7209 gen_op('|');
7213 /* XXX: fix this mess */
7214 static void expr_land_const(void)
7216 expr_or();
7217 while (tok == TOK_LAND) {
7218 next();
7219 expr_or();
7220 gen_op(TOK_LAND);
7224 /* XXX: fix this mess */
7225 static void expr_lor_const(void)
7227 expr_land_const();
7228 while (tok == TOK_LOR) {
7229 next();
7230 expr_land_const();
7231 gen_op(TOK_LOR);
7235 /* only used if non constant */
7236 static void expr_land(void)
7238 int t;
7240 expr_or();
7241 if (tok == TOK_LAND) {
7242 t = 0;
7243 for(;;) {
7244 t = gtst(1, t);
7245 if (tok != TOK_LAND) {
7246 vseti(VT_JMPI, t);
7247 break;
7249 next();
7250 expr_or();
7255 static void expr_lor(void)
7257 int t;
7259 expr_land();
7260 if (tok == TOK_LOR) {
7261 t = 0;
7262 for(;;) {
7263 t = gtst(0, t);
7264 if (tok != TOK_LOR) {
7265 vseti(VT_JMP, t);
7266 break;
7268 next();
7269 expr_land();
7274 /* XXX: better constant handling */
7275 static void expr_eq(void)
7277 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7278 SValue sv;
7279 CType type, type1, type2;
7281 if (const_wanted) {
7282 int c1, c;
7283 expr_lor_const();
7284 if (tok == '?') {
7285 c = vtop->c.i;
7286 vpop();
7287 next();
7288 if (tok == ':' && gnu_ext) {
7289 c1 = c;
7290 } else {
7291 gexpr();
7292 c1 = vtop->c.i;
7293 vpop();
7295 skip(':');
7296 expr_eq();
7297 if (c)
7298 vtop->c.i = c1;
7300 } else {
7301 expr_lor();
7302 if (tok == '?') {
7303 next();
7304 if (vtop != vstack) {
7305 /* needed to avoid having different registers saved in
7306 each branch */
7307 if (is_float(vtop->type.t))
7308 rc = RC_FLOAT;
7309 else
7310 rc = RC_INT;
7311 gv(rc);
7312 save_regs(1);
7314 if (tok == ':' && gnu_ext) {
7315 gv_dup();
7316 tt = gtst(1, 0);
7317 } else {
7318 tt = gtst(1, 0);
7319 gexpr();
7321 type1 = vtop->type;
7322 sv = *vtop; /* save value to handle it later */
7323 vtop--; /* no vpop so that FP stack is not flushed */
7324 skip(':');
7325 u = gjmp(0);
7326 gsym(tt);
7327 expr_eq();
7328 type2 = vtop->type;
7330 t1 = type1.t;
7331 bt1 = t1 & VT_BTYPE;
7332 t2 = type2.t;
7333 bt2 = t2 & VT_BTYPE;
7334 /* cast operands to correct type according to ISOC rules */
7335 if (is_float(bt1) || is_float(bt2)) {
7336 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7337 type.t = VT_LDOUBLE;
7338 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7339 type.t = VT_DOUBLE;
7340 } else {
7341 type.t = VT_FLOAT;
7343 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7344 /* cast to biggest op */
7345 type.t = VT_LLONG;
7346 /* convert to unsigned if it does not fit in a long long */
7347 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7348 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7349 type.t |= VT_UNSIGNED;
7350 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7351 /* XXX: test pointer compatibility */
7352 type = type1;
7353 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7354 /* XXX: test structure compatibility */
7355 type = type1;
7356 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7357 /* NOTE: as an extension, we accept void on only one side */
7358 type.t = VT_VOID;
7359 } else {
7360 /* integer operations */
7361 type.t = VT_INT;
7362 /* convert to unsigned if it does not fit in an integer */
7363 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7364 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7365 type.t |= VT_UNSIGNED;
7368 /* now we convert second operand */
7369 gen_cast(&type);
7370 rc = RC_INT;
7371 if (is_float(type.t)) {
7372 rc = RC_FLOAT;
7373 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7374 /* for long longs, we use fixed registers to avoid having
7375 to handle a complicated move */
7376 rc = RC_IRET;
7379 r2 = gv(rc);
7380 /* this is horrible, but we must also convert first
7381 operand */
7382 tt = gjmp(0);
7383 gsym(u);
7384 /* put again first value and cast it */
7385 *vtop = sv;
7386 gen_cast(&type);
7387 r1 = gv(rc);
7388 move_reg(r2, r1);
7389 vtop->r = r2;
7390 gsym(tt);
7395 static void gexpr(void)
7397 while (1) {
7398 expr_eq();
7399 if (tok != ',')
7400 break;
7401 vpop();
7402 next();
7406 /* parse an expression and return its type without any side effect. */
7407 static void expr_type(CType *type)
7409 int saved_nocode_wanted;
7411 saved_nocode_wanted = nocode_wanted;
7412 nocode_wanted = 1;
7413 gexpr();
7414 *type = vtop->type;
7415 vpop();
7416 nocode_wanted = saved_nocode_wanted;
7419 /* parse a unary expression and return its type without any side
7420 effect. */
7421 static void unary_type(CType *type)
7423 int a;
7425 a = nocode_wanted;
7426 nocode_wanted = 1;
7427 unary();
7428 *type = vtop->type;
7429 vpop();
7430 nocode_wanted = a;
7433 /* parse a constant expression and return value in vtop. */
7434 static void expr_const1(void)
7436 int a;
7437 a = const_wanted;
7438 const_wanted = 1;
7439 expr_eq();
7440 const_wanted = a;
7443 /* parse an integer constant and return its value. */
7444 static int expr_const(void)
7446 int c;
7447 expr_const1();
7448 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7449 expect("constant expression");
7450 c = vtop->c.i;
7451 vpop();
7452 return c;
7455 /* return the label token if current token is a label, otherwise
7456 return zero */
7457 static int is_label(void)
7459 int last_tok;
7461 /* fast test first */
7462 if (tok < TOK_UIDENT)
7463 return 0;
7464 /* no need to save tokc because tok is an identifier */
7465 last_tok = tok;
7466 next();
7467 if (tok == ':') {
7468 next();
7469 return last_tok;
7470 } else {
7471 unget_tok(last_tok);
7472 return 0;
7476 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7477 int case_reg, int is_expr)
7479 int a, b, c, d;
7480 Sym *s;
7482 /* generate line number info */
7483 if (do_debug &&
7484 (last_line_num != file->line_num || last_ind != ind)) {
7485 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7486 last_ind = ind;
7487 last_line_num = file->line_num;
7490 if (is_expr) {
7491 /* default return value is (void) */
7492 vpushi(0);
7493 vtop->type.t = VT_VOID;
7496 if (tok == TOK_IF) {
7497 /* if test */
7498 next();
7499 skip('(');
7500 gexpr();
7501 skip(')');
7502 a = gtst(1, 0);
7503 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7504 c = tok;
7505 if (c == TOK_ELSE) {
7506 next();
7507 d = gjmp(0);
7508 gsym(a);
7509 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7510 gsym(d); /* patch else jmp */
7511 } else
7512 gsym(a);
7513 } else if (tok == TOK_WHILE) {
7514 next();
7515 d = ind;
7516 skip('(');
7517 gexpr();
7518 skip(')');
7519 a = gtst(1, 0);
7520 b = 0;
7521 block(&a, &b, case_sym, def_sym, case_reg, 0);
7522 gjmp_addr(d);
7523 gsym(a);
7524 gsym_addr(b, d);
7525 } else if (tok == '{') {
7526 Sym *llabel;
7528 next();
7529 /* record local declaration stack position */
7530 s = local_stack;
7531 llabel = local_label_stack;
7532 /* handle local labels declarations */
7533 if (tok == TOK_LABEL) {
7534 next();
7535 for(;;) {
7536 if (tok < TOK_UIDENT)
7537 expect("label identifier");
7538 label_push(&local_label_stack, tok, LABEL_DECLARED);
7539 next();
7540 if (tok == ',') {
7541 next();
7542 } else {
7543 skip(';');
7544 break;
7548 while (tok != '}') {
7549 decl(VT_LOCAL);
7550 if (tok != '}') {
7551 if (is_expr)
7552 vpop();
7553 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7556 /* pop locally defined labels */
7557 label_pop(&local_label_stack, llabel);
7558 /* pop locally defined symbols */
7559 sym_pop(&local_stack, s);
7560 next();
7561 } else if (tok == TOK_RETURN) {
7562 next();
7563 if (tok != ';') {
7564 gexpr();
7565 gen_assign_cast(&func_vt);
7566 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7567 CType type;
7568 /* if returning structure, must copy it to implicit
7569 first pointer arg location */
7570 type = func_vt;
7571 mk_pointer(&type);
7572 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7573 indir();
7574 vswap();
7575 /* copy structure value to pointer */
7576 vstore();
7577 } else if (is_float(func_vt.t)) {
7578 gv(RC_FRET);
7579 } else {
7580 gv(RC_IRET);
7582 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7584 skip(';');
7585 rsym = gjmp(rsym); /* jmp */
7586 } else if (tok == TOK_BREAK) {
7587 /* compute jump */
7588 if (!bsym)
7589 error("cannot break");
7590 *bsym = gjmp(*bsym);
7591 next();
7592 skip(';');
7593 } else if (tok == TOK_CONTINUE) {
7594 /* compute jump */
7595 if (!csym)
7596 error("cannot continue");
7597 *csym = gjmp(*csym);
7598 next();
7599 skip(';');
7600 } else if (tok == TOK_FOR) {
7601 int e;
7602 next();
7603 skip('(');
7604 if (tok != ';') {
7605 gexpr();
7606 vpop();
7608 skip(';');
7609 d = ind;
7610 c = ind;
7611 a = 0;
7612 b = 0;
7613 if (tok != ';') {
7614 gexpr();
7615 a = gtst(1, 0);
7617 skip(';');
7618 if (tok != ')') {
7619 e = gjmp(0);
7620 c = ind;
7621 gexpr();
7622 vpop();
7623 gjmp_addr(d);
7624 gsym(e);
7626 skip(')');
7627 block(&a, &b, case_sym, def_sym, case_reg, 0);
7628 gjmp_addr(c);
7629 gsym(a);
7630 gsym_addr(b, c);
7631 } else
7632 if (tok == TOK_DO) {
7633 next();
7634 a = 0;
7635 b = 0;
7636 d = ind;
7637 block(&a, &b, case_sym, def_sym, case_reg, 0);
7638 skip(TOK_WHILE);
7639 skip('(');
7640 gsym(b);
7641 gexpr();
7642 c = gtst(0, 0);
7643 gsym_addr(c, d);
7644 skip(')');
7645 gsym(a);
7646 skip(';');
7647 } else
7648 if (tok == TOK_SWITCH) {
7649 next();
7650 skip('(');
7651 gexpr();
7652 /* XXX: other types than integer */
7653 case_reg = gv(RC_INT);
7654 vpop();
7655 skip(')');
7656 a = 0;
7657 b = gjmp(0); /* jump to first case */
7658 c = 0;
7659 block(&a, csym, &b, &c, case_reg, 0);
7660 /* if no default, jmp after switch */
7661 if (c == 0)
7662 c = ind;
7663 /* default label */
7664 gsym_addr(b, c);
7665 /* break label */
7666 gsym(a);
7667 } else
7668 if (tok == TOK_CASE) {
7669 int v1, v2;
7670 if (!case_sym)
7671 expect("switch");
7672 next();
7673 v1 = expr_const();
7674 v2 = v1;
7675 if (gnu_ext && tok == TOK_DOTS) {
7676 next();
7677 v2 = expr_const();
7678 if (v2 < v1)
7679 warning("empty case range");
7681 /* since a case is like a label, we must skip it with a jmp */
7682 b = gjmp(0);
7683 gsym(*case_sym);
7684 vseti(case_reg, 0);
7685 vpushi(v1);
7686 if (v1 == v2) {
7687 gen_op(TOK_EQ);
7688 *case_sym = gtst(1, 0);
7689 } else {
7690 gen_op(TOK_GE);
7691 *case_sym = gtst(1, 0);
7692 vseti(case_reg, 0);
7693 vpushi(v2);
7694 gen_op(TOK_LE);
7695 *case_sym = gtst(1, *case_sym);
7697 gsym(b);
7698 skip(':');
7699 is_expr = 0;
7700 goto block_after_label;
7701 } else
7702 if (tok == TOK_DEFAULT) {
7703 next();
7704 skip(':');
7705 if (!def_sym)
7706 expect("switch");
7707 if (*def_sym)
7708 error("too many 'default'");
7709 *def_sym = ind;
7710 is_expr = 0;
7711 goto block_after_label;
7712 } else
7713 if (tok == TOK_GOTO) {
7714 next();
7715 if (tok == '*' && gnu_ext) {
7716 /* computed goto */
7717 next();
7718 gexpr();
7719 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7720 expect("pointer");
7721 ggoto();
7722 } else if (tok >= TOK_UIDENT) {
7723 s = label_find(tok);
7724 /* put forward definition if needed */
7725 if (!s) {
7726 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7727 } else {
7728 if (s->r == LABEL_DECLARED)
7729 s->r = LABEL_FORWARD;
7731 /* label already defined */
7732 if (s->r & LABEL_FORWARD)
7733 s->next = (void *)gjmp((long)s->next);
7734 else
7735 gjmp_addr((long)s->next);
7736 next();
7737 } else {
7738 expect("label identifier");
7740 skip(';');
7741 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7742 asm_instr();
7743 } else {
7744 b = is_label();
7745 if (b) {
7746 /* label case */
7747 s = label_find(b);
7748 if (s) {
7749 if (s->r == LABEL_DEFINED)
7750 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7751 gsym((long)s->next);
7752 s->r = LABEL_DEFINED;
7753 } else {
7754 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7756 s->next = (void *)ind;
7757 /* we accept this, but it is a mistake */
7758 block_after_label:
7759 if (tok == '}') {
7760 warning("deprecated use of label at end of compound statement");
7761 } else {
7762 if (is_expr)
7763 vpop();
7764 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7766 } else {
7767 /* expression case */
7768 if (tok != ';') {
7769 if (is_expr) {
7770 vpop();
7771 gexpr();
7772 } else {
7773 gexpr();
7774 vpop();
7777 skip(';');
7782 /* t is the array or struct type. c is the array or struct
7783 address. cur_index/cur_field is the pointer to the current
7784 value. 'size_only' is true if only size info is needed (only used
7785 in arrays) */
7786 static void decl_designator(CType *type, Section *sec, unsigned long c,
7787 int *cur_index, Sym **cur_field,
7788 int size_only)
7790 Sym *s, *f;
7791 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7792 CType type1;
7794 notfirst = 0;
7795 elem_size = 0;
7796 nb_elems = 1;
7797 if (gnu_ext && (l = is_label()) != 0)
7798 goto struct_field;
7799 while (tok == '[' || tok == '.') {
7800 if (tok == '[') {
7801 if (!(type->t & VT_ARRAY))
7802 expect("array type");
7803 s = type->ref;
7804 next();
7805 index = expr_const();
7806 if (index < 0 || (s->c >= 0 && index >= s->c))
7807 expect("invalid index");
7808 if (tok == TOK_DOTS && gnu_ext) {
7809 next();
7810 index_last = expr_const();
7811 if (index_last < 0 ||
7812 (s->c >= 0 && index_last >= s->c) ||
7813 index_last < index)
7814 expect("invalid index");
7815 } else {
7816 index_last = index;
7818 skip(']');
7819 if (!notfirst)
7820 *cur_index = index_last;
7821 type = pointed_type(type);
7822 elem_size = type_size(type, &align);
7823 c += index * elem_size;
7824 /* NOTE: we only support ranges for last designator */
7825 nb_elems = index_last - index + 1;
7826 if (nb_elems != 1) {
7827 notfirst = 1;
7828 break;
7830 } else {
7831 next();
7832 l = tok;
7833 next();
7834 struct_field:
7835 if ((type->t & VT_BTYPE) != VT_STRUCT)
7836 expect("struct/union type");
7837 s = type->ref;
7838 l |= SYM_FIELD;
7839 f = s->next;
7840 while (f) {
7841 if (f->v == l)
7842 break;
7843 f = f->next;
7845 if (!f)
7846 expect("field");
7847 if (!notfirst)
7848 *cur_field = f;
7849 /* XXX: fix this mess by using explicit storage field */
7850 type1 = f->type;
7851 type1.t |= (type->t & ~VT_TYPE);
7852 type = &type1;
7853 c += f->c;
7855 notfirst = 1;
7857 if (notfirst) {
7858 if (tok == '=') {
7859 next();
7860 } else {
7861 if (!gnu_ext)
7862 expect("=");
7864 } else {
7865 if (type->t & VT_ARRAY) {
7866 index = *cur_index;
7867 type = pointed_type(type);
7868 c += index * type_size(type, &align);
7869 } else {
7870 f = *cur_field;
7871 if (!f)
7872 error("too many field init");
7873 /* XXX: fix this mess by using explicit storage field */
7874 type1 = f->type;
7875 type1.t |= (type->t & ~VT_TYPE);
7876 type = &type1;
7877 c += f->c;
7880 decl_initializer(type, sec, c, 0, size_only);
7882 /* XXX: make it more general */
7883 if (!size_only && nb_elems > 1) {
7884 unsigned long c_end;
7885 uint8_t *src, *dst;
7886 int i;
7888 if (!sec)
7889 error("range init not supported yet for dynamic storage");
7890 c_end = c + nb_elems * elem_size;
7891 if (c_end > sec->data_allocated)
7892 section_realloc(sec, c_end);
7893 src = sec->data + c;
7894 dst = src;
7895 for(i = 1; i < nb_elems; i++) {
7896 dst += elem_size;
7897 memcpy(dst, src, elem_size);
7902 #define EXPR_VAL 0
7903 #define EXPR_CONST 1
7904 #define EXPR_ANY 2
7906 /* store a value or an expression directly in global data or in local array */
7907 static void init_putv(CType *type, Section *sec, unsigned long c,
7908 int v, int expr_type)
7910 int saved_global_expr, bt, bit_pos, bit_size;
7911 void *ptr;
7912 unsigned long long bit_mask;
7913 CType dtype;
7915 switch(expr_type) {
7916 case EXPR_VAL:
7917 vpushi(v);
7918 break;
7919 case EXPR_CONST:
7920 /* compound literals must be allocated globally in this case */
7921 saved_global_expr = global_expr;
7922 global_expr = 1;
7923 expr_const1();
7924 global_expr = saved_global_expr;
7925 /* NOTE: symbols are accepted */
7926 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7927 error("initializer element is not constant");
7928 break;
7929 case EXPR_ANY:
7930 expr_eq();
7931 break;
7934 dtype = *type;
7935 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7937 if (sec) {
7938 /* XXX: not portable */
7939 /* XXX: generate error if incorrect relocation */
7940 gen_assign_cast(&dtype);
7941 bt = type->t & VT_BTYPE;
7942 ptr = sec->data + c;
7943 /* XXX: make code faster ? */
7944 if (!(type->t & VT_BITFIELD)) {
7945 bit_pos = 0;
7946 bit_size = 32;
7947 bit_mask = -1LL;
7948 } else {
7949 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7950 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7951 bit_mask = (1LL << bit_size) - 1;
7953 if ((vtop->r & VT_SYM) &&
7954 (bt == VT_BYTE ||
7955 bt == VT_SHORT ||
7956 bt == VT_DOUBLE ||
7957 bt == VT_LDOUBLE ||
7958 bt == VT_LLONG ||
7959 (bt == VT_INT && bit_size != 32)))
7960 error("initializer element is not computable at load time");
7961 switch(bt) {
7962 case VT_BYTE:
7963 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7964 break;
7965 case VT_SHORT:
7966 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7967 break;
7968 case VT_DOUBLE:
7969 *(double *)ptr = vtop->c.d;
7970 break;
7971 case VT_LDOUBLE:
7972 *(long double *)ptr = vtop->c.ld;
7973 break;
7974 case VT_LLONG:
7975 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7976 break;
7977 default:
7978 if (vtop->r & VT_SYM) {
7979 greloc(sec, vtop->sym, c, R_DATA_32);
7981 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7982 break;
7984 vtop--;
7985 } else {
7986 vset(&dtype, VT_LOCAL, c);
7987 vswap();
7988 vstore();
7989 vpop();
7993 /* put zeros for variable based init */
7994 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7996 if (sec) {
7997 /* nothing to do because globals are already set to zero */
7998 } else {
7999 vpush_global_sym(&func_old_type, TOK_memset);
8000 vseti(VT_LOCAL, c);
8001 vpushi(0);
8002 vpushi(size);
8003 gfunc_call(3);
8007 /* 't' contains the type and storage info. 'c' is the offset of the
8008 object in section 'sec'. If 'sec' is NULL, it means stack based
8009 allocation. 'first' is true if array '{' must be read (multi
8010 dimension implicit array init handling). 'size_only' is true if
8011 size only evaluation is wanted (only for arrays). */
8012 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8013 int first, int size_only)
8015 int index, array_length, n, no_oblock, nb, parlevel, i;
8016 int size1, align1, expr_type;
8017 Sym *s, *f;
8018 CType *t1;
8020 if (type->t & VT_ARRAY) {
8021 s = type->ref;
8022 n = s->c;
8023 array_length = 0;
8024 t1 = pointed_type(type);
8025 size1 = type_size(t1, &align1);
8027 no_oblock = 1;
8028 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8029 tok == '{') {
8030 skip('{');
8031 no_oblock = 0;
8034 /* only parse strings here if correct type (otherwise: handle
8035 them as ((w)char *) expressions */
8036 if ((tok == TOK_LSTR &&
8037 (t1->t & VT_BTYPE) == VT_INT) ||
8038 (tok == TOK_STR &&
8039 (t1->t & VT_BTYPE) == VT_BYTE)) {
8040 while (tok == TOK_STR || tok == TOK_LSTR) {
8041 int cstr_len, ch;
8042 CString *cstr;
8044 cstr = tokc.cstr;
8045 /* compute maximum number of chars wanted */
8046 if (tok == TOK_STR)
8047 cstr_len = cstr->size;
8048 else
8049 cstr_len = cstr->size / sizeof(int);
8050 cstr_len--;
8051 nb = cstr_len;
8052 if (n >= 0 && nb > (n - array_length))
8053 nb = n - array_length;
8054 if (!size_only) {
8055 if (cstr_len > nb)
8056 warning("initializer-string for array is too long");
8057 /* in order to go faster for common case (char
8058 string in global variable, we handle it
8059 specifically */
8060 if (sec && tok == TOK_STR && size1 == 1) {
8061 memcpy(sec->data + c + array_length, cstr->data, nb);
8062 } else {
8063 for(i=0;i<nb;i++) {
8064 if (tok == TOK_STR)
8065 ch = ((unsigned char *)cstr->data)[i];
8066 else
8067 ch = ((int *)cstr->data)[i];
8068 init_putv(t1, sec, c + (array_length + i) * size1,
8069 ch, EXPR_VAL);
8073 array_length += nb;
8074 next();
8076 /* only add trailing zero if enough storage (no
8077 warning in this case since it is standard) */
8078 if (n < 0 || array_length < n) {
8079 if (!size_only) {
8080 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8082 array_length++;
8084 } else {
8085 index = 0;
8086 while (tok != '}') {
8087 decl_designator(type, sec, c, &index, NULL, size_only);
8088 if (n >= 0 && index >= n)
8089 error("index too large");
8090 /* must put zero in holes (note that doing it that way
8091 ensures that it even works with designators) */
8092 if (!size_only && array_length < index) {
8093 init_putz(t1, sec, c + array_length * size1,
8094 (index - array_length) * size1);
8096 index++;
8097 if (index > array_length)
8098 array_length = index;
8099 /* special test for multi dimensional arrays (may not
8100 be strictly correct if designators are used at the
8101 same time) */
8102 if (index >= n && no_oblock)
8103 break;
8104 if (tok == '}')
8105 break;
8106 skip(',');
8109 if (!no_oblock)
8110 skip('}');
8111 /* put zeros at the end */
8112 if (!size_only && n >= 0 && array_length < n) {
8113 init_putz(t1, sec, c + array_length * size1,
8114 (n - array_length) * size1);
8116 /* patch type size if needed */
8117 if (n < 0)
8118 s->c = array_length;
8119 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8120 (sec || !first || tok == '{')) {
8121 int par_count;
8123 /* NOTE: the previous test is a specific case for automatic
8124 struct/union init */
8125 /* XXX: union needs only one init */
8127 /* XXX: this test is incorrect for local initializers
8128 beginning with ( without {. It would be much more difficult
8129 to do it correctly (ideally, the expression parser should
8130 be used in all cases) */
8131 par_count = 0;
8132 if (tok == '(') {
8133 AttributeDef ad1;
8134 CType type1;
8135 next();
8136 while (tok == '(') {
8137 par_count++;
8138 next();
8140 if (!parse_btype(&type1, &ad1))
8141 expect("cast");
8142 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8143 #if 0
8144 if (!is_assignable_types(type, &type1))
8145 error("invalid type for cast");
8146 #endif
8147 skip(')');
8149 no_oblock = 1;
8150 if (first || tok == '{') {
8151 skip('{');
8152 no_oblock = 0;
8154 s = type->ref;
8155 f = s->next;
8156 array_length = 0;
8157 index = 0;
8158 n = s->c;
8159 while (tok != '}') {
8160 decl_designator(type, sec, c, NULL, &f, size_only);
8161 index = f->c;
8162 if (!size_only && array_length < index) {
8163 init_putz(type, sec, c + array_length,
8164 index - array_length);
8166 index = index + type_size(&f->type, &align1);
8167 if (index > array_length)
8168 array_length = index;
8169 f = f->next;
8170 if (no_oblock && f == NULL)
8171 break;
8172 if (tok == '}')
8173 break;
8174 skip(',');
8176 /* put zeros at the end */
8177 if (!size_only && array_length < n) {
8178 init_putz(type, sec, c + array_length,
8179 n - array_length);
8181 if (!no_oblock)
8182 skip('}');
8183 while (par_count) {
8184 skip(')');
8185 par_count--;
8187 } else if (tok == '{') {
8188 next();
8189 decl_initializer(type, sec, c, first, size_only);
8190 skip('}');
8191 } else if (size_only) {
8192 /* just skip expression */
8193 parlevel = 0;
8194 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8195 tok != -1) {
8196 if (tok == '(')
8197 parlevel++;
8198 else if (tok == ')')
8199 parlevel--;
8200 next();
8202 } else {
8203 /* currently, we always use constant expression for globals
8204 (may change for scripting case) */
8205 expr_type = EXPR_CONST;
8206 if (!sec)
8207 expr_type = EXPR_ANY;
8208 init_putv(type, sec, c, 0, expr_type);
8212 /* parse an initializer for type 't' if 'has_init' is non zero, and
8213 allocate space in local or global data space ('r' is either
8214 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8215 variable 'v' of scope 'scope' is declared before initializers are
8216 parsed. If 'v' is zero, then a reference to the new object is put
8217 in the value stack. If 'has_init' is 2, a special parsing is done
8218 to handle string constants. */
8219 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8220 int has_init, int v, int scope)
8222 int size, align, addr, data_offset;
8223 int level;
8224 ParseState saved_parse_state;
8225 TokenString init_str;
8226 Section *sec;
8228 size = type_size(type, &align);
8229 /* If unknown size, we must evaluate it before
8230 evaluating initializers because
8231 initializers can generate global data too
8232 (e.g. string pointers or ISOC99 compound
8233 literals). It also simplifies local
8234 initializers handling */
8235 tok_str_new(&init_str);
8236 if (size < 0) {
8237 if (!has_init)
8238 error("unknown type size");
8239 /* get all init string */
8240 if (has_init == 2) {
8241 /* only get strings */
8242 while (tok == TOK_STR || tok == TOK_LSTR) {
8243 tok_str_add_tok(&init_str);
8244 next();
8246 } else {
8247 level = 0;
8248 while (level > 0 || (tok != ',' && tok != ';')) {
8249 if (tok < 0)
8250 error("unexpected end of file in initializer");
8251 tok_str_add_tok(&init_str);
8252 if (tok == '{')
8253 level++;
8254 else if (tok == '}') {
8255 if (level == 0)
8256 break;
8257 level--;
8259 next();
8262 tok_str_add(&init_str, -1);
8263 tok_str_add(&init_str, 0);
8265 /* compute size */
8266 save_parse_state(&saved_parse_state);
8268 macro_ptr = init_str.str;
8269 next();
8270 decl_initializer(type, NULL, 0, 1, 1);
8271 /* prepare second initializer parsing */
8272 macro_ptr = init_str.str;
8273 next();
8275 /* if still unknown size, error */
8276 size = type_size(type, &align);
8277 if (size < 0)
8278 error("unknown type size");
8280 /* take into account specified alignment if bigger */
8281 if (ad->aligned > align)
8282 align = ad->aligned;
8283 if ((r & VT_VALMASK) == VT_LOCAL) {
8284 sec = NULL;
8285 if (do_bounds_check && (type->t & VT_ARRAY))
8286 loc--;
8287 loc = (loc - size) & -align;
8288 addr = loc;
8289 /* handles bounds */
8290 /* XXX: currently, since we do only one pass, we cannot track
8291 '&' operators, so we add only arrays */
8292 if (do_bounds_check && (type->t & VT_ARRAY)) {
8293 unsigned long *bounds_ptr;
8294 /* add padding between regions */
8295 loc--;
8296 /* then add local bound info */
8297 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8298 bounds_ptr[0] = addr;
8299 bounds_ptr[1] = size;
8301 if (v) {
8302 /* local variable */
8303 sym_push(v, type, r, addr);
8304 } else {
8305 /* push local reference */
8306 vset(type, r, addr);
8308 } else {
8309 Sym *sym;
8311 sym = NULL;
8312 if (v && scope == VT_CONST) {
8313 /* see if the symbol was already defined */
8314 sym = sym_find(v);
8315 if (sym) {
8316 if (!is_compatible_types(&sym->type, type))
8317 error("incompatible types for redefinition of '%s'",
8318 get_tok_str(v, NULL));
8319 if (sym->type.t & VT_EXTERN) {
8320 /* if the variable is extern, it was not allocated */
8321 sym->type.t &= ~VT_EXTERN;
8322 } else {
8323 /* we accept several definitions of the same
8324 global variable. this is tricky, because we
8325 must play with the SHN_COMMON type of the symbol */
8326 /* XXX: should check if the variable was already
8327 initialized. It is incorrect to initialized it
8328 twice */
8329 /* no init data, we won't add more to the symbol */
8330 if (!has_init)
8331 goto no_alloc;
8336 /* allocate symbol in corresponding section */
8337 sec = ad->section;
8338 if (!sec) {
8339 if (has_init)
8340 sec = data_section;
8342 if (sec) {
8343 data_offset = sec->data_offset;
8344 data_offset = (data_offset + align - 1) & -align;
8345 addr = data_offset;
8346 /* very important to increment global pointer at this time
8347 because initializers themselves can create new initializers */
8348 data_offset += size;
8349 /* add padding if bound check */
8350 if (do_bounds_check)
8351 data_offset++;
8352 sec->data_offset = data_offset;
8353 /* allocate section space to put the data */
8354 if (sec->sh_type != SHT_NOBITS &&
8355 data_offset > sec->data_allocated)
8356 section_realloc(sec, data_offset);
8357 } else {
8358 addr = 0; /* avoid warning */
8361 if (v) {
8362 if (scope == VT_CONST) {
8363 if (!sym)
8364 goto do_def;
8365 } else {
8366 do_def:
8367 sym = sym_push(v, type, r | VT_SYM, 0);
8369 /* update symbol definition */
8370 if (sec) {
8371 put_extern_sym(sym, sec, addr, size);
8372 } else {
8373 Elf32_Sym *esym;
8374 /* put a common area */
8375 put_extern_sym(sym, NULL, align, size);
8376 /* XXX: find a nicer way */
8377 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8378 esym->st_shndx = SHN_COMMON;
8380 } else {
8381 CValue cval;
8383 /* push global reference */
8384 sym = get_sym_ref(type, sec, addr, size);
8385 cval.ul = 0;
8386 vsetc(type, VT_CONST | VT_SYM, &cval);
8387 vtop->sym = sym;
8390 /* handles bounds now because the symbol must be defined
8391 before for the relocation */
8392 if (do_bounds_check) {
8393 unsigned long *bounds_ptr;
8395 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8396 /* then add global bound info */
8397 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8398 bounds_ptr[0] = 0; /* relocated */
8399 bounds_ptr[1] = size;
8402 if (has_init) {
8403 decl_initializer(type, sec, addr, 1, 0);
8404 /* restore parse state if needed */
8405 if (init_str.str) {
8406 tok_str_free(init_str.str);
8407 restore_parse_state(&saved_parse_state);
8410 no_alloc: ;
8413 void put_func_debug(Sym *sym)
8415 char buf[512];
8417 /* stabs info */
8418 /* XXX: we put here a dummy type */
8419 snprintf(buf, sizeof(buf), "%s:%c1",
8420 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8421 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8422 cur_text_section, sym->c);
8423 last_ind = 0;
8424 last_line_num = 0;
8427 /* not finished : try to put some local vars in registers */
8428 //#define CONFIG_REG_VARS
8430 #ifdef CONFIG_REG_VARS
8431 void add_var_ref(int t)
8433 printf("%s:%d: &%s\n",
8434 file->filename, file->line_num,
8435 get_tok_str(t, NULL));
8438 /* first pass on a function with heuristic to extract variable usage
8439 and pointer references to local variables for register allocation */
8440 void analyse_function(void)
8442 int level, t;
8444 for(;;) {
8445 if (tok == -1)
8446 break;
8447 /* any symbol coming after '&' is considered as being a
8448 variable whose reference is taken. It is highly unaccurate
8449 but it is difficult to do better without a complete parse */
8450 if (tok == '&') {
8451 next();
8452 /* if '& number', then no need to examine next tokens */
8453 if (tok == TOK_CINT ||
8454 tok == TOK_CUINT ||
8455 tok == TOK_CLLONG ||
8456 tok == TOK_CULLONG) {
8457 continue;
8458 } else if (tok >= TOK_UIDENT) {
8459 /* if '& ident [' or '& ident ->', then ident address
8460 is not needed */
8461 t = tok;
8462 next();
8463 if (tok != '[' && tok != TOK_ARROW)
8464 add_var_ref(t);
8465 } else {
8466 level = 0;
8467 while (tok != '}' && tok != ';' &&
8468 !((tok == ',' || tok == ')') && level == 0)) {
8469 if (tok >= TOK_UIDENT) {
8470 add_var_ref(tok);
8471 } else if (tok == '(') {
8472 level++;
8473 } else if (tok == ')') {
8474 level--;
8476 next();
8479 } else {
8480 next();
8484 #endif
8486 /* parse an old style function declaration list */
8487 /* XXX: check multiple parameter */
8488 static void func_decl_list(Sym *func_sym)
8490 AttributeDef ad;
8491 int v;
8492 Sym *s;
8493 CType btype, type;
8495 /* parse each declaration */
8496 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8497 if (!parse_btype(&btype, &ad))
8498 expect("declaration list");
8499 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8500 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8501 tok == ';') {
8502 /* we accept no variable after */
8503 } else {
8504 for(;;) {
8505 type = btype;
8506 type_decl(&type, &ad, &v, TYPE_DIRECT);
8507 /* find parameter in function parameter list */
8508 s = func_sym->next;
8509 while (s != NULL) {
8510 if ((s->v & ~SYM_FIELD) == v)
8511 goto found;
8512 s = s->next;
8514 error("declaration for parameter '%s' but no such parameter",
8515 get_tok_str(v, NULL));
8516 found:
8517 /* check that no storage specifier except 'register' was given */
8518 if (type.t & VT_STORAGE)
8519 error("storage class specified for '%s'", get_tok_str(v, NULL));
8520 convert_parameter_type(&type);
8521 /* we can add the type (NOTE: it could be local to the function) */
8522 s->type = type;
8523 /* accept other parameters */
8524 if (tok == ',')
8525 next();
8526 else
8527 break;
8530 skip(';');
8534 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8535 static void decl(int l)
8537 int v, has_init, r;
8538 CType type, btype;
8539 Sym *sym;
8540 AttributeDef ad;
8542 while (1) {
8543 if (!parse_btype(&btype, &ad)) {
8544 /* skip redundant ';' */
8545 /* XXX: find more elegant solution */
8546 if (tok == ';') {
8547 next();
8548 continue;
8550 /* special test for old K&R protos without explicit int
8551 type. Only accepted when defining global data */
8552 if (l == VT_LOCAL || tok < TOK_DEFINE)
8553 break;
8554 btype.t = VT_INT;
8556 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8557 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8558 tok == ';') {
8559 /* we accept no variable after */
8560 next();
8561 continue;
8563 while (1) { /* iterate thru each declaration */
8564 type = btype;
8565 type_decl(&type, &ad, &v, TYPE_DIRECT);
8566 #if 0
8568 char buf[500];
8569 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8570 printf("type = '%s'\n", buf);
8572 #endif
8573 if ((type.t & VT_BTYPE) == VT_FUNC) {
8574 /* if old style function prototype, we accept a
8575 declaration list */
8576 sym = type.ref;
8577 if (sym->c == FUNC_OLD)
8578 func_decl_list(sym);
8581 if (tok == '{') {
8582 #ifdef CONFIG_REG_VARS
8583 TokenString func_str;
8584 ParseState saved_parse_state;
8585 int block_level;
8586 #endif
8588 if (l == VT_LOCAL)
8589 error("cannot use local functions");
8590 if (!(type.t & VT_FUNC))
8591 expect("function definition");
8593 /* reject abstract declarators in function definition */
8594 sym = type.ref;
8595 while ((sym = sym->next) != NULL)
8596 if (!(sym->v & ~SYM_FIELD))
8597 expect("identifier");
8599 /* XXX: cannot do better now: convert extern line to static inline */
8600 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8601 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8603 #ifdef CONFIG_REG_VARS
8604 /* parse all function code and record it */
8606 tok_str_new(&func_str);
8608 block_level = 0;
8609 for(;;) {
8610 int t;
8611 if (tok == -1)
8612 error("unexpected end of file");
8613 tok_str_add_tok(&func_str);
8614 t = tok;
8615 next();
8616 if (t == '{') {
8617 block_level++;
8618 } else if (t == '}') {
8619 block_level--;
8620 if (block_level == 0)
8621 break;
8624 tok_str_add(&func_str, -1);
8625 tok_str_add(&func_str, 0);
8627 save_parse_state(&saved_parse_state);
8629 macro_ptr = func_str.str;
8630 next();
8631 analyse_function();
8632 #endif
8634 /* compute text section */
8635 cur_text_section = ad.section;
8636 if (!cur_text_section)
8637 cur_text_section = text_section;
8638 ind = cur_text_section->data_offset;
8639 funcname = get_tok_str(v, NULL);
8640 sym = sym_find(v);
8641 if (sym) {
8642 /* if symbol is already defined, then put complete type */
8643 sym->type = type;
8644 } else {
8645 /* put function symbol */
8646 sym = global_identifier_push(v, type.t, 0);
8647 sym->type.ref = type.ref;
8649 /* NOTE: we patch the symbol size later */
8650 put_extern_sym(sym, cur_text_section, ind, 0);
8651 func_ind = ind;
8652 sym->r = VT_SYM | VT_CONST;
8653 /* put debug symbol */
8654 if (do_debug)
8655 put_func_debug(sym);
8656 /* push a dummy symbol to enable local sym storage */
8657 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8658 gfunc_prolog(&type);
8659 loc = 0;
8660 rsym = 0;
8661 #ifdef CONFIG_REG_VARS
8662 macro_ptr = func_str.str;
8663 next();
8664 #endif
8665 block(NULL, NULL, NULL, NULL, 0, 0);
8666 gsym(rsym);
8667 gfunc_epilog();
8668 cur_text_section->data_offset = ind;
8669 label_pop(&global_label_stack, NULL);
8670 sym_pop(&local_stack, NULL); /* reset local stack */
8671 /* end of function */
8672 /* patch symbol size */
8673 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8674 ind - func_ind;
8675 if (do_debug) {
8676 put_stabn(N_FUN, 0, 0, ind - func_ind);
8678 funcname = ""; /* for safety */
8679 func_vt.t = VT_VOID; /* for safety */
8680 ind = 0; /* for safety */
8682 #ifdef CONFIG_REG_VARS
8683 tok_str_free(func_str.str);
8684 restore_parse_state(&saved_parse_state);
8685 #endif
8686 break;
8687 } else {
8688 if (btype.t & VT_TYPEDEF) {
8689 /* save typedefed type */
8690 /* XXX: test storage specifiers ? */
8691 sym = sym_push(v, &type, 0, 0);
8692 sym->type.t |= VT_TYPEDEF;
8693 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8694 /* external function definition */
8695 external_sym(v, &type, 0);
8696 } else {
8697 /* not lvalue if array */
8698 r = 0;
8699 if (!(type.t & VT_ARRAY))
8700 r |= lvalue_type(type.t);
8701 has_init = (tok == '=');
8702 if ((btype.t & VT_EXTERN) ||
8703 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8704 !has_init && l == VT_CONST && type.ref->c < 0)) {
8705 /* external variable */
8706 /* NOTE: as GCC, uninitialized global static
8707 arrays of null size are considered as
8708 extern */
8709 external_sym(v, &type, r);
8710 } else {
8711 if (type.t & VT_STATIC)
8712 r |= VT_CONST;
8713 else
8714 r |= l;
8715 if (has_init)
8716 next();
8717 decl_initializer_alloc(&type, &ad, r,
8718 has_init, v, l);
8721 if (tok != ',') {
8722 skip(';');
8723 break;
8725 next();
8731 /* better than nothing, but needs extension to handle '-E' option
8732 correctly too */
8733 static void preprocess_init(TCCState *s1)
8735 s1->include_stack_ptr = s1->include_stack;
8736 /* XXX: move that before to avoid having to initialize
8737 file->ifdef_stack_ptr ? */
8738 s1->ifdef_stack_ptr = s1->ifdef_stack;
8739 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8741 /* XXX: not ANSI compliant: bound checking says error */
8742 vtop = vstack - 1;
8745 /* compile the C file opened in 'file'. Return non zero if errors. */
8746 static int tcc_compile(TCCState *s1)
8748 Sym *define_start;
8749 char buf[512];
8750 volatile int section_sym;
8752 #ifdef INC_DEBUG
8753 printf("%s: **** new file\n", file->filename);
8754 #endif
8755 preprocess_init(s1);
8757 funcname = "";
8758 anon_sym = SYM_FIRST_ANOM;
8760 /* file info: full path + filename */
8761 section_sym = 0; /* avoid warning */
8762 if (do_debug) {
8763 section_sym = put_elf_sym(symtab_section, 0, 0,
8764 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8765 text_section->sh_num, NULL);
8766 getcwd(buf, sizeof(buf));
8767 pstrcat(buf, sizeof(buf), "/");
8768 put_stabs_r(buf, N_SO, 0, 0,
8769 text_section->data_offset, text_section, section_sym);
8770 put_stabs_r(file->filename, N_SO, 0, 0,
8771 text_section->data_offset, text_section, section_sym);
8773 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8774 symbols can be safely used */
8775 put_elf_sym(symtab_section, 0, 0,
8776 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8777 SHN_ABS, file->filename);
8779 /* define some often used types */
8780 int_type.t = VT_INT;
8782 char_pointer_type.t = VT_BYTE;
8783 mk_pointer(&char_pointer_type);
8785 func_old_type.t = VT_FUNC;
8786 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8788 #if 0
8789 /* define 'void *alloca(unsigned int)' builtin function */
8791 Sym *s1;
8793 p = anon_sym++;
8794 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8795 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8796 s1->next = NULL;
8797 sym->next = s1;
8798 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8800 #endif
8802 define_start = define_stack;
8804 if (setjmp(s1->error_jmp_buf) == 0) {
8805 s1->nb_errors = 0;
8806 s1->error_set_jmp_enabled = 1;
8808 ch = file->buf_ptr[0];
8809 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8810 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8811 next();
8812 decl(VT_CONST);
8813 if (tok != TOK_EOF)
8814 expect("declaration");
8816 /* end of translation unit info */
8817 if (do_debug) {
8818 put_stabs_r(NULL, N_SO, 0, 0,
8819 text_section->data_offset, text_section, section_sym);
8822 s1->error_set_jmp_enabled = 0;
8824 /* reset define stack, but leave -Dsymbols (may be incorrect if
8825 they are undefined) */
8826 free_defines(define_start);
8828 sym_pop(&global_stack, NULL);
8830 return s1->nb_errors != 0 ? -1 : 0;
8833 #ifdef LIBTCC
8834 int tcc_compile_string(TCCState *s, const char *str)
8836 BufferedFile bf1, *bf = &bf1;
8837 int ret, len;
8838 char *buf;
8840 /* init file structure */
8841 bf->fd = -1;
8842 /* XXX: avoid copying */
8843 len = strlen(str);
8844 buf = tcc_malloc(len + 1);
8845 if (!buf)
8846 return -1;
8847 memcpy(buf, str, len);
8848 buf[len] = CH_EOB;
8849 bf->buf_ptr = buf;
8850 bf->buf_end = buf + len;
8851 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8852 bf->line_num = 1;
8853 file = bf;
8855 ret = tcc_compile(s);
8857 tcc_free(buf);
8859 /* currently, no need to close */
8860 return ret;
8862 #endif
8864 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8865 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8867 BufferedFile bf1, *bf = &bf1;
8869 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8870 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8871 /* default value */
8872 if (!value)
8873 value = "1";
8874 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8876 /* init file structure */
8877 bf->fd = -1;
8878 bf->buf_ptr = bf->buffer;
8879 bf->buf_end = bf->buffer + strlen(bf->buffer);
8880 *bf->buf_end = CH_EOB;
8881 bf->filename[0] = '\0';
8882 bf->line_num = 1;
8883 file = bf;
8885 s1->include_stack_ptr = s1->include_stack;
8887 /* parse with define parser */
8888 ch = file->buf_ptr[0];
8889 next_nomacro();
8890 parse_define();
8891 file = NULL;
8894 /* undefine a preprocessor symbol */
8895 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8897 TokenSym *ts;
8898 Sym *s;
8899 ts = tok_alloc(sym, strlen(sym));
8900 s = define_find(ts->tok);
8901 /* undefine symbol by putting an invalid name */
8902 if (s)
8903 define_undef(s);
8906 #ifdef CONFIG_TCC_ASM
8908 #ifdef TCC_TARGET_I386
8909 #include "i386-asm.c"
8910 #endif
8911 #include "tccasm.c"
8913 #else
8914 static void asm_instr(void)
8916 error("inline asm() not supported");
8918 #endif
8920 #include "tccelf.c"
8922 /* print the position in the source file of PC value 'pc' by reading
8923 the stabs debug information */
8924 static void rt_printline(unsigned long wanted_pc)
8926 Stab_Sym *sym, *sym_end;
8927 char func_name[128], last_func_name[128];
8928 unsigned long func_addr, last_pc, pc;
8929 const char *incl_files[INCLUDE_STACK_SIZE];
8930 int incl_index, len, last_line_num, i;
8931 const char *str, *p;
8933 fprintf(stderr, "0x%08lx:", wanted_pc);
8935 func_name[0] = '\0';
8936 func_addr = 0;
8937 incl_index = 0;
8938 last_func_name[0] = '\0';
8939 last_pc = 0xffffffff;
8940 last_line_num = 1;
8941 sym = (Stab_Sym *)stab_section->data + 1;
8942 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8943 while (sym < sym_end) {
8944 switch(sym->n_type) {
8945 /* function start or end */
8946 case N_FUN:
8947 if (sym->n_strx == 0) {
8948 /* we test if between last line and end of function */
8949 pc = sym->n_value + func_addr;
8950 if (wanted_pc >= last_pc && wanted_pc < pc)
8951 goto found;
8952 func_name[0] = '\0';
8953 func_addr = 0;
8954 } else {
8955 str = stabstr_section->data + sym->n_strx;
8956 p = strchr(str, ':');
8957 if (!p) {
8958 pstrcpy(func_name, sizeof(func_name), str);
8959 } else {
8960 len = p - str;
8961 if (len > sizeof(func_name) - 1)
8962 len = sizeof(func_name) - 1;
8963 memcpy(func_name, str, len);
8964 func_name[len] = '\0';
8966 func_addr = sym->n_value;
8968 break;
8969 /* line number info */
8970 case N_SLINE:
8971 pc = sym->n_value + func_addr;
8972 if (wanted_pc >= last_pc && wanted_pc < pc)
8973 goto found;
8974 last_pc = pc;
8975 last_line_num = sym->n_desc;
8976 /* XXX: slow! */
8977 strcpy(last_func_name, func_name);
8978 break;
8979 /* include files */
8980 case N_BINCL:
8981 str = stabstr_section->data + sym->n_strx;
8982 add_incl:
8983 if (incl_index < INCLUDE_STACK_SIZE) {
8984 incl_files[incl_index++] = str;
8986 break;
8987 case N_EINCL:
8988 if (incl_index > 1)
8989 incl_index--;
8990 break;
8991 case N_SO:
8992 if (sym->n_strx == 0) {
8993 incl_index = 0; /* end of translation unit */
8994 } else {
8995 str = stabstr_section->data + sym->n_strx;
8996 /* do not add path */
8997 len = strlen(str);
8998 if (len > 0 && str[len - 1] != '/')
8999 goto add_incl;
9001 break;
9003 sym++;
9006 /* second pass: we try symtab symbols (no line number info) */
9007 incl_index = 0;
9009 Elf32_Sym *sym, *sym_end;
9010 int type;
9012 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9013 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9014 sym < sym_end;
9015 sym++) {
9016 type = ELF32_ST_TYPE(sym->st_info);
9017 if (type == STT_FUNC) {
9018 if (wanted_pc >= sym->st_value &&
9019 wanted_pc < sym->st_value + sym->st_size) {
9020 pstrcpy(last_func_name, sizeof(last_func_name),
9021 strtab_section->data + sym->st_name);
9022 goto found;
9027 /* did not find any info: */
9028 fprintf(stderr, " ???\n");
9029 return;
9030 found:
9031 if (last_func_name[0] != '\0') {
9032 fprintf(stderr, " %s()", last_func_name);
9034 if (incl_index > 0) {
9035 fprintf(stderr, " (%s:%d",
9036 incl_files[incl_index - 1], last_line_num);
9037 for(i = incl_index - 2; i >= 0; i--)
9038 fprintf(stderr, ", included from %s", incl_files[i]);
9039 fprintf(stderr, ")");
9041 fprintf(stderr, "\n");
9044 #ifndef WIN32
9046 #ifdef __i386__
9048 /* fix for glibc 2.1 */
9049 #ifndef REG_EIP
9050 #define REG_EIP EIP
9051 #define REG_EBP EBP
9052 #endif
9054 /* return the PC at frame level 'level'. Return non zero if not found */
9055 static int rt_get_caller_pc(unsigned long *paddr,
9056 ucontext_t *uc, int level)
9058 unsigned long fp;
9059 int i;
9061 if (level == 0) {
9062 #ifdef __FreeBSD__
9063 *paddr = uc->uc_mcontext.mc_eip;
9064 #else
9065 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9066 #endif
9067 return 0;
9068 } else {
9069 #ifdef __FreeBSD__
9070 fp = uc->uc_mcontext.mc_ebp;
9071 #else
9072 fp = uc->uc_mcontext.gregs[REG_EBP];
9073 #endif
9074 for(i=1;i<level;i++) {
9075 /* XXX: check address validity with program info */
9076 if (fp <= 0x1000 || fp >= 0xc0000000)
9077 return -1;
9078 fp = ((unsigned long *)fp)[0];
9080 *paddr = ((unsigned long *)fp)[1];
9081 return 0;
9084 #else
9086 #warning add arch specific rt_get_caller_pc()
9088 static int rt_get_caller_pc(unsigned long *paddr,
9089 ucontext_t *uc, int level)
9091 return -1;
9093 #endif
9095 /* emit a run time error at position 'pc' */
9096 void rt_error(ucontext_t *uc, const char *fmt, ...)
9098 va_list ap;
9099 unsigned long pc;
9100 int i;
9102 va_start(ap, fmt);
9103 fprintf(stderr, "Runtime error: ");
9104 vfprintf(stderr, fmt, ap);
9105 fprintf(stderr, "\n");
9106 for(i=0;i<num_callers;i++) {
9107 if (rt_get_caller_pc(&pc, uc, i) < 0)
9108 break;
9109 if (i == 0)
9110 fprintf(stderr, "at ");
9111 else
9112 fprintf(stderr, "by ");
9113 rt_printline(pc);
9115 exit(255);
9116 va_end(ap);
9119 /* signal handler for fatal errors */
9120 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9122 ucontext_t *uc = puc;
9124 switch(signum) {
9125 case SIGFPE:
9126 switch(siginf->si_code) {
9127 case FPE_INTDIV:
9128 case FPE_FLTDIV:
9129 rt_error(uc, "division by zero");
9130 break;
9131 default:
9132 rt_error(uc, "floating point exception");
9133 break;
9135 break;
9136 case SIGBUS:
9137 case SIGSEGV:
9138 if (rt_bound_error_msg && *rt_bound_error_msg)
9139 rt_error(uc, *rt_bound_error_msg);
9140 else
9141 rt_error(uc, "dereferencing invalid pointer");
9142 break;
9143 case SIGILL:
9144 rt_error(uc, "illegal instruction");
9145 break;
9146 case SIGABRT:
9147 rt_error(uc, "abort() called");
9148 break;
9149 default:
9150 rt_error(uc, "caught signal %d", signum);
9151 break;
9153 exit(255);
9155 #endif
9157 /* do all relocations (needed before using tcc_get_symbol()) */
9158 int tcc_relocate(TCCState *s1)
9160 Section *s;
9161 int i;
9163 s1->nb_errors = 0;
9165 tcc_add_runtime(s1);
9167 build_got_entries(s1);
9169 relocate_common_syms();
9171 /* compute relocation address : section are relocated in place. We
9172 also alloc the bss space */
9173 for(i = 1; i < s1->nb_sections; i++) {
9174 s = s1->sections[i];
9175 if (s->sh_flags & SHF_ALLOC) {
9176 if (s->sh_type == SHT_NOBITS)
9177 s->data = tcc_mallocz(s->data_offset);
9178 s->sh_addr = (unsigned long)s->data;
9182 relocate_syms(s1, 1);
9184 if (s1->nb_errors != 0)
9185 return -1;
9187 /* relocate each section */
9188 for(i = 1; i < s1->nb_sections; i++) {
9189 s = s1->sections[i];
9190 if (s->reloc)
9191 relocate_section(s1, s);
9193 return 0;
9196 /* launch the compiled program with the given arguments */
9197 int tcc_run(TCCState *s1, int argc, char **argv)
9199 int (*prog_main)(int, char **);
9201 if (tcc_relocate(s1) < 0)
9202 return -1;
9204 prog_main = tcc_get_symbol_err(s1, "main");
9206 if (do_debug) {
9207 #ifdef WIN32
9208 error("debug mode currently not available for Windows");
9209 #else
9210 struct sigaction sigact;
9211 /* install TCC signal handlers to print debug info on fatal
9212 runtime errors */
9213 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9214 sigact.sa_sigaction = sig_error;
9215 sigemptyset(&sigact.sa_mask);
9216 sigaction(SIGFPE, &sigact, NULL);
9217 sigaction(SIGILL, &sigact, NULL);
9218 sigaction(SIGSEGV, &sigact, NULL);
9219 sigaction(SIGBUS, &sigact, NULL);
9220 sigaction(SIGABRT, &sigact, NULL);
9221 #endif
9224 #ifdef CONFIG_TCC_BCHECK
9225 if (do_bounds_check) {
9226 void (*bound_init)(void);
9228 /* set error function */
9229 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9230 "__bound_error_msg");
9232 /* XXX: use .init section so that it also work in binary ? */
9233 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9234 bound_init();
9236 #endif
9237 return (*prog_main)(argc, argv);
9240 TCCState *tcc_new(void)
9242 const char *p, *r;
9243 TCCState *s;
9244 TokenSym *ts;
9245 int i, c;
9247 s = tcc_mallocz(sizeof(TCCState));
9248 if (!s)
9249 return NULL;
9250 tcc_state = s;
9251 s->output_type = TCC_OUTPUT_MEMORY;
9253 /* init isid table */
9254 for(i=0;i<256;i++)
9255 isidnum_table[i] = isid(i) || isnum(i);
9257 /* add all tokens */
9258 table_ident = NULL;
9259 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9261 tok_ident = TOK_IDENT;
9262 p = tcc_keywords;
9263 while (*p) {
9264 r = p;
9265 for(;;) {
9266 c = *r++;
9267 if (c == '\0')
9268 break;
9270 ts = tok_alloc(p, r - p - 1);
9271 p = r;
9274 /* we add dummy defines for some special macros to speed up tests
9275 and to have working defined() */
9276 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9277 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9278 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9279 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9281 /* standard defines */
9282 tcc_define_symbol(s, "__STDC__", NULL);
9283 #if defined(TCC_TARGET_I386)
9284 tcc_define_symbol(s, "__i386__", NULL);
9285 #endif
9286 #if defined(TCC_TARGET_ARM)
9287 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9288 tcc_define_symbol(s, "__arm_elf__", NULL);
9289 tcc_define_symbol(s, "__arm_elf", NULL);
9290 tcc_define_symbol(s, "arm_elf", NULL);
9291 tcc_define_symbol(s, "__arm__", NULL);
9292 tcc_define_symbol(s, "__arm", NULL);
9293 tcc_define_symbol(s, "arm", NULL);
9294 tcc_define_symbol(s, "__APCS_32__", NULL);
9295 #endif
9296 #if defined(linux)
9297 tcc_define_symbol(s, "__linux__", NULL);
9298 tcc_define_symbol(s, "linux", NULL);
9299 #endif
9300 /* tiny C specific defines */
9301 tcc_define_symbol(s, "__TINYC__", NULL);
9303 /* tiny C & gcc defines */
9304 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9305 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9306 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9308 /* default library paths */
9309 tcc_add_library_path(s, "/usr/local/lib");
9310 tcc_add_library_path(s, "/usr/lib");
9311 tcc_add_library_path(s, "/lib");
9313 /* no section zero */
9314 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9316 /* create standard sections */
9317 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9318 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9319 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9321 /* symbols are always generated for linking stage */
9322 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9323 ".strtab",
9324 ".hashtab", SHF_PRIVATE);
9325 strtab_section = symtab_section->link;
9327 /* private symbol table for dynamic symbols */
9328 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9329 ".dynstrtab",
9330 ".dynhashtab", SHF_PRIVATE);
9331 s->alacarte_link = 1;
9333 #ifdef CHAR_IS_UNSIGNED
9334 s->char_is_unsigned = 1;
9335 #endif
9336 return s;
9339 void tcc_delete(TCCState *s1)
9341 int i, n;
9343 /* free -D defines */
9344 free_defines(NULL);
9346 /* free tokens */
9347 n = tok_ident - TOK_IDENT;
9348 for(i = 0; i < n; i++)
9349 tcc_free(table_ident[i]);
9350 tcc_free(table_ident);
9352 /* free all sections */
9354 free_section(symtab_section->hash);
9356 free_section(s1->dynsymtab_section->hash);
9357 free_section(s1->dynsymtab_section->link);
9358 free_section(s1->dynsymtab_section);
9360 for(i = 1; i < s1->nb_sections; i++)
9361 free_section(s1->sections[i]);
9362 tcc_free(s1->sections);
9364 /* free loaded dlls array */
9365 for(i = 0; i < s1->nb_loaded_dlls; i++)
9366 tcc_free(s1->loaded_dlls[i]);
9367 tcc_free(s1->loaded_dlls);
9369 /* library paths */
9370 for(i = 0; i < s1->nb_library_paths; i++)
9371 tcc_free(s1->library_paths[i]);
9372 tcc_free(s1->library_paths);
9374 /* cached includes */
9375 for(i = 0; i < s1->nb_cached_includes; i++)
9376 tcc_free(s1->cached_includes[i]);
9377 tcc_free(s1->cached_includes);
9379 for(i = 0; i < s1->nb_include_paths; i++)
9380 tcc_free(s1->include_paths[i]);
9381 tcc_free(s1->include_paths);
9383 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9384 tcc_free(s1->sysinclude_paths[i]);
9385 tcc_free(s1->sysinclude_paths);
9387 tcc_free(s1);
9390 int tcc_add_include_path(TCCState *s1, const char *pathname)
9392 char *pathname1;
9394 pathname1 = tcc_strdup(pathname);
9395 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9396 return 0;
9399 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9401 char *pathname1;
9403 pathname1 = tcc_strdup(pathname);
9404 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9405 return 0;
9408 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9410 const char *ext, *filename1;
9411 Elf32_Ehdr ehdr;
9412 int fd, ret;
9413 BufferedFile *saved_file;
9415 /* find source file type with extension */
9416 filename1 = strrchr(filename, '/');
9417 if (filename1)
9418 filename1++;
9419 else
9420 filename1 = filename;
9421 ext = strrchr(filename1, '.');
9422 if (ext)
9423 ext++;
9425 /* open the file */
9426 saved_file = file;
9427 file = tcc_open(s1, filename);
9428 if (!file) {
9429 if (flags & AFF_PRINT_ERROR) {
9430 error_noabort("file '%s' not found", filename);
9432 ret = -1;
9433 goto fail1;
9436 if (!ext || !strcmp(ext, "c")) {
9437 /* C file assumed */
9438 ret = tcc_compile(s1);
9439 } else
9440 #ifdef CONFIG_TCC_ASM
9441 if (!strcmp(ext, "S")) {
9442 /* preprocessed assembler */
9443 ret = tcc_assemble(s1, 1);
9444 } else if (!strcmp(ext, "s")) {
9445 /* non preprocessed assembler */
9446 ret = tcc_assemble(s1, 0);
9447 } else
9448 #endif
9450 fd = file->fd;
9451 /* assume executable format: auto guess file type */
9452 ret = read(fd, &ehdr, sizeof(ehdr));
9453 lseek(fd, 0, SEEK_SET);
9454 if (ret <= 0) {
9455 error_noabort("could not read header");
9456 goto fail;
9457 } else if (ret != sizeof(ehdr)) {
9458 goto try_load_script;
9461 if (ehdr.e_ident[0] == ELFMAG0 &&
9462 ehdr.e_ident[1] == ELFMAG1 &&
9463 ehdr.e_ident[2] == ELFMAG2 &&
9464 ehdr.e_ident[3] == ELFMAG3) {
9465 file->line_num = 0; /* do not display line number if error */
9466 if (ehdr.e_type == ET_REL) {
9467 ret = tcc_load_object_file(s1, fd, 0);
9468 } else if (ehdr.e_type == ET_DYN) {
9469 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9470 void *h;
9471 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9472 if (h)
9473 ret = 0;
9474 else
9475 ret = -1;
9476 } else {
9477 ret = tcc_load_dll(s1, fd, filename,
9478 (flags & AFF_REFERENCED_DLL) != 0);
9480 } else {
9481 error_noabort("unrecognized ELF file");
9482 goto fail;
9484 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9485 file->line_num = 0; /* do not display line number if error */
9486 ret = tcc_load_archive(s1, fd);
9487 } else {
9488 /* as GNU ld, consider it is an ld script if not recognized */
9489 try_load_script:
9490 ret = tcc_load_ldscript(s1);
9491 if (ret < 0) {
9492 error_noabort("unrecognized file type");
9493 goto fail;
9497 the_end:
9498 tcc_close(file);
9499 fail1:
9500 file = saved_file;
9501 return ret;
9502 fail:
9503 ret = -1;
9504 goto the_end;
9507 int tcc_add_file(TCCState *s, const char *filename)
9509 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9512 int tcc_add_library_path(TCCState *s, const char *pathname)
9514 char *pathname1;
9516 pathname1 = tcc_strdup(pathname);
9517 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9518 return 0;
9521 /* find and load a dll. Return non zero if not found */
9522 /* XXX: add '-rpath' option support ? */
9523 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9525 char buf[1024];
9526 int i;
9528 for(i = 0; i < s->nb_library_paths; i++) {
9529 snprintf(buf, sizeof(buf), "%s/%s",
9530 s->library_paths[i], filename);
9531 if (tcc_add_file_internal(s, buf, flags) == 0)
9532 return 0;
9534 return -1;
9537 /* the library name is the same as the argument of the '-l' option */
9538 int tcc_add_library(TCCState *s, const char *libraryname)
9540 char buf[1024];
9541 int i;
9543 /* first we look for the dynamic library if not static linking */
9544 if (!s->static_link) {
9545 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9546 if (tcc_add_dll(s, buf, 0) == 0)
9547 return 0;
9550 /* then we look for the static library */
9551 for(i = 0; i < s->nb_library_paths; i++) {
9552 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9553 s->library_paths[i], libraryname);
9554 if (tcc_add_file_internal(s, buf, 0) == 0)
9555 return 0;
9557 return -1;
9560 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9562 add_elf_sym(symtab_section, val, 0,
9563 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9564 SHN_ABS, name);
9565 return 0;
9568 int tcc_set_output_type(TCCState *s, int output_type)
9570 char buf[1024];
9572 s->output_type = output_type;
9574 if (!s->nostdinc) {
9575 /* default include paths */
9576 /* XXX: reverse order needed if -isystem support */
9577 tcc_add_sysinclude_path(s, "/usr/local/include");
9578 tcc_add_sysinclude_path(s, "/usr/include");
9579 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9580 tcc_add_sysinclude_path(s, buf);
9583 /* if bound checking, then add corresponding sections */
9584 #ifdef CONFIG_TCC_BCHECK
9585 if (do_bounds_check) {
9586 /* define symbol */
9587 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9588 /* create bounds sections */
9589 bounds_section = new_section(s, ".bounds",
9590 SHT_PROGBITS, SHF_ALLOC);
9591 lbounds_section = new_section(s, ".lbounds",
9592 SHT_PROGBITS, SHF_ALLOC);
9594 #endif
9596 if (s->char_is_unsigned) {
9597 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9600 /* add debug sections */
9601 if (do_debug) {
9602 /* stab symbols */
9603 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9604 stab_section->sh_entsize = sizeof(Stab_Sym);
9605 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9606 put_elf_str(stabstr_section, "");
9607 stab_section->link = stabstr_section;
9608 /* put first entry */
9609 put_stabs("", 0, 0, 0, 0);
9612 /* add libc crt1/crti objects */
9613 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9614 !s->nostdlib) {
9615 if (output_type != TCC_OUTPUT_DLL)
9616 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9617 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9619 return 0;
9622 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9623 #define FD_INVERT 0x0002 /* invert value before storing */
9625 typedef struct FlagDef {
9626 uint16_t offset;
9627 uint16_t flags;
9628 const char *name;
9629 } FlagDef;
9631 static const FlagDef warning_defs[] = {
9632 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9633 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9634 { offsetof(TCCState, warn_error), 0, "error" },
9635 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9636 "implicit-function-declaration" },
9639 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9640 const char *name, int value)
9642 int i;
9643 const FlagDef *p;
9644 const char *r;
9646 r = name;
9647 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9648 r += 3;
9649 value = !value;
9651 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9652 if (!strcmp(r, p->name))
9653 goto found;
9655 return -1;
9656 found:
9657 if (p->flags & FD_INVERT)
9658 value = !value;
9659 *(int *)((uint8_t *)s + p->offset) = value;
9660 return 0;
9664 /* set/reset a warning */
9665 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9667 int i;
9668 const FlagDef *p;
9670 if (!strcmp(warning_name, "all")) {
9671 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9672 if (p->flags & WD_ALL)
9673 *(int *)((uint8_t *)s + p->offset) = 1;
9675 return 0;
9676 } else {
9677 return set_flag(s, warning_defs, countof(warning_defs),
9678 warning_name, value);
9682 static const FlagDef flag_defs[] = {
9683 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9684 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9687 /* set/reset a flag */
9688 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9690 return set_flag(s, flag_defs, countof(flag_defs),
9691 flag_name, value);
9694 #if !defined(LIBTCC)
9696 /* extract the basename of a file */
9697 static const char *tcc_basename(const char *name)
9699 const char *p;
9700 p = strrchr(name, '/');
9701 #ifdef WIN32
9702 if (!p)
9703 p = strrchr(name, '\\');
9704 #endif
9705 if (!p)
9706 p = name;
9707 else
9708 p++;
9709 return p;
9712 static int64_t getclock_us(void)
9714 #ifdef WIN32
9715 struct _timeb tb;
9716 _ftime(&tb);
9717 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9718 #else
9719 struct timeval tv;
9720 gettimeofday(&tv, NULL);
9721 return tv.tv_sec * 1000000LL + tv.tv_usec;
9722 #endif
9725 void help(void)
9727 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9728 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9729 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9730 " [infile1 infile2...] [-run infile args...]\n"
9731 "\n"
9732 "General options:\n"
9733 " -v display current version\n"
9734 " -c compile only - generate an object file\n"
9735 " -o outfile set output filename\n"
9736 " -Bdir set tcc internal library path\n"
9737 " -bench output compilation statistics\n"
9738 " -run run compiled source\n"
9739 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9740 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9741 " -w disable all warnings\n"
9742 "Preprocessor options:\n"
9743 " -Idir add include path 'dir'\n"
9744 " -Dsym[=val] define 'sym' with value 'val'\n"
9745 " -Usym undefine 'sym'\n"
9746 "Linker options:\n"
9747 " -Ldir add library path 'dir'\n"
9748 " -llib link with dynamic or static library 'lib'\n"
9749 " -shared generate a shared library\n"
9750 " -static static linking\n"
9751 " -rdynamic export all global symbols to dynamic linker\n"
9752 " -r relocatable output\n"
9753 "Debugger options:\n"
9754 " -g generate runtime debug info\n"
9755 #ifdef CONFIG_TCC_BCHECK
9756 " -b compile with built-in memory and bounds checker (implies -g)\n"
9757 #endif
9758 " -bt N show N callers in stack traces\n"
9762 #define TCC_OPTION_HAS_ARG 0x0001
9763 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9765 typedef struct TCCOption {
9766 const char *name;
9767 uint16_t index;
9768 uint16_t flags;
9769 } TCCOption;
9771 enum {
9772 TCC_OPTION_HELP,
9773 TCC_OPTION_I,
9774 TCC_OPTION_D,
9775 TCC_OPTION_U,
9776 TCC_OPTION_L,
9777 TCC_OPTION_B,
9778 TCC_OPTION_l,
9779 TCC_OPTION_bench,
9780 TCC_OPTION_bt,
9781 TCC_OPTION_b,
9782 TCC_OPTION_g,
9783 TCC_OPTION_c,
9784 TCC_OPTION_static,
9785 TCC_OPTION_shared,
9786 TCC_OPTION_o,
9787 TCC_OPTION_r,
9788 TCC_OPTION_W,
9789 TCC_OPTION_O,
9790 TCC_OPTION_m,
9791 TCC_OPTION_f,
9792 TCC_OPTION_nostdinc,
9793 TCC_OPTION_nostdlib,
9794 TCC_OPTION_print_search_dirs,
9795 TCC_OPTION_rdynamic,
9796 TCC_OPTION_run,
9797 TCC_OPTION_v,
9798 TCC_OPTION_w,
9801 static const TCCOption tcc_options[] = {
9802 { "h", TCC_OPTION_HELP, 0 },
9803 { "?", TCC_OPTION_HELP, 0 },
9804 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9805 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9806 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9807 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9808 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9809 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9810 { "bench", TCC_OPTION_bench, 0 },
9811 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9812 #ifdef CONFIG_TCC_BCHECK
9813 { "b", TCC_OPTION_b, 0 },
9814 #endif
9815 { "g", TCC_OPTION_g, 0 },
9816 { "c", TCC_OPTION_c, 0 },
9817 { "static", TCC_OPTION_static, 0 },
9818 { "shared", TCC_OPTION_shared, 0 },
9819 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9820 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9821 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9822 { "r", TCC_OPTION_r, 0 },
9823 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9824 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9825 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9826 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9827 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9828 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9829 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9830 { "v", TCC_OPTION_v, 0 },
9831 { "w", TCC_OPTION_w, 0 },
9832 { NULL },
9835 /* convert 'str' into an array of space separated strings */
9836 static int expand_args(char ***pargv, const char *str)
9838 const char *s1;
9839 char **argv, *arg;
9840 int argc, len;
9842 argc = 0;
9843 argv = NULL;
9844 for(;;) {
9845 while (is_space(*str))
9846 str++;
9847 if (*str == '\0')
9848 break;
9849 s1 = str;
9850 while (*str != '\0' && !is_space(*str))
9851 str++;
9852 len = str - s1;
9853 arg = tcc_malloc(len + 1);
9854 memcpy(arg, s1, len);
9855 arg[len] = '\0';
9856 dynarray_add((void ***)&argv, &argc, arg);
9858 *pargv = argv;
9859 return argc;
9862 static char **files;
9863 static int nb_files, nb_libraries;
9864 static int multiple_files;
9865 static int print_search_dirs;
9866 static int output_type;
9867 static int reloc_output;
9868 static const char *outfile;
9870 int parse_args(TCCState *s, int argc, char **argv)
9872 int optind;
9873 const TCCOption *popt;
9874 const char *optarg, *p1, *r1;
9875 char *r;
9877 optind = 0;
9878 while (1) {
9879 if (optind >= argc) {
9880 if (nb_files == 0 && !print_search_dirs)
9881 goto show_help;
9882 else
9883 break;
9885 r = argv[optind++];
9886 if (r[0] != '-') {
9887 /* add a new file */
9888 dynarray_add((void ***)&files, &nb_files, r);
9889 if (!multiple_files) {
9890 optind--;
9891 /* argv[0] will be this file */
9892 break;
9894 } else {
9895 /* find option in table (match only the first chars */
9896 popt = tcc_options;
9897 for(;;) {
9898 p1 = popt->name;
9899 if (p1 == NULL)
9900 error("invalid option -- '%s'", r);
9901 r1 = r + 1;
9902 for(;;) {
9903 if (*p1 == '\0')
9904 goto option_found;
9905 if (*r1 != *p1)
9906 break;
9907 p1++;
9908 r1++;
9910 popt++;
9912 option_found:
9913 if (popt->flags & TCC_OPTION_HAS_ARG) {
9914 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9915 optarg = r1;
9916 } else {
9917 if (optind >= argc)
9918 error("argument to '%s' is missing", r);
9919 optarg = argv[optind++];
9921 } else {
9922 if (*r1 != '\0')
9923 goto show_help;
9924 optarg = NULL;
9927 switch(popt->index) {
9928 case TCC_OPTION_HELP:
9929 show_help:
9930 help();
9931 exit(1);
9932 case TCC_OPTION_I:
9933 if (tcc_add_include_path(s, optarg) < 0)
9934 error("too many include paths");
9935 break;
9936 case TCC_OPTION_D:
9938 char *sym, *value;
9939 sym = (char *)optarg;
9940 value = strchr(sym, '=');
9941 if (value) {
9942 *value = '\0';
9943 value++;
9945 tcc_define_symbol(s, sym, value);
9947 break;
9948 case TCC_OPTION_U:
9949 tcc_undefine_symbol(s, optarg);
9950 break;
9951 case TCC_OPTION_L:
9952 tcc_add_library_path(s, optarg);
9953 break;
9954 case TCC_OPTION_B:
9955 /* set tcc utilities path (mainly for tcc development) */
9956 tcc_lib_path = optarg;
9957 break;
9958 case TCC_OPTION_l:
9959 dynarray_add((void ***)&files, &nb_files, r);
9960 nb_libraries++;
9961 break;
9962 case TCC_OPTION_bench:
9963 do_bench = 1;
9964 break;
9965 case TCC_OPTION_bt:
9966 num_callers = atoi(optarg);
9967 break;
9968 #ifdef CONFIG_TCC_BCHECK
9969 case TCC_OPTION_b:
9970 do_bounds_check = 1;
9971 do_debug = 1;
9972 break;
9973 #endif
9974 case TCC_OPTION_g:
9975 do_debug = 1;
9976 break;
9977 case TCC_OPTION_c:
9978 multiple_files = 1;
9979 output_type = TCC_OUTPUT_OBJ;
9980 break;
9981 case TCC_OPTION_static:
9982 s->static_link = 1;
9983 break;
9984 case TCC_OPTION_shared:
9985 output_type = TCC_OUTPUT_DLL;
9986 break;
9987 case TCC_OPTION_o:
9988 multiple_files = 1;
9989 outfile = optarg;
9990 break;
9991 case TCC_OPTION_r:
9992 /* generate a .o merging several output files */
9993 reloc_output = 1;
9994 output_type = TCC_OUTPUT_OBJ;
9995 break;
9996 case TCC_OPTION_nostdinc:
9997 s->nostdinc = 1;
9998 break;
9999 case TCC_OPTION_nostdlib:
10000 s->nostdlib = 1;
10001 break;
10002 case TCC_OPTION_print_search_dirs:
10003 print_search_dirs = 1;
10004 break;
10005 case TCC_OPTION_run:
10007 int argc1;
10008 char **argv1;
10009 argc1 = expand_args(&argv1, optarg);
10010 if (argc1 > 0) {
10011 parse_args(s, argc1, argv1);
10013 multiple_files = 0;
10014 output_type = TCC_OUTPUT_MEMORY;
10016 break;
10017 case TCC_OPTION_v:
10018 printf("tcc version %s\n", TCC_VERSION);
10019 exit(0);
10020 case TCC_OPTION_f:
10021 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10022 goto unsupported_option;
10023 break;
10024 case TCC_OPTION_W:
10025 if (tcc_set_warning(s, optarg, 1) < 0 &&
10026 s->warn_unsupported)
10027 goto unsupported_option;
10028 break;
10029 case TCC_OPTION_w:
10030 s->warn_none = 1;
10031 break;
10032 case TCC_OPTION_rdynamic:
10033 s->rdynamic = 1;
10034 break;
10035 default:
10036 if (s->warn_unsupported) {
10037 unsupported_option:
10038 warning("unsupported option '%s'", r);
10040 break;
10044 return optind;
10047 int main(int argc, char **argv)
10049 int i;
10050 TCCState *s;
10051 int nb_objfiles, ret, optind;
10052 char objfilename[1024];
10053 int64_t start_time = 0;
10055 s = tcc_new();
10056 output_type = TCC_OUTPUT_EXE;
10057 outfile = NULL;
10058 multiple_files = 1;
10059 files = NULL;
10060 nb_files = 0;
10061 nb_libraries = 0;
10062 reloc_output = 0;
10063 print_search_dirs = 0;
10065 optind = parse_args(s, argc - 1, argv + 1) + 1;
10067 if (print_search_dirs) {
10068 /* enough for Linux kernel */
10069 printf("install: %s/\n", tcc_lib_path);
10070 return 0;
10073 nb_objfiles = nb_files - nb_libraries;
10075 /* if outfile provided without other options, we output an
10076 executable */
10077 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10078 output_type = TCC_OUTPUT_EXE;
10080 /* check -c consistency : only single file handled. XXX: checks file type */
10081 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10082 /* accepts only a single input file */
10083 if (nb_objfiles != 1)
10084 error("cannot specify multiple files with -c");
10085 if (nb_libraries != 0)
10086 error("cannot specify libraries with -c");
10089 /* compute default outfile name */
10090 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10091 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10092 char *ext;
10093 /* strip path */
10094 pstrcpy(objfilename, sizeof(objfilename) - 1,
10095 tcc_basename(files[0]));
10096 /* add .o extension */
10097 ext = strrchr(objfilename, '.');
10098 if (!ext)
10099 goto default_outfile;
10100 strcpy(ext + 1, "o");
10101 } else {
10102 default_outfile:
10103 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10105 outfile = objfilename;
10108 if (do_bench) {
10109 start_time = getclock_us();
10112 tcc_set_output_type(s, output_type);
10114 /* compile or add each files or library */
10115 for(i = 0;i < nb_files; i++) {
10116 const char *filename;
10118 filename = files[i];
10119 if (filename[0] == '-') {
10120 if (tcc_add_library(s, filename + 2) < 0)
10121 error("cannot find %s", filename);
10122 } else {
10123 if (tcc_add_file(s, filename) < 0) {
10124 ret = 1;
10125 goto the_end;
10130 /* free all files */
10131 tcc_free(files);
10133 if (do_bench) {
10134 double total_time;
10135 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10136 if (total_time < 0.001)
10137 total_time = 0.001;
10138 if (total_bytes < 1)
10139 total_bytes = 1;
10140 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10141 tok_ident - TOK_IDENT, total_lines, total_bytes,
10142 total_time, (int)(total_lines / total_time),
10143 total_bytes / total_time / 1000000.0);
10146 if (s->output_type != TCC_OUTPUT_MEMORY) {
10147 tcc_output_file(s, outfile);
10148 ret = 0;
10149 } else {
10150 ret = tcc_run(s, argc - optind, argv + optind);
10152 the_end:
10153 /* XXX: cannot do it with bound checking because of the malloc hooks */
10154 if (!do_bounds_check)
10155 tcc_delete(s);
10157 #ifdef MEM_DEBUG
10158 if (do_bench) {
10159 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10161 #endif
10162 return ret;
10165 #endif