aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2016-10-01 20:19:37 +0200
committergrischka <grischka>2016-10-01 20:19:37 +0200
commiteacdc426d76a88aa9b6efc698106d3f36a774905 (patch)
treef20ac27ca31fb9a98e366e430f11bd80e2ce3c8c
parent09a487eb2b2bcabeaeec8d2c7ca422993df0efb5 (diff)
downloadtinycc-eacdc426d76a88aa9b6efc698106d3f36a774905.tar.gz
tinycc-eacdc426d76a88aa9b6efc698106d3f36a774905.tar.bz2
libtcc: cleanup @listfile
Also: - allow more than one item per line - respect "quoted items" and escaped quotes \" (also for LIBTCCAPI tcc_setoptions) - cleanup some copy & paste
-rw-r--r--libtcc.c227
-rw-r--r--tcc.c36
-rw-r--r--tcc.h16
-rw-r--r--tccpe.c17
-rw-r--r--tccpp.c15
5 files changed, 141 insertions, 170 deletions
diff --git a/libtcc.c b/libtcc.c
index ee149aa..cb0d680 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -2074,43 +2074,51 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype
dynarray_add((void ***)&s->files, &s->nb_files, f);
}
-ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
+/* read list file */
+static void args_parser_listfile(TCCState *s, const char *filename)
+{
+ int fd;
+ size_t len;
+ char *p;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ tcc_error("file '%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);
+ tcc_free(p);
+}
+
+PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
{
const TCCOption *popt;
const char *optarg, *r;
int optind = 0;
- ParseArgsState *pas = s->parse_args_state;
+ int run = 0;
+ int filetype = 0;
+ int x;
+ char buf[1024];
+
+ ++s->args_ref;
while (optind < argc) {
r = argv[optind++];
- if (r[0] != '-' || r[1] == '\0') {
- /* handle list files */
- if (r[0] == '@' && r[1]) {
- char buf[sizeof file->filename], *p;
- char **argv = NULL;
- int argc = 0;
- FILE *fp;
- fp = fopen(r + 1, "rb");
- if (fp == NULL)
- tcc_error("list file '%s' not found", r + 1);
- while (fgets(buf, sizeof buf, fp)) {
- p = trimfront(trimback(buf, strchr(buf, 0)));
- if (0 == *p || ';' == *p)
- continue;
- dynarray_add((void ***)&argv, &argc, tcc_strdup(p));
- }
- fclose(fp);
- tcc_parse_args1(s, argc, argv);
- dynarray_reset(&argv, &argc);
- } else {
- args_parser_add_file(s, r, pas->filetype);
- if (pas->run) {
- optind--;
- /* argv[0] will be this file */
- break;
- }
+ if (r[0] == '@' && r[1] != '\0') {
+ args_parser_listfile(s, r + 1);
+ continue;
+ }
+
+ if (r[0] != '-' || r[1] == '\0') {
+ args_parser_add_file(s, r, filetype);
+ if (run) {
+ optind--;
+ /* argv[0] will be this file */
+ break;
}
continue;
}
@@ -2160,7 +2168,7 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break;
case TCC_OPTION_pthread:
parse_option_D(s, "_REENTRANT");
- pas->pthread = 1;
+ s->args_pthread = 1;
break;
case TCC_OPTION_bench:
s->do_bench = 1;
@@ -2180,9 +2188,11 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
s->do_debug = 1;
break;
case TCC_OPTION_c:
+ x = TCC_OUTPUT_OBJ;
+ set_output_type:
if (s->output_type)
- tcc_warning("-c: some compiler action already specified (%d)", s->output_type);
- s->output_type = TCC_OUTPUT_OBJ;
+ tcc_warning("-%s: overriding compiler action already specified", popt->name);
+ s->output_type = x;
break;
case TCC_OPTION_d:
if (*optarg == 'D')
@@ -2214,10 +2224,8 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
allow to use a tcc as a reference compiler for "make test" */
break;
case TCC_OPTION_shared:
- if (s->output_type)
- tcc_warning("-shared: some compiler action already specified (%d)", s->output_type);
- s->output_type = TCC_OUTPUT_DLL;
- break;
+ x = TCC_OUTPUT_DLL;
+ goto set_output_type;
case TCC_OPTION_soname:
s->soname = tcc_strdup(optarg);
break;
@@ -2233,34 +2241,15 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break;
case TCC_OPTION_r:
/* generate a .o merging several output files */
- if (s->output_type)
- tcc_warning("-r: some compiler action already specified (%d)", s->output_type);
s->option_r = 1;
- s->output_type = TCC_OUTPUT_OBJ;
- break;
+ x = TCC_OUTPUT_OBJ;
+ goto set_output_type;
case TCC_OPTION_isystem:
tcc_add_sysinclude_path(s, optarg);
break;
case TCC_OPTION_iwithprefix:
- if (1) {
- char buf[1024];
- int buf_size = sizeof(buf)-1;
- char *p = &buf[0];
-
- char *sysroot = "{B}/";
- int len = strlen(sysroot);
- if (len > buf_size)
- len = buf_size;
- strncpy(p, sysroot, len);
- p += len;
- buf_size -= len;
-
- len = strlen(optarg);
- if (len > buf_size)
- len = buf_size;
- strncpy(p, optarg, len+1);
- tcc_add_sysinclude_path(s, buf);
- }
+ snprintf(buf, sizeof buf, "{B}/%s", optarg);
+ tcc_add_sysinclude_path(s, buf);
break;
case TCC_OPTION_nostdinc:
s->nostdinc = 1;
@@ -2275,12 +2264,10 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
#ifndef TCC_IS_NATIVE
tcc_error("-run is not available in a cross compiler");
#endif
- if (s->output_type)
- tcc_warning("-run: some compiler action already specified (%d)", s->output_type);
- s->output_type = TCC_OUTPUT_MEMORY;
tcc_set_options(s, optarg);
- pas->run = 1;
- break;
+ run = 1;
+ x = TCC_OUTPUT_MEMORY;
+ goto set_output_type;
case TCC_OPTION_v:
do ++s->verbose; while (*optarg++ == 'v');
break;
@@ -2299,15 +2286,13 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
s->rdynamic = 1;
break;
case TCC_OPTION_Wl:
- if (pas->linker_arg.size)
- --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ',');
- cstr_cat(&pas->linker_arg, optarg, 0);
+ if (s->linker_arg.size)
+ --s->linker_arg.size, cstr_ccat(&s->linker_arg, ',');
+ cstr_cat(&s->linker_arg, optarg, 0);
break;
case TCC_OPTION_E:
- if (s->output_type)
- tcc_warning("-E: some compiler action already specified (%d)", s->output_type);
- s->output_type = TCC_OUTPUT_PREPROCESS;
- break;
+ x = TCC_OUTPUT_PREPROCESS;
+ goto set_output_type;
case TCC_OPTION_P:
s->Pflag = atoi(optarg) + 1;
break;
@@ -2327,25 +2312,20 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break;
case TCC_OPTION_x:
if (*optarg == 'c')
- pas->filetype = TCC_FILETYPE_C;
+ filetype = TCC_FILETYPE_C;
else
if (*optarg == 'a')
- pas->filetype = TCC_FILETYPE_ASM_PP;
+ filetype = TCC_FILETYPE_ASM_PP;
else
if (*optarg == 'n')
- pas->filetype = 0;
+ filetype = 0;
else
tcc_warning("unsupported language '%s'", optarg);
break;
case TCC_OPTION_O:
- if (1) {
- int opt = atoi(optarg);
- char *sym = "__OPTIMIZE__";
- if (opt)
- tcc_define_symbol(s, sym, 0);
- else
- tcc_undefine_symbol(s, sym);
- }
+ x = atoi(optarg);
+ if (x > 0)
+ tcc_define_symbol(s, "__OPTIMIZE__", NULL);
break;
case TCC_OPTION_pedantic:
case TCC_OPTION_pipe:
@@ -2358,62 +2338,55 @@ unsupported_option:
break;
}
}
- return optind;
-}
-
-PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
-{
- ParseArgsState *pas;
- int ret, is_allocated = 0;
-
- if (!s->parse_args_state) {
- s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState));
- cstr_new(&s->parse_args_state->linker_arg);
- is_allocated = 1;
- }
- pas = s->parse_args_state;
-
- ret = tcc_parse_args1(s, argc, argv);
-
- if (s->output_type == 0)
- s->output_type = TCC_OUTPUT_EXE;
- if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ) {
- args_parser_add_file(s, "-lpthread", TCC_FILETYPE_BINARY);
- s->nb_libraries++;
+ if (1 == s->args_ref) {
+ /* top instance */
+ if (s->output_type != TCC_OUTPUT_OBJ) {
+ tcc_set_linker(s, (const char *)s->linker_arg.data);
+ if (s->args_pthread) {
+ args_parser_add_file(s, optarg, 'l');
+ s->nb_libraries++;
+ }
+ }
+ cstr_free(&s->linker_arg);
+ s->args_pthread = 0;
}
+ --s->args_ref;
- if (s->output_type == TCC_OUTPUT_EXE || s->output_type == TCC_OUTPUT_DLL)
- tcc_set_linker(s, (const char *)pas->linker_arg.data);
-
- if (is_allocated) {
- cstr_free(&pas->linker_arg);
- tcc_free(pas);
- s->parse_args_state = NULL;
- }
- return ret;
+ return optind;
}
-LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
+LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
{
- const char *s1;
- char **argv, *arg;
- int argc, len;
- int ret;
+ char **argv;
+ int argc;
+ int ret, q, c;
+ CString str;
argc = 0, argv = NULL;
for(;;) {
- while (is_space(*str))
- str++;
- if (*str == '\0')
+ while (c = (unsigned char)*r, c && c <= ' ')
+ ++r;
+ if (c == 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);
+ 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((void ***)&argv, &argc, tcc_strdup(str.data));
+ cstr_free(&str);
}
ret = tcc_parse_args(s, argc, argv);
dynarray_reset(&argv, &argc);
diff --git a/tcc.c b/tcc.c
index 0132a2e..730e1e4 100644
--- a/tcc.c
+++ b/tcc.c
@@ -92,7 +92,7 @@ static void help(void)
" -bench show compilation statistics\n"
" -xc -xa specify type of the next infile\n"
" - use stdin pipe as infile\n"
- " @listfile read line separated arguments from 'listfile'\n"
+ " @listfile read arguments from listfile\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n"
@@ -256,9 +256,6 @@ int main(int argc, char **argv)
optind = tcc_parse_args(s, argc - 1, argv + 1);
- if (s->do_bench)
- start_time = getclock_us();
-
tcc_set_environment(s);
if (optind == 0) {
@@ -272,17 +269,18 @@ int main(int argc, char **argv)
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)
+ if (s->nb_files == 0) {
+ if (optind == 1) {
+ if (s->print_search_dirs || s->verbose == 2) {
+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+ display_info(s, 1);
+ return 1;
+ }
+ if (s->verbose)
+ return 1;
+ }
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) {
@@ -293,6 +291,8 @@ int main(int argc, char **argv)
tcc_error("cannot specify multiple files with -c");
}
+ if (s->output_type == 0)
+ s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
@@ -305,6 +305,9 @@ int main(int argc, char **argv)
}
}
+ if (s->do_bench)
+ start_time = getclock_us();
+
/* compile or add each files or library */
for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
struct filespec *f = s->files[i];
@@ -322,6 +325,8 @@ int main(int argc, char **argv)
}
if (0 == ret) {
+ if (s->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);
@@ -335,9 +340,6 @@ int main(int argc, char **argv)
}
}
- if (s->do_bench)
- tcc_print_stats(s, getclock_us() - start_time);
-
tcc_delete(s);
return ret;
}
diff --git a/tcc.h b/tcc.h
index 42088e1..9567848 100644
--- a/tcc.h
+++ b/tcc.h
@@ -638,14 +638,6 @@ struct sym_attr {
#endif
};
-typedef struct ParseArgsState
-{
- int run;
- int pthread;
- int filetype;
- CString linker_arg; /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
-} ParseArgsState;
-
#if !defined(MEM_DEBUG)
#define tal_free(al, p) tal_free_impl(al, p)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size)
@@ -682,6 +674,7 @@ typedef struct tal_header_t {
#endif
} tal_header_t;
+
struct TCCState {
int verbose; /* if true, display some information during compilation */
@@ -860,7 +853,10 @@ struct TCCState {
int do_bench; /* option -bench */
int gen_deps; /* option -MD */
char *deps_outfile; /* option -MF */
- ParseArgsState *parse_args_state;
+
+ int args_pthread; /* -pthread option */
+ CString linker_arg; /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
+ int args_ref; /* tcc_parse_args recursive counter */
};
struct filespec {
@@ -1312,8 +1308,6 @@ ST_FUNC void preprocess_delete(void);
ST_FUNC int tcc_preprocess(TCCState *s1);
ST_FUNC void skip(int c);
ST_FUNC NORETURN void expect(const char *msg);
-ST_FUNC char *trimfront(char *p);
-ST_FUNC char *trimback(char *a, char *e);
/* ------------ tccgen.c ------------ */
diff --git a/tccpe.c b/tccpe.c
index 4069e51..83acc2f 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -1566,6 +1566,23 @@ quit:
}
/* ------------------------------------------------------------- */
+
+static char *trimfront(char *p)
+{
+ while (*p && (unsigned char)*p <= ' ')
+ ++p;
+ return p;
+}
+
+static char *trimback(char *a, char *e)
+{
+ while (e > a && (unsigned char)e[-1] <= ' ')
+ --e;
+ *e = 0;;
+ return a;
+}
+
+/* ------------------------------------------------------------- */
static int pe_load_def(TCCState *s1, int fd)
{
int state = 0, ret = -1, dllindex = 0, ord;
diff --git a/tccpp.c b/tccpp.c
index c40a14c..11d8dab 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -133,21 +133,6 @@ ST_FUNC void end_macro(void)
}
}
-ST_FUNC char *trimfront(char *p)
-{
- while (*p && (unsigned char)*p <= ' ')
- ++p;
- return p;
-}
-
-ST_FUNC char *trimback(char *a, char *e)
-{
- while (e > a && (unsigned char)e[-1] <= ' ')
- --e;
- *e = 0;;
- return a;
-}
-
/* ------------------------------------------------------------------------- */
/* Custom allocator for tiny objects */