aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2017-02-18 09:55:34 +0100
committergrischka <grischka>2017-02-18 09:55:34 +0100
commit2d3b9559bf569f137cefb7f8386a0dc58e33c81f (patch)
tree4da5267d5dd1bf907bdf82d7065c751a05757e6e
parentf34b1feaca557cd9da198610b67d4328fb0c7a84 (diff)
downloadtinycc-2d3b9559bf569f137cefb7f8386a0dc58e33c81f.tar.gz
tinycc-2d3b9559bf569f137cefb7f8386a0dc58e33c81f.tar.bz2
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)
-rw-r--r--Changelog1
-rw-r--r--Makefile20
-rw-r--r--TODO1
-rw-r--r--conftest.c22
-rw-r--r--lib/Makefile30
-rw-r--r--libtcc.c210
-rw-r--r--libtcc.h2
-rw-r--r--tcc.c335
-rw-r--r--tcc.h34
-rw-r--r--tccasm.c1
-rw-r--r--tccpe.c122
-rw-r--r--tcctools.c547
-rw-r--r--tests/tcctest.c2
-rw-r--r--win32/build-tcc.bat31
-rw-r--r--win32/tcc-win32.txt22
-rw-r--r--win32/tools/tiny_impdef.c249
-rw-r--r--win32/tools/tiny_libmaker.c278
17 files changed, 994 insertions, 913 deletions
diff --git a/Changelog b/Changelog
index a8928fc..8264d1d 100644
--- a/Changelog
+++ b/Changelog
@@ -7,6 +7,7 @@ User interface:
- -mms-bitfields option (David Mertens)
- -include <file> option (Michael Matz)
- @listfile support (Vlad Vissoultchev)
+- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
(Andrew Aladjev, Urs Janssen)
diff --git a/Makefile b/Makefile
index c13ce37..f9008ff 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@ LIBS =
ifdef CONFIG_WIN32
ifneq ($(DISABLE_STATIC),no)
LIBTCC = libtcc.dll
+ LIBTCCDEF = libtcc.def
endif
else
LIBS=-lm
@@ -82,7 +83,7 @@ ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CRO
ARM64_CROSS = arm64-tcc$(EXESUF)
C67_CROSS = c67-tcc$(EXESUF)
-CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
+CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
@@ -94,7 +95,6 @@ ARM64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
ifdef CONFIG_WIN32
- PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
ifeq ($(ARCH),x86-64)
NATIVE_FILES=$(WIN64_FILES)
PROGS_CROSS=$(WIN32_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS)
@@ -124,11 +124,7 @@ NATIVE_FILES=$(ARM64_FILES)
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)
endif
-ifeq ($(TARGETOS),Darwin)
- PROGS += tiny_libmaker$(EXESUF)
-endif
-
-TCCLIBS = $(LIBTCC1) $(LIBTCC)
+TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
ifdef CONFIG_CROSS
@@ -179,7 +175,7 @@ $(ARM64_CROSS): $(ARM64_FILES)
# libtcc generation and test
ifndef ONE_SOURCE
-LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
+LIBTCC_OBJ = $(filter-out tcc.o tcctools.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
else
LIBTCC_OBJ = libtcc.o
@@ -187,6 +183,8 @@ LIBTCC_INC = $(NATIVE_FILES)
libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
endif
+tcc.o : tcctools.c
+
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
$(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS)
@@ -199,9 +197,11 @@ libtcc.so: $(LIBTCC_OBJ)
libtcc.so: CFLAGS+=-fPIC
# windows : libtcc.dll
-libtcc.dll : $(LIBTCC_OBJ) tiny_impdef$(EXESUF)
+libtcc.dll : $(LIBTCC_OBJ)
$(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)
- ./tiny_impdef $@
+
+libtcc.def : libtcc.dll tcc$(EXESUF)
+ ./tcc$(EXESUF) -impdef $< -o $@
libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL
diff --git a/TODO b/TODO
index 5e6f7bf..3adeef2 100644
--- a/TODO
+++ b/TODO
@@ -2,6 +2,7 @@ TODO list:
Bugs:
+- i386 fastcall is mostly wrong
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
optimized gcc/msc code
- see transparent union pb in /urs/include/sys/socket.h
diff --git a/conftest.c b/conftest.c
index fa07a1b..2824cc8 100644
--- a/conftest.c
+++ b/conftest.c
@@ -1,9 +1,9 @@
#include <stdio.h>
/* Define architecture */
-#if defined(__i386__)
+#if defined(__i386__) || defined _M_IX86
# define TRIPLET_ARCH "i386"
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined _M_AMD64
# define TRIPLET_ARCH "x86_64"
#elif defined(__arm__)
# define TRIPLET_ARCH "arm"
@@ -18,6 +18,8 @@
# define TRIPLET_OS "linux"
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
# define TRIPLET_OS "kfreebsd"
+#elif defined _WIN32
+# define TRIPLET_OS "win32"
#elif !defined (__GNU__)
# define TRIPLET_OS "unknown"
#endif
@@ -33,7 +35,9 @@
# define TRIPLET_ABI "gnu"
#endif
-#ifdef __GNU__
+#if defined _WIN32
+# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS
+#elif defined __GNU__
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
#else
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
@@ -59,6 +63,13 @@ int main(int argc, char *argv[])
case 'v':
printf("%d\n", __GNUC__);
break;
+#elif defined __TINYC__
+ case 'v':
+ puts("0");
+ break;
+ case 'm':
+ printf("%d\n", __TINYC__);
+ break;
#else
case 'm':
case 'v':
@@ -68,9 +79,8 @@ int main(int argc, char *argv[])
case 't':
puts(TRIPLET);
break;
- case -1:
- /* to test -Wno-unused-result */
- fread(NULL, 1, 1, NULL);
+
+ default:
break;
}
return 0;
diff --git a/lib/Makefile b/lib/Makefile
index 4cc8093..85dc5cf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -20,9 +20,6 @@ ifndef TARGET
TARGET = x86_64
else ifeq ($(ARCH),arm)
TARGET = arm
- # using gcc, need asm
- XCC = $(CC)
- XFLAGS = $(CFLAGS) -fPIC
else ifeq ($(ARCH),arm64)
TARGET = arm64
endif
@@ -37,6 +34,9 @@ cross : $(DIR)/libtcc1.a
native : TCC = $(TOP)/tcc$(EXESUF)
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
+XCC = $(TCC) -B$(TOPSRC)
+XAR = $(TCC) -ar
+
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
ARM_O = libtcc1.o armeabi.o alloca-arm.o
@@ -47,53 +47,43 @@ ifeq "$(TARGET)" "i386-win32"
OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
else ifeq "$(TARGET)" "x86_64-win32"
OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O))
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
else ifeq "$(TARGET)" "i386"
OBJ = $(addprefix $(DIR)/,$(I386_O))
TGT = -DTCC_TARGET_I386
- XCC ?= $(TCC) -B$(TOPSRC)
else ifeq "$(TARGET)" "x86_64"
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
TGT = -DTCC_TARGET_X86_64
- XCC ?= $(TCC) -B$(TOPSRC)
else ifeq "$(TARGET)" "arm"
OBJ = $(addprefix $(DIR)/,$(ARM_O))
TGT = -DTCC_TARGET_ARM
- XCC ?= $(TCC) -B$(TOPSRC)
+ # using gcc, need asm
+ XCC = $(CC)
+ XFLAGS = $(CFLAGS) -fPIC
+ XAR = $(AR)
else ifeq "$(TARGET)" "arm64"
OBJ = $(addprefix $(DIR)/,$(ARM64_O))
TGT = -DTCC_TARGET_ARM64
- XCC ?= $(TCC) -B$(TOPSRC)
else
$(error libtcc1.a not supported on target '$(TARGET)')
endif
ifeq ($(TARGETOS),Darwin)
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
XFLAGS += -D_ANSI_SOURCE
BCHECK_O =
endif
-ifdef XAR
-AR = $(XAR)
-endif
-
-$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
- $(AR) rcs $@ $(OBJ)
+$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ)
+ $(XAR) rcs $@ $(OBJ)
$(DIR)/%.o : %.c
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
$(DIR)/%.o : %.S
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
-# windows : utilities
-$(DIR)/tiny_%$(EXESUF) : $(TOPSRC)/win32/tools/tiny_%.c
- $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(TGT)
-$(OBJ) $(XAR) : $(DIR)/exists
+$(OBJ) : $(DIR)/exists
%/exists :
mkdir -p $(DIR)
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)
diff --git a/libtcc.h b/libtcc.h
index 799ffd8..a1b31e3 100644
--- a/libtcc.h
+++ b/libtcc.h
@@ -27,7 +27,7 @@ LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
void (*error_func)(void *opaque, const char *msg));
/* set options as from command line (multiple supported) */
-LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
+LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
/*****************************/
/* preprocessor */
diff --git a/tcc.c b/tcc.c
index c5a1f0e..2ca3bb8 100644
--- a/tcc.c
+++ b/tcc.c
@@ -23,69 +23,7 @@
#else
#include "tcc.h"
#endif
-
-static void print_paths(const char *msg, char **paths, int nb_paths)
-{
- int i;
- printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
- for(i = 0; i < nb_paths; i++)
- printf(" %s\n", paths[i]);
-}
-
-static void display_info(TCCState *s, int what)
-{
- switch (what) {
- case 0:
- printf("tcc version %s ("
-#ifdef TCC_TARGET_I386
- "i386"
-#elif defined TCC_TARGET_X86_64
- "x86-64"
-#elif defined TCC_TARGET_C67
- "C67"
-#elif defined TCC_TARGET_ARM
- "ARM"
-# ifdef TCC_ARM_HARDFLOAT
- " Hard Float"
-# endif
-#elif defined TCC_TARGET_ARM64
- "AArch64"
-# ifdef TCC_ARM_HARDFLOAT
- " Hard Float"
-# endif
-#endif
-#ifdef TCC_TARGET_PE
- " Windows"
-#elif defined(__APPLE__)
- /* Current Apple OS name as of 2016 */
- " macOS"
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- " FreeBSD"
-#elif defined(__DragonFly__)
- " DragonFly BSD"
-#elif defined(__NetBSD__)
- " NetBSD"
-#elif defined(__OpenBSD__)
- " OpenBSD"
-#elif defined(__linux__)
- " Linux"
-#else
- " Unidentified system"
-#endif
- ")\n", TCC_VERSION);
- break;
- case 1:
- printf("install: %s\n", s->tcc_lib_path);
- /* print_paths("programs", NULL, 0); */
- print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
- print_paths("libraries", s->library_paths, s->nb_library_paths);
-#ifndef TCC_TARGET_PE
- print_paths("crt", s->crt_paths, s->nb_crt_paths);
- printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
-#endif
- break;
- }
-}
+#include "tcctools.c"
static void help(void)
{
@@ -100,7 +38,8 @@ static void help(void)
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
" -w disable all warnings\n"
" -v show version\n"
- " -vv show included files (as sole argument: show search paths)\n"
+ " -vv show included files (as sole argument show search paths)\n"
+ " -h show this help\n"
" -bench show compilation statistics\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
@@ -147,114 +86,74 @@ static void help(void)
#ifdef TCC_TARGET_X86_64
" -mno-sse disable floats on x86-64\n"
#endif
+ "Tools:\n"
+ " create library : tcc -ar [rcsv] lib.a files\n"
+#ifdef TCC_TARGET_PE
+ " create .def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
+#endif
);
}
-/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-#ifdef _WIN32
-#include <process.h>
-
-static char *str_replace(const char *str, const char *p, const char *r)
-{
- const char *s, *s0;
- char *d, *d0;
- int sl, pl, rl;
-
- sl = strlen(str);
- pl = strlen(p);
- rl = strlen(r);
- for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
- for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
- if (d) {
- memcpy(d, s0, sl = s - s0), d += sl;
- memcpy(d, r, rl), d += rl;
- } else
- sl += rl - pl;
- }
- if (d) {
- strcpy(d, s0);
- return d0;
- }
- }
-}
-static int execvp_win32(const char *prog, char **argv)
-{
- int ret; char **p;
- /* replace all " by \" */
- for (p = argv; *p; ++p)
- if (strchr(*p, '"'))
- *p = str_replace(*p, "\"", "\\\"");
- ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
- if (-1 == ret)
- return ret;
- cwait(&ret, ret, WAIT_CHILD);
- exit(ret);
-}
-#define execvp execvp_win32
-#endif
-static void exec_other_tcc(TCCState *s, char **argv, int option)
+static void version(void)
{
- char child_path[4096], *a0 = argv[0]; const char *target;
- int l;
-
- switch (option) {
-
+ printf("tcc version %s ("
#ifdef TCC_TARGET_I386
- case 32: break;
- case 64: target = "x86_64";
-#else
- case 64: break;
- case 32: target = "i386";
-
+ "i386"
+#elif defined TCC_TARGET_X86_64
+ "x86-64"
+#elif defined TCC_TARGET_C67
+ "C67"
+#elif defined TCC_TARGET_ARM
+ "ARM"
+# ifdef TCC_ARM_HARDFLOAT
+ " Hard Float"
+# endif
+#elif defined TCC_TARGET_ARM64
+ "AArch64"
+# ifdef TCC_ARM_HARDFLOAT
+ " Hard Float"
+# endif
#endif
- l = tcc_basename(a0) - a0;
- snprintf(child_path, sizeof child_path,
#ifdef TCC_TARGET_PE
- "%.*s%s-win32-tcc"
+ " Windows"
+#elif defined(__APPLE__)
+ /* Current Apple OS name as of 2016 */
+ " macOS"
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ " FreeBSD"
+#elif defined(__DragonFly__)
+ " DragonFly BSD"
+#elif defined(__NetBSD__)
+ " NetBSD"
+#elif defined(__OpenBSD__)
+ " OpenBSD"
+#elif defined(__linux__)
+ " Linux"
#else
- "%.*s%s-tcc"
+ " Unidentified system"
#endif
- , l, a0, target);
- if (strcmp(a0, child_path)) {
- if (s->verbose > 0)
- printf("tcc: using '%s'\n", child_path + l), fflush(stdout);
- execvp(argv[0] = child_path, argv);
- }
- tcc_error("'%s' not found", child_path + l);
- }
+ ")\n", TCC_VERSION);
}
-#else
-#define exec_other_tcc(s, argv, option)
-#endif
-static void gen_makedeps(TCCState *s, const char *target, const char *filename)
+static void print_dirs(const char *msg, char **paths, int nb_paths)
{
- FILE *depout;
- char buf[1024];
int i;
+ printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
+ for(i = 0; i < nb_paths; i++)
+ printf(" %s\n", paths[i]);
+}
- if (!filename) {
- /* compute filename automatically: dir/file.o -> dir/file.d */
- snprintf(buf, sizeof buf, "%.*s.d",
- (int)(tcc_fileextension(target) - target), target);
- filename = buf;
- }
-
- if (s->verbose)
- printf("<- %s\n", filename);
-
- /* XXX return err codes instead of error() ? */
- depout = fopen(filename, "w");
- if (!depout)
- tcc_error("could not open '%s'", filename);
-
- fprintf(depout, "%s: \\\n", target);
- for (i=0; i<s->nb_target_deps; ++i)
- fprintf(depout, " %s \\\n", s->target_deps[i]);
- fprintf(depout, "\n");
- fclose(depout);
+static void print_search_dirs(TCCState *s)
+{
+ printf("install: %s\n", s->tcc_lib_path);
+ /* print_dirs("programs", NULL, 0); */
+ print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
+ print_dirs("libraries", s->library_paths, s->nb_library_paths);
+#ifndef TCC_TARGET_PE
+ print_dirs("crt", s->crt_paths, s->nb_crt_paths);
+ printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
+#endif
}
static char *default_outputfile(TCCState *s, const char *first_file)
@@ -296,109 +195,113 @@ static unsigned getclock_ms(void)
int main(int argc, char **argv)
{
TCCState *s;
- int ret, optind, i;
+ int ret, opt, n = 0;
unsigned start_time = 0;
- const char *first_file = NULL;
+ const char *first_file;
+redo:
s = tcc_new();
+ opt = tcc_parse_args(s, &argc, &argv, 1);
- optind = tcc_parse_args(s, argc - 1, argv + 1);
-
- tcc_set_environment(s);
+ if (n == 0) {
+ if (opt == OPT_HELP)
+ return help(), 1;
+ if (opt == OPT_M32 || opt == OPT_M64)
+ tcc_tool_cross(s, argv, opt); /* never returns */
+ if (s->verbose)
+ version();
+ if (opt == OPT_AR)
+ return tcc_tool_ar(s, argc, argv);
+#ifdef TCC_TARGET_PE
+ if (opt == OPT_IMPDEF)
+ return tcc_tool_impdef(s, argc, argv);
+#endif
+ if (opt == OPT_V)
+ return 0;
- if (optind == 0) {
- help();
- return 1;
- }
+ tcc_set_environment(s);
- if (s->cross_target)
- exec_other_tcc(s, argv, s->cross_target);
+ if (opt == OPT_PRINT_DIRS) {
+ /* initialize search dirs */
+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+ print_search_dirs(s);
+ return 0;
+ }
- if (s->verbose)
- display_info(s, 0);
+ n = s->nb_files;
+ if (n == 0)
+ tcc_error("no input files\n");
- 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->output_type == TCC_OUTPUT_PREPROCESS) {
+ if (!s->outfile) {
+ s->ppfp = stdout;
+ } else {
+ s->ppfp = fopen(s->outfile, "w");
+ if (!s->ppfp)
+ tcc_error("could not write '%s'", s->outfile);
}
- if (s->verbose)
- return 1;
+ } else if (s->output_type == TCC_OUTPUT_OBJ) {
+ if (s->nb_libraries != 0 && !s->option_r)
+ tcc_error("cannot specify libraries with -c");
+ if (n > 1 && s->outfile)
+ tcc_error("cannot specify output file with -c many files");
+ } else {
+ if (s->option_pthread)
+ tcc_set_options(s, "-lpthread");
}
- 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) {
- if (s->nb_libraries != 0)
- tcc_error("cannot specify libraries with -c");
- /* accepts only a single input file */
- if (s->nb_files != 1)
- tcc_error("cannot specify multiple files with -c");
+ if (s->do_bench)
+ start_time = getclock_ms();
}
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) {
- if (!s->outfile) {
- s->ppfp = stdout;
- } else {
- s->ppfp = fopen(s->outfile, "w");
- if (!s->ppfp)
- tcc_error("could not write '%s'", s->outfile);
- }
- } else if (s->output_type != TCC_OUTPUT_OBJ) {
- if (s->option_pthread)
- tcc_set_options(s, "-lpthread");
- }
-
- if (s->do_bench)
- start_time = getclock_ms();
-
/* compile or add each files or library */
- for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
- struct filespec *f = s->files[i];
- if (f->type >= AFF_TYPE_LIB) {
- s->alacarte_link = f->type == AFF_TYPE_LIB;
+ for (first_file = NULL, ret = 0;;) {
+ struct filespec *f = s->files[s->nb_files - n];
+ s->filetype = f->type;
+ s->alacarte_link = f->alacarte;
+ if (f->type == AFF_TYPE_LIB) {
if (tcc_add_library_err(s, f->name) < 0)
ret = 1;
} else {
if (1 == s->verbose)
printf("-> %s\n", f->name);
- s->filetype = f->type;
- if (tcc_add_file(s, f->name) < 0)
- ret = 1;
if (!first_file)
first_file = f->name;
+ if (tcc_add_file(s, f->name) < 0)
+ ret = 1;
}
- s->filetype = AFF_TYPE_NONE;
+ s->filetype = 0;
s->alacarte_link = 1;
+ if (ret || --n == 0 || s->output_type == TCC_OUTPUT_OBJ)
+ break;
}
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile)
fclose(s->ppfp);
-
} else if (0 == ret) {
if (s->output_type == TCC_OUTPUT_MEMORY) {
#ifdef TCC_IS_NATIVE
- ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
+ ret = tcc_run(s, argc, argv);
#endif
} else {
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
- ret = !!tcc_output_file(s, s->outfile);
- if (s->gen_deps && !ret)
+ if (tcc_output_file(s, s->outfile))
+ ret = 1;
+ else if (s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
- if (s->do_bench)
+ if (s->do_bench && ret == 0 && n == 0)
tcc_print_stats(s, getclock_ms() - start_time);
tcc_delete(s);
+ if (ret == 0 && n)
+ goto redo; /* compile more files with -c */
return ret;
}
diff --git a/tcc.h b/tcc.h
index 3494836..fcf5780 100644
--- a/tcc.h
+++ b/tcc.h
@@ -767,17 +767,19 @@ struct TCCState {
int nb_libraries; /* number of libs thereof */
int filetype;
char *outfile; /* output filename */
- int cross_target; /* -m32/-m64 */
- int print_search_dirs; /* option */
int option_r; /* option -r */
int do_bench; /* option -bench */
int gen_deps; /* option -MD */
char *deps_outfile; /* option -MF */
int option_pthread; /* -pthread option */
+ int argc;
+ char **argv;
};
struct filespec {
- char type, name[1];
+ char type;
+ char alacarte;
+ char name[1];
};
/* The current value can be: */
@@ -1091,7 +1093,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#define realloc(p, s) use_tcc_realloc(p, s)
#undef strdup
#define strdup(s) use_tcc_strdup(s)
-PUB_FUNC void tcc_memstats(int bench);
+PUB_FUNC void tcc_memcheck(void);
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
PUB_FUNC void tcc_warning(const char *fmt, ...);
@@ -1131,14 +1133,12 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#define AFF_TYPE_ASMPP 3
#define AFF_TYPE_BIN 4
#define AFF_TYPE_LIB 5
-#define AFF_TYPE_LIBWH 6
/* values from tcc_object_type(...) */
#define AFF_BINTYPE_REL 1
#define AFF_BINTYPE_DYN 2
#define AFF_BINTYPE_AR 3
#define AFF_BINTYPE_C67 4
-
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
#ifndef TCC_TARGET_PE
@@ -1149,12 +1149,21 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
-PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
+PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
PUB_FUNC void tcc_set_environment(TCCState *s);
#ifdef _WIN32
ST_FUNC char *normalize_slashes(char *path);
#endif
+/* tcc_parse_args return codes: */
+#define OPT_HELP 1
+#define OPT_V 3
+#define OPT_PRINT_DIRS 4
+#define OPT_AR 5
+#define OPT_IMPDEF 6
+#define OPT_M32 32
+#define OPT_M64 64
+
/* ------------ tccpp.c ------------ */
ST_DATA struct BufferedFile *file;
@@ -1567,6 +1576,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
#ifdef TCC_TARGET_X86_64
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
#endif
+PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
/* symbol properties stored in Elf32_Sym->st_other */
# define ST_PE_EXPORT 0x10
# define ST_PE_IMPORT 0x20
@@ -1595,6 +1605,16 @@ ST_FUNC void tcc_set_num_callers(int n);
ST_FUNC void tcc_run_free(TCCState *s1);
#endif
+/* ------------ tcctools.c ----------------- */
+#if 0 /* included in tcc.c */
+ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
+#ifdef TCC_TARGET_PE
+ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
+#endif
+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
+ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
+#endif
+
/********************************************************/
#undef ST_DATA
#ifdef ONE_SOURCE
diff --git a/tccasm.c b/tccasm.c
index b7d5881..0999a03 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -1005,6 +1005,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
/* default section is text */
cur_text_section = text_section;
ind = cur_text_section->data_offset;
+ nocode_wanted = 0;
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
symbols can be safely used */
diff --git a/tccpe.c b/tccpe.c
index cf2e475..50690df 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -962,7 +962,7 @@ static void pe_build_exports(struct pe_info *pe)
} else {
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
if (pe->s1->verbose)
- printf("<- %s (%d symbols)\n", buf, sym_count);
+ printf("<- %s (%d symbol%s)\n", buf, sym_count, "s" + (sym_count < 2));
}
#endif
@@ -1543,6 +1543,102 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
return len == read(fd, buffer, len);
}
+/* ------------------------------------------------------------- */
+
+PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
+{
+ int l, i, n, n0, ret;
+ char *p;
+ int fd;
+
+ IMAGE_SECTION_HEADER ish;
+ IMAGE_EXPORT_DIRECTORY ied;
+ IMAGE_DOS_HEADER dh;
+ IMAGE_FILE_HEADER ih;
+ DWORD sig, ref, addr, ptr, namep;
+#ifdef TCC_TARGET_X86_64
+ IMAGE_OPTIONAL_HEADER64 oh;
+#else
+ IMAGE_OPTIONAL_HEADER32 oh;
+#endif
+ int pef_hdroffset, opt_hdroffset, sec_hdroffset;
+
+ n = n0 = 0;
+ p = NULL;
+ ret = -1;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ goto the_end_1;
+ ret = 1;
+
+ if (!read_mem(fd, 0, &dh, sizeof dh))
+ goto the_end;
+ if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
+ goto the_end;
+ if (sig != 0x00004550)
+ goto the_end;
+ pef_hdroffset = dh.e_lfanew + sizeof sig;
+ if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
+ goto the_end;
+ if (IMAGE_FILE_MACHINE != ih.Machine) {
+ if (ih.Machine == 0x014C)
+ ret = 32;
+ else if (ih.Machine == 0x8664)
+ ret = 64;
+ goto the_end;
+ }
+ opt_hdroffset = pef_hdroffset + sizeof ih;
+ sec_hdroffset = opt_hdroffset + sizeof oh;
+ if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
+ goto the_end;
+
+ if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
+ goto the_end_0;
+
+ addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ //printf("addr: %08x\n", addr);
+ for (i = 0; i < ih.NumberOfSections; ++i) {
+ if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
+ goto the_end;
+ //printf("vaddr: %08x\n", ish.VirtualAddress);
+ if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
+ goto found;
+ }
+ goto the_end_0;
+
+found:
+ ref = ish.VirtualAddress - ish.PointerToRawData;
+ if (!read_mem(fd, addr - ref, &ied, sizeof ied))
+ goto the_end;
+
+ namep = ied.AddressOfNames - ref;
+ for (i = 0; i < ied.NumberOfNames; ++i) {
+ if (!read_mem(fd, namep, &ptr, sizeof ptr))
+ goto the_end;
+ namep += sizeof ptr;
+ for (l = 0;;) {
+ if (n+1 >= n0)
+ p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
+ if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
+ tcc_free(p), p = NULL;
+ goto the_end;
+ }
+ if (p[n++] == 0)
+ break;
+ }
+ }
+ if (p)
+ p[n] = 0;
+the_end_0:
+ ret = 0;
+the_end:
+ close(fd);
+the_end_1:
+ *pp = p;
+ return ret;
+}
+
/* -------------------------------------------------------------
* This is for compiled windows resources in 'coff' format
* as generated by 'windres.exe -O coff ...'.
@@ -1660,20 +1756,20 @@ quit:
}
/* ------------------------------------------------------------- */
-#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
-#include "win32/tools/tiny_impdef.c"
-
-static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
+static int pe_load_dll(TCCState *s1, const char *filename)
{
char *p, *q;
- int index;
- p = get_export_names(fd);
- if (!p)
+ int index, ret;
+
+ ret = tcc_get_dllexports(filename, &p);
+ if (ret) {
return -1;
- index = add_dllref(s1, dllname);
- for (q = p; *q; q += 1 + strlen(q))
- pe_putimport(s1, index, q, 0);
- tcc_free(p);
+ } else if (p) {
+ index = add_dllref(s1, tcc_basename(filename));
+ for (q = p; *q; q += 1 + strlen(q))
+ pe_putimport(s1, index, q, 0);
+ tcc_free(p);
+ }
return 0;
}
@@ -1687,7 +1783,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
else if (pe_load_res(s1, fd) == 0)
ret = 0;
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
- ret = pe_load_dll(s1, tcc_basename(filename), fd);
+ ret = pe_load_dll(s1, filename);
return ret;
}
diff --git a/tcctools.c b/tcctools.c
new file mode 100644
index 0000000..235b783
--- /dev/null
+++ b/tcctools.c
@@ -0,0 +1,547 @@
+/* -------------------------------------------------------------- */
+/*
+ * TCC - Tiny C Compiler
+ *
+ * tcctools.c - extra tools and and -m32/64 support
+ *
+ */
+
+/* -------------------------------------------------------------- */
+/*
+ * This program is for making libtcc1.a without ar
+ * tiny_libmaker - tiny elf lib maker
+ * usage: tiny_libmaker [lib] files...
+ * Copyright (c) 2007 Timppa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "tcc.h"
+
+//#define ARMAG "!<arch>\n"
+#define ARFMAG "`\n"
+
+typedef struct {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6];
+ char ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+} ArHdr;
+
+static unsigned long le2belong(unsigned long ul) {
+ return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
+ ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
+}
+
+/* Returns 1 if s contains any of the chars of list, else 0 */
+static int contains_any(const char *s, const char *list) {
+ const char *l;
+ for (; *s; s++) {
+ for (l = list; *l; l++) {
+ if (*s == *l)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int ar_usage(int ret) {
+ fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n");
+ fprintf(stderr, "create library ([abdioptxN] not supported).\n");
+ return ret;
+}
+
+ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
+{
+ static ArHdr arhdr = {
+ "/ ",
+ " ",
+ "0 ",
+ "0 ",
+ "0 ",
+ " ",
+ ARFMAG
+ };
+
+ static ArHdr arhdro = {
+ " ",
+ " ",
+ "0 ",
+ "0 ",
+ "0 ",
+ " ",
+ ARFMAG
+ };
+
+ FILE *fi, *fh = NULL, *fo = NULL;
+ ElfW(Ehdr) *ehdr;
+ ElfW(Shdr) *shdr;
+ ElfW(Sym) *sym;
+ int i, fsize, i_lib, i_obj;
+ char *buf, *shstr, *symtab = NULL, *strtab = NULL;
+ int symtabsize = 0;//, strtabsize = 0;
+ char *anames = NULL;
+ int *afpos = NULL;
+ int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
+ char tfile[260], stmp[20];
+ char *file, *name;
+ int ret = 2;
+ char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
+ int verbose = 0;
+
+ i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
+ for (i = 1; i < argc; i++) {
+ const char *a = argv[i];
+ if (*a == '-' && strstr(a, "."))
+ ret = 1; // -x.y is always invalid (same as gnu ar)
+ if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
+ if (contains_any(a, ops_conflict))
+ ret = 1;
+ if (strstr(a, "v"))
+ verbose = 1;
+ } else { // lib or obj files: don't abort - keep validating all args.
+ if (!i_lib) // first file is the lib
+ i_lib = i;
+ else if (!i_obj) // second file is the first obj
+ i_obj = i;
+ }
+ }
+
+ if (!i_obj) // i_obj implies also i_lib. we require both.
+ ret = 1;
+
+ if (ret == 1)
+ return ar_usage(ret);
+
+ if ((fh = fopen(argv[i_lib], "wb")) == NULL)
+ {
+ fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]);
+ goto the_end;
+ }
+
+ sprintf(tfile, "%s.tmp", argv[i_lib]);
+ if ((fo = fopen(tfile, "wb+")) == NULL)
+ {
+ fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile);
+ goto the_end;
+ }
+
+ funcmax = 250;
+ afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
+ memcpy(&arhdro.ar_mode, "100666", 6);
+
+ // i_obj = first input object file
+ while (i_obj < argc)
+ {
+ if (*argv[i_obj] == '-') { // by now, all options start with '-'
+ i_obj++;
+ continue;
+ }
+ if ((fi = fopen(argv[i_obj], "rb")) == NULL) {
+ fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]);
+ goto the_end;
+ }
+ if (verbose)
+ printf("a - %s\n", argv[i_obj]);
+
+ fseek(fi, 0, SEEK_END);
+ fsize = ftell(fi);
+ fseek(fi, 0, SEEK_SET);
+ buf = tcc_malloc(fsize + 1);
+ fread(buf, fsize, 1, fi);
+ fclose(fi);
+
+ // elf header
+ ehdr = (ElfW(Ehdr) *)buf;
+ if (ehdr->e_ident[4] != ELFCLASSW)
+ {
+ fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]);
+ goto the_end;
+ }
+
+ shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
+ shstr = (char *)(buf + shdr->sh_offset);
+ for (i = 0; i < ehdr->e_shnum; i++)
+ {
+ shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
+ if (!shdr->sh_offset)
+ continue;
+ if (shdr->sh_type == SHT_SYMTAB)
+ {
+ symtab = (char *)(buf + shdr->sh_offset);
+ symtabsize = shdr->sh_size;
+ }
+ if (shdr->sh_type == SHT_STRTAB)
+ {
+ if (!strcmp(shstr + shdr->sh_name, ".strtab"))
+ {
+ strtab = (char *)(buf + shdr->sh_offset);
+ //strtabsize = shdr->sh_size;
+ }
+ }
+ }
+
+ if (symtab && symtabsize)
+ {
+ int nsym = symtabsize / sizeof(ElfW(Sym));
+ //printf("symtab: info size shndx name\n");
+ for (i = 1; i < nsym; i++)
+ {
+ sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
+ if (sym->st_shndx &&
+ (sym->st_info == 0x10
+ || sym->st_info == 0x11
+ || sym->st_info == 0x12
+ )) {
+ //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
+ istrlen = strlen(strtab + sym->st_name)+1;
+ anames = tcc_realloc(anames, strpos+istrlen);
+ strcpy(anames + strpos, strtab + sym->st_name);
+ strpos += istrlen;
+ if (++funccnt >= funcmax) {
+ funcmax += 250;
+ afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
+ }
+ afpos[funccnt] = fpos;
+ }
+ }
+ }
+
+ file = argv[i_obj];
+ for (name = strchr(file, 0);
+ name > file && name[-1] != '/' && name[-1] != '\\';
+ --name);
+ istrlen = strlen(name);
+ if (istrlen >= sizeof(arhdro.ar_name))
+ istrlen = sizeof(arhdro.ar_name) - 1;
+ memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
+ memcpy(arhdro.ar_name, name, istrlen);
+ arhdro.ar_name[istrlen] = '/';
+ sprintf(stmp, "%-10d", fsize);
+ memcpy(&arhdro.ar_size, stmp, 10);
+ fwrite(&arhdro, sizeof(arhdro), 1, fo);
+ fwrite(buf, fsize, 1, fo);
+ tcc_free(buf);
+ i_obj++;
+ fpos += (fsize + sizeof(arhdro));
+ }
+ hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
+ fpos = 0;
+ if ((hofs & 1)) // align
+ hofs++, fpos = 1;
+ // write header
+ fwrite("!<arch>\n", 8, 1, fh);
+ sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
+ memcpy(&arhdr.ar_size, stmp, 10);
+ fwrite(&arhdr, sizeof(arhdr), 1, fh);
+ afpos[0] = le2belong(funccnt);
+ for (i=1; i<=funccnt; i++)
+ afpos[i] = le2belong(afpos[i] + hofs);
+ fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
+ fwrite(anames, strpos, 1, fh);
+ if (fpos)
+ fwrite("", 1, 1, fh);
+ // write objects
+ fseek(fo, 0, SEEK_END);
+ fsize = ftell(fo);
+ fseek(fo, 0, SEEK_SET);
+ buf = tcc_malloc(fsize + 1);
+ fread(buf, fsize, 1, fo);
+ fwrite(buf, fsize, 1, fh);
+ tcc_free(buf);
+ ret = 0;
+the_end:
+ if (anames)
+ tcc_free(anames);
+ if (afpos)
+ tcc_free(afpos);
+ if (fh)
+ fclose(fh);
+ if (fo)
+ fclose(fo), remove(tfile);
+ return ret;
+}
+
+/* -------------------------------------------------------------- */
+/*
+ * tiny_impdef creates an export definition file (.def) from a dll
+ * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
+ *
+ * Copyright (c) 2005,2007 grischka
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef TCC_TARGET_PE
+
+ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
+{
+ int ret, v, i;
+ char infile[MAX_PATH];
+ char outfile[MAX_PATH];
+
+ const char *file;
+ char *p, *q;
+ FILE *fp, *op;
+
+#ifdef _WIN32
+ char path[MAX_PATH];
+#endif
+
+ infile[0] = outfile[0] = 0;
+ fp = op = NULL;
+ ret = 1;
+ p = NULL;
+ v = 0;
+
+ for (i = 1; i < argc; ++i) {
+ const char *a = argv[i];
+ if ('-' == a[0]) {
+ if (0 == strcmp(a, "-v")) {
+ v = 1;
+ } else if (0 == strcmp(a, "-o")) {
+ if (++i == argc)
+ goto usage;
+ strcpy(outfile, argv[i]);
+ } else
+ goto usage;
+ } else if (0 == infile[0])
+ strcpy(infile, a);
+ else
+ goto usage;
+ }
+
+ if (0 == infile[0]) {
+usage:
+ fprintf(stderr,
+ "usage: tcc -impdef library.dll [-v] [-o outputfile]\n"
+ "create export definition file (.def) from dll\n"
+ );
+ goto the_end;
+ }
+
+ if (0 == outfile[0]) {
+ strcpy(outfile, tcc_basename(infile));
+ q = strrchr(outfile, '.');
+ if (NULL == q)
+ q = strchr(outfile, 0);
+ strcpy(q, ".def");
+ }
+
+ file = infile;
+#ifdef _WIN32
+ if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
+ file = path;
+#endif
+ ret = tcc_get_dllexports(file, &p);
+ if (ret || !p) {
+ fprintf(stderr, "tcc: impdef: %s '%s'\n",
+ ret == 32 ? "can't read symbols from 32bit" :
+ ret == 64 ? "can't read symbols from 64bit" :
+ ret == -1 ? "can't find file" :
+ ret == 0 ? "no symbols found in" :
+ "unknown file type", file);
+ ret = 1;
+ goto the_end;
+ }
+
+ if (v)
+ printf("-> %s\n", file);
+
+ op = fopen(outfile, "w");
+ if (NULL == op) {
+ fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
+ goto the_end;
+ }
+
+ fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file));
+ for (q = p, i = 0; *q; ++i) {
+ fprintf(op, "%s\n", q);
+ q += strlen(q) + 1;
+ }
+
+ if (v)
+ printf("<- %s (%d symbol%s)\n", outfile, i, "s" + (i<2));
+
+ ret = 0;
+
+the_end:
+ /* cannot free memory received from tcc_get_dllexports
+ if it came from a dll */
+ /* if (p)
+ tcc_free(p); */
+ if (fp)
+ fclose(fp);
+ if (op)
+ fclose(op);
+ return ret;
+}
+
+#endif /* TCC_TARGET_PE */
+
+/* -------------------------------------------------------------- */
+/*
+ * TCC - Tiny C Compiler
+ *
+ * Copyright (c) 2001-2004 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
+
+#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
+
+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option)
+{
+ tcc_error("-m%d not implemented.", option);
+}
+
+#else
+#ifdef _WIN32
+#include <process.h>
+
+static char *str_replace(const char *str, const char *p, const char *r)
+{
+ const char *s, *s0;
+ char *d, *d0;
+ int sl, pl, rl;
+
+ sl = strlen(str);
+ pl = strlen(p);
+ rl = strlen(r);
+ for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
+ for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
+ if (d) {
+ memcpy(d, s0, sl = s - s0), d += sl;
+ memcpy(d, r, rl), d += rl;
+ } else
+ sl += rl - pl;
+ }
+ if (d) {
+ strcpy(d, s0);
+ return d0;
+ }
+ }
+}
+
+static int execvp_win32(const char *prog, char **argv)
+{
+ int ret; char **p;
+ /* replace all " by \" */
+ for (p = argv; *p; ++p)
+ if (strchr(*p, '"'))
+ *p = str_replace(*p, "\"", "\\\"");
+ ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
+ if (-1 == ret)
+ return ret;
+ _cwait(&ret, ret, WAIT_CHILD);
+ exit(ret);
+}
+#define execvp execvp_win32
+#endif /* _WIN32 */
+
+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
+{
+ char program[4096];
+ char *a0 = argv[0];
+ int prefix = tcc_basename(a0) - a0;
+
+ snprintf(program, sizeof program,
+ "%.*s%s"
+#ifdef TCC_TARGET_PE
+ "-win32"
+#endif
+ "-tcc"
+#ifdef _WIN32
+ ".exe"
+#endif
+ , prefix, a0, target == 64 ? "x86_64" : "i386");
+
+ if (strcmp(a0, program))
+ execvp(argv[0] = program, argv);
+ tcc_error("could not run '%s'", program);
+}
+
+#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
+/* -------------------------------------------------------------- */
+/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
+
+#ifdef _WIN32
+int _CRT_glob = 1;
+#ifndef _CRT_glob
+int _dowildcard = 1;
+#endif
+#endif
+
+/* -------------------------------------------------------------- */
+/* generate xxx.d file */
+
+ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
+{
+ FILE *depout;
+ char buf[1024];
+ int i;
+
+ if (!filename) {
+ /* compute filename automatically: dir/file.o -> dir/file.d */
+ snprintf(buf, sizeof buf, "%.*s.d",
+ (int)(tcc_fileextension(target) - target), target);
+ filename = buf;
+ }
+
+ if (s->verbose)
+ printf("<- %s\n", filename);
+
+ /* XXX return err codes instead of error() ? */
+ depout = fopen(filename, "w");
+ if (!depout)
+ tcc_error("could not open '%s'", filename);
+
+ fprintf(depout, "%s: \\\n", target);
+ for (i=0; i<s->nb_target_deps; ++i)
+ fprintf(depout, " %s \\\n", s->target_deps[i]);
+ fprintf(depout, "\n");
+ fclose(depout);
+}
+
+/* -------------------------------------------------------------- */
diff --git a/tests/tcctest.c b/tests/tcctest.c
index e5b6558..988b212 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -3431,7 +3431,7 @@ void builtin_test(void)
i = sizeof (__builtin_choose_expr (0, ll, s));
printf("bce: %d\n", i);
- printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
+ //printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
}
#ifndef _WIN32
diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat
index daf5a12..924e808 100644
--- a/win32/build-tcc.bat
+++ b/win32/build-tcc.bat
@@ -5,10 +5,6 @@
@echo off
setlocal
-set VSCOMNTOOLS=%VS150COMNTOOLS%
-if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
-if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
-if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
set CC=gcc -Os -s
set /p VERSION= < ..\VERSION
set INST=
@@ -70,10 +66,17 @@ goto :a1
if not (%1)==() goto :usage
if not "%CC%"=="@call :cl" goto :p1
+set VSCOMNTOOLS=%VS150COMNTOOLS%
+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
+if %CLVARS%_==_ goto :p1
+if exist %CLVARS% call %CLVARS%
:p1
+
if not %T%_==_ goto :p2
set T=32
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
@@ -97,9 +100,6 @@ set PX=i386-win32
@echo on
-@if %CLVARS%_==_ goto :config.h
-call %CLVARS%
-
:config.h
echo>..\config.h #define TCC_VERSION "%VERSION%"
echo>> ..\config.h #ifdef TCC_TARGET_X86_64
@@ -108,7 +108,7 @@ echo>> ..\config.h #else
echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
echo>> ..\config.h #endif
-@del /q *tcc.exe tiny_*.exe *tcc.dll
+for %%f in (*tcc.exe *tcc.dll) do @del %%f
:compiler
%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL
@@ -116,10 +116,6 @@ echo>> ..\config.h #endif
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D%
%CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE
-:tools
-%CC% -o tiny_impdef.exe tools\tiny_impdef.c %D%
-%CC% -o tiny_libmaker.exe tools\tiny_libmaker.c %D%
-
@if (%TCC_FILES%)==(no) goto :files-done
if not exist libtcc mkdir libtcc
@@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64
copy>nul ..\include\*.h include
copy>nul ..\tcclib.h include
copy>nul ..\libtcc.h libtcc
-tiny_impdef libtcc.dll -o libtcc\libtcc.def
copy>nul ..\tests\libtcc_test.c examples
copy>nul tcc-win32.txt doc
-copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
-%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX%
+.\tcc -impdef libtcc.dll -o libtcc\libtcc.def
+@if errorlevel 1 goto :the_end
:libtcc1.a
@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o
@@ -149,7 +144,7 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
.\tcc -m32 %D32% -w -c ../lib/bcheck.c
.\tcc -m32 %D32% -c ../lib/alloca86.S
.\tcc -m32 %D32% -c ../lib/alloca86-bt.S
-tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
+.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
@if errorlevel 1 goto :the_end
.\tcc -m64 %D64% -c ../lib/libtcc1.c
.\tcc -m64 %D64% -c lib/crt1.c
@@ -162,7 +157,7 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
.\tcc -m64 %D64% -w -c ../lib/bcheck.c
.\tcc -m64 %D64% -c ../lib/alloca86_64.S
.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
-tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
+.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
@if errorlevel 1 goto :the_end
:tcc-doc.html
@@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html
:doc-done
:files-done
-@del /q *.o *.def *-m??.exe
+for %%f in (*.o *.def) do @del %%f
:copy-install
@if (%INST%)==() goto :the_end
diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt
index dfcfb1b..3609684 100644
--- a/win32/tcc-win32.txt
+++ b/win32/tcc-win32.txt
@@ -39,7 +39,7 @@
For the 'Hello DLL' example type
tcc -shared dll.c
- tiny_impdef dll.dll (optional)
+ tcc -impdef dll.dll (optional)
tcc hello_dll.c dll.def
@@ -66,10 +66,10 @@
To link with Windows system DLLs, TCC uses import definition
files (.def) instead of libraries.
- The included 'tiny_impdef' program may be used to make additional
- .def files for any DLL. For example:
+ The now built-in 'tiny_impdef' program may be used to make
+ additional .def files for any DLL. For example
- tiny_impdef.exe opengl32.dll
+ tcc -impdef [-v] opengl32.dll [-o opengl32.def]
Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
the TCC commandline to link a program that uses opengl32.dll.
@@ -98,10 +98,10 @@
Tiny Libmaker:
--------------
- The included tiny_libmaker tool by Timovj Lahde can be used as
+ The now built-in tiny_libmaker tool by Timovj Lahde can be used as
'ar' replacement to make a library from several object files:
- tiny_libmaker [rcs] library objectfiles ...
+ tcc -ar [rcsv] library objectfiles ...
Compilation from source:
@@ -143,14 +143,12 @@
------------
- On the object file level, currently TCC supports only the ELF format,
not COFF as used by MinGW and MSVC. It is not possible to exchange
- object files or libraries between TCC and these compilers. However
- libraries for TCC from objects by TCC can be made using tiny_libmaker
- or MinGW's ar.
+ object files or libraries between TCC and these compilers.
- - No leading underscore is generated in the ELF symbols.
-
- - Bounds checking (option -b) is not supported on 64-bit OS.
+ However libraries for TCC from objects by TCC can be made using
+ tcc -ar lib.a files.o ,,,
+ - No leading underscore is generated in the ELF symbols.
Documentation and License:
--------------------------
diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c
deleted file mode 100644
index b6debe6..0000000
--- a/win32/tools/tiny_impdef.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* -------------------------------------------------------------- */
-/*
- * tiny_impdef creates an export definition file (.def) from a dll
- * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
- *
- * Copyright (c) 2005,2007 grischka
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <stdio.h>
-#include <io.h>
-#include <malloc.h>
-
-static char *get_export_names(int fd);
-#define tcc_free free
-#define tcc_realloc realloc
-
-/* extract the basename of a file */
-static char *file_basename(const char *name)
-{
- const char *p = strchr(name, 0);
- while (p > name
- && p[-1] != '/'
- && p[-1] != '\\'
- )
- --p;
- return (char*)p;
-}
-
-int main(int argc, char **argv)
-{
- int ret, v, i;
- char infile[MAX_PATH];
- char outfile[MAX_PATH];
-
- static const char *ext[] = { ".dll", ".exe", NULL };
- const char *file, **pp;
- char path[MAX_PATH], *p, *q;
- FILE *fp, *op;
-
- infile[0] = 0;
- outfile[0] = 0;
- fp = op = NULL;
- v = 0;
- ret = 1;
- p = NULL;
-
- for (i = 1; i < argc; ++i) {
- const char *a = argv[i];
- if ('-' == a[0]) {
- if (0 == strcmp(a, "-v")) {
- v = 1;
- } else if (0 == strcmp(a, "-o")) {
- if (++i == argc)
- goto usage;
- strcpy(outfile, argv[i]);
- } else
- goto usage;
- } else if (0 == infile[0])
- strcpy(infile, a);
- else
- goto usage;
- }
-
- if (0 == infile[0]) {
-usage:
- fprintf(stderr,
- "tiny_impdef: create export definition file (.def) from a dll\n"
- "Usage: tiny_impdef library.dll [-o outputfile]\n"
- );
- goto the_end;
- }
-
- if (0 == outfile[0])
- {
- strcpy(outfile, file_basename(infile));
- q = strrchr(outfile, '.');
- if (NULL == q)
- q = strchr(outfile, 0);
- strcpy(q, ".def");
- }
-
- file = infile;
-
-#ifdef _WIN32
- pp = ext;
- do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
- file = path;
- break;
- } while (*pp++);
-#endif
-
- fp = fopen(file, "rb");
- if (NULL == fp) {
- fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
- goto the_end;
- }
- if (v)
- printf("--> %s\n", file);
-
- p = get_export_names(fileno(fp));
- if (NULL == p) {
- fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
- goto the_end;
- }
-
- op = fopen(outfile, "w");
- if (NULL == op) {
- fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
- goto the_end;
- }
-
- fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
- for (q = p, i = 0; *q; ++i) {
- fprintf(op, "%s\n", q);
- q += strlen(q) + 1;
- }
-
- if (v) {
- printf("<-- %s\n", outfile);
- printf("%d symbol(s) found\n", i);
- }
-
- ret = 0;
-
-the_end:
- if (p)
- free(p);
- if (fp)
- fclose(fp);
- if (op)
- fclose(op);
- return ret;
-}
-
-int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
-{
- lseek(fd, offset, SEEK_SET);
- return len == read(fd, buffer, len);
-}
-
-/* -------------------------------------------------------------- */
-
-#if defined TCC_TARGET_X86_64
-# define IMAGE_FILE_MACHINE 0x8664
-#elif defined TCC_TARGET_ARM
-# define IMAGE_FILE_MACHINE 0x01C0
-#elif 1 /* defined TCC_TARGET_I386 */
-# define IMAGE_FILE_MACHINE 0x014C
-#endif
-
-/* -------------------------------------------------------------- */
-#endif
-
-static char *get_export_names(int fd)
-{
- int l, i, n, n0;
- char *p;
-
- IMAGE_SECTION_HEADER ish;
- IMAGE_EXPORT_DIRECTORY ied;
- IMAGE_DOS_HEADER dh;
- IMAGE_FILE_HEADER ih;
- DWORD sig, ref, addr, ptr, namep;
-#ifdef TCC_TARGET_X86_64
- IMAGE_OPTIONAL_HEADER64 oh;
-#else
- IMAGE_OPTIONAL_HEADER32 oh;
-#endif
- int pef_hdroffset, opt_hdroffset, sec_hdroffset;
-
- n = n0 = 0;
- p = NULL;
-
- if (!read_mem(fd, 0, &dh, sizeof dh))
- goto the_end;
- if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
- goto the_end;
- if (sig != 0x00004550)
- goto the_end;
- pef_hdroffset = dh.e_lfanew + sizeof sig;
- if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
- goto the_end;
- if (IMAGE_FILE_MACHINE != ih.Machine)
- goto the_end;
- opt_hdroffset = pef_hdroffset + sizeof ih;
- sec_hdroffset = opt_hdroffset + sizeof oh;
- if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
- goto the_end;
-
- if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
- goto the_end;
-
- addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- //printf("addr: %08x\n", addr);
- for (i = 0; i < ih.NumberOfSections; ++i) {
- if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
- goto the_end;
- //printf("vaddr: %08x\n", ish.VirtualAddress);
- if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
- goto found;
- }
- goto the_end;
-
-found:
- ref = ish.VirtualAddress - ish.PointerToRawData;
- if (!read_mem(fd, addr - ref, &ied, sizeof ied))
- goto the_end;
-
- namep = ied.AddressOfNames - ref;
- for (i = 0; i < ied.NumberOfNames; ++i) {
- if (!read_mem(fd, namep, &ptr, sizeof ptr))
- goto the_end;
- namep += sizeof ptr;
- for (l = 0;;) {
- if (n+1 >= n0)
- p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
- if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
- tcc_free(p), p = NULL;
- goto the_end;
- }
- if (p[n++] == 0)
- break;
- }
- }
- if (p)
- p[n] = 0;
-the_end:
- return p;
-}
-
-/* -------------------------------------------------------------- */
diff --git a/win32/tools/tiny_libmaker.c b/win32/tools/tiny_libmaker.c
deleted file mode 100644
index a694915..0000000
--- a/win32/tools/tiny_libmaker.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * This program is for making libtcc1.a without ar
- * tiny_libmaker - tiny elf lib maker
- * usage: tiny_libmaker [lib] files...
- * Copyright (c) 2007 Timppa
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../../elf.h"
-
-#ifdef TCC_TARGET_X86_64
-# define ELFCLASSW ELFCLASS64
-# define ElfW(type) Elf##64##_##type
-# define ELFW(type) ELF##64##_##type
-#else
-# define ELFCLASSW ELFCLASS32
-# define ElfW(type) Elf##32##_##type
-# define ELFW(type) ELF##32##_##type
-#endif
-
-#define ARMAG "!<arch>\n"
-#define ARFMAG "`\n"
-
-typedef struct ArHdr {
- char ar_name[16];
- char ar_date[12];
- char ar_uid[6];
- char ar_gid[6];
- char ar_mode[8];
- char ar_size[10];
- char ar_fmag[2];
-} ArHdr;
-
-unsigned long le2belong(unsigned long ul) {
- return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
- ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
-}
-
-ArHdr arhdr = {
- "/ ",
- " ",
- "0 ",
- "0 ",
- "0 ",
- " ",
- ARFMAG
- };
-
-ArHdr arhdro = {
- " ",
- " ",
- "0 ",
- "0 ",
- "0 ",
- " ",
- ARFMAG
- };
-
-/* Returns 1 if s contains any of the chars of list, else 0 */
-int contains_any(const char *s, const char *list) {
- const char *l;
- for (; *s; s++) {
- for (l = list; *l; l++) {
- if (*s == *l)
- return 1;
- }
- }
- return 0;
-}
-
-int usage(int ret) {
- fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n");
- fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n");
- return ret;
-}
-
-int main(int argc, char **argv)
-{
- FILE *fi, *fh = NULL, *fo = NULL;
- ElfW(Ehdr) *ehdr;
- ElfW(Shdr) *shdr;
- ElfW(Sym) *sym;
- int i, fsize, i_lib, i_obj;
- char *buf, *shstr, *symtab = NULL, *strtab = NULL;
- int symtabsize = 0;//, strtabsize = 0;
- char *anames = NULL;
- int *afpos = NULL;
- int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
- char tfile[260], stmp[20];
- char *file, *name;
- int ret = 2;
- char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
- int verbose = 0;
-
- i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
- for (i = 1; i < argc; i++) {
- const char *a = argv[i];
- if (*a == '-' && strstr(a, "."))
- return usage(1); // -x.y is always invalid (same as gnu ar)
- if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
- if (contains_any(a, ops_conflict))
- return usage(1);
- if (strstr(a, "v"))
- verbose = 1;
- } else { // lib or obj files: don't abort - keep validating all args.
- if (!i_lib) // first file is the lib
- i_lib = i;
- else if (!i_obj) // second file is the first obj
- i_obj = i;
- }
- }
- if (!i_obj) // i_obj implies also i_lib. we require both.
- return usage(1);
-
- if ((fh = fopen(argv[i_lib], "wb")) == NULL)
- {
- fprintf(stderr, "Can't open file %s \n", argv[i_lib]);
- goto the_end;
- }
-
- sprintf(tfile, "%s.tmp", argv[i_lib]);
- if ((fo = fopen(tfile, "wb+")) == NULL)
- {
- fprintf(stderr, "Can't create temporary file %s\n", tfile);
- goto the_end;
- }
-
- funcmax = 250;
- afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
- memcpy(&arhdro.ar_mode, "100666", 6);
-
- // i_obj = first input object file
- while (i_obj < argc)
- {
- if (*argv[i_obj] == '-') { // by now, all options start with '-'
- i_obj++;
- continue;
- }
- if (verbose)
- printf("a - %s\n", argv[i_obj]);
-
- if ((fi = fopen(argv[i_obj], "rb")) == NULL)
- {
- fprintf(stderr, "Can't open file %s \n", argv[i_obj]);
- goto the_end;
- }
- fseek(fi, 0, SEEK_END);
- fsize = ftell(fi);
- fseek(fi, 0, SEEK_SET);
- buf = malloc(fsize + 1);
- fread(buf, fsize, 1, fi);
- fclose(fi);
-
- // elf header
- ehdr = (ElfW(Ehdr) *)buf;
- if (ehdr->e_ident[4] != ELFCLASSW)
- {
- fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]);
- goto the_end;
- }
-
- shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
- shstr = (char *)(buf + shdr->sh_offset);
- for (i = 0; i < ehdr->e_shnum; i++)
- {
- shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
- if (!shdr->sh_offset)
- continue;
- if (shdr->sh_type == SHT_SYMTAB)
- {
- symtab = (char *)(buf + shdr->sh_offset);
- symtabsize = shdr->sh_size;
- }
- if (shdr->sh_type == SHT_STRTAB)
- {
- if (!strcmp(shstr + shdr->sh_name, ".strtab"))
- {
- strtab = (char *)(buf + shdr->sh_offset);
- //strtabsize = shdr->sh_size;
- }
- }
- }
-
- if (symtab && symtabsize)
- {
- int nsym = symtabsize / sizeof(ElfW(Sym));
- //printf("symtab: info size shndx name\n");
- for (i = 1; i < nsym; i++)
- {
- sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
- if (sym->st_shndx &&
- (sym->st_info == 0x10
- || sym->st_info == 0x11
- || sym->st_info == 0x12
- )) {
- //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
- istrlen = strlen(strtab + sym->st_name)+1;
- anames = realloc(anames, strpos+istrlen);
- strcpy(anames + strpos, strtab + sym->st_name);
- strpos += istrlen;
- if (++funccnt >= funcmax) {
- funcmax += 250;
- afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
- }
- afpos[funccnt] = fpos;
- }
- }
- }
-
- file = argv[i_obj];
- for (name = strchr(file, 0);
- name > file && name[-1] != '/' && name[-1] != '\\';
- --name);
- istrlen = strlen(name);
- if (istrlen >= sizeof(arhdro.ar_name))
- istrlen = sizeof(arhdro.ar_name) - 1;
- memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
- memcpy(arhdro.ar_name, name, istrlen);
- arhdro.ar_name[istrlen] = '/';
- sprintf(stmp, "%-10d", fsize);
- memcpy(&arhdro.ar_size, stmp, 10);
- fwrite(&arhdro, sizeof(arhdro), 1, fo);
- fwrite(buf, fsize, 1, fo);
- free(buf);
- i_obj++;
- fpos += (fsize + sizeof(arhdro));
- }
- hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
- fpos = 0;
- if ((hofs & 1)) // align
- hofs++, fpos = 1;
- // write header
- fwrite("!<arch>\n", 8, 1, fh);
- sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
- memcpy(&arhdr.ar_size, stmp, 10);
- fwrite(&arhdr, sizeof(arhdr), 1, fh);
- afpos[0] = le2belong(funccnt);
- for (i=1; i<=funccnt; i++)
- afpos[i] = le2belong(afpos[i] + hofs);
- fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
- fwrite(anames, strpos, 1, fh);
- if (fpos)
- fwrite("", 1, 1, fh);
- // write objects
- fseek(fo, 0, SEEK_END);
- fsize = ftell(fo);
- fseek(fo, 0, SEEK_SET);
- buf = malloc(fsize + 1);
- fread(buf, fsize, 1, fo);
- fwrite(buf, fsize, 1, fh);
- free(buf);
- ret = 0;
-the_end:
- if (anames)
- free(anames);
- if (afpos)
- free(afpos);
- if (fh)
- fclose(fh);
- if (fo)
- fclose(fo), remove(tfile);
- return ret;
-}