suppressed warning for const function parameters
[tinycc/miki.git] / tcc.c
blob3da2068f1acd66431569327f33643db86fa64113
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 */
65 /* default target is I386 */
66 #if !defined(TCC_TARGET_I386)
67 #define TCC_TARGET_I386
68 #endif
70 #if !defined(WIN32) && !defined(TCC_UCLIBC)
71 #define CONFIG_TCC_BCHECK /* enable bound checking code */
72 #endif
74 /* define it to include assembler support */
75 #define CONFIG_TCC_ASM
77 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
78 executables or dlls */
79 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
81 #define INCLUDE_STACK_SIZE 32
82 #define IFDEF_STACK_SIZE 64
83 #define VSTACK_SIZE 64
84 #define STRING_MAX_SIZE 1024
86 #define TOK_HASH_SIZE 2048 /* must be a power of two */
87 #define TOK_ALLOC_INCR 512 /* must be a power of two */
88 #define TOK_STR_ALLOC_INCR_BITS 6
89 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
90 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
92 /* token symbol management */
93 typedef struct TokenSym {
94 struct TokenSym *hash_next;
95 struct Sym *sym_define; /* direct pointer to define */
96 struct Sym *sym_label; /* direct pointer to label */
97 struct Sym *sym_struct; /* direct pointer to structure */
98 struct Sym *sym_identifier; /* direct pointer to identifier */
99 int tok; /* token number */
100 int len;
101 char str[1];
102 } TokenSym;
104 typedef struct CString {
105 int size; /* size in bytes */
106 void *data; /* either 'char *' or 'int *' */
107 int size_allocated;
108 void *data_allocated; /* if non NULL, data has been malloced */
109 } CString;
111 /* type definition */
112 typedef struct CType {
113 int t;
114 struct Sym *ref;
115 } CType;
117 /* constant value */
118 typedef union CValue {
119 long double ld;
120 double d;
121 float f;
122 int i;
123 unsigned int ui;
124 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
125 long long ll;
126 unsigned long long ull;
127 struct CString *cstr;
128 void *ptr;
129 int tab[1];
130 } CValue;
132 /* value on stack */
133 typedef struct SValue {
134 CType type; /* type */
135 unsigned short r; /* register + flags */
136 unsigned short r2; /* second register, used for 'long long'
137 type. If not used, set to VT_CONST */
138 CValue c; /* constant, if VT_CONST */
139 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
140 } SValue;
142 /* symbol management */
143 typedef struct Sym {
144 int v; /* symbol token */
145 int r; /* associated register */
146 int c; /* associated number */
147 CType type; /* associated type */
148 struct Sym *next; /* next related symbol */
149 struct Sym *prev; /* prev symbol in stack */
150 struct Sym *prev_tok; /* previous symbol for this token */
151 } Sym;
153 /* section definition */
154 /* XXX: use directly ELF structure for parameters ? */
155 /* special flag to indicate that the section should not be linked to
156 the other ones */
157 #define SHF_PRIVATE 0x80000000
159 typedef struct Section {
160 unsigned long data_offset; /* current data offset */
161 unsigned char *data; /* section data */
162 unsigned long data_allocated; /* used for realloc() handling */
163 int sh_name; /* elf section name (only used during output) */
164 int sh_num; /* elf section number */
165 int sh_type; /* elf section type */
166 int sh_flags; /* elf section flags */
167 int sh_info; /* elf section info */
168 int sh_addralign; /* elf section alignment */
169 int sh_entsize; /* elf entry size */
170 unsigned long sh_size; /* section size (only used during output) */
171 unsigned long sh_addr; /* address at which the section is relocated */
172 unsigned long sh_offset; /* address at which the section is relocated */
173 int nb_hashed_syms; /* used to resize the hash table */
174 struct Section *link; /* link to another section */
175 struct Section *reloc; /* corresponding section for relocation, if any */
176 struct Section *hash; /* hash table for symbols */
177 struct Section *next;
178 char name[64]; /* section name */
179 } Section;
181 typedef struct DLLReference {
182 int level;
183 char name[1];
184 } DLLReference;
186 /* GNUC attribute definition */
187 typedef struct AttributeDef {
188 int aligned;
189 Section *section;
190 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
191 } AttributeDef;
193 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
194 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
195 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
197 /* stored in 'Sym.c' field */
198 #define FUNC_NEW 1 /* ansi function prototype */
199 #define FUNC_OLD 2 /* old function prototype */
200 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
202 /* stored in 'Sym.r' field */
203 #define FUNC_CDECL 0 /* standard c call */
204 #define FUNC_STDCALL 1 /* pascal c call */
206 /* field 'Sym.t' for macros */
207 #define MACRO_OBJ 0 /* object like macro */
208 #define MACRO_FUNC 1 /* function like macro */
210 /* field 'Sym.r' for C labels */
211 #define LABEL_DEFINED 0 /* label is defined */
212 #define LABEL_FORWARD 1 /* label is forward defined */
213 #define LABEL_DECLARED 2 /* label is declared but never used */
215 /* type_decl() types */
216 #define TYPE_ABSTRACT 1 /* type without variable */
217 #define TYPE_DIRECT 2 /* type with variable */
219 #define IO_BUF_SIZE 8192
221 typedef struct BufferedFile {
222 uint8_t *buf_ptr;
223 uint8_t *buf_end;
224 int fd;
225 int line_num; /* current line number - here to simplify code */
226 int ifndef_macro; /* #ifndef macro / #endif search */
227 int ifndef_macro_saved; /* saved ifndef_macro */
228 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
229 char inc_type; /* type of include */
230 char inc_filename[512]; /* filename specified by the user */
231 char filename[1024]; /* current filename - here to simplify code */
232 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
233 } BufferedFile;
235 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
236 #define CH_EOF (-1) /* end of file */
238 /* parsing state (used to save parser state to reparse part of the
239 source several times) */
240 typedef struct ParseState {
241 int *macro_ptr;
242 int line_num;
243 int tok;
244 CValue tokc;
245 } ParseState;
247 /* used to record tokens */
248 typedef struct TokenString {
249 int *str;
250 int len;
251 int allocated_len;
252 int last_line_num;
253 } TokenString;
255 /* include file cache, used to find files faster and also to eliminate
256 inclusion if the include file is protected by #ifndef ... #endif */
257 typedef struct CachedInclude {
258 int ifndef_macro;
259 char type; /* '"' or '>' to give include type */
260 char filename[1]; /* path specified in #include */
261 } CachedInclude;
263 /* parser */
264 static struct BufferedFile *file;
265 static int ch, tok;
266 static CValue tokc;
267 static CString tokcstr; /* current parsed string, if any */
268 /* additional informations about token */
269 static int tok_flags;
270 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
271 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
272 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
274 static int *macro_ptr, *macro_ptr_allocated;
275 static int *unget_saved_macro_ptr;
276 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
277 static int unget_buffer_enabled;
278 static int parse_flags;
279 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
280 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
281 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
282 token. line feed is also
283 returned at eof */
285 static Section *text_section, *data_section, *bss_section; /* predefined sections */
286 static Section *cur_text_section; /* current section where function code is
287 generated */
288 /* bound check related sections */
289 static Section *bounds_section; /* contains global data bound description */
290 static Section *lbounds_section; /* contains local data bound description */
291 /* symbol sections */
292 static Section *symtab_section, *strtab_section;
294 /* debug sections */
295 static Section *stab_section, *stabstr_section;
297 /* loc : local variable index
298 ind : output code index
299 rsym: return symbol
300 anon_sym: anonymous symbol index
302 static int rsym, anon_sym, ind, loc;
303 /* expression generation modifiers */
304 static int const_wanted; /* true if constant wanted */
305 static int nocode_wanted; /* true if no code generation wanted for an expression */
306 static int global_expr; /* true if compound literals must be allocated
307 globally (used during initializers parsing */
308 static CType func_vt; /* current function return type (used by return
309 instruction) */
310 static int func_vc;
311 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
312 static int tok_ident;
313 static TokenSym **table_ident;
314 static TokenSym *hash_ident[TOK_HASH_SIZE];
315 static char token_buf[STRING_MAX_SIZE + 1];
316 static char *funcname;
317 static Sym *global_stack, *local_stack;
318 static Sym *define_stack;
319 static Sym *global_label_stack, *local_label_stack;
321 static SValue vstack[VSTACK_SIZE], *vtop;
322 /* some predefined types */
323 static CType char_pointer_type, func_old_type, int_type;
324 /* true if isid(c) || isnum(c) */
325 static unsigned char isidnum_table[256];
327 /* compile with debug symbol (and use them if error during execution) */
328 static int do_debug = 0;
330 /* compile with built-in memory and bounds checker */
331 static int do_bounds_check = 0;
333 /* display benchmark infos */
334 #if !defined(LIBTCC)
335 static int do_bench = 0;
336 #endif
337 static int total_lines;
338 static int total_bytes;
340 /* use GNU C extensions */
341 static int gnu_ext = 1;
343 /* use Tiny C extensions */
344 static int tcc_ext = 1;
346 /* max number of callers shown if error */
347 static int num_callers = 6;
348 static const char **rt_bound_error_msg;
350 /* XXX: get rid of this ASAP */
351 static struct TCCState *tcc_state;
353 /* give the path of the tcc libraries */
354 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
356 struct TCCState {
357 int output_type;
359 BufferedFile **include_stack_ptr;
360 int *ifdef_stack_ptr;
362 /* include file handling */
363 char **include_paths;
364 int nb_include_paths;
365 char **sysinclude_paths;
366 int nb_sysinclude_paths;
367 CachedInclude **cached_includes;
368 int nb_cached_includes;
370 char **library_paths;
371 int nb_library_paths;
373 /* array of all loaded dlls (including those referenced by loaded
374 dlls) */
375 DLLReference **loaded_dlls;
376 int nb_loaded_dlls;
378 /* sections */
379 Section **sections;
380 int nb_sections; /* number of sections, including first dummy section */
382 /* got handling */
383 Section *got;
384 Section *plt;
385 unsigned long *got_offsets;
386 int nb_got_offsets;
387 /* give the correspondance from symtab indexes to dynsym indexes */
388 int *symtab_to_dynsym;
390 /* temporary dynamic symbol sections (for dll loading) */
391 Section *dynsymtab_section;
392 /* exported dynamic symbol section */
393 Section *dynsym;
395 int nostdinc; /* if true, no standard headers are added */
396 int nostdlib; /* if true, no standard libraries are added */
398 /* if true, static linking is performed */
399 int static_link;
401 /* if true, all symbols are exported */
402 int rdynamic;
404 /* if true, only link in referenced objects from archive */
405 int alacarte_link;
407 /* warning switches */
408 int warn_write_strings;
409 int warn_unsupported;
410 int warn_error;
412 /* error handling */
413 void *error_opaque;
414 void (*error_func)(void *opaque, const char *msg);
415 int error_set_jmp_enabled;
416 jmp_buf error_jmp_buf;
417 int nb_errors;
419 /* tiny assembler state */
420 Sym *asm_labels;
422 /* see include_stack_ptr */
423 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
425 /* see ifdef_stack_ptr */
426 int ifdef_stack[IFDEF_STACK_SIZE];
429 /* The current value can be: */
430 #define VT_VALMASK 0x00ff
431 #define VT_CONST 0x00f0 /* constant in vc
432 (must be first non register value) */
433 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
434 #define VT_LOCAL 0x00f2 /* offset on stack */
435 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
436 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
437 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
438 #define VT_LVAL 0x0100 /* var is an lvalue */
439 #define VT_SYM 0x0200 /* a symbol value is added */
440 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
441 char/short stored in integer registers) */
442 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
443 dereferencing value */
444 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
445 bounding function call point is in vc */
446 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
447 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
448 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
449 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
451 /* types */
452 #define VT_INT 0 /* integer type */
453 #define VT_BYTE 1 /* signed byte type */
454 #define VT_SHORT 2 /* short type */
455 #define VT_VOID 3 /* void type */
456 #define VT_PTR 4 /* pointer */
457 #define VT_ENUM 5 /* enum definition */
458 #define VT_FUNC 6 /* function type */
459 #define VT_STRUCT 7 /* struct/union definition */
460 #define VT_FLOAT 8 /* IEEE float */
461 #define VT_DOUBLE 9 /* IEEE double */
462 #define VT_LDOUBLE 10 /* IEEE long double */
463 #define VT_BOOL 11 /* ISOC99 boolean type */
464 #define VT_LLONG 12 /* 64 bit integer */
465 #define VT_LONG 13 /* long integer (NEVER USED as type, only
466 during parsing) */
467 #define VT_BTYPE 0x000f /* mask for basic type */
468 #define VT_UNSIGNED 0x0010 /* unsigned type */
469 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
470 #define VT_BITFIELD 0x0040 /* bitfield modifier */
471 #define VT_CONSTANT 0x0800 /* const modifier */
472 #define VT_VOLATILE 0x1000 /* volatile modifier */
474 /* storage */
475 #define VT_EXTERN 0x00000080 /* extern definition */
476 #define VT_STATIC 0x00000100 /* static variable */
477 #define VT_TYPEDEF 0x00000200 /* typedef definition */
478 #define VT_INLINE 0x00000400 /* inline definition */
480 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
482 /* type mask (except storage) */
483 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
484 #define VT_TYPE (~(VT_STORAGE))
486 /* token values */
488 /* warning: the following compare tokens depend on i386 asm code */
489 #define TOK_ULT 0x92
490 #define TOK_UGE 0x93
491 #define TOK_EQ 0x94
492 #define TOK_NE 0x95
493 #define TOK_ULE 0x96
494 #define TOK_UGT 0x97
495 #define TOK_LT 0x9c
496 #define TOK_GE 0x9d
497 #define TOK_LE 0x9e
498 #define TOK_GT 0x9f
500 #define TOK_LAND 0xa0
501 #define TOK_LOR 0xa1
503 #define TOK_DEC 0xa2
504 #define TOK_MID 0xa3 /* inc/dec, to void constant */
505 #define TOK_INC 0xa4
506 #define TOK_UDIV 0xb0 /* unsigned division */
507 #define TOK_UMOD 0xb1 /* unsigned modulo */
508 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
509 #define TOK_CINT 0xb3 /* number in tokc */
510 #define TOK_CCHAR 0xb4 /* char constant in tokc */
511 #define TOK_STR 0xb5 /* pointer to string in tokc */
512 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
513 #define TOK_LCHAR 0xb7
514 #define TOK_LSTR 0xb8
515 #define TOK_CFLOAT 0xb9 /* float constant */
516 #define TOK_LINENUM 0xba /* line number info */
517 #define TOK_CDOUBLE 0xc0 /* double constant */
518 #define TOK_CLDOUBLE 0xc1 /* long double constant */
519 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
520 #define TOK_ADDC1 0xc3 /* add with carry generation */
521 #define TOK_ADDC2 0xc4 /* add with carry use */
522 #define TOK_SUBC1 0xc5 /* add with carry generation */
523 #define TOK_SUBC2 0xc6 /* add with carry use */
524 #define TOK_CUINT 0xc8 /* unsigned int constant */
525 #define TOK_CLLONG 0xc9 /* long long constant */
526 #define TOK_CULLONG 0xca /* unsigned long long constant */
527 #define TOK_ARROW 0xcb
528 #define TOK_DOTS 0xcc /* three dots */
529 #define TOK_SHR 0xcd /* unsigned shift right */
530 #define TOK_PPNUM 0xce /* preprocessor number */
532 #define TOK_SHL 0x01 /* shift left */
533 #define TOK_SAR 0x02 /* signed shift right */
535 /* assignement operators : normal operator or 0x80 */
536 #define TOK_A_MOD 0xa5
537 #define TOK_A_AND 0xa6
538 #define TOK_A_MUL 0xaa
539 #define TOK_A_ADD 0xab
540 #define TOK_A_SUB 0xad
541 #define TOK_A_DIV 0xaf
542 #define TOK_A_XOR 0xde
543 #define TOK_A_OR 0xfc
544 #define TOK_A_SHL 0x81
545 #define TOK_A_SAR 0x82
547 #ifndef offsetof
548 #define offsetof(type, field) ((size_t) &((type *)0)->field)
549 #endif
551 #ifndef countof
552 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
553 #endif
555 /* WARNING: the content of this string encodes token numbers */
556 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";
558 #define TOK_EOF (-1) /* end of file */
559 #define TOK_LINEFEED 10 /* line feed */
561 /* all identificators and strings have token above that */
562 #define TOK_IDENT 256
564 /* only used for i386 asm opcodes definitions */
565 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
567 #define DEF_BWL(x) \
568 DEF(TOK_ASM_ ## x ## b, #x "b") \
569 DEF(TOK_ASM_ ## x ## w, #x "w") \
570 DEF(TOK_ASM_ ## x ## l, #x "l") \
571 DEF(TOK_ASM_ ## x, #x)
573 #define DEF_WL(x) \
574 DEF(TOK_ASM_ ## x ## w, #x "w") \
575 DEF(TOK_ASM_ ## x ## l, #x "l") \
576 DEF(TOK_ASM_ ## x, #x)
578 #define DEF_FP1(x) \
579 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
580 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
581 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
582 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
584 #define DEF_FP(x) \
585 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
586 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
587 DEF_FP1(x)
589 #define DEF_ASMTEST(x) \
590 DEF_ASM(x ## o) \
591 DEF_ASM(x ## no) \
592 DEF_ASM(x ## b) \
593 DEF_ASM(x ## c) \
594 DEF_ASM(x ## nae) \
595 DEF_ASM(x ## nb) \
596 DEF_ASM(x ## nc) \
597 DEF_ASM(x ## ae) \
598 DEF_ASM(x ## e) \
599 DEF_ASM(x ## z) \
600 DEF_ASM(x ## ne) \
601 DEF_ASM(x ## nz) \
602 DEF_ASM(x ## be) \
603 DEF_ASM(x ## na) \
604 DEF_ASM(x ## nbe) \
605 DEF_ASM(x ## a) \
606 DEF_ASM(x ## s) \
607 DEF_ASM(x ## ns) \
608 DEF_ASM(x ## p) \
609 DEF_ASM(x ## pe) \
610 DEF_ASM(x ## np) \
611 DEF_ASM(x ## po) \
612 DEF_ASM(x ## l) \
613 DEF_ASM(x ## nge) \
614 DEF_ASM(x ## nl) \
615 DEF_ASM(x ## ge) \
616 DEF_ASM(x ## le) \
617 DEF_ASM(x ## ng) \
618 DEF_ASM(x ## nle) \
619 DEF_ASM(x ## g)
621 #define TOK_ASM_int TOK_INT
623 enum {
624 TOK_LAST = TOK_IDENT - 1,
625 #define DEF(id, str) id,
626 #include "tcctok.h"
627 #undef DEF
630 static const char tcc_keywords[] =
631 #define DEF(id, str) str "\0"
632 #include "tcctok.h"
633 #undef DEF
636 #define TOK_UIDENT TOK_DEFINE
638 #ifdef WIN32
639 #define snprintf _snprintf
640 #define vsnprintf _vsnprintf
641 #endif
643 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
644 /* currently incorrect */
645 long double strtold(const char *nptr, char **endptr)
647 return (long double)strtod(nptr, endptr);
649 float strtof(const char *nptr, char **endptr)
651 return (float)strtod(nptr, endptr);
653 #else
654 /* XXX: need to define this to use them in non ISOC99 context */
655 extern float strtof (const char *__nptr, char **__endptr);
656 extern long double strtold (const char *__nptr, char **__endptr);
657 #endif
659 static char *pstrcpy(char *buf, int buf_size, const char *s);
660 static char *pstrcat(char *buf, int buf_size, const char *s);
662 static void next(void);
663 static void next_nomacro(void);
664 static void parse_expr_type(CType *type);
665 static void expr_type(CType *type);
666 static void unary_type(CType *type);
667 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
668 int case_reg, int is_expr);
669 static int expr_const(void);
670 static void expr_eq(void);
671 static void gexpr(void);
672 static void decl(int l);
673 static void decl_initializer(CType *type, Section *sec, unsigned long c,
674 int first, int size_only);
675 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
676 int has_init, int v, int scope);
677 int gv(int rc);
678 void gv2(int rc1, int rc2);
679 void move_reg(int r, int s);
680 void save_regs(int n);
681 void save_reg(int r);
682 void vpop(void);
683 void vswap(void);
684 void vdup(void);
685 int get_reg(int rc);
687 static void macro_subst(TokenString *tok_str, Sym **nested_list,
688 const int *macro_str, int can_read_stream);
689 int save_reg_forced(int r);
690 void gen_op(int op);
691 void force_charshort_cast(int t);
692 static void gen_cast(CType *type);
693 void vstore(void);
694 static Sym *sym_find(int v);
695 static Sym *sym_push(int v, CType *type, int r, int c);
697 /* type handling */
698 static int type_size(CType *type, int *a);
699 static inline CType *pointed_type(CType *type);
700 static int pointed_size(CType *type);
701 static int lvalue_type(int t);
702 static int parse_btype(CType *type, AttributeDef *ad);
703 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
704 static int is_compatible_types(CType *type1, CType *type2);
706 void error(const char *fmt, ...);
707 void vpushi(int v);
708 void vset(CType *type, int r, int v);
709 void type_to_str(char *buf, int buf_size,
710 CType *type, const char *varstr);
711 char *get_tok_str(int v, CValue *cv);
712 static Sym *get_sym_ref(CType *type, Section *sec,
713 unsigned long offset, unsigned long size);
714 static Sym *external_global_sym(int v, CType *type, int r);
716 /* section generation */
717 static void section_realloc(Section *sec, unsigned long new_size);
718 static void *section_ptr_add(Section *sec, unsigned long size);
719 static void put_extern_sym(Sym *sym, Section *section,
720 unsigned long value, unsigned long size);
721 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
722 static int put_elf_str(Section *s, const char *sym);
723 static int put_elf_sym(Section *s,
724 unsigned long value, unsigned long size,
725 int info, int other, int shndx, const char *name);
726 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
727 int info, int sh_num, const char *name);
728 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
729 int type, int symbol);
730 static void put_stabs(const char *str, int type, int other, int desc,
731 unsigned long value);
732 static void put_stabs_r(const char *str, int type, int other, int desc,
733 unsigned long value, Section *sec, int sym_index);
734 static void put_stabn(int type, int other, int desc, int value);
735 static void put_stabd(int type, int other, int desc);
736 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
738 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
739 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
740 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
742 /* tccasm.c */
744 #ifdef CONFIG_TCC_ASM
746 typedef struct ExprValue {
747 uint32_t v;
748 Sym *sym;
749 } ExprValue;
751 #define MAX_ASM_OPERANDS 30
753 typedef struct ASMOperand {
754 int id; /* GCC 3 optionnal identifier (0 if number only supported */
755 char *constraint;
756 char asm_str[16]; /* computed asm string for operand */
757 SValue *vt; /* C value of the expression */
758 int ref_index; /* if >= 0, gives reference to a output constraint */
759 int priority; /* priority, used to assign registers */
760 int reg; /* if >= 0, register number used for this operand */
761 int is_llong; /* true if double register value */
762 } ASMOperand;
764 static void asm_expr(TCCState *s1, ExprValue *pe);
765 static int asm_int_expr(TCCState *s1);
766 static int find_constraint(ASMOperand *operands, int nb_operands,
767 const char *name, const char **pp);
769 static int tcc_assemble(TCCState *s1, int do_preprocess);
771 #endif
773 static void asm_instr(void);
775 /* true if float/double/long double type */
776 static inline int is_float(int t)
778 int bt;
779 bt = t & VT_BTYPE;
780 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
783 #ifdef TCC_TARGET_I386
784 #include "i386-gen.c"
785 #endif
787 #ifdef CONFIG_TCC_STATIC
789 #define RTLD_LAZY 0x001
790 #define RTLD_NOW 0x002
791 #define RTLD_GLOBAL 0x100
792 #define RTLD_DEFAULT NULL
794 /* dummy function for profiling */
795 void *dlopen(const char *filename, int flag)
797 return NULL;
800 const char *dlerror(void)
802 return "error";
805 typedef struct TCCSyms {
806 char *str;
807 void *ptr;
808 } TCCSyms;
810 #define TCCSYM(a) { #a, &a, },
812 /* add the symbol you want here if no dynamic linking is done */
813 static TCCSyms tcc_syms[] = {
814 TCCSYM(printf)
815 TCCSYM(fprintf)
816 TCCSYM(fopen)
817 TCCSYM(fclose)
818 { NULL, NULL },
821 void *dlsym(void *handle, const char *symbol)
823 TCCSyms *p;
824 p = tcc_syms;
825 while (p->str != NULL) {
826 if (!strcmp(p->str, symbol))
827 return p->ptr;
828 p++;
830 return NULL;
833 #endif
835 /********************************************************/
837 /* we use our own 'finite' function to avoid potential problems with
838 non standard math libs */
839 /* XXX: endianness dependent */
840 int ieee_finite(double d)
842 int *p = (int *)&d;
843 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
846 /* copy a string and truncate it. */
847 static char *pstrcpy(char *buf, int buf_size, const char *s)
849 char *q, *q_end;
850 int c;
852 if (buf_size > 0) {
853 q = buf;
854 q_end = buf + buf_size - 1;
855 while (q < q_end) {
856 c = *s++;
857 if (c == '\0')
858 break;
859 *q++ = c;
861 *q = '\0';
863 return buf;
866 /* strcat and truncate. */
867 static char *pstrcat(char *buf, int buf_size, const char *s)
869 int len;
870 len = strlen(buf);
871 if (len < buf_size)
872 pstrcpy(buf + len, buf_size - len, s);
873 return buf;
876 /* memory management */
877 #ifdef MEM_DEBUG
878 int mem_cur_size;
879 int mem_max_size;
880 #endif
882 static inline void tcc_free(void *ptr)
884 #ifdef MEM_DEBUG
885 mem_cur_size -= malloc_usable_size(ptr);
886 #endif
887 free(ptr);
890 static void *tcc_malloc(unsigned long size)
892 void *ptr;
893 ptr = malloc(size);
894 if (!ptr && size)
895 error("memory full");
896 #ifdef MEM_DEBUG
897 mem_cur_size += malloc_usable_size(ptr);
898 if (mem_cur_size > mem_max_size)
899 mem_max_size = mem_cur_size;
900 #endif
901 return ptr;
904 static void *tcc_mallocz(unsigned long size)
906 void *ptr;
907 ptr = tcc_malloc(size);
908 memset(ptr, 0, size);
909 return ptr;
912 static inline void *tcc_realloc(void *ptr, unsigned long size)
914 void *ptr1;
915 #ifdef MEM_DEBUG
916 mem_cur_size -= malloc_usable_size(ptr);
917 #endif
918 ptr1 = realloc(ptr, size);
919 #ifdef MEM_DEBUG
920 /* NOTE: count not correct if alloc error, but not critical */
921 mem_cur_size += malloc_usable_size(ptr1);
922 if (mem_cur_size > mem_max_size)
923 mem_max_size = mem_cur_size;
924 #endif
925 return ptr1;
928 static char *tcc_strdup(const char *str)
930 char *ptr;
931 ptr = tcc_malloc(strlen(str) + 1);
932 strcpy(ptr, str);
933 return ptr;
936 #define free(p) use_tcc_free(p)
937 #define malloc(s) use_tcc_malloc(s)
938 #define realloc(p, s) use_tcc_realloc(p, s)
940 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
942 int nb, nb_alloc;
943 void **pp;
945 nb = *nb_ptr;
946 pp = *ptab;
947 /* every power of two we double array size */
948 if ((nb & (nb - 1)) == 0) {
949 if (!nb)
950 nb_alloc = 1;
951 else
952 nb_alloc = nb * 2;
953 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
954 if (!pp)
955 error("memory full");
956 *ptab = pp;
958 pp[nb++] = data;
959 *nb_ptr = nb;
962 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
964 Section *sec;
966 sec = tcc_mallocz(sizeof(Section));
967 pstrcpy(sec->name, sizeof(sec->name), name);
968 sec->sh_type = sh_type;
969 sec->sh_flags = sh_flags;
970 switch(sh_type) {
971 case SHT_HASH:
972 case SHT_REL:
973 case SHT_DYNSYM:
974 case SHT_SYMTAB:
975 case SHT_DYNAMIC:
976 sec->sh_addralign = 4;
977 break;
978 case SHT_STRTAB:
979 sec->sh_addralign = 1;
980 break;
981 default:
982 sec->sh_addralign = 32; /* default conservative alignment */
983 break;
986 /* only add section if not private */
987 if (!(sh_flags & SHF_PRIVATE)) {
988 sec->sh_num = s1->nb_sections;
989 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
991 return sec;
994 static void free_section(Section *s)
996 tcc_free(s->data);
997 tcc_free(s);
1000 /* realloc section and set its content to zero */
1001 static void section_realloc(Section *sec, unsigned long new_size)
1003 unsigned long size;
1004 unsigned char *data;
1006 size = sec->data_allocated;
1007 if (size == 0)
1008 size = 1;
1009 while (size < new_size)
1010 size = size * 2;
1011 data = tcc_realloc(sec->data, size);
1012 if (!data)
1013 error("memory full");
1014 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1015 sec->data = data;
1016 sec->data_allocated = size;
1019 /* reserve at least 'size' bytes in section 'sec' from
1020 sec->data_offset. */
1021 static void *section_ptr_add(Section *sec, unsigned long size)
1023 unsigned long offset, offset1;
1025 offset = sec->data_offset;
1026 offset1 = offset + size;
1027 if (offset1 > sec->data_allocated)
1028 section_realloc(sec, offset1);
1029 sec->data_offset = offset1;
1030 return sec->data + offset;
1033 /* return a reference to a section, and create it if it does not
1034 exists */
1035 Section *find_section(TCCState *s1, const char *name)
1037 Section *sec;
1038 int i;
1039 for(i = 1; i < s1->nb_sections; i++) {
1040 sec = s1->sections[i];
1041 if (!strcmp(name, sec->name))
1042 return sec;
1044 /* sections are created as PROGBITS */
1045 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1048 /* update sym->c so that it points to an external symbol in section
1049 'section' with value 'value' */
1050 static void put_extern_sym(Sym *sym, Section *section,
1051 unsigned long value, unsigned long size)
1053 int sym_type, sym_bind, sh_num, info;
1054 Elf32_Sym *esym;
1055 const char *name;
1057 if (section)
1058 sh_num = section->sh_num;
1059 else
1060 sh_num = SHN_UNDEF;
1061 if (!sym->c) {
1062 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1063 sym_type = STT_FUNC;
1064 else
1065 sym_type = STT_OBJECT;
1066 if (sym->type.t & VT_STATIC)
1067 sym_bind = STB_LOCAL;
1068 else
1069 sym_bind = STB_GLOBAL;
1071 name = get_tok_str(sym->v, NULL);
1072 #ifdef CONFIG_TCC_BCHECK
1073 if (do_bounds_check) {
1074 char buf[32];
1076 /* XXX: avoid doing that for statics ? */
1077 /* if bound checking is activated, we change some function
1078 names by adding the "__bound" prefix */
1079 switch(sym->v) {
1080 #if 0
1081 /* XXX: we rely only on malloc hooks */
1082 case TOK_malloc:
1083 case TOK_free:
1084 case TOK_realloc:
1085 case TOK_memalign:
1086 case TOK_calloc:
1087 #endif
1088 case TOK_memcpy:
1089 case TOK_memmove:
1090 case TOK_memset:
1091 case TOK_strlen:
1092 case TOK_strcpy:
1093 strcpy(buf, "__bound_");
1094 strcat(buf, name);
1095 name = buf;
1096 break;
1099 #endif
1100 info = ELF32_ST_INFO(sym_bind, sym_type);
1101 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1102 } else {
1103 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1104 esym->st_value = value;
1105 esym->st_size = size;
1106 esym->st_shndx = sh_num;
1110 /* add a new relocation entry to symbol 'sym' in section 's' */
1111 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1113 if (!sym->c)
1114 put_extern_sym(sym, NULL, 0, 0);
1115 /* now we can add ELF relocation info */
1116 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1119 static inline int isid(int c)
1121 return (c >= 'a' && c <= 'z') ||
1122 (c >= 'A' && c <= 'Z') ||
1123 c == '_';
1126 static inline int isnum(int c)
1128 return c >= '0' && c <= '9';
1131 static inline int isoct(int c)
1133 return c >= '0' && c <= '7';
1136 static inline int toup(int c)
1138 if (c >= 'a' && c <= 'z')
1139 return c - 'a' + 'A';
1140 else
1141 return c;
1144 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1146 int len;
1147 len = strlen(buf);
1148 vsnprintf(buf + len, buf_size - len, fmt, ap);
1151 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1153 va_list ap;
1154 va_start(ap, fmt);
1155 strcat_vprintf(buf, buf_size, fmt, ap);
1156 va_end(ap);
1159 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1161 char buf[2048];
1162 BufferedFile **f;
1164 buf[0] = '\0';
1165 if (file) {
1166 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1167 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1168 (*f)->filename, (*f)->line_num);
1169 if (file->line_num > 0) {
1170 strcat_printf(buf, sizeof(buf),
1171 "%s:%d: ", file->filename, file->line_num);
1172 } else {
1173 strcat_printf(buf, sizeof(buf),
1174 "%s: ", file->filename);
1176 } else {
1177 strcat_printf(buf, sizeof(buf),
1178 "tcc: ");
1180 if (is_warning)
1181 strcat_printf(buf, sizeof(buf), "warning: ");
1182 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1184 if (!s1->error_func) {
1185 /* default case: stderr */
1186 fprintf(stderr, "%s\n", buf);
1187 } else {
1188 s1->error_func(s1->error_opaque, buf);
1190 if (!is_warning || s1->warn_error)
1191 s1->nb_errors++;
1194 #ifdef LIBTCC
1195 void tcc_set_error_func(TCCState *s, void *error_opaque,
1196 void (*error_func)(void *opaque, const char *msg))
1198 s->error_opaque = error_opaque;
1199 s->error_func = error_func;
1201 #endif
1203 /* error without aborting current compilation */
1204 void error_noabort(const char *fmt, ...)
1206 TCCState *s1 = tcc_state;
1207 va_list ap;
1209 va_start(ap, fmt);
1210 error1(s1, 0, fmt, ap);
1211 va_end(ap);
1214 void error(const char *fmt, ...)
1216 TCCState *s1 = tcc_state;
1217 va_list ap;
1219 va_start(ap, fmt);
1220 error1(s1, 0, fmt, ap);
1221 va_end(ap);
1222 /* better than nothing: in some cases, we accept to handle errors */
1223 if (s1->error_set_jmp_enabled) {
1224 longjmp(s1->error_jmp_buf, 1);
1225 } else {
1226 /* XXX: eliminate this someday */
1227 exit(1);
1231 void expect(const char *msg)
1233 error("%s expected", msg);
1236 void warning(const char *fmt, ...)
1238 TCCState *s1 = tcc_state;
1239 va_list ap;
1241 va_start(ap, fmt);
1242 error1(s1, 1, fmt, ap);
1243 va_end(ap);
1246 void skip(int c)
1248 if (tok != c)
1249 error("'%c' expected", c);
1250 next();
1253 static void test_lvalue(void)
1255 if (!(vtop->r & VT_LVAL))
1256 expect("lvalue");
1259 /* allocate a new token */
1260 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1262 TokenSym *ts, **ptable;
1263 int i;
1265 if (tok_ident >= SYM_FIRST_ANOM)
1266 error("memory full");
1268 /* expand token table if needed */
1269 i = tok_ident - TOK_IDENT;
1270 if ((i % TOK_ALLOC_INCR) == 0) {
1271 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1272 if (!ptable)
1273 error("memory full");
1274 table_ident = ptable;
1277 ts = tcc_malloc(sizeof(TokenSym) + len);
1278 table_ident[i] = ts;
1279 ts->tok = tok_ident++;
1280 ts->sym_define = NULL;
1281 ts->sym_label = NULL;
1282 ts->sym_struct = NULL;
1283 ts->sym_identifier = NULL;
1284 ts->len = len;
1285 ts->hash_next = NULL;
1286 memcpy(ts->str, str, len);
1287 ts->str[len] = '\0';
1288 *pts = ts;
1289 return ts;
1292 #define TOK_HASH_INIT 1
1293 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1295 /* find a token and add it if not found */
1296 static TokenSym *tok_alloc(const char *str, int len)
1298 TokenSym *ts, **pts;
1299 int i;
1300 unsigned int h;
1302 h = TOK_HASH_INIT;
1303 for(i=0;i<len;i++)
1304 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1305 h &= (TOK_HASH_SIZE - 1);
1307 pts = &hash_ident[h];
1308 for(;;) {
1309 ts = *pts;
1310 if (!ts)
1311 break;
1312 if (ts->len == len && !memcmp(ts->str, str, len))
1313 return ts;
1314 pts = &(ts->hash_next);
1316 return tok_alloc_new(pts, str, len);
1319 /* CString handling */
1321 static void cstr_realloc(CString *cstr, int new_size)
1323 int size;
1324 void *data;
1326 size = cstr->size_allocated;
1327 if (size == 0)
1328 size = 8; /* no need to allocate a too small first string */
1329 while (size < new_size)
1330 size = size * 2;
1331 data = tcc_realloc(cstr->data_allocated, size);
1332 if (!data)
1333 error("memory full");
1334 cstr->data_allocated = data;
1335 cstr->size_allocated = size;
1336 cstr->data = data;
1339 /* add a byte */
1340 static void cstr_ccat(CString *cstr, int ch)
1342 int size;
1343 size = cstr->size + 1;
1344 if (size > cstr->size_allocated)
1345 cstr_realloc(cstr, size);
1346 ((unsigned char *)cstr->data)[size - 1] = ch;
1347 cstr->size = size;
1350 static void cstr_cat(CString *cstr, const char *str)
1352 int c;
1353 for(;;) {
1354 c = *str;
1355 if (c == '\0')
1356 break;
1357 cstr_ccat(cstr, c);
1358 str++;
1362 /* add a wide char */
1363 static void cstr_wccat(CString *cstr, int ch)
1365 int size;
1366 size = cstr->size + sizeof(int);
1367 if (size > cstr->size_allocated)
1368 cstr_realloc(cstr, size);
1369 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1370 cstr->size = size;
1373 static void cstr_new(CString *cstr)
1375 memset(cstr, 0, sizeof(CString));
1378 /* free string and reset it to NULL */
1379 static void cstr_free(CString *cstr)
1381 tcc_free(cstr->data_allocated);
1382 cstr_new(cstr);
1385 #define cstr_reset(cstr) cstr_free(cstr)
1387 static CString *cstr_dup(CString *cstr1)
1389 CString *cstr;
1390 int size;
1392 cstr = tcc_malloc(sizeof(CString));
1393 size = cstr1->size;
1394 cstr->size = size;
1395 cstr->size_allocated = size;
1396 cstr->data_allocated = tcc_malloc(size);
1397 cstr->data = cstr->data_allocated;
1398 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1399 return cstr;
1402 /* XXX: unicode ? */
1403 static void add_char(CString *cstr, int c)
1405 if (c == '\'' || c == '\"' || c == '\\') {
1406 /* XXX: could be more precise if char or string */
1407 cstr_ccat(cstr, '\\');
1409 if (c >= 32 && c <= 126) {
1410 cstr_ccat(cstr, c);
1411 } else {
1412 cstr_ccat(cstr, '\\');
1413 if (c == '\n') {
1414 cstr_ccat(cstr, 'n');
1415 } else {
1416 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1417 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1418 cstr_ccat(cstr, '0' + (c & 7));
1423 /* XXX: buffer overflow */
1424 /* XXX: float tokens */
1425 char *get_tok_str(int v, CValue *cv)
1427 static char buf[STRING_MAX_SIZE + 1];
1428 static CString cstr_buf;
1429 CString *cstr;
1430 unsigned char *q;
1431 char *p;
1432 int i, len;
1434 /* NOTE: to go faster, we give a fixed buffer for small strings */
1435 cstr_reset(&cstr_buf);
1436 cstr_buf.data = buf;
1437 cstr_buf.size_allocated = sizeof(buf);
1438 p = buf;
1440 switch(v) {
1441 case TOK_CINT:
1442 case TOK_CUINT:
1443 /* XXX: not quite exact, but only useful for testing */
1444 sprintf(p, "%u", cv->ui);
1445 break;
1446 case TOK_CLLONG:
1447 case TOK_CULLONG:
1448 /* XXX: not quite exact, but only useful for testing */
1449 sprintf(p, "%Lu", cv->ull);
1450 break;
1451 case TOK_CCHAR:
1452 case TOK_LCHAR:
1453 cstr_ccat(&cstr_buf, '\'');
1454 add_char(&cstr_buf, cv->i);
1455 cstr_ccat(&cstr_buf, '\'');
1456 cstr_ccat(&cstr_buf, '\0');
1457 break;
1458 case TOK_PPNUM:
1459 cstr = cv->cstr;
1460 len = cstr->size - 1;
1461 for(i=0;i<len;i++)
1462 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1463 cstr_ccat(&cstr_buf, '\0');
1464 break;
1465 case TOK_STR:
1466 case TOK_LSTR:
1467 cstr = cv->cstr;
1468 cstr_ccat(&cstr_buf, '\"');
1469 if (v == TOK_STR) {
1470 len = cstr->size - 1;
1471 for(i=0;i<len;i++)
1472 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1473 } else {
1474 len = (cstr->size / sizeof(int)) - 1;
1475 for(i=0;i<len;i++)
1476 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1478 cstr_ccat(&cstr_buf, '\"');
1479 cstr_ccat(&cstr_buf, '\0');
1480 break;
1481 case TOK_LT:
1482 v = '<';
1483 goto addv;
1484 case TOK_GT:
1485 v = '>';
1486 goto addv;
1487 case TOK_A_SHL:
1488 return strcpy(p, "<<=");
1489 case TOK_A_SAR:
1490 return strcpy(p, ">>=");
1491 default:
1492 if (v < TOK_IDENT) {
1493 /* search in two bytes table */
1494 q = tok_two_chars;
1495 while (*q) {
1496 if (q[2] == v) {
1497 *p++ = q[0];
1498 *p++ = q[1];
1499 *p = '\0';
1500 return buf;
1502 q += 3;
1504 addv:
1505 *p++ = v;
1506 *p = '\0';
1507 } else if (v < tok_ident) {
1508 return table_ident[v - TOK_IDENT]->str;
1509 } else if (v >= SYM_FIRST_ANOM) {
1510 /* special name for anonymous symbol */
1511 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1512 } else {
1513 /* should never happen */
1514 return NULL;
1516 break;
1518 return cstr_buf.data;
1521 /* push, without hashing */
1522 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1524 Sym *s;
1525 s = tcc_malloc(sizeof(Sym));
1526 s->v = v;
1527 s->type.t = t;
1528 s->c = c;
1529 s->next = NULL;
1530 /* add in stack */
1531 s->prev = *ps;
1532 *ps = s;
1533 return s;
1536 /* find a symbol and return its associated structure. 's' is the top
1537 of the symbol stack */
1538 static Sym *sym_find2(Sym *s, int v)
1540 while (s) {
1541 if (s->v == v)
1542 return s;
1543 s = s->prev;
1545 return NULL;
1548 /* structure lookup */
1549 static inline Sym *struct_find(int v)
1551 v -= TOK_IDENT;
1552 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1553 return NULL;
1554 return table_ident[v]->sym_struct;
1557 /* find an identifier */
1558 static inline Sym *sym_find(int v)
1560 v -= TOK_IDENT;
1561 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1562 return NULL;
1563 return table_ident[v]->sym_identifier;
1566 /* push a given symbol on the symbol stack */
1567 static Sym *sym_push(int v, CType *type, int r, int c)
1569 Sym *s, **ps;
1570 TokenSym *ts;
1572 if (local_stack)
1573 ps = &local_stack;
1574 else
1575 ps = &global_stack;
1576 s = sym_push2(ps, v, type->t, c);
1577 s->type.ref = type->ref;
1578 s->r = r;
1579 /* don't record fields or anonymous symbols */
1580 /* XXX: simplify */
1581 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1582 /* record symbol in token array */
1583 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1584 if (v & SYM_STRUCT)
1585 ps = &ts->sym_struct;
1586 else
1587 ps = &ts->sym_identifier;
1588 s->prev_tok = *ps;
1589 *ps = s;
1591 return s;
1594 /* push a global identifier */
1595 static Sym *global_identifier_push(int v, int t, int c)
1597 Sym *s, **ps;
1598 s = sym_push2(&global_stack, v, t, c);
1599 /* don't record anonymous symbol */
1600 if (v < SYM_FIRST_ANOM) {
1601 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1602 /* modify the top most local identifier, so that
1603 sym_identifier will point to 's' when popped */
1604 while (*ps != NULL)
1605 ps = &(*ps)->prev_tok;
1606 s->prev_tok = NULL;
1607 *ps = s;
1609 return s;
1612 /* pop symbols until top reaches 'b' */
1613 static void sym_pop(Sym **ptop, Sym *b)
1615 Sym *s, *ss, **ps;
1616 TokenSym *ts;
1617 int v;
1619 s = *ptop;
1620 while(s != b) {
1621 ss = s->prev;
1622 v = s->v;
1623 /* remove symbol in token array */
1624 /* XXX: simplify */
1625 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1626 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1627 if (v & SYM_STRUCT)
1628 ps = &ts->sym_struct;
1629 else
1630 ps = &ts->sym_identifier;
1631 *ps = s->prev_tok;
1633 tcc_free(s);
1634 s = ss;
1636 *ptop = b;
1639 /* I/O layer */
1641 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1643 int fd;
1644 BufferedFile *bf;
1646 fd = open(filename, O_RDONLY);
1647 if (fd < 0)
1648 return NULL;
1649 bf = tcc_malloc(sizeof(BufferedFile));
1650 if (!bf) {
1651 close(fd);
1652 return NULL;
1654 bf->fd = fd;
1655 bf->buf_ptr = bf->buffer;
1656 bf->buf_end = bf->buffer;
1657 bf->buffer[0] = CH_EOB; /* put eob symbol */
1658 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1659 bf->line_num = 1;
1660 bf->ifndef_macro = 0;
1661 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1662 // printf("opening '%s'\n", filename);
1663 return bf;
1666 void tcc_close(BufferedFile *bf)
1668 total_lines += bf->line_num;
1669 close(bf->fd);
1670 tcc_free(bf);
1673 /* fill input buffer and peek next char */
1674 static int tcc_peekc_slow(BufferedFile *bf)
1676 int len;
1677 /* only tries to read if really end of buffer */
1678 if (bf->buf_ptr >= bf->buf_end) {
1679 if (bf->fd != -1) {
1680 #if defined(PARSE_DEBUG)
1681 len = 8;
1682 #else
1683 len = IO_BUF_SIZE;
1684 #endif
1685 len = read(bf->fd, bf->buffer, len);
1686 if (len < 0)
1687 len = 0;
1688 } else {
1689 len = 0;
1691 total_bytes += len;
1692 bf->buf_ptr = bf->buffer;
1693 bf->buf_end = bf->buffer + len;
1694 *bf->buf_end = CH_EOB;
1696 if (bf->buf_ptr < bf->buf_end) {
1697 return bf->buf_ptr[0];
1698 } else {
1699 bf->buf_ptr = bf->buf_end;
1700 return CH_EOF;
1704 /* return the current character, handling end of block if necessary
1705 (but not stray) */
1706 static int handle_eob(void)
1708 return tcc_peekc_slow(file);
1711 /* read next char from current input file and handle end of input buffer */
1712 static inline void inp(void)
1714 ch = *(++(file->buf_ptr));
1715 /* end of buffer/file handling */
1716 if (ch == CH_EOB)
1717 ch = handle_eob();
1720 /* handle '\[\r]\n' */
1721 static void handle_stray(void)
1723 while (ch == '\\') {
1724 inp();
1725 if (ch == '\n') {
1726 file->line_num++;
1727 inp();
1728 } else if (ch == '\r') {
1729 inp();
1730 if (ch != '\n')
1731 goto fail;
1732 file->line_num++;
1733 inp();
1734 } else {
1735 fail:
1736 error("stray '\\' in program");
1741 /* skip the stray and handle the \\n case. Output an error if
1742 incorrect char after the stray */
1743 static int handle_stray1(uint8_t *p)
1745 int c;
1747 if (p >= file->buf_end) {
1748 file->buf_ptr = p;
1749 c = handle_eob();
1750 p = file->buf_ptr;
1751 if (c == '\\')
1752 goto parse_stray;
1753 } else {
1754 parse_stray:
1755 file->buf_ptr = p;
1756 ch = *p;
1757 handle_stray();
1758 p = file->buf_ptr;
1759 c = *p;
1761 return c;
1764 /* handle just the EOB case, but not stray */
1765 #define PEEKC_EOB(c, p)\
1767 p++;\
1768 c = *p;\
1769 if (c == '\\') {\
1770 file->buf_ptr = p;\
1771 c = handle_eob();\
1772 p = file->buf_ptr;\
1776 /* handle the complicated stray case */
1777 #define PEEKC(c, p)\
1779 p++;\
1780 c = *p;\
1781 if (c == '\\') {\
1782 c = handle_stray1(p);\
1783 p = file->buf_ptr;\
1787 /* input with '\[\r]\n' handling. Note that this function cannot
1788 handle other characters after '\', so you cannot call it inside
1789 strings or comments */
1790 static void minp(void)
1792 inp();
1793 if (ch == '\\')
1794 handle_stray();
1798 /* single line C++ comments */
1799 static uint8_t *parse_line_comment(uint8_t *p)
1801 int c;
1803 p++;
1804 for(;;) {
1805 c = *p;
1806 if (c == '\n' || c == CH_EOF) {
1807 break;
1808 } else if (c == '\\') {
1809 PEEKC_EOB(c, p);
1810 if (c == '\n') {
1811 file->line_num++;
1812 PEEKC_EOB(c, p);
1813 } else if (c == '\r') {
1814 PEEKC_EOB(c, p);
1815 if (c == '\n') {
1816 file->line_num++;
1817 PEEKC_EOB(c, p);
1820 } else {
1821 p++;
1824 return p;
1827 /* C comments */
1828 static uint8_t *parse_comment(uint8_t *p)
1830 int c;
1832 p++;
1833 for(;;) {
1834 /* fast skip loop */
1835 for(;;) {
1836 c = *p;
1837 if (c == '\n' || c == '*' || c == '\\')
1838 break;
1839 p++;
1840 c = *p;
1841 if (c == '\n' || c == '*' || c == '\\')
1842 break;
1843 p++;
1845 /* now we can handle all the cases */
1846 if (c == '\n') {
1847 file->line_num++;
1848 p++;
1849 } else if (c == '*') {
1850 p++;
1851 for(;;) {
1852 c = *p;
1853 if (c == '*') {
1854 p++;
1855 } else if (c == '/') {
1856 goto end_of_comment;
1857 } else if (c == '\\') {
1858 file->buf_ptr = p;
1859 c = handle_eob();
1860 p = file->buf_ptr;
1861 if (c == '\\') {
1862 /* skip '\[\r]\n', otherwise just skip the stray */
1863 while (c == '\\') {
1864 PEEKC_EOB(c, p);
1865 if (c == '\n') {
1866 file->line_num++;
1867 PEEKC_EOB(c, p);
1868 } else if (c == '\r') {
1869 PEEKC_EOB(c, p);
1870 if (c == '\n') {
1871 file->line_num++;
1872 PEEKC_EOB(c, p);
1874 } else {
1875 goto after_star;
1879 } else {
1880 break;
1883 after_star: ;
1884 } else {
1885 /* stray, eob or eof */
1886 file->buf_ptr = p;
1887 c = handle_eob();
1888 p = file->buf_ptr;
1889 if (c == CH_EOF) {
1890 error("unexpected end of file in comment");
1891 } else if (c == '\\') {
1892 p++;
1896 end_of_comment:
1897 p++;
1898 return p;
1901 #define cinp minp
1903 /* space exlcuding newline */
1904 static inline int is_space(int ch)
1906 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1909 static inline void skip_spaces(void)
1911 while (is_space(ch))
1912 cinp();
1915 /* parse a string without interpreting escapes */
1916 static uint8_t *parse_pp_string(uint8_t *p,
1917 int sep, CString *str)
1919 int c;
1920 p++;
1921 for(;;) {
1922 c = *p;
1923 if (c == sep) {
1924 break;
1925 } else if (c == '\\') {
1926 file->buf_ptr = p;
1927 c = handle_eob();
1928 p = file->buf_ptr;
1929 if (c == CH_EOF) {
1930 unterminated_string:
1931 /* XXX: indicate line number of start of string */
1932 error("missing terminating %c character", sep);
1933 } else if (c == '\\') {
1934 /* escape : just skip \[\r]\n */
1935 PEEKC_EOB(c, p);
1936 if (c == '\n') {
1937 file->line_num++;
1938 p++;
1939 } else if (c == '\r') {
1940 PEEKC_EOB(c, p);
1941 if (c != '\n')
1942 expect("'\n' after '\r'");
1943 file->line_num++;
1944 p++;
1945 } else if (c == CH_EOF) {
1946 goto unterminated_string;
1947 } else {
1948 if (str) {
1949 cstr_ccat(str, '\\');
1950 cstr_ccat(str, c);
1952 p++;
1955 } else if (c == '\n') {
1956 file->line_num++;
1957 goto add_char;
1958 } else if (c == '\r') {
1959 PEEKC_EOB(c, p);
1960 if (c != '\n') {
1961 cstr_ccat(str, '\r');
1962 } else {
1963 file->line_num++;
1964 goto add_char;
1966 } else {
1967 add_char:
1968 if (str)
1969 cstr_ccat(str, c);
1970 p++;
1973 p++;
1974 return p;
1977 /* skip block of text until #else, #elif or #endif. skip also pairs of
1978 #if/#endif */
1979 void preprocess_skip(void)
1981 int a, start_of_line, c;
1982 uint8_t *p;
1984 p = file->buf_ptr;
1985 start_of_line = 1;
1986 a = 0;
1987 for(;;) {
1988 redo_no_start:
1989 c = *p;
1990 switch(c) {
1991 case ' ':
1992 case '\t':
1993 case '\f':
1994 case '\v':
1995 case '\r':
1996 p++;
1997 goto redo_no_start;
1998 case '\n':
1999 start_of_line = 1;
2000 file->line_num++;
2001 p++;
2002 goto redo_no_start;
2003 case '\\':
2004 file->buf_ptr = p;
2005 c = handle_eob();
2006 if (c == CH_EOF) {
2007 expect("#endif");
2008 } else if (c == '\\') {
2009 /* XXX: incorrect: should not give an error */
2010 ch = file->buf_ptr[0];
2011 handle_stray();
2013 p = file->buf_ptr;
2014 goto redo_no_start;
2015 /* skip strings */
2016 case '\"':
2017 case '\'':
2018 p = parse_pp_string(p, c, NULL);
2019 break;
2020 /* skip comments */
2021 case '/':
2022 file->buf_ptr = p;
2023 ch = *p;
2024 minp();
2025 p = file->buf_ptr;
2026 if (ch == '*') {
2027 p = parse_comment(p);
2028 } else if (ch == '/') {
2029 p = parse_line_comment(p);
2031 break;
2033 case '#':
2034 p++;
2035 if (start_of_line) {
2036 file->buf_ptr = p;
2037 next_nomacro();
2038 p = file->buf_ptr;
2039 if (a == 0 &&
2040 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2041 goto the_end;
2042 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2043 a++;
2044 else if (tok == TOK_ENDIF)
2045 a--;
2047 break;
2048 default:
2049 p++;
2050 break;
2052 start_of_line = 0;
2054 the_end: ;
2055 file->buf_ptr = p;
2058 /* ParseState handling */
2060 /* XXX: currently, no include file info is stored. Thus, we cannot display
2061 accurate messages if the function or data definition spans multiple
2062 files */
2064 /* save current parse state in 's' */
2065 void save_parse_state(ParseState *s)
2067 s->line_num = file->line_num;
2068 s->macro_ptr = macro_ptr;
2069 s->tok = tok;
2070 s->tokc = tokc;
2073 /* restore parse state from 's' */
2074 void restore_parse_state(ParseState *s)
2076 file->line_num = s->line_num;
2077 macro_ptr = s->macro_ptr;
2078 tok = s->tok;
2079 tokc = s->tokc;
2082 /* return the number of additional 'ints' necessary to store the
2083 token */
2084 static inline int tok_ext_size(int t)
2086 switch(t) {
2087 /* 4 bytes */
2088 case TOK_CINT:
2089 case TOK_CUINT:
2090 case TOK_CCHAR:
2091 case TOK_LCHAR:
2092 case TOK_STR:
2093 case TOK_LSTR:
2094 case TOK_CFLOAT:
2095 case TOK_LINENUM:
2096 case TOK_PPNUM:
2097 return 1;
2098 case TOK_CDOUBLE:
2099 case TOK_CLLONG:
2100 case TOK_CULLONG:
2101 return 2;
2102 case TOK_CLDOUBLE:
2103 return LDOUBLE_SIZE / 4;
2104 default:
2105 return 0;
2109 /* token string handling */
2111 static inline void tok_str_new(TokenString *s)
2113 s->str = NULL;
2114 s->len = 0;
2115 s->allocated_len = 0;
2116 s->last_line_num = -1;
2119 static void tok_str_free(int *str)
2121 const int *p;
2122 CString *cstr;
2123 int t;
2125 p = str;
2126 for(;;) {
2127 t = *p;
2128 /* NOTE: we test zero separately so that GCC can generate a
2129 table for the following switch */
2130 if (t == 0)
2131 break;
2132 switch(t) {
2133 case TOK_CINT:
2134 case TOK_CUINT:
2135 case TOK_CCHAR:
2136 case TOK_LCHAR:
2137 case TOK_CFLOAT:
2138 case TOK_LINENUM:
2139 p += 2;
2140 break;
2141 case TOK_PPNUM:
2142 case TOK_STR:
2143 case TOK_LSTR:
2144 /* XXX: use a macro to be portable on 64 bit ? */
2145 cstr = (CString *)p[1];
2146 cstr_free(cstr);
2147 tcc_free(cstr);
2148 p += 2;
2149 break;
2150 case TOK_CDOUBLE:
2151 case TOK_CLLONG:
2152 case TOK_CULLONG:
2153 p += 3;
2154 break;
2155 case TOK_CLDOUBLE:
2156 p += 1 + (LDOUBLE_SIZE / 4);
2157 break;
2158 default:
2159 p++;
2160 break;
2163 tcc_free(str);
2166 static int *tok_str_realloc(TokenString *s)
2168 int *str, len;
2170 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2171 str = tcc_realloc(s->str, len * sizeof(int));
2172 if (!str)
2173 error("memory full");
2174 s->allocated_len = len;
2175 s->str = str;
2176 return str;
2179 static void tok_str_add(TokenString *s, int t)
2181 int len, *str;
2183 len = s->len;
2184 str = s->str;
2185 if (len >= s->allocated_len)
2186 str = tok_str_realloc(s);
2187 str[len++] = t;
2188 s->len = len;
2191 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2193 int len, *str;
2195 len = s->len;
2196 str = s->str;
2198 /* allocate space for worst case */
2199 if (len + TOK_MAX_SIZE > s->allocated_len)
2200 str = tok_str_realloc(s);
2201 str[len++] = t;
2202 switch(t) {
2203 case TOK_CINT:
2204 case TOK_CUINT:
2205 case TOK_CCHAR:
2206 case TOK_LCHAR:
2207 case TOK_CFLOAT:
2208 case TOK_LINENUM:
2209 str[len++] = cv->tab[0];
2210 break;
2211 case TOK_PPNUM:
2212 case TOK_STR:
2213 case TOK_LSTR:
2214 str[len++] = (int)cstr_dup(cv->cstr);
2215 break;
2216 case TOK_CDOUBLE:
2217 case TOK_CLLONG:
2218 case TOK_CULLONG:
2219 str[len++] = cv->tab[0];
2220 str[len++] = cv->tab[1];
2221 break;
2222 case TOK_CLDOUBLE:
2223 #if LDOUBLE_SIZE == 12
2224 str[len++] = cv->tab[0];
2225 str[len++] = cv->tab[1];
2226 str[len++] = cv->tab[2];
2227 #else
2228 #error add long double size support
2229 #endif
2230 break;
2231 default:
2232 break;
2234 s->len = len;
2237 /* add the current parse token in token string 's' */
2238 static void tok_str_add_tok(TokenString *s)
2240 CValue cval;
2242 /* save line number info */
2243 if (file->line_num != s->last_line_num) {
2244 s->last_line_num = file->line_num;
2245 cval.i = s->last_line_num;
2246 tok_str_add2(s, TOK_LINENUM, &cval);
2248 tok_str_add2(s, tok, &tokc);
2251 #if LDOUBLE_SIZE == 12
2252 #define LDOUBLE_GET(p, cv) \
2253 cv.tab[0] = p[0]; \
2254 cv.tab[1] = p[1]; \
2255 cv.tab[2] = p[2];
2256 #else
2257 #error add long double size support
2258 #endif
2261 /* get a token from an integer array and increment pointer
2262 accordingly. we code it as a macro to avoid pointer aliasing. */
2263 #define TOK_GET(t, p, cv) \
2265 t = *p++; \
2266 switch(t) { \
2267 case TOK_CINT: \
2268 case TOK_CUINT: \
2269 case TOK_CCHAR: \
2270 case TOK_LCHAR: \
2271 case TOK_CFLOAT: \
2272 case TOK_LINENUM: \
2273 case TOK_STR: \
2274 case TOK_LSTR: \
2275 case TOK_PPNUM: \
2276 cv.tab[0] = *p++; \
2277 break; \
2278 case TOK_CDOUBLE: \
2279 case TOK_CLLONG: \
2280 case TOK_CULLONG: \
2281 cv.tab[0] = p[0]; \
2282 cv.tab[1] = p[1]; \
2283 p += 2; \
2284 break; \
2285 case TOK_CLDOUBLE: \
2286 LDOUBLE_GET(p, cv); \
2287 p += LDOUBLE_SIZE / 4; \
2288 break; \
2289 default: \
2290 break; \
2294 /* defines handling */
2295 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2297 Sym *s;
2299 s = sym_push2(&define_stack, v, macro_type, (int)str);
2300 s->next = first_arg;
2301 table_ident[v - TOK_IDENT]->sym_define = s;
2304 /* undefined a define symbol. Its name is just set to zero */
2305 static void define_undef(Sym *s)
2307 int v;
2308 v = s->v;
2309 if (v >= TOK_IDENT && v < tok_ident)
2310 table_ident[v - TOK_IDENT]->sym_define = NULL;
2311 s->v = 0;
2314 static inline Sym *define_find(int v)
2316 v -= TOK_IDENT;
2317 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2318 return NULL;
2319 return table_ident[v]->sym_define;
2322 /* free define stack until top reaches 'b' */
2323 static void free_defines(Sym *b)
2325 Sym *top, *top1;
2326 int v;
2328 top = define_stack;
2329 while (top != b) {
2330 top1 = top->prev;
2331 /* do not free args or predefined defines */
2332 if (top->c)
2333 tok_str_free((int *)top->c);
2334 v = top->v;
2335 if (v >= TOK_IDENT && v < tok_ident)
2336 table_ident[v - TOK_IDENT]->sym_define = NULL;
2337 tcc_free(top);
2338 top = top1;
2340 define_stack = b;
2343 /* label lookup */
2344 static Sym *label_find(int v)
2346 v -= TOK_IDENT;
2347 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2348 return NULL;
2349 return table_ident[v]->sym_label;
2352 static Sym *label_push(Sym **ptop, int v, int flags)
2354 Sym *s, **ps;
2355 s = sym_push2(ptop, v, 0, 0);
2356 s->r = flags;
2357 ps = &table_ident[v - TOK_IDENT]->sym_label;
2358 if (ptop == &global_label_stack) {
2359 /* modify the top most local identifier, so that
2360 sym_identifier will point to 's' when popped */
2361 while (*ps != NULL)
2362 ps = &(*ps)->prev_tok;
2364 s->prev_tok = *ps;
2365 *ps = s;
2366 return s;
2369 /* pop labels until element last is reached. Look if any labels are
2370 undefined. Define symbols if '&&label' was used. */
2371 static void label_pop(Sym **ptop, Sym *slast)
2373 Sym *s, *s1;
2374 for(s = *ptop; s != slast; s = s1) {
2375 s1 = s->prev;
2376 if (s->r == LABEL_DECLARED) {
2377 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2378 } else if (s->r == LABEL_FORWARD) {
2379 error("label '%s' used but not defined",
2380 get_tok_str(s->v, NULL));
2381 } else {
2382 if (s->c) {
2383 /* define corresponding symbol. A size of
2384 1 is put. */
2385 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2388 /* remove label */
2389 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2390 tcc_free(s);
2392 *ptop = slast;
2395 /* eval an expression for #if/#elif */
2396 static int expr_preprocess(void)
2398 int c, t;
2399 TokenString str;
2401 tok_str_new(&str);
2402 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2403 next(); /* do macro subst */
2404 if (tok == TOK_DEFINED) {
2405 next_nomacro();
2406 t = tok;
2407 if (t == '(')
2408 next_nomacro();
2409 c = define_find(tok) != 0;
2410 if (t == '(')
2411 next_nomacro();
2412 tok = TOK_CINT;
2413 tokc.i = c;
2414 } else if (tok >= TOK_IDENT) {
2415 /* if undefined macro */
2416 tok = TOK_CINT;
2417 tokc.i = 0;
2419 tok_str_add_tok(&str);
2421 tok_str_add(&str, -1); /* simulate end of file */
2422 tok_str_add(&str, 0);
2423 /* now evaluate C constant expression */
2424 macro_ptr = str.str;
2425 next();
2426 c = expr_const();
2427 macro_ptr = NULL;
2428 tok_str_free(str.str);
2429 return c != 0;
2432 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2433 static void tok_print(int *str)
2435 int t;
2436 CValue cval;
2438 while (1) {
2439 TOK_GET(t, str, cval);
2440 if (!t)
2441 break;
2442 printf(" %s", get_tok_str(t, &cval));
2444 printf("\n");
2446 #endif
2448 /* parse after #define */
2449 static void parse_define(void)
2451 Sym *s, *first, **ps;
2452 int v, t, varg, is_vaargs, c;
2453 TokenString str;
2455 v = tok;
2456 if (v < TOK_IDENT)
2457 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2458 /* XXX: should check if same macro (ANSI) */
2459 first = NULL;
2460 t = MACRO_OBJ;
2461 /* '(' must be just after macro definition for MACRO_FUNC */
2462 c = file->buf_ptr[0];
2463 if (c == '\\')
2464 c = handle_stray1(file->buf_ptr);
2465 if (c == '(') {
2466 next_nomacro();
2467 next_nomacro();
2468 ps = &first;
2469 while (tok != ')') {
2470 varg = tok;
2471 next_nomacro();
2472 is_vaargs = 0;
2473 if (varg == TOK_DOTS) {
2474 varg = TOK___VA_ARGS__;
2475 is_vaargs = 1;
2476 } else if (tok == TOK_DOTS && gnu_ext) {
2477 is_vaargs = 1;
2478 next_nomacro();
2480 if (varg < TOK_IDENT)
2481 error("badly punctuated parameter list");
2482 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2483 *ps = s;
2484 ps = &s->next;
2485 if (tok != ',')
2486 break;
2487 next_nomacro();
2489 t = MACRO_FUNC;
2491 tok_str_new(&str);
2492 next_nomacro();
2493 /* EOF testing necessary for '-D' handling */
2494 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2495 tok_str_add2(&str, tok, &tokc);
2496 next_nomacro();
2498 tok_str_add(&str, 0);
2499 #ifdef PP_DEBUG
2500 printf("define %s %d: ", get_tok_str(v, NULL), t);
2501 tok_print(str.str);
2502 #endif
2503 define_push(v, t, str.str, first);
2506 /* XXX: use a token or a hash table to accelerate matching ? */
2507 static CachedInclude *search_cached_include(TCCState *s1,
2508 int type, const char *filename)
2510 CachedInclude *e;
2511 int i;
2513 for(i = 0;i < s1->nb_cached_includes; i++) {
2514 e = s1->cached_includes[i];
2515 if (e->type == type && !strcmp(e->filename, filename))
2516 return e;
2518 return NULL;
2521 static inline void add_cached_include(TCCState *s1, int type,
2522 const char *filename, int ifndef_macro)
2524 CachedInclude *e;
2526 if (search_cached_include(s1, type, filename))
2527 return;
2528 #ifdef INC_DEBUG
2529 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2530 #endif
2531 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2532 if (!e)
2533 return;
2534 e->type = type;
2535 strcpy(e->filename, filename);
2536 e->ifndef_macro = ifndef_macro;
2537 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2540 /* is_bof is true if first non space token at beginning of file */
2541 static void preprocess(int is_bof)
2543 TCCState *s1 = tcc_state;
2544 int size, i, c, n, saved_parse_flags;
2545 char buf[1024], *q, *p;
2546 char buf1[1024];
2547 BufferedFile *f;
2548 Sym *s;
2549 CachedInclude *e;
2551 saved_parse_flags = parse_flags;
2552 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2553 PARSE_FLAG_LINEFEED;
2554 next_nomacro();
2555 redo:
2556 switch(tok) {
2557 case TOK_DEFINE:
2558 next_nomacro();
2559 parse_define();
2560 break;
2561 case TOK_UNDEF:
2562 next_nomacro();
2563 s = define_find(tok);
2564 /* undefine symbol by putting an invalid name */
2565 if (s)
2566 define_undef(s);
2567 break;
2568 case TOK_INCLUDE:
2569 ch = file->buf_ptr[0];
2570 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2571 skip_spaces();
2572 if (ch == '<') {
2573 c = '>';
2574 goto read_name;
2575 } else if (ch == '\"') {
2576 c = ch;
2577 read_name:
2578 /* XXX: better stray handling */
2579 minp();
2580 q = buf;
2581 while (ch != c && ch != '\n' && ch != CH_EOF) {
2582 if ((q - buf) < sizeof(buf) - 1)
2583 *q++ = ch;
2584 minp();
2586 *q = '\0';
2587 minp();
2588 #if 0
2589 /* eat all spaces and comments after include */
2590 /* XXX: slightly incorrect */
2591 while (ch1 != '\n' && ch1 != CH_EOF)
2592 inp();
2593 #endif
2594 } else {
2595 /* computed #include : either we have only strings or
2596 we have anything enclosed in '<>' */
2597 next();
2598 buf[0] = '\0';
2599 if (tok == TOK_STR) {
2600 while (tok != TOK_LINEFEED) {
2601 if (tok != TOK_STR) {
2602 include_syntax:
2603 error("'#include' expects \"FILENAME\" or <FILENAME>");
2605 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2606 next();
2608 c = '\"';
2609 } else {
2610 int len;
2611 while (tok != TOK_LINEFEED) {
2612 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2613 next();
2615 len = strlen(buf);
2616 /* check syntax and remove '<>' */
2617 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2618 goto include_syntax;
2619 memmove(buf, buf + 1, len - 2);
2620 buf[len - 2] = '\0';
2621 c = '>';
2625 e = search_cached_include(s1, c, buf);
2626 if (e && define_find(e->ifndef_macro)) {
2627 /* no need to parse the include because the 'ifndef macro'
2628 is defined */
2629 #ifdef INC_DEBUG
2630 printf("%s: skipping %s\n", file->filename, buf);
2631 #endif
2632 } else {
2633 if (c == '\"') {
2634 /* first search in current dir if "header.h" */
2635 size = 0;
2636 p = strrchr(file->filename, '/');
2637 if (p)
2638 size = p + 1 - file->filename;
2639 if (size > sizeof(buf1) - 1)
2640 size = sizeof(buf1) - 1;
2641 memcpy(buf1, file->filename, size);
2642 buf1[size] = '\0';
2643 pstrcat(buf1, sizeof(buf1), buf);
2644 f = tcc_open(s1, buf1);
2645 if (f)
2646 goto found;
2648 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2649 error("#include recursion too deep");
2650 /* now search in all the include paths */
2651 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2652 for(i = 0; i < n; i++) {
2653 const char *path;
2654 if (i < s1->nb_include_paths)
2655 path = s1->include_paths[i];
2656 else
2657 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2658 pstrcpy(buf1, sizeof(buf1), path);
2659 pstrcat(buf1, sizeof(buf1), "/");
2660 pstrcat(buf1, sizeof(buf1), buf);
2661 f = tcc_open(s1, buf1);
2662 if (f)
2663 goto found;
2665 error("include file '%s' not found", buf);
2666 f = NULL;
2667 found:
2668 #ifdef INC_DEBUG
2669 printf("%s: including %s\n", file->filename, buf1);
2670 #endif
2671 f->inc_type = c;
2672 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2673 /* push current file in stack */
2674 /* XXX: fix current line init */
2675 *s1->include_stack_ptr++ = file;
2676 file = f;
2677 /* add include file debug info */
2678 if (do_debug) {
2679 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2681 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2682 ch = file->buf_ptr[0];
2683 goto the_end;
2685 break;
2686 case TOK_IFNDEF:
2687 c = 1;
2688 goto do_ifdef;
2689 case TOK_IF:
2690 c = expr_preprocess();
2691 goto do_if;
2692 case TOK_IFDEF:
2693 c = 0;
2694 do_ifdef:
2695 next_nomacro();
2696 if (tok < TOK_IDENT)
2697 error("invalid argument for '#if%sdef'", c ? "n" : "");
2698 if (is_bof) {
2699 if (c) {
2700 #ifdef INC_DEBUG
2701 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2702 #endif
2703 file->ifndef_macro = tok;
2706 c = (define_find(tok) != 0) ^ c;
2707 do_if:
2708 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2709 error("memory full");
2710 *s1->ifdef_stack_ptr++ = c;
2711 goto test_skip;
2712 case TOK_ELSE:
2713 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2714 error("#else without matching #if");
2715 if (s1->ifdef_stack_ptr[-1] & 2)
2716 error("#else after #else");
2717 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2718 goto test_skip;
2719 case TOK_ELIF:
2720 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2721 error("#elif without matching #if");
2722 c = s1->ifdef_stack_ptr[-1];
2723 if (c > 1)
2724 error("#elif after #else");
2725 /* last #if/#elif expression was true: we skip */
2726 if (c == 1)
2727 goto skip;
2728 c = expr_preprocess();
2729 s1->ifdef_stack_ptr[-1] = c;
2730 test_skip:
2731 if (!(c & 1)) {
2732 skip:
2733 preprocess_skip();
2734 is_bof = 0;
2735 goto redo;
2737 break;
2738 case TOK_ENDIF:
2739 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2740 error("#endif without matching #if");
2741 s1->ifdef_stack_ptr--;
2742 /* '#ifndef macro' was at the start of file. Now we check if
2743 an '#endif' is exactly at the end of file */
2744 if (file->ifndef_macro &&
2745 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2746 file->ifndef_macro_saved = file->ifndef_macro;
2747 /* need to set to zero to avoid false matches if another
2748 #ifndef at middle of file */
2749 file->ifndef_macro = 0;
2750 while (tok != TOK_LINEFEED)
2751 next_nomacro();
2752 tok_flags |= TOK_FLAG_ENDIF;
2753 goto the_end;
2755 break;
2756 case TOK_LINE:
2757 next();
2758 if (tok != TOK_CINT)
2759 error("#line");
2760 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2761 next();
2762 if (tok != TOK_LINEFEED) {
2763 if (tok != TOK_STR)
2764 error("#line");
2765 pstrcpy(file->filename, sizeof(file->filename),
2766 (char *)tokc.cstr->data);
2768 break;
2769 case TOK_ERROR:
2770 case TOK_WARNING:
2771 c = tok;
2772 ch = file->buf_ptr[0];
2773 skip_spaces();
2774 q = buf;
2775 while (ch != '\n' && ch != CH_EOF) {
2776 if ((q - buf) < sizeof(buf) - 1)
2777 *q++ = ch;
2778 minp();
2780 *q = '\0';
2781 if (c == TOK_ERROR)
2782 error("#error %s", buf);
2783 else
2784 warning("#warning %s", buf);
2785 break;
2786 case TOK_PRAGMA:
2787 /* ignored */
2788 break;
2789 default:
2790 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2791 /* '!' is ignored to allow C scripts. numbers are ignored
2792 to emulate cpp behaviour */
2793 } else {
2794 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2796 break;
2798 /* ignore other preprocess commands or #! for C scripts */
2799 while (tok != TOK_LINEFEED)
2800 next_nomacro();
2801 the_end:
2802 parse_flags = saved_parse_flags;
2805 /* evaluate escape codes in a string. */
2806 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2808 int c, n;
2809 const char *p;
2811 p = buf;
2812 for(;;) {
2813 c = *p;
2814 if (c == '\0')
2815 break;
2816 if (c == '\\') {
2817 p++;
2818 /* escape */
2819 c = *p;
2820 switch(c) {
2821 case '0': case '1': case '2': case '3':
2822 case '4': case '5': case '6': case '7':
2823 /* at most three octal digits */
2824 n = c - '0';
2825 p++;
2826 c = *p;
2827 if (isoct(c)) {
2828 n = n * 8 + c - '0';
2829 p++;
2830 c = *p;
2831 if (isoct(c)) {
2832 n = n * 8 + c - '0';
2833 p++;
2836 c = n;
2837 goto add_char_nonext;
2838 case 'x':
2839 p++;
2840 n = 0;
2841 for(;;) {
2842 c = *p;
2843 if (c >= 'a' && c <= 'f')
2844 c = c - 'a' + 10;
2845 else if (c >= 'A' && c <= 'F')
2846 c = c - 'A' + 10;
2847 else if (isnum(c))
2848 c = c - '0';
2849 else
2850 break;
2851 n = n * 16 + c;
2852 p++;
2854 c = n;
2855 goto add_char_nonext;
2856 case 'a':
2857 c = '\a';
2858 break;
2859 case 'b':
2860 c = '\b';
2861 break;
2862 case 'f':
2863 c = '\f';
2864 break;
2865 case 'n':
2866 c = '\n';
2867 break;
2868 case 'r':
2869 c = '\r';
2870 break;
2871 case 't':
2872 c = '\t';
2873 break;
2874 case 'v':
2875 c = '\v';
2876 break;
2877 case 'e':
2878 if (!gnu_ext)
2879 goto invalid_escape;
2880 c = 27;
2881 break;
2882 case '\'':
2883 case '\"':
2884 case '\\':
2885 case '?':
2886 break;
2887 default:
2888 invalid_escape:
2889 error("invalid escaped char");
2892 p++;
2893 add_char_nonext:
2894 if (!is_long)
2895 cstr_ccat(outstr, c);
2896 else
2897 cstr_wccat(outstr, c);
2899 /* add a trailing '\0' */
2900 if (!is_long)
2901 cstr_ccat(outstr, '\0');
2902 else
2903 cstr_wccat(outstr, '\0');
2906 /* we use 64 bit numbers */
2907 #define BN_SIZE 2
2909 /* bn = (bn << shift) | or_val */
2910 void bn_lshift(unsigned int *bn, int shift, int or_val)
2912 int i;
2913 unsigned int v;
2914 for(i=0;i<BN_SIZE;i++) {
2915 v = bn[i];
2916 bn[i] = (v << shift) | or_val;
2917 or_val = v >> (32 - shift);
2921 void bn_zero(unsigned int *bn)
2923 int i;
2924 for(i=0;i<BN_SIZE;i++) {
2925 bn[i] = 0;
2929 /* parse number in null terminated string 'p' and return it in the
2930 current token */
2931 void parse_number(const char *p)
2933 int b, t, shift, frac_bits, s, exp_val, ch;
2934 char *q;
2935 unsigned int bn[BN_SIZE];
2936 double d;
2938 /* number */
2939 q = token_buf;
2940 ch = *p++;
2941 t = ch;
2942 ch = *p++;
2943 *q++ = t;
2944 b = 10;
2945 if (t == '.') {
2946 goto float_frac_parse;
2947 } else if (t == '0') {
2948 if (ch == 'x' || ch == 'X') {
2949 q--;
2950 ch = *p++;
2951 b = 16;
2952 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2953 q--;
2954 ch = *p++;
2955 b = 2;
2958 /* parse all digits. cannot check octal numbers at this stage
2959 because of floating point constants */
2960 while (1) {
2961 if (ch >= 'a' && ch <= 'f')
2962 t = ch - 'a' + 10;
2963 else if (ch >= 'A' && ch <= 'F')
2964 t = ch - 'A' + 10;
2965 else if (isnum(ch))
2966 t = ch - '0';
2967 else
2968 break;
2969 if (t >= b)
2970 break;
2971 if (q >= token_buf + STRING_MAX_SIZE) {
2972 num_too_long:
2973 error("number too long");
2975 *q++ = ch;
2976 ch = *p++;
2978 if (ch == '.' ||
2979 ((ch == 'e' || ch == 'E') && b == 10) ||
2980 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2981 if (b != 10) {
2982 /* NOTE: strtox should support that for hexa numbers, but
2983 non ISOC99 libcs do not support it, so we prefer to do
2984 it by hand */
2985 /* hexadecimal or binary floats */
2986 /* XXX: handle overflows */
2987 *q = '\0';
2988 if (b == 16)
2989 shift = 4;
2990 else
2991 shift = 2;
2992 bn_zero(bn);
2993 q = token_buf;
2994 while (1) {
2995 t = *q++;
2996 if (t == '\0') {
2997 break;
2998 } else if (t >= 'a') {
2999 t = t - 'a' + 10;
3000 } else if (t >= 'A') {
3001 t = t - 'A' + 10;
3002 } else {
3003 t = t - '0';
3005 bn_lshift(bn, shift, t);
3007 frac_bits = 0;
3008 if (ch == '.') {
3009 ch = *p++;
3010 while (1) {
3011 t = ch;
3012 if (t >= 'a' && t <= 'f') {
3013 t = t - 'a' + 10;
3014 } else if (t >= 'A' && t <= 'F') {
3015 t = t - 'A' + 10;
3016 } else if (t >= '0' && t <= '9') {
3017 t = t - '0';
3018 } else {
3019 break;
3021 if (t >= b)
3022 error("invalid digit");
3023 bn_lshift(bn, shift, t);
3024 frac_bits += shift;
3025 ch = *p++;
3028 if (ch != 'p' && ch != 'P')
3029 expect("exponent");
3030 ch = *p++;
3031 s = 1;
3032 exp_val = 0;
3033 if (ch == '+') {
3034 ch = *p++;
3035 } else if (ch == '-') {
3036 s = -1;
3037 ch = *p++;
3039 if (ch < '0' || ch > '9')
3040 expect("exponent digits");
3041 while (ch >= '0' && ch <= '9') {
3042 exp_val = exp_val * 10 + ch - '0';
3043 ch = *p++;
3045 exp_val = exp_val * s;
3047 /* now we can generate the number */
3048 /* XXX: should patch directly float number */
3049 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3050 d = ldexp(d, exp_val - frac_bits);
3051 t = toup(ch);
3052 if (t == 'F') {
3053 ch = *p++;
3054 tok = TOK_CFLOAT;
3055 /* float : should handle overflow */
3056 tokc.f = (float)d;
3057 } else if (t == 'L') {
3058 ch = *p++;
3059 tok = TOK_CLDOUBLE;
3060 /* XXX: not large enough */
3061 tokc.ld = (long double)d;
3062 } else {
3063 tok = TOK_CDOUBLE;
3064 tokc.d = d;
3066 } else {
3067 /* decimal floats */
3068 if (ch == '.') {
3069 if (q >= token_buf + STRING_MAX_SIZE)
3070 goto num_too_long;
3071 *q++ = ch;
3072 ch = *p++;
3073 float_frac_parse:
3074 while (ch >= '0' && ch <= '9') {
3075 if (q >= token_buf + STRING_MAX_SIZE)
3076 goto num_too_long;
3077 *q++ = ch;
3078 ch = *p++;
3081 if (ch == 'e' || ch == 'E') {
3082 if (q >= token_buf + STRING_MAX_SIZE)
3083 goto num_too_long;
3084 *q++ = ch;
3085 ch = *p++;
3086 if (ch == '-' || ch == '+') {
3087 if (q >= token_buf + STRING_MAX_SIZE)
3088 goto num_too_long;
3089 *q++ = ch;
3090 ch = *p++;
3092 if (ch < '0' || ch > '9')
3093 expect("exponent digits");
3094 while (ch >= '0' && ch <= '9') {
3095 if (q >= token_buf + STRING_MAX_SIZE)
3096 goto num_too_long;
3097 *q++ = ch;
3098 ch = *p++;
3101 *q = '\0';
3102 t = toup(ch);
3103 errno = 0;
3104 if (t == 'F') {
3105 ch = *p++;
3106 tok = TOK_CFLOAT;
3107 tokc.f = strtof(token_buf, NULL);
3108 } else if (t == 'L') {
3109 ch = *p++;
3110 tok = TOK_CLDOUBLE;
3111 tokc.ld = strtold(token_buf, NULL);
3112 } else {
3113 tok = TOK_CDOUBLE;
3114 tokc.d = strtod(token_buf, NULL);
3117 } else {
3118 unsigned long long n, n1;
3119 int lcount, ucount;
3121 /* integer number */
3122 *q = '\0';
3123 q = token_buf;
3124 if (b == 10 && *q == '0') {
3125 b = 8;
3126 q++;
3128 n = 0;
3129 while(1) {
3130 t = *q++;
3131 /* no need for checks except for base 10 / 8 errors */
3132 if (t == '\0') {
3133 break;
3134 } else if (t >= 'a') {
3135 t = t - 'a' + 10;
3136 } else if (t >= 'A') {
3137 t = t - 'A' + 10;
3138 } else {
3139 t = t - '0';
3140 if (t >= b)
3141 error("invalid digit");
3143 n1 = n;
3144 n = n * b + t;
3145 /* detect overflow */
3146 /* XXX: this test is not reliable */
3147 if (n < n1)
3148 error("integer constant overflow");
3151 /* XXX: not exactly ANSI compliant */
3152 if ((n & 0xffffffff00000000LL) != 0) {
3153 if ((n >> 63) != 0)
3154 tok = TOK_CULLONG;
3155 else
3156 tok = TOK_CLLONG;
3157 } else if (n > 0x7fffffff) {
3158 tok = TOK_CUINT;
3159 } else {
3160 tok = TOK_CINT;
3162 lcount = 0;
3163 ucount = 0;
3164 for(;;) {
3165 t = toup(ch);
3166 if (t == 'L') {
3167 if (lcount >= 2)
3168 error("three 'l's in integer constant");
3169 lcount++;
3170 if (lcount == 2) {
3171 if (tok == TOK_CINT)
3172 tok = TOK_CLLONG;
3173 else if (tok == TOK_CUINT)
3174 tok = TOK_CULLONG;
3176 ch = *p++;
3177 } else if (t == 'U') {
3178 if (ucount >= 1)
3179 error("two 'u's in integer constant");
3180 ucount++;
3181 if (tok == TOK_CINT)
3182 tok = TOK_CUINT;
3183 else if (tok == TOK_CLLONG)
3184 tok = TOK_CULLONG;
3185 ch = *p++;
3186 } else {
3187 break;
3190 if (tok == TOK_CINT || tok == TOK_CUINT)
3191 tokc.ui = n;
3192 else
3193 tokc.ull = n;
3198 #define PARSE2(c1, tok1, c2, tok2) \
3199 case c1: \
3200 PEEKC(c, p); \
3201 if (c == c2) { \
3202 p++; \
3203 tok = tok2; \
3204 } else { \
3205 tok = tok1; \
3207 break;
3209 /* return next token without macro substitution */
3210 static inline void next_nomacro1(void)
3212 int t, c, is_long;
3213 TokenSym *ts;
3214 uint8_t *p, *p1;
3215 unsigned int h;
3217 p = file->buf_ptr;
3218 redo_no_start:
3219 c = *p;
3220 switch(c) {
3221 case ' ':
3222 case '\t':
3223 case '\f':
3224 case '\v':
3225 case '\r':
3226 p++;
3227 goto redo_no_start;
3229 case '\\':
3230 /* first look if it is in fact an end of buffer */
3231 if (p >= file->buf_end) {
3232 file->buf_ptr = p;
3233 handle_eob();
3234 p = file->buf_ptr;
3235 if (p >= file->buf_end)
3236 goto parse_eof;
3237 else
3238 goto redo_no_start;
3239 } else {
3240 file->buf_ptr = p;
3241 ch = *p;
3242 handle_stray();
3243 p = file->buf_ptr;
3244 goto redo_no_start;
3246 parse_eof:
3248 TCCState *s1 = tcc_state;
3249 if (parse_flags & PARSE_FLAG_LINEFEED) {
3250 tok = TOK_LINEFEED;
3251 } else if (s1->include_stack_ptr == s1->include_stack ||
3252 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3253 /* no include left : end of file. */
3254 tok = TOK_EOF;
3255 } else {
3256 /* pop include file */
3258 /* test if previous '#endif' was after a #ifdef at
3259 start of file */
3260 if (tok_flags & TOK_FLAG_ENDIF) {
3261 #ifdef INC_DEBUG
3262 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3263 #endif
3264 add_cached_include(s1, file->inc_type, file->inc_filename,
3265 file->ifndef_macro_saved);
3268 /* add end of include file debug info */
3269 if (do_debug) {
3270 put_stabd(N_EINCL, 0, 0);
3272 /* pop include stack */
3273 tcc_close(file);
3274 s1->include_stack_ptr--;
3275 file = *s1->include_stack_ptr;
3276 p = file->buf_ptr;
3277 goto redo_no_start;
3280 break;
3282 case '\n':
3283 if (parse_flags & PARSE_FLAG_LINEFEED) {
3284 tok = TOK_LINEFEED;
3285 } else {
3286 file->line_num++;
3287 tok_flags |= TOK_FLAG_BOL;
3288 p++;
3289 goto redo_no_start;
3291 break;
3293 case '#':
3294 /* XXX: simplify */
3295 PEEKC(c, p);
3296 if ((tok_flags & TOK_FLAG_BOL) &&
3297 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3298 file->buf_ptr = p;
3299 preprocess(tok_flags & TOK_FLAG_BOF);
3300 p = file->buf_ptr;
3301 goto redo_no_start;
3302 } else {
3303 if (c == '#') {
3304 p++;
3305 tok = TOK_TWOSHARPS;
3306 } else {
3307 tok = '#';
3310 break;
3312 case 'a': case 'b': case 'c': case 'd':
3313 case 'e': case 'f': case 'g': case 'h':
3314 case 'i': case 'j': case 'k': case 'l':
3315 case 'm': case 'n': case 'o': case 'p':
3316 case 'q': case 'r': case 's': case 't':
3317 case 'u': case 'v': case 'w': case 'x':
3318 case 'y': case 'z':
3319 case 'A': case 'B': case 'C': case 'D':
3320 case 'E': case 'F': case 'G': case 'H':
3321 case 'I': case 'J': case 'K':
3322 case 'M': case 'N': case 'O': case 'P':
3323 case 'Q': case 'R': case 'S': case 'T':
3324 case 'U': case 'V': case 'W': case 'X':
3325 case 'Y': case 'Z':
3326 case '_':
3327 parse_ident_fast:
3328 p1 = p;
3329 h = TOK_HASH_INIT;
3330 h = TOK_HASH_FUNC(h, c);
3331 p++;
3332 for(;;) {
3333 c = *p;
3334 if (!isidnum_table[c])
3335 break;
3336 h = TOK_HASH_FUNC(h, c);
3337 p++;
3339 if (c != '\\') {
3340 TokenSym **pts;
3341 int len;
3343 /* fast case : no stray found, so we have the full token
3344 and we have already hashed it */
3345 len = p - p1;
3346 h &= (TOK_HASH_SIZE - 1);
3347 pts = &hash_ident[h];
3348 for(;;) {
3349 ts = *pts;
3350 if (!ts)
3351 break;
3352 if (ts->len == len && !memcmp(ts->str, p1, len))
3353 goto token_found;
3354 pts = &(ts->hash_next);
3356 ts = tok_alloc_new(pts, p1, len);
3357 token_found: ;
3358 } else {
3359 /* slower case */
3360 cstr_reset(&tokcstr);
3362 while (p1 < p) {
3363 cstr_ccat(&tokcstr, *p1);
3364 p1++;
3366 p--;
3367 PEEKC(c, p);
3368 parse_ident_slow:
3369 while (isidnum_table[c]) {
3370 cstr_ccat(&tokcstr, c);
3371 PEEKC(c, p);
3373 ts = tok_alloc(tokcstr.data, tokcstr.size);
3375 tok = ts->tok;
3376 break;
3377 case 'L':
3378 t = p[1];
3379 if (t != '\\' && t != '\'' && t != '\"') {
3380 /* fast case */
3381 goto parse_ident_fast;
3382 } else {
3383 PEEKC(c, p);
3384 if (c == '\'' || c == '\"') {
3385 is_long = 1;
3386 goto str_const;
3387 } else {
3388 cstr_reset(&tokcstr);
3389 cstr_ccat(&tokcstr, 'L');
3390 goto parse_ident_slow;
3393 break;
3394 case '0': case '1': case '2': case '3':
3395 case '4': case '5': case '6': case '7':
3396 case '8': case '9':
3398 cstr_reset(&tokcstr);
3399 /* after the first digit, accept digits, alpha, '.' or sign if
3400 prefixed by 'eEpP' */
3401 parse_num:
3402 for(;;) {
3403 t = c;
3404 cstr_ccat(&tokcstr, c);
3405 PEEKC(c, p);
3406 if (!(isnum(c) || isid(c) || c == '.' ||
3407 ((c == '+' || c == '-') &&
3408 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3409 break;
3411 /* We add a trailing '\0' to ease parsing */
3412 cstr_ccat(&tokcstr, '\0');
3413 tokc.cstr = &tokcstr;
3414 tok = TOK_PPNUM;
3415 break;
3416 case '.':
3417 /* special dot handling because it can also start a number */
3418 PEEKC(c, p);
3419 if (isnum(c)) {
3420 cstr_reset(&tokcstr);
3421 cstr_ccat(&tokcstr, '.');
3422 goto parse_num;
3423 } else if (c == '.') {
3424 PEEKC(c, p);
3425 if (c != '.')
3426 expect("'.'");
3427 PEEKC(c, p);
3428 tok = TOK_DOTS;
3429 } else {
3430 tok = '.';
3432 break;
3433 case '\'':
3434 case '\"':
3435 is_long = 0;
3436 str_const:
3438 CString str;
3439 int sep;
3441 sep = c;
3443 /* parse the string */
3444 cstr_new(&str);
3445 p = parse_pp_string(p, sep, &str);
3446 cstr_ccat(&str, '\0');
3448 /* eval the escape (should be done as TOK_PPNUM) */
3449 cstr_reset(&tokcstr);
3450 parse_escape_string(&tokcstr, str.data, is_long);
3451 cstr_free(&str);
3453 if (sep == '\'') {
3454 int char_size;
3455 /* XXX: make it portable */
3456 if (!is_long)
3457 char_size = 1;
3458 else
3459 char_size = sizeof(int);
3460 if (tokcstr.size <= char_size)
3461 error("empty character constant");
3462 if (tokcstr.size > 2 * char_size)
3463 warning("multi-character character constant");
3464 if (!is_long) {
3465 tokc.i = *(int8_t *)tokcstr.data;
3466 tok = TOK_CCHAR;
3467 } else {
3468 tokc.i = *(int *)tokcstr.data;
3469 tok = TOK_LCHAR;
3471 } else {
3472 tokc.cstr = &tokcstr;
3473 if (!is_long)
3474 tok = TOK_STR;
3475 else
3476 tok = TOK_LSTR;
3479 break;
3481 case '<':
3482 PEEKC(c, p);
3483 if (c == '=') {
3484 p++;
3485 tok = TOK_LE;
3486 } else if (c == '<') {
3487 PEEKC(c, p);
3488 if (c == '=') {
3489 p++;
3490 tok = TOK_A_SHL;
3491 } else {
3492 tok = TOK_SHL;
3494 } else {
3495 tok = TOK_LT;
3497 break;
3499 case '>':
3500 PEEKC(c, p);
3501 if (c == '=') {
3502 p++;
3503 tok = TOK_GE;
3504 } else if (c == '>') {
3505 PEEKC(c, p);
3506 if (c == '=') {
3507 p++;
3508 tok = TOK_A_SAR;
3509 } else {
3510 tok = TOK_SAR;
3512 } else {
3513 tok = TOK_GT;
3515 break;
3517 case '&':
3518 PEEKC(c, p);
3519 if (c == '&') {
3520 p++;
3521 tok = TOK_LAND;
3522 } else if (c == '=') {
3523 p++;
3524 tok = TOK_A_AND;
3525 } else {
3526 tok = '&';
3528 break;
3530 case '|':
3531 PEEKC(c, p);
3532 if (c == '|') {
3533 p++;
3534 tok = TOK_LOR;
3535 } else if (c == '=') {
3536 p++;
3537 tok = TOK_A_OR;
3538 } else {
3539 tok = '|';
3541 break;
3543 case '+':
3544 PEEKC(c, p);
3545 if (c == '+') {
3546 p++;
3547 tok = TOK_INC;
3548 } else if (c == '=') {
3549 p++;
3550 tok = TOK_A_ADD;
3551 } else {
3552 tok = '+';
3554 break;
3556 case '-':
3557 PEEKC(c, p);
3558 if (c == '-') {
3559 p++;
3560 tok = TOK_DEC;
3561 } else if (c == '=') {
3562 p++;
3563 tok = TOK_A_SUB;
3564 } else if (c == '>') {
3565 p++;
3566 tok = TOK_ARROW;
3567 } else {
3568 tok = '-';
3570 break;
3572 PARSE2('!', '!', '=', TOK_NE)
3573 PARSE2('=', '=', '=', TOK_EQ)
3574 PARSE2('*', '*', '=', TOK_A_MUL)
3575 PARSE2('%', '%', '=', TOK_A_MOD)
3576 PARSE2('^', '^', '=', TOK_A_XOR)
3578 /* comments or operator */
3579 case '/':
3580 PEEKC(c, p);
3581 if (c == '*') {
3582 p = parse_comment(p);
3583 goto redo_no_start;
3584 } else if (c == '/') {
3585 p = parse_line_comment(p);
3586 goto redo_no_start;
3587 } else if (c == '=') {
3588 p++;
3589 tok = TOK_A_DIV;
3590 } else {
3591 tok = '/';
3593 break;
3595 /* simple tokens */
3596 case '(':
3597 case ')':
3598 case '[':
3599 case ']':
3600 case '{':
3601 case '}':
3602 case ',':
3603 case ';':
3604 case ':':
3605 case '?':
3606 case '~':
3607 case '$': /* only used in assembler */
3608 tok = c;
3609 p++;
3610 break;
3611 default:
3612 error("unrecognized character \\x%02x", c);
3613 break;
3615 file->buf_ptr = p;
3616 tok_flags = 0;
3617 #if defined(PARSE_DEBUG)
3618 printf("token = %s\n", get_tok_str(tok, &tokc));
3619 #endif
3622 /* return next token without macro substitution. Can read input from
3623 macro_ptr buffer */
3624 static void next_nomacro(void)
3626 if (macro_ptr) {
3627 redo:
3628 tok = *macro_ptr;
3629 if (tok) {
3630 TOK_GET(tok, macro_ptr, tokc);
3631 if (tok == TOK_LINENUM) {
3632 file->line_num = tokc.i;
3633 goto redo;
3636 } else {
3637 next_nomacro1();
3641 /* substitute args in macro_str and return allocated string */
3642 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3644 int *st, last_tok, t, notfirst;
3645 Sym *s;
3646 CValue cval;
3647 TokenString str;
3648 CString cstr;
3650 tok_str_new(&str);
3651 last_tok = 0;
3652 while(1) {
3653 TOK_GET(t, macro_str, cval);
3654 if (!t)
3655 break;
3656 if (t == '#') {
3657 /* stringize */
3658 TOK_GET(t, macro_str, cval);
3659 if (!t)
3660 break;
3661 s = sym_find2(args, t);
3662 if (s) {
3663 cstr_new(&cstr);
3664 st = (int *)s->c;
3665 notfirst = 0;
3666 while (*st) {
3667 if (notfirst)
3668 cstr_ccat(&cstr, ' ');
3669 TOK_GET(t, st, cval);
3670 cstr_cat(&cstr, get_tok_str(t, &cval));
3671 notfirst = 1;
3673 cstr_ccat(&cstr, '\0');
3674 #ifdef PP_DEBUG
3675 printf("stringize: %s\n", (char *)cstr.data);
3676 #endif
3677 /* add string */
3678 cval.cstr = &cstr;
3679 tok_str_add2(&str, TOK_STR, &cval);
3680 cstr_free(&cstr);
3681 } else {
3682 tok_str_add2(&str, t, &cval);
3684 } else if (t >= TOK_IDENT) {
3685 s = sym_find2(args, t);
3686 if (s) {
3687 st = (int *)s->c;
3688 /* if '##' is present before or after, no arg substitution */
3689 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3690 /* special case for var arg macros : ## eats the
3691 ',' if empty VA_ARGS variable. */
3692 /* XXX: test of the ',' is not 100%
3693 reliable. should fix it to avoid security
3694 problems */
3695 if (gnu_ext && s->type.t &&
3696 last_tok == TOK_TWOSHARPS &&
3697 str.len >= 2 && str.str[str.len - 2] == ',') {
3698 if (*st == 0) {
3699 /* suppress ',' '##' */
3700 str.len -= 2;
3701 } else {
3702 /* suppress '##' and add variable */
3703 str.len--;
3704 goto add_var;
3706 } else {
3707 int t1;
3708 add_var:
3709 for(;;) {
3710 TOK_GET(t1, st, cval);
3711 if (!t1)
3712 break;
3713 tok_str_add2(&str, t1, &cval);
3716 } else {
3717 /* NOTE: the stream cannot be read when macro
3718 substituing an argument */
3719 macro_subst(&str, nested_list, st, 0);
3721 } else {
3722 tok_str_add(&str, t);
3724 } else {
3725 tok_str_add2(&str, t, &cval);
3727 last_tok = t;
3729 tok_str_add(&str, 0);
3730 return str.str;
3733 static char const ab_month_name[12][4] =
3735 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3736 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3739 /* do macro substitution of current token with macro 's' and add
3740 result to (tok_str,tok_len). 'nested_list' is the list of all
3741 macros we got inside to avoid recursing. Return non zero if no
3742 substitution needs to be done */
3743 static int macro_subst_tok(TokenString *tok_str,
3744 Sym **nested_list, Sym *s, int can_read_stream)
3746 Sym *args, *sa, *sa1;
3747 int mstr_allocated, parlevel, *mstr, t;
3748 TokenString str;
3749 char *cstrval;
3750 CValue cval;
3751 CString cstr;
3753 /* if symbol is a macro, prepare substitution */
3755 /* special macros */
3756 if (tok == TOK___LINE__) {
3757 cval.i = file->line_num;
3758 tok_str_add2(tok_str, TOK_CINT, &cval);
3759 } else if (tok == TOK___FILE__) {
3760 cstrval = file->filename;
3761 goto add_cstr;
3762 tok_str_add2(tok_str, TOK_STR, &cval);
3763 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3764 time_t ti;
3765 struct tm *tm;
3766 char buf[64];
3768 time(&ti);
3769 tm = localtime(&ti);
3770 if (tok == TOK___DATE__) {
3771 snprintf(buf, sizeof(buf), "%s %2d %d",
3772 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3773 } else {
3774 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3775 tm->tm_hour, tm->tm_min, tm->tm_sec);
3777 cstrval = buf;
3778 add_cstr:
3779 cstr_new(&cstr);
3780 cstr_cat(&cstr, cstrval);
3781 cstr_ccat(&cstr, '\0');
3782 cval.cstr = &cstr;
3783 tok_str_add2(tok_str, TOK_STR, &cval);
3784 cstr_free(&cstr);
3785 } else {
3786 mstr = (int *)s->c;
3787 mstr_allocated = 0;
3788 if (s->type.t == MACRO_FUNC) {
3789 /* NOTE: we do not use next_nomacro to avoid eating the
3790 next token. XXX: find better solution */
3791 if (macro_ptr) {
3792 t = *macro_ptr;
3793 if (t == 0 && can_read_stream) {
3794 /* end of macro stream: we must look at the token
3795 after in the file */
3796 macro_ptr = NULL;
3797 goto parse_stream;
3799 } else {
3800 parse_stream:
3801 /* XXX: incorrect with comments */
3802 ch = file->buf_ptr[0];
3803 while (is_space(ch) || ch == '\n')
3804 cinp();
3805 t = ch;
3807 if (t != '(') /* no macro subst */
3808 return -1;
3810 /* argument macro */
3811 next_nomacro();
3812 next_nomacro();
3813 args = NULL;
3814 sa = s->next;
3815 /* NOTE: empty args are allowed, except if no args */
3816 for(;;) {
3817 /* handle '()' case */
3818 if (!args && !sa && tok == ')')
3819 break;
3820 if (!sa)
3821 error("macro '%s' used with too many args",
3822 get_tok_str(s->v, 0));
3823 tok_str_new(&str);
3824 parlevel = 0;
3825 /* NOTE: non zero sa->t indicates VA_ARGS */
3826 while ((parlevel > 0 ||
3827 (tok != ')' &&
3828 (tok != ',' || sa->type.t))) &&
3829 tok != -1) {
3830 if (tok == '(')
3831 parlevel++;
3832 else if (tok == ')')
3833 parlevel--;
3834 tok_str_add2(&str, tok, &tokc);
3835 next_nomacro();
3837 tok_str_add(&str, 0);
3838 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3839 sa = sa->next;
3840 if (tok == ')') {
3841 /* special case for gcc var args: add an empty
3842 var arg argument if it is omitted */
3843 if (sa && sa->type.t && gnu_ext)
3844 continue;
3845 else
3846 break;
3848 if (tok != ',')
3849 expect(",");
3850 next_nomacro();
3852 if (sa) {
3853 error("macro '%s' used with too few args",
3854 get_tok_str(s->v, 0));
3857 /* now subst each arg */
3858 mstr = macro_arg_subst(nested_list, mstr, args);
3859 /* free memory */
3860 sa = args;
3861 while (sa) {
3862 sa1 = sa->prev;
3863 tok_str_free((int *)sa->c);
3864 tcc_free(sa);
3865 sa = sa1;
3867 mstr_allocated = 1;
3869 sym_push2(nested_list, s->v, 0, 0);
3870 macro_subst(tok_str, nested_list, mstr, 1);
3871 /* pop nested defined symbol */
3872 sa1 = *nested_list;
3873 *nested_list = sa1->prev;
3874 tcc_free(sa1);
3875 if (mstr_allocated)
3876 tok_str_free(mstr);
3878 return 0;
3881 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3882 return the resulting string (which must be freed). */
3883 static inline int *macro_twosharps(const int *macro_str)
3885 TokenSym *ts;
3886 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3887 int t;
3888 const char *p1, *p2;
3889 CValue cval;
3890 TokenString macro_str1;
3891 CString cstr;
3893 start_macro_ptr = macro_str;
3894 /* we search the first '##' */
3895 for(;;) {
3896 macro_ptr1 = macro_str;
3897 TOK_GET(t, macro_str, cval);
3898 /* nothing more to do if end of string */
3899 if (t == 0)
3900 return NULL;
3901 if (*macro_str == TOK_TWOSHARPS)
3902 break;
3905 /* we saw '##', so we need more processing to handle it */
3906 cstr_new(&cstr);
3907 tok_str_new(&macro_str1);
3908 tok = t;
3909 tokc = cval;
3911 /* add all tokens seen so far */
3912 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3913 TOK_GET(t, ptr, cval);
3914 tok_str_add2(&macro_str1, t, &cval);
3916 saved_macro_ptr = macro_ptr;
3917 /* XXX: get rid of the use of macro_ptr here */
3918 macro_ptr = (int *)macro_str;
3919 for(;;) {
3920 while (*macro_ptr == TOK_TWOSHARPS) {
3921 macro_ptr++;
3922 macro_ptr1 = macro_ptr;
3923 t = *macro_ptr;
3924 if (t) {
3925 TOK_GET(t, macro_ptr, cval);
3926 /* We concatenate the two tokens if we have an
3927 identifier or a preprocessing number */
3928 cstr_reset(&cstr);
3929 p1 = get_tok_str(tok, &tokc);
3930 cstr_cat(&cstr, p1);
3931 p2 = get_tok_str(t, &cval);
3932 cstr_cat(&cstr, p2);
3933 cstr_ccat(&cstr, '\0');
3935 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3936 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3937 if (tok == TOK_PPNUM) {
3938 /* if number, then create a number token */
3939 /* NOTE: no need to allocate because
3940 tok_str_add2() does it */
3941 tokc.cstr = &cstr;
3942 } else {
3943 /* if identifier, we must do a test to
3944 validate we have a correct identifier */
3945 if (t == TOK_PPNUM) {
3946 const char *p;
3947 int c;
3949 p = p2;
3950 for(;;) {
3951 c = *p;
3952 if (c == '\0')
3953 break;
3954 p++;
3955 if (!isnum(c) && !isid(c))
3956 goto error_pasting;
3959 ts = tok_alloc(cstr.data, strlen(cstr.data));
3960 tok = ts->tok; /* modify current token */
3962 } else {
3963 const char *str = cstr.data;
3964 const unsigned char *q;
3966 /* we look for a valid token */
3967 /* XXX: do more extensive checks */
3968 if (!strcmp(str, ">>=")) {
3969 tok = TOK_A_SAR;
3970 } else if (!strcmp(str, "<<=")) {
3971 tok = TOK_A_SHL;
3972 } else if (strlen(str) == 2) {
3973 /* search in two bytes table */
3974 q = tok_two_chars;
3975 for(;;) {
3976 if (!*q)
3977 goto error_pasting;
3978 if (q[0] == str[0] && q[1] == str[1])
3979 break;
3980 q += 3;
3982 tok = q[2];
3983 } else {
3984 error_pasting:
3985 /* NOTE: because get_tok_str use a static buffer,
3986 we must save it */
3987 cstr_reset(&cstr);
3988 p1 = get_tok_str(tok, &tokc);
3989 cstr_cat(&cstr, p1);
3990 cstr_ccat(&cstr, '\0');
3991 p2 = get_tok_str(t, &cval);
3992 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3993 /* cannot merge tokens: just add them separately */
3994 tok_str_add2(&macro_str1, tok, &tokc);
3995 /* XXX: free associated memory ? */
3996 tok = t;
3997 tokc = cval;
4002 tok_str_add2(&macro_str1, tok, &tokc);
4003 next_nomacro();
4004 if (tok == 0)
4005 break;
4007 macro_ptr = (int *)saved_macro_ptr;
4008 cstr_free(&cstr);
4009 tok_str_add(&macro_str1, 0);
4010 return macro_str1.str;
4014 /* do macro substitution of macro_str and add result to
4015 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4016 inside to avoid recursing. */
4017 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4018 const int *macro_str, int can_read_stream)
4020 Sym *s;
4021 int *saved_macro_ptr, *macro_str1;
4022 const int *ptr;
4023 int t, ret;
4024 CValue cval;
4026 /* first scan for '##' operator handling */
4027 ptr = macro_str;
4028 macro_str1 = macro_twosharps(ptr);
4029 if (macro_str1)
4030 ptr = macro_str1;
4031 while (1) {
4032 /* NOTE: ptr == NULL can only happen if tokens are read from
4033 file stream due to a macro function call */
4034 if (ptr == NULL)
4035 break;
4036 TOK_GET(t, ptr, cval);
4037 if (t == 0)
4038 break;
4039 s = define_find(t);
4040 if (s != NULL) {
4041 /* if nested substitution, do nothing */
4042 if (sym_find2(*nested_list, t))
4043 goto no_subst;
4044 saved_macro_ptr = macro_ptr;
4045 macro_ptr = (int *)ptr;
4046 tok = t;
4047 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4048 ptr = (int *)macro_ptr;
4049 macro_ptr = saved_macro_ptr;
4050 if (ret != 0)
4051 goto no_subst;
4052 } else {
4053 no_subst:
4054 tok_str_add2(tok_str, t, &cval);
4057 if (macro_str1)
4058 tok_str_free(macro_str1);
4061 /* return next token with macro substitution */
4062 static void next(void)
4064 Sym *nested_list, *s;
4065 TokenString str;
4067 redo:
4068 next_nomacro();
4069 if (!macro_ptr) {
4070 /* if not reading from macro substituted string, then try
4071 to substitute macros */
4072 if (tok >= TOK_IDENT &&
4073 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4074 s = define_find(tok);
4075 if (s) {
4076 /* we have a macro: we try to substitute */
4077 tok_str_new(&str);
4078 nested_list = NULL;
4079 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4080 /* substitution done, NOTE: maybe empty */
4081 tok_str_add(&str, 0);
4082 macro_ptr = str.str;
4083 macro_ptr_allocated = str.str;
4084 goto redo;
4088 } else {
4089 if (tok == 0) {
4090 /* end of macro or end of unget buffer */
4091 if (unget_buffer_enabled) {
4092 macro_ptr = unget_saved_macro_ptr;
4093 unget_buffer_enabled = 0;
4094 } else {
4095 /* end of macro string: free it */
4096 tok_str_free(macro_ptr_allocated);
4097 macro_ptr = NULL;
4099 goto redo;
4103 /* convert preprocessor tokens into C tokens */
4104 if (tok == TOK_PPNUM &&
4105 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4106 parse_number((char *)tokc.cstr->data);
4110 /* push back current token and set current token to 'last_tok'. Only
4111 identifier case handled for labels. */
4112 static inline void unget_tok(int last_tok)
4114 int i, n;
4115 int *q;
4116 unget_saved_macro_ptr = macro_ptr;
4117 unget_buffer_enabled = 1;
4118 q = unget_saved_buffer;
4119 macro_ptr = q;
4120 *q++ = tok;
4121 n = tok_ext_size(tok) - 1;
4122 for(i=0;i<n;i++)
4123 *q++ = tokc.tab[i];
4124 *q = 0; /* end of token string */
4125 tok = last_tok;
4129 void swap(int *p, int *q)
4131 int t;
4132 t = *p;
4133 *p = *q;
4134 *q = t;
4137 void vsetc(CType *type, int r, CValue *vc)
4139 int v;
4141 if (vtop >= vstack + VSTACK_SIZE)
4142 error("memory full");
4143 /* cannot let cpu flags if other instruction are generated. Also
4144 avoid leaving VT_JMP anywhere except on the top of the stack
4145 because it would complicate the code generator. */
4146 if (vtop >= vstack) {
4147 v = vtop->r & VT_VALMASK;
4148 if (v == VT_CMP || (v & ~1) == VT_JMP)
4149 gv(RC_INT);
4151 vtop++;
4152 vtop->type = *type;
4153 vtop->r = r;
4154 vtop->r2 = VT_CONST;
4155 vtop->c = *vc;
4158 /* push integer constant */
4159 void vpushi(int v)
4161 CValue cval;
4162 cval.i = v;
4163 vsetc(&int_type, VT_CONST, &cval);
4166 /* Return a static symbol pointing to a section */
4167 static Sym *get_sym_ref(CType *type, Section *sec,
4168 unsigned long offset, unsigned long size)
4170 int v;
4171 Sym *sym;
4173 v = anon_sym++;
4174 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4175 sym->type.ref = type->ref;
4176 sym->r = VT_CONST | VT_SYM;
4177 put_extern_sym(sym, sec, offset, size);
4178 return sym;
4181 /* push a reference to a section offset by adding a dummy symbol */
4182 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4184 CValue cval;
4186 cval.ul = 0;
4187 vsetc(type, VT_CONST | VT_SYM, &cval);
4188 vtop->sym = get_sym_ref(type, sec, offset, size);
4191 /* define a new external reference to a symbol 'v' of type 'u' */
4192 static Sym *external_global_sym(int v, CType *type, int r)
4194 Sym *s;
4196 s = sym_find(v);
4197 if (!s) {
4198 /* push forward reference */
4199 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4200 s->type.ref = type->ref;
4201 s->r = r | VT_CONST | VT_SYM;
4203 return s;
4206 /* define a new external reference to a symbol 'v' of type 'u' */
4207 static Sym *external_sym(int v, CType *type, int r)
4209 Sym *s;
4211 s = sym_find(v);
4212 if (!s) {
4213 /* push forward reference */
4214 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4215 s->type.t |= VT_EXTERN;
4216 } else {
4217 if (!is_compatible_types(&s->type, type))
4218 error("incompatible types for redefinition of '%s'",
4219 get_tok_str(v, NULL));
4221 return s;
4224 /* push a reference to global symbol v */
4225 static void vpush_global_sym(CType *type, int v)
4227 Sym *sym;
4228 CValue cval;
4230 sym = external_global_sym(v, type, 0);
4231 cval.ul = 0;
4232 vsetc(type, VT_CONST | VT_SYM, &cval);
4233 vtop->sym = sym;
4236 void vset(CType *type, int r, int v)
4238 CValue cval;
4240 cval.i = v;
4241 vsetc(type, r, &cval);
4244 void vseti(int r, int v)
4246 CType type;
4247 type.t = VT_INT;
4248 vset(&type, r, v);
4251 void vswap(void)
4253 SValue tmp;
4255 tmp = vtop[0];
4256 vtop[0] = vtop[-1];
4257 vtop[-1] = tmp;
4260 void vpushv(SValue *v)
4262 if (vtop >= vstack + VSTACK_SIZE)
4263 error("memory full");
4264 vtop++;
4265 *vtop = *v;
4268 void vdup(void)
4270 vpushv(vtop);
4273 /* save r to the memory stack, and mark it as being free */
4274 void save_reg(int r)
4276 int l, saved, size, align;
4277 SValue *p, sv;
4278 CType *type;
4280 /* modify all stack values */
4281 saved = 0;
4282 l = 0;
4283 for(p=vstack;p<=vtop;p++) {
4284 if ((p->r & VT_VALMASK) == r ||
4285 (p->r2 & VT_VALMASK) == r) {
4286 /* must save value on stack if not already done */
4287 if (!saved) {
4288 /* NOTE: must reload 'r' because r might be equal to r2 */
4289 r = p->r & VT_VALMASK;
4290 /* store register in the stack */
4291 type = &p->type;
4292 if ((p->r & VT_LVAL) ||
4293 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4294 type = &int_type;
4295 size = type_size(type, &align);
4296 loc = (loc - size) & -align;
4297 sv.type.t = type->t;
4298 sv.r = VT_LOCAL | VT_LVAL;
4299 sv.c.ul = loc;
4300 store(r, &sv);
4301 #ifdef TCC_TARGET_I386
4302 /* x86 specific: need to pop fp register ST0 if saved */
4303 if (r == TREG_ST0) {
4304 o(0xd9dd); /* fstp %st(1) */
4306 #endif
4307 /* special long long case */
4308 if ((type->t & VT_BTYPE) == VT_LLONG) {
4309 sv.c.ul += 4;
4310 store(p->r2, &sv);
4312 l = loc;
4313 saved = 1;
4315 /* mark that stack entry as being saved on the stack */
4316 if (p->r & VT_LVAL) {
4317 /* also clear the bounded flag because the
4318 relocation address of the function was stored in
4319 p->c.ul */
4320 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4321 } else {
4322 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4324 p->r2 = VT_CONST;
4325 p->c.ul = l;
4330 /* find a free register of class 'rc'. If none, save one register */
4331 int get_reg(int rc)
4333 int r;
4334 SValue *p;
4336 /* find a free register */
4337 for(r=0;r<NB_REGS;r++) {
4338 if (reg_classes[r] & rc) {
4339 for(p=vstack;p<=vtop;p++) {
4340 if ((p->r & VT_VALMASK) == r ||
4341 (p->r2 & VT_VALMASK) == r)
4342 goto notfound;
4344 return r;
4346 notfound: ;
4349 /* no register left : free the first one on the stack (VERY
4350 IMPORTANT to start from the bottom to ensure that we don't
4351 spill registers used in gen_opi()) */
4352 for(p=vstack;p<=vtop;p++) {
4353 r = p->r & VT_VALMASK;
4354 if (r < VT_CONST && (reg_classes[r] & rc))
4355 goto save_found;
4356 /* also look at second register (if long long) */
4357 r = p->r2 & VT_VALMASK;
4358 if (r < VT_CONST && (reg_classes[r] & rc)) {
4359 save_found:
4360 save_reg(r);
4361 return r;
4364 /* Should never comes here */
4365 return -1;
4368 /* save registers up to (vtop - n) stack entry */
4369 void save_regs(int n)
4371 int r;
4372 SValue *p, *p1;
4373 p1 = vtop - n;
4374 for(p = vstack;p <= p1; p++) {
4375 r = p->r & VT_VALMASK;
4376 if (r < VT_CONST) {
4377 save_reg(r);
4382 /* move register 's' to 'r', and flush previous value of r to memory
4383 if needed */
4384 void move_reg(int r, int s)
4386 SValue sv;
4388 if (r != s) {
4389 save_reg(r);
4390 sv.type.t = VT_INT;
4391 sv.r = s;
4392 sv.c.ul = 0;
4393 load(r, &sv);
4397 /* get address of vtop (vtop MUST BE an lvalue) */
4398 void gaddrof(void)
4400 vtop->r &= ~VT_LVAL;
4401 /* tricky: if saved lvalue, then we can go back to lvalue */
4402 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4403 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4406 #ifdef CONFIG_TCC_BCHECK
4407 /* generate lvalue bound code */
4408 void gbound(void)
4410 int lval_type;
4411 CType type1;
4413 vtop->r &= ~VT_MUSTBOUND;
4414 /* if lvalue, then use checking code before dereferencing */
4415 if (vtop->r & VT_LVAL) {
4416 /* if not VT_BOUNDED value, then make one */
4417 if (!(vtop->r & VT_BOUNDED)) {
4418 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4419 /* must save type because we must set it to int to get pointer */
4420 type1 = vtop->type;
4421 vtop->type.t = VT_INT;
4422 gaddrof();
4423 vpushi(0);
4424 gen_bounded_ptr_add();
4425 vtop->r |= lval_type;
4426 vtop->type = type1;
4428 /* then check for dereferencing */
4429 gen_bounded_ptr_deref();
4432 #endif
4434 /* store vtop a register belonging to class 'rc'. lvalues are
4435 converted to values. Cannot be used if cannot be converted to
4436 register value (such as structures). */
4437 int gv(int rc)
4439 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4440 unsigned long long ll;
4442 /* NOTE: get_reg can modify vstack[] */
4443 if (vtop->type.t & VT_BITFIELD) {
4444 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4445 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4446 /* remove bit field info to avoid loops */
4447 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4448 /* generate shifts */
4449 vpushi(32 - (bit_pos + bit_size));
4450 gen_op(TOK_SHL);
4451 vpushi(32 - bit_size);
4452 /* NOTE: transformed to SHR if unsigned */
4453 gen_op(TOK_SAR);
4454 r = gv(rc);
4455 } else {
4456 if (is_float(vtop->type.t) &&
4457 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4458 Sym *sym;
4459 int *ptr;
4460 unsigned long offset;
4462 /* XXX: unify with initializers handling ? */
4463 /* CPUs usually cannot use float constants, so we store them
4464 generically in data segment */
4465 size = type_size(&vtop->type, &align);
4466 offset = (data_section->data_offset + align - 1) & -align;
4467 data_section->data_offset = offset;
4468 /* XXX: not portable yet */
4469 ptr = section_ptr_add(data_section, size);
4470 size = size >> 2;
4471 for(i=0;i<size;i++)
4472 ptr[i] = vtop->c.tab[i];
4473 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4474 vtop->r |= VT_LVAL | VT_SYM;
4475 vtop->sym = sym;
4476 vtop->c.ul = 0;
4478 #ifdef CONFIG_TCC_BCHECK
4479 if (vtop->r & VT_MUSTBOUND)
4480 gbound();
4481 #endif
4483 r = vtop->r & VT_VALMASK;
4484 /* need to reload if:
4485 - constant
4486 - lvalue (need to dereference pointer)
4487 - already a register, but not in the right class */
4488 if (r >= VT_CONST ||
4489 (vtop->r & VT_LVAL) ||
4490 !(reg_classes[r] & rc) ||
4491 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4492 !(reg_classes[vtop->r2] & rc))) {
4493 r = get_reg(rc);
4494 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4495 /* two register type load : expand to two words
4496 temporarily */
4497 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4498 /* load constant */
4499 ll = vtop->c.ull;
4500 vtop->c.ui = ll; /* first word */
4501 load(r, vtop);
4502 vtop->r = r; /* save register value */
4503 vpushi(ll >> 32); /* second word */
4504 } else if (r >= VT_CONST ||
4505 (vtop->r & VT_LVAL)) {
4506 /* load from memory */
4507 load(r, vtop);
4508 vdup();
4509 vtop[-1].r = r; /* save register value */
4510 /* increment pointer to get second word */
4511 vtop->type.t = VT_INT;
4512 gaddrof();
4513 vpushi(4);
4514 gen_op('+');
4515 vtop->r |= VT_LVAL;
4516 } else {
4517 /* move registers */
4518 load(r, vtop);
4519 vdup();
4520 vtop[-1].r = r; /* save register value */
4521 vtop->r = vtop[-1].r2;
4523 /* allocate second register */
4524 rc2 = RC_INT;
4525 if (rc == RC_IRET)
4526 rc2 = RC_LRET;
4527 r2 = get_reg(rc2);
4528 load(r2, vtop);
4529 vpop();
4530 /* write second register */
4531 vtop->r2 = r2;
4532 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4533 int t1, t;
4534 /* lvalue of scalar type : need to use lvalue type
4535 because of possible cast */
4536 t = vtop->type.t;
4537 t1 = t;
4538 /* compute memory access type */
4539 if (vtop->r & VT_LVAL_BYTE)
4540 t = VT_BYTE;
4541 else if (vtop->r & VT_LVAL_SHORT)
4542 t = VT_SHORT;
4543 if (vtop->r & VT_LVAL_UNSIGNED)
4544 t |= VT_UNSIGNED;
4545 vtop->type.t = t;
4546 load(r, vtop);
4547 /* restore wanted type */
4548 vtop->type.t = t1;
4549 } else {
4550 /* one register type load */
4551 load(r, vtop);
4554 vtop->r = r;
4556 return r;
4559 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4560 void gv2(int rc1, int rc2)
4562 int v;
4564 /* generate more generic register first. But VT_JMP or VT_CMP
4565 values must be generated first in all cases to avoid possible
4566 reload errors */
4567 v = vtop[0].r & VT_VALMASK;
4568 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4569 vswap();
4570 gv(rc1);
4571 vswap();
4572 gv(rc2);
4573 /* test if reload is needed for first register */
4574 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4575 vswap();
4576 gv(rc1);
4577 vswap();
4579 } else {
4580 gv(rc2);
4581 vswap();
4582 gv(rc1);
4583 vswap();
4584 /* test if reload is needed for first register */
4585 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4586 gv(rc2);
4591 /* expand long long on stack in two int registers */
4592 void lexpand(void)
4594 int u;
4596 u = vtop->type.t & VT_UNSIGNED;
4597 gv(RC_INT);
4598 vdup();
4599 vtop[0].r = vtop[-1].r2;
4600 vtop[0].r2 = VT_CONST;
4601 vtop[-1].r2 = VT_CONST;
4602 vtop[0].type.t = VT_INT | u;
4603 vtop[-1].type.t = VT_INT | u;
4606 /* build a long long from two ints */
4607 void lbuild(int t)
4609 gv2(RC_INT, RC_INT);
4610 vtop[-1].r2 = vtop[0].r;
4611 vtop[-1].type.t = t;
4612 vpop();
4615 /* rotate n first stack elements to the bottom
4616 I1 ... In -> I2 ... In I1 [top is right]
4618 void vrotb(int n)
4620 int i;
4621 SValue tmp;
4623 tmp = vtop[-n + 1];
4624 for(i=-n+1;i!=0;i++)
4625 vtop[i] = vtop[i+1];
4626 vtop[0] = tmp;
4629 /* rotate n first stack elements to the top
4630 I1 ... In -> In I1 ... I(n-1) [top is right]
4632 void vrott(int n)
4634 int i;
4635 SValue tmp;
4637 tmp = vtop[0];
4638 for(i = 0;i < n - 1; i++)
4639 vtop[-i] = vtop[-i - 1];
4640 vtop[-n + 1] = tmp;
4643 /* pop stack value */
4644 void vpop(void)
4646 int v;
4647 v = vtop->r & VT_VALMASK;
4648 #ifdef TCC_TARGET_I386
4649 /* for x86, we need to pop the FP stack */
4650 if (v == TREG_ST0 && !nocode_wanted) {
4651 o(0xd9dd); /* fstp %st(1) */
4652 } else
4653 #endif
4654 if (v == VT_JMP || v == VT_JMPI) {
4655 /* need to put correct jump if && or || without test */
4656 gsym(vtop->c.ul);
4658 vtop--;
4661 /* convert stack entry to register and duplicate its value in another
4662 register */
4663 void gv_dup(void)
4665 int rc, t, r, r1;
4666 SValue sv;
4668 t = vtop->type.t;
4669 if ((t & VT_BTYPE) == VT_LLONG) {
4670 lexpand();
4671 gv_dup();
4672 vswap();
4673 vrotb(3);
4674 gv_dup();
4675 vrotb(4);
4676 /* stack: H L L1 H1 */
4677 lbuild(t);
4678 vrotb(3);
4679 vrotb(3);
4680 vswap();
4681 lbuild(t);
4682 vswap();
4683 } else {
4684 /* duplicate value */
4685 rc = RC_INT;
4686 sv.type.t = VT_INT;
4687 if (is_float(t)) {
4688 rc = RC_FLOAT;
4689 sv.type.t = t;
4691 r = gv(rc);
4692 r1 = get_reg(rc);
4693 sv.r = r;
4694 sv.c.ul = 0;
4695 load(r1, &sv); /* move r to r1 */
4696 vdup();
4697 /* duplicates value */
4698 vtop->r = r1;
4702 /* generate CPU independent (unsigned) long long operations */
4703 void gen_opl(int op)
4705 int t, a, b, op1, c, i;
4706 int func;
4707 SValue tmp;
4709 switch(op) {
4710 case '/':
4711 case TOK_PDIV:
4712 func = TOK___divdi3;
4713 goto gen_func;
4714 case TOK_UDIV:
4715 func = TOK___udivdi3;
4716 goto gen_func;
4717 case '%':
4718 func = TOK___moddi3;
4719 goto gen_func;
4720 case TOK_UMOD:
4721 func = TOK___umoddi3;
4722 gen_func:
4723 /* call generic long long function */
4724 vpush_global_sym(&func_old_type, func);
4725 vrott(3);
4726 gfunc_call(2);
4727 vpushi(0);
4728 vtop->r = REG_IRET;
4729 vtop->r2 = REG_LRET;
4730 break;
4731 case '^':
4732 case '&':
4733 case '|':
4734 case '*':
4735 case '+':
4736 case '-':
4737 t = vtop->type.t;
4738 vswap();
4739 lexpand();
4740 vrotb(3);
4741 lexpand();
4742 /* stack: L1 H1 L2 H2 */
4743 tmp = vtop[0];
4744 vtop[0] = vtop[-3];
4745 vtop[-3] = tmp;
4746 tmp = vtop[-2];
4747 vtop[-2] = vtop[-3];
4748 vtop[-3] = tmp;
4749 vswap();
4750 /* stack: H1 H2 L1 L2 */
4751 if (op == '*') {
4752 vpushv(vtop - 1);
4753 vpushv(vtop - 1);
4754 gen_op(TOK_UMULL);
4755 lexpand();
4756 /* stack: H1 H2 L1 L2 ML MH */
4757 for(i=0;i<4;i++)
4758 vrotb(6);
4759 /* stack: ML MH H1 H2 L1 L2 */
4760 tmp = vtop[0];
4761 vtop[0] = vtop[-2];
4762 vtop[-2] = tmp;
4763 /* stack: ML MH H1 L2 H2 L1 */
4764 gen_op('*');
4765 vrotb(3);
4766 vrotb(3);
4767 gen_op('*');
4768 /* stack: ML MH M1 M2 */
4769 gen_op('+');
4770 gen_op('+');
4771 } else if (op == '+' || op == '-') {
4772 /* XXX: add non carry method too (for MIPS or alpha) */
4773 if (op == '+')
4774 op1 = TOK_ADDC1;
4775 else
4776 op1 = TOK_SUBC1;
4777 gen_op(op1);
4778 /* stack: H1 H2 (L1 op L2) */
4779 vrotb(3);
4780 vrotb(3);
4781 gen_op(op1 + 1); /* TOK_xxxC2 */
4782 } else {
4783 gen_op(op);
4784 /* stack: H1 H2 (L1 op L2) */
4785 vrotb(3);
4786 vrotb(3);
4787 /* stack: (L1 op L2) H1 H2 */
4788 gen_op(op);
4789 /* stack: (L1 op L2) (H1 op H2) */
4791 /* stack: L H */
4792 lbuild(t);
4793 break;
4794 case TOK_SAR:
4795 case TOK_SHR:
4796 case TOK_SHL:
4797 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4798 t = vtop[-1].type.t;
4799 vswap();
4800 lexpand();
4801 vrotb(3);
4802 /* stack: L H shift */
4803 c = (int)vtop->c.i;
4804 /* constant: simpler */
4805 /* NOTE: all comments are for SHL. the other cases are
4806 done by swaping words */
4807 vpop();
4808 if (op != TOK_SHL)
4809 vswap();
4810 if (c >= 32) {
4811 /* stack: L H */
4812 vpop();
4813 if (c > 32) {
4814 vpushi(c - 32);
4815 gen_op(op);
4817 if (op != TOK_SAR) {
4818 vpushi(0);
4819 } else {
4820 gv_dup();
4821 vpushi(31);
4822 gen_op(TOK_SAR);
4824 vswap();
4825 } else {
4826 vswap();
4827 gv_dup();
4828 /* stack: H L L */
4829 vpushi(c);
4830 gen_op(op);
4831 vswap();
4832 vpushi(32 - c);
4833 if (op == TOK_SHL)
4834 gen_op(TOK_SHR);
4835 else
4836 gen_op(TOK_SHL);
4837 vrotb(3);
4838 /* stack: L L H */
4839 vpushi(c);
4840 if (op == TOK_SHL)
4841 gen_op(TOK_SHL);
4842 else
4843 gen_op(TOK_SHR);
4844 gen_op('|');
4846 if (op != TOK_SHL)
4847 vswap();
4848 lbuild(t);
4849 } else {
4850 /* XXX: should provide a faster fallback on x86 ? */
4851 switch(op) {
4852 case TOK_SAR:
4853 func = TOK___sardi3;
4854 goto gen_func;
4855 case TOK_SHR:
4856 func = TOK___shrdi3;
4857 goto gen_func;
4858 case TOK_SHL:
4859 func = TOK___shldi3;
4860 goto gen_func;
4863 break;
4864 default:
4865 /* compare operations */
4866 t = vtop->type.t;
4867 vswap();
4868 lexpand();
4869 vrotb(3);
4870 lexpand();
4871 /* stack: L1 H1 L2 H2 */
4872 tmp = vtop[-1];
4873 vtop[-1] = vtop[-2];
4874 vtop[-2] = tmp;
4875 /* stack: L1 L2 H1 H2 */
4876 /* compare high */
4877 op1 = op;
4878 /* when values are equal, we need to compare low words. since
4879 the jump is inverted, we invert the test too. */
4880 if (op1 == TOK_LT)
4881 op1 = TOK_LE;
4882 else if (op1 == TOK_GT)
4883 op1 = TOK_GE;
4884 else if (op1 == TOK_ULT)
4885 op1 = TOK_ULE;
4886 else if (op1 == TOK_UGT)
4887 op1 = TOK_UGE;
4888 a = 0;
4889 b = 0;
4890 gen_op(op1);
4891 if (op1 != TOK_NE) {
4892 a = gtst(1, 0);
4894 if (op != TOK_EQ) {
4895 /* generate non equal test */
4896 /* XXX: NOT PORTABLE yet */
4897 if (a == 0) {
4898 b = gtst(0, 0);
4899 } else {
4900 #ifdef TCC_TARGET_I386
4901 b = psym(0x850f, 0);
4902 #else
4903 error("not implemented");
4904 #endif
4907 /* compare low. Always unsigned */
4908 op1 = op;
4909 if (op1 == TOK_LT)
4910 op1 = TOK_ULT;
4911 else if (op1 == TOK_LE)
4912 op1 = TOK_ULE;
4913 else if (op1 == TOK_GT)
4914 op1 = TOK_UGT;
4915 else if (op1 == TOK_GE)
4916 op1 = TOK_UGE;
4917 gen_op(op1);
4918 a = gtst(1, a);
4919 gsym(b);
4920 vseti(VT_JMPI, a);
4921 break;
4925 /* handle integer constant optimizations and various machine
4926 independent opt */
4927 void gen_opic(int op)
4929 int fc, c1, c2, n;
4930 SValue *v1, *v2;
4932 v1 = vtop - 1;
4933 v2 = vtop;
4934 /* currently, we cannot do computations with forward symbols */
4935 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4936 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4937 if (c1 && c2) {
4938 fc = v2->c.i;
4939 switch(op) {
4940 case '+': v1->c.i += fc; break;
4941 case '-': v1->c.i -= fc; break;
4942 case '&': v1->c.i &= fc; break;
4943 case '^': v1->c.i ^= fc; break;
4944 case '|': v1->c.i |= fc; break;
4945 case '*': v1->c.i *= fc; break;
4947 case TOK_PDIV:
4948 case '/':
4949 case '%':
4950 case TOK_UDIV:
4951 case TOK_UMOD:
4952 /* if division by zero, generate explicit division */
4953 if (fc == 0) {
4954 if (const_wanted)
4955 error("division by zero in constant");
4956 goto general_case;
4958 switch(op) {
4959 default: v1->c.i /= fc; break;
4960 case '%': v1->c.i %= fc; break;
4961 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4962 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4964 break;
4965 case TOK_SHL: v1->c.i <<= fc; break;
4966 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4967 case TOK_SAR: v1->c.i >>= fc; break;
4968 /* tests */
4969 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4970 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4971 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4972 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4973 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4974 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4975 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4976 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4977 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4978 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4979 /* logical */
4980 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4981 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4982 default:
4983 goto general_case;
4985 vtop--;
4986 } else {
4987 /* if commutative ops, put c2 as constant */
4988 if (c1 && (op == '+' || op == '&' || op == '^' ||
4989 op == '|' || op == '*')) {
4990 vswap();
4991 swap(&c1, &c2);
4993 fc = vtop->c.i;
4994 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4995 op == TOK_PDIV) &&
4996 fc == 1) ||
4997 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4998 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4999 fc == 0) ||
5000 (op == '&' &&
5001 fc == -1))) {
5002 /* nothing to do */
5003 vtop--;
5004 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5005 /* try to use shifts instead of muls or divs */
5006 if (fc > 0 && (fc & (fc - 1)) == 0) {
5007 n = -1;
5008 while (fc) {
5009 fc >>= 1;
5010 n++;
5012 vtop->c.i = n;
5013 if (op == '*')
5014 op = TOK_SHL;
5015 else if (op == TOK_PDIV)
5016 op = TOK_SAR;
5017 else
5018 op = TOK_SHR;
5020 goto general_case;
5021 } else if (c2 && (op == '+' || op == '-') &&
5022 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5023 (VT_CONST | VT_SYM)) {
5024 /* symbol + constant case */
5025 if (op == '-')
5026 fc = -fc;
5027 vtop--;
5028 vtop->c.i += fc;
5029 } else {
5030 general_case:
5031 if (!nocode_wanted) {
5032 /* call low level op generator */
5033 gen_opi(op);
5034 } else {
5035 vtop--;
5041 /* generate a floating point operation with constant propagation */
5042 void gen_opif(int op)
5044 int c1, c2;
5045 SValue *v1, *v2;
5046 long double f1, f2;
5048 v1 = vtop - 1;
5049 v2 = vtop;
5050 /* currently, we cannot do computations with forward symbols */
5051 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5052 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5053 if (c1 && c2) {
5054 if (v1->type.t == VT_FLOAT) {
5055 f1 = v1->c.f;
5056 f2 = v2->c.f;
5057 } else if (v1->type.t == VT_DOUBLE) {
5058 f1 = v1->c.d;
5059 f2 = v2->c.d;
5060 } else {
5061 f1 = v1->c.ld;
5062 f2 = v2->c.ld;
5065 /* NOTE: we only do constant propagation if finite number (not
5066 NaN or infinity) (ANSI spec) */
5067 if (!ieee_finite(f1) || !ieee_finite(f2))
5068 goto general_case;
5070 switch(op) {
5071 case '+': f1 += f2; break;
5072 case '-': f1 -= f2; break;
5073 case '*': f1 *= f2; break;
5074 case '/':
5075 if (f2 == 0.0) {
5076 if (const_wanted)
5077 error("division by zero in constant");
5078 goto general_case;
5080 f1 /= f2;
5081 break;
5082 /* XXX: also handles tests ? */
5083 default:
5084 goto general_case;
5086 /* XXX: overflow test ? */
5087 if (v1->type.t == VT_FLOAT) {
5088 v1->c.f = f1;
5089 } else if (v1->type.t == VT_DOUBLE) {
5090 v1->c.d = f1;
5091 } else {
5092 v1->c.ld = f1;
5094 vtop--;
5095 } else {
5096 general_case:
5097 if (!nocode_wanted) {
5098 gen_opf(op);
5099 } else {
5100 vtop--;
5105 static int pointed_size(CType *type)
5107 int align;
5108 return type_size(pointed_type(type), &align);
5111 static inline int is_null_pointer(SValue *p)
5113 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5114 return 0;
5115 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5116 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5119 static inline int is_integer_btype(int bt)
5121 return (bt == VT_BYTE || bt == VT_SHORT ||
5122 bt == VT_INT || bt == VT_LLONG);
5125 /* check types for comparison or substraction of pointers */
5126 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5128 CType *type1, *type2, tmp_type1, tmp_type2;
5129 int bt1, bt2;
5131 /* null pointers are accepted for all comparisons as gcc */
5132 if (is_null_pointer(p1) || is_null_pointer(p2))
5133 return;
5134 type1 = &p1->type;
5135 type2 = &p2->type;
5136 bt1 = type1->t & VT_BTYPE;
5137 bt2 = type2->t & VT_BTYPE;
5138 /* accept comparison between pointer and integer with a warning */
5139 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5140 warning("comparison between pointer and integer");
5141 return;
5144 /* both must be pointers or implicit function pointers */
5145 if (bt1 == VT_PTR) {
5146 type1 = pointed_type(type1);
5147 } else if (bt1 != VT_FUNC)
5148 goto invalid_operands;
5150 if (bt2 == VT_PTR) {
5151 type2 = pointed_type(type2);
5152 } else if (bt2 != VT_FUNC) {
5153 invalid_operands:
5154 error("invalid operands to binary %s", get_tok_str(op, NULL));
5156 if ((type1->t & VT_BTYPE) == VT_VOID ||
5157 (type2->t & VT_BTYPE) == VT_VOID)
5158 return;
5159 tmp_type1 = *type1;
5160 tmp_type2 = *type2;
5161 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5162 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5163 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5164 /* gcc-like error if '-' is used */
5165 if (op == '-')
5166 goto invalid_operands;
5167 else
5168 warning("comparison of distinct pointer types lacks a cast");
5172 /* generic gen_op: handles types problems */
5173 void gen_op(int op)
5175 int u, t1, t2, bt1, bt2, t;
5176 CType type1;
5178 t1 = vtop[-1].type.t;
5179 t2 = vtop[0].type.t;
5180 bt1 = t1 & VT_BTYPE;
5181 bt2 = t2 & VT_BTYPE;
5183 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5184 /* at least one operand is a pointer */
5185 /* relationnal op: must be both pointers */
5186 if (op >= TOK_ULT && op <= TOK_GT) {
5187 check_comparison_pointer_types(vtop - 1, vtop, op);
5188 /* pointers are handled are unsigned */
5189 t = VT_INT | VT_UNSIGNED;
5190 goto std_op;
5192 /* if both pointers, then it must be the '-' op */
5193 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5194 if (op != '-')
5195 error("cannot use pointers here");
5196 check_comparison_pointer_types(vtop - 1, vtop, op);
5197 /* XXX: check that types are compatible */
5198 u = pointed_size(&vtop[-1].type);
5199 gen_opic(op);
5200 /* set to integer type */
5201 vtop->type.t = VT_INT;
5202 vpushi(u);
5203 gen_op(TOK_PDIV);
5204 } else {
5205 /* exactly one pointer : must be '+' or '-'. */
5206 if (op != '-' && op != '+')
5207 error("cannot use pointers here");
5208 /* Put pointer as first operand */
5209 if (bt2 == VT_PTR) {
5210 vswap();
5211 swap(&t1, &t2);
5213 type1 = vtop[-1].type;
5214 /* XXX: cast to int ? (long long case) */
5215 vpushi(pointed_size(&vtop[-1].type));
5216 gen_op('*');
5217 #ifdef CONFIG_TCC_BCHECK
5218 /* if evaluating constant expression, no code should be
5219 generated, so no bound check */
5220 if (do_bounds_check && !const_wanted) {
5221 /* if bounded pointers, we generate a special code to
5222 test bounds */
5223 if (op == '-') {
5224 vpushi(0);
5225 vswap();
5226 gen_op('-');
5228 gen_bounded_ptr_add();
5229 } else
5230 #endif
5232 gen_opic(op);
5234 /* put again type if gen_opic() swaped operands */
5235 vtop->type = type1;
5237 } else if (is_float(bt1) || is_float(bt2)) {
5238 /* compute bigger type and do implicit casts */
5239 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5240 t = VT_LDOUBLE;
5241 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5242 t = VT_DOUBLE;
5243 } else {
5244 t = VT_FLOAT;
5246 /* floats can only be used for a few operations */
5247 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5248 (op < TOK_ULT || op > TOK_GT))
5249 error("invalid operands for binary operation");
5250 goto std_op;
5251 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5252 /* cast to biggest op */
5253 t = VT_LLONG;
5254 /* convert to unsigned if it does not fit in a long long */
5255 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5256 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5257 t |= VT_UNSIGNED;
5258 goto std_op;
5259 } else {
5260 /* integer operations */
5261 t = VT_INT;
5262 /* convert to unsigned if it does not fit in an integer */
5263 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5264 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5265 t |= VT_UNSIGNED;
5266 std_op:
5267 /* XXX: currently, some unsigned operations are explicit, so
5268 we modify them here */
5269 if (t & VT_UNSIGNED) {
5270 if (op == TOK_SAR)
5271 op = TOK_SHR;
5272 else if (op == '/')
5273 op = TOK_UDIV;
5274 else if (op == '%')
5275 op = TOK_UMOD;
5276 else if (op == TOK_LT)
5277 op = TOK_ULT;
5278 else if (op == TOK_GT)
5279 op = TOK_UGT;
5280 else if (op == TOK_LE)
5281 op = TOK_ULE;
5282 else if (op == TOK_GE)
5283 op = TOK_UGE;
5285 vswap();
5286 type1.t = t;
5287 gen_cast(&type1);
5288 vswap();
5289 /* special case for shifts and long long: we keep the shift as
5290 an integer */
5291 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5292 type1.t = VT_INT;
5293 gen_cast(&type1);
5294 if (is_float(t))
5295 gen_opif(op);
5296 else if ((t & VT_BTYPE) == VT_LLONG)
5297 gen_opl(op);
5298 else
5299 gen_opic(op);
5300 if (op >= TOK_ULT && op <= TOK_GT) {
5301 /* relationnal op: the result is an int */
5302 vtop->type.t = VT_INT;
5303 } else {
5304 vtop->type.t = t;
5309 /* generic itof for unsigned long long case */
5310 void gen_cvt_itof1(int t)
5312 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5313 (VT_LLONG | VT_UNSIGNED)) {
5315 if (t == VT_FLOAT)
5316 vpush_global_sym(&func_old_type, TOK___ulltof);
5317 else if (t == VT_DOUBLE)
5318 vpush_global_sym(&func_old_type, TOK___ulltod);
5319 else
5320 vpush_global_sym(&func_old_type, TOK___ulltold);
5321 vrott(2);
5322 gfunc_call(1);
5323 vpushi(0);
5324 vtop->r = REG_FRET;
5325 } else {
5326 gen_cvt_itof(t);
5330 /* generic ftoi for unsigned long long case */
5331 void gen_cvt_ftoi1(int t)
5333 int st;
5335 if (t == (VT_LLONG | VT_UNSIGNED)) {
5336 /* not handled natively */
5337 st = vtop->type.t & VT_BTYPE;
5338 if (st == VT_FLOAT)
5339 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5340 else if (st == VT_DOUBLE)
5341 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5342 else
5343 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5344 vrott(2);
5345 gfunc_call(1);
5346 vpushi(0);
5347 vtop->r = REG_IRET;
5348 vtop->r2 = REG_LRET;
5349 } else {
5350 gen_cvt_ftoi(t);
5354 /* force char or short cast */
5355 void force_charshort_cast(int t)
5357 int bits, dbt;
5358 dbt = t & VT_BTYPE;
5359 /* XXX: add optimization if lvalue : just change type and offset */
5360 if (dbt == VT_BYTE)
5361 bits = 8;
5362 else
5363 bits = 16;
5364 if (t & VT_UNSIGNED) {
5365 vpushi((1 << bits) - 1);
5366 gen_op('&');
5367 } else {
5368 bits = 32 - bits;
5369 vpushi(bits);
5370 gen_op(TOK_SHL);
5371 vpushi(bits);
5372 gen_op(TOK_SAR);
5376 /* cast 'vtop' to 'type' */
5377 static void gen_cast(CType *type)
5379 int sbt, dbt, sf, df, c;
5381 /* special delayed cast for char/short */
5382 /* XXX: in some cases (multiple cascaded casts), it may still
5383 be incorrect */
5384 if (vtop->r & VT_MUSTCAST) {
5385 vtop->r &= ~VT_MUSTCAST;
5386 force_charshort_cast(vtop->type.t);
5389 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5390 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5392 if (sbt != dbt && !nocode_wanted) {
5393 sf = is_float(sbt);
5394 df = is_float(dbt);
5395 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5396 if (sf && df) {
5397 /* convert from fp to fp */
5398 if (c) {
5399 /* constant case: we can do it now */
5400 /* XXX: in ISOC, cannot do it if error in convert */
5401 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5402 vtop->c.f = (float)vtop->c.d;
5403 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5404 vtop->c.f = (float)vtop->c.ld;
5405 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5406 vtop->c.d = (double)vtop->c.f;
5407 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5408 vtop->c.d = (double)vtop->c.ld;
5409 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5410 vtop->c.ld = (long double)vtop->c.f;
5411 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5412 vtop->c.ld = (long double)vtop->c.d;
5413 } else {
5414 /* non constant case: generate code */
5415 gen_cvt_ftof(dbt);
5417 } else if (df) {
5418 /* convert int to fp */
5419 if (c) {
5420 switch(sbt) {
5421 case VT_LLONG | VT_UNSIGNED:
5422 case VT_LLONG:
5423 /* XXX: add const cases for long long */
5424 goto do_itof;
5425 case VT_INT | VT_UNSIGNED:
5426 switch(dbt) {
5427 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5428 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5429 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5431 break;
5432 default:
5433 switch(dbt) {
5434 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5435 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5436 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5438 break;
5440 } else {
5441 do_itof:
5442 gen_cvt_itof1(dbt);
5444 } else if (sf) {
5445 /* convert fp to int */
5446 /* we handle char/short/etc... with generic code */
5447 if (dbt != (VT_INT | VT_UNSIGNED) &&
5448 dbt != (VT_LLONG | VT_UNSIGNED) &&
5449 dbt != VT_LLONG)
5450 dbt = VT_INT;
5451 if (c) {
5452 switch(dbt) {
5453 case VT_LLONG | VT_UNSIGNED:
5454 case VT_LLONG:
5455 /* XXX: add const cases for long long */
5456 goto do_ftoi;
5457 case VT_INT | VT_UNSIGNED:
5458 switch(sbt) {
5459 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5460 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5461 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5463 break;
5464 default:
5465 /* int case */
5466 switch(sbt) {
5467 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5468 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5469 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5471 break;
5473 } else {
5474 do_ftoi:
5475 gen_cvt_ftoi1(dbt);
5477 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5478 /* additional cast for char/short/bool... */
5479 vtop->type.t = dbt;
5480 gen_cast(type);
5482 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5483 if ((sbt & VT_BTYPE) != VT_LLONG) {
5484 /* scalar to long long */
5485 if (c) {
5486 if (sbt == (VT_INT | VT_UNSIGNED))
5487 vtop->c.ll = vtop->c.ui;
5488 else
5489 vtop->c.ll = vtop->c.i;
5490 } else {
5491 /* machine independent conversion */
5492 gv(RC_INT);
5493 /* generate high word */
5494 if (sbt == (VT_INT | VT_UNSIGNED)) {
5495 vpushi(0);
5496 gv(RC_INT);
5497 } else {
5498 gv_dup();
5499 vpushi(31);
5500 gen_op(TOK_SAR);
5502 /* patch second register */
5503 vtop[-1].r2 = vtop->r;
5504 vpop();
5507 } else if (dbt == VT_BOOL) {
5508 /* scalar to bool */
5509 vpushi(0);
5510 gen_op(TOK_NE);
5511 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5512 (dbt & VT_BTYPE) == VT_SHORT) {
5513 force_charshort_cast(dbt);
5514 } else if ((dbt & VT_BTYPE) == VT_INT) {
5515 /* scalar to int */
5516 if (sbt == VT_LLONG) {
5517 /* from long long: just take low order word */
5518 lexpand();
5519 vpop();
5521 /* if lvalue and single word type, nothing to do because
5522 the lvalue already contains the real type size (see
5523 VT_LVAL_xxx constants) */
5526 vtop->type = *type;
5529 /* return type size. Put alignment at 'a' */
5530 static int type_size(CType *type, int *a)
5532 Sym *s;
5533 int bt;
5535 bt = type->t & VT_BTYPE;
5536 if (bt == VT_STRUCT) {
5537 /* struct/union */
5538 s = type->ref;
5539 *a = s->r;
5540 return s->c;
5541 } else if (bt == VT_PTR) {
5542 if (type->t & VT_ARRAY) {
5543 s = type->ref;
5544 return type_size(&s->type, a) * s->c;
5545 } else {
5546 *a = PTR_SIZE;
5547 return PTR_SIZE;
5549 } else if (bt == VT_LDOUBLE) {
5550 *a = LDOUBLE_ALIGN;
5551 return LDOUBLE_SIZE;
5552 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5553 *a = 4; /* XXX: i386 specific */
5554 return 8;
5555 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5556 *a = 4;
5557 return 4;
5558 } else if (bt == VT_SHORT) {
5559 *a = 2;
5560 return 2;
5561 } else {
5562 /* char, void, function, _Bool */
5563 *a = 1;
5564 return 1;
5568 /* return the pointed type of t */
5569 static inline CType *pointed_type(CType *type)
5571 return &type->ref->type;
5574 /* modify type so that its it is a pointer to type. */
5575 static void mk_pointer(CType *type)
5577 Sym *s;
5578 s = sym_push(SYM_FIELD, type, 0, -1);
5579 type->t = VT_PTR | (type->t & ~VT_TYPE);
5580 type->ref = s;
5583 /* compare function types. OLD functions match any new functions */
5584 static int is_compatible_func(CType *type1, CType *type2)
5586 Sym *s1, *s2;
5588 s1 = type1->ref;
5589 s2 = type2->ref;
5590 if (!is_compatible_types(&s1->type, &s2->type))
5591 return 0;
5592 /* XXX: not complete */
5593 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5594 return 1;
5595 if (s1->c != s2->c)
5596 return 0;
5597 while (s1 != NULL) {
5598 if (s2 == NULL)
5599 return 0;
5600 if (!is_compatible_types(&s1->type, &s2->type))
5601 return 0;
5602 s1 = s1->next;
5603 s2 = s2->next;
5605 if (s2)
5606 return 0;
5607 return 1;
5610 /* return true if type1 and type2 are exactly the same (including
5611 qualifiers).
5613 - enums are not checked as gcc __builtin_types_compatible_p ()
5615 static int is_compatible_types(CType *type1, CType *type2)
5617 int bt1, t1, t2;
5619 t1 = type1->t & VT_TYPE;
5620 t2 = type2->t & VT_TYPE;
5621 /* XXX: bitfields ? */
5622 if (t1 != t2)
5623 return 0;
5624 /* test more complicated cases */
5625 bt1 = t1 & VT_BTYPE;
5626 if (bt1 == VT_PTR) {
5627 type1 = pointed_type(type1);
5628 type2 = pointed_type(type2);
5629 return is_compatible_types(type1, type2);
5630 } else if (bt1 == VT_STRUCT) {
5631 return (type1->ref == type2->ref);
5632 } else if (bt1 == VT_FUNC) {
5633 return is_compatible_func(type1, type2);
5634 } else {
5635 return 1;
5639 /* print a type. If 'varstr' is not NULL, then the variable is also
5640 printed in the type */
5641 /* XXX: union */
5642 /* XXX: add array and function pointers */
5643 void type_to_str(char *buf, int buf_size,
5644 CType *type, const char *varstr)
5646 int bt, v, t;
5647 Sym *s, *sa;
5648 char buf1[256];
5649 const char *tstr;
5651 t = type->t & VT_TYPE;
5652 bt = t & VT_BTYPE;
5653 buf[0] = '\0';
5654 if (t & VT_CONSTANT)
5655 pstrcat(buf, buf_size, "const ");
5656 if (t & VT_VOLATILE)
5657 pstrcat(buf, buf_size, "volatile ");
5658 if (t & VT_UNSIGNED)
5659 pstrcat(buf, buf_size, "unsigned ");
5660 switch(bt) {
5661 case VT_VOID:
5662 tstr = "void";
5663 goto add_tstr;
5664 case VT_BOOL:
5665 tstr = "_Bool";
5666 goto add_tstr;
5667 case VT_BYTE:
5668 tstr = "char";
5669 goto add_tstr;
5670 case VT_SHORT:
5671 tstr = "short";
5672 goto add_tstr;
5673 case VT_INT:
5674 tstr = "int";
5675 goto add_tstr;
5676 case VT_LONG:
5677 tstr = "long";
5678 goto add_tstr;
5679 case VT_LLONG:
5680 tstr = "long long";
5681 goto add_tstr;
5682 case VT_FLOAT:
5683 tstr = "float";
5684 goto add_tstr;
5685 case VT_DOUBLE:
5686 tstr = "double";
5687 goto add_tstr;
5688 case VT_LDOUBLE:
5689 tstr = "long double";
5690 add_tstr:
5691 pstrcat(buf, buf_size, tstr);
5692 break;
5693 case VT_ENUM:
5694 case VT_STRUCT:
5695 if (bt == VT_STRUCT)
5696 tstr = "struct ";
5697 else
5698 tstr = "enum ";
5699 pstrcat(buf, buf_size, tstr);
5700 v = type->ref->v & ~SYM_STRUCT;
5701 if (v >= SYM_FIRST_ANOM)
5702 pstrcat(buf, buf_size, "<anonymous>");
5703 else
5704 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5705 break;
5706 case VT_FUNC:
5707 s = type->ref;
5708 type_to_str(buf, buf_size, &s->type, varstr);
5709 pstrcat(buf, buf_size, "(");
5710 sa = s->next;
5711 while (sa != NULL) {
5712 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5713 pstrcat(buf, buf_size, buf1);
5714 sa = sa->next;
5715 if (sa)
5716 pstrcat(buf, buf_size, ", ");
5718 pstrcat(buf, buf_size, ")");
5719 goto no_var;
5720 case VT_PTR:
5721 s = type->ref;
5722 pstrcpy(buf1, sizeof(buf1), "*");
5723 if (varstr)
5724 pstrcat(buf1, sizeof(buf1), varstr);
5725 type_to_str(buf, buf_size, &s->type, buf1);
5726 goto no_var;
5728 if (varstr) {
5729 pstrcat(buf, buf_size, " ");
5730 pstrcat(buf, buf_size, varstr);
5732 no_var: ;
5735 /* verify type compatibility to store vtop in 'dt' type, and generate
5736 casts if needed. */
5737 static void gen_assign_cast(CType *dt)
5739 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5740 char buf1[256], buf2[256];
5741 int dbt, sbt;
5743 st = &vtop->type; /* source type */
5744 dbt = dt->t & VT_BTYPE;
5745 sbt = st->t & VT_BTYPE;
5746 if (dt->t & VT_CONSTANT)
5747 warning("assignment of read-only location");
5748 switch(dbt) {
5749 case VT_PTR:
5750 /* special cases for pointers */
5751 /* '0' can also be a pointer */
5752 if (is_null_pointer(vtop))
5753 goto type_ok;
5754 /* accept implicit pointer to integer cast with warning */
5755 if (is_integer_btype(sbt)) {
5756 warning("assignment makes pointer from integer without a cast");
5757 goto type_ok;
5759 type1 = pointed_type(dt);
5760 /* a function is implicitely a function pointer */
5761 if (sbt == VT_FUNC) {
5762 if ((type1->t & VT_BTYPE) != VT_VOID &&
5763 !is_compatible_types(pointed_type(dt), st))
5764 goto error;
5765 else
5766 goto type_ok;
5768 if (sbt != VT_PTR)
5769 goto error;
5770 type2 = pointed_type(st);
5771 if ((type1->t & VT_BTYPE) == VT_VOID ||
5772 (type2->t & VT_BTYPE) == VT_VOID) {
5773 /* void * can match anything */
5774 } else {
5775 /* exact type match, except for unsigned */
5776 tmp_type1 = *type1;
5777 tmp_type2 = *type2;
5778 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5779 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5780 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5781 goto error;
5783 /* check const and volatile */
5784 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5785 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5786 warning("assignment discards qualifiers from pointer target type");
5787 break;
5788 case VT_BYTE:
5789 case VT_SHORT:
5790 case VT_INT:
5791 case VT_LLONG:
5792 if (sbt == VT_PTR || sbt == VT_FUNC) {
5793 warning("assignment makes integer from pointer without a cast");
5795 /* XXX: more tests */
5796 break;
5797 case VT_STRUCT:
5798 if (!is_compatible_types(dt, st)) {
5799 error:
5800 type_to_str(buf1, sizeof(buf1), st, NULL);
5801 type_to_str(buf2, sizeof(buf2), dt, NULL);
5802 error("cannot cast '%s' to '%s'", buf1, buf2);
5804 break;
5806 type_ok:
5807 gen_cast(dt);
5810 /* store vtop in lvalue pushed on stack */
5811 void vstore(void)
5813 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5815 ft = vtop[-1].type.t;
5816 sbt = vtop->type.t & VT_BTYPE;
5817 dbt = ft & VT_BTYPE;
5818 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5819 (sbt == VT_INT && dbt == VT_SHORT)) {
5820 /* optimize char/short casts */
5821 delayed_cast = VT_MUSTCAST;
5822 vtop->type.t = ft & VT_TYPE;
5823 /* XXX: factorize */
5824 if (ft & VT_CONSTANT)
5825 warning("assignment of read-only location");
5826 } else {
5827 delayed_cast = 0;
5828 gen_assign_cast(&vtop[-1].type);
5831 if (sbt == VT_STRUCT) {
5832 /* if structure, only generate pointer */
5833 /* structure assignment : generate memcpy */
5834 /* XXX: optimize if small size */
5835 if (!nocode_wanted) {
5836 size = type_size(&vtop->type, &align);
5838 vpush_global_sym(&func_old_type, TOK_memcpy);
5840 /* destination */
5841 vpushv(vtop - 2);
5842 vtop->type.t = VT_INT;
5843 gaddrof();
5844 /* source */
5845 vpushv(vtop - 2);
5846 vtop->type.t = VT_INT;
5847 gaddrof();
5848 /* type size */
5849 vpushi(size);
5850 gfunc_call(3);
5852 vswap();
5853 vpop();
5854 } else {
5855 vswap();
5856 vpop();
5858 /* leave source on stack */
5859 } else if (ft & VT_BITFIELD) {
5860 /* bitfield store handling */
5861 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5862 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5863 /* remove bit field info to avoid loops */
5864 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5866 /* duplicate destination */
5867 vdup();
5868 vtop[-1] = vtop[-2];
5870 /* mask and shift source */
5871 vpushi((1 << bit_size) - 1);
5872 gen_op('&');
5873 vpushi(bit_pos);
5874 gen_op(TOK_SHL);
5875 /* load destination, mask and or with source */
5876 vswap();
5877 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5878 gen_op('&');
5879 gen_op('|');
5880 /* store result */
5881 vstore();
5882 } else {
5883 #ifdef CONFIG_TCC_BCHECK
5884 /* bound check case */
5885 if (vtop[-1].r & VT_MUSTBOUND) {
5886 vswap();
5887 gbound();
5888 vswap();
5890 #endif
5891 if (!nocode_wanted) {
5892 rc = RC_INT;
5893 if (is_float(ft))
5894 rc = RC_FLOAT;
5895 r = gv(rc); /* generate value */
5896 /* if lvalue was saved on stack, must read it */
5897 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5898 SValue sv;
5899 t = get_reg(RC_INT);
5900 sv.type.t = VT_INT;
5901 sv.r = VT_LOCAL | VT_LVAL;
5902 sv.c.ul = vtop[-1].c.ul;
5903 load(t, &sv);
5904 vtop[-1].r = t | VT_LVAL;
5906 store(r, vtop - 1);
5907 /* two word case handling : store second register at word + 4 */
5908 if ((ft & VT_BTYPE) == VT_LLONG) {
5909 vswap();
5910 /* convert to int to increment easily */
5911 vtop->type.t = VT_INT;
5912 gaddrof();
5913 vpushi(4);
5914 gen_op('+');
5915 vtop->r |= VT_LVAL;
5916 vswap();
5917 /* XXX: it works because r2 is spilled last ! */
5918 store(vtop->r2, vtop - 1);
5921 vswap();
5922 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5923 vtop->r |= delayed_cast;
5927 /* post defines POST/PRE add. c is the token ++ or -- */
5928 void inc(int post, int c)
5930 test_lvalue();
5931 vdup(); /* save lvalue */
5932 if (post) {
5933 gv_dup(); /* duplicate value */
5934 vrotb(3);
5935 vrotb(3);
5937 /* add constant */
5938 vpushi(c - TOK_MID);
5939 gen_op('+');
5940 vstore(); /* store value */
5941 if (post)
5942 vpop(); /* if post op, return saved value */
5945 /* Parse GNUC __attribute__ extension. Currently, the following
5946 extensions are recognized:
5947 - aligned(n) : set data/function alignment.
5948 - section(x) : generate data/code in this section.
5949 - unused : currently ignored, but may be used someday.
5951 static void parse_attribute(AttributeDef *ad)
5953 int t, n;
5955 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5956 next();
5957 skip('(');
5958 skip('(');
5959 while (tok != ')') {
5960 if (tok < TOK_IDENT)
5961 expect("attribute name");
5962 t = tok;
5963 next();
5964 switch(t) {
5965 case TOK_SECTION1:
5966 case TOK_SECTION2:
5967 skip('(');
5968 if (tok != TOK_STR)
5969 expect("section name");
5970 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5971 next();
5972 skip(')');
5973 break;
5974 case TOK_ALIGNED1:
5975 case TOK_ALIGNED2:
5976 if (tok == '(') {
5977 next();
5978 n = expr_const();
5979 if (n <= 0 || (n & (n - 1)) != 0)
5980 error("alignment must be a positive power of two");
5981 skip(')');
5982 } else {
5983 n = MAX_ALIGN;
5985 ad->aligned = n;
5986 break;
5987 case TOK_UNUSED1:
5988 case TOK_UNUSED2:
5989 /* currently, no need to handle it because tcc does not
5990 track unused objects */
5991 break;
5992 case TOK_NORETURN1:
5993 case TOK_NORETURN2:
5994 /* currently, no need to handle it because tcc does not
5995 track unused objects */
5996 break;
5997 case TOK_CDECL1:
5998 case TOK_CDECL2:
5999 case TOK_CDECL3:
6000 ad->func_call = FUNC_CDECL;
6001 break;
6002 case TOK_STDCALL1:
6003 case TOK_STDCALL2:
6004 case TOK_STDCALL3:
6005 ad->func_call = FUNC_STDCALL;
6006 break;
6007 default:
6008 if (tcc_state->warn_unsupported)
6009 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6010 /* skip parameters */
6011 /* XXX: skip parenthesis too */
6012 if (tok == '(') {
6013 next();
6014 while (tok != ')' && tok != -1)
6015 next();
6016 next();
6018 break;
6020 if (tok != ',')
6021 break;
6022 next();
6024 skip(')');
6025 skip(')');
6029 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6030 static void struct_decl(CType *type, int u)
6032 int a, v, size, align, maxalign, c, offset;
6033 int bit_size, bit_pos, bsize, bt, lbit_pos;
6034 Sym *s, *ss, **ps;
6035 AttributeDef ad;
6036 CType type1, btype;
6038 a = tok; /* save decl type */
6039 next();
6040 if (tok != '{') {
6041 v = tok;
6042 next();
6043 /* struct already defined ? return it */
6044 if (v < TOK_IDENT)
6045 expect("struct/union/enum name");
6046 s = struct_find(v);
6047 if (s) {
6048 if (s->type.t != a)
6049 error("invalid type");
6050 goto do_decl;
6052 } else {
6053 v = anon_sym++;
6055 type1.t = a;
6056 /* we put an undefined size for struct/union */
6057 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6058 s->r = 0; /* default alignment is zero as gcc */
6059 /* put struct/union/enum name in type */
6060 do_decl:
6061 type->t = u;
6062 type->ref = s;
6064 if (tok == '{') {
6065 next();
6066 if (s->c != -1)
6067 error("struct/union/enum already defined");
6068 /* cannot be empty */
6069 c = 0;
6070 /* non empty enums are not allowed */
6071 if (a == TOK_ENUM) {
6072 for(;;) {
6073 v = tok;
6074 if (v < TOK_UIDENT)
6075 expect("identifier");
6076 next();
6077 if (tok == '=') {
6078 next();
6079 c = expr_const();
6081 /* enum symbols have static storage */
6082 ss = sym_push(v, &int_type, VT_CONST, c);
6083 ss->type.t |= VT_STATIC;
6084 if (tok != ',')
6085 break;
6086 next();
6087 c++;
6088 /* NOTE: we accept a trailing comma */
6089 if (tok == '}')
6090 break;
6092 skip('}');
6093 } else {
6094 maxalign = 1;
6095 ps = &s->next;
6096 bit_pos = 0;
6097 offset = 0;
6098 while (tok != '}') {
6099 parse_btype(&btype, &ad);
6100 while (1) {
6101 bit_size = -1;
6102 v = 0;
6103 type1 = btype;
6104 if (tok != ':') {
6105 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6106 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6107 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6108 error("invalid type for '%s'",
6109 get_tok_str(v, NULL));
6111 if (tok == ':') {
6112 next();
6113 bit_size = expr_const();
6114 /* XXX: handle v = 0 case for messages */
6115 if (bit_size < 0)
6116 error("negative width in bit-field '%s'",
6117 get_tok_str(v, NULL));
6118 if (v && bit_size == 0)
6119 error("zero width for bit-field '%s'",
6120 get_tok_str(v, NULL));
6122 size = type_size(&type1, &align);
6123 lbit_pos = 0;
6124 if (bit_size >= 0) {
6125 bt = type1.t & VT_BTYPE;
6126 if (bt != VT_INT &&
6127 bt != VT_BYTE &&
6128 bt != VT_SHORT &&
6129 bt != VT_ENUM)
6130 error("bitfields must have scalar type");
6131 bsize = size * 8;
6132 if (bit_size > bsize) {
6133 error("width of '%s' exceeds its type",
6134 get_tok_str(v, NULL));
6135 } else if (bit_size == bsize) {
6136 /* no need for bit fields */
6137 bit_pos = 0;
6138 } else if (bit_size == 0) {
6139 /* XXX: what to do if only padding in a
6140 structure ? */
6141 /* zero size: means to pad */
6142 if (bit_pos > 0)
6143 bit_pos = bsize;
6144 } else {
6145 /* we do not have enough room ? */
6146 if ((bit_pos + bit_size) > bsize)
6147 bit_pos = 0;
6148 lbit_pos = bit_pos;
6149 /* XXX: handle LSB first */
6150 type1.t |= VT_BITFIELD |
6151 (bit_pos << VT_STRUCT_SHIFT) |
6152 (bit_size << (VT_STRUCT_SHIFT + 6));
6153 bit_pos += bit_size;
6155 } else {
6156 bit_pos = 0;
6158 if (v) {
6159 /* add new memory data only if starting
6160 bit field */
6161 if (lbit_pos == 0) {
6162 if (a == TOK_STRUCT) {
6163 c = (c + align - 1) & -align;
6164 offset = c;
6165 c += size;
6166 } else {
6167 offset = 0;
6168 if (size > c)
6169 c = size;
6171 if (align > maxalign)
6172 maxalign = align;
6174 #if 0
6175 printf("add field %s offset=%d",
6176 get_tok_str(v, NULL), offset);
6177 if (type1.t & VT_BITFIELD) {
6178 printf(" pos=%d size=%d",
6179 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6180 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6182 printf("\n");
6183 #endif
6184 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6185 *ps = ss;
6186 ps = &ss->next;
6188 if (tok == ';' || tok == TOK_EOF)
6189 break;
6190 skip(',');
6192 skip(';');
6194 skip('}');
6195 /* store size and alignment */
6196 s->c = (c + maxalign - 1) & -maxalign;
6197 s->r = maxalign;
6202 /* return 0 if no type declaration. otherwise, return the basic type
6203 and skip it.
6205 static int parse_btype(CType *type, AttributeDef *ad)
6207 int t, u, type_found;
6208 Sym *s;
6209 CType type1;
6211 memset(ad, 0, sizeof(AttributeDef));
6212 type_found = 0;
6213 t = 0;
6214 while(1) {
6215 switch(tok) {
6216 case TOK_EXTENSION:
6217 /* currently, we really ignore extension */
6218 next();
6219 continue;
6221 /* basic types */
6222 case TOK_CHAR:
6223 u = VT_BYTE;
6224 basic_type:
6225 next();
6226 basic_type1:
6227 if ((t & VT_BTYPE) != 0)
6228 error("too many basic types");
6229 t |= u;
6230 break;
6231 case TOK_VOID:
6232 u = VT_VOID;
6233 goto basic_type;
6234 case TOK_SHORT:
6235 u = VT_SHORT;
6236 goto basic_type;
6237 case TOK_INT:
6238 next();
6239 break;
6240 case TOK_LONG:
6241 next();
6242 if ((t & VT_BTYPE) == VT_DOUBLE) {
6243 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6244 } else if ((t & VT_BTYPE) == VT_LONG) {
6245 t = (t & ~VT_BTYPE) | VT_LLONG;
6246 } else {
6247 u = VT_LONG;
6248 goto basic_type1;
6250 break;
6251 case TOK_BOOL:
6252 u = VT_BOOL;
6253 goto basic_type;
6254 case TOK_FLOAT:
6255 u = VT_FLOAT;
6256 goto basic_type;
6257 case TOK_DOUBLE:
6258 next();
6259 if ((t & VT_BTYPE) == VT_LONG) {
6260 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6261 } else {
6262 u = VT_DOUBLE;
6263 goto basic_type1;
6265 break;
6266 case TOK_ENUM:
6267 struct_decl(&type1, VT_ENUM);
6268 basic_type2:
6269 u = type1.t;
6270 type->ref = type1.ref;
6271 goto basic_type1;
6272 case TOK_STRUCT:
6273 case TOK_UNION:
6274 struct_decl(&type1, VT_STRUCT);
6275 goto basic_type2;
6277 /* type modifiers */
6278 case TOK_CONST1:
6279 case TOK_CONST2:
6280 case TOK_CONST3:
6281 t |= VT_CONSTANT;
6282 next();
6283 break;
6284 case TOK_VOLATILE1:
6285 case TOK_VOLATILE2:
6286 case TOK_VOLATILE3:
6287 t |= VT_VOLATILE;
6288 next();
6289 break;
6290 case TOK_REGISTER:
6291 case TOK_SIGNED1:
6292 case TOK_SIGNED2:
6293 case TOK_SIGNED3:
6294 case TOK_AUTO:
6295 case TOK_RESTRICT1:
6296 case TOK_RESTRICT2:
6297 case TOK_RESTRICT3:
6298 next();
6299 break;
6300 case TOK_UNSIGNED:
6301 t |= VT_UNSIGNED;
6302 next();
6303 break;
6305 /* storage */
6306 case TOK_EXTERN:
6307 t |= VT_EXTERN;
6308 next();
6309 break;
6310 case TOK_STATIC:
6311 t |= VT_STATIC;
6312 next();
6313 break;
6314 case TOK_TYPEDEF:
6315 t |= VT_TYPEDEF;
6316 next();
6317 break;
6318 case TOK_INLINE1:
6319 case TOK_INLINE2:
6320 case TOK_INLINE3:
6321 t |= VT_INLINE;
6322 next();
6323 break;
6325 /* GNUC attribute */
6326 case TOK_ATTRIBUTE1:
6327 case TOK_ATTRIBUTE2:
6328 parse_attribute(ad);
6329 break;
6330 /* GNUC typeof */
6331 case TOK_TYPEOF1:
6332 case TOK_TYPEOF2:
6333 case TOK_TYPEOF3:
6334 next();
6335 parse_expr_type(&type1);
6336 goto basic_type2;
6337 default:
6338 s = sym_find(tok);
6339 if (!s || !(s->type.t & VT_TYPEDEF))
6340 goto the_end;
6341 t |= (s->type.t & ~VT_TYPEDEF);
6342 type->ref = s->type.ref;
6343 next();
6344 break;
6346 type_found = 1;
6348 the_end:
6349 /* long is never used as type */
6350 if ((t & VT_BTYPE) == VT_LONG)
6351 t = (t & ~VT_BTYPE) | VT_INT;
6352 type->t = t;
6353 return type_found;
6356 /* convert a function parameter type (array to pointer and function to
6357 function pointer) */
6358 static inline void convert_parameter_type(CType *pt)
6360 /* array must be transformed to pointer according to ANSI C */
6361 pt->t &= ~VT_ARRAY;
6362 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6363 mk_pointer(pt);
6367 static void post_type(CType *type, AttributeDef *ad)
6369 int n, l, t1;
6370 Sym **plast, *s, *first;
6371 AttributeDef ad1;
6372 CType pt;
6374 if (tok == '(') {
6375 /* function declaration */
6376 next();
6377 l = 0;
6378 first = NULL;
6379 plast = &first;
6380 while (tok != ')') {
6381 /* read param name and compute offset */
6382 if (l != FUNC_OLD) {
6383 if (!parse_btype(&pt, &ad1)) {
6384 if (l) {
6385 error("invalid type");
6386 } else {
6387 l = FUNC_OLD;
6388 goto old_proto;
6391 l = FUNC_NEW;
6392 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6393 break;
6394 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6395 if ((pt.t & VT_BTYPE) == VT_VOID)
6396 error("parameter declared as void");
6397 } else {
6398 old_proto:
6399 n = tok;
6400 pt.t = VT_INT;
6401 next();
6403 convert_parameter_type(&pt);
6404 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6405 *plast = s;
6406 plast = &s->next;
6407 if (tok == ',') {
6408 next();
6409 if (l == FUNC_NEW && tok == TOK_DOTS) {
6410 l = FUNC_ELLIPSIS;
6411 next();
6412 break;
6416 /* if no parameters, then old type prototype */
6417 if (l == 0)
6418 l = FUNC_OLD;
6419 skip(')');
6420 t1 = type->t & VT_STORAGE;
6421 /* NOTE: const is ignored in returned type as it has a special
6422 meaning in gcc / C++ */
6423 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6424 post_type(type, ad);
6425 /* we push a anonymous symbol which will contain the function prototype */
6426 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6427 s->next = first;
6428 type->t = t1 | VT_FUNC;
6429 type->ref = s;
6430 } else if (tok == '[') {
6431 /* array definition */
6432 next();
6433 n = -1;
6434 if (tok != ']') {
6435 n = expr_const();
6436 if (n < 0)
6437 error("invalid array size");
6439 skip(']');
6440 /* parse next post type */
6441 t1 = type->t & VT_STORAGE;
6442 type->t &= ~VT_STORAGE;
6443 post_type(type, ad);
6445 /* we push a anonymous symbol which will contain the array
6446 element type */
6447 s = sym_push(SYM_FIELD, type, 0, n);
6448 type->t = t1 | VT_ARRAY | VT_PTR;
6449 type->ref = s;
6453 /* Parse a type declaration (except basic type), and return the type
6454 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6455 expected. 'type' should contain the basic type. 'ad' is the
6456 attribute definition of the basic type. It can be modified by
6457 type_decl().
6459 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6461 Sym *s;
6462 CType type1, *type2;
6463 int qualifiers;
6465 while (tok == '*') {
6466 qualifiers = 0;
6467 redo:
6468 next();
6469 switch(tok) {
6470 case TOK_CONST1:
6471 case TOK_CONST2:
6472 case TOK_CONST3:
6473 qualifiers |= VT_CONSTANT;
6474 goto redo;
6475 case TOK_VOLATILE1:
6476 case TOK_VOLATILE2:
6477 case TOK_VOLATILE3:
6478 qualifiers |= VT_VOLATILE;
6479 goto redo;
6480 case TOK_RESTRICT1:
6481 case TOK_RESTRICT2:
6482 case TOK_RESTRICT3:
6483 goto redo;
6485 mk_pointer(type);
6486 type->t |= qualifiers;
6489 /* XXX: clarify attribute handling */
6490 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6491 parse_attribute(ad);
6493 /* recursive type */
6494 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6495 type1.t = 0; /* XXX: same as int */
6496 if (tok == '(') {
6497 next();
6498 /* XXX: this is not correct to modify 'ad' at this point, but
6499 the syntax is not clear */
6500 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6501 parse_attribute(ad);
6502 type_decl(&type1, ad, v, td);
6503 skip(')');
6504 } else {
6505 /* type identifier */
6506 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6507 *v = tok;
6508 next();
6509 } else {
6510 if (!(td & TYPE_ABSTRACT))
6511 expect("identifier");
6512 *v = 0;
6515 post_type(type, ad);
6516 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6517 parse_attribute(ad);
6518 if (!type1.t)
6519 return;
6520 /* append type at the end of type1 */
6521 type2 = &type1;
6522 for(;;) {
6523 s = type2->ref;
6524 type2 = &s->type;
6525 if (!type2->t) {
6526 *type2 = *type;
6527 break;
6530 *type = type1;
6533 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6534 static int lvalue_type(int t)
6536 int bt, r;
6537 r = VT_LVAL;
6538 bt = t & VT_BTYPE;
6539 if (bt == VT_BYTE || bt == VT_BOOL)
6540 r |= VT_LVAL_BYTE;
6541 else if (bt == VT_SHORT)
6542 r |= VT_LVAL_SHORT;
6543 else
6544 return r;
6545 if (t & VT_UNSIGNED)
6546 r |= VT_LVAL_UNSIGNED;
6547 return r;
6550 /* indirection with full error checking and bound check */
6551 static void indir(void)
6553 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6554 expect("pointer");
6555 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6556 gv(RC_INT);
6557 vtop->type = *pointed_type(&vtop->type);
6558 /* an array is never an lvalue */
6559 if (!(vtop->type.t & VT_ARRAY)) {
6560 vtop->r |= lvalue_type(vtop->type.t);
6561 /* if bound checking, the referenced pointer must be checked */
6562 if (do_bounds_check)
6563 vtop->r |= VT_MUSTBOUND;
6567 /* pass a parameter to a function and do type checking and casting */
6568 static void gfunc_param_typed(Sym *func, Sym *arg)
6570 int func_type;
6571 CType type;
6573 func_type = func->c;
6574 if (func_type == FUNC_OLD ||
6575 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6576 /* default casting : only need to convert float to double */
6577 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6578 type.t = VT_DOUBLE;
6579 gen_cast(&type);
6581 } else if (arg == NULL) {
6582 error("too many arguments to function");
6583 } else {
6584 type = arg->type;
6585 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6586 gen_assign_cast(&type);
6590 /* parse an expression of the form '(type)' or '(expr)' and return its
6591 type */
6592 static void parse_expr_type(CType *type)
6594 int n;
6595 AttributeDef ad;
6597 skip('(');
6598 if (parse_btype(type, &ad)) {
6599 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6600 } else {
6601 expr_type(type);
6603 skip(')');
6606 static void parse_type(CType *type)
6608 AttributeDef ad;
6609 int n;
6611 if (!parse_btype(type, &ad)) {
6612 expect("type");
6614 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6617 static void vpush_tokc(int t)
6619 CType type;
6620 type.t = t;
6621 vsetc(&type, VT_CONST, &tokc);
6624 static void unary(void)
6626 int n, t, align, size, r;
6627 CType type;
6628 Sym *s;
6629 AttributeDef ad;
6631 /* XXX: GCC 2.95.3 does not generate a table although it should be
6632 better here */
6633 tok_next:
6634 switch(tok) {
6635 case TOK_EXTENSION:
6636 next();
6637 goto tok_next;
6638 case TOK_CINT:
6639 case TOK_CCHAR:
6640 case TOK_LCHAR:
6641 vpushi(tokc.i);
6642 next();
6643 break;
6644 case TOK_CUINT:
6645 vpush_tokc(VT_INT | VT_UNSIGNED);
6646 next();
6647 break;
6648 case TOK_CLLONG:
6649 vpush_tokc(VT_LLONG);
6650 next();
6651 break;
6652 case TOK_CULLONG:
6653 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6654 next();
6655 break;
6656 case TOK_CFLOAT:
6657 vpush_tokc(VT_FLOAT);
6658 next();
6659 break;
6660 case TOK_CDOUBLE:
6661 vpush_tokc(VT_DOUBLE);
6662 next();
6663 break;
6664 case TOK_CLDOUBLE:
6665 vpush_tokc(VT_LDOUBLE);
6666 next();
6667 break;
6668 case TOK___FUNCTION__:
6669 if (!gnu_ext)
6670 goto tok_identifier;
6671 /* fall thru */
6672 case TOK___FUNC__:
6674 void *ptr;
6675 int len;
6676 /* special function name identifier */
6677 len = strlen(funcname) + 1;
6678 /* generate char[len] type */
6679 type.t = VT_BYTE;
6680 mk_pointer(&type);
6681 type.t |= VT_ARRAY;
6682 type.ref->c = len;
6683 vpush_ref(&type, data_section, data_section->data_offset, len);
6684 ptr = section_ptr_add(data_section, len);
6685 memcpy(ptr, funcname, len);
6686 next();
6688 break;
6689 case TOK_LSTR:
6690 t = VT_INT;
6691 goto str_init;
6692 case TOK_STR:
6693 /* string parsing */
6694 t = VT_BYTE;
6695 str_init:
6696 if (tcc_state->warn_write_strings)
6697 t |= VT_CONSTANT;
6698 type.t = t;
6699 mk_pointer(&type);
6700 type.t |= VT_ARRAY;
6701 memset(&ad, 0, sizeof(AttributeDef));
6702 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6703 break;
6704 case '(':
6705 next();
6706 /* cast ? */
6707 if (parse_btype(&type, &ad)) {
6708 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6709 skip(')');
6710 /* check ISOC99 compound literal */
6711 if (tok == '{') {
6712 /* data is allocated locally by default */
6713 if (global_expr)
6714 r = VT_CONST;
6715 else
6716 r = VT_LOCAL;
6717 /* all except arrays are lvalues */
6718 if (!(type.t & VT_ARRAY))
6719 r |= lvalue_type(type.t);
6720 memset(&ad, 0, sizeof(AttributeDef));
6721 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6722 } else {
6723 unary();
6724 gen_cast(&type);
6726 } else if (tok == '{') {
6727 /* save all registers */
6728 save_regs(0);
6729 /* statement expression : we do not accept break/continue
6730 inside as GCC does */
6731 block(NULL, NULL, NULL, NULL, 0, 1);
6732 skip(')');
6733 } else {
6734 gexpr();
6735 skip(')');
6737 break;
6738 case '*':
6739 next();
6740 unary();
6741 indir();
6742 break;
6743 case '&':
6744 next();
6745 unary();
6746 /* functions names must be treated as function pointers,
6747 except for unary '&' and sizeof. Since we consider that
6748 functions are not lvalues, we only have to handle it
6749 there and in function calls. */
6750 /* arrays can also be used although they are not lvalues */
6751 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6752 !(vtop->type.t & VT_ARRAY))
6753 test_lvalue();
6754 mk_pointer(&vtop->type);
6755 gaddrof();
6756 break;
6757 case '!':
6758 next();
6759 unary();
6760 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6761 vtop->c.i = !vtop->c.i;
6762 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6763 vtop->c.i = vtop->c.i ^ 1;
6764 else
6765 vseti(VT_JMP, gtst(1, 0));
6766 break;
6767 case '~':
6768 next();
6769 unary();
6770 vpushi(-1);
6771 gen_op('^');
6772 break;
6773 case '+':
6774 next();
6775 /* in order to force cast, we add zero */
6776 unary();
6777 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6778 error("pointer not accepted for unary plus");
6779 vpushi(0);
6780 gen_op('+');
6781 break;
6782 case TOK_SIZEOF:
6783 case TOK_ALIGNOF1:
6784 case TOK_ALIGNOF2:
6785 t = tok;
6786 next();
6787 if (tok == '(') {
6788 parse_expr_type(&type);
6789 } else {
6790 unary_type(&type);
6792 size = type_size(&type, &align);
6793 if (t == TOK_SIZEOF) {
6794 if (size < 0)
6795 error("sizeof applied to an incomplete type");
6796 vpushi(size);
6797 } else {
6798 vpushi(align);
6800 break;
6802 case TOK_builtin_types_compatible_p:
6804 CType type1, type2;
6805 next();
6806 skip('(');
6807 parse_type(&type1);
6808 skip(',');
6809 parse_type(&type2);
6810 skip(')');
6811 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6812 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6813 vpushi(is_compatible_types(&type1, &type2));
6815 break;
6816 case TOK_builtin_constant_p:
6818 int saved_nocode_wanted, res;
6819 next();
6820 skip('(');
6821 saved_nocode_wanted = nocode_wanted;
6822 nocode_wanted = 1;
6823 gexpr();
6824 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6825 vpop();
6826 nocode_wanted = saved_nocode_wanted;
6827 skip(')');
6828 vpushi(res);
6830 break;
6831 case TOK_INC:
6832 case TOK_DEC:
6833 t = tok;
6834 next();
6835 unary();
6836 inc(0, t);
6837 break;
6838 case '-':
6839 next();
6840 vpushi(0);
6841 unary();
6842 gen_op('-');
6843 break;
6844 case TOK_LAND:
6845 if (!gnu_ext)
6846 goto tok_identifier;
6847 next();
6848 /* allow to take the address of a label */
6849 if (tok < TOK_UIDENT)
6850 expect("label identifier");
6851 s = label_find(tok);
6852 if (!s) {
6853 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6854 } else {
6855 if (s->r == LABEL_DECLARED)
6856 s->r = LABEL_FORWARD;
6858 if (!s->type.t) {
6859 s->type.t = VT_VOID;
6860 mk_pointer(&s->type);
6861 s->type.t |= VT_STATIC;
6863 vset(&s->type, VT_CONST | VT_SYM, 0);
6864 vtop->sym = s;
6865 next();
6866 break;
6867 default:
6868 tok_identifier:
6869 t = tok;
6870 next();
6871 if (t < TOK_UIDENT)
6872 expect("identifier");
6873 s = sym_find(t);
6874 if (!s) {
6875 if (tok != '(')
6876 error("'%s' undeclared", get_tok_str(t, NULL));
6877 /* for simple function calls, we tolerate undeclared
6878 external reference to int() function */
6879 s = external_global_sym(t, &func_old_type, 0);
6881 vset(&s->type, s->r, s->c);
6882 /* if forward reference, we must point to s */
6883 if (vtop->r & VT_SYM) {
6884 vtop->sym = s;
6885 vtop->c.ul = 0;
6887 break;
6890 /* post operations */
6891 while (1) {
6892 if (tok == TOK_INC || tok == TOK_DEC) {
6893 inc(1, tok);
6894 next();
6895 } else if (tok == '.' || tok == TOK_ARROW) {
6896 /* field */
6897 if (tok == TOK_ARROW)
6898 indir();
6899 test_lvalue();
6900 gaddrof();
6901 next();
6902 /* expect pointer on structure */
6903 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6904 expect("struct or union");
6905 s = vtop->type.ref;
6906 /* find field */
6907 tok |= SYM_FIELD;
6908 while ((s = s->next) != NULL) {
6909 if (s->v == tok)
6910 break;
6912 if (!s)
6913 error("field not found");
6914 /* add field offset to pointer */
6915 vtop->type = char_pointer_type; /* change type to 'char *' */
6916 vpushi(s->c);
6917 gen_op('+');
6918 /* change type to field type, and set to lvalue */
6919 vtop->type = s->type;
6920 /* an array is never an lvalue */
6921 if (!(vtop->type.t & VT_ARRAY)) {
6922 vtop->r |= lvalue_type(vtop->type.t);
6923 /* if bound checking, the referenced pointer must be checked */
6924 if (do_bounds_check)
6925 vtop->r |= VT_MUSTBOUND;
6927 next();
6928 } else if (tok == '[') {
6929 next();
6930 gexpr();
6931 gen_op('+');
6932 indir();
6933 skip(']');
6934 } else if (tok == '(') {
6935 SValue ret;
6936 Sym *sa;
6937 int nb_args;
6939 /* function call */
6940 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6941 /* pointer test (no array accepted) */
6942 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6943 vtop->type = *pointed_type(&vtop->type);
6944 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6945 goto error_func;
6946 } else {
6947 error_func:
6948 expect("function pointer");
6950 } else {
6951 vtop->r &= ~VT_LVAL; /* no lvalue */
6953 /* get return type */
6954 s = vtop->type.ref;
6955 next();
6956 sa = s->next; /* first parameter */
6957 nb_args = 0;
6958 /* compute first implicit argument if a structure is returned */
6959 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6960 /* get some space for the returned structure */
6961 size = type_size(&s->type, &align);
6962 loc = (loc - size) & -align;
6963 ret.type = s->type;
6964 ret.r = VT_LOCAL | VT_LVAL;
6965 /* pass it as 'int' to avoid structure arg passing
6966 problems */
6967 vseti(VT_LOCAL, loc);
6968 ret.c = vtop->c;
6969 nb_args++;
6970 } else {
6971 ret.type = s->type;
6972 ret.r2 = VT_CONST;
6973 /* return in register */
6974 if (is_float(ret.type.t)) {
6975 ret.r = REG_FRET;
6976 } else {
6977 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6978 ret.r2 = REG_LRET;
6979 ret.r = REG_IRET;
6981 ret.c.i = 0;
6983 if (tok != ')') {
6984 for(;;) {
6985 expr_eq();
6986 gfunc_param_typed(s, sa);
6987 nb_args++;
6988 if (sa)
6989 sa = sa->next;
6990 if (tok == ')')
6991 break;
6992 skip(',');
6995 if (sa)
6996 error("too few arguments to function");
6997 skip(')');
6998 if (!nocode_wanted) {
6999 gfunc_call(nb_args);
7000 } else {
7001 vtop -= (nb_args + 1);
7003 /* return value */
7004 vsetc(&ret.type, ret.r, &ret.c);
7005 vtop->r2 = ret.r2;
7006 } else {
7007 break;
7012 static void uneq(void)
7014 int t;
7016 unary();
7017 if (tok == '=' ||
7018 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7019 tok == TOK_A_XOR || tok == TOK_A_OR ||
7020 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7021 test_lvalue();
7022 t = tok;
7023 next();
7024 if (t == '=') {
7025 expr_eq();
7026 } else {
7027 vdup();
7028 expr_eq();
7029 gen_op(t & 0x7f);
7031 vstore();
7035 static void expr_prod(void)
7037 int t;
7039 uneq();
7040 while (tok == '*' || tok == '/' || tok == '%') {
7041 t = tok;
7042 next();
7043 uneq();
7044 gen_op(t);
7048 static void expr_sum(void)
7050 int t;
7052 expr_prod();
7053 while (tok == '+' || tok == '-') {
7054 t = tok;
7055 next();
7056 expr_prod();
7057 gen_op(t);
7061 static void expr_shift(void)
7063 int t;
7065 expr_sum();
7066 while (tok == TOK_SHL || tok == TOK_SAR) {
7067 t = tok;
7068 next();
7069 expr_sum();
7070 gen_op(t);
7074 static void expr_cmp(void)
7076 int t;
7078 expr_shift();
7079 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7080 tok == TOK_ULT || tok == TOK_UGE) {
7081 t = tok;
7082 next();
7083 expr_shift();
7084 gen_op(t);
7088 static void expr_cmpeq(void)
7090 int t;
7092 expr_cmp();
7093 while (tok == TOK_EQ || tok == TOK_NE) {
7094 t = tok;
7095 next();
7096 expr_cmp();
7097 gen_op(t);
7101 static void expr_and(void)
7103 expr_cmpeq();
7104 while (tok == '&') {
7105 next();
7106 expr_cmpeq();
7107 gen_op('&');
7111 static void expr_xor(void)
7113 expr_and();
7114 while (tok == '^') {
7115 next();
7116 expr_and();
7117 gen_op('^');
7121 static void expr_or(void)
7123 expr_xor();
7124 while (tok == '|') {
7125 next();
7126 expr_xor();
7127 gen_op('|');
7131 /* XXX: fix this mess */
7132 static void expr_land_const(void)
7134 expr_or();
7135 while (tok == TOK_LAND) {
7136 next();
7137 expr_or();
7138 gen_op(TOK_LAND);
7142 /* XXX: fix this mess */
7143 static void expr_lor_const(void)
7145 expr_land_const();
7146 while (tok == TOK_LOR) {
7147 next();
7148 expr_land_const();
7149 gen_op(TOK_LOR);
7153 /* only used if non constant */
7154 static void expr_land(void)
7156 int t;
7158 expr_or();
7159 if (tok == TOK_LAND) {
7160 t = 0;
7161 for(;;) {
7162 t = gtst(1, t);
7163 if (tok != TOK_LAND) {
7164 vseti(VT_JMPI, t);
7165 break;
7167 next();
7168 expr_or();
7173 static void expr_lor(void)
7175 int t;
7177 expr_land();
7178 if (tok == TOK_LOR) {
7179 t = 0;
7180 for(;;) {
7181 t = gtst(0, t);
7182 if (tok != TOK_LOR) {
7183 vseti(VT_JMP, t);
7184 break;
7186 next();
7187 expr_land();
7192 /* XXX: better constant handling */
7193 static void expr_eq(void)
7195 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7196 SValue sv;
7197 CType type, type1, type2;
7199 if (const_wanted) {
7200 int c1, c;
7201 expr_lor_const();
7202 if (tok == '?') {
7203 c = vtop->c.i;
7204 vpop();
7205 next();
7206 if (tok == ':' && gnu_ext) {
7207 c1 = c;
7208 } else {
7209 gexpr();
7210 c1 = vtop->c.i;
7211 vpop();
7213 skip(':');
7214 expr_eq();
7215 if (c)
7216 vtop->c.i = c1;
7218 } else {
7219 expr_lor();
7220 if (tok == '?') {
7221 next();
7222 if (vtop != vstack) {
7223 /* needed to avoid having different registers saved in
7224 each branch */
7225 if (is_float(vtop->type.t))
7226 rc = RC_FLOAT;
7227 else
7228 rc = RC_INT;
7229 gv(rc);
7230 save_regs(1);
7232 if (tok == ':' && gnu_ext) {
7233 gv_dup();
7234 tt = gtst(1, 0);
7235 } else {
7236 tt = gtst(1, 0);
7237 gexpr();
7239 type1 = vtop->type;
7240 sv = *vtop; /* save value to handle it later */
7241 vtop--; /* no vpop so that FP stack is not flushed */
7242 skip(':');
7243 u = gjmp(0);
7244 gsym(tt);
7245 expr_eq();
7246 type2 = vtop->type;
7248 t1 = type1.t;
7249 bt1 = t1 & VT_BTYPE;
7250 t2 = type2.t;
7251 bt2 = t2 & VT_BTYPE;
7252 /* cast operands to correct type according to ISOC rules */
7253 if (is_float(bt1) || is_float(bt2)) {
7254 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7255 type.t = VT_LDOUBLE;
7256 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7257 type.t = VT_DOUBLE;
7258 } else {
7259 type.t = VT_FLOAT;
7261 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7262 /* cast to biggest op */
7263 type.t = VT_LLONG;
7264 /* convert to unsigned if it does not fit in a long long */
7265 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7266 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7267 type.t |= VT_UNSIGNED;
7268 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7269 /* XXX: test pointer compatibility */
7270 type = type1;
7271 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7272 /* XXX: test structure compatibility */
7273 type = type1;
7274 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7275 /* NOTE: as an extension, we accept void on only one side */
7276 type.t = VT_VOID;
7277 } else {
7278 /* integer operations */
7279 type.t = VT_INT;
7280 /* convert to unsigned if it does not fit in an integer */
7281 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7282 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7283 type.t |= VT_UNSIGNED;
7286 /* now we convert second operand */
7287 gen_cast(&type);
7288 rc = RC_INT;
7289 if (is_float(type.t)) {
7290 rc = RC_FLOAT;
7291 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7292 /* for long longs, we use fixed registers to avoid having
7293 to handle a complicated move */
7294 rc = RC_IRET;
7297 r2 = gv(rc);
7298 /* this is horrible, but we must also convert first
7299 operand */
7300 tt = gjmp(0);
7301 gsym(u);
7302 /* put again first value and cast it */
7303 *vtop = sv;
7304 gen_cast(&type);
7305 r1 = gv(rc);
7306 move_reg(r2, r1);
7307 vtop->r = r2;
7308 gsym(tt);
7313 static void gexpr(void)
7315 while (1) {
7316 expr_eq();
7317 if (tok != ',')
7318 break;
7319 vpop();
7320 next();
7324 /* parse an expression and return its type without any side effect. */
7325 static void expr_type(CType *type)
7327 int saved_nocode_wanted;
7329 saved_nocode_wanted = nocode_wanted;
7330 nocode_wanted = 1;
7331 gexpr();
7332 *type = vtop->type;
7333 vpop();
7334 nocode_wanted = saved_nocode_wanted;
7337 /* parse a unary expression and return its type without any side
7338 effect. */
7339 static void unary_type(CType *type)
7341 int a;
7343 a = nocode_wanted;
7344 nocode_wanted = 1;
7345 unary();
7346 *type = vtop->type;
7347 vpop();
7348 nocode_wanted = a;
7351 /* parse a constant expression and return value in vtop. */
7352 static void expr_const1(void)
7354 int a;
7355 a = const_wanted;
7356 const_wanted = 1;
7357 expr_eq();
7358 const_wanted = a;
7361 /* parse an integer constant and return its value. */
7362 static int expr_const(void)
7364 int c;
7365 expr_const1();
7366 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7367 expect("constant expression");
7368 c = vtop->c.i;
7369 vpop();
7370 return c;
7373 /* return the label token if current token is a label, otherwise
7374 return zero */
7375 static int is_label(void)
7377 int last_tok;
7379 /* fast test first */
7380 if (tok < TOK_UIDENT)
7381 return 0;
7382 /* no need to save tokc because tok is an identifier */
7383 last_tok = tok;
7384 next();
7385 if (tok == ':') {
7386 next();
7387 return last_tok;
7388 } else {
7389 unget_tok(last_tok);
7390 return 0;
7394 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7395 int case_reg, int is_expr)
7397 int a, b, c, d;
7398 Sym *s;
7400 /* generate line number info */
7401 if (do_debug &&
7402 (last_line_num != file->line_num || last_ind != ind)) {
7403 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7404 last_ind = ind;
7405 last_line_num = file->line_num;
7408 if (is_expr) {
7409 /* default return value is (void) */
7410 vpushi(0);
7411 vtop->type.t = VT_VOID;
7414 if (tok == TOK_IF) {
7415 /* if test */
7416 next();
7417 skip('(');
7418 gexpr();
7419 skip(')');
7420 a = gtst(1, 0);
7421 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7422 c = tok;
7423 if (c == TOK_ELSE) {
7424 next();
7425 d = gjmp(0);
7426 gsym(a);
7427 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7428 gsym(d); /* patch else jmp */
7429 } else
7430 gsym(a);
7431 } else if (tok == TOK_WHILE) {
7432 next();
7433 d = ind;
7434 skip('(');
7435 gexpr();
7436 skip(')');
7437 a = gtst(1, 0);
7438 b = 0;
7439 block(&a, &b, case_sym, def_sym, case_reg, 0);
7440 gjmp_addr(d);
7441 gsym(a);
7442 gsym_addr(b, d);
7443 } else if (tok == '{') {
7444 Sym *llabel;
7446 next();
7447 /* record local declaration stack position */
7448 s = local_stack;
7449 llabel = local_label_stack;
7450 /* handle local labels declarations */
7451 if (tok == TOK_LABEL) {
7452 next();
7453 for(;;) {
7454 if (tok < TOK_UIDENT)
7455 expect("label identifier");
7456 label_push(&local_label_stack, tok, LABEL_DECLARED);
7457 next();
7458 if (tok == ',') {
7459 next();
7460 } else {
7461 skip(';');
7462 break;
7466 while (tok != '}') {
7467 decl(VT_LOCAL);
7468 if (tok != '}') {
7469 if (is_expr)
7470 vpop();
7471 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7474 /* pop locally defined labels */
7475 label_pop(&local_label_stack, llabel);
7476 /* pop locally defined symbols */
7477 sym_pop(&local_stack, s);
7478 next();
7479 } else if (tok == TOK_RETURN) {
7480 next();
7481 if (tok != ';') {
7482 gexpr();
7483 gen_assign_cast(&func_vt);
7484 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7485 CType type;
7486 /* if returning structure, must copy it to implicit
7487 first pointer arg location */
7488 type = func_vt;
7489 mk_pointer(&type);
7490 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7491 indir();
7492 vswap();
7493 /* copy structure value to pointer */
7494 vstore();
7495 } else if (is_float(func_vt.t)) {
7496 gv(RC_FRET);
7497 } else {
7498 gv(RC_IRET);
7500 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7502 skip(';');
7503 rsym = gjmp(rsym); /* jmp */
7504 } else if (tok == TOK_BREAK) {
7505 /* compute jump */
7506 if (!bsym)
7507 error("cannot break");
7508 *bsym = gjmp(*bsym);
7509 next();
7510 skip(';');
7511 } else if (tok == TOK_CONTINUE) {
7512 /* compute jump */
7513 if (!csym)
7514 error("cannot continue");
7515 *csym = gjmp(*csym);
7516 next();
7517 skip(';');
7518 } else if (tok == TOK_FOR) {
7519 int e;
7520 next();
7521 skip('(');
7522 if (tok != ';') {
7523 gexpr();
7524 vpop();
7526 skip(';');
7527 d = ind;
7528 c = ind;
7529 a = 0;
7530 b = 0;
7531 if (tok != ';') {
7532 gexpr();
7533 a = gtst(1, 0);
7535 skip(';');
7536 if (tok != ')') {
7537 e = gjmp(0);
7538 c = ind;
7539 gexpr();
7540 vpop();
7541 gjmp_addr(d);
7542 gsym(e);
7544 skip(')');
7545 block(&a, &b, case_sym, def_sym, case_reg, 0);
7546 gjmp_addr(c);
7547 gsym(a);
7548 gsym_addr(b, c);
7549 } else
7550 if (tok == TOK_DO) {
7551 next();
7552 a = 0;
7553 b = 0;
7554 d = ind;
7555 block(&a, &b, case_sym, def_sym, case_reg, 0);
7556 skip(TOK_WHILE);
7557 skip('(');
7558 gsym(b);
7559 gexpr();
7560 c = gtst(0, 0);
7561 gsym_addr(c, d);
7562 skip(')');
7563 gsym(a);
7564 skip(';');
7565 } else
7566 if (tok == TOK_SWITCH) {
7567 next();
7568 skip('(');
7569 gexpr();
7570 /* XXX: other types than integer */
7571 case_reg = gv(RC_INT);
7572 vpop();
7573 skip(')');
7574 a = 0;
7575 b = gjmp(0); /* jump to first case */
7576 c = 0;
7577 block(&a, csym, &b, &c, case_reg, 0);
7578 /* if no default, jmp after switch */
7579 if (c == 0)
7580 c = ind;
7581 /* default label */
7582 gsym_addr(b, c);
7583 /* break label */
7584 gsym(a);
7585 } else
7586 if (tok == TOK_CASE) {
7587 int v1, v2;
7588 if (!case_sym)
7589 expect("switch");
7590 next();
7591 v1 = expr_const();
7592 v2 = v1;
7593 if (gnu_ext && tok == TOK_DOTS) {
7594 next();
7595 v2 = expr_const();
7596 if (v2 < v1)
7597 warning("empty case range");
7599 /* since a case is like a label, we must skip it with a jmp */
7600 b = gjmp(0);
7601 gsym(*case_sym);
7602 vseti(case_reg, 0);
7603 vpushi(v1);
7604 if (v1 == v2) {
7605 gen_op(TOK_EQ);
7606 *case_sym = gtst(1, 0);
7607 } else {
7608 gen_op(TOK_GE);
7609 *case_sym = gtst(1, 0);
7610 vseti(case_reg, 0);
7611 vpushi(v2);
7612 gen_op(TOK_LE);
7613 *case_sym = gtst(1, *case_sym);
7615 gsym(b);
7616 skip(':');
7617 is_expr = 0;
7618 goto block_after_label;
7619 } else
7620 if (tok == TOK_DEFAULT) {
7621 next();
7622 skip(':');
7623 if (!def_sym)
7624 expect("switch");
7625 if (*def_sym)
7626 error("too many 'default'");
7627 *def_sym = ind;
7628 is_expr = 0;
7629 goto block_after_label;
7630 } else
7631 if (tok == TOK_GOTO) {
7632 next();
7633 if (tok == '*' && gnu_ext) {
7634 /* computed goto */
7635 next();
7636 gexpr();
7637 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7638 expect("pointer");
7639 ggoto();
7640 } else if (tok >= TOK_UIDENT) {
7641 s = label_find(tok);
7642 /* put forward definition if needed */
7643 if (!s) {
7644 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7645 } else {
7646 if (s->r == LABEL_DECLARED)
7647 s->r = LABEL_FORWARD;
7649 /* label already defined */
7650 if (s->r & LABEL_FORWARD)
7651 s->next = (void *)gjmp((long)s->next);
7652 else
7653 gjmp_addr((long)s->next);
7654 next();
7655 } else {
7656 expect("label identifier");
7658 skip(';');
7659 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7660 asm_instr();
7661 } else {
7662 b = is_label();
7663 if (b) {
7664 /* label case */
7665 s = label_find(b);
7666 if (s) {
7667 if (s->r == LABEL_DEFINED)
7668 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7669 gsym((long)s->next);
7670 s->r = LABEL_DEFINED;
7671 } else {
7672 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7674 s->next = (void *)ind;
7675 /* we accept this, but it is a mistake */
7676 block_after_label:
7677 if (tok == '}') {
7678 warning("deprecated use of label at end of compound statement");
7679 } else {
7680 if (is_expr)
7681 vpop();
7682 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7684 } else {
7685 /* expression case */
7686 if (tok != ';') {
7687 if (is_expr) {
7688 vpop();
7689 gexpr();
7690 } else {
7691 gexpr();
7692 vpop();
7695 skip(';');
7700 /* t is the array or struct type. c is the array or struct
7701 address. cur_index/cur_field is the pointer to the current
7702 value. 'size_only' is true if only size info is needed (only used
7703 in arrays) */
7704 static void decl_designator(CType *type, Section *sec, unsigned long c,
7705 int *cur_index, Sym **cur_field,
7706 int size_only)
7708 Sym *s, *f;
7709 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7710 CType type1;
7712 notfirst = 0;
7713 elem_size = 0;
7714 nb_elems = 1;
7715 if (gnu_ext && (l = is_label()) != 0)
7716 goto struct_field;
7717 while (tok == '[' || tok == '.') {
7718 if (tok == '[') {
7719 if (!(type->t & VT_ARRAY))
7720 expect("array type");
7721 s = type->ref;
7722 next();
7723 index = expr_const();
7724 if (index < 0 || (s->c >= 0 && index >= s->c))
7725 expect("invalid index");
7726 if (tok == TOK_DOTS && gnu_ext) {
7727 next();
7728 index_last = expr_const();
7729 if (index_last < 0 ||
7730 (s->c >= 0 && index_last >= s->c) ||
7731 index_last < index)
7732 expect("invalid index");
7733 } else {
7734 index_last = index;
7736 skip(']');
7737 if (!notfirst)
7738 *cur_index = index_last;
7739 type = pointed_type(type);
7740 elem_size = type_size(type, &align);
7741 c += index * elem_size;
7742 /* NOTE: we only support ranges for last designator */
7743 nb_elems = index_last - index + 1;
7744 if (nb_elems != 1) {
7745 notfirst = 1;
7746 break;
7748 } else {
7749 next();
7750 l = tok;
7751 next();
7752 struct_field:
7753 if ((type->t & VT_BTYPE) != VT_STRUCT)
7754 expect("struct/union type");
7755 s = type->ref;
7756 l |= SYM_FIELD;
7757 f = s->next;
7758 while (f) {
7759 if (f->v == l)
7760 break;
7761 f = f->next;
7763 if (!f)
7764 expect("field");
7765 if (!notfirst)
7766 *cur_field = f;
7767 /* XXX: fix this mess by using explicit storage field */
7768 type1 = f->type;
7769 type1.t |= (type->t & ~VT_TYPE);
7770 type = &type1;
7771 c += f->c;
7773 notfirst = 1;
7775 if (notfirst) {
7776 if (tok == '=') {
7777 next();
7778 } else {
7779 if (!gnu_ext)
7780 expect("=");
7782 } else {
7783 if (type->t & VT_ARRAY) {
7784 index = *cur_index;
7785 type = pointed_type(type);
7786 c += index * type_size(type, &align);
7787 } else {
7788 f = *cur_field;
7789 if (!f)
7790 error("too many field init");
7791 /* XXX: fix this mess by using explicit storage field */
7792 type1 = f->type;
7793 type1.t |= (type->t & ~VT_TYPE);
7794 type = &type1;
7795 c += f->c;
7798 decl_initializer(type, sec, c, 0, size_only);
7800 /* XXX: make it more general */
7801 if (!size_only && nb_elems > 1) {
7802 unsigned long c_end;
7803 uint8_t *src, *dst;
7804 int i;
7806 if (!sec)
7807 error("range init not supported yet for dynamic storage");
7808 c_end = c + nb_elems * elem_size;
7809 if (c_end > sec->data_allocated)
7810 section_realloc(sec, c_end);
7811 src = sec->data + c;
7812 dst = src;
7813 for(i = 1; i < nb_elems; i++) {
7814 dst += elem_size;
7815 memcpy(dst, src, elem_size);
7820 #define EXPR_VAL 0
7821 #define EXPR_CONST 1
7822 #define EXPR_ANY 2
7824 /* store a value or an expression directly in global data or in local array */
7825 static void init_putv(CType *type, Section *sec, unsigned long c,
7826 int v, int expr_type)
7828 int saved_global_expr, bt, bit_pos, bit_size;
7829 void *ptr;
7830 unsigned long long bit_mask;
7831 CType dtype;
7833 switch(expr_type) {
7834 case EXPR_VAL:
7835 vpushi(v);
7836 break;
7837 case EXPR_CONST:
7838 /* compound literals must be allocated globally in this case */
7839 saved_global_expr = global_expr;
7840 global_expr = 1;
7841 expr_const1();
7842 global_expr = saved_global_expr;
7843 /* NOTE: symbols are accepted */
7844 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7845 error("initializer element is not constant");
7846 break;
7847 case EXPR_ANY:
7848 expr_eq();
7849 break;
7852 dtype = *type;
7853 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7855 if (sec) {
7856 /* XXX: not portable */
7857 /* XXX: generate error if incorrect relocation */
7858 gen_assign_cast(&dtype);
7859 bt = type->t & VT_BTYPE;
7860 ptr = sec->data + c;
7861 /* XXX: make code faster ? */
7862 if (!(type->t & VT_BITFIELD)) {
7863 bit_pos = 0;
7864 bit_size = 32;
7865 bit_mask = -1LL;
7866 } else {
7867 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7868 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7869 bit_mask = (1LL << bit_size) - 1;
7871 if ((vtop->r & VT_SYM) &&
7872 (bt == VT_BYTE ||
7873 bt == VT_SHORT ||
7874 bt == VT_DOUBLE ||
7875 bt == VT_LDOUBLE ||
7876 bt == VT_LLONG ||
7877 (bt == VT_INT && bit_size != 32)))
7878 error("initializer element is not computable at load time");
7879 switch(bt) {
7880 case VT_BYTE:
7881 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7882 break;
7883 case VT_SHORT:
7884 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7885 break;
7886 case VT_DOUBLE:
7887 *(double *)ptr = vtop->c.d;
7888 break;
7889 case VT_LDOUBLE:
7890 *(long double *)ptr = vtop->c.ld;
7891 break;
7892 case VT_LLONG:
7893 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7894 break;
7895 default:
7896 if (vtop->r & VT_SYM) {
7897 greloc(sec, vtop->sym, c, R_DATA_32);
7899 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7900 break;
7902 vtop--;
7903 } else {
7904 vset(&dtype, VT_LOCAL, c);
7905 vswap();
7906 vstore();
7907 vpop();
7911 /* put zeros for variable based init */
7912 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7914 if (sec) {
7915 /* nothing to do because globals are already set to zero */
7916 } else {
7917 vpush_global_sym(&func_old_type, TOK_memset);
7918 vseti(VT_LOCAL, c);
7919 vpushi(0);
7920 vpushi(size);
7921 gfunc_call(3);
7925 /* 't' contains the type and storage info. 'c' is the offset of the
7926 object in section 'sec'. If 'sec' is NULL, it means stack based
7927 allocation. 'first' is true if array '{' must be read (multi
7928 dimension implicit array init handling). 'size_only' is true if
7929 size only evaluation is wanted (only for arrays). */
7930 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7931 int first, int size_only)
7933 int index, array_length, n, no_oblock, nb, parlevel, i;
7934 int size1, align1, expr_type;
7935 Sym *s, *f;
7936 CType *t1;
7938 if (type->t & VT_ARRAY) {
7939 s = type->ref;
7940 n = s->c;
7941 array_length = 0;
7942 t1 = pointed_type(type);
7943 size1 = type_size(t1, &align1);
7945 no_oblock = 1;
7946 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7947 tok == '{') {
7948 skip('{');
7949 no_oblock = 0;
7952 /* only parse strings here if correct type (otherwise: handle
7953 them as ((w)char *) expressions */
7954 if ((tok == TOK_LSTR &&
7955 (t1->t & VT_BTYPE) == VT_INT) ||
7956 (tok == TOK_STR &&
7957 (t1->t & VT_BTYPE) == VT_BYTE)) {
7958 while (tok == TOK_STR || tok == TOK_LSTR) {
7959 int cstr_len, ch;
7960 CString *cstr;
7962 cstr = tokc.cstr;
7963 /* compute maximum number of chars wanted */
7964 if (tok == TOK_STR)
7965 cstr_len = cstr->size;
7966 else
7967 cstr_len = cstr->size / sizeof(int);
7968 cstr_len--;
7969 nb = cstr_len;
7970 if (n >= 0 && nb > (n - array_length))
7971 nb = n - array_length;
7972 if (!size_only) {
7973 if (cstr_len > nb)
7974 warning("initializer-string for array is too long");
7975 /* in order to go faster for common case (char
7976 string in global variable, we handle it
7977 specifically */
7978 if (sec && tok == TOK_STR && size1 == 1) {
7979 memcpy(sec->data + c + array_length, cstr->data, nb);
7980 } else {
7981 for(i=0;i<nb;i++) {
7982 if (tok == TOK_STR)
7983 ch = ((unsigned char *)cstr->data)[i];
7984 else
7985 ch = ((int *)cstr->data)[i];
7986 init_putv(t1, sec, c + (array_length + i) * size1,
7987 ch, EXPR_VAL);
7991 array_length += nb;
7992 next();
7994 /* only add trailing zero if enough storage (no
7995 warning in this case since it is standard) */
7996 if (n < 0 || array_length < n) {
7997 if (!size_only) {
7998 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8000 array_length++;
8002 } else {
8003 index = 0;
8004 while (tok != '}') {
8005 decl_designator(type, sec, c, &index, NULL, size_only);
8006 if (n >= 0 && index >= n)
8007 error("index too large");
8008 /* must put zero in holes (note that doing it that way
8009 ensures that it even works with designators) */
8010 if (!size_only && array_length < index) {
8011 init_putz(t1, sec, c + array_length * size1,
8012 (index - array_length) * size1);
8014 index++;
8015 if (index > array_length)
8016 array_length = index;
8017 /* special test for multi dimensional arrays (may not
8018 be strictly correct if designators are used at the
8019 same time) */
8020 if (index >= n && no_oblock)
8021 break;
8022 if (tok == '}')
8023 break;
8024 skip(',');
8027 if (!no_oblock)
8028 skip('}');
8029 /* put zeros at the end */
8030 if (!size_only && n >= 0 && array_length < n) {
8031 init_putz(t1, sec, c + array_length * size1,
8032 (n - array_length) * size1);
8034 /* patch type size if needed */
8035 if (n < 0)
8036 s->c = array_length;
8037 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8038 (sec || !first || tok == '{')) {
8039 int par_count;
8041 /* NOTE: the previous test is a specific case for automatic
8042 struct/union init */
8043 /* XXX: union needs only one init */
8045 /* XXX: this test is incorrect for local initializers
8046 beginning with ( without {. It would be much more difficult
8047 to do it correctly (ideally, the expression parser should
8048 be used in all cases) */
8049 par_count = 0;
8050 if (tok == '(') {
8051 AttributeDef ad1;
8052 CType type1;
8053 next();
8054 while (tok == '(') {
8055 par_count++;
8056 next();
8058 if (!parse_btype(&type1, &ad1))
8059 expect("cast");
8060 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8061 #if 0
8062 if (!is_assignable_types(type, &type1))
8063 error("invalid type for cast");
8064 #endif
8065 skip(')');
8067 no_oblock = 1;
8068 if (first || tok == '{') {
8069 skip('{');
8070 no_oblock = 0;
8072 s = type->ref;
8073 f = s->next;
8074 array_length = 0;
8075 index = 0;
8076 n = s->c;
8077 while (tok != '}') {
8078 decl_designator(type, sec, c, NULL, &f, size_only);
8079 index = f->c;
8080 if (!size_only && array_length < index) {
8081 init_putz(type, sec, c + array_length,
8082 index - array_length);
8084 index = index + type_size(&f->type, &align1);
8085 if (index > array_length)
8086 array_length = index;
8087 f = f->next;
8088 if (no_oblock && f == NULL)
8089 break;
8090 if (tok == '}')
8091 break;
8092 skip(',');
8094 /* put zeros at the end */
8095 if (!size_only && array_length < n) {
8096 init_putz(type, sec, c + array_length,
8097 n - array_length);
8099 if (!no_oblock)
8100 skip('}');
8101 while (par_count) {
8102 skip(')');
8103 par_count--;
8105 } else if (tok == '{') {
8106 next();
8107 decl_initializer(type, sec, c, first, size_only);
8108 skip('}');
8109 } else if (size_only) {
8110 /* just skip expression */
8111 parlevel = 0;
8112 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8113 tok != -1) {
8114 if (tok == '(')
8115 parlevel++;
8116 else if (tok == ')')
8117 parlevel--;
8118 next();
8120 } else {
8121 /* currently, we always use constant expression for globals
8122 (may change for scripting case) */
8123 expr_type = EXPR_CONST;
8124 if (!sec)
8125 expr_type = EXPR_ANY;
8126 init_putv(type, sec, c, 0, expr_type);
8130 /* parse an initializer for type 't' if 'has_init' is non zero, and
8131 allocate space in local or global data space ('r' is either
8132 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8133 variable 'v' of scope 'scope' is declared before initializers are
8134 parsed. If 'v' is zero, then a reference to the new object is put
8135 in the value stack. If 'has_init' is 2, a special parsing is done
8136 to handle string constants. */
8137 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8138 int has_init, int v, int scope)
8140 int size, align, addr, data_offset;
8141 int level;
8142 ParseState saved_parse_state;
8143 TokenString init_str;
8144 Section *sec;
8146 size = type_size(type, &align);
8147 /* If unknown size, we must evaluate it before
8148 evaluating initializers because
8149 initializers can generate global data too
8150 (e.g. string pointers or ISOC99 compound
8151 literals). It also simplifies local
8152 initializers handling */
8153 tok_str_new(&init_str);
8154 if (size < 0) {
8155 if (!has_init)
8156 error("unknown type size");
8157 /* get all init string */
8158 if (has_init == 2) {
8159 /* only get strings */
8160 while (tok == TOK_STR || tok == TOK_LSTR) {
8161 tok_str_add_tok(&init_str);
8162 next();
8164 } else {
8165 level = 0;
8166 while (level > 0 || (tok != ',' && tok != ';')) {
8167 if (tok < 0)
8168 error("unexpected end of file in initializer");
8169 tok_str_add_tok(&init_str);
8170 if (tok == '{')
8171 level++;
8172 else if (tok == '}') {
8173 if (level == 0)
8174 break;
8175 level--;
8177 next();
8180 tok_str_add(&init_str, -1);
8181 tok_str_add(&init_str, 0);
8183 /* compute size */
8184 save_parse_state(&saved_parse_state);
8186 macro_ptr = init_str.str;
8187 next();
8188 decl_initializer(type, NULL, 0, 1, 1);
8189 /* prepare second initializer parsing */
8190 macro_ptr = init_str.str;
8191 next();
8193 /* if still unknown size, error */
8194 size = type_size(type, &align);
8195 if (size < 0)
8196 error("unknown type size");
8198 /* take into account specified alignment if bigger */
8199 if (ad->aligned > align)
8200 align = ad->aligned;
8201 if ((r & VT_VALMASK) == VT_LOCAL) {
8202 sec = NULL;
8203 if (do_bounds_check && (type->t & VT_ARRAY))
8204 loc--;
8205 loc = (loc - size) & -align;
8206 addr = loc;
8207 /* handles bounds */
8208 /* XXX: currently, since we do only one pass, we cannot track
8209 '&' operators, so we add only arrays */
8210 if (do_bounds_check && (type->t & VT_ARRAY)) {
8211 unsigned long *bounds_ptr;
8212 /* add padding between regions */
8213 loc--;
8214 /* then add local bound info */
8215 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8216 bounds_ptr[0] = addr;
8217 bounds_ptr[1] = size;
8219 if (v) {
8220 /* local variable */
8221 sym_push(v, type, r, addr);
8222 } else {
8223 /* push local reference */
8224 vset(type, r, addr);
8226 } else {
8227 Sym *sym;
8229 sym = NULL;
8230 if (v && scope == VT_CONST) {
8231 /* see if the symbol was already defined */
8232 sym = sym_find(v);
8233 if (sym) {
8234 if (!is_compatible_types(&sym->type, type))
8235 error("incompatible types for redefinition of '%s'",
8236 get_tok_str(v, NULL));
8237 if (sym->type.t & VT_EXTERN) {
8238 /* if the variable is extern, it was not allocated */
8239 sym->type.t &= ~VT_EXTERN;
8240 } else {
8241 /* we accept several definitions of the same
8242 global variable. this is tricky, because we
8243 must play with the SHN_COMMON type of the symbol */
8244 /* XXX: should check if the variable was already
8245 initialized. It is incorrect to initialized it
8246 twice */
8247 /* no init data, we won't add more to the symbol */
8248 if (!has_init)
8249 goto no_alloc;
8254 /* allocate symbol in corresponding section */
8255 sec = ad->section;
8256 if (!sec) {
8257 if (has_init)
8258 sec = data_section;
8260 if (sec) {
8261 data_offset = sec->data_offset;
8262 data_offset = (data_offset + align - 1) & -align;
8263 addr = data_offset;
8264 /* very important to increment global pointer at this time
8265 because initializers themselves can create new initializers */
8266 data_offset += size;
8267 /* add padding if bound check */
8268 if (do_bounds_check)
8269 data_offset++;
8270 sec->data_offset = data_offset;
8271 /* allocate section space to put the data */
8272 if (sec->sh_type != SHT_NOBITS &&
8273 data_offset > sec->data_allocated)
8274 section_realloc(sec, data_offset);
8275 } else {
8276 addr = 0; /* avoid warning */
8279 if (v) {
8280 if (scope == VT_CONST) {
8281 if (!sym)
8282 goto do_def;
8283 } else {
8284 do_def:
8285 sym = sym_push(v, type, r | VT_SYM, 0);
8287 /* update symbol definition */
8288 if (sec) {
8289 put_extern_sym(sym, sec, addr, size);
8290 } else {
8291 Elf32_Sym *esym;
8292 /* put a common area */
8293 put_extern_sym(sym, NULL, align, size);
8294 /* XXX: find a nicer way */
8295 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8296 esym->st_shndx = SHN_COMMON;
8298 } else {
8299 CValue cval;
8301 /* push global reference */
8302 sym = get_sym_ref(type, sec, addr, size);
8303 cval.ul = 0;
8304 vsetc(type, VT_CONST | VT_SYM, &cval);
8305 vtop->sym = sym;
8308 /* handles bounds now because the symbol must be defined
8309 before for the relocation */
8310 if (do_bounds_check) {
8311 unsigned long *bounds_ptr;
8313 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8314 /* then add global bound info */
8315 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8316 bounds_ptr[0] = 0; /* relocated */
8317 bounds_ptr[1] = size;
8320 if (has_init) {
8321 decl_initializer(type, sec, addr, 1, 0);
8322 /* restore parse state if needed */
8323 if (init_str.str) {
8324 tok_str_free(init_str.str);
8325 restore_parse_state(&saved_parse_state);
8328 no_alloc: ;
8331 void put_func_debug(Sym *sym)
8333 char buf[512];
8335 /* stabs info */
8336 /* XXX: we put here a dummy type */
8337 snprintf(buf, sizeof(buf), "%s:%c1",
8338 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8339 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8340 cur_text_section, sym->c);
8341 last_ind = 0;
8342 last_line_num = 0;
8345 /* not finished : try to put some local vars in registers */
8346 //#define CONFIG_REG_VARS
8348 #ifdef CONFIG_REG_VARS
8349 void add_var_ref(int t)
8351 printf("%s:%d: &%s\n",
8352 file->filename, file->line_num,
8353 get_tok_str(t, NULL));
8356 /* first pass on a function with heuristic to extract variable usage
8357 and pointer references to local variables for register allocation */
8358 void analyse_function(void)
8360 int level, t;
8362 for(;;) {
8363 if (tok == -1)
8364 break;
8365 /* any symbol coming after '&' is considered as being a
8366 variable whose reference is taken. It is highly unaccurate
8367 but it is difficult to do better without a complete parse */
8368 if (tok == '&') {
8369 next();
8370 /* if '& number', then no need to examine next tokens */
8371 if (tok == TOK_CINT ||
8372 tok == TOK_CUINT ||
8373 tok == TOK_CLLONG ||
8374 tok == TOK_CULLONG) {
8375 continue;
8376 } else if (tok >= TOK_UIDENT) {
8377 /* if '& ident [' or '& ident ->', then ident address
8378 is not needed */
8379 t = tok;
8380 next();
8381 if (tok != '[' && tok != TOK_ARROW)
8382 add_var_ref(t);
8383 } else {
8384 level = 0;
8385 while (tok != '}' && tok != ';' &&
8386 !((tok == ',' || tok == ')') && level == 0)) {
8387 if (tok >= TOK_UIDENT) {
8388 add_var_ref(tok);
8389 } else if (tok == '(') {
8390 level++;
8391 } else if (tok == ')') {
8392 level--;
8394 next();
8397 } else {
8398 next();
8402 #endif
8404 /* parse an old style function declaration list */
8405 /* XXX: check multiple parameter */
8406 static void func_decl_list(Sym *func_sym)
8408 AttributeDef ad;
8409 int v;
8410 Sym *s;
8411 CType btype, type;
8413 /* parse each declaration */
8414 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8415 if (!parse_btype(&btype, &ad))
8416 expect("declaration list");
8417 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8418 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8419 tok == ';') {
8420 /* we accept no variable after */
8421 } else {
8422 for(;;) {
8423 type = btype;
8424 type_decl(&type, &ad, &v, TYPE_DIRECT);
8425 /* find parameter in function parameter list */
8426 s = func_sym->next;
8427 while (s != NULL) {
8428 if ((s->v & ~SYM_FIELD) == v)
8429 goto found;
8430 s = s->next;
8432 error("declaration for parameter '%s' but no such parameter",
8433 get_tok_str(v, NULL));
8434 found:
8435 /* check that no storage specifier except 'register' was given */
8436 if (type.t & VT_STORAGE)
8437 error("storage class specified for '%s'", get_tok_str(v, NULL));
8438 convert_parameter_type(&type);
8439 /* we can add the type (NOTE: it could be local to the function) */
8440 s->type = type;
8441 /* accept other parameters */
8442 if (tok == ',')
8443 next();
8444 else
8445 break;
8448 skip(';');
8452 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8453 static void decl(int l)
8455 int v, has_init, r;
8456 CType type, btype;
8457 Sym *sym;
8458 AttributeDef ad;
8460 while (1) {
8461 if (!parse_btype(&btype, &ad)) {
8462 /* skip redundant ';' */
8463 /* XXX: find more elegant solution */
8464 if (tok == ';') {
8465 next();
8466 continue;
8468 /* special test for old K&R protos without explicit int
8469 type. Only accepted when defining global data */
8470 if (l == VT_LOCAL || tok < TOK_DEFINE)
8471 break;
8472 btype.t = VT_INT;
8474 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8475 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8476 tok == ';') {
8477 /* we accept no variable after */
8478 next();
8479 continue;
8481 while (1) { /* iterate thru each declaration */
8482 type = btype;
8483 type_decl(&type, &ad, &v, TYPE_DIRECT);
8484 #if 0
8486 char buf[500];
8487 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8488 printf("type = '%s'\n", buf);
8490 #endif
8491 if ((type.t & VT_BTYPE) == VT_FUNC) {
8492 /* if old style function prototype, we accept a
8493 declaration list */
8494 sym = type.ref;
8495 if (sym->c == FUNC_OLD)
8496 func_decl_list(sym);
8499 if (tok == '{') {
8500 #ifdef CONFIG_REG_VARS
8501 TokenString func_str;
8502 ParseState saved_parse_state;
8503 int block_level;
8504 #endif
8506 if (l == VT_LOCAL)
8507 error("cannot use local functions");
8508 if (!(type.t & VT_FUNC))
8509 expect("function definition");
8510 /* XXX: cannot do better now: convert extern line to static inline */
8511 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8512 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8514 #ifdef CONFIG_REG_VARS
8515 /* parse all function code and record it */
8517 tok_str_new(&func_str);
8519 block_level = 0;
8520 for(;;) {
8521 int t;
8522 if (tok == -1)
8523 error("unexpected end of file");
8524 tok_str_add_tok(&func_str);
8525 t = tok;
8526 next();
8527 if (t == '{') {
8528 block_level++;
8529 } else if (t == '}') {
8530 block_level--;
8531 if (block_level == 0)
8532 break;
8535 tok_str_add(&func_str, -1);
8536 tok_str_add(&func_str, 0);
8538 save_parse_state(&saved_parse_state);
8540 macro_ptr = func_str.str;
8541 next();
8542 analyse_function();
8543 #endif
8545 /* compute text section */
8546 cur_text_section = ad.section;
8547 if (!cur_text_section)
8548 cur_text_section = text_section;
8549 ind = cur_text_section->data_offset;
8550 funcname = get_tok_str(v, NULL);
8551 sym = sym_find(v);
8552 if (sym) {
8553 /* if symbol is already defined, then put complete type */
8554 sym->type = type;
8555 } else {
8556 /* put function symbol */
8557 sym = global_identifier_push(v, type.t, 0);
8558 sym->type.ref = type.ref;
8560 /* NOTE: we patch the symbol size later */
8561 put_extern_sym(sym, cur_text_section, ind, 0);
8562 func_ind = ind;
8563 sym->r = VT_SYM | VT_CONST;
8564 /* put debug symbol */
8565 if (do_debug)
8566 put_func_debug(sym);
8567 /* push a dummy symbol to enable local sym storage */
8568 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8569 gfunc_prolog(&type);
8570 loc = 0;
8571 rsym = 0;
8572 #ifdef CONFIG_REG_VARS
8573 macro_ptr = func_str.str;
8574 next();
8575 #endif
8576 block(NULL, NULL, NULL, NULL, 0, 0);
8577 gsym(rsym);
8578 gfunc_epilog();
8579 cur_text_section->data_offset = ind;
8580 label_pop(&global_label_stack, NULL);
8581 sym_pop(&local_stack, NULL); /* reset local stack */
8582 /* end of function */
8583 /* patch symbol size */
8584 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8585 ind - func_ind;
8586 if (do_debug) {
8587 put_stabn(N_FUN, 0, 0, ind - func_ind);
8589 funcname = ""; /* for safety */
8590 func_vt.t = VT_VOID; /* for safety */
8591 ind = 0; /* for safety */
8593 #ifdef CONFIG_REG_VARS
8594 tok_str_free(func_str.str);
8595 restore_parse_state(&saved_parse_state);
8596 #endif
8597 break;
8598 } else {
8599 if (btype.t & VT_TYPEDEF) {
8600 /* save typedefed type */
8601 /* XXX: test storage specifiers ? */
8602 sym = sym_push(v, &type, 0, 0);
8603 sym->type.t |= VT_TYPEDEF;
8604 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8605 /* external function definition */
8606 external_sym(v, &type, 0);
8607 } else {
8608 /* not lvalue if array */
8609 r = 0;
8610 if (!(type.t & VT_ARRAY))
8611 r |= lvalue_type(type.t);
8612 has_init = (tok == '=');
8613 if ((btype.t & VT_EXTERN) ||
8614 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8615 !has_init && l == VT_CONST && type.ref->c < 0)) {
8616 /* external variable */
8617 /* NOTE: as GCC, uninitialized global static
8618 arrays of null size are considered as
8619 extern */
8620 external_sym(v, &type, r);
8621 } else {
8622 if (type.t & VT_STATIC)
8623 r |= VT_CONST;
8624 else
8625 r |= l;
8626 if (has_init)
8627 next();
8628 decl_initializer_alloc(&type, &ad, r,
8629 has_init, v, l);
8632 if (tok != ',') {
8633 skip(';');
8634 break;
8636 next();
8642 /* better than nothing, but needs extension to handle '-E' option
8643 correctly too */
8644 static void preprocess_init(TCCState *s1)
8646 s1->include_stack_ptr = s1->include_stack;
8647 /* XXX: move that before to avoid having to initialize
8648 file->ifdef_stack_ptr ? */
8649 s1->ifdef_stack_ptr = s1->ifdef_stack;
8650 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8652 /* XXX: not ANSI compliant: bound checking says error */
8653 vtop = vstack - 1;
8656 /* compile the C file opened in 'file'. Return non zero if errors. */
8657 static int tcc_compile(TCCState *s1)
8659 Sym *define_start;
8660 char buf[512];
8661 volatile int section_sym;
8663 #ifdef INC_DEBUG
8664 printf("%s: **** new file\n", file->filename);
8665 #endif
8666 preprocess_init(s1);
8668 funcname = "";
8669 anon_sym = SYM_FIRST_ANOM;
8671 /* file info: full path + filename */
8672 section_sym = 0; /* avoid warning */
8673 if (do_debug) {
8674 section_sym = put_elf_sym(symtab_section, 0, 0,
8675 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8676 text_section->sh_num, NULL);
8677 getcwd(buf, sizeof(buf));
8678 pstrcat(buf, sizeof(buf), "/");
8679 put_stabs_r(buf, N_SO, 0, 0,
8680 text_section->data_offset, text_section, section_sym);
8681 put_stabs_r(file->filename, N_SO, 0, 0,
8682 text_section->data_offset, text_section, section_sym);
8684 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8685 symbols can be safely used */
8686 put_elf_sym(symtab_section, 0, 0,
8687 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8688 SHN_ABS, file->filename);
8690 /* define some often used types */
8691 int_type.t = VT_INT;
8693 char_pointer_type.t = VT_BYTE;
8694 mk_pointer(&char_pointer_type);
8696 func_old_type.t = VT_FUNC;
8697 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8699 #if 0
8700 /* define 'void *alloca(unsigned int)' builtin function */
8702 Sym *s1;
8704 p = anon_sym++;
8705 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8706 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8707 s1->next = NULL;
8708 sym->next = s1;
8709 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8711 #endif
8713 define_start = define_stack;
8715 if (setjmp(s1->error_jmp_buf) == 0) {
8716 s1->nb_errors = 0;
8717 s1->error_set_jmp_enabled = 1;
8719 ch = file->buf_ptr[0];
8720 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8721 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8722 next();
8723 decl(VT_CONST);
8724 if (tok != TOK_EOF)
8725 expect("declaration");
8727 /* end of translation unit info */
8728 if (do_debug) {
8729 put_stabs_r(NULL, N_SO, 0, 0,
8730 text_section->data_offset, text_section, section_sym);
8733 s1->error_set_jmp_enabled = 0;
8735 /* reset define stack, but leave -Dsymbols (may be incorrect if
8736 they are undefined) */
8737 free_defines(define_start);
8739 sym_pop(&global_stack, NULL);
8741 return s1->nb_errors != 0 ? -1 : 0;
8744 #ifdef LIBTCC
8745 int tcc_compile_string(TCCState *s, const char *str)
8747 BufferedFile bf1, *bf = &bf1;
8748 int ret, len;
8749 char *buf;
8751 /* init file structure */
8752 bf->fd = -1;
8753 /* XXX: avoid copying */
8754 len = strlen(str);
8755 buf = tcc_malloc(len + 1);
8756 if (!buf)
8757 return -1;
8758 memcpy(buf, str, len);
8759 buf[len] = CH_EOB;
8760 bf->buf_ptr = buf;
8761 bf->buf_end = buf + len;
8762 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8763 bf->line_num = 1;
8764 file = bf;
8766 ret = tcc_compile(s);
8768 tcc_free(buf);
8770 /* currently, no need to close */
8771 return ret;
8773 #endif
8775 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8776 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8778 BufferedFile bf1, *bf = &bf1;
8780 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8781 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8782 /* default value */
8783 if (!value)
8784 value = "1";
8785 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8787 /* init file structure */
8788 bf->fd = -1;
8789 bf->buf_ptr = bf->buffer;
8790 bf->buf_end = bf->buffer + strlen(bf->buffer);
8791 *bf->buf_end = CH_EOB;
8792 bf->filename[0] = '\0';
8793 bf->line_num = 1;
8794 file = bf;
8796 s1->include_stack_ptr = s1->include_stack;
8798 /* parse with define parser */
8799 ch = file->buf_ptr[0];
8800 next_nomacro();
8801 parse_define();
8802 file = NULL;
8805 /* undefine a preprocessor symbol */
8806 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8808 TokenSym *ts;
8809 Sym *s;
8810 ts = tok_alloc(sym, strlen(sym));
8811 s = define_find(ts->tok);
8812 /* undefine symbol by putting an invalid name */
8813 if (s)
8814 define_undef(s);
8817 #ifdef CONFIG_TCC_ASM
8819 #include "i386-asm.c"
8820 #include "tccasm.c"
8822 #else
8823 static void asm_instr(void)
8825 error("inline asm() not supported");
8827 #endif
8829 #include "tccelf.c"
8831 /* print the position in the source file of PC value 'pc' by reading
8832 the stabs debug information */
8833 static void rt_printline(unsigned long wanted_pc)
8835 Stab_Sym *sym, *sym_end;
8836 char func_name[128], last_func_name[128];
8837 unsigned long func_addr, last_pc, pc;
8838 const char *incl_files[INCLUDE_STACK_SIZE];
8839 int incl_index, len, last_line_num, i;
8840 const char *str, *p;
8842 fprintf(stderr, "0x%08lx:", wanted_pc);
8844 func_name[0] = '\0';
8845 func_addr = 0;
8846 incl_index = 0;
8847 last_func_name[0] = '\0';
8848 last_pc = 0xffffffff;
8849 last_line_num = 1;
8850 sym = (Stab_Sym *)stab_section->data + 1;
8851 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8852 while (sym < sym_end) {
8853 switch(sym->n_type) {
8854 /* function start or end */
8855 case N_FUN:
8856 if (sym->n_strx == 0) {
8857 /* we test if between last line and end of function */
8858 pc = sym->n_value + func_addr;
8859 if (wanted_pc >= last_pc && wanted_pc < pc)
8860 goto found;
8861 func_name[0] = '\0';
8862 func_addr = 0;
8863 } else {
8864 str = stabstr_section->data + sym->n_strx;
8865 p = strchr(str, ':');
8866 if (!p) {
8867 pstrcpy(func_name, sizeof(func_name), str);
8868 } else {
8869 len = p - str;
8870 if (len > sizeof(func_name) - 1)
8871 len = sizeof(func_name) - 1;
8872 memcpy(func_name, str, len);
8873 func_name[len] = '\0';
8875 func_addr = sym->n_value;
8877 break;
8878 /* line number info */
8879 case N_SLINE:
8880 pc = sym->n_value + func_addr;
8881 if (wanted_pc >= last_pc && wanted_pc < pc)
8882 goto found;
8883 last_pc = pc;
8884 last_line_num = sym->n_desc;
8885 /* XXX: slow! */
8886 strcpy(last_func_name, func_name);
8887 break;
8888 /* include files */
8889 case N_BINCL:
8890 str = stabstr_section->data + sym->n_strx;
8891 add_incl:
8892 if (incl_index < INCLUDE_STACK_SIZE) {
8893 incl_files[incl_index++] = str;
8895 break;
8896 case N_EINCL:
8897 if (incl_index > 1)
8898 incl_index--;
8899 break;
8900 case N_SO:
8901 if (sym->n_strx == 0) {
8902 incl_index = 0; /* end of translation unit */
8903 } else {
8904 str = stabstr_section->data + sym->n_strx;
8905 /* do not add path */
8906 len = strlen(str);
8907 if (len > 0 && str[len - 1] != '/')
8908 goto add_incl;
8910 break;
8912 sym++;
8915 /* second pass: we try symtab symbols (no line number info) */
8916 incl_index = 0;
8918 Elf32_Sym *sym, *sym_end;
8919 int type;
8921 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8922 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8923 sym < sym_end;
8924 sym++) {
8925 type = ELF32_ST_TYPE(sym->st_info);
8926 if (type == STT_FUNC) {
8927 if (wanted_pc >= sym->st_value &&
8928 wanted_pc < sym->st_value + sym->st_size) {
8929 pstrcpy(last_func_name, sizeof(last_func_name),
8930 strtab_section->data + sym->st_name);
8931 goto found;
8936 /* did not find any info: */
8937 fprintf(stderr, " ???\n");
8938 return;
8939 found:
8940 if (last_func_name[0] != '\0') {
8941 fprintf(stderr, " %s()", last_func_name);
8943 if (incl_index > 0) {
8944 fprintf(stderr, " (%s:%d",
8945 incl_files[incl_index - 1], last_line_num);
8946 for(i = incl_index - 2; i >= 0; i--)
8947 fprintf(stderr, ", included from %s", incl_files[i]);
8948 fprintf(stderr, ")");
8950 fprintf(stderr, "\n");
8953 #ifndef WIN32
8955 #ifdef __i386__
8957 /* fix for glibc 2.1 */
8958 #ifndef REG_EIP
8959 #define REG_EIP EIP
8960 #define REG_EBP EBP
8961 #endif
8963 /* return the PC at frame level 'level'. Return non zero if not found */
8964 static int rt_get_caller_pc(unsigned long *paddr,
8965 ucontext_t *uc, int level)
8967 unsigned long fp;
8968 int i;
8970 if (level == 0) {
8971 #ifdef __FreeBSD__
8972 *paddr = uc->uc_mcontext.mc_eip;
8973 #else
8974 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8975 #endif
8976 return 0;
8977 } else {
8978 #ifdef __FreeBSD__
8979 fp = uc->uc_mcontext.mc_ebp;
8980 #else
8981 fp = uc->uc_mcontext.gregs[REG_EBP];
8982 #endif
8983 for(i=1;i<level;i++) {
8984 /* XXX: check address validity with program info */
8985 if (fp <= 0x1000 || fp >= 0xc0000000)
8986 return -1;
8987 fp = ((unsigned long *)fp)[0];
8989 *paddr = ((unsigned long *)fp)[1];
8990 return 0;
8993 #else
8994 #error add arch specific rt_get_caller_pc()
8995 #endif
8997 /* emit a run time error at position 'pc' */
8998 void rt_error(ucontext_t *uc, const char *fmt, ...)
9000 va_list ap;
9001 unsigned long pc;
9002 int i;
9004 va_start(ap, fmt);
9005 fprintf(stderr, "Runtime error: ");
9006 vfprintf(stderr, fmt, ap);
9007 fprintf(stderr, "\n");
9008 for(i=0;i<num_callers;i++) {
9009 if (rt_get_caller_pc(&pc, uc, i) < 0)
9010 break;
9011 if (i == 0)
9012 fprintf(stderr, "at ");
9013 else
9014 fprintf(stderr, "by ");
9015 rt_printline(pc);
9017 exit(255);
9018 va_end(ap);
9021 /* signal handler for fatal errors */
9022 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9024 ucontext_t *uc = puc;
9026 switch(signum) {
9027 case SIGFPE:
9028 switch(siginf->si_code) {
9029 case FPE_INTDIV:
9030 case FPE_FLTDIV:
9031 rt_error(uc, "division by zero");
9032 break;
9033 default:
9034 rt_error(uc, "floating point exception");
9035 break;
9037 break;
9038 case SIGBUS:
9039 case SIGSEGV:
9040 if (rt_bound_error_msg && *rt_bound_error_msg)
9041 rt_error(uc, *rt_bound_error_msg);
9042 else
9043 rt_error(uc, "dereferencing invalid pointer");
9044 break;
9045 case SIGILL:
9046 rt_error(uc, "illegal instruction");
9047 break;
9048 case SIGABRT:
9049 rt_error(uc, "abort() called");
9050 break;
9051 default:
9052 rt_error(uc, "caught signal %d", signum);
9053 break;
9055 exit(255);
9057 #endif
9059 /* do all relocations (needed before using tcc_get_symbol()) */
9060 int tcc_relocate(TCCState *s1)
9062 Section *s;
9063 int i;
9065 s1->nb_errors = 0;
9067 tcc_add_runtime(s1);
9069 relocate_common_syms();
9071 /* compute relocation address : section are relocated in place. We
9072 also alloc the bss space */
9073 for(i = 1; i < s1->nb_sections; i++) {
9074 s = s1->sections[i];
9075 if (s->sh_flags & SHF_ALLOC) {
9076 if (s->sh_type == SHT_NOBITS)
9077 s->data = tcc_mallocz(s->data_offset);
9078 s->sh_addr = (unsigned long)s->data;
9082 relocate_syms(s1, 1);
9084 if (s1->nb_errors != 0)
9085 return -1;
9087 /* relocate each section */
9088 for(i = 1; i < s1->nb_sections; i++) {
9089 s = s1->sections[i];
9090 if (s->reloc)
9091 relocate_section(s1, s);
9093 return 0;
9096 /* launch the compiled program with the given arguments */
9097 int tcc_run(TCCState *s1, int argc, char **argv)
9099 int (*prog_main)(int, char **);
9101 if (tcc_relocate(s1) < 0)
9102 return -1;
9104 prog_main = tcc_get_symbol(s1, "main");
9106 if (do_debug) {
9107 #ifdef WIN32
9108 error("debug mode currently not available for Windows");
9109 #else
9110 struct sigaction sigact;
9111 /* install TCC signal handlers to print debug info on fatal
9112 runtime errors */
9113 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9114 sigact.sa_sigaction = sig_error;
9115 sigemptyset(&sigact.sa_mask);
9116 sigaction(SIGFPE, &sigact, NULL);
9117 sigaction(SIGILL, &sigact, NULL);
9118 sigaction(SIGSEGV, &sigact, NULL);
9119 sigaction(SIGBUS, &sigact, NULL);
9120 sigaction(SIGABRT, &sigact, NULL);
9121 #endif
9124 #ifdef CONFIG_TCC_BCHECK
9125 if (do_bounds_check) {
9126 void (*bound_init)(void);
9128 /* set error function */
9129 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
9131 /* XXX: use .init section so that it also work in binary ? */
9132 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
9133 bound_init();
9135 #endif
9136 return (*prog_main)(argc, argv);
9139 TCCState *tcc_new(void)
9141 const char *p, *r;
9142 TCCState *s;
9143 TokenSym *ts;
9144 int i, c;
9146 s = tcc_mallocz(sizeof(TCCState));
9147 if (!s)
9148 return NULL;
9149 tcc_state = s;
9150 s->output_type = TCC_OUTPUT_MEMORY;
9152 /* init isid table */
9153 for(i=0;i<256;i++)
9154 isidnum_table[i] = isid(i) || isnum(i);
9156 /* add all tokens */
9157 table_ident = NULL;
9158 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9160 tok_ident = TOK_IDENT;
9161 p = tcc_keywords;
9162 while (*p) {
9163 r = p;
9164 for(;;) {
9165 c = *r++;
9166 if (c == '\0')
9167 break;
9169 ts = tok_alloc(p, r - p - 1);
9170 p = r;
9173 /* we add dummy defines for some special macros to speed up tests
9174 and to have working defined() */
9175 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9176 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9177 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9178 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9180 /* standard defines */
9181 tcc_define_symbol(s, "__STDC__", NULL);
9182 #if defined(TCC_TARGET_I386)
9183 tcc_define_symbol(s, "__i386__", NULL);
9184 #endif
9185 #if defined(linux)
9186 tcc_define_symbol(s, "__linux__", NULL);
9187 tcc_define_symbol(s, "linux", NULL);
9188 #endif
9189 /* tiny C specific defines */
9190 tcc_define_symbol(s, "__TINYC__", NULL);
9192 /* tiny C & gcc defines */
9193 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9194 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9195 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9197 /* default library paths */
9198 tcc_add_library_path(s, "/usr/local/lib");
9199 tcc_add_library_path(s, "/usr/lib");
9200 tcc_add_library_path(s, "/lib");
9202 /* no section zero */
9203 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9205 /* create standard sections */
9206 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9207 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9208 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9210 /* symbols are always generated for linking stage */
9211 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9212 ".strtab",
9213 ".hashtab", SHF_PRIVATE);
9214 strtab_section = symtab_section->link;
9216 /* private symbol table for dynamic symbols */
9217 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9218 ".dynstrtab",
9219 ".dynhashtab", SHF_PRIVATE);
9220 s->alacarte_link = 1;
9221 return s;
9224 void tcc_delete(TCCState *s1)
9226 int i, n;
9228 /* free -D defines */
9229 free_defines(NULL);
9231 /* free tokens */
9232 n = tok_ident - TOK_IDENT;
9233 for(i = 0; i < n; i++)
9234 tcc_free(table_ident[i]);
9235 tcc_free(table_ident);
9237 /* free all sections */
9239 free_section(symtab_section->hash);
9241 free_section(s1->dynsymtab_section->hash);
9242 free_section(s1->dynsymtab_section->link);
9243 free_section(s1->dynsymtab_section);
9245 for(i = 1; i < s1->nb_sections; i++)
9246 free_section(s1->sections[i]);
9247 tcc_free(s1->sections);
9249 /* free loaded dlls array */
9250 for(i = 0; i < s1->nb_loaded_dlls; i++)
9251 tcc_free(s1->loaded_dlls[i]);
9252 tcc_free(s1->loaded_dlls);
9254 /* library paths */
9255 for(i = 0; i < s1->nb_library_paths; i++)
9256 tcc_free(s1->library_paths[i]);
9257 tcc_free(s1->library_paths);
9259 /* cached includes */
9260 for(i = 0; i < s1->nb_cached_includes; i++)
9261 tcc_free(s1->cached_includes[i]);
9262 tcc_free(s1->cached_includes);
9264 for(i = 0; i < s1->nb_include_paths; i++)
9265 tcc_free(s1->include_paths[i]);
9266 tcc_free(s1->include_paths);
9268 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9269 tcc_free(s1->sysinclude_paths[i]);
9270 tcc_free(s1->sysinclude_paths);
9272 tcc_free(s1);
9275 int tcc_add_include_path(TCCState *s1, const char *pathname)
9277 char *pathname1;
9279 pathname1 = tcc_strdup(pathname);
9280 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9281 return 0;
9284 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9286 char *pathname1;
9288 pathname1 = tcc_strdup(pathname);
9289 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9290 return 0;
9293 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9295 const char *ext, *filename1;
9296 Elf32_Ehdr ehdr;
9297 int fd, ret;
9298 BufferedFile *saved_file;
9300 /* find source file type with extension */
9301 filename1 = strrchr(filename, '/');
9302 if (filename1)
9303 filename1++;
9304 else
9305 filename1 = filename;
9306 ext = strrchr(filename1, '.');
9307 if (ext)
9308 ext++;
9310 /* open the file */
9311 saved_file = file;
9312 file = tcc_open(s1, filename);
9313 if (!file) {
9314 if (flags & AFF_PRINT_ERROR) {
9315 error_noabort("file '%s' not found", filename);
9317 ret = -1;
9318 goto fail1;
9321 if (!ext || !strcmp(ext, "c")) {
9322 /* C file assumed */
9323 ret = tcc_compile(s1);
9324 } else
9325 #ifdef CONFIG_TCC_ASM
9326 if (!strcmp(ext, "S")) {
9327 /* preprocessed assembler */
9328 ret = tcc_assemble(s1, 1);
9329 } else if (!strcmp(ext, "s")) {
9330 /* non preprocessed assembler */
9331 ret = tcc_assemble(s1, 0);
9332 } else
9333 #endif
9335 fd = file->fd;
9336 /* assume executable format: auto guess file type */
9337 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9338 error_noabort("could not read header");
9339 goto fail;
9341 lseek(fd, 0, SEEK_SET);
9343 if (ehdr.e_ident[0] == ELFMAG0 &&
9344 ehdr.e_ident[1] == ELFMAG1 &&
9345 ehdr.e_ident[2] == ELFMAG2 &&
9346 ehdr.e_ident[3] == ELFMAG3) {
9347 file->line_num = 0; /* do not display line number if error */
9348 if (ehdr.e_type == ET_REL) {
9349 ret = tcc_load_object_file(s1, fd, 0);
9350 } else if (ehdr.e_type == ET_DYN) {
9351 ret = tcc_load_dll(s1, fd, filename,
9352 (flags & AFF_REFERENCED_DLL) != 0);
9353 } else {
9354 error_noabort("unrecognized ELF file");
9355 goto fail;
9357 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9358 file->line_num = 0; /* do not display line number if error */
9359 ret = tcc_load_archive(s1, fd);
9360 } else {
9361 /* as GNU ld, consider it is an ld script if not recognized */
9362 ret = tcc_load_ldscript(s1);
9363 if (ret < 0) {
9364 error_noabort("unrecognized file type");
9365 goto fail;
9369 the_end:
9370 tcc_close(file);
9371 fail1:
9372 file = saved_file;
9373 return ret;
9374 fail:
9375 ret = -1;
9376 goto the_end;
9379 int tcc_add_file(TCCState *s, const char *filename)
9381 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9384 int tcc_add_library_path(TCCState *s, const char *pathname)
9386 char *pathname1;
9388 pathname1 = tcc_strdup(pathname);
9389 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9390 return 0;
9393 /* find and load a dll. Return non zero if not found */
9394 /* XXX: add '-rpath' option support ? */
9395 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9397 char buf[1024];
9398 int i;
9400 for(i = 0; i < s->nb_library_paths; i++) {
9401 snprintf(buf, sizeof(buf), "%s/%s",
9402 s->library_paths[i], filename);
9403 if (tcc_add_file_internal(s, buf, flags) == 0)
9404 return 0;
9406 return -1;
9409 /* the library name is the same as the argument of the '-l' option */
9410 int tcc_add_library(TCCState *s, const char *libraryname)
9412 char buf[1024];
9413 int i;
9414 void *h;
9416 /* first we look for the dynamic library if not static linking */
9417 if (!s->static_link) {
9418 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9419 /* if we output to memory, then we simply we dlopen(). */
9420 if (s->output_type == TCC_OUTPUT_MEMORY) {
9421 /* Since the libc is already loaded, we don't need to load it again */
9422 if (!strcmp(libraryname, "c"))
9423 return 0;
9424 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9425 if (h)
9426 return 0;
9427 } else {
9428 if (tcc_add_dll(s, buf, 0) == 0)
9429 return 0;
9433 /* then we look for the static library */
9434 for(i = 0; i < s->nb_library_paths; i++) {
9435 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9436 s->library_paths[i], libraryname);
9437 if (tcc_add_file_internal(s, buf, 0) == 0)
9438 return 0;
9440 return -1;
9443 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9445 add_elf_sym(symtab_section, val, 0,
9446 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9447 SHN_ABS, name);
9448 return 0;
9451 int tcc_set_output_type(TCCState *s, int output_type)
9453 char buf[1024];
9455 s->output_type = output_type;
9457 if (!s->nostdinc) {
9458 /* default include paths */
9459 /* XXX: reverse order needed if -isystem support */
9460 tcc_add_sysinclude_path(s, "/usr/local/include");
9461 tcc_add_sysinclude_path(s, "/usr/include");
9462 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9463 tcc_add_sysinclude_path(s, buf);
9466 /* if bound checking, then add corresponding sections */
9467 #ifdef CONFIG_TCC_BCHECK
9468 if (do_bounds_check) {
9469 /* define symbol */
9470 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9471 /* create bounds sections */
9472 bounds_section = new_section(s, ".bounds",
9473 SHT_PROGBITS, SHF_ALLOC);
9474 lbounds_section = new_section(s, ".lbounds",
9475 SHT_PROGBITS, SHF_ALLOC);
9477 #endif
9479 /* add debug sections */
9480 if (do_debug) {
9481 /* stab symbols */
9482 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9483 stab_section->sh_entsize = sizeof(Stab_Sym);
9484 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9485 put_elf_str(stabstr_section, "");
9486 stab_section->link = stabstr_section;
9487 /* put first entry */
9488 put_stabs("", 0, 0, 0, 0);
9491 /* add libc crt1/crti objects */
9492 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9493 !s->nostdlib) {
9494 if (output_type != TCC_OUTPUT_DLL)
9495 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9496 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9498 return 0;
9501 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9503 typedef struct WarningDef {
9504 int offset;
9505 int flags;
9506 const char *name;
9507 } WarningDef;
9509 static const WarningDef warning_defs[] = {
9510 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9511 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9512 { offsetof(TCCState, warn_error), 0, "error" },
9515 /* set/reset a warning */
9516 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9518 int i;
9519 const WarningDef *p;
9520 if (!strcmp(warning_name, "all")) {
9521 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9522 if (p->flags & WD_ALL)
9523 *(int *)((uint8_t *)s + p->offset) = 1;
9525 } else {
9526 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9527 if (!strcmp(warning_name, p->name))
9528 goto found;
9530 return -1;
9531 found:
9532 *(int *)((uint8_t *)s + p->offset) = value;
9534 return 0;
9538 #if !defined(LIBTCC)
9540 /* extract the basename of a file */
9541 static const char *tcc_basename(const char *name)
9543 const char *p;
9544 p = strrchr(name, '/');
9545 #ifdef WIN32
9546 if (!p)
9547 p = strrchr(name, '\\');
9548 #endif
9549 if (!p)
9550 p = name;
9551 else
9552 p++;
9553 return p;
9556 static int64_t getclock_us(void)
9558 #ifdef WIN32
9559 struct _timeb tb;
9560 _ftime(&tb);
9561 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9562 #else
9563 struct timeval tv;
9564 gettimeofday(&tv, NULL);
9565 return tv.tv_sec * 1000000LL + tv.tv_usec;
9566 #endif
9569 void help(void)
9571 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9572 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9573 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9574 " [infile1 infile2...] [-run infile args...]\n"
9575 "\n"
9576 "General options:\n"
9577 " -v display current version\n"
9578 " -c compile only - generate an object file\n"
9579 " -o outfile set output filename\n"
9580 " -Bdir set tcc internal library path\n"
9581 " -bench output compilation statistics\n"
9582 " -run run compiled source\n"
9583 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9584 "Preprocessor options:\n"
9585 " -Idir add include path 'dir'\n"
9586 " -Dsym[=val] define 'sym' with value 'val'\n"
9587 " -Usym undefine 'sym'\n"
9588 "Linker options:\n"
9589 " -Ldir add library path 'dir'\n"
9590 " -llib link with dynamic or static library 'lib'\n"
9591 " -shared generate a shared library\n"
9592 " -static static linking\n"
9593 " -rdynamic export all global symbols to dynamic linker\n"
9594 " -r relocatable output\n"
9595 "Debugger options:\n"
9596 " -g generate runtime debug info\n"
9597 #ifdef CONFIG_TCC_BCHECK
9598 " -b compile with built-in memory and bounds checker (implies -g)\n"
9599 #endif
9600 " -bt N show N callers in stack traces\n"
9604 #define TCC_OPTION_HAS_ARG 0x0001
9605 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9607 typedef struct TCCOption {
9608 const char *name;
9609 uint16_t index;
9610 uint16_t flags;
9611 } TCCOption;
9613 enum {
9614 TCC_OPTION_HELP,
9615 TCC_OPTION_I,
9616 TCC_OPTION_D,
9617 TCC_OPTION_U,
9618 TCC_OPTION_L,
9619 TCC_OPTION_B,
9620 TCC_OPTION_l,
9621 TCC_OPTION_bench,
9622 TCC_OPTION_bt,
9623 TCC_OPTION_b,
9624 TCC_OPTION_g,
9625 TCC_OPTION_c,
9626 TCC_OPTION_static,
9627 TCC_OPTION_shared,
9628 TCC_OPTION_o,
9629 TCC_OPTION_r,
9630 TCC_OPTION_W,
9631 TCC_OPTION_O,
9632 TCC_OPTION_m,
9633 TCC_OPTION_f,
9634 TCC_OPTION_nostdinc,
9635 TCC_OPTION_nostdlib,
9636 TCC_OPTION_print_search_dirs,
9637 TCC_OPTION_rdynamic,
9638 TCC_OPTION_run,
9639 TCC_OPTION_v,
9642 static const TCCOption tcc_options[] = {
9643 { "h", TCC_OPTION_HELP, 0 },
9644 { "?", TCC_OPTION_HELP, 0 },
9645 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9646 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9647 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9648 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9649 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9650 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9651 { "bench", TCC_OPTION_bench, 0 },
9652 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9653 #ifdef CONFIG_TCC_BCHECK
9654 { "b", TCC_OPTION_b, 0 },
9655 #endif
9656 { "g", TCC_OPTION_g, 0 },
9657 { "c", TCC_OPTION_c, 0 },
9658 { "static", TCC_OPTION_static, 0 },
9659 { "shared", TCC_OPTION_shared, 0 },
9660 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9661 { "run", TCC_OPTION_run, 0 },
9662 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9663 { "r", TCC_OPTION_r, 0 },
9664 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9665 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9666 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9667 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9668 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9669 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9670 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9671 { "v", TCC_OPTION_v, 0 },
9672 { NULL },
9675 int main(int argc, char **argv)
9677 char *r;
9678 int optind, output_type, multiple_files, i, reloc_output;
9679 TCCState *s;
9680 char **files;
9681 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9682 char objfilename[1024];
9683 int64_t start_time = 0;
9684 const TCCOption *popt;
9685 const char *optarg, *p1, *r1, *outfile;
9686 int print_search_dirs;
9688 s = tcc_new();
9689 output_type = TCC_OUTPUT_EXE;
9691 optind = 1;
9692 outfile = NULL;
9693 multiple_files = 1;
9694 dminus = 0;
9695 files = NULL;
9696 nb_files = 0;
9697 nb_libraries = 0;
9698 reloc_output = 0;
9699 print_search_dirs = 0;
9700 while (1) {
9701 if (optind >= argc) {
9702 if (nb_files == 0 && !print_search_dirs)
9703 goto show_help;
9704 else
9705 break;
9707 r = argv[optind++];
9708 if (r[0] != '-') {
9709 /* add a new file */
9710 dynarray_add((void ***)&files, &nb_files, r);
9711 if (!multiple_files) {
9712 optind--;
9713 /* argv[0] will be this file */
9714 break;
9716 } else {
9717 /* find option in table (match only the first chars */
9718 popt = tcc_options;
9719 for(;;) {
9720 p1 = popt->name;
9721 if (p1 == NULL)
9722 error("invalid option -- '%s'", r);
9723 r1 = r + 1;
9724 for(;;) {
9725 if (*p1 == '\0')
9726 goto option_found;
9727 if (*r1 != *p1)
9728 break;
9729 p1++;
9730 r1++;
9732 popt++;
9734 option_found:
9735 if (popt->flags & TCC_OPTION_HAS_ARG) {
9736 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9737 optarg = r1;
9738 } else {
9739 if (optind >= argc)
9740 error("argument to '%s' is missing", r);
9741 optarg = argv[optind++];
9743 } else {
9744 if (*r1 != '\0')
9745 goto show_help;
9746 optarg = NULL;
9749 switch(popt->index) {
9750 case TCC_OPTION_HELP:
9751 show_help:
9752 help();
9753 return 1;
9754 case TCC_OPTION_I:
9755 if (tcc_add_include_path(s, optarg) < 0)
9756 error("too many include paths");
9757 break;
9758 case TCC_OPTION_D:
9760 char *sym, *value;
9761 sym = (char *)optarg;
9762 value = strchr(sym, '=');
9763 if (value) {
9764 *value = '\0';
9765 value++;
9767 tcc_define_symbol(s, sym, value);
9769 break;
9770 case TCC_OPTION_U:
9771 tcc_undefine_symbol(s, optarg);
9772 break;
9773 case TCC_OPTION_L:
9774 tcc_add_library_path(s, optarg);
9775 break;
9776 case TCC_OPTION_B:
9777 /* set tcc utilities path (mainly for tcc development) */
9778 tcc_lib_path = optarg;
9779 break;
9780 case TCC_OPTION_l:
9781 dynarray_add((void ***)&files, &nb_files, r);
9782 nb_libraries++;
9783 break;
9784 case TCC_OPTION_bench:
9785 do_bench = 1;
9786 break;
9787 case TCC_OPTION_bt:
9788 num_callers = atoi(optarg);
9789 break;
9790 #ifdef CONFIG_TCC_BCHECK
9791 case TCC_OPTION_b:
9792 do_bounds_check = 1;
9793 do_debug = 1;
9794 break;
9795 #endif
9796 case TCC_OPTION_g:
9797 do_debug = 1;
9798 break;
9799 case TCC_OPTION_c:
9800 multiple_files = 1;
9801 output_type = TCC_OUTPUT_OBJ;
9802 break;
9803 case TCC_OPTION_static:
9804 s->static_link = 1;
9805 break;
9806 case TCC_OPTION_shared:
9807 output_type = TCC_OUTPUT_DLL;
9808 break;
9809 case TCC_OPTION_o:
9810 multiple_files = 1;
9811 outfile = optarg;
9812 break;
9813 case TCC_OPTION_r:
9814 /* generate a .o merging several output files */
9815 reloc_output = 1;
9816 output_type = TCC_OUTPUT_OBJ;
9817 break;
9818 case TCC_OPTION_nostdinc:
9819 s->nostdinc = 1;
9820 break;
9821 case TCC_OPTION_nostdlib:
9822 s->nostdlib = 1;
9823 break;
9824 case TCC_OPTION_print_search_dirs:
9825 print_search_dirs = 1;
9826 break;
9827 case TCC_OPTION_run:
9828 multiple_files = 0;
9829 output_type = TCC_OUTPUT_MEMORY;
9830 break;
9831 case TCC_OPTION_v:
9832 printf("tcc version %s\n", TCC_VERSION);
9833 return 0;
9834 case TCC_OPTION_W:
9836 const char *p = optarg;
9837 int value;
9838 value = 1;
9839 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9840 p += 2;
9841 value = 0;
9843 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9844 goto unsupported_option;
9846 break;
9847 case TCC_OPTION_rdynamic:
9848 s->rdynamic = 1;
9849 break;
9850 default:
9851 if (s->warn_unsupported) {
9852 unsupported_option:
9853 warning("unsupported option '%s'", r);
9855 break;
9859 if (print_search_dirs) {
9860 /* enough for Linux kernel */
9861 printf("install: %s/\n", tcc_lib_path);
9862 return 0;
9865 nb_objfiles = nb_files - nb_libraries;
9867 /* if outfile provided without other options, we output an
9868 executable */
9869 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9870 output_type = TCC_OUTPUT_EXE;
9872 /* check -c consistency : only single file handled. XXX: checks file type */
9873 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9874 /* accepts only a single input file */
9875 if (nb_objfiles != 1)
9876 error("cannot specify multiple files with -c");
9877 if (nb_libraries != 0)
9878 error("cannot specify libraries with -c");
9881 /* compute default outfile name */
9882 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9883 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9884 char *ext;
9885 /* strip path */
9886 pstrcpy(objfilename, sizeof(objfilename) - 1,
9887 tcc_basename(files[0]));
9888 /* add .o extension */
9889 ext = strrchr(objfilename, '.');
9890 if (!ext)
9891 goto default_outfile;
9892 strcpy(ext + 1, "o");
9893 } else {
9894 default_outfile:
9895 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9897 outfile = objfilename;
9900 if (do_bench) {
9901 start_time = getclock_us();
9904 tcc_set_output_type(s, output_type);
9906 /* compile or add each files or library */
9907 for(i = 0;i < nb_files; i++) {
9908 const char *filename;
9910 filename = files[i];
9911 if (filename[0] == '-') {
9912 if (tcc_add_library(s, filename + 2) < 0)
9913 error("cannot find %s", filename);
9914 } else {
9915 if (tcc_add_file(s, filename) < 0) {
9916 ret = 1;
9917 goto the_end;
9922 /* free all files */
9923 tcc_free(files);
9925 if (do_bench) {
9926 double total_time;
9927 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9928 if (total_time < 0.001)
9929 total_time = 0.001;
9930 if (total_bytes < 1)
9931 total_bytes = 1;
9932 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9933 tok_ident - TOK_IDENT, total_lines, total_bytes,
9934 total_time, (int)(total_lines / total_time),
9935 total_bytes / total_time / 1000000.0);
9938 if (s->output_type != TCC_OUTPUT_MEMORY) {
9939 tcc_output_file(s, outfile);
9940 ret = 0;
9941 } else {
9942 ret = tcc_run(s, argc - optind, argv + optind);
9944 the_end:
9945 /* XXX: cannot do it with bound checking because of the malloc hooks */
9946 if (!do_bounds_check)
9947 tcc_delete(s);
9949 #ifdef MEM_DEBUG
9950 if (do_bench) {
9951 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9953 #endif
9954 return ret;
9957 #endif