Subversion Repositories Kolibri OS

Rev

Rev 6410 | Rev 6441 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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