tcctools.c: integrate tiny_libmaker/_impdef

usage:
    tcc -ar [rcsv] lib files...
    tcc -impdef lib.dll [-v] [-o lib.def]

also:
- support more files with -c: tcc -c f1.c f2.c ...
- fix a bug which caused tcc f1.c f2.S to produce no asm
- allow tcc -ar @listfile too
- change prototype: _void_ tcc_set_options(...)
- apply -Wl,-whole-archive when a librariy is given
  as libxxx.a also (not just for -lxxx)
This commit is contained in:
grischka
2017-02-18 09:55:34 +01:00
parent f34b1feaca
commit 2d3b9559bf
17 changed files with 998 additions and 917 deletions

212
libtcc.c
View File

@ -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);
}
/* read list file */
static void args_parser_listfile(TCCState *s, const char *filename)
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
{
int fd;
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, int optind, int *pargc, char ***pargv)
{
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)