aboutsummaryrefslogtreecommitdiff
path: root/libtcc.c
diff options
context:
space:
mode:
authorgrischka <grischka>2013-02-12 19:13:28 +0100
committergrischka <grischka>2013-02-12 19:13:28 +0100
commit05108a3b0a8eff70739b253b8995999b1861f9f2 (patch)
tree690c17ebe3cd0479e278bc3b65e00eba7ec674fd /libtcc.c
parent829655949b7964c66e1f7da9d44c19655dba88aa (diff)
downloadtinycc-05108a3b0a8eff70739b253b8995999b1861f9f2.tar.gz
tinycc-05108a3b0a8eff70739b253b8995999b1861f9f2.tar.bz2
libtcc: new LIBTCCAPI tcc_set_options(TCCState*, const char*str)
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
Diffstat (limited to 'libtcc.c')
-rw-r--r--libtcc.c631
1 files changed, 423 insertions, 208 deletions
diff --git a/libtcc.c b/libtcc.c
index 968c6e4..cd5f13b 100644
--- 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;
+}
+
+static char *copy_linker_arg(const char *p)
+{
+ const char *q = p;
+ skip_linker_arg(&q);
+ return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
+}
/* set linker options */
-PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
+static int tcc_set_linker(TCCState *s, const char *option)
{
- char *p = option;
- char *end;
-
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)) {
+ if (strstart("pe-", &p)) {
+#elif defined(TCC_TARGET_X86_64)
+ if (strstart("elf64-", &p)) {
#else
-#if defined(TCC_TARGET_X86_64)
- if (strstart(p, "elf64-", NULL)) {
-#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
+ goto err;
- } 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 (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);
}
-
- if (multi) {
- option = NULL;
- p = strchr( (end) ? end : p, ',');
- if (p) {
- *p = 0; /* terminate last option */
- option = ++p;
- }
- } else
- option = NULL;
+ 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;
- }
-}
-