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
master
grischka 2016-10-01 20:19:37 +02:00
parent 09a487eb2b
commit eacdc426d7
5 changed files with 143 additions and 172 deletions

231
libtcc.c
View File

@ -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); 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 TCCOption *popt;
const char *optarg, *r; const char *optarg, *r;
int optind = 0; 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) { while (optind < argc) {
r = argv[optind++]; 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 (r[0] == '@' && r[1] != '\0') {
if (fp == NULL) args_parser_listfile(s, r + 1);
tcc_error("list file '%s' not found", r + 1); continue;
while (fgets(buf, sizeof buf, fp)) { }
p = trimfront(trimback(buf, strchr(buf, 0)));
if (0 == *p || ';' == *p) if (r[0] != '-' || r[1] == '\0') {
continue; args_parser_add_file(s, r, filetype);
dynarray_add((void ***)&argv, &argc, tcc_strdup(p)); if (run) {
} optind--;
fclose(fp); /* argv[0] will be this file */
tcc_parse_args1(s, argc, argv); break;
dynarray_reset(&argv, &argc);
} else {
args_parser_add_file(s, r, pas->filetype);
if (pas->run) {
optind--;
/* argv[0] will be this file */
break;
}
} }
continue; continue;
} }
@ -2160,7 +2168,7 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break; break;
case TCC_OPTION_pthread: case TCC_OPTION_pthread:
parse_option_D(s, "_REENTRANT"); parse_option_D(s, "_REENTRANT");
pas->pthread = 1; s->args_pthread = 1;
break; break;
case TCC_OPTION_bench: case TCC_OPTION_bench:
s->do_bench = 1; s->do_bench = 1;
@ -2180,9 +2188,11 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
s->do_debug = 1; s->do_debug = 1;
break; break;
case TCC_OPTION_c: case TCC_OPTION_c:
x = TCC_OUTPUT_OBJ;
set_output_type:
if (s->output_type) if (s->output_type)
tcc_warning("-c: some compiler action already specified (%d)", s->output_type); tcc_warning("-%s: overriding compiler action already specified", popt->name);
s->output_type = TCC_OUTPUT_OBJ; s->output_type = x;
break; break;
case TCC_OPTION_d: case TCC_OPTION_d:
if (*optarg == '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" */ allow to use a tcc as a reference compiler for "make test" */
break; break;
case TCC_OPTION_shared: case TCC_OPTION_shared:
if (s->output_type) x = TCC_OUTPUT_DLL;
tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); goto set_output_type;
s->output_type = TCC_OUTPUT_DLL;
break;
case TCC_OPTION_soname: case TCC_OPTION_soname:
s->soname = tcc_strdup(optarg); s->soname = tcc_strdup(optarg);
break; break;
@ -2233,34 +2241,15 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break; break;
case TCC_OPTION_r: case TCC_OPTION_r:
/* generate a .o merging several output files */ /* 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->option_r = 1;
s->output_type = TCC_OUTPUT_OBJ; x = TCC_OUTPUT_OBJ;
break; goto set_output_type;
case TCC_OPTION_isystem: case TCC_OPTION_isystem:
tcc_add_sysinclude_path(s, optarg); tcc_add_sysinclude_path(s, optarg);
break; break;
case TCC_OPTION_iwithprefix: case TCC_OPTION_iwithprefix:
if (1) { snprintf(buf, sizeof buf, "{B}/%s", optarg);
char buf[1024]; tcc_add_sysinclude_path(s, buf);
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);
}
break; break;
case TCC_OPTION_nostdinc: case TCC_OPTION_nostdinc:
s->nostdinc = 1; s->nostdinc = 1;
@ -2275,12 +2264,10 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
#ifndef TCC_IS_NATIVE #ifndef TCC_IS_NATIVE
tcc_error("-run is not available in a cross compiler"); tcc_error("-run is not available in a cross compiler");
#endif #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); tcc_set_options(s, optarg);
pas->run = 1; run = 1;
break; x = TCC_OUTPUT_MEMORY;
goto set_output_type;
case TCC_OPTION_v: case TCC_OPTION_v:
do ++s->verbose; while (*optarg++ == 'v'); do ++s->verbose; while (*optarg++ == 'v');
break; break;
@ -2299,15 +2286,13 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
s->rdynamic = 1; s->rdynamic = 1;
break; break;
case TCC_OPTION_Wl: case TCC_OPTION_Wl:
if (pas->linker_arg.size) if (s->linker_arg.size)
--pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); --s->linker_arg.size, cstr_ccat(&s->linker_arg, ',');
cstr_cat(&pas->linker_arg, optarg, 0); cstr_cat(&s->linker_arg, optarg, 0);
break; break;
case TCC_OPTION_E: case TCC_OPTION_E:
if (s->output_type) x = TCC_OUTPUT_PREPROCESS;
tcc_warning("-E: some compiler action already specified (%d)", s->output_type); goto set_output_type;
s->output_type = TCC_OUTPUT_PREPROCESS;
break;
case TCC_OPTION_P: case TCC_OPTION_P:
s->Pflag = atoi(optarg) + 1; s->Pflag = atoi(optarg) + 1;
break; break;
@ -2327,25 +2312,20 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
break; break;
case TCC_OPTION_x: case TCC_OPTION_x:
if (*optarg == 'c') if (*optarg == 'c')
pas->filetype = TCC_FILETYPE_C; filetype = TCC_FILETYPE_C;
else else
if (*optarg == 'a') if (*optarg == 'a')
pas->filetype = TCC_FILETYPE_ASM_PP; filetype = TCC_FILETYPE_ASM_PP;
else else
if (*optarg == 'n') if (*optarg == 'n')
pas->filetype = 0; filetype = 0;
else else
tcc_warning("unsupported language '%s'", optarg); tcc_warning("unsupported language '%s'", optarg);
break; break;
case TCC_OPTION_O: case TCC_OPTION_O:
if (1) { x = atoi(optarg);
int opt = atoi(optarg); if (x > 0)
char *sym = "__OPTIMIZE__"; tcc_define_symbol(s, "__OPTIMIZE__", NULL);
if (opt)
tcc_define_symbol(s, sym, 0);
else
tcc_undefine_symbol(s, sym);
}
break; break;
case TCC_OPTION_pedantic: case TCC_OPTION_pedantic:
case TCC_OPTION_pipe: case TCC_OPTION_pipe:
@ -2358,62 +2338,55 @@ unsupported_option:
break; 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; 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; char **argv;
int ret, is_allocated = 0; int argc;
int ret, q, c;
if (!s->parse_args_state) { CString str;
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;
argc = 0, argv = NULL; argc = 0, argv = NULL;
for(;;) { for(;;) {
while (is_space(*str)) while (c = (unsigned char)*r, c && c <= ' ')
str++; ++r;
if (*str == '\0') if (c == 0)
break; break;
s1 = str; q = 0;
while (*str != '\0' && !is_space(*str)) cstr_new(&str);
str++; while (c = (unsigned char)*r, c) {
len = str - s1; ++r;
arg = tcc_malloc(len + 1); if (c == '\\' && (*r == '"' || *r == '\\')) {
pstrncpy(arg, s1, len); c = *r++;
dynarray_add((void ***)&argv, &argc, arg); } 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); ret = tcc_parse_args(s, argc, argv);
dynarray_reset(&argv, &argc); dynarray_reset(&argv, &argc);

36
tcc.c
View File

@ -92,7 +92,7 @@ static void help(void)
" -bench show compilation statistics\n" " -bench show compilation statistics\n"
" -xc -xa specify type of the next infile\n" " -xc -xa specify type of the next infile\n"
" - use stdin pipe as 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" "Preprocessor options:\n"
" -Idir add include path 'dir'\n" " -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\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); optind = tcc_parse_args(s, argc - 1, argv + 1);
if (s->do_bench)
start_time = getclock_us();
tcc_set_environment(s); tcc_set_environment(s);
if (optind == 0) { if (optind == 0) {
@ -272,17 +269,18 @@ int main(int argc, char **argv)
if (s->verbose) if (s->verbose)
display_info(s, 0); display_info(s, 0);
if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) { if (s->nb_files == 0) {
tcc_set_output_type(s, TCC_OUTPUT_MEMORY); if (optind == 1) {
display_info(s, 1); if (s->print_search_dirs || s->verbose == 2) {
return 0; tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
} display_info(s, 1);
return 1;
if (s->verbose && optind == 1) }
return 0; if (s->verbose)
return 1;
if (s->nb_files == 0) }
tcc_error("no input files\n"); tcc_error("no input files\n");
}
/* check -c consistency : only single file handled. XXX: checks file type */ /* check -c consistency : only single file handled. XXX: checks file type */
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { 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"); 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); tcc_set_output_type(s, s->output_type);
if (s->output_type == TCC_OUTPUT_PREPROCESS) { 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 */ /* compile or add each files or library */
for(i = ret = 0; i < s->nb_files && ret == 0; i++) { for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
struct filespec *f = s->files[i]; struct filespec *f = s->files[i];
@ -322,6 +325,8 @@ int main(int argc, char **argv)
} }
if (0 == ret) { if (0 == ret) {
if (s->do_bench)
tcc_print_stats(s, getclock_us() - start_time);
if (s->output_type == TCC_OUTPUT_MEMORY) { if (s->output_type == TCC_OUTPUT_MEMORY) {
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind); 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); tcc_delete(s);
return ret; return ret;
} }

16
tcc.h
View File

@ -638,14 +638,6 @@ struct sym_attr {
#endif #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) #if !defined(MEM_DEBUG)
#define tal_free(al, p) tal_free_impl(al, p) #define tal_free(al, p) tal_free_impl(al, p)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size) #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size)
@ -682,6 +674,7 @@ typedef struct tal_header_t {
#endif #endif
} tal_header_t; } tal_header_t;
struct TCCState { struct TCCState {
int verbose; /* if true, display some information during compilation */ int verbose; /* if true, display some information during compilation */
@ -860,7 +853,10 @@ struct TCCState {
int do_bench; /* option -bench */ int do_bench; /* option -bench */
int gen_deps; /* option -MD */ int gen_deps; /* option -MD */
char *deps_outfile; /* option -MF */ 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 { struct filespec {
@ -1312,8 +1308,6 @@ ST_FUNC void preprocess_delete(void);
ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC int tcc_preprocess(TCCState *s1);
ST_FUNC void skip(int c); ST_FUNC void skip(int c);
ST_FUNC NORETURN void expect(const char *msg); ST_FUNC NORETURN void expect(const char *msg);
ST_FUNC char *trimfront(char *p);
ST_FUNC char *trimback(char *a, char *e);
/* ------------ tccgen.c ------------ */ /* ------------ tccgen.c ------------ */

17
tccpe.c
View File

@ -1565,6 +1565,23 @@ quit:
return ret; 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) static int pe_load_def(TCCState *s1, int fd)
{ {

15
tccpp.c
View File

@ -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 */ /* Custom allocator for tiny objects */