aboutsummaryrefslogtreecommitdiff
path: root/libtcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtcc.c')
-rw-r--r--libtcc.c210
1 files changed, 128 insertions, 82 deletions
diff --git a/libtcc.c b/libtcc.c
index 34e944c..3282c28 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -239,7 +239,7 @@ PUB_FUNC char *tcc_strdup(const char *str)
return ptr;
}
-PUB_FUNC void tcc_memstats(int bench)
+PUB_FUNC void tcc_memcheck(void)
{
}
@@ -379,7 +379,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
return ptr;
}
-PUB_FUNC void tcc_memstats(int bench)
+PUB_FUNC void tcc_memcheck(void)
{
if (mem_cur_size) {
mem_debug_header_t *header = mem_debug_chain;
@@ -393,8 +393,7 @@ PUB_FUNC void tcc_memstats(int bench)
#if MEM_DEBUG-0 == 2
exit(2);
#endif
- } else if (bench)
- fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size);
+ }
}
#endif /* MEM_DEBUG */
@@ -435,7 +434,7 @@ ST_FUNC void dynarray_reset(void *pp, int *n)
*(void**)pp = NULL;
}
-static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
+static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
{
const char *p;
do {
@@ -878,18 +877,14 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
"name proto __asm__ (#alias) __THROW");
# endif
-#endif /* ndef TCC_TARGET_PE */
-
/* Some GCC builtins that are simple to express as macros. */
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
-
+#endif /* ndef TCC_TARGET_PE */
return s;
}
LIBTCCAPI void tcc_delete(TCCState *s1)
{
- int bench = s1->do_bench;
-
tcc_cleanup();
/* free sections */
@@ -915,6 +910,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
dynarray_reset(&s1->files, &s1->nb_files);
dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
+ dynarray_reset(&s1->argv, &s1->argc);
#ifdef TCC_IS_NATIVE
/* free runtime memory */
@@ -923,7 +919,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
tcc_free(s1);
if (0 == --nb_states)
- tcc_memstats(bench);
+ tcc_memcheck();
}
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
@@ -965,7 +961,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
# endif
#else
/* paths for crt objects */
- tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
+ tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
/* add libc crt1/crti objects */
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
!s->nostdlib) {
@@ -979,13 +975,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
{
- tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);
+ tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
return 0;
}
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
{
- tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
+ tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
return 0;
}
@@ -1106,7 +1102,7 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
{
- tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);
+ tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
return 0;
}
@@ -1440,6 +1436,7 @@ typedef struct TCCOption {
enum {
TCC_OPTION_HELP,
+ TCC_OPTION_v,
TCC_OPTION_I,
TCC_OPTION_D,
TCC_OPTION_U,
@@ -1480,13 +1477,14 @@ enum {
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
+ TCC_OPTION_x,
+ TCC_OPTION_ar,
+ TCC_OPTION_impdef
};
#define TCC_OPTION_HAS_ARG 0x0001
@@ -1496,6 +1494,7 @@ static const TCCOption tcc_options[] = {
{ "h", TCC_OPTION_HELP, 0 },
{ "-help", TCC_OPTION_HELP, 0 },
{ "?", TCC_OPTION_HELP, 0 },
+ { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
@@ -1542,13 +1541,16 @@ static const TCCOption tcc_options[] = {
{ "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 },
+ { "ar", TCC_OPTION_ar, 0},
+#ifdef TCC_TARGET_PE
+ { "impdef", TCC_OPTION_impdef, 0},
+#endif
{ NULL, 0, 0 },
};
@@ -1595,58 +1597,106 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype
{
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
f->type = filetype;
+ f->alacarte = s->alacarte_link;
strcpy(f->name, filename);
dynarray_add(&s->files, &s->nb_files, f);
}
+static int args_parser_make_argv(const char *r, int *argc, char ***argv)
+{
+ int ret = 0, q, c;
+ CString str;
+ for(;;) {
+ while (c = (unsigned char)*r, c && c <= ' ')
+ ++r;
+ if (c == 0)
+ break;
+ q = 0;
+ cstr_new(&str);
+ while (c = (unsigned char)*r, c) {
+ ++r;
+ if (c == '\\' && (*r == '"' || *r == '\\')) {
+ c = *r++;
+ } else if (c == '"') {
+ q = !q;
+ continue;
+ } else if (q == 0 && c <= ' ') {
+ break;
+ }
+ cstr_ccat(&str, c);
+ }
+ cstr_ccat(&str, 0);
+ //printf("<%s>\n", str.data), fflush(stdout);
+ dynarray_add(argv, argc, tcc_strdup(str.data));
+ cstr_free(&str);
+ ++ret;
+ }
+ return ret;
+}
+
/* read list file */
-static void args_parser_listfile(TCCState *s, const char *filename)
+static void args_parser_listfile(TCCState *s,
+ const char *filename, int optind, int *pargc, char ***pargv)
{
- int fd;
+ int fd, i;
size_t len;
char *p;
+ int argc = 0;
+ char **argv = NULL;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
- tcc_error("file '%s' not found", filename);
+ tcc_error("listfile '%s' not found", filename);
len = lseek(fd, 0, SEEK_END);
p = tcc_malloc(len + 1), p[len] = 0;
lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd);
- tcc_set_options(s, p);
+
+ for (i = 0; i < *pargc; ++i)
+ if (i == optind)
+ args_parser_make_argv(p, &argc, &argv);
+ else
+ dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
+
tcc_free(p);
+ dynarray_reset(&s->argv, &s->argc);
+ *pargc = s->argc = argc, *pargv = s->argv = argv;
}
-PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
+PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
{
const TCCOption *popt;
const char *optarg, *r;
const char *run = NULL;
- int optind = 0;
- int x;
int last_o = -1;
+ int x;
CString linker_arg; /* collect -Wl options */
char buf[1024];
+ int tool = 0, arg_start = 0, noaction = optind;
+ char **argv = *pargv;
+ int argc = *pargc;
cstr_new(&linker_arg);
while (optind < argc) {
-
- r = argv[optind++];
-
-reparse:
+ r = argv[optind];
if (r[0] == '@' && r[1] != '\0') {
- args_parser_listfile(s, r + 1);
+ args_parser_listfile(s, r + 1, optind, &argc, &argv);
continue;
}
-
+ optind++;
+ if (tool) {
+ if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
+ ++s->verbose;
+ continue;
+ }
+reparse:
if (r[0] != '-' || r[1] == '\0') {
if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
args_parser_add_file(s, r, s->filetype);
if (run) {
tcc_set_options(s, run);
- optind--;
- /* argv[0] will be this file */
+ arg_start = optind - 1;
break;
}
continue;
@@ -1675,7 +1725,7 @@ reparse:
switch(popt->index) {
case TCC_OPTION_HELP:
- return 0;
+ return OPT_HELP;
case TCC_OPTION_I:
tcc_add_include_path(s, optarg);
break;
@@ -1693,7 +1743,7 @@ reparse:
tcc_set_lib_path(s, optarg);
break;
case TCC_OPTION_l:
- args_parser_add_file(s, optarg, AFF_TYPE_LIBWH - s->alacarte_link);
+ args_parser_add_file(s, optarg, AFF_TYPE_LIB);
s->nb_libraries++;
break;
case TCC_OPTION_pthread:
@@ -1774,9 +1824,6 @@ reparse:
case TCC_OPTION_nostdlib:
s->nostdlib = 1;
break;
- case TCC_OPTION_print_search_dirs:
- s->print_search_dirs = 1;
- break;
case TCC_OPTION_run:
#ifndef TCC_IS_NATIVE
tcc_error("-run is not available in a cross compiler");
@@ -1786,6 +1833,7 @@ reparse:
goto set_output_type;
case TCC_OPTION_v:
do ++s->verbose; while (*optarg++ == 'v');
+ ++noaction;
break;
case TCC_OPTION_f:
if (set_flag(s, options_f, optarg) < 0)
@@ -1804,12 +1852,13 @@ reparse:
break;
#endif
case TCC_OPTION_m:
- if (set_flag(s, options_m, optarg) == 0)
- break;
- else if (x = atoi(optarg), x == 32 || x == 64)
- s->cross_target = x;
- else
- goto unsupported_option;
+ if (set_flag(s, options_m, optarg) < 0) {
+ if (x = atoi(optarg), x != 32 && x != 64)
+ goto unsupported_option;
+ if (PTR_SIZE != x/8)
+ return x;
+ ++noaction;
+ }
break;
case TCC_OPTION_W:
if (set_flag(s, options_W, optarg) < 0)
@@ -1860,6 +1909,20 @@ reparse:
case TCC_OPTION_O:
last_o = atoi(optarg);
break;
+ case TCC_OPTION_print_search_dirs:
+ x = OPT_PRINT_DIRS;
+ goto extra_action;
+ case TCC_OPTION_impdef:
+ x = OPT_IMPDEF;
+ goto extra_action;
+ case TCC_OPTION_ar:
+ x = OPT_AR;
+ extra_action:
+ arg_start = optind - 1;
+ if (arg_start != noaction)
+ tcc_error("cannot parse %s here", r);
+ tool = x;
+ break;
case TCC_OPTION_traditional:
case TCC_OPTION_pedantic:
case TCC_OPTION_pipe:
@@ -1873,53 +1936,32 @@ unsupported_option:
break;
}
}
-
if (last_o > 0)
tcc_define_symbol(s, "__OPTIMIZE__", NULL);
-
if (linker_arg.size) {
r = linker_arg.data;
goto arg_err;
}
-
- return optind;
+ *pargc = argc - arg_start;
+ *pargv = argv + arg_start;
+ if (tool)
+ return tool;
+ if (optind != noaction)
+ return 0;
+ if (s->verbose == 2)
+ return OPT_PRINT_DIRS;
+ if (s->verbose)
+ return OPT_V;
+ return OPT_HELP;
}
-LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
+LIBTCCAPI void tcc_set_options(TCCState *s, const char *r)
{
- char **argv;
- int argc;
- int ret, q, c;
- CString str;
-
- argc = 0, argv = NULL;
- for(;;) {
- while (c = (unsigned char)*r, c && c <= ' ')
- ++r;
- if (c == 0)
- break;
- q = 0;
- cstr_new(&str);
- while (c = (unsigned char)*r, c) {
- ++r;
- if (c == '\\' && (*r == '"' || *r == '\\')) {
- c = *r++;
- } else if (c == '"') {
- q = !q;
- continue;
- } else if (q == 0 && c <= ' ') {
- break;
- }
- cstr_ccat(&str, c);
- }
- cstr_ccat(&str, 0);
- //printf("<%s>\n", str.data), fflush(stdout);
- dynarray_add(&argv, &argc, tcc_strdup(str.data));
- cstr_free(&str);
- }
- ret = tcc_parse_args(s, argc, argv);
+ char **argv = NULL;
+ int argc = 0;
+ args_parser_make_argv(r, &argc, &argv);
+ tcc_parse_args(s, &argc, &argv, 0);
dynarray_reset(&argv, &argc);
- return ret;
}
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
@@ -1928,11 +1970,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
total_time = 1;
if (total_bytes < 1)
total_bytes = 1;
- fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %u lines/s, %0.1f MB/s\n",
+ fprintf(stderr, "* %d idents, %d lines, %d bytes\n"
+ "* %0.3f s, %u lines/s, %0.1f MB/s\n",
tok_ident - TOK_IDENT, total_lines, total_bytes,
(double)total_time/1000,
(unsigned)total_lines*1000/total_time,
(double)total_bytes/1000/total_time);
+#ifdef MEM_DEBUG
+ fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
+#endif
}
PUB_FUNC void tcc_set_environment(TCCState *s)