~ubuntu-branches/ubuntu/wily/tcc/wily

« back to all changes in this revision

Viewing changes to tcc.c

  • Committer: Package Import Robot
  • Author(s): Graham Inggs
  • Date: 2015-09-27 08:17:02 UTC
  • mfrom: (17.1.16 wily-proposed)
  • Revision ID: package-import@ubuntu.com-20150927081702-utgd126t8647rcp0
Tags: 0.9.27~git20140923.9d7fb33-3ubuntu1
Disable stack protection on i386 to avoid FTBFS with
undefined symbol '__stack_chk_fail_local' (LP: #1500147).

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "tcc.h"
25
25
#endif
26
26
 
27
 
static char **files;
28
 
static int nb_files, nb_libraries;
29
 
static int multiple_files;
30
 
static int print_search_dirs;
31
 
static int output_type;
32
 
static int reloc_output;
33
 
static char *outfile;
34
 
static int do_bench = 0;
35
 
static int gen_deps;
36
 
static const char *deps_outfile;
37
 
static const char *m_option;
38
 
static CString linker_arg;
39
 
 
40
 
#define TCC_OPTION_HAS_ARG 0x0001
41
 
#define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
42
 
 
43
27
static void help(void)
44
28
{
45
29
    printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
46
30
           "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
47
31
           "       tcc [options...] -run infile [arguments...]\n"
48
32
           "General options:\n"
49
 
           "  -v          display current version, increase verbosity\n"
50
33
           "  -c          compile only - generate an object file\n"
51
34
           "  -o outfile  set output filename\n"
52
 
           "  -Bdir       set tcc internal library and include path\n"
53
 
           "  -bench      output compilation statistics\n"
54
35
           "  -run        run compiled source\n"
55
36
           "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
56
37
           "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
57
38
           "  -w          disable all warnings\n"
 
39
           "  -v          show version\n"
 
40
           "  -vv         show included files (as sole argument: show search paths)\n"
 
41
           "  -dumpversion\n"
 
42
           "  -bench      show compilation statistics\n"
58
43
           "Preprocessor options:\n"
59
44
           "  -E          preprocess only\n"
60
45
           "  -Idir       add include path 'dir'\n"
64
49
           "  -Ldir       add library path 'dir'\n"
65
50
           "  -llib       link with dynamic or static library 'lib'\n"
66
51
           "  -pthread    link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
 
52
           "  -r          generate (relocatable) object file\n"
 
53
           "  -rdynamic   export all global symbols to dynamic linker\n"
67
54
           "  -shared     generate a shared library\n"
68
55
           "  -soname     set name for shared library to be used at runtime\n"
69
56
           "  -static     static linking\n"
70
 
           "  -rdynamic   export all global symbols to dynamic linker\n"
71
 
           "  -r          generate (relocatable) object file\n"
 
57
           "  -Wl,-opt[=val]  set linker option (see manual)\n"
72
58
           "Debugger options:\n"
73
59
           "  -g          generate runtime debug info\n"
74
60
#ifdef CONFIG_TCC_BCHECK
78
64
           "  -bt N       show N callers in stack traces\n"
79
65
#endif
80
66
           "Misc options:\n"
 
67
           "  -nostdinc   do not use standard system include paths\n"
 
68
           "  -nostdlib   do not link with standard crt and libraries\n"
 
69
           "  -Bdir       use 'dir' as tcc internal library and include path\n"
81
70
           "  -MD         generate target dependencies for make\n"
82
71
           "  -MF depfile put generated dependencies here\n"
83
72
           );
84
73
}
85
74
 
86
 
typedef struct TCCOption {
87
 
    const char *name;
88
 
    uint16_t index;
89
 
    uint16_t flags;
90
 
} TCCOption;
91
 
 
92
 
enum {
93
 
    TCC_OPTION_HELP,
94
 
    TCC_OPTION_I,
95
 
    TCC_OPTION_D,
96
 
    TCC_OPTION_U,
97
 
    TCC_OPTION_L,
98
 
    TCC_OPTION_B,
99
 
    TCC_OPTION_l,
100
 
    TCC_OPTION_bench,
101
 
    TCC_OPTION_bt,
102
 
    TCC_OPTION_b,
103
 
    TCC_OPTION_g,
104
 
    TCC_OPTION_c,
105
 
    TCC_OPTION_static,
106
 
    TCC_OPTION_shared,
107
 
    TCC_OPTION_soname,
108
 
    TCC_OPTION_o,
109
 
    TCC_OPTION_r,
110
 
    TCC_OPTION_s,
111
 
    TCC_OPTION_Wl,
112
 
    TCC_OPTION_W,
113
 
    TCC_OPTION_O,
114
 
    TCC_OPTION_m,
115
 
    TCC_OPTION_f,
116
 
    TCC_OPTION_isystem,
117
 
    TCC_OPTION_nostdinc,
118
 
    TCC_OPTION_nostdlib,
119
 
    TCC_OPTION_print_search_dirs,
120
 
    TCC_OPTION_rdynamic,
121
 
    TCC_OPTION_pedantic,
122
 
    TCC_OPTION_pthread,
123
 
    TCC_OPTION_run,
124
 
    TCC_OPTION_v,
125
 
    TCC_OPTION_w,
126
 
    TCC_OPTION_pipe,
127
 
    TCC_OPTION_E,
128
 
    TCC_OPTION_MD,
129
 
    TCC_OPTION_MF,
130
 
    TCC_OPTION_x,
131
 
};
132
 
 
133
 
static const TCCOption tcc_options[] = {
134
 
    { "h", TCC_OPTION_HELP, 0 },
135
 
    { "-help", TCC_OPTION_HELP, 0 },
136
 
    { "?", TCC_OPTION_HELP, 0 },
137
 
    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
138
 
    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
139
 
    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
140
 
    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
141
 
    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
142
 
    { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
143
 
    { "bench", TCC_OPTION_bench, 0 },
144
 
#ifdef CONFIG_TCC_BACKTRACE
145
 
    { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
146
 
#endif
147
 
#ifdef CONFIG_TCC_BCHECK
148
 
    { "b", TCC_OPTION_b, 0 },
149
 
#endif
150
 
    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
151
 
    { "c", TCC_OPTION_c, 0 },
152
 
    { "static", TCC_OPTION_static, 0 },
153
 
    { "shared", TCC_OPTION_shared, 0 },
154
 
    { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
155
 
    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
156
 
    { "pedantic", TCC_OPTION_pedantic, 0},
157
 
    { "pthread", TCC_OPTION_pthread, 0},
158
 
    { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
159
 
    { "rdynamic", TCC_OPTION_rdynamic, 0 },
160
 
    { "r", TCC_OPTION_r, 0 },
161
 
    { "s", TCC_OPTION_s, 0 },
162
 
    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
163
 
    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
164
 
    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
165
 
    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
166
 
    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
167
 
    { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
168
 
    { "nostdinc", TCC_OPTION_nostdinc, 0 },
169
 
    { "nostdlib", TCC_OPTION_nostdlib, 0 },
170
 
    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 
171
 
    { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
172
 
    { "w", TCC_OPTION_w, 0 },
173
 
    { "pipe", TCC_OPTION_pipe, 0},
174
 
    { "E", TCC_OPTION_E, 0},
175
 
    { "MD", TCC_OPTION_MD, 0},
176
 
    { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
177
 
    { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
178
 
    { NULL },
179
 
};
180
 
 
181
 
static int64_t getclock_us(void)
182
 
{
183
 
#ifdef _WIN32
184
 
    struct _timeb tb;
185
 
    _ftime(&tb);
186
 
    return (tb.time * 1000LL + tb.millitm) * 1000LL;
187
 
#else
188
 
    struct timeval tv;
189
 
    gettimeofday(&tv, NULL);
190
 
    return tv.tv_sec * 1000000LL + tv.tv_usec;
191
 
#endif
192
 
}
193
 
 
194
 
/* convert 'str' into an array of space separated strings */
195
 
static int expand_args(char ***pargv, const char *str)
196
 
{
197
 
    const char *s1;
198
 
    char **argv, *arg;
199
 
    int argc, len;
200
 
 
201
 
    argc = 0;
202
 
    argv = NULL;
203
 
    for(;;) {
204
 
        while (is_space(*str))
205
 
            str++;
206
 
        if (*str == '\0')
207
 
            break;
208
 
        s1 = str;
209
 
        while (*str != '\0' && !is_space(*str))
210
 
            str++;
211
 
        len = str - s1;
212
 
        arg = tcc_malloc(len + 1);
213
 
        memcpy(arg, s1, len);
214
 
        arg[len] = '\0';
215
 
        dynarray_add((void ***)&argv, &argc, arg);
216
 
    }
217
 
    *pargv = argv;
218
 
    return argc;
219
 
}
220
 
 
221
75
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
222
76
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
223
77
#ifdef _WIN32
224
78
#include <process.h>
225
79
static int execvp_win32(const char *prog, char **argv)
226
80
{
227
 
    int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
 
81
    int ret = spawnvp(P_NOWAIT, prog, (const char *const*)argv);
228
82
    if (-1 == ret)
229
83
        return ret;
230
84
    cwait(&ret, ret, WAIT_CHILD);
262
116
            tcc_warning("unsupported option \"-m%s\"", optarg);
263
117
    }
264
118
}
265
 
#endif
266
 
 
267
 
static void parse_option_D(TCCState *s1, const char *optarg)
268
 
{
269
 
    char *sym = tcc_strdup(optarg);
270
 
    char *value = strchr(sym, '=');
271
 
    if (value)
272
 
        *value++ = '\0';
273
 
    tcc_define_symbol(s1, sym, value);
274
 
    tcc_free(sym);
275
 
}
276
 
 
277
 
static int parse_args(TCCState *s, int argc, char **argv)
278
 
{
279
 
    int optind;
280
 
    const TCCOption *popt;
281
 
    const char *optarg, *p1, *r1;
282
 
    char *r;
283
 
    int was_pthread;
284
 
 
285
 
    was_pthread = 0; /* is set if commandline contains -pthread key */
286
 
    optind = 0;
287
 
    cstr_new(&linker_arg);
288
 
 
289
 
    while (optind < argc) {
290
 
 
291
 
        r = argv[optind++];
292
 
        if (r[0] != '-' || r[1] == '\0') {
293
 
            /* add a new file */
294
 
            dynarray_add((void ***)&files, &nb_files, r);
295
 
            if (!multiple_files) {
296
 
                optind--;
297
 
                /* argv[0] will be this file */
298
 
                break;
299
 
            }
300
 
        } else {
301
 
            /* find option in table (match only the first chars */
302
 
            popt = tcc_options;
303
 
            for(;;) {
304
 
                p1 = popt->name;
305
 
                if (p1 == NULL)
306
 
                    tcc_error("invalid option -- '%s'", r);
307
 
                r1 = r + 1;
308
 
                for(;;) {
309
 
                    if (*p1 == '\0')
310
 
                        goto option_found;
311
 
                    if (*r1 != *p1)
312
 
                        break;
313
 
                    p1++;
314
 
                    r1++;
315
 
                }
316
 
                popt++;
317
 
            }
318
 
        option_found:
319
 
            if (popt->flags & TCC_OPTION_HAS_ARG) {
320
 
                if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
321
 
                    optarg = r1;
322
 
                } else {
323
 
                    if (optind >= argc)
324
 
                        tcc_error("argument to '%s' is missing", r);
325
 
                    optarg = argv[optind++];
326
 
                }
327
 
            } else {
328
 
                if (*r1 != '\0')
329
 
                    return 0;
330
 
                optarg = NULL;
331
 
            }
332
 
                
333
 
            switch(popt->index) {
334
 
            case TCC_OPTION_HELP:
335
 
                return 0;
336
 
 
337
 
            case TCC_OPTION_I:
338
 
                if (tcc_add_include_path(s, optarg) < 0)
339
 
                    tcc_error("too many include paths");
340
 
                break;
341
 
            case TCC_OPTION_D:
342
 
                parse_option_D(s, optarg);
343
 
                break;
344
 
            case TCC_OPTION_U:
345
 
                tcc_undefine_symbol(s, optarg);
346
 
                break;
347
 
            case TCC_OPTION_L:
348
 
                tcc_add_library_path(s, optarg);
349
 
                break;
350
 
            case TCC_OPTION_B:
351
 
                /* set tcc utilities path (mainly for tcc development) */
352
 
                tcc_set_lib_path(s, optarg);
353
 
                break;
354
 
            case TCC_OPTION_l:
355
 
                dynarray_add((void ***)&files, &nb_files, r);
356
 
                nb_libraries++;
357
 
                break;
358
 
            case TCC_OPTION_pthread:
359
 
                was_pthread = 1;
360
 
                parse_option_D(s, "_REENTRANT");
361
 
                break;
362
 
            case TCC_OPTION_bench:
363
 
                do_bench = 1;
364
 
                break;
365
 
#ifdef CONFIG_TCC_BACKTRACE
366
 
            case TCC_OPTION_bt:
367
 
                tcc_set_num_callers(atoi(optarg));
368
 
                break;
369
 
#endif
370
 
#ifdef CONFIG_TCC_BCHECK
371
 
            case TCC_OPTION_b:
372
 
                s->do_bounds_check = 1;
373
 
                s->do_debug = 1;
374
 
                break;
375
 
#endif
376
 
            case TCC_OPTION_g:
377
 
                s->do_debug = 1;
378
 
                break;
379
 
            case TCC_OPTION_c:
380
 
                multiple_files = 1;
381
 
                output_type = TCC_OUTPUT_OBJ;
382
 
                break;
383
 
            case TCC_OPTION_static:
384
 
                s->static_link = 1;
385
 
                break;
386
 
            case TCC_OPTION_shared:
387
 
                output_type = TCC_OUTPUT_DLL;
388
 
                break;
389
 
            case TCC_OPTION_soname:
390
 
                s->soname = optarg;
391
 
                break;
392
 
            case TCC_OPTION_m:
393
 
                m_option = optarg;
394
 
                break;
395
 
            case TCC_OPTION_o:
396
 
                multiple_files = 1;
397
 
                outfile = tcc_strdup(optarg);
398
 
                break;
399
 
            case TCC_OPTION_r:
400
 
                /* generate a .o merging several output files */
401
 
                reloc_output = 1;
402
 
                output_type = TCC_OUTPUT_OBJ;
403
 
                break;
404
 
            case TCC_OPTION_isystem:
405
 
                tcc_add_sysinclude_path(s, optarg);
406
 
                break;
407
 
            case TCC_OPTION_nostdinc:
408
 
                s->nostdinc = 1;
409
 
                break;
410
 
            case TCC_OPTION_nostdlib:
411
 
                s->nostdlib = 1;
412
 
                break;
413
 
            case TCC_OPTION_print_search_dirs:
414
 
                print_search_dirs = 1;
415
 
                break;
416
 
            case TCC_OPTION_run:
417
 
            {
418
 
                int argc1;
419
 
                char **argv1;
420
 
                argc1 = expand_args(&argv1, optarg);
421
 
                if (argc1 > 0) {
422
 
                    parse_args(s, argc1, argv1);
423
 
                }
424
 
                multiple_files = 0;
425
 
                output_type = TCC_OUTPUT_MEMORY;
426
 
                break;
427
 
            }
428
 
            case TCC_OPTION_v:
429
 
                do ++s->verbose; while (*optarg++ == 'v');
430
 
                break;
431
 
            case TCC_OPTION_f:
432
 
                if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
433
 
                    goto unsupported_option;
434
 
                break;
435
 
            case TCC_OPTION_W:
436
 
                if (tcc_set_warning(s, optarg, 1) < 0 && 
437
 
                    s->warn_unsupported)
438
 
                    goto unsupported_option;
439
 
                break;
440
 
            case TCC_OPTION_w:
441
 
                s->warn_none = 1;
442
 
                break;
443
 
            case TCC_OPTION_rdynamic:
444
 
                s->rdynamic = 1;
445
 
                break;
446
 
            case TCC_OPTION_Wl:
447
 
                if (linker_arg.size)
448
 
                    --linker_arg.size, cstr_ccat(&linker_arg, ',');
449
 
                cstr_cat(&linker_arg, optarg);
450
 
                cstr_ccat(&linker_arg, '\0');
451
 
                break;
452
 
            case TCC_OPTION_E:
453
 
                output_type = TCC_OUTPUT_PREPROCESS;
454
 
                break;
455
 
            case TCC_OPTION_MD:
456
 
                gen_deps = 1;
457
 
                break;
458
 
            case TCC_OPTION_MF:
459
 
                deps_outfile = optarg;
460
 
                break;
461
 
            case TCC_OPTION_x:
462
 
                break;
463
 
            default:
464
 
                if (s->warn_unsupported) {
465
 
                unsupported_option:
466
 
                    tcc_warning("unsupported option '%s'", r);
467
 
                }
468
 
                break;
469
 
            }
470
 
        }
471
 
    }
472
 
    if (NULL != (r1 = tcc_set_linker(s, (char *) linker_arg.data, TRUE)))
473
 
        tcc_error("unsupported linker option '%s'", r1);
474
 
    /* fixme: these options could be different on your platform */
475
 
    if (was_pthread && output_type != TCC_OUTPUT_OBJ) {
476
 
        dynarray_add((void ***)&files, &nb_files, "-lpthread");
477
 
        nb_libraries++;
478
 
    }
479
 
    return optind;
 
119
#else
 
120
#define exec_other_tcc(s, argv, optarg)
 
121
#endif
 
122
 
 
123
static void gen_makedeps(TCCState *s, const char *target, const char *filename)
 
124
{
 
125
    FILE *depout;
 
126
    char buf[1024], *ext;
 
127
    int i;
 
128
 
 
129
    if (!filename) {
 
130
        /* compute filename automatically
 
131
         * dir/file.o -> dir/file.d             */
 
132
        pstrcpy(buf, sizeof(buf), target);
 
133
        ext = tcc_fileextension(buf);
 
134
        pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
 
135
        filename = buf;
 
136
    }
 
137
 
 
138
    if (s->verbose)
 
139
        printf("<- %s\n", filename);
 
140
 
 
141
    /* XXX return err codes instead of error() ? */
 
142
    depout = fopen(filename, "w");
 
143
    if (!depout)
 
144
        tcc_error("could not open '%s'", filename);
 
145
 
 
146
    fprintf(depout, "%s : \\\n", target);
 
147
    for (i=0; i<s->nb_target_deps; ++i)
 
148
        fprintf(depout, " %s \\\n", s->target_deps[i]);
 
149
    fprintf(depout, "\n");
 
150
    fclose(depout);
 
151
}
 
152
 
 
153
static char *default_outputfile(TCCState *s, const char *first_file)
 
154
{
 
155
    char buf[1024];
 
156
    char *ext;
 
157
    const char *name = "a";
 
158
 
 
159
    if (first_file && strcmp(first_file, "-"))
 
160
        name = tcc_basename(first_file);
 
161
    pstrcpy(buf, sizeof(buf), name);
 
162
    ext = tcc_fileextension(buf);
 
163
#ifdef TCC_TARGET_PE
 
164
    if (s->output_type == TCC_OUTPUT_DLL)
 
165
        strcpy(ext, ".dll");
 
166
    else
 
167
    if (s->output_type == TCC_OUTPUT_EXE)
 
168
        strcpy(ext, ".exe");
 
169
    else
 
170
#endif
 
171
    if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) ||
 
172
          (s->output_type == TCC_OUTPUT_PREPROCESS) )
 
173
        && *ext)
 
174
        strcpy(ext, ".o");
 
175
    else
 
176
        strcpy(buf, "a.out");
 
177
 
 
178
    return tcc_strdup(buf);
 
179
}
 
180
 
 
181
static void print_paths(const char *msg, char **paths, int nb_paths)
 
182
{
 
183
    int i;
 
184
    printf("%s:\n%s", msg, nb_paths ? "" : "  -\n");
 
185
    for(i = 0; i < nb_paths; i++)
 
186
        printf("  %s\n", paths[i]);
 
187
}
 
188
 
 
189
static void display_info(TCCState *s, int what)
 
190
{
 
191
    switch (what) {
 
192
    case 0:
 
193
        printf("tcc version %s ("
 
194
#ifdef TCC_TARGET_I386
 
195
        "i386"
 
196
# ifdef TCC_TARGET_PE
 
197
        " Win32"
 
198
# endif
 
199
#elif defined TCC_TARGET_X86_64
 
200
        "x86-64"
 
201
# ifdef TCC_TARGET_PE
 
202
        " Win64"
 
203
# endif
 
204
#elif defined TCC_TARGET_ARM
 
205
        "ARM"
 
206
# ifdef TCC_ARM_HARDFLOAT
 
207
        " Hard Float"
 
208
# endif
 
209
# ifdef TCC_TARGET_PE
 
210
        " WinCE"
 
211
# endif
 
212
#endif
 
213
#ifndef TCC_TARGET_PE
 
214
# ifdef __linux
 
215
        " Linux"
 
216
# endif
 
217
#endif
 
218
        ")\n", TCC_VERSION);
 
219
        break;
 
220
    case 1:
 
221
        printf("install: %s/\n", s->tcc_lib_path);
 
222
        /* print_paths("programs", NULL, 0); */
 
223
        print_paths("crt", s->crt_paths, s->nb_crt_paths);
 
224
        print_paths("libraries", s->library_paths, s->nb_library_paths);
 
225
        print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
 
226
        printf("elfinterp:\n  %s\n",  DEFAULT_ELFINTERP(s));
 
227
        break;
 
228
    }
 
229
}
 
230
 
 
231
static int64_t getclock_us(void)
 
232
{
 
233
#ifdef _WIN32
 
234
    struct _timeb tb;
 
235
    _ftime(&tb);
 
236
    return (tb.time * 1000LL + tb.millitm) * 1000LL;
 
237
#else
 
238
    struct timeval tv;
 
239
    gettimeofday(&tv, NULL);
 
240
    return tv.tv_sec * 1000000LL + tv.tv_usec;
 
241
#endif
480
242
}
481
243
 
482
244
int main(int argc, char **argv)
483
245
{
484
 
    int i;
485
246
    TCCState *s;
486
 
    int nb_objfiles, ret, optind;
 
247
    int ret, optind, i, bench;
487
248
    int64_t start_time = 0;
488
 
    const char *default_file = NULL;
 
249
    const char *first_file = NULL;
489
250
 
490
251
    s = tcc_new();
491
 
 
492
 
    output_type = TCC_OUTPUT_EXE;
493
 
    outfile = NULL;
494
 
    multiple_files = 1;
495
 
    files = NULL;
496
 
    nb_files = 0;
497
 
    nb_libraries = 0;
498
 
    reloc_output = 0;
499
 
    print_search_dirs = 0;
500
 
    m_option = NULL;
501
 
    ret = 0;
502
 
 
503
 
    optind = parse_args(s, argc - 1, argv + 1);
504
 
 
505
 
#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
506
 
    if (m_option)
507
 
        exec_other_tcc(s, argv, m_option);
508
 
#endif
509
 
 
510
 
    if (print_search_dirs) {
511
 
        /* enough for Linux kernel */
512
 
        printf("install: %s/\n", s->tcc_lib_path);
513
 
        return 0;
514
 
    }
515
 
 
516
 
    if (s->verbose)
517
 
        printf("tcc version %s\n", TCC_VERSION);
518
 
 
519
 
    if (optind == 0 || nb_files == 0) {
520
 
        if (optind && s->verbose)
521
 
            return 0;
 
252
    s->output_type = TCC_OUTPUT_EXE;
 
253
 
 
254
    optind = tcc_parse_args(s, argc - 1, argv + 1);
 
255
    tcc_set_environment(s);
 
256
 
 
257
    if (optind == 0) {
522
258
        help();
523
259
        return 1;
524
260
    }
525
261
 
526
 
    nb_objfiles = nb_files - nb_libraries;
527
 
 
528
 
    /* if outfile provided without other options, we output an
529
 
       executable */
530
 
    if (outfile && output_type == TCC_OUTPUT_MEMORY)
531
 
        output_type = TCC_OUTPUT_EXE;
 
262
    if (s->option_m)
 
263
        exec_other_tcc(s, argv, s->option_m);
 
264
 
 
265
    if (s->verbose)
 
266
        display_info(s, 0);
 
267
 
 
268
    if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) {
 
269
        tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
 
270
        display_info(s, 1);
 
271
        return 0;
 
272
    }
 
273
 
 
274
    if (s->verbose && optind == 1)
 
275
        return 0;
 
276
 
 
277
    if (s->nb_files == 0)
 
278
        tcc_error("no input files\n");
532
279
 
533
280
    /* check -c consistency : only single file handled. XXX: checks file type */
534
 
    if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
 
281
    if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
 
282
        if (s->nb_libraries != 0)
 
283
            tcc_error("cannot specify libraries with -c");
535
284
        /* accepts only a single input file */
536
 
        if (nb_objfiles != 1)
 
285
        if (s->nb_files != 1)
537
286
            tcc_error("cannot specify multiple files with -c");
538
 
        if (nb_libraries != 0)
539
 
            tcc_error("cannot specify libraries with -c");
540
287
    }
541
288
    
542
 
    if (output_type == TCC_OUTPUT_PREPROCESS) {
543
 
        if (!outfile) {
544
 
            s->outfile = stdout;
 
289
    if (s->output_type == TCC_OUTPUT_PREPROCESS) {
 
290
        if (!s->outfile) {
 
291
            s->ppfp = stdout;
545
292
        } else {
546
 
            s->outfile = fopen(outfile, "w");
547
 
            if (!s->outfile)
548
 
                tcc_error("could not open '%s'", outfile);
 
293
            s->ppfp = fopen(s->outfile, "w");
 
294
            if (!s->ppfp)
 
295
                tcc_error("could not write '%s'", s->outfile);
549
296
        }
550
297
    }
551
298
 
552
 
    if (do_bench) {
 
299
    bench = s->do_bench;
 
300
    if (bench)
553
301
        start_time = getclock_us();
554
 
    }
555
302
 
556
 
    tcc_set_output_type(s, output_type);
557
 
    s->reloc_output = reloc_output;
 
303
    tcc_set_output_type(s, s->output_type);
558
304
 
559
305
    /* compile or add each files or library */
560
 
    for(i = 0; i < nb_files && ret == 0; i++) {
 
306
    for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
561
307
        const char *filename;
562
308
 
563
 
        filename = files[i];
 
309
        filename = s->files[i];
564
310
        if (filename[0] == '-' && filename[1] == 'l') {
565
311
            if (tcc_add_library(s, filename + 2) < 0) {
566
 
                tcc_error_noabort("cannot find %s", filename);
 
312
                tcc_error_noabort("cannot find '%s'", filename);
567
313
                ret = 1;
568
314
            }
569
315
        } else {
571
317
                printf("-> %s\n", filename);
572
318
            if (tcc_add_file(s, filename) < 0)
573
319
                ret = 1;
574
 
            if (!default_file)
575
 
                default_file = filename;
 
320
            if (!first_file)
 
321
                first_file = filename;
576
322
        }
577
323
    }
578
324
 
579
 
    /* free all files */
580
 
    tcc_free(files);
581
 
 
582
325
    if (0 == ret) {
583
 
        if (do_bench)
 
326
        if (bench)
584
327
            tcc_print_stats(s, getclock_us() - start_time);
585
328
 
586
329
        if (s->output_type == TCC_OUTPUT_MEMORY) {
588
331
            ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
589
332
#else
590
333
            tcc_error_noabort("-run is not available in a cross compiler");
 
334
            ret = 1;
591
335
#endif
592
336
        } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
593
337
             if (s->outfile)
594
 
                fclose(s->outfile);
 
338
                fclose(s->ppfp);
595
339
        } else {
596
 
            if (!outfile)
597
 
                outfile = tcc_default_target(s, default_file);
598
 
            ret = !!tcc_output_file(s, outfile);
 
340
            if (!s->outfile)
 
341
                s->outfile = default_outputfile(s, first_file);
 
342
            ret = !!tcc_output_file(s, s->outfile);
599
343
            /* dump collected dependencies */
600
 
            if (gen_deps && !ret)
601
 
                tcc_gen_makedeps(s, outfile, deps_outfile);
 
344
            if (s->gen_deps && !ret)
 
345
                gen_makedeps(s, s->outfile, s->deps_outfile);
602
346
        }
603
347
    }
604
348
 
605
349
    tcc_delete(s);
606
 
    cstr_free(&linker_arg);
607
 
    tcc_free(outfile);
608
 
 
609
 
#ifdef MEM_DEBUG
610
 
    if (do_bench) {
611
 
        printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
612
 
    }
613
 
#endif
 
350
    if (bench)
 
351
        tcc_memstats();
614
352
    return ret;
615
353
}