Subversion Repositories Kolibri OS

Rev

Rev 145 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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