From eacdc426d76a88aa9b6efc698106d3f36a774905 Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 1 Oct 2016 20:19:37 +0200 Subject: [PATCH] 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 --- libtcc.c | 231 ++++++++++++++++++++++++------------------------------- tcc.c | 36 +++++---- tcc.h | 16 ++-- tccpe.c | 17 ++++ tccpp.c | 15 ---- 5 files changed, 143 insertions(+), 172 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; } } + + 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; + return optind; } -PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) +LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) { - 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 (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; -} - -LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) -{ - 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," */ -} 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," */ + 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 @@ -1565,6 +1565,23 @@ quit: return ret; } +/* ------------------------------------------------------------- */ + +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) { 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 */