libtcc: new LIBTCCAPI tcc_set_options(TCCState*, const char*str)
authorgrischka <grischka>
Tue, 12 Feb 2013 18:13:28 +0000 (12 19:13 +0100)
committergrischka <grischka>
Tue, 12 Feb 2013 18:13:28 +0000 (12 19:13 +0100)
This replaces       -> use instead:
-----------------------------------
- tcc_set_linker    -> tcc_set_options(s, "-Wl,...");
- tcc_set_warning   -> tcc_set_options(s, "-W...");
- tcc_enable_debug  -> tcc_set_options(s, "-g");

parse_args is moved to libtcc.c (now tcc_parse_args).

Also some cleanups:
- reorder TCCState members
- add some comments here and there
- do not use argv's directly, make string copies
- use const char* in tcc_set_linker
- tccpe: use fd instead of fp

tested with -D MEM_DEBUG: 0 bytes left

12 files changed:
Changelog
libtcc.c
libtcc.h
tcc.c
tcc.h
tccelf.c
tccpe.c
tccpp.c
tccrun.c
win32/tcc-win32.txt
win32/tools/tiny_impdef.c
win32/tools/tiny_libmaker.c

index 44b96e1..bab887c 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -4,7 +4,8 @@ User interface:
 - -MD/-MF (automatically generate dependencies for make)
 - -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
 - -m32/-m64 to re-exec cross compiler (Henry Kroll III)
-- Mimic all GNU -option forms supported by ld (Kirill Smelkov)
+- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
+- new LIBTCCAPI tcc_set_options() (grischka)
 
 Platforms:
 - Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
index 968c6e4..cd5f13b 100644 (file)
--- a/libtcc.c
+++ b/libtcc.c
@@ -197,8 +197,8 @@ PUB_FUNC char *tcc_fileextension (const char *name)
 #undef realloc
 
 #ifdef MEM_DEBUG
-int mem_cur_size;
-int mem_max_size;
+ST_DATA int mem_cur_size;
+ST_DATA int mem_max_size;
 unsigned malloc_usable_size(void*);
 #endif
 
@@ -261,7 +261,7 @@ PUB_FUNC char *tcc_strdup(const char *str)
 PUB_FUNC void tcc_memstats(void)
 {
 #ifdef MEM_DEBUG
-    printf("memory in use: %d\n", mem_cur_size);
+    printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
 #endif
 }
 
@@ -272,7 +272,7 @@ PUB_FUNC void tcc_memstats(void)
 /********************************************************/
 /* dynarrays */
 
-PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
+ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
 {
     int nb, nb_alloc;
     void **pp;
@@ -292,7 +292,7 @@ PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
     *nb_ptr = nb;
 }
 
-PUB_FUNC void dynarray_reset(void *pp, int *n)
+ST_FUNC void dynarray_reset(void *pp, int *n)
 {
     void **p;
     for (p = *(void***)pp; *n; ++p, --*n)
@@ -860,10 +860,10 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
         define_undef(s);
 }
 
+/* cleanup all static data used during compilation */
 static void tcc_cleanup(void)
 {
     int i, n;
-
     if (NULL == tcc_state)
         return;
     tcc_state = NULL;
@@ -915,18 +915,23 @@ LIBTCCAPI TCCState *tcc_new(void)
     define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
     define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
 
+    /* define __TINYC__ 92X  */
+    sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
+    sprintf(buffer, "%d", a*10000 + b*100 + c);
+    tcc_define_symbol(s, "__TINYC__", buffer);
+
     /* standard defines */
     tcc_define_symbol(s, "__STDC__", NULL);
     tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
+
+    /* target defines */
 #if defined(TCC_TARGET_I386)
     tcc_define_symbol(s, "__i386__", NULL);
     tcc_define_symbol(s, "__i386", NULL);
     tcc_define_symbol(s, "i386", NULL);
-#endif
-#if defined(TCC_TARGET_X86_64)
+#elif defined(TCC_TARGET_X86_64)
     tcc_define_symbol(s, "__x86_64__", NULL);
-#endif
-#if defined(TCC_TARGET_ARM)
+#elif defined(TCC_TARGET_ARM)
     tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
     tcc_define_symbol(s, "__arm_elf__", NULL);
     tcc_define_symbol(s, "__arm_elf", NULL);
@@ -936,34 +941,31 @@ LIBTCCAPI TCCState *tcc_new(void)
     tcc_define_symbol(s, "arm", NULL);
     tcc_define_symbol(s, "__APCS_32__", NULL);
 #endif
+
 #ifdef TCC_TARGET_PE
     tcc_define_symbol(s, "_WIN32", NULL);
-#ifdef TCC_TARGET_X86_64
+# ifdef TCC_TARGET_X86_64
     tcc_define_symbol(s, "_WIN64", NULL);
-#endif
+# endif
 #else
     tcc_define_symbol(s, "__unix__", NULL);
     tcc_define_symbol(s, "__unix", NULL);
     tcc_define_symbol(s, "unix", NULL);
-#if defined(__FreeBSD__)
-#define str(s) #s
-    tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
-#undef str
-#endif
-#if defined(__FreeBSD_kernel__)
-    tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
-#endif
-#if defined(__linux)
+# if defined(__linux)
     tcc_define_symbol(s, "__linux__", NULL);
     tcc_define_symbol(s, "__linux", NULL);
+# endif
+# if defined(__FreeBSD__)
+#  define str(s) #s
+    tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
+#  undef str
+# endif
+# if defined(__FreeBSD_kernel__)
+    tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
+# endif
 #endif
-#endif
-    /* tiny C specific defines */
-    sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
-    sprintf(buffer, "%d", a*10000 + b*100 + c);
-    tcc_define_symbol(s, "__TINYC__", buffer);
 
-    /* tiny C & gcc defines */
+    /* TinyCC & gcc defines */
 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
@@ -978,11 +980,10 @@ LIBTCCAPI TCCState *tcc_new(void)
     tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
 #endif
 
+#ifndef TCC_TARGET_PE
     /* glibc defines */
     tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
     tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
-    
-#ifndef TCC_TARGET_PE
     /* default library paths */
     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
     /* paths for crt objects */
@@ -1010,16 +1011,15 @@ LIBTCCAPI TCCState *tcc_new(void)
                                       ".dynhashtab", SHF_PRIVATE);
     s->alacarte_link = 1;
     s->nocommon = 1;
+    s->section_align = ELF_PAGE_SIZE;
 
 #ifdef CHAR_IS_UNSIGNED
     s->char_is_unsigned = 1;
 #endif
     /* enable this if you want symbols with leading underscore on windows: */
-#if defined(TCC_TARGET_PE) && 0
+#if 0 //def TCC_TARGET_PE
     s->leading_underscore = 1;
 #endif
-    if (s->section_align == 0)
-        s->section_align = ELF_PAGE_SIZE;
 #ifdef TCC_TARGET_I386
     s->seg_size = 32;
 #endif
@@ -1060,16 +1060,25 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
     dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
     dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
 
-    dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
-
     tcc_free(s1->tcc_lib_path);
+    tcc_free(s1->soname);
+    tcc_free(s1->rpath);
+    tcc_free(s1->init_symbol);
+    tcc_free(s1->fini_symbol);
+    tcc_free(s1->outfile);
+    tcc_free(s1->deps_outfile);
+    dynarray_reset(&s1->files, &s1->nb_files);
+    dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
 
-#ifdef HAVE_SELINUX
+#ifdef TCC_IS_NATIVE
+# ifdef HAVE_SELINUX
     munmap (s1->write_mem, s1->mem_size);
     munmap (s1->runtime_mem, s1->mem_size);    
-#else
+# else
     tcc_free(s1->runtime_mem);
+# endif
 #endif
+
     tcc_free(s1);
 }
 
@@ -1236,7 +1245,6 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt,
     return -1;
 }
 
-#ifndef TCC_TARGET_PE
 /* find and load a dll. Return non zero if not found */
 /* XXX: add '-rpath' option support ? */
 ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
@@ -1244,7 +1252,6 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
     return tcc_add_library_internal(s, "%s/%s", filename, flags,
         s->library_paths, s->nb_library_paths);
 }
-#endif
 
 ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
 {
@@ -1276,11 +1283,15 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
 LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
 {
 #ifdef TCC_TARGET_PE
-pe_putimport(s, 0, name, (uintptr_t)val);
+    /* On x86_64 'val' might not be reachable with a 32bit offset.
+       So it is handled here as if it were in a DLL. */
+    pe_putimport(s, 0, name, (uintptr_t)val);
 #else
-add_elf_sym(symtab_section, (uintptr_t)val, 0,
-            ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-            SHN_ABS, name);
+    /* XXX: Same problem on linux but currently "solved" elsewhere
+       via the rather dirty 'runtime_plt_and_got' hack. */
+    add_elf_sym(symtab_section, (uintptr_t)val, 0,
+        ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
+        SHN_ABS, name);
 #endif
     return 0;
 }
@@ -1341,6 +1352,12 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
     return 0;
 }
 
+LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
+{
+    tcc_free(s->tcc_lib_path);
+    s->tcc_lib_path = tcc_strdup(path);
+}
+
 #define WD_ALL    0x0001 /* warning is activated when using -Wall */
 #define FD_INVERT 0x0002 /* invert value before storing */
 
@@ -1382,14 +1399,8 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
     return 0;
 }
 
-/* enable debug */
-LIBTCCAPI void tcc_enable_debug(TCCState *s)
-{
-    s->do_debug = 1;
-}
-
 /* set/reset a warning */
-LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value)
+static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
 {
     int i;
     const FlagDef *p;
@@ -1414,30 +1425,28 @@ static const FlagDef flag_defs[] = {
 };
 
 /* set/reset a flag */
-PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value)
+static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
 {
     return set_flag(s, flag_defs, countof(flag_defs),
                     flag_name, value);
 }
 
 
-static int strstart(const char *str, const char *val, char **ptr)
+static int strstart(const char *val, const char **str)
 {
     const char *p, *q;
-    p = str;
+    p = *str;
     q = val;
-    while (*q != '\0') {
+    while (*q) {
         if (*p != *q)
             return 0;
         p++;
         q++;
     }
-    if (ptr)
-        *ptr = (char *) p;
+    *str = p;
     return 1;
 }
 
-
 /* Like strstart, but automatically takes into account that ld options can
  *
  * - start with double or single dash (e.g. '--soname' or '-soname')
@@ -1446,7 +1455,7 @@ static int strstart(const char *str, const char *val, char **ptr)
  *
  * you provide `val` always in 'option[=]' form (no leading -)
  */
-static int link_option(const char *str, const char *val, char **ptr)
+static int link_option(const char *str, const char *val, const char **ptr)
 {
     const char *p, *q;
 
@@ -1476,64 +1485,72 @@ static int link_option(const char *str, const char *val, char **ptr)
     }
 
     if (ptr)
-        *ptr = (char *) p;
+        *ptr = p;
     return 1;
 }
 
+static const char *skip_linker_arg(const char **str)
+{
+    const char *s1 = *str;
+    const char *s2 = strchr(s1, ',');
+    *str = s2 ? s2++ : (s2 = s1 + strlen(s1));
+    return s2;
+}
 
-/* set linker options */
-PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
+static char *copy_linker_arg(const char *p)
 {
-    char *p = option;
-    char *end;
+    const char *q = p;
+    skip_linker_arg(&q);
+    return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
+}
 
+/* set linker options */
+static int tcc_set_linker(TCCState *s, const char *option)
+{
     while (option && *option) {
-        end = NULL;
+
+        const char *p = option;
+        char *end = NULL;
+        int ignoring = 0;
+
         if (link_option(option, "Bsymbolic", &p)) {
             s->symbolic = 1;
         } else if (link_option(option, "nostdlib", &p)) {
             s->nostdlib = 1;
         } else if (link_option(option, "fini=", &p)) {
-            s->fini_symbol = p;
-            if (s->warn_unsupported)
-                tcc_warning("ignoring -fini %s", p);
-        } else if (link_option(option, "image-base=", &p)) {
+            s->fini_symbol = copy_linker_arg(p);
+            ignoring = 1;
+        } else if (link_option(option, "image-base=", &p)
+                || link_option(option, "Ttext=", &p)) {
             s->text_addr = strtoull(p, &end, 16);
             s->has_text_addr = 1;
         } else if (link_option(option, "init=", &p)) {
-            s->init_symbol = p;
-            if (s->warn_unsupported)
-                tcc_warning("ignoring -init %s", p);
+            s->init_symbol = copy_linker_arg(p);
+            ignoring = 1;
         } else if (link_option(option, "oformat=", &p)) {
 #if defined(TCC_TARGET_PE)
-            if (strstart(p, "pe-", NULL)) {
-#else
-#if defined(TCC_TARGET_X86_64)
-            if (strstart(p, "elf64-", NULL)) {
+            if (strstart("pe-", &p)) {
+#elif defined(TCC_TARGET_X86_64)
+            if (strstart("elf64-", &p)) {
 #else
-            if (strstart(p, "elf32-", NULL)) {
-#endif
+            if (strstart("elf32-", &p)) {
 #endif
                 s->output_format = TCC_OUTPUT_FORMAT_ELF;
             } else if (!strcmp(p, "binary")) {
                 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
-            } else
 #ifdef TCC_TARGET_COFF
-            if (!strcmp(p, "coff")) {
+            } else if (!strcmp(p, "coff")) {
                 s->output_format = TCC_OUTPUT_FORMAT_COFF;
-            } else
 #endif
-            {
-                return p;
-            }
+            } else
+                goto err;
 
         } else if (link_option(option, "rpath=", &p)) {
-            s->rpath = p;
+            s->rpath = copy_linker_arg(p);
         } else if (link_option(option, "section-alignment=", &p)) {
             s->section_align = strtoul(p, &end, 16);
         } else if (link_option(option, "soname=", &p)) {
-            s->soname = p;
-            multi = 0;
+            s->soname = copy_linker_arg(p);
 #ifdef TCC_TARGET_PE
         } else if (link_option(option, "file-alignment=", &p)) {
             s->pe_file_align = strtoul(p, &end, 16);
@@ -1561,98 +1578,346 @@ PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
             if (!strcmp(p, "wince")) {
                 s->pe_subsystem = 9;
 #endif
-            } else {
-                return p;
-            }
+            } else
+                goto err;
 #endif
-
-        } else if (link_option(option, "Ttext=", &p)) {
-            s->text_addr = strtoull(p, &end, 16);
-            s->has_text_addr = 1;
-        } else {
-            char *comma_ptr = strchr(option, ',');
-            if (comma_ptr)
-                *comma_ptr = '\0';
-            return option;
-        }
-
-        if (multi) {
-            option = NULL;
-            p = strchr( (end) ? end : p, ',');
-            if (p) {
-                *p = 0;    /* terminate last option */
-                option = ++p;
-            }
         } else
-            option = NULL;
+            goto err;
+
+        if (ignoring && s->warn_unsupported) err: {
+            char buf[100], *e;
+            pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
+            if (ignoring)
+                tcc_warning("unsupported linker option '%s'", buf);
+            else
+                tcc_error("unsupported linker option '%s'", buf);
+        }
+        option = skip_linker_arg(&p);
     }
-    return NULL;
+    return 0;
 }
 
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
+typedef struct TCCOption {
+    const char *name;
+    uint16_t index;
+    uint16_t flags;
+} TCCOption;
+
+enum {
+    TCC_OPTION_HELP,
+    TCC_OPTION_I,
+    TCC_OPTION_D,
+    TCC_OPTION_U,
+    TCC_OPTION_L,
+    TCC_OPTION_B,
+    TCC_OPTION_l,
+    TCC_OPTION_bench,
+    TCC_OPTION_bt,
+    TCC_OPTION_b,
+    TCC_OPTION_g,
+    TCC_OPTION_c,
+    TCC_OPTION_static,
+    TCC_OPTION_shared,
+    TCC_OPTION_soname,
+    TCC_OPTION_o,
+    TCC_OPTION_r,
+    TCC_OPTION_s,
+    TCC_OPTION_Wl,
+    TCC_OPTION_W,
+    TCC_OPTION_O,
+    TCC_OPTION_m,
+    TCC_OPTION_f,
+    TCC_OPTION_isystem,
+    TCC_OPTION_nostdinc,
+    TCC_OPTION_nostdlib,
+    TCC_OPTION_print_search_dirs,
+    TCC_OPTION_rdynamic,
+    TCC_OPTION_pedantic,
+    TCC_OPTION_pthread,
+    TCC_OPTION_run,
+    TCC_OPTION_v,
+    TCC_OPTION_w,
+    TCC_OPTION_pipe,
+    TCC_OPTION_E,
+    TCC_OPTION_MD,
+    TCC_OPTION_MF,
+    TCC_OPTION_x,
+};
+
+#define TCC_OPTION_HAS_ARG 0x0001
+#define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
+
+static const TCCOption tcc_options[] = {
+    { "h", TCC_OPTION_HELP, 0 },
+    { "-help", TCC_OPTION_HELP, 0 },
+    { "?", TCC_OPTION_HELP, 0 },
+    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
+    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
+    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
+    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
+    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
+    { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "bench", TCC_OPTION_bench, 0 },
+#ifdef CONFIG_TCC_BACKTRACE
+    { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
+#endif
+#ifdef CONFIG_TCC_BCHECK
+    { "b", TCC_OPTION_b, 0 },
+#endif
+    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "c", TCC_OPTION_c, 0 },
+    { "static", TCC_OPTION_static, 0 },
+    { "shared", TCC_OPTION_shared, 0 },
+    { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
+    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
+    { "pedantic", TCC_OPTION_pedantic, 0},
+    { "pthread", TCC_OPTION_pthread, 0},
+    { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "rdynamic", TCC_OPTION_rdynamic, 0 },
+    { "r", TCC_OPTION_r, 0 },
+    { "s", TCC_OPTION_s, 0 },
+    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
+    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
+    { "nostdinc", TCC_OPTION_nostdinc, 0 },
+    { "nostdlib", TCC_OPTION_nostdlib, 0 },
+    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 
+    { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "w", TCC_OPTION_w, 0 },
+    { "pipe", TCC_OPTION_pipe, 0},
+    { "E", TCC_OPTION_E, 0},
+    { "MD", TCC_OPTION_MD, 0},
+    { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
+    { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
+    { NULL, 0, 0 },
+};
+
+static void parse_option_D(TCCState *s1, const char *optarg)
 {
-    tcc_free(s->tcc_lib_path);
-    s->tcc_lib_path = tcc_strdup(path);
+    char *sym = tcc_strdup(optarg);
+    char *value = strchr(sym, '=');
+    if (value)
+        *value++ = '\0';
+    tcc_define_symbol(s1, sym, value);
+    tcc_free(sym);
 }
 
-PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file)
+PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
 {
-    char buf[1024];
-    char *ext;
-    const char *name = "a";
+    const TCCOption *popt;
+    const char *optarg, *r;
+    int run = 0;
+    int pthread = 0;
+    int optind = 0;
 
-    if (default_file && strcmp(default_file, "-"))
-        name = tcc_basename(default_file);
-    pstrcpy(buf, sizeof(buf), name);
-    ext = tcc_fileextension(buf);
-#ifdef TCC_TARGET_PE
-    if (s->output_type == TCC_OUTPUT_DLL)
-        strcpy(ext, ".dll");
-    else
-    if (s->output_type == TCC_OUTPUT_EXE)
-        strcpy(ext, ".exe");
-    else
-#endif
-    if (( (s->output_type == TCC_OUTPUT_OBJ && !s->reloc_output) ||
-          (s->output_type == TCC_OUTPUT_PREPROCESS) )
-        && *ext)
-        strcpy(ext, ".o");
-    else
-        strcpy(buf, "a.out");
+    /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
+    CString linker_arg;
+    cstr_new(&linker_arg);
 
-    return tcc_strdup(buf);
-}
+    while (optind < argc) {
 
+        r = argv[optind++];
+        if (r[0] != '-' || r[1] == '\0') {
+            /* add a new file */
+            dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
+            if (run) {
+                optind--;
+                /* argv[0] will be this file */
+                break;
+            }
+            continue;
+        }
 
-PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename)
-{
-    FILE *depout;
-    char buf[1024], *ext;
-    int i;
+        /* find option in table */
+        for(popt = tcc_options; ; ++popt) {
+            const char *p1 = popt->name;
+            const char *r1 = r + 1;
+            if (p1 == NULL)
+                tcc_error("invalid option -- '%s'", r);
+            if (!strstart(p1, &r1))
+                continue;
+            optarg = r1;
+            if (popt->flags & TCC_OPTION_HAS_ARG) {
+                if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
+                    if (optind >= argc)
+                        tcc_error("argument to '%s' is missing", r);
+                    optarg = argv[optind++];
+                }
+            } else if (*r1 != '\0')
+                continue;
+            break;
+        }
 
-    if (!filename) {
-        /* compute filename automatically
-         * dir/file.o -> dir/file.d             */
-        pstrcpy(buf, sizeof(buf), target);
-        ext = tcc_fileextension(buf);
-        pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
-        filename = buf;
+        switch(popt->index) {
+        case TCC_OPTION_HELP:
+            return 0;
+        case TCC_OPTION_I:
+            if (tcc_add_include_path(s, optarg) < 0)
+                tcc_error("too many include paths");
+            break;
+        case TCC_OPTION_D:
+            parse_option_D(s, optarg);
+            break;
+        case TCC_OPTION_U:
+            tcc_undefine_symbol(s, optarg);
+            break;
+        case TCC_OPTION_L:
+            tcc_add_library_path(s, optarg);
+            break;
+        case TCC_OPTION_B:
+            /* set tcc utilities path (mainly for tcc development) */
+            tcc_set_lib_path(s, optarg);
+            break;
+        case TCC_OPTION_l:
+            dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
+            s->nb_libraries++;
+            break;
+        case TCC_OPTION_pthread:
+            parse_option_D(s, "_REENTRANT");
+            pthread = 1;
+            break;
+        case TCC_OPTION_bench:
+            s->do_bench = 1;
+            break;
+#ifdef CONFIG_TCC_BACKTRACE
+        case TCC_OPTION_bt:
+            tcc_set_num_callers(atoi(optarg));
+            break;
+#endif
+#ifdef CONFIG_TCC_BCHECK
+        case TCC_OPTION_b:
+            s->do_bounds_check = 1;
+            s->do_debug = 1;
+            break;
+#endif
+        case TCC_OPTION_g:
+            s->do_debug = 1;
+            break;
+        case TCC_OPTION_c:
+            s->output_type = TCC_OUTPUT_OBJ;
+            break;
+        case TCC_OPTION_static:
+            s->static_link = 1;
+            break;
+        case TCC_OPTION_shared:
+            s->output_type = TCC_OUTPUT_DLL;
+            break;
+        case TCC_OPTION_soname:
+            s->soname = tcc_strdup(optarg);
+            break;
+        case TCC_OPTION_m:
+            s->option_m = tcc_strdup(optarg);
+            break;
+        case TCC_OPTION_o:
+            s->outfile = tcc_strdup(optarg);
+            break;
+        case TCC_OPTION_r:
+            /* generate a .o merging several output files */
+            s->option_r = 1;
+            s->output_type = TCC_OUTPUT_OBJ;
+            break;
+        case TCC_OPTION_isystem:
+            tcc_add_sysinclude_path(s, optarg);
+            break;
+        case TCC_OPTION_nostdinc:
+            s->nostdinc = 1;
+            break;
+        case TCC_OPTION_nostdlib:
+            s->nostdlib = 1;
+            break;
+        case TCC_OPTION_print_search_dirs:
+            s->print_search_dirs = 1;
+            break;
+        case TCC_OPTION_run:
+            s->output_type = TCC_OUTPUT_MEMORY;
+            tcc_set_options(s, optarg);
+            run = 1;
+            break;
+        case TCC_OPTION_v:
+            do ++s->verbose; while (*optarg++ == 'v');
+            break;
+        case TCC_OPTION_f:
+            if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
+                goto unsupported_option;
+            break;
+        case TCC_OPTION_W:
+            if (tcc_set_warning(s, optarg, 1) < 0 && 
+                s->warn_unsupported)
+                goto unsupported_option;
+            break;
+        case TCC_OPTION_w:
+            s->warn_none = 1;
+            break;
+        case TCC_OPTION_rdynamic:
+            s->rdynamic = 1;
+            break;
+        case TCC_OPTION_Wl:
+            if (linker_arg.size)
+                --linker_arg.size, cstr_ccat(&linker_arg, ',');
+            cstr_cat(&linker_arg, optarg);
+            cstr_ccat(&linker_arg, '\0');
+            break;
+        case TCC_OPTION_E:
+            s->output_type = TCC_OUTPUT_PREPROCESS;
+            break;
+        case TCC_OPTION_MD:
+            s->gen_deps = 1;
+            break;
+        case TCC_OPTION_MF:
+            s->deps_outfile = tcc_strdup(optarg);
+            break;
+        case TCC_OPTION_O:
+        case TCC_OPTION_pedantic:
+        case TCC_OPTION_pipe:
+        case TCC_OPTION_s:
+        case TCC_OPTION_x:
+            /* ignored */
+            break;
+        default:
+            if (s->warn_unsupported) {
+            unsupported_option:
+                tcc_warning("unsupported option '%s'", r);
+            }
+            break;
+        }
     }
 
-    if (s->verbose)
-        printf("<- %s\n", filename);
+    if (pthread && s->output_type != TCC_OUTPUT_OBJ)
+        tcc_set_options(s, "-lpthread");
 
-    /* XXX return err codes instead of error() ? */
-    depout = fopen(filename, "w");
-    if (!depout)
-        tcc_error("could not open '%s'", filename);
+    tcc_set_linker(s, (const char *)linker_arg.data);
+    cstr_free(&linker_arg);
 
-    fprintf(depout, "%s : \\\n", target);
-    for (i=0; i<s->nb_target_deps; ++i)
-        fprintf(depout, " %s \\\n", s->target_deps[i]);
-    fprintf(depout, "\n");
-    fclose(depout);
+    return optind;
+}
+
+LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
+{
+    const char *s1;
+    char **argv, *arg;
+    int argc, len;
+    int ret;
+
+    argc = 0, argv = NULL;
+    for(;;) {
+        while (is_space(*str))
+            str++;
+        if (*str == '\0')
+            break;
+        s1 = str;
+        while (*str != '\0' && !is_space(*str))
+            str++;
+        len = str - s1;
+        arg = tcc_malloc(len + 1);
+        pstrncpy(arg, s1, len);
+        dynarray_add((void ***)&argv, &argc, arg);
+    }
+    ret = tcc_parse_args(s, argc, argv);
+    dynarray_reset(&argv, &argc);
+    return ret;
 }
 
 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
@@ -1668,53 +1933,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
            tt, (int)(total_lines / tt),
            total_bytes / tt / 1000000.0);
 }
-
-static void print_paths(const char *msg, char **paths, int nb_paths)
-{
-    int i;
-    printf("%s:\n%s", msg, nb_paths ? "" : "  -\n");
-    for(i = 0; i < nb_paths; i++)
-        printf("  %s\n", paths[i]);
-}
-
-PUB_FUNC void tcc_display_info(TCCState *s, int what)
-{
-    switch (what) {
-    case 0:
-        printf("tcc version %s ("
-#ifdef TCC_TARGET_I386
-        "i386"
-# ifdef TCC_TARGET_PE
-        " Win32"
-# endif
-#elif defined TCC_TARGET_X86_64
-        "x86-64"
-# ifdef TCC_TARGET_PE
-        " Win64"
-# endif
-#elif defined TCC_TARGET_ARM
-        "ARM"
-# ifdef TCC_ARM_HARDFLOAT
-        " Hard Float"
-# endif
-# ifdef TCC_TARGET_PE
-        " WinCE"
-# endif
-#endif
-#ifndef TCC_TARGET_PE
-# ifdef __linux
-        " Linux"
-# endif
-#endif
-        ")\n", TCC_VERSION);
-        break;
-    case 1:
-        printf("install: %s/\n", s->tcc_lib_path);
-        /* print_paths("programs", NULL, 0); */
-        print_paths("crt", s->crt_paths, s->nb_crt_paths);
-        print_paths("libraries", s->library_paths, s->nb_library_paths);
-        print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
-        break;
-    }
-}
-
index 278dca3..e69cc6b 100644 (file)
--- a/libtcc.h
+++ b/libtcc.h
@@ -19,18 +19,15 @@ LIBTCCAPI TCCState *tcc_new(void);
 /* free a TCC compilation context */
 LIBTCCAPI void tcc_delete(TCCState *s);
 
-/* add debug information in the generated code */
-LIBTCCAPI void tcc_enable_debug(TCCState *s);
+/* set CONFIG_TCCDIR at runtime */
+LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
 
 /* set error/warning display callback */
 LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
-                        void (*error_func)(void *opaque, const char *msg));
-
-/* set/reset a warning */
-LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value);
+    void (*error_func)(void *opaque, const char *msg));
 
-/* set linker option */
-LIBTCCAPI const char * tcc_set_linker(TCCState *s, char *option, int multi);
+/* set options as from command line (multiple supported) */
+LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
 
 /*****************************/
 /* preprocessor */
@@ -50,29 +47,22 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
 /*****************************/
 /* compiling */
 
-/* add a file (either a C file, dll, an object, a library or an ld
-   script). Return -1 if error. */
+/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
 LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
 
-/* compile a string containing a C source. Return non zero if
-   error. */
+/* compile a string containing a C source. Return -1 if error. */
 LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
 
 /*****************************/
 /* linking commands */
 
 /* set output type. MUST BE CALLED before any compilation */
-#define TCC_OUTPUT_MEMORY   0 /* output will be ran in memory (no
-                                 output file) (default) */
+LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
+#define TCC_OUTPUT_MEMORY   0 /* output will be run in memory (default) */
 #define TCC_OUTPUT_EXE      1 /* executable file */
 #define TCC_OUTPUT_DLL      2 /* dynamic library */
 #define TCC_OUTPUT_OBJ      3 /* object file */
-#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
-LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
-
-#define TCC_OUTPUT_FORMAT_ELF    0 /* default output format: ELF */
-#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
-#define TCC_OUTPUT_FORMAT_COFF   2 /* COFF */
+#define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */
 
 /* equivalent to -Lpath option */
 LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
@@ -91,21 +81,18 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
    tcc_relocate() before. */
 LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
 
-/* do all relocations (needed before using tcc_get_symbol())
-   possible values for 'ptr':
+/* do all relocations (needed before using tcc_get_symbol()) */
+LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
+/* possible values for 'ptr':
    - TCC_RELOCATE_AUTO : Allocate and manage memory internally
    - NULL              : return required memory size for the step below
    - memory address    : copy code to memory passed by the caller
-   returns -1 on error. */
-LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
+   returns -1 if error. */
 #define TCC_RELOCATE_AUTO (void*)1
 
 /* return symbol value or NULL if not found */
 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
 
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/tcc.c b/tcc.c
dissimilarity index 66%
index 7fabe8b..f4ff3f8 100644 (file)
--- a/tcc.c
+++ b/tcc.c
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef ONE_SOURCE
-#include "libtcc.c"
-#else
-#include "tcc.h"
-#endif
-
-static char **files;
-static int nb_files, nb_libraries;
-static int multiple_files;
-static int print_search_dirs;
-static int output_type;
-static int reloc_output;
-static char *outfile;
-static int do_bench = 0;
-static int gen_deps;
-static const char *deps_outfile;
-static const char *m_option;
-static CString linker_arg;
-
-#define TCC_OPTION_HAS_ARG 0x0001
-#define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
-
-static void help(void)
-{
-    printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
-           "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
-           "       tcc [options...] -run infile [arguments...]\n"
-           "General options:\n"
-           "  -c          compile only - generate an object file\n"
-           "  -o outfile  set output filename\n"
-           "  -run        run compiled source\n"
-           "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
-           "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
-           "  -w          disable all warnings\n"
-           "  -v          show version\n"
-           "  -vv         show included files (as sole argument: show search paths)\n"
-           "  -bench      show compilation statistics\n"
-           "Preprocessor options:\n"
-           "  -E          preprocess only\n"
-           "  -Idir       add include path 'dir'\n"
-           "  -Dsym[=val] define 'sym' with value 'val'\n"
-           "  -Usym       undefine 'sym'\n"
-           "  -nostdinc   do not use standard system include paths\n"
-           "Linker options:\n"
-           "  -Ldir       add library path 'dir'\n"
-           "  -llib       link with dynamic or static library 'lib'\n"
-           "  -Bdir       use 'dir' as tcc internal library and include path\n"
-           "  -nostdlib   do not link with standard crt and libraries\n"
-           "  -pthread    link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
-           "  -r          generate (relocatable) object file\n"
-           "  -rdynamic   export all global symbols to dynamic linker\n"
-           "  -shared     generate a shared library\n"
-           "  -soname     set name for shared library to be used at runtime\n"
-           "  -static     static linking\n"
-           "  -Wl,opt[=val]  set linker option 'opt' (see manual)\n"
-           "Debugger options:\n"
-           "  -g          generate runtime debug info\n"
-#ifdef CONFIG_TCC_BCHECK
-           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
-#endif
-#ifdef CONFIG_TCC_BACKTRACE
-           "  -bt N       show N callers in stack traces\n"
-#endif
-           "Misc options:\n"
-           "  -MD         generate target dependencies for make\n"
-           "  -MF depfile put generated dependencies here\n"
-           );
-}
-
-typedef struct TCCOption {
-    const char *name;
-    uint16_t index;
-    uint16_t flags;
-} TCCOption;
-
-enum {
-    TCC_OPTION_HELP,
-    TCC_OPTION_I,
-    TCC_OPTION_D,
-    TCC_OPTION_U,
-    TCC_OPTION_L,
-    TCC_OPTION_B,
-    TCC_OPTION_l,
-    TCC_OPTION_bench,
-    TCC_OPTION_bt,
-    TCC_OPTION_b,
-    TCC_OPTION_g,
-    TCC_OPTION_c,
-    TCC_OPTION_static,
-    TCC_OPTION_shared,
-    TCC_OPTION_soname,
-    TCC_OPTION_o,
-    TCC_OPTION_r,
-    TCC_OPTION_s,
-    TCC_OPTION_Wl,
-    TCC_OPTION_W,
-    TCC_OPTION_O,
-    TCC_OPTION_m,
-    TCC_OPTION_f,
-    TCC_OPTION_isystem,
-    TCC_OPTION_nostdinc,
-    TCC_OPTION_nostdlib,
-    TCC_OPTION_print_search_dirs,
-    TCC_OPTION_rdynamic,
-    TCC_OPTION_pedantic,
-    TCC_OPTION_pthread,
-    TCC_OPTION_run,
-    TCC_OPTION_v,
-    TCC_OPTION_w,
-    TCC_OPTION_pipe,
-    TCC_OPTION_E,
-    TCC_OPTION_MD,
-    TCC_OPTION_MF,
-    TCC_OPTION_x,
-};
-
-static const TCCOption tcc_options[] = {
-    { "h", TCC_OPTION_HELP, 0 },
-    { "-help", TCC_OPTION_HELP, 0 },
-    { "?", TCC_OPTION_HELP, 0 },
-    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
-    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
-    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
-    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
-    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
-    { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "bench", TCC_OPTION_bench, 0 },
-#ifdef CONFIG_TCC_BACKTRACE
-    { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
-#endif
-#ifdef CONFIG_TCC_BCHECK
-    { "b", TCC_OPTION_b, 0 },
-#endif
-    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "c", TCC_OPTION_c, 0 },
-    { "static", TCC_OPTION_static, 0 },
-    { "shared", TCC_OPTION_shared, 0 },
-    { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
-    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
-    { "pedantic", TCC_OPTION_pedantic, 0},
-    { "pthread", TCC_OPTION_pthread, 0},
-    { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "rdynamic", TCC_OPTION_rdynamic, 0 },
-    { "r", TCC_OPTION_r, 0 },
-    { "s", TCC_OPTION_s, 0 },
-    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
-    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
-    { "nostdinc", TCC_OPTION_nostdinc, 0 },
-    { "nostdlib", TCC_OPTION_nostdlib, 0 },
-    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 
-    { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "w", TCC_OPTION_w, 0 },
-    { "pipe", TCC_OPTION_pipe, 0},
-    { "E", TCC_OPTION_E, 0},
-    { "MD", TCC_OPTION_MD, 0},
-    { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
-    { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
-    { NULL, 0, 0 },
-};
-
-static int64_t getclock_us(void)
-{
-#ifdef _WIN32
-    struct _timeb tb;
-    _ftime(&tb);
-    return (tb.time * 1000LL + tb.millitm) * 1000LL;
-#else
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return tv.tv_sec * 1000000LL + tv.tv_usec;
-#endif
-}
-
-/* convert 'str' into an array of space separated strings */
-static int expand_args(char ***pargv, const char *str)
-{
-    const char *s1;
-    char **argv, *arg;
-    int argc, len;
-
-    argc = 0;
-    argv = NULL;
-    for(;;) {
-        while (is_space(*str))
-            str++;
-        if (*str == '\0')
-            break;
-        s1 = str;
-        while (*str != '\0' && !is_space(*str))
-            str++;
-        len = str - s1;
-        arg = tcc_malloc(len + 1);
-        memcpy(arg, s1, len);
-        arg[len] = '\0';
-        dynarray_add((void ***)&argv, &argc, arg);
-    }
-    *pargv = argv;
-    return argc;
-}
-
-/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-#ifdef _WIN32
-#include <process.h>
-static int execvp_win32(const char *prog, char **argv)
-{
-    int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
-    if (-1 == ret)
-        return ret;
-    cwait(&ret, ret, WAIT_CHILD);
-    exit(ret);
-}
-#define execvp execvp_win32
-#endif
-static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
-{
-    char child_path[4096], *child_name; const char *target;
-    switch (atoi(optarg)) {
-#ifdef TCC_TARGET_I386
-        case 32: break;
-        case 64: target = "x86_64";
-#else
-        case 64: break;
-        case 32: target = "i386";
-#endif
-            pstrcpy(child_path, sizeof child_path - 40, argv[0]);
-            child_name = tcc_basename(child_path);
-            strcpy(child_name, target);
-#ifdef TCC_TARGET_PE
-            strcat(child_name, "-win32");
-#endif
-            strcat(child_name, "-tcc");
-            if (strcmp(argv[0], child_path)) {
-                if (s->verbose > 0)
-                    printf("tcc: using '%s'\n", child_name), fflush(stdout);
-                execvp(argv[0] = child_path, argv);
-            }
-            tcc_error("'%s' not found", child_name);
-        case 0: /* ignore -march etc. */
-            break;
-        default:
-            tcc_warning("unsupported option \"-m%s\"", optarg);
-    }
-}
-#endif
-
-static void parse_option_D(TCCState *s1, const char *optarg)
-{
-    char *sym = tcc_strdup(optarg);
-    char *value = strchr(sym, '=');
-    if (value)
-        *value++ = '\0';
-    tcc_define_symbol(s1, sym, value);
-    tcc_free(sym);
-}
-
-static int parse_args(TCCState *s, int argc, char **argv)
-{
-    int optind;
-    const TCCOption *popt;
-    const char *optarg, *p1, *r1;
-    char *r;
-    int was_pthread;
-
-    was_pthread = 0; /* is set if commandline contains -pthread key */
-    optind = 0;
-    cstr_new(&linker_arg);
-
-    while (optind < argc) {
-
-        r = argv[optind++];
-        if (r[0] != '-' || r[1] == '\0') {
-            /* add a new file */
-            dynarray_add((void ***)&files, &nb_files, r);
-            if (!multiple_files) {
-                optind--;
-                /* argv[0] will be this file */
-                break;
-            }
-        } else {
-            /* find option in table (match only the first chars */
-            popt = tcc_options;
-            for(;;) {
-                p1 = popt->name;
-                if (p1 == NULL)
-                    tcc_error("invalid option -- '%s'", r);
-                r1 = r + 1;
-                for(;;) {
-                    if (*p1 == '\0')
-                        goto option_found;
-                    if (*r1 != *p1)
-                        break;
-                    p1++;
-                    r1++;
-                }
-                popt++;
-            }
-        option_found:
-            if (popt->flags & TCC_OPTION_HAS_ARG) {
-                if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
-                    optarg = r1;
-                } else {
-                    if (optind >= argc)
-                        tcc_error("argument to '%s' is missing", r);
-                    optarg = argv[optind++];
-                }
-            } else {
-                if (*r1 != '\0')
-                    return 0;
-                optarg = NULL;
-            }
-                
-            switch(popt->index) {
-            case TCC_OPTION_HELP:
-                return 0;
-
-            case TCC_OPTION_I:
-                if (tcc_add_include_path(s, optarg) < 0)
-                    tcc_error("too many include paths");
-                break;
-            case TCC_OPTION_D:
-                parse_option_D(s, optarg);
-                break;
-            case TCC_OPTION_U:
-                tcc_undefine_symbol(s, optarg);
-                break;
-            case TCC_OPTION_L:
-                tcc_add_library_path(s, optarg);
-                break;
-            case TCC_OPTION_B:
-                /* set tcc utilities path (mainly for tcc development) */
-                tcc_set_lib_path(s, optarg);
-                break;
-            case TCC_OPTION_l:
-                dynarray_add((void ***)&files, &nb_files, r);
-                nb_libraries++;
-                break;
-            case TCC_OPTION_pthread:
-                was_pthread = 1;
-                parse_option_D(s, "_REENTRANT");
-                break;
-            case TCC_OPTION_bench:
-                do_bench = 1;
-                break;
-#ifdef CONFIG_TCC_BACKTRACE
-            case TCC_OPTION_bt:
-                tcc_set_num_callers(atoi(optarg));
-                break;
-#endif
-#ifdef CONFIG_TCC_BCHECK
-            case TCC_OPTION_b:
-                s->do_bounds_check = 1;
-                s->do_debug = 1;
-                break;
-#endif
-            case TCC_OPTION_g:
-                s->do_debug = 1;
-                break;
-            case TCC_OPTION_c:
-                multiple_files = 1;
-                output_type = TCC_OUTPUT_OBJ;
-                break;
-            case TCC_OPTION_static:
-                s->static_link = 1;
-                break;
-            case TCC_OPTION_shared:
-                output_type = TCC_OUTPUT_DLL;
-                break;
-            case TCC_OPTION_soname:
-                s->soname = optarg;
-                break;
-            case TCC_OPTION_m:
-                m_option = optarg;
-                break;
-            case TCC_OPTION_o:
-                multiple_files = 1;
-                outfile = tcc_strdup(optarg);
-                break;
-            case TCC_OPTION_r:
-                /* generate a .o merging several output files */
-                reloc_output = 1;
-                output_type = TCC_OUTPUT_OBJ;
-                break;
-            case TCC_OPTION_isystem:
-                tcc_add_sysinclude_path(s, optarg);
-                break;
-            case TCC_OPTION_nostdinc:
-                s->nostdinc = 1;
-                break;
-            case TCC_OPTION_nostdlib:
-                s->nostdlib = 1;
-                break;
-            case TCC_OPTION_print_search_dirs:
-                print_search_dirs = 1;
-                break;
-            case TCC_OPTION_run:
-            {
-                int argc1;
-                char **argv1;
-                argc1 = expand_args(&argv1, optarg);
-                if (argc1 > 0) {
-                    parse_args(s, argc1, argv1);
-                }
-                multiple_files = 0;
-                output_type = TCC_OUTPUT_MEMORY;
-                break;
-            }
-            case TCC_OPTION_v:
-                do ++s->verbose; while (*optarg++ == 'v');
-                break;
-            case TCC_OPTION_f:
-                if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
-                    goto unsupported_option;
-                break;
-            case TCC_OPTION_W:
-                if (tcc_set_warning(s, optarg, 1) < 0 && 
-                    s->warn_unsupported)
-                    goto unsupported_option;
-                break;
-            case TCC_OPTION_w:
-                s->warn_none = 1;
-                break;
-            case TCC_OPTION_rdynamic:
-                s->rdynamic = 1;
-                break;
-            case TCC_OPTION_Wl:
-                if (linker_arg.size)
-                    --linker_arg.size, cstr_ccat(&linker_arg, ',');
-                cstr_cat(&linker_arg, optarg);
-                cstr_ccat(&linker_arg, '\0');
-                break;
-            case TCC_OPTION_E:
-                output_type = TCC_OUTPUT_PREPROCESS;
-                break;
-            case TCC_OPTION_MD:
-                gen_deps = 1;
-                break;
-            case TCC_OPTION_MF:
-                deps_outfile = optarg;
-                break;
-            case TCC_OPTION_O:
-            case TCC_OPTION_pedantic:
-            case TCC_OPTION_pipe:
-            case TCC_OPTION_s:
-            case TCC_OPTION_x:
-                /* ignored */
-                break;
-            default:
-                if (s->warn_unsupported) {
-                unsupported_option:
-                    tcc_warning("unsupported option '%s'", r);
-                }
-                break;
-            }
-        }
-    }
-    if (NULL != (r1 = tcc_set_linker(s, (char *) linker_arg.data, 1)))
-        tcc_error("unsupported linker option '%s'", r1);
-    /* fixme: these options could be different on your platform */
-    if (was_pthread && output_type != TCC_OUTPUT_OBJ) {
-        dynarray_add((void ***)&files, &nb_files, "-lpthread");
-        nb_libraries++;
-    }
-    return optind;
-}
-
-int main(int argc, char **argv)
-{
-    int i;
-    TCCState *s;
-    int nb_objfiles, ret, optind;
-    int64_t start_time = 0;
-    const char *default_file = NULL;
-
-    s = tcc_new();
-
-    output_type = TCC_OUTPUT_EXE;
-    outfile = NULL;
-    multiple_files = 1;
-    files = NULL;
-    nb_files = 0;
-    nb_libraries = 0;
-    reloc_output = 0;
-    print_search_dirs = 0;
-    m_option = NULL;
-    ret = 0;
-
-    optind = parse_args(s, argc - 1, argv + 1);
-
-#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
-    if (m_option)
-        exec_other_tcc(s, argv, m_option);
-#endif
-
-    if (print_search_dirs) {
-psd:
-        tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
-        tcc_display_info(s, 1);
-        return 0;
-    }
-
-    if (s->verbose)
-        tcc_display_info(s, 0);
-
-    if (optind == 0 || nb_files == 0) {
-        if (optind && s->verbose) {
-            if (s->verbose == 2)
-                goto psd;
-            return 0;
-        }
-        help();
-        return 1;
-    }
-
-    nb_objfiles = nb_files - nb_libraries;
-
-    /* if outfile provided without other options, we output an
-       executable */
-    if (outfile && output_type == TCC_OUTPUT_MEMORY)
-        output_type = TCC_OUTPUT_EXE;
-
-    /* check -c consistency : only single file handled. XXX: checks file type */
-    if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
-        /* accepts only a single input file */
-        if (nb_objfiles != 1)
-            tcc_error("cannot specify multiple files with -c");
-        if (nb_libraries != 0)
-            tcc_error("cannot specify libraries with -c");
-    }
-    
-    if (output_type == TCC_OUTPUT_PREPROCESS) {
-        if (!outfile) {
-            s->outfile = stdout;
-        } else {
-            s->outfile = fopen(outfile, "w");
-            if (!s->outfile)
-                tcc_error("could not open '%s'", outfile);
-        }
-    }
-
-    if (do_bench) {
-        start_time = getclock_us();
-    }
-
-    tcc_set_output_type(s, output_type);
-    s->reloc_output = reloc_output;
-
-    /* compile or add each files or library */
-    for(i = 0; i < nb_files && ret == 0; i++) {
-        const char *filename;
-
-        filename = files[i];
-        if (filename[0] == '-' && filename[1] == 'l') {
-            if (tcc_add_library(s, filename + 2) < 0) {
-                tcc_error_noabort("cannot find %s", filename);
-                ret = 1;
-            }
-        } else {
-            if (1 == s->verbose)
-                printf("-> %s\n", filename);
-            if (tcc_add_file(s, filename) < 0)
-                ret = 1;
-            if (!default_file)
-                default_file = filename;
-        }
-    }
-
-    /* free all files */
-    tcc_free(files);
-
-    if (0 == ret) {
-        if (do_bench)
-            tcc_print_stats(s, getclock_us() - start_time);
-
-        if (s->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_IS_NATIVE
-            ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
-#else
-            tcc_error_noabort("-run is not available in a cross compiler");
-#endif
-        } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
-             if (s->outfile)
-                fclose(s->outfile);
-        } else {
-            if (!outfile)
-                outfile = tcc_default_target(s, default_file);
-            ret = !!tcc_output_file(s, outfile);
-            /* dump collected dependencies */
-            if (gen_deps && !ret)
-                tcc_gen_makedeps(s, outfile, deps_outfile);
-        }
-    }
-
-    tcc_delete(s);
-    cstr_free(&linker_arg);
-    tcc_free(outfile);
-
-#ifdef MEM_DEBUG
-    if (do_bench) {
-        printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
-    }
-#endif
-    return ret;
-}
+/*
+ *  TCC - Tiny C Compiler
+ * 
+ *  Copyright (c) 2001-2004 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef ONE_SOURCE
+#include "libtcc.c"
+#else
+#include "tcc.h"
+#endif
+
+static void help(void)
+{
+    printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
+           "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
+           "       tcc [options...] -run infile [arguments...]\n"
+           "General options:\n"
+           "  -c          compile only - generate an object file\n"
+           "  -o outfile  set output filename\n"
+           "  -run        run compiled source\n"
+           "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
+           "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
+           "  -w          disable all warnings\n"
+           "  -v          show version\n"
+           "  -vv         show included files (as sole argument: show search paths)\n"
+           "  -bench      show compilation statistics\n"
+           "Preprocessor options:\n"
+           "  -E          preprocess only\n"
+           "  -Idir       add include path 'dir'\n"
+           "  -Dsym[=val] define 'sym' with value 'val'\n"
+           "  -Usym       undefine 'sym'\n"
+           "Linker options:\n"
+           "  -Ldir       add library path 'dir'\n"
+           "  -llib       link with dynamic or static library 'lib'\n"
+           "  -pthread    link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
+           "  -r          generate (relocatable) object file\n"
+           "  -rdynamic   export all global symbols to dynamic linker\n"
+           "  -shared     generate a shared library\n"
+           "  -soname     set name for shared library to be used at runtime\n"
+           "  -static     static linking\n"
+           "  -Wl,-opt[=val]  set linker option (see manual)\n"
+           "Debugger options:\n"
+           "  -g          generate runtime debug info\n"
+#ifdef CONFIG_TCC_BCHECK
+           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
+#endif
+#ifdef CONFIG_TCC_BACKTRACE
+           "  -bt N       show N callers in stack traces\n"
+#endif
+           "Misc options:\n"
+           "  -nostdinc   do not use standard system include paths\n"
+           "  -nostdlib   do not link with standard crt and libraries\n"
+           "  -Bdir       use 'dir' as tcc internal library and include path\n"
+           "  -MD         generate target dependencies for make\n"
+           "  -MF depfile put generated dependencies here\n"
+           );
+}
+
+/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
+#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
+#ifdef _WIN32
+#include <process.h>
+static int execvp_win32(const char *prog, char **argv)
+{
+    int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
+    if (-1 == ret)
+        return ret;
+    cwait(&ret, ret, WAIT_CHILD);
+    exit(ret);
+}
+#define execvp execvp_win32
+#endif
+static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
+{
+    char child_path[4096], *child_name; const char *target;
+    switch (atoi(optarg)) {
+#ifdef TCC_TARGET_I386
+        case 32: break;
+        case 64: target = "x86_64";
+#else
+        case 64: break;
+        case 32: target = "i386";
+#endif
+            pstrcpy(child_path, sizeof child_path - 40, argv[0]);
+            child_name = tcc_basename(child_path);
+            strcpy(child_name, target);
+#ifdef TCC_TARGET_PE
+            strcat(child_name, "-win32");
+#endif
+            strcat(child_name, "-tcc");
+            if (strcmp(argv[0], child_path)) {
+                if (s->verbose > 0)
+                    printf("tcc: using '%s'\n", child_name), fflush(stdout);
+                execvp(argv[0] = child_path, argv);
+            }
+            tcc_error("'%s' not found", child_name);
+        case 0: /* ignore -march etc. */
+            break;
+        default:
+            tcc_warning("unsupported option \"-m%s\"", optarg);
+    }
+}
+#else
+#define exec_other_tcc(s, argv, optarg)
+#endif
+
+static void gen_makedeps(TCCState *s, const char *target, const char *filename)
+{
+    FILE *depout;
+    char buf[1024], *ext;
+    int i;
+
+    if (!filename) {
+        /* compute filename automatically
+         * dir/file.o -> dir/file.d             */
+        pstrcpy(buf, sizeof(buf), target);
+        ext = tcc_fileextension(buf);
+        pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
+        filename = buf;
+    }
+
+    if (s->verbose)
+        printf("<- %s\n", filename);
+
+    /* XXX return err codes instead of error() ? */
+    depout = fopen(filename, "w");
+    if (!depout)
+        tcc_error("could not open '%s'", filename);
+
+    fprintf(depout, "%s : \\\n", target);
+    for (i=0; i<s->nb_target_deps; ++i)
+        fprintf(depout, " %s \\\n", s->target_deps[i]);
+    fprintf(depout, "\n");
+    fclose(depout);
+}
+
+static char *default_outputfile(TCCState *s, const char *first_file)
+{
+    char buf[1024];
+    char *ext;
+    const char *name = "a";
+
+    if (first_file && strcmp(first_file, "-"))
+        name = tcc_basename(first_file);
+    pstrcpy(buf, sizeof(buf), name);
+    ext = tcc_fileextension(buf);
+#ifdef TCC_TARGET_PE
+    if (s->output_type == TCC_OUTPUT_DLL)
+        strcpy(ext, ".dll");
+    else
+    if (s->output_type == TCC_OUTPUT_EXE)
+        strcpy(ext, ".exe");
+    else
+#endif
+    if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) ||
+          (s->output_type == TCC_OUTPUT_PREPROCESS) )
+        && *ext)
+        strcpy(ext, ".o");
+    else
+        strcpy(buf, "a.out");
+
+    return tcc_strdup(buf);
+}
+
+static void print_paths(const char *msg, char **paths, int nb_paths)
+{
+    int i;
+    printf("%s:\n%s", msg, nb_paths ? "" : "  -\n");
+    for(i = 0; i < nb_paths; i++)
+        printf("  %s\n", paths[i]);
+}
+
+static void display_info(TCCState *s, int what)
+{
+    switch (what) {
+    case 0:
+        printf("tcc version %s ("
+#ifdef TCC_TARGET_I386
+        "i386"
+# ifdef TCC_TARGET_PE
+        " Win32"
+# endif
+#elif defined TCC_TARGET_X86_64
+        "x86-64"
+# ifdef TCC_TARGET_PE
+        " Win64"
+# endif
+#elif defined TCC_TARGET_ARM
+        "ARM"
+# ifdef TCC_ARM_HARDFLOAT
+        " Hard Float"
+# endif
+# ifdef TCC_TARGET_PE
+        " WinCE"
+# endif
+#endif
+#ifndef TCC_TARGET_PE
+# ifdef __linux
+        " Linux"
+# endif
+#endif
+        ")\n", TCC_VERSION);
+        break;
+    case 1:
+        printf("install: %s/\n", s->tcc_lib_path);
+        /* print_paths("programs", NULL, 0); */
+        print_paths("crt", s->crt_paths, s->nb_crt_paths);
+        print_paths("libraries", s->library_paths, s->nb_library_paths);
+        print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
+        break;
+    }
+}
+
+static int64_t getclock_us(void)
+{
+#ifdef _WIN32
+    struct _timeb tb;
+    _ftime(&tb);
+    return (tb.time * 1000LL + tb.millitm) * 1000LL;
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * 1000000LL + tv.tv_usec;
+#endif
+}
+
+int main(int argc, char **argv)
+{
+    TCCState *s;
+    int ret, optind, i, bench;
+    int64_t start_time = 0;
+    const char *first_file = NULL;
+
+    s = tcc_new();
+    s->output_type = TCC_OUTPUT_EXE;
+
+    optind = tcc_parse_args(s, argc - 1, argv + 1);
+
+    if (optind == 0) {
+        help();
+        return 1;
+    }
+
+    if (s->option_m)
+        exec_other_tcc(s, argv, s->option_m);
+
+    if (s->verbose)
+        display_info(s, 0);
+
+    if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) {
+        tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+        display_info(s, 1);
+        return 0;
+    }
+
+    if (s->verbose && optind == 1)
+        return 0;
+
+    if (s->nb_files == 0)
+        tcc_error("no input files\n");
+
+    /* check -c consistency : only single file handled. XXX: checks file type */
+    if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
+        if (s->nb_libraries != 0)
+            tcc_error("cannot specify libraries with -c");
+        /* accepts only a single input file */
+        if (s->nb_files != 1)
+            tcc_error("cannot specify multiple files with -c");
+    }
+    
+    if (s->output_type == TCC_OUTPUT_PREPROCESS) {
+        if (!s->outfile) {
+            s->ppfp = stdout;
+        } else {
+            s->ppfp = fopen(s->outfile, "w");
+            if (!s->ppfp)
+                tcc_error("could not write '%s'", s->outfile);
+        }
+    }
+
+    bench = s->do_bench;
+    if (bench)
+        start_time = getclock_us();
+
+    tcc_set_output_type(s, s->output_type);
+
+    /* compile or add each files or library */
+    for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
+        const char *filename;
+
+        filename = s->files[i];
+        if (filename[0] == '-' && filename[1] == 'l') {
+            if (tcc_add_library(s, filename + 2) < 0) {
+                tcc_error_noabort("cannot find '%s'", filename);
+                ret = 1;
+            }
+        } else {
+            if (1 == s->verbose)
+                printf("-> %s\n", filename);
+            if (tcc_add_file(s, filename) < 0)
+                ret = 1;
+            if (!first_file)
+                first_file = filename;
+        }
+    }
+
+    if (0 == ret) {
+        if (bench)
+            tcc_print_stats(s, getclock_us() - start_time);
+
+        if (s->output_type == TCC_OUTPUT_MEMORY) {
+#ifdef TCC_IS_NATIVE
+            ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
+#else
+            tcc_error_noabort("-run is not available in a cross compiler");
+            ret = 1;
+#endif
+        } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
+             if (s->outfile)
+                fclose(s->ppfp);
+        } else {
+            if (!s->outfile)
+                s->outfile = default_outputfile(s, first_file);
+            ret = !!tcc_output_file(s, s->outfile);
+            /* dump collected dependencies */
+            if (s->gen_deps && !ret)
+                gen_makedeps(s, s->outfile, s->deps_outfile);
+        }
+    }
+
+    tcc_delete(s);
+    if (bench)
+        tcc_memstats();
+    return ret;
+}
diff --git a/tcc.h b/tcc.h
index 460c417..fa09434 100644 (file)
--- a/tcc.h
+++ b/tcc.h
 #include "config.h"
 
 #ifdef CONFIG_TCCBOOT
-
 #include "tccboot.h"
 #define CONFIG_TCC_STATIC
-
 #else
 
 #include <stdlib.h>
 
 #endif /* !CONFIG_TCCBOOT */
 
-#ifndef PAGESIZE
-#define PAGESIZE 4096
-#endif
-
 #ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#ifndef SA_SIGINFO
-#define SA_SIGINFO 0x00000004u
+# define O_BINARY 0
 #endif
 
 #include "elf.h"
@@ -516,82 +506,22 @@ struct sym_attr {
 };
 
 struct TCCState {
-    unsigned output_type    : 8;
-    unsigned reloc_output   : 1;
-    BufferedFile **include_stack_ptr;
-    int *ifdef_stack_ptr;
-
-    /* include file handling */
-    char **include_paths;
-    int nb_include_paths;
-    char **sysinclude_paths;
-    int nb_sysinclude_paths;
-    CachedInclude **cached_includes;
-    int nb_cached_includes;
-
-    char **library_paths;
-    int nb_library_paths;
-    char **crt_paths;
-    int nb_crt_paths;
-
-    /* array of all loaded dlls (including those referenced by loaded
-       dlls) */
-    DLLReference **loaded_dlls;
-    int nb_loaded_dlls;
-
-    /* sections */
-    Section **sections;
-    int nb_sections; /* number of sections, including first dummy section */
-
-    Section **priv_sections;
-    int nb_priv_sections; /* number of private sections */
-
-    /* got & plt handling */
-    Section *got;
-    Section *plt;
-    struct sym_attr *sym_attrs;
-    int nb_sym_attrs;
-    /* give the correspondance from symtab indexes to dynsym indexes */
-    int *symtab_to_dynsym;
-
-    /* temporary dynamic symbol sections (for dll loading) */
-    Section *dynsymtab_section;
-    /* exported dynamic symbol section */
-    Section *dynsym;
-
-    /* copy of the gobal symtab_section variable */
-    Section *symtab;
 
+    int verbose; /* if true, display some information during compilation */
     int nostdinc; /* if true, no standard headers are added */
     int nostdlib; /* if true, no standard libraries are added */
     int nocommon; /* if true, do not use common symbols for .bss data */
+    int static_link; /* if true, static linking is performed */
+    int rdynamic; /* if true, all symbols are exported */
+    int symbolic; /* if true, resolve symbols in the current module first */
+    int alacarte_link; /* if true, only link in referenced objects from archive */
 
-    /* if true, static linking is performed */
-    int static_link;
-
-    /* soname as specified on the command line (-soname) */
-    const char *soname;
-    /* rpath as specified on the command line (-Wl,-rpath=) */
-    const char *rpath;
-
-    /* if true, all symbols are exported */
-    int rdynamic;
-
-    /* if true, resolve symbols in the current module first (-Wl,Bsymbolic) */
-    int symbolic;
-
-    /* if true, only link in referenced objects from archive */
-    int alacarte_link;
-
-    /* address of text section */
-    addr_t text_addr;
-    int has_text_addr;
+    char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
+    char *soname; /* as specified on the command line (-soname) */
+    char *rpath; /* as specified on the command line (-Wl,-rpath=) */
 
-    /* symbols to call at load-time / unload-time */
-    const char *init_symbol;
-    const char *fini_symbol;
-    
+    /* output type, see TCC_OUTPUT_XXX */
+    int output_type;
     /* output format, see TCC_OUTPUT_FORMAT_xxx */
     int output_format;
 
@@ -606,16 +536,43 @@ struct TCCState {
     int warn_none;
     int warn_implicit_function_declaration;
 
-    /* display some information during compilation */
-    int verbose;
     /* compile with debug symbol (and use them if error during execution) */
     int do_debug;
 #ifdef CONFIG_TCC_BCHECK
     /* compile with built-in memory and bounds checker */
     int do_bounds_check;
 #endif
-    /* give the path of the tcc libraries */
-    char *tcc_lib_path;
+
+    addr_t text_addr; /* address of text section */
+    int has_text_addr;
+
+    unsigned long section_align; /* section alignment */
+
+    char *init_symbol; /* symbols to call at load-time (not used currently) */
+    char *fini_symbol; /* symbols to call at unload-time (not used currently) */
+    
+#ifdef TCC_TARGET_I386
+    int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
+#endif
+
+    /* array of all loaded dlls (including those referenced by loaded dlls) */
+    DLLReference **loaded_dlls;
+    int nb_loaded_dlls;
+
+    /* include paths */
+    char **include_paths;
+    int nb_include_paths;
+
+    char **sysinclude_paths;
+    int nb_sysinclude_paths;
+
+    /* library paths */
+    char **library_paths;
+    int nb_library_paths;
+
+    /* crt?.o object path */
+    char **crt_paths;
+    int nb_crt_paths;
 
     /* error handling */
     void *error_opaque;
@@ -624,72 +581,101 @@ struct TCCState {
     jmp_buf error_jmp_buf;
     int nb_errors;
 
-    /* tiny assembler state */
-    Sym *asm_labels;
+    /* output file for preprocessing (-E) */
+    FILE *ppfp;
 
-    /* see include_stack_ptr */
+    /* for -MD/-MF: collected dependencies for this compilation */
+    char **target_deps;
+    int nb_target_deps;
+
+    /* compilation */
     BufferedFile *include_stack[INCLUDE_STACK_SIZE];
+    BufferedFile **include_stack_ptr;
 
-    /* see ifdef_stack_ptr */
     int ifdef_stack[IFDEF_STACK_SIZE];
+    int *ifdef_stack_ptr;
 
-    /* see cached_includes */
+    /* included files enclosed with #ifndef MACRO */
     int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
+    CachedInclude **cached_includes;
+    int nb_cached_includes;
 
-    /* pack stack */
+    /* #pragma pack stack */
     int pack_stack[PACK_STACK_SIZE];
     int *pack_stack_ptr;
 
-    /* output file for preprocessing */
-    FILE *outfile;
-
-    /* automatically collected dependencies for this compilation */
-    char **target_deps;
-    int nb_target_deps;
-
-    /* for tcc_relocate */
-    int runtime_added;
-    void *runtime_mem;
-#ifdef HAVE_SELINUX
-    void *write_mem;
-    unsigned long mem_size;
-#endif
-
+    /* inline functions are stored as token lists and compiled last
+       only if referenced */
     struct InlineFunc **inline_fns;
     int nb_inline_fns;
 
-#ifdef TCC_TARGET_I386
-    int seg_size;
-#endif
+    /* sections */
+    Section **sections;
+    int nb_sections; /* number of sections, including first dummy section */
+
+    Section **priv_sections;
+    int nb_priv_sections; /* number of private sections */
+
+    /* got & plt handling */
+    Section *got;
+    Section *plt;
+    struct sym_attr *sym_attrs;
+    int nb_sym_attrs;
+    /* give the correspondance from symtab indexes to dynsym indexes */
+    int *symtab_to_dynsym;
 
-    /* section alignment */
-    unsigned long section_align;
+    /* temporary dynamic symbol sections (for dll loading) */
+    Section *dynsymtab_section;
+    /* exported dynamic symbol section */
+    Section *dynsym;
+    /* copy of the gobal symtab_section variable */
+    Section *symtab;
+    /* tiny assembler state */
+    Sym *asm_labels;
 
 #ifdef TCC_TARGET_PE
     /* PE info */
     int pe_subsystem;
-    unsigned long pe_file_align;
-    unsigned long pe_stack_size;
-#ifdef TCC_TARGET_X86_64
+    unsigned pe_file_align;
+    unsigned pe_stack_size;
+# ifdef TCC_TARGET_X86_64
     Section *uw_pdata;
     int uw_sym;
     unsigned uw_offs;
-#endif
+# endif
 #endif
 
-#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE \
- && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
+#ifdef TCC_IS_NATIVE
+    /* for tcc_relocate */
+    void *runtime_mem;
+# ifdef HAVE_SELINUX
+    void *write_mem;
+    unsigned long mem_size;
+# endif
+# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
     /* write PLT and GOT here */
     char *runtime_plt_and_got;
-    unsigned int runtime_plt_and_got_offset;
-# define TCC_HAS_RUNTIME_PLTGOT
+    unsigned runtime_plt_and_got_offset;
+#  define TCC_HAS_RUNTIME_PLTGOT
+# endif
 #endif
+
+    /* used by main and tcc_parse_args only */
+    char **files; /* files seen on command line */
+    int nb_files; /* number thereof */
+    int nb_libraries; /* number of libs thereof */
+    char *outfile; /* output filename */
+    char *option_m; /* only -m32/-m64 handled */
+    int print_search_dirs; /* option */
+    int option_r; /* option -r */
+    int do_bench; /* option -bench */
+    int gen_deps; /* option -MD  */
+    char *deps_outfile; /* option -MF */
 };
 
 /* The current value can be: */
-#define VT_VALMASK   0x003f
-#define VT_CONST     0x0030  /* constant in vc
-                              (must be first non register value) */
+#define VT_VALMASK   0x003f  /* mask for value location, register or: */
+#define VT_CONST     0x0030  /* constant in vc (must be first non register value) */
 #define VT_LLOCAL    0x0031  /* lvalue, offset on stack */
 #define VT_LOCAL     0x0032  /* offset on stack */
 #define VT_CMP       0x0033  /* the value is stored in processor flags (in vc) */
@@ -710,29 +696,29 @@ struct TCCState {
 #define VT_LVAL_TYPE     (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
 
 /* types */
-#define VT_INT        0  /* integer type */
-#define VT_BYTE       1  /* signed byte type */
-#define VT_SHORT      2  /* short type */
-#define VT_VOID       3  /* void type */
-#define VT_PTR        4  /* pointer */
-#define VT_ENUM       5  /* enum definition */
-#define VT_FUNC       6  /* function type */
-#define VT_STRUCT     7  /* struct/union definition */
-#define VT_FLOAT      8  /* IEEE float */
-#define VT_DOUBLE     9  /* IEEE double */
-#define VT_LDOUBLE   10  /* IEEE long double */
-#define VT_BOOL      11  /* ISOC99 boolean type */
-#define VT_LLONG     12  /* 64 bit integer */
-#define VT_LONG      13  /* long integer (NEVER USED as type, only
-                            during parsing) */
-#define VT_BTYPE      0x000f /* mask for basic type */
-#define VT_UNSIGNED   0x0010  /* unsigned type */
-#define VT_ARRAY      0x0020  /* array type (also has VT_PTR) */
-#define VT_VLA        0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
-#define VT_BITFIELD   0x0040  /* bitfield modifier */
-#define VT_CONSTANT   0x0800  /* const modifier */
-#define VT_VOLATILE   0x1000  /* volatile modifier */
-#define VT_SIGNED     0x2000  /* signed type */
+#define VT_BTYPE       0x000f  /* mask for basic type */
+#define VT_INT              0  /* integer type */
+#define VT_BYTE             1  /* signed byte type */
+#define VT_SHORT            2  /* short type */
+#define VT_VOID             3  /* void type */
+#define VT_PTR              4  /* pointer */
+#define VT_ENUM             5  /* enum definition */
+#define VT_FUNC             6  /* function type */
+#define VT_STRUCT           7  /* struct/union definition */
+#define VT_FLOAT            8  /* IEEE float */
+#define VT_DOUBLE           9  /* IEEE double */
+#define VT_LDOUBLE         10  /* IEEE long double */
+#define VT_BOOL            11  /* ISOC99 boolean type */
+#define VT_LLONG           12  /* 64 bit integer */
+#define VT_LONG            13  /* long integer (NEVER USED as type, only
+                                  during parsing) */
+#define VT_UNSIGNED    0x0010  /* unsigned type */
+#define VT_ARRAY       0x0020  /* array type (also has VT_PTR) */
+#define VT_BITFIELD    0x0040  /* bitfield modifier */
+#define VT_CONSTANT    0x0800  /* const modifier */
+#define VT_VOLATILE    0x1000  /* volatile modifier */
+#define VT_SIGNED      0x2000  /* signed type */
+#define VT_VLA     0x00020000  /* VLA type (also has VT_PTR and VT_ARRAY) */
 
 /* storage */
 #define VT_EXTERN  0x00000080  /* extern definition */
@@ -741,13 +727,13 @@ struct TCCState {
 #define VT_INLINE  0x00000400  /* inline definition */
 #define VT_IMPORT  0x00004000  /* win32: extern data imported from dll */
 #define VT_EXPORT  0x00008000  /* win32: data exported from dll */
-#define VT_WEAK    0x00010000  /* win32: data exported from dll */
+#define VT_WEAK    0x00010000  /* weak symbol */
 
-#define VT_STRUCT_SHIFT 18   /* shift for bitfield shift values */
+#define VT_STRUCT_SHIFT 18     /* shift for bitfield shift values (max: 32 - 2*6) */
 
 /* type mask (except storage) */
 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK)
-#define VT_TYPE    (~(VT_STORAGE))
+#define VT_TYPE (~(VT_STORAGE))
 
 /* token values */
 
@@ -999,6 +985,11 @@ ST_DATA int tcc_ext;
 /* XXX: get rid of this ASAP */
 ST_DATA struct TCCState *tcc_state;
 
+#ifdef MEM_DEBUG
+ST_DATA int mem_cur_size;
+ST_DATA int mem_max_size;
+#endif
+
 #define AFF_PRINT_ERROR     0x0001 /* print error if file not found */
 #define AFF_REFERENCED_DLL  0x0002 /* load a referenced dll from another dll */
 #define AFF_PREPROCESS      0x0004 /* preprocess file */
@@ -1020,19 +1011,19 @@ PUB_FUNC char *tcc_strdup(const char *str);
 #undef strdup
 #define strdup(s) use_tcc_strdup(s)
 PUB_FUNC void tcc_memstats(void);
-PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
-PUB_FUNC void dynarray_reset(void *pp, int *n);
 PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
 PUB_FUNC void tcc_error(const char *fmt, ...);
 PUB_FUNC void tcc_warning(const char *fmt, ...);
 
 /* other utilities */
-PUB_FUNC void cstr_ccat(CString *cstr, int ch);
-PUB_FUNC void cstr_cat(CString *cstr, const char *str);
-PUB_FUNC void cstr_wccat(CString *cstr, int ch);
-PUB_FUNC void cstr_new(CString *cstr);
-PUB_FUNC void cstr_free(CString *cstr);
-PUB_FUNC void cstr_reset(CString *cstr);
+ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
+ST_FUNC void dynarray_reset(void *pp, int *n);
+ST_FUNC void cstr_ccat(CString *cstr, int ch);
+ST_FUNC void cstr_cat(CString *cstr, const char *str);
+ST_FUNC void cstr_wccat(CString *cstr, int ch);
+ST_FUNC void cstr_new(CString *cstr);
+ST_FUNC void cstr_free(CString *cstr);
+ST_FUNC void cstr_reset(CString *cstr);
 
 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
 ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
@@ -1059,15 +1050,10 @@ ST_FUNC void tcc_close(void);
 
 ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
 ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
-#ifndef TCC_TARGET_PE
 ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
-#endif
 
-PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value);
 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time);
-PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file);
-PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename);
-PUB_FUNC void tcc_display_info(TCCState *s, int what);
+PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
 
 /* ------------ tccpp.c ------------ */
 
@@ -1208,6 +1194,10 @@ ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsign
 
 /* ------------ tccelf.c ------------ */
 
+#define TCC_OUTPUT_FORMAT_ELF    0 /* default output format: ELF */
+#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
+#define TCC_OUTPUT_FORMAT_COFF   2 /* COFF */
+
 #define ARMAG  "!<arch>\012"    /* For COFF and a.out archives */
 
 typedef struct {
@@ -1259,11 +1249,11 @@ ST_FUNC int handle_eob(void);
 
 /* ------------ xxx-gen.c ------------ */
 
-ST_DATA const int reg_classes[NB_REGS
 #ifdef TCC_TARGET_X86_64
-    + 7
+ST_DATA const int reg_classes[NB_REGS+7];
+#else
+ST_DATA const int reg_classes[NB_REGS];
 #endif
-];
 
 ST_FUNC void gsym_addr(int t, int a);
 ST_FUNC void gsym(int t);
@@ -1329,7 +1319,6 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
 /* ------------ tccasm.c ------------ */
 ST_FUNC void asm_instr(void);
 ST_FUNC void asm_global_instr(void);
-
 #ifdef CONFIG_TCC_ASM
 ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
@@ -1343,14 +1332,13 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
 ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
 ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
 #endif
+
 /* ------------ tccpe.c -------------- */
 #ifdef TCC_TARGET_PE
 ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
 ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
 ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
-/* tiny_impdef.c */
-ST_FUNC char *get_export_names(FILE *fp);
 #ifdef TCC_TARGET_X86_64
 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
 #endif
@@ -1366,7 +1354,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
 /* dummy function for profiling */
 ST_FUNC void *dlopen(const char *filename, int flag);
 ST_FUNC void dlclose(void *p);
-//ST_FUNC const char *dlerror(void);
+ST_FUNC const char *dlerror(void);
 ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
 #elif !defined _WIN32
 ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
@@ -1376,7 +1364,7 @@ ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
 ST_DATA int rt_num_callers;
 ST_DATA const char **rt_bound_error_msg;
 ST_DATA void *rt_prog_main;
-PUB_FUNC void tcc_set_num_callers(int n);
+ST_FUNC void tcc_set_num_callers(int n);
 #endif
 #endif
 
index 41bd1a5..500ea18 100644 (file)
--- a/tccelf.c
+++ b/tccelf.c
@@ -240,7 +240,7 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
             } else if (s == tcc_state->dynsymtab_section) {
                 /* we accept that two DLL define the same symbol */
             } else {
-#if 1
+#if 0
                 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
                        sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
 #endif
diff --git a/tccpe.c b/tccpe.c
index 120dc4e..79be6f3 100644 (file)
--- a/tccpe.c
+++ b/tccpe.c
@@ -1505,10 +1505,10 @@ static int add_dllref(TCCState *s1, const char *dllname)
 
 /* ------------------------------------------------------------- */
 
-static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
+static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
 {
-    fseek(fp, offset, 0);
-    return len == fread(buffer, 1, len, fp);
+    lseek(fd, offset, SEEK_SET);
+    return len == read(fd, buffer, len);
 }
 
 /* -------------------------------------------------------------
@@ -1516,7 +1516,7 @@ static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
  *  as generated by 'windres.exe -O coff ...'.
  */
 
-static int pe_load_res(TCCState *s1, FILE *fp)
+static int pe_load_res(TCCState *s1, int fd)
 {
     struct pe_rsrc_header hdr;
     Section *rsrc_section;
@@ -1524,7 +1524,7 @@ static int pe_load_res(TCCState *s1, FILE *fp)
     BYTE *ptr;
     unsigned offs;
 
-    if (!read_mem(fp, 0, &hdr, sizeof hdr))
+    if (!read_mem(fd, 0, &hdr, sizeof hdr))
         goto quit;
 
     if (hdr.filehdr.Machine != 0x014C
@@ -1535,13 +1535,13 @@ static int pe_load_res(TCCState *s1, FILE *fp)
     rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
     ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
     offs = hdr.sectionhdr.PointerToRawData;
-    if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
+    if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
         goto quit;
     offs = hdr.sectionhdr.PointerToRelocations;
     for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
     {
         struct pe_rsrc_reloc rel;
-        if (!read_mem(fp, offs, &rel, sizeof rel))
+        if (!read_mem(fd, offs, &rel, sizeof rel))
             goto quit;
         // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
         if (rel.type != 7) /* DIR32NB */
@@ -1571,22 +1571,26 @@ static char *trimback(char *a, char *e)
     return a;
 }
 
-static char *get_line(char *line, int size, FILE *fp)
+static char *get_line(char *line, int size, int fd)
 {
-    if (NULL == fgets(line, size, fp))
+    int n;
+    for (n = 0; n < size - 1; )
+        if (read(fd, line + n, 1) < 1 || line[n++] == '\n')
+            break;
+    if (0 == n)
         return NULL;
-    trimback(line, strchr(line, 0));
+    trimback(line, line + n);
     return trimfront(line);
 }
 
 /* ------------------------------------------------------------- */
-static int pe_load_def(TCCState *s1, FILE *fp)
+static int pe_load_def(TCCState *s1, int fd)
 {
     int state = 0, ret = -1, dllindex = 0;
     char line[400], dllname[80], *p;
 
     for (;;) {
-        p = get_line(line, sizeof line, fp);
+        p = get_line(line, sizeof line, fd);
         if (NULL == p)
             break;
         if (0 == *p || ';' == *p)
@@ -1623,11 +1627,11 @@ quit:
 #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
 #include "win32/tools/tiny_impdef.c"
 
-static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
+static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
 {
     char *p, *q;
     int index;
-    p = get_export_names(fp);
+    p = get_export_names(fd);
     if (!p)
         return -1;
     index = add_dllref(s1, dllname);
@@ -1640,18 +1644,14 @@ static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
 /* ------------------------------------------------------------- */
 ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
 {
-    FILE *fp = fdopen(dup(fd), "rb");
     int ret = -1;
     char buf[10];
-    if (fp) {
-        if (0 == strcmp(tcc_fileextension(filename), ".def"))
-            ret = pe_load_def(s1, fp);
-        else if (pe_load_res(s1, fp) == 0)
-            ret = 0;
-        else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
-            ret = pe_load_dll(s1, tcc_basename(filename), fp);
-        fclose(fp);
-    }
+    if (0 == strcmp(tcc_fileextension(filename), ".def"))
+        ret = pe_load_def(s1, fd);
+    else if (pe_load_res(s1, fd) == 0)
+        ret = 0;
+    else if (read_mem(fd, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
+        ret = pe_load_dll(s1, tcc_basename(filename), fd);
     return ret;
 }
 
@@ -1723,7 +1723,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
 #define PE_STDSYM(n,s) "_" n s
 #endif
 
-static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
+static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
 {
     const char *start_symbol;
     ADDR3264 addr = 0;
@@ -1762,15 +1762,17 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
 
     if (0 == s1->nostdlib) {
         static const char *libs[] = {
-            "tcc1", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
+            "libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
         };
         const char **pp, *p;
         for (pp = libs; 0 != (p = *pp); ++pp) {
             if (0 == *p) {
                 if (PE_DLL != pe_type && PE_GUI != pe_type)
                     break;
-            } else if (tcc_add_library(s1, p) < 0)
+            } else if (pp == libs ? tcc_add_dll(s1, p, 0) : tcc_add_library(s1, p)) {
                 tcc_error_noabort("cannot find library: %s", p);
+                break;
+            }
         }
     }
 
@@ -1802,7 +1804,7 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
     pe.s1 = s1;
 
     tcc_add_bcheck(s1);
-    pe_add_runtime_ex(s1, &pe);
+    pe_add_runtime(s1, &pe);
     relocate_common_syms(); /* assign bss adresses */
     tcc_add_linker_symbols(s1);
 
diff --git a/tccpp.c b/tccpp.c
index c0c7aec..ac01d83 100644 (file)
--- a/tccpp.c
+++ b/tccpp.c
@@ -118,7 +118,7 @@ static void cstr_realloc(CString *cstr, int new_size)
 }
 
 /* add a byte */
-PUB_FUNC void cstr_ccat(CString *cstr, int ch)
+ST_FUNC void cstr_ccat(CString *cstr, int ch)
 {
     int size;
     size = cstr->size + 1;
@@ -128,7 +128,7 @@ PUB_FUNC void cstr_ccat(CString *cstr, int ch)
     cstr->size = size;
 }
 
-PUB_FUNC void cstr_cat(CString *cstr, const char *str)
+ST_FUNC void cstr_cat(CString *cstr, const char *str)
 {
     int c;
     for(;;) {
@@ -141,7 +141,7 @@ PUB_FUNC void cstr_cat(CString *cstr, const char *str)
 }
 
 /* add a wide char */
-PUB_FUNC void cstr_wccat(CString *cstr, int ch)
+ST_FUNC void cstr_wccat(CString *cstr, int ch)
 {
     int size;
     size = cstr->size + sizeof(nwchar_t);
@@ -151,20 +151,20 @@ PUB_FUNC void cstr_wccat(CString *cstr, int ch)
     cstr->size = size;
 }
 
-PUB_FUNC void cstr_new(CString *cstr)
+ST_FUNC void cstr_new(CString *cstr)
 {
     memset(cstr, 0, sizeof(CString));
 }
 
 /* free string and reset it to NULL */
-PUB_FUNC void cstr_free(CString *cstr)
+ST_FUNC void cstr_free(CString *cstr)
 {
     tcc_free(cstr->data_allocated);
     cstr_new(cstr);
 }
 
 /* reset string to empty */
-PUB_FUNC void cstr_reset(CString *cstr)
+ST_FUNC void cstr_reset(CString *cstr)
 {
     cstr->size = 0;
 }
@@ -3112,17 +3112,17 @@ print_line:
                   : ""
                   ;
                 iptr = iptr_new;
-                fprintf(s1->outfile, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
+                fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
             } else {
                 while (d)
-                    fputs("\n", s1->outfile), --d;
+                    fputs("\n", s1->ppfp), --d;
             }
             line_ref = (file_ref = file)->line_num;
             token_seen = tok != TOK_LINEFEED;
             if (!token_seen)
                 continue;
         }
-        fputs(get_tok_str(tok, &tokc), s1->outfile);
+        fputs(get_tok_str(tok, &tokc), s1->ppfp);
     }
     free_defines(define_start);
     return 0;
index b647962..50178a8 100644 (file)
--- a/tccrun.c
+++ b/tccrun.c
@@ -54,33 +54,36 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
     if (TCC_RELOCATE_AUTO != ptr)
         return tcc_relocate_ex(s1, ptr);
 
+    ret = tcc_relocate_ex(s1, NULL);
+    if (ret < 0)
+        return ret;
+
 #ifdef HAVE_SELINUX
-    /* Use mmap instead of malloc for Selinux
-    Ref http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
-    char tmpfname[] = "/tmp/.tccrunXXXXXX";
-    int fd = mkstemp (tmpfname);
-    if ((ret= tcc_relocate_ex(s1,NULL)) < 0)return -1;
-    s1->mem_size=ret;
-    unlink (tmpfname); ftruncate (fd, s1->mem_size);
-    s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
-        MAP_SHARED, fd, 0);
-    if(s1->write_mem == MAP_FAILED){
-        tcc_error("/tmp not writeable");
-        return -1;
-    }
-    s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
-        MAP_SHARED, fd, 0);
-    if(s1->runtime_mem == MAP_FAILED){
-        tcc_error("/tmp not executable");
-        return -1;
+    {   /* Use mmap instead of malloc for Selinux.  Ref:
+           http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
+
+        char tmpfname[] = "/tmp/.tccrunXXXXXX";
+        int fd = mkstemp (tmpfname);
+
+        s1->mem_size = ret;
+        unlink (tmpfname);
+        ftruncate (fd, s1->mem_size);
+
+        s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
+            MAP_SHARED, fd, 0);
+        if (s1->write_mem == MAP_FAILED)
+            tcc_error("/tmp not writeable");
+
+        s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
+            MAP_SHARED, fd, 0);
+        if (s1->runtime_mem == MAP_FAILED)
+            tcc_error("/tmp not executable");
+
+        ret = tcc_relocate_ex(s1, s1->write_mem);
     }
-    ret = tcc_relocate_ex(s1, s1->write_mem);
 #else
-    ret = tcc_relocate_ex(s1, NULL);
-    if (-1 != ret) {
-        s1->runtime_mem = tcc_malloc(ret);
-        ret = tcc_relocate_ex(s1, s1->runtime_mem);
-    }
+    s1->runtime_mem = tcc_malloc(ret);
+    ret = tcc_relocate_ex(s1, s1->runtime_mem);
 #endif
     return ret;
 }
@@ -130,8 +133,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
     addr_t mem;
     int i;
 
-    if (0 == s1->runtime_added) {
-        s1->runtime_added = 1;
+    if (NULL == ptr) {
         s1->nb_errors = 0;
 #ifdef TCC_TARGET_PE
         pe_output_file(s1, NULL);
@@ -215,6 +217,9 @@ static void set_pages_executable(void *ptr, unsigned long length)
     unsigned long old_protect;
     VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
 #else
+#ifndef PAGESIZE
+# define PAGESIZE 4096
+#endif
     addr_t start, end;
     start = (addr_t)ptr & ~(PAGESIZE - 1);
     end = (addr_t)ptr + length;
@@ -226,7 +231,7 @@ static void set_pages_executable(void *ptr, unsigned long length)
 /* ------------------------------------------------------------- */
 #ifdef CONFIG_TCC_BACKTRACE
 
-PUB_FUNC void tcc_set_num_callers(int n)
+ST_FUNC void tcc_set_num_callers(int n)
 {
     rt_num_callers = n;
 }
@@ -436,6 +441,10 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
     exit(255);
 }
 
+#ifndef SA_SIGINFO
+# define SA_SIGINFO 0x00000004u
+#endif
+
 /* Generate a stack backtrace when a CPU exception occurs. */
 static void set_exception_handler(void)
 {
@@ -663,14 +672,8 @@ static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
 #endif /* _WIN32 */
 #endif /* CONFIG_TCC_BACKTRACE */
 /* ------------------------------------------------------------- */
-
 #ifdef CONFIG_TCC_STATIC
 
-#define RTLD_LAZY       0x001
-#define RTLD_NOW        0x002
-#define RTLD_GLOBAL     0x100
-#define RTLD_DEFAULT    NULL
-
 /* dummy function for profiling */
 ST_FUNC void *dlopen(const char *filename, int flag)
 {
@@ -680,26 +683,27 @@ ST_FUNC void *dlopen(const char *filename, int flag)
 ST_FUNC void dlclose(void *p)
 {
 }
-/*
-const char *dlerror(void)
+
+ST_FUNC const char *dlerror(void)
 {
     return "error";
 }
-*/
+
 typedef struct TCCSyms {
     char *str;
     void *ptr;
 } TCCSyms;
 
-#define TCCSYM(a) { #a, &a, },
 
 /* add the symbol you want here if no dynamic linking is done */
 static TCCSyms tcc_syms[] = {
 #if !defined(CONFIG_TCCBOOT)
+#define TCCSYM(a) { #a, &a, },
     TCCSYM(printf)
     TCCSYM(fprintf)
     TCCSYM(fopen)
     TCCSYM(fclose)
+#undef TCCSYM
 #endif
     { NULL, NULL },
 };
index 12f6ae7..dc06b8f 100644 (file)
@@ -6,13 +6,11 @@
     under MS-Windows.  See tcc-doc.html to have all the features.
 
 
-
     Installation from the binary ZIP package:
     -----------------------------------------
     Unzip the package to a directory of your choice.
     
 
-
     Set the system PATH:
     --------------------
     To be able to invoke the compiler from everywhere on your computer by
@@ -20,7 +18,6 @@
     system PATH.
 
 
-
     Examples:
     ---------
     Open a console window (DOS box) and 'cd' to the examples directory.
        tiny_impdef dll.dll (optional)
         tcc hello_dll.c dll.def
 
-    For the 'libtcc_test' example type
 
-        tcc examples/libtcc_test.c -I libtcc -L libtcc -ltcc
+    Using libtcc as JIT compiler in your program
+    --------------------------------------------
+    Check out the 'libtcc_test' example:
+
+    - Running it from source:
+        tcc -I libtcc libtcc/libtcc.def -run examples/libtcc_test.c
+
+    - Compiling with TCC:
+        tcc examples/libtcc_test.c -I libtcc libtcc/libtcc.def
+
+    - Compiling with MinGW:
+        gcc examples/libtcc_test.c -I libtcc libtcc.dll
+
+    - Compiling with MSVC:
+        lib /def:libtcc\libtcc.def /out:libtcc.lib
+        cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
 
 
     Import Definition Files:
@@ -58,7 +69,6 @@
     the TCC commandline to link a program that uses opengl32.dll.
 
 
-
     Header Files:
     -------------
     The system header files (except _mingw.h) are from the MinGW
@@ -71,7 +81,6 @@
     into your "tcc/include/winapi" directory.
 
 
-
     Resource Files:
     ---------------
     TCC can link windows resources in coff format as generated by MinGW's
@@ -81,7 +90,6 @@
         tcc app.c appres.o -o app.exe
 
 
-
     Tiny Libmaker:
     --------------
     The included tiny_libmaker tool by Timovj Lahde can be used as
        tiny_libmaker [rcs] library objectfiles ...
 
 
-
     Compilation from source:
     ------------------------
     * You can use the MinGW and MSYS tools available at
 
         http://www.mingw.org
 
-    Untar the TCC archive and type in the MSYS shell:
+      Untar the TCC archive and type in the MSYS shell:
 
-       ./configure
-       make
-       make install
+        ./configure [--prefix installpath]
+        make
+        make install
 
     The default install location is c:\Program Files\tcc
 
-
     * Alternatively you can compile TCC with just GCC from MinGW using
 
-        win32\build-tcc.bat
-
-    To install, copy the entire contents of the win32 directory to
-    where you want.
+        build-tcc.bat (from the win32 directory)
 
+      To install, copy the entire contents of the win32 directory to
+      where you want.
 
 
     Limitations:
     - Bounds checking (option -b) is not supported on 64-bit OS.
 
 
-
     Documentation and License:
     --------------------------
     TCC is distributed under the GNU Lesser General Public License. (See
        http://fabrice.bellard.free.fr/tcc/
 
 
-
     WinAPI Help and 3rd-party tools:
     --------------------------------
     The Windows API documentation (Win95) in a single .hlp file is
     "ResEd", available at the RadASM website.
 
 
-
     --- grischka
index 586c49d..1739549 100644 (file)
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <stdio.h>
+#include <io.h>
 #include <malloc.h>
 
-char *get_export_names(FILE *fp);
+char *get_export_names(int fd);
 #define tcc_free free
 #define tcc_realloc realloc
 
@@ -114,7 +115,7 @@ usage:
     if (v)
         printf("--> %s\n", file);
 
-    p = get_export_names(fp);
+    p = get_export_names(fileno(fp));
     if (NULL == p) {
         fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
         goto the_end;
@@ -149,18 +150,18 @@ the_end:
     return ret;
 }
 
-/* -------------------------------------------------------------- */
-
-int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
+int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
 {
-    fseek(fp, offset, 0);
-    return len == fread(buffer, 1, len, fp);
+    lseek(fd, offset, SEEK_SET);
+    return len == read(fd, buffer, len);
 }
 
 /* -------------------------------------------------------------- */
+
+/* -------------------------------------------------------------- */
 #endif
 
-char *get_export_names(FILE *fp)
+char *get_export_names(int fd)
 {
     int l, i, n, n0;
     char *p;
@@ -182,20 +183,20 @@ char *get_export_names(FILE *fp)
     n = n0 = 0;
     p = NULL;
 
-    if (!read_mem(fp, 0, &dh, sizeof dh))
+    if (!read_mem(fd, 0, &dh, sizeof dh))
         goto the_end;
-    if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig))
+    if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
         goto the_end;
     if (sig != 0x00004550)
         goto the_end;
     pef_hdroffset = dh.e_lfanew + sizeof sig;
-    if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih))
+    if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
         goto the_end;
     if (MACHINE != ih.Machine)
         goto the_end;
     opt_hdroffset = pef_hdroffset + sizeof ih;
     sec_hdroffset = opt_hdroffset + sizeof oh;
-    if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh))
+    if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
         goto the_end;
 
     if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
@@ -204,7 +205,7 @@ char *get_export_names(FILE *fp)
     addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
     //printf("addr: %08x\n", addr);
     for (i = 0; i < ih.NumberOfSections; ++i) {
-        if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
+        if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
             goto the_end;
         //printf("vaddr: %08x\n", ish.VirtualAddress);
         if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
@@ -214,18 +215,18 @@ char *get_export_names(FILE *fp)
 
 found:
     ref = ish.VirtualAddress - ish.PointerToRawData;
-    if (!read_mem(fp, addr - ref, &ied, sizeof ied))
+    if (!read_mem(fd, addr - ref, &ied, sizeof ied))
         goto the_end;
 
     namep = ied.AddressOfNames - ref;
     for (i = 0; i < ied.NumberOfNames; ++i) {
-        if (!read_mem(fp, namep, &ptr, sizeof ptr))
+        if (!read_mem(fd, namep, &ptr, sizeof ptr))
             goto the_end;
         namep += sizeof ptr;
         for (l = 0;;) {
             if (n+1 >= n0)
                 p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
-            if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) {
+            if (!read_mem(fd, ptr - ref + l, p + n, 1) || ++l >= 80) {
                 tcc_free(p), p = NULL;
                 goto the_end;
             }
index a85c685..62d2a2e 100644 (file)
@@ -79,7 +79,7 @@ int main(int argc, char **argv)
     ElfW(Sym) *sym;
     int i, fsize, iarg;
     char *buf, *shstr, *symtab = NULL, *strtab = NULL;
-    int symtabsize = 0, strtabsize = 0;
+    int symtabsize = 0;//, strtabsize = 0;
     char *anames = NULL;
     int *afpos = NULL;
     int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
@@ -171,7 +171,7 @@ int main(int argc, char **argv)
                 if (!strcmp(shstr + shdr->sh_name, ".strtab"))
                 {
                     strtab = (char *)(buf + shdr->sh_offset);
-                    strtabsize = shdr->sh_size;
+                    //strtabsize = shdr->sh_size;
                 }
             }
         }