suppressed ch1 and preparser
[tinycc/miki.git] / tcc.c
blobc8637e2bde7233623a5651cd5276422de9e38dd6
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <setjmp.h>
31 #ifdef WIN32
32 #include <sys/timeb.h>
33 #endif
34 #ifndef WIN32
35 #include <sys/time.h>
36 #include <sys/ucontext.h>
37 #endif
38 #include "elf.h"
39 #include "stab.h"
40 #ifndef CONFIG_TCC_STATIC
41 #include <dlfcn.h>
42 #endif
44 #include "libtcc.h"
46 /* parser debug */
47 //#define PARSE_DEBUG
48 /* preprocessor debug */
49 //#define PP_DEBUG
50 /* include file debug */
51 //#define INC_DEBUG
53 //#define MEM_DEBUG
55 /* target selection */
56 //#define TCC_TARGET_I386 /* i386 code generator */
57 //#define TCC_TARGET_IL /* .NET CLI generator */
59 /* default target is I386 */
60 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
61 #define TCC_TARGET_I386
62 #endif
64 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
65 #define CONFIG_TCC_BCHECK /* enable bound checking code */
66 #endif
68 #ifndef CONFIG_TCC_PREFIX
69 #define CONFIG_TCC_PREFIX "/usr/local"
70 #endif
72 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
73 executables or dlls */
74 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
76 #define INCLUDE_STACK_SIZE 32
77 #define IFDEF_STACK_SIZE 64
78 #define VSTACK_SIZE 64
79 #define STRING_MAX_SIZE 1024
81 #define TOK_HASH_SIZE 2048 /* must be a power of two */
82 #define TOK_ALLOC_INCR 512 /* must be a power of two */
84 /* token symbol management */
85 typedef struct TokenSym {
86 struct TokenSym *hash_next;
87 struct Sym *sym_define; /* direct pointer to define */
88 struct Sym *sym_label; /* direct pointer to label */
89 struct Sym *sym_struct; /* direct pointer to structure */
90 struct Sym *sym_identifier; /* direct pointer to identifier */
91 int tok; /* token number */
92 int len;
93 char str[1];
94 } TokenSym;
96 typedef struct CString {
97 int size; /* size in bytes */
98 void *data; /* either 'char *' or 'int *' */
99 int size_allocated;
100 void *data_allocated; /* if non NULL, data has been malloced */
101 } CString;
103 /* type definition */
104 typedef struct CType {
105 int t;
106 struct Sym *ref;
107 } CType;
109 /* constant value */
110 typedef union CValue {
111 long double ld;
112 double d;
113 float f;
114 int i;
115 unsigned int ui;
116 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
117 long long ll;
118 unsigned long long ull;
119 struct CString *cstr;
120 void *ptr;
121 int tab[1];
122 } CValue;
124 /* value on stack */
125 typedef struct SValue {
126 CType type; /* type */
127 unsigned short r; /* register + flags */
128 unsigned short r2; /* second register, used for 'long long'
129 type. If not used, set to VT_CONST */
130 CValue c; /* constant, if VT_CONST */
131 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
132 } SValue;
134 /* symbol management */
135 typedef struct Sym {
136 int v; /* symbol token */
137 int r; /* associated register */
138 int c; /* associated number */
139 CType type; /* associated type */
140 struct Sym *next; /* next related symbol */
141 struct Sym *prev; /* prev symbol in stack */
142 struct Sym *prev_tok; /* previous symbol for this token */
143 } Sym;
145 /* section definition */
146 /* XXX: use directly ELF structure for parameters ? */
147 /* special flag to indicate that the section should not be linked to
148 the other ones */
149 #define SHF_PRIVATE 0x80000000
151 typedef struct Section {
152 unsigned long data_offset; /* current data offset */
153 unsigned char *data; /* section data */
154 unsigned long data_allocated; /* used for realloc() handling */
155 int sh_name; /* elf section name (only used during output) */
156 int sh_num; /* elf section number */
157 int sh_type; /* elf section type */
158 int sh_flags; /* elf section flags */
159 int sh_info; /* elf section info */
160 int sh_addralign; /* elf section alignment */
161 int sh_entsize; /* elf entry size */
162 unsigned long sh_size; /* section size (only used during output) */
163 unsigned long sh_addr; /* address at which the section is relocated */
164 unsigned long sh_offset; /* address at which the section is relocated */
165 int nb_hashed_syms; /* used to resize the hash table */
166 struct Section *link; /* link to another section */
167 struct Section *reloc; /* corresponding section for relocation, if any */
168 struct Section *hash; /* hash table for symbols */
169 struct Section *next;
170 char name[64]; /* section name */
171 } Section;
173 typedef struct DLLReference {
174 int level;
175 char name[1];
176 } DLLReference;
178 /* GNUC attribute definition */
179 typedef struct AttributeDef {
180 int aligned;
181 Section *section;
182 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
183 } AttributeDef;
185 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
186 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
187 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
189 /* stored in 'Sym.c' field */
190 #define FUNC_NEW 1 /* ansi function prototype */
191 #define FUNC_OLD 2 /* old function prototype */
192 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
194 /* stored in 'Sym.r' field */
195 #define FUNC_CDECL 0 /* standard c call */
196 #define FUNC_STDCALL 1 /* pascal c call */
198 /* field 'Sym.t' for macros */
199 #define MACRO_OBJ 0 /* object like macro */
200 #define MACRO_FUNC 1 /* function like macro */
202 /* field 'Sym.r' for labels */
203 #define LABEL_FORWARD 1 /* label is forward defined */
205 /* type_decl() types */
206 #define TYPE_ABSTRACT 1 /* type without variable */
207 #define TYPE_DIRECT 2 /* type with variable */
209 #define IO_BUF_SIZE 8192
211 typedef struct BufferedFile {
212 unsigned char *buf_ptr;
213 unsigned char *buf_end;
214 int fd;
215 int line_num; /* current line number - here to simply code */
216 int ifndef_macro; /*'#ifndef macro \n #define macro' search */
217 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
218 char inc_type; /* type of include */
219 char inc_filename[512]; /* filename specified by the user */
220 char filename[1024]; /* current filename - here to simplify code */
221 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
222 } BufferedFile;
224 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
225 #define CH_EOF (-1) /* end of file */
227 /* parsing state (used to save parser state to reparse part of the
228 source several times) */
229 typedef struct ParseState {
230 int *macro_ptr;
231 int line_num;
232 int tok;
233 CValue tokc;
234 } ParseState;
236 /* used to record tokens */
237 typedef struct TokenString {
238 int *str;
239 int len;
240 int last_line_num;
241 } TokenString;
243 /* include file cache, used to find files faster and also to eliminate
244 inclusion if the include file is protected by #ifndef ... #endif */
245 typedef struct CachedInclude {
246 int ifndef_macro;
247 char type; /* '"' or '>' to give include type */
248 char filename[1]; /* path specified in #include */
249 } CachedInclude;
251 /* parser */
252 struct BufferedFile *file;
253 int ch, tok, tok1;
254 CValue tokc, tok1c;
255 CString tokcstr; /* current parsed string, if any */
256 /* if true, line feed is returned as a token. line feed is also
257 returned at eof */
258 int return_linefeed;
259 /* set to TRUE if eof was reached */
260 int eof_seen;
261 Section *text_section, *data_section, *bss_section; /* predefined sections */
262 Section *cur_text_section; /* current section where function code is
263 generated */
264 /* bound check related sections */
265 Section *bounds_section; /* contains global data bound description */
266 Section *lbounds_section; /* contains local data bound description */
267 /* symbol sections */
268 Section *symtab_section, *strtab_section;
270 /* debug sections */
271 Section *stab_section, *stabstr_section;
273 /* loc : local variable index
274 ind : output code index
275 rsym: return symbol
276 anon_sym: anonymous symbol index
278 int rsym, anon_sym,
279 prog, ind, loc;
280 /* expression generation modifiers */
281 int const_wanted; /* true if constant wanted */
282 int nocode_wanted; /* true if no code generation wanted for an expression */
283 int global_expr; /* true if compound literals must be allocated
284 globally (used during initializers parsing */
285 CType func_vt; /* current function return type (used by return
286 instruction) */
287 int func_vc;
288 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
289 int tok_ident;
290 TokenSym **table_ident;
291 TokenSym *hash_ident[TOK_HASH_SIZE];
292 char token_buf[STRING_MAX_SIZE + 1];
293 char *funcname;
294 Sym *global_stack, *local_stack;
295 Sym *define_stack;
296 Sym *label_stack;
298 SValue vstack[VSTACK_SIZE], *vtop;
299 int *macro_ptr, *macro_ptr_allocated;
300 /* some predefined types */
301 CType char_pointer_type, func_old_type, int_type;
303 /* compile with debug symbol (and use them if error during execution) */
304 int do_debug = 0;
306 /* compile with built-in memory and bounds checker */
307 int do_bounds_check = 0;
309 /* display benchmark infos */
310 int do_bench = 0;
311 int total_lines;
312 int total_bytes;
314 /* use GNU C extensions */
315 int gnu_ext = 1;
317 /* use Tiny C extensions */
318 int tcc_ext = 1;
320 /* max number of callers shown if error */
321 static int num_callers = 6;
322 static const char **rt_bound_error_msg;
324 /* XXX: suppress that ASAP */
325 static struct TCCState *tcc_state;
327 /* give the path of the tcc libraries */
328 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
330 struct TCCState {
331 int output_type;
333 BufferedFile **include_stack_ptr;
334 int *ifdef_stack_ptr;
336 /* include file handling */
337 char **include_paths;
338 int nb_include_paths;
339 char **sysinclude_paths;
340 int nb_sysinclude_paths;
341 CachedInclude **cached_includes;
342 int nb_cached_includes;
344 char **library_paths;
345 int nb_library_paths;
347 /* array of all loaded dlls (including those referenced by loaded
348 dlls) */
349 DLLReference **loaded_dlls;
350 int nb_loaded_dlls;
352 /* sections */
353 Section **sections;
354 int nb_sections; /* number of sections, including first dummy section */
356 /* got handling */
357 Section *got;
358 unsigned long *got_offsets;
359 int nb_got_offsets;
360 int nb_plt_entries;
361 /* give the correspondance from symtab indexes to dynsym indexes */
362 int *symtab_to_dynsym;
364 /* temporary dynamic symbol sections (for dll loading) */
365 Section *dynsymtab_section;
366 /* exported dynamic symbol section */
367 Section *dynsym;
369 /* if true, static linking is performed */
370 int static_link;
372 /* error handling */
373 void *error_opaque;
374 void (*error_func)(void *opaque, const char *msg);
375 int error_set_jmp_enabled;
376 jmp_buf error_jmp_buf;
377 int nb_errors;
379 /* see include_stack_ptr */
380 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
382 /* see ifdef_stack_ptr */
383 int ifdef_stack[IFDEF_STACK_SIZE];
386 /* The current value can be: */
387 #define VT_VALMASK 0x00ff
388 #define VT_CONST 0x00f0 /* constant in vc
389 (must be first non register value) */
390 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
391 #define VT_LOCAL 0x00f2 /* offset on stack */
392 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
393 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
394 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
395 #define VT_LVAL 0x0100 /* var is an lvalue */
396 #define VT_SYM 0x0200 /* a symbol value is added */
397 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
398 char/short stored in integer registers) */
399 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
400 dereferencing value */
401 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
402 bounding function call point is in vc */
403 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
404 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
405 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
406 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
408 /* types */
409 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
411 #define VT_INT 0 /* integer type */
412 #define VT_BYTE 1 /* signed byte type */
413 #define VT_SHORT 2 /* short type */
414 #define VT_VOID 3 /* void type */
415 #define VT_PTR 4 /* pointer */
416 #define VT_ENUM 5 /* enum definition */
417 #define VT_FUNC 6 /* function type */
418 #define VT_STRUCT 7 /* struct/union definition */
419 #define VT_FLOAT 8 /* IEEE float */
420 #define VT_DOUBLE 9 /* IEEE double */
421 #define VT_LDOUBLE 10 /* IEEE long double */
422 #define VT_BOOL 11 /* ISOC99 boolean type */
423 #define VT_LLONG 12 /* 64 bit integer */
424 #define VT_LONG 13 /* long integer (NEVER USED as type, only
425 during parsing) */
426 #define VT_BTYPE 0x000f /* mask for basic type */
427 #define VT_UNSIGNED 0x0010 /* unsigned type */
428 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
429 #define VT_BITFIELD 0x0040 /* bitfield modifier */
431 /* storage */
432 #define VT_EXTERN 0x00000080 /* extern definition */
433 #define VT_STATIC 0x00000100 /* static variable */
434 #define VT_TYPEDEF 0x00000200 /* typedef definition */
436 /* type mask (except storage) */
437 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
439 /* token values */
441 /* warning: the following compare tokens depend on i386 asm code */
442 #define TOK_ULT 0x92
443 #define TOK_UGE 0x93
444 #define TOK_EQ 0x94
445 #define TOK_NE 0x95
446 #define TOK_ULE 0x96
447 #define TOK_UGT 0x97
448 #define TOK_LT 0x9c
449 #define TOK_GE 0x9d
450 #define TOK_LE 0x9e
451 #define TOK_GT 0x9f
453 #define TOK_LAND 0xa0
454 #define TOK_LOR 0xa1
456 #define TOK_DEC 0xa2
457 #define TOK_MID 0xa3 /* inc/dec, to void constant */
458 #define TOK_INC 0xa4
459 #define TOK_UDIV 0xb0 /* unsigned division */
460 #define TOK_UMOD 0xb1 /* unsigned modulo */
461 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
462 #define TOK_CINT 0xb3 /* number in tokc */
463 #define TOK_CCHAR 0xb4 /* char constant in tokc */
464 #define TOK_STR 0xb5 /* pointer to string in tokc */
465 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
466 #define TOK_LCHAR 0xb7
467 #define TOK_LSTR 0xb8
468 #define TOK_CFLOAT 0xb9 /* float constant */
469 #define TOK_LINENUM 0xba /* line number info */
470 #define TOK_CDOUBLE 0xc0 /* double constant */
471 #define TOK_CLDOUBLE 0xc1 /* long double constant */
472 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
473 #define TOK_ADDC1 0xc3 /* add with carry generation */
474 #define TOK_ADDC2 0xc4 /* add with carry use */
475 #define TOK_SUBC1 0xc5 /* add with carry generation */
476 #define TOK_SUBC2 0xc6 /* add with carry use */
477 #define TOK_CUINT 0xc8 /* unsigned int constant */
478 #define TOK_CLLONG 0xc9 /* long long constant */
479 #define TOK_CULLONG 0xca /* unsigned long long constant */
480 #define TOK_ARROW 0xcb
481 #define TOK_DOTS 0xcc /* three dots */
482 #define TOK_SHR 0xcd /* unsigned shift right */
483 #define TOK_PPNUM 0xce /* preprocessor number */
485 #define TOK_SHL 0x01 /* shift left */
486 #define TOK_SAR 0x02 /* signed shift right */
488 /* assignement operators : normal operator or 0x80 */
489 #define TOK_A_MOD 0xa5
490 #define TOK_A_AND 0xa6
491 #define TOK_A_MUL 0xaa
492 #define TOK_A_ADD 0xab
493 #define TOK_A_SUB 0xad
494 #define TOK_A_DIV 0xaf
495 #define TOK_A_XOR 0xde
496 #define TOK_A_OR 0xfc
497 #define TOK_A_SHL 0x81
498 #define TOK_A_SAR 0x82
500 /* WARNING: the content of this string encodes token numbers */
501 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";
503 #define TOK_EOF (-1) /* end of file */
504 #define TOK_LINEFEED 10 /* line feed */
506 /* all identificators and strings have token above that */
507 #define TOK_IDENT 256
509 enum {
510 TOK_LAST = TOK_IDENT - 1,
511 #define DEF(id, str) id,
512 #include "tcctok.h"
513 #undef DEF
516 static const char *tcc_keywords =
517 #define DEF(id, str) str "\0"
518 #include "tcctok.h"
519 #undef DEF
522 #define TOK_UIDENT TOK_DEFINE
524 #ifdef WIN32
525 #define snprintf _snprintf
526 #define vsnprintf _vsnprintf
527 #endif
529 #if defined(WIN32) || defined(TCC_UCLIBC)
530 /* currently incorrect */
531 long double strtold(const char *nptr, char **endptr)
533 return (long double)strtod(nptr, endptr);
535 float strtof(const char *nptr, char **endptr)
537 return (float)strtod(nptr, endptr);
539 #else
540 /* XXX: need to define this to use them in non ISOC99 context */
541 extern float strtof (const char *__nptr, char **__endptr);
542 extern long double strtold (const char *__nptr, char **__endptr);
543 #endif
545 static char *pstrcpy(char *buf, int buf_size, const char *s);
546 static char *pstrcat(char *buf, int buf_size, const char *s);
548 static void sum(int l);
549 static void next(void);
550 static void next_nomacro(void);
551 static void parse_expr_type(CType *type);
552 static void expr_type(CType *type);
553 static void unary_type(CType *type);
554 static int expr_const(void);
555 static void expr_eq(void);
556 static void gexpr(void);
557 static void decl(int l);
558 static void decl_initializer(CType *type, Section *sec, unsigned long c,
559 int first, int size_only);
560 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
561 int has_init, int v, int scope);
562 int gv(int rc);
563 void gv2(int rc1, int rc2);
564 void move_reg(int r, int s);
565 void save_regs(int n);
566 void save_reg(int r);
567 void vpop(void);
568 void vswap(void);
569 void vdup(void);
570 int get_reg(int rc);
572 static void macro_subst(TokenString *tok_str,
573 Sym **nested_list, int *macro_str);
574 int save_reg_forced(int r);
575 void gen_op(int op);
576 void force_charshort_cast(int t);
577 static void gen_cast(CType *type);
578 void vstore(void);
579 static Sym *sym_find(int v);
580 static Sym *sym_push(int v, CType *type, int r, int c);
582 /* type handling */
583 int type_size(CType *type, int *a);
584 static inline CType *pointed_type(CType *type);
585 static int pointed_size(CType *type);
586 static int lvalue_type(int t);
587 static int is_compatible_types(CType *type1, CType *type2);
588 static int parse_btype(CType *type, AttributeDef *ad);
589 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
591 void error(const char *fmt, ...);
592 void vpushi(int v);
593 void vset(CType *type, int r, int v);
594 void type_to_str(char *buf, int buf_size,
595 CType *type, const char *varstr);
596 char *get_tok_str(int v, CValue *cv);
597 static Sym *get_sym_ref(CType *type, Section *sec,
598 unsigned long offset, unsigned long size);
599 static Sym *external_global_sym(int v, CType *type, int r);
601 /* section generation */
602 static void section_realloc(Section *sec, unsigned long new_size);
603 static void *section_ptr_add(Section *sec, unsigned long size);
604 static void put_extern_sym(Sym *sym, Section *section,
605 unsigned long value, unsigned long size);
606 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
607 static int put_elf_str(Section *s, const char *sym);
608 static int put_elf_sym(Section *s,
609 unsigned long value, unsigned long size,
610 int info, int other, int shndx, const char *name);
611 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
612 int info, int sh_num, const char *name);
613 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
614 int type, int symbol);
615 static void put_stabs(const char *str, int type, int other, int desc,
616 unsigned long value);
617 static void put_stabs_r(const char *str, int type, int other, int desc,
618 unsigned long value, Section *sec, int sym_index);
619 static void put_stabn(int type, int other, int desc, int value);
620 static void put_stabd(int type, int other, int desc);
621 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
623 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
624 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
625 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
627 /* true if float/double/long double type */
628 static inline int is_float(int t)
630 int bt;
631 bt = t & VT_BTYPE;
632 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
635 #ifdef TCC_TARGET_I386
636 #include "i386-gen.c"
637 #endif
638 #ifdef TCC_TARGET_IL
639 #include "il-gen.c"
640 #endif
642 #ifdef CONFIG_TCC_STATIC
644 #define RTLD_LAZY 0x001
645 #define RTLD_NOW 0x002
646 #define RTLD_GLOBAL 0x100
647 #define RTLD_DEFAULT NULL
649 /* dummy function for profiling */
650 void *dlopen(const char *filename, int flag)
652 return NULL;
655 const char *dlerror(void)
657 return "error";
660 typedef struct TCCSyms {
661 char *str;
662 void *ptr;
663 } TCCSyms;
665 #define TCCSYM(a) { #a, &a, },
667 /* add the symbol you want here if no dynamic linking is done */
668 static TCCSyms tcc_syms[] = {
669 TCCSYM(printf)
670 TCCSYM(fprintf)
671 TCCSYM(fopen)
672 TCCSYM(fclose)
673 { NULL, NULL },
676 void *dlsym(void *handle, const char *symbol)
678 TCCSyms *p;
679 p = tcc_syms;
680 while (p->str != NULL) {
681 if (!strcmp(p->str, symbol))
682 return p->ptr;
683 p++;
685 return NULL;
688 #endif
690 /********************************************************/
692 /* we use our own 'finite' function to avoid potential problems with
693 non standard math libs */
694 /* XXX: endianness dependant */
695 int ieee_finite(double d)
697 int *p = (int *)&d;
698 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
701 /* copy a string and truncate it. */
702 static char *pstrcpy(char *buf, int buf_size, const char *s)
704 char *q, *q_end;
705 int c;
707 if (buf_size > 0) {
708 q = buf;
709 q_end = buf + buf_size - 1;
710 while (q < q_end) {
711 c = *s++;
712 if (c == '\0')
713 break;
714 *q++ = c;
716 *q = '\0';
718 return buf;
721 /* strcat and truncate. */
722 static char *pstrcat(char *buf, int buf_size, const char *s)
724 int len;
725 len = strlen(buf);
726 if (len < buf_size)
727 pstrcpy(buf + len, buf_size - len, s);
728 return buf;
731 /* memory management */
732 #ifdef MEM_DEBUG
733 int mem_cur_size;
734 int mem_max_size;
735 #endif
737 static inline void tcc_free(void *ptr)
739 #ifdef MEM_DEBUG
740 mem_cur_size -= malloc_usable_size(ptr);
741 #endif
742 free(ptr);
745 static void *tcc_malloc(unsigned long size)
747 void *ptr;
748 ptr = malloc(size);
749 if (!ptr && size)
750 error("memory full");
751 #ifdef MEM_DEBUG
752 mem_cur_size += malloc_usable_size(ptr);
753 if (mem_cur_size > mem_max_size)
754 mem_max_size = mem_cur_size;
755 #endif
756 return ptr;
759 static void *tcc_mallocz(unsigned long size)
761 void *ptr;
762 ptr = tcc_malloc(size);
763 memset(ptr, 0, size);
764 return ptr;
767 static inline void *tcc_realloc(void *ptr, unsigned long size)
769 void *ptr1;
770 #ifdef MEM_DEBUG
771 mem_cur_size -= malloc_usable_size(ptr);
772 #endif
773 ptr1 = realloc(ptr, size);
774 #ifdef MEM_DEBUG
775 /* NOTE: count not correct if alloc error, but not critical */
776 mem_cur_size += malloc_usable_size(ptr1);
777 if (mem_cur_size > mem_max_size)
778 mem_max_size = mem_cur_size;
779 #endif
780 return ptr1;
783 static char *tcc_strdup(const char *str)
785 char *ptr;
786 ptr = tcc_malloc(strlen(str) + 1);
787 strcpy(ptr, str);
788 return ptr;
791 #define free(p) use_tcc_free(p)
792 #define malloc(s) use_tcc_malloc(s)
793 #define realloc(p, s) use_tcc_realloc(p, s)
795 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
797 int nb, nb_alloc;
798 void **pp;
800 nb = *nb_ptr;
801 pp = *ptab;
802 /* every power of two we double array size */
803 if ((nb & (nb - 1)) == 0) {
804 if (!nb)
805 nb_alloc = 1;
806 else
807 nb_alloc = nb * 2;
808 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
809 if (!pp)
810 error("memory full");
811 *ptab = pp;
813 pp[nb++] = data;
814 *nb_ptr = nb;
817 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
819 Section *sec;
821 sec = tcc_mallocz(sizeof(Section));
822 pstrcpy(sec->name, sizeof(sec->name), name);
823 sec->sh_type = sh_type;
824 sec->sh_flags = sh_flags;
825 switch(sh_type) {
826 case SHT_HASH:
827 case SHT_REL:
828 case SHT_DYNSYM:
829 case SHT_SYMTAB:
830 case SHT_DYNAMIC:
831 sec->sh_addralign = 4;
832 break;
833 case SHT_STRTAB:
834 sec->sh_addralign = 1;
835 break;
836 default:
837 sec->sh_addralign = 32; /* default conservative alignment */
838 break;
841 /* only add section if not private */
842 if (!(sh_flags & SHF_PRIVATE)) {
843 sec->sh_num = s1->nb_sections;
844 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
846 return sec;
849 static void free_section(Section *s)
851 tcc_free(s->data);
852 tcc_free(s);
855 /* realloc section and set its content to zero */
856 static void section_realloc(Section *sec, unsigned long new_size)
858 unsigned long size;
859 unsigned char *data;
861 size = sec->data_allocated;
862 if (size == 0)
863 size = 1;
864 while (size < new_size)
865 size = size * 2;
866 data = tcc_realloc(sec->data, size);
867 if (!data)
868 error("memory full");
869 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
870 sec->data = data;
871 sec->data_allocated = size;
874 /* reserve at least 'size' bytes in section 'sec' from
875 sec->data_offset. */
876 static void *section_ptr_add(Section *sec, unsigned long size)
878 unsigned long offset, offset1;
880 offset = sec->data_offset;
881 offset1 = offset + size;
882 if (offset1 > sec->data_allocated)
883 section_realloc(sec, offset1);
884 sec->data_offset = offset1;
885 return sec->data + offset;
888 /* return a reference to a section, and create it if it does not
889 exists */
890 Section *find_section(TCCState *s1, const char *name)
892 Section *sec;
893 int i;
894 for(i = 1; i < s1->nb_sections; i++) {
895 sec = s1->sections[i];
896 if (!strcmp(name, sec->name))
897 return sec;
899 /* sections are created as PROGBITS */
900 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
903 /* update sym->c so that it points to an external symbol in section
904 'section' with value 'value' */
905 static void put_extern_sym(Sym *sym, Section *section,
906 unsigned long value, unsigned long size)
908 int sym_type, sym_bind, sh_num, info;
909 Elf32_Sym *esym;
910 const char *name;
912 if (section)
913 sh_num = section->sh_num;
914 else
915 sh_num = SHN_UNDEF;
916 if (!sym->c) {
917 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
918 sym_type = STT_FUNC;
919 else
920 sym_type = STT_OBJECT;
921 if (sym->type.t & VT_STATIC)
922 sym_bind = STB_LOCAL;
923 else
924 sym_bind = STB_GLOBAL;
926 name = get_tok_str(sym->v, NULL);
927 #ifdef CONFIG_TCC_BCHECK
928 if (do_bounds_check) {
929 char buf[32];
931 /* XXX: avoid doing that for statics ? */
932 /* if bound checking is activated, we change some function
933 names by adding the "__bound" prefix */
934 switch(sym->v) {
935 #if 0
936 /* XXX: we rely only on malloc hooks */
937 case TOK_malloc:
938 case TOK_free:
939 case TOK_realloc:
940 case TOK_memalign:
941 case TOK_calloc:
942 #endif
943 case TOK_memcpy:
944 case TOK_memmove:
945 case TOK_memset:
946 case TOK_strlen:
947 case TOK_strcpy:
948 strcpy(buf, "__bound_");
949 strcat(buf, name);
950 name = buf;
951 break;
954 #endif
955 info = ELF32_ST_INFO(sym_bind, sym_type);
956 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
957 } else {
958 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
959 esym->st_value = value;
960 esym->st_size = size;
961 esym->st_shndx = sh_num;
965 /* add a new relocation entry to symbol 'sym' in section 's' */
966 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
968 if (!sym->c)
969 put_extern_sym(sym, NULL, 0, 0);
970 /* now we can add ELF relocation info */
971 put_elf_reloc(symtab_section, s, offset, type, sym->c);
974 static inline int isid(int c)
976 return (c >= 'a' && c <= 'z') ||
977 (c >= 'A' && c <= 'Z') ||
978 c == '_';
981 static inline int isnum(int c)
983 return c >= '0' && c <= '9';
986 static inline int isoct(int c)
988 return c >= '0' && c <= '7';
991 static inline int toup(int c)
993 if (c >= 'a' && c <= 'z')
994 return c - 'a' + 'A';
995 else
996 return c;
999 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1001 int len;
1002 len = strlen(buf);
1003 vsnprintf(buf + len, buf_size - len, fmt, ap);
1006 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1008 va_list ap;
1009 va_start(ap, fmt);
1010 strcat_vprintf(buf, buf_size, fmt, ap);
1011 va_end(ap);
1014 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1016 char buf[2048];
1017 BufferedFile **f;
1019 buf[0] = '\0';
1020 if (file) {
1021 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1022 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1023 (*f)->filename, (*f)->line_num);
1024 if (file->line_num > 0) {
1025 strcat_printf(buf, sizeof(buf),
1026 "%s:%d: ", file->filename, file->line_num);
1027 } else {
1028 strcat_printf(buf, sizeof(buf),
1029 "%s: ", file->filename);
1031 } else {
1032 strcat_printf(buf, sizeof(buf),
1033 "tcc: ");
1035 if (is_warning)
1036 strcat_printf(buf, sizeof(buf), "warning: ");
1037 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1039 if (!s1->error_func) {
1040 /* default case: stderr */
1041 fprintf(stderr, "%s\n", buf);
1042 } else {
1043 s1->error_func(s1->error_opaque, buf);
1045 if (!is_warning)
1046 s1->nb_errors++;
1049 #ifdef LIBTCC
1050 void tcc_set_error_func(TCCState *s, void *error_opaque,
1051 void (*error_func)(void *opaque, const char *msg))
1053 s->error_opaque = error_opaque;
1054 s->error_func = error_func;
1056 #endif
1058 /* error without aborting current compilation */
1059 void error_noabort(const char *fmt, ...)
1061 TCCState *s1 = tcc_state;
1062 va_list ap;
1064 va_start(ap, fmt);
1065 error1(s1, 0, fmt, ap);
1066 va_end(ap);
1069 void error(const char *fmt, ...)
1071 TCCState *s1 = tcc_state;
1072 va_list ap;
1074 va_start(ap, fmt);
1075 error1(s1, 0, fmt, ap);
1076 va_end(ap);
1077 /* better than nothing: in some cases, we accept to handle errors */
1078 if (s1->error_set_jmp_enabled) {
1079 longjmp(s1->error_jmp_buf, 1);
1080 } else {
1081 /* XXX: suppress it someday */
1082 exit(1);
1086 void expect(const char *msg)
1088 error("%s expected", msg);
1091 void warning(const char *fmt, ...)
1093 TCCState *s1 = tcc_state;
1094 va_list ap;
1096 va_start(ap, fmt);
1097 error1(s1, 1, fmt, ap);
1098 va_end(ap);
1101 void skip(int c)
1103 if (tok != c)
1104 error("'%c' expected", c);
1105 next();
1108 void test_lvalue(void)
1110 if (!(vtop->r & VT_LVAL))
1111 expect("lvalue");
1114 TokenSym *tok_alloc(const char *str, int len)
1116 TokenSym *ts, **pts, **ptable;
1117 int h, i;
1119 h = 1;
1120 for(i=0;i<len;i++)
1121 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
1123 pts = &hash_ident[h];
1124 while (1) {
1125 ts = *pts;
1126 if (!ts)
1127 break;
1128 if (ts->len == len && !memcmp(ts->str, str, len))
1129 return ts;
1130 pts = &(ts->hash_next);
1133 if (tok_ident >= SYM_FIRST_ANOM)
1134 error("memory full");
1136 /* expand token table if needed */
1137 i = tok_ident - TOK_IDENT;
1138 if ((i % TOK_ALLOC_INCR) == 0) {
1139 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1140 if (!ptable)
1141 error("memory full");
1142 table_ident = ptable;
1145 ts = tcc_malloc(sizeof(TokenSym) + len);
1146 table_ident[i] = ts;
1147 ts->tok = tok_ident++;
1148 ts->sym_define = NULL;
1149 ts->sym_label = NULL;
1150 ts->sym_struct = NULL;
1151 ts->sym_identifier = NULL;
1152 ts->len = len;
1153 ts->hash_next = NULL;
1154 memcpy(ts->str, str, len);
1155 ts->str[len] = '\0';
1156 *pts = ts;
1157 return ts;
1160 /* CString handling */
1162 static void cstr_realloc(CString *cstr, int new_size)
1164 int size;
1165 void *data;
1167 size = cstr->size_allocated;
1168 if (size == 0)
1169 size = 8; /* no need to allocate a too small first string */
1170 while (size < new_size)
1171 size = size * 2;
1172 data = tcc_realloc(cstr->data_allocated, size);
1173 if (!data)
1174 error("memory full");
1175 cstr->data_allocated = data;
1176 cstr->size_allocated = size;
1177 cstr->data = data;
1180 /* add a byte */
1181 static void cstr_ccat(CString *cstr, int ch)
1183 int size;
1184 size = cstr->size + 1;
1185 if (size > cstr->size_allocated)
1186 cstr_realloc(cstr, size);
1187 ((unsigned char *)cstr->data)[size - 1] = ch;
1188 cstr->size = size;
1191 static void cstr_cat(CString *cstr, const char *str)
1193 int c;
1194 for(;;) {
1195 c = *str;
1196 if (c == '\0')
1197 break;
1198 cstr_ccat(cstr, c);
1199 str++;
1203 /* add a wide char */
1204 static void cstr_wccat(CString *cstr, int ch)
1206 int size;
1207 size = cstr->size + sizeof(int);
1208 if (size > cstr->size_allocated)
1209 cstr_realloc(cstr, size);
1210 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1211 cstr->size = size;
1214 static void cstr_new(CString *cstr)
1216 memset(cstr, 0, sizeof(CString));
1219 /* free string and reset it to NULL */
1220 static void cstr_free(CString *cstr)
1222 tcc_free(cstr->data_allocated);
1223 cstr_new(cstr);
1226 #define cstr_reset(cstr) cstr_free(cstr)
1228 /* XXX: unicode ? */
1229 static void add_char(CString *cstr, int c)
1231 if (c == '\'' || c == '\"' || c == '\\') {
1232 /* XXX: could be more precise if char or string */
1233 cstr_ccat(cstr, '\\');
1235 if (c >= 32 && c <= 126) {
1236 cstr_ccat(cstr, c);
1237 } else {
1238 cstr_ccat(cstr, '\\');
1239 if (c == '\n') {
1240 cstr_ccat(cstr, 'n');
1241 } else {
1242 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1243 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1244 cstr_ccat(cstr, '0' + (c & 7));
1249 /* XXX: buffer overflow */
1250 /* XXX: float tokens */
1251 char *get_tok_str(int v, CValue *cv)
1253 static char buf[STRING_MAX_SIZE + 1];
1254 static CString cstr_buf;
1255 CString *cstr;
1256 unsigned char *q;
1257 char *p;
1258 int i, len;
1260 /* NOTE: to go faster, we give a fixed buffer for small strings */
1261 cstr_reset(&cstr_buf);
1262 cstr_buf.data = buf;
1263 cstr_buf.size_allocated = sizeof(buf);
1264 p = buf;
1266 switch(v) {
1267 case TOK_CINT:
1268 case TOK_CUINT:
1269 /* XXX: not quite exact, but only useful for testing */
1270 sprintf(p, "%u", cv->ui);
1271 break;
1272 case TOK_CLLONG:
1273 case TOK_CULLONG:
1274 /* XXX: not quite exact, but only useful for testing */
1275 sprintf(p, "%Lu", cv->ull);
1276 break;
1277 case TOK_CCHAR:
1278 case TOK_LCHAR:
1279 cstr_ccat(&cstr_buf, '\'');
1280 add_char(&cstr_buf, cv->i);
1281 cstr_ccat(&cstr_buf, '\'');
1282 cstr_ccat(&cstr_buf, '\0');
1283 break;
1284 case TOK_PPNUM:
1285 cstr = cv->cstr;
1286 len = cstr->size - 1;
1287 for(i=0;i<len;i++)
1288 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1289 cstr_ccat(&cstr_buf, '\0');
1290 break;
1291 case TOK_STR:
1292 case TOK_LSTR:
1293 cstr = cv->cstr;
1294 cstr_ccat(&cstr_buf, '\"');
1295 if (v == TOK_STR) {
1296 len = cstr->size - 1;
1297 for(i=0;i<len;i++)
1298 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1299 } else {
1300 len = (cstr->size / sizeof(int)) - 1;
1301 for(i=0;i<len;i++)
1302 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1304 cstr_ccat(&cstr_buf, '\"');
1305 cstr_ccat(&cstr_buf, '\0');
1306 break;
1307 case TOK_LT:
1308 v = '<';
1309 goto addv;
1310 case TOK_GT:
1311 v = '>';
1312 goto addv;
1313 case TOK_A_SHL:
1314 return strcpy(p, "<<=");
1315 case TOK_A_SAR:
1316 return strcpy(p, ">>=");
1317 default:
1318 if (v < TOK_IDENT) {
1319 /* search in two bytes table */
1320 q = tok_two_chars;
1321 while (*q) {
1322 if (q[2] == v) {
1323 *p++ = q[0];
1324 *p++ = q[1];
1325 *p = '\0';
1326 return buf;
1328 q += 3;
1330 addv:
1331 *p++ = v;
1332 *p = '\0';
1333 } else if (v < tok_ident) {
1334 return table_ident[v - TOK_IDENT]->str;
1335 } else if (v >= SYM_FIRST_ANOM) {
1336 /* special name for anonymous symbol */
1337 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1338 } else {
1339 /* should never happen */
1340 return NULL;
1342 break;
1344 return cstr_buf.data;
1347 /* push, without hashing */
1348 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1350 Sym *s;
1351 s = tcc_malloc(sizeof(Sym));
1352 s->v = v;
1353 s->type.t = t;
1354 s->c = c;
1355 s->next = NULL;
1356 /* add in stack */
1357 s->prev = *ps;
1358 *ps = s;
1359 return s;
1362 /* find a symbol and return its associated structure. 's' is the top
1363 of the symbol stack */
1364 static Sym *sym_find2(Sym *s, int v)
1366 while (s) {
1367 if (s->v == v)
1368 return s;
1369 s = s->prev;
1371 return NULL;
1374 /* structure lookup */
1375 static Sym *struct_find(int v)
1377 v -= TOK_IDENT;
1378 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1379 return NULL;
1380 return table_ident[v]->sym_struct;
1383 /* find an identifier */
1384 static inline Sym *sym_find(int v)
1386 v -= TOK_IDENT;
1387 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1388 return NULL;
1389 return table_ident[v]->sym_identifier;
1392 /* push a given symbol on the symbol stack */
1393 static Sym *sym_push(int v, CType *type, int r, int c)
1395 Sym *s, **ps;
1396 TokenSym *ts;
1398 if (local_stack)
1399 ps = &local_stack;
1400 else
1401 ps = &global_stack;
1402 s = sym_push2(ps, v, type->t, c);
1403 s->type.ref = type->ref;
1404 s->r = r;
1405 /* don't record fields or anonymous symbols */
1406 /* XXX: simplify */
1407 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1408 /* record symbol in token array */
1409 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1410 if (v & SYM_STRUCT)
1411 ps = &ts->sym_struct;
1412 else
1413 ps = &ts->sym_identifier;
1414 s->prev_tok = *ps;
1415 *ps = s;
1417 return s;
1420 /* push a global identifier */
1421 static Sym *global_identifier_push(int v, int t, int c)
1423 Sym *s, **ps;
1424 s = sym_push2(&global_stack, v, t, c);
1425 /* don't record anonymous symbol */
1426 if (v < SYM_FIRST_ANOM) {
1427 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1428 /* modify the top most local identifier, so that
1429 sym_identifier will point to 's' when popped */
1430 while (*ps != NULL)
1431 ps = &(*ps)->prev_tok;
1432 s->prev_tok = NULL;
1433 *ps = s;
1435 return s;
1438 /* pop symbols until top reaches 'b' */
1439 static void sym_pop(Sym **ptop, Sym *b)
1441 Sym *s, *ss, **ps;
1442 TokenSym *ts;
1443 int v;
1445 s = *ptop;
1446 while(s != b) {
1447 ss = s->prev;
1448 v = s->v;
1449 /* remove symbol in token array */
1450 /* XXX: simplify */
1451 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1452 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1453 if (v & SYM_STRUCT)
1454 ps = &ts->sym_struct;
1455 else
1456 ps = &ts->sym_identifier;
1457 *ps = s->prev_tok;
1459 tcc_free(s);
1460 s = ss;
1462 *ptop = b;
1465 /* I/O layer */
1467 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1469 int fd;
1470 BufferedFile *bf;
1472 fd = open(filename, O_RDONLY);
1473 if (fd < 0)
1474 return NULL;
1475 bf = tcc_malloc(sizeof(BufferedFile));
1476 if (!bf) {
1477 close(fd);
1478 return NULL;
1480 bf->fd = fd;
1481 bf->buf_ptr = bf->buffer;
1482 bf->buf_end = bf->buffer;
1483 bf->buffer[0] = CH_EOB; /* put eob symbol */
1484 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1485 bf->line_num = 0;
1486 bf->ifndef_macro = 0;
1487 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1488 // printf("opening '%s'\n", filename);
1489 return bf;
1492 void tcc_close(BufferedFile *bf)
1494 total_lines += bf->line_num;
1495 close(bf->fd);
1496 tcc_free(bf);
1499 /* fill input buffer and return next char */
1500 int tcc_getc_slow(BufferedFile *bf)
1502 int len;
1503 /* only tries to read if really end of buffer */
1504 if (bf->buf_ptr >= bf->buf_end) {
1505 if (bf->fd != -1) {
1506 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1507 if (len < 0)
1508 len = 0;
1509 } else {
1510 len = 0;
1512 total_bytes += len;
1513 bf->buf_ptr = bf->buffer;
1514 bf->buf_end = bf->buffer + len;
1515 *bf->buf_end = CH_EOB;
1517 if (bf->buf_ptr < bf->buf_end) {
1518 return *bf->buf_ptr++;
1519 } else {
1520 bf->buf_ptr = bf->buf_end;
1521 return CH_EOF;
1525 /* no need to put that inline */
1526 void handle_eob(void)
1528 TCCState *s1 = tcc_state;
1530 /* no need to do anything if not at EOB */
1531 if (file->buf_ptr <= file->buf_end)
1532 return;
1534 for(;;) {
1535 ch = tcc_getc_slow(file);
1536 if (ch != CH_EOF)
1537 return;
1538 eof_seen = 1;
1539 if (return_linefeed) {
1540 ch = '\n';
1541 return;
1543 if (s1->include_stack_ptr == s1->include_stack)
1544 return;
1545 /* add end of include file debug info */
1546 if (do_debug) {
1547 put_stabd(N_EINCL, 0, 0);
1549 /* pop include stack */
1550 tcc_close(file);
1551 s1->include_stack_ptr--;
1552 file = *s1->include_stack_ptr;
1556 /* read next char from current input file and handle end of input buffer */
1557 static inline void inp(void)
1559 ch = *(file->buf_ptr++);
1560 /* end of buffer/file handling */
1561 if (ch == CH_EOB)
1562 handle_eob();
1565 /* handle '\[\r]\n' */
1566 static void handle_stray(void)
1568 while (ch == '\\') {
1569 inp();
1570 if (ch == '\n') {
1571 file->line_num++;
1572 inp();
1573 } else if (ch == '\r') {
1574 inp();
1575 if (ch != '\n')
1576 goto fail;
1577 file->line_num++;
1578 inp();
1579 } else {
1580 fail:
1581 error("stray '\\' in program");
1586 /* input with '\[\r]\n' handling. Note that this function cannot
1587 handle other characters after '\', so you cannot call it inside
1588 strings or comments */
1589 static void minp(void)
1591 inp();
1592 if (ch == '\\')
1593 handle_stray();
1597 static void parse_line_comment(void)
1599 /* single line C++ comments */
1600 /* XXX: accept '\\\n' ? */
1601 inp();
1602 while (ch != '\n' && ch != TOK_EOF)
1603 inp();
1606 static void parse_comment(void)
1608 /* C comments */
1609 minp();
1610 for(;;) {
1611 /* fast skip loop */
1612 while (ch != '\n' && ch != '*' && ch != TOK_EOF)
1613 inp();
1614 /* now we can handle all the cases */
1615 if (ch == '\n') {
1616 file->line_num++;
1617 inp();
1618 } else if (ch == '*') {
1619 for(;;) {
1620 inp();
1621 if (ch == '/') {
1622 goto end_of_comment;
1623 } else if (ch == '\\') {
1624 inp();
1625 if (ch == '\n') {
1626 file->line_num++;
1627 inp();
1628 } else if (ch == '\r') {
1629 inp();
1630 if (ch != '\n')
1631 break;
1632 file->line_num++;
1633 inp();
1634 } else {
1635 break;
1637 } else if (ch != '*') {
1638 break;
1641 } else {
1642 error("unexpected end of file in comment");
1645 end_of_comment:
1646 inp();
1649 #define cinp minp
1651 /* space exlcuding newline */
1652 static inline int is_space(int ch)
1654 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1657 static inline void skip_spaces(void)
1659 while (is_space(ch))
1660 cinp();
1663 /* skip block of text until #else, #elif or #endif. skip also pairs of
1664 #if/#endif */
1665 void preprocess_skip(void)
1667 int a, start_of_line, sep;
1669 start_of_line = 1;
1670 a = 0;
1671 while (1) {
1672 switch(ch) {
1673 case ' ':
1674 case '\t':
1675 case '\f':
1676 case '\v':
1677 case '\r':
1678 inp();
1679 break;
1680 case '\n':
1681 start_of_line = 1;
1682 file->line_num++;
1683 inp();
1684 break;
1685 case '\\':
1686 handle_stray();
1687 break;
1688 /* skip strings */
1689 case '\"':
1690 case '\'':
1691 start_of_line = 0;
1692 sep = ch;
1693 inp();
1694 while (ch != sep) {
1695 /* XXX: better error message */
1696 if (ch == TOK_EOF) {
1697 error("unterminated string");
1698 } else if (ch == '\n') {
1699 file->line_num++;
1700 } else if (ch == '\\') {
1701 /* ignore next char */
1702 inp();
1703 if (ch == '\n')
1704 file->line_num++;
1706 inp();
1708 minp();
1709 break;
1710 /* skip comments */
1711 case '/':
1712 minp();
1713 if (ch == '*') {
1714 parse_comment();
1715 } else if (ch == '/') {
1716 parse_line_comment();
1717 } else {
1718 start_of_line = 0;
1720 break;
1722 case '#':
1723 minp();
1724 if (start_of_line) {
1725 next_nomacro();
1726 if (a == 0 &&
1727 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1728 goto the_end;
1729 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1730 a++;
1731 else if (tok == TOK_ENDIF)
1732 a--;
1734 start_of_line = 0;
1735 break;
1736 case CH_EOF:
1737 expect("#endif");
1738 break;
1739 default:
1740 inp();
1741 start_of_line = 0;
1742 break;
1745 the_end: ;
1748 /* ParseState handling */
1750 /* XXX: currently, no include file info is stored. Thus, we cannot display
1751 accurate messages if the function or data definition spans multiple
1752 files */
1754 /* save current parse state in 's' */
1755 void save_parse_state(ParseState *s)
1757 s->line_num = file->line_num;
1758 s->macro_ptr = macro_ptr;
1759 s->tok = tok;
1760 s->tokc = tokc;
1763 /* restore parse state from 's' */
1764 void restore_parse_state(ParseState *s)
1766 file->line_num = s->line_num;
1767 macro_ptr = s->macro_ptr;
1768 tok = s->tok;
1769 tokc = s->tokc;
1772 /* return the number of additionnal 'ints' necessary to store the
1773 token */
1774 static inline int tok_ext_size(int t)
1776 switch(t) {
1777 /* 4 bytes */
1778 case TOK_CINT:
1779 case TOK_CUINT:
1780 case TOK_CCHAR:
1781 case TOK_LCHAR:
1782 case TOK_STR:
1783 case TOK_LSTR:
1784 case TOK_CFLOAT:
1785 case TOK_LINENUM:
1786 case TOK_PPNUM:
1787 return 1;
1788 case TOK_CDOUBLE:
1789 case TOK_CLLONG:
1790 case TOK_CULLONG:
1791 return 2;
1792 case TOK_CLDOUBLE:
1793 return LDOUBLE_SIZE / 4;
1794 default:
1795 return 0;
1799 /* token string handling */
1801 static inline void tok_str_new(TokenString *s)
1803 s->str = NULL;
1804 s->len = 0;
1805 s->last_line_num = -1;
1808 static void tok_str_free(int *str)
1810 const int *p;
1811 CString *cstr;
1812 int t;
1814 p = str;
1815 for(;;) {
1816 t = *p++;
1817 if (t == 0)
1818 break;
1819 if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
1820 /* XXX: use a macro to be portable on 64 bit ? */
1821 cstr = (CString *)(*p++);
1822 cstr_free(cstr);
1823 tcc_free(cstr);
1824 } else {
1825 p += tok_ext_size(t);
1828 tcc_free(str);
1831 static void tok_str_add(TokenString *s, int t)
1833 int len, *str;
1835 len = s->len;
1836 str = s->str;
1837 if ((len & 63) == 0) {
1838 str = tcc_realloc(str, (len + 64) * sizeof(int));
1839 if (!str)
1840 return;
1841 s->str = str;
1843 str[len++] = t;
1844 s->len = len;
1847 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1849 int n, i, size;
1850 CString *cstr, *cstr1;
1851 CValue cv1;
1853 tok_str_add(s, t);
1854 if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
1855 /* special case: need to duplicate string */
1856 cstr1 = cv->cstr;
1857 cstr = tcc_malloc(sizeof(CString));
1858 size = cstr1->size;
1859 cstr->size = size;
1860 cstr->size_allocated = size;
1861 cstr->data_allocated = tcc_malloc(size);
1862 cstr->data = cstr->data_allocated;
1863 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1864 cv1.cstr = cstr;
1865 tok_str_add(s, cv1.tab[0]);
1866 } else {
1867 n = tok_ext_size(t);
1868 for(i=0;i<n;i++)
1869 tok_str_add(s, cv->tab[i]);
1873 /* add the current parse token in token string 's' */
1874 static void tok_str_add_tok(TokenString *s)
1876 CValue cval;
1878 /* save line number info */
1879 if (file->line_num != s->last_line_num) {
1880 s->last_line_num = file->line_num;
1881 cval.i = s->last_line_num;
1882 tok_str_add2(s, TOK_LINENUM, &cval);
1884 tok_str_add2(s, tok, &tokc);
1887 /* get a token from an integer array and increment pointer accordingly */
1888 static int tok_get(int **tok_str, CValue *cv)
1890 int *p, t, n, i;
1892 p = *tok_str;
1893 t = *p++;
1894 n = tok_ext_size(t);
1895 for(i=0;i<n;i++)
1896 cv->tab[i] = *p++;
1897 *tok_str = p;
1898 return t;
1901 /* defines handling */
1902 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
1904 Sym *s;
1906 s = sym_push2(&define_stack, v, macro_type, (int)str);
1907 s->next = first_arg;
1908 table_ident[v - TOK_IDENT]->sym_define = s;
1911 /* undefined a define symbol. Its name is just set to zero */
1912 static void define_undef(Sym *s)
1914 int v;
1915 v = s->v;
1916 if (v >= TOK_IDENT && v < tok_ident)
1917 table_ident[v - TOK_IDENT]->sym_define = NULL;
1918 s->v = 0;
1921 static inline Sym *define_find(int v)
1923 v -= TOK_IDENT;
1924 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1925 return NULL;
1926 return table_ident[v]->sym_define;
1929 /* free define stack until top reaches 'b' */
1930 static void free_defines(Sym *b)
1932 Sym *top, *top1;
1933 int v;
1935 top = define_stack;
1936 while (top != b) {
1937 top1 = top->prev;
1938 /* do not free args or predefined defines */
1939 if (top->c)
1940 tok_str_free((int *)top->c);
1941 v = top->v;
1942 if (v >= TOK_IDENT && v < tok_ident)
1943 table_ident[v - TOK_IDENT]->sym_define = NULL;
1944 tcc_free(top);
1945 top = top1;
1947 define_stack = b;
1950 /* label lookup */
1951 static Sym *label_find(int v)
1953 v -= TOK_IDENT;
1954 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1955 return NULL;
1956 return table_ident[v]->sym_label;
1959 static Sym *label_push(int v, int flags)
1961 Sym *s;
1962 s = sym_push2(&label_stack, v, 0, 0);
1963 s->r = flags;
1964 table_ident[v - TOK_IDENT]->sym_label = s;
1965 return s;
1968 /* eval an expression for #if/#elif */
1969 int expr_preprocess(void)
1971 int c, t;
1972 TokenString str;
1974 tok_str_new(&str);
1975 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1976 next(); /* do macro subst */
1977 if (tok == TOK_DEFINED) {
1978 next_nomacro();
1979 t = tok;
1980 if (t == '(')
1981 next_nomacro();
1982 c = define_find(tok) != 0;
1983 if (t == '(')
1984 next_nomacro();
1985 tok = TOK_CINT;
1986 tokc.i = c;
1987 } else if (tok >= TOK_IDENT) {
1988 /* if undefined macro */
1989 tok = TOK_CINT;
1990 tokc.i = 0;
1992 tok_str_add_tok(&str);
1994 tok_str_add(&str, -1); /* simulate end of file */
1995 tok_str_add(&str, 0);
1996 /* now evaluate C constant expression */
1997 macro_ptr = str.str;
1998 next();
1999 c = expr_const();
2000 macro_ptr = NULL;
2001 tok_str_free(str.str);
2002 return c != 0;
2005 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2006 void tok_print(int *str)
2008 int t;
2009 CValue cval;
2011 while (1) {
2012 t = tok_get(&str, &cval);
2013 if (!t)
2014 break;
2015 printf(" %s", get_tok_str(t, &cval));
2017 printf("\n");
2019 #endif
2021 /* parse after #define */
2022 void parse_define(void)
2024 Sym *s, *first, **ps;
2025 int v, t, varg, is_vaargs;
2026 TokenString str;
2028 v = tok;
2029 if (v < TOK_IDENT)
2030 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2031 /* XXX: should check if same macro (ANSI) */
2032 first = NULL;
2033 t = MACRO_OBJ;
2034 /* '(' must be just after macro definition for MACRO_FUNC */
2035 if (ch == '(') {
2036 next_nomacro();
2037 next_nomacro();
2038 ps = &first;
2039 while (tok != ')') {
2040 varg = tok;
2041 next_nomacro();
2042 is_vaargs = 0;
2043 if (varg == TOK_DOTS) {
2044 varg = TOK___VA_ARGS__;
2045 is_vaargs = 1;
2046 } else if (tok == TOK_DOTS && gnu_ext) {
2047 is_vaargs = 1;
2048 next_nomacro();
2050 if (varg < TOK_IDENT)
2051 error("badly punctuated parameter list");
2052 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2053 *ps = s;
2054 ps = &s->next;
2055 if (tok != ',')
2056 break;
2057 next_nomacro();
2059 t = MACRO_FUNC;
2061 tok_str_new(&str);
2062 next_nomacro();
2063 /* EOF testing necessary for '-D' handling */
2064 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2065 tok_str_add2(&str, tok, &tokc);
2066 next_nomacro();
2068 tok_str_add(&str, 0);
2069 #ifdef PP_DEBUG
2070 printf("define %s %d: ", get_tok_str(v, NULL), t);
2071 tok_print(str.str);
2072 #endif
2073 define_push(v, t, str.str, first);
2076 /* XXX: use a token or a hash table to accelerate matching ? */
2077 static CachedInclude *search_cached_include(TCCState *s1,
2078 int type, const char *filename)
2080 CachedInclude *e;
2081 int i;
2083 for(i = 0;i < s1->nb_cached_includes; i++) {
2084 e = s1->cached_includes[i];
2085 if (e->type == type && !strcmp(e->filename, filename))
2086 return e;
2088 return NULL;
2091 static inline void add_cached_include(TCCState *s1, int type,
2092 const char *filename, int ifndef_macro)
2094 CachedInclude *e;
2096 if (search_cached_include(s1, type, filename))
2097 return;
2098 #ifdef INC_DEBUG
2099 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2100 #endif
2101 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2102 if (!e)
2103 return;
2104 e->type = type;
2105 strcpy(e->filename, filename);
2106 e->ifndef_macro = ifndef_macro;
2107 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2111 enum IncludeState {
2112 INCLUDE_STATE_NONE = 0,
2113 INCLUDE_STATE_SEEK_IFNDEF,
2116 void preprocess(void)
2118 TCCState *s1 = tcc_state;
2119 int size, i, c, n, line_num;
2120 enum IncludeState state;
2121 char buf[1024], *q, *p;
2122 char buf1[1024];
2123 BufferedFile *f;
2124 Sym *s;
2125 CachedInclude *e;
2127 return_linefeed = 1; /* linefeed will be returned as a
2128 token. EOF is also returned as line feed */
2129 state = INCLUDE_STATE_NONE;
2130 eof_seen = 0;
2131 redo1:
2132 next_nomacro();
2133 redo:
2134 switch(tok) {
2135 case TOK_DEFINE:
2136 next_nomacro();
2137 parse_define();
2138 break;
2139 case TOK_UNDEF:
2140 next_nomacro();
2141 s = define_find(tok);
2142 /* undefine symbol by putting an invalid name */
2143 if (s)
2144 define_undef(s);
2145 break;
2146 case TOK_INCLUDE:
2147 skip_spaces();
2148 if (ch == '<') {
2149 c = '>';
2150 goto read_name;
2151 } else if (ch == '\"') {
2152 c = ch;
2153 read_name:
2154 minp();
2155 q = buf;
2156 while (ch != c && ch != '\n' && ch != CH_EOF) {
2157 if ((q - buf) < sizeof(buf) - 1)
2158 *q++ = ch;
2159 minp();
2161 *q = '\0';
2162 #if 0
2163 /* eat all spaces and comments after include */
2164 /* XXX: slightly incorrect */
2165 while (ch1 != '\n' && ch1 != CH_EOF)
2166 inp();
2167 #endif
2168 } else {
2169 /* computed #include : either we have only strings or
2170 we have anything enclosed in '<>' */
2171 next();
2172 buf[0] = '\0';
2173 if (tok == TOK_STR) {
2174 while (tok != TOK_LINEFEED) {
2175 if (tok != TOK_STR) {
2176 include_syntax:
2177 error("'#include' expects \"FILENAME\" or <FILENAME>");
2179 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2180 next();
2182 c = '\"';
2183 } else {
2184 int len;
2185 while (tok != TOK_LINEFEED) {
2186 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2187 next();
2189 len = strlen(buf);
2190 /* check syntax and remove '<>' */
2191 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2192 goto include_syntax;
2193 memmove(buf, buf + 1, len - 2);
2194 buf[len - 2] = '\0';
2195 c = '>';
2199 ch = '\n';
2200 e = search_cached_include(s1, c, buf);
2201 if (e && define_find(e->ifndef_macro)) {
2202 /* no need to parse the include because the 'ifndef macro'
2203 is defined */
2204 #ifdef INC_DEBUG
2205 printf("%s: skipping %s\n", file->filename, buf);
2206 #endif
2207 } else {
2208 if (c == '\"') {
2209 /* first search in current dir if "header.h" */
2210 size = 0;
2211 p = strrchr(file->filename, '/');
2212 if (p)
2213 size = p + 1 - file->filename;
2214 if (size > sizeof(buf1) - 1)
2215 size = sizeof(buf1) - 1;
2216 memcpy(buf1, file->filename, size);
2217 buf1[size] = '\0';
2218 pstrcat(buf1, sizeof(buf1), buf);
2219 f = tcc_open(s1, buf1);
2220 if (f)
2221 goto found;
2223 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2224 error("#include recursion too deep");
2225 /* now search in all the include paths */
2226 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2227 for(i = 0; i < n; i++) {
2228 const char *path;
2229 if (i < s1->nb_include_paths)
2230 path = s1->include_paths[i];
2231 else
2232 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2233 pstrcpy(buf1, sizeof(buf1), path);
2234 pstrcat(buf1, sizeof(buf1), "/");
2235 pstrcat(buf1, sizeof(buf1), buf);
2236 f = tcc_open(s1, buf1);
2237 if (f)
2238 goto found;
2240 error("include file '%s' not found", buf);
2241 f = NULL;
2242 found:
2243 #ifdef INC_DEBUG
2244 printf("%s: including %s\n", file->filename, buf1);
2245 #endif
2246 f->inc_type = c;
2247 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2248 /* push current file in stack */
2249 /* XXX: fix current line init */
2250 *s1->include_stack_ptr++ = file;
2251 file = f;
2252 /* add include file debug info */
2253 if (do_debug) {
2254 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2256 /* we check for the construct: #ifndef IDENT \n #define IDENT */
2257 inp();
2258 /* get first non space char */
2259 while (is_space(ch) || ch == '\n')
2260 cinp();
2261 if (ch != '#')
2262 goto the_end;
2263 state = INCLUDE_STATE_SEEK_IFNDEF;
2264 cinp();
2265 goto redo1;
2267 break;
2268 case TOK_IFNDEF:
2269 c = 1;
2270 goto do_ifdef;
2271 case TOK_IF:
2272 c = expr_preprocess();
2273 goto do_if;
2274 case TOK_IFDEF:
2275 c = 0;
2276 do_ifdef:
2277 next_nomacro();
2278 if (tok < TOK_IDENT)
2279 error("invalid argument for '#if%sdef'", c ? "n" : "");
2280 if (state == INCLUDE_STATE_SEEK_IFNDEF) {
2281 if (c) {
2282 file->ifndef_macro = tok;
2284 state = INCLUDE_STATE_NONE;
2286 c = (define_find(tok) != 0) ^ c;
2287 do_if:
2288 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2289 error("memory full");
2290 *s1->ifdef_stack_ptr++ = c;
2291 goto test_skip;
2292 case TOK_ELSE:
2293 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2294 error("#else without matching #if");
2295 if (s1->ifdef_stack_ptr[-1] & 2)
2296 error("#else after #else");
2297 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2298 goto test_skip;
2299 case TOK_ELIF:
2300 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2301 error("#elif without matching #if");
2302 c = s1->ifdef_stack_ptr[-1];
2303 if (c > 1)
2304 error("#elif after #else");
2305 /* last #if/#elif expression was true: we skip */
2306 if (c == 1)
2307 goto skip;
2308 c = expr_preprocess();
2309 s1->ifdef_stack_ptr[-1] = c;
2310 test_skip:
2311 if (!(c & 1)) {
2312 skip:
2313 preprocess_skip();
2314 state = INCLUDE_STATE_NONE;
2315 goto redo;
2317 break;
2318 case TOK_ENDIF:
2319 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2320 error("#endif without matching #if");
2321 if (file->ifndef_macro &&
2322 s1->ifdef_stack_ptr == (file->ifdef_stack_ptr + 1)) {
2323 /* '#ifndef macro \n #define macro' was at the start of
2324 file. Now we check if an '#endif' is exactly at the end
2325 of file */
2326 while (tok != TOK_LINEFEED)
2327 next_nomacro();
2328 /* XXX: should also skip comments, but it is more complicated */
2329 if (eof_seen) {
2330 add_cached_include(s1, file->inc_type, file->inc_filename,
2331 file->ifndef_macro);
2332 } else {
2333 /* if not end of file, we must desactivate the ifndef
2334 macro search */
2335 file->ifndef_macro = 0;
2338 s1->ifdef_stack_ptr--;
2339 break;
2340 case TOK_LINE:
2341 next();
2342 if (tok != TOK_CINT)
2343 error("#line");
2344 line_num = tokc.i;
2345 next();
2346 if (tok != TOK_LINEFEED) {
2347 if (tok != TOK_STR)
2348 error("#line");
2349 pstrcpy(file->filename, sizeof(file->filename),
2350 (char *)tokc.cstr->data);
2352 /* NOTE: we do it there to avoid problems with linefeed */
2353 file->line_num = line_num;
2354 break;
2355 case TOK_ERROR:
2356 case TOK_WARNING:
2357 c = tok;
2358 skip_spaces();
2359 q = buf;
2360 while (ch != '\n' && ch != CH_EOF) {
2361 if ((q - buf) < sizeof(buf) - 1)
2362 *q++ = ch;
2363 minp();
2365 *q = '\0';
2366 if (c == TOK_ERROR)
2367 error("#error %s", buf);
2368 else
2369 warning("#warning %s", buf);
2370 break;
2371 default:
2372 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2373 /* '!' is ignored to allow C scripts. numbers are ignored
2374 to emulate cpp behaviour */
2375 } else {
2376 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2378 break;
2380 /* ignore other preprocess commands or #! for C scripts */
2381 while (tok != TOK_LINEFEED && tok != TOK_EOF)
2382 next_nomacro();
2383 the_end:
2384 return_linefeed = 0;
2387 /* read a number in base b */
2388 static int getn(int b)
2390 int n, t;
2391 n = 0;
2392 while (1) {
2393 if (ch >= 'a' && ch <= 'f')
2394 t = ch - 'a' + 10;
2395 else if (ch >= 'A' && ch <= 'F')
2396 t = ch - 'A' + 10;
2397 else if (isnum(ch))
2398 t = ch - '0';
2399 else
2400 break;
2401 if (t < 0 || t >= b)
2402 break;
2403 n = n * b + t;
2404 inp();
2406 return n;
2409 /* read a character for string or char constant and eval escape codes */
2410 static int getq(void)
2412 int c;
2414 redo:
2415 c = ch;
2416 inp();
2417 if (c == '\\') {
2418 switch(ch) {
2419 case '0': case '1': case '2': case '3':
2420 case '4': case '5': case '6': case '7':
2421 /* at most three octal digits */
2422 c = ch - '0';
2423 inp();
2424 if (isoct(ch)) {
2425 c = c * 8 + ch - '0';
2426 inp();
2427 if (isoct(ch)) {
2428 c = c * 8 + ch - '0';
2429 inp();
2432 return c;
2433 case 'x':
2434 inp();
2435 return getn(16);
2436 case 'a':
2437 c = '\a';
2438 break;
2439 case 'b':
2440 c = '\b';
2441 break;
2442 case 'f':
2443 c = '\f';
2444 break;
2445 case 'n':
2446 c = '\n';
2447 break;
2448 case 'r':
2449 c = '\r';
2450 break;
2451 case 't':
2452 c = '\t';
2453 break;
2454 case 'v':
2455 c = '\v';
2456 break;
2457 case 'e':
2458 if (!gnu_ext)
2459 goto invalid_escape;
2460 c = 27;
2461 break;
2462 case '\'':
2463 case '\"':
2464 case '\\':
2465 case '?':
2466 c = ch;
2467 break;
2468 case '\n':
2469 inp();
2470 goto redo;
2471 case '\r':
2472 inp();
2473 if (ch != '\n')
2474 goto invalid_escape;
2475 inp();
2476 goto redo;
2477 default:
2478 invalid_escape:
2479 error("invalid escaped char");
2481 inp();
2482 } else if (c == '\r' && ch == '\n') {
2483 inp();
2484 c = '\n';
2486 return c;
2489 /* we use 64 bit numbers */
2490 #define BN_SIZE 2
2492 /* bn = (bn << shift) | or_val */
2493 void bn_lshift(unsigned int *bn, int shift, int or_val)
2495 int i;
2496 unsigned int v;
2497 for(i=0;i<BN_SIZE;i++) {
2498 v = bn[i];
2499 bn[i] = (v << shift) | or_val;
2500 or_val = v >> (32 - shift);
2504 void bn_zero(unsigned int *bn)
2506 int i;
2507 for(i=0;i<BN_SIZE;i++) {
2508 bn[i] = 0;
2512 /* parse number in null terminated string 'p' and return it in the
2513 current token */
2514 void parse_number(const char *p)
2516 int b, t, shift, frac_bits, s, exp_val, ch;
2517 char *q;
2518 unsigned int bn[BN_SIZE];
2519 double d;
2521 /* number */
2522 q = token_buf;
2523 ch = *p++;
2524 t = ch;
2525 ch = *p++;
2526 *q++ = t;
2527 b = 10;
2528 if (t == '.') {
2529 goto float_frac_parse;
2530 } else if (t == '0') {
2531 if (ch == 'x' || ch == 'X') {
2532 q--;
2533 ch = *p++;
2534 b = 16;
2535 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2536 q--;
2537 ch = *p++;
2538 b = 2;
2541 /* parse all digits. cannot check octal numbers at this stage
2542 because of floating point constants */
2543 while (1) {
2544 if (ch >= 'a' && ch <= 'f')
2545 t = ch - 'a' + 10;
2546 else if (ch >= 'A' && ch <= 'F')
2547 t = ch - 'A' + 10;
2548 else if (isnum(ch))
2549 t = ch - '0';
2550 else
2551 break;
2552 if (t >= b)
2553 break;
2554 if (q >= token_buf + STRING_MAX_SIZE) {
2555 num_too_long:
2556 error("number too long");
2558 *q++ = ch;
2559 ch = *p++;
2561 if (ch == '.' ||
2562 ((ch == 'e' || ch == 'E') && b == 10) ||
2563 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2564 if (b != 10) {
2565 /* NOTE: strtox should support that for hexa numbers, but
2566 non ISOC99 libcs do not support it, so we prefer to do
2567 it by hand */
2568 /* hexadecimal or binary floats */
2569 /* XXX: handle overflows */
2570 *q = '\0';
2571 if (b == 16)
2572 shift = 4;
2573 else
2574 shift = 2;
2575 bn_zero(bn);
2576 q = token_buf;
2577 while (1) {
2578 t = *q++;
2579 if (t == '\0') {
2580 break;
2581 } else if (t >= 'a') {
2582 t = t - 'a' + 10;
2583 } else if (t >= 'A') {
2584 t = t - 'A' + 10;
2585 } else {
2586 t = t - '0';
2588 bn_lshift(bn, shift, t);
2590 frac_bits = 0;
2591 if (ch == '.') {
2592 ch = *p++;
2593 while (1) {
2594 t = ch;
2595 if (t >= 'a' && t <= 'f') {
2596 t = t - 'a' + 10;
2597 } else if (t >= 'A' && t <= 'F') {
2598 t = t - 'A' + 10;
2599 } else if (t >= '0' && t <= '9') {
2600 t = t - '0';
2601 } else {
2602 break;
2604 if (t >= b)
2605 error("invalid digit");
2606 bn_lshift(bn, shift, t);
2607 frac_bits += shift;
2608 ch = *p++;
2611 if (ch != 'p' && ch != 'P')
2612 expect("exponent");
2613 ch = *p++;
2614 s = 1;
2615 exp_val = 0;
2616 if (ch == '+') {
2617 ch = *p++;
2618 } else if (ch == '-') {
2619 s = -1;
2620 ch = *p++;
2622 if (ch < '0' || ch > '9')
2623 expect("exponent digits");
2624 while (ch >= '0' && ch <= '9') {
2625 exp_val = exp_val * 10 + ch - '0';
2626 ch = *p++;
2628 exp_val = exp_val * s;
2630 /* now we can generate the number */
2631 /* XXX: should patch directly float number */
2632 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2633 d = ldexp(d, exp_val - frac_bits);
2634 t = toup(ch);
2635 if (t == 'F') {
2636 ch = *p++;
2637 tok = TOK_CFLOAT;
2638 /* float : should handle overflow */
2639 tokc.f = (float)d;
2640 } else if (t == 'L') {
2641 ch = *p++;
2642 tok = TOK_CLDOUBLE;
2643 /* XXX: not large enough */
2644 tokc.ld = (long double)d;
2645 } else {
2646 tok = TOK_CDOUBLE;
2647 tokc.d = d;
2649 } else {
2650 /* decimal floats */
2651 if (ch == '.') {
2652 if (q >= token_buf + STRING_MAX_SIZE)
2653 goto num_too_long;
2654 *q++ = ch;
2655 ch = *p++;
2656 float_frac_parse:
2657 while (ch >= '0' && ch <= '9') {
2658 if (q >= token_buf + STRING_MAX_SIZE)
2659 goto num_too_long;
2660 *q++ = ch;
2661 ch = *p++;
2664 if (ch == 'e' || ch == 'E') {
2665 if (q >= token_buf + STRING_MAX_SIZE)
2666 goto num_too_long;
2667 *q++ = ch;
2668 ch = *p++;
2669 if (ch == '-' || ch == '+') {
2670 if (q >= token_buf + STRING_MAX_SIZE)
2671 goto num_too_long;
2672 *q++ = ch;
2673 ch = *p++;
2675 if (ch < '0' || ch > '9')
2676 expect("exponent digits");
2677 while (ch >= '0' && ch <= '9') {
2678 if (q >= token_buf + STRING_MAX_SIZE)
2679 goto num_too_long;
2680 *q++ = ch;
2681 ch = *p++;
2684 *q = '\0';
2685 t = toup(ch);
2686 errno = 0;
2687 if (t == 'F') {
2688 ch = *p++;
2689 tok = TOK_CFLOAT;
2690 tokc.f = strtof(token_buf, NULL);
2691 } else if (t == 'L') {
2692 ch = *p++;
2693 tok = TOK_CLDOUBLE;
2694 tokc.ld = strtold(token_buf, NULL);
2695 } else {
2696 tok = TOK_CDOUBLE;
2697 tokc.d = strtod(token_buf, NULL);
2700 } else {
2701 unsigned long long n, n1;
2702 int lcount, ucount;
2704 /* integer number */
2705 *q = '\0';
2706 q = token_buf;
2707 if (b == 10 && *q == '0') {
2708 b = 8;
2709 q++;
2711 n = 0;
2712 while(1) {
2713 t = *q++;
2714 /* no need for checks except for base 10 / 8 errors */
2715 if (t == '\0') {
2716 break;
2717 } else if (t >= 'a') {
2718 t = t - 'a' + 10;
2719 } else if (t >= 'A') {
2720 t = t - 'A' + 10;
2721 } else {
2722 t = t - '0';
2723 if (t >= b)
2724 error("invalid digit");
2726 n1 = n;
2727 n = n * b + t;
2728 /* detect overflow */
2729 /* XXX: this test is not reliable */
2730 if (n < n1)
2731 error("integer constant overflow");
2734 /* XXX: not exactly ANSI compliant */
2735 if ((n & 0xffffffff00000000LL) != 0) {
2736 if ((n >> 63) != 0)
2737 tok = TOK_CULLONG;
2738 else
2739 tok = TOK_CLLONG;
2740 } else if (n > 0x7fffffff) {
2741 tok = TOK_CUINT;
2742 } else {
2743 tok = TOK_CINT;
2745 lcount = 0;
2746 ucount = 0;
2747 for(;;) {
2748 t = toup(ch);
2749 if (t == 'L') {
2750 if (lcount >= 2)
2751 error("three 'l's in integer constant");
2752 lcount++;
2753 if (lcount == 2) {
2754 if (tok == TOK_CINT)
2755 tok = TOK_CLLONG;
2756 else if (tok == TOK_CUINT)
2757 tok = TOK_CULLONG;
2759 ch = *p++;
2760 } else if (t == 'U') {
2761 if (ucount >= 1)
2762 error("two 'u's in integer constant");
2763 ucount++;
2764 if (tok == TOK_CINT)
2765 tok = TOK_CUINT;
2766 else if (tok == TOK_CLLONG)
2767 tok = TOK_CULLONG;
2768 ch = *p++;
2769 } else {
2770 break;
2773 if (tok == TOK_CINT || tok == TOK_CUINT)
2774 tokc.ui = n;
2775 else
2776 tokc.ull = n;
2780 /* return next token without macro substitution */
2781 static inline void next_nomacro1(void)
2783 int b, t, start_of_line;
2784 char *q;
2785 TokenSym *ts;
2787 start_of_line = 0;
2788 redo_no_start:
2789 switch(ch) {
2790 case ' ':
2791 case '\t':
2792 case '\f':
2793 case '\v':
2794 case '\r':
2795 inp();
2796 goto redo_no_start;
2798 case '\\':
2799 handle_stray();
2800 goto redo_no_start;
2802 case '\n':
2803 file->line_num++;
2804 if (return_linefeed) {
2805 /* XXX: should eat token ? */
2806 tok = TOK_LINEFEED;
2807 } else {
2808 start_of_line = 1;
2809 inp();
2810 goto redo_no_start;
2812 break;
2814 case '#':
2815 minp();
2816 if (start_of_line) {
2817 preprocess();
2818 goto redo_no_start;
2819 } else {
2820 if (ch == '#') {
2821 inp();
2822 tok = TOK_TWOSHARPS;
2823 } else {
2824 tok = '#';
2827 break;
2829 case 'a': case 'b': case 'c': case 'd':
2830 case 'e': case 'f': case 'g': case 'h':
2831 case 'i': case 'j': case 'k': case 'l':
2832 case 'm': case 'n': case 'o': case 'p':
2833 case 'q': case 'r': case 's': case 't':
2834 case 'u': case 'v': case 'w': case 'x':
2835 case 'y': case 'z':
2836 case 'A': case 'B': case 'C': case 'D':
2837 case 'E': case 'F': case 'G': case 'H':
2838 case 'I': case 'J': case 'K':
2839 case 'M': case 'N': case 'O': case 'P':
2840 case 'Q': case 'R': case 'S': case 'T':
2841 case 'U': case 'V': case 'W': case 'X':
2842 case 'Y': case 'Z':
2843 case '_':
2844 q = token_buf;
2845 *q++ = ch;
2846 cinp();
2847 parse_ident:
2848 while (isid(ch) || isnum(ch)) {
2849 if (q >= token_buf + STRING_MAX_SIZE)
2850 error("ident too long");
2851 *q++ = ch;
2852 cinp();
2854 *q = '\0';
2855 ts = tok_alloc(token_buf, q - token_buf);
2856 tok = ts->tok;
2857 break;
2858 case 'L':
2859 minp();
2860 if (ch == '\'') {
2861 tok = TOK_LCHAR;
2862 goto char_const;
2864 if (ch == '\"') {
2865 tok = TOK_LSTR;
2866 goto str_const;
2868 q = token_buf;
2869 *q++ = 'L';
2870 goto parse_ident;
2872 case '0': case '1': case '2': case '3':
2873 case '4': case '5': case '6': case '7':
2874 case '8': case '9':
2876 cstr_reset(&tokcstr);
2877 /* after the first digit, accept digits, alpha, '.' or sign if
2878 prefixed by 'eEpP' */
2879 parse_num:
2880 for(;;) {
2881 t = ch;
2882 cstr_ccat(&tokcstr, ch);
2883 cinp();
2884 if (!(isnum(ch) || isid(ch) || ch == '.' ||
2885 ((ch == '+' || ch == '-') &&
2886 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
2887 break;
2889 /* We add a trailing '\0' to ease parsing */
2890 cstr_ccat(&tokcstr, '\0');
2891 tokc.cstr = &tokcstr;
2892 tok = TOK_PPNUM;
2893 break;
2894 case '.':
2895 /* special dot handling because it can also start a number */
2896 cinp();
2897 if (isnum(ch)) {
2898 cstr_reset(&tokcstr);
2899 cstr_ccat(&tokcstr, '.');
2900 goto parse_num;
2902 if (ch == '.') {
2903 cinp();
2904 if (ch != '.')
2905 expect("'.'");
2906 cinp();
2907 tok = TOK_DOTS;
2908 } else {
2909 tok = '.';
2911 break;
2912 case '\'':
2913 tok = TOK_CCHAR;
2914 char_const:
2915 inp();
2916 b = getq();
2917 /* this cast is needed if >= 128 */
2918 if (tok == TOK_CCHAR)
2919 b = (char)b;
2920 tokc.i = b;
2921 if (ch != '\'')
2922 error("unterminated character constant");
2923 inp();
2924 break;
2925 case '\"':
2926 tok = TOK_STR;
2927 str_const:
2928 inp();
2929 cstr_reset(&tokcstr);
2930 while (ch != '\"') {
2931 b = getq();
2932 if (ch == CH_EOF)
2933 error("unterminated string");
2934 if (tok == TOK_STR)
2935 cstr_ccat(&tokcstr, b);
2936 else
2937 cstr_wccat(&tokcstr, b);
2939 if (tok == TOK_STR)
2940 cstr_ccat(&tokcstr, '\0');
2941 else
2942 cstr_wccat(&tokcstr, '\0');
2943 tokc.cstr = &tokcstr;
2944 inp();
2945 break;
2947 case '<':
2948 cinp();
2949 if (ch == '=') {
2950 cinp();
2951 tok = TOK_LE;
2952 } else if (ch == '<') {
2953 cinp();
2954 if (ch == '=') {
2955 cinp();
2956 tok = TOK_A_SHL;
2957 } else {
2958 tok = TOK_SHL;
2960 } else {
2961 tok = TOK_LT;
2963 break;
2965 case '>':
2966 cinp();
2967 if (ch == '=') {
2968 cinp();
2969 tok = TOK_GE;
2970 } else if (ch == '>') {
2971 cinp();
2972 if (ch == '=') {
2973 cinp();
2974 tok = TOK_A_SAR;
2975 } else {
2976 tok = TOK_SAR;
2978 } else {
2979 tok = TOK_GT;
2981 break;
2983 case '!':
2984 tok = ch;
2985 cinp();
2986 if (ch == '=') {
2987 cinp();
2988 tok = TOK_NE;
2990 break;
2992 case '=':
2993 tok = ch;
2994 cinp();
2995 if (ch == '=') {
2996 cinp();
2997 tok = TOK_EQ;
2999 break;
3001 case '&':
3002 tok = ch;
3003 cinp();
3004 if (ch == '&') {
3005 cinp();
3006 tok = TOK_LAND;
3007 } else if (ch == '=') {
3008 cinp();
3009 tok = TOK_A_AND;
3011 break;
3013 case '|':
3014 tok = ch;
3015 cinp();
3016 if (ch == '|') {
3017 cinp();
3018 tok = TOK_LOR;
3019 } else if (ch == '=') {
3020 cinp();
3021 tok = TOK_A_OR;
3023 break;
3025 case '+':
3026 tok = ch;
3027 cinp();
3028 if (ch == '+') {
3029 cinp();
3030 tok = TOK_INC;
3031 } else if (ch == '=') {
3032 cinp();
3033 tok = TOK_A_ADD;
3035 break;
3037 case '-':
3038 tok = ch;
3039 cinp();
3040 if (ch == '-') {
3041 cinp();
3042 tok = TOK_DEC;
3043 } else if (ch == '=') {
3044 cinp();
3045 tok = TOK_A_SUB;
3046 } else if (ch == '>') {
3047 cinp();
3048 tok = TOK_ARROW;
3050 break;
3052 case '*':
3053 tok = ch;
3054 cinp();
3055 if (ch == '=') {
3056 cinp();
3057 tok = TOK_A_MUL;
3059 break;
3061 case '%':
3062 tok = ch;
3063 cinp();
3064 if (ch == '=') {
3065 cinp();
3066 tok = TOK_A_MOD;
3068 break;
3070 case '^':
3071 tok = ch;
3072 cinp();
3073 if (ch == '=') {
3074 cinp();
3075 tok = TOK_A_XOR;
3077 break;
3079 /* comments or operator */
3080 case '/':
3081 minp();
3082 if (ch == '*') {
3083 parse_comment();
3084 goto redo_no_start;
3085 } else if (ch == '/') {
3086 parse_line_comment();
3087 goto redo_no_start;
3088 } else if (ch == '=') {
3089 cinp();
3090 tok = TOK_A_DIV;
3091 } else {
3092 tok = '/';
3094 break;
3096 /* simple tokens */
3097 case '(':
3098 case ')':
3099 case '[':
3100 case ']':
3101 case '{':
3102 case '}':
3103 case ',':
3104 case ';':
3105 case ':':
3106 case '?':
3107 case '~':
3108 tok = ch;
3109 cinp();
3110 break;
3111 case CH_EOF:
3112 tok = TOK_EOF;
3113 break;
3114 default:
3115 error("unrecognized character \\x%02x", ch);
3116 break;
3118 #if defined(PARSE_DEBUG)
3119 printf("token = %s\n", get_tok_str(tok, &tokc));
3120 #endif
3123 /* return next token without macro substitution. Can read input from
3124 macro_ptr buffer */
3125 static void next_nomacro(void)
3127 if (macro_ptr) {
3128 redo:
3129 tok = *macro_ptr;
3130 if (tok) {
3131 tok = tok_get(&macro_ptr, &tokc);
3132 if (tok == TOK_LINENUM) {
3133 file->line_num = tokc.i;
3134 goto redo;
3137 } else {
3138 next_nomacro1();
3142 /* substitute args in macro_str and return allocated string */
3143 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3145 int *st, last_tok, t, notfirst;
3146 Sym *s;
3147 CValue cval;
3148 TokenString str;
3149 CString cstr;
3151 tok_str_new(&str);
3152 last_tok = 0;
3153 while(1) {
3154 t = tok_get(&macro_str, &cval);
3155 if (!t)
3156 break;
3157 if (t == '#') {
3158 /* stringize */
3159 t = tok_get(&macro_str, &cval);
3160 if (!t)
3161 break;
3162 s = sym_find2(args, t);
3163 if (s) {
3164 cstr_new(&cstr);
3165 st = (int *)s->c;
3166 notfirst = 0;
3167 while (*st) {
3168 if (notfirst)
3169 cstr_ccat(&cstr, ' ');
3170 t = tok_get(&st, &cval);
3171 cstr_cat(&cstr, get_tok_str(t, &cval));
3172 notfirst = 1;
3174 cstr_ccat(&cstr, '\0');
3175 #ifdef PP_DEBUG
3176 printf("stringize: %s\n", (char *)cstr.data);
3177 #endif
3178 /* add string */
3179 cval.cstr = &cstr;
3180 tok_str_add2(&str, TOK_STR, &cval);
3181 cstr_free(&cstr);
3182 } else {
3183 tok_str_add2(&str, t, &cval);
3185 } else if (t >= TOK_IDENT) {
3186 s = sym_find2(args, t);
3187 if (s) {
3188 st = (int *)s->c;
3189 /* if '##' is present before or after, no arg substitution */
3190 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3191 /* special case for var arg macros : ## eats the
3192 ',' if empty VA_ARGS variable. */
3193 /* XXX: test of the ',' is not 100%
3194 reliable. should fix it to avoid security
3195 problems */
3196 if (gnu_ext && s->type.t &&
3197 last_tok == TOK_TWOSHARPS &&
3198 str.len >= 2 && str.str[str.len - 2] == ',') {
3199 if (*st == 0) {
3200 /* suppress ',' '##' */
3201 str.len -= 2;
3202 } else {
3203 /* suppress '##' and add variable */
3204 str.len--;
3205 goto add_var;
3207 } else {
3208 int t1;
3209 add_var:
3210 for(;;) {
3211 t1 = tok_get(&st, &cval);
3212 if (!t1)
3213 break;
3214 tok_str_add2(&str, t1, &cval);
3217 } else {
3218 macro_subst(&str, nested_list, st);
3220 } else {
3221 tok_str_add(&str, t);
3223 } else {
3224 tok_str_add2(&str, t, &cval);
3226 last_tok = t;
3228 tok_str_add(&str, 0);
3229 return str.str;
3232 /* handle the '##' operator */
3233 static int *macro_twosharps(void)
3235 TokenSym *ts;
3236 int *macro_ptr1;
3237 int t;
3238 const char *p1, *p2;
3239 CValue cval;
3240 TokenString macro_str1;
3241 CString cstr;
3243 cstr_new(&cstr);
3244 tok_str_new(&macro_str1);
3245 tok = 0;
3246 while (1) {
3247 next_nomacro();
3248 if (tok == 0)
3249 break;
3250 while (*macro_ptr == TOK_TWOSHARPS) {
3251 macro_ptr++;
3252 macro_ptr1 = macro_ptr;
3253 t = *macro_ptr;
3254 if (t) {
3255 t = tok_get(&macro_ptr, &cval);
3257 /* We concatenate the two tokens if we have an
3258 identifier or a preprocessing number */
3259 cstr_reset(&cstr);
3260 p1 = get_tok_str(tok, &tokc);
3261 cstr_cat(&cstr, p1);
3262 p2 = get_tok_str(t, &cval);
3263 cstr_cat(&cstr, p2);
3264 cstr_ccat(&cstr, '\0');
3266 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3267 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3268 if (tok == TOK_PPNUM) {
3269 /* if number, then create a number token */
3270 /* NOTE: no need to allocate because
3271 tok_str_add2() does it */
3272 tokc.cstr = &cstr;
3273 } else {
3274 /* if identifier, we must do a test to
3275 validate we have a correct identifier */
3276 if (t == TOK_PPNUM) {
3277 const char *p;
3278 int c;
3280 p = p2;
3281 for(;;) {
3282 c = *p;
3283 if (c == '\0')
3284 break;
3285 p++;
3286 if (!isnum(c) && !isid(c))
3287 goto error_pasting;
3290 ts = tok_alloc(cstr.data, strlen(cstr.data));
3291 tok = ts->tok; /* modify current token */
3293 } else {
3294 const char *str = cstr.data;
3295 const unsigned char *q;
3297 /* we look for a valid token */
3298 /* XXX: do more extensive checks */
3299 if (!strcmp(str, ">>=")) {
3300 tok = TOK_A_SAR;
3301 } else if (!strcmp(str, "<<=")) {
3302 tok = TOK_A_SHL;
3303 } else if (strlen(str) == 2) {
3304 /* search in two bytes table */
3305 q = tok_two_chars;
3306 for(;;) {
3307 if (!*q)
3308 goto error_pasting;
3309 if (q[0] == str[0] && q[1] == str[1])
3310 break;
3311 q += 3;
3313 tok = q[2];
3314 } else {
3315 error_pasting:
3316 /* NOTE: because get_tok_str use a static buffer,
3317 we must save it */
3318 cstr_reset(&cstr);
3319 p1 = get_tok_str(tok, &tokc);
3320 cstr_cat(&cstr, p1);
3321 cstr_ccat(&cstr, '\0');
3322 p2 = get_tok_str(t, &cval);
3323 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3324 /* cannot merge tokens: just add them separately */
3325 tok_str_add2(&macro_str1, tok, &tokc);
3326 /* XXX: free associated memory ? */
3327 tok = t;
3328 tokc = cval;
3333 tok_str_add2(&macro_str1, tok, &tokc);
3335 cstr_free(&cstr);
3336 tok_str_add(&macro_str1, 0);
3337 return macro_str1.str;
3341 /* do macro substitution of current token with macro 's' and add
3342 result to (tok_str,tok_len). 'nested_list' is the list of all
3343 macros we got inside to avoid recursing. Return non zero if no
3344 substitution needs to be done */
3345 static int macro_subst_tok(TokenString *tok_str,
3346 Sym **nested_list, Sym *s)
3348 Sym *args, *sa, *sa1;
3349 int mstr_allocated, parlevel, *mstr, t;
3350 TokenString str;
3351 char *cstrval;
3352 CValue cval;
3353 CString cstr;
3355 /* if symbol is a macro, prepare substitution */
3356 /* if nested substitution, do nothing */
3357 if (sym_find2(*nested_list, tok))
3358 return -1;
3360 /* special macros */
3361 if (tok == TOK___LINE__) {
3362 cval.i = file->line_num;
3363 tok_str_add2(tok_str, TOK_CINT, &cval);
3364 } else if (tok == TOK___FILE__) {
3365 cstrval = file->filename;
3366 goto add_cstr;
3367 tok_str_add2(tok_str, TOK_STR, &cval);
3368 } else if (tok == TOK___DATE__) {
3369 cstrval = "Jan 1 2002";
3370 goto add_cstr;
3371 } else if (tok == TOK___TIME__) {
3372 cstrval = "00:00:00";
3373 add_cstr:
3374 cstr_new(&cstr);
3375 cstr_cat(&cstr, cstrval);
3376 cstr_ccat(&cstr, '\0');
3377 cval.cstr = &cstr;
3378 tok_str_add2(tok_str, TOK_STR, &cval);
3379 cstr_free(&cstr);
3380 } else {
3381 mstr = (int *)s->c;
3382 mstr_allocated = 0;
3383 if (s->type.t == MACRO_FUNC) {
3384 /* NOTE: we do not use next_nomacro to avoid eating the
3385 next token. XXX: find better solution */
3386 if (macro_ptr) {
3387 t = *macro_ptr;
3388 } else {
3389 while (is_space(ch) || ch == '\n')
3390 cinp();
3391 t = ch;
3393 if (t != '(') /* no macro subst */
3394 return -1;
3396 /* argument macro */
3397 next_nomacro();
3398 next_nomacro();
3399 args = NULL;
3400 sa = s->next;
3401 /* NOTE: empty args are allowed, except if no args */
3402 for(;;) {
3403 /* handle '()' case */
3404 if (!args && tok == ')')
3405 break;
3406 if (!sa)
3407 error("macro '%s' used with too many args",
3408 get_tok_str(s->v, 0));
3409 tok_str_new(&str);
3410 parlevel = 0;
3411 /* NOTE: non zero sa->t indicates VA_ARGS */
3412 while ((parlevel > 0 ||
3413 (tok != ')' &&
3414 (tok != ',' || sa->type.t))) &&
3415 tok != -1) {
3416 if (tok == '(')
3417 parlevel++;
3418 else if (tok == ')')
3419 parlevel--;
3420 tok_str_add2(&str, tok, &tokc);
3421 next_nomacro();
3423 tok_str_add(&str, 0);
3424 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3425 sa = sa->next;
3426 if (tok == ')') {
3427 /* special case for gcc var args: add an empty
3428 var arg argument if it is omitted */
3429 if (sa && sa->type.t && gnu_ext)
3430 continue;
3431 else
3432 break;
3434 if (tok != ',')
3435 expect(",");
3436 next_nomacro();
3438 if (sa) {
3439 error("macro '%s' used with too few args",
3440 get_tok_str(s->v, 0));
3443 /* now subst each arg */
3444 mstr = macro_arg_subst(nested_list, mstr, args);
3445 /* free memory */
3446 sa = args;
3447 while (sa) {
3448 sa1 = sa->prev;
3449 tok_str_free((int *)sa->c);
3450 tcc_free(sa);
3451 sa = sa1;
3453 mstr_allocated = 1;
3455 sym_push2(nested_list, s->v, 0, 0);
3456 macro_subst(tok_str, nested_list, mstr);
3457 /* pop nested defined symbol */
3458 sa1 = *nested_list;
3459 *nested_list = sa1->prev;
3460 tcc_free(sa1);
3461 if (mstr_allocated)
3462 tok_str_free(mstr);
3464 return 0;
3467 /* do macro substitution of macro_str and add result to
3468 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3469 inside to avoid recursing. */
3470 static void macro_subst(TokenString *tok_str,
3471 Sym **nested_list, int *macro_str)
3473 Sym *s;
3474 int *saved_macro_ptr;
3475 int *macro_str1;
3477 saved_macro_ptr = macro_ptr;
3478 macro_ptr = macro_str;
3479 /* first scan for '##' operator handling */
3480 macro_str1 = macro_twosharps();
3481 macro_ptr = macro_str1;
3483 while (1) {
3484 next_nomacro();
3485 if (tok == 0)
3486 break;
3487 s = define_find(tok);
3488 if (s != NULL) {
3489 if (macro_subst_tok(tok_str, nested_list, s) != 0)
3490 goto no_subst;
3491 } else {
3492 no_subst:
3493 tok_str_add2(tok_str, tok, &tokc);
3496 macro_ptr = saved_macro_ptr;
3497 tok_str_free(macro_str1);
3500 /* return next token with macro substitution */
3501 static void next(void)
3503 Sym *nested_list, *s;
3504 TokenString str;
3506 /* special 'ungettok' case for label parsing */
3507 if (tok1) {
3508 tok = tok1;
3509 tokc = tok1c;
3510 tok1 = 0;
3511 } else {
3512 redo:
3513 next_nomacro();
3514 if (!macro_ptr) {
3515 /* if not reading from macro substituted string, then try
3516 to substitute macros */
3517 if (tok >= TOK_IDENT) {
3518 s = define_find(tok);
3519 if (s) {
3520 /* we have a macro: we try to substitute */
3521 tok_str_new(&str);
3522 nested_list = NULL;
3523 if (macro_subst_tok(&str, &nested_list, s) == 0) {
3524 /* substitution done, NOTE: maybe empty */
3525 tok_str_add(&str, 0);
3526 macro_ptr = str.str;
3527 macro_ptr_allocated = str.str;
3528 goto redo;
3532 } else {
3533 if (tok == 0) {
3534 /* end of macro string: free it */
3535 tok_str_free(macro_ptr_allocated);
3536 macro_ptr = NULL;
3537 goto redo;
3541 /* convert preprocessor tokens into C tokens */
3542 if (tok == TOK_PPNUM) {
3543 parse_number((char *)tokc.cstr->data);
3548 void swap(int *p, int *q)
3550 int t;
3551 t = *p;
3552 *p = *q;
3553 *q = t;
3556 void vsetc(CType *type, int r, CValue *vc)
3558 int v;
3560 if (vtop >= vstack + VSTACK_SIZE)
3561 error("memory full");
3562 /* cannot let cpu flags if other instruction are generated. Also
3563 avoid leaving VT_JMP anywhere except on the top of the stack
3564 because it would complicate the code generator. */
3565 if (vtop >= vstack) {
3566 v = vtop->r & VT_VALMASK;
3567 if (v == VT_CMP || (v & ~1) == VT_JMP)
3568 gv(RC_INT);
3570 vtop++;
3571 vtop->type = *type;
3572 vtop->r = r;
3573 vtop->r2 = VT_CONST;
3574 vtop->c = *vc;
3577 /* push integer constant */
3578 void vpushi(int v)
3580 CValue cval;
3581 cval.i = v;
3582 vsetc(&int_type, VT_CONST, &cval);
3585 /* Return a static symbol pointing to a section */
3586 static Sym *get_sym_ref(CType *type, Section *sec,
3587 unsigned long offset, unsigned long size)
3589 int v;
3590 Sym *sym;
3592 v = anon_sym++;
3593 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
3594 sym->type.ref = type->ref;
3595 sym->r = VT_CONST | VT_SYM;
3596 put_extern_sym(sym, sec, offset, size);
3597 return sym;
3600 /* push a reference to a section offset by adding a dummy symbol */
3601 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
3603 CValue cval;
3605 cval.ul = 0;
3606 vsetc(type, VT_CONST | VT_SYM, &cval);
3607 vtop->sym = get_sym_ref(type, sec, offset, size);
3610 /* define a new external reference to a symbol 'v' of type 'u' */
3611 static Sym *external_global_sym(int v, CType *type, int r)
3613 Sym *s;
3615 s = sym_find(v);
3616 if (!s) {
3617 /* push forward reference */
3618 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
3619 s->type.ref = type->ref;
3620 s->r = r | VT_CONST | VT_SYM;
3622 return s;
3625 /* define a new external reference to a symbol 'v' of type 'u' */
3626 static Sym *external_sym(int v, CType *type, int r)
3628 Sym *s;
3630 s = sym_find(v);
3631 if (!s) {
3632 /* push forward reference */
3633 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
3634 s->type.t |= VT_EXTERN;
3636 return s;
3639 /* push a reference to global symbol v */
3640 static void vpush_global_sym(CType *type, int v)
3642 Sym *sym;
3643 CValue cval;
3645 sym = external_global_sym(v, type, 0);
3646 cval.ul = 0;
3647 vsetc(type, VT_CONST | VT_SYM, &cval);
3648 vtop->sym = sym;
3651 void vset(CType *type, int r, int v)
3653 CValue cval;
3655 cval.i = v;
3656 vsetc(type, r, &cval);
3659 void vseti(int r, int v)
3661 CType type;
3662 type.t = VT_INT;
3663 vset(&type, r, v);
3666 void vswap(void)
3668 SValue tmp;
3670 tmp = vtop[0];
3671 vtop[0] = vtop[-1];
3672 vtop[-1] = tmp;
3675 void vpushv(SValue *v)
3677 if (vtop >= vstack + VSTACK_SIZE)
3678 error("memory full");
3679 vtop++;
3680 *vtop = *v;
3683 void vdup(void)
3685 vpushv(vtop);
3688 /* save r to the memory stack, and mark it as being free */
3689 void save_reg(int r)
3691 int l, saved, size, align;
3692 SValue *p, sv;
3693 CType *type;
3695 /* modify all stack values */
3696 saved = 0;
3697 l = 0;
3698 for(p=vstack;p<=vtop;p++) {
3699 if ((p->r & VT_VALMASK) == r ||
3700 (p->r2 & VT_VALMASK) == r) {
3701 /* must save value on stack if not already done */
3702 if (!saved) {
3703 /* NOTE: must reload 'r' because r might be equal to r2 */
3704 r = p->r & VT_VALMASK;
3705 /* store register in the stack */
3706 type = &p->type;
3707 if ((p->r & VT_LVAL) ||
3708 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
3709 type = &int_type;
3710 size = type_size(type, &align);
3711 loc = (loc - size) & -align;
3712 sv.type.t = type->t;
3713 sv.r = VT_LOCAL | VT_LVAL;
3714 sv.c.ul = loc;
3715 store(r, &sv);
3716 #ifdef TCC_TARGET_I386
3717 /* x86 specific: need to pop fp register ST0 if saved */
3718 if (r == REG_ST0) {
3719 o(0xd9dd); /* fstp %st(1) */
3721 #endif
3722 /* special long long case */
3723 if ((type->t & VT_BTYPE) == VT_LLONG) {
3724 sv.c.ul += 4;
3725 store(p->r2, &sv);
3727 l = loc;
3728 saved = 1;
3730 /* mark that stack entry as being saved on the stack */
3731 if (p->r & VT_LVAL) {
3732 /* also suppress the bounded flag because the
3733 relocation address of the function was stored in
3734 p->c.ul */
3735 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
3736 } else {
3737 p->r = lvalue_type(p->type.t) | VT_LOCAL;
3739 p->r2 = VT_CONST;
3740 p->c.ul = l;
3745 /* find a free register of class 'rc'. If none, save one register */
3746 int get_reg(int rc)
3748 int r;
3749 SValue *p;
3751 /* find a free register */
3752 for(r=0;r<NB_REGS;r++) {
3753 if (reg_classes[r] & rc) {
3754 for(p=vstack;p<=vtop;p++) {
3755 if ((p->r & VT_VALMASK) == r ||
3756 (p->r2 & VT_VALMASK) == r)
3757 goto notfound;
3759 return r;
3761 notfound: ;
3764 /* no register left : free the first one on the stack (VERY
3765 IMPORTANT to start from the bottom to ensure that we don't
3766 spill registers used in gen_opi()) */
3767 for(p=vstack;p<=vtop;p++) {
3768 r = p->r & VT_VALMASK;
3769 if (r < VT_CONST && (reg_classes[r] & rc))
3770 goto save_found;
3771 /* also look at second register (if long long) */
3772 r = p->r2 & VT_VALMASK;
3773 if (r < VT_CONST && (reg_classes[r] & rc)) {
3774 save_found:
3775 save_reg(r);
3776 return r;
3779 /* Should never comes here */
3780 return -1;
3783 /* save registers up to (vtop - n) stack entry */
3784 void save_regs(int n)
3786 int r;
3787 SValue *p, *p1;
3788 p1 = vtop - n;
3789 for(p = vstack;p <= p1; p++) {
3790 r = p->r & VT_VALMASK;
3791 if (r < VT_CONST) {
3792 save_reg(r);
3797 /* move register 's' to 'r', and flush previous value of r to memory
3798 if needed */
3799 void move_reg(int r, int s)
3801 SValue sv;
3803 if (r != s) {
3804 save_reg(r);
3805 sv.type.t = VT_INT;
3806 sv.r = s;
3807 sv.c.ul = 0;
3808 load(r, &sv);
3812 /* get address of vtop (vtop MUST BE an lvalue) */
3813 void gaddrof(void)
3815 vtop->r &= ~VT_LVAL;
3816 /* tricky: if saved lvalue, then we can go back to lvalue */
3817 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
3818 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
3821 #ifdef CONFIG_TCC_BCHECK
3822 /* generate lvalue bound code */
3823 void gbound(void)
3825 int lval_type;
3826 CType type1;
3828 vtop->r &= ~VT_MUSTBOUND;
3829 /* if lvalue, then use checking code before dereferencing */
3830 if (vtop->r & VT_LVAL) {
3831 /* if not VT_BOUNDED value, then make one */
3832 if (!(vtop->r & VT_BOUNDED)) {
3833 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
3834 /* must save type because we must set it to int to get pointer */
3835 type1 = vtop->type;
3836 vtop->type.t = VT_INT;
3837 gaddrof();
3838 vpushi(0);
3839 gen_bounded_ptr_add();
3840 vtop->r |= lval_type;
3841 vtop->type = type1;
3843 /* then check for dereferencing */
3844 gen_bounded_ptr_deref();
3847 #endif
3849 /* store vtop a register belonging to class 'rc'. lvalues are
3850 converted to values. Cannot be used if cannot be converted to
3851 register value (such as structures). */
3852 int gv(int rc)
3854 int r, r2, rc2, bit_pos, bit_size, size, align, i;
3855 unsigned long long ll;
3857 /* NOTE: get_reg can modify vstack[] */
3858 if (vtop->type.t & VT_BITFIELD) {
3859 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
3860 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3861 /* remove bit field info to avoid loops */
3862 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3863 /* generate shifts */
3864 vpushi(32 - (bit_pos + bit_size));
3865 gen_op(TOK_SHL);
3866 vpushi(32 - bit_size);
3867 /* NOTE: transformed to SHR if unsigned */
3868 gen_op(TOK_SAR);
3869 r = gv(rc);
3870 } else {
3871 if (is_float(vtop->type.t) &&
3872 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3873 Sym *sym;
3874 int *ptr;
3875 unsigned long offset;
3877 /* XXX: unify with initializers handling ? */
3878 /* CPUs usually cannot use float constants, so we store them
3879 generically in data segment */
3880 size = type_size(&vtop->type, &align);
3881 offset = (data_section->data_offset + align - 1) & -align;
3882 data_section->data_offset = offset;
3883 /* XXX: not portable yet */
3884 ptr = section_ptr_add(data_section, size);
3885 size = size >> 2;
3886 for(i=0;i<size;i++)
3887 ptr[i] = vtop->c.tab[i];
3888 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
3889 vtop->r |= VT_LVAL | VT_SYM;
3890 vtop->sym = sym;
3891 vtop->c.ul = 0;
3893 #ifdef CONFIG_TCC_BCHECK
3894 if (vtop->r & VT_MUSTBOUND)
3895 gbound();
3896 #endif
3898 r = vtop->r & VT_VALMASK;
3899 /* need to reload if:
3900 - constant
3901 - lvalue (need to dereference pointer)
3902 - already a register, but not in the right class */
3903 if (r >= VT_CONST ||
3904 (vtop->r & VT_LVAL) ||
3905 !(reg_classes[r] & rc) ||
3906 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
3907 !(reg_classes[vtop->r2] & rc))) {
3908 r = get_reg(rc);
3909 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
3910 /* two register type load : expand to two words
3911 temporarily */
3912 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3913 /* load constant */
3914 ll = vtop->c.ull;
3915 vtop->c.ui = ll; /* first word */
3916 load(r, vtop);
3917 vtop->r = r; /* save register value */
3918 vpushi(ll >> 32); /* second word */
3919 } else if (r >= VT_CONST ||
3920 (vtop->r & VT_LVAL)) {
3921 /* load from memory */
3922 load(r, vtop);
3923 vdup();
3924 vtop[-1].r = r; /* save register value */
3925 /* increment pointer to get second word */
3926 vtop->type.t = VT_INT;
3927 gaddrof();
3928 vpushi(4);
3929 gen_op('+');
3930 vtop->r |= VT_LVAL;
3931 } else {
3932 /* move registers */
3933 load(r, vtop);
3934 vdup();
3935 vtop[-1].r = r; /* save register value */
3936 vtop->r = vtop[-1].r2;
3938 /* allocate second register */
3939 rc2 = RC_INT;
3940 if (rc == RC_IRET)
3941 rc2 = RC_LRET;
3942 r2 = get_reg(rc2);
3943 load(r2, vtop);
3944 vpop();
3945 /* write second register */
3946 vtop->r2 = r2;
3947 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
3948 int t1, t;
3949 /* lvalue of scalar type : need to use lvalue type
3950 because of possible cast */
3951 t = vtop->type.t;
3952 t1 = t;
3953 /* compute memory access type */
3954 if (vtop->r & VT_LVAL_BYTE)
3955 t = VT_BYTE;
3956 else if (vtop->r & VT_LVAL_SHORT)
3957 t = VT_SHORT;
3958 if (vtop->r & VT_LVAL_UNSIGNED)
3959 t |= VT_UNSIGNED;
3960 vtop->type.t = t;
3961 load(r, vtop);
3962 /* restore wanted type */
3963 vtop->type.t = t1;
3964 } else {
3965 /* one register type load */
3966 load(r, vtop);
3969 vtop->r = r;
3971 return r;
3974 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
3975 void gv2(int rc1, int rc2)
3977 int v;
3979 /* generate more generic register first. But VT_JMP or VT_CMP
3980 values must be generated first in all cases to avoid possible
3981 reload errors */
3982 v = vtop[0].r & VT_VALMASK;
3983 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
3984 vswap();
3985 gv(rc1);
3986 vswap();
3987 gv(rc2);
3988 /* test if reload is needed for first register */
3989 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
3990 vswap();
3991 gv(rc1);
3992 vswap();
3994 } else {
3995 gv(rc2);
3996 vswap();
3997 gv(rc1);
3998 vswap();
3999 /* test if reload is needed for first register */
4000 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4001 gv(rc2);
4006 /* expand long long on stack in two int registers */
4007 void lexpand(void)
4009 int u;
4011 u = vtop->type.t & VT_UNSIGNED;
4012 gv(RC_INT);
4013 vdup();
4014 vtop[0].r = vtop[-1].r2;
4015 vtop[0].r2 = VT_CONST;
4016 vtop[-1].r2 = VT_CONST;
4017 vtop[0].type.t = VT_INT | u;
4018 vtop[-1].type.t = VT_INT | u;
4021 /* build a long long from two ints */
4022 void lbuild(int t)
4024 gv2(RC_INT, RC_INT);
4025 vtop[-1].r2 = vtop[0].r;
4026 vtop[-1].type.t = t;
4027 vpop();
4030 /* rotate n first stack elements to the bottom */
4031 void vrotb(int n)
4033 int i;
4034 SValue tmp;
4036 tmp = vtop[-n + 1];
4037 for(i=-n+1;i!=0;i++)
4038 vtop[i] = vtop[i+1];
4039 vtop[0] = tmp;
4042 /* pop stack value */
4043 void vpop(void)
4045 int v;
4046 v = vtop->r & VT_VALMASK;
4047 #ifdef TCC_TARGET_I386
4048 /* for x86, we need to pop the FP stack */
4049 if (v == REG_ST0 && !nocode_wanted) {
4050 o(0xd9dd); /* fstp %st(1) */
4051 } else
4052 #endif
4053 if (v == VT_JMP || v == VT_JMPI) {
4054 /* need to put correct jump if && or || without test */
4055 gsym(vtop->c.ul);
4057 vtop--;
4060 /* convert stack entry to register and duplicate its value in another
4061 register */
4062 void gv_dup(void)
4064 int rc, t, r, r1;
4065 SValue sv;
4067 t = vtop->type.t;
4068 if ((t & VT_BTYPE) == VT_LLONG) {
4069 lexpand();
4070 gv_dup();
4071 vswap();
4072 vrotb(3);
4073 gv_dup();
4074 vrotb(4);
4075 /* stack: H L L1 H1 */
4076 lbuild(t);
4077 vrotb(3);
4078 vrotb(3);
4079 vswap();
4080 lbuild(t);
4081 vswap();
4082 } else {
4083 /* duplicate value */
4084 rc = RC_INT;
4085 sv.type.t = VT_INT;
4086 if (is_float(t)) {
4087 rc = RC_FLOAT;
4088 sv.type.t = t;
4090 r = gv(rc);
4091 r1 = get_reg(rc);
4092 sv.r = r;
4093 sv.c.ul = 0;
4094 load(r1, &sv); /* move r to r1 */
4095 vdup();
4096 /* duplicates value */
4097 vtop->r = r1;
4101 /* generate CPU independent (unsigned) long long operations */
4102 void gen_opl(int op)
4104 int t, a, b, op1, c, i;
4105 int func;
4106 GFuncContext gf;
4107 SValue tmp;
4109 switch(op) {
4110 case '/':
4111 case TOK_PDIV:
4112 func = TOK___divdi3;
4113 goto gen_func;
4114 case TOK_UDIV:
4115 func = TOK___udivdi3;
4116 goto gen_func;
4117 case '%':
4118 func = TOK___moddi3;
4119 goto gen_func;
4120 case TOK_UMOD:
4121 func = TOK___umoddi3;
4122 gen_func:
4123 /* call generic long long function */
4124 gfunc_start(&gf, FUNC_CDECL);
4125 gfunc_param(&gf);
4126 gfunc_param(&gf);
4127 vpush_global_sym(&func_old_type, func);
4128 gfunc_call(&gf);
4129 vpushi(0);
4130 vtop->r = REG_IRET;
4131 vtop->r2 = REG_LRET;
4132 break;
4133 case '^':
4134 case '&':
4135 case '|':
4136 case '*':
4137 case '+':
4138 case '-':
4139 t = vtop->type.t;
4140 vswap();
4141 lexpand();
4142 vrotb(3);
4143 lexpand();
4144 /* stack: L1 H1 L2 H2 */
4145 tmp = vtop[0];
4146 vtop[0] = vtop[-3];
4147 vtop[-3] = tmp;
4148 tmp = vtop[-2];
4149 vtop[-2] = vtop[-3];
4150 vtop[-3] = tmp;
4151 vswap();
4152 /* stack: H1 H2 L1 L2 */
4153 if (op == '*') {
4154 vpushv(vtop - 1);
4155 vpushv(vtop - 1);
4156 gen_op(TOK_UMULL);
4157 lexpand();
4158 /* stack: H1 H2 L1 L2 ML MH */
4159 for(i=0;i<4;i++)
4160 vrotb(6);
4161 /* stack: ML MH H1 H2 L1 L2 */
4162 tmp = vtop[0];
4163 vtop[0] = vtop[-2];
4164 vtop[-2] = tmp;
4165 /* stack: ML MH H1 L2 H2 L1 */
4166 gen_op('*');
4167 vrotb(3);
4168 vrotb(3);
4169 gen_op('*');
4170 /* stack: ML MH M1 M2 */
4171 gen_op('+');
4172 gen_op('+');
4173 } else if (op == '+' || op == '-') {
4174 /* XXX: add non carry method too (for MIPS or alpha) */
4175 if (op == '+')
4176 op1 = TOK_ADDC1;
4177 else
4178 op1 = TOK_SUBC1;
4179 gen_op(op1);
4180 /* stack: H1 H2 (L1 op L2) */
4181 vrotb(3);
4182 vrotb(3);
4183 gen_op(op1 + 1); /* TOK_xxxC2 */
4184 } else {
4185 gen_op(op);
4186 /* stack: H1 H2 (L1 op L2) */
4187 vrotb(3);
4188 vrotb(3);
4189 /* stack: (L1 op L2) H1 H2 */
4190 gen_op(op);
4191 /* stack: (L1 op L2) (H1 op H2) */
4193 /* stack: L H */
4194 lbuild(t);
4195 break;
4196 case TOK_SAR:
4197 case TOK_SHR:
4198 case TOK_SHL:
4199 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4200 t = vtop[-1].type.t;
4201 vswap();
4202 lexpand();
4203 vrotb(3);
4204 /* stack: L H shift */
4205 c = (int)vtop->c.i;
4206 /* constant: simpler */
4207 /* NOTE: all comments are for SHL. the other cases are
4208 done by swaping words */
4209 vpop();
4210 if (op != TOK_SHL)
4211 vswap();
4212 if (c >= 32) {
4213 /* stack: L H */
4214 vpop();
4215 if (c > 32) {
4216 vpushi(c - 32);
4217 gen_op(op);
4219 if (op != TOK_SAR) {
4220 vpushi(0);
4221 } else {
4222 gv_dup();
4223 vpushi(31);
4224 gen_op(TOK_SAR);
4226 vswap();
4227 } else {
4228 vswap();
4229 gv_dup();
4230 /* stack: H L L */
4231 vpushi(c);
4232 gen_op(op);
4233 vswap();
4234 vpushi(32 - c);
4235 if (op == TOK_SHL)
4236 gen_op(TOK_SHR);
4237 else
4238 gen_op(TOK_SHL);
4239 vrotb(3);
4240 /* stack: L L H */
4241 vpushi(c);
4242 if (op == TOK_SHL)
4243 gen_op(TOK_SHL);
4244 else
4245 gen_op(TOK_SHR);
4246 gen_op('|');
4248 if (op != TOK_SHL)
4249 vswap();
4250 lbuild(t);
4251 } else {
4252 /* XXX: should provide a faster fallback on x86 ? */
4253 switch(op) {
4254 case TOK_SAR:
4255 func = TOK___sardi3;
4256 goto gen_func;
4257 case TOK_SHR:
4258 func = TOK___shrdi3;
4259 goto gen_func;
4260 case TOK_SHL:
4261 func = TOK___shldi3;
4262 goto gen_func;
4265 break;
4266 default:
4267 /* compare operations */
4268 t = vtop->type.t;
4269 vswap();
4270 lexpand();
4271 vrotb(3);
4272 lexpand();
4273 /* stack: L1 H1 L2 H2 */
4274 tmp = vtop[-1];
4275 vtop[-1] = vtop[-2];
4276 vtop[-2] = tmp;
4277 /* stack: L1 L2 H1 H2 */
4278 /* compare high */
4279 op1 = op;
4280 /* when values are equal, we need to compare low words. since
4281 the jump is inverted, we invert the test too. */
4282 if (op1 == TOK_LT)
4283 op1 = TOK_LE;
4284 else if (op1 == TOK_GT)
4285 op1 = TOK_GE;
4286 else if (op1 == TOK_ULT)
4287 op1 = TOK_ULE;
4288 else if (op1 == TOK_UGT)
4289 op1 = TOK_UGE;
4290 a = 0;
4291 b = 0;
4292 gen_op(op1);
4293 if (op1 != TOK_NE) {
4294 a = gtst(1, 0);
4296 if (op != TOK_EQ) {
4297 /* generate non equal test */
4298 /* XXX: NOT PORTABLE yet */
4299 if (a == 0) {
4300 b = gtst(0, 0);
4301 } else {
4302 #ifdef TCC_TARGET_I386
4303 b = psym(0x850f, 0);
4304 #else
4305 error("not implemented");
4306 #endif
4309 /* compare low */
4310 gen_op(op);
4311 a = gtst(1, a);
4312 gsym(b);
4313 vseti(VT_JMPI, a);
4314 break;
4318 /* handle integer constant optimizations and various machine
4319 independant opt */
4320 void gen_opic(int op)
4322 int fc, c1, c2, n;
4323 SValue *v1, *v2;
4325 v1 = vtop - 1;
4326 v2 = vtop;
4327 /* currently, we cannot do computations with forward symbols */
4328 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4329 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4330 if (c1 && c2) {
4331 fc = v2->c.i;
4332 switch(op) {
4333 case '+': v1->c.i += fc; break;
4334 case '-': v1->c.i -= fc; break;
4335 case '&': v1->c.i &= fc; break;
4336 case '^': v1->c.i ^= fc; break;
4337 case '|': v1->c.i |= fc; break;
4338 case '*': v1->c.i *= fc; break;
4340 case TOK_PDIV:
4341 case '/':
4342 case '%':
4343 case TOK_UDIV:
4344 case TOK_UMOD:
4345 /* if division by zero, generate explicit division */
4346 if (fc == 0) {
4347 if (const_wanted)
4348 error("division by zero in constant");
4349 goto general_case;
4351 switch(op) {
4352 default: v1->c.i /= fc; break;
4353 case '%': v1->c.i %= fc; break;
4354 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4355 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4357 break;
4358 case TOK_SHL: v1->c.i <<= fc; break;
4359 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4360 case TOK_SAR: v1->c.i >>= fc; break;
4361 /* tests */
4362 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4363 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4364 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4365 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4366 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4367 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4368 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4369 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4370 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4371 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4372 /* logical */
4373 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4374 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4375 default:
4376 goto general_case;
4378 vtop--;
4379 } else {
4380 /* if commutative ops, put c2 as constant */
4381 if (c1 && (op == '+' || op == '&' || op == '^' ||
4382 op == '|' || op == '*')) {
4383 vswap();
4384 swap(&c1, &c2);
4386 fc = vtop->c.i;
4387 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4388 op == TOK_PDIV) &&
4389 fc == 1) ||
4390 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4391 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4392 fc == 0) ||
4393 (op == '&' &&
4394 fc == -1))) {
4395 /* nothing to do */
4396 vtop--;
4397 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4398 /* try to use shifts instead of muls or divs */
4399 if (fc > 0 && (fc & (fc - 1)) == 0) {
4400 n = -1;
4401 while (fc) {
4402 fc >>= 1;
4403 n++;
4405 vtop->c.i = n;
4406 if (op == '*')
4407 op = TOK_SHL;
4408 else if (op == TOK_PDIV)
4409 op = TOK_SAR;
4410 else
4411 op = TOK_SHR;
4413 goto general_case;
4414 } else if (c2 && (op == '+' || op == '-') &&
4415 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4416 (VT_CONST | VT_SYM)) {
4417 /* symbol + constant case */
4418 if (op == '-')
4419 fc = -fc;
4420 vtop--;
4421 vtop->c.i += fc;
4422 } else {
4423 general_case:
4424 if (!nocode_wanted) {
4425 /* call low level op generator */
4426 gen_opi(op);
4427 } else {
4428 vtop--;
4434 /* generate a floating point operation with constant propagation */
4435 void gen_opif(int op)
4437 int c1, c2;
4438 SValue *v1, *v2;
4439 long double f1, f2;
4441 v1 = vtop - 1;
4442 v2 = vtop;
4443 /* currently, we cannot do computations with forward symbols */
4444 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4445 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4446 if (c1 && c2) {
4447 if (v1->type.t == VT_FLOAT) {
4448 f1 = v1->c.f;
4449 f2 = v2->c.f;
4450 } else if (v1->type.t == VT_DOUBLE) {
4451 f1 = v1->c.d;
4452 f2 = v2->c.d;
4453 } else {
4454 f1 = v1->c.ld;
4455 f2 = v2->c.ld;
4458 /* NOTE: we only do constant propagation if finite number (not
4459 NaN or infinity) (ANSI spec) */
4460 if (!ieee_finite(f1) || !ieee_finite(f2))
4461 goto general_case;
4463 switch(op) {
4464 case '+': f1 += f2; break;
4465 case '-': f1 -= f2; break;
4466 case '*': f1 *= f2; break;
4467 case '/':
4468 if (f2 == 0.0) {
4469 if (const_wanted)
4470 error("division by zero in constant");
4471 goto general_case;
4473 f1 /= f2;
4474 break;
4475 /* XXX: also handles tests ? */
4476 default:
4477 goto general_case;
4479 /* XXX: overflow test ? */
4480 if (v1->type.t == VT_FLOAT) {
4481 v1->c.f = f1;
4482 } else if (v1->type.t == VT_DOUBLE) {
4483 v1->c.d = f1;
4484 } else {
4485 v1->c.ld = f1;
4487 vtop--;
4488 } else {
4489 general_case:
4490 if (!nocode_wanted) {
4491 gen_opf(op);
4492 } else {
4493 vtop--;
4498 static int pointed_size(CType *type)
4500 int align;
4501 return type_size(pointed_type(type), &align);
4504 #if 0
4505 void check_pointer_types(SValue *p1, SValue *p2)
4507 char buf1[256], buf2[256];
4508 int t1, t2;
4509 t1 = p1->t;
4510 t2 = p2->t;
4511 if (!is_compatible_types(t1, t2)) {
4512 type_to_str(buf1, sizeof(buf1), t1, NULL);
4513 type_to_str(buf2, sizeof(buf2), t2, NULL);
4514 error("incompatible pointers '%s' and '%s'", buf1, buf2);
4517 #endif
4519 /* generic gen_op: handles types problems */
4520 void gen_op(int op)
4522 int u, t1, t2, bt1, bt2, t;
4523 CType type1;
4525 t1 = vtop[-1].type.t;
4526 t2 = vtop[0].type.t;
4527 bt1 = t1 & VT_BTYPE;
4528 bt2 = t2 & VT_BTYPE;
4530 if (bt1 == VT_PTR || bt2 == VT_PTR) {
4531 /* at least one operand is a pointer */
4532 /* relationnal op: must be both pointers */
4533 if (op >= TOK_ULT && op <= TOK_GT) {
4534 // check_pointer_types(vtop, vtop - 1);
4535 /* pointers are handled are unsigned */
4536 t = VT_INT | VT_UNSIGNED;
4537 goto std_op;
4539 /* if both pointers, then it must be the '-' op */
4540 if (bt1 == VT_PTR && bt2 == VT_PTR) {
4541 if (op != '-')
4542 error("cannot use pointers here");
4543 // check_pointer_types(vtop - 1, vtop);
4544 /* XXX: check that types are compatible */
4545 u = pointed_size(&vtop[-1].type);
4546 gen_opic(op);
4547 /* set to integer type */
4548 vtop->type.t = VT_INT;
4549 vpushi(u);
4550 gen_op(TOK_PDIV);
4551 } else {
4552 /* exactly one pointer : must be '+' or '-'. */
4553 if (op != '-' && op != '+')
4554 error("cannot use pointers here");
4555 /* Put pointer as first operand */
4556 if (bt2 == VT_PTR) {
4557 vswap();
4558 swap(&t1, &t2);
4560 type1 = vtop[-1].type;
4561 /* XXX: cast to int ? (long long case) */
4562 vpushi(pointed_size(&vtop[-1].type));
4563 gen_op('*');
4564 #ifdef CONFIG_TCC_BCHECK
4565 /* if evaluating constant expression, no code should be
4566 generated, so no bound check */
4567 if (do_bounds_check && !const_wanted) {
4568 /* if bounded pointers, we generate a special code to
4569 test bounds */
4570 if (op == '-') {
4571 vpushi(0);
4572 vswap();
4573 gen_op('-');
4575 gen_bounded_ptr_add();
4576 } else
4577 #endif
4579 gen_opic(op);
4581 /* put again type if gen_opic() swaped operands */
4582 vtop->type = type1;
4584 } else if (is_float(bt1) || is_float(bt2)) {
4585 /* compute bigger type and do implicit casts */
4586 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
4587 t = VT_LDOUBLE;
4588 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
4589 t = VT_DOUBLE;
4590 } else {
4591 t = VT_FLOAT;
4593 /* floats can only be used for a few operations */
4594 if (op != '+' && op != '-' && op != '*' && op != '/' &&
4595 (op < TOK_ULT || op > TOK_GT))
4596 error("invalid operands for binary operation");
4597 goto std_op;
4598 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
4599 /* cast to biggest op */
4600 t = VT_LLONG;
4601 /* convert to unsigned if it does not fit in a long long */
4602 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
4603 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
4604 t |= VT_UNSIGNED;
4605 goto std_op;
4606 } else {
4607 /* integer operations */
4608 t = VT_INT;
4609 /* convert to unsigned if it does not fit in an integer */
4610 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
4611 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
4612 t |= VT_UNSIGNED;
4613 std_op:
4614 /* XXX: currently, some unsigned operations are explicit, so
4615 we modify them here */
4616 if (t & VT_UNSIGNED) {
4617 if (op == TOK_SAR)
4618 op = TOK_SHR;
4619 else if (op == '/')
4620 op = TOK_UDIV;
4621 else if (op == '%')
4622 op = TOK_UMOD;
4623 else if (op == TOK_LT)
4624 op = TOK_ULT;
4625 else if (op == TOK_GT)
4626 op = TOK_UGT;
4627 else if (op == TOK_LE)
4628 op = TOK_ULE;
4629 else if (op == TOK_GE)
4630 op = TOK_UGE;
4632 vswap();
4633 type1.t = t;
4634 gen_cast(&type1);
4635 vswap();
4636 /* special case for shifts and long long: we keep the shift as
4637 an integer */
4638 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
4639 type1.t = VT_INT;
4640 gen_cast(&type1);
4641 if (is_float(t))
4642 gen_opif(op);
4643 else if ((t & VT_BTYPE) == VT_LLONG)
4644 gen_opl(op);
4645 else
4646 gen_opic(op);
4647 if (op >= TOK_ULT && op <= TOK_GT) {
4648 /* relationnal op: the result is an int */
4649 vtop->type.t = VT_INT;
4650 } else {
4651 vtop->type.t = t;
4656 /* generic itof for unsigned long long case */
4657 void gen_cvt_itof1(int t)
4659 GFuncContext gf;
4661 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
4662 (VT_LLONG | VT_UNSIGNED)) {
4664 gfunc_start(&gf, FUNC_CDECL);
4665 gfunc_param(&gf);
4666 if (t == VT_FLOAT)
4667 vpush_global_sym(&func_old_type, TOK___ulltof);
4668 else if (t == VT_DOUBLE)
4669 vpush_global_sym(&func_old_type, TOK___ulltod);
4670 else
4671 vpush_global_sym(&func_old_type, TOK___ulltold);
4672 gfunc_call(&gf);
4673 vpushi(0);
4674 vtop->r = REG_FRET;
4675 } else {
4676 gen_cvt_itof(t);
4680 /* generic ftoi for unsigned long long case */
4681 void gen_cvt_ftoi1(int t)
4683 GFuncContext gf;
4684 int st;
4686 if (t == (VT_LLONG | VT_UNSIGNED)) {
4687 /* not handled natively */
4688 gfunc_start(&gf, FUNC_CDECL);
4689 st = vtop->type.t & VT_BTYPE;
4690 gfunc_param(&gf);
4691 if (st == VT_FLOAT)
4692 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
4693 else if (st == VT_DOUBLE)
4694 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
4695 else
4696 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
4697 gfunc_call(&gf);
4698 vpushi(0);
4699 vtop->r = REG_IRET;
4700 vtop->r2 = REG_LRET;
4701 } else {
4702 gen_cvt_ftoi(t);
4706 /* force char or short cast */
4707 void force_charshort_cast(int t)
4709 int bits, dbt;
4710 dbt = t & VT_BTYPE;
4711 /* XXX: add optimization if lvalue : just change type and offset */
4712 if (dbt == VT_BYTE)
4713 bits = 8;
4714 else
4715 bits = 16;
4716 if (t & VT_UNSIGNED) {
4717 vpushi((1 << bits) - 1);
4718 gen_op('&');
4719 } else {
4720 bits = 32 - bits;
4721 vpushi(bits);
4722 gen_op(TOK_SHL);
4723 vpushi(bits);
4724 gen_op(TOK_SAR);
4728 /* cast 'vtop' to 'type' */
4729 static void gen_cast(CType *type)
4731 int sbt, dbt, sf, df, c;
4733 /* special delayed cast for char/short */
4734 /* XXX: in some cases (multiple cascaded casts), it may still
4735 be incorrect */
4736 if (vtop->r & VT_MUSTCAST) {
4737 vtop->r &= ~VT_MUSTCAST;
4738 force_charshort_cast(vtop->type.t);
4741 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
4742 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
4744 if (sbt != dbt && !nocode_wanted) {
4745 sf = is_float(sbt);
4746 df = is_float(dbt);
4747 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4748 if (sf && df) {
4749 /* convert from fp to fp */
4750 if (c) {
4751 /* constant case: we can do it now */
4752 /* XXX: in ISOC, cannot do it if error in convert */
4753 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
4754 vtop->c.f = (float)vtop->c.d;
4755 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
4756 vtop->c.f = (float)vtop->c.ld;
4757 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
4758 vtop->c.d = (double)vtop->c.f;
4759 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
4760 vtop->c.d = (double)vtop->c.ld;
4761 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
4762 vtop->c.ld = (long double)vtop->c.f;
4763 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
4764 vtop->c.ld = (long double)vtop->c.d;
4765 } else {
4766 /* non constant case: generate code */
4767 gen_cvt_ftof(dbt);
4769 } else if (df) {
4770 /* convert int to fp */
4771 if (c) {
4772 switch(sbt) {
4773 case VT_LLONG | VT_UNSIGNED:
4774 case VT_LLONG:
4775 /* XXX: add const cases for long long */
4776 goto do_itof;
4777 case VT_INT | VT_UNSIGNED:
4778 switch(dbt) {
4779 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
4780 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
4781 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
4783 break;
4784 default:
4785 switch(dbt) {
4786 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
4787 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
4788 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
4790 break;
4792 } else {
4793 do_itof:
4794 gen_cvt_itof1(dbt);
4796 } else if (sf) {
4797 /* convert fp to int */
4798 /* we handle char/short/etc... with generic code */
4799 if (dbt != (VT_INT | VT_UNSIGNED) &&
4800 dbt != (VT_LLONG | VT_UNSIGNED) &&
4801 dbt != VT_LLONG)
4802 dbt = VT_INT;
4803 if (c) {
4804 switch(dbt) {
4805 case VT_LLONG | VT_UNSIGNED:
4806 case VT_LLONG:
4807 /* XXX: add const cases for long long */
4808 goto do_ftoi;
4809 case VT_INT | VT_UNSIGNED:
4810 switch(sbt) {
4811 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
4812 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4813 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4815 break;
4816 default:
4817 /* int case */
4818 switch(sbt) {
4819 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
4820 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
4821 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
4823 break;
4825 } else {
4826 do_ftoi:
4827 gen_cvt_ftoi1(dbt);
4829 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
4830 /* additionnal cast for char/short/bool... */
4831 vtop->type.t = dbt;
4832 gen_cast(type);
4834 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
4835 if ((sbt & VT_BTYPE) != VT_LLONG) {
4836 /* scalar to long long */
4837 if (c) {
4838 if (sbt == (VT_INT | VT_UNSIGNED))
4839 vtop->c.ll = vtop->c.ui;
4840 else
4841 vtop->c.ll = vtop->c.i;
4842 } else {
4843 /* machine independant conversion */
4844 gv(RC_INT);
4845 /* generate high word */
4846 if (sbt == (VT_INT | VT_UNSIGNED)) {
4847 vpushi(0);
4848 gv(RC_INT);
4849 } else {
4850 gv_dup();
4851 vpushi(31);
4852 gen_op(TOK_SAR);
4854 /* patch second register */
4855 vtop[-1].r2 = vtop->r;
4856 vpop();
4859 } else if (dbt == VT_BOOL) {
4860 /* scalar to bool */
4861 vpushi(0);
4862 gen_op(TOK_NE);
4863 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
4864 (dbt & VT_BTYPE) == VT_SHORT) {
4865 force_charshort_cast(dbt);
4866 } else if ((dbt & VT_BTYPE) == VT_INT) {
4867 /* scalar to int */
4868 if (sbt == VT_LLONG) {
4869 /* from long long: just take low order word */
4870 lexpand();
4871 vpop();
4873 /* if lvalue and single word type, nothing to do because
4874 the lvalue already contains the real type size (see
4875 VT_LVAL_xxx constants) */
4878 vtop->type = *type;
4881 /* return type size. Put alignment at 'a' */
4882 int type_size(CType *type, int *a)
4884 Sym *s;
4885 int bt;
4887 bt = type->t & VT_BTYPE;
4888 if (bt == VT_STRUCT) {
4889 /* struct/union */
4890 s = type->ref;
4891 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
4892 return s->c;
4893 } else if (bt == VT_PTR) {
4894 if (type->t & VT_ARRAY) {
4895 s = type->ref;
4896 return type_size(&s->type, a) * s->c;
4897 } else {
4898 *a = PTR_SIZE;
4899 return PTR_SIZE;
4901 } else if (bt == VT_LDOUBLE) {
4902 *a = LDOUBLE_ALIGN;
4903 return LDOUBLE_SIZE;
4904 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
4905 *a = 8;
4906 return 8;
4907 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
4908 *a = 4;
4909 return 4;
4910 } else if (bt == VT_SHORT) {
4911 *a = 2;
4912 return 2;
4913 } else {
4914 /* char, void, function, _Bool */
4915 *a = 1;
4916 return 1;
4920 /* return the pointed type of t */
4921 static inline CType *pointed_type(CType *type)
4923 return &type->ref->type;
4926 /* modify type so that its it is a pointer to type. */
4927 static void mk_pointer(CType *type)
4929 Sym *s;
4930 s = sym_push(SYM_FIELD, type, 0, -1);
4931 type->t = VT_PTR | (type->t & ~VT_TYPE);
4932 type->ref = s;
4935 static int is_compatible_types(CType *type1, CType *type2)
4937 Sym *s1, *s2;
4938 int bt1, bt2, t1, t2;
4940 t1 = type1->t & VT_TYPE;
4941 t2 = type2->t & VT_TYPE;
4942 bt1 = t1 & VT_BTYPE;
4943 bt2 = t2 & VT_BTYPE;
4944 if (bt1 == VT_PTR) {
4945 type1 = pointed_type(type1);
4946 /* if function, then convert implicitely to function pointer */
4947 if (bt2 != VT_FUNC) {
4948 if (bt2 != VT_PTR)
4949 return 0;
4950 type2 = pointed_type(type2);
4952 /* void matches everything */
4953 /* XXX: not fully compliant */
4954 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
4955 return 1;
4956 return is_compatible_types(type1, type2);
4957 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
4958 return (t2 == t1);
4959 } else if (bt1 == VT_FUNC) {
4960 if (bt2 != VT_FUNC)
4961 return 0;
4962 s1 = type1->ref;
4963 s2 = type2->ref;
4964 if (!is_compatible_types(&s1->type, &s2->type))
4965 return 0;
4966 /* XXX: not complete */
4967 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
4968 return 1;
4969 if (s1->c != s2->c)
4970 return 0;
4971 while (s1 != NULL) {
4972 if (s2 == NULL)
4973 return 0;
4974 if (!is_compatible_types(&s1->type, &s2->type))
4975 return 0;
4976 s1 = s1->next;
4977 s2 = s2->next;
4979 if (s2)
4980 return 0;
4981 return 1;
4982 } else {
4983 /* XXX: not complete */
4984 return 1;
4988 /* print a type. If 'varstr' is not NULL, then the variable is also
4989 printed in the type */
4990 /* XXX: union */
4991 /* XXX: add array and function pointers */
4992 void type_to_str(char *buf, int buf_size,
4993 CType *type, const char *varstr)
4995 int bt, v, t;
4996 Sym *s, *sa;
4997 char buf1[256];
4998 const char *tstr;
5000 t = type->t & VT_TYPE;
5001 bt = t & VT_BTYPE;
5002 buf[0] = '\0';
5003 if (t & VT_UNSIGNED)
5004 pstrcat(buf, buf_size, "unsigned ");
5005 switch(bt) {
5006 case VT_VOID:
5007 tstr = "void";
5008 goto add_tstr;
5009 case VT_BOOL:
5010 tstr = "_Bool";
5011 goto add_tstr;
5012 case VT_BYTE:
5013 tstr = "char";
5014 goto add_tstr;
5015 case VT_SHORT:
5016 tstr = "short";
5017 goto add_tstr;
5018 case VT_INT:
5019 tstr = "int";
5020 goto add_tstr;
5021 case VT_LONG:
5022 tstr = "long";
5023 goto add_tstr;
5024 case VT_LLONG:
5025 tstr = "long long";
5026 goto add_tstr;
5027 case VT_FLOAT:
5028 tstr = "float";
5029 goto add_tstr;
5030 case VT_DOUBLE:
5031 tstr = "double";
5032 goto add_tstr;
5033 case VT_LDOUBLE:
5034 tstr = "long double";
5035 add_tstr:
5036 pstrcat(buf, buf_size, tstr);
5037 break;
5038 case VT_ENUM:
5039 case VT_STRUCT:
5040 if (bt == VT_STRUCT)
5041 tstr = "struct ";
5042 else
5043 tstr = "enum ";
5044 pstrcat(buf, buf_size, tstr);
5045 v = type->ref->v;
5046 if (v >= SYM_FIRST_ANOM)
5047 pstrcat(buf, buf_size, "<anonymous>");
5048 else
5049 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5050 break;
5051 case VT_FUNC:
5052 s = type->ref;
5053 type_to_str(buf, buf_size, &s->type, varstr);
5054 pstrcat(buf, buf_size, "(");
5055 sa = s->next;
5056 while (sa != NULL) {
5057 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5058 pstrcat(buf, buf_size, buf1);
5059 sa = sa->next;
5060 if (sa)
5061 pstrcat(buf, buf_size, ", ");
5063 pstrcat(buf, buf_size, ")");
5064 goto no_var;
5065 case VT_PTR:
5066 s = type->ref;
5067 pstrcpy(buf1, sizeof(buf1), "*");
5068 if (varstr)
5069 pstrcat(buf1, sizeof(buf1), varstr);
5070 type_to_str(buf, buf_size, &s->type, buf1);
5071 goto no_var;
5073 if (varstr) {
5074 pstrcat(buf, buf_size, " ");
5075 pstrcat(buf, buf_size, varstr);
5077 no_var: ;
5080 /* verify type compatibility to store vtop in 'dt' type, and generate
5081 casts if needed. */
5082 void gen_assign_cast(CType *dt)
5084 CType *st;
5085 char buf1[256], buf2[256];
5087 st = &vtop->type; /* source type */
5088 if ((dt->t & VT_BTYPE) == VT_PTR) {
5089 /* special cases for pointers */
5090 /* a function is implicitely a function pointer */
5091 if ((st->t & VT_BTYPE) == VT_FUNC) {
5092 if (!is_compatible_types(pointed_type(dt), st))
5093 goto error;
5094 else
5095 goto type_ok;
5097 /* '0' can also be a pointer */
5098 if ((st->t & VT_BTYPE) == VT_INT &&
5099 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5100 vtop->c.i == 0)
5101 goto type_ok;
5103 if (!is_compatible_types(dt, st)) {
5104 error:
5105 type_to_str(buf1, sizeof(buf1), st, NULL);
5106 type_to_str(buf2, sizeof(buf2), dt, NULL);
5107 error("cannot cast '%s' to '%s'", buf1, buf2);
5109 type_ok:
5110 gen_cast(dt);
5113 /* store vtop in lvalue pushed on stack */
5114 void vstore(void)
5116 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5117 GFuncContext gf;
5119 ft = vtop[-1].type.t;
5120 sbt = vtop->type.t & VT_BTYPE;
5121 dbt = ft & VT_BTYPE;
5122 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5123 (sbt == VT_INT && dbt == VT_SHORT)) {
5124 /* optimize char/short casts */
5125 delayed_cast = VT_MUSTCAST;
5126 vtop->type.t = ft & VT_TYPE;
5127 } else {
5128 delayed_cast = 0;
5129 gen_assign_cast(&vtop[-1].type);
5132 if (sbt == VT_STRUCT) {
5133 /* if structure, only generate pointer */
5134 /* structure assignment : generate memcpy */
5135 /* XXX: optimize if small size */
5136 if (!nocode_wanted) {
5137 vdup();
5138 gfunc_start(&gf, FUNC_CDECL);
5139 /* type size */
5140 size = type_size(&vtop->type, &align);
5141 vpushi(size);
5142 gfunc_param(&gf);
5143 /* source */
5144 vtop->type.t = VT_INT;
5145 gaddrof();
5146 gfunc_param(&gf);
5147 /* destination */
5148 vswap();
5149 vtop->type.t = VT_INT;
5150 gaddrof();
5151 gfunc_param(&gf);
5153 save_regs(0);
5154 vpush_global_sym(&func_old_type, TOK_memcpy);
5155 gfunc_call(&gf);
5156 } else {
5157 vswap();
5158 vpop();
5160 /* leave source on stack */
5161 } else if (ft & VT_BITFIELD) {
5162 /* bitfield store handling */
5163 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5164 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5165 /* remove bit field info to avoid loops */
5166 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5168 /* duplicate destination */
5169 vdup();
5170 vtop[-1] = vtop[-2];
5172 /* mask and shift source */
5173 vpushi((1 << bit_size) - 1);
5174 gen_op('&');
5175 vpushi(bit_pos);
5176 gen_op(TOK_SHL);
5177 /* load destination, mask and or with source */
5178 vswap();
5179 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5180 gen_op('&');
5181 gen_op('|');
5182 /* store result */
5183 vstore();
5184 } else {
5185 #ifdef CONFIG_TCC_BCHECK
5186 /* bound check case */
5187 if (vtop[-1].r & VT_MUSTBOUND) {
5188 vswap();
5189 gbound();
5190 vswap();
5192 #endif
5193 if (!nocode_wanted) {
5194 rc = RC_INT;
5195 if (is_float(ft))
5196 rc = RC_FLOAT;
5197 r = gv(rc); /* generate value */
5198 /* if lvalue was saved on stack, must read it */
5199 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5200 SValue sv;
5201 t = get_reg(RC_INT);
5202 sv.type.t = VT_INT;
5203 sv.r = VT_LOCAL | VT_LVAL;
5204 sv.c.ul = vtop[-1].c.ul;
5205 load(t, &sv);
5206 vtop[-1].r = t | VT_LVAL;
5208 store(r, vtop - 1);
5209 /* two word case handling : store second register at word + 4 */
5210 if ((ft & VT_BTYPE) == VT_LLONG) {
5211 vswap();
5212 /* convert to int to increment easily */
5213 vtop->type.t = VT_INT;
5214 gaddrof();
5215 vpushi(4);
5216 gen_op('+');
5217 vtop->r |= VT_LVAL;
5218 vswap();
5219 /* XXX: it works because r2 is spilled last ! */
5220 store(vtop->r2, vtop - 1);
5223 vswap();
5224 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5225 vtop->r |= delayed_cast;
5229 /* post defines POST/PRE add. c is the token ++ or -- */
5230 void inc(int post, int c)
5232 test_lvalue();
5233 vdup(); /* save lvalue */
5234 if (post) {
5235 gv_dup(); /* duplicate value */
5236 vrotb(3);
5237 vrotb(3);
5239 /* add constant */
5240 vpushi(c - TOK_MID);
5241 gen_op('+');
5242 vstore(); /* store value */
5243 if (post)
5244 vpop(); /* if post op, return saved value */
5247 /* Parse GNUC __attribute__ extension. Currently, the following
5248 extensions are recognized:
5249 - aligned(n) : set data/function alignment.
5250 - section(x) : generate data/code in this section.
5251 - unused : currently ignored, but may be used someday.
5253 void parse_attribute(AttributeDef *ad)
5255 int t, n;
5257 next();
5258 skip('(');
5259 skip('(');
5260 while (tok != ')') {
5261 if (tok < TOK_IDENT)
5262 expect("attribute name");
5263 t = tok;
5264 next();
5265 switch(t) {
5266 case TOK_SECTION:
5267 case TOK___SECTION__:
5268 skip('(');
5269 if (tok != TOK_STR)
5270 expect("section name");
5271 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5272 next();
5273 skip(')');
5274 break;
5275 case TOK_ALIGNED:
5276 case TOK___ALIGNED__:
5277 skip('(');
5278 n = expr_const();
5279 if (n <= 0 || (n & (n - 1)) != 0)
5280 error("alignment must be a positive power of two");
5281 ad->aligned = n;
5282 skip(')');
5283 break;
5284 case TOK_UNUSED:
5285 case TOK___UNUSED__:
5286 /* currently, no need to handle it because tcc does not
5287 track unused objects */
5288 break;
5289 case TOK_NORETURN:
5290 case TOK___NORETURN__:
5291 /* currently, no need to handle it because tcc does not
5292 track unused objects */
5293 break;
5294 case TOK_CDECL:
5295 case TOK___CDECL:
5296 case TOK___CDECL__:
5297 ad->func_call = FUNC_CDECL;
5298 break;
5299 case TOK_STDCALL:
5300 case TOK___STDCALL:
5301 case TOK___STDCALL__:
5302 ad->func_call = FUNC_STDCALL;
5303 break;
5304 default:
5305 warning("'%s' attribute ignored", get_tok_str(t, NULL));
5306 /* skip parameters */
5307 /* XXX: skip parenthesis too */
5308 if (tok == '(') {
5309 next();
5310 while (tok != ')' && tok != -1)
5311 next();
5312 next();
5314 break;
5316 if (tok != ',')
5317 break;
5318 next();
5320 skip(')');
5321 skip(')');
5324 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5325 static void struct_decl(CType *type, int u)
5327 int a, v, size, align, maxalign, c, offset;
5328 int bit_size, bit_pos, bsize, bt, lbit_pos;
5329 Sym *s, *ss, **ps;
5330 AttributeDef ad;
5331 CType type1, btype;
5333 a = tok; /* save decl type */
5334 next();
5335 if (tok != '{') {
5336 v = tok;
5337 next();
5338 /* struct already defined ? return it */
5339 /* XXX: check consistency */
5340 s = struct_find(v);
5341 if (s) {
5342 if (s->type.t != a)
5343 error("invalid type");
5344 goto do_decl;
5346 } else {
5347 v = anon_sym++;
5349 type1.t = a;
5350 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5351 /* put struct/union/enum name in type */
5352 do_decl:
5353 type->t = u;
5354 type->ref = s;
5356 if (tok == '{') {
5357 next();
5358 if (s->c)
5359 error("struct/union/enum already defined");
5360 /* cannot be empty */
5361 c = 0;
5362 maxalign = 0;
5363 ps = &s->next;
5364 bit_pos = 0;
5365 offset = 0;
5366 while (1) {
5367 if (a == TOK_ENUM) {
5368 v = tok;
5369 next();
5370 if (tok == '=') {
5371 next();
5372 c = expr_const();
5374 /* enum symbols have static storage */
5375 ss = sym_push(v, &int_type, VT_CONST, c);
5376 ss->type.t |= VT_STATIC;
5377 if (tok == ',')
5378 next();
5379 c++;
5380 } else {
5381 parse_btype(&btype, &ad);
5382 while (1) {
5383 bit_size = -1;
5384 v = 0;
5385 type1 = btype;
5386 if (tok != ':') {
5387 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5388 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5389 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
5390 error("invalid type for '%s'",
5391 get_tok_str(v, NULL));
5393 if (tok == ':') {
5394 next();
5395 bit_size = expr_const();
5396 /* XXX: handle v = 0 case for messages */
5397 if (bit_size < 0)
5398 error("negative width in bit-field '%s'",
5399 get_tok_str(v, NULL));
5400 if (v && bit_size == 0)
5401 error("zero width for bit-field '%s'",
5402 get_tok_str(v, NULL));
5404 size = type_size(&type1, &align);
5405 lbit_pos = 0;
5406 if (bit_size >= 0) {
5407 bt = type1.t & VT_BTYPE;
5408 if (bt != VT_INT &&
5409 bt != VT_BYTE &&
5410 bt != VT_SHORT)
5411 error("bitfields must have scalar type");
5412 bsize = size * 8;
5413 if (bit_size > bsize) {
5414 error("width of '%s' exceeds its type",
5415 get_tok_str(v, NULL));
5416 } else if (bit_size == bsize) {
5417 /* no need for bit fields */
5418 bit_pos = 0;
5419 } else if (bit_size == 0) {
5420 /* XXX: what to do if only padding in a
5421 structure ? */
5422 /* zero size: means to pad */
5423 if (bit_pos > 0)
5424 bit_pos = bsize;
5425 } else {
5426 /* we do not have enough room ? */
5427 if ((bit_pos + bit_size) > bsize)
5428 bit_pos = 0;
5429 lbit_pos = bit_pos;
5430 /* XXX: handle LSB first */
5431 type1.t |= VT_BITFIELD |
5432 (bit_pos << VT_STRUCT_SHIFT) |
5433 (bit_size << (VT_STRUCT_SHIFT + 6));
5434 bit_pos += bit_size;
5436 } else {
5437 bit_pos = 0;
5439 if (v) {
5440 /* add new memory data only if starting
5441 bit field */
5442 if (lbit_pos == 0) {
5443 if (a == TOK_STRUCT) {
5444 c = (c + align - 1) & -align;
5445 offset = c;
5446 c += size;
5447 } else {
5448 offset = 0;
5449 if (size > c)
5450 c = size;
5452 if (align > maxalign)
5453 maxalign = align;
5455 #if 0
5456 printf("add field %s offset=%d",
5457 get_tok_str(v, NULL), offset);
5458 if (type1.t & VT_BITFIELD) {
5459 printf(" pos=%d size=%d",
5460 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
5461 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
5463 printf("\n");
5464 #endif
5465 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
5466 *ps = ss;
5467 ps = &ss->next;
5469 if (tok == ';' || tok == -1)
5470 break;
5471 skip(',');
5473 skip(';');
5475 if (tok == '}')
5476 break;
5478 skip('}');
5479 /* size for struct/union, dummy for enum */
5480 s->c = (c + maxalign - 1) & -maxalign;
5484 /* return 0 if no type declaration. otherwise, return the basic type
5485 and skip it.
5487 static int parse_btype(CType *type, AttributeDef *ad)
5489 int t, u, type_found;
5490 Sym *s;
5491 CType type1;
5493 memset(ad, 0, sizeof(AttributeDef));
5494 type_found = 0;
5495 t = 0;
5496 while(1) {
5497 switch(tok) {
5498 /* basic types */
5499 case TOK_CHAR:
5500 u = VT_BYTE;
5501 basic_type:
5502 next();
5503 basic_type1:
5504 if ((t & VT_BTYPE) != 0)
5505 error("too many basic types");
5506 t |= u;
5507 break;
5508 case TOK_VOID:
5509 u = VT_VOID;
5510 goto basic_type;
5511 case TOK_SHORT:
5512 u = VT_SHORT;
5513 goto basic_type;
5514 case TOK_INT:
5515 next();
5516 break;
5517 case TOK_LONG:
5518 next();
5519 if ((t & VT_BTYPE) == VT_DOUBLE) {
5520 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5521 } else if ((t & VT_BTYPE) == VT_LONG) {
5522 t = (t & ~VT_BTYPE) | VT_LLONG;
5523 } else {
5524 u = VT_LONG;
5525 goto basic_type1;
5527 break;
5528 case TOK_BOOL:
5529 u = VT_BOOL;
5530 goto basic_type;
5531 case TOK_FLOAT:
5532 u = VT_FLOAT;
5533 goto basic_type;
5534 case TOK_DOUBLE:
5535 next();
5536 if ((t & VT_BTYPE) == VT_LONG) {
5537 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5538 } else {
5539 u = VT_DOUBLE;
5540 goto basic_type1;
5542 break;
5543 case TOK_ENUM:
5544 struct_decl(&type1, VT_ENUM);
5545 basic_type2:
5546 u = type1.t;
5547 type->ref = type1.ref;
5548 goto basic_type1;
5549 case TOK_STRUCT:
5550 case TOK_UNION:
5551 struct_decl(&type1, VT_STRUCT);
5552 goto basic_type2;
5554 /* type modifiers */
5555 case TOK_CONST:
5556 case TOK_VOLATILE:
5557 case TOK_REGISTER:
5558 case TOK_SIGNED:
5559 case TOK___SIGNED__:
5560 case TOK_AUTO:
5561 case TOK_INLINE:
5562 case TOK___INLINE__:
5563 case TOK_RESTRICT:
5564 next();
5565 break;
5566 case TOK_UNSIGNED:
5567 t |= VT_UNSIGNED;
5568 next();
5569 break;
5571 /* storage */
5572 case TOK_EXTERN:
5573 t |= VT_EXTERN;
5574 next();
5575 break;
5576 case TOK_STATIC:
5577 t |= VT_STATIC;
5578 next();
5579 break;
5580 case TOK_TYPEDEF:
5581 t |= VT_TYPEDEF;
5582 next();
5583 break;
5584 /* GNUC attribute */
5585 case TOK___ATTRIBUTE__:
5586 parse_attribute(ad);
5587 break;
5588 /* GNUC typeof */
5589 case TOK_TYPEOF:
5590 next();
5591 parse_expr_type(&type1);
5592 goto basic_type2;
5593 default:
5594 s = sym_find(tok);
5595 if (!s || !(s->type.t & VT_TYPEDEF))
5596 goto the_end;
5597 t |= (s->type.t & ~VT_TYPEDEF);
5598 type->ref = s->type.ref;
5599 next();
5600 break;
5602 type_found = 1;
5604 the_end:
5605 /* long is never used as type */
5606 if ((t & VT_BTYPE) == VT_LONG)
5607 t = (t & ~VT_BTYPE) | VT_INT;
5608 type->t = t;
5609 return type_found;
5612 static void post_type(CType *type, AttributeDef *ad)
5614 int n, l, t1;
5615 Sym **plast, *s, *first;
5616 AttributeDef ad1;
5617 CType pt;
5619 if (tok == '(') {
5620 /* function declaration */
5621 next();
5622 l = 0;
5623 first = NULL;
5624 plast = &first;
5625 while (tok != ')') {
5626 /* read param name and compute offset */
5627 if (l != FUNC_OLD) {
5628 if (!parse_btype(&pt, &ad1)) {
5629 if (l) {
5630 error("invalid type");
5631 } else {
5632 l = FUNC_OLD;
5633 goto old_proto;
5636 l = FUNC_NEW;
5637 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
5638 break;
5639 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
5640 if ((pt.t & VT_BTYPE) == VT_VOID)
5641 error("parameter declared as void");
5642 } else {
5643 old_proto:
5644 n = tok;
5645 pt.t = VT_INT;
5646 next();
5648 /* array must be transformed to pointer according to ANSI C */
5649 pt.t &= ~VT_ARRAY;
5650 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
5651 *plast = s;
5652 plast = &s->next;
5653 if (tok == ',') {
5654 next();
5655 if (l == FUNC_NEW && tok == TOK_DOTS) {
5656 l = FUNC_ELLIPSIS;
5657 next();
5658 break;
5662 /* if no parameters, then old type prototype */
5663 if (l == 0)
5664 l = FUNC_OLD;
5665 skip(')');
5666 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5667 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5668 post_type(type, ad);
5669 /* we push a anonymous symbol which will contain the function prototype */
5670 s = sym_push(SYM_FIELD, type, ad->func_call, l);
5671 s->next = first;
5672 type->t = t1 | VT_FUNC;
5673 type->ref = s;
5674 } else if (tok == '[') {
5675 /* array definition */
5676 next();
5677 n = -1;
5678 if (tok != ']') {
5679 n = expr_const();
5680 if (n < 0)
5681 error("invalid array size");
5683 skip(']');
5684 /* parse next post type */
5685 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5686 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5687 post_type(type, ad);
5689 /* we push a anonymous symbol which will contain the array
5690 element type */
5691 s = sym_push(SYM_FIELD, type, 0, n);
5692 type->t = t1 | VT_ARRAY | VT_PTR;
5693 type->ref = s;
5697 /* Parse a type declaration (except basic type), and return the type
5698 in 'type'. 'td' is a bitmask indicating which kind of type decl is
5699 expected. 'type' should contain the basic type. 'ad' is the
5700 attribute definition of the basic type. It can be modified by
5701 type_decl().
5703 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
5705 Sym *s;
5706 CType type1, *type2;
5708 while (tok == '*') {
5709 next();
5710 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
5711 next();
5712 mk_pointer(type);
5715 /* recursive type */
5716 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
5717 type1.t = 0; /* XXX: same as int */
5718 if (tok == '(') {
5719 next();
5720 /* XXX: this is not correct to modify 'ad' at this point, but
5721 the syntax is not clear */
5722 if (tok == TOK___ATTRIBUTE__)
5723 parse_attribute(ad);
5724 type_decl(&type1, ad, v, td);
5725 skip(')');
5726 } else {
5727 /* type identifier */
5728 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
5729 *v = tok;
5730 next();
5731 } else {
5732 if (!(td & TYPE_ABSTRACT))
5733 expect("identifier");
5734 *v = 0;
5737 post_type(type, ad);
5738 if (tok == TOK___ATTRIBUTE__)
5739 parse_attribute(ad);
5740 if (!type1.t)
5741 return;
5742 /* append type at the end of type1 */
5743 type2 = &type1;
5744 for(;;) {
5745 s = type2->ref;
5746 type2 = &s->type;
5747 if (!type2->t) {
5748 *type2 = *type;
5749 break;
5752 *type = type1;
5755 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
5756 static int lvalue_type(int t)
5758 int bt, r;
5759 r = VT_LVAL;
5760 bt = t & VT_BTYPE;
5761 if (bt == VT_BYTE)
5762 r |= VT_LVAL_BYTE;
5763 else if (bt == VT_SHORT)
5764 r |= VT_LVAL_SHORT;
5765 else
5766 return r;
5767 if (t & VT_UNSIGNED)
5768 r |= VT_LVAL_UNSIGNED;
5769 return r;
5772 /* indirection with full error checking and bound check */
5773 static void indir(void)
5775 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
5776 expect("pointer");
5777 if ((vtop->r & VT_LVAL) && !nocode_wanted)
5778 gv(RC_INT);
5779 vtop->type = *pointed_type(&vtop->type);
5780 /* an array is never an lvalue */
5781 if (!(vtop->type.t & VT_ARRAY)) {
5782 vtop->r |= lvalue_type(vtop->type.t);
5783 /* if bound checking, the referenced pointer must be checked */
5784 if (do_bounds_check)
5785 vtop->r |= VT_MUSTBOUND;
5789 /* pass a parameter to a function and do type checking and casting */
5790 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
5792 int func_type;
5793 CType type;
5795 func_type = func->c;
5796 if (func_type == FUNC_OLD ||
5797 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
5798 /* default casting : only need to convert float to double */
5799 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
5800 type.t = VT_DOUBLE;
5801 gen_cast(&type);
5803 } else if (arg == NULL) {
5804 error("too many arguments to function");
5805 } else {
5806 gen_assign_cast(&arg->type);
5808 if (!nocode_wanted) {
5809 gfunc_param(gf);
5810 } else {
5811 vpop();
5815 /* parse an expression of the form '(type)' or '(expr)' and return its
5816 type */
5817 static void parse_expr_type(CType *type)
5819 int n;
5820 AttributeDef ad;
5822 skip('(');
5823 if (parse_btype(type, &ad)) {
5824 type_decl(type, &ad, &n, TYPE_ABSTRACT);
5825 } else {
5826 expr_type(type);
5828 skip(')');
5831 static void vpush_tokc(int t)
5833 CType type;
5834 type.t = t;
5835 vsetc(&type, VT_CONST, &tokc);
5838 static void unary(void)
5840 int n, t, align, size, r;
5841 CType type;
5842 Sym *s;
5843 GFuncContext gf;
5844 AttributeDef ad;
5846 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
5847 vpushi(tokc.i);
5848 next();
5849 } else if (tok == TOK_CUINT) {
5850 vpush_tokc(VT_INT | VT_UNSIGNED);
5851 next();
5852 } else if (tok == TOK_CLLONG) {
5853 vpush_tokc(VT_LLONG);
5854 next();
5855 } else if (tok == TOK_CULLONG) {
5856 vpush_tokc(VT_LLONG | VT_UNSIGNED);
5857 next();
5858 } else if (tok == TOK_CFLOAT) {
5859 vpush_tokc(VT_FLOAT);
5860 next();
5861 } else if (tok == TOK_CDOUBLE) {
5862 vpush_tokc(VT_DOUBLE);
5863 next();
5864 } else if (tok == TOK_CLDOUBLE) {
5865 vpush_tokc(VT_LDOUBLE);
5866 next();
5867 } else if (tok == TOK___FUNC__ || (tok == TOK___FUNCTION__ && gnu_ext)) {
5868 void *ptr;
5869 int len;
5870 /* special function name identifier */
5872 len = strlen(funcname) + 1;
5873 /* generate char[len] type */
5874 type.t = VT_BYTE;
5875 mk_pointer(&type);
5876 type.t |= VT_ARRAY;
5877 type.ref->c = len;
5878 vpush_ref(&type, data_section, data_section->data_offset, len);
5879 ptr = section_ptr_add(data_section, len);
5880 memcpy(ptr, funcname, len);
5881 next();
5882 } else if (tok == TOK_LSTR) {
5883 t = VT_INT;
5884 goto str_init;
5885 } else if (tok == TOK_STR) {
5886 /* string parsing */
5887 t = VT_BYTE;
5888 str_init:
5889 type.t = t;
5890 mk_pointer(&type);
5891 type.t |= VT_ARRAY;
5892 memset(&ad, 0, sizeof(AttributeDef));
5893 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
5894 } else {
5895 t = tok;
5896 next();
5897 if (t == '(') {
5898 /* cast ? */
5899 if (parse_btype(&type, &ad)) {
5900 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
5901 skip(')');
5902 /* check ISOC99 compound literal */
5903 if (tok == '{') {
5904 /* data is allocated locally by default */
5905 if (global_expr)
5906 r = VT_CONST;
5907 else
5908 r = VT_LOCAL;
5909 /* all except arrays are lvalues */
5910 if (!(type.t & VT_ARRAY))
5911 r |= lvalue_type(type.t);
5912 memset(&ad, 0, sizeof(AttributeDef));
5913 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
5914 } else {
5915 unary();
5916 gen_cast(&type);
5918 } else {
5919 gexpr();
5920 skip(')');
5922 } else if (t == '*') {
5923 unary();
5924 indir();
5925 } else if (t == '&') {
5926 unary();
5927 /* functions names must be treated as function pointers,
5928 except for unary '&' and sizeof. Since we consider that
5929 functions are not lvalues, we only have to handle it
5930 there and in function calls. */
5931 /* arrays can also be used although they are not lvalues */
5932 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
5933 !(vtop->type.t & VT_ARRAY))
5934 test_lvalue();
5935 mk_pointer(&vtop->type);
5936 gaddrof();
5937 } else if (t == '!') {
5938 unary();
5939 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
5940 vtop->c.i = !vtop->c.i;
5941 else if ((vtop->r & VT_VALMASK) == VT_CMP)
5942 vtop->c.i = vtop->c.i ^ 1;
5943 else
5944 vseti(VT_JMP, gtst(1, 0));
5945 } else if (t == '~') {
5946 unary();
5947 vpushi(-1);
5948 gen_op('^');
5949 } else if (t == '+') {
5950 /* in order to force cast, we add zero */
5951 unary();
5952 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
5953 error("pointer not accepted for unary plus");
5954 vpushi(0);
5955 gen_op('+');
5956 } else if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
5957 if (tok == '(') {
5958 parse_expr_type(&type);
5959 } else {
5960 unary_type(&type);
5962 size = type_size(&type, &align);
5963 if (t == TOK_SIZEOF)
5964 vpushi(size);
5965 else
5966 vpushi(align);
5967 } else if (t == TOK_INC || t == TOK_DEC) {
5968 unary();
5969 inc(0, t);
5970 } else if (t == '-') {
5971 vpushi(0);
5972 unary();
5973 gen_op('-');
5974 } else if (t == TOK_LAND && gnu_ext) {
5975 /* allow to take the address of a label */
5976 if (tok < TOK_UIDENT)
5977 expect("label identifier");
5978 s = label_find(tok);
5979 if (!s) {
5980 s = label_push(tok, LABEL_FORWARD);
5982 if (!s->type.t) {
5983 s->type.t = VT_VOID;
5984 mk_pointer(&s->type);
5985 s->type.t |= VT_STATIC;
5987 vset(&s->type, VT_CONST | VT_SYM, 0);
5988 vtop->sym = s;
5989 next();
5990 } else {
5991 if (t < TOK_UIDENT)
5992 expect("identifier");
5993 s = sym_find(t);
5994 if (!s) {
5995 if (tok != '(')
5996 error("'%s' undeclared", get_tok_str(t, NULL));
5997 /* for simple function calls, we tolerate undeclared
5998 external reference to int() function */
5999 s = external_global_sym(t, &func_old_type, 0);
6001 vset(&s->type, s->r, s->c);
6002 /* if forward reference, we must point to s */
6003 if (vtop->r & VT_SYM) {
6004 vtop->sym = s;
6005 vtop->c.ul = 0;
6010 /* post operations */
6011 while (1) {
6012 if (tok == TOK_INC || tok == TOK_DEC) {
6013 inc(1, tok);
6014 next();
6015 } else if (tok == '.' || tok == TOK_ARROW) {
6016 /* field */
6017 if (tok == TOK_ARROW)
6018 indir();
6019 test_lvalue();
6020 gaddrof();
6021 next();
6022 /* expect pointer on structure */
6023 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6024 expect("struct or union");
6025 s = vtop->type.ref;
6026 /* find field */
6027 tok |= SYM_FIELD;
6028 while ((s = s->next) != NULL) {
6029 if (s->v == tok)
6030 break;
6032 if (!s)
6033 error("field not found");
6034 /* add field offset to pointer */
6035 vtop->type = char_pointer_type; /* change type to 'char *' */
6036 vpushi(s->c);
6037 gen_op('+');
6038 /* change type to field type, and set to lvalue */
6039 vtop->type = s->type;
6040 /* an array is never an lvalue */
6041 if (!(vtop->type.t & VT_ARRAY)) {
6042 vtop->r |= lvalue_type(vtop->type.t);
6043 /* if bound checking, the referenced pointer must be checked */
6044 if (do_bounds_check)
6045 vtop->r |= VT_MUSTBOUND;
6047 next();
6048 } else if (tok == '[') {
6049 next();
6050 gexpr();
6051 gen_op('+');
6052 indir();
6053 skip(']');
6054 } else if (tok == '(') {
6055 SValue ret;
6056 Sym *sa;
6058 /* function call */
6059 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6060 /* pointer test (no array accepted) */
6061 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6062 vtop->type = *pointed_type(&vtop->type);
6063 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6064 goto error_func;
6065 } else {
6066 error_func:
6067 expect("function pointer");
6069 } else {
6070 vtop->r &= ~VT_LVAL; /* no lvalue */
6072 /* get return type */
6073 s = vtop->type.ref;
6074 if (!nocode_wanted) {
6075 save_regs(0); /* save used temporary registers */
6076 gfunc_start(&gf, s->r);
6078 next();
6079 sa = s->next; /* first parameter */
6080 #ifdef INVERT_FUNC_PARAMS
6082 int parlevel;
6083 Sym *args, *s1;
6084 ParseState saved_parse_state;
6085 TokenString str;
6087 /* read each argument and store it on a stack */
6088 args = NULL;
6089 if (tok != ')') {
6090 for(;;) {
6091 tok_str_new(&str);
6092 parlevel = 0;
6093 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6094 tok != TOK_EOF) {
6095 if (tok == '(')
6096 parlevel++;
6097 else if (tok == ')')
6098 parlevel--;
6099 tok_str_add_tok(&str);
6100 next();
6102 tok_str_add(&str, -1); /* end of file added */
6103 tok_str_add(&str, 0);
6104 s1 = sym_push2(&args, 0, 0, (int)str.str);
6105 s1->next = sa; /* add reference to argument */
6106 if (sa)
6107 sa = sa->next;
6108 if (tok == ')')
6109 break;
6110 skip(',');
6114 /* now generate code in reverse order by reading the stack */
6115 save_parse_state(&saved_parse_state);
6116 while (args) {
6117 macro_ptr = (int *)args->c;
6118 next();
6119 expr_eq();
6120 if (tok != -1)
6121 expect("',' or ')'");
6122 gfunc_param_typed(&gf, s, args->next);
6123 s1 = args->prev;
6124 tok_str_free((int *)args->c);
6125 tcc_free(args);
6126 args = s1;
6128 restore_parse_state(&saved_parse_state);
6130 #endif
6131 /* compute first implicit argument if a structure is returned */
6132 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6133 /* get some space for the returned structure */
6134 size = type_size(&s->type, &align);
6135 loc = (loc - size) & -align;
6136 ret.type = s->type;
6137 ret.r = VT_LOCAL | VT_LVAL;
6138 /* pass it as 'int' to avoid structure arg passing
6139 problems */
6140 vseti(VT_LOCAL, loc);
6141 ret.c = vtop->c;
6142 if (!nocode_wanted)
6143 gfunc_param(&gf);
6144 else
6145 vtop--;
6146 } else {
6147 ret.type = s->type;
6148 ret.r2 = VT_CONST;
6149 /* return in register */
6150 if (is_float(ret.type.t)) {
6151 ret.r = REG_FRET;
6152 } else {
6153 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6154 ret.r2 = REG_LRET;
6155 ret.r = REG_IRET;
6157 ret.c.i = 0;
6159 #ifndef INVERT_FUNC_PARAMS
6160 if (tok != ')') {
6161 for(;;) {
6162 expr_eq();
6163 gfunc_param_typed(&gf, s, sa);
6164 if (sa)
6165 sa = sa->next;
6166 if (tok == ')')
6167 break;
6168 skip(',');
6171 #endif
6172 if (sa)
6173 error("too few arguments to function");
6174 skip(')');
6175 if (!nocode_wanted)
6176 gfunc_call(&gf);
6177 else
6178 vtop--;
6179 /* return value */
6180 vsetc(&ret.type, ret.r, &ret.c);
6181 vtop->r2 = ret.r2;
6182 } else {
6183 break;
6188 static void uneq(void)
6190 int t;
6192 unary();
6193 if (tok == '=' ||
6194 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6195 tok == TOK_A_XOR || tok == TOK_A_OR ||
6196 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6197 test_lvalue();
6198 t = tok;
6199 next();
6200 if (t == '=') {
6201 expr_eq();
6202 } else {
6203 vdup();
6204 expr_eq();
6205 gen_op(t & 0x7f);
6207 vstore();
6211 static void sum(int l)
6213 int t;
6215 if (l == 0)
6216 uneq();
6217 else {
6218 sum(--l);
6219 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
6220 (l == 1 && (tok == '+' || tok == '-')) ||
6221 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
6222 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
6223 tok == TOK_ULT || tok == TOK_UGE)) ||
6224 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
6225 (l == 5 && tok == '&') ||
6226 (l == 6 && tok == '^') ||
6227 (l == 7 && tok == '|') ||
6228 (l == 8 && tok == TOK_LAND) ||
6229 (l == 9 && tok == TOK_LOR)) {
6230 t = tok;
6231 next();
6232 sum(l);
6233 gen_op(t);
6238 /* only used if non constant */
6239 static void eand(void)
6241 int t;
6243 sum(8);
6244 t = 0;
6245 while (1) {
6246 if (tok != TOK_LAND) {
6247 if (t) {
6248 t = gtst(1, t);
6249 vseti(VT_JMPI, t);
6251 break;
6253 t = gtst(1, t);
6254 next();
6255 sum(8);
6259 static void eor(void)
6261 int t;
6263 eand();
6264 t = 0;
6265 while (1) {
6266 if (tok != TOK_LOR) {
6267 if (t) {
6268 t = gtst(0, t);
6269 vseti(VT_JMP, t);
6271 break;
6273 t = gtst(0, t);
6274 next();
6275 eand();
6279 /* XXX: better constant handling */
6280 static void expr_eq(void)
6282 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
6283 SValue sv;
6284 CType type, type1, type2;
6286 if (const_wanted) {
6287 int c1, c;
6288 sum(10);
6289 if (tok == '?') {
6290 c = vtop->c.i;
6291 vpop();
6292 next();
6293 gexpr();
6294 c1 = vtop->c.i;
6295 vpop();
6296 skip(':');
6297 expr_eq();
6298 if (c)
6299 vtop->c.i = c1;
6301 } else {
6302 eor();
6303 if (tok == '?') {
6304 next();
6305 save_regs(1); /* we need to save all registers here except
6306 at the top because it is a branch point */
6307 tt = gtst(1, 0);
6308 gexpr();
6309 type1 = vtop->type;
6310 sv = *vtop; /* save value to handle it later */
6311 vtop--; /* no vpop so that FP stack is not flushed */
6312 skip(':');
6313 u = gjmp(0);
6315 gsym(tt);
6316 expr_eq();
6317 type2 = vtop->type;
6319 t1 = type1.t;
6320 bt1 = t1 & VT_BTYPE;
6321 t2 = type2.t;
6322 bt2 = t2 & VT_BTYPE;
6323 /* cast operands to correct type according to ISOC rules */
6324 if (is_float(bt1) || is_float(bt2)) {
6325 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
6326 type.t = VT_LDOUBLE;
6327 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
6328 type.t = VT_DOUBLE;
6329 } else {
6330 type.t = VT_FLOAT;
6332 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6333 /* cast to biggest op */
6334 type.t = VT_LLONG;
6335 /* convert to unsigned if it does not fit in a long long */
6336 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6337 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6338 type.t |= VT_UNSIGNED;
6339 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
6340 /* XXX: test pointer compatibility */
6341 type = type1;
6342 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
6343 /* XXX: test structure compatibility */
6344 type = type1;
6345 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
6346 /* NOTE: as an extension, we accept void on only one side */
6347 type.t = VT_VOID;
6348 } else {
6349 /* integer operations */
6350 type.t = VT_INT;
6351 /* convert to unsigned if it does not fit in an integer */
6352 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6353 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6354 type.t |= VT_UNSIGNED;
6357 /* now we convert second operand */
6358 gen_cast(&type);
6359 rc = RC_INT;
6360 if (is_float(type.t)) {
6361 rc = RC_FLOAT;
6362 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
6363 /* for long longs, we use fixed registers to avoid having
6364 to handle a complicated move */
6365 rc = RC_IRET;
6367 r2 = gv(rc);
6368 /* this is horrible, but we must also convert first
6369 operand */
6370 tt = gjmp(0);
6371 gsym(u);
6372 /* put again first value and cast it */
6373 *vtop = sv;
6374 gen_cast(&type);
6375 r1 = gv(rc);
6376 move_reg(r2, r1);
6377 vtop->r = r2;
6378 gsym(tt);
6383 static void gexpr(void)
6385 while (1) {
6386 expr_eq();
6387 if (tok != ',')
6388 break;
6389 vpop();
6390 next();
6394 /* parse an expression and return its type without any side effect. */
6395 static void expr_type(CType *type)
6397 int a;
6399 a = nocode_wanted;
6400 nocode_wanted = 1;
6401 gexpr();
6402 *type = vtop->type;
6403 vpop();
6404 nocode_wanted = a;
6407 /* parse a unary expression and return its type without any side
6408 effect. */
6409 static void unary_type(CType *type)
6411 int a;
6413 a = nocode_wanted;
6414 nocode_wanted = 1;
6415 unary();
6416 *type = vtop->type;
6417 vpop();
6418 nocode_wanted = a;
6421 /* parse a constant expression and return value in vtop. */
6422 static void expr_const1(void)
6424 int a;
6425 a = const_wanted;
6426 const_wanted = 1;
6427 expr_eq();
6428 const_wanted = a;
6431 /* parse an integer constant and return its value. */
6432 static int expr_const(void)
6434 int c;
6435 expr_const1();
6436 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
6437 expect("constant expression");
6438 c = vtop->c.i;
6439 vpop();
6440 return c;
6443 /* return the label token if current token is a label, otherwise
6444 return zero */
6445 static int is_label(void)
6447 int t;
6448 CValue c;
6450 /* fast test first */
6451 if (tok < TOK_UIDENT)
6452 return 0;
6453 /* no need to save tokc since we expect an identifier */
6454 t = tok;
6455 c = tokc;
6456 next();
6457 if (tok == ':') {
6458 next();
6459 return t;
6460 } else {
6461 /* XXX: may not work in all cases (macros ?) */
6462 tok1 = tok;
6463 tok1c = tokc;
6464 tok = t;
6465 tokc = c;
6466 return 0;
6470 static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
6472 int a, b, c, d;
6473 Sym *s;
6475 /* generate line number info */
6476 if (do_debug &&
6477 (last_line_num != file->line_num || last_ind != ind)) {
6478 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
6479 last_ind = ind;
6480 last_line_num = file->line_num;
6483 if (tok == TOK_IF) {
6484 /* if test */
6485 next();
6486 skip('(');
6487 gexpr();
6488 skip(')');
6489 a = gtst(1, 0);
6490 block(bsym, csym, case_sym, def_sym, case_reg);
6491 c = tok;
6492 if (c == TOK_ELSE) {
6493 next();
6494 d = gjmp(0);
6495 gsym(a);
6496 block(bsym, csym, case_sym, def_sym, case_reg);
6497 gsym(d); /* patch else jmp */
6498 } else
6499 gsym(a);
6500 } else if (tok == TOK_WHILE) {
6501 next();
6502 d = ind;
6503 skip('(');
6504 gexpr();
6505 skip(')');
6506 a = gtst(1, 0);
6507 b = 0;
6508 block(&a, &b, case_sym, def_sym, case_reg);
6509 gjmp_addr(d);
6510 gsym(a);
6511 gsym_addr(b, d);
6512 } else if (tok == '{') {
6513 next();
6514 /* declarations */
6515 s = local_stack;
6516 while (tok != '}') {
6517 decl(VT_LOCAL);
6518 if (tok != '}')
6519 block(bsym, csym, case_sym, def_sym, case_reg);
6521 /* pop locally defined symbols */
6522 sym_pop(&local_stack, s);
6523 next();
6524 } else if (tok == TOK_RETURN) {
6525 next();
6526 if (tok != ';') {
6527 gexpr();
6528 gen_assign_cast(&func_vt);
6529 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
6530 CType type;
6531 /* if returning structure, must copy it to implicit
6532 first pointer arg location */
6533 type = func_vt;
6534 mk_pointer(&type);
6535 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
6536 indir();
6537 vswap();
6538 /* copy structure value to pointer */
6539 vstore();
6540 } else if (is_float(func_vt.t)) {
6541 gv(RC_FRET);
6542 } else {
6543 gv(RC_IRET);
6545 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6547 skip(';');
6548 rsym = gjmp(rsym); /* jmp */
6549 } else if (tok == TOK_BREAK) {
6550 /* compute jump */
6551 if (!bsym)
6552 error("cannot break");
6553 *bsym = gjmp(*bsym);
6554 next();
6555 skip(';');
6556 } else if (tok == TOK_CONTINUE) {
6557 /* compute jump */
6558 if (!csym)
6559 error("cannot continue");
6560 *csym = gjmp(*csym);
6561 next();
6562 skip(';');
6563 } else if (tok == TOK_FOR) {
6564 int e;
6565 next();
6566 skip('(');
6567 if (tok != ';') {
6568 gexpr();
6569 vpop();
6571 skip(';');
6572 d = ind;
6573 c = ind;
6574 a = 0;
6575 b = 0;
6576 if (tok != ';') {
6577 gexpr();
6578 a = gtst(1, 0);
6580 skip(';');
6581 if (tok != ')') {
6582 e = gjmp(0);
6583 c = ind;
6584 gexpr();
6585 vpop();
6586 gjmp_addr(d);
6587 gsym(e);
6589 skip(')');
6590 block(&a, &b, case_sym, def_sym, case_reg);
6591 gjmp_addr(c);
6592 gsym(a);
6593 gsym_addr(b, c);
6594 } else
6595 if (tok == TOK_DO) {
6596 next();
6597 a = 0;
6598 b = 0;
6599 d = ind;
6600 block(&a, &b, case_sym, def_sym, case_reg);
6601 skip(TOK_WHILE);
6602 skip('(');
6603 gsym(b);
6604 gexpr();
6605 c = gtst(0, 0);
6606 gsym_addr(c, d);
6607 skip(')');
6608 gsym(a);
6609 skip(';');
6610 } else
6611 if (tok == TOK_SWITCH) {
6612 next();
6613 skip('(');
6614 gexpr();
6615 /* XXX: other types than integer */
6616 case_reg = gv(RC_INT);
6617 vpop();
6618 skip(')');
6619 a = 0;
6620 b = gjmp(0); /* jump to first case */
6621 c = 0;
6622 block(&a, csym, &b, &c, case_reg);
6623 /* if no default, jmp after switch */
6624 if (c == 0)
6625 c = ind;
6626 /* default label */
6627 gsym_addr(b, c);
6628 /* break label */
6629 gsym(a);
6630 } else
6631 if (tok == TOK_CASE) {
6632 int v1, v2;
6633 if (!case_sym)
6634 expect("switch");
6635 next();
6636 v1 = expr_const();
6637 v2 = v1;
6638 if (gnu_ext && tok == TOK_DOTS) {
6639 next();
6640 v2 = expr_const();
6641 if (v2 < v1)
6642 warning("empty case range");
6644 /* since a case is like a label, we must skip it with a jmp */
6645 b = gjmp(0);
6646 gsym(*case_sym);
6647 vseti(case_reg, 0);
6648 vpushi(v1);
6649 if (v1 == v2) {
6650 gen_op(TOK_EQ);
6651 *case_sym = gtst(1, 0);
6652 } else {
6653 gen_op(TOK_GE);
6654 *case_sym = gtst(1, 0);
6655 vseti(case_reg, 0);
6656 vpushi(v2);
6657 gen_op(TOK_LE);
6658 *case_sym = gtst(1, *case_sym);
6660 gsym(b);
6661 skip(':');
6662 block(bsym, csym, case_sym, def_sym, case_reg);
6663 } else
6664 if (tok == TOK_DEFAULT) {
6665 next();
6666 skip(':');
6667 if (!def_sym)
6668 expect("switch");
6669 if (*def_sym)
6670 error("too many 'default'");
6671 *def_sym = ind;
6672 block(bsym, csym, case_sym, def_sym, case_reg);
6673 } else
6674 if (tok == TOK_GOTO) {
6675 next();
6676 if (tok == '*' && gnu_ext) {
6677 /* computed goto */
6678 next();
6679 gexpr();
6680 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6681 expect("pointer");
6682 ggoto();
6683 } else if (tok >= TOK_UIDENT) {
6684 s = label_find(tok);
6685 /* put forward definition if needed */
6686 if (!s) {
6687 s = label_push(tok, LABEL_FORWARD);
6689 /* label already defined */
6690 if (s->r & LABEL_FORWARD)
6691 s->next = (void *)gjmp((long)s->next);
6692 else
6693 gjmp_addr((long)s->next);
6694 next();
6695 } else {
6696 expect("label identifier");
6698 skip(';');
6699 } else {
6700 b = is_label();
6701 if (b) {
6702 /* label case */
6703 s = label_find(b);
6704 if (s) {
6705 if (!(s->r & LABEL_FORWARD))
6706 error("multiple defined label");
6707 gsym((long)s->next);
6708 } else {
6709 s = label_push(b, 0);
6711 s->next = (void *)ind;
6712 s->r = 0;
6713 /* we accept this, but it is a mistake */
6714 if (tok == '}')
6715 warning("deprecated use of label at end of compound statement");
6716 else
6717 block(bsym, csym, case_sym, def_sym, case_reg);
6718 } else {
6719 /* expression case */
6720 if (tok != ';') {
6721 gexpr();
6722 vpop();
6724 skip(';');
6729 /* t is the array or struct type. c is the array or struct
6730 address. cur_index/cur_field is the pointer to the current
6731 value. 'size_only' is true if only size info is needed (only used
6732 in arrays) */
6733 static void decl_designator(CType *type, Section *sec, unsigned long c,
6734 int *cur_index, Sym **cur_field,
6735 int size_only)
6737 Sym *s, *f;
6738 int notfirst, index, align, l;
6739 CType type1;
6741 notfirst = 0;
6742 if (gnu_ext && (l = is_label()) != 0)
6743 goto struct_field;
6745 while (tok == '[' || tok == '.') {
6746 if (tok == '[') {
6747 if (!(type->t & VT_ARRAY))
6748 expect("array type");
6749 s = type->ref;
6750 next();
6751 index = expr_const();
6752 if (index < 0 || (s->c >= 0 && index >= s->c))
6753 expect("invalid index");
6754 skip(']');
6755 if (!notfirst)
6756 *cur_index = index;
6757 type = pointed_type(type);
6758 c += index * type_size(type, &align);
6759 } else {
6760 next();
6761 l = tok;
6762 next();
6763 struct_field:
6764 if ((type->t & VT_BTYPE) != VT_STRUCT)
6765 expect("struct/union type");
6766 s = type->ref;
6767 l |= SYM_FIELD;
6768 f = s->next;
6769 while (f) {
6770 if (f->v == l)
6771 break;
6772 f = f->next;
6774 if (!f)
6775 expect("field");
6776 if (!notfirst)
6777 *cur_field = f;
6778 /* XXX: suppress this mess by using explicit storage field */
6779 type1 = f->type;
6780 type1.t |= (type->t & ~VT_TYPE);
6781 type = &type1;
6782 c += f->c;
6784 notfirst = 1;
6786 if (notfirst) {
6787 if (tok == '=') {
6788 next();
6789 } else {
6790 if (!gnu_ext)
6791 expect("=");
6793 } else {
6794 if (type->t & VT_ARRAY) {
6795 index = *cur_index;
6796 type = pointed_type(type);
6797 c += index * type_size(type, &align);
6798 } else {
6799 f = *cur_field;
6800 if (!f)
6801 error("too many field init");
6802 /* XXX: suppress this mess by using explicit storage field */
6803 type1 = f->type;
6804 type1.t |= (type->t & ~VT_TYPE);
6805 type = &type1;
6806 c += f->c;
6809 decl_initializer(type, sec, c, 0, size_only);
6812 #define EXPR_VAL 0
6813 #define EXPR_CONST 1
6814 #define EXPR_ANY 2
6816 /* store a value or an expression directly in global data or in local array */
6817 static void init_putv(CType *type, Section *sec, unsigned long c,
6818 int v, int expr_type)
6820 int saved_global_expr, bt;
6821 void *ptr;
6823 switch(expr_type) {
6824 case EXPR_VAL:
6825 vpushi(v);
6826 break;
6827 case EXPR_CONST:
6828 /* compound literals must be allocated globally in this case */
6829 saved_global_expr = global_expr;
6830 global_expr = 1;
6831 expr_const1();
6832 global_expr = saved_global_expr;
6833 /* NOTE: symbols are accepted */
6834 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
6835 error("initializer element is not constant");
6836 break;
6837 case EXPR_ANY:
6838 expr_eq();
6839 break;
6842 if (sec) {
6843 /* XXX: not portable */
6844 /* XXX: generate error if incorrect relocation */
6845 gen_assign_cast(type);
6846 bt = type->t & VT_BTYPE;
6847 ptr = sec->data + c;
6848 if ((vtop->r & VT_SYM) &&
6849 (bt == VT_BYTE ||
6850 bt == VT_SHORT ||
6851 bt == VT_DOUBLE ||
6852 bt == VT_LDOUBLE ||
6853 bt == VT_LLONG))
6854 error("initializer element is not computable at load time");
6855 switch(bt) {
6856 case VT_BYTE:
6857 *(char *)ptr = vtop->c.i;
6858 break;
6859 case VT_SHORT:
6860 *(short *)ptr = vtop->c.i;
6861 break;
6862 case VT_DOUBLE:
6863 *(double *)ptr = vtop->c.d;
6864 break;
6865 case VT_LDOUBLE:
6866 *(long double *)ptr = vtop->c.ld;
6867 break;
6868 case VT_LLONG:
6869 *(long long *)ptr = vtop->c.ll;
6870 break;
6871 default:
6872 if (vtop->r & VT_SYM) {
6873 greloc(sec, vtop->sym, c, R_DATA_32);
6875 *(int *)ptr = vtop->c.i;
6876 break;
6878 vtop--;
6879 } else {
6880 vset(type, VT_LOCAL, c);
6881 vswap();
6882 vstore();
6883 vpop();
6887 /* put zeros for variable based init */
6888 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
6890 GFuncContext gf;
6892 if (sec) {
6893 /* nothing to do because globals are already set to zero */
6894 } else {
6895 gfunc_start(&gf, FUNC_CDECL);
6896 vpushi(size);
6897 gfunc_param(&gf);
6898 vpushi(0);
6899 gfunc_param(&gf);
6900 vseti(VT_LOCAL, c);
6901 gfunc_param(&gf);
6902 vpush_global_sym(&func_old_type, TOK_memset);
6903 gfunc_call(&gf);
6907 /* 't' contains the type and storage info. 'c' is the offset of the
6908 object in section 'sec'. If 'sec' is NULL, it means stack based
6909 allocation. 'first' is true if array '{' must be read (multi
6910 dimension implicit array init handling). 'size_only' is true if
6911 size only evaluation is wanted (only for arrays). */
6912 static void decl_initializer(CType *type, Section *sec, unsigned long c,
6913 int first, int size_only)
6915 int index, array_length, n, no_oblock, nb, parlevel, i;
6916 int size1, align1, expr_type;
6917 Sym *s, *f;
6918 CType *t1;
6920 if (type->t & VT_ARRAY) {
6921 s = type->ref;
6922 n = s->c;
6923 array_length = 0;
6924 t1 = pointed_type(type);
6925 size1 = type_size(t1, &align1);
6927 no_oblock = 1;
6928 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
6929 tok == '{') {
6930 skip('{');
6931 no_oblock = 0;
6934 /* only parse strings here if correct type (otherwise: handle
6935 them as ((w)char *) expressions */
6936 if ((tok == TOK_LSTR &&
6937 (t1->t & VT_BTYPE) == VT_INT) ||
6938 (tok == TOK_STR &&
6939 (t1->t & VT_BTYPE) == VT_BYTE)) {
6940 while (tok == TOK_STR || tok == TOK_LSTR) {
6941 int cstr_len, ch;
6942 CString *cstr;
6944 cstr = tokc.cstr;
6945 /* compute maximum number of chars wanted */
6946 if (tok == TOK_STR)
6947 cstr_len = cstr->size;
6948 else
6949 cstr_len = cstr->size / sizeof(int);
6950 cstr_len--;
6951 nb = cstr_len;
6952 if (n >= 0 && nb > (n - array_length))
6953 nb = n - array_length;
6954 if (!size_only) {
6955 if (cstr_len > nb)
6956 warning("initializer-string for array is too long");
6957 /* in order to go faster for common case (char
6958 string in global variable, we handle it
6959 specifically */
6960 if (sec && tok == TOK_STR && size1 == 1) {
6961 memcpy(sec->data + c + array_length, cstr->data, nb);
6962 } else {
6963 for(i=0;i<nb;i++) {
6964 if (tok == TOK_STR)
6965 ch = ((unsigned char *)cstr->data)[i];
6966 else
6967 ch = ((int *)cstr->data)[i];
6968 init_putv(t1, sec, c + (array_length + i) * size1,
6969 ch, EXPR_VAL);
6973 array_length += nb;
6974 next();
6976 /* only add trailing zero if enough storage (no
6977 warning in this case since it is standard) */
6978 if (n < 0 || array_length < n) {
6979 if (!size_only) {
6980 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
6982 array_length++;
6984 } else {
6985 index = 0;
6986 while (tok != '}') {
6987 decl_designator(type, sec, c, &index, NULL, size_only);
6988 if (n >= 0 && index >= n)
6989 error("index too large");
6990 /* must put zero in holes (note that doing it that way
6991 ensures that it even works with designators) */
6992 if (!size_only && array_length < index) {
6993 init_putz(t1, sec, c + array_length * size1,
6994 (index - array_length) * size1);
6996 index++;
6997 if (index > array_length)
6998 array_length = index;
6999 /* special test for multi dimensional arrays (may not
7000 be strictly correct if designators are used at the
7001 same time) */
7002 if (index >= n && no_oblock)
7003 break;
7004 if (tok == '}')
7005 break;
7006 skip(',');
7009 if (!no_oblock)
7010 skip('}');
7011 /* put zeros at the end */
7012 if (!size_only && n >= 0 && array_length < n) {
7013 init_putz(t1, sec, c + array_length * size1,
7014 (n - array_length) * size1);
7016 /* patch type size if needed */
7017 if (n < 0)
7018 s->c = array_length;
7019 } else if ((type->t & VT_BTYPE) == VT_STRUCT && tok == '{') {
7020 /* XXX: union needs only one init */
7021 next();
7022 s = type->ref;
7023 f = s->next;
7024 array_length = 0;
7025 index = 0;
7026 n = s->c;
7027 while (tok != '}') {
7028 decl_designator(type, sec, c, NULL, &f, size_only);
7029 /* fill with zero between fields */
7030 index = f->c;
7031 if (!size_only && array_length < index) {
7032 init_putz(type, sec, c + array_length,
7033 index - array_length);
7035 index = index + type_size(&f->type, &align1);
7036 if (index > array_length)
7037 array_length = index;
7038 if (tok == '}')
7039 break;
7040 skip(',');
7041 f = f->next;
7043 /* put zeros at the end */
7044 if (!size_only && array_length < n) {
7045 init_putz(type, sec, c + array_length,
7046 n - array_length);
7048 skip('}');
7049 } else if (tok == '{') {
7050 next();
7051 decl_initializer(type, sec, c, first, size_only);
7052 skip('}');
7053 } else if (size_only) {
7054 /* just skip expression */
7055 parlevel = 0;
7056 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7057 tok != -1) {
7058 if (tok == '(')
7059 parlevel++;
7060 else if (tok == ')')
7061 parlevel--;
7062 next();
7064 } else {
7065 /* currently, we always use constant expression for globals
7066 (may change for scripting case) */
7067 expr_type = EXPR_CONST;
7068 if (!sec)
7069 expr_type = EXPR_ANY;
7070 init_putv(type, sec, c, 0, expr_type);
7074 /* parse an initializer for type 't' if 'has_init' is non zero, and
7075 allocate space in local or global data space ('r' is either
7076 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7077 variable 'v' of scope 'scope' is declared before initializers are
7078 parsed. If 'v' is zero, then a reference to the new object is put
7079 in the value stack. If 'has_init' is 2, a special parsing is done
7080 to handle string constants. */
7081 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
7082 int has_init, int v, int scope)
7084 int size, align, addr, data_offset;
7085 int level;
7086 ParseState saved_parse_state;
7087 TokenString init_str;
7088 Section *sec;
7090 size = type_size(type, &align);
7091 /* If unknown size, we must evaluate it before
7092 evaluating initializers because
7093 initializers can generate global data too
7094 (e.g. string pointers or ISOC99 compound
7095 literals). It also simplifies local
7096 initializers handling */
7097 tok_str_new(&init_str);
7098 if (size < 0) {
7099 if (!has_init)
7100 error("unknown type size");
7101 /* get all init string */
7102 if (has_init == 2) {
7103 /* only get strings */
7104 while (tok == TOK_STR || tok == TOK_LSTR) {
7105 tok_str_add_tok(&init_str);
7106 next();
7108 } else {
7109 level = 0;
7110 while (level > 0 || (tok != ',' && tok != ';')) {
7111 if (tok < 0)
7112 error("unexpected end of file in initializer");
7113 tok_str_add_tok(&init_str);
7114 if (tok == '{')
7115 level++;
7116 else if (tok == '}') {
7117 if (level == 0)
7118 break;
7119 level--;
7121 next();
7124 tok_str_add(&init_str, -1);
7125 tok_str_add(&init_str, 0);
7127 /* compute size */
7128 save_parse_state(&saved_parse_state);
7130 macro_ptr = init_str.str;
7131 next();
7132 decl_initializer(type, NULL, 0, 1, 1);
7133 /* prepare second initializer parsing */
7134 macro_ptr = init_str.str;
7135 next();
7137 /* if still unknown size, error */
7138 size = type_size(type, &align);
7139 if (size < 0)
7140 error("unknown type size");
7142 /* take into account specified alignment if bigger */
7143 if (ad->aligned > align)
7144 align = ad->aligned;
7145 if ((r & VT_VALMASK) == VT_LOCAL) {
7146 sec = NULL;
7147 if (do_bounds_check && (type->t & VT_ARRAY))
7148 loc--;
7149 #ifdef TCC_TARGET_IL
7150 /* XXX: ugly patch to allocate local variables for IL, just
7151 for testing */
7152 addr = loc;
7153 loc++;
7154 #else
7155 loc = (loc - size) & -align;
7156 addr = loc;
7157 #endif
7158 /* handles bounds */
7159 /* XXX: currently, since we do only one pass, we cannot track
7160 '&' operators, so we add only arrays */
7161 if (do_bounds_check && (type->t & VT_ARRAY)) {
7162 unsigned long *bounds_ptr;
7163 /* add padding between regions */
7164 loc--;
7165 /* then add local bound info */
7166 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
7167 bounds_ptr[0] = addr;
7168 bounds_ptr[1] = size;
7170 } else {
7171 /* compute section */
7172 sec = ad->section;
7173 if (!sec) {
7174 if (has_init)
7175 sec = data_section;
7176 else
7177 sec = bss_section;
7179 data_offset = sec->data_offset;
7180 data_offset = (data_offset + align - 1) & -align;
7181 addr = data_offset;
7182 /* very important to increment global pointer at this time
7183 because initializers themselves can create new initializers */
7184 data_offset += size;
7185 /* add padding if bound check */
7186 if (do_bounds_check)
7187 data_offset++;
7188 sec->data_offset = data_offset;
7189 /* allocate section space to put the data */
7190 if (sec->sh_type != SHT_NOBITS &&
7191 data_offset > sec->data_allocated)
7192 section_realloc(sec, data_offset);
7194 if (!sec) {
7195 if (v) {
7196 /* local variable */
7197 sym_push(v, type, r, addr);
7198 } else {
7199 /* push local reference */
7200 vset(type, r, addr);
7202 } else {
7203 Sym *sym;
7205 if (v) {
7206 if (scope == VT_CONST) {
7207 /* global scope: see if already defined */
7208 sym = sym_find(v);
7209 if (!sym)
7210 goto do_def;
7211 if (!is_compatible_types(&sym->type, type))
7212 error("incompatible types for redefinition of '%s'",
7213 get_tok_str(v, NULL));
7214 if (!(sym->type.t & VT_EXTERN))
7215 error("redefinition of '%s'", get_tok_str(v, NULL));
7216 sym->type.t &= ~VT_EXTERN;
7217 } else {
7218 do_def:
7219 sym = sym_push(v, type, r | VT_SYM, 0);
7221 put_extern_sym(sym, sec, addr, size);
7222 } else {
7223 CValue cval;
7225 /* push global reference */
7226 sym = get_sym_ref(type, sec, addr, size);
7227 cval.ul = 0;
7228 vsetc(type, VT_CONST | VT_SYM, &cval);
7229 vtop->sym = sym;
7232 /* handles bounds now because the symbol must be defined
7233 before for the relocation */
7234 if (do_bounds_check) {
7235 unsigned long *bounds_ptr;
7237 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
7238 /* then add global bound info */
7239 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
7240 bounds_ptr[0] = 0; /* relocated */
7241 bounds_ptr[1] = size;
7244 if (has_init) {
7245 decl_initializer(type, sec, addr, 1, 0);
7246 /* restore parse state if needed */
7247 if (init_str.str) {
7248 tok_str_free(init_str.str);
7249 restore_parse_state(&saved_parse_state);
7254 void put_func_debug(Sym *sym)
7256 char buf[512];
7258 /* stabs info */
7259 /* XXX: we put here a dummy type */
7260 snprintf(buf, sizeof(buf), "%s:%c1",
7261 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
7262 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
7263 cur_text_section, sym->c);
7264 last_ind = 0;
7265 last_line_num = 0;
7268 /* not finished : try to put some local vars in registers */
7269 //#define CONFIG_REG_VARS
7271 #ifdef CONFIG_REG_VARS
7272 void add_var_ref(int t)
7274 printf("%s:%d: &%s\n",
7275 file->filename, file->line_num,
7276 get_tok_str(t, NULL));
7279 /* first pass on a function with heuristic to extract variable usage
7280 and pointer references to local variables for register allocation */
7281 void analyse_function(void)
7283 int level, t;
7285 for(;;) {
7286 if (tok == -1)
7287 break;
7288 /* any symbol coming after '&' is considered as being a
7289 variable whose reference is taken. It is highly unaccurate
7290 but it is difficult to do better without a complete parse */
7291 if (tok == '&') {
7292 next();
7293 /* if '& number', then no need to examine next tokens */
7294 if (tok == TOK_CINT ||
7295 tok == TOK_CUINT ||
7296 tok == TOK_CLLONG ||
7297 tok == TOK_CULLONG) {
7298 continue;
7299 } else if (tok >= TOK_UIDENT) {
7300 /* if '& ident [' or '& ident ->', then ident address
7301 is not needed */
7302 t = tok;
7303 next();
7304 if (tok != '[' && tok != TOK_ARROW)
7305 add_var_ref(t);
7306 } else {
7307 level = 0;
7308 while (tok != '}' && tok != ';' &&
7309 !((tok == ',' || tok == ')') && level == 0)) {
7310 if (tok >= TOK_UIDENT) {
7311 add_var_ref(tok);
7312 } else if (tok == '(') {
7313 level++;
7314 } else if (tok == ')') {
7315 level--;
7317 next();
7320 } else {
7321 next();
7325 #endif
7327 /* parse an old style function declaration list */
7328 /* XXX: check multiple parameter */
7329 static void func_decl_list(Sym *func_sym)
7331 AttributeDef ad;
7332 int v;
7333 Sym *s;
7334 CType btype, type;
7336 /* parse each declaration */
7337 while (tok != '{' && tok != ';' && tok != TOK_EOF) {
7338 if (!parse_btype(&btype, &ad))
7339 expect("declaration list");
7340 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7341 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7342 tok == ';') {
7343 /* we accept no variable after */
7344 } else {
7345 for(;;) {
7346 type = btype;
7347 type_decl(&type, &ad, &v, TYPE_DIRECT);
7348 /* find parameter in function parameter list */
7349 s = func_sym->next;
7350 while (s != NULL) {
7351 if ((s->v & ~SYM_FIELD) == v)
7352 goto found;
7353 s = s->next;
7355 error("declaration for parameter '%s' but no such parameter",
7356 get_tok_str(v, NULL));
7357 found:
7358 /* check that no storage specifier except 'register' was given */
7359 if (type.t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
7360 error("storage class specified for '%s'", get_tok_str(v, NULL));
7361 /* we can add the type (NOTE: it could be local to the function) */
7362 s->type = type;
7363 /* accept other parameters */
7364 if (tok == ',')
7365 next();
7366 else
7367 break;
7370 skip(';');
7374 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
7375 static void decl(int l)
7377 int v, has_init, r;
7378 CType type, btype;
7379 Sym *sym;
7380 AttributeDef ad;
7382 while (1) {
7383 if (!parse_btype(&btype, &ad)) {
7384 /* skip redundant ';' */
7385 /* XXX: find more elegant solution */
7386 if (tok == ';') {
7387 next();
7388 continue;
7390 /* special test for old K&R protos without explicit int
7391 type. Only accepted when defining global data */
7392 if (l == VT_LOCAL || tok < TOK_DEFINE)
7393 break;
7394 btype.t = VT_INT;
7396 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7397 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7398 tok == ';') {
7399 /* we accept no variable after */
7400 next();
7401 continue;
7403 while (1) { /* iterate thru each declaration */
7404 type = btype;
7405 type_decl(&type, &ad, &v, TYPE_DIRECT);
7406 #if 0
7408 char buf[500];
7409 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
7410 printf("type = '%s'\n", buf);
7412 #endif
7413 if ((type.t & VT_BTYPE) == VT_FUNC) {
7414 /* if old style function prototype, we accept a
7415 declaration list */
7416 sym = type.ref;
7417 if (sym->c == FUNC_OLD)
7418 func_decl_list(sym);
7421 if (tok == '{') {
7422 #ifdef CONFIG_REG_VARS
7423 TokenString func_str;
7424 ParseState saved_parse_state;
7425 int block_level;
7426 #endif
7428 if (l == VT_LOCAL)
7429 error("cannot use local functions");
7430 if (!(type.t & VT_FUNC))
7431 expect("function definition");
7433 #ifdef CONFIG_REG_VARS
7434 /* parse all function code and record it */
7436 tok_str_new(&func_str);
7438 block_level = 0;
7439 for(;;) {
7440 int t;
7441 if (tok == -1)
7442 error("unexpected end of file");
7443 tok_str_add_tok(&func_str);
7444 t = tok;
7445 next();
7446 if (t == '{') {
7447 block_level++;
7448 } else if (t == '}') {
7449 block_level--;
7450 if (block_level == 0)
7451 break;
7454 tok_str_add(&func_str, -1);
7455 tok_str_add(&func_str, 0);
7457 save_parse_state(&saved_parse_state);
7459 macro_ptr = func_str.str;
7460 next();
7461 analyse_function();
7462 #endif
7464 /* compute text section */
7465 cur_text_section = ad.section;
7466 if (!cur_text_section)
7467 cur_text_section = text_section;
7468 ind = cur_text_section->data_offset;
7469 funcname = get_tok_str(v, NULL);
7470 sym = sym_find(v);
7471 if (sym) {
7472 /* if symbol is already defined, then put complete type */
7473 sym->type = type;
7474 } else {
7475 /* put function symbol */
7476 sym = global_identifier_push(v, type.t, 0);
7477 sym->type.ref = type.ref;
7479 /* NOTE: we patch the symbol size later */
7480 put_extern_sym(sym, cur_text_section, ind, 0);
7481 func_ind = ind;
7482 sym->r = VT_SYM | VT_CONST;
7483 /* put debug symbol */
7484 if (do_debug)
7485 put_func_debug(sym);
7486 /* push a dummy symbol to enable local sym storage */
7487 sym_push2(&local_stack, SYM_FIELD, 0, 0);
7488 gfunc_prolog(&type);
7489 loc = 0;
7490 rsym = 0;
7491 #ifdef CONFIG_REG_VARS
7492 macro_ptr = func_str.str;
7493 next();
7494 #endif
7495 block(NULL, NULL, NULL, NULL, 0);
7496 gsym(rsym);
7497 gfunc_epilog();
7498 cur_text_section->data_offset = ind;
7499 /* look if any labels are undefined. Define symbols if
7500 '&&label' was used. */
7502 Sym *s, *s1;
7503 for(s = label_stack; s != NULL; s = s1) {
7504 s1 = s->prev;
7505 if (s->r & LABEL_FORWARD) {
7506 error("label '%s' used but not defined",
7507 get_tok_str(s->v, NULL));
7509 if (s->c) {
7510 /* define corresponding symbol. A size of
7511 1 is put. */
7512 put_extern_sym(s, cur_text_section, (long)s->next, 1);
7514 /* remove label */
7515 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
7516 tcc_free(s);
7518 label_stack = NULL;
7520 sym_pop(&local_stack, NULL); /* reset local stack */
7521 /* end of function */
7522 /* patch symbol size */
7523 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
7524 ind - func_ind;
7525 if (do_debug) {
7526 put_stabn(N_FUN, 0, 0, ind - func_ind);
7528 funcname = ""; /* for safety */
7529 func_vt.t = VT_VOID; /* for safety */
7530 ind = 0; /* for safety */
7532 #ifdef CONFIG_REG_VARS
7533 tok_str_free(func_str.str);
7534 restore_parse_state(&saved_parse_state);
7535 #endif
7536 break;
7537 } else {
7538 if (btype.t & VT_TYPEDEF) {
7539 /* save typedefed type */
7540 /* XXX: test storage specifiers ? */
7541 sym = sym_push(v, &type, 0, 0);
7542 sym->type.t |= VT_TYPEDEF;
7543 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
7544 /* external function definition */
7545 external_sym(v, &type, 0);
7546 } else {
7547 /* not lvalue if array */
7548 r = 0;
7549 if (!(type.t & VT_ARRAY))
7550 r |= lvalue_type(type.t);
7551 if (btype.t & VT_EXTERN) {
7552 /* external variable */
7553 external_sym(v, &type, r);
7554 } else {
7555 if (type.t & VT_STATIC)
7556 r |= VT_CONST;
7557 else
7558 r |= l;
7559 has_init = (tok == '=');
7560 if (has_init)
7561 next();
7562 decl_initializer_alloc(&type, &ad, r,
7563 has_init, v, l);
7566 if (tok != ',') {
7567 skip(';');
7568 break;
7570 next();
7576 /* compile the C file opened in 'file'. Return non zero if errors. */
7577 static int tcc_compile(TCCState *s1)
7579 Sym *define_start;
7580 char buf[512];
7581 volatile int section_sym;
7583 #ifdef INC_DEBUG
7584 printf("%s: **** new file\n", file->filename);
7585 #endif
7586 funcname = "";
7587 s1->include_stack_ptr = s1->include_stack;
7588 /* XXX: move that before to avoid having to initialize
7589 file->ifdef_stack_ptr ? */
7590 s1->ifdef_stack_ptr = s1->ifdef_stack;
7591 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7593 /* XXX: not ANSI compliant: bound checking says error */
7594 vtop = vstack - 1;
7595 anon_sym = SYM_FIRST_ANOM;
7597 /* file info: full path + filename */
7598 section_sym = 0; /* avoid warning */
7599 if (do_debug) {
7600 section_sym = put_elf_sym(symtab_section, 0, 0,
7601 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
7602 text_section->sh_num, NULL);
7603 getcwd(buf, sizeof(buf));
7604 pstrcat(buf, sizeof(buf), "/");
7605 put_stabs_r(buf, N_SO, 0, 0,
7606 text_section->data_offset, text_section, section_sym);
7607 put_stabs_r(file->filename, N_SO, 0, 0,
7608 text_section->data_offset, text_section, section_sym);
7610 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
7611 symbols can be safely used */
7612 put_elf_sym(symtab_section, 0, 0,
7613 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
7614 SHN_ABS, file->filename);
7616 /* define some often used types */
7617 int_type.t = VT_INT;
7619 char_pointer_type.t = VT_BYTE;
7620 mk_pointer(&char_pointer_type);
7622 func_old_type.t = VT_FUNC;
7623 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
7625 #if 0
7626 /* define 'void *alloca(unsigned int)' builtin function */
7628 Sym *s1;
7630 p = anon_sym++;
7631 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
7632 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
7633 s1->next = NULL;
7634 sym->next = s1;
7635 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
7637 #endif
7639 define_start = define_stack;
7641 if (setjmp(s1->error_jmp_buf) == 0) {
7642 s1->nb_errors = 0;
7643 s1->error_set_jmp_enabled = 1;
7645 ch = '\n'; /* needed to parse correctly first preprocessor command */
7646 next();
7647 decl(VT_CONST);
7648 if (tok != -1)
7649 expect("declaration");
7651 /* end of translation unit info */
7652 if (do_debug) {
7653 put_stabs_r(NULL, N_SO, 0, 0,
7654 text_section->data_offset, text_section, section_sym);
7657 s1->error_set_jmp_enabled = 0;
7659 /* reset define stack, but leave -Dsymbols (may be incorrect if
7660 they are undefined) */
7661 free_defines(define_start);
7663 sym_pop(&global_stack, NULL);
7665 return s1->nb_errors != 0 ? -1 : 0;
7668 #ifdef LIBTCC
7669 int tcc_compile_string(TCCState *s, const char *str)
7671 BufferedFile bf1, *bf = &bf1;
7672 int ret, len;
7673 char *buf;
7675 /* init file structure */
7676 bf->fd = -1;
7677 /* XXX: avoid copying */
7678 len = strlen(str);
7679 buf = tcc_malloc(len + 1);
7680 if (!buf)
7681 return -1;
7682 buf[len] = CH_EOB;
7683 bf->buf_ptr = buf;
7684 bf->buf_end = buf + len;
7685 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
7686 bf->line_num = 1;
7687 file = bf;
7689 ret = tcc_compile(s);
7691 tcc_free(buf);
7693 /* currently, no need to close */
7694 return ret;
7696 #endif
7698 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
7699 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
7701 BufferedFile bf1, *bf = &bf1;
7703 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
7704 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
7705 /* default value */
7706 if (!value)
7707 value = "1";
7708 pstrcat(bf->buffer, IO_BUF_SIZE, value);
7710 /* init file structure */
7711 bf->fd = -1;
7712 bf->buf_ptr = bf->buffer;
7713 bf->buf_end = bf->buffer + strlen(bf->buffer);
7714 *bf->buf_end = CH_EOB;
7715 bf->filename[0] = '\0';
7716 bf->line_num = 1;
7717 file = bf;
7719 s1->include_stack_ptr = s1->include_stack;
7721 /* parse with define parser */
7722 ch = '\n'; /* needed to parse correctly first preprocessor command */
7723 next_nomacro();
7724 parse_define();
7725 file = NULL;
7728 /* undefine a preprocessor symbol */
7729 void tcc_undefine_symbol(TCCState *s1, const char *sym)
7731 TokenSym *ts;
7732 Sym *s;
7733 ts = tok_alloc(sym, strlen(sym));
7734 s = define_find(ts->tok);
7735 /* undefine symbol by putting an invalid name */
7736 if (s)
7737 define_undef(s);
7740 #include "tccelf.c"
7742 /* print the position in the source file of PC value 'pc' by reading
7743 the stabs debug information */
7744 static void rt_printline(unsigned long wanted_pc)
7746 Stab_Sym *sym, *sym_end;
7747 char func_name[128], last_func_name[128];
7748 unsigned long func_addr, last_pc, pc;
7749 const char *incl_files[INCLUDE_STACK_SIZE];
7750 int incl_index, len, last_line_num, i;
7751 const char *str, *p;
7753 fprintf(stderr, "0x%08lx:", wanted_pc);
7755 func_name[0] = '\0';
7756 func_addr = 0;
7757 incl_index = 0;
7758 last_func_name[0] = '\0';
7759 last_pc = 0xffffffff;
7760 last_line_num = 1;
7761 sym = (Stab_Sym *)stab_section->data + 1;
7762 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
7763 while (sym < sym_end) {
7764 switch(sym->n_type) {
7765 /* function start or end */
7766 case N_FUN:
7767 if (sym->n_strx == 0) {
7768 /* we test if between last line and end of function */
7769 pc = sym->n_value + func_addr;
7770 if (wanted_pc >= last_pc && wanted_pc < pc)
7771 goto found;
7772 func_name[0] = '\0';
7773 func_addr = 0;
7774 } else {
7775 str = stabstr_section->data + sym->n_strx;
7776 p = strchr(str, ':');
7777 if (!p) {
7778 pstrcpy(func_name, sizeof(func_name), str);
7779 } else {
7780 len = p - str;
7781 if (len > sizeof(func_name) - 1)
7782 len = sizeof(func_name) - 1;
7783 memcpy(func_name, str, len);
7784 func_name[len] = '\0';
7786 func_addr = sym->n_value;
7788 break;
7789 /* line number info */
7790 case N_SLINE:
7791 pc = sym->n_value + func_addr;
7792 if (wanted_pc >= last_pc && wanted_pc < pc)
7793 goto found;
7794 last_pc = pc;
7795 last_line_num = sym->n_desc;
7796 /* XXX: slow! */
7797 strcpy(last_func_name, func_name);
7798 break;
7799 /* include files */
7800 case N_BINCL:
7801 str = stabstr_section->data + sym->n_strx;
7802 add_incl:
7803 if (incl_index < INCLUDE_STACK_SIZE) {
7804 incl_files[incl_index++] = str;
7806 break;
7807 case N_EINCL:
7808 if (incl_index > 1)
7809 incl_index--;
7810 break;
7811 case N_SO:
7812 if (sym->n_strx == 0) {
7813 incl_index = 0; /* end of translation unit */
7814 } else {
7815 str = stabstr_section->data + sym->n_strx;
7816 /* do not add path */
7817 len = strlen(str);
7818 if (len > 0 && str[len - 1] != '/')
7819 goto add_incl;
7821 break;
7823 sym++;
7826 /* second pass: we try symtab symbols (no line number info) */
7827 incl_index = 0;
7829 Elf32_Sym *sym, *sym_end;
7830 int type;
7832 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
7833 for(sym = (Elf32_Sym *)symtab_section->data + 1;
7834 sym < sym_end;
7835 sym++) {
7836 type = ELF32_ST_TYPE(sym->st_info);
7837 if (type == STT_FUNC) {
7838 if (wanted_pc >= sym->st_value &&
7839 wanted_pc < sym->st_value + sym->st_size) {
7840 pstrcpy(last_func_name, sizeof(last_func_name),
7841 strtab_section->data + sym->st_name);
7842 goto found;
7847 /* did not find any info: */
7848 fprintf(stderr, " ???\n");
7849 return;
7850 found:
7851 if (last_func_name[0] != '\0') {
7852 fprintf(stderr, " %s()", last_func_name);
7854 if (incl_index > 0) {
7855 fprintf(stderr, " (%s:%d",
7856 incl_files[incl_index - 1], last_line_num);
7857 for(i = incl_index - 2; i >= 0; i--)
7858 fprintf(stderr, ", included from %s", incl_files[i]);
7859 fprintf(stderr, ")");
7861 fprintf(stderr, "\n");
7864 #ifndef WIN32
7866 #ifdef __i386__
7868 #ifndef EIP
7869 #define EIP 14
7870 #define EBP 6
7871 #endif
7873 /* return the PC at frame level 'level'. Return non zero if not found */
7874 static int rt_get_caller_pc(unsigned long *paddr,
7875 struct ucontext *uc, int level)
7877 unsigned long fp;
7878 int i;
7880 if (level == 0) {
7881 *paddr = uc->uc_mcontext.gregs[EIP];
7882 return 0;
7883 } else {
7884 fp = uc->uc_mcontext.gregs[EBP];
7885 for(i=1;i<level;i++) {
7886 /* XXX: check address validity with program info */
7887 if (fp <= 0x1000 || fp >= 0xc0000000)
7888 return -1;
7889 fp = ((unsigned long *)fp)[0];
7891 *paddr = ((unsigned long *)fp)[1];
7892 return 0;
7895 #else
7896 #error add arch specific rt_get_caller_pc()
7897 #endif
7899 /* emit a run time error at position 'pc' */
7900 void rt_error(struct ucontext *uc, const char *fmt, ...)
7902 va_list ap;
7903 unsigned long pc;
7904 int i;
7906 va_start(ap, fmt);
7907 fprintf(stderr, "Runtime error: ");
7908 vfprintf(stderr, fmt, ap);
7909 fprintf(stderr, "\n");
7910 for(i=0;i<num_callers;i++) {
7911 if (rt_get_caller_pc(&pc, uc, i) < 0)
7912 break;
7913 if (i == 0)
7914 fprintf(stderr, "at ");
7915 else
7916 fprintf(stderr, "by ");
7917 rt_printline(pc);
7919 exit(255);
7920 va_end(ap);
7923 /* signal handler for fatal errors */
7924 static void sig_error(int signum, siginfo_t *siginf, void *puc)
7926 struct ucontext *uc = puc;
7928 switch(signum) {
7929 case SIGFPE:
7930 switch(siginf->si_code) {
7931 case FPE_INTDIV:
7932 case FPE_FLTDIV:
7933 rt_error(uc, "division by zero");
7934 break;
7935 default:
7936 rt_error(uc, "floating point exception");
7937 break;
7939 break;
7940 case SIGBUS:
7941 case SIGSEGV:
7942 if (rt_bound_error_msg && *rt_bound_error_msg)
7943 rt_error(uc, *rt_bound_error_msg);
7944 else
7945 rt_error(uc, "dereferencing invalid pointer");
7946 break;
7947 case SIGILL:
7948 rt_error(uc, "illegal instruction");
7949 break;
7950 case SIGABRT:
7951 rt_error(uc, "abort() called");
7952 break;
7953 default:
7954 rt_error(uc, "caught signal %d", signum);
7955 break;
7957 exit(255);
7959 #endif
7961 /* do all relocations (needed before using tcc_get_symbol()) */
7962 int tcc_relocate(TCCState *s1)
7964 Section *s;
7965 int i;
7967 s1->nb_errors = 0;
7969 tcc_add_runtime(s1);
7971 relocate_common_syms();
7973 /* compute relocation address : section are relocated in place. We
7974 also alloc the bss space */
7975 for(i = 1; i < s1->nb_sections; i++) {
7976 s = s1->sections[i];
7977 if (s->sh_flags & SHF_ALLOC) {
7978 if (s->sh_type == SHT_NOBITS)
7979 s->data = tcc_mallocz(s->data_offset);
7980 s->sh_addr = (unsigned long)s->data;
7984 relocate_syms(s1, 1);
7986 if (s1->nb_errors != 0)
7987 return -1;
7989 /* relocate each section */
7990 for(i = 1; i < s1->nb_sections; i++) {
7991 s = s1->sections[i];
7992 if (s->reloc)
7993 relocate_section(s1, s);
7995 return 0;
7998 /* launch the compiled program with the given arguments */
7999 int tcc_run(TCCState *s1, int argc, char **argv)
8001 int (*prog_main)(int, char **);
8003 if (tcc_relocate(s1) < 0)
8004 return -1;
8006 prog_main = tcc_get_symbol(s1, "main");
8008 if (do_debug) {
8009 #ifdef WIN32
8010 error("debug mode currently not available for Windows");
8011 #else
8012 struct sigaction sigact;
8013 /* install TCC signal handlers to print debug info on fatal
8014 runtime errors */
8015 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
8016 sigact.sa_sigaction = sig_error;
8017 sigemptyset(&sigact.sa_mask);
8018 sigaction(SIGFPE, &sigact, NULL);
8019 sigaction(SIGILL, &sigact, NULL);
8020 sigaction(SIGSEGV, &sigact, NULL);
8021 sigaction(SIGBUS, &sigact, NULL);
8022 sigaction(SIGABRT, &sigact, NULL);
8023 #endif
8026 #ifdef CONFIG_TCC_BCHECK
8027 if (do_bounds_check) {
8028 void (*bound_init)(void);
8030 /* set error function */
8031 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8033 /* XXX: use .init section so that it also work in binary ? */
8034 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8035 bound_init();
8037 #endif
8038 return (*prog_main)(argc, argv);
8041 TCCState *tcc_new(void)
8043 const char *p, *r;
8044 TCCState *s;
8046 s = tcc_mallocz(sizeof(TCCState));
8047 if (!s)
8048 return NULL;
8049 tcc_state = s;
8050 s->output_type = TCC_OUTPUT_MEMORY;
8052 /* default include paths */
8053 tcc_add_sysinclude_path(s, "/usr/local/include");
8054 tcc_add_sysinclude_path(s, "/usr/include");
8055 tcc_add_sysinclude_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
8057 /* add all tokens */
8058 table_ident = NULL;
8059 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
8061 tok_ident = TOK_IDENT;
8062 p = tcc_keywords;
8063 while (*p) {
8064 r = p;
8065 while (*r++);
8066 tok_alloc(p, r - p - 1);
8067 p = r;
8070 /* we add dummy defines for some special macros to speed up tests
8071 and to have working defined() */
8072 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
8073 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
8074 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
8075 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
8077 /* standard defines */
8078 tcc_define_symbol(s, "__STDC__", NULL);
8079 #if defined(TCC_TARGET_I386)
8080 tcc_define_symbol(s, "__i386__", NULL);
8081 #endif
8082 #if defined(linux)
8083 tcc_define_symbol(s, "linux", NULL);
8084 #endif
8085 /* tiny C specific defines */
8086 tcc_define_symbol(s, "__TINYC__", NULL);
8088 /* default library paths */
8089 tcc_add_library_path(s, "/usr/local/lib");
8090 tcc_add_library_path(s, "/usr/lib");
8091 tcc_add_library_path(s, "/lib");
8093 /* no section zero */
8094 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
8096 /* create standard sections */
8097 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8098 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8099 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8101 /* symbols are always generated for linking stage */
8102 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
8103 ".strtab",
8104 ".hashtab", SHF_PRIVATE);
8105 strtab_section = symtab_section->link;
8107 /* private symbol table for dynamic symbols */
8108 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
8109 ".dynstrtab",
8110 ".dynhashtab", SHF_PRIVATE);
8111 return s;
8114 void tcc_delete(TCCState *s1)
8116 int i, n;
8118 /* free -D defines */
8119 free_defines(NULL);
8121 /* free tokens */
8122 n = tok_ident - TOK_IDENT;
8123 for(i = 0; i < n; i++)
8124 tcc_free(table_ident[i]);
8125 tcc_free(table_ident);
8127 /* free all sections */
8129 free_section(symtab_section->hash);
8131 free_section(s1->dynsymtab_section->hash);
8132 free_section(s1->dynsymtab_section->link);
8133 free_section(s1->dynsymtab_section);
8135 for(i = 1; i < s1->nb_sections; i++)
8136 free_section(s1->sections[i]);
8137 tcc_free(s1->sections);
8139 /* free loaded dlls array */
8140 for(i = 0; i < s1->nb_loaded_dlls; i++)
8141 tcc_free(s1->loaded_dlls[i]);
8142 tcc_free(s1->loaded_dlls);
8144 /* library paths */
8145 for(i = 0; i < s1->nb_library_paths; i++)
8146 tcc_free(s1->library_paths[i]);
8147 tcc_free(s1->library_paths);
8149 /* cached includes */
8150 for(i = 0; i < s1->nb_cached_includes; i++)
8151 tcc_free(s1->cached_includes[i]);
8152 tcc_free(s1->cached_includes);
8154 for(i = 0; i < s1->nb_include_paths; i++)
8155 tcc_free(s1->include_paths[i]);
8156 tcc_free(s1->include_paths);
8158 for(i = 0; i < s1->nb_sysinclude_paths; i++)
8159 tcc_free(s1->sysinclude_paths[i]);
8160 tcc_free(s1->sysinclude_paths);
8162 tcc_free(s1);
8165 int tcc_add_include_path(TCCState *s1, const char *pathname)
8167 char *pathname1;
8169 pathname1 = tcc_strdup(pathname);
8170 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
8171 return 0;
8174 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
8176 char *pathname1;
8178 pathname1 = tcc_strdup(pathname);
8179 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
8180 return 0;
8183 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
8185 const char *ext;
8186 Elf32_Ehdr ehdr;
8187 int fd, ret;
8188 BufferedFile *saved_file;
8190 /* find source file type with extension */
8191 ext = strrchr(filename, '.');
8192 if (ext)
8193 ext++;
8195 /* open the file */
8196 saved_file = file;
8197 file = tcc_open(s1, filename);
8198 if (!file) {
8199 if (flags & AFF_PRINT_ERROR) {
8200 error_noabort("file '%s' not found", filename);
8202 ret = -1;
8203 goto fail1;
8206 if (!ext || !strcmp(ext, "c")) {
8207 /* C file assumed */
8208 ret = tcc_compile(s1);
8209 } else {
8210 fd = file->fd;
8211 /* assume executable format: auto guess file type */
8212 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
8213 error_noabort("could not read header");
8214 goto fail;
8216 lseek(fd, 0, SEEK_SET);
8218 if (ehdr.e_ident[0] == ELFMAG0 &&
8219 ehdr.e_ident[1] == ELFMAG1 &&
8220 ehdr.e_ident[2] == ELFMAG2 &&
8221 ehdr.e_ident[3] == ELFMAG3) {
8222 file->line_num = 0; /* do not display line number if error */
8223 if (ehdr.e_type == ET_REL) {
8224 ret = tcc_load_object_file(s1, fd, 0);
8225 } else if (ehdr.e_type == ET_DYN) {
8226 ret = tcc_load_dll(s1, fd, filename,
8227 (flags & AFF_REFERENCED_DLL) != 0);
8228 } else {
8229 error_noabort("unrecognized ELF file");
8230 goto fail;
8232 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
8233 file->line_num = 0; /* do not display line number if error */
8234 ret = tcc_load_archive(s1, fd);
8235 } else {
8236 /* as GNU ld, consider it is an ld script if not recognized */
8237 ret = tcc_load_ldscript(s1);
8238 if (ret < 0) {
8239 error_noabort("unrecognized file type");
8240 goto fail;
8244 the_end:
8245 tcc_close(file);
8246 fail1:
8247 file = saved_file;
8248 return ret;
8249 fail:
8250 ret = -1;
8251 goto the_end;
8254 int tcc_add_file(TCCState *s, const char *filename)
8256 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
8259 int tcc_add_library_path(TCCState *s, const char *pathname)
8261 char *pathname1;
8263 pathname1 = tcc_strdup(pathname);
8264 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
8265 return 0;
8268 /* find and load a dll. Return non zero if not found */
8269 /* XXX: add '-rpath' option support ? */
8270 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
8272 char buf[1024];
8273 int i;
8275 for(i = 0; i < s->nb_library_paths; i++) {
8276 snprintf(buf, sizeof(buf), "%s/%s",
8277 s->library_paths[i], filename);
8278 if (tcc_add_file_internal(s, buf, flags) == 0)
8279 return 0;
8281 return -1;
8284 /* the library name is the same as the argument of the '-l' option */
8285 int tcc_add_library(TCCState *s, const char *libraryname)
8287 char buf[1024];
8288 int i;
8289 void *h;
8291 /* first we look for the dynamic library if not static linking */
8292 if (!s->static_link) {
8293 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8294 /* if we output to memory, then we simply we dlopen(). */
8295 if (s->output_type == TCC_OUTPUT_MEMORY) {
8296 /* Since the libc is already loaded, we don't need to load it again */
8297 if (!strcmp(libraryname, "c"))
8298 return 0;
8299 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
8300 if (h)
8301 return 0;
8302 } else {
8303 if (tcc_add_dll(s, buf, 0) == 0)
8304 return 0;
8308 /* then we look for the static library */
8309 for(i = 0; i < s->nb_library_paths; i++) {
8310 snprintf(buf, sizeof(buf), "%s/lib%s.a",
8311 s->library_paths[i], libraryname);
8312 if (tcc_add_file_internal(s, buf, 0) == 0)
8313 return 0;
8315 return -1;
8318 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
8320 add_elf_sym(symtab_section, val, 0,
8321 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
8322 SHN_ABS, name);
8323 return 0;
8326 int tcc_set_output_type(TCCState *s, int output_type)
8328 s->output_type = output_type;
8330 /* if bound checking, then add corresponding sections */
8331 #ifdef CONFIG_TCC_BCHECK
8332 if (do_bounds_check) {
8333 /* define symbol */
8334 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
8335 /* create bounds sections */
8336 bounds_section = new_section(s, ".bounds",
8337 SHT_PROGBITS, SHF_ALLOC);
8338 lbounds_section = new_section(s, ".lbounds",
8339 SHT_PROGBITS, SHF_ALLOC);
8341 #endif
8343 /* add debug sections */
8344 if (do_debug) {
8345 /* stab symbols */
8346 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
8347 stab_section->sh_entsize = sizeof(Stab_Sym);
8348 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
8349 put_elf_str(stabstr_section, "");
8350 stab_section->link = stabstr_section;
8351 /* put first entry */
8352 put_stabs("", 0, 0, 0, 0);
8355 /* add libc crt1/crti objects */
8356 if (output_type == TCC_OUTPUT_EXE ||
8357 output_type == TCC_OUTPUT_DLL) {
8358 if (output_type != TCC_OUTPUT_DLL)
8359 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
8360 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
8362 return 0;
8365 #if !defined(LIBTCC)
8367 static int64_t getclock_us(void)
8369 #ifdef WIN32
8370 struct _timeb tb;
8371 _ftime(&tb);
8372 return (tb.time * 1000LL + tb.millitm) * 1000LL;
8373 #else
8374 struct timeval tv;
8375 gettimeofday(&tv, NULL);
8376 return tv.tv_sec * 1000000LL + tv.tv_usec;
8377 #endif
8380 void help(void)
8382 printf("tcc version 0.9.13 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
8383 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
8384 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
8385 " [--] infile1 [infile2... --] [infile_args...]\n"
8386 "\n"
8387 "General options:\n"
8388 " -c compile only - generate an object file\n"
8389 " -o outfile set output filename\n"
8390 " -- allows multiples input files if no -o option given. Also\n"
8391 " separate input files from runtime arguments\n"
8392 " -Bdir set tcc internal library path\n"
8393 " -bench output compilation statistics\n"
8394 "Preprocessor options:\n"
8395 " -Idir add include path 'dir'\n"
8396 " -Dsym[=val] define 'sym' with value 'val'\n"
8397 " -Usym undefine 'sym'\n"
8398 "Linker options:\n"
8399 " -Ldir add library path 'dir'\n"
8400 " -llib link with dynamic or static library 'lib'\n"
8401 " -shared generate a shared library\n"
8402 " -static static linking\n"
8403 " -r relocatable output\n"
8404 "Debugger options:\n"
8405 " -g generate runtime debug info\n"
8406 #ifdef CONFIG_TCC_BCHECK
8407 " -b compile with built-in memory and bounds checker (implies -g)\n"
8408 #endif
8409 " -bt N show N callers in stack traces\n"
8413 int main(int argc, char **argv)
8415 char *r, *outfile;
8416 int optind, output_type, multiple_files, i, reloc_output;
8417 TCCState *s;
8418 char **files;
8419 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
8420 char objfilename[1024];
8421 int64_t start_time = 0;
8423 s = tcc_new();
8424 output_type = TCC_OUTPUT_MEMORY;
8426 optind = 1;
8427 outfile = NULL;
8428 multiple_files = 0;
8429 dminus = 0;
8430 files = NULL;
8431 nb_files = 0;
8432 nb_libraries = 0;
8433 reloc_output = 0;
8434 while (1) {
8435 if (optind >= argc) {
8436 if (nb_files == 0)
8437 goto show_help;
8438 else
8439 break;
8441 r = argv[optind++];
8442 if (r[0] != '-') {
8443 /* add a new file */
8444 dynarray_add((void ***)&files, &nb_files, r);
8445 if (!multiple_files) {
8446 optind--;
8447 /* argv[0] will be this file */
8448 break;
8450 } else if (r[1] == '-') {
8451 /* '--' enables multiple files input and also ends several file input */
8452 if (dminus && multiple_files) {
8453 optind--; /* argv[0] will be '--' */
8454 break;
8456 dminus = 1;
8457 multiple_files = 1;
8458 } else if (r[1] == 'h' || r[1] == '?') {
8459 show_help:
8460 help();
8461 return 1;
8462 } else if (r[1] == 'I') {
8463 if (tcc_add_include_path(s, r + 2) < 0)
8464 error("too many include paths");
8465 } else if (r[1] == 'D') {
8466 char *sym, *value;
8467 sym = r + 2;
8468 value = strchr(sym, '=');
8469 if (value) {
8470 *value = '\0';
8471 value++;
8473 tcc_define_symbol(s, sym, value);
8474 } else if (r[1] == 'U') {
8475 tcc_undefine_symbol(s, r + 2);
8476 } else if (r[1] == 'L') {
8477 tcc_add_library_path(s, r + 2);
8478 } else if (r[1] == 'B') {
8479 /* set tcc utilities path (mainly for tcc development) */
8480 tcc_lib_path = r + 2;
8481 } else if (r[1] == 'l') {
8482 dynarray_add((void ***)&files, &nb_files, r);
8483 nb_libraries++;
8484 } else if (!strcmp(r + 1, "bench")) {
8485 do_bench = 1;
8486 } else if (!strcmp(r + 1, "bt")) {
8487 num_callers = atoi(argv[optind++]);
8488 } else
8489 #ifdef CONFIG_TCC_BCHECK
8490 if (r[1] == 'b') {
8491 do_bounds_check = 1;
8492 do_debug = 1;
8493 } else
8494 #endif
8495 if (r[1] == 'g') {
8496 do_debug = 1;
8497 } else if (r[1] == 'c') {
8498 multiple_files = 1;
8499 output_type = TCC_OUTPUT_OBJ;
8500 } else if (!strcmp(r + 1, "static")) {
8501 s->static_link = 1;
8502 } else if (!strcmp(r + 1, "shared")) {
8503 output_type = TCC_OUTPUT_DLL;
8504 } else if (r[1] == 'o') {
8505 if (optind >= argc)
8506 goto show_help;
8507 multiple_files = 1;
8508 outfile = argv[optind++];
8509 } else if (r[1] == 'r') {
8510 /* generate a .o merging several output files */
8511 reloc_output = 1;
8512 output_type = TCC_OUTPUT_OBJ;
8513 } else if (r[1] == 'W' || r[1] == 'O' || r[1] == 'm' || r[1] == 'f') {
8514 /* ignore those options to be a drop-in replacement for gcc */
8515 } else {
8516 error("invalid option -- '%s'", r);
8520 nb_objfiles = nb_files - nb_libraries;
8522 /* if outfile provided without other options, we output an
8523 executable */
8524 if (outfile && output_type == TCC_OUTPUT_MEMORY)
8525 output_type = TCC_OUTPUT_EXE;
8527 /* check -c consistency : only single file handled. XXX: checks file type */
8528 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8529 /* accepts only a single input file */
8530 if (nb_objfiles != 1)
8531 error("cannot specify multiple files with -c");
8532 if (nb_libraries != 0)
8533 error("cannot specify libraries with -c");
8536 /* compute default outfile name */
8537 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
8538 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8539 char *ext;
8540 /* add .o extension */
8541 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
8542 ext = strrchr(objfilename, '.');
8543 if (!ext)
8544 goto default_outfile;
8545 strcpy(ext + 1, "o");
8546 } else {
8547 default_outfile:
8548 pstrcpy(objfilename, sizeof(objfilename), "a.out");
8550 outfile = objfilename;
8553 if (do_bench) {
8554 start_time = getclock_us();
8557 tcc_set_output_type(s, output_type);
8559 /* compile or add each files or library */
8560 for(i = 0;i < nb_files; i++) {
8561 const char *filename;
8563 filename = files[i];
8564 if (filename[0] == '-') {
8565 if (tcc_add_library(s, filename + 2) < 0)
8566 error("cannot find %s", filename);
8567 } else {
8568 if (tcc_add_file(s, filename) < 0) {
8569 ret = 1;
8570 goto the_end;
8575 /* free all files */
8576 tcc_free(files);
8578 if (do_bench) {
8579 double total_time;
8580 total_time = (double)(getclock_us() - start_time) / 1000000.0;
8581 if (total_time < 0.001)
8582 total_time = 0.001;
8583 if (total_bytes < 1)
8584 total_bytes = 1;
8585 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
8586 tok_ident - TOK_IDENT, total_lines, total_bytes,
8587 total_time, (int)(total_lines / total_time),
8588 total_bytes / total_time / 1000000.0);
8591 if (s->output_type != TCC_OUTPUT_MEMORY) {
8592 tcc_output_file(s, outfile);
8593 ret = 0;
8594 } else {
8595 ret = tcc_run(s, argc - optind, argv + optind);
8597 the_end:
8598 /* XXX: cannot do it with bound checking because of the malloc hooks */
8599 if (!do_bounds_check)
8600 tcc_delete(s);
8602 #ifdef MEM_DEBUG
8603 if (do_bench) {
8604 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
8606 #endif
8607 return ret;
8610 #endif