1 /*
2  *  TCC - Tiny C Compiler
3  *
4  *  Copyright (c) 2001-2004 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #define _GNU_SOURCE
21 #include "config.h"
22 
23 #ifdef CONFIG_TCCBOOT
24 
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
27 
28 #else
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef _WIN32
42 #include <sys/timeb.h>
43 #include <windows.h>
44 #endif
45 #ifndef _WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
50 
51 #endif /* !CONFIG_TCCBOOT */
52 
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
56 
57 #include "elf.h"
58 #include "stab.h"
59 
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
63 
64 #include "libtcc.h"
65 
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
72 
73 //#define MEM_DEBUG
74 
75 /* assembler debug */
76 //#define ASM_DEBUG
77 
78 /* target selection */
79 //#define TCC_TARGET_I386   /* i386 code generator */
80 //#define TCC_TARGET_ARM    /* ARMv4 code generator */
81 //#define TCC_TARGET_C67    /* TMS320C67xx code generator */
82 
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85     !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
88 
89 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90     !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
93 
94 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
97 
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
102 
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
107 
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
113 
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115    executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
117 
118 #define INCLUDE_STACK_SIZE  32
119 #define IFDEF_STACK_SIZE    64
120 #define VSTACK_SIZE         256
121 #define STRING_MAX_SIZE     1024
122 #define PACK_STACK_SIZE     8
123 
124 #define TOK_HASH_SIZE       8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR      512  /* must be a power of two */
126 #define TOK_MAX_SIZE        4 /* token max size in int unit when stored in string */
127 
128 /* token symbol management */
129 typedef struct TokenSym {
130     struct TokenSym *hash_next;
131     struct Sym *sym_define; /* direct pointer to define */
132     struct Sym *sym_label; /* direct pointer to label */
133     struct Sym *sym_struct; /* direct pointer to structure */
134     struct Sym *sym_identifier; /* direct pointer to identifier */
135     int tok; /* token number */
136     int len;
137     char str[1];
138 } TokenSym;
139 
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
145 
146 typedef struct CString {
147     int size; /* size in bytes */
148     void *data; /* either 'char *' or 'nwchar_t *' */
149     int size_allocated;
150     void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
152 
153 /* type definition */
154 typedef struct CType {
155     int t;
156     struct Sym *ref;
157 } CType;
158 
159 /* constant value */
160 typedef union CValue {
161     long double ld;
162     double d;
163     float f;
164     int i;
165     unsigned int ui;
166     unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167     long long ll;
168     unsigned long long ull;
169     struct CString *cstr;
170     void *ptr;
171     int tab[1];
172 } CValue;
173 
174 /* value on stack */
175 typedef struct SValue {
176     CType type;      /* type */
177     unsigned short r;      /* register + flags */
178     unsigned short r2;     /* second register, used for 'long long'
179                               type. If not used, set to VT_CONST */
180     CValue c;              /* constant, if VT_CONST */
181     struct Sym *sym;       /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
183 
184 /* symbol management */
185 typedef struct Sym {
186     int v;    /* symbol token */
187     int r;    /* associated register */
188     int c;    /* associated number */
189     CType type;    /* associated type */
190     struct Sym *next; /* next related symbol */
191     struct Sym *prev; /* prev symbol in stack */
192     struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
194 
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198    the other ones */
199 #define SHF_PRIVATE 0x80000000
200 
201 typedef struct Section {
202     unsigned long data_offset; /* current data offset */
203     unsigned char *data;       /* section data */
204     unsigned long data_allocated; /* used for realloc() handling */
205     int sh_name;             /* elf section name (only used during output) */
206     int sh_num;              /* elf section number */
207     int sh_type;             /* elf section type */
208     int sh_flags;            /* elf section flags */
209     int sh_info;             /* elf section info */
210     int sh_addralign;        /* elf section alignment */
211     int sh_entsize;          /* elf entry size */
212     unsigned long sh_size;   /* section size (only used during output) */
213     unsigned long sh_addr;      /* address at which the section is relocated */
214     unsigned long sh_offset;    /* file offset */
215     int nb_hashed_syms;      /* used to resize the hash table */
216     struct Section *link;    /* link to another section */
217     struct Section *reloc;   /* corresponding section for relocation, if any */
218     struct Section *hash;     /* hash table for symbols */
219     struct Section *next;
220     char name[1];           /* section name */
221 } Section;
222 
223 typedef struct DLLReference {
224     int level;
225     char name[1];
226 } DLLReference;
227 
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230     int aligned;
231     int packed;
232     Section *section;
233     int func_attr; /* calling convention, exports, ... */
234 } AttributeDef;
235 
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
238 typedef struct {
239     unsigned
240       func_call : 8,
241       func_args : 8,
242       func_export : 1;
243 } func_attr_t;
244 
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
250 
251 #define SYM_STRUCT     0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD      0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
254 
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW       1 /* ansi function prototype */
257 #define FUNC_OLD       2 /* old function prototype */
258 #define FUNC_ELLIPSIS  3 /* ansi function prototype with ... */
259 
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL     0 /* standard c call */
262 #define FUNC_STDCALL   1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
267 
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ      0 /* object like macro */
270 #define MACRO_FUNC     1 /* function like macro */
271 
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED  0 /* label is defined */
274 #define LABEL_FORWARD  1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
276 
277 /* type_decl() types */
278 #define TYPE_ABSTRACT  1 /* type without variable */
279 #define TYPE_DIRECT    2 /* type with variable */
280 
281 #define IO_BUF_SIZE 8192
282 
283 typedef struct BufferedFile {
284     uint8_t *buf_ptr;
285     uint8_t *buf_end;
286     int fd;
287     int line_num;    /* current line number - here to simplify code */
288     int ifndef_macro;  /* #ifndef macro / #endif search */
289     int ifndef_macro_saved; /* saved ifndef_macro */
290     int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
291     char inc_type;          /* type of include */
292     char inc_filename[512]; /* filename specified by the user */
293     char filename[1024];    /* current filename - here to simplify code */
294     unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
295 } BufferedFile;
296 
297 #define CH_EOB   '\\'       /* end of buffer or '\0' char in file */
298 #define CH_EOF   (-1)   /* end of file */
299 
300 /* parsing state (used to save parser state to reparse part of the
301    source several times) */
302 typedef struct ParseState {
303     int *macro_ptr;
304     int line_num;
305     int tok;
306     CValue tokc;
307 } ParseState;
308 
309 /* used to record tokens */
310 typedef struct TokenString {
311     int *str;
312     int len;
313     int allocated_len;
314     int last_line_num;
315 } TokenString;
316 
317 /* include file cache, used to find files faster and also to eliminate
318    inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude {
320     int ifndef_macro;
321     int hash_next; /* -1 if none */
322     char type; /* '"' or '>' to give include type */
323     char filename[1]; /* path specified in #include */
324 } CachedInclude;
325 
326 #define CACHED_INCLUDES_HASH_SIZE 512
327 
328 /* parser */
329 static struct BufferedFile *file;
330 static int ch, tok;
331 static CValue tokc;
332 static CString tokcstr; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags;
335 #define TOK_FLAG_BOL   0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF   0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF   0x0008 /* end of file */
339 
340 static int *macro_ptr, *macro_ptr_allocated;
341 static int *unget_saved_macro_ptr;
342 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
343 static int unget_buffer_enabled;
344 static int parse_flags;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM    0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED   0x0004 /* line feed is returned as a
348                                         token. line feed is also
349                                         returned at eof */
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
351 
352 static Section *text_section, *data_section, *bss_section; /* predefined sections */
353 static Section *cur_text_section; /* current section where function code is
354                               generated */
355 #ifdef CONFIG_TCC_ASM
356 static Section *last_text_section; /* to handle .previous asm directive */
357 #endif
358 /* bound check related sections */
359 static Section *bounds_section; /* contains global data bound description */
360 static Section *lbounds_section; /* contains local data bound description */
361 /* symbol sections */
362 static Section *symtab_section, *strtab_section;
363 
364 /* debug sections */
365 static Section *stab_section, *stabstr_section;
366 
367 /* loc : local variable index
368    ind : output code index
369    rsym: return symbol
370    anon_sym: anonymous symbol index
371 */
372 static int rsym, anon_sym, ind, loc;
373 /* expression generation modifiers */
374 static int const_wanted; /* true if constant wanted */
375 static int nocode_wanted; /* true if no code generation wanted for an expression */
376 static int global_expr;  /* true if compound literals must be allocated
377                             globally (used during initializers parsing */
378 static CType func_vt; /* current function return type (used by return
379                          instruction) */
380 static int func_vc;
381 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
382 static int tok_ident;
383 static TokenSym **table_ident;
384 static TokenSym *hash_ident[TOK_HASH_SIZE];
385 static char token_buf[STRING_MAX_SIZE + 1];
386 static char *funcname;
387 static Sym *global_stack, *local_stack;
388 static Sym *define_stack;
389 static Sym *global_label_stack, *local_label_stack;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym *sym_free_first;
393 
394 static SValue vstack[VSTACK_SIZE], *vtop;
395 /* some predefined types */
396 static CType char_pointer_type, func_old_type, int_type;
397 /* true if isid(c) || isnum(c) */
398 static unsigned char isidnum_table[256];
399 
400 /* display some information during compilation */
401 static int verbose = 0;
402 
403 /* compile with debug symbol (and use them if error during execution) */
404 static int do_debug = 0;
405 
406 /* compile with built-in memory and bounds checker */
407 static int do_bounds_check = 0;
408 
409 /* display benchmark infos */
410 #if !defined(LIBTCC)
411 static int do_bench = 0;
412 #endif
413 static int total_lines;
414 static int total_bytes;
415 
416 /* use GNU C extensions */
417 static int gnu_ext = 1;
418 
419 /* use Tiny C extensions */
420 static int tcc_ext = 1;
421 
422 /* max number of callers shown if error */
423 static int num_callers = 6;
424 static const char **rt_bound_error_msg;
425 
426 /* XXX: get rid of this ASAP */
427 static struct TCCState *tcc_state;
428 
429 /* give the path of the tcc libraries */
430 //static const char *tcc_lib_path = CONFIG_TCCDIR;
431 static char tcc_lib_path[1024];
432 
433 struct TCCState {
434     int output_type;
435 
436     BufferedFile **include_stack_ptr;
437     int *ifdef_stack_ptr;
438 
439     /* include file handling */
440     char **include_paths;
441     int nb_include_paths;
442     char **sysinclude_paths;
443     int nb_sysinclude_paths;
444     CachedInclude **cached_includes;
445     int nb_cached_includes;
446 
447     char **library_paths;
448     int nb_library_paths;
449 
450     /* array of all loaded dlls (including those referenced by loaded
451        dlls) */
452     DLLReference **loaded_dlls;
453     int nb_loaded_dlls;
454 
455     /* sections */
456     Section **sections;
457     int nb_sections; /* number of sections, including first dummy section */
458 
459     /* got handling */
460     Section *got;
461     Section *plt;
462     unsigned long *got_offsets;
463     int nb_got_offsets;
464     /* give the correspondance from symtab indexes to dynsym indexes */
465     int *symtab_to_dynsym;
466 
467     /* temporary dynamic symbol sections (for dll loading) */
468     Section *dynsymtab_section;
469     /* exported dynamic symbol section */
470     Section *dynsym;
471 
472     int nostdinc; /* if true, no standard headers are added */
473     int nostdlib; /* if true, no standard libraries are added */
474 
475     int nocommon; /* if true, do not use common symbols for .bss data */
476 
477     /* if true, static linking is performed */
478     int static_link;
479 
480     /* soname as specified on the command line (-soname) */
481     const char *soname;
482 
483     /* if true, all symbols are exported */
484     int rdynamic;
485 
486     /* if true, only link in referenced objects from archive */
487     int alacarte_link;
488 
489     /* address of text section */
490     unsigned long text_addr;
491     int has_text_addr;
492 
493     /* output format, see TCC_OUTPUT_FORMAT_xxx */
494     int output_format;
495 
496     /* C language options */
497     int char_is_unsigned;
498     int leading_underscore;
499 
500     /* warning switches */
501     int warn_write_strings;
502     int warn_unsupported;
503     int warn_error;
504     int warn_none;
505     int warn_implicit_function_declaration;
506 
507     /* error handling */
508     void *error_opaque;
509     void (*error_func)(void *opaque, const char *msg);
510     int error_set_jmp_enabled;
511     jmp_buf error_jmp_buf;
512     int nb_errors;
513 
514     /* tiny assembler state */
515     Sym *asm_labels;
516 
517     /* see include_stack_ptr */
518     BufferedFile *include_stack[INCLUDE_STACK_SIZE];
519 
520     /* see ifdef_stack_ptr */
521     int ifdef_stack[IFDEF_STACK_SIZE];
522 
523     /* see cached_includes */
524     int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
525 
526     /* pack stack */
527     int pack_stack[PACK_STACK_SIZE];
528     int *pack_stack_ptr;
529 
530     /* output file for preprocessing */
531     FILE *outfile;
532 };
533 
534 /* The current value can be: */
535 #define VT_VALMASK   0x00ff
536 #define VT_CONST     0x00f0  /* constant in vc
537                               (must be first non register value) */
538 #define VT_LLOCAL    0x00f1  /* lvalue, offset on stack */
539 #define VT_LOCAL     0x00f2  /* offset on stack */
540 #define VT_CMP       0x00f3  /* the value is stored in processor flags (in vc) */
541 #define VT_JMP       0x00f4  /* value is the consequence of jmp true (even) */
542 #define VT_JMPI      0x00f5  /* value is the consequence of jmp false (odd) */
543 #define VT_LVAL      0x0100  /* var is an lvalue */
544 #define VT_SYM       0x0200  /* a symbol value is added */
545 #define VT_MUSTCAST  0x0400  /* value must be casted to be correct (used for
546                                 char/short stored in integer registers) */
547 #define VT_MUSTBOUND 0x0800  /* bound checking must be done before
548                                 dereferencing value */
549 #define VT_BOUNDED   0x8000  /* value is bounded. The address of the
550                                 bounding function call point is in vc */
551 #define VT_LVAL_BYTE     0x1000  /* lvalue is a byte */
552 #define VT_LVAL_SHORT    0x2000  /* lvalue is a short */
553 #define VT_LVAL_UNSIGNED 0x4000  /* lvalue is unsigned */
554 #define VT_LVAL_TYPE     (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
555 
556 /* types */
557 #define VT_INT        0  /* integer type */
558 #define VT_BYTE       1  /* signed byte type */
559 #define VT_SHORT      2  /* short type */
560 #define VT_VOID       3  /* void type */
561 #define VT_PTR        4  /* pointer */
562 #define VT_ENUM       5  /* enum definition */
563 #define VT_FUNC       6  /* function type */
564 #define VT_STRUCT     7  /* struct/union definition */
565 #define VT_FLOAT      8  /* IEEE float */
566 #define VT_DOUBLE     9  /* IEEE double */
567 #define VT_LDOUBLE   10  /* IEEE long double */
568 #define VT_BOOL      11  /* ISOC99 boolean type */
569 #define VT_LLONG     12  /* 64 bit integer */
570 #define VT_LONG      13  /* long integer (NEVER USED as type, only
571                             during parsing) */
572 #define VT_BTYPE      0x000f /* mask for basic type */
573 #define VT_UNSIGNED   0x0010  /* unsigned type */
574 #define VT_ARRAY      0x0020  /* array type (also has VT_PTR) */
575 #define VT_BITFIELD   0x0040  /* bitfield modifier */
576 #define VT_CONSTANT   0x0800  /* const modifier */
577 #define VT_VOLATILE   0x1000  /* volatile modifier */
578 #define VT_SIGNED     0x2000  /* signed type */
579 
580 /* storage */
581 #define VT_EXTERN  0x00000080  /* extern definition */
582 #define VT_STATIC  0x00000100  /* static variable */
583 #define VT_TYPEDEF 0x00000200  /* typedef definition */
584 #define VT_INLINE  0x00000400  /* inline definition */
585 
586 #define VT_STRUCT_SHIFT 16   /* shift for bitfield shift values */
587 
588 /* type mask (except storage) */
589 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
590 #define VT_TYPE    (~(VT_STORAGE))
591 
592 /* token values */
593 
594 /* warning: the following compare tokens depend on i386 asm code */
595 #define TOK_ULT 0x92
596 #define TOK_UGE 0x93
597 #define TOK_EQ  0x94
598 #define TOK_NE  0x95
599 #define TOK_ULE 0x96
600 #define TOK_UGT 0x97
601 #define TOK_Nset 0x98
602 #define TOK_Nclear 0x99
603 #define TOK_LT  0x9c
604 #define TOK_GE  0x9d
605 #define TOK_LE  0x9e
606 #define TOK_GT  0x9f
607 
608 #define TOK_LAND  0xa0
609 #define TOK_LOR   0xa1
610 
611 #define TOK_DEC   0xa2
612 #define TOK_MID   0xa3 /* inc/dec, to void constant */
613 #define TOK_INC   0xa4
614 #define TOK_UDIV  0xb0 /* unsigned division */
615 #define TOK_UMOD  0xb1 /* unsigned modulo */
616 #define TOK_PDIV  0xb2 /* fast division with undefined rounding for pointers */
617 #define TOK_CINT   0xb3 /* number in tokc */
618 #define TOK_CCHAR 0xb4 /* char constant in tokc */
619 #define TOK_STR   0xb5 /* pointer to string in tokc */
620 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
621 #define TOK_LCHAR    0xb7
622 #define TOK_LSTR     0xb8
623 #define TOK_CFLOAT   0xb9 /* float constant */
624 #define TOK_LINENUM  0xba /* line number info */
625 #define TOK_CDOUBLE  0xc0 /* double constant */
626 #define TOK_CLDOUBLE 0xc1 /* long double constant */
627 #define TOK_UMULL    0xc2 /* unsigned 32x32 -> 64 mul */
628 #define TOK_ADDC1    0xc3 /* add with carry generation */
629 #define TOK_ADDC2    0xc4 /* add with carry use */
630 #define TOK_SUBC1    0xc5 /* add with carry generation */
631 #define TOK_SUBC2    0xc6 /* add with carry use */
632 #define TOK_CUINT    0xc8 /* unsigned int constant */
633 #define TOK_CLLONG   0xc9 /* long long constant */
634 #define TOK_CULLONG  0xca /* unsigned long long constant */
635 #define TOK_ARROW    0xcb
636 #define TOK_DOTS     0xcc /* three dots */
637 #define TOK_SHR      0xcd /* unsigned shift right */
638 #define TOK_PPNUM    0xce /* preprocessor number */
639 
640 #define TOK_SHL   0x01 /* shift left */
641 #define TOK_SAR   0x02 /* signed shift right */
642 
643 /* assignement operators : normal operator or 0x80 */
644 #define TOK_A_MOD 0xa5
645 #define TOK_A_AND 0xa6
646 #define TOK_A_MUL 0xaa
647 #define TOK_A_ADD 0xab
648 #define TOK_A_SUB 0xad
649 #define TOK_A_DIV 0xaf
650 #define TOK_A_XOR 0xde
651 #define TOK_A_OR  0xfc
652 #define TOK_A_SHL 0x81
653 #define TOK_A_SAR 0x82
654 
655 #ifndef offsetof
656 #define offsetof(type, field) ((size_t) &((type *)0)->field)
657 #endif
658 
659 #ifndef countof
660 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
661 #endif
662 
663 /* WARNING: the content of this string encodes token numbers */
664 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";
665 
666 #define TOK_EOF       (-1)  /* end of file */
667 #define TOK_LINEFEED  10    /* line feed */
668 
669 /* all identificators and strings have token above that */
670 #define TOK_IDENT 256
671 
672 /* only used for i386 asm opcodes definitions */
673 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
674 
675 #define DEF_BWL(x) \
676  DEF(TOK_ASM_ ## x ## b, #x "b") \
677  DEF(TOK_ASM_ ## x ## w, #x "w") \
678  DEF(TOK_ASM_ ## x ## l, #x "l") \
679  DEF(TOK_ASM_ ## x, #x)
680 
681 #define DEF_WL(x) \
682  DEF(TOK_ASM_ ## x ## w, #x "w") \
683  DEF(TOK_ASM_ ## x ## l, #x "l") \
684  DEF(TOK_ASM_ ## x, #x)
685 
686 #define DEF_FP1(x) \
687  DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
688  DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
689  DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
690  DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
691 
692 #define DEF_FP(x) \
693  DEF(TOK_ASM_ ## f ## x, "f" #x ) \
694  DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
695  DEF_FP1(x)
696 
697 #define DEF_ASMTEST(x) \
698  DEF_ASM(x ## o) \
699  DEF_ASM(x ## no) \
700  DEF_ASM(x ## b) \
701  DEF_ASM(x ## c) \
702  DEF_ASM(x ## nae) \
703  DEF_ASM(x ## nb) \
704  DEF_ASM(x ## nc) \
705  DEF_ASM(x ## ae) \
706  DEF_ASM(x ## e) \
707  DEF_ASM(x ## z) \
708  DEF_ASM(x ## ne) \
709  DEF_ASM(x ## nz) \
710  DEF_ASM(x ## be) \
711  DEF_ASM(x ## na) \
712  DEF_ASM(x ## nbe) \
713  DEF_ASM(x ## a) \
714  DEF_ASM(x ## s) \
715  DEF_ASM(x ## ns) \
716  DEF_ASM(x ## p) \
717  DEF_ASM(x ## pe) \
718  DEF_ASM(x ## np) \
719  DEF_ASM(x ## po) \
720  DEF_ASM(x ## l) \
721  DEF_ASM(x ## nge) \
722  DEF_ASM(x ## nl) \
723  DEF_ASM(x ## ge) \
724  DEF_ASM(x ## le) \
725  DEF_ASM(x ## ng) \
726  DEF_ASM(x ## nle) \
727  DEF_ASM(x ## g)
728 
729 #define TOK_ASM_int TOK_INT
730 
731 enum tcc_token {
732     TOK_LAST = TOK_IDENT - 1,
733 #define DEF(id, str) id,
734 #include "tcctok.h"
735 #undef DEF
736 };
737 
738 static const char tcc_keywords[] =
739 #define DEF(id, str) str "\0"
740 #include "tcctok.h"
741 #undef DEF
742 ;
743 
744 #define TOK_UIDENT TOK_DEFINE
745 
746 #ifdef _WIN32
747 #define snprintf _snprintf
748 #define vsnprintf _vsnprintf
749 #ifndef __GNUC__
750   #define strtold (long double)strtod
751   #define strtof (float)strtod
752   #define strtoll (long long)strtol
753 #endif
754 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
755     || defined(__OpenBSD__)
756 /* currently incorrect */
strtold(const char * nptr,char ** endptr)757 long double strtold(const char *nptr, char **endptr)
758 {
759     return (long double)strtod(nptr, endptr);
760 }
strtof(const char * nptr,char ** endptr)761 float strtof(const char *nptr, char **endptr)
762 {
763     return (float)strtod(nptr, endptr);
764 }
765 #else
766 /* XXX: need to define this to use them in non ISOC99 context */
767 extern float strtof (const char *__nptr, char **__endptr);
768 extern long double strtold (const char *__nptr, char **__endptr);
769 #endif
770 
771 static char *pstrcpy(char *buf, int buf_size, const char *s);
772 static char *pstrcat(char *buf, int buf_size, const char *s);
773 static char *tcc_basename(const char *name);
774 static char *tcc_fileextension (const char *p);
775 
776 static void next(void);
777 static void next_nomacro(void);
778 static void parse_expr_type(CType *type);
779 static void expr_type(CType *type);
780 static void unary_type(CType *type);
781 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
782                   int case_reg, int is_expr);
783 static int expr_const(void);
784 static void expr_eq(void);
785 static void gexpr(void);
786 static void gen_inline_functions(void);
787 static void decl(int l);
788 static void decl_initializer(CType *type, Section *sec, unsigned long c,
789                              int first, int size_only);
790 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
791                                    int has_init, int v, int scope);
792 int gv(int rc);
793 void gv2(int rc1, int rc2);
794 void move_reg(int r, int s);
795 void save_regs(int n);
796 void save_reg(int r);
797 void vpop(void);
798 void vswap(void);
799 void vdup(void);
800 int get_reg(int rc);
801 int get_reg_ex(int rc,int rc2);
802 
803 struct macro_level {
804     struct macro_level *prev;
805     int *p;
806 };
807 
808 static void macro_subst(TokenString *tok_str, Sym **nested_list,
809                         const int *macro_str, struct macro_level **can_read_stream);
810 void gen_op(int op);
811 void force_charshort_cast(int t);
812 static void gen_cast(CType *type);
813 void vstore(void);
814 static Sym *sym_find(int v);
815 static Sym *sym_push(int v, CType *type, int r, int c);
816 
817 /* type handling */
818 static int type_size(CType *type, int *a);
819 static inline CType *pointed_type(CType *type);
820 static int pointed_size(CType *type);
821 static int lvalue_type(int t);
822 static int parse_btype(CType *type, AttributeDef *ad);
823 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
824 static int compare_types(CType *type1, CType *type2, int unqualified);
825 static int is_compatible_types(CType *type1, CType *type2);
826 static int is_compatible_parameter_types(CType *type1, CType *type2);
827 
828 int ieee_finite(double d);
829 void error(const char *fmt, ...);
830 void vpushi(int v);
831 void vrott(int n);
832 void vnrott(int n);
833 void lexpand_nr(void);
834 static void vpush_global_sym(CType *type, int v);
835 void vset(CType *type, int r, int v);
836 void type_to_str(char *buf, int buf_size,
837                  CType *type, const char *varstr);
838 char *get_tok_str(int v, CValue *cv);
839 static Sym *get_sym_ref(CType *type, Section *sec,
840                         unsigned long offset, unsigned long size);
841 static Sym *external_global_sym(int v, CType *type, int r);
842 
843 /* section generation */
844 static void section_realloc(Section *sec, unsigned long new_size);
845 static void *section_ptr_add(Section *sec, unsigned long size);
846 static void put_extern_sym(Sym *sym, Section *section,
847                            unsigned long value, unsigned long size);
848 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
849 static int put_elf_str(Section *s, const char *sym);
850 static int put_elf_sym(Section *s,
851                        unsigned long value, unsigned long size,
852                        int info, int other, int shndx, const char *name);
853 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
854                        int info, int other, int sh_num, const char *name);
855 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
856                           int type, int symbol);
857 static void put_stabs(const char *str, int type, int other, int desc,
858                       unsigned long value);
859 static void put_stabs_r(const char *str, int type, int other, int desc,
860                         unsigned long value, Section *sec, int sym_index);
861 static void put_stabn(int type, int other, int desc, int value);
862 static void put_stabd(int type, int other, int desc);
863 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
864 
865 #define AFF_PRINT_ERROR     0x0001 /* print error if file not found */
866 #define AFF_REFERENCED_DLL  0x0002 /* load a referenced dll from another dll */
867 #define AFF_PREPROCESS      0x0004 /* preprocess file */
868 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
869 
870 /* tcccoff.c */
871 int tcc_output_coff(TCCState *s1, FILE *f);
872 
873 /* tccpe.c */
874 void *resolve_sym(TCCState *s1, const char *sym, int type);
875 int pe_load_def_file(struct TCCState *s1, int fd);
876 int pe_test_res_file(void *v, int size);
877 int pe_load_res_file(struct TCCState *s1, int fd);
878 void pe_add_runtime(struct TCCState *s1);
879 void pe_guess_outfile(char *objfilename, int output_type);
880 int pe_output_file(struct TCCState *s1, const char *filename);
881 
882 /* tccasm.c */
883 
884 #ifdef CONFIG_TCC_ASM
885 
886 typedef struct ExprValue {
887     uint32_t v;
888     Sym *sym;
889 } ExprValue;
890 
891 #define MAX_ASM_OPERANDS 30
892 
893 typedef struct ASMOperand {
894     int id; /* GCC 3 optionnal identifier (0 if number only supported */
895     char *constraint;
896     char asm_str[16]; /* computed asm string for operand */
897     SValue *vt; /* C value of the expression */
898     int ref_index; /* if >= 0, gives reference to a output constraint */
899     int input_index; /* if >= 0, gives reference to an input constraint */
900     int priority; /* priority, used to assign registers */
901     int reg; /* if >= 0, register number used for this operand */
902     int is_llong; /* true if double register value */
903     int is_memory; /* true if memory operand */
904     int is_rw;     /* for '+' modifier */
905 } ASMOperand;
906 
907 static void asm_expr(TCCState *s1, ExprValue *pe);
908 static int asm_int_expr(TCCState *s1);
909 static int find_constraint(ASMOperand *operands, int nb_operands,
910                            const char *name, const char **pp);
911 
912 static int tcc_assemble(TCCState *s1, int do_preprocess);
913 
914 #endif
915 
916 static void asm_instr(void);
917 static void asm_global_instr(void);
918 
919 /* true if float/double/long double type */
is_float(int t)920 static inline int is_float(int t)
921 {
922     int bt;
923     bt = t & VT_BTYPE;
924     return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
925 }
926 
927 #ifdef TCC_TARGET_I386
928 #include "i386-gen.c"
929 #endif
930 
931 #ifdef TCC_TARGET_ARM
932 #include "arm-gen.c"
933 #endif
934 
935 #ifdef TCC_TARGET_C67
936 #include "c67-gen.c"
937 #endif
938 
939 #ifdef CONFIG_TCC_STATIC
940 
941 #define RTLD_LAZY       0x001
942 #define RTLD_NOW        0x002
943 #define RTLD_GLOBAL     0x100
944 #define RTLD_DEFAULT    NULL
945 
946 /* dummy function for profiling */
dlopen(const char * filename,int flag)947 void *dlopen(const char *filename, int flag)
948 {
949     return NULL;
950 }
951 
dlerror(void)952 const char *dlerror(void)
953 {
954     return "error";
955 }
956 
957 typedef struct TCCSyms {
958     char *str;
959     void *ptr;
960 } TCCSyms;
961 
962 #define TCCSYM(a) { #a, &a, },
963 
964 /* add the symbol you want here if no dynamic linking is done */
965 static TCCSyms tcc_syms[] = {
966 #if !defined(CONFIG_TCCBOOT)
967     TCCSYM(printf)
968     TCCSYM(fprintf)
969     TCCSYM(fopen)
970     TCCSYM(fclose)
971 #endif
972     { NULL, NULL },
973 };
974 
resolve_sym(TCCState * s1,const char * symbol,int type)975 void *resolve_sym(TCCState *s1, const char *symbol, int type)
976 {
977     TCCSyms *p;
978     p = tcc_syms;
979     while (p->str != NULL) {
980         if (!strcmp(p->str, symbol))
981             return p->ptr;
982         p++;
983     }
984     return NULL;
985 }
986 
987 #elif !defined(_WIN32)
988 
989 #include <dlfcn.h>
990 
resolve_sym(TCCState * s1,const char * sym,int type)991 void *resolve_sym(TCCState *s1, const char *sym, int type)
992 {
993     return dlsym(RTLD_DEFAULT, sym);
994 }
995 
996 #endif
997 
998 /********************************************************/
999 
1000 /* we use our own 'finite' function to avoid potential problems with
1001    non standard math libs */
1002 /* XXX: endianness dependent */
ieee_finite(double d)1003 int ieee_finite(double d)
1004 {
1005     int *p = (int *)&d;
1006     return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1007 }
1008 
1009 /* copy a string and truncate it. */
pstrcpy(char * buf,int buf_size,const char * s)1010 static char *pstrcpy(char *buf, int buf_size, const char *s)
1011 {
1012     char *q, *q_end;
1013     int c;
1014 
1015     if (buf_size > 0) {
1016         q = buf;
1017         q_end = buf + buf_size - 1;
1018         while (q < q_end) {
1019             c = *s++;
1020             if (c == '\0')
1021                 break;
1022             *q++ = c;
1023         }
1024         *q = '\0';
1025     }
1026     return buf;
1027 }
1028 
1029 /* strcat and truncate. */
pstrcat(char * buf,int buf_size,const char * s)1030 static char *pstrcat(char *buf, int buf_size, const char *s)
1031 {
1032     int len;
1033     len = strlen(buf);
1034     if (len < buf_size)
1035         pstrcpy(buf + len, buf_size - len, s);
1036     return buf;
1037 }
1038 
1039 #ifndef LIBTCC
strstart(const char * str,const char * val,const char ** ptr)1040 static int strstart(const char *str, const char *val, const char **ptr)
1041 {
1042     const char *p, *q;
1043     p = str;
1044     q = val;
1045     while (*q != '\0') {
1046         if (*p != *q)
1047             return 0;
1048         p++;
1049         q++;
1050     }
1051     if (ptr)
1052         *ptr = p;
1053     return 1;
1054 }
1055 #endif
1056 
1057 /* extract the basename of a file */
tcc_basename(const char * name)1058 static char *tcc_basename(const char *name)
1059 {
1060     char *p = strchr(name, 0);
1061     while (p > name
1062         && p[-1] != '/'
1063 #ifdef _WIN32
1064         && p[-1] != '\\'
1065 #endif
1066         )
1067         --p;
1068     return p;
1069 }
1070 
tcc_fileextension(const char * name)1071 static char *tcc_fileextension (const char *name)
1072 {
1073     char *b = tcc_basename(name);
1074     char *e = strrchr(b, '.');
1075     return e ? e : strchr(b, 0);
1076 }
1077 
1078 #ifdef _WIN32
normalize_slashes(char * path)1079 char *normalize_slashes(char *path)
1080 {
1081     char *p;
1082     for (p = path; *p; ++p)
1083         if (*p == '\\')
1084             *p = '/';
1085     return path;
1086 }
1087 
w32_tcc_lib_path(void)1088 char *w32_tcc_lib_path(void)
1089 {
1090     /* on win32, we suppose the lib and includes are at the location
1091        of 'tcc.exe' */
1092     char path[1024], *p;
1093     GetModuleFileNameA(NULL, path, sizeof path);
1094     p = tcc_basename(normalize_slashes(strlwr(path)));
1095     if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1096         p -= 5;
1097     else if (p > path)
1098         p--;
1099     *p = 0;
1100     return strdup(path);
1101 }
1102 #endif
1103 
set_pages_executable(void * ptr,unsigned long length)1104 void set_pages_executable(void *ptr, unsigned long length)
1105 {
1106 #ifdef _WIN32
1107     unsigned long old_protect;
1108     VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1109 #else
1110     unsigned long start, end;
1111     start = (unsigned long)ptr & ~(PAGESIZE - 1);
1112     end = (unsigned long)ptr + length;
1113     end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1114     mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1115 #endif
1116 }
1117 
1118 /* memory management */
1119 #ifdef MEM_DEBUG
1120 int mem_cur_size;
1121 int mem_max_size;
1122 #endif
1123 
tcc_free(void * ptr)1124 static inline void tcc_free(void *ptr)
1125 {
1126 #ifdef MEM_DEBUG
1127     mem_cur_size -= malloc_usable_size(ptr);
1128 #endif
1129     free(ptr);
1130 }
1131 
tcc_malloc(unsigned long size)1132 static void *tcc_malloc(unsigned long size)
1133 {
1134     void *ptr;
1135     ptr = malloc(size);
1136     if (!ptr && size)
1137         error("memory full");
1138 #ifdef MEM_DEBUG
1139     mem_cur_size += malloc_usable_size(ptr);
1140     if (mem_cur_size > mem_max_size)
1141         mem_max_size = mem_cur_size;
1142 #endif
1143     return ptr;
1144 }
1145 
tcc_mallocz(unsigned long size)1146 static void *tcc_mallocz(unsigned long size)
1147 {
1148     void *ptr;
1149     ptr = tcc_malloc(size);
1150     memset(ptr, 0, size);
1151     return ptr;
1152 }
1153 
tcc_realloc(void * ptr,unsigned long size)1154 static inline void *tcc_realloc(void *ptr, unsigned long size)
1155 {
1156     void *ptr1;
1157 #ifdef MEM_DEBUG
1158     mem_cur_size -= malloc_usable_size(ptr);
1159 #endif
1160     ptr1 = realloc(ptr, size);
1161 #ifdef MEM_DEBUG
1162     /* NOTE: count not correct if alloc error, but not critical */
1163     mem_cur_size += malloc_usable_size(ptr1);
1164     if (mem_cur_size > mem_max_size)
1165         mem_max_size = mem_cur_size;
1166 #endif
1167     return ptr1;
1168 }
1169 
tcc_strdup(const char * str)1170 static char *tcc_strdup(const char *str)
1171 {
1172     char *ptr;
1173     ptr = tcc_malloc(strlen(str) + 1);
1174     strcpy(ptr, str);
1175     return ptr;
1176 }
1177 
1178 #define free(p) use_tcc_free(p)
1179 #define malloc(s) use_tcc_malloc(s)
1180 #define realloc(p, s) use_tcc_realloc(p, s)
1181 
dynarray_add(void *** ptab,int * nb_ptr,void * data)1182 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1183 {
1184     int nb, nb_alloc;
1185     void **pp;
1186 
1187     nb = *nb_ptr;
1188     pp = *ptab;
1189     /* every power of two we double array size */
1190     if ((nb & (nb - 1)) == 0) {
1191         if (!nb)
1192             nb_alloc = 1;
1193         else
1194             nb_alloc = nb * 2;
1195         pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1196         if (!pp)
1197             error("memory full");
1198         *ptab = pp;
1199     }
1200     pp[nb++] = data;
1201     *nb_ptr = nb;
1202 }
1203 
dynarray_reset(void * pp,int * n)1204 static void dynarray_reset(void *pp, int *n)
1205 {
1206     void **p;
1207     for (p = *(void***)pp; *n; ++p, --*n)
1208         if (*p)
1209             tcc_free(*p);
1210     tcc_free(*(void**)pp);
1211     *(void**)pp = NULL;
1212 }
1213 
1214 /* symbol allocator */
__sym_malloc(void)1215 static Sym *__sym_malloc(void)
1216 {
1217     Sym *sym_pool, *sym, *last_sym;
1218     int i;
1219 
1220     sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1221 
1222     last_sym = sym_free_first;
1223     sym = sym_pool;
1224     for(i = 0; i < SYM_POOL_NB; i++) {
1225         sym->next = last_sym;
1226         last_sym = sym;
1227         sym++;
1228     }
1229     sym_free_first = last_sym;
1230     return last_sym;
1231 }
1232 
sym_malloc(void)1233 static inline Sym *sym_malloc(void)
1234 {
1235     Sym *sym;
1236     sym = sym_free_first;
1237     if (!sym)
1238         sym = __sym_malloc();
1239     sym_free_first = sym->next;
1240     return sym;
1241 }
1242 
sym_free(Sym * sym)1243 static inline void sym_free(Sym *sym)
1244 {
1245     sym->next = sym_free_first;
1246     sym_free_first = sym;
1247 }
1248 
new_section(TCCState * s1,const char * name,int sh_type,int sh_flags)1249 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1250 {
1251     Section *sec;
1252 
1253     sec = tcc_mallocz(sizeof(Section) + strlen(name));
1254     strcpy(sec->name, name);
1255     sec->sh_type = sh_type;
1256     sec->sh_flags = sh_flags;
1257     switch(sh_type) {
1258     case SHT_HASH:
1259     case SHT_REL:
1260     case SHT_DYNSYM:
1261     case SHT_SYMTAB:
1262     case SHT_DYNAMIC:
1263         sec->sh_addralign = 4;
1264         break;
1265     case SHT_STRTAB:
1266         sec->sh_addralign = 1;
1267         break;
1268     default:
1269         sec->sh_addralign = 32; /* default conservative alignment */
1270         break;
1271     }
1272 
1273     /* only add section if not private */
1274     if (!(sh_flags & SHF_PRIVATE)) {
1275         sec->sh_num = s1->nb_sections;
1276         dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1277     }
1278     return sec;
1279 }
1280 
free_section(Section * s)1281 static void free_section(Section *s)
1282 {
1283     tcc_free(s->data);
1284     tcc_free(s);
1285 }
1286 
1287 /* realloc section and set its content to zero */
section_realloc(Section * sec,unsigned long new_size)1288 static void section_realloc(Section *sec, unsigned long new_size)
1289 {
1290     unsigned long size;
1291     unsigned char *data;
1292 
1293     size = sec->data_allocated;
1294     if (size == 0)
1295         size = 1;
1296     while (size < new_size)
1297         size = size * 2;
1298     data = tcc_realloc(sec->data, size);
1299     if (!data)
1300         error("memory full");
1301     memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1302     sec->data = data;
1303     sec->data_allocated = size;
1304 }
1305 
1306 /* reserve at least 'size' bytes in section 'sec' from
1307    sec->data_offset. */
section_ptr_add(Section * sec,unsigned long size)1308 static void *section_ptr_add(Section *sec, unsigned long size)
1309 {
1310     unsigned long offset, offset1;
1311 
1312     offset = sec->data_offset;
1313     offset1 = offset + size;
1314     if (offset1 > sec->data_allocated)
1315         section_realloc(sec, offset1);
1316     sec->data_offset = offset1;
1317     return sec->data + offset;
1318 }
1319 
1320 /* return a reference to a section, and create it if it does not
1321    exists */
find_section(TCCState * s1,const char * name)1322 Section *find_section(TCCState *s1, const char *name)
1323 {
1324     Section *sec;
1325     int i;
1326     for(i = 1; i < s1->nb_sections; i++) {
1327         sec = s1->sections[i];
1328         if (!strcmp(name, sec->name))
1329             return sec;
1330     }
1331     /* sections are created as PROGBITS */
1332     return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1333 }
1334 
1335 #define SECTION_ABS ((void *)1)
1336 
1337 /* update sym->c so that it points to an external symbol in section
1338    'section' with value 'value' */
put_extern_sym2(Sym * sym,Section * section,unsigned long value,unsigned long size,int can_add_underscore)1339 static void put_extern_sym2(Sym *sym, Section *section,
1340                             unsigned long value, unsigned long size,
1341                             int can_add_underscore)
1342 {
1343     int sym_type, sym_bind, sh_num, info, other, attr;
1344     Elf32_Sym *esym;
1345     const char *name;
1346     char buf1[256];
1347 
1348     if (section == NULL)
1349         sh_num = SHN_UNDEF;
1350     else if (section == SECTION_ABS)
1351         sh_num = SHN_ABS;
1352     else
1353         sh_num = section->sh_num;
1354 
1355     other = attr = 0;
1356 
1357     if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1358         sym_type = STT_FUNC;
1359 #ifdef TCC_TARGET_PE
1360         if (sym->type.ref)
1361             attr = sym->type.ref->r;
1362         if (FUNC_EXPORT(attr))
1363             other |= 1;
1364         if (FUNC_CALL(attr) == FUNC_STDCALL)
1365             other |= 2;
1366 #endif
1367     } else {
1368         sym_type = STT_OBJECT;
1369     }
1370 
1371     if (sym->type.t & VT_STATIC)
1372         sym_bind = STB_LOCAL;
1373     else
1374         sym_bind = STB_GLOBAL;
1375 
1376     if (!sym->c) {
1377         name = get_tok_str(sym->v, NULL);
1378 #ifdef CONFIG_TCC_BCHECK
1379         if (do_bounds_check) {
1380             char buf[32];
1381 
1382             /* XXX: avoid doing that for statics ? */
1383             /* if bound checking is activated, we change some function
1384                names by adding the "__bound" prefix */
1385             switch(sym->v) {
1386 #if 0
1387             /* XXX: we rely only on malloc hooks */
1388             case TOK_malloc:
1389             case TOK_free:
1390             case TOK_realloc:
1391             case TOK_memalign:
1392             case TOK_calloc:
1393 #endif
1394             case TOK_memcpy:
1395             case TOK_memmove:
1396             case TOK_memset:
1397             case TOK_strlen:
1398             case TOK_strcpy:
1399             case TOK__alloca:
1400                 strcpy(buf, "__bound_");
1401                 strcat(buf, name);
1402                 name = buf;
1403                 break;
1404             }
1405         }
1406 #endif
1407 
1408 #ifdef TCC_TARGET_PE
1409         if ((other & 2) && can_add_underscore) {
1410             sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1411             name = buf1;
1412         } else
1413 #endif
1414         if (tcc_state->leading_underscore && can_add_underscore) {
1415             buf1[0] = '_';
1416             pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1417             name = buf1;
1418         }
1419         info = ELF32_ST_INFO(sym_bind, sym_type);
1420         sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1421     } else {
1422         esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1423         esym->st_value = value;
1424         esym->st_size = size;
1425         esym->st_shndx = sh_num;
1426         esym->st_other |= other;
1427     }
1428 }
1429 
put_extern_sym(Sym * sym,Section * section,unsigned long value,unsigned long size)1430 static void put_extern_sym(Sym *sym, Section *section,
1431                            unsigned long value, unsigned long size)
1432 {
1433     put_extern_sym2(sym, section, value, size, 1);
1434 }
1435 
1436 /* add a new relocation entry to symbol 'sym' in section 's' */
greloc(Section * s,Sym * sym,unsigned long offset,int type)1437 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1438 {
1439     if (!sym->c)
1440         put_extern_sym(sym, NULL, 0, 0);
1441     /* now we can add ELF relocation info */
1442     put_elf_reloc(symtab_section, s, offset, type, sym->c);
1443 }
1444 
isid(int c)1445 static inline int isid(int c)
1446 {
1447     return (c >= 'a' && c <= 'z') ||
1448         (c >= 'A' && c <= 'Z') ||
1449         c == '_';
1450 }
1451 
isnum(int c)1452 static inline int isnum(int c)
1453 {
1454     return c >= '0' && c <= '9';
1455 }
1456 
isoct(int c)1457 static inline int isoct(int c)
1458 {
1459     return c >= '0' && c <= '7';
1460 }
1461 
toup(int c)1462 static inline int toup(int c)
1463 {
1464     if (c >= 'a' && c <= 'z')
1465         return c - 'a' + 'A';
1466     else
1467         return c;
1468 }
1469 
strcat_vprintf(char * buf,int buf_size,const char * fmt,va_list ap)1470 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1471 {
1472     int len;
1473     len = strlen(buf);
1474     vsnprintf(buf + len, buf_size - len, fmt, ap);
1475 }
1476 
strcat_printf(char * buf,int buf_size,const char * fmt,...)1477 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1478 {
1479     va_list ap;
1480     va_start(ap, fmt);
1481     strcat_vprintf(buf, buf_size, fmt, ap);
1482     va_end(ap);
1483 }
1484 
error1(TCCState * s1,int is_warning,const char * fmt,va_list ap)1485 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1486 {
1487     char buf[2048];
1488     BufferedFile **f;
1489 
1490     buf[0] = '\0';
1491     if (file) {
1492         for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1493             strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1494                           (*f)->filename, (*f)->line_num);
1495         if (file->line_num > 0) {
1496             strcat_printf(buf, sizeof(buf),
1497                           "Line %d: ", file->line_num);
1498         } else {
1499             strcat_printf(buf, sizeof(buf),
1500                           "%s: ", file->filename);
1501         }
1502     } else {
1503         strcat_printf(buf, sizeof(buf),
1504                       "tcc: ");
1505     }
1506     if (is_warning)
1507         strcat_printf(buf, sizeof(buf), "warning: ");
1508     strcat_vprintf(buf, sizeof(buf), fmt, ap);
1509 
1510     if (!s1->error_func) {
1511         /* default case: stderr */
1512         fprintf(stderr, "%s\n", buf);
1513     } else {
1514         s1->error_func(s1->error_opaque, buf);
1515     }
1516     if (!is_warning || s1->warn_error)
1517         s1->nb_errors++;
1518 }
1519 
1520 #ifdef LIBTCC
tcc_set_error_func(TCCState * s,void * error_opaque,void (* error_func)(void * opaque,const char * msg))1521 void tcc_set_error_func(TCCState *s, void *error_opaque,
1522                         void (*error_func)(void *opaque, const char *msg))
1523 {
1524     s->error_opaque = error_opaque;
1525     s->error_func = error_func;
1526 }
1527 #endif
1528 
1529 /* error without aborting current compilation */
error_noabort(const char * fmt,...)1530 void error_noabort(const char *fmt, ...)
1531 {
1532     TCCState *s1 = tcc_state;
1533     va_list ap;
1534 
1535     va_start(ap, fmt);
1536     error1(s1, 0, fmt, ap);
1537     va_end(ap);
1538 }
1539 
error(const char * fmt,...)1540 void error(const char *fmt, ...)
1541 {
1542     TCCState *s1 = tcc_state;
1543     va_list ap;
1544 
1545     va_start(ap, fmt);
1546     error1(s1, 0, fmt, ap);
1547     va_end(ap);
1548     /* better than nothing: in some cases, we accept to handle errors */
1549     if (s1->error_set_jmp_enabled) {
1550         longjmp(s1->error_jmp_buf, 1);
1551     } else {
1552         /* XXX: eliminate this someday */
1553         exit(1);
1554     }
1555 }
1556 
expect(const char * msg)1557 void expect(const char *msg)
1558 {
1559     error("%s expected", msg);
1560 }
1561 
warning(const char * fmt,...)1562 void warning(const char *fmt, ...)
1563 {
1564     TCCState *s1 = tcc_state;
1565     va_list ap;
1566 
1567     if (s1->warn_none)
1568         return;
1569 
1570     va_start(ap, fmt);
1571     error1(s1, 1, fmt, ap);
1572     va_end(ap);
1573 }
1574 
skip(int c)1575 void skip(int c)
1576 {
1577     if (tok != c)
1578         error("'%c' expected", c);
1579     next();
1580 }
1581 
test_lvalue(void)1582 static void test_lvalue(void)
1583 {
1584     if (!(vtop->r & VT_LVAL))
1585         expect("lvalue");
1586 }
1587 
1588 /* allocate a new token */
tok_alloc_new(TokenSym ** pts,const char * str,int len)1589 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1590 {
1591     TokenSym *ts, **ptable;
1592     int i;
1593 
1594     if (tok_ident >= SYM_FIRST_ANOM)
1595         error("memory full");
1596 
1597     /* expand token table if needed */
1598     i = tok_ident - TOK_IDENT;
1599     if ((i % TOK_ALLOC_INCR) == 0) {
1600         ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1601         if (!ptable)
1602             error("memory full");
1603         table_ident = ptable;
1604     }
1605 
1606     ts = tcc_malloc(sizeof(TokenSym) + len);
1607     table_ident[i] = ts;
1608     ts->tok = tok_ident++;
1609     ts->sym_define = NULL;
1610     ts->sym_label = NULL;
1611     ts->sym_struct = NULL;
1612     ts->sym_identifier = NULL;
1613     ts->len = len;
1614     ts->hash_next = NULL;
1615     memcpy(ts->str, str, len);
1616     ts->str[len] = '\0';
1617     *pts = ts;
1618     return ts;
1619 }
1620 
1621 #define TOK_HASH_INIT 1
1622 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1623 
1624 /* find a token and add it if not found */
tok_alloc(const char * str,int len)1625 static TokenSym *tok_alloc(const char *str, int len)
1626 {
1627     TokenSym *ts, **pts;
1628     int i;
1629     unsigned int h;
1630 
1631     h = TOK_HASH_INIT;
1632     for(i=0;i<len;i++)
1633         h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1634     h &= (TOK_HASH_SIZE - 1);
1635 
1636     pts = &hash_ident[h];
1637     for(;;) {
1638         ts = *pts;
1639         if (!ts)
1640             break;
1641         if (ts->len == len && !memcmp(ts->str, str, len))
1642             return ts;
1643         pts = &(ts->hash_next);
1644     }
1645     return tok_alloc_new(pts, str, len);
1646 }
1647 
1648 /* CString handling */
1649 
cstr_realloc(CString * cstr,int new_size)1650 static void cstr_realloc(CString *cstr, int new_size)
1651 {
1652     int size;
1653     void *data;
1654 
1655     size = cstr->size_allocated;
1656     if (size == 0)
1657         size = 8; /* no need to allocate a too small first string */
1658     while (size < new_size)
1659         size = size * 2;
1660     data = tcc_realloc(cstr->data_allocated, size);
1661     if (!data)
1662         error("memory full");
1663     cstr->data_allocated = data;
1664     cstr->size_allocated = size;
1665     cstr->data = data;
1666 }
1667 
1668 /* add a byte */
cstr_ccat(CString * cstr,int ch)1669 static inline void cstr_ccat(CString *cstr, int ch)
1670 {
1671     int size;
1672     size = cstr->size + 1;
1673     if (size > cstr->size_allocated)
1674         cstr_realloc(cstr, size);
1675     ((unsigned char *)cstr->data)[size - 1] = ch;
1676     cstr->size = size;
1677 }
1678 
cstr_cat(CString * cstr,const char * str)1679 static void cstr_cat(CString *cstr, const char *str)
1680 {
1681     int c;
1682     for(;;) {
1683         c = *str;
1684         if (c == '\0')
1685             break;
1686         cstr_ccat(cstr, c);
1687         str++;
1688     }
1689 }
1690 
1691 /* add a wide char */
cstr_wccat(CString * cstr,int ch)1692 static void cstr_wccat(CString *cstr, int ch)
1693 {
1694     int size;
1695     size = cstr->size + sizeof(nwchar_t);
1696     if (size > cstr->size_allocated)
1697         cstr_realloc(cstr, size);
1698     *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1699     cstr->size = size;
1700 }
1701 
cstr_new(CString * cstr)1702 static void cstr_new(CString *cstr)
1703 {
1704     memset(cstr, 0, sizeof(CString));
1705 }
1706 
1707 /* free string and reset it to NULL */
cstr_free(CString * cstr)1708 static void cstr_free(CString *cstr)
1709 {
1710     tcc_free(cstr->data_allocated);
1711     cstr_new(cstr);
1712 }
1713 
1714 #define cstr_reset(cstr) cstr_free(cstr)
1715 
1716 /* XXX: unicode ? */
add_char(CString * cstr,int c)1717 static void add_char(CString *cstr, int c)
1718 {
1719     if (c == '\'' || c == '\"' || c == '\\') {
1720         /* XXX: could be more precise if char or string */
1721         cstr_ccat(cstr, '\\');
1722     }
1723     if (c >= 32 && c <= 126) {
1724         cstr_ccat(cstr, c);
1725     } else {
1726         cstr_ccat(cstr, '\\');
1727         if (c == '\n') {
1728             cstr_ccat(cstr, 'n');
1729         } else {
1730             cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1731             cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1732             cstr_ccat(cstr, '0' + (c & 7));
1733         }
1734     }
1735 }
1736 
1737 /* XXX: buffer overflow */
1738 /* XXX: float tokens */
get_tok_str(int v,CValue * cv)1739 char *get_tok_str(int v, CValue *cv)
1740 {
1741     static char buf[STRING_MAX_SIZE + 1];
1742     static CString cstr_buf;
1743     CString *cstr;
1744     unsigned char *q;
1745     char *p;
1746     int i, len;
1747 
1748     /* NOTE: to go faster, we give a fixed buffer for small strings */
1749     cstr_reset(&cstr_buf);
1750     cstr_buf.data = buf;
1751     cstr_buf.size_allocated = sizeof(buf);
1752     p = buf;
1753 
1754     switch(v) {
1755     case TOK_CINT:
1756     case TOK_CUINT:
1757         /* XXX: not quite exact, but only useful for testing */
1758         sprintf(p, "%u", cv->ui);
1759         break;
1760     case TOK_CLLONG:
1761     case TOK_CULLONG:
1762         /* XXX: not quite exact, but only useful for testing  */
1763         sprintf(p, "%Lu", cv->ull);
1764         break;
1765     case TOK_CCHAR:
1766     case TOK_LCHAR:
1767         cstr_ccat(&cstr_buf, '\'');
1768         add_char(&cstr_buf, cv->i);
1769         cstr_ccat(&cstr_buf, '\'');
1770         cstr_ccat(&cstr_buf, '\0');
1771         break;
1772     case TOK_PPNUM:
1773         cstr = cv->cstr;
1774         len = cstr->size - 1;
1775         for(i=0;i<len;i++)
1776             add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1777         cstr_ccat(&cstr_buf, '\0');
1778         break;
1779     case TOK_STR:
1780     case TOK_LSTR:
1781         cstr = cv->cstr;
1782         cstr_ccat(&cstr_buf, '\"');
1783         if (v == TOK_STR) {
1784             len = cstr->size - 1;
1785             for(i=0;i<len;i++)
1786                 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1787         } else {
1788             len = (cstr->size / sizeof(nwchar_t)) - 1;
1789             for(i=0;i<len;i++)
1790                 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1791         }
1792         cstr_ccat(&cstr_buf, '\"');
1793         cstr_ccat(&cstr_buf, '\0');
1794         break;
1795     case TOK_LT:
1796         v = '<';
1797         goto addv;
1798     case TOK_GT:
1799         v = '>';
1800         goto addv;
1801     case TOK_DOTS:
1802         return strcpy(p, "...");
1803     case TOK_A_SHL:
1804         return strcpy(p, "<<=");
1805     case TOK_A_SAR:
1806         return strcpy(p, ">>=");
1807     default:
1808         if (v < TOK_IDENT) {
1809             /* search in two bytes table */
1810             q = tok_two_chars;
1811             while (*q) {
1812                 if (q[2] == v) {
1813                     *p++ = q[0];
1814                     *p++ = q[1];
1815                     *p = '\0';
1816                     return buf;
1817                 }
1818                 q += 3;
1819             }
1820         addv:
1821             *p++ = v;
1822             *p = '\0';
1823         } else if (v < tok_ident) {
1824             return table_ident[v - TOK_IDENT]->str;
1825         } else if (v >= SYM_FIRST_ANOM) {
1826             /* special name for anonymous symbol */
1827             sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1828         } else {
1829             /* should never happen */
1830             return NULL;
1831         }
1832         break;
1833     }
1834     return cstr_buf.data;
1835 }
1836 
1837 /* push, without hashing */
sym_push2(Sym ** ps,int v,int t,int c)1838 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1839 {
1840     Sym *s;
1841     s = sym_malloc();
1842     s->v = v;
1843     s->type.t = t;
1844     s->c = c;
1845     s->next = NULL;
1846     /* add in stack */
1847     s->prev = *ps;
1848     *ps = s;
1849     return s;
1850 }
1851 
1852 /* find a symbol and return its associated structure. 's' is the top
1853    of the symbol stack */
sym_find2(Sym * s,int v)1854 static Sym *sym_find2(Sym *s, int v)
1855 {
1856     while (s) {
1857         if (s->v == v)
1858             return s;
1859         s = s->prev;
1860     }
1861     return NULL;
1862 }
1863 
1864 /* structure lookup */
struct_find(int v)1865 static inline Sym *struct_find(int v)
1866 {
1867     v -= TOK_IDENT;
1868     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1869         return NULL;
1870     return table_ident[v]->sym_struct;
1871 }
1872 
1873 /* find an identifier */
sym_find(int v)1874 static inline Sym *sym_find(int v)
1875 {
1876     v -= TOK_IDENT;
1877     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1878         return NULL;
1879     return table_ident[v]->sym_identifier;
1880 }
1881 
1882 /* push a given symbol on the symbol stack */
sym_push(int v,CType * type,int r,int c)1883 static Sym *sym_push(int v, CType *type, int r, int c)
1884 {
1885     Sym *s, **ps;
1886     TokenSym *ts;
1887 
1888     if (local_stack)
1889         ps = &local_stack;
1890     else
1891         ps = &global_stack;
1892     s = sym_push2(ps, v, type->t, c);
1893     s->type.ref = type->ref;
1894     s->r = r;
1895     /* don't record fields or anonymous symbols */
1896     /* XXX: simplify */
1897     if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1898         /* record symbol in token array */
1899         ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1900         if (v & SYM_STRUCT)
1901             ps = &ts->sym_struct;
1902         else
1903             ps = &ts->sym_identifier;
1904         s->prev_tok = *ps;
1905         *ps = s;
1906     }
1907     return s;
1908 }
1909 
1910 /* push a global identifier */
global_identifier_push(int v,int t,int c)1911 static Sym *global_identifier_push(int v, int t, int c)
1912 {
1913     Sym *s, **ps;
1914     s = sym_push2(&global_stack, v, t, c);
1915     /* don't record anonymous symbol */
1916     if (v < SYM_FIRST_ANOM) {
1917         ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1918         /* modify the top most local identifier, so that
1919            sym_identifier will point to 's' when popped */
1920         while (*ps != NULL)
1921             ps = &(*ps)->prev_tok;
1922         s->prev_tok = NULL;
1923         *ps = s;
1924     }
1925     return s;
1926 }
1927 
1928 /* pop symbols until top reaches 'b' */
sym_pop(Sym ** ptop,Sym * b)1929 static void sym_pop(Sym **ptop, Sym *b)
1930 {
1931     Sym *s, *ss, **ps;
1932     TokenSym *ts;
1933     int v;
1934 
1935     s = *ptop;
1936     while(s != b) {
1937         ss = s->prev;
1938         v = s->v;
1939         /* remove symbol in token array */
1940         /* XXX: simplify */
1941         if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1942             ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1943             if (v & SYM_STRUCT)
1944                 ps = &ts->sym_struct;
1945             else
1946                 ps = &ts->sym_identifier;
1947             *ps = s->prev_tok;
1948         }
1949         sym_free(s);
1950         s = ss;
1951     }
1952     *ptop = b;
1953 }
1954 
1955 /* I/O layer */
1956 
tcc_open(TCCState * s1,const char * filename)1957 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1958 {
1959     int fd;
1960     BufferedFile *bf;
1961 
1962     if (strcmp(filename, "-") == 0)
1963         fd = 0, filename = "stdin";
1964     else
1965         fd = open(filename, O_RDONLY | O_BINARY);
1966     if ((verbose == 2 && fd >= 0) || verbose == 3)
1967         printf("%s %*s%s\n", fd < 0 ? "nf":"->",
1968                (s1->include_stack_ptr - s1->include_stack), "", filename);
1969     if (fd < 0)
1970         return NULL;
1971     bf = tcc_malloc(sizeof(BufferedFile));
1972     bf->fd = fd;
1973     bf->buf_ptr = bf->buffer;
1974     bf->buf_end = bf->buffer;
1975     bf->buffer[0] = CH_EOB; /* put eob symbol */
1976     pstrcpy(bf->filename, sizeof(bf->filename), filename);
1977 #ifdef _WIN32
1978     normalize_slashes(bf->filename);
1979 #endif
1980     bf->line_num = 1;
1981     bf->ifndef_macro = 0;
1982     bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1983     //    printf("opening '%s'\n", filename);
1984     return bf;
1985 }
1986 
tcc_close(BufferedFile * bf)1987 void tcc_close(BufferedFile *bf)
1988 {
1989     total_lines += bf->line_num;
1990     close(bf->fd);
1991     tcc_free(bf);
1992 }
1993 
1994 /* fill input buffer and peek next char */
tcc_peekc_slow(BufferedFile * bf)1995 static int tcc_peekc_slow(BufferedFile *bf)
1996 {
1997     int len;
1998     /* only tries to read if really end of buffer */
1999     if (bf->buf_ptr >= bf->buf_end) {
2000         if (bf->fd != -1) {
2001 #if defined(PARSE_DEBUG)
2002             len = 8;
2003 #else
2004             len = IO_BUF_SIZE;
2005 #endif
2006             len = read(bf->fd, bf->buffer, len);
2007             if (len < 0)
2008                 len = 0;
2009         } else {
2010             len = 0;
2011         }
2012         total_bytes += len;
2013         bf->buf_ptr = bf->buffer;
2014         bf->buf_end = bf->buffer + len;
2015         *bf->buf_end = CH_EOB;
2016     }
2017     if (bf->buf_ptr < bf->buf_end) {
2018         return bf->buf_ptr[0];
2019     } else {
2020         bf->buf_ptr = bf->buf_end;
2021         return CH_EOF;
2022     }
2023 }
2024 
2025 /* return the current character, handling end of block if necessary
2026    (but not stray) */
handle_eob(void)2027 static int handle_eob(void)
2028 {
2029     return tcc_peekc_slow(file);
2030 }
2031 
2032 /* read next char from current input file and handle end of input buffer */
inp(void)2033 static inline void inp(void)
2034 {
2035     ch = *(++(file->buf_ptr));
2036     /* end of buffer/file handling */
2037     if (ch == CH_EOB)
2038         ch = handle_eob();
2039 }
2040 
2041 /* handle '\[\r]\n' */
handle_stray_noerror(void)2042 static int handle_stray_noerror(void)
2043 {
2044     while (ch == '\\') {
2045         inp();
2046         if (ch == '\n') {
2047             file->line_num++;
2048             inp();
2049         } else if (ch == '\r') {
2050             inp();
2051             if (ch != '\n')
2052                 goto fail;
2053             file->line_num++;
2054             inp();
2055         } else {
2056         fail:
2057             return 1;
2058         }
2059     }
2060     return 0;
2061 }
2062 
handle_stray(void)2063 static void handle_stray(void)
2064 {
2065     if (handle_stray_noerror())
2066         error("stray '\\' in program");
2067 }
2068 
2069 /* skip the stray and handle the \\n case. Output an error if
2070    incorrect char after the stray */
handle_stray1(uint8_t * p)2071 static int handle_stray1(uint8_t *p)
2072 {
2073     int c;
2074 
2075     if (p >= file->buf_end) {
2076         file->buf_ptr = p;
2077         c = handle_eob();
2078         p = file->buf_ptr;
2079         if (c == '\\')
2080             goto parse_stray;
2081     } else {
2082     parse_stray:
2083         file->buf_ptr = p;
2084         ch = *p;
2085         handle_stray();
2086         p = file->buf_ptr;
2087         c = *p;
2088     }
2089     return c;
2090 }
2091 
2092 /* handle just the EOB case, but not stray */
2093 #define PEEKC_EOB(c, p)\
2094 {\
2095     p++;\
2096     c = *p;\
2097     if (c == '\\') {\
2098         file->buf_ptr = p;\
2099         c = handle_eob();\
2100         p = file->buf_ptr;\
2101     }\
2102 }
2103 
2104 /* handle the complicated stray case */
2105 #define PEEKC(c, p)\
2106 {\
2107     p++;\
2108     c = *p;\
2109     if (c == '\\') {\
2110         c = handle_stray1(p);\
2111         p = file->buf_ptr;\
2112     }\
2113 }
2114 
2115 /* input with '\[\r]\n' handling. Note that this function cannot
2116    handle other characters after '\', so you cannot call it inside
2117    strings or comments */
minp(void)2118 static void minp(void)
2119 {
2120     inp();
2121     if (ch == '\\')
2122         handle_stray();
2123 }
2124 
2125 
2126 /* single line C++ comments */
parse_line_comment(uint8_t * p)2127 static uint8_t *parse_line_comment(uint8_t *p)
2128 {
2129     int c;
2130 
2131     p++;
2132     for(;;) {
2133         c = *p;
2134     redo:
2135         if (c == '\n' || c == CH_EOF) {
2136             break;
2137         } else if (c == '\\') {
2138             file->buf_ptr = p;
2139             c = handle_eob();
2140             p = file->buf_ptr;
2141             if (c == '\\') {
2142                 PEEKC_EOB(c, p);
2143                 if (c == '\n') {
2144                     file->line_num++;
2145                     PEEKC_EOB(c, p);
2146                 } else if (c == '\r') {
2147                     PEEKC_EOB(c, p);
2148                     if (c == '\n') {
2149                         file->line_num++;
2150                         PEEKC_EOB(c, p);
2151                     }
2152                 }
2153             } else {
2154                 goto redo;
2155             }
2156         } else {
2157             p++;
2158         }
2159     }
2160     return p;
2161 }
2162 
2163 /* C comments */
parse_comment(uint8_t * p)2164 static uint8_t *parse_comment(uint8_t *p)
2165 {
2166     int c;
2167 
2168     p++;
2169     for(;;) {
2170         /* fast skip loop */
2171         for(;;) {
2172             c = *p;
2173             if (c == '\n' || c == '*' || c == '\\')
2174                 break;
2175             p++;
2176             c = *p;
2177             if (c == '\n' || c == '*' || c == '\\')
2178                 break;
2179             p++;
2180         }
2181         /* now we can handle all the cases */
2182         if (c == '\n') {
2183             file->line_num++;
2184             p++;
2185         } else if (c == '*') {
2186             p++;
2187             for(;;) {
2188                 c = *p;
2189                 if (c == '*') {
2190                     p++;
2191                 } else if (c == '/') {
2192                     goto end_of_comment;
2193                 } else if (c == '\\') {
2194                     file->buf_ptr = p;
2195                     c = handle_eob();
2196                     p = file->buf_ptr;
2197                     if (c == '\\') {
2198                         /* skip '\[\r]\n', otherwise just skip the stray */
2199                         while (c == '\\') {
2200                             PEEKC_EOB(c, p);
2201                             if (c == '\n') {
2202                                 file->line_num++;
2203                                 PEEKC_EOB(c, p);
2204                             } else if (c == '\r') {
2205                                 PEEKC_EOB(c, p);
2206                                 if (c == '\n') {
2207                                     file->line_num++;
2208                                     PEEKC_EOB(c, p);
2209                                 }
2210                             } else {
2211                                 goto after_star;
2212                             }
2213                         }
2214                     }
2215                 } else {
2216                     break;
2217                 }
2218             }
2219         after_star: ;
2220         } else {
2221             /* stray, eob or eof */
2222             file->buf_ptr = p;
2223             c = handle_eob();
2224             p = file->buf_ptr;
2225             if (c == CH_EOF) {
2226                 error("unexpected end of file in comment");
2227             } else if (c == '\\') {
2228                 p++;
2229             }
2230         }
2231     }
2232  end_of_comment:
2233     p++;
2234     return p;
2235 }
2236 
2237 #define cinp minp
2238 
2239 /* space exlcuding newline */
is_space(int ch)2240 static inline int is_space(int ch)
2241 {
2242     return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2243 }
2244 
skip_spaces(void)2245 static inline void skip_spaces(void)
2246 {
2247     while (is_space(ch))
2248         cinp();
2249 }
2250 
2251 /* parse a string without interpreting escapes */
parse_pp_string(uint8_t * p,int sep,CString * str)2252 static uint8_t *parse_pp_string(uint8_t *p,
2253                                 int sep, CString *str)
2254 {
2255     int c;
2256     p++;
2257     for(;;) {
2258         c = *p;
2259         if (c == sep) {
2260             break;
2261         } else if (c == '\\') {
2262             file->buf_ptr = p;
2263             c = handle_eob();
2264             p = file->buf_ptr;
2265             if (c == CH_EOF) {
2266             unterminated_string:
2267                 /* XXX: indicate line number of start of string */
2268                 error("missing terminating %c character", sep);
2269             } else if (c == '\\') {
2270                 /* escape : just skip \[\r]\n */
2271                 PEEKC_EOB(c, p);
2272                 if (c == '\n') {
2273                     file->line_num++;
2274                     p++;
2275                 } else if (c == '\r') {
2276                     PEEKC_EOB(c, p);
2277                     if (c != '\n')
2278                         expect("'\n' after '\r'");
2279                     file->line_num++;
2280                     p++;
2281                 } else if (c == CH_EOF) {
2282                     goto unterminated_string;
2283                 } else {
2284                     if (str) {
2285                         cstr_ccat(str, '\\');
2286                         cstr_ccat(str, c);
2287                     }
2288                     p++;
2289                 }
2290             }
2291         } else if (c == '\n') {
2292             file->line_num++;
2293             goto add_char;
2294         } else if (c == '\r') {
2295             PEEKC_EOB(c, p);
2296             if (c != '\n') {
2297                 if (str)
2298                     cstr_ccat(str, '\r');
2299             } else {
2300                 file->line_num++;
2301                 goto add_char;
2302             }
2303         } else {
2304         add_char:
2305             if (str)
2306                 cstr_ccat(str, c);
2307             p++;
2308         }
2309     }
2310     p++;
2311     return p;
2312 }
2313 
2314 /* skip block of text until #else, #elif or #endif. skip also pairs of
2315    #if/#endif */
preprocess_skip(void)2316 void preprocess_skip(void)
2317 {
2318     int a, start_of_line, c, in_warn_or_error;
2319     uint8_t *p;
2320 
2321     p = file->buf_ptr;
2322     a = 0;
2323 redo_start:
2324     start_of_line = 1;
2325     in_warn_or_error = 0;
2326     for(;;) {
2327     redo_no_start:
2328         c = *p;
2329         switch(c) {
2330         case ' ':
2331         case '\t':
2332         case '\f':
2333         case '\v':
2334         case '\r':
2335             p++;
2336             goto redo_no_start;
2337         case '\n':
2338             file->line_num++;
2339             p++;
2340             goto redo_start;
2341         case '\\':
2342             file->buf_ptr = p;
2343             c = handle_eob();
2344             if (c == CH_EOF) {
2345                 expect("#endif");
2346             } else if (c == '\\') {
2347                 ch = file->buf_ptr[0];
2348                 handle_stray_noerror();
2349             }
2350             p = file->buf_ptr;
2351             goto redo_no_start;
2352         /* skip strings */
2353         case '\"':
2354         case '\'':
2355             if (in_warn_or_error)
2356                 goto _default;
2357             p = parse_pp_string(p, c, NULL);
2358             break;
2359         /* skip comments */
2360         case '/':
2361             if (in_warn_or_error)
2362                 goto _default;
2363             file->buf_ptr = p;
2364             ch = *p;
2365             minp();
2366             p = file->buf_ptr;
2367             if (ch == '*') {
2368                 p = parse_comment(p);
2369             } else if (ch == '/') {
2370                 p = parse_line_comment(p);
2371             }
2372             break;
2373         case '#':
2374             p++;
2375             if (start_of_line) {
2376                 file->buf_ptr = p;
2377                 next_nomacro();
2378                 p = file->buf_ptr;
2379                 if (a == 0 &&
2380                     (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2381                     goto the_end;
2382                 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2383                     a++;
2384                 else if (tok == TOK_ENDIF)
2385                     a--;
2386                 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2387                     in_warn_or_error = 1;
2388             }
2389             break;
2390 _default:
2391         default:
2392             p++;
2393             break;
2394         }
2395         start_of_line = 0;
2396     }
2397  the_end: ;
2398     file->buf_ptr = p;
2399 }
2400 
2401 /* ParseState handling */
2402 
2403 /* XXX: currently, no include file info is stored. Thus, we cannot display
2404    accurate messages if the function or data definition spans multiple
2405    files */
2406 
2407 /* save current parse state in 's' */
save_parse_state(ParseState * s)2408 void save_parse_state(ParseState *s)
2409 {
2410     s->line_num = file->line_num;
2411     s->macro_ptr = macro_ptr;
2412     s->tok = tok;
2413     s->tokc = tokc;
2414 }
2415 
2416 /* restore parse state from 's' */
restore_parse_state(ParseState * s)2417 void restore_parse_state(ParseState *s)
2418 {
2419     file->line_num = s->line_num;
2420     macro_ptr = s->macro_ptr;
2421     tok = s->tok;
2422     tokc = s->tokc;
2423 }
2424 
2425 /* return the number of additional 'ints' necessary to store the
2426    token */
tok_ext_size(int t)2427 static inline int tok_ext_size(int t)
2428 {
2429     switch(t) {
2430         /* 4 bytes */
2431     case TOK_CINT:
2432     case TOK_CUINT:
2433     case TOK_CCHAR:
2434     case TOK_LCHAR:
2435     case TOK_CFLOAT:
2436     case TOK_LINENUM:
2437         return 1;
2438     case TOK_STR:
2439     case TOK_LSTR:
2440     case TOK_PPNUM:
2441         error("unsupported token");
2442         return 1;
2443     case TOK_CDOUBLE:
2444     case TOK_CLLONG:
2445     case TOK_CULLONG:
2446         return 2;
2447     case TOK_CLDOUBLE:
2448         return LDOUBLE_SIZE / 4;
2449     default:
2450         return 0;
2451     }
2452 }
2453 
2454 /* token string handling */
2455 
tok_str_new(TokenString * s)2456 static inline void tok_str_new(TokenString *s)
2457 {
2458     s->str = NULL;
2459     s->len = 0;
2460     s->allocated_len = 0;
2461     s->last_line_num = -1;
2462 }
2463 
tok_str_free(int * str)2464 static void tok_str_free(int *str)
2465 {
2466     tcc_free(str);
2467 }
2468 
tok_str_realloc(TokenString * s)2469 static int *tok_str_realloc(TokenString *s)
2470 {
2471     int *str, len;
2472 
2473     if (s->allocated_len == 0) {
2474         len = 8;
2475     } else {
2476         len = s->allocated_len * 2;
2477     }
2478     str = tcc_realloc(s->str, len * sizeof(int));
2479     if (!str)
2480         error("memory full");
2481     s->allocated_len = len;
2482     s->str = str;
2483     return str;
2484 }
2485 
tok_str_add(TokenString * s,int t)2486 static void tok_str_add(TokenString *s, int t)
2487 {
2488     int len, *str;
2489 
2490     len = s->len;
2491     str = s->str;
2492     if (len >= s->allocated_len)
2493         str = tok_str_realloc(s);
2494     str[len++] = t;
2495     s->len = len;
2496 }
2497 
tok_str_add2(TokenString * s,int t,CValue * cv)2498 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2499 {
2500     int len, *str;
2501 
2502     len = s->len;
2503     str = s->str;
2504 
2505     /* allocate space for worst case */
2506     if (len + TOK_MAX_SIZE > s->allocated_len)
2507         str = tok_str_realloc(s);
2508     str[len++] = t;
2509     switch(t) {
2510     case TOK_CINT:
2511     case TOK_CUINT:
2512     case TOK_CCHAR:
2513     case TOK_LCHAR:
2514     case TOK_CFLOAT:
2515     case TOK_LINENUM:
2516         str[len++] = cv->tab[0];
2517         break;
2518     case TOK_PPNUM:
2519     case TOK_STR:
2520     case TOK_LSTR:
2521         {
2522             int nb_words;
2523             CString *cstr;
2524 
2525             nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2526             while ((len + nb_words) > s->allocated_len)
2527                 str = tok_str_realloc(s);
2528             cstr = (CString *)(str + len);
2529             cstr->data = NULL;
2530             cstr->size = cv->cstr->size;
2531             cstr->data_allocated = NULL;
2532             cstr->size_allocated = cstr->size;
2533             memcpy((char *)cstr + sizeof(CString),
2534                    cv->cstr->data, cstr->size);
2535             len += nb_words;
2536         }
2537         break;
2538     case TOK_CDOUBLE:
2539     case TOK_CLLONG:
2540     case TOK_CULLONG:
2541 #if LDOUBLE_SIZE == 8
2542     case TOK_CLDOUBLE:
2543 #endif
2544         str[len++] = cv->tab[0];
2545         str[len++] = cv->tab[1];
2546         break;
2547 #if LDOUBLE_SIZE == 12
2548     case TOK_CLDOUBLE:
2549         str[len++] = cv->tab[0];
2550         str[len++] = cv->tab[1];
2551         str[len++] = cv->tab[2];
2552 #elif LDOUBLE_SIZE != 8
2553 #error add long double size support
2554 #endif
2555         break;
2556     default:
2557         break;
2558     }
2559     s->len = len;
2560 }
2561 
2562 /* add the current parse token in token string 's' */
tok_str_add_tok(TokenString * s)2563 static void tok_str_add_tok(TokenString *s)
2564 {
2565     CValue cval;
2566 
2567     /* save line number info */
2568     if (file->line_num != s->last_line_num) {
2569         s->last_line_num = file->line_num;
2570         cval.i = s->last_line_num;
2571         tok_str_add2(s, TOK_LINENUM, &cval);
2572     }
2573     tok_str_add2(s, tok, &tokc);
2574 }
2575 
2576 #if LDOUBLE_SIZE == 12
2577 #define LDOUBLE_GET(p, cv)                      \
2578         cv.tab[0] = p[0];                       \
2579         cv.tab[1] = p[1];                       \
2580         cv.tab[2] = p[2];
2581 #elif LDOUBLE_SIZE == 8
2582 #define LDOUBLE_GET(p, cv)                      \
2583         cv.tab[0] = p[0];                       \
2584         cv.tab[1] = p[1];
2585 #else
2586 #error add long double size support
2587 #endif
2588 
2589 
2590 /* get a token from an integer array and increment pointer
2591    accordingly. we code it as a macro to avoid pointer aliasing. */
2592 #define TOK_GET(t, p, cv)                       \
2593 {                                               \
2594     t = *p++;                                   \
2595     switch(t) {                                 \
2596     case TOK_CINT:                              \
2597     case TOK_CUINT:                             \
2598     case TOK_CCHAR:                             \
2599     case TOK_LCHAR:                             \
2600     case TOK_CFLOAT:                            \
2601     case TOK_LINENUM:                           \
2602         cv.tab[0] = *p++;                       \
2603         break;                                  \
2604     case TOK_STR:                               \
2605     case TOK_LSTR:                              \
2606     case TOK_PPNUM:                             \
2607         cv.cstr = (CString *)p;                 \
2608         cv.cstr->data = (char *)p + sizeof(CString);\
2609         p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2610         break;                                  \
2611     case TOK_CDOUBLE:                           \
2612     case TOK_CLLONG:                            \
2613     case TOK_CULLONG:                           \
2614         cv.tab[0] = p[0];                       \
2615         cv.tab[1] = p[1];                       \
2616         p += 2;                                 \
2617         break;                                  \
2618     case TOK_CLDOUBLE:                          \
2619         LDOUBLE_GET(p, cv);                     \
2620         p += LDOUBLE_SIZE / 4;                  \
2621         break;                                  \
2622     default:                                    \
2623         break;                                  \
2624     }                                           \
2625 }
2626 
2627 /* defines handling */
define_push(int v,int macro_type,int * str,Sym * first_arg)2628 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2629 {
2630     Sym *s;
2631 
2632     s = sym_push2(&define_stack, v, macro_type, (int)str);
2633     s->next = first_arg;
2634     table_ident[v - TOK_IDENT]->sym_define = s;
2635 }
2636 
2637 /* undefined a define symbol. Its name is just set to zero */
define_undef(Sym * s)2638 static void define_undef(Sym *s)
2639 {
2640     int v;
2641     v = s->v;
2642     if (v >= TOK_IDENT && v < tok_ident)
2643         table_ident[v - TOK_IDENT]->sym_define = NULL;
2644     s->v = 0;
2645 }
2646 
define_find(int v)2647 static inline Sym *define_find(int v)
2648 {
2649     v -= TOK_IDENT;
2650     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2651         return NULL;
2652     return table_ident[v]->sym_define;
2653 }
2654 
2655 /* free define stack until top reaches 'b' */
free_defines(Sym * b)2656 static void free_defines(Sym *b)
2657 {
2658     Sym *top, *top1;
2659     int v;
2660 
2661     top = define_stack;
2662     while (top != b) {
2663         top1 = top->prev;
2664         /* do not free args or predefined defines */
2665         if (top->c)
2666             tok_str_free((int *)top->c);
2667         v = top->v;
2668         if (v >= TOK_IDENT && v < tok_ident)
2669             table_ident[v - TOK_IDENT]->sym_define = NULL;
2670         sym_free(top);
2671         top = top1;
2672     }
2673     define_stack = b;
2674 }
2675 
2676 /* label lookup */
label_find(int v)2677 static Sym *label_find(int v)
2678 {
2679     v -= TOK_IDENT;
2680     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2681         return NULL;
2682     return table_ident[v]->sym_label;
2683 }
2684 
label_push(Sym ** ptop,int v,int flags)2685 static Sym *label_push(Sym **ptop, int v, int flags)
2686 {
2687     Sym *s, **ps;
2688     s = sym_push2(ptop, v, 0, 0);
2689     s->r = flags;
2690     ps = &table_ident[v - TOK_IDENT]->sym_label;
2691     if (ptop == &global_label_stack) {
2692         /* modify the top most local identifier, so that
2693            sym_identifier will point to 's' when popped */
2694         while (*ps != NULL)
2695             ps = &(*ps)->prev_tok;
2696     }
2697     s->prev_tok = *ps;
2698     *ps = s;
2699     return s;
2700 }
2701 
2702 /* pop labels until element last is reached. Look if any labels are
2703    undefined. Define symbols if '&&label' was used. */
label_pop(Sym ** ptop,Sym * slast)2704 static void label_pop(Sym **ptop, Sym *slast)
2705 {
2706     Sym *s, *s1;
2707     for(s = *ptop; s != slast; s = s1) {
2708         s1 = s->prev;
2709         if (s->r == LABEL_DECLARED) {
2710             warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2711         } else if (s->r == LABEL_FORWARD) {
2712                 error("label '%s' used but not defined",
2713                       get_tok_str(s->v, NULL));
2714         } else {
2715             if (s->c) {
2716                 /* define corresponding symbol. A size of
2717                    1 is put. */
2718                 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2719             }
2720         }
2721         /* remove label */
2722         table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2723         sym_free(s);
2724     }
2725     *ptop = slast;
2726 }
2727 
2728 /* eval an expression for #if/#elif */
expr_preprocess(void)2729 static int expr_preprocess(void)
2730 {
2731     int c, t;
2732     TokenString str;
2733 
2734     tok_str_new(&str);
2735     while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2736         next(); /* do macro subst */
2737         if (tok == TOK_DEFINED) {
2738             next_nomacro();
2739             t = tok;
2740             if (t == '(')
2741                 next_nomacro();
2742             c = define_find(tok) != 0;
2743             if (t == '(')
2744                 next_nomacro();
2745             tok = TOK_CINT;
2746             tokc.i = c;
2747         } else if (tok >= TOK_IDENT) {
2748             /* if undefined macro */
2749             tok = TOK_CINT;
2750             tokc.i = 0;
2751         }
2752         tok_str_add_tok(&str);
2753     }
2754     tok_str_add(&str, -1); /* simulate end of file */
2755     tok_str_add(&str, 0);
2756     /* now evaluate C constant expression */
2757     macro_ptr = str.str;
2758     next();
2759     c = expr_const();
2760     macro_ptr = NULL;
2761     tok_str_free(str.str);
2762     return c != 0;
2763 }
2764 
2765 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
tok_print(int * str)2766 static void tok_print(int *str)
2767 {
2768     int t;
2769     CValue cval;
2770 
2771     while (1) {
2772         TOK_GET(t, str, cval);
2773         if (!t)
2774             break;
2775         printf(" %s", get_tok_str(t, &cval));
2776     }
2777     printf("\n");
2778 }
2779 #endif
2780 
2781 /* parse after #define */
parse_define(void)2782 static void parse_define(void)
2783 {
2784     Sym *s, *first, **ps;
2785     int v, t, varg, is_vaargs, c;
2786     TokenString str;
2787 
2788     v = tok;
2789     if (v < TOK_IDENT)
2790         error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2791     /* XXX: should check if same macro (ANSI) */
2792     first = NULL;
2793     t = MACRO_OBJ;
2794     /* '(' must be just after macro definition for MACRO_FUNC */
2795     c = file->buf_ptr[0];
2796     if (c == '\\')
2797         c = handle_stray1(file->buf_ptr);
2798     if (c == '(') {
2799         next_nomacro();
2800         next_nomacro();
2801         ps = &first;
2802         while (tok != ')') {
2803             varg = tok;
2804             next_nomacro();
2805             is_vaargs = 0;
2806             if (varg == TOK_DOTS) {
2807                 varg = TOK___VA_ARGS__;
2808                 is_vaargs = 1;
2809             } else if (tok == TOK_DOTS && gnu_ext) {
2810                 is_vaargs = 1;
2811                 next_nomacro();
2812             }
2813             if (varg < TOK_IDENT)
2814                 error("badly punctuated parameter list");
2815             s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2816             *ps = s;
2817             ps = &s->next;
2818             if (tok != ',')
2819                 break;
2820             next_nomacro();
2821         }
2822         t = MACRO_FUNC;
2823     }
2824     tok_str_new(&str);
2825     next_nomacro();
2826     /* EOF testing necessary for '-D' handling */
2827     while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2828         tok_str_add2(&str, tok, &tokc);
2829         next_nomacro();
2830     }
2831     tok_str_add(&str, 0);
2832 #ifdef PP_DEBUG
2833     printf("define %s %d: ", get_tok_str(v, NULL), t);
2834     tok_print(str.str);
2835 #endif
2836     define_push(v, t, str.str, first);
2837 }
2838 
hash_cached_include(int type,const char * filename)2839 static inline int hash_cached_include(int type, const char *filename)
2840 {
2841     const unsigned char *s;
2842     unsigned int h;
2843 
2844     h = TOK_HASH_INIT;
2845     h = TOK_HASH_FUNC(h, type);
2846     s = filename;
2847     while (*s) {
2848         h = TOK_HASH_FUNC(h, *s);
2849         s++;
2850     }
2851     h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2852     return h;
2853 }
2854 
2855 /* XXX: use a token or a hash table to accelerate matching ? */
search_cached_include(TCCState * s1,int type,const char * filename)2856 static CachedInclude *search_cached_include(TCCState *s1,
2857                                             int type, const char *filename)
2858 {
2859     CachedInclude *e;
2860     int i, h;
2861     h = hash_cached_include(type, filename);
2862     i = s1->cached_includes_hash[h];
2863     for(;;) {
2864         if (i == 0)
2865             break;
2866         e = s1->cached_includes[i - 1];
2867         if (e->type == type && !strcmp(e->filename, filename))
2868             return e;
2869         i = e->hash_next;
2870     }
2871     return NULL;
2872 }
2873 
add_cached_include(TCCState * s1,int type,const char * filename,int ifndef_macro)2874 static inline void add_cached_include(TCCState *s1, int type,
2875                                       const char *filename, int ifndef_macro)
2876 {
2877     CachedInclude *e;
2878     int h;
2879 
2880     if (search_cached_include(s1, type, filename))
2881         return;
2882 #ifdef INC_DEBUG
2883     printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2884 #endif
2885     e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2886     if (!e)
2887         return;
2888     e->type = type;
2889     strcpy(e->filename, filename);
2890     e->ifndef_macro = ifndef_macro;
2891     dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2892     /* add in hash table */
2893     h = hash_cached_include(type, filename);
2894     e->hash_next = s1->cached_includes_hash[h];
2895     s1->cached_includes_hash[h] = s1->nb_cached_includes;
2896 }
2897 
pragma_parse(TCCState * s1)2898 static void pragma_parse(TCCState *s1)
2899 {
2900     int val;
2901 
2902     next();
2903     if (tok == TOK_pack) {
2904         /*
2905           This may be:
2906           #pragma pack(1) // set
2907           #pragma pack() // reset to default
2908           #pragma pack(push,1) // push & set
2909           #pragma pack(pop) // restore previous
2910         */
2911         next();
2912         skip('(');
2913         if (tok == TOK_ASM_pop) {
2914             next();
2915             if (s1->pack_stack_ptr <= s1->pack_stack) {
2916             stk_error:
2917                 error("out of pack stack");
2918             }
2919             s1->pack_stack_ptr--;
2920         } else {
2921             val = 0;
2922             if (tok != ')') {
2923                 if (tok == TOK_ASM_push) {
2924                     next();
2925                     if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2926                         goto stk_error;
2927                     s1->pack_stack_ptr++;
2928                     skip(',');
2929                 }
2930                 if (tok != TOK_CINT) {
2931                 pack_error:
2932                     error("invalid pack pragma");
2933                 }
2934                 val = tokc.i;
2935                 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2936                     goto pack_error;
2937                 next();
2938             }
2939             *s1->pack_stack_ptr = val;
2940             skip(')');
2941         }
2942     }
2943 }
2944 
2945 /* is_bof is true if first non space token at beginning of file */
preprocess(int is_bof)2946 static void preprocess(int is_bof)
2947 {
2948     TCCState *s1 = tcc_state;
2949     int size, i, c, n, saved_parse_flags;
2950     char buf[1024], *q;
2951     char buf1[1024];
2952     BufferedFile *f;
2953     Sym *s;
2954     CachedInclude *e;
2955 
2956     saved_parse_flags = parse_flags;
2957     parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2958         PARSE_FLAG_LINEFEED;
2959     next_nomacro();
2960  redo:
2961     switch(tok) {
2962     case TOK_DEFINE:
2963         next_nomacro();
2964         parse_define();
2965         break;
2966     case TOK_UNDEF:
2967         next_nomacro();
2968         s = define_find(tok);
2969         /* undefine symbol by putting an invalid name */
2970         if (s)
2971             define_undef(s);
2972         break;
2973     case TOK_INCLUDE:
2974     case TOK_INCLUDE_NEXT:
2975         ch = file->buf_ptr[0];
2976         /* XXX: incorrect if comments : use next_nomacro with a special mode */
2977         skip_spaces();
2978         if (ch == '<') {
2979             c = '>';
2980             goto read_name;
2981         } else if (ch == '\"') {
2982             c = ch;
2983         read_name:
2984             inp();
2985             q = buf;
2986             while (ch != c && ch != '\n' && ch != CH_EOF) {
2987                 if ((q - buf) < sizeof(buf) - 1)
2988                     *q++ = ch;
2989                 if (ch == '\\') {
2990                     if (handle_stray_noerror() == 0)
2991                         --q;
2992                 } else
2993                     inp();
2994             }
2995             *q = '\0';
2996             minp();
2997 #if 0
2998             /* eat all spaces and comments after include */
2999             /* XXX: slightly incorrect */
3000             while (ch1 != '\n' && ch1 != CH_EOF)
3001                 inp();
3002 #endif
3003         } else {
3004             /* computed #include : either we have only strings or
3005                we have anything enclosed in '<>' */
3006             next();
3007             buf[0] = '\0';
3008             if (tok == TOK_STR) {
3009                 while (tok != TOK_LINEFEED) {
3010                     if (tok != TOK_STR) {
3011                     include_syntax:
3012                         error("'#include' expects \"FILENAME\" or <FILENAME>");
3013                     }
3014                     pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3015                     next();
3016                 }
3017                 c = '\"';
3018             } else {
3019                 int len;
3020                 while (tok != TOK_LINEFEED) {
3021                     pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3022                     next();
3023                 }
3024                 len = strlen(buf);
3025                 /* check syntax and remove '<>' */
3026                 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3027                     goto include_syntax;
3028                 memmove(buf, buf + 1, len - 2);
3029                 buf[len - 2] = '\0';
3030                 c = '>';
3031             }
3032         }
3033 
3034         e = search_cached_include(s1, c, buf);
3035         if (e && define_find(e->ifndef_macro)) {
3036             /* no need to parse the include because the 'ifndef macro'
3037                is defined */
3038 #ifdef INC_DEBUG
3039             printf("%s: skipping %s\n", file->filename, buf);
3040 #endif
3041         } else {
3042             if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3043                 error("#include recursion too deep");
3044             /* push current file in stack */
3045             /* XXX: fix current line init */
3046             *s1->include_stack_ptr++ = file;
3047             if (c == '\"') {
3048                 /* first search in current dir if "header.h" */
3049                 size = tcc_basename(file->filename) - file->filename;
3050                 if (size > sizeof(buf1) - 1)
3051                     size = sizeof(buf1) - 1;
3052                 memcpy(buf1, file->filename, size);
3053                 buf1[size] = '\0';
3054                 pstrcat(buf1, sizeof(buf1), buf);
3055                 f = tcc_open(s1, buf1);
3056                 if (f) {
3057                     if (tok == TOK_INCLUDE_NEXT)
3058                         tok = TOK_INCLUDE;
3059                     else
3060                         goto found;
3061                 }
3062             }
3063             /* now search in all the include paths */
3064             n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3065             for(i = 0; i < n; i++) {
3066                 const char *path;
3067                 if (i < s1->nb_include_paths)
3068                     path = s1->include_paths[i];
3069                 else
3070                     path = s1->sysinclude_paths[i - s1->nb_include_paths];
3071                 pstrcpy(buf1, sizeof(buf1), path);
3072                 pstrcat(buf1, sizeof(buf1), "/");
3073                 pstrcat(buf1, sizeof(buf1), buf);
3074                 f = tcc_open(s1, buf1);
3075                 if (f) {
3076                     if (tok == TOK_INCLUDE_NEXT)
3077                         tok = TOK_INCLUDE;
3078                     else
3079                         goto found;
3080                 }
3081             }
3082             --s1->include_stack_ptr;
3083             error("include file '%s' not found", buf);
3084             break;
3085         found:
3086 #ifdef INC_DEBUG
3087             printf("%s: including %s\n", file->filename, buf1);
3088 #endif
3089             f->inc_type = c;
3090             pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3091             file = f;
3092             /* add include file debug info */
3093             if (do_debug) {
3094                 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3095             }
3096             tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3097             ch = file->buf_ptr[0];
3098             goto the_end;
3099         }
3100         break;
3101     case TOK_IFNDEF:
3102         c = 1;
3103         goto do_ifdef;
3104     case TOK_IF:
3105         c = expr_preprocess();
3106         goto do_if;
3107     case TOK_IFDEF:
3108         c = 0;
3109     do_ifdef:
3110         next_nomacro();
3111         if (tok < TOK_IDENT)
3112             error("invalid argument for '#if%sdef'", c ? "n" : "");
3113         if (is_bof) {
3114             if (c) {
3115 #ifdef INC_DEBUG
3116                 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3117 #endif
3118                 file->ifndef_macro = tok;
3119             }
3120         }
3121         c = (define_find(tok) != 0) ^ c;
3122     do_if:
3123         if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3124             error("memory full");
3125         *s1->ifdef_stack_ptr++ = c;
3126         goto test_skip;
3127     case TOK_ELSE:
3128         if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3129             error("#else without matching #if");
3130         if (s1->ifdef_stack_ptr[-1] & 2)
3131             error("#else after #else");
3132         c = (s1->ifdef_stack_ptr[-1] ^= 3);
3133         goto test_skip;
3134     case TOK_ELIF:
3135         if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3136             error("#elif without matching #if");
3137         c = s1->ifdef_stack_ptr[-1];
3138         if (c > 1)
3139             error("#elif after #else");
3140         /* last #if/#elif expression was true: we skip */
3141         if (c == 1)
3142             goto skip;
3143         c = expr_preprocess();
3144         s1->ifdef_stack_ptr[-1] = c;
3145     test_skip:
3146         if (!(c & 1)) {
3147         skip:
3148             preprocess_skip();
3149             is_bof = 0;
3150             goto redo;
3151         }
3152         break;
3153     case TOK_ENDIF:
3154         if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3155             error("#endif without matching #if");
3156         s1->ifdef_stack_ptr--;
3157         /* '#ifndef macro' was at the start of file. Now we check if
3158            an '#endif' is exactly at the end of file */
3159         if (file->ifndef_macro &&
3160             s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3161             file->ifndef_macro_saved = file->ifndef_macro;
3162             /* need to set to zero to avoid false matches if another
3163                #ifndef at middle of file */
3164             file->ifndef_macro = 0;
3165             while (tok != TOK_LINEFEED)
3166                 next_nomacro();
3167             tok_flags |= TOK_FLAG_ENDIF;
3168             goto the_end;
3169         }
3170         break;
3171     case TOK_LINE:
3172         next();
3173         if (tok != TOK_CINT)
3174             error("#line");
3175         file->line_num = tokc.i - 1; /* the line number will be incremented after */
3176         next();
3177         if (tok != TOK_LINEFEED) {
3178             if (tok != TOK_STR)
3179                 error("#line");
3180             pstrcpy(file->filename, sizeof(file->filename),
3181                     (char *)tokc.cstr->data);
3182         }
3183         break;
3184     case TOK_ERROR:
3185     case TOK_WARNING:
3186         c = tok;
3187         ch = file->buf_ptr[0];
3188         skip_spaces();
3189         q = buf;
3190         while (ch != '\n' && ch != CH_EOF) {
3191             if ((q - buf) < sizeof(buf) - 1)
3192                 *q++ = ch;
3193             if (ch == '\\') {
3194                 if (handle_stray_noerror() == 0)
3195                     --q;
3196             } else
3197                 inp();
3198         }
3199         *q = '\0';
3200         if (c == TOK_ERROR)
3201             error("#error %s", buf);
3202         else
3203             warning("#warning %s", buf);
3204         break;
3205     case TOK_PRAGMA:
3206         pragma_parse(s1);
3207         break;
3208     default:
3209         if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3210             /* '!' is ignored to allow C scripts. numbers are ignored
3211                to emulate cpp behaviour */
3212         } else {
3213             if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3214                 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3215         }
3216         break;
3217     }
3218     /* ignore other preprocess commands or #! for C scripts */
3219     while (tok != TOK_LINEFEED)
3220         next_nomacro();
3221  the_end:
3222     parse_flags = saved_parse_flags;
3223 }
3224 
3225 /* evaluate escape codes in a string. */
parse_escape_string(CString * outstr,const uint8_t * buf,int is_long)3226 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3227 {
3228     int c, n;
3229     const uint8_t *p;
3230 
3231     p = buf;
3232     for(;;) {
3233         c = *p;
3234         if (c == '\0')
3235             break;
3236         if (c == '\\') {
3237             p++;
3238             /* escape */
3239             c = *p;
3240             switch(c) {
3241             case '0': case '1': case '2': case '3':
3242             case '4': case '5': case '6': case '7':
3243                 /* at most three octal digits */
3244                 n = c - '0';
3245                 p++;
3246                 c = *p;
3247                 if (isoct(c)) {
3248                     n = n * 8 + c - '0';
3249                     p++;
3250                     c = *p;
3251                     if (isoct(c)) {
3252                         n = n * 8 + c - '0';
3253                         p++;
3254                     }
3255                 }
3256                 c = n;
3257                 goto add_char_nonext;
3258             case 'x':
3259             case 'u':
3260             case 'U':
3261                 p++;
3262                 n = 0;
3263                 for(;;) {
3264                     c = *p;
3265                     if (c >= 'a' && c <= 'f')
3266                         c = c - 'a' + 10;
3267                     else if (c >= 'A' && c <= 'F')
3268                         c = c - 'A' + 10;
3269                     else if (isnum(c))
3270                         c = c - '0';
3271                     else
3272                         break;
3273                     n = n * 16 + c;
3274                     p++;
3275                 }
3276                 c = n;
3277                 goto add_char_nonext;
3278             case 'a':
3279                 c = '\a';
3280                 break;
3281             case 'b':
3282                 c = '\b';
3283                 break;
3284             case 'f':
3285                 c = '\f';
3286                 break;
3287             case 'n':
3288                 c = '\n';
3289                 break;
3290             case 'r':
3291                 c = '\r';
3292                 break;
3293             case 't':
3294                 c = '\t';
3295                 break;
3296             case 'v':
3297                 c = '\v';
3298                 break;
3299             case 'e':
3300                 if (!gnu_ext)
3301                     goto invalid_escape;
3302                 c = 27;
3303                 break;
3304             case '\'':
3305             case '\"':
3306             case '\\':
3307             case '?':
3308                 break;
3309             default:
3310             invalid_escape:
3311                 if (c >= '!' && c <= '~')
3312                     warning("unknown escape sequence: \'\\%c\'", c);
3313                 else
3314                     warning("unknown escape sequence: \'\\x%x\'", c);
3315                 break;
3316             }
3317         }
3318         p++;
3319     add_char_nonext:
3320         if (!is_long)
3321             cstr_ccat(outstr, c);
3322         else
3323             cstr_wccat(outstr, c);
3324     }
3325     /* add a trailing '\0' */
3326     if (!is_long)
3327         cstr_ccat(outstr, '\0');
3328     else
3329         cstr_wccat(outstr, '\0');
3330 }
3331 
3332 /* we use 64 bit numbers */
3333 #define BN_SIZE 2
3334 
3335 /* bn = (bn << shift) | or_val */
bn_lshift(unsigned int * bn,int shift,int or_val)3336 void bn_lshift(unsigned int *bn, int shift, int or_val)
3337 {
3338     int i;
3339     unsigned int v;
3340     for(i=0;i<BN_SIZE;i++) {
3341         v = bn[i];
3342         bn[i] = (v << shift) | or_val;
3343         or_val = v >> (32 - shift);
3344     }
3345 }
3346 
bn_zero(unsigned int * bn)3347 void bn_zero(unsigned int *bn)
3348 {
3349     int i;
3350     for(i=0;i<BN_SIZE;i++) {
3351         bn[i] = 0;
3352     }
3353 }
3354 
3355 /* parse number in null terminated string 'p' and return it in the
3356    current token */
parse_number(const char * p)3357 void parse_number(const char *p)
3358 {
3359     int b, t, shift, frac_bits, s, exp_val, ch;
3360     char *q;
3361     unsigned int bn[BN_SIZE];
3362     double d;
3363 
3364     /* number */
3365     q = token_buf;
3366     ch = *p++;
3367     t = ch;
3368     ch = *p++;
3369     *q++ = t;
3370     b = 10;
3371     if (t == '.') {
3372         goto float_frac_parse;
3373     } else if (t == '0') {
3374         if (ch == 'x' || ch == 'X') {
3375             q--;
3376             ch = *p++;
3377             b = 16;
3378         } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3379             q--;
3380             ch = *p++;
3381             b = 2;
3382         }
3383     }
3384     /* parse all digits. cannot check octal numbers at this stage
3385        because of floating point constants */
3386     while (1) {
3387         if (ch >= 'a' && ch <= 'f')
3388             t = ch - 'a' + 10;
3389         else if (ch >= 'A' && ch <= 'F')
3390             t = ch - 'A' + 10;
3391         else if (isnum(ch))
3392             t = ch - '0';
3393         else
3394             break;
3395         if (t >= b)
3396             break;
3397         if (q >= token_buf + STRING_MAX_SIZE) {
3398         num_too_long:
3399             error("number too long");
3400         }
3401         *q++ = ch;
3402         ch = *p++;
3403     }
3404     if (ch == '.' ||
3405         ((ch == 'e' || ch == 'E') && b == 10) ||
3406         ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3407         if (b != 10) {
3408             /* NOTE: strtox should support that for hexa numbers, but
3409                non ISOC99 libcs do not support it, so we prefer to do
3410                it by hand */
3411             /* hexadecimal or binary floats */
3412             /* XXX: handle overflows */
3413             *q = '\0';
3414             if (b == 16)
3415                 shift = 4;
3416             else
3417                 shift = 2;
3418             bn_zero(bn);
3419             q = token_buf;
3420             while (1) {
3421                 t = *q++;
3422                 if (t == '\0') {
3423                     break;
3424                 } else if (t >= 'a') {
3425                     t = t - 'a' + 10;
3426                 } else if (t >= 'A') {
3427                     t = t - 'A' + 10;
3428                 } else {
3429                     t = t - '0';
3430                 }
3431                 bn_lshift(bn, shift, t);
3432             }
3433             frac_bits = 0;
3434             if (ch == '.') {
3435                 ch = *p++;
3436                 while (1) {
3437                     t = ch;
3438                     if (t >= 'a' && t <= 'f') {
3439                         t = t - 'a' + 10;
3440                     } else if (t >= 'A' && t <= 'F') {
3441                         t = t - 'A' + 10;
3442                     } else if (t >= '0' && t <= '9') {
3443                         t = t - '0';
3444                     } else {
3445                         break;
3446                     }
3447                     if (t >= b)
3448                         error("invalid digit");
3449                     bn_lshift(bn, shift, t);
3450                     frac_bits += shift;
3451                     ch = *p++;
3452                 }
3453             }
3454             if (ch != 'p' && ch != 'P')
3455                 expect("exponent");
3456             ch = *p++;
3457             s = 1;
3458             exp_val = 0;
3459             if (ch == '+') {
3460                 ch = *p++;
3461             } else if (ch == '-') {
3462                 s = -1;
3463                 ch = *p++;
3464             }
3465             if (ch < '0' || ch > '9')
3466                 expect("exponent digits");
3467             while (ch >= '0' && ch <= '9') {
3468                 exp_val = exp_val * 10 + ch - '0';
3469                 ch = *p++;
3470             }
3471             exp_val = exp_val * s;
3472 
3473             /* now we can generate the number */
3474             /* XXX: should patch directly float number */
3475             d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3476             d = ldexp(d, exp_val - frac_bits);
3477             t = toup(ch);
3478             if (t == 'F') {
3479                 ch = *p++;
3480                 tok = TOK_CFLOAT;
3481                 /* float : should handle overflow */
3482                 tokc.f = (float)d;
3483             } else if (t == 'L') {
3484                 ch = *p++;
3485                 tok = TOK_CLDOUBLE;
3486                 /* XXX: not large enough */
3487                 tokc.ld = (long double)d;
3488             } else {
3489                 tok = TOK_CDOUBLE;
3490                 tokc.d = d;
3491             }
3492         } else {
3493             /* decimal floats */
3494             if (ch == '.') {
3495                 if (q >= token_buf + STRING_MAX_SIZE)
3496                     goto num_too_long;
3497                 *q++ = ch;
3498                 ch = *p++;
3499             float_frac_parse:
3500                 while (ch >= '0' && ch <= '9') {
3501                     if (q >= token_buf + STRING_MAX_SIZE)
3502                         goto num_too_long;
3503                     *q++ = ch;
3504                     ch = *p++;
3505                 }
3506             }
3507             if (ch == 'e' || ch == 'E') {
3508                 if (q >= token_buf + STRING_MAX_SIZE)
3509                     goto num_too_long;
3510                 *q++ = ch;
3511                 ch = *p++;
3512                 if (ch == '-' || ch == '+') {
3513                     if (q >= token_buf + STRING_MAX_SIZE)
3514                         goto num_too_long;
3515                     *q++ = ch;
3516                     ch = *p++;
3517                 }
3518                 if (ch < '0' || ch > '9')
3519                     expect("exponent digits");
3520                 while (ch >= '0' && ch <= '9') {
3521                     if (q >= token_buf + STRING_MAX_SIZE)
3522                         goto num_too_long;
3523                     *q++ = ch;
3524                     ch = *p++;
3525                 }
3526             }
3527             *q = '\0';
3528             t = toup(ch);
3529             errno = 0;
3530             if (t == 'F') {
3531                 ch = *p++;
3532                 tok = TOK_CFLOAT;
3533                 tokc.f = strtof(token_buf, NULL);
3534             } else if (t == 'L') {
3535                 ch = *p++;
3536                 tok = TOK_CLDOUBLE;
3537                 tokc.ld = strtold(token_buf, NULL);
3538             } else {
3539                 tok = TOK_CDOUBLE;
3540                 tokc.d = strtod(token_buf, NULL);
3541             }
3542         }
3543     } else {
3544         unsigned long long n, n1;
3545         int lcount, ucount;
3546 
3547         /* integer number */
3548         *q = '\0';
3549         q = token_buf;
3550         if (b == 10 && *q == '0') {
3551             b = 8;
3552             q++;
3553         }
3554         n = 0;
3555         while(1) {
3556             t = *q++;
3557             /* no need for checks except for base 10 / 8 errors */
3558             if (t == '\0') {
3559                 break;
3560             } else if (t >= 'a') {
3561                 t = t - 'a' + 10;
3562             } else if (t >= 'A') {
3563                 t = t - 'A' + 10;
3564             } else {
3565                 t = t - '0';
3566                 if (t >= b)
3567                     error("invalid digit");
3568             }
3569             n1 = n;
3570             n = n * b + t;
3571             /* detect overflow */
3572             /* XXX: this test is not reliable */
3573             if (n < n1)
3574                 error("integer constant overflow");
3575         }
3576 
3577         /* XXX: not exactly ANSI compliant */
3578         if ((n & 0xffffffff00000000LL) != 0) {
3579             if ((n >> 63) != 0)
3580                 tok = TOK_CULLONG;
3581             else
3582                 tok = TOK_CLLONG;
3583         } else if (n > 0x7fffffff) {
3584             tok = TOK_CUINT;
3585         } else {
3586             tok = TOK_CINT;
3587         }
3588         lcount = 0;
3589         ucount = 0;
3590         for(;;) {
3591             t = toup(ch);
3592             if (t == 'L') {
3593                 if (lcount >= 2)
3594                     error("three 'l's in integer constant");
3595                 lcount++;
3596                 if (lcount == 2) {
3597                     if (tok == TOK_CINT)
3598                         tok = TOK_CLLONG;
3599                     else if (tok == TOK_CUINT)
3600                         tok = TOK_CULLONG;
3601                 }
3602                 ch = *p++;
3603             } else if (t == 'U') {
3604                 if (ucount >= 1)
3605                     error("two 'u's in integer constant");
3606                 ucount++;
3607                 if (tok == TOK_CINT)
3608                     tok = TOK_CUINT;
3609                 else if (tok == TOK_CLLONG)
3610                     tok = TOK_CULLONG;
3611                 ch = *p++;
3612             } else {
3613                 break;
3614             }
3615         }
3616         if (tok == TOK_CINT || tok == TOK_CUINT)
3617             tokc.ui = n;
3618         else
3619             tokc.ull = n;
3620     }
3621 }
3622 
3623 
3624 #define PARSE2(c1, tok1, c2, tok2)              \
3625     case c1:                                    \
3626         PEEKC(c, p);                            \
3627         if (c == c2) {                          \
3628             p++;                                \
3629             tok = tok2;                         \
3630         } else {                                \
3631             tok = tok1;                         \
3632         }                                       \
3633         break;
3634 
3635 /* return next token without macro substitution */
next_nomacro1(void)3636 static inline void next_nomacro1(void)
3637 {
3638     int t, c, is_long;
3639     TokenSym *ts;
3640     uint8_t *p, *p1;
3641     unsigned int h;
3642 
3643     p = file->buf_ptr;
3644  redo_no_start:
3645     c = *p;
3646     switch(c) {
3647     case ' ':
3648     case '\t':
3649     case '\f':
3650     case '\v':
3651     case '\r':
3652         p++;
3653         goto redo_no_start;
3654 
3655     case '\\':
3656         /* first look if it is in fact an end of buffer */
3657         if (p >= file->buf_end) {
3658             file->buf_ptr = p;
3659             handle_eob();
3660             p = file->buf_ptr;
3661             if (p >= file->buf_end)
3662                 goto parse_eof;
3663             else
3664                 goto redo_no_start;
3665         } else {
3666             file->buf_ptr = p;
3667             ch = *p;
3668             handle_stray();
3669             p = file->buf_ptr;
3670             goto redo_no_start;
3671         }
3672     parse_eof:
3673         {
3674             TCCState *s1 = tcc_state;
3675             if ((parse_flags & PARSE_FLAG_LINEFEED)
3676                 && !(tok_flags & TOK_FLAG_EOF)) {
3677                 tok_flags |= TOK_FLAG_EOF;
3678                 tok = TOK_LINEFEED;
3679                 goto keep_tok_flags;
3680             } else if (s1->include_stack_ptr == s1->include_stack ||
3681                        !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3682                 /* no include left : end of file. */
3683                 tok = TOK_EOF;
3684             } else {
3685                 tok_flags &= ~TOK_FLAG_EOF;
3686                 /* pop include file */
3687 
3688                 /* test if previous '#endif' was after a #ifdef at
3689                    start of file */
3690                 if (tok_flags & TOK_FLAG_ENDIF) {
3691 #ifdef INC_DEBUG
3692                     printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3693 #endif
3694                     add_cached_include(s1, file->inc_type, file->inc_filename,
3695                                        file->ifndef_macro_saved);
3696                 }
3697 
3698                 /* add end of include file debug info */
3699                 if (do_debug) {
3700                     put_stabd(N_EINCL, 0, 0);
3701                 }
3702                 /* pop include stack */
3703                 tcc_close(file);
3704                 s1->include_stack_ptr--;
3705                 file = *s1->include_stack_ptr;
3706                 p = file->buf_ptr;
3707                 goto redo_no_start;
3708             }
3709         }
3710         break;
3711 
3712     case '\n':
3713         file->line_num++;
3714         tok_flags |= TOK_FLAG_BOL;
3715         p++;
3716         if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3717             goto redo_no_start;
3718         tok = TOK_LINEFEED;
3719         goto keep_tok_flags;
3720 
3721     case '#':
3722         /* XXX: simplify */
3723         PEEKC(c, p);
3724         if ((tok_flags & TOK_FLAG_BOL) &&
3725             (parse_flags & PARSE_FLAG_PREPROCESS)) {
3726             file->buf_ptr = p;
3727             preprocess(tok_flags & TOK_FLAG_BOF);
3728             p = file->buf_ptr;
3729             goto redo_no_start;
3730         } else {
3731             if (c == '#') {
3732                 p++;
3733                 tok = TOK_TWOSHARPS;
3734             } else {
3735                 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3736                     p = parse_line_comment(p - 1);
3737                     goto redo_no_start;
3738                 } else {
3739                     tok = '#';
3740                 }
3741             }
3742         }
3743         break;
3744 
3745     case 'a': case 'b': case 'c': case 'd':
3746     case 'e': case 'f': case 'g': case 'h':
3747     case 'i': case 'j': case 'k': case 'l':
3748     case 'm': case 'n': case 'o': case 'p':
3749     case 'q': case 'r': case 's': case 't':
3750     case 'u': case 'v': case 'w': case 'x':
3751     case 'y': case 'z':
3752     case 'A': case 'B': case 'C': case 'D':
3753     case 'E': case 'F': case 'G': case 'H':
3754     case 'I': case 'J': case 'K':
3755     case 'M': case 'N': case 'O': case 'P':
3756     case 'Q': case 'R': case 'S': case 'T':
3757     case 'U': case 'V': case 'W': case 'X':
3758     case 'Y': case 'Z':
3759     case '_':
3760     parse_ident_fast:
3761         p1 = p;
3762         h = TOK_HASH_INIT;
3763         h = TOK_HASH_FUNC(h, c);
3764         p++;
3765         for(;;) {
3766             c = *p;
3767             if (!isidnum_table[c])
3768                 break;
3769             h = TOK_HASH_FUNC(h, c);
3770             p++;
3771         }
3772         if (c != '\\') {
3773             TokenSym **pts;
3774             int len;
3775 
3776             /* fast case : no stray found, so we have the full token
3777                and we have already hashed it */
3778             len = p - p1;
3779             h &= (TOK_HASH_SIZE - 1);
3780             pts = &hash_ident[h];
3781             for(;;) {
3782                 ts = *pts;
3783                 if (!ts)
3784                     break;
3785                 if (ts->len == len && !memcmp(ts->str, p1, len))
3786                     goto token_found;
3787                 pts = &(ts->hash_next);
3788             }
3789             ts = tok_alloc_new(pts, p1, len);
3790         token_found: ;
3791         } else {
3792             /* slower case */
3793             cstr_reset(&tokcstr);
3794 
3795             while (p1 < p) {
3796                 cstr_ccat(&tokcstr, *p1);
3797                 p1++;
3798             }
3799             p--;
3800             PEEKC(c, p);
3801         parse_ident_slow:
3802             while (isidnum_table[c]) {
3803                 cstr_ccat(&tokcstr, c);
3804                 PEEKC(c, p);
3805             }
3806             ts = tok_alloc(tokcstr.data, tokcstr.size);
3807         }
3808         tok = ts->tok;
3809         break;
3810     case 'L':
3811         t = p[1];
3812         if (t != '\\' && t != '\'' && t != '\"') {
3813             /* fast case */
3814             goto parse_ident_fast;
3815         } else {
3816             PEEKC(c, p);
3817             if (c == '\'' || c == '\"') {
3818                 is_long = 1;
3819                 goto str_const;
3820             } else {
3821                 cstr_reset(&tokcstr);
3822                 cstr_ccat(&tokcstr, 'L');
3823                 goto parse_ident_slow;
3824             }
3825         }
3826         break;
3827     case '0': case '1': case '2': case '3':
3828     case '4': case '5': case '6': case '7':
3829     case '8': case '9':
3830 
3831         cstr_reset(&tokcstr);
3832         /* after the first digit, accept digits, alpha, '.' or sign if
3833            prefixed by 'eEpP' */
3834     parse_num:
3835         for(;;) {
3836             t = c;
3837             cstr_ccat(&tokcstr, c);
3838             PEEKC(c, p);
3839             if (!(isnum(c) || isid(c) || c == '.' ||
3840                   ((c == '+' || c == '-') &&
3841                    (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3842                 break;
3843         }
3844         /* We add a trailing '\0' to ease parsing */
3845         cstr_ccat(&tokcstr, '\0');
3846         tokc.cstr = &tokcstr;
3847         tok = TOK_PPNUM;
3848         break;
3849     case '.':
3850         /* special dot handling because it can also start a number */
3851         PEEKC(c, p);
3852         if (isnum(c)) {
3853             cstr_reset(&tokcstr);
3854             cstr_ccat(&tokcstr, '.');
3855             goto parse_num;
3856         } else if (c == '.') {
3857             PEEKC(c, p);
3858             if (c != '.')
3859                 expect("'.'");
3860             PEEKC(c, p);
3861             tok = TOK_DOTS;
3862         } else {
3863             tok = '.';
3864         }
3865         break;
3866     case '\'':
3867     case '\"':
3868         is_long = 0;
3869     str_const:
3870         {
3871             CString str;
3872             int sep;
3873 
3874             sep = c;
3875 
3876             /* parse the string */
3877             cstr_new(&str);
3878             p = parse_pp_string(p, sep, &str);
3879             cstr_ccat(&str, '\0');
3880 
3881             /* eval the escape (should be done as TOK_PPNUM) */
3882             cstr_reset(&tokcstr);
3883             parse_escape_string(&tokcstr, str.data, is_long);
3884             cstr_free(&str);
3885 
3886             if (sep == '\'') {
3887                 int char_size;
3888                 /* XXX: make it portable */
3889                 if (!is_long)
3890                     char_size = 1;
3891                 else
3892                     char_size = sizeof(nwchar_t);
3893                 if (tokcstr.size <= char_size)
3894                     error("empty character constant");
3895                 if (tokcstr.size > 2 * char_size)
3896                     warning("multi-character character constant");
3897                 if (!is_long) {
3898                     tokc.i = *(int8_t *)tokcstr.data;
3899                     tok = TOK_CCHAR;
3900                 } else {
3901                     tokc.i = *(nwchar_t *)tokcstr.data;
3902                     tok = TOK_LCHAR;
3903                 }
3904             } else {
3905                 tokc.cstr = &tokcstr;
3906                 if (!is_long)
3907                     tok = TOK_STR;
3908                 else
3909                     tok = TOK_LSTR;
3910             }
3911         }
3912         break;
3913 
3914     case '<':
3915         PEEKC(c, p);
3916         if (c == '=') {
3917             p++;
3918             tok = TOK_LE;
3919         } else if (c == '<') {
3920             PEEKC(c, p);
3921             if (c == '=') {
3922                 p++;
3923                 tok = TOK_A_SHL;
3924             } else {
3925                 tok = TOK_SHL;
3926             }
3927         } else {
3928             tok = TOK_LT;
3929         }
3930         break;
3931 
3932     case '>':
3933         PEEKC(c, p);
3934         if (c == '=') {
3935             p++;
3936             tok = TOK_GE;
3937         } else if (c == '>') {
3938             PEEKC(c, p);
3939             if (c == '=') {
3940                 p++;
3941                 tok = TOK_A_SAR;
3942             } else {
3943                 tok = TOK_SAR;
3944             }
3945         } else {
3946             tok = TOK_GT;
3947         }
3948         break;
3949 
3950     case '&':
3951         PEEKC(c, p);
3952         if (c == '&') {
3953             p++;
3954             tok = TOK_LAND;
3955         } else if (c == '=') {
3956             p++;
3957             tok = TOK_A_AND;
3958         } else {
3959             tok = '&';
3960         }
3961         break;
3962 
3963     case '|':
3964         PEEKC(c, p);
3965         if (c == '|') {
3966             p++;
3967             tok = TOK_LOR;
3968         } else if (c == '=') {
3969             p++;
3970             tok = TOK_A_OR;
3971         } else {
3972             tok = '|';
3973         }
3974         break;
3975 
3976     case '+':
3977         PEEKC(c, p);
3978         if (c == '+') {
3979             p++;
3980             tok = TOK_INC;
3981         } else if (c == '=') {
3982             p++;
3983             tok = TOK_A_ADD;
3984         } else {
3985             tok = '+';
3986         }
3987         break;
3988 
3989     case '-':
3990         PEEKC(c, p);
3991         if (c == '-') {
3992             p++;
3993             tok = TOK_DEC;
3994         } else if (c == '=') {
3995             p++;
3996             tok = TOK_A_SUB;
3997         } else if (c == '>') {
3998             p++;
3999             tok = TOK_ARROW;
4000         } else {
4001             tok = '-';
4002         }
4003         break;
4004 
4005     PARSE2('!', '!', '=', TOK_NE)
4006     PARSE2('=', '=', '=', TOK_EQ)
4007     PARSE2('*', '*', '=', TOK_A_MUL)
4008     PARSE2('%', '%', '=', TOK_A_MOD)
4009     PARSE2('^', '^', '=', TOK_A_XOR)
4010 
4011         /* comments or operator */
4012     case '/':
4013         PEEKC(c, p);
4014         if (c == '*') {
4015             p = parse_comment(p);
4016             goto redo_no_start;
4017         } else if (c == '/') {
4018             p = parse_line_comment(p);
4019             goto redo_no_start;
4020         } else if (c == '=') {
4021             p++;
4022             tok = TOK_A_DIV;
4023         } else {
4024             tok = '/';
4025         }
4026         break;
4027 
4028         /* simple tokens */
4029     case '(':
4030     case ')':
4031     case '[':
4032     case ']':
4033     case '{':
4034     case '}':
4035     case ',':
4036     case ';':
4037     case ':':
4038     case '?':
4039     case '~':
4040     case '$': /* only used in assembler */
4041     case '@': /* dito */
4042         tok = c;
4043         p++;
4044         break;
4045     default:
4046         error("unrecognized character \\x%02x", c);
4047         break;
4048     }
4049     tok_flags = 0;
4050 keep_tok_flags:
4051     file->buf_ptr = p;
4052 #if defined(PARSE_DEBUG)
4053     printf("token = %s\n", get_tok_str(tok, &tokc));
4054 #endif
4055 }
4056 
4057 /* return next token without macro substitution. Can read input from
4058    macro_ptr buffer */
next_nomacro(void)4059 static void next_nomacro(void)
4060 {
4061     if (macro_ptr) {
4062     redo:
4063         tok = *macro_ptr;
4064         if (tok) {
4065             TOK_GET(tok, macro_ptr, tokc);
4066             if (tok == TOK_LINENUM) {
4067                 file->line_num = tokc.i;
4068                 goto redo;
4069             }
4070         }
4071     } else {
4072         next_nomacro1();
4073     }
4074 }
4075 
4076 /* substitute args in macro_str and return allocated string */
macro_arg_subst(Sym ** nested_list,int * macro_str,Sym * args)4077 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4078 {
4079     int *st, last_tok, t, notfirst;
4080     Sym *s;
4081     CValue cval;
4082     TokenString str;
4083     CString cstr;
4084 
4085     tok_str_new(&str);
4086     last_tok = 0;
4087     while(1) {
4088         TOK_GET(t, macro_str, cval);
4089         if (!t)
4090             break;
4091         if (t == '#') {
4092             /* stringize */
4093             TOK_GET(t, macro_str, cval);
4094             if (!t)
4095                 break;
4096             s = sym_find2(args, t);
4097             if (s) {
4098                 cstr_new(&cstr);
4099                 st = (int *)s->c;
4100                 notfirst = 0;
4101                 while (*st) {
4102                     if (notfirst)
4103                         cstr_ccat(&cstr, ' ');
4104                     TOK_GET(t, st, cval);
4105                     cstr_cat(&cstr, get_tok_str(t, &cval));
4106 #ifndef PP_NOSPACES
4107                     notfirst = 1;
4108 #endif
4109                 }
4110                 cstr_ccat(&cstr, '\0');
4111 #ifdef PP_DEBUG
4112                 printf("stringize: %s\n", (char *)cstr.data);
4113 #endif
4114                 /* add string */
4115                 cval.cstr = &cstr;
4116                 tok_str_add2(&str, TOK_STR, &cval);
4117                 cstr_free(&cstr);
4118             } else {
4119                 tok_str_add2(&str, t, &cval);
4120             }
4121         } else if (t >= TOK_IDENT) {
4122             s = sym_find2(args, t);
4123             if (s) {
4124                 st = (int *)s->c;
4125                 /* if '##' is present before or after, no arg substitution */
4126                 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4127                     /* special case for var arg macros : ## eats the
4128                        ',' if empty VA_ARGS variable. */
4129                     /* XXX: test of the ',' is not 100%
4130                        reliable. should fix it to avoid security
4131                        problems */
4132                     if (gnu_ext && s->type.t &&
4133                         last_tok == TOK_TWOSHARPS &&
4134                         str.len >= 2 && str.str[str.len - 2] == ',') {
4135                         if (*st == 0) {
4136                             /* suppress ',' '##' */
4137                             str.len -= 2;
4138                         } else {
4139                             /* suppress '##' and add variable */
4140                             str.len--;
4141                             goto add_var;
4142                         }
4143                     } else {
4144                         int t1;
4145                     add_var:
4146                         for(;;) {
4147                             TOK_GET(t1, st, cval);
4148                             if (!t1)
4149                                 break;
4150                             tok_str_add2(&str, t1, &cval);
4151                         }
4152                     }
4153                 } else {
4154                     /* NOTE: the stream cannot be read when macro
4155                        substituing an argument */
4156                     macro_subst(&str, nested_list, st, NULL);
4157                 }
4158             } else {
4159                 tok_str_add(&str, t);
4160             }
4161         } else {
4162             tok_str_add2(&str, t, &cval);
4163         }
4164         last_tok = t;
4165     }
4166     tok_str_add(&str, 0);
4167     return str.str;
4168 }
4169 
4170 static char const ab_month_name[12][4] =
4171 {
4172     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4173     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4174 };
4175 
4176 /* do macro substitution of current token with macro 's' and add
4177    result to (tok_str,tok_len). 'nested_list' is the list of all
4178    macros we got inside to avoid recursing. Return non zero if no
4179    substitution needs to be done */
macro_subst_tok(TokenString * tok_str,Sym ** nested_list,Sym * s,struct macro_level ** can_read_stream)4180 static int macro_subst_tok(TokenString *tok_str,
4181                            Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4182 {
4183     Sym *args, *sa, *sa1;
4184     int mstr_allocated, parlevel, *mstr, t, t1;
4185     TokenString str;
4186     char *cstrval;
4187     CValue cval;
4188     CString cstr;
4189     char buf[32];
4190 
4191     /* if symbol is a macro, prepare substitution */
4192     /* special macros */
4193     if (tok == TOK___LINE__) {
4194         snprintf(buf, sizeof(buf), "%d", file->line_num);
4195         cstrval = buf;
4196         t1 = TOK_PPNUM;
4197         goto add_cstr1;
4198     } else if (tok == TOK___FILE__) {
4199         cstrval = file->filename;
4200         goto add_cstr;
4201     } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4202         time_t ti;
4203         struct tm *tm;
4204 
4205         time(&ti);
4206         tm = localtime(&ti);
4207         if (tok == TOK___DATE__) {
4208             snprintf(buf, sizeof(buf), "%s %2d %d",
4209                      ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4210         } else {
4211             snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4212                      tm->tm_hour, tm->tm_min, tm->tm_sec);
4213         }
4214         cstrval = buf;
4215     add_cstr:
4216         t1 = TOK_STR;
4217     add_cstr1:
4218         cstr_new(&cstr);
4219         cstr_cat(&cstr, cstrval);
4220         cstr_ccat(&cstr, '\0');
4221         cval.cstr = &cstr;
4222         tok_str_add2(tok_str, t1, &cval);
4223         cstr_free(&cstr);
4224     } else {
4225         mstr = (int *)s->c;
4226         mstr_allocated = 0;
4227         if (s->type.t == MACRO_FUNC) {
4228             /* NOTE: we do not use next_nomacro to avoid eating the
4229                next token. XXX: find better solution */
4230         redo:
4231             if (macro_ptr) {
4232                 t = *macro_ptr;
4233                 if (t == 0 && can_read_stream) {
4234                     /* end of macro stream: we must look at the token
4235                        after in the file */
4236                     struct macro_level *ml = *can_read_stream;
4237                     macro_ptr = NULL;
4238                     if (ml)
4239                     {
4240                         macro_ptr = ml->p;
4241                         ml->p = NULL;
4242                         *can_read_stream = ml -> prev;
4243                     }
4244                     goto redo;
4245                 }
4246             } else {
4247                 /* XXX: incorrect with comments */
4248                 ch = file->buf_ptr[0];
4249                 while (is_space(ch) || ch == '\n')
4250                     cinp();
4251                 t = ch;
4252             }
4253             if (t != '(') /* no macro subst */
4254                 return -1;
4255 
4256             /* argument macro */
4257             next_nomacro();
4258             next_nomacro();
4259             args = NULL;
4260             sa = s->next;
4261             /* NOTE: empty args are allowed, except if no args */
4262             for(;;) {
4263                 /* handle '()' case */
4264                 if (!args && !sa && tok == ')')
4265                     break;
4266                 if (!sa)
4267                     error("macro '%s' used with too many args",
4268                           get_tok_str(s->v, 0));
4269                 tok_str_new(&str);
4270                 parlevel = 0;
4271                 /* NOTE: non zero sa->t indicates VA_ARGS */
4272                 while ((parlevel > 0 ||
4273                         (tok != ')' &&
4274                          (tok != ',' || sa->type.t))) &&
4275                        tok != -1) {
4276                     if (tok == '(')
4277                         parlevel++;
4278                     else if (tok == ')')
4279                         parlevel--;
4280                     if (tok != TOK_LINEFEED)
4281                         tok_str_add2(&str, tok, &tokc);
4282                     next_nomacro();
4283                 }
4284                 tok_str_add(&str, 0);
4285                 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4286                 sa = sa->next;
4287                 if (tok == ')') {
4288                     /* special case for gcc var args: add an empty
4289                        var arg argument if it is omitted */
4290                     if (sa && sa->type.t && gnu_ext)
4291                         continue;
4292                     else
4293                         break;
4294                 }
4295                 if (tok != ',')
4296                     expect(",");
4297                 next_nomacro();
4298             }
4299             if (sa) {
4300                 error("macro '%s' used with too few args",
4301                       get_tok_str(s->v, 0));
4302             }
4303 
4304             /* now subst each arg */
4305             mstr = macro_arg_subst(nested_list, mstr, args);
4306             /* free memory */
4307             sa = args;
4308             while (sa) {
4309                 sa1 = sa->prev;
4310                 tok_str_free((int *)sa->c);
4311                 sym_free(sa);
4312                 sa = sa1;
4313             }
4314             mstr_allocated = 1;
4315         }
4316         sym_push2(nested_list, s->v, 0, 0);
4317         macro_subst(tok_str, nested_list, mstr, can_read_stream);
4318         /* pop nested defined symbol */
4319         sa1 = *nested_list;
4320         *nested_list = sa1->prev;
4321         sym_free(sa1);
4322         if (mstr_allocated)
4323             tok_str_free(mstr);
4324     }
4325     return 0;
4326 }
4327 
4328 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4329    return the resulting string (which must be freed). */
macro_twosharps(const int * macro_str)4330 static inline int *macro_twosharps(const int *macro_str)
4331 {
4332     TokenSym *ts;
4333     const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4334     int t;
4335     const char *p1, *p2;
4336     CValue cval;
4337     TokenString macro_str1;
4338     CString cstr;
4339 
4340     start_macro_ptr = macro_str;
4341     /* we search the first '##' */
4342     for(;;) {
4343         macro_ptr1 = macro_str;
4344         TOK_GET(t, macro_str, cval);
4345         /* nothing more to do if end of string */
4346         if (t == 0)
4347             return NULL;
4348         if (*macro_str == TOK_TWOSHARPS)
4349             break;
4350     }
4351 
4352     /* we saw '##', so we need more processing to handle it */
4353     cstr_new(&cstr);
4354     tok_str_new(&macro_str1);
4355     tok = t;
4356     tokc = cval;
4357 
4358     /* add all tokens seen so far */
4359     for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4360         TOK_GET(t, ptr, cval);
4361         tok_str_add2(&macro_str1, t, &cval);
4362     }
4363     saved_macro_ptr = macro_ptr;
4364     /* XXX: get rid of the use of macro_ptr here */
4365     macro_ptr = (int *)macro_str;
4366     for(;;) {
4367         while (*macro_ptr == TOK_TWOSHARPS) {
4368             macro_ptr++;
4369             macro_ptr1 = macro_ptr;
4370             t = *macro_ptr;
4371             if (t) {
4372                 TOK_GET(t, macro_ptr, cval);
4373                 /* We concatenate the two tokens if we have an
4374                    identifier or a preprocessing number */
4375                 cstr_reset(&cstr);
4376                 p1 = get_tok_str(tok, &tokc);
4377                 cstr_cat(&cstr, p1);
4378                 p2 = get_tok_str(t, &cval);
4379                 cstr_cat(&cstr, p2);
4380                 cstr_ccat(&cstr, '\0');
4381 
4382                 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4383                     (t >= TOK_IDENT || t == TOK_PPNUM)) {
4384                     if (tok == TOK_PPNUM) {
4385                         /* if number, then create a number token */
4386                         /* NOTE: no need to allocate because
4387                            tok_str_add2() does it */
4388                         cstr_reset(&tokcstr);
4389                         tokcstr = cstr;
4390                         cstr_new(&cstr);
4391                         tokc.cstr = &tokcstr;
4392                     } else {
4393                         /* if identifier, we must do a test to
4394                            validate we have a correct identifier */
4395                         if (t == TOK_PPNUM) {
4396                             const char *p;
4397                             int c;
4398 
4399                             p = p2;
4400                             for(;;) {
4401                                 c = *p;
4402                                 if (c == '\0')
4403                                     break;
4404                                 p++;
4405                                 if (!isnum(c) && !isid(c))
4406                                     goto error_pasting;
4407                             }
4408                         }
4409                         ts = tok_alloc(cstr.data, strlen(cstr.data));
4410                         tok = ts->tok; /* modify current token */
4411                     }
4412                 } else {
4413                     const char *str = cstr.data;
4414                     const unsigned char *q;
4415 
4416                     /* we look for a valid token */
4417                     /* XXX: do more extensive checks */
4418                     if (!strcmp(str, ">>=")) {
4419                         tok = TOK_A_SAR;
4420                     } else if (!strcmp(str, "<<=")) {
4421                         tok = TOK_A_SHL;
4422                     } else if (strlen(str) == 2) {
4423                         /* search in two bytes table */
4424                         q = tok_two_chars;
4425                         for(;;) {
4426                             if (!*q)
4427                                 goto error_pasting;
4428                             if (q[0] == str[0] && q[1] == str[1])
4429                                 break;
4430                             q += 3;
4431                         }
4432                         tok = q[2];
4433                     } else {
4434                     error_pasting:
4435                         /* NOTE: because get_tok_str use a static buffer,
4436                            we must save it */
4437                         cstr_reset(&cstr);
4438                         p1 = get_tok_str(tok, &tokc);
4439                         cstr_cat(&cstr, p1);
4440                         cstr_ccat(&cstr, '\0');
4441                         p2 = get_tok_str(t, &cval);
4442                         warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4443                         /* cannot merge tokens: just add them separately */
4444                         tok_str_add2(&macro_str1, tok, &tokc);
4445                         /* XXX: free associated memory ? */
4446                         tok = t;
4447                         tokc = cval;
4448                     }
4449                 }
4450             }
4451         }
4452         tok_str_add2(&macro_str1, tok, &tokc);
4453         next_nomacro();
4454         if (tok == 0)
4455             break;
4456     }
4457     macro_ptr = (int *)saved_macro_ptr;
4458     cstr_free(&cstr);
4459     tok_str_add(&macro_str1, 0);
4460     return macro_str1.str;
4461 }
4462 
4463 
4464 /* do macro substitution of macro_str and add result to
4465    (tok_str,tok_len). 'nested_list' is the list of all macros we got
4466    inside to avoid recursing. */
macro_subst(TokenString * tok_str,Sym ** nested_list,const int * macro_str,struct macro_level ** can_read_stream)4467 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4468                         const int *macro_str, struct macro_level ** can_read_stream)
4469 {
4470     Sym *s;
4471     int *macro_str1;
4472     const int *ptr;
4473     int t, ret;
4474     CValue cval;
4475     struct macro_level ml;
4476 
4477     /* first scan for '##' operator handling */
4478     ptr = macro_str;
4479     macro_str1 = macro_twosharps(ptr);
4480     if (macro_str1)
4481         ptr = macro_str1;
4482     while (1) {
4483         /* NOTE: ptr == NULL can only happen if tokens are read from
4484            file stream due to a macro function call */
4485         if (ptr == NULL)
4486             break;
4487         TOK_GET(t, ptr, cval);
4488         if (t == 0)
4489             break;
4490         s = define_find(t);
4491         if (s != NULL) {
4492             /* if nested substitution, do nothing */
4493             if (sym_find2(*nested_list, t))
4494                 goto no_subst;
4495             ml.p = macro_ptr;
4496             if (can_read_stream)
4497                 ml.prev = *can_read_stream, *can_read_stream = &ml;
4498             macro_ptr = (int *)ptr;
4499             tok = t;
4500             ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4501             ptr = (int *)macro_ptr;
4502             macro_ptr = ml.p;
4503             if (can_read_stream && *can_read_stream == &ml)
4504                 *can_read_stream = ml.prev;
4505             if (ret != 0)
4506                 goto no_subst;
4507         } else {
4508         no_subst:
4509             tok_str_add2(tok_str, t, &cval);
4510         }
4511     }
4512     if (macro_str1)
4513         tok_str_free(macro_str1);
4514 }
4515 
4516 /* return next token with macro substitution */
next(void)4517 static void next(void)
4518 {
4519     Sym *nested_list, *s;
4520     TokenString str;
4521     struct macro_level *ml;
4522 
4523  redo:
4524     next_nomacro();
4525     if (!macro_ptr) {
4526         /* if not reading from macro substituted string, then try
4527            to substitute macros */
4528         if (tok >= TOK_IDENT &&
4529             (parse_flags & PARSE_FLAG_PREPROCESS)) {
4530             s = define_find(tok);
4531             if (s) {
4532                 /* we have a macro: we try to substitute */
4533                 tok_str_new(&str);
4534                 nested_list = NULL;
4535                 ml = NULL;
4536                 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4537                     /* substitution done, NOTE: maybe empty */
4538                     tok_str_add(&str, 0);
4539                     macro_ptr = str.str;
4540                     macro_ptr_allocated = str.str;
4541                     goto redo;
4542                 }
4543             }
4544         }
4545     } else {
4546         if (tok == 0) {
4547             /* end of macro or end of unget buffer */
4548             if (unget_buffer_enabled) {
4549                 macro_ptr = unget_saved_macro_ptr;
4550                 unget_buffer_enabled = 0;
4551             } else {
4552                 /* end of macro string: free it */
4553                 tok_str_free(macro_ptr_allocated);
4554                 macro_ptr = NULL;
4555             }
4556             goto redo;
4557         }
4558     }
4559 
4560     /* convert preprocessor tokens into C tokens */
4561     if (tok == TOK_PPNUM &&
4562         (parse_flags & PARSE_FLAG_TOK_NUM)) {
4563         parse_number((char *)tokc.cstr->data);
4564     }
4565 }
4566 
4567 /* push back current token and set current token to 'last_tok'. Only
4568    identifier case handled for labels. */
unget_tok(int last_tok)4569 static inline void unget_tok(int last_tok)
4570 {
4571     int i, n;
4572     int *q;
4573     unget_saved_macro_ptr = macro_ptr;
4574     unget_buffer_enabled = 1;
4575     q = unget_saved_buffer;
4576     macro_ptr = q;
4577     *q++ = tok;
4578     n = tok_ext_size(tok) - 1;
4579     for(i=0;i<n;i++)
4580         *q++ = tokc.tab[i];
4581     *q = 0; /* end of token string */
4582     tok = last_tok;
4583 }
4584 
4585 
swap(int * p,int * q)4586 void swap(int *p, int *q)
4587 {
4588     int t;
4589     t = *p;
4590     *p = *q;
4591     *q = t;
4592 }
4593 
vsetc(CType * type,int r,CValue * vc)4594 void vsetc(CType *type, int r, CValue *vc)
4595 {
4596     int v;
4597 
4598     if (vtop >= vstack + (VSTACK_SIZE - 1))
4599         error("memory full");
4600     /* cannot let cpu flags if other instruction are generated. Also
4601        avoid leaving VT_JMP anywhere except on the top of the stack
4602        because it would complicate the code generator. */
4603     if (vtop >= vstack) {
4604         v = vtop->r & VT_VALMASK;
4605         if (v == VT_CMP || (v & ~1) == VT_JMP)
4606             gv(RC_INT);
4607     }
4608     vtop++;
4609     vtop->type = *type;
4610     vtop->r = r;
4611     vtop->r2 = VT_CONST;
4612     vtop->c = *vc;
4613 }
4614 
4615 /* push integer constant */
vpushi(int v)4616 void vpushi(int v)
4617 {
4618     CValue cval;
4619     cval.i = v;
4620     vsetc(&int_type, VT_CONST, &cval);
4621 }
4622 
4623 /* Return a static symbol pointing to a section */
get_sym_ref(CType * type,Section * sec,unsigned long offset,unsigned long size)4624 static Sym *get_sym_ref(CType *type, Section *sec,
4625                         unsigned long offset, unsigned long size)
4626 {
4627     int v;
4628     Sym *sym;
4629 
4630     v = anon_sym++;
4631     sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4632     sym->type.ref = type->ref;
4633     sym->r = VT_CONST | VT_SYM;
4634     put_extern_sym(sym, sec, offset, size);
4635     return sym;
4636 }
4637 
4638 /* push a reference to a section offset by adding a dummy symbol */
vpush_ref(CType * type,Section * sec,unsigned long offset,unsigned long size)4639 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4640 {
4641     CValue cval;
4642 
4643     cval.ul = 0;
4644     vsetc(type, VT_CONST | VT_SYM, &cval);
4645     vtop->sym = get_sym_ref(type, sec, offset, size);
4646 }
4647 
4648 /* define a new external reference to a symbol 'v' of type 'u' */
external_global_sym(int v,CType * type,int r)4649 static Sym *external_global_sym(int v, CType *type, int r)
4650 {
4651     Sym *s;
4652 
4653     s = sym_find(v);
4654     if (!s) {
4655         /* push forward reference */
4656         s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4657         s->type.ref = type->ref;
4658         s->r = r | VT_CONST | VT_SYM;
4659     }
4660     return s;
4661 }
4662 
4663 /* define a new external reference to a symbol 'v' of type 'u' */
external_sym(int v,CType * type,int r)4664 static Sym *external_sym(int v, CType *type, int r)
4665 {
4666     Sym *s;
4667 
4668     s = sym_find(v);
4669     if (!s) {
4670         /* push forward reference */
4671         s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4672         s->type.t |= VT_EXTERN;
4673     } else {
4674         if (!is_compatible_types(&s->type, type))
4675             error("incompatible types for redefinition of '%s'",
4676                   get_tok_str(v, NULL));
4677     }
4678     return s;
4679 }
4680 
4681 /* push a reference to global symbol v */
vpush_global_sym(CType * type,int v)4682 static void vpush_global_sym(CType *type, int v)
4683 {
4684     Sym *sym;
4685     CValue cval;
4686 
4687     sym = external_global_sym(v, type, 0);
4688     cval.ul = 0;
4689     vsetc(type, VT_CONST | VT_SYM, &cval);
4690     vtop->sym = sym;
4691 }
4692 
vset(CType * type,int r,int v)4693 void vset(CType *type, int r, int v)
4694 {
4695     CValue cval;
4696 
4697     cval.i = v;
4698     vsetc(type, r, &cval);
4699 }
4700 
vseti(int r,int v)4701 void vseti(int r, int v)
4702 {
4703     CType type;
4704     type.t = VT_INT;
4705     vset(&type, r, v);
4706 }
4707 
vswap(void)4708 void vswap(void)
4709 {
4710     SValue tmp;
4711 
4712     tmp = vtop[0];
4713     vtop[0] = vtop[-1];
4714     vtop[-1] = tmp;
4715 }
4716 
vpushv(SValue * v)4717 void vpushv(SValue *v)
4718 {
4719     if (vtop >= vstack + (VSTACK_SIZE - 1))
4720         error("memory full");
4721     vtop++;
4722     *vtop = *v;
4723 }
4724 
vdup(void)4725 void vdup(void)
4726 {
4727     vpushv(vtop);
4728 }
4729 
4730 /* save r to the memory stack, and mark it as being free */
save_reg(int r)4731 void save_reg(int r)
4732 {
4733     int l, saved, size, align;
4734     SValue *p, sv;
4735     CType *type;
4736 
4737     /* modify all stack values */
4738     saved = 0;
4739     l = 0;
4740     for(p=vstack;p<=vtop;p++) {
4741         if ((p->r & VT_VALMASK) == r ||
4742             ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4743             /* must save value on stack if not already done */
4744             if (!saved) {
4745                 /* NOTE: must reload 'r' because r might be equal to r2 */
4746                 r = p->r & VT_VALMASK;
4747                 /* store register in the stack */
4748                 type = &p->type;
4749                 if ((p->r & VT_LVAL) ||
4750                     (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4751                     type = &int_type;
4752                 size = type_size(type, &align);
4753                 loc = (loc - size) & -align;
4754                 sv.type.t = type->t;
4755                 sv.r = VT_LOCAL | VT_LVAL;
4756                 sv.c.ul = loc;
4757                 store(r, &sv);
4758 #ifdef TCC_TARGET_I386
4759                 /* x86 specific: need to pop fp register ST0 if saved */
4760                 if (r == TREG_ST0) {
4761                     o(0xd9dd); /* fstp %st(1) */
4762                 }
4763 #endif
4764                 /* special long long case */
4765                 if ((type->t & VT_BTYPE) == VT_LLONG) {
4766                     sv.c.ul += 4;
4767                     store(p->r2, &sv);
4768                 }
4769                 l = loc;
4770                 saved = 1;
4771             }
4772             /* mark that stack entry as being saved on the stack */
4773             if (p->r & VT_LVAL) {
4774                 /* also clear the bounded flag because the
4775                    relocation address of the function was stored in
4776                    p->c.ul */
4777                 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4778             } else {
4779                 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4780             }
4781             p->r2 = VT_CONST;
4782             p->c.ul = l;
4783         }
4784     }
4785 }
4786 
4787 /* find a register of class 'rc2' with at most one reference on stack.
4788  * If none, call get_reg(rc) */
get_reg_ex(int rc,int rc2)4789 int get_reg_ex(int rc, int rc2)
4790 {
4791     int r;
4792     SValue *p;
4793 
4794     for(r=0;r<NB_REGS;r++) {
4795         if (reg_classes[r] & rc2) {
4796             int n;
4797             n=0;
4798             for(p = vstack; p <= vtop; p++) {
4799                 if ((p->r & VT_VALMASK) == r ||
4800                     (p->r2 & VT_VALMASK) == r)
4801                     n++;
4802             }
4803             if (n <= 1)
4804                 return r;
4805         }
4806     }
4807     return get_reg(rc);
4808 }
4809 
4810 /* find a free register of class 'rc'. If none, save one register */
get_reg(int rc)4811 int get_reg(int rc)
4812 {
4813     int r;
4814     SValue *p;
4815 
4816     /* find a free register */
4817     for(r=0;r<NB_REGS;r++) {
4818         if (reg_classes[r] & rc) {
4819             for(p=vstack;p<=vtop;p++) {
4820                 if ((p->r & VT_VALMASK) == r ||
4821                     (p->r2 & VT_VALMASK) == r)
4822                     goto notfound;
4823             }
4824             return r;
4825         }
4826     notfound: ;
4827     }
4828 
4829     /* no register left : free the first one on the stack (VERY
4830        IMPORTANT to start from the bottom to ensure that we don't
4831        spill registers used in gen_opi()) */
4832     for(p=vstack;p<=vtop;p++) {
4833         r = p->r & VT_VALMASK;
4834         if (r < VT_CONST && (reg_classes[r] & rc))
4835             goto save_found;
4836         /* also look at second register (if long long) */
4837         r = p->r2 & VT_VALMASK;
4838         if (r < VT_CONST && (reg_classes[r] & rc)) {
4839         save_found:
4840             save_reg(r);
4841             return r;
4842         }
4843     }
4844     /* Should never comes here */
4845     return -1;
4846 }
4847 
4848 /* save registers up to (vtop - n) stack entry */
save_regs(int n)4849 void save_regs(int n)
4850 {
4851     int r;
4852     SValue *p, *p1;
4853     p1 = vtop - n;
4854     for(p = vstack;p <= p1; p++) {
4855         r = p->r & VT_VALMASK;
4856         if (r < VT_CONST) {
4857             save_reg(r);
4858         }
4859     }
4860 }
4861 
4862 /* move register 's' to 'r', and flush previous value of r to memory
4863    if needed */
move_reg(int r,int s)4864 void move_reg(int r, int s)
4865 {
4866     SValue sv;
4867 
4868     if (r != s) {
4869         save_reg(r);
4870         sv.type.t = VT_INT;
4871         sv.r = s;
4872         sv.c.ul = 0;
4873         load(r, &sv);
4874     }
4875 }
4876 
4877 /* get address of vtop (vtop MUST BE an lvalue) */
gaddrof(void)4878 void gaddrof(void)
4879 {
4880     vtop->r &= ~VT_LVAL;
4881     /* tricky: if saved lvalue, then we can go back to lvalue */
4882     if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4883         vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4884 }
4885 
4886 #ifdef CONFIG_TCC_BCHECK
4887 /* generate lvalue bound code */
gbound(void)4888 void gbound(void)
4889 {
4890     int lval_type;
4891     CType type1;
4892 
4893     vtop->r &= ~VT_MUSTBOUND;
4894     /* if lvalue, then use checking code before dereferencing */
4895     if (vtop->r & VT_LVAL) {
4896         /* if not VT_BOUNDED value, then make one */
4897         if (!(vtop->r & VT_BOUNDED)) {
4898             lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4899             /* must save type because we must set it to int to get pointer */
4900             type1 = vtop->type;
4901             vtop->type.t = VT_INT;
4902             gaddrof();
4903             vpushi(0);
4904             gen_bounded_ptr_add();
4905             vtop->r |= lval_type;
4906             vtop->type = type1;
4907         }
4908         /* then check for dereferencing */
4909         gen_bounded_ptr_deref();
4910     }
4911 }
4912 #endif
4913 
4914 /* store vtop a register belonging to class 'rc'. lvalues are
4915    converted to values. Cannot be used if cannot be converted to
4916    register value (such as structures). */
gv(int rc)4917 int gv(int rc)
4918 {
4919     int r, r2, rc2, bit_pos, bit_size, size, align, i;
4920     unsigned long long ll;
4921 
4922     /* NOTE: get_reg can modify vstack[] */
4923     if (vtop->type.t & VT_BITFIELD) {
4924         bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4925         bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4926         /* remove bit field info to avoid loops */
4927         vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4928         /* generate shifts */
4929         vpushi(32 - (bit_pos + bit_size));
4930         gen_op(TOK_SHL);
4931         vpushi(32 - bit_size);
4932         /* NOTE: transformed to SHR if unsigned */
4933         gen_op(TOK_SAR);
4934         r = gv(rc);
4935     } else {
4936         if (is_float(vtop->type.t) &&
4937             (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4938             Sym *sym;
4939             int *ptr;
4940             unsigned long offset;
4941 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4942             CValue check;
4943 #endif
4944 
4945             /* XXX: unify with initializers handling ? */
4946             /* CPUs usually cannot use float constants, so we store them
4947                generically in data segment */
4948             size = type_size(&vtop->type, &align);
4949             offset = (data_section->data_offset + align - 1) & -align;
4950             data_section->data_offset = offset;
4951             /* XXX: not portable yet */
4952 #ifdef __i386__
4953             /* Zero pad x87 tenbyte long doubles */
4954             if (size == 12)
4955                 vtop->c.tab[2] &= 0xffff;
4956 #endif
4957             ptr = section_ptr_add(data_section, size);
4958             size = size >> 2;
4959 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4960             check.d = 1;
4961             if(check.tab[0])
4962                 for(i=0;i<size;i++)
4963                     ptr[i] = vtop->c.tab[size-1-i];
4964             else
4965 #endif
4966             for(i=0;i<size;i++)
4967                 ptr[i] = vtop->c.tab[i];
4968             sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4969             vtop->r |= VT_LVAL | VT_SYM;
4970             vtop->sym = sym;
4971             vtop->c.ul = 0;
4972         }
4973 #ifdef CONFIG_TCC_BCHECK
4974         if (vtop->r & VT_MUSTBOUND)
4975             gbound();
4976 #endif
4977 
4978         r = vtop->r & VT_VALMASK;
4979         /* need to reload if:
4980            - constant
4981            - lvalue (need to dereference pointer)
4982            - already a register, but not in the right class */
4983         if (r >= VT_CONST ||
4984             (vtop->r & VT_LVAL) ||
4985             !(reg_classes[r] & rc) ||
4986             ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4987              !(reg_classes[vtop->r2] & rc))) {
4988             r = get_reg(rc);
4989             if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4990                 /* two register type load : expand to two words
4991                    temporarily */
4992                 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4993                     /* load constant */
4994                     ll = vtop->c.ull;
4995                     vtop->c.ui = ll; /* first word */
4996                     load(r, vtop);
4997                     vtop->r = r; /* save register value */
4998                     vpushi(ll >> 32); /* second word */
4999                 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5000                            (vtop->r & VT_LVAL)) {
5001                     /* We do not want to modifier the long long
5002                        pointer here, so the safest (and less
5003                        efficient) is to save all the other registers
5004                        in the stack. XXX: totally inefficient. */
5005                     save_regs(1);
5006                     /* load from memory */
5007                     load(r, vtop);
5008                     vdup();
5009                     vtop[-1].r = r; /* save register value */
5010                     /* increment pointer to get second word */
5011                     vtop->type.t = VT_INT;
5012                     gaddrof();
5013                     vpushi(4);
5014                     gen_op('+');
5015                     vtop->r |= VT_LVAL;
5016                 } else {
5017                     /* move registers */
5018                     load(r, vtop);
5019                     vdup();
5020                     vtop[-1].r = r; /* save register value */
5021                     vtop->r = vtop[-1].r2;
5022                 }
5023                 /* allocate second register */
5024                 rc2 = RC_INT;
5025                 if (rc == RC_IRET)
5026                     rc2 = RC_LRET;
5027                 r2 = get_reg(rc2);
5028                 load(r2, vtop);
5029                 vpop();
5030                 /* write second register */
5031                 vtop->r2 = r2;
5032             } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5033                 int t1, t;
5034                 /* lvalue of scalar type : need to use lvalue type
5035                    because of possible cast */
5036                 t = vtop->type.t;
5037                 t1 = t;
5038                 /* compute memory access type */
5039                 if (vtop->r & VT_LVAL_BYTE)
5040                     t = VT_BYTE;
5041                 else if (vtop->r & VT_LVAL_SHORT)
5042                     t = VT_SHORT;
5043                 if (vtop->r & VT_LVAL_UNSIGNED)
5044                     t |= VT_UNSIGNED;
5045                 vtop->type.t = t;
5046                 load(r, vtop);
5047                 /* restore wanted type */
5048                 vtop->type.t = t1;
5049             } else {
5050                 /* one register type load */
5051                 load(r, vtop);
5052             }
5053         }
5054         vtop->r = r;
5055 #ifdef TCC_TARGET_C67
5056         /* uses register pairs for doubles */
5057         if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5058             vtop->r2 = r+1;
5059 #endif
5060     }
5061     return r;
5062 }
5063 
5064 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
gv2(int rc1,int rc2)5065 void gv2(int rc1, int rc2)
5066 {
5067     int v;
5068 
5069     /* generate more generic register first. But VT_JMP or VT_CMP
5070        values must be generated first in all cases to avoid possible
5071        reload errors */
5072     v = vtop[0].r & VT_VALMASK;
5073     if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5074         vswap();
5075         gv(rc1);
5076         vswap();
5077         gv(rc2);
5078         /* test if reload is needed for first register */
5079         if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5080             vswap();
5081             gv(rc1);
5082             vswap();
5083         }
5084     } else {
5085         gv(rc2);
5086         vswap();
5087         gv(rc1);
5088         vswap();
5089         /* test if reload is needed for first register */
5090         if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5091             gv(rc2);
5092         }
5093     }
5094 }
5095 
5096 /* expand long long on stack in two int registers */
lexpand(void)5097 void lexpand(void)
5098 {
5099     int u;
5100 
5101     u = vtop->type.t & VT_UNSIGNED;
5102     gv(RC_INT);
5103     vdup();
5104     vtop[0].r = vtop[-1].r2;
5105     vtop[0].r2 = VT_CONST;
5106     vtop[-1].r2 = VT_CONST;
5107     vtop[0].type.t = VT_INT | u;
5108     vtop[-1].type.t = VT_INT | u;
5109 }
5110 
5111 #ifdef TCC_TARGET_ARM
5112 /* expand long long on stack */
lexpand_nr(void)5113 void lexpand_nr(void)
5114 {
5115     int u,v;
5116 
5117     u = vtop->type.t & VT_UNSIGNED;
5118     vdup();
5119     vtop->r2 = VT_CONST;
5120     vtop->type.t = VT_INT | u;
5121     v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5122     if (v == VT_CONST) {
5123       vtop[-1].c.ui = vtop->c.ull;
5124       vtop->c.ui = vtop->c.ull >> 32;
5125       vtop->r = VT_CONST;
5126     } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5127       vtop->c.ui += 4;
5128       vtop->r = vtop[-1].r;
5129     } else if (v > VT_CONST) {
5130       vtop--;
5131       lexpand();
5132     } else
5133       vtop->r = vtop[-1].r2;
5134     vtop[-1].r2 = VT_CONST;
5135     vtop[-1].type.t = VT_INT | u;
5136 }
5137 #endif
5138 
5139 /* build a long long from two ints */
lbuild(int t)5140 void lbuild(int t)
5141 {
5142     gv2(RC_INT, RC_INT);
5143     vtop[-1].r2 = vtop[0].r;
5144     vtop[-1].type.t = t;
5145     vpop();
5146 }
5147 
5148 /* rotate n first stack elements to the bottom
5149    I1 ... In -> I2 ... In I1 [top is right]
5150 */
vrotb(int n)5151 void vrotb(int n)
5152 {
5153     int i;
5154     SValue tmp;
5155 
5156     tmp = vtop[-n + 1];
5157     for(i=-n+1;i!=0;i++)
5158         vtop[i] = vtop[i+1];
5159     vtop[0] = tmp;
5160 }
5161 
5162 /* rotate n first stack elements to the top
5163    I1 ... In -> In I1 ... I(n-1)  [top is right]
5164  */
vrott(int n)5165 void vrott(int n)
5166 {
5167     int i;
5168     SValue tmp;
5169 
5170     tmp = vtop[0];
5171     for(i = 0;i < n - 1; i++)
5172         vtop[-i] = vtop[-i - 1];
5173     vtop[-n + 1] = tmp;
5174 }
5175 
5176 #ifdef TCC_TARGET_ARM
5177 /* like vrott but in other direction
5178    In ... I1 -> I(n-1) ... I1 In  [top is right]
5179  */
vnrott(int n)5180 void vnrott(int n)
5181 {
5182     int i;
5183     SValue tmp;
5184 
5185     tmp = vtop[-n + 1];
5186     for(i = n - 1; i > 0; i--)
5187         vtop[-i] = vtop[-i + 1];
5188     vtop[0] = tmp;
5189 }
5190 #endif
5191 
5192 /* pop stack value */
vpop(void)5193 void vpop(void)
5194 {
5195     int v;
5196     v = vtop->r & VT_VALMASK;
5197 #ifdef TCC_TARGET_I386
5198     /* for x86, we need to pop the FP stack */
5199     if (v == TREG_ST0 && !nocode_wanted) {
5200         o(0xd9dd); /* fstp %st(1) */
5201     } else
5202 #endif
5203     if (v == VT_JMP || v == VT_JMPI) {
5204         /* need to put correct jump if && or || without test */
5205         gsym(vtop->c.ul);
5206     }
5207     vtop--;
5208 }
5209 
5210 /* convert stack entry to register and duplicate its value in another
5211    register */
gv_dup(void)5212 void gv_dup(void)
5213 {
5214     int rc, t, r, r1;
5215     SValue sv;
5216 
5217     t = vtop->type.t;
5218     if ((t & VT_BTYPE) == VT_LLONG) {
5219         lexpand();
5220         gv_dup();
5221         vswap();
5222         vrotb(3);
5223         gv_dup();
5224         vrotb(4);
5225         /* stack: H L L1 H1 */
5226         lbuild(t);
5227         vrotb(3);
5228         vrotb(3);
5229         vswap();
5230         lbuild(t);
5231         vswap();
5232     } else {
5233         /* duplicate value */
5234         rc = RC_INT;
5235         sv.type.t = VT_INT;
5236         if (is_float(t)) {
5237             rc = RC_FLOAT;
5238             sv.type.t = t;
5239         }
5240         r = gv(rc);
5241         r1 = get_reg(rc);
5242         sv.r = r;
5243         sv.c.ul = 0;
5244         load(r1, &sv); /* move r to r1 */
5245         vdup();
5246         /* duplicates value */
5247         vtop->r = r1;
5248     }
5249 }
5250 
5251 /* generate CPU independent (unsigned) long long operations */
gen_opl(int op)5252 void gen_opl(int op)
5253 {
5254     int t, a, b, op1, c, i;
5255     int func;
5256     SValue tmp;
5257 
5258     switch(op) {
5259     case '/':
5260     case TOK_PDIV:
5261         func = TOK___divdi3;
5262         goto gen_func;
5263     case TOK_UDIV:
5264         func = TOK___udivdi3;
5265         goto gen_func;
5266     case '%':
5267         func = TOK___moddi3;
5268         goto gen_func;
5269     case TOK_UMOD:
5270         func = TOK___umoddi3;
5271     gen_func:
5272         /* call generic long long function */
5273         vpush_global_sym(&func_old_type, func);
5274         vrott(3);
5275         gfunc_call(2);
5276         vpushi(0);
5277         vtop->r = REG_IRET;
5278         vtop->r2 = REG_LRET;
5279         break;
5280     case '^':
5281     case '&':
5282     case '|':
5283     case '*':
5284     case '+':
5285     case '-':
5286         t = vtop->type.t;
5287         vswap();
5288         lexpand();
5289         vrotb(3);
5290         lexpand();
5291         /* stack: L1 H1 L2 H2 */
5292         tmp = vtop[0];
5293         vtop[0] = vtop[-3];
5294         vtop[-3] = tmp;
5295         tmp = vtop[-2];
5296         vtop[-2] = vtop[-3];
5297         vtop[-3] = tmp;
5298         vswap();
5299         /* stack: H1 H2 L1 L2 */
5300         if (op == '*') {
5301             vpushv(vtop - 1);
5302             vpushv(vtop - 1);
5303             gen_op(TOK_UMULL);
5304             lexpand();
5305             /* stack: H1 H2 L1 L2 ML MH */
5306             for(i=0;i<4;i++)
5307                 vrotb(6);
5308             /* stack: ML MH H1 H2 L1 L2 */
5309             tmp = vtop[0];
5310             vtop[0] = vtop[-2];
5311             vtop[-2] = tmp;
5312             /* stack: ML MH H1 L2 H2 L1 */
5313             gen_op('*');
5314             vrotb(3);
5315             vrotb(3);
5316             gen_op('*');
5317             /* stack: ML MH M1 M2 */
5318             gen_op('+');
5319             gen_op('+');
5320         } else if (op == '+' || op == '-') {
5321             /* XXX: add non carry method too (for MIPS or alpha) */
5322             if (op == '+')
5323                 op1 = TOK_ADDC1;
5324             else
5325                 op1 = TOK_SUBC1;
5326             gen_op(op1);
5327             /* stack: H1 H2 (L1 op L2) */
5328             vrotb(3);
5329             vrotb(3);
5330             gen_op(op1 + 1); /* TOK_xxxC2 */
5331         } else {
5332             gen_op(op);
5333             /* stack: H1 H2 (L1 op L2) */
5334             vrotb(3);
5335             vrotb(3);
5336             /* stack: (L1 op L2) H1 H2 */
5337             gen_op(op);
5338             /* stack: (L1 op L2) (H1 op H2) */
5339         }
5340         /* stack: L H */
5341         lbuild(t);
5342         break;
5343     case TOK_SAR:
5344     case TOK_SHR:
5345     case TOK_SHL:
5346         if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5347             t = vtop[-1].type.t;
5348             vswap();
5349             lexpand();
5350             vrotb(3);
5351             /* stack: L H shift */
5352             c = (int)vtop->c.i;
5353             /* constant: simpler */
5354             /* NOTE: all comments are for SHL. the other cases are
5355                done by swaping words */
5356             vpop();
5357             if (op != TOK_SHL)
5358                 vswap();
5359             if (c >= 32) {
5360                 /* stack: L H */
5361                 vpop();
5362                 if (c > 32) {
5363                     vpushi(c - 32);
5364                     gen_op(op);
5365                 }
5366                 if (op != TOK_SAR) {
5367                     vpushi(0);
5368                 } else {
5369                     gv_dup();
5370                     vpushi(31);
5371                     gen_op(TOK_SAR);
5372                 }
5373                 vswap();
5374             } else {
5375                 vswap();
5376                 gv_dup();
5377                 /* stack: H L L */
5378                 vpushi(c);
5379                 gen_op(op);
5380                 vswap();
5381                 vpushi(32 - c);
5382                 if (op == TOK_SHL)
5383                     gen_op(TOK_SHR);
5384                 else
5385                     gen_op(TOK_SHL);
5386                 vrotb(3);
5387                 /* stack: L L H */
5388                 vpushi(c);
5389                 if (op == TOK_SHL)
5390                     gen_op(TOK_SHL);
5391                 else
5392                     gen_op(TOK_SHR);
5393                 gen_op('|');
5394             }
5395             if (op != TOK_SHL)
5396                 vswap();
5397             lbuild(t);
5398         } else {
5399             /* XXX: should provide a faster fallback on x86 ? */
5400             switch(op) {
5401             case TOK_SAR:
5402                 func = TOK___sardi3;
5403                 goto gen_func;
5404             case TOK_SHR:
5405                 func = TOK___shrdi3;
5406                 goto gen_func;
5407             case TOK_SHL:
5408                 func = TOK___shldi3;
5409                 goto gen_func;
5410             }
5411         }
5412         break;
5413     default:
5414         /* compare operations */
5415         t = vtop->type.t;
5416         vswap();
5417         lexpand();
5418         vrotb(3);
5419         lexpand();
5420         /* stack: L1 H1 L2 H2 */
5421         tmp = vtop[-1];
5422         vtop[-1] = vtop[-2];
5423         vtop[-2] = tmp;
5424         /* stack: L1 L2 H1 H2 */
5425         /* compare high */
5426         op1 = op;
5427         /* when values are equal, we need to compare low words. since
5428            the jump is inverted, we invert the test too. */
5429         if (op1 == TOK_LT)
5430             op1 = TOK_LE;
5431         else if (op1 == TOK_GT)
5432             op1 = TOK_GE;
5433         else if (op1 == TOK_ULT)
5434             op1 = TOK_ULE;
5435         else if (op1 == TOK_UGT)
5436             op1 = TOK_UGE;
5437         a = 0;
5438         b = 0;
5439         gen_op(op1);
5440         if (op1 != TOK_NE) {
5441             a = gtst(1, 0);
5442         }
5443         if (op != TOK_EQ) {
5444             /* generate non equal test */
5445             /* XXX: NOT PORTABLE yet */
5446             if (a == 0) {
5447                 b = gtst(0, 0);
5448             } else {
5449 #if defined(TCC_TARGET_I386)
5450                 b = psym(0x850f, 0);
5451 #elif defined(TCC_TARGET_ARM)
5452                 b = ind;
5453                 o(0x1A000000 | encbranch(ind, 0, 1));
5454 #elif defined(TCC_TARGET_C67)
5455                 error("not implemented");
5456 #else
5457 #error not supported
5458 #endif
5459             }
5460         }
5461         /* compare low. Always unsigned */
5462         op1 = op;
5463         if (op1 == TOK_LT)
5464             op1 = TOK_ULT;
5465         else if (op1 == TOK_LE)
5466             op1 = TOK_ULE;
5467         else if (op1 == TOK_GT)
5468             op1 = TOK_UGT;
5469         else if (op1 == TOK_GE)
5470             op1 = TOK_UGE;
5471         gen_op(op1);
5472         a = gtst(1, a);
5473         gsym(b);
5474         vseti(VT_JMPI, a);
5475         break;
5476     }
5477 }
5478 
5479 /* handle integer constant optimizations and various machine
5480    independent opt */
gen_opic(int op)5481 void gen_opic(int op)
5482 {
5483     int c1, c2, t1, t2, n;
5484     SValue *v1, *v2;
5485     long long l1, l2;
5486     typedef unsigned long long U;
5487 
5488     v1 = vtop - 1;
5489     v2 = vtop;
5490     t1 = v1->type.t & VT_BTYPE;
5491     t2 = v2->type.t & VT_BTYPE;
5492     l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5493     l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5494 
5495     /* currently, we cannot do computations with forward symbols */
5496     c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5497     c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5498     if (c1 && c2) {
5499         switch(op) {
5500         case '+': l1 += l2; break;
5501         case '-': l1 -= l2; break;
5502         case '&': l1 &= l2; break;
5503         case '^': l1 ^= l2; break;
5504         case '|': l1 |= l2; break;
5505         case '*': l1 *= l2; break;
5506 
5507         case TOK_PDIV:
5508         case '/':
5509         case '%':
5510         case TOK_UDIV:
5511         case TOK_UMOD:
5512             /* if division by zero, generate explicit division */
5513             if (l2 == 0) {
5514                 if (const_wanted)
5515                     error("division by zero in constant");
5516                 goto general_case;
5517             }
5518             switch(op) {
5519             default: l1 /= l2; break;
5520             case '%': l1 %= l2; break;
5521             case TOK_UDIV: l1 = (U)l1 / l2; break;
5522             case TOK_UMOD: l1 = (U)l1 % l2; break;
5523             }
5524             break;
5525         case TOK_SHL: l1 <<= l2; break;
5526         case TOK_SHR: l1 = (U)l1 >> l2; break;
5527         case TOK_SAR: l1 >>= l2; break;
5528             /* tests */
5529         case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5530         case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5531         case TOK_EQ: l1 = l1 == l2; break;
5532         case TOK_NE: l1 = l1 != l2; break;
5533         case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5534         case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5535         case TOK_LT: l1 = l1 < l2; break;
5536         case TOK_GE: l1 = l1 >= l2; break;
5537         case TOK_LE: l1 = l1 <= l2; break;
5538         case TOK_GT: l1 = l1 > l2; break;
5539             /* logical */
5540         case TOK_LAND: l1 = l1 && l2; break;
5541         case TOK_LOR: l1 = l1 || l2; break;
5542         default:
5543             goto general_case;
5544         }
5545         v1->c.ll = l1;
5546         vtop--;
5547     } else {
5548         /* if commutative ops, put c2 as constant */
5549         if (c1 && (op == '+' || op == '&' || op == '^' ||
5550                    op == '|' || op == '*')) {
5551             vswap();
5552             c2 = c1; //c = c1, c1 = c2, c2 = c;
5553             l2 = l1; //l = l1, l1 = l2, l2 = l;
5554         }
5555         /* Filter out NOP operations like x*1, x-0, x&-1... */
5556         if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5557                      op == TOK_PDIV) &&
5558                     l2 == 1) ||
5559                    ((op == '+' || op == '-' || op == '|' || op == '^' ||
5560                      op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5561                     l2 == 0) ||
5562                    (op == '&' &&
5563                     l2 == -1))) {
5564             /* nothing to do */
5565             vtop--;
5566         } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5567             /* try to use shifts instead of muls or divs */
5568             if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5569                 n = -1;
5570                 while (l2) {
5571                     l2 >>= 1;
5572                     n++;
5573                 }
5574                 vtop->c.ll = n;
5575                 if (op == '*')
5576                     op = TOK_SHL;
5577                 else if (op == TOK_PDIV)
5578                     op = TOK_SAR;
5579                 else
5580                     op = TOK_SHR;
5581             }
5582             goto general_case;
5583         } else if (c2 && (op == '+' || op == '-') &&
5584                    (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5585                    (VT_CONST | VT_SYM)) {
5586             /* symbol + constant case */
5587             if (op == '-')
5588                 l2 = -l2;
5589             vtop--;
5590             vtop->c.ll += l2;
5591         } else {
5592         general_case:
5593             if (!nocode_wanted) {
5594                 /* call low level op generator */
5595                 if (t1 == VT_LLONG || t2 == VT_LLONG)
5596                     gen_opl(op);
5597                 else
5598                     gen_opi(op);
5599             } else {
5600                 vtop--;
5601             }
5602         }
5603     }
5604 }
5605 
5606 /* generate a floating point operation with constant propagation */
gen_opif(int op)5607 void gen_opif(int op)
5608 {
5609     int c1, c2;
5610     SValue *v1, *v2;
5611     long double f1, f2;
5612 
5613     v1 = vtop - 1;
5614     v2 = vtop;
5615     /* currently, we cannot do computations with forward symbols */
5616     c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5617     c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5618     if (c1 && c2) {
5619         if (v1->type.t == VT_FLOAT) {
5620             f1 = v1->c.f;
5621             f2 = v2->c.f;
5622         } else if (v1->type.t == VT_DOUBLE) {
5623             f1 = v1->c.d;
5624             f2 = v2->c.d;
5625         } else {
5626             f1 = v1->c.ld;
5627             f2 = v2->c.ld;
5628         }
5629 
5630         /* NOTE: we only do constant propagation if finite number (not
5631            NaN or infinity) (ANSI spec) */
5632         if (!ieee_finite(f1) || !ieee_finite(f2))
5633             goto general_case;
5634 
5635         switch(op) {
5636         case '+': f1 += f2; break;
5637         case '-': f1 -= f2; break;
5638         case '*': f1 *= f2; break;
5639         case '/':
5640             if (f2 == 0.0) {
5641                 if (const_wanted)
5642                     error("division by zero in constant");
5643                 goto general_case;
5644             }
5645             f1 /= f2;
5646             break;
5647             /* XXX: also handles tests ? */
5648         default:
5649             goto general_case;
5650         }
5651         /* XXX: overflow test ? */
5652         if (v1->type.t == VT_FLOAT) {
5653             v1->c.f = f1;
5654         } else if (v1->type.t == VT_DOUBLE) {
5655             v1->c.d = f1;
5656         } else {
5657             v1->c.ld = f1;
5658         }
5659         vtop--;
5660     } else {
5661     general_case:
5662         if (!nocode_wanted) {
5663             gen_opf(op);
5664         } else {
5665             vtop--;
5666         }
5667     }
5668 }
5669 
pointed_size(CType * type)5670 static int pointed_size(CType *type)
5671 {
5672     int align;
5673     return type_size(pointed_type(type), &align);
5674 }
5675 
is_null_pointer(SValue * p)5676 static inline int is_null_pointer(SValue *p)
5677 {
5678     if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5679         return 0;
5680     return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5681         ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5682 }
5683 
is_integer_btype(int bt)5684 static inline int is_integer_btype(int bt)
5685 {
5686     return (bt == VT_BYTE || bt == VT_SHORT ||
5687             bt == VT_INT || bt == VT_LLONG);
5688 }
5689 
5690 /* check types for comparison or substraction of pointers */
check_comparison_pointer_types(SValue * p1,SValue * p2,int op)5691 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5692 {
5693     CType *type1, *type2, tmp_type1, tmp_type2;
5694     int bt1, bt2;
5695 
5696     /* null pointers are accepted for all comparisons as gcc */
5697     if (is_null_pointer(p1) || is_null_pointer(p2))
5698         return;
5699     type1 = &p1->type;
5700     type2 = &p2->type;
5701     bt1 = type1->t & VT_BTYPE;
5702     bt2 = type2->t & VT_BTYPE;
5703     /* accept comparison between pointer and integer with a warning */
5704     if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5705         if (op != TOK_LOR && op != TOK_LAND )
5706             warning("comparison between pointer and integer");
5707         return;
5708     }
5709 
5710     /* both must be pointers or implicit function pointers */
5711     if (bt1 == VT_PTR) {
5712         type1 = pointed_type(type1);
5713     } else if (bt1 != VT_FUNC)
5714         goto invalid_operands;
5715 
5716     if (bt2 == VT_PTR) {
5717         type2 = pointed_type(type2);
5718     } else if (bt2 != VT_FUNC) {
5719     invalid_operands:
5720         error("invalid operands to binary %s", get_tok_str(op, NULL));
5721     }
5722     if ((type1->t & VT_BTYPE) == VT_VOID ||
5723         (type2->t & VT_BTYPE) == VT_VOID)
5724         return;
5725     tmp_type1 = *type1;
5726     tmp_type2 = *type2;
5727     tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5728     tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5729     if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5730         /* gcc-like error if '-' is used */
5731         if (op == '-')
5732             goto invalid_operands;
5733         else
5734             warning("comparison of distinct pointer types lacks a cast");
5735     }
5736 }
5737 
5738 /* generic gen_op: handles types problems */
gen_op(int op)5739 void gen_op(int op)
5740 {
5741     int u, t1, t2, bt1, bt2, t;
5742     CType type1;
5743 
5744     t1 = vtop[-1].type.t;
5745     t2 = vtop[0].type.t;
5746     bt1 = t1 & VT_BTYPE;
5747     bt2 = t2 & VT_BTYPE;
5748 
5749     if (bt1 == VT_PTR || bt2 == VT_PTR) {
5750         /* at least one operand is a pointer */
5751         /* relationnal op: must be both pointers */
5752         if (op >= TOK_ULT && op <= TOK_LOR) {
5753             check_comparison_pointer_types(vtop - 1, vtop, op);
5754             /* pointers are handled are unsigned */
5755             t = VT_INT | VT_UNSIGNED;
5756             goto std_op;
5757         }
5758         /* if both pointers, then it must be the '-' op */
5759         if (bt1 == VT_PTR && bt2 == VT_PTR) {
5760             if (op != '-')
5761                 error("cannot use pointers here");
5762             check_comparison_pointer_types(vtop - 1, vtop, op);
5763             /* XXX: check that types are compatible */
5764             u = pointed_size(&vtop[-1].type);
5765             gen_opic(op);
5766             /* set to integer type */
5767             vtop->type.t = VT_INT;
5768             vpushi(u);
5769             gen_op(TOK_PDIV);
5770         } else {
5771             /* exactly one pointer : must be '+' or '-'. */
5772             if (op != '-' && op != '+')
5773                 error("cannot use pointers here");
5774             /* Put pointer as first operand */
5775             if (bt2 == VT_PTR) {
5776                 vswap();
5777                 swap(&t1, &t2);
5778             }
5779             type1 = vtop[-1].type;
5780             /* XXX: cast to int ? (long long case) */
5781             vpushi(pointed_size(&vtop[-1].type));
5782             gen_op('*');
5783 #ifdef CONFIG_TCC_BCHECK
5784             /* if evaluating constant expression, no code should be
5785                generated, so no bound check */
5786             if (do_bounds_check && !const_wanted) {
5787                 /* if bounded pointers, we generate a special code to
5788                    test bounds */
5789                 if (op == '-') {
5790                     vpushi(0);
5791                     vswap();
5792                     gen_op('-');
5793                 }
5794                 gen_bounded_ptr_add();
5795             } else
5796 #endif
5797             {
5798                 gen_opic(op);
5799             }
5800             /* put again type if gen_opic() swaped operands */
5801             vtop->type = type1;
5802         }
5803     } else if (is_float(bt1) || is_float(bt2)) {
5804         /* compute bigger type and do implicit casts */
5805         if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5806             t = VT_LDOUBLE;
5807         } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5808             t = VT_DOUBLE;
5809         } else {
5810             t = VT_FLOAT;
5811         }
5812         /* floats can only be used for a few operations */
5813         if (op != '+' && op != '-' && op != '*' && op != '/' &&
5814             (op < TOK_ULT || op > TOK_GT))
5815             error("invalid operands for binary operation");
5816         goto std_op;
5817     } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5818         /* cast to biggest op */
5819         t = VT_LLONG;
5820         /* convert to unsigned if it does not fit in a long long */
5821         if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5822             (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5823             t |= VT_UNSIGNED;
5824         goto std_op;
5825     } else {
5826         /* integer operations */
5827         t = VT_INT;
5828         /* convert to unsigned if it does not fit in an integer */
5829         if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5830             (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5831             t |= VT_UNSIGNED;
5832     std_op:
5833         /* XXX: currently, some unsigned operations are explicit, so
5834            we modify them here */
5835         if (t & VT_UNSIGNED) {
5836             if (op == TOK_SAR)
5837                 op = TOK_SHR;
5838             else if (op == '/')
5839                 op = TOK_UDIV;
5840             else if (op == '%')
5841                 op = TOK_UMOD;
5842             else if (op == TOK_LT)
5843                 op = TOK_ULT;
5844             else if (op == TOK_GT)
5845                 op = TOK_UGT;
5846             else if (op == TOK_LE)
5847                 op = TOK_ULE;
5848             else if (op == TOK_GE)
5849                 op = TOK_UGE;
5850         }
5851         vswap();
5852         type1.t = t;
5853         gen_cast(&type1);
5854         vswap();
5855         /* special case for shifts and long long: we keep the shift as
5856            an integer */
5857         if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5858             type1.t = VT_INT;
5859         gen_cast(&type1);
5860         if (is_float(t))
5861             gen_opif(op);
5862         else
5863             gen_opic(op);
5864         if (op >= TOK_ULT && op <= TOK_GT) {
5865             /* relationnal op: the result is an int */
5866             vtop->type.t = VT_INT;
5867         } else {
5868             vtop->type.t = t;
5869         }
5870     }
5871 }
5872 
5873 /* generic itof for unsigned long long case */
gen_cvt_itof1(int t)5874 void gen_cvt_itof1(int t)
5875 {
5876     if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5877         (VT_LLONG | VT_UNSIGNED)) {
5878 
5879         if (t == VT_FLOAT)
5880             vpush_global_sym(&func_old_type, TOK___ulltof);
5881         else if (t == VT_DOUBLE)
5882             vpush_global_sym(&func_old_type, TOK___ulltod);
5883         else
5884             vpush_global_sym(&func_old_type, TOK___ulltold);
5885         vrott(2);
5886         gfunc_call(1);
5887         vpushi(0);
5888         vtop->r = REG_FRET;
5889     } else {
5890         gen_cvt_itof(t);
5891     }
5892 }
5893 
5894 /* generic ftoi for unsigned long long case */
gen_cvt_ftoi1(int t)5895 void gen_cvt_ftoi1(int t)
5896 {
5897     int st;
5898 
5899     if (t == (VT_LLONG | VT_UNSIGNED)) {
5900         /* not handled natively */
5901         st = vtop->type.t & VT_BTYPE;
5902         if (st == VT_FLOAT)
5903             vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5904         else if (st == VT_DOUBLE)
5905             vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5906         else
5907             vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5908         vrott(2);
5909         gfunc_call(1);
5910         vpushi(0);
5911         vtop->r = REG_IRET;
5912         vtop->r2 = REG_LRET;
5913     } else {
5914         gen_cvt_ftoi(t);
5915     }
5916 }
5917 
5918 /* force char or short cast */
force_charshort_cast(int t)5919 void force_charshort_cast(int t)
5920 {
5921     int bits, dbt;
5922     dbt = t & VT_BTYPE;
5923     /* XXX: add optimization if lvalue : just change type and offset */
5924     if (dbt == VT_BYTE)
5925         bits = 8;
5926     else
5927         bits = 16;
5928     if (t & VT_UNSIGNED) {
5929         vpushi((1 << bits) - 1);
5930         gen_op('&');
5931     } else {
5932         bits = 32 - bits;
5933         vpushi(bits);
5934         gen_op(TOK_SHL);
5935         /* result must be signed or the SAR is converted to an SHL
5936            This was not the case when "t" was a signed short
5937            and the last value on the stack was an unsigned int */
5938         vtop->type.t &= ~VT_UNSIGNED;
5939         vpushi(bits);
5940         gen_op(TOK_SAR);
5941     }
5942 }
5943 
5944 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
gen_cast(CType * type)5945 static void gen_cast(CType *type)
5946 {
5947     int sbt, dbt, sf, df, c;
5948 
5949     /* special delayed cast for char/short */
5950     /* XXX: in some cases (multiple cascaded casts), it may still
5951        be incorrect */
5952     if (vtop->r & VT_MUSTCAST) {
5953         vtop->r &= ~VT_MUSTCAST;
5954         force_charshort_cast(vtop->type.t);
5955     }
5956 
5957     /* bitfields first get cast to ints */
5958     if (vtop->type.t & VT_BITFIELD) {
5959         gv(RC_INT);
5960     }
5961 
5962     dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5963     sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5964 
5965     if (sbt != dbt && !nocode_wanted) {
5966         sf = is_float(sbt);
5967         df = is_float(dbt);
5968         c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5969         if (sf && df) {
5970             /* convert from fp to fp */
5971             if (c) {
5972                 /* constant case: we can do it now */
5973                 /* XXX: in ISOC, cannot do it if error in convert */
5974                 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5975                     vtop->c.f = (float)vtop->c.d;
5976                 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5977                     vtop->c.f = (float)vtop->c.ld;
5978                 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5979                     vtop->c.d = (double)vtop->c.f;
5980                 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5981                     vtop->c.d = (double)vtop->c.ld;
5982                 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5983                     vtop->c.ld = (long double)vtop->c.f;
5984                 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5985                     vtop->c.ld = (long double)vtop->c.d;
5986             } else {
5987                 /* non constant case: generate code */
5988                 gen_cvt_ftof(dbt);
5989             }
5990         } else if (df) {
5991             /* convert int to fp */
5992             if (c) {
5993                 switch(sbt) {
5994                 case VT_LLONG | VT_UNSIGNED:
5995                 case VT_LLONG:
5996                     /* XXX: add const cases for long long */
5997                     goto do_itof;
5998                 case VT_INT | VT_UNSIGNED:
5999                     switch(dbt) {
6000                     case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
6001                     case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
6002                     case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
6003                     }
6004                     break;
6005                 default:
6006                     switch(dbt) {
6007                     case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
6008                     case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
6009                     case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
6010                     }
6011                     break;
6012                 }
6013             } else {
6014             do_itof:
6015 #if !defined(TCC_TARGET_ARM)
6016                 gen_cvt_itof1(dbt);
6017 #else
6018                 gen_cvt_itof(dbt);
6019 #endif
6020             }
6021         } else if (sf) {
6022             /* convert fp to int */
6023             if (dbt == VT_BOOL) {
6024                  vpushi(0);
6025                  gen_op(TOK_NE);
6026             } else {
6027                 /* we handle char/short/etc... with generic code */
6028                 if (dbt != (VT_INT | VT_UNSIGNED) &&
6029                     dbt != (VT_LLONG | VT_UNSIGNED) &&
6030                     dbt != VT_LLONG)
6031                     dbt = VT_INT;
6032                 if (c) {
6033                     switch(dbt) {
6034                     case VT_LLONG | VT_UNSIGNED:
6035                     case VT_LLONG:
6036                         /* XXX: add const cases for long long */
6037                         goto do_ftoi;
6038                     case VT_INT | VT_UNSIGNED:
6039                         switch(sbt) {
6040                         case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6041                         case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6042                         case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6043                         }
6044                         break;
6045                     default:
6046                         /* int case */
6047                         switch(sbt) {
6048                         case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6049                         case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6050                         case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6051                         }
6052                         break;
6053                     }
6054                 } else {
6055                 do_ftoi:
6056                     gen_cvt_ftoi1(dbt);
6057                 }
6058                 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6059                     /* additional cast for char/short... */
6060                     vtop->type.t = dbt;
6061                     gen_cast(type);
6062                 }
6063             }
6064         } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6065             if ((sbt & VT_BTYPE) != VT_LLONG) {
6066                 /* scalar to long long */
6067                 if (c) {
6068                     if (sbt == (VT_INT | VT_UNSIGNED))
6069                         vtop->c.ll = vtop->c.ui;
6070                     else
6071                         vtop->c.ll = vtop->c.i;
6072                 } else {
6073                     /* machine independent conversion */
6074                     gv(RC_INT);
6075                     /* generate high word */
6076                     if (sbt == (VT_INT | VT_UNSIGNED)) {
6077                         vpushi(0);
6078                         gv(RC_INT);
6079                     } else {
6080                         gv_dup();
6081                         vpushi(31);
6082                         gen_op(TOK_SAR);
6083                     }
6084                     /* patch second register */
6085                     vtop[-1].r2 = vtop->r;
6086                     vpop();
6087                 }
6088             }
6089         } else if (dbt == VT_BOOL) {
6090             /* scalar to bool */
6091             vpushi(0);
6092             gen_op(TOK_NE);
6093         } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6094                    (dbt & VT_BTYPE) == VT_SHORT) {
6095             if (sbt == VT_PTR) {
6096                 vtop->type.t = VT_INT;
6097                 warning("nonportable conversion from pointer to char/short");
6098             }
6099             force_charshort_cast(dbt);
6100         } else if ((dbt & VT_BTYPE) == VT_INT) {
6101             /* scalar to int */
6102             if (sbt == VT_LLONG) {
6103                 /* from long long: just take low order word */
6104                 lexpand();
6105                 vpop();
6106             }
6107             /* if lvalue and single word type, nothing to do because
6108                the lvalue already contains the real type size (see
6109                VT_LVAL_xxx constants) */
6110         }
6111     } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6112         /* if we are casting between pointer types,
6113            we must update the VT_LVAL_xxx size */
6114         vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6115                   | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6116     }
6117     vtop->type = *type;
6118 }
6119 
6120 /* return type size. Put alignment at 'a' */
type_size(CType * type,int * a)6121 static int type_size(CType *type, int *a)
6122 {
6123     Sym *s;
6124     int bt;
6125 
6126     bt = type->t & VT_BTYPE;
6127     if (bt == VT_STRUCT) {
6128         /* struct/union */
6129         s = type->ref;
6130         *a = s->r;
6131         return s->c;
6132     } else if (bt == VT_PTR) {
6133         if (type->t & VT_ARRAY) {
6134             s = type->ref;
6135             return type_size(&s->type, a) * s->c;
6136         } else {
6137             *a = PTR_SIZE;
6138             return PTR_SIZE;
6139         }
6140     } else if (bt == VT_LDOUBLE) {
6141         *a = LDOUBLE_ALIGN;
6142         return LDOUBLE_SIZE;
6143     } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6144 #ifdef TCC_TARGET_I386
6145         *a = 4;
6146 #elif defined(TCC_TARGET_ARM)
6147 #ifdef TCC_ARM_EABI
6148         *a = 8;
6149 #else
6150         *a = 4;
6151 #endif
6152 #else
6153         *a = 8;
6154 #endif
6155         return 8;
6156     } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6157         *a = 4;
6158         return 4;
6159     } else if (bt == VT_SHORT) {
6160         *a = 2;
6161         return 2;
6162     } else {
6163         /* char, void, function, _Bool */
6164         *a = 1;
6165         return 1;
6166     }
6167 }
6168 
6169 /* return the pointed type of t */
pointed_type(CType * type)6170 static inline CType *pointed_type(CType *type)
6171 {
6172     return &type->ref->type;
6173 }
6174 
6175 /* modify type so that its it is a pointer to type. */
mk_pointer(CType * type)6176 static void mk_pointer(CType *type)
6177 {
6178     Sym *s;
6179     s = sym_push(SYM_FIELD, type, 0, -1);
6180     type->t = VT_PTR | (type->t & ~VT_TYPE);
6181     type->ref = s;
6182 }
6183 
6184 /* compare function types. OLD functions match any new functions */
is_compatible_func(CType * type1,CType * type2)6185 static int is_compatible_func(CType *type1, CType *type2)
6186 {
6187     Sym *s1, *s2;
6188 
6189     s1 = type1->ref;
6190     s2 = type2->ref;
6191     if (!is_compatible_types(&s1->type, &s2->type))
6192         return 0;
6193     /* check func_call */
6194     if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6195         return 0;
6196     /* XXX: not complete */
6197     if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6198         return 1;
6199     if (s1->c != s2->c)
6200         return 0;
6201     while (s1 != NULL) {
6202         if (s2 == NULL)
6203             return 0;
6204         if (!is_compatible_parameter_types(&s1->type, &s2->type))
6205             return 0;
6206         s1 = s1->next;
6207         s2 = s2->next;
6208     }
6209     if (s2)
6210         return 0;
6211     return 1;
6212 }
6213 
6214 /* return true if type1 and type2 are the same.  If unqualified is
6215    true, qualifiers on the types are ignored.
6216 
6217    - enums are not checked as gcc __builtin_types_compatible_p ()
6218  */
compare_types(CType * type1,CType * type2,int unqualified)6219 static int compare_types(CType *type1, CType *type2, int unqualified)
6220 {
6221     int bt1, t1, t2;
6222 
6223     t1 = type1->t & VT_TYPE;
6224     t2 = type2->t & VT_TYPE;
6225     if (unqualified) {
6226         /* strip qualifiers before comparing */
6227         t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6228         t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6229     }
6230     /* XXX: bitfields ? */
6231     if (t1 != t2)
6232         return 0;
6233     /* test more complicated cases */
6234     bt1 = t1 & VT_BTYPE;
6235     if (bt1 == VT_PTR) {
6236         type1 = pointed_type(type1);
6237         type2 = pointed_type(type2);
6238         return is_compatible_types(type1, type2);
6239     } else if (bt1 == VT_STRUCT) {
6240         return (type1->ref == type2->ref);
6241     } else if (bt1 == VT_FUNC) {
6242         return is_compatible_func(type1, type2);
6243     } else {
6244         return 1;
6245     }
6246 }
6247 
6248 /* return true if type1 and type2 are exactly the same (including
6249    qualifiers).
6250 */
is_compatible_types(CType * type1,CType * type2)6251 static int is_compatible_types(CType *type1, CType *type2)
6252 {
6253     return compare_types(type1,type2,0);
6254 }
6255 
6256 /* return true if type1 and type2 are the same (ignoring qualifiers).
6257 */
is_compatible_parameter_types(CType * type1,CType * type2)6258 static int is_compatible_parameter_types(CType *type1, CType *type2)
6259 {
6260     return compare_types(type1,type2,1);
6261 }
6262 
6263 /* print a type. If 'varstr' is not NULL, then the variable is also
6264    printed in the type */
6265 /* XXX: union */
6266 /* XXX: add array and function pointers */
type_to_str(char * buf,int buf_size,CType * type,const char * varstr)6267 void type_to_str(char *buf, int buf_size,
6268                  CType *type, const char *varstr)
6269 {
6270     int bt, v, t;
6271     Sym *s, *sa;
6272     char buf1[256];
6273     const char *tstr;
6274 
6275     t = type->t & VT_TYPE;
6276     bt = t & VT_BTYPE;
6277     buf[0] = '\0';
6278     if (t & VT_CONSTANT)
6279         pstrcat(buf, buf_size, "const ");
6280     if (t & VT_VOLATILE)
6281         pstrcat(buf, buf_size, "volatile ");
6282     if (t & VT_UNSIGNED)
6283         pstrcat(buf, buf_size, "unsigned ");
6284     switch(bt) {
6285     case VT_VOID:
6286         tstr = "void";
6287         goto add_tstr;
6288     case VT_BOOL:
6289         tstr = "_Bool";
6290         goto add_tstr;
6291     case VT_BYTE:
6292         tstr = "char";
6293         goto add_tstr;
6294     case VT_SHORT:
6295         tstr = "short";
6296         goto add_tstr;
6297     case VT_INT:
6298         tstr = "int";
6299         goto add_tstr;
6300     case VT_LONG:
6301         tstr = "long";
6302         goto add_tstr;
6303     case VT_LLONG:
6304         tstr = "long long";
6305         goto add_tstr;
6306     case VT_FLOAT:
6307         tstr = "float";
6308         goto add_tstr;
6309     case VT_DOUBLE:
6310         tstr = "double";
6311         goto add_tstr;
6312     case VT_LDOUBLE:
6313         tstr = "long double";
6314     add_tstr:
6315         pstrcat(buf, buf_size, tstr);
6316         break;
6317     case VT_ENUM:
6318     case VT_STRUCT:
6319         if (bt == VT_STRUCT)
6320             tstr = "struct ";
6321         else
6322             tstr = "enum ";
6323         pstrcat(buf, buf_size, tstr);
6324         v = type->ref->v & ~SYM_STRUCT;
6325         if (v >= SYM_FIRST_ANOM)
6326             pstrcat(buf, buf_size, "<anonymous>");
6327         else
6328             pstrcat(buf, buf_size, get_tok_str(v, NULL));
6329         break;
6330     case VT_FUNC:
6331         s = type->ref;
6332         type_to_str(buf, buf_size, &s->type, varstr);
6333         pstrcat(buf, buf_size, "(");
6334         sa = s->next;
6335         while (sa != NULL) {
6336             type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6337             pstrcat(buf, buf_size, buf1);
6338             sa = sa->next;
6339             if (sa)
6340                 pstrcat(buf, buf_size, ", ");
6341         }
6342         pstrcat(buf, buf_size, ")");
6343         goto no_var;
6344     case VT_PTR:
6345         s = type->ref;
6346         pstrcpy(buf1, sizeof(buf1), "*");
6347         if (varstr)
6348             pstrcat(buf1, sizeof(buf1), varstr);
6349         type_to_str(buf, buf_size, &s->type, buf1);
6350         goto no_var;
6351     }
6352     if (varstr) {
6353         pstrcat(buf, buf_size, " ");
6354         pstrcat(buf, buf_size, varstr);
6355     }
6356  no_var: ;
6357 }
6358 
6359 /* verify type compatibility to store vtop in 'dt' type, and generate
6360    casts if needed. */
gen_assign_cast(CType * dt)6361 static void gen_assign_cast(CType *dt)
6362 {
6363     CType *st, *type1, *type2, tmp_type1, tmp_type2;
6364     char buf1[256], buf2[256];
6365     int dbt, sbt;
6366 
6367     st = &vtop->type; /* source type */
6368     dbt = dt->t & VT_BTYPE;
6369     sbt = st->t & VT_BTYPE;
6370     if (dt->t & VT_CONSTANT)
6371         warning("assignment of read-only location");
6372     switch(dbt) {
6373     case VT_PTR:
6374         /* special cases for pointers */
6375         /* '0' can also be a pointer */
6376         if (is_null_pointer(vtop))
6377             goto type_ok;
6378         /* accept implicit pointer to integer cast with warning */
6379         if (is_integer_btype(sbt)) {
6380             warning("assignment makes pointer from integer without a cast");
6381             goto type_ok;
6382         }
6383         type1 = pointed_type(dt);
6384         /* a function is implicitely a function pointer */
6385         if (sbt == VT_FUNC) {
6386             if ((type1->t & VT_BTYPE) != VT_VOID &&
6387                 !is_compatible_types(pointed_type(dt), st))
6388                 goto error;
6389             else
6390                 goto type_ok;
6391         }
6392         if (sbt != VT_PTR)
6393             goto error;
6394         type2 = pointed_type(st);
6395         if ((type1->t & VT_BTYPE) == VT_VOID ||
6396             (type2->t & VT_BTYPE) == VT_VOID) {
6397             /* void * can match anything */
6398         } else {
6399             /* exact type match, except for unsigned */
6400             tmp_type1 = *type1;
6401             tmp_type2 = *type2;
6402             tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6403             tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6404             if (!is_compatible_types(&tmp_type1, &tmp_type2))
6405                 warning("assignment from incompatible pointer type");
6406         }
6407         /* check const and volatile */
6408         if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6409             (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6410             warning("assignment discards qualifiers from pointer target type");
6411         break;
6412     case VT_BYTE:
6413     case VT_SHORT:
6414     case VT_INT:
6415     case VT_LLONG:
6416         if (sbt == VT_PTR || sbt == VT_FUNC) {
6417             warning("assignment makes integer from pointer without a cast");
6418         }
6419         /* XXX: more tests */
6420         break;
6421     case VT_STRUCT:
6422         tmp_type1 = *dt;
6423         tmp_type2 = *st;
6424         tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6425         tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6426         if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6427         error:
6428             type_to_str(buf1, sizeof(buf1), st, NULL);
6429             type_to_str(buf2, sizeof(buf2), dt, NULL);
6430             error("cannot cast '%s' to '%s'", buf1, buf2);
6431         }
6432         break;
6433     }
6434  type_ok:
6435     gen_cast(dt);
6436 }
6437 
6438 /* store vtop in lvalue pushed on stack */
vstore(void)6439 void vstore(void)
6440 {
6441     int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6442 
6443     ft = vtop[-1].type.t;
6444     sbt = vtop->type.t & VT_BTYPE;
6445     dbt = ft & VT_BTYPE;
6446     if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6447         (sbt == VT_INT && dbt == VT_SHORT)) {
6448         /* optimize char/short casts */
6449         delayed_cast = VT_MUSTCAST;
6450         vtop->type.t = ft & VT_TYPE;
6451         /* XXX: factorize */
6452         if (ft & VT_CONSTANT)
6453             warning("assignment of read-only location");
6454     } else {
6455         delayed_cast = 0;
6456         if (!(ft & VT_BITFIELD))
6457             gen_assign_cast(&vtop[-1].type);
6458     }
6459 
6460     if (sbt == VT_STRUCT) {
6461         /* if structure, only generate pointer */
6462         /* structure assignment : generate memcpy */
6463         /* XXX: optimize if small size */
6464         if (!nocode_wanted) {
6465             size = type_size(&vtop->type, &align);
6466 
6467 #ifdef TCC_ARM_EABI
6468             if(!(align & 7))
6469                 vpush_global_sym(&func_old_type, TOK_memcpy8);
6470             else if(!(align & 3))
6471                 vpush_global_sym(&func_old_type, TOK_memcpy4);
6472             else
6473 #endif
6474             vpush_global_sym(&func_old_type, TOK_memcpy);
6475 
6476             /* destination */
6477             vpushv(vtop - 2);
6478             vtop->type.t = VT_INT;
6479             gaddrof();
6480             /* source */
6481             vpushv(vtop - 2);
6482             vtop->type.t = VT_INT;
6483             gaddrof();
6484             /* type size */
6485             vpushi(size);
6486             gfunc_call(3);
6487 
6488             vswap();
6489             vpop();
6490         } else {
6491             vswap();
6492             vpop();
6493         }
6494         /* leave source on stack */
6495     } else if (ft & VT_BITFIELD) {
6496         /* bitfield store handling */
6497         bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6498         bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6499         /* remove bit field info to avoid loops */
6500         vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6501 
6502         /* duplicate source into other register */
6503         gv_dup();
6504         vswap();
6505         vrott(3);
6506 
6507         /* duplicate destination */
6508         vdup();
6509         vtop[-1] = vtop[-2];
6510 
6511         /* mask and shift source */
6512         vpushi((1 << bit_size) - 1);
6513         gen_op('&');
6514         vpushi(bit_pos);
6515         gen_op(TOK_SHL);
6516         /* load destination, mask and or with source */
6517         vswap();
6518         vpushi(~(((1 << bit_size) - 1) << bit_pos));
6519         gen_op('&');
6520         gen_op('|');
6521         /* store result */
6522         vstore();
6523 
6524         /* pop off shifted source from "duplicate source..." above */
6525         vpop();
6526 
6527     } else {
6528 #ifdef CONFIG_TCC_BCHECK
6529         /* bound check case */
6530         if (vtop[-1].r & VT_MUSTBOUND) {
6531             vswap();
6532             gbound();
6533             vswap();
6534         }
6535 #endif
6536         if (!nocode_wanted) {
6537             rc = RC_INT;
6538             if (is_float(ft))
6539                 rc = RC_FLOAT;
6540             r = gv(rc);  /* generate value */
6541             /* if lvalue was saved on stack, must read it */
6542             if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6543                 SValue sv;
6544                 t = get_reg(RC_INT);
6545                 sv.type.t = VT_INT;
6546                 sv.r = VT_LOCAL | VT_LVAL;
6547                 sv.c.ul = vtop[-1].c.ul;
6548                 load(t, &sv);
6549                 vtop[-1].r = t | VT_LVAL;
6550             }
6551             store(r, vtop - 1);
6552             /* two word case handling : store second register at word + 4 */
6553             if ((ft & VT_BTYPE) == VT_LLONG) {
6554                 vswap();
6555                 /* convert to int to increment easily */
6556                 vtop->type.t = VT_INT;
6557                 gaddrof();
6558                 vpushi(4);
6559                 gen_op('+');
6560                 vtop->r |= VT_LVAL;
6561                 vswap();
6562                 /* XXX: it works because r2 is spilled last ! */
6563                 store(vtop->r2, vtop - 1);
6564             }
6565         }
6566         vswap();
6567         vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6568         vtop->r |= delayed_cast;
6569     }
6570 }
6571 
6572 /* post defines POST/PRE add. c is the token ++ or -- */
inc(int post,int c)6573 void inc(int post, int c)
6574 {
6575     test_lvalue();
6576     vdup(); /* save lvalue */
6577     if (post) {
6578         gv_dup(); /* duplicate value */
6579         vrotb(3);
6580         vrotb(3);
6581     }
6582     /* add constant */
6583     vpushi(c - TOK_MID);
6584     gen_op('+');
6585     vstore(); /* store value */
6586     if (post)
6587         vpop(); /* if post op, return saved value */
6588 }
6589 
6590 /* Parse GNUC __attribute__ extension. Currently, the following
6591    extensions are recognized:
6592    - aligned(n) : set data/function alignment.
6593    - packed : force data alignment to 1
6594    - section(x) : generate data/code in this section.
6595    - unused : currently ignored, but may be used someday.
6596    - regparm(n) : pass function parameters in registers (i386 only)
6597  */
parse_attribute(AttributeDef * ad)6598 static void parse_attribute(AttributeDef *ad)
6599 {
6600     int t, n;
6601 
6602     while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6603     next();
6604     skip('(');
6605     skip('(');
6606     while (tok != ')') {
6607         if (tok < TOK_IDENT)
6608             expect("attribute name");
6609         t = tok;
6610         next();
6611         switch(t) {
6612         case TOK_SECTION1:
6613         case TOK_SECTION2:
6614             skip('(');
6615             if (tok != TOK_STR)
6616                 expect("section name");
6617             ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6618             next();
6619             skip(')');
6620             break;
6621         case TOK_ALIGNED1:
6622         case TOK_ALIGNED2:
6623             if (tok == '(') {
6624                 next();
6625                 n = expr_const();
6626                 if (n <= 0 || (n & (n - 1)) != 0)
6627                     error("alignment must be a positive power of two");
6628                 skip(')');
6629             } else {
6630                 n = MAX_ALIGN;
6631             }
6632             ad->aligned = n;
6633             break;
6634         case TOK_PACKED1:
6635         case TOK_PACKED2:
6636             ad->packed = 1;
6637             break;
6638         case TOK_UNUSED1:
6639         case TOK_UNUSED2:
6640             /* currently, no need to handle it because tcc does not
6641                track unused objects */
6642             break;
6643         case TOK_NORETURN1:
6644         case TOK_NORETURN2:
6645             /* currently, no need to handle it because tcc does not
6646                track unused objects */
6647             break;
6648         case TOK_CDECL1:
6649         case TOK_CDECL2:
6650         case TOK_CDECL3:
6651             FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6652             break;
6653         case TOK_STDCALL1:
6654         case TOK_STDCALL2:
6655         case TOK_STDCALL3:
6656             FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6657             break;
6658 #ifdef TCC_TARGET_I386
6659         case TOK_REGPARM1:
6660         case TOK_REGPARM2:
6661             skip('(');
6662             n = expr_const();
6663             if (n > 3)
6664                 n = 3;
6665             else if (n < 0)
6666                 n = 0;
6667             if (n > 0)
6668                 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6669             skip(')');
6670             break;
6671         case TOK_FASTCALL1:
6672         case TOK_FASTCALL2:
6673         case TOK_FASTCALL3:
6674             FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6675             break;
6676 #endif
6677         case TOK_DLLEXPORT:
6678             FUNC_EXPORT(ad->func_attr) = 1;
6679             break;
6680         default:
6681             if (tcc_state->warn_unsupported)
6682                 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6683             /* skip parameters */
6684             if (tok == '(') {
6685                 int parenthesis = 0;
6686                 do {
6687                     if (tok == '(')
6688                         parenthesis++;
6689                     else if (tok == ')')
6690                         parenthesis--;
6691                     next();
6692                 } while (parenthesis && tok != -1);
6693             }
6694             break;
6695         }
6696         if (tok != ',')
6697             break;
6698         next();
6699     }
6700     skip(')');
6701     skip(')');
6702     }
6703 }
6704 
6705 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
struct_decl(CType * type,int u)6706 static void struct_decl(CType *type, int u)
6707 {
6708     int a, v, size, align, maxalign, c, offset;
6709     int bit_size, bit_pos, bsize, bt, lbit_pos;
6710     Sym *s, *ss, *ass, **ps;
6711     AttributeDef ad;
6712     CType type1, btype;
6713 
6714     a = tok; /* save decl type */
6715     next();
6716     if (tok != '{') {
6717         v = tok;
6718         next();
6719         /* struct already defined ? return it */
6720         if (v < TOK_IDENT)
6721             expect("struct/union/enum name");
6722         s = struct_find(v);
6723         if (s) {
6724             if (s->type.t != a)
6725                 error("invalid type");
6726             goto do_decl;
6727         }
6728     } else {
6729         v = anon_sym++;
6730     }
6731     type1.t = a;
6732     /* we put an undefined size for struct/union */
6733     s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6734     s->r = 0; /* default alignment is zero as gcc */
6735     /* put struct/union/enum name in type */
6736  do_decl:
6737     type->t = u;
6738     type->ref = s;
6739 
6740     if (tok == '{') {
6741         next();
6742         if (s->c != -1)
6743             error("struct/union/enum already defined");
6744         /* cannot be empty */
6745         c = 0;
6746         /* non empty enums are not allowed */
6747         if (a == TOK_ENUM) {
6748             for(;;) {
6749                 v = tok;
6750                 if (v < TOK_UIDENT)
6751                     expect("identifier");
6752                 next();
6753                 if (tok == '=') {
6754                     next();
6755                     c = expr_const();
6756                 }
6757                 /* enum symbols have static storage */
6758                 ss = sym_push(v, &int_type, VT_CONST, c);
6759                 ss->type.t |= VT_STATIC;
6760                 if (tok != ',')
6761                     break;
6762                 next();
6763                 c++;
6764                 /* NOTE: we accept a trailing comma */
6765                 if (tok == '}')
6766                     break;
6767             }
6768             skip('}');
6769         } else {
6770             maxalign = 1;
6771             ps = &s->next;
6772             bit_pos = 0;
6773             offset = 0;
6774             while (tok != '}') {
6775                 parse_btype(&btype, &ad);
6776                 while (1) {
6777                     bit_size = -1;
6778                     v = 0;
6779                     type1 = btype;
6780                     if (tok != ':') {
6781                         type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6782                         if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6783                             expect("identifier");
6784                         if ((type1.t & VT_BTYPE) == VT_FUNC ||
6785                             (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6786                             error("invalid type for '%s'",
6787                                   get_tok_str(v, NULL));
6788                     }
6789                     if (tok == ':') {
6790                         next();
6791                         bit_size = expr_const();
6792                         /* XXX: handle v = 0 case for messages */
6793                         if (bit_size < 0)
6794                             error("negative width in bit-field '%s'",
6795                                   get_tok_str(v, NULL));
6796                         if (v && bit_size == 0)
6797                             error("zero width for bit-field '%s'",
6798                                   get_tok_str(v, NULL));
6799                     }
6800                     size = type_size(&type1, &align);
6801                     if (ad.aligned) {
6802                         if (align < ad.aligned)
6803                             align = ad.aligned;
6804                     } else if (ad.packed) {
6805                         align = 1;
6806                     } else if (*tcc_state->pack_stack_ptr) {
6807                         if (align > *tcc_state->pack_stack_ptr)
6808                             align = *tcc_state->pack_stack_ptr;
6809                     }
6810                     lbit_pos = 0;
6811                     if (bit_size >= 0) {
6812                         bt = type1.t & VT_BTYPE;
6813                         if (bt != VT_INT &&
6814                             bt != VT_BYTE &&
6815                             bt != VT_SHORT &&
6816                             bt != VT_BOOL &&
6817                             bt != VT_ENUM)
6818                             error("bitfields must have scalar type");
6819                         bsize = size * 8;
6820                         if (bit_size > bsize) {
6821                             error("width of '%s' exceeds its type",
6822                                   get_tok_str(v, NULL));
6823                         } else if (bit_size == bsize) {
6824                             /* no need for bit fields */
6825                             bit_pos = 0;
6826                         } else if (bit_size == 0) {
6827                             /* XXX: what to do if only padding in a
6828                                structure ? */
6829                             /* zero size: means to pad */
6830                             if (bit_pos > 0)
6831                                 bit_pos = bsize;
6832                         } else {
6833                             /* we do not have enough room ? */
6834                             if ((bit_pos + bit_size) > bsize)
6835                                 bit_pos = 0;
6836                             lbit_pos = bit_pos;
6837                             /* XXX: handle LSB first */
6838                             type1.t |= VT_BITFIELD |
6839                                 (bit_pos << VT_STRUCT_SHIFT) |
6840                                 (bit_size << (VT_STRUCT_SHIFT + 6));
6841                             bit_pos += bit_size;
6842                         }
6843                     } else {
6844                         bit_pos = 0;
6845                     }
6846                     if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6847                         /* add new memory data only if starting
6848                            bit field */
6849                         if (lbit_pos == 0) {
6850                             if (a == TOK_STRUCT) {
6851                                 c = (c + align - 1) & -align;
6852                                 offset = c;
6853                                 if (size > 0)
6854                                     c += size;
6855                             } else {
6856                                 offset = 0;
6857                                 if (size > c)
6858                                     c = size;
6859                             }
6860                             if (align > maxalign)
6861                                 maxalign = align;
6862                         }
6863 #if 0
6864                         printf("add field %s offset=%d",
6865                                get_tok_str(v, NULL), offset);
6866                         if (type1.t & VT_BITFIELD) {
6867                             printf(" pos=%d size=%d",
6868                                    (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6869                                    (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6870                         }
6871                         printf("\n");
6872 #endif
6873                     }
6874                     if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6875                         ass = type1.ref;
6876                         while ((ass = ass->next) != NULL) {
6877                            ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6878                            *ps = ss;
6879                            ps = &ss->next;
6880                         }
6881                     } else if (v) {
6882                         ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6883                         *ps = ss;
6884                         ps = &ss->next;
6885                     }
6886                     if (tok == ';' || tok == TOK_EOF)
6887                         break;
6888                     skip(',');
6889                 }
6890                 skip(';');
6891             }
6892             skip('}');
6893             /* store size and alignment */
6894             s->c = (c + maxalign - 1) & -maxalign;
6895             s->r = maxalign;
6896         }
6897     }
6898 }
6899 
6900 /* return 0 if no type declaration. otherwise, return the basic type
6901    and skip it.
6902  */
parse_btype(CType * type,AttributeDef * ad)6903 static int parse_btype(CType *type, AttributeDef *ad)
6904 {
6905     int t, u, type_found, typespec_found, typedef_found;
6906     Sym *s;
6907     CType type1;
6908 
6909     memset(ad, 0, sizeof(AttributeDef));
6910     type_found = 0;
6911     typespec_found = 0;
6912     typedef_found = 0;
6913     t = 0;
6914     while(1) {
6915         switch(tok) {
6916         case TOK_EXTENSION:
6917             /* currently, we really ignore extension */
6918             next();
6919             continue;
6920 
6921             /* basic types */
6922         case TOK_CHAR:
6923             u = VT_BYTE;
6924         basic_type:
6925             next();
6926         basic_type1:
6927             if ((t & VT_BTYPE) != 0)
6928                 error("too many basic types");
6929             t |= u;
6930             typespec_found = 1;
6931             break;
6932         case TOK_VOID:
6933             u = VT_VOID;
6934             goto basic_type;
6935         case TOK_SHORT:
6936             u = VT_SHORT;
6937             goto basic_type;
6938         case TOK_INT:
6939             next();
6940             typespec_found = 1;
6941             break;
6942         case TOK_LONG:
6943             next();
6944             if ((t & VT_BTYPE) == VT_DOUBLE) {
6945                 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6946             } else if ((t & VT_BTYPE) == VT_LONG) {
6947                 t = (t & ~VT_BTYPE) | VT_LLONG;
6948             } else {
6949                 u = VT_LONG;
6950                 goto basic_type1;
6951             }
6952             break;
6953         case TOK_BOOL:
6954             u = VT_BOOL;
6955             goto basic_type;
6956         case TOK_FLOAT:
6957             u = VT_FLOAT;
6958             goto basic_type;
6959         case TOK_DOUBLE:
6960             next();
6961             if ((t & VT_BTYPE) == VT_LONG) {
6962                 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6963             } else {
6964                 u = VT_DOUBLE;
6965                 goto basic_type1;
6966             }
6967             break;
6968         case TOK_ENUM:
6969             struct_decl(&type1, VT_ENUM);
6970         basic_type2:
6971             u = type1.t;
6972             type->ref = type1.ref;
6973             goto basic_type1;
6974         case TOK_STRUCT:
6975         case TOK_UNION:
6976             struct_decl(&type1, VT_STRUCT);
6977             goto basic_type2;
6978 
6979             /* type modifiers */
6980         case TOK_CONST1:
6981         case TOK_CONST2:
6982         case TOK_CONST3:
6983             t |= VT_CONSTANT;
6984             next();
6985             break;
6986         case TOK_VOLATILE1:
6987         case TOK_VOLATILE2:
6988         case TOK_VOLATILE3:
6989             t |= VT_VOLATILE;
6990             next();
6991             break;
6992         case TOK_SIGNED1:
6993         case TOK_SIGNED2:
6994         case TOK_SIGNED3:
6995             typespec_found = 1;
6996             t |= VT_SIGNED;
6997             next();
6998             break;
6999         case TOK_REGISTER:
7000         case TOK_AUTO:
7001         case TOK_RESTRICT1:
7002         case TOK_RESTRICT2:
7003         case TOK_RESTRICT3:
7004             next();
7005             break;
7006         case TOK_UNSIGNED:
7007             t |= VT_UNSIGNED;
7008             next();
7009             typespec_found = 1;
7010             break;
7011 
7012             /* storage */
7013         case TOK_EXTERN:
7014             t |= VT_EXTERN;
7015             next();
7016             break;
7017         case TOK_STATIC:
7018             t |= VT_STATIC;
7019             next();
7020             break;
7021         case TOK_TYPEDEF:
7022             t |= VT_TYPEDEF;
7023             next();
7024             break;
7025         case TOK_INLINE1:
7026         case TOK_INLINE2:
7027         case TOK_INLINE3:
7028             t |= VT_INLINE;
7029             next();
7030             break;
7031 
7032             /* GNUC attribute */
7033         case TOK_ATTRIBUTE1:
7034         case TOK_ATTRIBUTE2:
7035             parse_attribute(ad);
7036             break;
7037             /* GNUC typeof */
7038         case TOK_TYPEOF1:
7039         case TOK_TYPEOF2:
7040         case TOK_TYPEOF3:
7041             next();
7042             parse_expr_type(&type1);
7043             goto basic_type2;
7044         default:
7045             if (typespec_found || typedef_found)
7046                 goto the_end;
7047             s = sym_find(tok);
7048             if (!s || !(s->type.t & VT_TYPEDEF))
7049                 goto the_end;
7050             typedef_found = 1;
7051             t |= (s->type.t & ~VT_TYPEDEF);
7052             type->ref = s->type.ref;
7053             next();
7054             typespec_found = 1;
7055             break;
7056         }
7057         type_found = 1;
7058     }
7059 the_end:
7060     if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7061         error("signed and unsigned modifier");
7062     if (tcc_state->char_is_unsigned) {
7063         if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7064             t |= VT_UNSIGNED;
7065     }
7066     t &= ~VT_SIGNED;
7067 
7068     /* long is never used as type */
7069     if ((t & VT_BTYPE) == VT_LONG)
7070         t = (t & ~VT_BTYPE) | VT_INT;
7071     type->t = t;
7072     return type_found;
7073 }
7074 
7075 /* convert a function parameter type (array to pointer and function to
7076    function pointer) */
convert_parameter_type(CType * pt)7077 static inline void convert_parameter_type(CType *pt)
7078 {
7079     /* remove const and volatile qualifiers (XXX: const could be used
7080        to indicate a const function parameter */
7081     pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7082     /* array must be transformed to pointer according to ANSI C */
7083     pt->t &= ~VT_ARRAY;
7084     if ((pt->t & VT_BTYPE) == VT_FUNC) {
7085         mk_pointer(pt);
7086     }
7087 }
7088 
post_type(CType * type,AttributeDef * ad)7089 static void post_type(CType *type, AttributeDef *ad)
7090 {
7091     int n, l, t1, arg_size, align;
7092     Sym **plast, *s, *first;
7093     AttributeDef ad1;
7094     CType pt;
7095 
7096     if (tok == '(') {
7097         /* function declaration */
7098         next();
7099         l = 0;
7100         first = NULL;
7101         plast = &first;
7102         arg_size = 0;
7103         if (tok != ')') {
7104             for(;;) {
7105                 /* read param name and compute offset */
7106                 if (l != FUNC_OLD) {
7107                     if (!parse_btype(&pt, &ad1)) {
7108                         if (l) {
7109                             error("invalid type");
7110                         } else {
7111                             l = FUNC_OLD;
7112                             goto old_proto;
7113                         }
7114                     }
7115                     l = FUNC_NEW;
7116                     if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7117                         break;
7118                     type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7119                     if ((pt.t & VT_BTYPE) == VT_VOID)
7120                         error("parameter declared as void");
7121                     arg_size += (type_size(&pt, &align) + 3) & ~3;
7122                 } else {
7123                 old_proto:
7124                     n = tok;
7125                     if (n < TOK_UIDENT)
7126                         expect("identifier");
7127                     pt.t = VT_INT;
7128                     next();
7129                 }
7130                 convert_parameter_type(&pt);
7131                 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7132                 *plast = s;
7133                 plast = &s->next;
7134                 if (tok == ')')
7135                     break;
7136                 skip(',');
7137                 if (l == FUNC_NEW && tok == TOK_DOTS) {
7138                     l = FUNC_ELLIPSIS;
7139                     next();
7140                     break;
7141                 }
7142             }
7143         }
7144         /* if no parameters, then old type prototype */
7145         if (l == 0)
7146             l = FUNC_OLD;
7147         skip(')');
7148         t1 = type->t & VT_STORAGE;
7149         /* NOTE: const is ignored in returned type as it has a special
7150            meaning in gcc / C++ */
7151         type->t &= ~(VT_STORAGE | VT_CONSTANT);
7152         post_type(type, ad);
7153         /* we push a anonymous symbol which will contain the function prototype */
7154         FUNC_ARGS(ad->func_attr) = arg_size;
7155         s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7156         s->next = first;
7157         type->t = t1 | VT_FUNC;
7158         type->ref = s;
7159     } else if (tok == '[') {
7160         /* array definition */
7161         next();
7162         n = -1;
7163         if (tok != ']') {
7164             n = expr_const();
7165             if (n < 0)
7166                 error("invalid array size");
7167         }
7168         skip(']');
7169         /* parse next post type */
7170         t1 = type->t & VT_STORAGE;
7171         type->t &= ~VT_STORAGE;
7172         post_type(type, ad);
7173 
7174         /* we push a anonymous symbol which will contain the array
7175            element type */
7176         s = sym_push(SYM_FIELD, type, 0, n);
7177         type->t = t1 | VT_ARRAY | VT_PTR;
7178         type->ref = s;
7179     }
7180 }
7181 
7182 /* Parse a type declaration (except basic type), and return the type
7183    in 'type'. 'td' is a bitmask indicating which kind of type decl is
7184    expected. 'type' should contain the basic type. 'ad' is the
7185    attribute definition of the basic type. It can be modified by
7186    type_decl().
7187  */
type_decl(CType * type,AttributeDef * ad,int * v,int td)7188 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7189 {
7190     Sym *s;
7191     CType type1, *type2;
7192     int qualifiers;
7193 
7194     while (tok == '*') {
7195         qualifiers = 0;
7196     redo:
7197         next();
7198         switch(tok) {
7199         case TOK_CONST1:
7200         case TOK_CONST2:
7201         case TOK_CONST3:
7202             qualifiers |= VT_CONSTANT;
7203             goto redo;
7204         case TOK_VOLATILE1:
7205         case TOK_VOLATILE2:
7206         case TOK_VOLATILE3:
7207             qualifiers |= VT_VOLATILE;
7208             goto redo;
7209         case TOK_RESTRICT1:
7210         case TOK_RESTRICT2:
7211         case TOK_RESTRICT3:
7212             goto redo;
7213         }
7214         mk_pointer(type);
7215         type->t |= qualifiers;
7216     }
7217 
7218     /* XXX: clarify attribute handling */
7219     if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7220         parse_attribute(ad);
7221 
7222     /* recursive type */
7223     /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7224     type1.t = 0; /* XXX: same as int */
7225     if (tok == '(') {
7226         next();
7227         /* XXX: this is not correct to modify 'ad' at this point, but
7228            the syntax is not clear */
7229         if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7230             parse_attribute(ad);
7231         type_decl(&type1, ad, v, td);
7232         skip(')');
7233     } else {
7234         /* type identifier */
7235         if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7236             *v = tok;
7237             next();
7238         } else {
7239             if (!(td & TYPE_ABSTRACT))
7240                 expect("identifier");
7241             *v = 0;
7242         }
7243     }
7244     post_type(type, ad);
7245     if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7246         parse_attribute(ad);
7247     if (!type1.t)
7248         return;
7249     /* append type at the end of type1 */
7250     type2 = &type1;
7251     for(;;) {
7252         s = type2->ref;
7253         type2 = &s->type;
7254         if (!type2->t) {
7255             *type2 = *type;
7256             break;
7257         }
7258     }
7259     *type = type1;
7260 }
7261 
7262 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
lvalue_type(int t)7263 static int lvalue_type(int t)
7264 {
7265     int bt, r;
7266     r = VT_LVAL;
7267     bt = t & VT_BTYPE;
7268     if (bt == VT_BYTE || bt == VT_BOOL)
7269         r |= VT_LVAL_BYTE;
7270     else if (bt == VT_SHORT)
7271         r |= VT_LVAL_SHORT;
7272     else
7273         return r;
7274     if (t & VT_UNSIGNED)
7275         r |= VT_LVAL_UNSIGNED;
7276     return r;
7277 }
7278 
7279 /* indirection with full error checking and bound check */
indir(void)7280 static void indir(void)
7281 {
7282     if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7283         if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7284             return;
7285         expect("pointer");
7286     }
7287     if ((vtop->r & VT_LVAL) && !nocode_wanted)
7288         gv(RC_INT);
7289     vtop->type = *pointed_type(&vtop->type);
7290     /* Arrays and functions are never lvalues */
7291     if (!(vtop->type.t & VT_ARRAY)
7292         && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7293         vtop->r |= lvalue_type(vtop->type.t);
7294         /* if bound checking, the referenced pointer must be checked */
7295         if (do_bounds_check)
7296             vtop->r |= VT_MUSTBOUND;
7297     }
7298 }
7299 
7300 /* pass a parameter to a function and do type checking and casting */
gfunc_param_typed(Sym * func,Sym * arg)7301 static void gfunc_param_typed(Sym *func, Sym *arg)
7302 {
7303     int func_type;
7304     CType type;
7305 
7306     func_type = func->c;
7307     if (func_type == FUNC_OLD ||
7308         (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7309         /* default casting : only need to convert float to double */
7310         if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7311             type.t = VT_DOUBLE;
7312             gen_cast(&type);
7313         }
7314     } else if (arg == NULL) {
7315         error("too many arguments to function");
7316     } else {
7317         type = arg->type;
7318         type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7319         gen_assign_cast(&type);
7320     }
7321 }
7322 
7323 /* parse an expression of the form '(type)' or '(expr)' and return its
7324    type */
parse_expr_type(CType * type)7325 static void parse_expr_type(CType *type)
7326 {
7327     int n;
7328     AttributeDef ad;
7329 
7330     skip('(');
7331     if (parse_btype(type, &ad)) {
7332         type_decl(type, &ad, &n, TYPE_ABSTRACT);
7333     } else {
7334         expr_type(type);
7335     }
7336     skip(')');
7337 }
7338 
parse_type(CType * type)7339 static void parse_type(CType *type)
7340 {
7341     AttributeDef ad;
7342     int n;
7343 
7344     if (!parse_btype(type, &ad)) {
7345         expect("type");
7346     }
7347     type_decl(type, &ad, &n, TYPE_ABSTRACT);
7348 }
7349 
vpush_tokc(int t)7350 static void vpush_tokc(int t)
7351 {
7352     CType type;
7353     type.t = t;
7354     vsetc(&type, VT_CONST, &tokc);
7355 }
7356 
unary(void)7357 static void unary(void)
7358 {
7359     int n, t, align, size, r;
7360     CType type;
7361     Sym *s;
7362     AttributeDef ad;
7363 
7364     /* XXX: GCC 2.95.3 does not generate a table although it should be
7365        better here */
7366  tok_next:
7367     switch(tok) {
7368     case TOK_EXTENSION:
7369         next();
7370         goto tok_next;
7371     case TOK_CINT:
7372     case TOK_CCHAR:
7373     case TOK_LCHAR:
7374         vpushi(tokc.i);
7375         next();
7376         break;
7377     case TOK_CUINT:
7378         vpush_tokc(VT_INT | VT_UNSIGNED);
7379         next();
7380         break;
7381     case TOK_CLLONG:
7382         vpush_tokc(VT_LLONG);
7383         next();
7384         break;
7385     case TOK_CULLONG:
7386         vpush_tokc(VT_LLONG | VT_UNSIGNED);
7387         next();
7388         break;
7389     case TOK_CFLOAT:
7390         vpush_tokc(VT_FLOAT);
7391         next();
7392         break;
7393     case TOK_CDOUBLE:
7394         vpush_tokc(VT_DOUBLE);
7395         next();
7396         break;
7397     case TOK_CLDOUBLE:
7398         vpush_tokc(VT_LDOUBLE);
7399         next();
7400         break;
7401     case TOK___FUNCTION__:
7402         if (!gnu_ext)
7403             goto tok_identifier;
7404         /* fall thru */
7405     case TOK___FUNC__:
7406         {
7407             void *ptr;
7408             int len;
7409             /* special function name identifier */
7410             len = strlen(funcname) + 1;
7411             /* generate char[len] type */
7412             type.t = VT_BYTE;
7413             mk_pointer(&type);
7414             type.t |= VT_ARRAY;
7415             type.ref->c = len;
7416             vpush_ref(&type, data_section, data_section->data_offset, len);
7417             ptr = section_ptr_add(data_section, len);
7418             memcpy(ptr, funcname, len);
7419             next();
7420         }
7421         break;
7422     case TOK_LSTR:
7423 #ifdef TCC_TARGET_PE
7424         t = VT_SHORT | VT_UNSIGNED;
7425 #else
7426         t = VT_INT;
7427 #endif
7428         goto str_init;
7429     case TOK_STR:
7430         /* string parsing */
7431         t = VT_BYTE;
7432     str_init:
7433         if (tcc_state->warn_write_strings)
7434             t |= VT_CONSTANT;
7435         type.t = t;
7436         mk_pointer(&type);
7437         type.t |= VT_ARRAY;
7438         memset(&ad, 0, sizeof(AttributeDef));
7439         decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7440         break;
7441     case '(':
7442         next();
7443         /* cast ? */
7444         if (parse_btype(&type, &ad)) {
7445             type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7446             skip(')');
7447             /* check ISOC99 compound literal */
7448             if (tok == '{') {
7449                     /* data is allocated locally by default */
7450                 if (global_expr)
7451                     r = VT_CONST;
7452                 else
7453                     r = VT_LOCAL;
7454                 /* all except arrays are lvalues */
7455                 if (!(type.t & VT_ARRAY))
7456                     r |= lvalue_type(type.t);
7457                 memset(&ad, 0, sizeof(AttributeDef));
7458                 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7459             } else {
7460                 unary();
7461                 gen_cast(&type);
7462             }
7463         } else if (tok == '{') {
7464             /* save all registers */
7465             save_regs(0);
7466             /* statement expression : we do not accept break/continue
7467                inside as GCC does */
7468             block(NULL, NULL, NULL, NULL, 0, 1);
7469             skip(')');
7470         } else {
7471             gexpr();
7472             skip(')');
7473         }
7474         break;
7475     case '*':
7476         next();
7477         unary();
7478         indir();
7479         break;
7480     case '&':
7481         next();
7482         unary();
7483         /* functions names must be treated as function pointers,
7484            except for unary '&' and sizeof. Since we consider that
7485            functions are not lvalues, we only have to handle it
7486            there and in function calls. */
7487         /* arrays can also be used although they are not lvalues */
7488         if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7489             !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7490             test_lvalue();
7491         mk_pointer(&vtop->type);
7492         gaddrof();
7493         break;
7494     case '!':
7495         next();
7496         unary();
7497         if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7498             vtop->c.i = !vtop->c.i;
7499         else if ((vtop->r & VT_VALMASK) == VT_CMP)
7500             vtop->c.i = vtop->c.i ^ 1;
7501         else {
7502             save_regs(1);
7503             vseti(VT_JMP, gtst(1, 0));
7504         }
7505         break;
7506     case '~':
7507         next();
7508         unary();
7509         vpushi(-1);
7510         gen_op('^');
7511         break;
7512     case '+':
7513         next();
7514         /* in order to force cast, we add zero */
7515         unary();
7516         if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7517             error("pointer not accepted for unary plus");
7518         vpushi(0);
7519         gen_op('+');
7520         break;
7521     case TOK_SIZEOF:
7522     case TOK_ALIGNOF1:
7523     case TOK_ALIGNOF2:
7524         t = tok;
7525         next();
7526         if (tok == '(') {
7527             parse_expr_type(&type);
7528         } else {
7529             unary_type(&type);
7530         }
7531         size = type_size(&type, &align);
7532         if (t == TOK_SIZEOF) {
7533             if (size < 0)
7534                 error("sizeof applied to an incomplete type");
7535             vpushi(size);
7536         } else {
7537             vpushi(align);
7538         }
7539         vtop->type.t |= VT_UNSIGNED;
7540         break;
7541 
7542     case TOK_builtin_types_compatible_p:
7543         {
7544             CType type1, type2;
7545             next();
7546             skip('(');
7547             parse_type(&type1);
7548             skip(',');
7549             parse_type(&type2);
7550             skip(')');
7551             type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7552             type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7553             vpushi(is_compatible_types(&type1, &type2));
7554         }
7555         break;
7556     case TOK_builtin_constant_p:
7557         {
7558             int saved_nocode_wanted, res;
7559             next();
7560             skip('(');
7561             saved_nocode_wanted = nocode_wanted;
7562             nocode_wanted = 1;
7563             gexpr();
7564             res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7565             vpop();
7566             nocode_wanted = saved_nocode_wanted;
7567             skip(')');
7568             vpushi(res);
7569         }
7570         break;
7571     case TOK_INC:
7572     case TOK_DEC:
7573         t = tok;
7574         next();
7575         unary();
7576         inc(0, t);
7577         break;
7578     case '-':
7579         next();
7580         vpushi(0);
7581         unary();
7582         gen_op('-');
7583         break;
7584     case TOK_LAND:
7585         if (!gnu_ext)
7586             goto tok_identifier;
7587         next();
7588         /* allow to take the address of a label */
7589         if (tok < TOK_UIDENT)
7590             expect("label identifier");
7591         s = label_find(tok);
7592         if (!s) {
7593             s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7594         } else {
7595             if (s->r == LABEL_DECLARED)
7596                 s->r = LABEL_FORWARD;
7597         }
7598         if (!s->type.t) {
7599             s->type.t = VT_VOID;
7600             mk_pointer(&s->type);
7601             s->type.t |= VT_STATIC;
7602         }
7603         vset(&s->type, VT_CONST | VT_SYM, 0);
7604         vtop->sym = s;
7605         next();
7606         break;
7607     default:
7608     tok_identifier:
7609         t = tok;
7610         next();
7611         if (t < TOK_UIDENT)
7612             expect("identifier");
7613         s = sym_find(t);
7614         if (!s) {
7615             if (tok != '(')
7616                 error("'%s' undeclared", get_tok_str(t, NULL));
7617             /* for simple function calls, we tolerate undeclared
7618                external reference to int() function */
7619             if (tcc_state->warn_implicit_function_declaration)
7620                 warning("implicit declaration of function '%s'",
7621                         get_tok_str(t, NULL));
7622             s = external_global_sym(t, &func_old_type, 0);
7623         }
7624         if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7625             (VT_STATIC | VT_INLINE | VT_FUNC)) {
7626             /* if referencing an inline function, then we generate a
7627                symbol to it if not already done. It will have the
7628                effect to generate code for it at the end of the
7629                compilation unit. Inline function as always
7630                generated in the text section. */
7631             if (!s->c)
7632                 put_extern_sym(s, text_section, 0, 0);
7633             r = VT_SYM | VT_CONST;
7634         } else {
7635             r = s->r;
7636         }
7637         vset(&s->type, r, s->c);
7638         /* if forward reference, we must point to s */
7639         if (vtop->r & VT_SYM) {
7640             vtop->sym = s;
7641             vtop->c.ul = 0;
7642         }
7643         break;
7644     }
7645 
7646     /* post operations */
7647     while (1) {
7648         if (tok == TOK_INC || tok == TOK_DEC) {
7649             inc(1, tok);
7650             next();
7651         } else if (tok == '.' || tok == TOK_ARROW) {
7652             /* field */
7653             if (tok == TOK_ARROW)
7654                 indir();
7655             test_lvalue();
7656             gaddrof();
7657             next();
7658             /* expect pointer on structure */
7659             if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7660                 expect("struct or union");
7661             s = vtop->type.ref;
7662             /* find field */
7663             tok |= SYM_FIELD;
7664             while ((s = s->next) != NULL) {
7665                 if (s->v == tok)
7666                     break;
7667             }
7668             if (!s)
7669                 error("field not found: %s",  get_tok_str(tok & ~SYM_FIELD, NULL));
7670             /* add field offset to pointer */
7671             vtop->type = char_pointer_type; /* change type to 'char *' */
7672             vpushi(s->c);
7673             gen_op('+');
7674             /* change type to field type, and set to lvalue */
7675             vtop->type = s->type;
7676             /* an array is never an lvalue */
7677             if (!(vtop->type.t & VT_ARRAY)) {
7678                 vtop->r |= lvalue_type(vtop->type.t);
7679                 /* if bound checking, the referenced pointer must be checked */
7680                 if (do_bounds_check)
7681                     vtop->r |= VT_MUSTBOUND;
7682             }
7683             next();
7684         } else if (tok == '[') {
7685             next();
7686             gexpr();
7687             gen_op('+');
7688             indir();
7689             skip(']');
7690         } else if (tok == '(') {
7691             SValue ret;
7692             Sym *sa;
7693             int nb_args;
7694 
7695             /* function call  */
7696             if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7697                 /* pointer test (no array accepted) */
7698                 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7699                     vtop->type = *pointed_type(&vtop->type);
7700                     if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7701                         goto error_func;
7702                 } else {
7703                 error_func:
7704                     expect("function pointer");
7705                 }
7706             } else {
7707                 vtop->r &= ~VT_LVAL; /* no lvalue */
7708             }
7709             /* get return type */
7710             s = vtop->type.ref;
7711             next();
7712             sa = s->next; /* first parameter */
7713             nb_args = 0;
7714             ret.r2 = VT_CONST;
7715             /* compute first implicit argument if a structure is returned */
7716             if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7717                 /* get some space for the returned structure */
7718                 size = type_size(&s->type, &align);
7719                 loc = (loc - size) & -align;
7720                 ret.type = s->type;
7721                 ret.r = VT_LOCAL | VT_LVAL;
7722                 /* pass it as 'int' to avoid structure arg passing
7723                    problems */
7724                 vseti(VT_LOCAL, loc);
7725                 ret.c = vtop->c;
7726                 nb_args++;
7727             } else {
7728                 ret.type = s->type;
7729                 /* return in register */
7730                 if (is_float(ret.type.t)) {
7731                     ret.r = REG_FRET;
7732                 } else {
7733                     if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7734                         ret.r2 = REG_LRET;
7735                     ret.r = REG_IRET;
7736                 }
7737                 ret.c.i = 0;
7738             }
7739             if (tok != ')') {
7740                 for(;;) {
7741                     expr_eq();
7742                     gfunc_param_typed(s, sa);
7743                     nb_args++;
7744                     if (sa)
7745                         sa = sa->next;
7746                     if (tok == ')')
7747                         break;
7748                     skip(',');
7749                 }
7750             }
7751             if (sa)
7752                 error("too few arguments to function");
7753             skip(')');
7754             if (!nocode_wanted) {
7755                 gfunc_call(nb_args);
7756             } else {
7757                 vtop -= (nb_args + 1);
7758             }
7759             /* return value */
7760             vsetc(&ret.type, ret.r, &ret.c);
7761             vtop->r2 = ret.r2;
7762         } else {
7763             break;
7764         }
7765     }
7766 }
7767 
uneq(void)7768 static void uneq(void)
7769 {
7770     int t;
7771 
7772     unary();
7773     if (tok == '=' ||
7774         (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7775         tok == TOK_A_XOR || tok == TOK_A_OR ||
7776         tok == TOK_A_SHL || tok == TOK_A_SAR) {
7777         test_lvalue();
7778         t = tok;
7779         next();
7780         if (t == '=') {
7781             expr_eq();
7782         } else {
7783             vdup();
7784             expr_eq();
7785             gen_op(t & 0x7f);
7786         }
7787         vstore();
7788     }
7789 }
7790 
expr_prod(void)7791 static void expr_prod(void)
7792 {
7793     int t;
7794 
7795     uneq();
7796     while (tok == '*' || tok == '/' || tok == '%') {
7797         t = tok;
7798         next();
7799         uneq();
7800         gen_op(t);
7801     }
7802 }
7803 
expr_sum(void)7804 static void expr_sum(void)
7805 {
7806     int t;
7807 
7808     expr_prod();
7809     while (tok == '+' || tok == '-') {
7810         t = tok;
7811         next();
7812         expr_prod();
7813         gen_op(t);
7814     }
7815 }
7816 
expr_shift(void)7817 static void expr_shift(void)
7818 {
7819     int t;
7820 
7821     expr_sum();
7822     while (tok == TOK_SHL || tok == TOK_SAR) {
7823         t = tok;
7824         next();
7825         expr_sum();
7826         gen_op(t);
7827     }
7828 }
7829 
expr_cmp(void)7830 static void expr_cmp(void)
7831 {
7832     int t;
7833 
7834     expr_shift();
7835     while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7836            tok == TOK_ULT || tok == TOK_UGE) {
7837         t = tok;
7838         next();
7839         expr_shift();
7840         gen_op(t);
7841     }
7842 }
7843 
expr_cmpeq(void)7844 static void expr_cmpeq(void)
7845 {
7846     int t;
7847 
7848     expr_cmp();
7849     while (tok == TOK_EQ || tok == TOK_NE) {
7850         t = tok;
7851         next();
7852         expr_cmp();
7853         gen_op(t);
7854     }
7855 }
7856 
expr_and(void)7857 static void expr_and(void)
7858 {
7859     expr_cmpeq();
7860     while (tok == '&') {
7861         next();
7862         expr_cmpeq();
7863         gen_op('&');
7864     }
7865 }
7866 
expr_xor(void)7867 static void expr_xor(void)
7868 {
7869     expr_and();
7870     while (tok == '^') {
7871         next();
7872         expr_and();
7873         gen_op('^');
7874     }
7875 }
7876 
expr_or(void)7877 static void expr_or(void)
7878 {
7879     expr_xor();
7880     while (tok == '|') {
7881         next();
7882         expr_xor();
7883         gen_op('|');
7884     }
7885 }
7886 
7887 /* XXX: fix this mess */
expr_land_const(void)7888 static void expr_land_const(void)
7889 {
7890     expr_or();
7891     while (tok == TOK_LAND) {
7892         next();
7893         expr_or();
7894         gen_op(TOK_LAND);
7895     }
7896 }
7897 
7898 /* XXX: fix this mess */
expr_lor_const(void)7899 static void expr_lor_const(void)
7900 {
7901     expr_land_const();
7902     while (tok == TOK_LOR) {
7903         next();
7904         expr_land_const();
7905         gen_op(TOK_LOR);
7906     }
7907 }
7908 
7909 /* only used if non constant */
expr_land(void)7910 static void expr_land(void)
7911 {
7912     int t;
7913 
7914     expr_or();
7915     if (tok == TOK_LAND) {
7916         t = 0;
7917         save_regs(1);
7918         for(;;) {
7919             t = gtst(1, t);
7920             if (tok != TOK_LAND) {
7921                 vseti(VT_JMPI, t);
7922                 break;
7923             }
7924             next();
7925             expr_or();
7926         }
7927     }
7928 }
7929 
expr_lor(void)7930 static void expr_lor(void)
7931 {
7932     int t;
7933 
7934     expr_land();
7935     if (tok == TOK_LOR) {
7936         t = 0;
7937         save_regs(1);
7938         for(;;) {
7939             t = gtst(0, t);
7940             if (tok != TOK_LOR) {
7941                 vseti(VT_JMP, t);
7942                 break;
7943             }
7944             next();
7945             expr_land();
7946         }
7947     }
7948 }
7949 
7950 /* XXX: better constant handling */
expr_eq(void)7951 static void expr_eq(void)
7952 {
7953     int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7954     SValue sv;
7955     CType type, type1, type2;
7956 
7957     if (const_wanted) {
7958         int c1, c;
7959         expr_lor_const();
7960         if (tok == '?') {
7961             c = vtop->c.i;
7962             vpop();
7963             next();
7964             if (tok == ':' && gnu_ext) {
7965                 c1 = c;
7966             } else {
7967                 gexpr();
7968                 c1 = vtop->c.i;
7969                 vpop();
7970             }
7971             skip(':');
7972             expr_eq();
7973             if (c)
7974                 vtop->c.i = c1;
7975         }
7976     } else {
7977         expr_lor();
7978         if (tok == '?') {
7979             next();
7980             if (vtop != vstack) {
7981                 /* needed to avoid having different registers saved in
7982                    each branch */
7983                 if (is_float(vtop->type.t))
7984                     rc = RC_FLOAT;
7985                 else
7986                     rc = RC_INT;
7987                     gv(rc);
7988                     save_regs(1);
7989             }
7990             if (tok == ':' && gnu_ext) {
7991                 gv_dup();
7992                 tt = gtst(1, 0);
7993             } else {
7994                 tt = gtst(1, 0);
7995                 gexpr();
7996             }
7997             type1 = vtop->type;
7998             sv = *vtop; /* save value to handle it later */
7999             vtop--; /* no vpop so that FP stack is not flushed */
8000             skip(':');
8001             u = gjmp(0);
8002             gsym(tt);
8003             expr_eq();
8004             type2 = vtop->type;
8005 
8006             t1 = type1.t;
8007             bt1 = t1 & VT_BTYPE;
8008             t2 = type2.t;
8009             bt2 = t2 & VT_BTYPE;
8010             /* cast operands to correct type according to ISOC rules */
8011             if (is_float(bt1) || is_float(bt2)) {
8012                 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8013                     type.t = VT_LDOUBLE;
8014                 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8015                     type.t = VT_DOUBLE;
8016                 } else {
8017                     type.t = VT_FLOAT;
8018                 }
8019             } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8020                 /* cast to biggest op */
8021                 type.t = VT_LLONG;
8022                 /* convert to unsigned if it does not fit in a long long */
8023                 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8024                     (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8025                     type.t |= VT_UNSIGNED;
8026             } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8027                 /* XXX: test pointer compatibility */
8028                 type = type1;
8029             } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8030                 /* XXX: test function pointer compatibility */
8031                 type = type1;
8032             } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8033                 /* XXX: test structure compatibility */
8034                 type = type1;
8035             } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8036                 /* NOTE: as an extension, we accept void on only one side */
8037                 type.t = VT_VOID;
8038             } else {
8039                 /* integer operations */
8040                 type.t = VT_INT;
8041                 /* convert to unsigned if it does not fit in an integer */
8042                 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8043                     (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8044                     type.t |= VT_UNSIGNED;
8045             }
8046 
8047             /* now we convert second operand */
8048             gen_cast(&type);
8049             if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8050                 gaddrof();
8051             rc = RC_INT;
8052             if (is_float(type.t)) {
8053                 rc = RC_FLOAT;
8054             } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8055                 /* for long longs, we use fixed registers to avoid having
8056                    to handle a complicated move */
8057                 rc = RC_IRET;
8058             }
8059 
8060             r2 = gv(rc);
8061             /* this is horrible, but we must also convert first
8062                operand */
8063             tt = gjmp(0);
8064             gsym(u);
8065             /* put again first value and cast it */
8066             *vtop = sv;
8067             gen_cast(&type);
8068             if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8069                 gaddrof();
8070             r1 = gv(rc);
8071             move_reg(r2, r1);
8072             vtop->r = r2;
8073             gsym(tt);
8074         }
8075     }
8076 }
8077 
gexpr(void)8078 static void gexpr(void)
8079 {
8080     while (1) {
8081         expr_eq();
8082         if (tok != ',')
8083             break;
8084         vpop();
8085         next();
8086     }
8087 }
8088 
8089 /* parse an expression and return its type without any side effect. */
expr_type(CType * type)8090 static void expr_type(CType *type)
8091 {
8092     int saved_nocode_wanted;
8093 
8094     saved_nocode_wanted = nocode_wanted;
8095     nocode_wanted = 1;
8096     gexpr();
8097     *type = vtop->type;
8098     vpop();
8099     nocode_wanted = saved_nocode_wanted;
8100 }
8101 
8102 /* parse a unary expression and return its type without any side
8103    effect. */
unary_type(CType * type)8104 static void unary_type(CType *type)
8105 {
8106     int a;
8107 
8108     a = nocode_wanted;
8109     nocode_wanted = 1;
8110     unary();
8111     *type = vtop->type;
8112     vpop();
8113     nocode_wanted = a;
8114 }
8115 
8116 /* parse a constant expression and return value in vtop.  */
expr_const1(void)8117 static void expr_const1(void)
8118 {
8119     int a;
8120     a = const_wanted;
8121     const_wanted = 1;
8122     expr_eq();
8123     const_wanted = a;
8124 }
8125 
8126 /* parse an integer constant and return its value. */
expr_const(void)8127 static int expr_const(void)
8128 {
8129     int c;
8130     expr_const1();
8131     if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8132         expect("constant expression");
8133     c = vtop->c.i;
8134     vpop();
8135     return c;
8136 }
8137 
8138 /* return the label token if current token is a label, otherwise
8139    return zero */
is_label(void)8140 static int is_label(void)
8141 {
8142     int last_tok;
8143 
8144     /* fast test first */
8145     if (tok < TOK_UIDENT)
8146         return 0;
8147     /* no need to save tokc because tok is an identifier */
8148     last_tok = tok;
8149     next();
8150     if (tok == ':') {
8151         next();
8152         return last_tok;
8153     } else {
8154         unget_tok(last_tok);
8155         return 0;
8156     }
8157 }
8158 
block(int * bsym,int * csym,int * case_sym,int * def_sym,int case_reg,int is_expr)8159 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8160                   int case_reg, int is_expr)
8161 {
8162     int a, b, c, d;
8163     Sym *s;
8164 
8165     /* generate line number info */
8166     if (do_debug &&
8167         (last_line_num != file->line_num || last_ind != ind)) {
8168         put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8169         last_ind = ind;
8170         last_line_num = file->line_num;
8171     }
8172 
8173     if (is_expr) {
8174         /* default return value is (void) */
8175         vpushi(0);
8176         vtop->type.t = VT_VOID;
8177     }
8178 
8179     if (tok == TOK_IF) {
8180         /* if test */
8181         next();
8182         skip('(');
8183         gexpr();
8184         skip(')');
8185         a = gtst(1, 0);
8186         block(bsym, csym, case_sym, def_sym, case_reg, 0);
8187         c = tok;
8188         if (c == TOK_ELSE) {
8189             next();
8190             d = gjmp(0);
8191             gsym(a);
8192             block(bsym, csym, case_sym, def_sym, case_reg, 0);
8193             gsym(d); /* patch else jmp */
8194         } else
8195             gsym(a);
8196     } else if (tok == TOK_WHILE) {
8197         next();
8198         d = ind;
8199         skip('(');
8200         gexpr();
8201         skip(')');
8202         a = gtst(1, 0);
8203         b = 0;
8204         block(&a, &b, case_sym, def_sym, case_reg, 0);
8205         gjmp_addr(d);
8206         gsym(a);
8207         gsym_addr(b, d);
8208     } else if (tok == '{') {
8209         Sym *llabel;
8210 
8211         next();
8212         /* record local declaration stack position */
8213         s = local_stack;
8214         llabel = local_label_stack;
8215         /* handle local labels declarations */
8216         if (tok == TOK_LABEL) {
8217             next();
8218             for(;;) {
8219                 if (tok < TOK_UIDENT)
8220                     expect("label identifier");
8221                 label_push(&local_label_stack, tok, LABEL_DECLARED);
8222                 next();
8223                 if (tok == ',') {
8224                     next();
8225                 } else {
8226                     skip(';');
8227                     break;
8228                 }
8229             }
8230         }
8231         while (tok != '}') {
8232             decl(VT_LOCAL);
8233             if (tok != '}') {
8234                 if (is_expr)
8235                     vpop();
8236                 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8237             }
8238         }
8239         /* pop locally defined labels */
8240         label_pop(&local_label_stack, llabel);
8241         /* pop locally defined symbols */
8242         sym_pop(&local_stack, s);
8243         next();
8244     } else if (tok == TOK_RETURN) {
8245         next();
8246         if (tok != ';') {
8247             gexpr();
8248             gen_assign_cast(&func_vt);
8249             if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8250                 CType type;
8251                 /* if returning structure, must copy it to implicit
8252                    first pointer arg location */
8253 #ifdef TCC_ARM_EABI
8254                 int align, size;
8255                 size = type_size(&func_vt,&align);
8256                 if(size <= 4)
8257                 {
8258                     if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8259                        && (align & 3))
8260                     {
8261                         int addr;
8262                         loc = (loc - size) & -4;
8263                         addr = loc;
8264                         type = func_vt;
8265                         vset(&type, VT_LOCAL | VT_LVAL, addr);
8266                         vswap();
8267                         vstore();
8268                         vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8269                     }
8270                     vtop->type = int_type;
8271                     gv(RC_IRET);
8272                 } else {
8273 #endif
8274                 type = func_vt;
8275                 mk_pointer(&type);
8276                 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8277                 indir();
8278                 vswap();
8279                 /* copy structure value to pointer */
8280                 vstore();
8281 #ifdef TCC_ARM_EABI
8282                 }
8283 #endif
8284             } else if (is_float(func_vt.t)) {
8285                 gv(RC_FRET);
8286             } else {
8287                 gv(RC_IRET);
8288             }
8289             vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8290         }
8291         skip(';');
8292         rsym = gjmp(rsym); /* jmp */
8293     } else if (tok == TOK_BREAK) {
8294         /* compute jump */
8295         if (!bsym)
8296             error("cannot break");
8297         *bsym = gjmp(*bsym);
8298         next();
8299         skip(';');
8300     } else if (tok == TOK_CONTINUE) {
8301         /* compute jump */
8302         if (!csym)
8303             error("cannot continue");
8304         *csym = gjmp(*csym);
8305         next();
8306         skip(';');
8307     } else if (tok == TOK_FOR) {
8308         int e;
8309         next();
8310         skip('(');
8311         if (tok != ';') {
8312             gexpr();
8313             vpop();
8314         }
8315         skip(';');
8316         d = ind;
8317         c = ind;
8318         a = 0;
8319         b = 0;
8320         if (tok != ';') {
8321             gexpr();
8322             a = gtst(1, 0);
8323         }
8324         skip(';');
8325         if (tok != ')') {
8326             e = gjmp(0);
8327             c = ind;
8328             gexpr();
8329             vpop();
8330             gjmp_addr(d);
8331             gsym(e);
8332         }
8333         skip(')');
8334         block(&a, &b, case_sym, def_sym, case_reg, 0);
8335         gjmp_addr(c);
8336         gsym(a);
8337         gsym_addr(b, c);
8338     } else
8339     if (tok == TOK_DO) {
8340         next();
8341         a = 0;
8342         b = 0;
8343         d = ind;
8344         block(&a, &b, case_sym, def_sym, case_reg, 0);
8345         skip(TOK_WHILE);
8346         skip('(');
8347         gsym(b);
8348         gexpr();
8349         c = gtst(0, 0);
8350         gsym_addr(c, d);
8351         skip(')');
8352         gsym(a);
8353         skip(';');
8354     } else
8355     if (tok == TOK_SWITCH) {
8356         next();
8357         skip('(');
8358         gexpr();
8359         /* XXX: other types than integer */
8360         case_reg = gv(RC_INT);
8361         vpop();
8362         skip(')');
8363         a = 0;
8364         b = gjmp(0); /* jump to first case */
8365         c = 0;
8366         block(&a, csym, &b, &c, case_reg, 0);
8367         /* if no default, jmp after switch */
8368         if (c == 0)
8369             c = ind;
8370         /* default label */
8371         gsym_addr(b, c);
8372         /* break label */
8373         gsym(a);
8374     } else
8375     if (tok == TOK_CASE) {
8376         int v1, v2;
8377         if (!case_sym)
8378             expect("switch");
8379         next();
8380         v1 = expr_const();
8381         v2 = v1;
8382         if (gnu_ext && tok == TOK_DOTS) {
8383             next();
8384             v2 = expr_const();
8385             if (v2 < v1)
8386                 warning("empty case range");
8387         }
8388         /* since a case is like a label, we must skip it with a jmp */
8389         b = gjmp(0);
8390         gsym(*case_sym);
8391         vseti(case_reg, 0);
8392         vpushi(v1);
8393         if (v1 == v2) {
8394             gen_op(TOK_EQ);
8395             *case_sym = gtst(1, 0);
8396         } else {
8397             gen_op(TOK_GE);
8398             *case_sym = gtst(1, 0);
8399             vseti(case_reg, 0);
8400             vpushi(v2);
8401             gen_op(TOK_LE);
8402             *case_sym = gtst(1, *case_sym);
8403         }
8404         gsym(b);
8405         skip(':');
8406         is_expr = 0;
8407         goto block_after_label;
8408     } else
8409     if (tok == TOK_DEFAULT) {
8410         next();
8411         skip(':');
8412         if (!def_sym)
8413             expect("switch");
8414         if (*def_sym)
8415             error("too many 'default'");
8416         *def_sym = ind;
8417         is_expr = 0;
8418         goto block_after_label;
8419     } else
8420     if (tok == TOK_GOTO) {
8421         next();
8422         if (tok == '*' && gnu_ext) {
8423             /* computed goto */
8424             next();
8425             gexpr();
8426             if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8427                 expect("pointer");
8428             ggoto();
8429         } else if (tok >= TOK_UIDENT) {
8430             s = label_find(tok);
8431             /* put forward definition if needed */
8432             if (!s) {
8433                 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8434             } else {
8435                 if (s->r == LABEL_DECLARED)
8436                     s->r = LABEL_FORWARD;
8437             }
8438             /* label already defined */
8439             if (s->r & LABEL_FORWARD)
8440                 s->next = (void *)gjmp((long)s->next);
8441             else
8442                 gjmp_addr((long)s->next);
8443             next();
8444         } else {
8445             expect("label identifier");
8446         }
8447         skip(';');
8448     } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8449         asm_instr();
8450     } else {
8451         b = is_label();
8452         if (b) {
8453             /* label case */
8454             s = label_find(b);
8455             if (s) {
8456                 if (s->r == LABEL_DEFINED)
8457                     error("duplicate label '%s'", get_tok_str(s->v, NULL));
8458                 gsym((long)s->next);
8459                 s->r = LABEL_DEFINED;
8460             } else {
8461                 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8462             }
8463             s->next = (void *)ind;
8464             /* we accept this, but it is a mistake */
8465         block_after_label:
8466             if (tok == '}') {
8467                 warning("deprecated use of label at end of compound statement");
8468             } else {
8469                 if (is_expr)
8470                     vpop();
8471                 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8472             }
8473         } else {
8474             /* expression case */
8475             if (tok != ';') {
8476                 if (is_expr) {
8477                     vpop();
8478                     gexpr();
8479                 } else {
8480                     gexpr();
8481                     vpop();
8482                 }
8483             }
8484             skip(';');
8485         }
8486     }
8487 }
8488 
8489 /* t is the array or struct type. c is the array or struct
8490    address. cur_index/cur_field is the pointer to the current
8491    value. 'size_only' is true if only size info is needed (only used
8492    in arrays) */
decl_designator(CType * type,Section * sec,unsigned long c,int * cur_index,Sym ** cur_field,int size_only)8493 static void decl_designator(CType *type, Section *sec, unsigned long c,
8494                             int *cur_index, Sym **cur_field,
8495                             int size_only)
8496 {
8497     Sym *s, *f;
8498     int notfirst, index, index_last, align, l, nb_elems, elem_size;
8499     CType type1;
8500 
8501     notfirst = 0;
8502     elem_size = 0;
8503     nb_elems = 1;
8504     if (gnu_ext && (l = is_label()) != 0)
8505         goto struct_field;
8506     while (tok == '[' || tok == '.') {
8507         if (tok == '[') {
8508             if (!(type->t & VT_ARRAY))
8509                 expect("array type");
8510             s = type->ref;
8511             next();
8512             index = expr_const();
8513             if (index < 0 || (s->c >= 0 && index >= s->c))
8514                 expect("invalid index");
8515             if (tok == TOK_DOTS && gnu_ext) {
8516                 next();
8517                 index_last = expr_const();
8518                 if (index_last < 0 ||
8519                     (s->c >= 0 && index_last >= s->c) ||
8520                     index_last < index)
8521                     expect("invalid index");
8522             } else {
8523                 index_last = index;
8524             }
8525             skip(']');
8526             if (!notfirst)
8527                 *cur_index = index_last;
8528             type = pointed_type(type);
8529             elem_size = type_size(type, &align);
8530             c += index * elem_size;
8531             /* NOTE: we only support ranges for last designator */
8532             nb_elems = index_last - index + 1;
8533             if (nb_elems != 1) {
8534                 notfirst = 1;
8535                 break;
8536             }
8537         } else {
8538             next();
8539             l = tok;
8540             next();
8541         struct_field:
8542             if ((type->t & VT_BTYPE) != VT_STRUCT)
8543                 expect("struct/union type");
8544             s = type->ref;
8545             l |= SYM_FIELD;
8546             f = s->next;
8547             while (f) {
8548                 if (f->v == l)
8549                     break;
8550                 f = f->next;
8551             }
8552             if (!f)
8553                 expect("field");
8554             if (!notfirst)
8555                 *cur_field = f;
8556             /* XXX: fix this mess by using explicit storage field */
8557             type1 = f->type;
8558             type1.t |= (type->t & ~VT_TYPE);
8559             type = &type1;
8560             c += f->c;
8561         }
8562         notfirst = 1;
8563     }
8564     if (notfirst) {
8565         if (tok == '=') {
8566             next();
8567         } else {
8568             if (!gnu_ext)
8569                 expect("=");
8570         }
8571     } else {
8572         if (type->t & VT_ARRAY) {
8573             index = *cur_index;
8574             type = pointed_type(type);
8575             c += index * type_size(type, &align);
8576         } else {
8577             f = *cur_field;
8578             if (!f)
8579                 error("too many field init");
8580             /* XXX: fix this mess by using explicit storage field */
8581             type1 = f->type;
8582             type1.t |= (type->t & ~VT_TYPE);
8583             type = &type1;
8584             c += f->c;
8585         }
8586     }
8587     decl_initializer(type, sec, c, 0, size_only);
8588 
8589     /* XXX: make it more general */
8590     if (!size_only && nb_elems > 1) {
8591         unsigned long c_end;
8592         uint8_t *src, *dst;
8593         int i;
8594 
8595         if (!sec)
8596             error("range init not supported yet for dynamic storage");
8597         c_end = c + nb_elems * elem_size;
8598         if (c_end > sec->data_allocated)
8599             section_realloc(sec, c_end);
8600         src = sec->data + c;
8601         dst = src;
8602         for(i = 1; i < nb_elems; i++) {
8603             dst += elem_size;
8604             memcpy(dst, src, elem_size);
8605         }
8606     }
8607 }
8608 
8609 #define EXPR_VAL   0
8610 #define EXPR_CONST 1
8611 #define EXPR_ANY   2
8612 
8613 /* store a value or an expression directly in global data or in local array */
init_putv(CType * type,Section * sec,unsigned long c,int v,int expr_type)8614 static void init_putv(CType *type, Section *sec, unsigned long c,
8615                       int v, int expr_type)
8616 {
8617     int saved_global_expr, bt, bit_pos, bit_size;
8618     void *ptr;
8619     unsigned long long bit_mask;
8620     CType dtype;
8621 
8622     switch(expr_type) {
8623     case EXPR_VAL:
8624         vpushi(v);
8625         break;
8626     case EXPR_CONST:
8627         /* compound literals must be allocated globally in this case */
8628         saved_global_expr = global_expr;
8629         global_expr = 1;
8630         expr_const1();
8631         global_expr = saved_global_expr;
8632         /* NOTE: symbols are accepted */
8633         if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8634             error("initializer element is not constant");
8635         break;
8636     case EXPR_ANY:
8637         expr_eq();
8638         break;
8639     }
8640 
8641     dtype = *type;
8642     dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8643 
8644     if (sec) {
8645         /* XXX: not portable */
8646         /* XXX: generate error if incorrect relocation */
8647         gen_assign_cast(&dtype);
8648         bt = type->t & VT_BTYPE;
8649         ptr = sec->data + c;
8650         /* XXX: make code faster ? */
8651         if (!(type->t & VT_BITFIELD)) {
8652             bit_pos = 0;
8653             bit_size = 32;
8654             bit_mask = -1LL;
8655         } else {
8656             bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8657             bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8658             bit_mask = (1LL << bit_size) - 1;
8659         }
8660         if ((vtop->r & VT_SYM) &&
8661             (bt == VT_BYTE ||
8662              bt == VT_SHORT ||
8663              bt == VT_DOUBLE ||
8664              bt == VT_LDOUBLE ||
8665              bt == VT_LLONG ||
8666              (bt == VT_INT && bit_size != 32)))
8667             error("initializer element is not computable at load time");
8668         switch(bt) {
8669         case VT_BYTE:
8670             *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8671             break;
8672         case VT_SHORT:
8673             *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8674             break;
8675         case VT_DOUBLE:
8676             *(double *)ptr = vtop->c.d;
8677             break;
8678         case VT_LDOUBLE:
8679             *(long double *)ptr = vtop->c.ld;
8680             break;
8681         case VT_LLONG:
8682             *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8683             break;
8684         default:
8685             if (vtop->r & VT_SYM) {
8686                 greloc(sec, vtop->sym, c, R_DATA_32);
8687             }
8688             *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8689             break;
8690         }
8691         vtop--;
8692     } else {
8693         vset(&dtype, VT_LOCAL|VT_LVAL, c);
8694         vswap();
8695         vstore();
8696         vpop();
8697     }
8698 }
8699 
8700 /* put zeros for variable based init */
init_putz(CType * t,Section * sec,unsigned long c,int size)8701 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8702 {
8703     if (sec) {
8704         /* nothing to do because globals are already set to zero */
8705     } else {
8706         vpush_global_sym(&func_old_type, TOK_memset);
8707         vseti(VT_LOCAL, c);
8708         vpushi(0);
8709         vpushi(size);
8710         gfunc_call(3);
8711     }
8712 }
8713 
8714 /* 't' contains the type and storage info. 'c' is the offset of the
8715    object in section 'sec'. If 'sec' is NULL, it means stack based
8716    allocation. 'first' is true if array '{' must be read (multi
8717    dimension implicit array init handling). 'size_only' is true if
8718    size only evaluation is wanted (only for arrays). */
decl_initializer(CType * type,Section * sec,unsigned long c,int first,int size_only)8719 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8720                              int first, int size_only)
8721 {
8722     int index, array_length, n, no_oblock, nb, parlevel, i;
8723     int size1, align1, expr_type;
8724     Sym *s, *f;
8725     CType *t1;
8726 
8727     if (type->t & VT_ARRAY) {
8728         s = type->ref;
8729         n = s->c;
8730         array_length = 0;
8731         t1 = pointed_type(type);
8732         size1 = type_size(t1, &align1);
8733 
8734         no_oblock = 1;
8735         if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8736             tok == '{') {
8737             skip('{');
8738             no_oblock = 0;
8739         }
8740 
8741         /* only parse strings here if correct type (otherwise: handle
8742            them as ((w)char *) expressions */
8743         if ((tok == TOK_LSTR &&
8744 #ifdef TCC_TARGET_PE
8745              (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8746 #else
8747              (t1->t & VT_BTYPE) == VT_INT
8748 #endif
8749             ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8750             while (tok == TOK_STR || tok == TOK_LSTR) {
8751                 int cstr_len, ch;
8752                 CString *cstr;
8753 
8754                 cstr = tokc.cstr;
8755                 /* compute maximum number of chars wanted */
8756                 if (tok == TOK_STR)
8757                     cstr_len = cstr->size;
8758                 else
8759                     cstr_len = cstr->size / sizeof(nwchar_t);
8760                 cstr_len--;
8761                 nb = cstr_len;
8762                 if (n >= 0 && nb > (n - array_length))
8763                     nb = n - array_length;
8764                 if (!size_only) {
8765                     if (cstr_len > nb)
8766                         warning("initializer-string for array is too long");
8767                     /* in order to go faster for common case (char
8768                        string in global variable, we handle it
8769                        specifically */
8770                     if (sec && tok == TOK_STR && size1 == 1) {
8771                         memcpy(sec->data + c + array_length, cstr->data, nb);
8772                     } else {
8773                         for(i=0;i<nb;i++) {
8774                             if (tok == TOK_STR)
8775                                 ch = ((unsigned char *)cstr->data)[i];
8776                             else
8777                                 ch = ((nwchar_t *)cstr->data)[i];
8778                             init_putv(t1, sec, c + (array_length + i) * size1,
8779                                       ch, EXPR_VAL);
8780                         }
8781                     }
8782                 }
8783                 array_length += nb;
8784                 next();
8785             }
8786             /* only add trailing zero if enough storage (no
8787                warning in this case since it is standard) */
8788             if (n < 0 || array_length < n) {
8789                 if (!size_only) {
8790                     init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8791                 }
8792                 array_length++;
8793             }
8794         } else {
8795             index = 0;
8796             while (tok != '}') {
8797                 decl_designator(type, sec, c, &index, NULL, size_only);
8798                 if (n >= 0 && index >= n)
8799                     error("index too large");
8800                 /* must put zero in holes (note that doing it that way
8801                    ensures that it even works with designators) */
8802                 if (!size_only && array_length < index) {
8803                     init_putz(t1, sec, c + array_length * size1,
8804                               (index - array_length) * size1);
8805                 }
8806                 index++;
8807                 if (index > array_length)
8808                     array_length = index;
8809                 /* special test for multi dimensional arrays (may not
8810                    be strictly correct if designators are used at the
8811                    same time) */
8812                 if (index >= n && no_oblock)
8813                     break;
8814                 if (tok == '}')
8815                     break;
8816                 skip(',');
8817             }
8818         }
8819         if (!no_oblock)
8820             skip('}');
8821         /* put zeros at the end */
8822         if (!size_only && n >= 0 && array_length < n) {
8823             init_putz(t1, sec, c + array_length * size1,
8824                       (n - array_length) * size1);
8825         }
8826         /* patch type size if needed */
8827         if (n < 0)
8828             s->c = array_length;
8829     } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8830                (sec || !first || tok == '{')) {
8831         int par_count;
8832 
8833         /* NOTE: the previous test is a specific case for automatic
8834            struct/union init */
8835         /* XXX: union needs only one init */
8836 
8837         /* XXX: this test is incorrect for local initializers
8838            beginning with ( without {. It would be much more difficult
8839            to do it correctly (ideally, the expression parser should
8840            be used in all cases) */
8841         par_count = 0;
8842         if (tok == '(') {
8843             AttributeDef ad1;
8844             CType type1;
8845             next();
8846             while (tok == '(') {
8847                 par_count++;
8848                 next();
8849             }
8850             if (!parse_btype(&type1, &ad1))
8851                 expect("cast");
8852             type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8853 #if 0
8854             if (!is_assignable_types(type, &type1))
8855                 error("invalid type for cast");
8856 #endif
8857             skip(')');
8858         }
8859         no_oblock = 1;
8860         if (first || tok == '{') {
8861             skip('{');
8862             no_oblock = 0;
8863         }
8864         s = type->ref;
8865         f = s->next;
8866         array_length = 0;
8867         index = 0;
8868         n = s->c;
8869         while (tok != '}') {
8870             decl_designator(type, sec, c, NULL, &f, size_only);
8871             index = f->c;
8872             if (!size_only && array_length < index) {
8873                 init_putz(type, sec, c + array_length,
8874                           index - array_length);
8875             }
8876             index = index + type_size(&f->type, &align1);
8877             if (index > array_length)
8878                 array_length = index;
8879             f = f->next;
8880             if (no_oblock && f == NULL)
8881                 break;
8882             if (tok == '}')
8883                 break;
8884             skip(',');
8885         }
8886         /* put zeros at the end */
8887         if (!size_only && array_length < n) {
8888             init_putz(type, sec, c + array_length,
8889                       n - array_length);
8890         }
8891         if (!no_oblock)
8892             skip('}');
8893         while (par_count) {
8894             skip(')');
8895             par_count--;
8896         }
8897     } else if (tok == '{') {
8898         next();
8899         decl_initializer(type, sec, c, first, size_only);
8900         skip('}');
8901     } else if (size_only) {
8902         /* just skip expression */
8903         parlevel = 0;
8904         while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8905                tok != -1) {
8906             if (tok == '(')
8907                 parlevel++;
8908             else if (tok == ')')
8909                 parlevel--;
8910             next();
8911         }
8912     } else {
8913         /* currently, we always use constant expression for globals
8914            (may change for scripting case) */
8915         expr_type = EXPR_CONST;
8916         if (!sec)
8917             expr_type = EXPR_ANY;
8918         init_putv(type, sec, c, 0, expr_type);
8919     }
8920 }
8921 
8922 /* parse an initializer for type 't' if 'has_init' is non zero, and
8923    allocate space in local or global data space ('r' is either
8924    VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8925    variable 'v' of scope 'scope' is declared before initializers are
8926    parsed. If 'v' is zero, then a reference to the new object is put
8927    in the value stack. If 'has_init' is 2, a special parsing is done
8928    to handle string constants. */
decl_initializer_alloc(CType * type,AttributeDef * ad,int r,int has_init,int v,int scope)8929 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8930                                    int has_init, int v, int scope)
8931 {
8932     int size, align, addr, data_offset;
8933     int level;
8934     ParseState saved_parse_state;
8935     TokenString init_str;
8936     Section *sec;
8937 
8938     size = type_size(type, &align);
8939     /* If unknown size, we must evaluate it before
8940        evaluating initializers because
8941        initializers can generate global data too
8942        (e.g. string pointers or ISOC99 compound
8943        literals). It also simplifies local
8944        initializers handling */
8945     tok_str_new(&init_str);
8946     if (size < 0) {
8947         if (!has_init)
8948             error("unknown type size");
8949         /* get all init string */
8950         if (has_init == 2) {
8951             /* only get strings */
8952             while (tok == TOK_STR || tok == TOK_LSTR) {
8953                 tok_str_add_tok(&init_str);
8954                 next();
8955             }
8956         } else {
8957             level = 0;
8958             while (level > 0 || (tok != ',' && tok != ';')) {
8959                 if (tok < 0)
8960                     error("unexpected end of file in initializer");
8961                 tok_str_add_tok(&init_str);
8962                 if (tok == '{')
8963                     level++;
8964                 else if (tok == '}') {
8965                     if (level == 0)
8966                         break;
8967                     level--;
8968                 }
8969                 next();
8970             }
8971         }
8972         tok_str_add(&init_str, -1);
8973         tok_str_add(&init_str, 0);
8974 
8975         /* compute size */
8976         save_parse_state(&saved_parse_state);
8977 
8978         macro_ptr = init_str.str;
8979         next();
8980         decl_initializer(type, NULL, 0, 1, 1);
8981         /* prepare second initializer parsing */
8982         macro_ptr = init_str.str;
8983         next();
8984 
8985         /* if still unknown size, error */
8986         size = type_size(type, &align);
8987         if (size < 0)
8988             error("unknown type size");
8989     }
8990     /* take into account specified alignment if bigger */
8991     if (ad->aligned) {
8992         if (ad->aligned > align)
8993             align = ad->aligned;
8994     } else if (ad->packed) {
8995         align = 1;
8996     }
8997     if ((r & VT_VALMASK) == VT_LOCAL) {
8998         sec = NULL;
8999         if (do_bounds_check && (type->t & VT_ARRAY))
9000             loc--;
9001         loc = (loc - size) & -align;
9002         addr = loc;
9003         /* handles bounds */
9004         /* XXX: currently, since we do only one pass, we cannot track
9005            '&' operators, so we add only arrays */
9006         if (do_bounds_check && (type->t & VT_ARRAY)) {
9007             unsigned long *bounds_ptr;
9008             /* add padding between regions */
9009             loc--;
9010             /* then add local bound info */
9011             bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9012             bounds_ptr[0] = addr;
9013             bounds_ptr[1] = size;
9014         }
9015         if (v) {
9016             /* local variable */
9017             sym_push(v, type, r, addr);
9018         } else {
9019             /* push local reference */
9020             vset(type, r, addr);
9021         }
9022     } else {
9023         Sym *sym;
9024 
9025         sym = NULL;
9026         if (v && scope == VT_CONST) {
9027             /* see if the symbol was already defined */
9028             sym = sym_find(v);
9029             if (sym) {
9030                 if (!is_compatible_types(&sym->type, type))
9031                     error("incompatible types for redefinition of '%s'",
9032                           get_tok_str(v, NULL));
9033                 if (sym->type.t & VT_EXTERN) {
9034                     /* if the variable is extern, it was not allocated */
9035                     sym->type.t &= ~VT_EXTERN;
9036                     /* set array size if it was ommited in extern
9037                        declaration */
9038                     if ((sym->type.t & VT_ARRAY) &&
9039                         sym->type.ref->c < 0 &&
9040                         type->ref->c >= 0)
9041                         sym->type.ref->c = type->ref->c;
9042                 } else {
9043                     /* we accept several definitions of the same
9044                        global variable. this is tricky, because we
9045                        must play with the SHN_COMMON type of the symbol */
9046                     /* XXX: should check if the variable was already
9047                        initialized. It is incorrect to initialized it
9048                        twice */
9049                     /* no init data, we won't add more to the symbol */
9050                     if (!has_init)
9051                         goto no_alloc;
9052                 }
9053             }
9054         }
9055 
9056         /* allocate symbol in corresponding section */
9057         sec = ad->section;
9058         if (!sec) {
9059             if (has_init)
9060                 sec = data_section;
9061             else if (tcc_state->nocommon)
9062                 sec = bss_section;
9063         }
9064         if (sec) {
9065             data_offset = sec->data_offset;
9066             data_offset = (data_offset + align - 1) & -align;
9067             addr = data_offset;
9068             /* very important to increment global pointer at this time
9069                because initializers themselves can create new initializers */
9070             data_offset += size;
9071             /* add padding if bound check */
9072             if (do_bounds_check)
9073                 data_offset++;
9074             sec->data_offset = data_offset;
9075             /* allocate section space to put the data */
9076             if (sec->sh_type != SHT_NOBITS &&
9077                 data_offset > sec->data_allocated)
9078                 section_realloc(sec, data_offset);
9079             /* align section if needed */
9080             if (align > sec->sh_addralign)
9081                 sec->sh_addralign = align;
9082         } else {
9083             addr = 0; /* avoid warning */
9084         }
9085 
9086         if (v) {
9087             if (scope != VT_CONST || !sym) {
9088                 sym = sym_push(v, type, r | VT_SYM, 0);
9089             }
9090             /* update symbol definition */
9091             if (sec) {
9092                 put_extern_sym(sym, sec, addr, size);
9093             } else {
9094                 Elf32_Sym *esym;
9095                 /* put a common area */
9096                 put_extern_sym(sym, NULL, align, size);
9097                 /* XXX: find a nicer way */
9098                 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9099                 esym->st_shndx = SHN_COMMON;
9100             }
9101         } else {
9102             CValue cval;
9103 
9104             /* push global reference */
9105             sym = get_sym_ref(type, sec, addr, size);
9106             cval.ul = 0;
9107             vsetc(type, VT_CONST | VT_SYM, &cval);
9108             vtop->sym = sym;
9109         }
9110 
9111         /* handles bounds now because the symbol must be defined
9112            before for the relocation */
9113         if (do_bounds_check) {
9114             unsigned long *bounds_ptr;
9115 
9116             greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9117             /* then add global bound info */
9118             bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9119             bounds_ptr[0] = 0; /* relocated */
9120             bounds_ptr[1] = size;
9121         }
9122     }
9123     if (has_init) {
9124         decl_initializer(type, sec, addr, 1, 0);
9125         /* restore parse state if needed */
9126         if (init_str.str) {
9127             tok_str_free(init_str.str);
9128             restore_parse_state(&saved_parse_state);
9129         }
9130     }
9131  no_alloc: ;
9132 }
9133 
put_func_debug(Sym * sym)9134 void put_func_debug(Sym *sym)
9135 {
9136     char buf[512];
9137 
9138     /* stabs info */
9139     /* XXX: we put here a dummy type */
9140     snprintf(buf, sizeof(buf), "%s:%c1",
9141              funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9142     put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9143                 cur_text_section, sym->c);
9144     last_ind = 0;
9145     last_line_num = 0;
9146 }
9147 
9148 /* parse an old style function declaration list */
9149 /* XXX: check multiple parameter */
func_decl_list(Sym * func_sym)9150 static void func_decl_list(Sym *func_sym)
9151 {
9152     AttributeDef ad;
9153     int v;
9154     Sym *s;
9155     CType btype, type;
9156 
9157     /* parse each declaration */
9158     while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9159         if (!parse_btype(&btype, &ad))
9160             expect("declaration list");
9161         if (((btype.t & VT_BTYPE) == VT_ENUM ||
9162              (btype.t & VT_BTYPE) == VT_STRUCT) &&
9163             tok == ';') {
9164             /* we accept no variable after */
9165         } else {
9166             for(;;) {
9167                 type = btype;
9168                 type_decl(&type, &ad, &v, TYPE_DIRECT);
9169                 /* find parameter in function parameter list */
9170                 s = func_sym->next;
9171                 while (s != NULL) {
9172                     if ((s->v & ~SYM_FIELD) == v)
9173                         goto found;
9174                     s = s->next;
9175                 }
9176                 error("declaration for parameter '%s' but no such parameter",
9177                       get_tok_str(v, NULL));
9178             found:
9179                 /* check that no storage specifier except 'register' was given */
9180                 if (type.t & VT_STORAGE)
9181                     error("storage class specified for '%s'", get_tok_str(v, NULL));
9182                 convert_parameter_type(&type);
9183                 /* we can add the type (NOTE: it could be local to the function) */
9184                 s->type = type;
9185                 /* accept other parameters */
9186                 if (tok == ',')
9187                     next();
9188                 else
9189                     break;
9190             }
9191         }
9192         skip(';');
9193     }
9194 }
9195 
9196 /* parse a function defined by symbol 'sym' and generate its code in
9197    'cur_text_section' */
gen_function(Sym * sym)9198 static void gen_function(Sym *sym)
9199 {
9200     int saved_nocode_wanted = nocode_wanted;
9201     nocode_wanted = 0;
9202     ind = cur_text_section->data_offset;
9203     /* NOTE: we patch the symbol size later */
9204     put_extern_sym(sym, cur_text_section, ind, 0);
9205     funcname = get_tok_str(sym->v, NULL);
9206     func_ind = ind;
9207     /* put debug symbol */
9208     if (do_debug)
9209         put_func_debug(sym);
9210     /* push a dummy symbol to enable local sym storage */
9211     sym_push2(&local_stack, SYM_FIELD, 0, 0);
9212     gfunc_prolog(&sym->type);
9213     rsym = 0;
9214     block(NULL, NULL, NULL, NULL, 0, 0);
9215     gsym(rsym);
9216     gfunc_epilog();
9217     cur_text_section->data_offset = ind;
9218     label_pop(&global_label_stack, NULL);
9219     sym_pop(&local_stack, NULL); /* reset local stack */
9220     /* end of function */
9221     /* patch symbol size */
9222     ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9223         ind - func_ind;
9224     if (do_debug) {
9225         put_stabn(N_FUN, 0, 0, ind - func_ind);
9226     }
9227     funcname = ""; /* for safety */
9228     func_vt.t = VT_VOID; /* for safety */
9229     ind = 0; /* for safety */
9230     nocode_wanted = saved_nocode_wanted;
9231 }
9232 
gen_inline_functions(void)9233 static void gen_inline_functions(void)
9234 {
9235     Sym *sym;
9236     CType *type;
9237     int *str, inline_generated;
9238 
9239     /* iterate while inline function are referenced */
9240     for(;;) {
9241         inline_generated = 0;
9242         for(sym = global_stack; sym != NULL; sym = sym->prev) {
9243             type = &sym->type;
9244             if (((type->t & VT_BTYPE) == VT_FUNC) &&
9245                 (type->t & (VT_STATIC | VT_INLINE)) ==
9246                 (VT_STATIC | VT_INLINE) &&
9247                 sym->c != 0) {
9248                 /* the function was used: generate its code and
9249                    convert it to a normal function */
9250                 str = INLINE_DEF(sym->r);
9251                 sym->r = VT_SYM | VT_CONST;
9252                 sym->type.t &= ~VT_INLINE;
9253 
9254                 macro_ptr = str;
9255                 next();
9256                 cur_text_section = text_section;
9257                 gen_function(sym);
9258                 macro_ptr = NULL; /* fail safe */
9259 
9260                 tok_str_free(str);
9261                 inline_generated = 1;
9262             }
9263         }
9264         if (!inline_generated)
9265             break;
9266     }
9267 
9268     /* free all remaining inline function tokens */
9269     for(sym = global_stack; sym != NULL; sym = sym->prev) {
9270         type = &sym->type;
9271         if (((type->t & VT_BTYPE) == VT_FUNC) &&
9272             (type->t & (VT_STATIC | VT_INLINE)) ==
9273             (VT_STATIC | VT_INLINE)) {
9274             //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9275             if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9276                 continue;
9277             str = INLINE_DEF(sym->r);
9278             tok_str_free(str);
9279             sym->r = 0; /* fail safe */
9280         }
9281     }
9282 }
9283 
9284 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
decl(int l)9285 static void decl(int l)
9286 {
9287     int v, has_init, r;
9288     CType type, btype;
9289     Sym *sym;
9290     AttributeDef ad;
9291 
9292     while (1) {
9293         if (!parse_btype(&btype, &ad)) {
9294             /* skip redundant ';' */
9295             /* XXX: find more elegant solution */
9296             if (tok == ';') {
9297                 next();
9298                 continue;
9299             }
9300             if (l == VT_CONST &&
9301                 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9302                 /* global asm block */
9303                 asm_global_instr();
9304                 continue;
9305             }
9306             /* special test for old K&R protos without explicit int
9307                type. Only accepted when defining global data */
9308             if (l == VT_LOCAL || tok < TOK_DEFINE)
9309                 break;
9310             btype.t = VT_INT;
9311         }
9312         if (((btype.t & VT_BTYPE) == VT_ENUM ||
9313              (btype.t & VT_BTYPE) == VT_STRUCT) &&
9314             tok == ';') {
9315             /* we accept no variable after */
9316             next();
9317             continue;
9318         }
9319         while (1) { /* iterate thru each declaration */
9320             type = btype;
9321             type_decl(&type, &ad, &v, TYPE_DIRECT);
9322 #if 0
9323             {
9324                 char buf[500];
9325                 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9326                 printf("type = '%s'\n", buf);
9327             }
9328 #endif
9329             if ((type.t & VT_BTYPE) == VT_FUNC) {
9330                 /* if old style function prototype, we accept a
9331                    declaration list */
9332                 sym = type.ref;
9333                 if (sym->c == FUNC_OLD)
9334                     func_decl_list(sym);
9335             }
9336 
9337             if (tok == '{') {
9338                 if (l == VT_LOCAL)
9339                     error("cannot use local functions");
9340                 if ((type.t & VT_BTYPE) != VT_FUNC)
9341                     expect("function definition");
9342 
9343                 /* reject abstract declarators in function definition */
9344                 sym = type.ref;
9345                 while ((sym = sym->next) != NULL)
9346                     if (!(sym->v & ~SYM_FIELD))
9347                        expect("identifier");
9348 
9349                 /* XXX: cannot do better now: convert extern line to static inline */
9350                 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9351                     type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9352 
9353                 sym = sym_find(v);
9354                 if (sym) {
9355                     if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9356                         goto func_error1;
9357                     /* specific case: if not func_call defined, we put
9358                        the one of the prototype */
9359                     /* XXX: should have default value */
9360                     r = sym->type.ref->r;
9361                     if (FUNC_CALL(r) != FUNC_CDECL
9362                      && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9363                         FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9364                     if (FUNC_EXPORT(r))
9365                         FUNC_EXPORT(type.ref->r) = 1;
9366 
9367                     if (!is_compatible_types(&sym->type, &type)) {
9368                     func_error1:
9369                         error("incompatible types for redefinition of '%s'",
9370                               get_tok_str(v, NULL));
9371                     }
9372                     /* if symbol is already defined, then put complete type */
9373                     sym->type = type;
9374                 } else {
9375                     /* put function symbol */
9376                     sym = global_identifier_push(v, type.t, 0);
9377                     sym->type.ref = type.ref;
9378                 }
9379 
9380                 /* static inline functions are just recorded as a kind
9381                    of macro. Their code will be emitted at the end of
9382                    the compilation unit only if they are used */
9383                 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9384                     (VT_INLINE | VT_STATIC)) {
9385                     TokenString func_str;
9386                     int block_level;
9387 
9388                     tok_str_new(&func_str);
9389 
9390                     block_level = 0;
9391                     for(;;) {
9392                         int t;
9393                         if (tok == TOK_EOF)
9394                             error("unexpected end of file");
9395                         tok_str_add_tok(&func_str);
9396                         t = tok;
9397                         next();
9398                         if (t == '{') {
9399                             block_level++;
9400                         } else if (t == '}') {
9401                             block_level--;
9402                             if (block_level == 0)
9403                                 break;
9404                         }
9405                     }
9406                     tok_str_add(&func_str, -1);
9407                     tok_str_add(&func_str, 0);
9408                     INLINE_DEF(sym->r) = func_str.str;
9409                 } else {
9410                     /* compute text section */
9411                     cur_text_section = ad.section;
9412                     if (!cur_text_section)
9413                         cur_text_section = text_section;
9414                     sym->r = VT_SYM | VT_CONST;
9415                     gen_function(sym);
9416                 }
9417                 break;
9418             } else {
9419                 if (btype.t & VT_TYPEDEF) {
9420                     /* save typedefed type  */
9421                     /* XXX: test storage specifiers ? */
9422                     sym = sym_push(v, &type, 0, 0);
9423                     sym->type.t |= VT_TYPEDEF;
9424                 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9425                     /* external function definition */
9426                     /* specific case for func_call attribute */
9427                     if (ad.func_attr)
9428                         type.ref->r = ad.func_attr;
9429                     external_sym(v, &type, 0);
9430                 } else {
9431                     /* not lvalue if array */
9432                     r = 0;
9433                     if (!(type.t & VT_ARRAY))
9434                         r |= lvalue_type(type.t);
9435                     has_init = (tok == '=');
9436                     if ((btype.t & VT_EXTERN) ||
9437                         ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9438                          !has_init && l == VT_CONST && type.ref->c < 0)) {
9439                         /* external variable */
9440                         /* NOTE: as GCC, uninitialized global static
9441                            arrays of null size are considered as
9442                            extern */
9443                         external_sym(v, &type, r);
9444                     } else {
9445                         type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9446                         if (type.t & VT_STATIC)
9447                             r |= VT_CONST;
9448                         else
9449                             r |= l;
9450                         if (has_init)
9451                             next();
9452                         decl_initializer_alloc(&type, &ad, r,
9453                                                has_init, v, l);
9454                     }
9455                 }
9456                 if (tok != ',') {
9457                     skip(';');
9458                     break;
9459                 }
9460                 next();
9461             }
9462         }
9463     }
9464 }
9465 
9466 /* better than nothing, but needs extension to handle '-E' option
9467    correctly too */
preprocess_init(TCCState * s1)9468 static void preprocess_init(TCCState *s1)
9469 {
9470     s1->include_stack_ptr = s1->include_stack;
9471     /* XXX: move that before to avoid having to initialize
9472        file->ifdef_stack_ptr ? */
9473     s1->ifdef_stack_ptr = s1->ifdef_stack;
9474     file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9475 
9476     /* XXX: not ANSI compliant: bound checking says error */
9477     vtop = vstack - 1;
9478     s1->pack_stack[0] = 0;
9479     s1->pack_stack_ptr = s1->pack_stack;
9480 }
9481 
9482 /* compile the C file opened in 'file'. Return non zero if errors. */
tcc_compile(TCCState * s1)9483 static int tcc_compile(TCCState *s1)
9484 {
9485     Sym *define_start;
9486     char buf[512];
9487     volatile int section_sym;
9488 
9489 #ifdef INC_DEBUG
9490     printf("%s: **** new file\n", file->filename);
9491 #endif
9492     preprocess_init(s1);
9493 
9494     funcname = "";
9495     anon_sym = SYM_FIRST_ANOM;
9496 
9497     /* file info: full path + filename */
9498     section_sym = 0; /* avoid warning */
9499     if (do_debug) {
9500         section_sym = put_elf_sym(symtab_section, 0, 0,
9501                                   ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9502                                   text_section->sh_num, NULL);
9503         getcwd(buf, sizeof(buf));
9504 #ifdef _WIN32
9505         normalize_slashes(buf);
9506 #endif
9507         pstrcat(buf, sizeof(buf), "/");
9508         put_stabs_r(buf, N_SO, 0, 0,
9509                     text_section->data_offset, text_section, section_sym);
9510         put_stabs_r(file->filename, N_SO, 0, 0,
9511                     text_section->data_offset, text_section, section_sym);
9512     }
9513     /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9514        symbols can be safely used */
9515     put_elf_sym(symtab_section, 0, 0,
9516                 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9517                 SHN_ABS, file->filename);
9518 
9519     /* define some often used types */
9520     int_type.t = VT_INT;
9521 
9522     char_pointer_type.t = VT_BYTE;
9523     mk_pointer(&char_pointer_type);
9524 
9525     func_old_type.t = VT_FUNC;
9526     func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9527 
9528 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9529     float_type.t = VT_FLOAT;
9530     double_type.t = VT_DOUBLE;
9531 
9532     func_float_type.t = VT_FUNC;
9533     func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9534     func_double_type.t = VT_FUNC;
9535     func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9536 #endif
9537 
9538 #if 0
9539     /* define 'void *alloca(unsigned int)' builtin function */
9540     {
9541         Sym *s1;
9542 
9543         p = anon_sym++;
9544         sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9545         s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9546         s1->next = NULL;
9547         sym->next = s1;
9548         sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9549     }
9550 #endif
9551 
9552     define_start = define_stack;
9553     nocode_wanted = 1;
9554 
9555     if (setjmp(s1->error_jmp_buf) == 0) {
9556         s1->nb_errors = 0;
9557         s1->error_set_jmp_enabled = 1;
9558 
9559         ch = file->buf_ptr[0];
9560         tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9561         parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9562         next();
9563         decl(VT_CONST);
9564         if (tok != TOK_EOF)
9565             expect("declaration");
9566 
9567         /* end of translation unit info */
9568         if (do_debug) {
9569             put_stabs_r(NULL, N_SO, 0, 0,
9570                         text_section->data_offset, text_section, section_sym);
9571         }
9572     }
9573     s1->error_set_jmp_enabled = 0;
9574 
9575     /* reset define stack, but leave -Dsymbols (may be incorrect if
9576        they are undefined) */
9577     free_defines(define_start);
9578 
9579     gen_inline_functions();
9580 
9581     sym_pop(&global_stack, NULL);
9582 
9583     return s1->nb_errors != 0 ? -1 : 0;
9584 }
9585 
9586 /* Preprocess the current file */
9587 /* XXX: add line and file infos, add options to preserve spaces */
tcc_preprocess(TCCState * s1)9588 static int tcc_preprocess(TCCState *s1)
9589 {
9590     Sym *define_start;
9591     int last_is_space;
9592 
9593     preprocess_init(s1);
9594 
9595     define_start = define_stack;
9596 
9597     ch = file->buf_ptr[0];
9598     tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9599     parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9600         PARSE_FLAG_LINEFEED;
9601     last_is_space = 1;
9602     next();
9603     for(;;) {
9604         if (tok == TOK_EOF) {
9605             break;
9606         } else if (tok == TOK_LINEFEED) {
9607             last_is_space = 1;
9608         } else {
9609             if (!last_is_space)
9610                 fputc(' ', s1->outfile);
9611             last_is_space = 0;
9612         }
9613         fputs(get_tok_str(tok, &tokc), s1->outfile);
9614         next();
9615     }
9616     free_defines(define_start);
9617     return 0;
9618 }
9619 
9620 #ifdef LIBTCC
tcc_compile_string(TCCState * s,const char * str)9621 int tcc_compile_string(TCCState *s, const char *str)
9622 {
9623     BufferedFile bf1, *bf = &bf1;
9624     int ret, len;
9625     char *buf;
9626 
9627     /* init file structure */
9628     bf->fd = -1;
9629     /* XXX: avoid copying */
9630     len = strlen(str);
9631     buf = tcc_malloc(len + 1);
9632     if (!buf)
9633         return -1;
9634     memcpy(buf, str, len);
9635     buf[len] = CH_EOB;
9636     bf->buf_ptr = buf;
9637     bf->buf_end = buf + len;
9638     pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9639     bf->line_num = 1;
9640     file = bf;
9641 
9642     ret = tcc_compile(s);
9643 
9644     tcc_free(buf);
9645 
9646     /* currently, no need to close */
9647     return ret;
9648 }
9649 #endif
9650 
9651 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
tcc_define_symbol(TCCState * s1,const char * sym,const char * value)9652 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9653 {
9654     BufferedFile bf1, *bf = &bf1;
9655 
9656     pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9657     pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9658     /* default value */
9659     if (!value)
9660         value = "1";
9661     pstrcat(bf->buffer, IO_BUF_SIZE, value);
9662 
9663     /* init file structure */
9664     bf->fd = -1;
9665     bf->buf_ptr = bf->buffer;
9666     bf->buf_end = bf->buffer + strlen(bf->buffer);
9667     *bf->buf_end = CH_EOB;
9668     bf->filename[0] = '\0';
9669     bf->line_num = 1;
9670     file = bf;
9671 
9672     s1->include_stack_ptr = s1->include_stack;
9673 
9674     /* parse with define parser */
9675     ch = file->buf_ptr[0];
9676     next_nomacro();
9677     parse_define();
9678     file = NULL;
9679 }
9680 
9681 /* undefine a preprocessor symbol */
tcc_undefine_symbol(TCCState * s1,const char * sym)9682 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9683 {
9684     TokenSym *ts;
9685     Sym *s;
9686     ts = tok_alloc(sym, strlen(sym));
9687     s = define_find(ts->tok);
9688     /* undefine symbol by putting an invalid name */
9689     if (s)
9690         define_undef(s);
9691 }
9692 
9693 #ifdef CONFIG_TCC_ASM
9694 
9695 #ifdef TCC_TARGET_I386
9696 #include "i386-asm.c"
9697 #endif
9698 #include "tccasm.c"
9699 
9700 #else
asm_instr(void)9701 static void asm_instr(void)
9702 {
9703     error("inline asm() not supported");
9704 }
asm_global_instr(void)9705 static void asm_global_instr(void)
9706 {
9707     error("inline asm() not supported");
9708 }
9709 #endif
9710 
9711 #include "tccelf.c"
9712 
9713 #ifdef TCC_TARGET_COFF
9714 #include "tcccoff.c"
9715 #endif
9716 
9717 #ifdef TCC_TARGET_PE
9718 #include "tccpe.c"
9719 #endif
9720 
9721 /* print the position in the source file of PC value 'pc' by reading
9722    the stabs debug information */
rt_printline(unsigned long wanted_pc)9723 static void rt_printline(unsigned long wanted_pc)
9724 {
9725     Stab_Sym *sym, *sym_end;
9726     char func_name[128], last_func_name[128];
9727     unsigned long func_addr, last_pc, pc;
9728     const char *incl_files[INCLUDE_STACK_SIZE];
9729     int incl_index, len, last_line_num, i;
9730     const char *str, *p;
9731 
9732     fprintf(stderr, "0x%08lx:", wanted_pc);
9733 
9734     func_name[0] = '\0';
9735     func_addr = 0;
9736     incl_index = 0;
9737     last_func_name[0] = '\0';
9738     last_pc = 0xffffffff;
9739     last_line_num = 1;
9740     sym = (Stab_Sym *)stab_section->data + 1;
9741     sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9742     while (sym < sym_end) {
9743         switch(sym->n_type) {
9744             /* function start or end */
9745         case N_FUN:
9746             if (sym->n_strx == 0) {
9747                 /* we test if between last line and end of function */
9748                 pc = sym->n_value + func_addr;
9749                 if (wanted_pc >= last_pc && wanted_pc < pc)
9750                     goto found;
9751                 func_name[0] = '\0';
9752                 func_addr = 0;
9753             } else {
9754                 str = stabstr_section->data + sym->n_strx;
9755                 p = strchr(str, ':');
9756                 if (!p) {
9757                     pstrcpy(func_name, sizeof(func_name), str);
9758                 } else {
9759                     len = p - str;
9760                     if (len > sizeof(func_name) - 1)
9761                         len = sizeof(func_name) - 1;
9762                     memcpy(func_name, str, len);
9763                     func_name[len] = '\0';
9764                 }
9765                 func_addr = sym->n_value;
9766             }
9767             break;
9768             /* line number info */
9769         case N_SLINE:
9770             pc = sym->n_value + func_addr;
9771             if (wanted_pc >= last_pc && wanted_pc < pc)
9772                 goto found;
9773             last_pc = pc;
9774             last_line_num = sym->n_desc;
9775             /* XXX: slow! */
9776             strcpy(last_func_name, func_name);
9777             break;
9778             /* include files */
9779         case N_BINCL:
9780             str = stabstr_section->data + sym->n_strx;
9781         add_incl:
9782             if (incl_index < INCLUDE_STACK_SIZE) {
9783                 incl_files[incl_index++] = str;
9784             }
9785             break;
9786         case N_EINCL:
9787             if (incl_index > 1)
9788                 incl_index--;
9789             break;
9790         case N_SO:
9791             if (sym->n_strx == 0) {
9792                 incl_index = 0; /* end of translation unit */
9793             } else {
9794                 str = stabstr_section->data + sym->n_strx;
9795                 /* do not add path */
9796                 len = strlen(str);
9797                 if (len > 0 && str[len - 1] != '/')
9798                     goto add_incl;
9799             }
9800             break;
9801         }
9802         sym++;
9803     }
9804 
9805     /* second pass: we try symtab symbols (no line number info) */
9806     incl_index = 0;
9807     {
9808         Elf32_Sym *sym, *sym_end;
9809         int type;
9810 
9811         sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9812         for(sym = (Elf32_Sym *)symtab_section->data + 1;
9813             sym < sym_end;
9814             sym++) {
9815             type = ELF32_ST_TYPE(sym->st_info);
9816             if (type == STT_FUNC) {
9817                 if (wanted_pc >= sym->st_value &&
9818                     wanted_pc < sym->st_value + sym->st_size) {
9819                     pstrcpy(last_func_name, sizeof(last_func_name),
9820                             strtab_section->data + sym->st_name);
9821                     goto found;
9822                 }
9823             }
9824         }
9825     }
9826     /* did not find any info: */
9827     fprintf(stderr, " ???\n");
9828     return;
9829  found:
9830     if (last_func_name[0] != '\0') {
9831         fprintf(stderr, " %s()", last_func_name);
9832     }
9833     if (incl_index > 0) {
9834         fprintf(stderr, " (%s:%d",
9835                 incl_files[incl_index - 1], last_line_num);
9836         for(i = incl_index - 2; i >= 0; i--)
9837             fprintf(stderr, ", included from %s", incl_files[i]);
9838         fprintf(stderr, ")");
9839     }
9840     fprintf(stderr, "\n");
9841 }
9842 
9843 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9844 
9845 #ifdef __i386__
9846 
9847 /* fix for glibc 2.1 */
9848 #ifndef REG_EIP
9849 #define REG_EIP EIP
9850 #define REG_EBP EBP
9851 #endif
9852 
9853 /* return the PC at frame level 'level'. Return non zero if not found */
rt_get_caller_pc(unsigned long * paddr,ucontext_t * uc,int level)9854 static int rt_get_caller_pc(unsigned long *paddr,
9855                             ucontext_t *uc, int level)
9856 {
9857     unsigned long fp;
9858     int i;
9859 
9860     if (level == 0) {
9861 #if defined(__FreeBSD__)
9862         *paddr = uc->uc_mcontext.mc_eip;
9863 #elif defined(__dietlibc__)
9864         *paddr = uc->uc_mcontext.eip;
9865 #else
9866         *paddr = uc->uc_mcontext.gregs[REG_EIP];
9867 #endif
9868         return 0;
9869     } else {
9870 #if defined(__FreeBSD__)
9871         fp = uc->uc_mcontext.mc_ebp;
9872 #elif defined(__dietlibc__)
9873         fp = uc->uc_mcontext.ebp;
9874 #else
9875         fp = uc->uc_mcontext.gregs[REG_EBP];
9876 #endif
9877         for(i=1;i<level;i++) {
9878             /* XXX: check address validity with program info */
9879             if (fp <= 0x1000 || fp >= 0xc0000000)
9880                 return -1;
9881             fp = ((unsigned long *)fp)[0];
9882         }
9883         *paddr = ((unsigned long *)fp)[1];
9884         return 0;
9885     }
9886 }
9887 #else
9888 
9889 #warning add arch specific rt_get_caller_pc()
9890 
rt_get_caller_pc(unsigned long * paddr,ucontext_t * uc,int level)9891 static int rt_get_caller_pc(unsigned long *paddr,
9892                             ucontext_t *uc, int level)
9893 {
9894     return -1;
9895 }
9896 #endif
9897 
9898 /* emit a run time error at position 'pc' */
rt_error(ucontext_t * uc,const char * fmt,...)9899 void rt_error(ucontext_t *uc, const char *fmt, ...)
9900 {
9901     va_list ap;
9902     unsigned long pc;
9903     int i;
9904 
9905     va_start(ap, fmt);
9906     fprintf(stderr, "Runtime error: ");
9907     vfprintf(stderr, fmt, ap);
9908     fprintf(stderr, "\n");
9909     for(i=0;i<num_callers;i++) {
9910         if (rt_get_caller_pc(&pc, uc, i) < 0)
9911             break;
9912         if (i == 0)
9913             fprintf(stderr, "at ");
9914         else
9915             fprintf(stderr, "by ");
9916         rt_printline(pc);
9917     }
9918     exit(255);
9919     va_end(ap);
9920 }
9921 
9922 /* signal handler for fatal errors */
sig_error(int signum,siginfo_t * siginf,void * puc)9923 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9924 {
9925     ucontext_t *uc = puc;
9926 
9927     switch(signum) {
9928     case SIGFPE:
9929         switch(siginf->si_code) {
9930         case FPE_INTDIV:
9931         case FPE_FLTDIV:
9932             rt_error(uc, "division by zero");
9933             break;
9934         default:
9935             rt_error(uc, "floating point exception");
9936             break;
9937         }
9938         break;
9939     case SIGBUS:
9940     case SIGSEGV:
9941         if (rt_bound_error_msg && *rt_bound_error_msg)
9942             rt_error(uc, *rt_bound_error_msg);
9943         else
9944             rt_error(uc, "dereferencing invalid pointer");
9945         break;
9946     case SIGILL:
9947         rt_error(uc, "illegal instruction");
9948         break;
9949     case SIGABRT:
9950         rt_error(uc, "abort() called");
9951         break;
9952     default:
9953         rt_error(uc, "caught signal %d", signum);
9954         break;
9955     }
9956     exit(255);
9957 }
9958 #endif
9959 
9960 /* do all relocations (needed before using tcc_get_symbol()) */
tcc_relocate(TCCState * s1)9961 int tcc_relocate(TCCState *s1)
9962 {
9963     Section *s;
9964     int i;
9965 
9966     s1->nb_errors = 0;
9967 
9968 #ifdef TCC_TARGET_PE
9969     pe_add_runtime(s1);
9970 #else
9971     tcc_add_runtime(s1);
9972 #endif
9973 
9974     relocate_common_syms();
9975 
9976     tcc_add_linker_symbols(s1);
9977 #ifndef TCC_TARGET_PE
9978     build_got_entries(s1);
9979 #endif
9980     /* compute relocation address : section are relocated in place. We
9981        also alloc the bss space */
9982     for(i = 1; i < s1->nb_sections; i++) {
9983         s = s1->sections[i];
9984         if (s->sh_flags & SHF_ALLOC) {
9985             if (s->sh_type == SHT_NOBITS)
9986                 s->data = tcc_mallocz(s->data_offset);
9987             s->sh_addr = (unsigned long)s->data;
9988         }
9989     }
9990 
9991     relocate_syms(s1, 1);
9992 
9993     if (s1->nb_errors != 0)
9994         return -1;
9995 
9996     /* relocate each section */
9997     for(i = 1; i < s1->nb_sections; i++) {
9998         s = s1->sections[i];
9999         if (s->reloc)
10000             relocate_section(s1, s);
10001     }
10002 
10003     /* mark executable sections as executable in memory */
10004     for(i = 1; i < s1->nb_sections; i++) {
10005         s = s1->sections[i];
10006         if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10007             (SHF_ALLOC | SHF_EXECINSTR))
10008             set_pages_executable(s->data, s->data_offset);
10009     }
10010     return 0;
10011 }
10012 
10013 /* launch the compiled program with the given arguments */
tcc_run(TCCState * s1,int argc,char ** argv)10014 int tcc_run(TCCState *s1, int argc, char **argv)
10015 {
10016     int (*prog_main)(int, char **);
10017 
10018     if (tcc_relocate(s1) < 0)
10019         return -1;
10020 
10021     prog_main = tcc_get_symbol_err(s1, "main");
10022 
10023     if (do_debug) {
10024 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10025         error("debug mode currently not available for Windows");
10026 #else
10027         struct sigaction sigact;
10028         /* install TCC signal handlers to print debug info on fatal
10029            runtime errors */
10030         sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10031         sigact.sa_sigaction = sig_error;
10032         sigemptyset(&sigact.sa_mask);
10033         sigaction(SIGFPE, &sigact, NULL);
10034         sigaction(SIGILL, &sigact, NULL);
10035         sigaction(SIGSEGV, &sigact, NULL);
10036         sigaction(SIGBUS, &sigact, NULL);
10037         sigaction(SIGABRT, &sigact, NULL);
10038 #endif
10039     }
10040 
10041 #ifdef CONFIG_TCC_BCHECK
10042     if (do_bounds_check) {
10043         void (*bound_init)(void);
10044 
10045         /* set error function */
10046         rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10047                                                         "__bound_error_msg");
10048 
10049         /* XXX: use .init section so that it also work in binary ? */
10050         bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10051         bound_init();
10052     }
10053 #endif
10054     return (*prog_main)(argc, argv);
10055 }
10056 
tcc_new(void)10057 TCCState *tcc_new(void)
10058 {
10059     const char *p, *r;
10060     TCCState *s;
10061     TokenSym *ts;
10062     int i, c;
10063 
10064     s = tcc_mallocz(sizeof(TCCState));
10065     if (!s)
10066         return NULL;
10067     tcc_state = s;
10068     s->output_type = TCC_OUTPUT_MEMORY;
10069 
10070     /* init isid table */
10071     for(i=0;i<256;i++)
10072         isidnum_table[i] = isid(i) || isnum(i);
10073 
10074     /* add all tokens */
10075     table_ident = NULL;
10076     memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10077 
10078     tok_ident = TOK_IDENT;
10079     p = tcc_keywords;
10080     while (*p) {
10081         r = p;
10082         for(;;) {
10083             c = *r++;
10084             if (c == '\0')
10085                 break;
10086         }
10087         ts = tok_alloc(p, r - p - 1);
10088         p = r;
10089     }
10090 
10091     /* we add dummy defines for some special macros to speed up tests
10092        and to have working defined() */
10093     define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10094     define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10095     define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10096     define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10097 
10098     /* standard defines */
10099     tcc_define_symbol(s, "__STDC__", NULL);
10100     tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10101 #if defined(TCC_TARGET_I386)
10102     tcc_define_symbol(s, "__i386__", NULL);
10103 #endif
10104 #if defined(TCC_TARGET_ARM)
10105     tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10106     tcc_define_symbol(s, "__arm_elf__", NULL);
10107     tcc_define_symbol(s, "__arm_elf", NULL);
10108     tcc_define_symbol(s, "arm_elf", NULL);
10109     tcc_define_symbol(s, "__arm__", NULL);
10110     tcc_define_symbol(s, "__arm", NULL);
10111     tcc_define_symbol(s, "arm", NULL);
10112     tcc_define_symbol(s, "__APCS_32__", NULL);
10113 #endif
10114 #ifdef TCC_TARGET_PE
10115     tcc_define_symbol(s, "_WIN32", NULL);
10116 #else
10117     tcc_define_symbol(s, "__unix__", NULL);
10118     tcc_define_symbol(s, "__unix", NULL);
10119 #if defined(__linux)
10120     tcc_define_symbol(s, "__linux__", NULL);
10121     tcc_define_symbol(s, "__linux", NULL);
10122 #endif
10123 #endif
10124     /* tiny C specific defines */
10125     tcc_define_symbol(s, "__TINYC__", NULL);
10126 
10127     /* tiny C & gcc defines */
10128     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10129     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10130 #ifdef TCC_TARGET_PE
10131     tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10132 #else
10133     tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10134 #endif
10135 
10136 #ifndef TCC_TARGET_PE
10137     /* default library paths */
10138     tcc_add_library_path(s, "/usr/local/lib");
10139     tcc_add_library_path(s, "/usr/lib");
10140     tcc_add_library_path(s, "/lib");
10141 #endif
10142 
10143     /* no section zero */
10144     dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10145 
10146     /* create standard sections */
10147     text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10148     data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10149     bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10150 
10151     /* symbols are always generated for linking stage */
10152     symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10153                                 ".strtab",
10154                                 ".hashtab", SHF_PRIVATE);
10155     strtab_section = symtab_section->link;
10156 
10157     /* private symbol table for dynamic symbols */
10158     s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10159                                       ".dynstrtab",
10160                                       ".dynhashtab", SHF_PRIVATE);
10161     s->alacarte_link = 1;
10162 
10163 #ifdef CHAR_IS_UNSIGNED
10164     s->char_is_unsigned = 1;
10165 #endif
10166 #if defined(TCC_TARGET_PE) && 0
10167     /* XXX: currently the PE linker is not ready to support that */
10168     s->leading_underscore = 1;
10169 #endif
10170 	strcpy(tcc_lib_path, CONFIG_TCCDIR);
10171     return s;
10172 }
10173 
SetLibPath(const char * path)10174 void SetLibPath(const char *path) {
10175 	strcpy(tcc_lib_path, path);
10176 }
10177 
NoStdlib(TCCState * s)10178 void NoStdlib(TCCState *s) {
10179 	s->nostdlib = 1;
10180 }
10181 
tcc_delete(TCCState * s1)10182 void tcc_delete(TCCState *s1)
10183 {
10184     int i, n;
10185 
10186     /* free -D defines */
10187     free_defines(NULL);
10188 
10189     /* free tokens */
10190     n = tok_ident - TOK_IDENT;
10191     for(i = 0; i < n; i++)
10192         tcc_free(table_ident[i]);
10193     tcc_free(table_ident);
10194 
10195     /* free all sections */
10196 
10197     free_section(symtab_section->hash);
10198 
10199     free_section(s1->dynsymtab_section->hash);
10200     free_section(s1->dynsymtab_section->link);
10201     free_section(s1->dynsymtab_section);
10202 
10203     for(i = 1; i < s1->nb_sections; i++)
10204         free_section(s1->sections[i]);
10205     tcc_free(s1->sections);
10206 
10207     /* free loaded dlls array */
10208     dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10209 
10210     /* free library paths */
10211     dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10212 
10213     /* free include paths */
10214     dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10215     dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10216     dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10217 
10218     tcc_free(s1);
10219 }
10220 
tcc_add_include_path(TCCState * s1,const char * pathname)10221 int tcc_add_include_path(TCCState *s1, const char *pathname)
10222 {
10223     char *pathname1;
10224 
10225     pathname1 = tcc_strdup(pathname);
10226     dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10227     return 0;
10228 }
10229 
tcc_add_sysinclude_path(TCCState * s1,const char * pathname)10230 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10231 {
10232     char *pathname1;
10233 
10234     pathname1 = tcc_strdup(pathname);
10235     dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10236     return 0;
10237 }
10238 
tcc_add_file_internal(TCCState * s1,const char * filename,int flags)10239 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10240 {
10241     const char *ext;
10242     Elf32_Ehdr ehdr;
10243     int fd, ret;
10244     BufferedFile *saved_file;
10245 
10246     /* find source file type with extension */
10247     ext = tcc_fileextension(filename);
10248     if (ext[0])
10249         ext++;
10250 
10251     /* open the file */
10252     saved_file = file;
10253     file = tcc_open(s1, filename);
10254     if (!file) {
10255         if (flags & AFF_PRINT_ERROR) {
10256             error_noabort("file '%s' not found", filename);
10257         }
10258         ret = -1;
10259         goto fail1;
10260     }
10261 
10262     if (flags & AFF_PREPROCESS) {
10263         ret = tcc_preprocess(s1);
10264     } else if (!ext[0] || !strcmp(ext, "c")) {
10265         /* C file assumed */
10266         ret = tcc_compile(s1);
10267     } else
10268 #ifdef CONFIG_TCC_ASM
10269     if (!strcmp(ext, "S")) {
10270         /* preprocessed assembler */
10271         ret = tcc_assemble(s1, 1);
10272     } else if (!strcmp(ext, "s")) {
10273         /* non preprocessed assembler */
10274         ret = tcc_assemble(s1, 0);
10275     } else
10276 #endif
10277 #ifdef TCC_TARGET_PE
10278     if (!strcmp(ext, "def")) {
10279         ret = pe_load_def_file(s1, file->fd);
10280     } else
10281 #endif
10282     {
10283         fd = file->fd;
10284         /* assume executable format: auto guess file type */
10285         ret = read(fd, &ehdr, sizeof(ehdr));
10286         lseek(fd, 0, SEEK_SET);
10287         if (ret <= 0) {
10288             error_noabort("could not read header");
10289             goto fail;
10290         } else if (ret != sizeof(ehdr)) {
10291             goto try_load_script;
10292         }
10293 
10294         if (ehdr.e_ident[0] == ELFMAG0 &&
10295             ehdr.e_ident[1] == ELFMAG1 &&
10296             ehdr.e_ident[2] == ELFMAG2 &&
10297             ehdr.e_ident[3] == ELFMAG3) {
10298             file->line_num = 0; /* do not display line number if error */
10299             if (ehdr.e_type == ET_REL) {
10300                 ret = tcc_load_object_file(s1, fd, 0);
10301             } else if (ehdr.e_type == ET_DYN) {
10302                 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10303 #ifdef TCC_TARGET_PE
10304                     ret = -1;
10305 #else
10306                     void *h;
10307                     h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10308                     if (h)
10309                         ret = 0;
10310                     else
10311                         ret = -1;
10312 #endif
10313                 } else {
10314                     ret = tcc_load_dll(s1, fd, filename,
10315                                        (flags & AFF_REFERENCED_DLL) != 0);
10316                 }
10317             } else {
10318                 error_noabort("unrecognized ELF file");
10319                 goto fail;
10320             }
10321         } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10322             file->line_num = 0; /* do not display line number if error */
10323             ret = tcc_load_archive(s1, fd);
10324         } else
10325 #ifdef TCC_TARGET_COFF
10326         if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10327             ret = tcc_load_coff(s1, fd);
10328         } else
10329 #endif
10330 #ifdef TCC_TARGET_PE
10331         if (pe_test_res_file(&ehdr, ret)) {
10332             ret = pe_load_res_file(s1, fd);
10333         } else
10334 #endif
10335         {
10336             /* as GNU ld, consider it is an ld script if not recognized */
10337         try_load_script:
10338             ret = tcc_load_ldscript(s1);
10339             if (ret < 0) {
10340                 error_noabort("unrecognized file type");
10341                 goto fail;
10342             }
10343         }
10344     }
10345  the_end:
10346     tcc_close(file);
10347  fail1:
10348     file = saved_file;
10349     return ret;
10350  fail:
10351     ret = -1;
10352     goto the_end;
10353 }
10354 
tcc_add_file(TCCState * s,const char * filename)10355 int tcc_add_file(TCCState *s, const char *filename)
10356 {
10357     return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10358 }
10359 
tcc_add_library_path(TCCState * s,const char * pathname)10360 int tcc_add_library_path(TCCState *s, const char *pathname)
10361 {
10362     char *pathname1;
10363 
10364     pathname1 = tcc_strdup(pathname);
10365     dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10366     return 0;
10367 }
10368 
10369 /* find and load a dll. Return non zero if not found */
10370 /* XXX: add '-rpath' option support ? */
tcc_add_dll(TCCState * s,const char * filename,int flags)10371 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10372 {
10373     char buf[1024];
10374     int i;
10375 
10376     for(i = 0; i < s->nb_library_paths; i++) {
10377         snprintf(buf, sizeof(buf), "%s/%s",
10378                  s->library_paths[i], filename);
10379         if (tcc_add_file_internal(s, buf, flags) == 0)
10380             return 0;
10381     }
10382     return -1;
10383 }
10384 
10385 /* the library name is the same as the argument of the '-l' option */
tcc_add_library(TCCState * s,const char * libraryname)10386 int tcc_add_library(TCCState *s, const char *libraryname)
10387 {
10388     char buf[1024];
10389     int i;
10390 
10391     /* first we look for the dynamic library if not static linking */
10392     if (!s->static_link) {
10393 #ifdef TCC_TARGET_PE
10394         snprintf(buf, sizeof(buf), "%s.def", libraryname);
10395 #else
10396         snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10397 #endif
10398         if (tcc_add_dll(s, buf, 0) == 0)
10399             return 0;
10400     }
10401 
10402     /* then we look for the static library */
10403     for(i = 0; i < s->nb_library_paths; i++) {
10404         snprintf(buf, sizeof(buf), "%s/lib%s.a",
10405                  s->library_paths[i], libraryname);
10406         if (tcc_add_file_internal(s, buf, 0) == 0)
10407             return 0;
10408     }
10409     return -1;
10410 }
10411 
tcc_add_symbol(TCCState * s,const char * name,unsigned long val)10412 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10413 {
10414     add_elf_sym(symtab_section, val, 0,
10415                 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10416                 SHN_ABS, name);
10417     return 0;
10418 }
10419 
tcc_set_output_type(TCCState * s,int output_type)10420 int tcc_set_output_type(TCCState *s, int output_type)
10421 {
10422     char buf[1024];
10423 
10424     s->output_type = output_type;
10425 
10426     if (!s->nostdinc) {
10427         /* default include paths */
10428         /* XXX: reverse order needed if -isystem support */
10429 #ifndef TCC_TARGET_PE
10430         tcc_add_sysinclude_path(s, "/usr/local/include");
10431         tcc_add_sysinclude_path(s, "/usr/include");
10432 #endif
10433         snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10434         tcc_add_sysinclude_path(s, buf);
10435 #ifdef TCC_TARGET_PE
10436         snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10437         tcc_add_sysinclude_path(s, buf);
10438 #endif
10439     }
10440 
10441     /* if bound checking, then add corresponding sections */
10442 #ifdef CONFIG_TCC_BCHECK
10443     if (do_bounds_check) {
10444         /* define symbol */
10445         tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10446         /* create bounds sections */
10447         bounds_section = new_section(s, ".bounds",
10448                                      SHT_PROGBITS, SHF_ALLOC);
10449         lbounds_section = new_section(s, ".lbounds",
10450                                       SHT_PROGBITS, SHF_ALLOC);
10451     }
10452 #endif
10453 
10454     if (s->char_is_unsigned) {
10455         tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10456     }
10457 
10458     /* add debug sections */
10459     if (do_debug) {
10460         /* stab symbols */
10461         stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10462         stab_section->sh_entsize = sizeof(Stab_Sym);
10463         stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10464         put_elf_str(stabstr_section, "");
10465         stab_section->link = stabstr_section;
10466         /* put first entry */
10467         put_stabs("", 0, 0, 0, 0);
10468     }
10469 
10470     /* add libc crt1/crti objects */
10471 #ifndef TCC_TARGET_PE
10472     if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10473         !s->nostdlib) {
10474         if (output_type != TCC_OUTPUT_DLL)
10475             tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10476         tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10477     }
10478 #endif
10479 
10480 #ifdef TCC_TARGET_PE
10481     snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10482     tcc_add_library_path(s, buf);
10483 #endif
10484 
10485     return 0;
10486 }
10487 
10488 #define WD_ALL    0x0001 /* warning is activated when using -Wall */
10489 #define FD_INVERT 0x0002 /* invert value before storing */
10490 
10491 typedef struct FlagDef {
10492     uint16_t offset;
10493     uint16_t flags;
10494     const char *name;
10495 } FlagDef;
10496 
10497 static const FlagDef warning_defs[] = {
10498     { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10499     { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10500     { offsetof(TCCState, warn_error), 0, "error" },
10501     { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10502       "implicit-function-declaration" },
10503 };
10504 
set_flag(TCCState * s,const FlagDef * flags,int nb_flags,const char * name,int value)10505 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10506                     const char *name, int value)
10507 {
10508     int i;
10509     const FlagDef *p;
10510     const char *r;
10511 
10512     r = name;
10513     if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10514         r += 3;
10515         value = !value;
10516     }
10517     for(i = 0, p = flags; i < nb_flags; i++, p++) {
10518         if (!strcmp(r, p->name))
10519             goto found;
10520     }
10521     return -1;
10522  found:
10523     if (p->flags & FD_INVERT)
10524         value = !value;
10525     *(int *)((uint8_t *)s + p->offset) = value;
10526     return 0;
10527 }
10528 
10529 
10530 /* set/reset a warning */
tcc_set_warning(TCCState * s,const char * warning_name,int value)10531 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10532 {
10533     int i;
10534     const FlagDef *p;
10535 
10536     if (!strcmp(warning_name, "all")) {
10537         for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10538             if (p->flags & WD_ALL)
10539                 *(int *)((uint8_t *)s + p->offset) = 1;
10540         }
10541         return 0;
10542     } else {
10543         return set_flag(s, warning_defs, countof(warning_defs),
10544                         warning_name, value);
10545     }
10546 }
10547 
10548 static const FlagDef flag_defs[] = {
10549     { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10550     { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10551     { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10552     { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10553 };
10554 
10555 /* set/reset a flag */
tcc_set_flag(TCCState * s,const char * flag_name,int value)10556 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10557 {
10558     return set_flag(s, flag_defs, countof(flag_defs),
10559                     flag_name, value);
10560 }
10561 
10562 #if !defined(LIBTCC)
10563 
getclock_us(void)10564 static int64_t getclock_us(void)
10565 {
10566 #ifdef _WIN32
10567     struct _timeb tb;
10568     _ftime(&tb);
10569     return (tb.time * 1000LL + tb.millitm) * 1000LL;
10570 #else
10571     struct timeval tv;
10572     gettimeofday(&tv, NULL);
10573     return tv.tv_sec * 1000000LL + tv.tv_usec;
10574 #endif
10575 }
10576 
help(void)10577 void help(void)
10578 {
10579     printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10580            "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10581            "           [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10582            "           [-static] [infile1 infile2...] [-run infile args...]\n"
10583            "\n"
10584            "General options:\n"
10585            "  -v          display current version, increase verbosity\n"
10586            "  -c          compile only - generate an object file\n"
10587            "  -o outfile  set output filename\n"
10588            "  -Bdir       set tcc internal library path\n"
10589            "  -bench      output compilation statistics\n"
10590            "  -run        run compiled source\n"
10591            "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10592            "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10593            "  -w          disable all warnings\n"
10594            "Preprocessor options:\n"
10595            "  -E          preprocess only\n"
10596            "  -Idir       add include path 'dir'\n"
10597            "  -Dsym[=val] define 'sym' with value 'val'\n"
10598            "  -Usym       undefine 'sym'\n"
10599            "Linker options:\n"
10600            "  -Ldir       add library path 'dir'\n"
10601            "  -llib       link with dynamic or static library 'lib'\n"
10602            "  -shared     generate a shared library\n"
10603            "  -soname     set name for shared library to be used at runtime\n"
10604            "  -static     static linking\n"
10605            "  -rdynamic   export all global symbols to dynamic linker\n"
10606            "  -r          generate (relocatable) object file\n"
10607            "Debugger options:\n"
10608            "  -g          generate runtime debug info\n"
10609 #ifdef CONFIG_TCC_BCHECK
10610            "  -b          compile with built-in memory and bounds checker (implies -g)\n"
10611 #endif
10612            "  -bt N       show N callers in stack traces\n"
10613            );
10614 }
10615 
10616 #define TCC_OPTION_HAS_ARG 0x0001
10617 #define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
10618 
10619 typedef struct TCCOption {
10620     const char *name;
10621     uint16_t index;
10622     uint16_t flags;
10623 } TCCOption;
10624 
10625 enum {
10626     TCC_OPTION_HELP,
10627     TCC_OPTION_I,
10628     TCC_OPTION_D,
10629     TCC_OPTION_U,
10630     TCC_OPTION_L,
10631     TCC_OPTION_B,
10632     TCC_OPTION_l,
10633     TCC_OPTION_bench,
10634     TCC_OPTION_bt,
10635     TCC_OPTION_b,
10636     TCC_OPTION_g,
10637     TCC_OPTION_c,
10638     TCC_OPTION_static,
10639     TCC_OPTION_shared,
10640     TCC_OPTION_soname,
10641     TCC_OPTION_o,
10642     TCC_OPTION_r,
10643     TCC_OPTION_Wl,
10644     TCC_OPTION_W,
10645     TCC_OPTION_O,
10646     TCC_OPTION_m,
10647     TCC_OPTION_f,
10648     TCC_OPTION_nostdinc,
10649     TCC_OPTION_nostdlib,
10650     TCC_OPTION_print_search_dirs,
10651     TCC_OPTION_rdynamic,
10652     TCC_OPTION_run,
10653     TCC_OPTION_v,
10654     TCC_OPTION_w,
10655     TCC_OPTION_pipe,
10656     TCC_OPTION_E,
10657 };
10658 
10659 static const TCCOption tcc_options[] = {
10660     { "h", TCC_OPTION_HELP, 0 },
10661     { "?", TCC_OPTION_HELP, 0 },
10662     { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10663     { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10664     { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10665     { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10666     { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10667     { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10668     { "bench", TCC_OPTION_bench, 0 },
10669     { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10670 #ifdef CONFIG_TCC_BCHECK
10671     { "b", TCC_OPTION_b, 0 },
10672 #endif
10673     { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10674     { "c", TCC_OPTION_c, 0 },
10675     { "static", TCC_OPTION_static, 0 },
10676     { "shared", TCC_OPTION_shared, 0 },
10677     { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10678     { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10679     { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10680     { "rdynamic", TCC_OPTION_rdynamic, 0 },
10681     { "r", TCC_OPTION_r, 0 },
10682     { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10683     { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10684     { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10685     { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10686     { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10687     { "nostdinc", TCC_OPTION_nostdinc, 0 },
10688     { "nostdlib", TCC_OPTION_nostdlib, 0 },
10689     { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10690     { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10691     { "w", TCC_OPTION_w, 0 },
10692     { "pipe", TCC_OPTION_pipe, 0},
10693     { "E", TCC_OPTION_E, 0},
10694     { NULL },
10695 };
10696 
10697 /* convert 'str' into an array of space separated strings */
expand_args(char *** pargv,const char * str)10698 static int expand_args(char ***pargv, const char *str)
10699 {
10700     const char *s1;
10701     char **argv, *arg;
10702     int argc, len;
10703 
10704     argc = 0;
10705     argv = NULL;
10706     for(;;) {
10707         while (is_space(*str))
10708             str++;
10709         if (*str == '\0')
10710             break;
10711         s1 = str;
10712         while (*str != '\0' && !is_space(*str))
10713             str++;
10714         len = str - s1;
10715         arg = tcc_malloc(len + 1);
10716         memcpy(arg, s1, len);
10717         arg[len] = '\0';
10718         dynarray_add((void ***)&argv, &argc, arg);
10719     }
10720     *pargv = argv;
10721     return argc;
10722 }
10723 
10724 static char **files;
10725 static int nb_files, nb_libraries;
10726 static int multiple_files;
10727 static int print_search_dirs;
10728 static int output_type;
10729 static int reloc_output;
10730 static const char *outfile;
10731 
parse_args(TCCState * s,int argc,char ** argv)10732 int parse_args(TCCState *s, int argc, char **argv)
10733 {
10734     int optind;
10735     const TCCOption *popt;
10736     const char *optarg, *p1, *r1;
10737     char *r;
10738 
10739     optind = 0;
10740     while (1) {
10741         if (optind >= argc) {
10742             if (nb_files == 0 && !print_search_dirs) {
10743                 if (verbose)
10744                     exit(0);
10745                 goto show_help;
10746             }
10747             break;
10748         }
10749         r = argv[optind++];
10750         if (r[0] != '-' || r[1] == '\0') {
10751             /* add a new file */
10752             dynarray_add((void ***)&files, &nb_files, r);
10753             if (!multiple_files) {
10754                 optind--;
10755                 /* argv[0] will be this file */
10756                 break;
10757             }
10758         } else {
10759             /* find option in table (match only the first chars */
10760             popt = tcc_options;
10761             for(;;) {
10762                 p1 = popt->name;
10763                 if (p1 == NULL)
10764                     error("invalid option -- '%s'", r);
10765                 r1 = r + 1;
10766                 for(;;) {
10767                     if (*p1 == '\0')
10768                         goto option_found;
10769                     if (*r1 != *p1)
10770                         break;
10771                     p1++;
10772                     r1++;
10773                 }
10774                 popt++;
10775             }
10776         option_found:
10777             if (popt->flags & TCC_OPTION_HAS_ARG) {
10778                 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10779                     optarg = r1;
10780                 } else {
10781                     if (optind >= argc)
10782                         error("argument to '%s' is missing", r);
10783                     optarg = argv[optind++];
10784                 }
10785             } else {
10786                 if (*r1 != '\0')
10787                     goto show_help;
10788                 optarg = NULL;
10789             }
10790 
10791             switch(popt->index) {
10792             case TCC_OPTION_HELP:
10793             show_help:
10794                 help();
10795                 exit(1);
10796             case TCC_OPTION_I:
10797                 if (tcc_add_include_path(s, optarg) < 0)
10798                     error("too many include paths");
10799                 break;
10800             case TCC_OPTION_D:
10801                 {
10802                     char *sym, *value;
10803                     sym = (char *)optarg;
10804                     value = strchr(sym, '=');
10805                     if (value) {
10806                         *value = '\0';
10807                         value++;
10808                     }
10809                     tcc_define_symbol(s, sym, value);
10810                 }
10811                 break;
10812             case TCC_OPTION_U:
10813                 tcc_undefine_symbol(s, optarg);
10814                 break;
10815             case TCC_OPTION_L:
10816                 tcc_add_library_path(s, optarg);
10817                 break;
10818             case TCC_OPTION_B:
10819                 /* set tcc utilities path (mainly for tcc development) */
10820                 strcpy(tcc_lib_path, optarg);
10821                 break;
10822             case TCC_OPTION_l:
10823                 dynarray_add((void ***)&files, &nb_files, r);
10824                 nb_libraries++;
10825                 break;
10826             case TCC_OPTION_bench:
10827                 do_bench = 1;
10828                 break;
10829             case TCC_OPTION_bt:
10830                 num_callers = atoi(optarg);
10831                 break;
10832 #ifdef CONFIG_TCC_BCHECK
10833             case TCC_OPTION_b:
10834                 do_bounds_check = 1;
10835                 do_debug = 1;
10836                 break;
10837 #endif
10838             case TCC_OPTION_g:
10839                 do_debug = 1;
10840                 break;
10841             case TCC_OPTION_c:
10842                 multiple_files = 1;
10843                 output_type = TCC_OUTPUT_OBJ;
10844                 break;
10845             case TCC_OPTION_static:
10846                 s->static_link = 1;
10847                 break;
10848             case TCC_OPTION_shared:
10849                 output_type = TCC_OUTPUT_DLL;
10850                 break;
10851             case TCC_OPTION_soname:
10852                 s->soname = optarg;
10853                 break;
10854             case TCC_OPTION_o:
10855                 multiple_files = 1;
10856                 outfile = optarg;
10857                 break;
10858             case TCC_OPTION_r:
10859                 /* generate a .o merging several output files */
10860                 reloc_output = 1;
10861                 output_type = TCC_OUTPUT_OBJ;
10862                 break;
10863             case TCC_OPTION_nostdinc:
10864                 s->nostdinc = 1;
10865                 break;
10866             case TCC_OPTION_nostdlib:
10867                 s->nostdlib = 1;
10868                 break;
10869             case TCC_OPTION_print_search_dirs:
10870                 print_search_dirs = 1;
10871                 break;
10872             case TCC_OPTION_run:
10873                 {
10874                     int argc1;
10875                     char **argv1;
10876                     argc1 = expand_args(&argv1, optarg);
10877                     if (argc1 > 0) {
10878                         parse_args(s, argc1, argv1);
10879                     }
10880                     multiple_files = 0;
10881                     output_type = TCC_OUTPUT_MEMORY;
10882                 }
10883                 break;
10884             case TCC_OPTION_v:
10885                 do {
10886                     if (0 == verbose++)
10887                         printf("tcc version %s\n", TCC_VERSION);
10888                 } while (*optarg++ == 'v');
10889                 break;
10890             case TCC_OPTION_f:
10891                 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10892                     goto unsupported_option;
10893                 break;
10894             case TCC_OPTION_W:
10895                 if (tcc_set_warning(s, optarg, 1) < 0 &&
10896                     s->warn_unsupported)
10897                     goto unsupported_option;
10898                 break;
10899             case TCC_OPTION_w:
10900                 s->warn_none = 1;
10901                 break;
10902             case TCC_OPTION_rdynamic:
10903                 s->rdynamic = 1;
10904                 break;
10905             case TCC_OPTION_Wl:
10906                 {
10907                     const char *p;
10908                     if (strstart(optarg, "-Ttext,", &p)) {
10909                         s->text_addr = strtoul(p, NULL, 16);
10910                         s->has_text_addr = 1;
10911                     } else if (strstart(optarg, "--oformat,", &p)) {
10912                         if (strstart(p, "elf32-", NULL)) {
10913                             s->output_format = TCC_OUTPUT_FORMAT_ELF;
10914                         } else if (!strcmp(p, "binary")) {
10915                             s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10916                         } else
10917 #ifdef TCC_TARGET_COFF
10918                         if (!strcmp(p, "coff")) {
10919                             s->output_format = TCC_OUTPUT_FORMAT_COFF;
10920                         } else
10921 #endif
10922                         {
10923                             error("target %s not found", p);
10924                         }
10925                     } else {
10926                         error("unsupported linker option '%s'", optarg);
10927                     }
10928                 }
10929                 break;
10930             case TCC_OPTION_E:
10931                 output_type = TCC_OUTPUT_PREPROCESS;
10932                 break;
10933             default:
10934                 if (s->warn_unsupported) {
10935                 unsupported_option:
10936                     warning("unsupported option '%s'", r);
10937                 }
10938                 break;
10939             }
10940         }
10941     }
10942     return optind;
10943 }
10944 
main(int argc,char ** argv)10945 int main(int argc, char **argv)
10946 {
10947     int i;
10948     TCCState *s;
10949     int nb_objfiles, ret, optind;
10950     char objfilename[1024];
10951     int64_t start_time = 0;
10952 
10953 #ifdef _WIN32
10954     strcpy(tcc_lib_path, w32_tcc_lib_path());
10955 #endif
10956 
10957     s = tcc_new();
10958     output_type = TCC_OUTPUT_EXE;
10959     outfile = NULL;
10960     multiple_files = 1;
10961     files = NULL;
10962     nb_files = 0;
10963     nb_libraries = 0;
10964     reloc_output = 0;
10965     print_search_dirs = 0;
10966     ret = 0;
10967 
10968     optind = parse_args(s, argc - 1, argv + 1) + 1;
10969 
10970     if (print_search_dirs) {
10971         /* enough for Linux kernel */
10972         printf("install: %s/\n", tcc_lib_path);
10973         return 0;
10974     }
10975 
10976     nb_objfiles = nb_files - nb_libraries;
10977 
10978     /* if outfile provided without other options, we output an
10979        executable */
10980     if (outfile && output_type == TCC_OUTPUT_MEMORY)
10981         output_type = TCC_OUTPUT_EXE;
10982 
10983     /* check -c consistency : only single file handled. XXX: checks file type */
10984     if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10985         /* accepts only a single input file */
10986         if (nb_objfiles != 1)
10987             error("cannot specify multiple files with -c");
10988         if (nb_libraries != 0)
10989             error("cannot specify libraries with -c");
10990     }
10991 
10992 
10993     if (output_type == TCC_OUTPUT_PREPROCESS) {
10994         if (!outfile) {
10995             s->outfile = stdout;
10996         } else {
10997             s->outfile = fopen(outfile, "w");
10998             if (!s->outfile)
10999                 error("could not open '%s", outfile);
11000         }
11001     } else if (output_type != TCC_OUTPUT_MEMORY) {
11002         if (!outfile) {
11003             /* compute default outfile name */
11004             char *ext;
11005             const char *name =
11006                 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11007             pstrcpy(objfilename, sizeof(objfilename), name);
11008             ext = tcc_fileextension(objfilename);
11009 #ifdef TCC_TARGET_PE
11010             if (output_type == TCC_OUTPUT_DLL)
11011                 strcpy(ext, ".dll");
11012             else
11013             if (output_type == TCC_OUTPUT_EXE)
11014                 strcpy(ext, ".exe");
11015             else
11016 #endif
11017             if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11018                 strcpy(ext, ".o");
11019             else
11020                 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11021             outfile = objfilename;
11022         }
11023     }
11024 
11025     if (do_bench) {
11026         start_time = getclock_us();
11027     }
11028 
11029     tcc_set_output_type(s, output_type);
11030 
11031     /* compile or add each files or library */
11032     for(i = 0; i < nb_files && ret == 0; i++) {
11033         const char *filename;
11034 
11035         filename = files[i];
11036         if (output_type == TCC_OUTPUT_PREPROCESS) {
11037             if (tcc_add_file_internal(s, filename,
11038                     AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11039                 ret = 1;
11040         } else if (filename[0] == '-' && filename[1]) {
11041             if (tcc_add_library(s, filename + 2) < 0)
11042                 error("cannot find %s", filename);
11043         } else {
11044             if (1 == verbose)
11045                 printf("-> %s\n", filename);
11046             if (tcc_add_file(s, filename) < 0)
11047                 ret = 1;
11048         }
11049     }
11050 
11051     /* free all files */
11052     tcc_free(files);
11053 
11054     if (ret)
11055         goto the_end;
11056 
11057     if (do_bench) {
11058         double total_time;
11059         total_time = (double)(getclock_us() - start_time) / 1000000.0;
11060         if (total_time < 0.001)
11061             total_time = 0.001;
11062         if (total_bytes < 1)
11063             total_bytes = 1;
11064         printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11065                tok_ident - TOK_IDENT, total_lines, total_bytes,
11066                total_time, (int)(total_lines / total_time),
11067                total_bytes / total_time / 1000000.0);
11068     }
11069 
11070     if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11071         if (outfile)
11072             fclose(s->outfile);
11073     } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11074         ret = tcc_run(s, argc - optind, argv + optind);
11075     } else
11076 #ifdef TCC_TARGET_PE
11077     if (s->output_type != TCC_OUTPUT_OBJ) {
11078         ret = pe_output_file(s, outfile);
11079     } else
11080 #endif
11081     {
11082         ret = tcc_output_file(s, outfile) ? 1 : 0;
11083     }
11084  the_end:
11085     /* XXX: cannot do it with bound checking because of the malloc hooks */
11086     if (!do_bounds_check)
11087         tcc_delete(s);
11088 
11089 #ifdef MEM_DEBUG
11090     if (do_bench) {
11091         printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11092     }
11093 #endif
11094     return ret;
11095 }
11096 
11097 #endif
11098