C67 COFF executable format support (TK)
[tinycc/miki.git] / tcc.c
blobff33b5ee7e1021a41bd3e0cb759dad871096a7fc
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 */
65 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
67 /* default target is I386 */
68 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
69 !defined(TCC_TARGET_C67)
70 #define TCC_TARGET_I386
71 #endif
73 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
74 !defined(TCC_TARGET_C67)
75 #define CONFIG_TCC_BCHECK /* enable bound checking code */
76 #endif
78 /* define it to include assembler support */
79 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
80 #define CONFIG_TCC_ASM
81 #endif
83 /* object format selection */
84 #if defined(TCC_TARGET_C67)
85 #define TCC_TARGET_COFF
86 #endif
88 #if !defined(WIN32)
89 #define FALSE 0
90 #define false 0
91 #define TRUE 1
92 #define true 1
93 typedef int BOOL;
94 #endif
96 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
97 executables or dlls */
98 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
100 #define INCLUDE_STACK_SIZE 32
101 #define IFDEF_STACK_SIZE 64
102 #define VSTACK_SIZE 64
103 #define STRING_MAX_SIZE 1024
105 #define TOK_HASH_SIZE 2048 /* must be a power of two */
106 #define TOK_ALLOC_INCR 512 /* must be a power of two */
107 #define TOK_STR_ALLOC_INCR_BITS 6
108 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
109 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
111 /* token symbol management */
112 typedef struct TokenSym {
113 struct TokenSym *hash_next;
114 struct Sym *sym_define; /* direct pointer to define */
115 struct Sym *sym_label; /* direct pointer to label */
116 struct Sym *sym_struct; /* direct pointer to structure */
117 struct Sym *sym_identifier; /* direct pointer to identifier */
118 int tok; /* token number */
119 int len;
120 char str[1];
121 } TokenSym;
123 typedef struct CString {
124 int size; /* size in bytes */
125 void *data; /* either 'char *' or 'int *' */
126 int size_allocated;
127 void *data_allocated; /* if non NULL, data has been malloced */
128 } CString;
130 /* type definition */
131 typedef struct CType {
132 int t;
133 struct Sym *ref;
134 } CType;
136 /* constant value */
137 typedef union CValue {
138 long double ld;
139 double d;
140 float f;
141 int i;
142 unsigned int ui;
143 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
144 long long ll;
145 unsigned long long ull;
146 struct CString *cstr;
147 void *ptr;
148 int tab[1];
149 } CValue;
151 /* value on stack */
152 typedef struct SValue {
153 CType type; /* type */
154 unsigned short r; /* register + flags */
155 unsigned short r2; /* second register, used for 'long long'
156 type. If not used, set to VT_CONST */
157 CValue c; /* constant, if VT_CONST */
158 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
159 } SValue;
161 /* symbol management */
162 typedef struct Sym {
163 int v; /* symbol token */
164 int r; /* associated register */
165 int c; /* associated number */
166 CType type; /* associated type */
167 struct Sym *next; /* next related symbol */
168 struct Sym *prev; /* prev symbol in stack */
169 struct Sym *prev_tok; /* previous symbol for this token */
170 } Sym;
172 /* section definition */
173 /* XXX: use directly ELF structure for parameters ? */
174 /* special flag to indicate that the section should not be linked to
175 the other ones */
176 #define SHF_PRIVATE 0x80000000
178 typedef struct Section {
179 unsigned long data_offset; /* current data offset */
180 unsigned char *data; /* section data */
181 unsigned long data_allocated; /* used for realloc() handling */
182 int sh_name; /* elf section name (only used during output) */
183 int sh_num; /* elf section number */
184 int sh_type; /* elf section type */
185 int sh_flags; /* elf section flags */
186 int sh_info; /* elf section info */
187 int sh_addralign; /* elf section alignment */
188 int sh_entsize; /* elf entry size */
189 unsigned long sh_size; /* section size (only used during output) */
190 unsigned long sh_addr; /* address at which the section is relocated */
191 unsigned long sh_offset; /* address at which the section is relocated */
192 int nb_hashed_syms; /* used to resize the hash table */
193 struct Section *link; /* link to another section */
194 struct Section *reloc; /* corresponding section for relocation, if any */
195 struct Section *hash; /* hash table for symbols */
196 struct Section *next;
197 char name[1]; /* section name */
198 } Section;
200 typedef struct DLLReference {
201 int level;
202 char name[1];
203 } DLLReference;
205 /* GNUC attribute definition */
206 typedef struct AttributeDef {
207 int aligned;
208 Section *section;
209 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
210 } AttributeDef;
212 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
213 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
214 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
216 /* stored in 'Sym.c' field */
217 #define FUNC_NEW 1 /* ansi function prototype */
218 #define FUNC_OLD 2 /* old function prototype */
219 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
221 /* stored in 'Sym.r' field */
222 #define FUNC_CDECL 0 /* standard c call */
223 #define FUNC_STDCALL 1 /* pascal c call */
225 /* field 'Sym.t' for macros */
226 #define MACRO_OBJ 0 /* object like macro */
227 #define MACRO_FUNC 1 /* function like macro */
229 /* field 'Sym.r' for C labels */
230 #define LABEL_DEFINED 0 /* label is defined */
231 #define LABEL_FORWARD 1 /* label is forward defined */
232 #define LABEL_DECLARED 2 /* label is declared but never used */
234 /* type_decl() types */
235 #define TYPE_ABSTRACT 1 /* type without variable */
236 #define TYPE_DIRECT 2 /* type with variable */
238 #define IO_BUF_SIZE 8192
240 typedef struct BufferedFile {
241 uint8_t *buf_ptr;
242 uint8_t *buf_end;
243 int fd;
244 int line_num; /* current line number - here to simplify code */
245 int ifndef_macro; /* #ifndef macro / #endif search */
246 int ifndef_macro_saved; /* saved ifndef_macro */
247 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
248 char inc_type; /* type of include */
249 char inc_filename[512]; /* filename specified by the user */
250 char filename[1024]; /* current filename - here to simplify code */
251 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
252 } BufferedFile;
254 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
255 #define CH_EOF (-1) /* end of file */
257 /* parsing state (used to save parser state to reparse part of the
258 source several times) */
259 typedef struct ParseState {
260 int *macro_ptr;
261 int line_num;
262 int tok;
263 CValue tokc;
264 } ParseState;
266 /* used to record tokens */
267 typedef struct TokenString {
268 int *str;
269 int len;
270 int allocated_len;
271 int last_line_num;
272 } TokenString;
274 /* include file cache, used to find files faster and also to eliminate
275 inclusion if the include file is protected by #ifndef ... #endif */
276 typedef struct CachedInclude {
277 int ifndef_macro;
278 char type; /* '"' or '>' to give include type */
279 char filename[1]; /* path specified in #include */
280 } CachedInclude;
282 /* parser */
283 static struct BufferedFile *file;
284 static int ch, tok;
285 static CValue tokc;
286 static CString tokcstr; /* current parsed string, if any */
287 /* additional informations about token */
288 static int tok_flags;
289 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
290 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
291 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
293 static int *macro_ptr, *macro_ptr_allocated;
294 static int *unget_saved_macro_ptr;
295 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
296 static int unget_buffer_enabled;
297 static int parse_flags;
298 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
299 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
300 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
301 token. line feed is also
302 returned at eof */
304 static Section *text_section, *data_section, *bss_section; /* predefined sections */
305 static Section *cur_text_section; /* current section where function code is
306 generated */
307 /* bound check related sections */
308 static Section *bounds_section; /* contains global data bound description */
309 static Section *lbounds_section; /* contains local data bound description */
310 /* symbol sections */
311 static Section *symtab_section, *strtab_section;
313 /* debug sections */
314 static Section *stab_section, *stabstr_section;
316 /* loc : local variable index
317 ind : output code index
318 rsym: return symbol
319 anon_sym: anonymous symbol index
321 static int rsym, anon_sym, ind, loc;
322 /* expression generation modifiers */
323 static int const_wanted; /* true if constant wanted */
324 static int nocode_wanted; /* true if no code generation wanted for an expression */
325 static int global_expr; /* true if compound literals must be allocated
326 globally (used during initializers parsing */
327 static CType func_vt; /* current function return type (used by return
328 instruction) */
329 static int func_vc;
330 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
331 static int tok_ident;
332 static TokenSym **table_ident;
333 static TokenSym *hash_ident[TOK_HASH_SIZE];
334 static char token_buf[STRING_MAX_SIZE + 1];
335 static char *funcname;
336 static Sym *global_stack, *local_stack;
337 static Sym *define_stack;
338 static Sym *global_label_stack, *local_label_stack;
340 static SValue vstack[VSTACK_SIZE], *vtop;
341 /* some predefined types */
342 static CType char_pointer_type, func_old_type, int_type;
343 /* true if isid(c) || isnum(c) */
344 static unsigned char isidnum_table[256];
346 /* compile with debug symbol (and use them if error during execution) */
347 static int do_debug = 0;
349 /* compile with built-in memory and bounds checker */
350 static int do_bounds_check = 0;
352 /* display benchmark infos */
353 #if !defined(LIBTCC)
354 static int do_bench = 0;
355 #endif
356 static int total_lines;
357 static int total_bytes;
359 /* use GNU C extensions */
360 static int gnu_ext = 1;
362 /* use Tiny C extensions */
363 static int tcc_ext = 1;
365 /* max number of callers shown if error */
366 static int num_callers = 6;
367 static const char **rt_bound_error_msg;
369 /* XXX: get rid of this ASAP */
370 static struct TCCState *tcc_state;
372 /* give the path of the tcc libraries */
373 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
375 struct TCCState {
376 int output_type;
378 BufferedFile **include_stack_ptr;
379 int *ifdef_stack_ptr;
381 /* include file handling */
382 char **include_paths;
383 int nb_include_paths;
384 char **sysinclude_paths;
385 int nb_sysinclude_paths;
386 CachedInclude **cached_includes;
387 int nb_cached_includes;
389 char **library_paths;
390 int nb_library_paths;
392 /* array of all loaded dlls (including those referenced by loaded
393 dlls) */
394 DLLReference **loaded_dlls;
395 int nb_loaded_dlls;
397 /* sections */
398 Section **sections;
399 int nb_sections; /* number of sections, including first dummy section */
401 /* got handling */
402 Section *got;
403 Section *plt;
404 unsigned long *got_offsets;
405 int nb_got_offsets;
406 /* give the correspondance from symtab indexes to dynsym indexes */
407 int *symtab_to_dynsym;
409 /* temporary dynamic symbol sections (for dll loading) */
410 Section *dynsymtab_section;
411 /* exported dynamic symbol section */
412 Section *dynsym;
414 int nostdinc; /* if true, no standard headers are added */
415 int nostdlib; /* if true, no standard libraries are added */
417 /* if true, static linking is performed */
418 int static_link;
420 /* if true, all symbols are exported */
421 int rdynamic;
423 /* if true, only link in referenced objects from archive */
424 int alacarte_link;
426 /* C language options */
427 int char_is_unsigned;
429 /* warning switches */
430 int warn_write_strings;
431 int warn_unsupported;
432 int warn_error;
433 int warn_none;
434 int warn_implicit_function_declaration;
436 /* error handling */
437 void *error_opaque;
438 void (*error_func)(void *opaque, const char *msg);
439 int error_set_jmp_enabled;
440 jmp_buf error_jmp_buf;
441 int nb_errors;
443 /* tiny assembler state */
444 Sym *asm_labels;
446 /* see include_stack_ptr */
447 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
449 /* see ifdef_stack_ptr */
450 int ifdef_stack[IFDEF_STACK_SIZE];
453 /* The current value can be: */
454 #define VT_VALMASK 0x00ff
455 #define VT_CONST 0x00f0 /* constant in vc
456 (must be first non register value) */
457 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
458 #define VT_LOCAL 0x00f2 /* offset on stack */
459 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
460 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
461 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
462 #define VT_LVAL 0x0100 /* var is an lvalue */
463 #define VT_SYM 0x0200 /* a symbol value is added */
464 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
465 char/short stored in integer registers) */
466 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
467 dereferencing value */
468 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
469 bounding function call point is in vc */
470 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
471 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
472 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
473 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
475 /* types */
476 #define VT_INT 0 /* integer type */
477 #define VT_BYTE 1 /* signed byte type */
478 #define VT_SHORT 2 /* short type */
479 #define VT_VOID 3 /* void type */
480 #define VT_PTR 4 /* pointer */
481 #define VT_ENUM 5 /* enum definition */
482 #define VT_FUNC 6 /* function type */
483 #define VT_STRUCT 7 /* struct/union definition */
484 #define VT_FLOAT 8 /* IEEE float */
485 #define VT_DOUBLE 9 /* IEEE double */
486 #define VT_LDOUBLE 10 /* IEEE long double */
487 #define VT_BOOL 11 /* ISOC99 boolean type */
488 #define VT_LLONG 12 /* 64 bit integer */
489 #define VT_LONG 13 /* long integer (NEVER USED as type, only
490 during parsing) */
491 #define VT_BTYPE 0x000f /* mask for basic type */
492 #define VT_UNSIGNED 0x0010 /* unsigned type */
493 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
494 #define VT_BITFIELD 0x0040 /* bitfield modifier */
495 #define VT_CONSTANT 0x0800 /* const modifier */
496 #define VT_VOLATILE 0x1000 /* volatile modifier */
497 #define VT_SIGNED 0x2000 /* signed type */
499 /* storage */
500 #define VT_EXTERN 0x00000080 /* extern definition */
501 #define VT_STATIC 0x00000100 /* static variable */
502 #define VT_TYPEDEF 0x00000200 /* typedef definition */
503 #define VT_INLINE 0x00000400 /* inline definition */
505 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
507 /* type mask (except storage) */
508 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
509 #define VT_TYPE (~(VT_STORAGE))
511 /* token values */
513 /* warning: the following compare tokens depend on i386 asm code */
514 #define TOK_ULT 0x92
515 #define TOK_UGE 0x93
516 #define TOK_EQ 0x94
517 #define TOK_NE 0x95
518 #define TOK_ULE 0x96
519 #define TOK_UGT 0x97
520 #define TOK_LT 0x9c
521 #define TOK_GE 0x9d
522 #define TOK_LE 0x9e
523 #define TOK_GT 0x9f
525 #define TOK_LAND 0xa0
526 #define TOK_LOR 0xa1
528 #define TOK_DEC 0xa2
529 #define TOK_MID 0xa3 /* inc/dec, to void constant */
530 #define TOK_INC 0xa4
531 #define TOK_UDIV 0xb0 /* unsigned division */
532 #define TOK_UMOD 0xb1 /* unsigned modulo */
533 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
534 #define TOK_CINT 0xb3 /* number in tokc */
535 #define TOK_CCHAR 0xb4 /* char constant in tokc */
536 #define TOK_STR 0xb5 /* pointer to string in tokc */
537 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
538 #define TOK_LCHAR 0xb7
539 #define TOK_LSTR 0xb8
540 #define TOK_CFLOAT 0xb9 /* float constant */
541 #define TOK_LINENUM 0xba /* line number info */
542 #define TOK_CDOUBLE 0xc0 /* double constant */
543 #define TOK_CLDOUBLE 0xc1 /* long double constant */
544 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
545 #define TOK_ADDC1 0xc3 /* add with carry generation */
546 #define TOK_ADDC2 0xc4 /* add with carry use */
547 #define TOK_SUBC1 0xc5 /* add with carry generation */
548 #define TOK_SUBC2 0xc6 /* add with carry use */
549 #define TOK_CUINT 0xc8 /* unsigned int constant */
550 #define TOK_CLLONG 0xc9 /* long long constant */
551 #define TOK_CULLONG 0xca /* unsigned long long constant */
552 #define TOK_ARROW 0xcb
553 #define TOK_DOTS 0xcc /* three dots */
554 #define TOK_SHR 0xcd /* unsigned shift right */
555 #define TOK_PPNUM 0xce /* preprocessor number */
557 #define TOK_SHL 0x01 /* shift left */
558 #define TOK_SAR 0x02 /* signed shift right */
560 /* assignement operators : normal operator or 0x80 */
561 #define TOK_A_MOD 0xa5
562 #define TOK_A_AND 0xa6
563 #define TOK_A_MUL 0xaa
564 #define TOK_A_ADD 0xab
565 #define TOK_A_SUB 0xad
566 #define TOK_A_DIV 0xaf
567 #define TOK_A_XOR 0xde
568 #define TOK_A_OR 0xfc
569 #define TOK_A_SHL 0x81
570 #define TOK_A_SAR 0x82
572 #ifndef offsetof
573 #define offsetof(type, field) ((size_t) &((type *)0)->field)
574 #endif
576 #ifndef countof
577 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
578 #endif
580 /* WARNING: the content of this string encodes token numbers */
581 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";
583 #define TOK_EOF (-1) /* end of file */
584 #define TOK_LINEFEED 10 /* line feed */
586 /* all identificators and strings have token above that */
587 #define TOK_IDENT 256
589 /* only used for i386 asm opcodes definitions */
590 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
592 #define DEF_BWL(x) \
593 DEF(TOK_ASM_ ## x ## b, #x "b") \
594 DEF(TOK_ASM_ ## x ## w, #x "w") \
595 DEF(TOK_ASM_ ## x ## l, #x "l") \
596 DEF(TOK_ASM_ ## x, #x)
598 #define DEF_WL(x) \
599 DEF(TOK_ASM_ ## x ## w, #x "w") \
600 DEF(TOK_ASM_ ## x ## l, #x "l") \
601 DEF(TOK_ASM_ ## x, #x)
603 #define DEF_FP1(x) \
604 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
605 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
606 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
607 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
609 #define DEF_FP(x) \
610 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
611 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
612 DEF_FP1(x)
614 #define DEF_ASMTEST(x) \
615 DEF_ASM(x ## o) \
616 DEF_ASM(x ## no) \
617 DEF_ASM(x ## b) \
618 DEF_ASM(x ## c) \
619 DEF_ASM(x ## nae) \
620 DEF_ASM(x ## nb) \
621 DEF_ASM(x ## nc) \
622 DEF_ASM(x ## ae) \
623 DEF_ASM(x ## e) \
624 DEF_ASM(x ## z) \
625 DEF_ASM(x ## ne) \
626 DEF_ASM(x ## nz) \
627 DEF_ASM(x ## be) \
628 DEF_ASM(x ## na) \
629 DEF_ASM(x ## nbe) \
630 DEF_ASM(x ## a) \
631 DEF_ASM(x ## s) \
632 DEF_ASM(x ## ns) \
633 DEF_ASM(x ## p) \
634 DEF_ASM(x ## pe) \
635 DEF_ASM(x ## np) \
636 DEF_ASM(x ## po) \
637 DEF_ASM(x ## l) \
638 DEF_ASM(x ## nge) \
639 DEF_ASM(x ## nl) \
640 DEF_ASM(x ## ge) \
641 DEF_ASM(x ## le) \
642 DEF_ASM(x ## ng) \
643 DEF_ASM(x ## nle) \
644 DEF_ASM(x ## g)
646 #define TOK_ASM_int TOK_INT
648 enum {
649 TOK_LAST = TOK_IDENT - 1,
650 #define DEF(id, str) id,
651 #include "tcctok.h"
652 #undef DEF
655 static const char tcc_keywords[] =
656 #define DEF(id, str) str "\0"
657 #include "tcctok.h"
658 #undef DEF
661 #define TOK_UIDENT TOK_DEFINE
663 #ifdef WIN32
664 #define snprintf _snprintf
665 #define vsnprintf _vsnprintf
666 #endif
668 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
669 /* currently incorrect */
670 long double strtold(const char *nptr, char **endptr)
672 return (long double)strtod(nptr, endptr);
674 float strtof(const char *nptr, char **endptr)
676 return (float)strtod(nptr, endptr);
678 #else
679 /* XXX: need to define this to use them in non ISOC99 context */
680 extern float strtof (const char *__nptr, char **__endptr);
681 extern long double strtold (const char *__nptr, char **__endptr);
682 #endif
684 static char *pstrcpy(char *buf, int buf_size, const char *s);
685 static char *pstrcat(char *buf, int buf_size, const char *s);
687 static void next(void);
688 static void next_nomacro(void);
689 static void parse_expr_type(CType *type);
690 static void expr_type(CType *type);
691 static void unary_type(CType *type);
692 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
693 int case_reg, int is_expr);
694 static int expr_const(void);
695 static void expr_eq(void);
696 static void gexpr(void);
697 static void decl(int l);
698 static void decl_initializer(CType *type, Section *sec, unsigned long c,
699 int first, int size_only);
700 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
701 int has_init, int v, int scope);
702 int gv(int rc);
703 void gv2(int rc1, int rc2);
704 void move_reg(int r, int s);
705 void save_regs(int n);
706 void save_reg(int r);
707 void vpop(void);
708 void vswap(void);
709 void vdup(void);
710 int get_reg(int rc);
711 int get_reg_ex(int rc,int rc2);
713 static void macro_subst(TokenString *tok_str, Sym **nested_list,
714 const int *macro_str, int can_read_stream);
715 int save_reg_forced(int r);
716 void gen_op(int op);
717 void force_charshort_cast(int t);
718 static void gen_cast(CType *type);
719 void vstore(void);
720 static Sym *sym_find(int v);
721 static Sym *sym_push(int v, CType *type, int r, int c);
723 /* type handling */
724 static int type_size(CType *type, int *a);
725 static inline CType *pointed_type(CType *type);
726 static int pointed_size(CType *type);
727 static int lvalue_type(int t);
728 static int parse_btype(CType *type, AttributeDef *ad);
729 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
730 static int is_compatible_types(CType *type1, CType *type2);
732 int ieee_finite(double d);
733 void error(const char *fmt, ...);
734 void vpushi(int v);
735 void vrott(int n);
736 void vnrott(int n);
737 void lexpand_nr(void);
738 static void vpush_global_sym(CType *type, int v);
739 void vset(CType *type, int r, int v);
740 void type_to_str(char *buf, int buf_size,
741 CType *type, const char *varstr);
742 char *get_tok_str(int v, CValue *cv);
743 static Sym *get_sym_ref(CType *type, Section *sec,
744 unsigned long offset, unsigned long size);
745 static Sym *external_global_sym(int v, CType *type, int r);
747 /* section generation */
748 static void section_realloc(Section *sec, unsigned long new_size);
749 static void *section_ptr_add(Section *sec, unsigned long size);
750 static void put_extern_sym(Sym *sym, Section *section,
751 unsigned long value, unsigned long size);
752 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
753 static int put_elf_str(Section *s, const char *sym);
754 static int put_elf_sym(Section *s,
755 unsigned long value, unsigned long size,
756 int info, int other, int shndx, const char *name);
757 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
758 int info, int sh_num, const char *name);
759 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
760 int type, int symbol);
761 static void put_stabs(const char *str, int type, int other, int desc,
762 unsigned long value);
763 static void put_stabs_r(const char *str, int type, int other, int desc,
764 unsigned long value, Section *sec, int sym_index);
765 static void put_stabn(int type, int other, int desc, int value);
766 static void put_stabd(int type, int other, int desc);
767 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
769 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
770 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
771 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
773 /* tcccoff.c */
774 int tcc_output_coff(TCCState *s1, const char *OutFile);
776 /* tccasm.c */
778 #ifdef CONFIG_TCC_ASM
780 typedef struct ExprValue {
781 uint32_t v;
782 Sym *sym;
783 } ExprValue;
785 #define MAX_ASM_OPERANDS 30
787 typedef struct ASMOperand {
788 int id; /* GCC 3 optionnal identifier (0 if number only supported */
789 char *constraint;
790 char asm_str[16]; /* computed asm string for operand */
791 SValue *vt; /* C value of the expression */
792 int ref_index; /* if >= 0, gives reference to a output constraint */
793 int priority; /* priority, used to assign registers */
794 int reg; /* if >= 0, register number used for this operand */
795 int is_llong; /* true if double register value */
796 } ASMOperand;
798 static void asm_expr(TCCState *s1, ExprValue *pe);
799 static int asm_int_expr(TCCState *s1);
800 static int find_constraint(ASMOperand *operands, int nb_operands,
801 const char *name, const char **pp);
803 static int tcc_assemble(TCCState *s1, int do_preprocess);
805 #endif
807 static void asm_instr(void);
809 /* true if float/double/long double type */
810 static inline int is_float(int t)
812 int bt;
813 bt = t & VT_BTYPE;
814 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
817 #ifdef TCC_TARGET_I386
818 #include "i386-gen.c"
819 #endif
821 #ifdef TCC_TARGET_ARM
822 #include "arm-gen.c"
823 #endif
825 #ifdef TCC_TARGET_C67
826 #include "c67-gen.c"
827 #endif
829 #ifdef CONFIG_TCC_STATIC
831 #define RTLD_LAZY 0x001
832 #define RTLD_NOW 0x002
833 #define RTLD_GLOBAL 0x100
834 #define RTLD_DEFAULT NULL
836 /* dummy function for profiling */
837 void *dlopen(const char *filename, int flag)
839 return NULL;
842 const char *dlerror(void)
844 return "error";
847 typedef struct TCCSyms {
848 char *str;
849 void *ptr;
850 } TCCSyms;
852 #define TCCSYM(a) { #a, &a, },
854 /* add the symbol you want here if no dynamic linking is done */
855 static TCCSyms tcc_syms[] = {
856 TCCSYM(printf)
857 TCCSYM(fprintf)
858 TCCSYM(fopen)
859 TCCSYM(fclose)
860 { NULL, NULL },
863 void *dlsym(void *handle, const char *symbol)
865 TCCSyms *p;
866 p = tcc_syms;
867 while (p->str != NULL) {
868 if (!strcmp(p->str, symbol))
869 return p->ptr;
870 p++;
872 return NULL;
875 #endif
877 /********************************************************/
879 /* we use our own 'finite' function to avoid potential problems with
880 non standard math libs */
881 /* XXX: endianness dependent */
882 int ieee_finite(double d)
884 int *p = (int *)&d;
885 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
888 /* copy a string and truncate it. */
889 static char *pstrcpy(char *buf, int buf_size, const char *s)
891 char *q, *q_end;
892 int c;
894 if (buf_size > 0) {
895 q = buf;
896 q_end = buf + buf_size - 1;
897 while (q < q_end) {
898 c = *s++;
899 if (c == '\0')
900 break;
901 *q++ = c;
903 *q = '\0';
905 return buf;
908 /* strcat and truncate. */
909 static char *pstrcat(char *buf, int buf_size, const char *s)
911 int len;
912 len = strlen(buf);
913 if (len < buf_size)
914 pstrcpy(buf + len, buf_size - len, s);
915 return buf;
918 /* memory management */
919 #ifdef MEM_DEBUG
920 int mem_cur_size;
921 int mem_max_size;
922 #endif
924 static inline void tcc_free(void *ptr)
926 #ifdef MEM_DEBUG
927 mem_cur_size -= malloc_usable_size(ptr);
928 #endif
929 free(ptr);
932 static void *tcc_malloc(unsigned long size)
934 void *ptr;
935 ptr = malloc(size);
936 if (!ptr && size)
937 error("memory full");
938 #ifdef MEM_DEBUG
939 mem_cur_size += malloc_usable_size(ptr);
940 if (mem_cur_size > mem_max_size)
941 mem_max_size = mem_cur_size;
942 #endif
943 return ptr;
946 static void *tcc_mallocz(unsigned long size)
948 void *ptr;
949 ptr = tcc_malloc(size);
950 memset(ptr, 0, size);
951 return ptr;
954 static inline void *tcc_realloc(void *ptr, unsigned long size)
956 void *ptr1;
957 #ifdef MEM_DEBUG
958 mem_cur_size -= malloc_usable_size(ptr);
959 #endif
960 ptr1 = realloc(ptr, size);
961 #ifdef MEM_DEBUG
962 /* NOTE: count not correct if alloc error, but not critical */
963 mem_cur_size += malloc_usable_size(ptr1);
964 if (mem_cur_size > mem_max_size)
965 mem_max_size = mem_cur_size;
966 #endif
967 return ptr1;
970 static char *tcc_strdup(const char *str)
972 char *ptr;
973 ptr = tcc_malloc(strlen(str) + 1);
974 strcpy(ptr, str);
975 return ptr;
978 #define free(p) use_tcc_free(p)
979 #define malloc(s) use_tcc_malloc(s)
980 #define realloc(p, s) use_tcc_realloc(p, s)
982 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
984 int nb, nb_alloc;
985 void **pp;
987 nb = *nb_ptr;
988 pp = *ptab;
989 /* every power of two we double array size */
990 if ((nb & (nb - 1)) == 0) {
991 if (!nb)
992 nb_alloc = 1;
993 else
994 nb_alloc = nb * 2;
995 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
996 if (!pp)
997 error("memory full");
998 *ptab = pp;
1000 pp[nb++] = data;
1001 *nb_ptr = nb;
1004 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1006 Section *sec;
1008 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1009 strcpy(sec->name, name);
1010 sec->sh_type = sh_type;
1011 sec->sh_flags = sh_flags;
1012 switch(sh_type) {
1013 case SHT_HASH:
1014 case SHT_REL:
1015 case SHT_DYNSYM:
1016 case SHT_SYMTAB:
1017 case SHT_DYNAMIC:
1018 sec->sh_addralign = 4;
1019 break;
1020 case SHT_STRTAB:
1021 sec->sh_addralign = 1;
1022 break;
1023 default:
1024 sec->sh_addralign = 32; /* default conservative alignment */
1025 break;
1028 /* only add section if not private */
1029 if (!(sh_flags & SHF_PRIVATE)) {
1030 sec->sh_num = s1->nb_sections;
1031 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1033 return sec;
1036 static void free_section(Section *s)
1038 tcc_free(s->data);
1039 tcc_free(s);
1042 /* realloc section and set its content to zero */
1043 static void section_realloc(Section *sec, unsigned long new_size)
1045 unsigned long size;
1046 unsigned char *data;
1048 size = sec->data_allocated;
1049 if (size == 0)
1050 size = 1;
1051 while (size < new_size)
1052 size = size * 2;
1053 data = tcc_realloc(sec->data, size);
1054 if (!data)
1055 error("memory full");
1056 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1057 sec->data = data;
1058 sec->data_allocated = size;
1061 /* reserve at least 'size' bytes in section 'sec' from
1062 sec->data_offset. */
1063 static void *section_ptr_add(Section *sec, unsigned long size)
1065 unsigned long offset, offset1;
1067 offset = sec->data_offset;
1068 offset1 = offset + size;
1069 if (offset1 > sec->data_allocated)
1070 section_realloc(sec, offset1);
1071 sec->data_offset = offset1;
1072 return sec->data + offset;
1075 /* return a reference to a section, and create it if it does not
1076 exists */
1077 Section *find_section(TCCState *s1, const char *name)
1079 Section *sec;
1080 int i;
1081 for(i = 1; i < s1->nb_sections; i++) {
1082 sec = s1->sections[i];
1083 if (!strcmp(name, sec->name))
1084 return sec;
1086 /* sections are created as PROGBITS */
1087 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1090 /* update sym->c so that it points to an external symbol in section
1091 'section' with value 'value' */
1092 static void put_extern_sym(Sym *sym, Section *section,
1093 unsigned long value, unsigned long size)
1095 int sym_type, sym_bind, sh_num, info;
1096 Elf32_Sym *esym;
1097 const char *name;
1099 if (section)
1100 sh_num = section->sh_num;
1101 else
1102 sh_num = SHN_UNDEF;
1103 if (!sym->c) {
1104 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1105 sym_type = STT_FUNC;
1106 else
1107 sym_type = STT_OBJECT;
1108 if (sym->type.t & VT_STATIC)
1109 sym_bind = STB_LOCAL;
1110 else
1111 sym_bind = STB_GLOBAL;
1113 name = get_tok_str(sym->v, NULL);
1114 #ifdef CONFIG_TCC_BCHECK
1115 if (do_bounds_check) {
1116 char buf[32];
1118 /* XXX: avoid doing that for statics ? */
1119 /* if bound checking is activated, we change some function
1120 names by adding the "__bound" prefix */
1121 switch(sym->v) {
1122 #if 0
1123 /* XXX: we rely only on malloc hooks */
1124 case TOK_malloc:
1125 case TOK_free:
1126 case TOK_realloc:
1127 case TOK_memalign:
1128 case TOK_calloc:
1129 #endif
1130 case TOK_memcpy:
1131 case TOK_memmove:
1132 case TOK_memset:
1133 case TOK_strlen:
1134 case TOK_strcpy:
1135 strcpy(buf, "__bound_");
1136 strcat(buf, name);
1137 name = buf;
1138 break;
1141 #endif
1142 info = ELF32_ST_INFO(sym_bind, sym_type);
1143 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1144 } else {
1145 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1146 esym->st_value = value;
1147 esym->st_size = size;
1148 esym->st_shndx = sh_num;
1152 /* add a new relocation entry to symbol 'sym' in section 's' */
1153 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1155 if (!sym->c)
1156 put_extern_sym(sym, NULL, 0, 0);
1157 /* now we can add ELF relocation info */
1158 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1161 static inline int isid(int c)
1163 return (c >= 'a' && c <= 'z') ||
1164 (c >= 'A' && c <= 'Z') ||
1165 c == '_';
1168 static inline int isnum(int c)
1170 return c >= '0' && c <= '9';
1173 static inline int isoct(int c)
1175 return c >= '0' && c <= '7';
1178 static inline int toup(int c)
1180 if (c >= 'a' && c <= 'z')
1181 return c - 'a' + 'A';
1182 else
1183 return c;
1186 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1188 int len;
1189 len = strlen(buf);
1190 vsnprintf(buf + len, buf_size - len, fmt, ap);
1193 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1195 va_list ap;
1196 va_start(ap, fmt);
1197 strcat_vprintf(buf, buf_size, fmt, ap);
1198 va_end(ap);
1201 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1203 char buf[2048];
1204 BufferedFile **f;
1206 buf[0] = '\0';
1207 if (file) {
1208 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1209 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1210 (*f)->filename, (*f)->line_num);
1211 if (file->line_num > 0) {
1212 strcat_printf(buf, sizeof(buf),
1213 "%s:%d: ", file->filename, file->line_num);
1214 } else {
1215 strcat_printf(buf, sizeof(buf),
1216 "%s: ", file->filename);
1218 } else {
1219 strcat_printf(buf, sizeof(buf),
1220 "tcc: ");
1222 if (is_warning)
1223 strcat_printf(buf, sizeof(buf), "warning: ");
1224 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1226 if (!s1->error_func) {
1227 /* default case: stderr */
1228 fprintf(stderr, "%s\n", buf);
1229 } else {
1230 s1->error_func(s1->error_opaque, buf);
1232 if (!is_warning || s1->warn_error)
1233 s1->nb_errors++;
1236 #ifdef LIBTCC
1237 void tcc_set_error_func(TCCState *s, void *error_opaque,
1238 void (*error_func)(void *opaque, const char *msg))
1240 s->error_opaque = error_opaque;
1241 s->error_func = error_func;
1243 #endif
1245 /* error without aborting current compilation */
1246 void error_noabort(const char *fmt, ...)
1248 TCCState *s1 = tcc_state;
1249 va_list ap;
1251 va_start(ap, fmt);
1252 error1(s1, 0, fmt, ap);
1253 va_end(ap);
1256 void error(const char *fmt, ...)
1258 TCCState *s1 = tcc_state;
1259 va_list ap;
1261 va_start(ap, fmt);
1262 error1(s1, 0, fmt, ap);
1263 va_end(ap);
1264 /* better than nothing: in some cases, we accept to handle errors */
1265 if (s1->error_set_jmp_enabled) {
1266 longjmp(s1->error_jmp_buf, 1);
1267 } else {
1268 /* XXX: eliminate this someday */
1269 exit(1);
1273 void expect(const char *msg)
1275 error("%s expected", msg);
1278 void warning(const char *fmt, ...)
1280 TCCState *s1 = tcc_state;
1281 va_list ap;
1283 if (s1->warn_none)
1284 return;
1286 va_start(ap, fmt);
1287 error1(s1, 1, fmt, ap);
1288 va_end(ap);
1291 void skip(int c)
1293 if (tok != c)
1294 error("'%c' expected", c);
1295 next();
1298 static void test_lvalue(void)
1300 if (!(vtop->r & VT_LVAL))
1301 expect("lvalue");
1304 /* allocate a new token */
1305 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1307 TokenSym *ts, **ptable;
1308 int i;
1310 if (tok_ident >= SYM_FIRST_ANOM)
1311 error("memory full");
1313 /* expand token table if needed */
1314 i = tok_ident - TOK_IDENT;
1315 if ((i % TOK_ALLOC_INCR) == 0) {
1316 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1317 if (!ptable)
1318 error("memory full");
1319 table_ident = ptable;
1322 ts = tcc_malloc(sizeof(TokenSym) + len);
1323 table_ident[i] = ts;
1324 ts->tok = tok_ident++;
1325 ts->sym_define = NULL;
1326 ts->sym_label = NULL;
1327 ts->sym_struct = NULL;
1328 ts->sym_identifier = NULL;
1329 ts->len = len;
1330 ts->hash_next = NULL;
1331 memcpy(ts->str, str, len);
1332 ts->str[len] = '\0';
1333 *pts = ts;
1334 return ts;
1337 #define TOK_HASH_INIT 1
1338 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1340 /* find a token and add it if not found */
1341 static TokenSym *tok_alloc(const char *str, int len)
1343 TokenSym *ts, **pts;
1344 int i;
1345 unsigned int h;
1347 h = TOK_HASH_INIT;
1348 for(i=0;i<len;i++)
1349 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1350 h &= (TOK_HASH_SIZE - 1);
1352 pts = &hash_ident[h];
1353 for(;;) {
1354 ts = *pts;
1355 if (!ts)
1356 break;
1357 if (ts->len == len && !memcmp(ts->str, str, len))
1358 return ts;
1359 pts = &(ts->hash_next);
1361 return tok_alloc_new(pts, str, len);
1364 /* CString handling */
1366 static void cstr_realloc(CString *cstr, int new_size)
1368 int size;
1369 void *data;
1371 size = cstr->size_allocated;
1372 if (size == 0)
1373 size = 8; /* no need to allocate a too small first string */
1374 while (size < new_size)
1375 size = size * 2;
1376 data = tcc_realloc(cstr->data_allocated, size);
1377 if (!data)
1378 error("memory full");
1379 cstr->data_allocated = data;
1380 cstr->size_allocated = size;
1381 cstr->data = data;
1384 /* add a byte */
1385 static void cstr_ccat(CString *cstr, int ch)
1387 int size;
1388 size = cstr->size + 1;
1389 if (size > cstr->size_allocated)
1390 cstr_realloc(cstr, size);
1391 ((unsigned char *)cstr->data)[size - 1] = ch;
1392 cstr->size = size;
1395 static void cstr_cat(CString *cstr, const char *str)
1397 int c;
1398 for(;;) {
1399 c = *str;
1400 if (c == '\0')
1401 break;
1402 cstr_ccat(cstr, c);
1403 str++;
1407 /* add a wide char */
1408 static void cstr_wccat(CString *cstr, int ch)
1410 int size;
1411 size = cstr->size + sizeof(int);
1412 if (size > cstr->size_allocated)
1413 cstr_realloc(cstr, size);
1414 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1415 cstr->size = size;
1418 static void cstr_new(CString *cstr)
1420 memset(cstr, 0, sizeof(CString));
1423 /* free string and reset it to NULL */
1424 static void cstr_free(CString *cstr)
1426 tcc_free(cstr->data_allocated);
1427 cstr_new(cstr);
1430 #define cstr_reset(cstr) cstr_free(cstr)
1432 static CString *cstr_dup(CString *cstr1)
1434 CString *cstr;
1435 int size;
1437 cstr = tcc_malloc(sizeof(CString));
1438 size = cstr1->size;
1439 cstr->size = size;
1440 cstr->size_allocated = size;
1441 cstr->data_allocated = tcc_malloc(size);
1442 cstr->data = cstr->data_allocated;
1443 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1444 return cstr;
1447 /* XXX: unicode ? */
1448 static void add_char(CString *cstr, int c)
1450 if (c == '\'' || c == '\"' || c == '\\') {
1451 /* XXX: could be more precise if char or string */
1452 cstr_ccat(cstr, '\\');
1454 if (c >= 32 && c <= 126) {
1455 cstr_ccat(cstr, c);
1456 } else {
1457 cstr_ccat(cstr, '\\');
1458 if (c == '\n') {
1459 cstr_ccat(cstr, 'n');
1460 } else {
1461 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1462 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1463 cstr_ccat(cstr, '0' + (c & 7));
1468 /* XXX: buffer overflow */
1469 /* XXX: float tokens */
1470 char *get_tok_str(int v, CValue *cv)
1472 static char buf[STRING_MAX_SIZE + 1];
1473 static CString cstr_buf;
1474 CString *cstr;
1475 unsigned char *q;
1476 char *p;
1477 int i, len;
1479 /* NOTE: to go faster, we give a fixed buffer for small strings */
1480 cstr_reset(&cstr_buf);
1481 cstr_buf.data = buf;
1482 cstr_buf.size_allocated = sizeof(buf);
1483 p = buf;
1485 switch(v) {
1486 case TOK_CINT:
1487 case TOK_CUINT:
1488 /* XXX: not quite exact, but only useful for testing */
1489 sprintf(p, "%u", cv->ui);
1490 break;
1491 case TOK_CLLONG:
1492 case TOK_CULLONG:
1493 /* XXX: not quite exact, but only useful for testing */
1494 sprintf(p, "%Lu", cv->ull);
1495 break;
1496 case TOK_CCHAR:
1497 case TOK_LCHAR:
1498 cstr_ccat(&cstr_buf, '\'');
1499 add_char(&cstr_buf, cv->i);
1500 cstr_ccat(&cstr_buf, '\'');
1501 cstr_ccat(&cstr_buf, '\0');
1502 break;
1503 case TOK_PPNUM:
1504 cstr = cv->cstr;
1505 len = cstr->size - 1;
1506 for(i=0;i<len;i++)
1507 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1508 cstr_ccat(&cstr_buf, '\0');
1509 break;
1510 case TOK_STR:
1511 case TOK_LSTR:
1512 cstr = cv->cstr;
1513 cstr_ccat(&cstr_buf, '\"');
1514 if (v == TOK_STR) {
1515 len = cstr->size - 1;
1516 for(i=0;i<len;i++)
1517 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1518 } else {
1519 len = (cstr->size / sizeof(int)) - 1;
1520 for(i=0;i<len;i++)
1521 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1523 cstr_ccat(&cstr_buf, '\"');
1524 cstr_ccat(&cstr_buf, '\0');
1525 break;
1526 case TOK_LT:
1527 v = '<';
1528 goto addv;
1529 case TOK_GT:
1530 v = '>';
1531 goto addv;
1532 case TOK_A_SHL:
1533 return strcpy(p, "<<=");
1534 case TOK_A_SAR:
1535 return strcpy(p, ">>=");
1536 default:
1537 if (v < TOK_IDENT) {
1538 /* search in two bytes table */
1539 q = tok_two_chars;
1540 while (*q) {
1541 if (q[2] == v) {
1542 *p++ = q[0];
1543 *p++ = q[1];
1544 *p = '\0';
1545 return buf;
1547 q += 3;
1549 addv:
1550 *p++ = v;
1551 *p = '\0';
1552 } else if (v < tok_ident) {
1553 return table_ident[v - TOK_IDENT]->str;
1554 } else if (v >= SYM_FIRST_ANOM) {
1555 /* special name for anonymous symbol */
1556 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1557 } else {
1558 /* should never happen */
1559 return NULL;
1561 break;
1563 return cstr_buf.data;
1566 /* push, without hashing */
1567 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1569 Sym *s;
1570 s = tcc_malloc(sizeof(Sym));
1571 s->v = v;
1572 s->type.t = t;
1573 s->c = c;
1574 s->next = NULL;
1575 /* add in stack */
1576 s->prev = *ps;
1577 *ps = s;
1578 return s;
1581 /* find a symbol and return its associated structure. 's' is the top
1582 of the symbol stack */
1583 static Sym *sym_find2(Sym *s, int v)
1585 while (s) {
1586 if (s->v == v)
1587 return s;
1588 s = s->prev;
1590 return NULL;
1593 /* structure lookup */
1594 static inline Sym *struct_find(int v)
1596 v -= TOK_IDENT;
1597 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1598 return NULL;
1599 return table_ident[v]->sym_struct;
1602 /* find an identifier */
1603 static inline Sym *sym_find(int v)
1605 v -= TOK_IDENT;
1606 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1607 return NULL;
1608 return table_ident[v]->sym_identifier;
1611 /* push a given symbol on the symbol stack */
1612 static Sym *sym_push(int v, CType *type, int r, int c)
1614 Sym *s, **ps;
1615 TokenSym *ts;
1617 if (local_stack)
1618 ps = &local_stack;
1619 else
1620 ps = &global_stack;
1621 s = sym_push2(ps, v, type->t, c);
1622 s->type.ref = type->ref;
1623 s->r = r;
1624 /* don't record fields or anonymous symbols */
1625 /* XXX: simplify */
1626 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1627 /* record symbol in token array */
1628 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1629 if (v & SYM_STRUCT)
1630 ps = &ts->sym_struct;
1631 else
1632 ps = &ts->sym_identifier;
1633 s->prev_tok = *ps;
1634 *ps = s;
1636 return s;
1639 /* push a global identifier */
1640 static Sym *global_identifier_push(int v, int t, int c)
1642 Sym *s, **ps;
1643 s = sym_push2(&global_stack, v, t, c);
1644 /* don't record anonymous symbol */
1645 if (v < SYM_FIRST_ANOM) {
1646 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1647 /* modify the top most local identifier, so that
1648 sym_identifier will point to 's' when popped */
1649 while (*ps != NULL)
1650 ps = &(*ps)->prev_tok;
1651 s->prev_tok = NULL;
1652 *ps = s;
1654 return s;
1657 /* pop symbols until top reaches 'b' */
1658 static void sym_pop(Sym **ptop, Sym *b)
1660 Sym *s, *ss, **ps;
1661 TokenSym *ts;
1662 int v;
1664 s = *ptop;
1665 while(s != b) {
1666 ss = s->prev;
1667 v = s->v;
1668 /* remove symbol in token array */
1669 /* XXX: simplify */
1670 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1671 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1672 if (v & SYM_STRUCT)
1673 ps = &ts->sym_struct;
1674 else
1675 ps = &ts->sym_identifier;
1676 *ps = s->prev_tok;
1678 tcc_free(s);
1679 s = ss;
1681 *ptop = b;
1684 /* I/O layer */
1686 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1688 int fd;
1689 BufferedFile *bf;
1691 fd = open(filename, O_RDONLY);
1692 if (fd < 0)
1693 return NULL;
1694 bf = tcc_malloc(sizeof(BufferedFile));
1695 if (!bf) {
1696 close(fd);
1697 return NULL;
1699 bf->fd = fd;
1700 bf->buf_ptr = bf->buffer;
1701 bf->buf_end = bf->buffer;
1702 bf->buffer[0] = CH_EOB; /* put eob symbol */
1703 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1704 bf->line_num = 1;
1705 bf->ifndef_macro = 0;
1706 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1707 // printf("opening '%s'\n", filename);
1708 return bf;
1711 void tcc_close(BufferedFile *bf)
1713 total_lines += bf->line_num;
1714 close(bf->fd);
1715 tcc_free(bf);
1718 /* fill input buffer and peek next char */
1719 static int tcc_peekc_slow(BufferedFile *bf)
1721 int len;
1722 /* only tries to read if really end of buffer */
1723 if (bf->buf_ptr >= bf->buf_end) {
1724 if (bf->fd != -1) {
1725 #if defined(PARSE_DEBUG)
1726 len = 8;
1727 #else
1728 len = IO_BUF_SIZE;
1729 #endif
1730 len = read(bf->fd, bf->buffer, len);
1731 if (len < 0)
1732 len = 0;
1733 } else {
1734 len = 0;
1736 total_bytes += len;
1737 bf->buf_ptr = bf->buffer;
1738 bf->buf_end = bf->buffer + len;
1739 *bf->buf_end = CH_EOB;
1741 if (bf->buf_ptr < bf->buf_end) {
1742 return bf->buf_ptr[0];
1743 } else {
1744 bf->buf_ptr = bf->buf_end;
1745 return CH_EOF;
1749 /* return the current character, handling end of block if necessary
1750 (but not stray) */
1751 static int handle_eob(void)
1753 return tcc_peekc_slow(file);
1756 /* read next char from current input file and handle end of input buffer */
1757 static inline void inp(void)
1759 ch = *(++(file->buf_ptr));
1760 /* end of buffer/file handling */
1761 if (ch == CH_EOB)
1762 ch = handle_eob();
1765 /* handle '\[\r]\n' */
1766 static void handle_stray(void)
1768 while (ch == '\\') {
1769 inp();
1770 if (ch == '\n') {
1771 file->line_num++;
1772 inp();
1773 } else if (ch == '\r') {
1774 inp();
1775 if (ch != '\n')
1776 goto fail;
1777 file->line_num++;
1778 inp();
1779 } else {
1780 fail:
1781 error("stray '\\' in program");
1786 /* skip the stray and handle the \\n case. Output an error if
1787 incorrect char after the stray */
1788 static int handle_stray1(uint8_t *p)
1790 int c;
1792 if (p >= file->buf_end) {
1793 file->buf_ptr = p;
1794 c = handle_eob();
1795 p = file->buf_ptr;
1796 if (c == '\\')
1797 goto parse_stray;
1798 } else {
1799 parse_stray:
1800 file->buf_ptr = p;
1801 ch = *p;
1802 handle_stray();
1803 p = file->buf_ptr;
1804 c = *p;
1806 return c;
1809 /* handle just the EOB case, but not stray */
1810 #define PEEKC_EOB(c, p)\
1812 p++;\
1813 c = *p;\
1814 if (c == '\\') {\
1815 file->buf_ptr = p;\
1816 c = handle_eob();\
1817 p = file->buf_ptr;\
1821 /* handle the complicated stray case */
1822 #define PEEKC(c, p)\
1824 p++;\
1825 c = *p;\
1826 if (c == '\\') {\
1827 c = handle_stray1(p);\
1828 p = file->buf_ptr;\
1832 /* input with '\[\r]\n' handling. Note that this function cannot
1833 handle other characters after '\', so you cannot call it inside
1834 strings or comments */
1835 static void minp(void)
1837 inp();
1838 if (ch == '\\')
1839 handle_stray();
1843 /* single line C++ comments */
1844 static uint8_t *parse_line_comment(uint8_t *p)
1846 int c;
1848 p++;
1849 for(;;) {
1850 c = *p;
1851 redo:
1852 if (c == '\n' || c == CH_EOF) {
1853 break;
1854 } else if (c == '\\') {
1855 file->buf_ptr = p;
1856 c = handle_eob();
1857 p = file->buf_ptr;
1858 if (c == '\\') {
1859 PEEKC_EOB(c, p);
1860 if (c == '\n') {
1861 file->line_num++;
1862 PEEKC_EOB(c, p);
1863 } else if (c == '\r') {
1864 PEEKC_EOB(c, p);
1865 if (c == '\n') {
1866 file->line_num++;
1867 PEEKC_EOB(c, p);
1870 } else {
1871 goto redo;
1873 } else {
1874 p++;
1877 return p;
1880 /* C comments */
1881 static uint8_t *parse_comment(uint8_t *p)
1883 int c;
1885 p++;
1886 for(;;) {
1887 /* fast skip loop */
1888 for(;;) {
1889 c = *p;
1890 if (c == '\n' || c == '*' || c == '\\')
1891 break;
1892 p++;
1893 c = *p;
1894 if (c == '\n' || c == '*' || c == '\\')
1895 break;
1896 p++;
1898 /* now we can handle all the cases */
1899 if (c == '\n') {
1900 file->line_num++;
1901 p++;
1902 } else if (c == '*') {
1903 p++;
1904 for(;;) {
1905 c = *p;
1906 if (c == '*') {
1907 p++;
1908 } else if (c == '/') {
1909 goto end_of_comment;
1910 } else if (c == '\\') {
1911 file->buf_ptr = p;
1912 c = handle_eob();
1913 p = file->buf_ptr;
1914 if (c == '\\') {
1915 /* skip '\[\r]\n', otherwise just skip the stray */
1916 while (c == '\\') {
1917 PEEKC_EOB(c, p);
1918 if (c == '\n') {
1919 file->line_num++;
1920 PEEKC_EOB(c, p);
1921 } else if (c == '\r') {
1922 PEEKC_EOB(c, p);
1923 if (c == '\n') {
1924 file->line_num++;
1925 PEEKC_EOB(c, p);
1927 } else {
1928 goto after_star;
1932 } else {
1933 break;
1936 after_star: ;
1937 } else {
1938 /* stray, eob or eof */
1939 file->buf_ptr = p;
1940 c = handle_eob();
1941 p = file->buf_ptr;
1942 if (c == CH_EOF) {
1943 error("unexpected end of file in comment");
1944 } else if (c == '\\') {
1945 p++;
1949 end_of_comment:
1950 p++;
1951 return p;
1954 #define cinp minp
1956 /* space exlcuding newline */
1957 static inline int is_space(int ch)
1959 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1962 static inline void skip_spaces(void)
1964 while (is_space(ch))
1965 cinp();
1968 /* parse a string without interpreting escapes */
1969 static uint8_t *parse_pp_string(uint8_t *p,
1970 int sep, CString *str)
1972 int c;
1973 p++;
1974 for(;;) {
1975 c = *p;
1976 if (c == sep) {
1977 break;
1978 } else if (c == '\\') {
1979 file->buf_ptr = p;
1980 c = handle_eob();
1981 p = file->buf_ptr;
1982 if (c == CH_EOF) {
1983 unterminated_string:
1984 /* XXX: indicate line number of start of string */
1985 error("missing terminating %c character", sep);
1986 } else if (c == '\\') {
1987 /* escape : just skip \[\r]\n */
1988 PEEKC_EOB(c, p);
1989 if (c == '\n') {
1990 file->line_num++;
1991 p++;
1992 } else if (c == '\r') {
1993 PEEKC_EOB(c, p);
1994 if (c != '\n')
1995 expect("'\n' after '\r'");
1996 file->line_num++;
1997 p++;
1998 } else if (c == CH_EOF) {
1999 goto unterminated_string;
2000 } else {
2001 if (str) {
2002 cstr_ccat(str, '\\');
2003 cstr_ccat(str, c);
2005 p++;
2008 } else if (c == '\n') {
2009 file->line_num++;
2010 goto add_char;
2011 } else if (c == '\r') {
2012 PEEKC_EOB(c, p);
2013 if (c != '\n') {
2014 cstr_ccat(str, '\r');
2015 } else {
2016 file->line_num++;
2017 goto add_char;
2019 } else {
2020 add_char:
2021 if (str)
2022 cstr_ccat(str, c);
2023 p++;
2026 p++;
2027 return p;
2030 /* skip block of text until #else, #elif or #endif. skip also pairs of
2031 #if/#endif */
2032 void preprocess_skip(void)
2034 int a, start_of_line, c;
2035 uint8_t *p;
2037 p = file->buf_ptr;
2038 start_of_line = 1;
2039 a = 0;
2040 for(;;) {
2041 redo_no_start:
2042 c = *p;
2043 switch(c) {
2044 case ' ':
2045 case '\t':
2046 case '\f':
2047 case '\v':
2048 case '\r':
2049 p++;
2050 goto redo_no_start;
2051 case '\n':
2052 start_of_line = 1;
2053 file->line_num++;
2054 p++;
2055 goto redo_no_start;
2056 case '\\':
2057 file->buf_ptr = p;
2058 c = handle_eob();
2059 if (c == CH_EOF) {
2060 expect("#endif");
2061 } else if (c == '\\') {
2062 /* XXX: incorrect: should not give an error */
2063 ch = file->buf_ptr[0];
2064 handle_stray();
2066 p = file->buf_ptr;
2067 goto redo_no_start;
2068 /* skip strings */
2069 case '\"':
2070 case '\'':
2071 p = parse_pp_string(p, c, NULL);
2072 break;
2073 /* skip comments */
2074 case '/':
2075 file->buf_ptr = p;
2076 ch = *p;
2077 minp();
2078 p = file->buf_ptr;
2079 if (ch == '*') {
2080 p = parse_comment(p);
2081 } else if (ch == '/') {
2082 p = parse_line_comment(p);
2084 break;
2086 case '#':
2087 p++;
2088 if (start_of_line) {
2089 file->buf_ptr = p;
2090 next_nomacro();
2091 p = file->buf_ptr;
2092 if (a == 0 &&
2093 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2094 goto the_end;
2095 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2096 a++;
2097 else if (tok == TOK_ENDIF)
2098 a--;
2100 break;
2101 default:
2102 p++;
2103 break;
2105 start_of_line = 0;
2107 the_end: ;
2108 file->buf_ptr = p;
2111 /* ParseState handling */
2113 /* XXX: currently, no include file info is stored. Thus, we cannot display
2114 accurate messages if the function or data definition spans multiple
2115 files */
2117 /* save current parse state in 's' */
2118 void save_parse_state(ParseState *s)
2120 s->line_num = file->line_num;
2121 s->macro_ptr = macro_ptr;
2122 s->tok = tok;
2123 s->tokc = tokc;
2126 /* restore parse state from 's' */
2127 void restore_parse_state(ParseState *s)
2129 file->line_num = s->line_num;
2130 macro_ptr = s->macro_ptr;
2131 tok = s->tok;
2132 tokc = s->tokc;
2135 /* return the number of additional 'ints' necessary to store the
2136 token */
2137 static inline int tok_ext_size(int t)
2139 switch(t) {
2140 /* 4 bytes */
2141 case TOK_CINT:
2142 case TOK_CUINT:
2143 case TOK_CCHAR:
2144 case TOK_LCHAR:
2145 case TOK_STR:
2146 case TOK_LSTR:
2147 case TOK_CFLOAT:
2148 case TOK_LINENUM:
2149 case TOK_PPNUM:
2150 return 1;
2151 case TOK_CDOUBLE:
2152 case TOK_CLLONG:
2153 case TOK_CULLONG:
2154 return 2;
2155 case TOK_CLDOUBLE:
2156 return LDOUBLE_SIZE / 4;
2157 default:
2158 return 0;
2162 /* token string handling */
2164 static inline void tok_str_new(TokenString *s)
2166 s->str = NULL;
2167 s->len = 0;
2168 s->allocated_len = 0;
2169 s->last_line_num = -1;
2172 static void tok_str_free(int *str)
2174 const int *p;
2175 CString *cstr;
2176 int t;
2178 p = str;
2179 for(;;) {
2180 t = *p;
2181 /* NOTE: we test zero separately so that GCC can generate a
2182 table for the following switch */
2183 if (t == 0)
2184 break;
2185 switch(t) {
2186 case TOK_CINT:
2187 case TOK_CUINT:
2188 case TOK_CCHAR:
2189 case TOK_LCHAR:
2190 case TOK_CFLOAT:
2191 case TOK_LINENUM:
2192 p += 2;
2193 break;
2194 case TOK_PPNUM:
2195 case TOK_STR:
2196 case TOK_LSTR:
2197 /* XXX: use a macro to be portable on 64 bit ? */
2198 cstr = (CString *)p[1];
2199 cstr_free(cstr);
2200 tcc_free(cstr);
2201 p += 2;
2202 break;
2203 case TOK_CDOUBLE:
2204 case TOK_CLLONG:
2205 case TOK_CULLONG:
2206 p += 3;
2207 break;
2208 case TOK_CLDOUBLE:
2209 p += 1 + (LDOUBLE_SIZE / 4);
2210 break;
2211 default:
2212 p++;
2213 break;
2216 tcc_free(str);
2219 static int *tok_str_realloc(TokenString *s)
2221 int *str, len;
2223 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2224 str = tcc_realloc(s->str, len * sizeof(int));
2225 if (!str)
2226 error("memory full");
2227 s->allocated_len = len;
2228 s->str = str;
2229 return str;
2232 static void tok_str_add(TokenString *s, int t)
2234 int len, *str;
2236 len = s->len;
2237 str = s->str;
2238 if (len >= s->allocated_len)
2239 str = tok_str_realloc(s);
2240 str[len++] = t;
2241 s->len = len;
2244 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2246 int len, *str;
2248 len = s->len;
2249 str = s->str;
2251 /* allocate space for worst case */
2252 if (len + TOK_MAX_SIZE > s->allocated_len)
2253 str = tok_str_realloc(s);
2254 str[len++] = t;
2255 switch(t) {
2256 case TOK_CINT:
2257 case TOK_CUINT:
2258 case TOK_CCHAR:
2259 case TOK_LCHAR:
2260 case TOK_CFLOAT:
2261 case TOK_LINENUM:
2262 str[len++] = cv->tab[0];
2263 break;
2264 case TOK_PPNUM:
2265 case TOK_STR:
2266 case TOK_LSTR:
2267 str[len++] = (int)cstr_dup(cv->cstr);
2268 break;
2269 case TOK_CDOUBLE:
2270 case TOK_CLLONG:
2271 case TOK_CULLONG:
2272 #if LDOUBLE_SIZE == 8
2273 case TOK_CLDOUBLE:
2274 #endif
2275 str[len++] = cv->tab[0];
2276 str[len++] = cv->tab[1];
2277 break;
2278 #if LDOUBLE_SIZE == 12
2279 case TOK_CLDOUBLE:
2280 str[len++] = cv->tab[0];
2281 str[len++] = cv->tab[1];
2282 str[len++] = cv->tab[2];
2283 #elif LDOUBLE_SIZE != 8
2284 #error add long double size support
2285 #endif
2286 break;
2287 default:
2288 break;
2290 s->len = len;
2293 /* add the current parse token in token string 's' */
2294 static void tok_str_add_tok(TokenString *s)
2296 CValue cval;
2298 /* save line number info */
2299 if (file->line_num != s->last_line_num) {
2300 s->last_line_num = file->line_num;
2301 cval.i = s->last_line_num;
2302 tok_str_add2(s, TOK_LINENUM, &cval);
2304 tok_str_add2(s, tok, &tokc);
2307 #if LDOUBLE_SIZE == 12
2308 #define LDOUBLE_GET(p, cv) \
2309 cv.tab[0] = p[0]; \
2310 cv.tab[1] = p[1]; \
2311 cv.tab[2] = p[2];
2312 #elif LDOUBLE_SIZE == 8
2313 #define LDOUBLE_GET(p, cv) \
2314 cv.tab[0] = p[0]; \
2315 cv.tab[1] = p[1];
2316 #else
2317 #error add long double size support
2318 #endif
2321 /* get a token from an integer array and increment pointer
2322 accordingly. we code it as a macro to avoid pointer aliasing. */
2323 #define TOK_GET(t, p, cv) \
2325 t = *p++; \
2326 switch(t) { \
2327 case TOK_CINT: \
2328 case TOK_CUINT: \
2329 case TOK_CCHAR: \
2330 case TOK_LCHAR: \
2331 case TOK_CFLOAT: \
2332 case TOK_LINENUM: \
2333 case TOK_STR: \
2334 case TOK_LSTR: \
2335 case TOK_PPNUM: \
2336 cv.tab[0] = *p++; \
2337 break; \
2338 case TOK_CDOUBLE: \
2339 case TOK_CLLONG: \
2340 case TOK_CULLONG: \
2341 cv.tab[0] = p[0]; \
2342 cv.tab[1] = p[1]; \
2343 p += 2; \
2344 break; \
2345 case TOK_CLDOUBLE: \
2346 LDOUBLE_GET(p, cv); \
2347 p += LDOUBLE_SIZE / 4; \
2348 break; \
2349 default: \
2350 break; \
2354 /* defines handling */
2355 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2357 Sym *s;
2359 s = sym_push2(&define_stack, v, macro_type, (int)str);
2360 s->next = first_arg;
2361 table_ident[v - TOK_IDENT]->sym_define = s;
2364 /* undefined a define symbol. Its name is just set to zero */
2365 static void define_undef(Sym *s)
2367 int v;
2368 v = s->v;
2369 if (v >= TOK_IDENT && v < tok_ident)
2370 table_ident[v - TOK_IDENT]->sym_define = NULL;
2371 s->v = 0;
2374 static inline Sym *define_find(int v)
2376 v -= TOK_IDENT;
2377 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2378 return NULL;
2379 return table_ident[v]->sym_define;
2382 /* free define stack until top reaches 'b' */
2383 static void free_defines(Sym *b)
2385 Sym *top, *top1;
2386 int v;
2388 top = define_stack;
2389 while (top != b) {
2390 top1 = top->prev;
2391 /* do not free args or predefined defines */
2392 if (top->c)
2393 tok_str_free((int *)top->c);
2394 v = top->v;
2395 if (v >= TOK_IDENT && v < tok_ident)
2396 table_ident[v - TOK_IDENT]->sym_define = NULL;
2397 tcc_free(top);
2398 top = top1;
2400 define_stack = b;
2403 /* label lookup */
2404 static Sym *label_find(int v)
2406 v -= TOK_IDENT;
2407 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2408 return NULL;
2409 return table_ident[v]->sym_label;
2412 static Sym *label_push(Sym **ptop, int v, int flags)
2414 Sym *s, **ps;
2415 s = sym_push2(ptop, v, 0, 0);
2416 s->r = flags;
2417 ps = &table_ident[v - TOK_IDENT]->sym_label;
2418 if (ptop == &global_label_stack) {
2419 /* modify the top most local identifier, so that
2420 sym_identifier will point to 's' when popped */
2421 while (*ps != NULL)
2422 ps = &(*ps)->prev_tok;
2424 s->prev_tok = *ps;
2425 *ps = s;
2426 return s;
2429 /* pop labels until element last is reached. Look if any labels are
2430 undefined. Define symbols if '&&label' was used. */
2431 static void label_pop(Sym **ptop, Sym *slast)
2433 Sym *s, *s1;
2434 for(s = *ptop; s != slast; s = s1) {
2435 s1 = s->prev;
2436 if (s->r == LABEL_DECLARED) {
2437 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2438 } else if (s->r == LABEL_FORWARD) {
2439 error("label '%s' used but not defined",
2440 get_tok_str(s->v, NULL));
2441 } else {
2442 if (s->c) {
2443 /* define corresponding symbol. A size of
2444 1 is put. */
2445 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2448 /* remove label */
2449 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2450 tcc_free(s);
2452 *ptop = slast;
2455 /* eval an expression for #if/#elif */
2456 static int expr_preprocess(void)
2458 int c, t;
2459 TokenString str;
2461 tok_str_new(&str);
2462 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2463 next(); /* do macro subst */
2464 if (tok == TOK_DEFINED) {
2465 next_nomacro();
2466 t = tok;
2467 if (t == '(')
2468 next_nomacro();
2469 c = define_find(tok) != 0;
2470 if (t == '(')
2471 next_nomacro();
2472 tok = TOK_CINT;
2473 tokc.i = c;
2474 } else if (tok >= TOK_IDENT) {
2475 /* if undefined macro */
2476 tok = TOK_CINT;
2477 tokc.i = 0;
2479 tok_str_add_tok(&str);
2481 tok_str_add(&str, -1); /* simulate end of file */
2482 tok_str_add(&str, 0);
2483 /* now evaluate C constant expression */
2484 macro_ptr = str.str;
2485 next();
2486 c = expr_const();
2487 macro_ptr = NULL;
2488 tok_str_free(str.str);
2489 return c != 0;
2492 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2493 static void tok_print(int *str)
2495 int t;
2496 CValue cval;
2498 while (1) {
2499 TOK_GET(t, str, cval);
2500 if (!t)
2501 break;
2502 printf(" %s", get_tok_str(t, &cval));
2504 printf("\n");
2506 #endif
2508 /* parse after #define */
2509 static void parse_define(void)
2511 Sym *s, *first, **ps;
2512 int v, t, varg, is_vaargs, c;
2513 TokenString str;
2515 v = tok;
2516 if (v < TOK_IDENT)
2517 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2518 /* XXX: should check if same macro (ANSI) */
2519 first = NULL;
2520 t = MACRO_OBJ;
2521 /* '(' must be just after macro definition for MACRO_FUNC */
2522 c = file->buf_ptr[0];
2523 if (c == '\\')
2524 c = handle_stray1(file->buf_ptr);
2525 if (c == '(') {
2526 next_nomacro();
2527 next_nomacro();
2528 ps = &first;
2529 while (tok != ')') {
2530 varg = tok;
2531 next_nomacro();
2532 is_vaargs = 0;
2533 if (varg == TOK_DOTS) {
2534 varg = TOK___VA_ARGS__;
2535 is_vaargs = 1;
2536 } else if (tok == TOK_DOTS && gnu_ext) {
2537 is_vaargs = 1;
2538 next_nomacro();
2540 if (varg < TOK_IDENT)
2541 error("badly punctuated parameter list");
2542 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2543 *ps = s;
2544 ps = &s->next;
2545 if (tok != ',')
2546 break;
2547 next_nomacro();
2549 t = MACRO_FUNC;
2551 tok_str_new(&str);
2552 next_nomacro();
2553 /* EOF testing necessary for '-D' handling */
2554 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2555 tok_str_add2(&str, tok, &tokc);
2556 next_nomacro();
2558 tok_str_add(&str, 0);
2559 #ifdef PP_DEBUG
2560 printf("define %s %d: ", get_tok_str(v, NULL), t);
2561 tok_print(str.str);
2562 #endif
2563 define_push(v, t, str.str, first);
2566 /* XXX: use a token or a hash table to accelerate matching ? */
2567 static CachedInclude *search_cached_include(TCCState *s1,
2568 int type, const char *filename)
2570 CachedInclude *e;
2571 int i;
2573 for(i = 0;i < s1->nb_cached_includes; i++) {
2574 e = s1->cached_includes[i];
2575 if (e->type == type && !strcmp(e->filename, filename))
2576 return e;
2578 return NULL;
2581 static inline void add_cached_include(TCCState *s1, int type,
2582 const char *filename, int ifndef_macro)
2584 CachedInclude *e;
2586 if (search_cached_include(s1, type, filename))
2587 return;
2588 #ifdef INC_DEBUG
2589 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2590 #endif
2591 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2592 if (!e)
2593 return;
2594 e->type = type;
2595 strcpy(e->filename, filename);
2596 e->ifndef_macro = ifndef_macro;
2597 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2600 /* is_bof is true if first non space token at beginning of file */
2601 static void preprocess(int is_bof)
2603 TCCState *s1 = tcc_state;
2604 int size, i, c, n, saved_parse_flags;
2605 char buf[1024], *q, *p;
2606 char buf1[1024];
2607 BufferedFile *f;
2608 Sym *s;
2609 CachedInclude *e;
2611 saved_parse_flags = parse_flags;
2612 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2613 PARSE_FLAG_LINEFEED;
2614 next_nomacro();
2615 redo:
2616 switch(tok) {
2617 case TOK_DEFINE:
2618 next_nomacro();
2619 parse_define();
2620 break;
2621 case TOK_UNDEF:
2622 next_nomacro();
2623 s = define_find(tok);
2624 /* undefine symbol by putting an invalid name */
2625 if (s)
2626 define_undef(s);
2627 break;
2628 case TOK_INCLUDE:
2629 ch = file->buf_ptr[0];
2630 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2631 skip_spaces();
2632 if (ch == '<') {
2633 c = '>';
2634 goto read_name;
2635 } else if (ch == '\"') {
2636 c = ch;
2637 read_name:
2638 /* XXX: better stray handling */
2639 minp();
2640 q = buf;
2641 while (ch != c && ch != '\n' && ch != CH_EOF) {
2642 if ((q - buf) < sizeof(buf) - 1)
2643 *q++ = ch;
2644 minp();
2646 *q = '\0';
2647 minp();
2648 #if 0
2649 /* eat all spaces and comments after include */
2650 /* XXX: slightly incorrect */
2651 while (ch1 != '\n' && ch1 != CH_EOF)
2652 inp();
2653 #endif
2654 } else {
2655 /* computed #include : either we have only strings or
2656 we have anything enclosed in '<>' */
2657 next();
2658 buf[0] = '\0';
2659 if (tok == TOK_STR) {
2660 while (tok != TOK_LINEFEED) {
2661 if (tok != TOK_STR) {
2662 include_syntax:
2663 error("'#include' expects \"FILENAME\" or <FILENAME>");
2665 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2666 next();
2668 c = '\"';
2669 } else {
2670 int len;
2671 while (tok != TOK_LINEFEED) {
2672 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2673 next();
2675 len = strlen(buf);
2676 /* check syntax and remove '<>' */
2677 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2678 goto include_syntax;
2679 memmove(buf, buf + 1, len - 2);
2680 buf[len - 2] = '\0';
2681 c = '>';
2685 e = search_cached_include(s1, c, buf);
2686 if (e && define_find(e->ifndef_macro)) {
2687 /* no need to parse the include because the 'ifndef macro'
2688 is defined */
2689 #ifdef INC_DEBUG
2690 printf("%s: skipping %s\n", file->filename, buf);
2691 #endif
2692 } else {
2693 if (c == '\"') {
2694 /* first search in current dir if "header.h" */
2695 size = 0;
2696 p = strrchr(file->filename, '/');
2697 if (p)
2698 size = p + 1 - file->filename;
2699 if (size > sizeof(buf1) - 1)
2700 size = sizeof(buf1) - 1;
2701 memcpy(buf1, file->filename, size);
2702 buf1[size] = '\0';
2703 pstrcat(buf1, sizeof(buf1), buf);
2704 f = tcc_open(s1, buf1);
2705 if (f)
2706 goto found;
2708 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2709 error("#include recursion too deep");
2710 /* now search in all the include paths */
2711 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2712 for(i = 0; i < n; i++) {
2713 const char *path;
2714 if (i < s1->nb_include_paths)
2715 path = s1->include_paths[i];
2716 else
2717 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2718 pstrcpy(buf1, sizeof(buf1), path);
2719 pstrcat(buf1, sizeof(buf1), "/");
2720 pstrcat(buf1, sizeof(buf1), buf);
2721 f = tcc_open(s1, buf1);
2722 if (f)
2723 goto found;
2725 error("include file '%s' not found", buf);
2726 f = NULL;
2727 found:
2728 #ifdef INC_DEBUG
2729 printf("%s: including %s\n", file->filename, buf1);
2730 #endif
2731 f->inc_type = c;
2732 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2733 /* push current file in stack */
2734 /* XXX: fix current line init */
2735 *s1->include_stack_ptr++ = file;
2736 file = f;
2737 /* add include file debug info */
2738 if (do_debug) {
2739 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2741 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2742 ch = file->buf_ptr[0];
2743 goto the_end;
2745 break;
2746 case TOK_IFNDEF:
2747 c = 1;
2748 goto do_ifdef;
2749 case TOK_IF:
2750 c = expr_preprocess();
2751 goto do_if;
2752 case TOK_IFDEF:
2753 c = 0;
2754 do_ifdef:
2755 next_nomacro();
2756 if (tok < TOK_IDENT)
2757 error("invalid argument for '#if%sdef'", c ? "n" : "");
2758 if (is_bof) {
2759 if (c) {
2760 #ifdef INC_DEBUG
2761 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2762 #endif
2763 file->ifndef_macro = tok;
2766 c = (define_find(tok) != 0) ^ c;
2767 do_if:
2768 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2769 error("memory full");
2770 *s1->ifdef_stack_ptr++ = c;
2771 goto test_skip;
2772 case TOK_ELSE:
2773 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2774 error("#else without matching #if");
2775 if (s1->ifdef_stack_ptr[-1] & 2)
2776 error("#else after #else");
2777 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2778 goto test_skip;
2779 case TOK_ELIF:
2780 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2781 error("#elif without matching #if");
2782 c = s1->ifdef_stack_ptr[-1];
2783 if (c > 1)
2784 error("#elif after #else");
2785 /* last #if/#elif expression was true: we skip */
2786 if (c == 1)
2787 goto skip;
2788 c = expr_preprocess();
2789 s1->ifdef_stack_ptr[-1] = c;
2790 test_skip:
2791 if (!(c & 1)) {
2792 skip:
2793 preprocess_skip();
2794 is_bof = 0;
2795 goto redo;
2797 break;
2798 case TOK_ENDIF:
2799 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2800 error("#endif without matching #if");
2801 s1->ifdef_stack_ptr--;
2802 /* '#ifndef macro' was at the start of file. Now we check if
2803 an '#endif' is exactly at the end of file */
2804 if (file->ifndef_macro &&
2805 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2806 file->ifndef_macro_saved = file->ifndef_macro;
2807 /* need to set to zero to avoid false matches if another
2808 #ifndef at middle of file */
2809 file->ifndef_macro = 0;
2810 while (tok != TOK_LINEFEED)
2811 next_nomacro();
2812 tok_flags |= TOK_FLAG_ENDIF;
2813 goto the_end;
2815 break;
2816 case TOK_LINE:
2817 next();
2818 if (tok != TOK_CINT)
2819 error("#line");
2820 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2821 next();
2822 if (tok != TOK_LINEFEED) {
2823 if (tok != TOK_STR)
2824 error("#line");
2825 pstrcpy(file->filename, sizeof(file->filename),
2826 (char *)tokc.cstr->data);
2828 break;
2829 case TOK_ERROR:
2830 case TOK_WARNING:
2831 c = tok;
2832 ch = file->buf_ptr[0];
2833 skip_spaces();
2834 q = buf;
2835 while (ch != '\n' && ch != CH_EOF) {
2836 if ((q - buf) < sizeof(buf) - 1)
2837 *q++ = ch;
2838 minp();
2840 *q = '\0';
2841 if (c == TOK_ERROR)
2842 error("#error %s", buf);
2843 else
2844 warning("#warning %s", buf);
2845 break;
2846 case TOK_PRAGMA:
2847 /* ignored */
2848 break;
2849 default:
2850 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2851 /* '!' is ignored to allow C scripts. numbers are ignored
2852 to emulate cpp behaviour */
2853 } else {
2854 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2856 break;
2858 /* ignore other preprocess commands or #! for C scripts */
2859 while (tok != TOK_LINEFEED)
2860 next_nomacro();
2861 the_end:
2862 parse_flags = saved_parse_flags;
2865 /* evaluate escape codes in a string. */
2866 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2868 int c, n;
2869 const uint8_t *p;
2871 p = buf;
2872 for(;;) {
2873 c = *p;
2874 if (c == '\0')
2875 break;
2876 if (c == '\\') {
2877 p++;
2878 /* escape */
2879 c = *p;
2880 switch(c) {
2881 case '0': case '1': case '2': case '3':
2882 case '4': case '5': case '6': case '7':
2883 /* at most three octal digits */
2884 n = c - '0';
2885 p++;
2886 c = *p;
2887 if (isoct(c)) {
2888 n = n * 8 + c - '0';
2889 p++;
2890 c = *p;
2891 if (isoct(c)) {
2892 n = n * 8 + c - '0';
2893 p++;
2896 c = n;
2897 goto add_char_nonext;
2898 case 'x':
2899 p++;
2900 n = 0;
2901 for(;;) {
2902 c = *p;
2903 if (c >= 'a' && c <= 'f')
2904 c = c - 'a' + 10;
2905 else if (c >= 'A' && c <= 'F')
2906 c = c - 'A' + 10;
2907 else if (isnum(c))
2908 c = c - '0';
2909 else
2910 break;
2911 n = n * 16 + c;
2912 p++;
2914 c = n;
2915 goto add_char_nonext;
2916 case 'a':
2917 c = '\a';
2918 break;
2919 case 'b':
2920 c = '\b';
2921 break;
2922 case 'f':
2923 c = '\f';
2924 break;
2925 case 'n':
2926 c = '\n';
2927 break;
2928 case 'r':
2929 c = '\r';
2930 break;
2931 case 't':
2932 c = '\t';
2933 break;
2934 case 'v':
2935 c = '\v';
2936 break;
2937 case 'e':
2938 if (!gnu_ext)
2939 goto invalid_escape;
2940 c = 27;
2941 break;
2942 case '\'':
2943 case '\"':
2944 case '\\':
2945 case '?':
2946 break;
2947 default:
2948 invalid_escape:
2949 if (c >= '!' && c <= '~')
2950 warning("unknown escape sequence: \'\\%c\'", c);
2951 else
2952 warning("unknown escape sequence: \'\\x%x\'", c);
2953 break;
2956 p++;
2957 add_char_nonext:
2958 if (!is_long)
2959 cstr_ccat(outstr, c);
2960 else
2961 cstr_wccat(outstr, c);
2963 /* add a trailing '\0' */
2964 if (!is_long)
2965 cstr_ccat(outstr, '\0');
2966 else
2967 cstr_wccat(outstr, '\0');
2970 /* we use 64 bit numbers */
2971 #define BN_SIZE 2
2973 /* bn = (bn << shift) | or_val */
2974 void bn_lshift(unsigned int *bn, int shift, int or_val)
2976 int i;
2977 unsigned int v;
2978 for(i=0;i<BN_SIZE;i++) {
2979 v = bn[i];
2980 bn[i] = (v << shift) | or_val;
2981 or_val = v >> (32 - shift);
2985 void bn_zero(unsigned int *bn)
2987 int i;
2988 for(i=0;i<BN_SIZE;i++) {
2989 bn[i] = 0;
2993 /* parse number in null terminated string 'p' and return it in the
2994 current token */
2995 void parse_number(const char *p)
2997 int b, t, shift, frac_bits, s, exp_val, ch;
2998 char *q;
2999 unsigned int bn[BN_SIZE];
3000 double d;
3002 /* number */
3003 q = token_buf;
3004 ch = *p++;
3005 t = ch;
3006 ch = *p++;
3007 *q++ = t;
3008 b = 10;
3009 if (t == '.') {
3010 goto float_frac_parse;
3011 } else if (t == '0') {
3012 if (ch == 'x' || ch == 'X') {
3013 q--;
3014 ch = *p++;
3015 b = 16;
3016 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3017 q--;
3018 ch = *p++;
3019 b = 2;
3022 /* parse all digits. cannot check octal numbers at this stage
3023 because of floating point constants */
3024 while (1) {
3025 if (ch >= 'a' && ch <= 'f')
3026 t = ch - 'a' + 10;
3027 else if (ch >= 'A' && ch <= 'F')
3028 t = ch - 'A' + 10;
3029 else if (isnum(ch))
3030 t = ch - '0';
3031 else
3032 break;
3033 if (t >= b)
3034 break;
3035 if (q >= token_buf + STRING_MAX_SIZE) {
3036 num_too_long:
3037 error("number too long");
3039 *q++ = ch;
3040 ch = *p++;
3042 if (ch == '.' ||
3043 ((ch == 'e' || ch == 'E') && b == 10) ||
3044 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3045 if (b != 10) {
3046 /* NOTE: strtox should support that for hexa numbers, but
3047 non ISOC99 libcs do not support it, so we prefer to do
3048 it by hand */
3049 /* hexadecimal or binary floats */
3050 /* XXX: handle overflows */
3051 *q = '\0';
3052 if (b == 16)
3053 shift = 4;
3054 else
3055 shift = 2;
3056 bn_zero(bn);
3057 q = token_buf;
3058 while (1) {
3059 t = *q++;
3060 if (t == '\0') {
3061 break;
3062 } else if (t >= 'a') {
3063 t = t - 'a' + 10;
3064 } else if (t >= 'A') {
3065 t = t - 'A' + 10;
3066 } else {
3067 t = t - '0';
3069 bn_lshift(bn, shift, t);
3071 frac_bits = 0;
3072 if (ch == '.') {
3073 ch = *p++;
3074 while (1) {
3075 t = ch;
3076 if (t >= 'a' && t <= 'f') {
3077 t = t - 'a' + 10;
3078 } else if (t >= 'A' && t <= 'F') {
3079 t = t - 'A' + 10;
3080 } else if (t >= '0' && t <= '9') {
3081 t = t - '0';
3082 } else {
3083 break;
3085 if (t >= b)
3086 error("invalid digit");
3087 bn_lshift(bn, shift, t);
3088 frac_bits += shift;
3089 ch = *p++;
3092 if (ch != 'p' && ch != 'P')
3093 expect("exponent");
3094 ch = *p++;
3095 s = 1;
3096 exp_val = 0;
3097 if (ch == '+') {
3098 ch = *p++;
3099 } else if (ch == '-') {
3100 s = -1;
3101 ch = *p++;
3103 if (ch < '0' || ch > '9')
3104 expect("exponent digits");
3105 while (ch >= '0' && ch <= '9') {
3106 exp_val = exp_val * 10 + ch - '0';
3107 ch = *p++;
3109 exp_val = exp_val * s;
3111 /* now we can generate the number */
3112 /* XXX: should patch directly float number */
3113 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3114 d = ldexp(d, exp_val - frac_bits);
3115 t = toup(ch);
3116 if (t == 'F') {
3117 ch = *p++;
3118 tok = TOK_CFLOAT;
3119 /* float : should handle overflow */
3120 tokc.f = (float)d;
3121 } else if (t == 'L') {
3122 ch = *p++;
3123 tok = TOK_CLDOUBLE;
3124 /* XXX: not large enough */
3125 tokc.ld = (long double)d;
3126 } else {
3127 tok = TOK_CDOUBLE;
3128 tokc.d = d;
3130 } else {
3131 /* decimal floats */
3132 if (ch == '.') {
3133 if (q >= token_buf + STRING_MAX_SIZE)
3134 goto num_too_long;
3135 *q++ = ch;
3136 ch = *p++;
3137 float_frac_parse:
3138 while (ch >= '0' && ch <= '9') {
3139 if (q >= token_buf + STRING_MAX_SIZE)
3140 goto num_too_long;
3141 *q++ = ch;
3142 ch = *p++;
3145 if (ch == 'e' || ch == 'E') {
3146 if (q >= token_buf + STRING_MAX_SIZE)
3147 goto num_too_long;
3148 *q++ = ch;
3149 ch = *p++;
3150 if (ch == '-' || ch == '+') {
3151 if (q >= token_buf + STRING_MAX_SIZE)
3152 goto num_too_long;
3153 *q++ = ch;
3154 ch = *p++;
3156 if (ch < '0' || ch > '9')
3157 expect("exponent digits");
3158 while (ch >= '0' && ch <= '9') {
3159 if (q >= token_buf + STRING_MAX_SIZE)
3160 goto num_too_long;
3161 *q++ = ch;
3162 ch = *p++;
3165 *q = '\0';
3166 t = toup(ch);
3167 errno = 0;
3168 if (t == 'F') {
3169 ch = *p++;
3170 tok = TOK_CFLOAT;
3171 tokc.f = strtof(token_buf, NULL);
3172 } else if (t == 'L') {
3173 ch = *p++;
3174 tok = TOK_CLDOUBLE;
3175 tokc.ld = strtold(token_buf, NULL);
3176 } else {
3177 tok = TOK_CDOUBLE;
3178 tokc.d = strtod(token_buf, NULL);
3181 } else {
3182 unsigned long long n, n1;
3183 int lcount, ucount;
3185 /* integer number */
3186 *q = '\0';
3187 q = token_buf;
3188 if (b == 10 && *q == '0') {
3189 b = 8;
3190 q++;
3192 n = 0;
3193 while(1) {
3194 t = *q++;
3195 /* no need for checks except for base 10 / 8 errors */
3196 if (t == '\0') {
3197 break;
3198 } else if (t >= 'a') {
3199 t = t - 'a' + 10;
3200 } else if (t >= 'A') {
3201 t = t - 'A' + 10;
3202 } else {
3203 t = t - '0';
3204 if (t >= b)
3205 error("invalid digit");
3207 n1 = n;
3208 n = n * b + t;
3209 /* detect overflow */
3210 /* XXX: this test is not reliable */
3211 if (n < n1)
3212 error("integer constant overflow");
3215 /* XXX: not exactly ANSI compliant */
3216 if ((n & 0xffffffff00000000LL) != 0) {
3217 if ((n >> 63) != 0)
3218 tok = TOK_CULLONG;
3219 else
3220 tok = TOK_CLLONG;
3221 } else if (n > 0x7fffffff) {
3222 tok = TOK_CUINT;
3223 } else {
3224 tok = TOK_CINT;
3226 lcount = 0;
3227 ucount = 0;
3228 for(;;) {
3229 t = toup(ch);
3230 if (t == 'L') {
3231 if (lcount >= 2)
3232 error("three 'l's in integer constant");
3233 lcount++;
3234 if (lcount == 2) {
3235 if (tok == TOK_CINT)
3236 tok = TOK_CLLONG;
3237 else if (tok == TOK_CUINT)
3238 tok = TOK_CULLONG;
3240 ch = *p++;
3241 } else if (t == 'U') {
3242 if (ucount >= 1)
3243 error("two 'u's in integer constant");
3244 ucount++;
3245 if (tok == TOK_CINT)
3246 tok = TOK_CUINT;
3247 else if (tok == TOK_CLLONG)
3248 tok = TOK_CULLONG;
3249 ch = *p++;
3250 } else {
3251 break;
3254 if (tok == TOK_CINT || tok == TOK_CUINT)
3255 tokc.ui = n;
3256 else
3257 tokc.ull = n;
3262 #define PARSE2(c1, tok1, c2, tok2) \
3263 case c1: \
3264 PEEKC(c, p); \
3265 if (c == c2) { \
3266 p++; \
3267 tok = tok2; \
3268 } else { \
3269 tok = tok1; \
3271 break;
3273 /* return next token without macro substitution */
3274 static inline void next_nomacro1(void)
3276 int t, c, is_long;
3277 TokenSym *ts;
3278 uint8_t *p, *p1;
3279 unsigned int h;
3281 p = file->buf_ptr;
3282 redo_no_start:
3283 c = *p;
3284 switch(c) {
3285 case ' ':
3286 case '\t':
3287 case '\f':
3288 case '\v':
3289 case '\r':
3290 p++;
3291 goto redo_no_start;
3293 case '\\':
3294 /* first look if it is in fact an end of buffer */
3295 if (p >= file->buf_end) {
3296 file->buf_ptr = p;
3297 handle_eob();
3298 p = file->buf_ptr;
3299 if (p >= file->buf_end)
3300 goto parse_eof;
3301 else
3302 goto redo_no_start;
3303 } else {
3304 file->buf_ptr = p;
3305 ch = *p;
3306 handle_stray();
3307 p = file->buf_ptr;
3308 goto redo_no_start;
3310 parse_eof:
3312 TCCState *s1 = tcc_state;
3313 if (parse_flags & PARSE_FLAG_LINEFEED) {
3314 tok = TOK_LINEFEED;
3315 } else if (s1->include_stack_ptr == s1->include_stack ||
3316 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3317 /* no include left : end of file. */
3318 tok = TOK_EOF;
3319 } else {
3320 /* pop include file */
3322 /* test if previous '#endif' was after a #ifdef at
3323 start of file */
3324 if (tok_flags & TOK_FLAG_ENDIF) {
3325 #ifdef INC_DEBUG
3326 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3327 #endif
3328 add_cached_include(s1, file->inc_type, file->inc_filename,
3329 file->ifndef_macro_saved);
3332 /* add end of include file debug info */
3333 if (do_debug) {
3334 put_stabd(N_EINCL, 0, 0);
3336 /* pop include stack */
3337 tcc_close(file);
3338 s1->include_stack_ptr--;
3339 file = *s1->include_stack_ptr;
3340 p = file->buf_ptr;
3341 goto redo_no_start;
3344 break;
3346 case '\n':
3347 if (parse_flags & PARSE_FLAG_LINEFEED) {
3348 tok = TOK_LINEFEED;
3349 } else {
3350 file->line_num++;
3351 tok_flags |= TOK_FLAG_BOL;
3352 p++;
3353 goto redo_no_start;
3355 break;
3357 case '#':
3358 /* XXX: simplify */
3359 PEEKC(c, p);
3360 if ((tok_flags & TOK_FLAG_BOL) &&
3361 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3362 file->buf_ptr = p;
3363 preprocess(tok_flags & TOK_FLAG_BOF);
3364 p = file->buf_ptr;
3365 goto redo_no_start;
3366 } else {
3367 if (c == '#') {
3368 p++;
3369 tok = TOK_TWOSHARPS;
3370 } else {
3371 tok = '#';
3374 break;
3376 case 'a': case 'b': case 'c': case 'd':
3377 case 'e': case 'f': case 'g': case 'h':
3378 case 'i': case 'j': case 'k': case 'l':
3379 case 'm': case 'n': case 'o': case 'p':
3380 case 'q': case 'r': case 's': case 't':
3381 case 'u': case 'v': case 'w': case 'x':
3382 case 'y': case 'z':
3383 case 'A': case 'B': case 'C': case 'D':
3384 case 'E': case 'F': case 'G': case 'H':
3385 case 'I': case 'J': case 'K':
3386 case 'M': case 'N': case 'O': case 'P':
3387 case 'Q': case 'R': case 'S': case 'T':
3388 case 'U': case 'V': case 'W': case 'X':
3389 case 'Y': case 'Z':
3390 case '_':
3391 parse_ident_fast:
3392 p1 = p;
3393 h = TOK_HASH_INIT;
3394 h = TOK_HASH_FUNC(h, c);
3395 p++;
3396 for(;;) {
3397 c = *p;
3398 if (!isidnum_table[c])
3399 break;
3400 h = TOK_HASH_FUNC(h, c);
3401 p++;
3403 if (c != '\\') {
3404 TokenSym **pts;
3405 int len;
3407 /* fast case : no stray found, so we have the full token
3408 and we have already hashed it */
3409 len = p - p1;
3410 h &= (TOK_HASH_SIZE - 1);
3411 pts = &hash_ident[h];
3412 for(;;) {
3413 ts = *pts;
3414 if (!ts)
3415 break;
3416 if (ts->len == len && !memcmp(ts->str, p1, len))
3417 goto token_found;
3418 pts = &(ts->hash_next);
3420 ts = tok_alloc_new(pts, p1, len);
3421 token_found: ;
3422 } else {
3423 /* slower case */
3424 cstr_reset(&tokcstr);
3426 while (p1 < p) {
3427 cstr_ccat(&tokcstr, *p1);
3428 p1++;
3430 p--;
3431 PEEKC(c, p);
3432 parse_ident_slow:
3433 while (isidnum_table[c]) {
3434 cstr_ccat(&tokcstr, c);
3435 PEEKC(c, p);
3437 ts = tok_alloc(tokcstr.data, tokcstr.size);
3439 tok = ts->tok;
3440 break;
3441 case 'L':
3442 t = p[1];
3443 if (t != '\\' && t != '\'' && t != '\"') {
3444 /* fast case */
3445 goto parse_ident_fast;
3446 } else {
3447 PEEKC(c, p);
3448 if (c == '\'' || c == '\"') {
3449 is_long = 1;
3450 goto str_const;
3451 } else {
3452 cstr_reset(&tokcstr);
3453 cstr_ccat(&tokcstr, 'L');
3454 goto parse_ident_slow;
3457 break;
3458 case '0': case '1': case '2': case '3':
3459 case '4': case '5': case '6': case '7':
3460 case '8': case '9':
3462 cstr_reset(&tokcstr);
3463 /* after the first digit, accept digits, alpha, '.' or sign if
3464 prefixed by 'eEpP' */
3465 parse_num:
3466 for(;;) {
3467 t = c;
3468 cstr_ccat(&tokcstr, c);
3469 PEEKC(c, p);
3470 if (!(isnum(c) || isid(c) || c == '.' ||
3471 ((c == '+' || c == '-') &&
3472 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3473 break;
3475 /* We add a trailing '\0' to ease parsing */
3476 cstr_ccat(&tokcstr, '\0');
3477 tokc.cstr = &tokcstr;
3478 tok = TOK_PPNUM;
3479 break;
3480 case '.':
3481 /* special dot handling because it can also start a number */
3482 PEEKC(c, p);
3483 if (isnum(c)) {
3484 cstr_reset(&tokcstr);
3485 cstr_ccat(&tokcstr, '.');
3486 goto parse_num;
3487 } else if (c == '.') {
3488 PEEKC(c, p);
3489 if (c != '.')
3490 expect("'.'");
3491 PEEKC(c, p);
3492 tok = TOK_DOTS;
3493 } else {
3494 tok = '.';
3496 break;
3497 case '\'':
3498 case '\"':
3499 is_long = 0;
3500 str_const:
3502 CString str;
3503 int sep;
3505 sep = c;
3507 /* parse the string */
3508 cstr_new(&str);
3509 p = parse_pp_string(p, sep, &str);
3510 cstr_ccat(&str, '\0');
3512 /* eval the escape (should be done as TOK_PPNUM) */
3513 cstr_reset(&tokcstr);
3514 parse_escape_string(&tokcstr, str.data, is_long);
3515 cstr_free(&str);
3517 if (sep == '\'') {
3518 int char_size;
3519 /* XXX: make it portable */
3520 if (!is_long)
3521 char_size = 1;
3522 else
3523 char_size = sizeof(int);
3524 if (tokcstr.size <= char_size)
3525 error("empty character constant");
3526 if (tokcstr.size > 2 * char_size)
3527 warning("multi-character character constant");
3528 if (!is_long) {
3529 tokc.i = *(int8_t *)tokcstr.data;
3530 tok = TOK_CCHAR;
3531 } else {
3532 tokc.i = *(int *)tokcstr.data;
3533 tok = TOK_LCHAR;
3535 } else {
3536 tokc.cstr = &tokcstr;
3537 if (!is_long)
3538 tok = TOK_STR;
3539 else
3540 tok = TOK_LSTR;
3543 break;
3545 case '<':
3546 PEEKC(c, p);
3547 if (c == '=') {
3548 p++;
3549 tok = TOK_LE;
3550 } else if (c == '<') {
3551 PEEKC(c, p);
3552 if (c == '=') {
3553 p++;
3554 tok = TOK_A_SHL;
3555 } else {
3556 tok = TOK_SHL;
3558 } else {
3559 tok = TOK_LT;
3561 break;
3563 case '>':
3564 PEEKC(c, p);
3565 if (c == '=') {
3566 p++;
3567 tok = TOK_GE;
3568 } else if (c == '>') {
3569 PEEKC(c, p);
3570 if (c == '=') {
3571 p++;
3572 tok = TOK_A_SAR;
3573 } else {
3574 tok = TOK_SAR;
3576 } else {
3577 tok = TOK_GT;
3579 break;
3581 case '&':
3582 PEEKC(c, p);
3583 if (c == '&') {
3584 p++;
3585 tok = TOK_LAND;
3586 } else if (c == '=') {
3587 p++;
3588 tok = TOK_A_AND;
3589 } else {
3590 tok = '&';
3592 break;
3594 case '|':
3595 PEEKC(c, p);
3596 if (c == '|') {
3597 p++;
3598 tok = TOK_LOR;
3599 } else if (c == '=') {
3600 p++;
3601 tok = TOK_A_OR;
3602 } else {
3603 tok = '|';
3605 break;
3607 case '+':
3608 PEEKC(c, p);
3609 if (c == '+') {
3610 p++;
3611 tok = TOK_INC;
3612 } else if (c == '=') {
3613 p++;
3614 tok = TOK_A_ADD;
3615 } else {
3616 tok = '+';
3618 break;
3620 case '-':
3621 PEEKC(c, p);
3622 if (c == '-') {
3623 p++;
3624 tok = TOK_DEC;
3625 } else if (c == '=') {
3626 p++;
3627 tok = TOK_A_SUB;
3628 } else if (c == '>') {
3629 p++;
3630 tok = TOK_ARROW;
3631 } else {
3632 tok = '-';
3634 break;
3636 PARSE2('!', '!', '=', TOK_NE)
3637 PARSE2('=', '=', '=', TOK_EQ)
3638 PARSE2('*', '*', '=', TOK_A_MUL)
3639 PARSE2('%', '%', '=', TOK_A_MOD)
3640 PARSE2('^', '^', '=', TOK_A_XOR)
3642 /* comments or operator */
3643 case '/':
3644 PEEKC(c, p);
3645 if (c == '*') {
3646 p = parse_comment(p);
3647 goto redo_no_start;
3648 } else if (c == '/') {
3649 p = parse_line_comment(p);
3650 goto redo_no_start;
3651 } else if (c == '=') {
3652 p++;
3653 tok = TOK_A_DIV;
3654 } else {
3655 tok = '/';
3657 break;
3659 /* simple tokens */
3660 case '(':
3661 case ')':
3662 case '[':
3663 case ']':
3664 case '{':
3665 case '}':
3666 case ',':
3667 case ';':
3668 case ':':
3669 case '?':
3670 case '~':
3671 case '$': /* only used in assembler */
3672 tok = c;
3673 p++;
3674 break;
3675 default:
3676 error("unrecognized character \\x%02x", c);
3677 break;
3679 file->buf_ptr = p;
3680 tok_flags = 0;
3681 #if defined(PARSE_DEBUG)
3682 printf("token = %s\n", get_tok_str(tok, &tokc));
3683 #endif
3686 /* return next token without macro substitution. Can read input from
3687 macro_ptr buffer */
3688 static void next_nomacro(void)
3690 if (macro_ptr) {
3691 redo:
3692 tok = *macro_ptr;
3693 if (tok) {
3694 TOK_GET(tok, macro_ptr, tokc);
3695 if (tok == TOK_LINENUM) {
3696 file->line_num = tokc.i;
3697 goto redo;
3700 } else {
3701 next_nomacro1();
3705 /* substitute args in macro_str and return allocated string */
3706 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3708 int *st, last_tok, t, notfirst;
3709 Sym *s;
3710 CValue cval;
3711 TokenString str;
3712 CString cstr;
3714 tok_str_new(&str);
3715 last_tok = 0;
3716 while(1) {
3717 TOK_GET(t, macro_str, cval);
3718 if (!t)
3719 break;
3720 if (t == '#') {
3721 /* stringize */
3722 TOK_GET(t, macro_str, cval);
3723 if (!t)
3724 break;
3725 s = sym_find2(args, t);
3726 if (s) {
3727 cstr_new(&cstr);
3728 st = (int *)s->c;
3729 notfirst = 0;
3730 while (*st) {
3731 if (notfirst)
3732 cstr_ccat(&cstr, ' ');
3733 TOK_GET(t, st, cval);
3734 cstr_cat(&cstr, get_tok_str(t, &cval));
3735 notfirst = 1;
3737 cstr_ccat(&cstr, '\0');
3738 #ifdef PP_DEBUG
3739 printf("stringize: %s\n", (char *)cstr.data);
3740 #endif
3741 /* add string */
3742 cval.cstr = &cstr;
3743 tok_str_add2(&str, TOK_STR, &cval);
3744 cstr_free(&cstr);
3745 } else {
3746 tok_str_add2(&str, t, &cval);
3748 } else if (t >= TOK_IDENT) {
3749 s = sym_find2(args, t);
3750 if (s) {
3751 st = (int *)s->c;
3752 /* if '##' is present before or after, no arg substitution */
3753 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3754 /* special case for var arg macros : ## eats the
3755 ',' if empty VA_ARGS variable. */
3756 /* XXX: test of the ',' is not 100%
3757 reliable. should fix it to avoid security
3758 problems */
3759 if (gnu_ext && s->type.t &&
3760 last_tok == TOK_TWOSHARPS &&
3761 str.len >= 2 && str.str[str.len - 2] == ',') {
3762 if (*st == 0) {
3763 /* suppress ',' '##' */
3764 str.len -= 2;
3765 } else {
3766 /* suppress '##' and add variable */
3767 str.len--;
3768 goto add_var;
3770 } else {
3771 int t1;
3772 add_var:
3773 for(;;) {
3774 TOK_GET(t1, st, cval);
3775 if (!t1)
3776 break;
3777 tok_str_add2(&str, t1, &cval);
3780 } else {
3781 /* NOTE: the stream cannot be read when macro
3782 substituing an argument */
3783 macro_subst(&str, nested_list, st, 0);
3785 } else {
3786 tok_str_add(&str, t);
3788 } else {
3789 tok_str_add2(&str, t, &cval);
3791 last_tok = t;
3793 tok_str_add(&str, 0);
3794 return str.str;
3797 static char const ab_month_name[12][4] =
3799 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3800 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3803 /* do macro substitution of current token with macro 's' and add
3804 result to (tok_str,tok_len). 'nested_list' is the list of all
3805 macros we got inside to avoid recursing. Return non zero if no
3806 substitution needs to be done */
3807 static int macro_subst_tok(TokenString *tok_str,
3808 Sym **nested_list, Sym *s, int can_read_stream)
3810 Sym *args, *sa, *sa1;
3811 int mstr_allocated, parlevel, *mstr, t;
3812 TokenString str;
3813 char *cstrval;
3814 CValue cval;
3815 CString cstr;
3817 /* if symbol is a macro, prepare substitution */
3819 /* special macros */
3820 if (tok == TOK___LINE__) {
3821 cval.i = file->line_num;
3822 tok_str_add2(tok_str, TOK_CINT, &cval);
3823 } else if (tok == TOK___FILE__) {
3824 cstrval = file->filename;
3825 goto add_cstr;
3826 tok_str_add2(tok_str, TOK_STR, &cval);
3827 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3828 time_t ti;
3829 struct tm *tm;
3830 char buf[64];
3832 time(&ti);
3833 tm = localtime(&ti);
3834 if (tok == TOK___DATE__) {
3835 snprintf(buf, sizeof(buf), "%s %2d %d",
3836 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3837 } else {
3838 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3839 tm->tm_hour, tm->tm_min, tm->tm_sec);
3841 cstrval = buf;
3842 add_cstr:
3843 cstr_new(&cstr);
3844 cstr_cat(&cstr, cstrval);
3845 cstr_ccat(&cstr, '\0');
3846 cval.cstr = &cstr;
3847 tok_str_add2(tok_str, TOK_STR, &cval);
3848 cstr_free(&cstr);
3849 } else {
3850 mstr = (int *)s->c;
3851 mstr_allocated = 0;
3852 if (s->type.t == MACRO_FUNC) {
3853 /* NOTE: we do not use next_nomacro to avoid eating the
3854 next token. XXX: find better solution */
3855 if (macro_ptr) {
3856 t = *macro_ptr;
3857 if (t == 0 && can_read_stream) {
3858 /* end of macro stream: we must look at the token
3859 after in the file */
3860 macro_ptr = NULL;
3861 goto parse_stream;
3863 } else {
3864 parse_stream:
3865 /* XXX: incorrect with comments */
3866 ch = file->buf_ptr[0];
3867 while (is_space(ch) || ch == '\n')
3868 cinp();
3869 t = ch;
3871 if (t != '(') /* no macro subst */
3872 return -1;
3874 /* argument macro */
3875 next_nomacro();
3876 next_nomacro();
3877 args = NULL;
3878 sa = s->next;
3879 /* NOTE: empty args are allowed, except if no args */
3880 for(;;) {
3881 /* handle '()' case */
3882 if (!args && !sa && tok == ')')
3883 break;
3884 if (!sa)
3885 error("macro '%s' used with too many args",
3886 get_tok_str(s->v, 0));
3887 tok_str_new(&str);
3888 parlevel = 0;
3889 /* NOTE: non zero sa->t indicates VA_ARGS */
3890 while ((parlevel > 0 ||
3891 (tok != ')' &&
3892 (tok != ',' || sa->type.t))) &&
3893 tok != -1) {
3894 if (tok == '(')
3895 parlevel++;
3896 else if (tok == ')')
3897 parlevel--;
3898 tok_str_add2(&str, tok, &tokc);
3899 next_nomacro();
3901 tok_str_add(&str, 0);
3902 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3903 sa = sa->next;
3904 if (tok == ')') {
3905 /* special case for gcc var args: add an empty
3906 var arg argument if it is omitted */
3907 if (sa && sa->type.t && gnu_ext)
3908 continue;
3909 else
3910 break;
3912 if (tok != ',')
3913 expect(",");
3914 next_nomacro();
3916 if (sa) {
3917 error("macro '%s' used with too few args",
3918 get_tok_str(s->v, 0));
3921 /* now subst each arg */
3922 mstr = macro_arg_subst(nested_list, mstr, args);
3923 /* free memory */
3924 sa = args;
3925 while (sa) {
3926 sa1 = sa->prev;
3927 tok_str_free((int *)sa->c);
3928 tcc_free(sa);
3929 sa = sa1;
3931 mstr_allocated = 1;
3933 sym_push2(nested_list, s->v, 0, 0);
3934 macro_subst(tok_str, nested_list, mstr, 1);
3935 /* pop nested defined symbol */
3936 sa1 = *nested_list;
3937 *nested_list = sa1->prev;
3938 tcc_free(sa1);
3939 if (mstr_allocated)
3940 tok_str_free(mstr);
3942 return 0;
3945 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3946 return the resulting string (which must be freed). */
3947 static inline int *macro_twosharps(const int *macro_str)
3949 TokenSym *ts;
3950 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3951 int t;
3952 const char *p1, *p2;
3953 CValue cval;
3954 TokenString macro_str1;
3955 CString cstr;
3957 start_macro_ptr = macro_str;
3958 /* we search the first '##' */
3959 for(;;) {
3960 macro_ptr1 = macro_str;
3961 TOK_GET(t, macro_str, cval);
3962 /* nothing more to do if end of string */
3963 if (t == 0)
3964 return NULL;
3965 if (*macro_str == TOK_TWOSHARPS)
3966 break;
3969 /* we saw '##', so we need more processing to handle it */
3970 cstr_new(&cstr);
3971 tok_str_new(&macro_str1);
3972 tok = t;
3973 tokc = cval;
3975 /* add all tokens seen so far */
3976 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3977 TOK_GET(t, ptr, cval);
3978 tok_str_add2(&macro_str1, t, &cval);
3980 saved_macro_ptr = macro_ptr;
3981 /* XXX: get rid of the use of macro_ptr here */
3982 macro_ptr = (int *)macro_str;
3983 for(;;) {
3984 while (*macro_ptr == TOK_TWOSHARPS) {
3985 macro_ptr++;
3986 macro_ptr1 = macro_ptr;
3987 t = *macro_ptr;
3988 if (t) {
3989 TOK_GET(t, macro_ptr, cval);
3990 /* We concatenate the two tokens if we have an
3991 identifier or a preprocessing number */
3992 cstr_reset(&cstr);
3993 p1 = get_tok_str(tok, &tokc);
3994 cstr_cat(&cstr, p1);
3995 p2 = get_tok_str(t, &cval);
3996 cstr_cat(&cstr, p2);
3997 cstr_ccat(&cstr, '\0');
3999 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4000 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4001 if (tok == TOK_PPNUM) {
4002 /* if number, then create a number token */
4003 /* NOTE: no need to allocate because
4004 tok_str_add2() does it */
4005 tokc.cstr = &cstr;
4006 } else {
4007 /* if identifier, we must do a test to
4008 validate we have a correct identifier */
4009 if (t == TOK_PPNUM) {
4010 const char *p;
4011 int c;
4013 p = p2;
4014 for(;;) {
4015 c = *p;
4016 if (c == '\0')
4017 break;
4018 p++;
4019 if (!isnum(c) && !isid(c))
4020 goto error_pasting;
4023 ts = tok_alloc(cstr.data, strlen(cstr.data));
4024 tok = ts->tok; /* modify current token */
4026 } else {
4027 const char *str = cstr.data;
4028 const unsigned char *q;
4030 /* we look for a valid token */
4031 /* XXX: do more extensive checks */
4032 if (!strcmp(str, ">>=")) {
4033 tok = TOK_A_SAR;
4034 } else if (!strcmp(str, "<<=")) {
4035 tok = TOK_A_SHL;
4036 } else if (strlen(str) == 2) {
4037 /* search in two bytes table */
4038 q = tok_two_chars;
4039 for(;;) {
4040 if (!*q)
4041 goto error_pasting;
4042 if (q[0] == str[0] && q[1] == str[1])
4043 break;
4044 q += 3;
4046 tok = q[2];
4047 } else {
4048 error_pasting:
4049 /* NOTE: because get_tok_str use a static buffer,
4050 we must save it */
4051 cstr_reset(&cstr);
4052 p1 = get_tok_str(tok, &tokc);
4053 cstr_cat(&cstr, p1);
4054 cstr_ccat(&cstr, '\0');
4055 p2 = get_tok_str(t, &cval);
4056 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4057 /* cannot merge tokens: just add them separately */
4058 tok_str_add2(&macro_str1, tok, &tokc);
4059 /* XXX: free associated memory ? */
4060 tok = t;
4061 tokc = cval;
4066 tok_str_add2(&macro_str1, tok, &tokc);
4067 next_nomacro();
4068 if (tok == 0)
4069 break;
4071 macro_ptr = (int *)saved_macro_ptr;
4072 cstr_free(&cstr);
4073 tok_str_add(&macro_str1, 0);
4074 return macro_str1.str;
4078 /* do macro substitution of macro_str and add result to
4079 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4080 inside to avoid recursing. */
4081 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4082 const int *macro_str, int can_read_stream)
4084 Sym *s;
4085 int *saved_macro_ptr, *macro_str1;
4086 const int *ptr;
4087 int t, ret;
4088 CValue cval;
4090 /* first scan for '##' operator handling */
4091 ptr = macro_str;
4092 macro_str1 = macro_twosharps(ptr);
4093 if (macro_str1)
4094 ptr = macro_str1;
4095 while (1) {
4096 /* NOTE: ptr == NULL can only happen if tokens are read from
4097 file stream due to a macro function call */
4098 if (ptr == NULL)
4099 break;
4100 TOK_GET(t, ptr, cval);
4101 if (t == 0)
4102 break;
4103 s = define_find(t);
4104 if (s != NULL) {
4105 /* if nested substitution, do nothing */
4106 if (sym_find2(*nested_list, t))
4107 goto no_subst;
4108 saved_macro_ptr = macro_ptr;
4109 macro_ptr = (int *)ptr;
4110 tok = t;
4111 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4112 ptr = (int *)macro_ptr;
4113 macro_ptr = saved_macro_ptr;
4114 if (ret != 0)
4115 goto no_subst;
4116 } else {
4117 no_subst:
4118 tok_str_add2(tok_str, t, &cval);
4121 if (macro_str1)
4122 tok_str_free(macro_str1);
4125 /* return next token with macro substitution */
4126 static void next(void)
4128 Sym *nested_list, *s;
4129 TokenString str;
4131 redo:
4132 next_nomacro();
4133 if (!macro_ptr) {
4134 /* if not reading from macro substituted string, then try
4135 to substitute macros */
4136 if (tok >= TOK_IDENT &&
4137 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4138 s = define_find(tok);
4139 if (s) {
4140 /* we have a macro: we try to substitute */
4141 tok_str_new(&str);
4142 nested_list = NULL;
4143 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4144 /* substitution done, NOTE: maybe empty */
4145 tok_str_add(&str, 0);
4146 macro_ptr = str.str;
4147 macro_ptr_allocated = str.str;
4148 goto redo;
4152 } else {
4153 if (tok == 0) {
4154 /* end of macro or end of unget buffer */
4155 if (unget_buffer_enabled) {
4156 macro_ptr = unget_saved_macro_ptr;
4157 unget_buffer_enabled = 0;
4158 } else {
4159 /* end of macro string: free it */
4160 tok_str_free(macro_ptr_allocated);
4161 macro_ptr = NULL;
4163 goto redo;
4167 /* convert preprocessor tokens into C tokens */
4168 if (tok == TOK_PPNUM &&
4169 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4170 parse_number((char *)tokc.cstr->data);
4174 /* push back current token and set current token to 'last_tok'. Only
4175 identifier case handled for labels. */
4176 static inline void unget_tok(int last_tok)
4178 int i, n;
4179 int *q;
4180 unget_saved_macro_ptr = macro_ptr;
4181 unget_buffer_enabled = 1;
4182 q = unget_saved_buffer;
4183 macro_ptr = q;
4184 *q++ = tok;
4185 n = tok_ext_size(tok) - 1;
4186 for(i=0;i<n;i++)
4187 *q++ = tokc.tab[i];
4188 *q = 0; /* end of token string */
4189 tok = last_tok;
4193 void swap(int *p, int *q)
4195 int t;
4196 t = *p;
4197 *p = *q;
4198 *q = t;
4201 void vsetc(CType *type, int r, CValue *vc)
4203 int v;
4205 if (vtop >= vstack + VSTACK_SIZE)
4206 error("memory full");
4207 /* cannot let cpu flags if other instruction are generated. Also
4208 avoid leaving VT_JMP anywhere except on the top of the stack
4209 because it would complicate the code generator. */
4210 if (vtop >= vstack) {
4211 v = vtop->r & VT_VALMASK;
4212 if (v == VT_CMP || (v & ~1) == VT_JMP)
4213 gv(RC_INT);
4215 vtop++;
4216 vtop->type = *type;
4217 vtop->r = r;
4218 vtop->r2 = VT_CONST;
4219 vtop->c = *vc;
4222 /* push integer constant */
4223 void vpushi(int v)
4225 CValue cval;
4226 cval.i = v;
4227 vsetc(&int_type, VT_CONST, &cval);
4230 /* Return a static symbol pointing to a section */
4231 static Sym *get_sym_ref(CType *type, Section *sec,
4232 unsigned long offset, unsigned long size)
4234 int v;
4235 Sym *sym;
4237 v = anon_sym++;
4238 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4239 sym->type.ref = type->ref;
4240 sym->r = VT_CONST | VT_SYM;
4241 put_extern_sym(sym, sec, offset, size);
4242 return sym;
4245 /* push a reference to a section offset by adding a dummy symbol */
4246 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4248 CValue cval;
4250 cval.ul = 0;
4251 vsetc(type, VT_CONST | VT_SYM, &cval);
4252 vtop->sym = get_sym_ref(type, sec, offset, size);
4255 /* define a new external reference to a symbol 'v' of type 'u' */
4256 static Sym *external_global_sym(int v, CType *type, int r)
4258 Sym *s;
4260 s = sym_find(v);
4261 if (!s) {
4262 /* push forward reference */
4263 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4264 s->type.ref = type->ref;
4265 s->r = r | VT_CONST | VT_SYM;
4267 return s;
4270 /* define a new external reference to a symbol 'v' of type 'u' */
4271 static Sym *external_sym(int v, CType *type, int r)
4273 Sym *s;
4275 s = sym_find(v);
4276 if (!s) {
4277 /* push forward reference */
4278 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4279 s->type.t |= VT_EXTERN;
4280 } else {
4281 if (!is_compatible_types(&s->type, type))
4282 error("incompatible types for redefinition of '%s'",
4283 get_tok_str(v, NULL));
4285 return s;
4288 /* push a reference to global symbol v */
4289 static void vpush_global_sym(CType *type, int v)
4291 Sym *sym;
4292 CValue cval;
4294 sym = external_global_sym(v, type, 0);
4295 cval.ul = 0;
4296 vsetc(type, VT_CONST | VT_SYM, &cval);
4297 vtop->sym = sym;
4300 void vset(CType *type, int r, int v)
4302 CValue cval;
4304 cval.i = v;
4305 vsetc(type, r, &cval);
4308 void vseti(int r, int v)
4310 CType type;
4311 type.t = VT_INT;
4312 vset(&type, r, v);
4315 void vswap(void)
4317 SValue tmp;
4319 tmp = vtop[0];
4320 vtop[0] = vtop[-1];
4321 vtop[-1] = tmp;
4324 void vpushv(SValue *v)
4326 if (vtop >= vstack + VSTACK_SIZE)
4327 error("memory full");
4328 vtop++;
4329 *vtop = *v;
4332 void vdup(void)
4334 vpushv(vtop);
4337 /* save r to the memory stack, and mark it as being free */
4338 void save_reg(int r)
4340 int l, saved, size, align;
4341 SValue *p, sv;
4342 CType *type;
4344 /* modify all stack values */
4345 saved = 0;
4346 l = 0;
4347 for(p=vstack;p<=vtop;p++) {
4348 if ((p->r & VT_VALMASK) == r ||
4349 (p->r2 & VT_VALMASK) == r) {
4350 /* must save value on stack if not already done */
4351 if (!saved) {
4352 /* NOTE: must reload 'r' because r might be equal to r2 */
4353 r = p->r & VT_VALMASK;
4354 /* store register in the stack */
4355 type = &p->type;
4356 if ((p->r & VT_LVAL) ||
4357 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4358 type = &int_type;
4359 size = type_size(type, &align);
4360 loc = (loc - size) & -align;
4361 sv.type.t = type->t;
4362 sv.r = VT_LOCAL | VT_LVAL;
4363 sv.c.ul = loc;
4364 store(r, &sv);
4365 #ifdef TCC_TARGET_I386
4366 /* x86 specific: need to pop fp register ST0 if saved */
4367 if (r == TREG_ST0) {
4368 o(0xd9dd); /* fstp %st(1) */
4370 #endif
4371 /* special long long case */
4372 if ((type->t & VT_BTYPE) == VT_LLONG) {
4373 sv.c.ul += 4;
4374 store(p->r2, &sv);
4376 l = loc;
4377 saved = 1;
4379 /* mark that stack entry as being saved on the stack */
4380 if (p->r & VT_LVAL) {
4381 /* also clear the bounded flag because the
4382 relocation address of the function was stored in
4383 p->c.ul */
4384 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4385 } else {
4386 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4388 p->r2 = VT_CONST;
4389 p->c.ul = l;
4394 /* find a register of class 'rc2' with at most one reference on stack.
4395 * If none, call get_reg(rc) */
4396 int get_reg_ex(int rc, int rc2)
4398 int r;
4399 SValue *p;
4401 for(r=0;r<NB_REGS;r++) {
4402 if (reg_classes[r] & rc2) {
4403 int n;
4404 n=0;
4405 for(p = vstack; p <= vtop; p++) {
4406 if ((p->r & VT_VALMASK) == r ||
4407 (p->r2 & VT_VALMASK) == r)
4408 n++;
4410 if (n <= 1)
4411 return r;
4414 return get_reg(rc);
4417 /* find a free register of class 'rc'. If none, save one register */
4418 int get_reg(int rc)
4420 int r;
4421 SValue *p;
4423 /* find a free register */
4424 for(r=0;r<NB_REGS;r++) {
4425 if (reg_classes[r] & rc) {
4426 for(p=vstack;p<=vtop;p++) {
4427 if ((p->r & VT_VALMASK) == r ||
4428 (p->r2 & VT_VALMASK) == r)
4429 goto notfound;
4431 return r;
4433 notfound: ;
4436 /* no register left : free the first one on the stack (VERY
4437 IMPORTANT to start from the bottom to ensure that we don't
4438 spill registers used in gen_opi()) */
4439 for(p=vstack;p<=vtop;p++) {
4440 r = p->r & VT_VALMASK;
4441 if (r < VT_CONST && (reg_classes[r] & rc))
4442 goto save_found;
4443 /* also look at second register (if long long) */
4444 r = p->r2 & VT_VALMASK;
4445 if (r < VT_CONST && (reg_classes[r] & rc)) {
4446 save_found:
4447 save_reg(r);
4448 return r;
4451 /* Should never comes here */
4452 return -1;
4455 /* save registers up to (vtop - n) stack entry */
4456 void save_regs(int n)
4458 int r;
4459 SValue *p, *p1;
4460 p1 = vtop - n;
4461 for(p = vstack;p <= p1; p++) {
4462 r = p->r & VT_VALMASK;
4463 if (r < VT_CONST) {
4464 save_reg(r);
4469 /* move register 's' to 'r', and flush previous value of r to memory
4470 if needed */
4471 void move_reg(int r, int s)
4473 SValue sv;
4475 if (r != s) {
4476 save_reg(r);
4477 sv.type.t = VT_INT;
4478 sv.r = s;
4479 sv.c.ul = 0;
4480 load(r, &sv);
4484 /* get address of vtop (vtop MUST BE an lvalue) */
4485 void gaddrof(void)
4487 vtop->r &= ~VT_LVAL;
4488 /* tricky: if saved lvalue, then we can go back to lvalue */
4489 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4490 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4493 #ifdef CONFIG_TCC_BCHECK
4494 /* generate lvalue bound code */
4495 void gbound(void)
4497 int lval_type;
4498 CType type1;
4500 vtop->r &= ~VT_MUSTBOUND;
4501 /* if lvalue, then use checking code before dereferencing */
4502 if (vtop->r & VT_LVAL) {
4503 /* if not VT_BOUNDED value, then make one */
4504 if (!(vtop->r & VT_BOUNDED)) {
4505 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4506 /* must save type because we must set it to int to get pointer */
4507 type1 = vtop->type;
4508 vtop->type.t = VT_INT;
4509 gaddrof();
4510 vpushi(0);
4511 gen_bounded_ptr_add();
4512 vtop->r |= lval_type;
4513 vtop->type = type1;
4515 /* then check for dereferencing */
4516 gen_bounded_ptr_deref();
4519 #endif
4521 /* store vtop a register belonging to class 'rc'. lvalues are
4522 converted to values. Cannot be used if cannot be converted to
4523 register value (such as structures). */
4524 int gv(int rc)
4526 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4527 unsigned long long ll;
4529 /* NOTE: get_reg can modify vstack[] */
4530 if (vtop->type.t & VT_BITFIELD) {
4531 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4532 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4533 /* remove bit field info to avoid loops */
4534 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4535 /* generate shifts */
4536 vpushi(32 - (bit_pos + bit_size));
4537 gen_op(TOK_SHL);
4538 vpushi(32 - bit_size);
4539 /* NOTE: transformed to SHR if unsigned */
4540 gen_op(TOK_SAR);
4541 r = gv(rc);
4542 } else {
4543 if (is_float(vtop->type.t) &&
4544 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4545 Sym *sym;
4546 int *ptr;
4547 unsigned long offset;
4549 /* XXX: unify with initializers handling ? */
4550 /* CPUs usually cannot use float constants, so we store them
4551 generically in data segment */
4552 size = type_size(&vtop->type, &align);
4553 offset = (data_section->data_offset + align - 1) & -align;
4554 data_section->data_offset = offset;
4555 /* XXX: not portable yet */
4556 ptr = section_ptr_add(data_section, size);
4557 size = size >> 2;
4558 for(i=0;i<size;i++)
4559 ptr[i] = vtop->c.tab[i];
4560 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4561 vtop->r |= VT_LVAL | VT_SYM;
4562 vtop->sym = sym;
4563 vtop->c.ul = 0;
4565 #ifdef CONFIG_TCC_BCHECK
4566 if (vtop->r & VT_MUSTBOUND)
4567 gbound();
4568 #endif
4570 r = vtop->r & VT_VALMASK;
4571 /* need to reload if:
4572 - constant
4573 - lvalue (need to dereference pointer)
4574 - already a register, but not in the right class */
4575 if (r >= VT_CONST ||
4576 (vtop->r & VT_LVAL) ||
4577 !(reg_classes[r] & rc) ||
4578 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4579 !(reg_classes[vtop->r2] & rc))) {
4580 r = get_reg(rc);
4581 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4582 /* two register type load : expand to two words
4583 temporarily */
4584 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4585 /* load constant */
4586 ll = vtop->c.ull;
4587 vtop->c.ui = ll; /* first word */
4588 load(r, vtop);
4589 vtop->r = r; /* save register value */
4590 vpushi(ll >> 32); /* second word */
4591 } else if (r >= VT_CONST ||
4592 (vtop->r & VT_LVAL)) {
4593 /* load from memory */
4594 load(r, vtop);
4595 vdup();
4596 vtop[-1].r = r; /* save register value */
4597 /* increment pointer to get second word */
4598 vtop->type.t = VT_INT;
4599 gaddrof();
4600 vpushi(4);
4601 gen_op('+');
4602 vtop->r |= VT_LVAL;
4603 } else {
4604 /* move registers */
4605 load(r, vtop);
4606 vdup();
4607 vtop[-1].r = r; /* save register value */
4608 vtop->r = vtop[-1].r2;
4610 /* allocate second register */
4611 rc2 = RC_INT;
4612 if (rc == RC_IRET)
4613 rc2 = RC_LRET;
4614 r2 = get_reg(rc2);
4615 load(r2, vtop);
4616 vpop();
4617 /* write second register */
4618 vtop->r2 = r2;
4619 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4620 int t1, t;
4621 /* lvalue of scalar type : need to use lvalue type
4622 because of possible cast */
4623 t = vtop->type.t;
4624 t1 = t;
4625 /* compute memory access type */
4626 if (vtop->r & VT_LVAL_BYTE)
4627 t = VT_BYTE;
4628 else if (vtop->r & VT_LVAL_SHORT)
4629 t = VT_SHORT;
4630 if (vtop->r & VT_LVAL_UNSIGNED)
4631 t |= VT_UNSIGNED;
4632 vtop->type.t = t;
4633 load(r, vtop);
4634 /* restore wanted type */
4635 vtop->type.t = t1;
4636 } else {
4637 /* one register type load */
4638 load(r, vtop);
4641 vtop->r = r;
4642 #ifdef TCC_TARGET_C67
4643 /* uses register pairs for doubles */
4644 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4645 vtop->r2 = r+1;
4646 #endif
4648 return r;
4651 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4652 void gv2(int rc1, int rc2)
4654 int v;
4656 /* generate more generic register first. But VT_JMP or VT_CMP
4657 values must be generated first in all cases to avoid possible
4658 reload errors */
4659 v = vtop[0].r & VT_VALMASK;
4660 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4661 vswap();
4662 gv(rc1);
4663 vswap();
4664 gv(rc2);
4665 /* test if reload is needed for first register */
4666 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4667 vswap();
4668 gv(rc1);
4669 vswap();
4671 } else {
4672 gv(rc2);
4673 vswap();
4674 gv(rc1);
4675 vswap();
4676 /* test if reload is needed for first register */
4677 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4678 gv(rc2);
4683 /* expand long long on stack in two int registers */
4684 void lexpand(void)
4686 int u;
4688 u = vtop->type.t & VT_UNSIGNED;
4689 gv(RC_INT);
4690 vdup();
4691 vtop[0].r = vtop[-1].r2;
4692 vtop[0].r2 = VT_CONST;
4693 vtop[-1].r2 = VT_CONST;
4694 vtop[0].type.t = VT_INT | u;
4695 vtop[-1].type.t = VT_INT | u;
4698 #ifdef TCC_TARGET_ARM
4699 /* expand long long on stack */
4700 void lexpand_nr(void)
4702 int u,v;
4704 u = vtop->type.t & VT_UNSIGNED;
4705 vdup();
4706 vtop->r2 = VT_CONST;
4707 vtop->type.t = VT_INT | u;
4708 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4709 if (v == VT_CONST) {
4710 vtop[-1].c.ui = vtop->c.ull;
4711 vtop->c.ui = vtop->c.ull >> 32;
4712 vtop->r = VT_CONST;
4713 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4714 vtop->c.ui += 4;
4715 vtop->r = vtop[-1].r;
4716 } else if (v > VT_CONST) {
4717 vtop--;
4718 lexpand();
4719 } else
4720 vtop->r = vtop[-1].r2;
4721 vtop[-1].r2 = VT_CONST;
4722 vtop[-1].type.t = VT_INT | u;
4724 #endif
4726 /* build a long long from two ints */
4727 void lbuild(int t)
4729 gv2(RC_INT, RC_INT);
4730 vtop[-1].r2 = vtop[0].r;
4731 vtop[-1].type.t = t;
4732 vpop();
4735 /* rotate n first stack elements to the bottom
4736 I1 ... In -> I2 ... In I1 [top is right]
4738 void vrotb(int n)
4740 int i;
4741 SValue tmp;
4743 tmp = vtop[-n + 1];
4744 for(i=-n+1;i!=0;i++)
4745 vtop[i] = vtop[i+1];
4746 vtop[0] = tmp;
4749 /* rotate n first stack elements to the top
4750 I1 ... In -> In I1 ... I(n-1) [top is right]
4752 void vrott(int n)
4754 int i;
4755 SValue tmp;
4757 tmp = vtop[0];
4758 for(i = 0;i < n - 1; i++)
4759 vtop[-i] = vtop[-i - 1];
4760 vtop[-n + 1] = tmp;
4763 #ifdef TCC_TARGET_ARM
4764 /* like vrott but in other direction
4765 In ... I1 -> I(n-1) ... I1 In [top is right]
4767 void vnrott(int n)
4769 int i;
4770 SValue tmp;
4772 tmp = vtop[-n + 1];
4773 for(i = n - 1; i > 0; i--)
4774 vtop[-i] = vtop[-i + 1];
4775 vtop[0] = tmp;
4777 #endif
4779 /* pop stack value */
4780 void vpop(void)
4782 int v;
4783 v = vtop->r & VT_VALMASK;
4784 #ifdef TCC_TARGET_I386
4785 /* for x86, we need to pop the FP stack */
4786 if (v == TREG_ST0 && !nocode_wanted) {
4787 o(0xd9dd); /* fstp %st(1) */
4788 } else
4789 #endif
4790 if (v == VT_JMP || v == VT_JMPI) {
4791 /* need to put correct jump if && or || without test */
4792 gsym(vtop->c.ul);
4794 vtop--;
4797 /* convert stack entry to register and duplicate its value in another
4798 register */
4799 void gv_dup(void)
4801 int rc, t, r, r1;
4802 SValue sv;
4804 t = vtop->type.t;
4805 if ((t & VT_BTYPE) == VT_LLONG) {
4806 lexpand();
4807 gv_dup();
4808 vswap();
4809 vrotb(3);
4810 gv_dup();
4811 vrotb(4);
4812 /* stack: H L L1 H1 */
4813 lbuild(t);
4814 vrotb(3);
4815 vrotb(3);
4816 vswap();
4817 lbuild(t);
4818 vswap();
4819 } else {
4820 /* duplicate value */
4821 rc = RC_INT;
4822 sv.type.t = VT_INT;
4823 if (is_float(t)) {
4824 rc = RC_FLOAT;
4825 sv.type.t = t;
4827 r = gv(rc);
4828 r1 = get_reg(rc);
4829 sv.r = r;
4830 sv.c.ul = 0;
4831 load(r1, &sv); /* move r to r1 */
4832 vdup();
4833 /* duplicates value */
4834 vtop->r = r1;
4838 /* generate CPU independent (unsigned) long long operations */
4839 void gen_opl(int op)
4841 int t, a, b, op1, c, i;
4842 int func;
4843 SValue tmp;
4845 switch(op) {
4846 case '/':
4847 case TOK_PDIV:
4848 func = TOK___divdi3;
4849 goto gen_func;
4850 case TOK_UDIV:
4851 func = TOK___udivdi3;
4852 goto gen_func;
4853 case '%':
4854 func = TOK___moddi3;
4855 goto gen_func;
4856 case TOK_UMOD:
4857 func = TOK___umoddi3;
4858 gen_func:
4859 /* call generic long long function */
4860 vpush_global_sym(&func_old_type, func);
4861 vrott(3);
4862 gfunc_call(2);
4863 vpushi(0);
4864 vtop->r = REG_IRET;
4865 vtop->r2 = REG_LRET;
4866 break;
4867 case '^':
4868 case '&':
4869 case '|':
4870 case '*':
4871 case '+':
4872 case '-':
4873 t = vtop->type.t;
4874 vswap();
4875 lexpand();
4876 vrotb(3);
4877 lexpand();
4878 /* stack: L1 H1 L2 H2 */
4879 tmp = vtop[0];
4880 vtop[0] = vtop[-3];
4881 vtop[-3] = tmp;
4882 tmp = vtop[-2];
4883 vtop[-2] = vtop[-3];
4884 vtop[-3] = tmp;
4885 vswap();
4886 /* stack: H1 H2 L1 L2 */
4887 if (op == '*') {
4888 vpushv(vtop - 1);
4889 vpushv(vtop - 1);
4890 gen_op(TOK_UMULL);
4891 lexpand();
4892 /* stack: H1 H2 L1 L2 ML MH */
4893 for(i=0;i<4;i++)
4894 vrotb(6);
4895 /* stack: ML MH H1 H2 L1 L2 */
4896 tmp = vtop[0];
4897 vtop[0] = vtop[-2];
4898 vtop[-2] = tmp;
4899 /* stack: ML MH H1 L2 H2 L1 */
4900 gen_op('*');
4901 vrotb(3);
4902 vrotb(3);
4903 gen_op('*');
4904 /* stack: ML MH M1 M2 */
4905 gen_op('+');
4906 gen_op('+');
4907 } else if (op == '+' || op == '-') {
4908 /* XXX: add non carry method too (for MIPS or alpha) */
4909 if (op == '+')
4910 op1 = TOK_ADDC1;
4911 else
4912 op1 = TOK_SUBC1;
4913 gen_op(op1);
4914 /* stack: H1 H2 (L1 op L2) */
4915 vrotb(3);
4916 vrotb(3);
4917 gen_op(op1 + 1); /* TOK_xxxC2 */
4918 } else {
4919 gen_op(op);
4920 /* stack: H1 H2 (L1 op L2) */
4921 vrotb(3);
4922 vrotb(3);
4923 /* stack: (L1 op L2) H1 H2 */
4924 gen_op(op);
4925 /* stack: (L1 op L2) (H1 op H2) */
4927 /* stack: L H */
4928 lbuild(t);
4929 break;
4930 case TOK_SAR:
4931 case TOK_SHR:
4932 case TOK_SHL:
4933 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4934 t = vtop[-1].type.t;
4935 vswap();
4936 lexpand();
4937 vrotb(3);
4938 /* stack: L H shift */
4939 c = (int)vtop->c.i;
4940 /* constant: simpler */
4941 /* NOTE: all comments are for SHL. the other cases are
4942 done by swaping words */
4943 vpop();
4944 if (op != TOK_SHL)
4945 vswap();
4946 if (c >= 32) {
4947 /* stack: L H */
4948 vpop();
4949 if (c > 32) {
4950 vpushi(c - 32);
4951 gen_op(op);
4953 if (op != TOK_SAR) {
4954 vpushi(0);
4955 } else {
4956 gv_dup();
4957 vpushi(31);
4958 gen_op(TOK_SAR);
4960 vswap();
4961 } else {
4962 vswap();
4963 gv_dup();
4964 /* stack: H L L */
4965 vpushi(c);
4966 gen_op(op);
4967 vswap();
4968 vpushi(32 - c);
4969 if (op == TOK_SHL)
4970 gen_op(TOK_SHR);
4971 else
4972 gen_op(TOK_SHL);
4973 vrotb(3);
4974 /* stack: L L H */
4975 vpushi(c);
4976 if (op == TOK_SHL)
4977 gen_op(TOK_SHL);
4978 else
4979 gen_op(TOK_SHR);
4980 gen_op('|');
4982 if (op != TOK_SHL)
4983 vswap();
4984 lbuild(t);
4985 } else {
4986 /* XXX: should provide a faster fallback on x86 ? */
4987 switch(op) {
4988 case TOK_SAR:
4989 func = TOK___sardi3;
4990 goto gen_func;
4991 case TOK_SHR:
4992 func = TOK___shrdi3;
4993 goto gen_func;
4994 case TOK_SHL:
4995 func = TOK___shldi3;
4996 goto gen_func;
4999 break;
5000 default:
5001 /* compare operations */
5002 t = vtop->type.t;
5003 vswap();
5004 lexpand();
5005 vrotb(3);
5006 lexpand();
5007 /* stack: L1 H1 L2 H2 */
5008 tmp = vtop[-1];
5009 vtop[-1] = vtop[-2];
5010 vtop[-2] = tmp;
5011 /* stack: L1 L2 H1 H2 */
5012 /* compare high */
5013 op1 = op;
5014 /* when values are equal, we need to compare low words. since
5015 the jump is inverted, we invert the test too. */
5016 if (op1 == TOK_LT)
5017 op1 = TOK_LE;
5018 else if (op1 == TOK_GT)
5019 op1 = TOK_GE;
5020 else if (op1 == TOK_ULT)
5021 op1 = TOK_ULE;
5022 else if (op1 == TOK_UGT)
5023 op1 = TOK_UGE;
5024 a = 0;
5025 b = 0;
5026 gen_op(op1);
5027 if (op1 != TOK_NE) {
5028 a = gtst(1, 0);
5030 if (op != TOK_EQ) {
5031 /* generate non equal test */
5032 /* XXX: NOT PORTABLE yet */
5033 if (a == 0) {
5034 b = gtst(0, 0);
5035 } else {
5036 #if defined(TCC_TARGET_I386)
5037 b = psym(0x850f, 0);
5038 #elif defined(TCC_TARGET_ARM)
5039 b = ind;
5040 o(0x1A000000 | encbranch(ind, 0, 1));
5041 #elif defined(TCC_TARGET_C67)
5042 error("not implemented");
5043 #else
5044 #error not supported
5045 #endif
5048 /* compare low. Always unsigned */
5049 op1 = op;
5050 if (op1 == TOK_LT)
5051 op1 = TOK_ULT;
5052 else if (op1 == TOK_LE)
5053 op1 = TOK_ULE;
5054 else if (op1 == TOK_GT)
5055 op1 = TOK_UGT;
5056 else if (op1 == TOK_GE)
5057 op1 = TOK_UGE;
5058 gen_op(op1);
5059 a = gtst(1, a);
5060 gsym(b);
5061 vseti(VT_JMPI, a);
5062 break;
5066 /* handle integer constant optimizations and various machine
5067 independent opt */
5068 void gen_opic(int op)
5070 int fc, c1, c2, n;
5071 SValue *v1, *v2;
5073 v1 = vtop - 1;
5074 v2 = vtop;
5075 /* currently, we cannot do computations with forward symbols */
5076 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5077 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5078 if (c1 && c2) {
5079 fc = v2->c.i;
5080 switch(op) {
5081 case '+': v1->c.i += fc; break;
5082 case '-': v1->c.i -= fc; break;
5083 case '&': v1->c.i &= fc; break;
5084 case '^': v1->c.i ^= fc; break;
5085 case '|': v1->c.i |= fc; break;
5086 case '*': v1->c.i *= fc; break;
5088 case TOK_PDIV:
5089 case '/':
5090 case '%':
5091 case TOK_UDIV:
5092 case TOK_UMOD:
5093 /* if division by zero, generate explicit division */
5094 if (fc == 0) {
5095 if (const_wanted)
5096 error("division by zero in constant");
5097 goto general_case;
5099 switch(op) {
5100 default: v1->c.i /= fc; break;
5101 case '%': v1->c.i %= fc; break;
5102 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5103 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5105 break;
5106 case TOK_SHL: v1->c.i <<= fc; break;
5107 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5108 case TOK_SAR: v1->c.i >>= fc; break;
5109 /* tests */
5110 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5111 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5112 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5113 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5114 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5115 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5116 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5117 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5118 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5119 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5120 /* logical */
5121 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5122 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5123 default:
5124 goto general_case;
5126 vtop--;
5127 } else {
5128 /* if commutative ops, put c2 as constant */
5129 if (c1 && (op == '+' || op == '&' || op == '^' ||
5130 op == '|' || op == '*')) {
5131 vswap();
5132 swap(&c1, &c2);
5134 fc = vtop->c.i;
5135 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5136 op == TOK_PDIV) &&
5137 fc == 1) ||
5138 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5139 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5140 fc == 0) ||
5141 (op == '&' &&
5142 fc == -1))) {
5143 /* nothing to do */
5144 vtop--;
5145 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5146 /* try to use shifts instead of muls or divs */
5147 if (fc > 0 && (fc & (fc - 1)) == 0) {
5148 n = -1;
5149 while (fc) {
5150 fc >>= 1;
5151 n++;
5153 vtop->c.i = n;
5154 if (op == '*')
5155 op = TOK_SHL;
5156 else if (op == TOK_PDIV)
5157 op = TOK_SAR;
5158 else
5159 op = TOK_SHR;
5161 goto general_case;
5162 } else if (c2 && (op == '+' || op == '-') &&
5163 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5164 (VT_CONST | VT_SYM)) {
5165 /* symbol + constant case */
5166 if (op == '-')
5167 fc = -fc;
5168 vtop--;
5169 vtop->c.i += fc;
5170 } else {
5171 general_case:
5172 if (!nocode_wanted) {
5173 /* call low level op generator */
5174 gen_opi(op);
5175 } else {
5176 vtop--;
5182 /* generate a floating point operation with constant propagation */
5183 void gen_opif(int op)
5185 int c1, c2;
5186 SValue *v1, *v2;
5187 long double f1, f2;
5189 v1 = vtop - 1;
5190 v2 = vtop;
5191 /* currently, we cannot do computations with forward symbols */
5192 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5193 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5194 if (c1 && c2) {
5195 if (v1->type.t == VT_FLOAT) {
5196 f1 = v1->c.f;
5197 f2 = v2->c.f;
5198 } else if (v1->type.t == VT_DOUBLE) {
5199 f1 = v1->c.d;
5200 f2 = v2->c.d;
5201 } else {
5202 f1 = v1->c.ld;
5203 f2 = v2->c.ld;
5206 /* NOTE: we only do constant propagation if finite number (not
5207 NaN or infinity) (ANSI spec) */
5208 if (!ieee_finite(f1) || !ieee_finite(f2))
5209 goto general_case;
5211 switch(op) {
5212 case '+': f1 += f2; break;
5213 case '-': f1 -= f2; break;
5214 case '*': f1 *= f2; break;
5215 case '/':
5216 if (f2 == 0.0) {
5217 if (const_wanted)
5218 error("division by zero in constant");
5219 goto general_case;
5221 f1 /= f2;
5222 break;
5223 /* XXX: also handles tests ? */
5224 default:
5225 goto general_case;
5227 /* XXX: overflow test ? */
5228 if (v1->type.t == VT_FLOAT) {
5229 v1->c.f = f1;
5230 } else if (v1->type.t == VT_DOUBLE) {
5231 v1->c.d = f1;
5232 } else {
5233 v1->c.ld = f1;
5235 vtop--;
5236 } else {
5237 general_case:
5238 if (!nocode_wanted) {
5239 gen_opf(op);
5240 } else {
5241 vtop--;
5246 static int pointed_size(CType *type)
5248 int align;
5249 return type_size(pointed_type(type), &align);
5252 static inline int is_null_pointer(SValue *p)
5254 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5255 return 0;
5256 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5257 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5260 static inline int is_integer_btype(int bt)
5262 return (bt == VT_BYTE || bt == VT_SHORT ||
5263 bt == VT_INT || bt == VT_LLONG);
5266 /* check types for comparison or substraction of pointers */
5267 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5269 CType *type1, *type2, tmp_type1, tmp_type2;
5270 int bt1, bt2;
5272 /* null pointers are accepted for all comparisons as gcc */
5273 if (is_null_pointer(p1) || is_null_pointer(p2))
5274 return;
5275 type1 = &p1->type;
5276 type2 = &p2->type;
5277 bt1 = type1->t & VT_BTYPE;
5278 bt2 = type2->t & VT_BTYPE;
5279 /* accept comparison between pointer and integer with a warning */
5280 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5281 warning("comparison between pointer and integer");
5282 return;
5285 /* both must be pointers or implicit function pointers */
5286 if (bt1 == VT_PTR) {
5287 type1 = pointed_type(type1);
5288 } else if (bt1 != VT_FUNC)
5289 goto invalid_operands;
5291 if (bt2 == VT_PTR) {
5292 type2 = pointed_type(type2);
5293 } else if (bt2 != VT_FUNC) {
5294 invalid_operands:
5295 error("invalid operands to binary %s", get_tok_str(op, NULL));
5297 if ((type1->t & VT_BTYPE) == VT_VOID ||
5298 (type2->t & VT_BTYPE) == VT_VOID)
5299 return;
5300 tmp_type1 = *type1;
5301 tmp_type2 = *type2;
5302 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5303 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5304 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5305 /* gcc-like error if '-' is used */
5306 if (op == '-')
5307 goto invalid_operands;
5308 else
5309 warning("comparison of distinct pointer types lacks a cast");
5313 /* generic gen_op: handles types problems */
5314 void gen_op(int op)
5316 int u, t1, t2, bt1, bt2, t;
5317 CType type1;
5319 t1 = vtop[-1].type.t;
5320 t2 = vtop[0].type.t;
5321 bt1 = t1 & VT_BTYPE;
5322 bt2 = t2 & VT_BTYPE;
5324 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5325 /* at least one operand is a pointer */
5326 /* relationnal op: must be both pointers */
5327 if (op >= TOK_ULT && op <= TOK_GT) {
5328 check_comparison_pointer_types(vtop - 1, vtop, op);
5329 /* pointers are handled are unsigned */
5330 t = VT_INT | VT_UNSIGNED;
5331 goto std_op;
5333 /* if both pointers, then it must be the '-' op */
5334 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5335 if (op != '-')
5336 error("cannot use pointers here");
5337 check_comparison_pointer_types(vtop - 1, vtop, op);
5338 /* XXX: check that types are compatible */
5339 u = pointed_size(&vtop[-1].type);
5340 gen_opic(op);
5341 /* set to integer type */
5342 vtop->type.t = VT_INT;
5343 vpushi(u);
5344 gen_op(TOK_PDIV);
5345 } else {
5346 /* exactly one pointer : must be '+' or '-'. */
5347 if (op != '-' && op != '+')
5348 error("cannot use pointers here");
5349 /* Put pointer as first operand */
5350 if (bt2 == VT_PTR) {
5351 vswap();
5352 swap(&t1, &t2);
5354 type1 = vtop[-1].type;
5355 /* XXX: cast to int ? (long long case) */
5356 vpushi(pointed_size(&vtop[-1].type));
5357 gen_op('*');
5358 #ifdef CONFIG_TCC_BCHECK
5359 /* if evaluating constant expression, no code should be
5360 generated, so no bound check */
5361 if (do_bounds_check && !const_wanted) {
5362 /* if bounded pointers, we generate a special code to
5363 test bounds */
5364 if (op == '-') {
5365 vpushi(0);
5366 vswap();
5367 gen_op('-');
5369 gen_bounded_ptr_add();
5370 } else
5371 #endif
5373 gen_opic(op);
5375 /* put again type if gen_opic() swaped operands */
5376 vtop->type = type1;
5378 } else if (is_float(bt1) || is_float(bt2)) {
5379 /* compute bigger type and do implicit casts */
5380 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5381 t = VT_LDOUBLE;
5382 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5383 t = VT_DOUBLE;
5384 } else {
5385 t = VT_FLOAT;
5387 /* floats can only be used for a few operations */
5388 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5389 (op < TOK_ULT || op > TOK_GT))
5390 error("invalid operands for binary operation");
5391 goto std_op;
5392 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5393 /* cast to biggest op */
5394 t = VT_LLONG;
5395 /* convert to unsigned if it does not fit in a long long */
5396 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5397 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5398 t |= VT_UNSIGNED;
5399 goto std_op;
5400 } else {
5401 /* integer operations */
5402 t = VT_INT;
5403 /* convert to unsigned if it does not fit in an integer */
5404 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5405 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5406 t |= VT_UNSIGNED;
5407 std_op:
5408 /* XXX: currently, some unsigned operations are explicit, so
5409 we modify them here */
5410 if (t & VT_UNSIGNED) {
5411 if (op == TOK_SAR)
5412 op = TOK_SHR;
5413 else if (op == '/')
5414 op = TOK_UDIV;
5415 else if (op == '%')
5416 op = TOK_UMOD;
5417 else if (op == TOK_LT)
5418 op = TOK_ULT;
5419 else if (op == TOK_GT)
5420 op = TOK_UGT;
5421 else if (op == TOK_LE)
5422 op = TOK_ULE;
5423 else if (op == TOK_GE)
5424 op = TOK_UGE;
5426 vswap();
5427 type1.t = t;
5428 gen_cast(&type1);
5429 vswap();
5430 /* special case for shifts and long long: we keep the shift as
5431 an integer */
5432 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5433 type1.t = VT_INT;
5434 gen_cast(&type1);
5435 if (is_float(t))
5436 gen_opif(op);
5437 else if ((t & VT_BTYPE) == VT_LLONG)
5438 gen_opl(op);
5439 else
5440 gen_opic(op);
5441 if (op >= TOK_ULT && op <= TOK_GT) {
5442 /* relationnal op: the result is an int */
5443 vtop->type.t = VT_INT;
5444 } else {
5445 vtop->type.t = t;
5450 /* generic itof for unsigned long long case */
5451 void gen_cvt_itof1(int t)
5453 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5454 (VT_LLONG | VT_UNSIGNED)) {
5456 if (t == VT_FLOAT)
5457 vpush_global_sym(&func_old_type, TOK___ulltof);
5458 else if (t == VT_DOUBLE)
5459 vpush_global_sym(&func_old_type, TOK___ulltod);
5460 else
5461 vpush_global_sym(&func_old_type, TOK___ulltold);
5462 vrott(2);
5463 gfunc_call(1);
5464 vpushi(0);
5465 vtop->r = REG_FRET;
5466 } else {
5467 gen_cvt_itof(t);
5471 /* generic ftoi for unsigned long long case */
5472 void gen_cvt_ftoi1(int t)
5474 int st;
5476 if (t == (VT_LLONG | VT_UNSIGNED)) {
5477 /* not handled natively */
5478 st = vtop->type.t & VT_BTYPE;
5479 if (st == VT_FLOAT)
5480 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5481 else if (st == VT_DOUBLE)
5482 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5483 else
5484 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5485 vrott(2);
5486 gfunc_call(1);
5487 vpushi(0);
5488 vtop->r = REG_IRET;
5489 vtop->r2 = REG_LRET;
5490 } else {
5491 gen_cvt_ftoi(t);
5495 /* force char or short cast */
5496 void force_charshort_cast(int t)
5498 int bits, dbt;
5499 dbt = t & VT_BTYPE;
5500 /* XXX: add optimization if lvalue : just change type and offset */
5501 if (dbt == VT_BYTE)
5502 bits = 8;
5503 else
5504 bits = 16;
5505 if (t & VT_UNSIGNED) {
5506 vpushi((1 << bits) - 1);
5507 gen_op('&');
5508 } else {
5509 bits = 32 - bits;
5510 vpushi(bits);
5511 gen_op(TOK_SHL);
5512 vpushi(bits);
5513 gen_op(TOK_SAR);
5517 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5518 static void gen_cast(CType *type)
5520 int sbt, dbt, sf, df, c;
5522 /* special delayed cast for char/short */
5523 /* XXX: in some cases (multiple cascaded casts), it may still
5524 be incorrect */
5525 if (vtop->r & VT_MUSTCAST) {
5526 vtop->r &= ~VT_MUSTCAST;
5527 force_charshort_cast(vtop->type.t);
5530 /* bitfields first get cast to ints */
5531 if (vtop->type.t & VT_BITFIELD) {
5532 gv(RC_INT);
5535 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5536 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5538 if (sbt != dbt && !nocode_wanted) {
5539 sf = is_float(sbt);
5540 df = is_float(dbt);
5541 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5542 if (sf && df) {
5543 /* convert from fp to fp */
5544 if (c) {
5545 /* constant case: we can do it now */
5546 /* XXX: in ISOC, cannot do it if error in convert */
5547 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5548 vtop->c.f = (float)vtop->c.d;
5549 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5550 vtop->c.f = (float)vtop->c.ld;
5551 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5552 vtop->c.d = (double)vtop->c.f;
5553 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5554 vtop->c.d = (double)vtop->c.ld;
5555 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5556 vtop->c.ld = (long double)vtop->c.f;
5557 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5558 vtop->c.ld = (long double)vtop->c.d;
5559 } else {
5560 /* non constant case: generate code */
5561 gen_cvt_ftof(dbt);
5563 } else if (df) {
5564 /* convert int to fp */
5565 if (c) {
5566 switch(sbt) {
5567 case VT_LLONG | VT_UNSIGNED:
5568 case VT_LLONG:
5569 /* XXX: add const cases for long long */
5570 goto do_itof;
5571 case VT_INT | VT_UNSIGNED:
5572 switch(dbt) {
5573 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5574 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5575 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5577 break;
5578 default:
5579 switch(dbt) {
5580 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5581 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5582 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5584 break;
5586 } else {
5587 do_itof:
5588 #if !defined(TCC_TARGET_ARM)
5589 gen_cvt_itof1(dbt);
5590 #else
5591 gen_cvt_itof(dbt);
5592 #endif
5594 } else if (sf) {
5595 /* convert fp to int */
5596 /* we handle char/short/etc... with generic code */
5597 if (dbt != (VT_INT | VT_UNSIGNED) &&
5598 dbt != (VT_LLONG | VT_UNSIGNED) &&
5599 dbt != VT_LLONG)
5600 dbt = VT_INT;
5601 if (c) {
5602 switch(dbt) {
5603 case VT_LLONG | VT_UNSIGNED:
5604 case VT_LLONG:
5605 /* XXX: add const cases for long long */
5606 goto do_ftoi;
5607 case VT_INT | VT_UNSIGNED:
5608 switch(sbt) {
5609 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5610 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5611 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5613 break;
5614 default:
5615 /* int case */
5616 switch(sbt) {
5617 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5618 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5619 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5621 break;
5623 } else {
5624 do_ftoi:
5625 gen_cvt_ftoi1(dbt);
5627 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5628 /* additional cast for char/short/bool... */
5629 vtop->type.t = dbt;
5630 gen_cast(type);
5632 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5633 if ((sbt & VT_BTYPE) != VT_LLONG) {
5634 /* scalar to long long */
5635 if (c) {
5636 if (sbt == (VT_INT | VT_UNSIGNED))
5637 vtop->c.ll = vtop->c.ui;
5638 else
5639 vtop->c.ll = vtop->c.i;
5640 } else {
5641 /* machine independent conversion */
5642 gv(RC_INT);
5643 /* generate high word */
5644 if (sbt == (VT_INT | VT_UNSIGNED)) {
5645 vpushi(0);
5646 gv(RC_INT);
5647 } else {
5648 gv_dup();
5649 vpushi(31);
5650 gen_op(TOK_SAR);
5652 /* patch second register */
5653 vtop[-1].r2 = vtop->r;
5654 vpop();
5657 } else if (dbt == VT_BOOL) {
5658 /* scalar to bool */
5659 vpushi(0);
5660 gen_op(TOK_NE);
5661 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5662 (dbt & VT_BTYPE) == VT_SHORT) {
5663 force_charshort_cast(dbt);
5664 } else if ((dbt & VT_BTYPE) == VT_INT) {
5665 /* scalar to int */
5666 if (sbt == VT_LLONG) {
5667 /* from long long: just take low order word */
5668 lexpand();
5669 vpop();
5671 /* if lvalue and single word type, nothing to do because
5672 the lvalue already contains the real type size (see
5673 VT_LVAL_xxx constants) */
5676 vtop->type = *type;
5679 /* return type size. Put alignment at 'a' */
5680 static int type_size(CType *type, int *a)
5682 Sym *s;
5683 int bt;
5685 bt = type->t & VT_BTYPE;
5686 if (bt == VT_STRUCT) {
5687 /* struct/union */
5688 s = type->ref;
5689 *a = s->r;
5690 return s->c;
5691 } else if (bt == VT_PTR) {
5692 if (type->t & VT_ARRAY) {
5693 s = type->ref;
5694 return type_size(&s->type, a) * s->c;
5695 } else {
5696 *a = PTR_SIZE;
5697 return PTR_SIZE;
5699 } else if (bt == VT_LDOUBLE) {
5700 *a = LDOUBLE_ALIGN;
5701 return LDOUBLE_SIZE;
5702 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5703 #ifdef TCC_TARGET_I386
5704 *a = 4;
5705 #else
5706 *a = 8;
5707 #endif
5708 return 8;
5709 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5710 *a = 4;
5711 return 4;
5712 } else if (bt == VT_SHORT) {
5713 *a = 2;
5714 return 2;
5715 } else {
5716 /* char, void, function, _Bool */
5717 *a = 1;
5718 return 1;
5722 /* return the pointed type of t */
5723 static inline CType *pointed_type(CType *type)
5725 return &type->ref->type;
5728 /* modify type so that its it is a pointer to type. */
5729 static void mk_pointer(CType *type)
5731 Sym *s;
5732 s = sym_push(SYM_FIELD, type, 0, -1);
5733 type->t = VT_PTR | (type->t & ~VT_TYPE);
5734 type->ref = s;
5737 /* compare function types. OLD functions match any new functions */
5738 static int is_compatible_func(CType *type1, CType *type2)
5740 Sym *s1, *s2;
5742 s1 = type1->ref;
5743 s2 = type2->ref;
5744 if (!is_compatible_types(&s1->type, &s2->type))
5745 return 0;
5746 /* XXX: not complete */
5747 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5748 return 1;
5749 if (s1->c != s2->c)
5750 return 0;
5751 while (s1 != NULL) {
5752 if (s2 == NULL)
5753 return 0;
5754 if (!is_compatible_types(&s1->type, &s2->type))
5755 return 0;
5756 s1 = s1->next;
5757 s2 = s2->next;
5759 if (s2)
5760 return 0;
5761 return 1;
5764 /* return true if type1 and type2 are exactly the same (including
5765 qualifiers).
5767 - enums are not checked as gcc __builtin_types_compatible_p ()
5769 static int is_compatible_types(CType *type1, CType *type2)
5771 int bt1, t1, t2;
5773 t1 = type1->t & VT_TYPE;
5774 t2 = type2->t & VT_TYPE;
5775 /* XXX: bitfields ? */
5776 if (t1 != t2)
5777 return 0;
5778 /* test more complicated cases */
5779 bt1 = t1 & VT_BTYPE;
5780 if (bt1 == VT_PTR) {
5781 type1 = pointed_type(type1);
5782 type2 = pointed_type(type2);
5783 return is_compatible_types(type1, type2);
5784 } else if (bt1 == VT_STRUCT) {
5785 return (type1->ref == type2->ref);
5786 } else if (bt1 == VT_FUNC) {
5787 return is_compatible_func(type1, type2);
5788 } else {
5789 return 1;
5793 /* print a type. If 'varstr' is not NULL, then the variable is also
5794 printed in the type */
5795 /* XXX: union */
5796 /* XXX: add array and function pointers */
5797 void type_to_str(char *buf, int buf_size,
5798 CType *type, const char *varstr)
5800 int bt, v, t;
5801 Sym *s, *sa;
5802 char buf1[256];
5803 const char *tstr;
5805 t = type->t & VT_TYPE;
5806 bt = t & VT_BTYPE;
5807 buf[0] = '\0';
5808 if (t & VT_CONSTANT)
5809 pstrcat(buf, buf_size, "const ");
5810 if (t & VT_VOLATILE)
5811 pstrcat(buf, buf_size, "volatile ");
5812 if (t & VT_UNSIGNED)
5813 pstrcat(buf, buf_size, "unsigned ");
5814 switch(bt) {
5815 case VT_VOID:
5816 tstr = "void";
5817 goto add_tstr;
5818 case VT_BOOL:
5819 tstr = "_Bool";
5820 goto add_tstr;
5821 case VT_BYTE:
5822 tstr = "char";
5823 goto add_tstr;
5824 case VT_SHORT:
5825 tstr = "short";
5826 goto add_tstr;
5827 case VT_INT:
5828 tstr = "int";
5829 goto add_tstr;
5830 case VT_LONG:
5831 tstr = "long";
5832 goto add_tstr;
5833 case VT_LLONG:
5834 tstr = "long long";
5835 goto add_tstr;
5836 case VT_FLOAT:
5837 tstr = "float";
5838 goto add_tstr;
5839 case VT_DOUBLE:
5840 tstr = "double";
5841 goto add_tstr;
5842 case VT_LDOUBLE:
5843 tstr = "long double";
5844 add_tstr:
5845 pstrcat(buf, buf_size, tstr);
5846 break;
5847 case VT_ENUM:
5848 case VT_STRUCT:
5849 if (bt == VT_STRUCT)
5850 tstr = "struct ";
5851 else
5852 tstr = "enum ";
5853 pstrcat(buf, buf_size, tstr);
5854 v = type->ref->v & ~SYM_STRUCT;
5855 if (v >= SYM_FIRST_ANOM)
5856 pstrcat(buf, buf_size, "<anonymous>");
5857 else
5858 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5859 break;
5860 case VT_FUNC:
5861 s = type->ref;
5862 type_to_str(buf, buf_size, &s->type, varstr);
5863 pstrcat(buf, buf_size, "(");
5864 sa = s->next;
5865 while (sa != NULL) {
5866 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5867 pstrcat(buf, buf_size, buf1);
5868 sa = sa->next;
5869 if (sa)
5870 pstrcat(buf, buf_size, ", ");
5872 pstrcat(buf, buf_size, ")");
5873 goto no_var;
5874 case VT_PTR:
5875 s = type->ref;
5876 pstrcpy(buf1, sizeof(buf1), "*");
5877 if (varstr)
5878 pstrcat(buf1, sizeof(buf1), varstr);
5879 type_to_str(buf, buf_size, &s->type, buf1);
5880 goto no_var;
5882 if (varstr) {
5883 pstrcat(buf, buf_size, " ");
5884 pstrcat(buf, buf_size, varstr);
5886 no_var: ;
5889 /* verify type compatibility to store vtop in 'dt' type, and generate
5890 casts if needed. */
5891 static void gen_assign_cast(CType *dt)
5893 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5894 char buf1[256], buf2[256];
5895 int dbt, sbt;
5897 st = &vtop->type; /* source type */
5898 dbt = dt->t & VT_BTYPE;
5899 sbt = st->t & VT_BTYPE;
5900 if (dt->t & VT_CONSTANT)
5901 warning("assignment of read-only location");
5902 switch(dbt) {
5903 case VT_PTR:
5904 /* special cases for pointers */
5905 /* '0' can also be a pointer */
5906 if (is_null_pointer(vtop))
5907 goto type_ok;
5908 /* accept implicit pointer to integer cast with warning */
5909 if (is_integer_btype(sbt)) {
5910 warning("assignment makes pointer from integer without a cast");
5911 goto type_ok;
5913 type1 = pointed_type(dt);
5914 /* a function is implicitely a function pointer */
5915 if (sbt == VT_FUNC) {
5916 if ((type1->t & VT_BTYPE) != VT_VOID &&
5917 !is_compatible_types(pointed_type(dt), st))
5918 goto error;
5919 else
5920 goto type_ok;
5922 if (sbt != VT_PTR)
5923 goto error;
5924 type2 = pointed_type(st);
5925 if ((type1->t & VT_BTYPE) == VT_VOID ||
5926 (type2->t & VT_BTYPE) == VT_VOID) {
5927 /* void * can match anything */
5928 } else {
5929 /* exact type match, except for unsigned */
5930 tmp_type1 = *type1;
5931 tmp_type2 = *type2;
5932 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5933 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5934 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5935 goto error;
5937 /* check const and volatile */
5938 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5939 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5940 warning("assignment discards qualifiers from pointer target type");
5941 break;
5942 case VT_BYTE:
5943 case VT_SHORT:
5944 case VT_INT:
5945 case VT_LLONG:
5946 if (sbt == VT_PTR || sbt == VT_FUNC) {
5947 warning("assignment makes integer from pointer without a cast");
5949 /* XXX: more tests */
5950 break;
5951 case VT_STRUCT:
5952 tmp_type1 = *dt;
5953 tmp_type2 = *st;
5954 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
5955 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
5956 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5957 error:
5958 type_to_str(buf1, sizeof(buf1), st, NULL);
5959 type_to_str(buf2, sizeof(buf2), dt, NULL);
5960 error("cannot cast '%s' to '%s'", buf1, buf2);
5962 break;
5964 type_ok:
5965 gen_cast(dt);
5968 /* store vtop in lvalue pushed on stack */
5969 void vstore(void)
5971 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5973 ft = vtop[-1].type.t;
5974 sbt = vtop->type.t & VT_BTYPE;
5975 dbt = ft & VT_BTYPE;
5976 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5977 (sbt == VT_INT && dbt == VT_SHORT)) {
5978 /* optimize char/short casts */
5979 delayed_cast = VT_MUSTCAST;
5980 vtop->type.t = ft & VT_TYPE;
5981 /* XXX: factorize */
5982 if (ft & VT_CONSTANT)
5983 warning("assignment of read-only location");
5984 } else {
5985 delayed_cast = 0;
5986 gen_assign_cast(&vtop[-1].type);
5989 if (sbt == VT_STRUCT) {
5990 /* if structure, only generate pointer */
5991 /* structure assignment : generate memcpy */
5992 /* XXX: optimize if small size */
5993 if (!nocode_wanted) {
5994 size = type_size(&vtop->type, &align);
5996 vpush_global_sym(&func_old_type, TOK_memcpy);
5998 /* destination */
5999 vpushv(vtop - 2);
6000 vtop->type.t = VT_INT;
6001 gaddrof();
6002 /* source */
6003 vpushv(vtop - 2);
6004 vtop->type.t = VT_INT;
6005 gaddrof();
6006 /* type size */
6007 vpushi(size);
6008 gfunc_call(3);
6010 vswap();
6011 vpop();
6012 } else {
6013 vswap();
6014 vpop();
6016 /* leave source on stack */
6017 } else if (ft & VT_BITFIELD) {
6018 /* bitfield store handling */
6019 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6020 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6021 /* remove bit field info to avoid loops */
6022 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6024 /* duplicate destination */
6025 vdup();
6026 vtop[-1] = vtop[-2];
6028 /* mask and shift source */
6029 vpushi((1 << bit_size) - 1);
6030 gen_op('&');
6031 vpushi(bit_pos);
6032 gen_op(TOK_SHL);
6033 /* load destination, mask and or with source */
6034 vswap();
6035 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6036 gen_op('&');
6037 gen_op('|');
6038 /* store result */
6039 vstore();
6040 } else {
6041 #ifdef CONFIG_TCC_BCHECK
6042 /* bound check case */
6043 if (vtop[-1].r & VT_MUSTBOUND) {
6044 vswap();
6045 gbound();
6046 vswap();
6048 #endif
6049 if (!nocode_wanted) {
6050 rc = RC_INT;
6051 if (is_float(ft))
6052 rc = RC_FLOAT;
6053 r = gv(rc); /* generate value */
6054 /* if lvalue was saved on stack, must read it */
6055 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6056 SValue sv;
6057 t = get_reg(RC_INT);
6058 sv.type.t = VT_INT;
6059 sv.r = VT_LOCAL | VT_LVAL;
6060 sv.c.ul = vtop[-1].c.ul;
6061 load(t, &sv);
6062 vtop[-1].r = t | VT_LVAL;
6064 store(r, vtop - 1);
6065 /* two word case handling : store second register at word + 4 */
6066 if ((ft & VT_BTYPE) == VT_LLONG) {
6067 vswap();
6068 /* convert to int to increment easily */
6069 vtop->type.t = VT_INT;
6070 gaddrof();
6071 vpushi(4);
6072 gen_op('+');
6073 vtop->r |= VT_LVAL;
6074 vswap();
6075 /* XXX: it works because r2 is spilled last ! */
6076 store(vtop->r2, vtop - 1);
6079 vswap();
6080 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6081 vtop->r |= delayed_cast;
6085 /* post defines POST/PRE add. c is the token ++ or -- */
6086 void inc(int post, int c)
6088 test_lvalue();
6089 vdup(); /* save lvalue */
6090 if (post) {
6091 gv_dup(); /* duplicate value */
6092 vrotb(3);
6093 vrotb(3);
6095 /* add constant */
6096 vpushi(c - TOK_MID);
6097 gen_op('+');
6098 vstore(); /* store value */
6099 if (post)
6100 vpop(); /* if post op, return saved value */
6103 /* Parse GNUC __attribute__ extension. Currently, the following
6104 extensions are recognized:
6105 - aligned(n) : set data/function alignment.
6106 - section(x) : generate data/code in this section.
6107 - unused : currently ignored, but may be used someday.
6109 static void parse_attribute(AttributeDef *ad)
6111 int t, n;
6113 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6114 next();
6115 skip('(');
6116 skip('(');
6117 while (tok != ')') {
6118 if (tok < TOK_IDENT)
6119 expect("attribute name");
6120 t = tok;
6121 next();
6122 switch(t) {
6123 case TOK_SECTION1:
6124 case TOK_SECTION2:
6125 skip('(');
6126 if (tok != TOK_STR)
6127 expect("section name");
6128 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6129 next();
6130 skip(')');
6131 break;
6132 case TOK_ALIGNED1:
6133 case TOK_ALIGNED2:
6134 if (tok == '(') {
6135 next();
6136 n = expr_const();
6137 if (n <= 0 || (n & (n - 1)) != 0)
6138 error("alignment must be a positive power of two");
6139 skip(')');
6140 } else {
6141 n = MAX_ALIGN;
6143 ad->aligned = n;
6144 break;
6145 case TOK_UNUSED1:
6146 case TOK_UNUSED2:
6147 /* currently, no need to handle it because tcc does not
6148 track unused objects */
6149 break;
6150 case TOK_NORETURN1:
6151 case TOK_NORETURN2:
6152 /* currently, no need to handle it because tcc does not
6153 track unused objects */
6154 break;
6155 case TOK_CDECL1:
6156 case TOK_CDECL2:
6157 case TOK_CDECL3:
6158 ad->func_call = FUNC_CDECL;
6159 break;
6160 case TOK_STDCALL1:
6161 case TOK_STDCALL2:
6162 case TOK_STDCALL3:
6163 ad->func_call = FUNC_STDCALL;
6164 break;
6165 default:
6166 if (tcc_state->warn_unsupported)
6167 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6168 /* skip parameters */
6169 /* XXX: skip parenthesis too */
6170 if (tok == '(') {
6171 next();
6172 while (tok != ')' && tok != -1)
6173 next();
6174 next();
6176 break;
6178 if (tok != ',')
6179 break;
6180 next();
6182 skip(')');
6183 skip(')');
6187 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6188 static void struct_decl(CType *type, int u)
6190 int a, v, size, align, maxalign, c, offset;
6191 int bit_size, bit_pos, bsize, bt, lbit_pos;
6192 Sym *s, *ss, **ps;
6193 AttributeDef ad;
6194 CType type1, btype;
6196 a = tok; /* save decl type */
6197 next();
6198 if (tok != '{') {
6199 v = tok;
6200 next();
6201 /* struct already defined ? return it */
6202 if (v < TOK_IDENT)
6203 expect("struct/union/enum name");
6204 s = struct_find(v);
6205 if (s) {
6206 if (s->type.t != a)
6207 error("invalid type");
6208 goto do_decl;
6210 } else {
6211 v = anon_sym++;
6213 type1.t = a;
6214 /* we put an undefined size for struct/union */
6215 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6216 s->r = 0; /* default alignment is zero as gcc */
6217 /* put struct/union/enum name in type */
6218 do_decl:
6219 type->t = u;
6220 type->ref = s;
6222 if (tok == '{') {
6223 next();
6224 if (s->c != -1)
6225 error("struct/union/enum already defined");
6226 /* cannot be empty */
6227 c = 0;
6228 /* non empty enums are not allowed */
6229 if (a == TOK_ENUM) {
6230 for(;;) {
6231 v = tok;
6232 if (v < TOK_UIDENT)
6233 expect("identifier");
6234 next();
6235 if (tok == '=') {
6236 next();
6237 c = expr_const();
6239 /* enum symbols have static storage */
6240 ss = sym_push(v, &int_type, VT_CONST, c);
6241 ss->type.t |= VT_STATIC;
6242 if (tok != ',')
6243 break;
6244 next();
6245 c++;
6246 /* NOTE: we accept a trailing comma */
6247 if (tok == '}')
6248 break;
6250 skip('}');
6251 } else {
6252 maxalign = 1;
6253 ps = &s->next;
6254 bit_pos = 0;
6255 offset = 0;
6256 while (tok != '}') {
6257 parse_btype(&btype, &ad);
6258 while (1) {
6259 bit_size = -1;
6260 v = 0;
6261 type1 = btype;
6262 if (tok != ':') {
6263 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6264 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6265 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6266 error("invalid type for '%s'",
6267 get_tok_str(v, NULL));
6269 if (tok == ':') {
6270 next();
6271 bit_size = expr_const();
6272 /* XXX: handle v = 0 case for messages */
6273 if (bit_size < 0)
6274 error("negative width in bit-field '%s'",
6275 get_tok_str(v, NULL));
6276 if (v && bit_size == 0)
6277 error("zero width for bit-field '%s'",
6278 get_tok_str(v, NULL));
6280 size = type_size(&type1, &align);
6281 lbit_pos = 0;
6282 if (bit_size >= 0) {
6283 bt = type1.t & VT_BTYPE;
6284 if (bt != VT_INT &&
6285 bt != VT_BYTE &&
6286 bt != VT_SHORT &&
6287 bt != VT_ENUM)
6288 error("bitfields must have scalar type");
6289 bsize = size * 8;
6290 if (bit_size > bsize) {
6291 error("width of '%s' exceeds its type",
6292 get_tok_str(v, NULL));
6293 } else if (bit_size == bsize) {
6294 /* no need for bit fields */
6295 bit_pos = 0;
6296 } else if (bit_size == 0) {
6297 /* XXX: what to do if only padding in a
6298 structure ? */
6299 /* zero size: means to pad */
6300 if (bit_pos > 0)
6301 bit_pos = bsize;
6302 } else {
6303 /* we do not have enough room ? */
6304 if ((bit_pos + bit_size) > bsize)
6305 bit_pos = 0;
6306 lbit_pos = bit_pos;
6307 /* XXX: handle LSB first */
6308 type1.t |= VT_BITFIELD |
6309 (bit_pos << VT_STRUCT_SHIFT) |
6310 (bit_size << (VT_STRUCT_SHIFT + 6));
6311 bit_pos += bit_size;
6313 } else {
6314 bit_pos = 0;
6316 if (v) {
6317 /* add new memory data only if starting
6318 bit field */
6319 if (lbit_pos == 0) {
6320 if (a == TOK_STRUCT) {
6321 c = (c + align - 1) & -align;
6322 offset = c;
6323 c += size;
6324 } else {
6325 offset = 0;
6326 if (size > c)
6327 c = size;
6329 if (align > maxalign)
6330 maxalign = align;
6332 #if 0
6333 printf("add field %s offset=%d",
6334 get_tok_str(v, NULL), offset);
6335 if (type1.t & VT_BITFIELD) {
6336 printf(" pos=%d size=%d",
6337 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6338 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6340 printf("\n");
6341 #endif
6342 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6343 *ps = ss;
6344 ps = &ss->next;
6346 if (tok == ';' || tok == TOK_EOF)
6347 break;
6348 skip(',');
6350 skip(';');
6352 skip('}');
6353 /* store size and alignment */
6354 s->c = (c + maxalign - 1) & -maxalign;
6355 s->r = maxalign;
6360 /* return 0 if no type declaration. otherwise, return the basic type
6361 and skip it.
6363 static int parse_btype(CType *type, AttributeDef *ad)
6365 int t, u, type_found, typespec_found;
6366 Sym *s;
6367 CType type1;
6369 memset(ad, 0, sizeof(AttributeDef));
6370 type_found = 0;
6371 typespec_found = 0;
6372 t = 0;
6373 while(1) {
6374 switch(tok) {
6375 case TOK_EXTENSION:
6376 /* currently, we really ignore extension */
6377 next();
6378 continue;
6380 /* basic types */
6381 case TOK_CHAR:
6382 u = VT_BYTE;
6383 basic_type:
6384 next();
6385 basic_type1:
6386 if ((t & VT_BTYPE) != 0)
6387 error("too many basic types");
6388 t |= u;
6389 typespec_found = 1;
6390 break;
6391 case TOK_VOID:
6392 u = VT_VOID;
6393 goto basic_type;
6394 case TOK_SHORT:
6395 u = VT_SHORT;
6396 goto basic_type;
6397 case TOK_INT:
6398 next();
6399 typespec_found = 1;
6400 break;
6401 case TOK_LONG:
6402 next();
6403 if ((t & VT_BTYPE) == VT_DOUBLE) {
6404 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6405 } else if ((t & VT_BTYPE) == VT_LONG) {
6406 t = (t & ~VT_BTYPE) | VT_LLONG;
6407 } else {
6408 u = VT_LONG;
6409 goto basic_type1;
6411 break;
6412 case TOK_BOOL:
6413 u = VT_BOOL;
6414 goto basic_type;
6415 case TOK_FLOAT:
6416 u = VT_FLOAT;
6417 goto basic_type;
6418 case TOK_DOUBLE:
6419 next();
6420 if ((t & VT_BTYPE) == VT_LONG) {
6421 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6422 } else {
6423 u = VT_DOUBLE;
6424 goto basic_type1;
6426 break;
6427 case TOK_ENUM:
6428 struct_decl(&type1, VT_ENUM);
6429 basic_type2:
6430 u = type1.t;
6431 type->ref = type1.ref;
6432 goto basic_type1;
6433 case TOK_STRUCT:
6434 case TOK_UNION:
6435 struct_decl(&type1, VT_STRUCT);
6436 goto basic_type2;
6438 /* type modifiers */
6439 case TOK_CONST1:
6440 case TOK_CONST2:
6441 case TOK_CONST3:
6442 t |= VT_CONSTANT;
6443 next();
6444 break;
6445 case TOK_VOLATILE1:
6446 case TOK_VOLATILE2:
6447 case TOK_VOLATILE3:
6448 t |= VT_VOLATILE;
6449 next();
6450 break;
6451 case TOK_SIGNED1:
6452 case TOK_SIGNED2:
6453 case TOK_SIGNED3:
6454 typespec_found = 1;
6455 t |= VT_SIGNED;
6456 next();
6457 break;
6458 case TOK_REGISTER:
6459 case TOK_AUTO:
6460 case TOK_RESTRICT1:
6461 case TOK_RESTRICT2:
6462 case TOK_RESTRICT3:
6463 next();
6464 break;
6465 case TOK_UNSIGNED:
6466 t |= VT_UNSIGNED;
6467 next();
6468 typespec_found = 1;
6469 break;
6471 /* storage */
6472 case TOK_EXTERN:
6473 t |= VT_EXTERN;
6474 next();
6475 break;
6476 case TOK_STATIC:
6477 t |= VT_STATIC;
6478 next();
6479 break;
6480 case TOK_TYPEDEF:
6481 t |= VT_TYPEDEF;
6482 next();
6483 break;
6484 case TOK_INLINE1:
6485 case TOK_INLINE2:
6486 case TOK_INLINE3:
6487 t |= VT_INLINE;
6488 next();
6489 break;
6491 /* GNUC attribute */
6492 case TOK_ATTRIBUTE1:
6493 case TOK_ATTRIBUTE2:
6494 parse_attribute(ad);
6495 break;
6496 /* GNUC typeof */
6497 case TOK_TYPEOF1:
6498 case TOK_TYPEOF2:
6499 case TOK_TYPEOF3:
6500 next();
6501 parse_expr_type(&type1);
6502 goto basic_type2;
6503 default:
6504 if (typespec_found)
6505 goto the_end;
6506 s = sym_find(tok);
6507 if (!s || !(s->type.t & VT_TYPEDEF))
6508 goto the_end;
6509 t |= (s->type.t & ~VT_TYPEDEF);
6510 type->ref = s->type.ref;
6511 next();
6512 break;
6514 type_found = 1;
6516 the_end:
6517 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6518 error("signed and unsigned modifier");
6519 if (tcc_state->char_is_unsigned) {
6520 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6521 t |= VT_UNSIGNED;
6523 t &= ~VT_SIGNED;
6525 /* long is never used as type */
6526 if ((t & VT_BTYPE) == VT_LONG)
6527 t = (t & ~VT_BTYPE) | VT_INT;
6528 type->t = t;
6529 return type_found;
6532 /* convert a function parameter type (array to pointer and function to
6533 function pointer) */
6534 static inline void convert_parameter_type(CType *pt)
6536 /* array must be transformed to pointer according to ANSI C */
6537 pt->t &= ~VT_ARRAY;
6538 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6539 mk_pointer(pt);
6543 static void post_type(CType *type, AttributeDef *ad)
6545 int n, l, t1;
6546 Sym **plast, *s, *first;
6547 AttributeDef ad1;
6548 CType pt;
6550 if (tok == '(') {
6551 /* function declaration */
6552 next();
6553 l = 0;
6554 first = NULL;
6555 plast = &first;
6556 while (tok != ')') {
6557 /* read param name and compute offset */
6558 if (l != FUNC_OLD) {
6559 if (!parse_btype(&pt, &ad1)) {
6560 if (l) {
6561 error("invalid type");
6562 } else {
6563 l = FUNC_OLD;
6564 goto old_proto;
6567 l = FUNC_NEW;
6568 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6569 break;
6570 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6571 if ((pt.t & VT_BTYPE) == VT_VOID)
6572 error("parameter declared as void");
6573 } else {
6574 old_proto:
6575 n = tok;
6576 pt.t = VT_INT;
6577 next();
6579 convert_parameter_type(&pt);
6580 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6581 *plast = s;
6582 plast = &s->next;
6583 if (tok == ',') {
6584 next();
6585 if (l == FUNC_NEW && tok == TOK_DOTS) {
6586 l = FUNC_ELLIPSIS;
6587 next();
6588 break;
6592 /* if no parameters, then old type prototype */
6593 if (l == 0)
6594 l = FUNC_OLD;
6595 skip(')');
6596 t1 = type->t & VT_STORAGE;
6597 /* NOTE: const is ignored in returned type as it has a special
6598 meaning in gcc / C++ */
6599 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6600 post_type(type, ad);
6601 /* we push a anonymous symbol which will contain the function prototype */
6602 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6603 s->next = first;
6604 type->t = t1 | VT_FUNC;
6605 type->ref = s;
6606 } else if (tok == '[') {
6607 /* array definition */
6608 next();
6609 n = -1;
6610 if (tok != ']') {
6611 n = expr_const();
6612 if (n < 0)
6613 error("invalid array size");
6615 skip(']');
6616 /* parse next post type */
6617 t1 = type->t & VT_STORAGE;
6618 type->t &= ~VT_STORAGE;
6619 post_type(type, ad);
6621 /* we push a anonymous symbol which will contain the array
6622 element type */
6623 s = sym_push(SYM_FIELD, type, 0, n);
6624 type->t = t1 | VT_ARRAY | VT_PTR;
6625 type->ref = s;
6629 /* Parse a type declaration (except basic type), and return the type
6630 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6631 expected. 'type' should contain the basic type. 'ad' is the
6632 attribute definition of the basic type. It can be modified by
6633 type_decl().
6635 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6637 Sym *s;
6638 CType type1, *type2;
6639 int qualifiers;
6641 while (tok == '*') {
6642 qualifiers = 0;
6643 redo:
6644 next();
6645 switch(tok) {
6646 case TOK_CONST1:
6647 case TOK_CONST2:
6648 case TOK_CONST3:
6649 qualifiers |= VT_CONSTANT;
6650 goto redo;
6651 case TOK_VOLATILE1:
6652 case TOK_VOLATILE2:
6653 case TOK_VOLATILE3:
6654 qualifiers |= VT_VOLATILE;
6655 goto redo;
6656 case TOK_RESTRICT1:
6657 case TOK_RESTRICT2:
6658 case TOK_RESTRICT3:
6659 goto redo;
6661 mk_pointer(type);
6662 type->t |= qualifiers;
6665 /* XXX: clarify attribute handling */
6666 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6667 parse_attribute(ad);
6669 /* recursive type */
6670 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6671 type1.t = 0; /* XXX: same as int */
6672 if (tok == '(') {
6673 next();
6674 /* XXX: this is not correct to modify 'ad' at this point, but
6675 the syntax is not clear */
6676 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6677 parse_attribute(ad);
6678 type_decl(&type1, ad, v, td);
6679 skip(')');
6680 } else {
6681 /* type identifier */
6682 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6683 *v = tok;
6684 next();
6685 } else {
6686 if (!(td & TYPE_ABSTRACT))
6687 expect("identifier");
6688 *v = 0;
6691 post_type(type, ad);
6692 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6693 parse_attribute(ad);
6694 if (!type1.t)
6695 return;
6696 /* append type at the end of type1 */
6697 type2 = &type1;
6698 for(;;) {
6699 s = type2->ref;
6700 type2 = &s->type;
6701 if (!type2->t) {
6702 *type2 = *type;
6703 break;
6706 *type = type1;
6709 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6710 static int lvalue_type(int t)
6712 int bt, r;
6713 r = VT_LVAL;
6714 bt = t & VT_BTYPE;
6715 if (bt == VT_BYTE || bt == VT_BOOL)
6716 r |= VT_LVAL_BYTE;
6717 else if (bt == VT_SHORT)
6718 r |= VT_LVAL_SHORT;
6719 else
6720 return r;
6721 if (t & VT_UNSIGNED)
6722 r |= VT_LVAL_UNSIGNED;
6723 return r;
6726 /* indirection with full error checking and bound check */
6727 static void indir(void)
6729 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6730 expect("pointer");
6731 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6732 gv(RC_INT);
6733 vtop->type = *pointed_type(&vtop->type);
6734 /* an array is never an lvalue */
6735 if (!(vtop->type.t & VT_ARRAY)) {
6736 vtop->r |= lvalue_type(vtop->type.t);
6737 /* if bound checking, the referenced pointer must be checked */
6738 if (do_bounds_check)
6739 vtop->r |= VT_MUSTBOUND;
6743 /* pass a parameter to a function and do type checking and casting */
6744 static void gfunc_param_typed(Sym *func, Sym *arg)
6746 int func_type;
6747 CType type;
6749 func_type = func->c;
6750 if (func_type == FUNC_OLD ||
6751 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6752 /* default casting : only need to convert float to double */
6753 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6754 type.t = VT_DOUBLE;
6755 gen_cast(&type);
6757 } else if (arg == NULL) {
6758 error("too many arguments to function");
6759 } else {
6760 type = arg->type;
6761 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6762 gen_assign_cast(&type);
6766 /* parse an expression of the form '(type)' or '(expr)' and return its
6767 type */
6768 static void parse_expr_type(CType *type)
6770 int n;
6771 AttributeDef ad;
6773 skip('(');
6774 if (parse_btype(type, &ad)) {
6775 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6776 } else {
6777 expr_type(type);
6779 skip(')');
6782 static void parse_type(CType *type)
6784 AttributeDef ad;
6785 int n;
6787 if (!parse_btype(type, &ad)) {
6788 expect("type");
6790 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6793 static void vpush_tokc(int t)
6795 CType type;
6796 type.t = t;
6797 vsetc(&type, VT_CONST, &tokc);
6800 static void unary(void)
6802 int n, t, align, size, r;
6803 CType type;
6804 Sym *s;
6805 AttributeDef ad;
6807 /* XXX: GCC 2.95.3 does not generate a table although it should be
6808 better here */
6809 tok_next:
6810 switch(tok) {
6811 case TOK_EXTENSION:
6812 next();
6813 goto tok_next;
6814 case TOK_CINT:
6815 case TOK_CCHAR:
6816 case TOK_LCHAR:
6817 vpushi(tokc.i);
6818 next();
6819 break;
6820 case TOK_CUINT:
6821 vpush_tokc(VT_INT | VT_UNSIGNED);
6822 next();
6823 break;
6824 case TOK_CLLONG:
6825 vpush_tokc(VT_LLONG);
6826 next();
6827 break;
6828 case TOK_CULLONG:
6829 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6830 next();
6831 break;
6832 case TOK_CFLOAT:
6833 vpush_tokc(VT_FLOAT);
6834 next();
6835 break;
6836 case TOK_CDOUBLE:
6837 vpush_tokc(VT_DOUBLE);
6838 next();
6839 break;
6840 case TOK_CLDOUBLE:
6841 vpush_tokc(VT_LDOUBLE);
6842 next();
6843 break;
6844 case TOK___FUNCTION__:
6845 if (!gnu_ext)
6846 goto tok_identifier;
6847 /* fall thru */
6848 case TOK___FUNC__:
6850 void *ptr;
6851 int len;
6852 /* special function name identifier */
6853 len = strlen(funcname) + 1;
6854 /* generate char[len] type */
6855 type.t = VT_BYTE;
6856 mk_pointer(&type);
6857 type.t |= VT_ARRAY;
6858 type.ref->c = len;
6859 vpush_ref(&type, data_section, data_section->data_offset, len);
6860 ptr = section_ptr_add(data_section, len);
6861 memcpy(ptr, funcname, len);
6862 next();
6864 break;
6865 case TOK_LSTR:
6866 t = VT_INT;
6867 goto str_init;
6868 case TOK_STR:
6869 /* string parsing */
6870 t = VT_BYTE;
6871 str_init:
6872 if (tcc_state->warn_write_strings)
6873 t |= VT_CONSTANT;
6874 type.t = t;
6875 mk_pointer(&type);
6876 type.t |= VT_ARRAY;
6877 memset(&ad, 0, sizeof(AttributeDef));
6878 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6879 break;
6880 case '(':
6881 next();
6882 /* cast ? */
6883 if (parse_btype(&type, &ad)) {
6884 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6885 skip(')');
6886 /* check ISOC99 compound literal */
6887 if (tok == '{') {
6888 /* data is allocated locally by default */
6889 if (global_expr)
6890 r = VT_CONST;
6891 else
6892 r = VT_LOCAL;
6893 /* all except arrays are lvalues */
6894 if (!(type.t & VT_ARRAY))
6895 r |= lvalue_type(type.t);
6896 memset(&ad, 0, sizeof(AttributeDef));
6897 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6898 } else {
6899 unary();
6900 gen_cast(&type);
6902 } else if (tok == '{') {
6903 /* save all registers */
6904 save_regs(0);
6905 /* statement expression : we do not accept break/continue
6906 inside as GCC does */
6907 block(NULL, NULL, NULL, NULL, 0, 1);
6908 skip(')');
6909 } else {
6910 gexpr();
6911 skip(')');
6913 break;
6914 case '*':
6915 next();
6916 unary();
6917 indir();
6918 break;
6919 case '&':
6920 next();
6921 unary();
6922 /* functions names must be treated as function pointers,
6923 except for unary '&' and sizeof. Since we consider that
6924 functions are not lvalues, we only have to handle it
6925 there and in function calls. */
6926 /* arrays can also be used although they are not lvalues */
6927 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6928 !(vtop->type.t & VT_ARRAY))
6929 test_lvalue();
6930 mk_pointer(&vtop->type);
6931 gaddrof();
6932 break;
6933 case '!':
6934 next();
6935 unary();
6936 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6937 vtop->c.i = !vtop->c.i;
6938 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6939 vtop->c.i = vtop->c.i ^ 1;
6940 else
6941 vseti(VT_JMP, gtst(1, 0));
6942 break;
6943 case '~':
6944 next();
6945 unary();
6946 vpushi(-1);
6947 gen_op('^');
6948 break;
6949 case '+':
6950 next();
6951 /* in order to force cast, we add zero */
6952 unary();
6953 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6954 error("pointer not accepted for unary plus");
6955 vpushi(0);
6956 gen_op('+');
6957 break;
6958 case TOK_SIZEOF:
6959 case TOK_ALIGNOF1:
6960 case TOK_ALIGNOF2:
6961 t = tok;
6962 next();
6963 if (tok == '(') {
6964 parse_expr_type(&type);
6965 } else {
6966 unary_type(&type);
6968 size = type_size(&type, &align);
6969 if (t == TOK_SIZEOF) {
6970 if (size < 0)
6971 error("sizeof applied to an incomplete type");
6972 vpushi(size);
6973 } else {
6974 vpushi(align);
6976 break;
6978 case TOK_builtin_types_compatible_p:
6980 CType type1, type2;
6981 next();
6982 skip('(');
6983 parse_type(&type1);
6984 skip(',');
6985 parse_type(&type2);
6986 skip(')');
6987 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6988 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6989 vpushi(is_compatible_types(&type1, &type2));
6991 break;
6992 case TOK_builtin_constant_p:
6994 int saved_nocode_wanted, res;
6995 next();
6996 skip('(');
6997 saved_nocode_wanted = nocode_wanted;
6998 nocode_wanted = 1;
6999 gexpr();
7000 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7001 vpop();
7002 nocode_wanted = saved_nocode_wanted;
7003 skip(')');
7004 vpushi(res);
7006 break;
7007 case TOK_INC:
7008 case TOK_DEC:
7009 t = tok;
7010 next();
7011 unary();
7012 inc(0, t);
7013 break;
7014 case '-':
7015 next();
7016 vpushi(0);
7017 unary();
7018 gen_op('-');
7019 break;
7020 case TOK_LAND:
7021 if (!gnu_ext)
7022 goto tok_identifier;
7023 next();
7024 /* allow to take the address of a label */
7025 if (tok < TOK_UIDENT)
7026 expect("label identifier");
7027 s = label_find(tok);
7028 if (!s) {
7029 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7030 } else {
7031 if (s->r == LABEL_DECLARED)
7032 s->r = LABEL_FORWARD;
7034 if (!s->type.t) {
7035 s->type.t = VT_VOID;
7036 mk_pointer(&s->type);
7037 s->type.t |= VT_STATIC;
7039 vset(&s->type, VT_CONST | VT_SYM, 0);
7040 vtop->sym = s;
7041 next();
7042 break;
7043 default:
7044 tok_identifier:
7045 t = tok;
7046 next();
7047 if (t < TOK_UIDENT)
7048 expect("identifier");
7049 s = sym_find(t);
7050 if (!s) {
7051 if (tok != '(')
7052 error("'%s' undeclared", get_tok_str(t, NULL));
7053 /* for simple function calls, we tolerate undeclared
7054 external reference to int() function */
7055 if (tcc_state->warn_implicit_function_declaration)
7056 warning("implicit declaration of function '%s'",
7057 get_tok_str(t, NULL));
7058 s = external_global_sym(t, &func_old_type, 0);
7060 vset(&s->type, s->r, s->c);
7061 /* if forward reference, we must point to s */
7062 if (vtop->r & VT_SYM) {
7063 vtop->sym = s;
7064 vtop->c.ul = 0;
7066 break;
7069 /* post operations */
7070 while (1) {
7071 if (tok == TOK_INC || tok == TOK_DEC) {
7072 inc(1, tok);
7073 next();
7074 } else if (tok == '.' || tok == TOK_ARROW) {
7075 /* field */
7076 if (tok == TOK_ARROW)
7077 indir();
7078 test_lvalue();
7079 gaddrof();
7080 next();
7081 /* expect pointer on structure */
7082 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7083 expect("struct or union");
7084 s = vtop->type.ref;
7085 /* find field */
7086 tok |= SYM_FIELD;
7087 while ((s = s->next) != NULL) {
7088 if (s->v == tok)
7089 break;
7091 if (!s)
7092 error("field not found");
7093 /* add field offset to pointer */
7094 vtop->type = char_pointer_type; /* change type to 'char *' */
7095 vpushi(s->c);
7096 gen_op('+');
7097 /* change type to field type, and set to lvalue */
7098 vtop->type = s->type;
7099 /* an array is never an lvalue */
7100 if (!(vtop->type.t & VT_ARRAY)) {
7101 vtop->r |= lvalue_type(vtop->type.t);
7102 /* if bound checking, the referenced pointer must be checked */
7103 if (do_bounds_check)
7104 vtop->r |= VT_MUSTBOUND;
7106 next();
7107 } else if (tok == '[') {
7108 next();
7109 gexpr();
7110 gen_op('+');
7111 indir();
7112 skip(']');
7113 } else if (tok == '(') {
7114 SValue ret;
7115 Sym *sa;
7116 int nb_args;
7118 /* function call */
7119 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7120 /* pointer test (no array accepted) */
7121 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7122 vtop->type = *pointed_type(&vtop->type);
7123 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7124 goto error_func;
7125 } else {
7126 error_func:
7127 expect("function pointer");
7129 } else {
7130 vtop->r &= ~VT_LVAL; /* no lvalue */
7132 /* get return type */
7133 s = vtop->type.ref;
7134 next();
7135 sa = s->next; /* first parameter */
7136 nb_args = 0;
7137 /* compute first implicit argument if a structure is returned */
7138 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7139 /* get some space for the returned structure */
7140 size = type_size(&s->type, &align);
7141 loc = (loc - size) & -align;
7142 ret.type = s->type;
7143 ret.r = VT_LOCAL | VT_LVAL;
7144 /* pass it as 'int' to avoid structure arg passing
7145 problems */
7146 vseti(VT_LOCAL, loc);
7147 ret.c = vtop->c;
7148 nb_args++;
7149 } else {
7150 ret.type = s->type;
7151 ret.r2 = VT_CONST;
7152 /* return in register */
7153 if (is_float(ret.type.t)) {
7154 ret.r = REG_FRET;
7155 } else {
7156 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7157 ret.r2 = REG_LRET;
7158 ret.r = REG_IRET;
7160 ret.c.i = 0;
7162 if (tok != ')') {
7163 for(;;) {
7164 expr_eq();
7165 gfunc_param_typed(s, sa);
7166 nb_args++;
7167 if (sa)
7168 sa = sa->next;
7169 if (tok == ')')
7170 break;
7171 skip(',');
7174 if (sa)
7175 error("too few arguments to function");
7176 skip(')');
7177 if (!nocode_wanted) {
7178 gfunc_call(nb_args);
7179 } else {
7180 vtop -= (nb_args + 1);
7182 /* return value */
7183 vsetc(&ret.type, ret.r, &ret.c);
7184 vtop->r2 = ret.r2;
7185 } else {
7186 break;
7191 static void uneq(void)
7193 int t;
7195 unary();
7196 if (tok == '=' ||
7197 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7198 tok == TOK_A_XOR || tok == TOK_A_OR ||
7199 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7200 test_lvalue();
7201 t = tok;
7202 next();
7203 if (t == '=') {
7204 expr_eq();
7205 } else {
7206 vdup();
7207 expr_eq();
7208 gen_op(t & 0x7f);
7210 vstore();
7214 static void expr_prod(void)
7216 int t;
7218 uneq();
7219 while (tok == '*' || tok == '/' || tok == '%') {
7220 t = tok;
7221 next();
7222 uneq();
7223 gen_op(t);
7227 static void expr_sum(void)
7229 int t;
7231 expr_prod();
7232 while (tok == '+' || tok == '-') {
7233 t = tok;
7234 next();
7235 expr_prod();
7236 gen_op(t);
7240 static void expr_shift(void)
7242 int t;
7244 expr_sum();
7245 while (tok == TOK_SHL || tok == TOK_SAR) {
7246 t = tok;
7247 next();
7248 expr_sum();
7249 gen_op(t);
7253 static void expr_cmp(void)
7255 int t;
7257 expr_shift();
7258 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7259 tok == TOK_ULT || tok == TOK_UGE) {
7260 t = tok;
7261 next();
7262 expr_shift();
7263 gen_op(t);
7267 static void expr_cmpeq(void)
7269 int t;
7271 expr_cmp();
7272 while (tok == TOK_EQ || tok == TOK_NE) {
7273 t = tok;
7274 next();
7275 expr_cmp();
7276 gen_op(t);
7280 static void expr_and(void)
7282 expr_cmpeq();
7283 while (tok == '&') {
7284 next();
7285 expr_cmpeq();
7286 gen_op('&');
7290 static void expr_xor(void)
7292 expr_and();
7293 while (tok == '^') {
7294 next();
7295 expr_and();
7296 gen_op('^');
7300 static void expr_or(void)
7302 expr_xor();
7303 while (tok == '|') {
7304 next();
7305 expr_xor();
7306 gen_op('|');
7310 /* XXX: fix this mess */
7311 static void expr_land_const(void)
7313 expr_or();
7314 while (tok == TOK_LAND) {
7315 next();
7316 expr_or();
7317 gen_op(TOK_LAND);
7321 /* XXX: fix this mess */
7322 static void expr_lor_const(void)
7324 expr_land_const();
7325 while (tok == TOK_LOR) {
7326 next();
7327 expr_land_const();
7328 gen_op(TOK_LOR);
7332 /* only used if non constant */
7333 static void expr_land(void)
7335 int t;
7337 expr_or();
7338 if (tok == TOK_LAND) {
7339 t = 0;
7340 for(;;) {
7341 t = gtst(1, t);
7342 if (tok != TOK_LAND) {
7343 vseti(VT_JMPI, t);
7344 break;
7346 next();
7347 expr_or();
7352 static void expr_lor(void)
7354 int t;
7356 expr_land();
7357 if (tok == TOK_LOR) {
7358 t = 0;
7359 for(;;) {
7360 t = gtst(0, t);
7361 if (tok != TOK_LOR) {
7362 vseti(VT_JMP, t);
7363 break;
7365 next();
7366 expr_land();
7371 /* XXX: better constant handling */
7372 static void expr_eq(void)
7374 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7375 SValue sv;
7376 CType type, type1, type2;
7378 if (const_wanted) {
7379 int c1, c;
7380 expr_lor_const();
7381 if (tok == '?') {
7382 c = vtop->c.i;
7383 vpop();
7384 next();
7385 if (tok == ':' && gnu_ext) {
7386 c1 = c;
7387 } else {
7388 gexpr();
7389 c1 = vtop->c.i;
7390 vpop();
7392 skip(':');
7393 expr_eq();
7394 if (c)
7395 vtop->c.i = c1;
7397 } else {
7398 expr_lor();
7399 if (tok == '?') {
7400 next();
7401 if (vtop != vstack) {
7402 /* needed to avoid having different registers saved in
7403 each branch */
7404 if (is_float(vtop->type.t))
7405 rc = RC_FLOAT;
7406 else
7407 rc = RC_INT;
7408 gv(rc);
7409 save_regs(1);
7411 if (tok == ':' && gnu_ext) {
7412 gv_dup();
7413 tt = gtst(1, 0);
7414 } else {
7415 tt = gtst(1, 0);
7416 gexpr();
7418 type1 = vtop->type;
7419 sv = *vtop; /* save value to handle it later */
7420 vtop--; /* no vpop so that FP stack is not flushed */
7421 skip(':');
7422 u = gjmp(0);
7423 gsym(tt);
7424 expr_eq();
7425 type2 = vtop->type;
7427 t1 = type1.t;
7428 bt1 = t1 & VT_BTYPE;
7429 t2 = type2.t;
7430 bt2 = t2 & VT_BTYPE;
7431 /* cast operands to correct type according to ISOC rules */
7432 if (is_float(bt1) || is_float(bt2)) {
7433 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7434 type.t = VT_LDOUBLE;
7435 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7436 type.t = VT_DOUBLE;
7437 } else {
7438 type.t = VT_FLOAT;
7440 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7441 /* cast to biggest op */
7442 type.t = VT_LLONG;
7443 /* convert to unsigned if it does not fit in a long long */
7444 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7445 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7446 type.t |= VT_UNSIGNED;
7447 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7448 /* XXX: test pointer compatibility */
7449 type = type1;
7450 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7451 /* XXX: test structure compatibility */
7452 type = type1;
7453 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7454 /* NOTE: as an extension, we accept void on only one side */
7455 type.t = VT_VOID;
7456 } else {
7457 /* integer operations */
7458 type.t = VT_INT;
7459 /* convert to unsigned if it does not fit in an integer */
7460 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7461 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7462 type.t |= VT_UNSIGNED;
7465 /* now we convert second operand */
7466 gen_cast(&type);
7467 rc = RC_INT;
7468 if (is_float(type.t)) {
7469 rc = RC_FLOAT;
7470 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7471 /* for long longs, we use fixed registers to avoid having
7472 to handle a complicated move */
7473 rc = RC_IRET;
7476 r2 = gv(rc);
7477 /* this is horrible, but we must also convert first
7478 operand */
7479 tt = gjmp(0);
7480 gsym(u);
7481 /* put again first value and cast it */
7482 *vtop = sv;
7483 gen_cast(&type);
7484 r1 = gv(rc);
7485 move_reg(r2, r1);
7486 vtop->r = r2;
7487 gsym(tt);
7492 static void gexpr(void)
7494 while (1) {
7495 expr_eq();
7496 if (tok != ',')
7497 break;
7498 vpop();
7499 next();
7503 /* parse an expression and return its type without any side effect. */
7504 static void expr_type(CType *type)
7506 int saved_nocode_wanted;
7508 saved_nocode_wanted = nocode_wanted;
7509 nocode_wanted = 1;
7510 gexpr();
7511 *type = vtop->type;
7512 vpop();
7513 nocode_wanted = saved_nocode_wanted;
7516 /* parse a unary expression and return its type without any side
7517 effect. */
7518 static void unary_type(CType *type)
7520 int a;
7522 a = nocode_wanted;
7523 nocode_wanted = 1;
7524 unary();
7525 *type = vtop->type;
7526 vpop();
7527 nocode_wanted = a;
7530 /* parse a constant expression and return value in vtop. */
7531 static void expr_const1(void)
7533 int a;
7534 a = const_wanted;
7535 const_wanted = 1;
7536 expr_eq();
7537 const_wanted = a;
7540 /* parse an integer constant and return its value. */
7541 static int expr_const(void)
7543 int c;
7544 expr_const1();
7545 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7546 expect("constant expression");
7547 c = vtop->c.i;
7548 vpop();
7549 return c;
7552 /* return the label token if current token is a label, otherwise
7553 return zero */
7554 static int is_label(void)
7556 int last_tok;
7558 /* fast test first */
7559 if (tok < TOK_UIDENT)
7560 return 0;
7561 /* no need to save tokc because tok is an identifier */
7562 last_tok = tok;
7563 next();
7564 if (tok == ':') {
7565 next();
7566 return last_tok;
7567 } else {
7568 unget_tok(last_tok);
7569 return 0;
7573 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7574 int case_reg, int is_expr)
7576 int a, b, c, d;
7577 Sym *s;
7579 /* generate line number info */
7580 if (do_debug &&
7581 (last_line_num != file->line_num || last_ind != ind)) {
7582 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7583 last_ind = ind;
7584 last_line_num = file->line_num;
7587 if (is_expr) {
7588 /* default return value is (void) */
7589 vpushi(0);
7590 vtop->type.t = VT_VOID;
7593 if (tok == TOK_IF) {
7594 /* if test */
7595 next();
7596 skip('(');
7597 gexpr();
7598 skip(')');
7599 a = gtst(1, 0);
7600 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7601 c = tok;
7602 if (c == TOK_ELSE) {
7603 next();
7604 d = gjmp(0);
7605 gsym(a);
7606 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7607 gsym(d); /* patch else jmp */
7608 } else
7609 gsym(a);
7610 } else if (tok == TOK_WHILE) {
7611 next();
7612 d = ind;
7613 skip('(');
7614 gexpr();
7615 skip(')');
7616 a = gtst(1, 0);
7617 b = 0;
7618 block(&a, &b, case_sym, def_sym, case_reg, 0);
7619 gjmp_addr(d);
7620 gsym(a);
7621 gsym_addr(b, d);
7622 } else if (tok == '{') {
7623 Sym *llabel;
7625 next();
7626 /* record local declaration stack position */
7627 s = local_stack;
7628 llabel = local_label_stack;
7629 /* handle local labels declarations */
7630 if (tok == TOK_LABEL) {
7631 next();
7632 for(;;) {
7633 if (tok < TOK_UIDENT)
7634 expect("label identifier");
7635 label_push(&local_label_stack, tok, LABEL_DECLARED);
7636 next();
7637 if (tok == ',') {
7638 next();
7639 } else {
7640 skip(';');
7641 break;
7645 while (tok != '}') {
7646 decl(VT_LOCAL);
7647 if (tok != '}') {
7648 if (is_expr)
7649 vpop();
7650 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7653 /* pop locally defined labels */
7654 label_pop(&local_label_stack, llabel);
7655 /* pop locally defined symbols */
7656 sym_pop(&local_stack, s);
7657 next();
7658 } else if (tok == TOK_RETURN) {
7659 next();
7660 if (tok != ';') {
7661 gexpr();
7662 gen_assign_cast(&func_vt);
7663 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7664 CType type;
7665 /* if returning structure, must copy it to implicit
7666 first pointer arg location */
7667 type = func_vt;
7668 mk_pointer(&type);
7669 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7670 indir();
7671 vswap();
7672 /* copy structure value to pointer */
7673 vstore();
7674 } else if (is_float(func_vt.t)) {
7675 gv(RC_FRET);
7676 } else {
7677 gv(RC_IRET);
7679 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7681 skip(';');
7682 rsym = gjmp(rsym); /* jmp */
7683 } else if (tok == TOK_BREAK) {
7684 /* compute jump */
7685 if (!bsym)
7686 error("cannot break");
7687 *bsym = gjmp(*bsym);
7688 next();
7689 skip(';');
7690 } else if (tok == TOK_CONTINUE) {
7691 /* compute jump */
7692 if (!csym)
7693 error("cannot continue");
7694 *csym = gjmp(*csym);
7695 next();
7696 skip(';');
7697 } else if (tok == TOK_FOR) {
7698 int e;
7699 next();
7700 skip('(');
7701 if (tok != ';') {
7702 gexpr();
7703 vpop();
7705 skip(';');
7706 d = ind;
7707 c = ind;
7708 a = 0;
7709 b = 0;
7710 if (tok != ';') {
7711 gexpr();
7712 a = gtst(1, 0);
7714 skip(';');
7715 if (tok != ')') {
7716 e = gjmp(0);
7717 c = ind;
7718 gexpr();
7719 vpop();
7720 gjmp_addr(d);
7721 gsym(e);
7723 skip(')');
7724 block(&a, &b, case_sym, def_sym, case_reg, 0);
7725 gjmp_addr(c);
7726 gsym(a);
7727 gsym_addr(b, c);
7728 } else
7729 if (tok == TOK_DO) {
7730 next();
7731 a = 0;
7732 b = 0;
7733 d = ind;
7734 block(&a, &b, case_sym, def_sym, case_reg, 0);
7735 skip(TOK_WHILE);
7736 skip('(');
7737 gsym(b);
7738 gexpr();
7739 c = gtst(0, 0);
7740 gsym_addr(c, d);
7741 skip(')');
7742 gsym(a);
7743 skip(';');
7744 } else
7745 if (tok == TOK_SWITCH) {
7746 next();
7747 skip('(');
7748 gexpr();
7749 /* XXX: other types than integer */
7750 case_reg = gv(RC_INT);
7751 vpop();
7752 skip(')');
7753 a = 0;
7754 b = gjmp(0); /* jump to first case */
7755 c = 0;
7756 block(&a, csym, &b, &c, case_reg, 0);
7757 /* if no default, jmp after switch */
7758 if (c == 0)
7759 c = ind;
7760 /* default label */
7761 gsym_addr(b, c);
7762 /* break label */
7763 gsym(a);
7764 } else
7765 if (tok == TOK_CASE) {
7766 int v1, v2;
7767 if (!case_sym)
7768 expect("switch");
7769 next();
7770 v1 = expr_const();
7771 v2 = v1;
7772 if (gnu_ext && tok == TOK_DOTS) {
7773 next();
7774 v2 = expr_const();
7775 if (v2 < v1)
7776 warning("empty case range");
7778 /* since a case is like a label, we must skip it with a jmp */
7779 b = gjmp(0);
7780 gsym(*case_sym);
7781 vseti(case_reg, 0);
7782 vpushi(v1);
7783 if (v1 == v2) {
7784 gen_op(TOK_EQ);
7785 *case_sym = gtst(1, 0);
7786 } else {
7787 gen_op(TOK_GE);
7788 *case_sym = gtst(1, 0);
7789 vseti(case_reg, 0);
7790 vpushi(v2);
7791 gen_op(TOK_LE);
7792 *case_sym = gtst(1, *case_sym);
7794 gsym(b);
7795 skip(':');
7796 is_expr = 0;
7797 goto block_after_label;
7798 } else
7799 if (tok == TOK_DEFAULT) {
7800 next();
7801 skip(':');
7802 if (!def_sym)
7803 expect("switch");
7804 if (*def_sym)
7805 error("too many 'default'");
7806 *def_sym = ind;
7807 is_expr = 0;
7808 goto block_after_label;
7809 } else
7810 if (tok == TOK_GOTO) {
7811 next();
7812 if (tok == '*' && gnu_ext) {
7813 /* computed goto */
7814 next();
7815 gexpr();
7816 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7817 expect("pointer");
7818 ggoto();
7819 } else if (tok >= TOK_UIDENT) {
7820 s = label_find(tok);
7821 /* put forward definition if needed */
7822 if (!s) {
7823 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7824 } else {
7825 if (s->r == LABEL_DECLARED)
7826 s->r = LABEL_FORWARD;
7828 /* label already defined */
7829 if (s->r & LABEL_FORWARD)
7830 s->next = (void *)gjmp((long)s->next);
7831 else
7832 gjmp_addr((long)s->next);
7833 next();
7834 } else {
7835 expect("label identifier");
7837 skip(';');
7838 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7839 asm_instr();
7840 } else {
7841 b = is_label();
7842 if (b) {
7843 /* label case */
7844 s = label_find(b);
7845 if (s) {
7846 if (s->r == LABEL_DEFINED)
7847 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7848 gsym((long)s->next);
7849 s->r = LABEL_DEFINED;
7850 } else {
7851 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7853 s->next = (void *)ind;
7854 /* we accept this, but it is a mistake */
7855 block_after_label:
7856 if (tok == '}') {
7857 warning("deprecated use of label at end of compound statement");
7858 } else {
7859 if (is_expr)
7860 vpop();
7861 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7863 } else {
7864 /* expression case */
7865 if (tok != ';') {
7866 if (is_expr) {
7867 vpop();
7868 gexpr();
7869 } else {
7870 gexpr();
7871 vpop();
7874 skip(';');
7879 /* t is the array or struct type. c is the array or struct
7880 address. cur_index/cur_field is the pointer to the current
7881 value. 'size_only' is true if only size info is needed (only used
7882 in arrays) */
7883 static void decl_designator(CType *type, Section *sec, unsigned long c,
7884 int *cur_index, Sym **cur_field,
7885 int size_only)
7887 Sym *s, *f;
7888 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7889 CType type1;
7891 notfirst = 0;
7892 elem_size = 0;
7893 nb_elems = 1;
7894 if (gnu_ext && (l = is_label()) != 0)
7895 goto struct_field;
7896 while (tok == '[' || tok == '.') {
7897 if (tok == '[') {
7898 if (!(type->t & VT_ARRAY))
7899 expect("array type");
7900 s = type->ref;
7901 next();
7902 index = expr_const();
7903 if (index < 0 || (s->c >= 0 && index >= s->c))
7904 expect("invalid index");
7905 if (tok == TOK_DOTS && gnu_ext) {
7906 next();
7907 index_last = expr_const();
7908 if (index_last < 0 ||
7909 (s->c >= 0 && index_last >= s->c) ||
7910 index_last < index)
7911 expect("invalid index");
7912 } else {
7913 index_last = index;
7915 skip(']');
7916 if (!notfirst)
7917 *cur_index = index_last;
7918 type = pointed_type(type);
7919 elem_size = type_size(type, &align);
7920 c += index * elem_size;
7921 /* NOTE: we only support ranges for last designator */
7922 nb_elems = index_last - index + 1;
7923 if (nb_elems != 1) {
7924 notfirst = 1;
7925 break;
7927 } else {
7928 next();
7929 l = tok;
7930 next();
7931 struct_field:
7932 if ((type->t & VT_BTYPE) != VT_STRUCT)
7933 expect("struct/union type");
7934 s = type->ref;
7935 l |= SYM_FIELD;
7936 f = s->next;
7937 while (f) {
7938 if (f->v == l)
7939 break;
7940 f = f->next;
7942 if (!f)
7943 expect("field");
7944 if (!notfirst)
7945 *cur_field = f;
7946 /* XXX: fix this mess by using explicit storage field */
7947 type1 = f->type;
7948 type1.t |= (type->t & ~VT_TYPE);
7949 type = &type1;
7950 c += f->c;
7952 notfirst = 1;
7954 if (notfirst) {
7955 if (tok == '=') {
7956 next();
7957 } else {
7958 if (!gnu_ext)
7959 expect("=");
7961 } else {
7962 if (type->t & VT_ARRAY) {
7963 index = *cur_index;
7964 type = pointed_type(type);
7965 c += index * type_size(type, &align);
7966 } else {
7967 f = *cur_field;
7968 if (!f)
7969 error("too many field init");
7970 /* XXX: fix this mess by using explicit storage field */
7971 type1 = f->type;
7972 type1.t |= (type->t & ~VT_TYPE);
7973 type = &type1;
7974 c += f->c;
7977 decl_initializer(type, sec, c, 0, size_only);
7979 /* XXX: make it more general */
7980 if (!size_only && nb_elems > 1) {
7981 unsigned long c_end;
7982 uint8_t *src, *dst;
7983 int i;
7985 if (!sec)
7986 error("range init not supported yet for dynamic storage");
7987 c_end = c + nb_elems * elem_size;
7988 if (c_end > sec->data_allocated)
7989 section_realloc(sec, c_end);
7990 src = sec->data + c;
7991 dst = src;
7992 for(i = 1; i < nb_elems; i++) {
7993 dst += elem_size;
7994 memcpy(dst, src, elem_size);
7999 #define EXPR_VAL 0
8000 #define EXPR_CONST 1
8001 #define EXPR_ANY 2
8003 /* store a value or an expression directly in global data or in local array */
8004 static void init_putv(CType *type, Section *sec, unsigned long c,
8005 int v, int expr_type)
8007 int saved_global_expr, bt, bit_pos, bit_size;
8008 void *ptr;
8009 unsigned long long bit_mask;
8010 CType dtype;
8012 switch(expr_type) {
8013 case EXPR_VAL:
8014 vpushi(v);
8015 break;
8016 case EXPR_CONST:
8017 /* compound literals must be allocated globally in this case */
8018 saved_global_expr = global_expr;
8019 global_expr = 1;
8020 expr_const1();
8021 global_expr = saved_global_expr;
8022 /* NOTE: symbols are accepted */
8023 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8024 error("initializer element is not constant");
8025 break;
8026 case EXPR_ANY:
8027 expr_eq();
8028 break;
8031 dtype = *type;
8032 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8034 if (sec) {
8035 /* XXX: not portable */
8036 /* XXX: generate error if incorrect relocation */
8037 gen_assign_cast(&dtype);
8038 bt = type->t & VT_BTYPE;
8039 ptr = sec->data + c;
8040 /* XXX: make code faster ? */
8041 if (!(type->t & VT_BITFIELD)) {
8042 bit_pos = 0;
8043 bit_size = 32;
8044 bit_mask = -1LL;
8045 } else {
8046 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8047 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8048 bit_mask = (1LL << bit_size) - 1;
8050 if ((vtop->r & VT_SYM) &&
8051 (bt == VT_BYTE ||
8052 bt == VT_SHORT ||
8053 bt == VT_DOUBLE ||
8054 bt == VT_LDOUBLE ||
8055 bt == VT_LLONG ||
8056 (bt == VT_INT && bit_size != 32)))
8057 error("initializer element is not computable at load time");
8058 switch(bt) {
8059 case VT_BYTE:
8060 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8061 break;
8062 case VT_SHORT:
8063 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8064 break;
8065 case VT_DOUBLE:
8066 *(double *)ptr = vtop->c.d;
8067 break;
8068 case VT_LDOUBLE:
8069 *(long double *)ptr = vtop->c.ld;
8070 break;
8071 case VT_LLONG:
8072 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8073 break;
8074 default:
8075 if (vtop->r & VT_SYM) {
8076 greloc(sec, vtop->sym, c, R_DATA_32);
8078 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8079 break;
8081 vtop--;
8082 } else {
8083 vset(&dtype, VT_LOCAL, c);
8084 vswap();
8085 vstore();
8086 vpop();
8090 /* put zeros for variable based init */
8091 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8093 if (sec) {
8094 /* nothing to do because globals are already set to zero */
8095 } else {
8096 vpush_global_sym(&func_old_type, TOK_memset);
8097 vseti(VT_LOCAL, c);
8098 vpushi(0);
8099 vpushi(size);
8100 gfunc_call(3);
8104 /* 't' contains the type and storage info. 'c' is the offset of the
8105 object in section 'sec'. If 'sec' is NULL, it means stack based
8106 allocation. 'first' is true if array '{' must be read (multi
8107 dimension implicit array init handling). 'size_only' is true if
8108 size only evaluation is wanted (only for arrays). */
8109 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8110 int first, int size_only)
8112 int index, array_length, n, no_oblock, nb, parlevel, i;
8113 int size1, align1, expr_type;
8114 Sym *s, *f;
8115 CType *t1;
8117 if (type->t & VT_ARRAY) {
8118 s = type->ref;
8119 n = s->c;
8120 array_length = 0;
8121 t1 = pointed_type(type);
8122 size1 = type_size(t1, &align1);
8124 no_oblock = 1;
8125 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8126 tok == '{') {
8127 skip('{');
8128 no_oblock = 0;
8131 /* only parse strings here if correct type (otherwise: handle
8132 them as ((w)char *) expressions */
8133 if ((tok == TOK_LSTR &&
8134 (t1->t & VT_BTYPE) == VT_INT) ||
8135 (tok == TOK_STR &&
8136 (t1->t & VT_BTYPE) == VT_BYTE)) {
8137 while (tok == TOK_STR || tok == TOK_LSTR) {
8138 int cstr_len, ch;
8139 CString *cstr;
8141 cstr = tokc.cstr;
8142 /* compute maximum number of chars wanted */
8143 if (tok == TOK_STR)
8144 cstr_len = cstr->size;
8145 else
8146 cstr_len = cstr->size / sizeof(int);
8147 cstr_len--;
8148 nb = cstr_len;
8149 if (n >= 0 && nb > (n - array_length))
8150 nb = n - array_length;
8151 if (!size_only) {
8152 if (cstr_len > nb)
8153 warning("initializer-string for array is too long");
8154 /* in order to go faster for common case (char
8155 string in global variable, we handle it
8156 specifically */
8157 if (sec && tok == TOK_STR && size1 == 1) {
8158 memcpy(sec->data + c + array_length, cstr->data, nb);
8159 } else {
8160 for(i=0;i<nb;i++) {
8161 if (tok == TOK_STR)
8162 ch = ((unsigned char *)cstr->data)[i];
8163 else
8164 ch = ((int *)cstr->data)[i];
8165 init_putv(t1, sec, c + (array_length + i) * size1,
8166 ch, EXPR_VAL);
8170 array_length += nb;
8171 next();
8173 /* only add trailing zero if enough storage (no
8174 warning in this case since it is standard) */
8175 if (n < 0 || array_length < n) {
8176 if (!size_only) {
8177 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8179 array_length++;
8181 } else {
8182 index = 0;
8183 while (tok != '}') {
8184 decl_designator(type, sec, c, &index, NULL, size_only);
8185 if (n >= 0 && index >= n)
8186 error("index too large");
8187 /* must put zero in holes (note that doing it that way
8188 ensures that it even works with designators) */
8189 if (!size_only && array_length < index) {
8190 init_putz(t1, sec, c + array_length * size1,
8191 (index - array_length) * size1);
8193 index++;
8194 if (index > array_length)
8195 array_length = index;
8196 /* special test for multi dimensional arrays (may not
8197 be strictly correct if designators are used at the
8198 same time) */
8199 if (index >= n && no_oblock)
8200 break;
8201 if (tok == '}')
8202 break;
8203 skip(',');
8206 if (!no_oblock)
8207 skip('}');
8208 /* put zeros at the end */
8209 if (!size_only && n >= 0 && array_length < n) {
8210 init_putz(t1, sec, c + array_length * size1,
8211 (n - array_length) * size1);
8213 /* patch type size if needed */
8214 if (n < 0)
8215 s->c = array_length;
8216 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8217 (sec || !first || tok == '{')) {
8218 int par_count;
8220 /* NOTE: the previous test is a specific case for automatic
8221 struct/union init */
8222 /* XXX: union needs only one init */
8224 /* XXX: this test is incorrect for local initializers
8225 beginning with ( without {. It would be much more difficult
8226 to do it correctly (ideally, the expression parser should
8227 be used in all cases) */
8228 par_count = 0;
8229 if (tok == '(') {
8230 AttributeDef ad1;
8231 CType type1;
8232 next();
8233 while (tok == '(') {
8234 par_count++;
8235 next();
8237 if (!parse_btype(&type1, &ad1))
8238 expect("cast");
8239 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8240 #if 0
8241 if (!is_assignable_types(type, &type1))
8242 error("invalid type for cast");
8243 #endif
8244 skip(')');
8246 no_oblock = 1;
8247 if (first || tok == '{') {
8248 skip('{');
8249 no_oblock = 0;
8251 s = type->ref;
8252 f = s->next;
8253 array_length = 0;
8254 index = 0;
8255 n = s->c;
8256 while (tok != '}') {
8257 decl_designator(type, sec, c, NULL, &f, size_only);
8258 index = f->c;
8259 if (!size_only && array_length < index) {
8260 init_putz(type, sec, c + array_length,
8261 index - array_length);
8263 index = index + type_size(&f->type, &align1);
8264 if (index > array_length)
8265 array_length = index;
8266 f = f->next;
8267 if (no_oblock && f == NULL)
8268 break;
8269 if (tok == '}')
8270 break;
8271 skip(',');
8273 /* put zeros at the end */
8274 if (!size_only && array_length < n) {
8275 init_putz(type, sec, c + array_length,
8276 n - array_length);
8278 if (!no_oblock)
8279 skip('}');
8280 while (par_count) {
8281 skip(')');
8282 par_count--;
8284 } else if (tok == '{') {
8285 next();
8286 decl_initializer(type, sec, c, first, size_only);
8287 skip('}');
8288 } else if (size_only) {
8289 /* just skip expression */
8290 parlevel = 0;
8291 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8292 tok != -1) {
8293 if (tok == '(')
8294 parlevel++;
8295 else if (tok == ')')
8296 parlevel--;
8297 next();
8299 } else {
8300 /* currently, we always use constant expression for globals
8301 (may change for scripting case) */
8302 expr_type = EXPR_CONST;
8303 if (!sec)
8304 expr_type = EXPR_ANY;
8305 init_putv(type, sec, c, 0, expr_type);
8309 /* parse an initializer for type 't' if 'has_init' is non zero, and
8310 allocate space in local or global data space ('r' is either
8311 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8312 variable 'v' of scope 'scope' is declared before initializers are
8313 parsed. If 'v' is zero, then a reference to the new object is put
8314 in the value stack. If 'has_init' is 2, a special parsing is done
8315 to handle string constants. */
8316 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8317 int has_init, int v, int scope)
8319 int size, align, addr, data_offset;
8320 int level;
8321 ParseState saved_parse_state;
8322 TokenString init_str;
8323 Section *sec;
8325 size = type_size(type, &align);
8326 /* If unknown size, we must evaluate it before
8327 evaluating initializers because
8328 initializers can generate global data too
8329 (e.g. string pointers or ISOC99 compound
8330 literals). It also simplifies local
8331 initializers handling */
8332 tok_str_new(&init_str);
8333 if (size < 0) {
8334 if (!has_init)
8335 error("unknown type size");
8336 /* get all init string */
8337 if (has_init == 2) {
8338 /* only get strings */
8339 while (tok == TOK_STR || tok == TOK_LSTR) {
8340 tok_str_add_tok(&init_str);
8341 next();
8343 } else {
8344 level = 0;
8345 while (level > 0 || (tok != ',' && tok != ';')) {
8346 if (tok < 0)
8347 error("unexpected end of file in initializer");
8348 tok_str_add_tok(&init_str);
8349 if (tok == '{')
8350 level++;
8351 else if (tok == '}') {
8352 if (level == 0)
8353 break;
8354 level--;
8356 next();
8359 tok_str_add(&init_str, -1);
8360 tok_str_add(&init_str, 0);
8362 /* compute size */
8363 save_parse_state(&saved_parse_state);
8365 macro_ptr = init_str.str;
8366 next();
8367 decl_initializer(type, NULL, 0, 1, 1);
8368 /* prepare second initializer parsing */
8369 macro_ptr = init_str.str;
8370 next();
8372 /* if still unknown size, error */
8373 size = type_size(type, &align);
8374 if (size < 0)
8375 error("unknown type size");
8377 /* take into account specified alignment if bigger */
8378 if (ad->aligned > align)
8379 align = ad->aligned;
8380 if ((r & VT_VALMASK) == VT_LOCAL) {
8381 sec = NULL;
8382 if (do_bounds_check && (type->t & VT_ARRAY))
8383 loc--;
8384 loc = (loc - size) & -align;
8385 addr = loc;
8386 /* handles bounds */
8387 /* XXX: currently, since we do only one pass, we cannot track
8388 '&' operators, so we add only arrays */
8389 if (do_bounds_check && (type->t & VT_ARRAY)) {
8390 unsigned long *bounds_ptr;
8391 /* add padding between regions */
8392 loc--;
8393 /* then add local bound info */
8394 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8395 bounds_ptr[0] = addr;
8396 bounds_ptr[1] = size;
8398 if (v) {
8399 /* local variable */
8400 sym_push(v, type, r, addr);
8401 } else {
8402 /* push local reference */
8403 vset(type, r, addr);
8405 } else {
8406 Sym *sym;
8408 sym = NULL;
8409 if (v && scope == VT_CONST) {
8410 /* see if the symbol was already defined */
8411 sym = sym_find(v);
8412 if (sym) {
8413 if (!is_compatible_types(&sym->type, type))
8414 error("incompatible types for redefinition of '%s'",
8415 get_tok_str(v, NULL));
8416 if (sym->type.t & VT_EXTERN) {
8417 /* if the variable is extern, it was not allocated */
8418 sym->type.t &= ~VT_EXTERN;
8419 } else {
8420 /* we accept several definitions of the same
8421 global variable. this is tricky, because we
8422 must play with the SHN_COMMON type of the symbol */
8423 /* XXX: should check if the variable was already
8424 initialized. It is incorrect to initialized it
8425 twice */
8426 /* no init data, we won't add more to the symbol */
8427 if (!has_init)
8428 goto no_alloc;
8433 /* allocate symbol in corresponding section */
8434 sec = ad->section;
8435 if (!sec) {
8436 if (has_init)
8437 sec = data_section;
8439 if (sec) {
8440 data_offset = sec->data_offset;
8441 data_offset = (data_offset + align - 1) & -align;
8442 addr = data_offset;
8443 /* very important to increment global pointer at this time
8444 because initializers themselves can create new initializers */
8445 data_offset += size;
8446 /* add padding if bound check */
8447 if (do_bounds_check)
8448 data_offset++;
8449 sec->data_offset = data_offset;
8450 /* allocate section space to put the data */
8451 if (sec->sh_type != SHT_NOBITS &&
8452 data_offset > sec->data_allocated)
8453 section_realloc(sec, data_offset);
8454 } else {
8455 addr = 0; /* avoid warning */
8458 if (v) {
8459 if (scope == VT_CONST) {
8460 if (!sym)
8461 goto do_def;
8462 } else {
8463 do_def:
8464 sym = sym_push(v, type, r | VT_SYM, 0);
8466 /* update symbol definition */
8467 if (sec) {
8468 put_extern_sym(sym, sec, addr, size);
8469 } else {
8470 Elf32_Sym *esym;
8471 /* put a common area */
8472 put_extern_sym(sym, NULL, align, size);
8473 /* XXX: find a nicer way */
8474 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8475 esym->st_shndx = SHN_COMMON;
8477 } else {
8478 CValue cval;
8480 /* push global reference */
8481 sym = get_sym_ref(type, sec, addr, size);
8482 cval.ul = 0;
8483 vsetc(type, VT_CONST | VT_SYM, &cval);
8484 vtop->sym = sym;
8487 /* handles bounds now because the symbol must be defined
8488 before for the relocation */
8489 if (do_bounds_check) {
8490 unsigned long *bounds_ptr;
8492 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8493 /* then add global bound info */
8494 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8495 bounds_ptr[0] = 0; /* relocated */
8496 bounds_ptr[1] = size;
8499 if (has_init) {
8500 decl_initializer(type, sec, addr, 1, 0);
8501 /* restore parse state if needed */
8502 if (init_str.str) {
8503 tok_str_free(init_str.str);
8504 restore_parse_state(&saved_parse_state);
8507 no_alloc: ;
8510 void put_func_debug(Sym *sym)
8512 char buf[512];
8514 /* stabs info */
8515 /* XXX: we put here a dummy type */
8516 snprintf(buf, sizeof(buf), "%s:%c1",
8517 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8518 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8519 cur_text_section, sym->c);
8520 last_ind = 0;
8521 last_line_num = 0;
8524 /* not finished : try to put some local vars in registers */
8525 //#define CONFIG_REG_VARS
8527 #ifdef CONFIG_REG_VARS
8528 void add_var_ref(int t)
8530 printf("%s:%d: &%s\n",
8531 file->filename, file->line_num,
8532 get_tok_str(t, NULL));
8535 /* first pass on a function with heuristic to extract variable usage
8536 and pointer references to local variables for register allocation */
8537 void analyse_function(void)
8539 int level, t;
8541 for(;;) {
8542 if (tok == -1)
8543 break;
8544 /* any symbol coming after '&' is considered as being a
8545 variable whose reference is taken. It is highly unaccurate
8546 but it is difficult to do better without a complete parse */
8547 if (tok == '&') {
8548 next();
8549 /* if '& number', then no need to examine next tokens */
8550 if (tok == TOK_CINT ||
8551 tok == TOK_CUINT ||
8552 tok == TOK_CLLONG ||
8553 tok == TOK_CULLONG) {
8554 continue;
8555 } else if (tok >= TOK_UIDENT) {
8556 /* if '& ident [' or '& ident ->', then ident address
8557 is not needed */
8558 t = tok;
8559 next();
8560 if (tok != '[' && tok != TOK_ARROW)
8561 add_var_ref(t);
8562 } else {
8563 level = 0;
8564 while (tok != '}' && tok != ';' &&
8565 !((tok == ',' || tok == ')') && level == 0)) {
8566 if (tok >= TOK_UIDENT) {
8567 add_var_ref(tok);
8568 } else if (tok == '(') {
8569 level++;
8570 } else if (tok == ')') {
8571 level--;
8573 next();
8576 } else {
8577 next();
8581 #endif
8583 /* parse an old style function declaration list */
8584 /* XXX: check multiple parameter */
8585 static void func_decl_list(Sym *func_sym)
8587 AttributeDef ad;
8588 int v;
8589 Sym *s;
8590 CType btype, type;
8592 /* parse each declaration */
8593 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8594 if (!parse_btype(&btype, &ad))
8595 expect("declaration list");
8596 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8597 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8598 tok == ';') {
8599 /* we accept no variable after */
8600 } else {
8601 for(;;) {
8602 type = btype;
8603 type_decl(&type, &ad, &v, TYPE_DIRECT);
8604 /* find parameter in function parameter list */
8605 s = func_sym->next;
8606 while (s != NULL) {
8607 if ((s->v & ~SYM_FIELD) == v)
8608 goto found;
8609 s = s->next;
8611 error("declaration for parameter '%s' but no such parameter",
8612 get_tok_str(v, NULL));
8613 found:
8614 /* check that no storage specifier except 'register' was given */
8615 if (type.t & VT_STORAGE)
8616 error("storage class specified for '%s'", get_tok_str(v, NULL));
8617 convert_parameter_type(&type);
8618 /* we can add the type (NOTE: it could be local to the function) */
8619 s->type = type;
8620 /* accept other parameters */
8621 if (tok == ',')
8622 next();
8623 else
8624 break;
8627 skip(';');
8631 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8632 static void decl(int l)
8634 int v, has_init, r;
8635 CType type, btype;
8636 Sym *sym;
8637 AttributeDef ad;
8639 while (1) {
8640 if (!parse_btype(&btype, &ad)) {
8641 /* skip redundant ';' */
8642 /* XXX: find more elegant solution */
8643 if (tok == ';') {
8644 next();
8645 continue;
8647 /* special test for old K&R protos without explicit int
8648 type. Only accepted when defining global data */
8649 if (l == VT_LOCAL || tok < TOK_DEFINE)
8650 break;
8651 btype.t = VT_INT;
8653 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8654 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8655 tok == ';') {
8656 /* we accept no variable after */
8657 next();
8658 continue;
8660 while (1) { /* iterate thru each declaration */
8661 type = btype;
8662 type_decl(&type, &ad, &v, TYPE_DIRECT);
8663 #if 0
8665 char buf[500];
8666 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8667 printf("type = '%s'\n", buf);
8669 #endif
8670 if ((type.t & VT_BTYPE) == VT_FUNC) {
8671 /* if old style function prototype, we accept a
8672 declaration list */
8673 sym = type.ref;
8674 if (sym->c == FUNC_OLD)
8675 func_decl_list(sym);
8678 if (tok == '{') {
8679 #ifdef CONFIG_REG_VARS
8680 TokenString func_str;
8681 ParseState saved_parse_state;
8682 int block_level;
8683 #endif
8685 if (l == VT_LOCAL)
8686 error("cannot use local functions");
8687 if (!(type.t & VT_FUNC))
8688 expect("function definition");
8690 /* reject abstract declarators in function definition */
8691 sym = type.ref;
8692 while ((sym = sym->next) != NULL)
8693 if (!(sym->v & ~SYM_FIELD))
8694 expect("identifier");
8696 /* XXX: cannot do better now: convert extern line to static inline */
8697 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8698 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8700 #ifdef CONFIG_REG_VARS
8701 /* parse all function code and record it */
8703 tok_str_new(&func_str);
8705 block_level = 0;
8706 for(;;) {
8707 int t;
8708 if (tok == -1)
8709 error("unexpected end of file");
8710 tok_str_add_tok(&func_str);
8711 t = tok;
8712 next();
8713 if (t == '{') {
8714 block_level++;
8715 } else if (t == '}') {
8716 block_level--;
8717 if (block_level == 0)
8718 break;
8721 tok_str_add(&func_str, -1);
8722 tok_str_add(&func_str, 0);
8724 save_parse_state(&saved_parse_state);
8726 macro_ptr = func_str.str;
8727 next();
8728 analyse_function();
8729 #endif
8731 /* compute text section */
8732 cur_text_section = ad.section;
8733 if (!cur_text_section)
8734 cur_text_section = text_section;
8735 ind = cur_text_section->data_offset;
8736 funcname = get_tok_str(v, NULL);
8737 sym = sym_find(v);
8738 if (sym) {
8739 /* if symbol is already defined, then put complete type */
8740 sym->type = type;
8741 } else {
8742 /* put function symbol */
8743 sym = global_identifier_push(v, type.t, 0);
8744 sym->type.ref = type.ref;
8746 /* NOTE: we patch the symbol size later */
8747 put_extern_sym(sym, cur_text_section, ind, 0);
8748 func_ind = ind;
8749 sym->r = VT_SYM | VT_CONST;
8750 /* put debug symbol */
8751 if (do_debug)
8752 put_func_debug(sym);
8753 /* push a dummy symbol to enable local sym storage */
8754 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8755 gfunc_prolog(&type);
8756 rsym = 0;
8757 #ifdef CONFIG_REG_VARS
8758 macro_ptr = func_str.str;
8759 next();
8760 #endif
8761 block(NULL, NULL, NULL, NULL, 0, 0);
8762 gsym(rsym);
8763 gfunc_epilog();
8764 cur_text_section->data_offset = ind;
8765 label_pop(&global_label_stack, NULL);
8766 sym_pop(&local_stack, NULL); /* reset local stack */
8767 /* end of function */
8768 /* patch symbol size */
8769 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8770 ind - func_ind;
8771 if (do_debug) {
8772 put_stabn(N_FUN, 0, 0, ind - func_ind);
8774 funcname = ""; /* for safety */
8775 func_vt.t = VT_VOID; /* for safety */
8776 ind = 0; /* for safety */
8778 #ifdef CONFIG_REG_VARS
8779 tok_str_free(func_str.str);
8780 restore_parse_state(&saved_parse_state);
8781 #endif
8782 break;
8783 } else {
8784 if (btype.t & VT_TYPEDEF) {
8785 /* save typedefed type */
8786 /* XXX: test storage specifiers ? */
8787 sym = sym_push(v, &type, 0, 0);
8788 sym->type.t |= VT_TYPEDEF;
8789 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8790 /* external function definition */
8791 external_sym(v, &type, 0);
8792 } else {
8793 /* not lvalue if array */
8794 r = 0;
8795 if (!(type.t & VT_ARRAY))
8796 r |= lvalue_type(type.t);
8797 has_init = (tok == '=');
8798 if ((btype.t & VT_EXTERN) ||
8799 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8800 !has_init && l == VT_CONST && type.ref->c < 0)) {
8801 /* external variable */
8802 /* NOTE: as GCC, uninitialized global static
8803 arrays of null size are considered as
8804 extern */
8805 external_sym(v, &type, r);
8806 } else {
8807 if (type.t & VT_STATIC)
8808 r |= VT_CONST;
8809 else
8810 r |= l;
8811 if (has_init)
8812 next();
8813 decl_initializer_alloc(&type, &ad, r,
8814 has_init, v, l);
8817 if (tok != ',') {
8818 skip(';');
8819 break;
8821 next();
8827 /* better than nothing, but needs extension to handle '-E' option
8828 correctly too */
8829 static void preprocess_init(TCCState *s1)
8831 s1->include_stack_ptr = s1->include_stack;
8832 /* XXX: move that before to avoid having to initialize
8833 file->ifdef_stack_ptr ? */
8834 s1->ifdef_stack_ptr = s1->ifdef_stack;
8835 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8837 /* XXX: not ANSI compliant: bound checking says error */
8838 vtop = vstack - 1;
8841 /* compile the C file opened in 'file'. Return non zero if errors. */
8842 static int tcc_compile(TCCState *s1)
8844 Sym *define_start;
8845 char buf[512];
8846 volatile int section_sym;
8848 #ifdef INC_DEBUG
8849 printf("%s: **** new file\n", file->filename);
8850 #endif
8851 preprocess_init(s1);
8853 funcname = "";
8854 anon_sym = SYM_FIRST_ANOM;
8856 /* file info: full path + filename */
8857 section_sym = 0; /* avoid warning */
8858 if (do_debug) {
8859 section_sym = put_elf_sym(symtab_section, 0, 0,
8860 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8861 text_section->sh_num, NULL);
8862 getcwd(buf, sizeof(buf));
8863 pstrcat(buf, sizeof(buf), "/");
8864 put_stabs_r(buf, N_SO, 0, 0,
8865 text_section->data_offset, text_section, section_sym);
8866 put_stabs_r(file->filename, N_SO, 0, 0,
8867 text_section->data_offset, text_section, section_sym);
8869 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8870 symbols can be safely used */
8871 put_elf_sym(symtab_section, 0, 0,
8872 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8873 SHN_ABS, file->filename);
8875 /* define some often used types */
8876 int_type.t = VT_INT;
8878 char_pointer_type.t = VT_BYTE;
8879 mk_pointer(&char_pointer_type);
8881 func_old_type.t = VT_FUNC;
8882 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8884 #if 0
8885 /* define 'void *alloca(unsigned int)' builtin function */
8887 Sym *s1;
8889 p = anon_sym++;
8890 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8891 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8892 s1->next = NULL;
8893 sym->next = s1;
8894 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8896 #endif
8898 define_start = define_stack;
8900 if (setjmp(s1->error_jmp_buf) == 0) {
8901 s1->nb_errors = 0;
8902 s1->error_set_jmp_enabled = 1;
8904 ch = file->buf_ptr[0];
8905 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8906 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8907 next();
8908 decl(VT_CONST);
8909 if (tok != TOK_EOF)
8910 expect("declaration");
8912 /* end of translation unit info */
8913 if (do_debug) {
8914 put_stabs_r(NULL, N_SO, 0, 0,
8915 text_section->data_offset, text_section, section_sym);
8918 s1->error_set_jmp_enabled = 0;
8920 /* reset define stack, but leave -Dsymbols (may be incorrect if
8921 they are undefined) */
8922 free_defines(define_start);
8924 sym_pop(&global_stack, NULL);
8926 return s1->nb_errors != 0 ? -1 : 0;
8929 #ifdef LIBTCC
8930 int tcc_compile_string(TCCState *s, const char *str)
8932 BufferedFile bf1, *bf = &bf1;
8933 int ret, len;
8934 char *buf;
8936 /* init file structure */
8937 bf->fd = -1;
8938 /* XXX: avoid copying */
8939 len = strlen(str);
8940 buf = tcc_malloc(len + 1);
8941 if (!buf)
8942 return -1;
8943 memcpy(buf, str, len);
8944 buf[len] = CH_EOB;
8945 bf->buf_ptr = buf;
8946 bf->buf_end = buf + len;
8947 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8948 bf->line_num = 1;
8949 file = bf;
8951 ret = tcc_compile(s);
8953 tcc_free(buf);
8955 /* currently, no need to close */
8956 return ret;
8958 #endif
8960 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8961 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8963 BufferedFile bf1, *bf = &bf1;
8965 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8966 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8967 /* default value */
8968 if (!value)
8969 value = "1";
8970 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8972 /* init file structure */
8973 bf->fd = -1;
8974 bf->buf_ptr = bf->buffer;
8975 bf->buf_end = bf->buffer + strlen(bf->buffer);
8976 *bf->buf_end = CH_EOB;
8977 bf->filename[0] = '\0';
8978 bf->line_num = 1;
8979 file = bf;
8981 s1->include_stack_ptr = s1->include_stack;
8983 /* parse with define parser */
8984 ch = file->buf_ptr[0];
8985 next_nomacro();
8986 parse_define();
8987 file = NULL;
8990 /* undefine a preprocessor symbol */
8991 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8993 TokenSym *ts;
8994 Sym *s;
8995 ts = tok_alloc(sym, strlen(sym));
8996 s = define_find(ts->tok);
8997 /* undefine symbol by putting an invalid name */
8998 if (s)
8999 define_undef(s);
9002 #ifdef CONFIG_TCC_ASM
9004 #ifdef TCC_TARGET_I386
9005 #include "i386-asm.c"
9006 #endif
9007 #include "tccasm.c"
9009 #else
9010 static void asm_instr(void)
9012 error("inline asm() not supported");
9014 #endif
9016 #include "tccelf.c"
9018 #ifdef TCC_TARGET_COFF
9019 #include "tcccoff.c"
9020 #endif
9022 /* print the position in the source file of PC value 'pc' by reading
9023 the stabs debug information */
9024 static void rt_printline(unsigned long wanted_pc)
9026 Stab_Sym *sym, *sym_end;
9027 char func_name[128], last_func_name[128];
9028 unsigned long func_addr, last_pc, pc;
9029 const char *incl_files[INCLUDE_STACK_SIZE];
9030 int incl_index, len, last_line_num, i;
9031 const char *str, *p;
9033 fprintf(stderr, "0x%08lx:", wanted_pc);
9035 func_name[0] = '\0';
9036 func_addr = 0;
9037 incl_index = 0;
9038 last_func_name[0] = '\0';
9039 last_pc = 0xffffffff;
9040 last_line_num = 1;
9041 sym = (Stab_Sym *)stab_section->data + 1;
9042 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9043 while (sym < sym_end) {
9044 switch(sym->n_type) {
9045 /* function start or end */
9046 case N_FUN:
9047 if (sym->n_strx == 0) {
9048 /* we test if between last line and end of function */
9049 pc = sym->n_value + func_addr;
9050 if (wanted_pc >= last_pc && wanted_pc < pc)
9051 goto found;
9052 func_name[0] = '\0';
9053 func_addr = 0;
9054 } else {
9055 str = stabstr_section->data + sym->n_strx;
9056 p = strchr(str, ':');
9057 if (!p) {
9058 pstrcpy(func_name, sizeof(func_name), str);
9059 } else {
9060 len = p - str;
9061 if (len > sizeof(func_name) - 1)
9062 len = sizeof(func_name) - 1;
9063 memcpy(func_name, str, len);
9064 func_name[len] = '\0';
9066 func_addr = sym->n_value;
9068 break;
9069 /* line number info */
9070 case N_SLINE:
9071 pc = sym->n_value + func_addr;
9072 if (wanted_pc >= last_pc && wanted_pc < pc)
9073 goto found;
9074 last_pc = pc;
9075 last_line_num = sym->n_desc;
9076 /* XXX: slow! */
9077 strcpy(last_func_name, func_name);
9078 break;
9079 /* include files */
9080 case N_BINCL:
9081 str = stabstr_section->data + sym->n_strx;
9082 add_incl:
9083 if (incl_index < INCLUDE_STACK_SIZE) {
9084 incl_files[incl_index++] = str;
9086 break;
9087 case N_EINCL:
9088 if (incl_index > 1)
9089 incl_index--;
9090 break;
9091 case N_SO:
9092 if (sym->n_strx == 0) {
9093 incl_index = 0; /* end of translation unit */
9094 } else {
9095 str = stabstr_section->data + sym->n_strx;
9096 /* do not add path */
9097 len = strlen(str);
9098 if (len > 0 && str[len - 1] != '/')
9099 goto add_incl;
9101 break;
9103 sym++;
9106 /* second pass: we try symtab symbols (no line number info) */
9107 incl_index = 0;
9109 Elf32_Sym *sym, *sym_end;
9110 int type;
9112 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9113 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9114 sym < sym_end;
9115 sym++) {
9116 type = ELF32_ST_TYPE(sym->st_info);
9117 if (type == STT_FUNC) {
9118 if (wanted_pc >= sym->st_value &&
9119 wanted_pc < sym->st_value + sym->st_size) {
9120 pstrcpy(last_func_name, sizeof(last_func_name),
9121 strtab_section->data + sym->st_name);
9122 goto found;
9127 /* did not find any info: */
9128 fprintf(stderr, " ???\n");
9129 return;
9130 found:
9131 if (last_func_name[0] != '\0') {
9132 fprintf(stderr, " %s()", last_func_name);
9134 if (incl_index > 0) {
9135 fprintf(stderr, " (%s:%d",
9136 incl_files[incl_index - 1], last_line_num);
9137 for(i = incl_index - 2; i >= 0; i--)
9138 fprintf(stderr, ", included from %s", incl_files[i]);
9139 fprintf(stderr, ")");
9141 fprintf(stderr, "\n");
9144 #ifndef WIN32
9146 #ifdef __i386__
9148 /* fix for glibc 2.1 */
9149 #ifndef REG_EIP
9150 #define REG_EIP EIP
9151 #define REG_EBP EBP
9152 #endif
9154 /* return the PC at frame level 'level'. Return non zero if not found */
9155 static int rt_get_caller_pc(unsigned long *paddr,
9156 ucontext_t *uc, int level)
9158 unsigned long fp;
9159 int i;
9161 if (level == 0) {
9162 #if defined(__FreeBSD__)
9163 *paddr = uc->uc_mcontext.mc_eip;
9164 #elif defined(__dietlibc__)
9165 *paddr = uc->uc_mcontext.eip;
9166 #else
9167 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9168 #endif
9169 return 0;
9170 } else {
9171 #if defined(__FreeBSD__)
9172 fp = uc->uc_mcontext.mc_ebp;
9173 #elif defined(__dietlibc__)
9174 fp = uc->uc_mcontext.ebp;
9175 #else
9176 fp = uc->uc_mcontext.gregs[REG_EBP];
9177 #endif
9178 for(i=1;i<level;i++) {
9179 /* XXX: check address validity with program info */
9180 if (fp <= 0x1000 || fp >= 0xc0000000)
9181 return -1;
9182 fp = ((unsigned long *)fp)[0];
9184 *paddr = ((unsigned long *)fp)[1];
9185 return 0;
9188 #else
9190 #warning add arch specific rt_get_caller_pc()
9192 static int rt_get_caller_pc(unsigned long *paddr,
9193 ucontext_t *uc, int level)
9195 return -1;
9197 #endif
9199 /* emit a run time error at position 'pc' */
9200 void rt_error(ucontext_t *uc, const char *fmt, ...)
9202 va_list ap;
9203 unsigned long pc;
9204 int i;
9206 va_start(ap, fmt);
9207 fprintf(stderr, "Runtime error: ");
9208 vfprintf(stderr, fmt, ap);
9209 fprintf(stderr, "\n");
9210 for(i=0;i<num_callers;i++) {
9211 if (rt_get_caller_pc(&pc, uc, i) < 0)
9212 break;
9213 if (i == 0)
9214 fprintf(stderr, "at ");
9215 else
9216 fprintf(stderr, "by ");
9217 rt_printline(pc);
9219 exit(255);
9220 va_end(ap);
9223 /* signal handler for fatal errors */
9224 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9226 ucontext_t *uc = puc;
9228 switch(signum) {
9229 case SIGFPE:
9230 switch(siginf->si_code) {
9231 case FPE_INTDIV:
9232 case FPE_FLTDIV:
9233 rt_error(uc, "division by zero");
9234 break;
9235 default:
9236 rt_error(uc, "floating point exception");
9237 break;
9239 break;
9240 case SIGBUS:
9241 case SIGSEGV:
9242 if (rt_bound_error_msg && *rt_bound_error_msg)
9243 rt_error(uc, *rt_bound_error_msg);
9244 else
9245 rt_error(uc, "dereferencing invalid pointer");
9246 break;
9247 case SIGILL:
9248 rt_error(uc, "illegal instruction");
9249 break;
9250 case SIGABRT:
9251 rt_error(uc, "abort() called");
9252 break;
9253 default:
9254 rt_error(uc, "caught signal %d", signum);
9255 break;
9257 exit(255);
9259 #endif
9261 /* do all relocations (needed before using tcc_get_symbol()) */
9262 int tcc_relocate(TCCState *s1)
9264 Section *s;
9265 int i;
9267 s1->nb_errors = 0;
9269 tcc_add_runtime(s1);
9271 build_got_entries(s1);
9273 relocate_common_syms();
9275 /* compute relocation address : section are relocated in place. We
9276 also alloc the bss space */
9277 for(i = 1; i < s1->nb_sections; i++) {
9278 s = s1->sections[i];
9279 if (s->sh_flags & SHF_ALLOC) {
9280 if (s->sh_type == SHT_NOBITS)
9281 s->data = tcc_mallocz(s->data_offset);
9282 s->sh_addr = (unsigned long)s->data;
9286 relocate_syms(s1, 1);
9288 if (s1->nb_errors != 0)
9289 return -1;
9291 /* relocate each section */
9292 for(i = 1; i < s1->nb_sections; i++) {
9293 s = s1->sections[i];
9294 if (s->reloc)
9295 relocate_section(s1, s);
9297 return 0;
9300 /* launch the compiled program with the given arguments */
9301 int tcc_run(TCCState *s1, int argc, char **argv)
9303 int (*prog_main)(int, char **);
9305 if (tcc_relocate(s1) < 0)
9306 return -1;
9308 prog_main = tcc_get_symbol_err(s1, "main");
9310 if (do_debug) {
9311 #ifdef WIN32
9312 error("debug mode currently not available for Windows");
9313 #else
9314 struct sigaction sigact;
9315 /* install TCC signal handlers to print debug info on fatal
9316 runtime errors */
9317 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9318 sigact.sa_sigaction = sig_error;
9319 sigemptyset(&sigact.sa_mask);
9320 sigaction(SIGFPE, &sigact, NULL);
9321 sigaction(SIGILL, &sigact, NULL);
9322 sigaction(SIGSEGV, &sigact, NULL);
9323 sigaction(SIGBUS, &sigact, NULL);
9324 sigaction(SIGABRT, &sigact, NULL);
9325 #endif
9328 #ifdef CONFIG_TCC_BCHECK
9329 if (do_bounds_check) {
9330 void (*bound_init)(void);
9332 /* set error function */
9333 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9334 "__bound_error_msg");
9336 /* XXX: use .init section so that it also work in binary ? */
9337 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9338 bound_init();
9340 #endif
9341 return (*prog_main)(argc, argv);
9344 TCCState *tcc_new(void)
9346 const char *p, *r;
9347 TCCState *s;
9348 TokenSym *ts;
9349 int i, c;
9351 s = tcc_mallocz(sizeof(TCCState));
9352 if (!s)
9353 return NULL;
9354 tcc_state = s;
9355 s->output_type = TCC_OUTPUT_MEMORY;
9357 /* init isid table */
9358 for(i=0;i<256;i++)
9359 isidnum_table[i] = isid(i) || isnum(i);
9361 /* add all tokens */
9362 table_ident = NULL;
9363 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9365 tok_ident = TOK_IDENT;
9366 p = tcc_keywords;
9367 while (*p) {
9368 r = p;
9369 for(;;) {
9370 c = *r++;
9371 if (c == '\0')
9372 break;
9374 ts = tok_alloc(p, r - p - 1);
9375 p = r;
9378 /* we add dummy defines for some special macros to speed up tests
9379 and to have working defined() */
9380 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9381 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9382 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9383 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9385 /* standard defines */
9386 tcc_define_symbol(s, "__STDC__", NULL);
9387 #if defined(TCC_TARGET_I386)
9388 tcc_define_symbol(s, "__i386__", NULL);
9389 #endif
9390 #if defined(TCC_TARGET_ARM)
9391 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9392 tcc_define_symbol(s, "__arm_elf__", NULL);
9393 tcc_define_symbol(s, "__arm_elf", NULL);
9394 tcc_define_symbol(s, "arm_elf", NULL);
9395 tcc_define_symbol(s, "__arm__", NULL);
9396 tcc_define_symbol(s, "__arm", NULL);
9397 tcc_define_symbol(s, "arm", NULL);
9398 tcc_define_symbol(s, "__APCS_32__", NULL);
9399 #endif
9400 #if defined(linux)
9401 tcc_define_symbol(s, "__linux__", NULL);
9402 tcc_define_symbol(s, "linux", NULL);
9403 #endif
9404 /* tiny C specific defines */
9405 tcc_define_symbol(s, "__TINYC__", NULL);
9407 /* tiny C & gcc defines */
9408 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9409 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9410 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9412 /* default library paths */
9413 tcc_add_library_path(s, "/usr/local/lib");
9414 tcc_add_library_path(s, "/usr/lib");
9415 tcc_add_library_path(s, "/lib");
9417 /* no section zero */
9418 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9420 /* create standard sections */
9421 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9422 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9423 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9425 /* symbols are always generated for linking stage */
9426 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9427 ".strtab",
9428 ".hashtab", SHF_PRIVATE);
9429 strtab_section = symtab_section->link;
9431 /* private symbol table for dynamic symbols */
9432 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9433 ".dynstrtab",
9434 ".dynhashtab", SHF_PRIVATE);
9435 s->alacarte_link = 1;
9437 #ifdef CHAR_IS_UNSIGNED
9438 s->char_is_unsigned = 1;
9439 #endif
9440 return s;
9443 void tcc_delete(TCCState *s1)
9445 int i, n;
9447 /* free -D defines */
9448 free_defines(NULL);
9450 /* free tokens */
9451 n = tok_ident - TOK_IDENT;
9452 for(i = 0; i < n; i++)
9453 tcc_free(table_ident[i]);
9454 tcc_free(table_ident);
9456 /* free all sections */
9458 free_section(symtab_section->hash);
9460 free_section(s1->dynsymtab_section->hash);
9461 free_section(s1->dynsymtab_section->link);
9462 free_section(s1->dynsymtab_section);
9464 for(i = 1; i < s1->nb_sections; i++)
9465 free_section(s1->sections[i]);
9466 tcc_free(s1->sections);
9468 /* free loaded dlls array */
9469 for(i = 0; i < s1->nb_loaded_dlls; i++)
9470 tcc_free(s1->loaded_dlls[i]);
9471 tcc_free(s1->loaded_dlls);
9473 /* library paths */
9474 for(i = 0; i < s1->nb_library_paths; i++)
9475 tcc_free(s1->library_paths[i]);
9476 tcc_free(s1->library_paths);
9478 /* cached includes */
9479 for(i = 0; i < s1->nb_cached_includes; i++)
9480 tcc_free(s1->cached_includes[i]);
9481 tcc_free(s1->cached_includes);
9483 for(i = 0; i < s1->nb_include_paths; i++)
9484 tcc_free(s1->include_paths[i]);
9485 tcc_free(s1->include_paths);
9487 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9488 tcc_free(s1->sysinclude_paths[i]);
9489 tcc_free(s1->sysinclude_paths);
9491 tcc_free(s1);
9494 int tcc_add_include_path(TCCState *s1, const char *pathname)
9496 char *pathname1;
9498 pathname1 = tcc_strdup(pathname);
9499 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9500 return 0;
9503 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9505 char *pathname1;
9507 pathname1 = tcc_strdup(pathname);
9508 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9509 return 0;
9512 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9514 const char *ext, *filename1;
9515 Elf32_Ehdr ehdr;
9516 int fd, ret;
9517 BufferedFile *saved_file;
9519 /* find source file type with extension */
9520 filename1 = strrchr(filename, '/');
9521 if (filename1)
9522 filename1++;
9523 else
9524 filename1 = filename;
9525 ext = strrchr(filename1, '.');
9526 if (ext)
9527 ext++;
9529 /* open the file */
9530 saved_file = file;
9531 file = tcc_open(s1, filename);
9532 if (!file) {
9533 if (flags & AFF_PRINT_ERROR) {
9534 error_noabort("file '%s' not found", filename);
9536 ret = -1;
9537 goto fail1;
9540 if (!ext || !strcmp(ext, "c")) {
9541 /* C file assumed */
9542 ret = tcc_compile(s1);
9543 } else
9544 #ifdef CONFIG_TCC_ASM
9545 if (!strcmp(ext, "S")) {
9546 /* preprocessed assembler */
9547 ret = tcc_assemble(s1, 1);
9548 } else if (!strcmp(ext, "s")) {
9549 /* non preprocessed assembler */
9550 ret = tcc_assemble(s1, 0);
9551 } else
9552 #endif
9554 fd = file->fd;
9555 /* assume executable format: auto guess file type */
9556 ret = read(fd, &ehdr, sizeof(ehdr));
9557 lseek(fd, 0, SEEK_SET);
9558 if (ret <= 0) {
9559 error_noabort("could not read header");
9560 goto fail;
9561 } else if (ret != sizeof(ehdr)) {
9562 goto try_load_script;
9565 if (ehdr.e_ident[0] == ELFMAG0 &&
9566 ehdr.e_ident[1] == ELFMAG1 &&
9567 ehdr.e_ident[2] == ELFMAG2 &&
9568 ehdr.e_ident[3] == ELFMAG3) {
9569 file->line_num = 0; /* do not display line number if error */
9570 if (ehdr.e_type == ET_REL) {
9571 ret = tcc_load_object_file(s1, fd, 0);
9572 } else if (ehdr.e_type == ET_DYN) {
9573 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9574 void *h;
9575 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9576 if (h)
9577 ret = 0;
9578 else
9579 ret = -1;
9580 } else {
9581 ret = tcc_load_dll(s1, fd, filename,
9582 (flags & AFF_REFERENCED_DLL) != 0);
9584 } else {
9585 error_noabort("unrecognized ELF file");
9586 goto fail;
9588 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9589 file->line_num = 0; /* do not display line number if error */
9590 ret = tcc_load_archive(s1, fd);
9591 } else
9592 #ifdef TCC_TARGET_COFF
9593 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9594 ret = tcc_load_coff(s1, fd);
9595 } else
9596 #endif
9598 /* as GNU ld, consider it is an ld script if not recognized */
9599 try_load_script:
9600 ret = tcc_load_ldscript(s1);
9601 if (ret < 0) {
9602 error_noabort("unrecognized file type");
9603 goto fail;
9607 the_end:
9608 tcc_close(file);
9609 fail1:
9610 file = saved_file;
9611 return ret;
9612 fail:
9613 ret = -1;
9614 goto the_end;
9617 int tcc_add_file(TCCState *s, const char *filename)
9619 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9622 int tcc_add_library_path(TCCState *s, const char *pathname)
9624 char *pathname1;
9626 pathname1 = tcc_strdup(pathname);
9627 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9628 return 0;
9631 /* find and load a dll. Return non zero if not found */
9632 /* XXX: add '-rpath' option support ? */
9633 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9635 char buf[1024];
9636 int i;
9638 for(i = 0; i < s->nb_library_paths; i++) {
9639 snprintf(buf, sizeof(buf), "%s/%s",
9640 s->library_paths[i], filename);
9641 if (tcc_add_file_internal(s, buf, flags) == 0)
9642 return 0;
9644 return -1;
9647 /* the library name is the same as the argument of the '-l' option */
9648 int tcc_add_library(TCCState *s, const char *libraryname)
9650 char buf[1024];
9651 int i;
9653 /* first we look for the dynamic library if not static linking */
9654 if (!s->static_link) {
9655 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9656 if (tcc_add_dll(s, buf, 0) == 0)
9657 return 0;
9660 /* then we look for the static library */
9661 for(i = 0; i < s->nb_library_paths; i++) {
9662 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9663 s->library_paths[i], libraryname);
9664 if (tcc_add_file_internal(s, buf, 0) == 0)
9665 return 0;
9667 return -1;
9670 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9672 add_elf_sym(symtab_section, val, 0,
9673 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9674 SHN_ABS, name);
9675 return 0;
9678 int tcc_set_output_type(TCCState *s, int output_type)
9680 char buf[1024];
9682 s->output_type = output_type;
9684 if (!s->nostdinc) {
9685 /* default include paths */
9686 /* XXX: reverse order needed if -isystem support */
9687 tcc_add_sysinclude_path(s, "/usr/local/include");
9688 tcc_add_sysinclude_path(s, "/usr/include");
9689 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9690 tcc_add_sysinclude_path(s, buf);
9693 /* if bound checking, then add corresponding sections */
9694 #ifdef CONFIG_TCC_BCHECK
9695 if (do_bounds_check) {
9696 /* define symbol */
9697 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9698 /* create bounds sections */
9699 bounds_section = new_section(s, ".bounds",
9700 SHT_PROGBITS, SHF_ALLOC);
9701 lbounds_section = new_section(s, ".lbounds",
9702 SHT_PROGBITS, SHF_ALLOC);
9704 #endif
9706 if (s->char_is_unsigned) {
9707 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9710 /* add debug sections */
9711 if (do_debug) {
9712 /* stab symbols */
9713 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9714 stab_section->sh_entsize = sizeof(Stab_Sym);
9715 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9716 put_elf_str(stabstr_section, "");
9717 stab_section->link = stabstr_section;
9718 /* put first entry */
9719 put_stabs("", 0, 0, 0, 0);
9722 /* add libc crt1/crti objects */
9723 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9724 !s->nostdlib) {
9725 if (output_type != TCC_OUTPUT_DLL)
9726 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9727 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9729 return 0;
9732 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9733 #define FD_INVERT 0x0002 /* invert value before storing */
9735 typedef struct FlagDef {
9736 uint16_t offset;
9737 uint16_t flags;
9738 const char *name;
9739 } FlagDef;
9741 static const FlagDef warning_defs[] = {
9742 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9743 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9744 { offsetof(TCCState, warn_error), 0, "error" },
9745 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9746 "implicit-function-declaration" },
9749 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9750 const char *name, int value)
9752 int i;
9753 const FlagDef *p;
9754 const char *r;
9756 r = name;
9757 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9758 r += 3;
9759 value = !value;
9761 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9762 if (!strcmp(r, p->name))
9763 goto found;
9765 return -1;
9766 found:
9767 if (p->flags & FD_INVERT)
9768 value = !value;
9769 *(int *)((uint8_t *)s + p->offset) = value;
9770 return 0;
9774 /* set/reset a warning */
9775 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9777 int i;
9778 const FlagDef *p;
9780 if (!strcmp(warning_name, "all")) {
9781 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9782 if (p->flags & WD_ALL)
9783 *(int *)((uint8_t *)s + p->offset) = 1;
9785 return 0;
9786 } else {
9787 return set_flag(s, warning_defs, countof(warning_defs),
9788 warning_name, value);
9792 static const FlagDef flag_defs[] = {
9793 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9794 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9797 /* set/reset a flag */
9798 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9800 return set_flag(s, flag_defs, countof(flag_defs),
9801 flag_name, value);
9804 #if !defined(LIBTCC)
9806 /* extract the basename of a file */
9807 static const char *tcc_basename(const char *name)
9809 const char *p;
9810 p = strrchr(name, '/');
9811 #ifdef WIN32
9812 if (!p)
9813 p = strrchr(name, '\\');
9814 #endif
9815 if (!p)
9816 p = name;
9817 else
9818 p++;
9819 return p;
9822 static int64_t getclock_us(void)
9824 #ifdef WIN32
9825 struct _timeb tb;
9826 _ftime(&tb);
9827 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9828 #else
9829 struct timeval tv;
9830 gettimeofday(&tv, NULL);
9831 return tv.tv_sec * 1000000LL + tv.tv_usec;
9832 #endif
9835 void help(void)
9837 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9838 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9839 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9840 " [infile1 infile2...] [-run infile args...]\n"
9841 "\n"
9842 "General options:\n"
9843 " -v display current version\n"
9844 " -c compile only - generate an object file\n"
9845 " -o outfile set output filename\n"
9846 " -Bdir set tcc internal library path\n"
9847 " -bench output compilation statistics\n"
9848 " -run run compiled source\n"
9849 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9850 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9851 " -w disable all warnings\n"
9852 "Preprocessor options:\n"
9853 " -Idir add include path 'dir'\n"
9854 " -Dsym[=val] define 'sym' with value 'val'\n"
9855 " -Usym undefine 'sym'\n"
9856 "Linker options:\n"
9857 " -Ldir add library path 'dir'\n"
9858 " -llib link with dynamic or static library 'lib'\n"
9859 " -shared generate a shared library\n"
9860 " -static static linking\n"
9861 " -rdynamic export all global symbols to dynamic linker\n"
9862 " -r relocatable output\n"
9863 "Debugger options:\n"
9864 " -g generate runtime debug info\n"
9865 #ifdef CONFIG_TCC_BCHECK
9866 " -b compile with built-in memory and bounds checker (implies -g)\n"
9867 #endif
9868 " -bt N show N callers in stack traces\n"
9872 #define TCC_OPTION_HAS_ARG 0x0001
9873 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9875 typedef struct TCCOption {
9876 const char *name;
9877 uint16_t index;
9878 uint16_t flags;
9879 } TCCOption;
9881 enum {
9882 TCC_OPTION_HELP,
9883 TCC_OPTION_I,
9884 TCC_OPTION_D,
9885 TCC_OPTION_U,
9886 TCC_OPTION_L,
9887 TCC_OPTION_B,
9888 TCC_OPTION_l,
9889 TCC_OPTION_bench,
9890 TCC_OPTION_bt,
9891 TCC_OPTION_b,
9892 TCC_OPTION_g,
9893 TCC_OPTION_c,
9894 TCC_OPTION_static,
9895 TCC_OPTION_shared,
9896 TCC_OPTION_o,
9897 TCC_OPTION_r,
9898 TCC_OPTION_W,
9899 TCC_OPTION_O,
9900 TCC_OPTION_m,
9901 TCC_OPTION_f,
9902 TCC_OPTION_nostdinc,
9903 TCC_OPTION_nostdlib,
9904 TCC_OPTION_print_search_dirs,
9905 TCC_OPTION_rdynamic,
9906 TCC_OPTION_run,
9907 TCC_OPTION_v,
9908 TCC_OPTION_w,
9911 static const TCCOption tcc_options[] = {
9912 { "h", TCC_OPTION_HELP, 0 },
9913 { "?", TCC_OPTION_HELP, 0 },
9914 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9915 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9916 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9917 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9918 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9919 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9920 { "bench", TCC_OPTION_bench, 0 },
9921 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9922 #ifdef CONFIG_TCC_BCHECK
9923 { "b", TCC_OPTION_b, 0 },
9924 #endif
9925 { "g", TCC_OPTION_g, 0 },
9926 { "c", TCC_OPTION_c, 0 },
9927 { "static", TCC_OPTION_static, 0 },
9928 { "shared", TCC_OPTION_shared, 0 },
9929 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9930 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9931 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9932 { "r", TCC_OPTION_r, 0 },
9933 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9934 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9935 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9936 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9937 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9938 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9939 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9940 { "v", TCC_OPTION_v, 0 },
9941 { "w", TCC_OPTION_w, 0 },
9942 { NULL },
9945 /* convert 'str' into an array of space separated strings */
9946 static int expand_args(char ***pargv, const char *str)
9948 const char *s1;
9949 char **argv, *arg;
9950 int argc, len;
9952 argc = 0;
9953 argv = NULL;
9954 for(;;) {
9955 while (is_space(*str))
9956 str++;
9957 if (*str == '\0')
9958 break;
9959 s1 = str;
9960 while (*str != '\0' && !is_space(*str))
9961 str++;
9962 len = str - s1;
9963 arg = tcc_malloc(len + 1);
9964 memcpy(arg, s1, len);
9965 arg[len] = '\0';
9966 dynarray_add((void ***)&argv, &argc, arg);
9968 *pargv = argv;
9969 return argc;
9972 static char **files;
9973 static int nb_files, nb_libraries;
9974 static int multiple_files;
9975 static int print_search_dirs;
9976 static int output_type;
9977 static int reloc_output;
9978 static const char *outfile;
9980 int parse_args(TCCState *s, int argc, char **argv)
9982 int optind;
9983 const TCCOption *popt;
9984 const char *optarg, *p1, *r1;
9985 char *r;
9987 optind = 0;
9988 while (1) {
9989 if (optind >= argc) {
9990 if (nb_files == 0 && !print_search_dirs)
9991 goto show_help;
9992 else
9993 break;
9995 r = argv[optind++];
9996 if (r[0] != '-') {
9997 /* add a new file */
9998 dynarray_add((void ***)&files, &nb_files, r);
9999 if (!multiple_files) {
10000 optind--;
10001 /* argv[0] will be this file */
10002 break;
10004 } else {
10005 /* find option in table (match only the first chars */
10006 popt = tcc_options;
10007 for(;;) {
10008 p1 = popt->name;
10009 if (p1 == NULL)
10010 error("invalid option -- '%s'", r);
10011 r1 = r + 1;
10012 for(;;) {
10013 if (*p1 == '\0')
10014 goto option_found;
10015 if (*r1 != *p1)
10016 break;
10017 p1++;
10018 r1++;
10020 popt++;
10022 option_found:
10023 if (popt->flags & TCC_OPTION_HAS_ARG) {
10024 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10025 optarg = r1;
10026 } else {
10027 if (optind >= argc)
10028 error("argument to '%s' is missing", r);
10029 optarg = argv[optind++];
10031 } else {
10032 if (*r1 != '\0')
10033 goto show_help;
10034 optarg = NULL;
10037 switch(popt->index) {
10038 case TCC_OPTION_HELP:
10039 show_help:
10040 help();
10041 exit(1);
10042 case TCC_OPTION_I:
10043 if (tcc_add_include_path(s, optarg) < 0)
10044 error("too many include paths");
10045 break;
10046 case TCC_OPTION_D:
10048 char *sym, *value;
10049 sym = (char *)optarg;
10050 value = strchr(sym, '=');
10051 if (value) {
10052 *value = '\0';
10053 value++;
10055 tcc_define_symbol(s, sym, value);
10057 break;
10058 case TCC_OPTION_U:
10059 tcc_undefine_symbol(s, optarg);
10060 break;
10061 case TCC_OPTION_L:
10062 tcc_add_library_path(s, optarg);
10063 break;
10064 case TCC_OPTION_B:
10065 /* set tcc utilities path (mainly for tcc development) */
10066 tcc_lib_path = optarg;
10067 break;
10068 case TCC_OPTION_l:
10069 dynarray_add((void ***)&files, &nb_files, r);
10070 nb_libraries++;
10071 break;
10072 case TCC_OPTION_bench:
10073 do_bench = 1;
10074 break;
10075 case TCC_OPTION_bt:
10076 num_callers = atoi(optarg);
10077 break;
10078 #ifdef CONFIG_TCC_BCHECK
10079 case TCC_OPTION_b:
10080 do_bounds_check = 1;
10081 do_debug = 1;
10082 break;
10083 #endif
10084 case TCC_OPTION_g:
10085 do_debug = 1;
10086 break;
10087 case TCC_OPTION_c:
10088 multiple_files = 1;
10089 output_type = TCC_OUTPUT_OBJ;
10090 break;
10091 case TCC_OPTION_static:
10092 s->static_link = 1;
10093 break;
10094 case TCC_OPTION_shared:
10095 output_type = TCC_OUTPUT_DLL;
10096 break;
10097 case TCC_OPTION_o:
10098 multiple_files = 1;
10099 outfile = optarg;
10100 break;
10101 case TCC_OPTION_r:
10102 /* generate a .o merging several output files */
10103 reloc_output = 1;
10104 output_type = TCC_OUTPUT_OBJ;
10105 break;
10106 case TCC_OPTION_nostdinc:
10107 s->nostdinc = 1;
10108 break;
10109 case TCC_OPTION_nostdlib:
10110 s->nostdlib = 1;
10111 break;
10112 case TCC_OPTION_print_search_dirs:
10113 print_search_dirs = 1;
10114 break;
10115 case TCC_OPTION_run:
10117 int argc1;
10118 char **argv1;
10119 argc1 = expand_args(&argv1, optarg);
10120 if (argc1 > 0) {
10121 parse_args(s, argc1, argv1);
10123 multiple_files = 0;
10124 output_type = TCC_OUTPUT_MEMORY;
10126 break;
10127 case TCC_OPTION_v:
10128 printf("tcc version %s\n", TCC_VERSION);
10129 exit(0);
10130 case TCC_OPTION_f:
10131 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10132 goto unsupported_option;
10133 break;
10134 case TCC_OPTION_W:
10135 if (tcc_set_warning(s, optarg, 1) < 0 &&
10136 s->warn_unsupported)
10137 goto unsupported_option;
10138 break;
10139 case TCC_OPTION_w:
10140 s->warn_none = 1;
10141 break;
10142 case TCC_OPTION_rdynamic:
10143 s->rdynamic = 1;
10144 break;
10145 default:
10146 if (s->warn_unsupported) {
10147 unsupported_option:
10148 warning("unsupported option '%s'", r);
10150 break;
10154 return optind;
10157 int main(int argc, char **argv)
10159 int i;
10160 TCCState *s;
10161 int nb_objfiles, ret, optind;
10162 char objfilename[1024];
10163 int64_t start_time = 0;
10165 s = tcc_new();
10166 output_type = TCC_OUTPUT_EXE;
10167 outfile = NULL;
10168 multiple_files = 1;
10169 files = NULL;
10170 nb_files = 0;
10171 nb_libraries = 0;
10172 reloc_output = 0;
10173 print_search_dirs = 0;
10175 optind = parse_args(s, argc - 1, argv + 1) + 1;
10177 if (print_search_dirs) {
10178 /* enough for Linux kernel */
10179 printf("install: %s/\n", tcc_lib_path);
10180 return 0;
10183 nb_objfiles = nb_files - nb_libraries;
10185 /* if outfile provided without other options, we output an
10186 executable */
10187 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10188 output_type = TCC_OUTPUT_EXE;
10190 /* check -c consistency : only single file handled. XXX: checks file type */
10191 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10192 /* accepts only a single input file */
10193 if (nb_objfiles != 1)
10194 error("cannot specify multiple files with -c");
10195 if (nb_libraries != 0)
10196 error("cannot specify libraries with -c");
10199 /* compute default outfile name */
10200 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10201 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10202 char *ext;
10203 /* strip path */
10204 pstrcpy(objfilename, sizeof(objfilename) - 1,
10205 tcc_basename(files[0]));
10206 /* add .o extension */
10207 ext = strrchr(objfilename, '.');
10208 if (!ext)
10209 goto default_outfile;
10210 strcpy(ext + 1, "o");
10211 } else {
10212 default_outfile:
10213 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10215 outfile = objfilename;
10218 if (do_bench) {
10219 start_time = getclock_us();
10222 tcc_set_output_type(s, output_type);
10224 /* compile or add each files or library */
10225 for(i = 0;i < nb_files; i++) {
10226 const char *filename;
10228 filename = files[i];
10229 if (filename[0] == '-') {
10230 if (tcc_add_library(s, filename + 2) < 0)
10231 error("cannot find %s", filename);
10232 } else {
10233 if (tcc_add_file(s, filename) < 0) {
10234 ret = 1;
10235 goto the_end;
10240 /* free all files */
10241 tcc_free(files);
10243 if (do_bench) {
10244 double total_time;
10245 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10246 if (total_time < 0.001)
10247 total_time = 0.001;
10248 if (total_bytes < 1)
10249 total_bytes = 1;
10250 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10251 tok_ident - TOK_IDENT, total_lines, total_bytes,
10252 total_time, (int)(total_lines / total_time),
10253 total_bytes / total_time / 1000000.0);
10256 if (s->output_type != TCC_OUTPUT_MEMORY) {
10257 tcc_output_file(s, outfile);
10258 ret = 0;
10259 } else {
10260 ret = tcc_run(s, argc - optind, argv + optind);
10262 the_end:
10263 /* XXX: cannot do it with bound checking because of the malloc hooks */
10264 if (!do_bounds_check)
10265 tcc_delete(s);
10267 #ifdef MEM_DEBUG
10268 if (do_bench) {
10269 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10271 #endif
10272 return ret;
10275 #endif