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)
Unified · Split
| @@ -7,6 +7,7 @@ User interface: · 6 unmodified lines | |||
| 7 | - -mms-bitfields option (David Mertens) | 7 | - -mms-bitfields option (David Mertens) |
| 8 | - -include <file> option (Michael Matz) | 8 | - -include <file> option (Michael Matz) |
| 9 | - @listfile support (Vlad Vissoultchev) | 9 | - @listfile support (Vlad Vissoultchev) |
| 10 | - tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka) | ||
| 10 | - CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support | 11 | - CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support |
| 11 | (Andrew Aladjev, Urs Janssen) | 12 | (Andrew Aladjev, Urs Janssen) |
| 12 | 13 | ||
| @@ -28,6 +28,7 @@ LIBS = · 27 unmodified lines | |||
| 28 | ifdef CONFIG_WIN32 | 28 | ifdef CONFIG_WIN32 |
| 29 | ifneq ($(DISABLE_STATIC),no) | 29 | ifneq ($(DISABLE_STATIC),no) |
| 30 | LIBTCC = libtcc.dll | 30 | LIBTCC = libtcc.dll |
| 31 | LIBTCCDEF = libtcc.def | ||
| 31 | endif | 32 | endif |
| 32 | else | 33 | else |
| 33 | LIBS=-lm | 34 | LIBS=-lm |
| @@ -82,7 +83,7 @@ ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CRO · 48 unmodified lines | |||
| 82 | ARM64_CROSS = arm64-tcc$(EXESUF) | 83 | ARM64_CROSS = arm64-tcc$(EXESUF) |
| 83 | C67_CROSS = c67-tcc$(EXESUF) | 84 | C67_CROSS = c67-tcc$(EXESUF) |
| 84 | 85 | ||
| 85 | CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c | 86 | CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c |
| 86 | CORE_FILES += tcc.h config.h libtcc.h tcctok.h | 87 | CORE_FILES += tcc.h config.h libtcc.h tcctok.h |
| 87 | I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h | 88 | I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h |
| 88 | WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c | 89 | 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 · 5 unmodified lines | |||
| 94 | C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c | 95 | C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c |
| 95 | 96 | ||
| 96 | ifdef CONFIG_WIN32 | 97 | ifdef CONFIG_WIN32 |
| 97 | PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) | ||
| 98 | ifeq ($(ARCH),x86-64) | 98 | ifeq ($(ARCH),x86-64) |
| 99 | NATIVE_FILES=$(WIN64_FILES) | 99 | NATIVE_FILES=$(WIN64_FILES) |
| 100 | PROGS_CROSS=$(WIN32_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) | 100 | PROGS_CROSS=$(WIN32_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
| @@ -124,11 +124,7 @@ NATIVE_FILES=$(ARM64_FILES) · 23 unmodified lines | |||
| 124 | PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) | 124 | PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) |
| 125 | endif | 125 | endif |
| 126 | 126 | ||
| 127 | ifeq ($(TARGETOS),Darwin) | 127 | TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF) |
| 128 | PROGS += tiny_libmaker$(EXESUF) | ||
| 129 | endif | ||
| 130 | |||
| 131 | TCCLIBS = $(LIBTCC1) $(LIBTCC) | ||
| 132 | TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info | 128 | TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info |
| 133 | 129 | ||
| 134 | ifdef CONFIG_CROSS | 130 | ifdef CONFIG_CROSS |
| @@ -179,7 +175,7 @@ $(ARM64_CROSS): $(ARM64_FILES) · 44 unmodified lines | |||
| 179 | 175 | ||
| 180 | # libtcc generation and test | 176 | # libtcc generation and test |
| 181 | ifndef ONE_SOURCE | 177 | ifndef ONE_SOURCE |
| 182 | LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) | 178 | LIBTCC_OBJ = $(filter-out tcc.o tcctools.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) |
| 183 | LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES)) | 179 | LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES)) |
| 184 | else | 180 | else |
| 185 | LIBTCC_OBJ = libtcc.o | 181 | LIBTCC_OBJ = libtcc.o |
| @@ -187,6 +183,8 @@ LIBTCC_INC = $(NATIVE_FILES) · 1 unmodified line | |||
| 187 | libtcc.o : NATIVE_DEFINES += -DONE_SOURCE | 183 | libtcc.o : NATIVE_DEFINES += -DONE_SOURCE |
| 188 | endif | 184 | endif |
| 189 | 185 | ||
| 186 | tcc.o : tcctools.c | ||
| 187 | |||
| 190 | $(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) | 188 | $(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) |
| 191 | $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS) | 189 | $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS) |
| 192 | 190 | ||
| @@ -199,9 +197,11 @@ libtcc.so: $(LIBTCC_OBJ) · 6 unmodified lines | |||
| 199 | libtcc.so: CFLAGS+=-fPIC | 197 | libtcc.so: CFLAGS+=-fPIC |
| 200 | 198 | ||
| 201 | # windows : libtcc.dll | 199 | # windows : libtcc.dll |
| 202 | libtcc.dll : $(LIBTCC_OBJ) tiny_impdef$(EXESUF) | 200 | libtcc.dll : $(LIBTCC_OBJ) |
| 203 | $(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS) | 201 | $(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS) |
| 204 | ./tiny_impdef $@ | 202 | |
| 203 | libtcc.def : libtcc.dll tcc$(EXESUF) | ||
| 204 | ./tcc$(EXESUF) -impdef $< -o $@ | ||
| 205 | 205 | ||
| 206 | libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL | 206 | libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL |
| 207 | 207 | ||
| @@ -2,6 +2,7 @@ TODO list: · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | Bugs: | 3 | Bugs: |
| 4 | 4 | ||
| 5 | - i386 fastcall is mostly wrong | ||
| 5 | - FPU st(0) is left unclean (kwisatz haderach). Incompatible with | 6 | - FPU st(0) is left unclean (kwisatz haderach). Incompatible with |
| 6 | optimized gcc/msc code | 7 | optimized gcc/msc code |
| 7 | - see transparent union pb in /urs/include/sys/socket.h | 8 | - see transparent union pb in /urs/include/sys/socket.h |
| @@ -1,9 +1,9 @@ | |||
| 1 | #include <stdio.h> | 1 | #include <stdio.h> |
| 2 | 2 | ||
| 3 | /* Define architecture */ | 3 | /* Define architecture */ |
| 4 | #if defined(__i386__) | 4 | #if defined(__i386__) || defined _M_IX86 |
| 5 | # define TRIPLET_ARCH "i386" | 5 | # define TRIPLET_ARCH "i386" |
| 6 | #elif defined(__x86_64__) | 6 | #elif defined(__x86_64__) || defined _M_AMD64 |
| 7 | # define TRIPLET_ARCH "x86_64" | 7 | # define TRIPLET_ARCH "x86_64" |
| 8 | #elif defined(__arm__) | 8 | #elif defined(__arm__) |
| 9 | # define TRIPLET_ARCH "arm" | 9 | # define TRIPLET_ARCH "arm" |
| @@ -18,6 +18,8 @@ · 8 unmodified lines | |||
| 18 | # define TRIPLET_OS "linux" | 18 | # define TRIPLET_OS "linux" |
| 19 | #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) | 19 | #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) |
| 20 | # define TRIPLET_OS "kfreebsd" | 20 | # define TRIPLET_OS "kfreebsd" |
| 21 | #elif defined _WIN32 | ||
| 22 | # define TRIPLET_OS "win32" | ||
| 21 | #elif !defined (__GNU__) | 23 | #elif !defined (__GNU__) |
| 22 | # define TRIPLET_OS "unknown" | 24 | # define TRIPLET_OS "unknown" |
| 23 | #endif | 25 | #endif |
| @@ -33,7 +35,9 @@ · 9 unmodified lines | |||
| 33 | # define TRIPLET_ABI "gnu" | 35 | # define TRIPLET_ABI "gnu" |
| 34 | #endif | 36 | #endif |
| 35 | 37 | ||
| 36 | #ifdef __GNU__ | 38 | #if defined _WIN32 |
| 39 | # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS | ||
| 40 | #elif defined __GNU__ | ||
| 37 | # define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI | 41 | # define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI |
| 38 | #else | 42 | #else |
| 39 | # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI | 43 | # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI |
| @@ -59,6 +63,13 @@ int main(int argc, char *argv[]) · 19 unmodified lines | |||
| 59 | case 'v': | 63 | case 'v': |
| 60 | printf("%d\n", __GNUC__); | 64 | printf("%d\n", __GNUC__); |
| 61 | break; | 65 | break; |
| 66 | #elif defined __TINYC__ | ||
| 67 | case 'v': | ||
| 68 | puts("0"); | ||
| 69 | break; | ||
| 70 | case 'm': | ||
| 71 | printf("%d\n", __TINYC__); | ||
| 72 | break; | ||
| 62 | #else | 73 | #else |
| 63 | case 'm': | 74 | case 'm': |
| 64 | case 'v': | 75 | case 'v': |
| @@ -68,9 +79,8 @@ int main(int argc, char *argv[]) · 3 unmodified lines | |||
| 68 | case 't': | 79 | case 't': |
| 69 | puts(TRIPLET); | 80 | puts(TRIPLET); |
| 70 | break; | 81 | break; |
| 71 | case -1: | 82 | |
| 72 | /* to test -Wno-unused-result */ | 83 | default: |
| 73 | fread(NULL, 1, 1, NULL); | ||
| 74 | break; | 84 | break; |
| 75 | } | 85 | } |
| 76 | return 0; | 86 | return 0; |
| @@ -20,9 +20,6 @@ ifndef TARGET · 19 unmodified lines | |||
| 20 | TARGET = x86_64 | 20 | TARGET = x86_64 |
| 21 | else ifeq ($(ARCH),arm) | 21 | else ifeq ($(ARCH),arm) |
| 22 | TARGET = arm | 22 | TARGET = arm |
| 23 | # using gcc, need asm | ||
| 24 | XCC = $(CC) | ||
| 25 | XFLAGS = $(CFLAGS) -fPIC | ||
| 26 | else ifeq ($(ARCH),arm64) | 23 | else ifeq ($(ARCH),arm64) |
| 27 | TARGET = arm64 | 24 | TARGET = arm64 |
| 28 | endif | 25 | endif |
| @@ -37,6 +34,9 @@ cross : $(DIR)/libtcc1.a · 8 unmodified lines | |||
| 37 | native : TCC = $(TOP)/tcc$(EXESUF) | 34 | native : TCC = $(TOP)/tcc$(EXESUF) |
| 38 | cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) | 35 | cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) |
| 39 | 36 | ||
| 37 | XCC = $(TCC) -B$(TOPSRC) | ||
| 38 | XAR = $(TCC) -ar | ||
| 39 | |||
| 40 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) | 40 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) |
| 41 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O) | 41 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O) |
| 42 | ARM_O = libtcc1.o armeabi.o alloca-arm.o | 42 | ARM_O = libtcc1.o armeabi.o alloca-arm.o |
| @@ -47,53 +47,43 @@ ifeq "$(TARGET)" "i386-win32" · 4 unmodified lines | |||
| 47 | OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O)) | 47 | OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O)) |
| 48 | TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE | 48 | TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE |
| 49 | XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include | 49 | XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include |
| 50 | XAR = $(DIR)/tiny_libmaker$(EXESUF) | ||
| 51 | else ifeq "$(TARGET)" "x86_64-win32" | 50 | else ifeq "$(TARGET)" "x86_64-win32" |
| 52 | OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O)) | 51 | OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O)) |
| 53 | TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE | 52 | TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE |
| 54 | XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include | 53 | XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include |
| 55 | XAR = $(DIR)/tiny_libmaker$(EXESUF) | ||
| 56 | else ifeq "$(TARGET)" "i386" | 54 | else ifeq "$(TARGET)" "i386" |
| 57 | OBJ = $(addprefix $(DIR)/,$(I386_O)) | 55 | OBJ = $(addprefix $(DIR)/,$(I386_O)) |
| 58 | TGT = -DTCC_TARGET_I386 | 56 | TGT = -DTCC_TARGET_I386 |
| 59 | XCC ?= $(TCC) -B$(TOPSRC) | ||
| 60 | else ifeq "$(TARGET)" "x86_64" | 57 | else ifeq "$(TARGET)" "x86_64" |
| 61 | OBJ = $(addprefix $(DIR)/,$(X86_64_O)) | 58 | OBJ = $(addprefix $(DIR)/,$(X86_64_O)) |
| 62 | TGT = -DTCC_TARGET_X86_64 | 59 | TGT = -DTCC_TARGET_X86_64 |
| 63 | XCC ?= $(TCC) -B$(TOPSRC) | ||
| 64 | else ifeq "$(TARGET)" "arm" | 60 | else ifeq "$(TARGET)" "arm" |
| 65 | OBJ = $(addprefix $(DIR)/,$(ARM_O)) | 61 | OBJ = $(addprefix $(DIR)/,$(ARM_O)) |
| 66 | TGT = -DTCC_TARGET_ARM | 62 | TGT = -DTCC_TARGET_ARM |
| 67 | XCC ?= $(TCC) -B$(TOPSRC) | 63 | # using gcc, need asm |
| 64 | XCC = $(CC) | ||
| 65 | XFLAGS = $(CFLAGS) -fPIC | ||
| 66 | XAR = $(AR) | ||
| 68 | else ifeq "$(TARGET)" "arm64" | 67 | else ifeq "$(TARGET)" "arm64" |
| 69 | OBJ = $(addprefix $(DIR)/,$(ARM64_O)) | 68 | OBJ = $(addprefix $(DIR)/,$(ARM64_O)) |
| 70 | TGT = -DTCC_TARGET_ARM64 | 69 | TGT = -DTCC_TARGET_ARM64 |
| 71 | XCC ?= $(TCC) -B$(TOPSRC) | ||
| 72 | else | 70 | else |
| 73 | $(error libtcc1.a not supported on target '$(TARGET)') | 71 | $(error libtcc1.a not supported on target '$(TARGET)') |
| 74 | endif | 72 | endif |
| 75 | 73 | ||
| 76 | ifeq ($(TARGETOS),Darwin) | 74 | ifeq ($(TARGETOS),Darwin) |
| 77 | XAR = $(DIR)/tiny_libmaker$(EXESUF) | ||
| 78 | XFLAGS += -D_ANSI_SOURCE | 75 | XFLAGS += -D_ANSI_SOURCE |
| 79 | BCHECK_O = | 76 | BCHECK_O = |
| 80 | endif | 77 | endif |
| 81 | 78 | ||
| 82 | ifdef XAR | 79 | $(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) |
| 83 | AR = $(XAR) | 80 | $(XAR) rcs $@ $(OBJ) |
| 84 | endif | ||
| 85 | |||
| 86 | $(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR) | ||
| 87 | $(AR) rcs $@ $(OBJ) | ||
| 88 | $(DIR)/%.o : %.c | 81 | $(DIR)/%.o : %.c |
| 89 | $(XCC) -c $< -o $@ $(TGT) $(XFLAGS) | 82 | $(XCC) -c $< -o $@ $(TGT) $(XFLAGS) |
| 90 | $(DIR)/%.o : %.S | 83 | $(DIR)/%.o : %.S |
| 91 | $(XCC) -c $< -o $@ $(TGT) $(XFLAGS) | 84 | $(XCC) -c $< -o $@ $(TGT) $(XFLAGS) |
| 92 | # windows : utilities | ||
| 93 | $(DIR)/tiny_%$(EXESUF) : $(TOPSRC)/win32/tools/tiny_%.c | ||
| 94 | $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(TGT) | ||
| 95 | 85 | ||
| 96 | $(OBJ) $(XAR) : $(DIR)/exists | 86 | $(OBJ) : $(DIR)/exists |
| 97 | 87 | ||
| 98 | %/exists : | 88 | %/exists : |
| 99 | mkdir -p $(DIR) | 89 | mkdir -p $(DIR) |
| @@ -239,7 +239,7 @@ PUB_FUNC char *tcc_strdup(const char *str) · 238 unmodified lines | |||
| 239 | return ptr; | 239 | return ptr; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | PUB_FUNC void tcc_memstats(int bench) | 242 | PUB_FUNC void tcc_memcheck(void) |
| 243 | { | 243 | { |
| 244 | } | 244 | } |
| 245 | 245 | ||
| @@ -379,7 +379,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) · 133 unmodified lines | |||
| 379 | return ptr; | 379 | return ptr; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | PUB_FUNC void tcc_memstats(int bench) | 382 | PUB_FUNC void tcc_memcheck(void) |
| 383 | { | 383 | { |
| 384 | if (mem_cur_size) { | 384 | if (mem_cur_size) { |
| 385 | mem_debug_header_t *header = mem_debug_chain; | 385 | mem_debug_header_t *header = mem_debug_chain; |
| @@ -393,8 +393,7 @@ PUB_FUNC void tcc_memstats(int bench) · 7 unmodified lines | |||
| 393 | #if MEM_DEBUG-0 == 2 | 393 | #if MEM_DEBUG-0 == 2 |
| 394 | exit(2); | 394 | exit(2); |
| 395 | #endif | 395 | #endif |
| 396 | } else if (bench) | 396 | } |
| 397 | fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size); | ||
| 398 | } | 397 | } |
| 399 | #endif /* MEM_DEBUG */ | 398 | #endif /* MEM_DEBUG */ |
| 400 | 399 | ||
| @@ -435,7 +434,7 @@ ST_FUNC void dynarray_reset(void *pp, int *n) · 34 unmodified lines | |||
| 435 | *(void**)pp = NULL; | 434 | *(void**)pp = NULL; |
| 436 | } | 435 | } |
| 437 | 436 | ||
| 438 | static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in) | 437 | static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in) |
| 439 | { | 438 | { |
| 440 | const char *p; | 439 | const char *p; |
| 441 | do { | 440 | do { |
| @@ -878,18 +877,14 @@ LIBTCCAPI TCCState *tcc_new(void) · 436 unmodified lines | |||
| 878 | tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", | 877 | tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", |
| 879 | "name proto __asm__ (#alias) __THROW"); | 878 | "name proto __asm__ (#alias) __THROW"); |
| 880 | # endif | 879 | # endif |
| 881 | #endif /* ndef TCC_TARGET_PE */ | ||
| 882 | |||
| 883 | /* Some GCC builtins that are simple to express as macros. */ | 880 | /* Some GCC builtins that are simple to express as macros. */ |
| 884 | tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); | 881 | tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); |
| 885 | 882 | #endif /* ndef TCC_TARGET_PE */ | |
| 886 | return s; | 883 | return s; |
| 887 | } | 884 | } |
| 888 | 885 | ||
| 889 | LIBTCCAPI void tcc_delete(TCCState *s1) | 886 | LIBTCCAPI void tcc_delete(TCCState *s1) |
| 890 | { | 887 | { |
| 891 | int bench = s1->do_bench; | ||
| 892 | |||
| 893 | tcc_cleanup(); | 888 | tcc_cleanup(); |
| 894 | 889 | ||
| 895 | /* free sections */ | 890 | /* free sections */ |
| @@ -915,6 +910,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 19 unmodified lines | |||
| 915 | dynarray_reset(&s1->files, &s1->nb_files); | 910 | dynarray_reset(&s1->files, &s1->nb_files); |
| 916 | dynarray_reset(&s1->target_deps, &s1->nb_target_deps); | 911 | dynarray_reset(&s1->target_deps, &s1->nb_target_deps); |
| 917 | dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); | 912 | dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); |
| 913 | dynarray_reset(&s1->argv, &s1->argc); | ||
| 918 | 914 | ||
| 919 | #ifdef TCC_IS_NATIVE | 915 | #ifdef TCC_IS_NATIVE |
| 920 | /* free runtime memory */ | 916 | /* free runtime memory */ |
| @@ -923,7 +919,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 2 unmodified lines | |||
| 923 | 919 | ||
| 924 | tcc_free(s1); | 920 | tcc_free(s1); |
| 925 | if (0 == --nb_states) | 921 | if (0 == --nb_states) |
| 926 | tcc_memstats(bench); | 922 | tcc_memcheck(); |
| 927 | } | 923 | } |
| 928 | 924 | ||
| 929 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) | 925 | 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) · 35 unmodified lines | |||
| 965 | # endif | 961 | # endif |
| 966 | #else | 962 | #else |
| 967 | /* paths for crt objects */ | 963 | /* paths for crt objects */ |
| 968 | tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); | 964 | tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); |
| 969 | /* add libc crt1/crti objects */ | 965 | /* add libc crt1/crti objects */ |
| 970 | if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && | 966 | if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && |
| 971 | !s->nostdlib) { | 967 | !s->nostdlib) { |
| @@ -979,13 +975,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 7 unmodified lines | |||
| 979 | 975 | ||
| 980 | LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) | 976 | LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) |
| 981 | { | 977 | { |
| 982 | tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname); | 978 | tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); |
| 983 | return 0; | 979 | return 0; |
| 984 | } | 980 | } |
| 985 | 981 | ||
| 986 | LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) | 982 | LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) |
| 987 | { | 983 | { |
| 988 | tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); | 984 | tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); |
| 989 | return 0; | 985 | return 0; |
| 990 | } | 986 | } |
| 991 | 987 | ||
| @@ -1106,7 +1102,7 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) · 114 unmodified lines | |||
| 1106 | 1102 | ||
| 1107 | LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) | 1103 | LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) |
| 1108 | { | 1104 | { |
| 1109 | tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname); | 1105 | tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); |
| 1110 | return 0; | 1106 | return 0; |
| 1111 | } | 1107 | } |
| 1112 | 1108 | ||
| @@ -1440,6 +1436,7 @@ typedef struct TCCOption { · 327 unmodified lines | |||
| 1440 | 1436 | ||
| 1441 | enum { | 1437 | enum { |
| 1442 | TCC_OPTION_HELP, | 1438 | TCC_OPTION_HELP, |
| 1439 | TCC_OPTION_v, | ||
| 1443 | TCC_OPTION_I, | 1440 | TCC_OPTION_I, |
| 1444 | TCC_OPTION_D, | 1441 | TCC_OPTION_D, |
| 1445 | TCC_OPTION_U, | 1442 | TCC_OPTION_U, |
| @@ -1480,13 +1477,14 @@ enum { · 34 unmodified lines | |||
| 1480 | TCC_OPTION_pedantic, | 1477 | TCC_OPTION_pedantic, |
| 1481 | TCC_OPTION_pthread, | 1478 | TCC_OPTION_pthread, |
| 1482 | TCC_OPTION_run, | 1479 | TCC_OPTION_run, |
| 1483 | TCC_OPTION_v, | ||
| 1484 | TCC_OPTION_w, | 1480 | TCC_OPTION_w, |
| 1485 | TCC_OPTION_pipe, | 1481 | TCC_OPTION_pipe, |
| 1486 | TCC_OPTION_E, | 1482 | TCC_OPTION_E, |
| 1487 | TCC_OPTION_MD, | 1483 | TCC_OPTION_MD, |
| 1488 | TCC_OPTION_MF, | 1484 | TCC_OPTION_MF, |
| 1489 | TCC_OPTION_x | 1485 | TCC_OPTION_x, |
| 1486 | TCC_OPTION_ar, | ||
| 1487 | TCC_OPTION_impdef | ||
| 1490 | }; | 1488 | }; |
| 1491 | 1489 | ||
| 1492 | #define TCC_OPTION_HAS_ARG 0x0001 | 1490 | #define TCC_OPTION_HAS_ARG 0x0001 |
| @@ -1496,6 +1494,7 @@ static const TCCOption tcc_options[] = { · 3 unmodified lines | |||
| 1496 | { "h", TCC_OPTION_HELP, 0 }, | 1494 | { "h", TCC_OPTION_HELP, 0 }, |
| 1497 | { "-help", TCC_OPTION_HELP, 0 }, | 1495 | { "-help", TCC_OPTION_HELP, 0 }, |
| 1498 | { "?", TCC_OPTION_HELP, 0 }, | 1496 | { "?", TCC_OPTION_HELP, 0 }, |
| 1497 | { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, | ||
| 1499 | { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, | 1498 | { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, |
| 1500 | { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, | 1499 | { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, |
| 1501 | { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, | 1500 | { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, |
| @@ -1542,13 +1541,16 @@ static const TCCOption tcc_options[] = { · 40 unmodified lines | |||
| 1542 | { "nostdinc", TCC_OPTION_nostdinc, 0 }, | 1541 | { "nostdinc", TCC_OPTION_nostdinc, 0 }, |
| 1543 | { "nostdlib", TCC_OPTION_nostdlib, 0 }, | 1542 | { "nostdlib", TCC_OPTION_nostdlib, 0 }, |
| 1544 | { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, | 1543 | { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, |
| 1545 | { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, | ||
| 1546 | { "w", TCC_OPTION_w, 0 }, | 1544 | { "w", TCC_OPTION_w, 0 }, |
| 1547 | { "pipe", TCC_OPTION_pipe, 0}, | 1545 | { "pipe", TCC_OPTION_pipe, 0}, |
| 1548 | { "E", TCC_OPTION_E, 0}, | 1546 | { "E", TCC_OPTION_E, 0}, |
| 1549 | { "MD", TCC_OPTION_MD, 0}, | 1547 | { "MD", TCC_OPTION_MD, 0}, |
| 1550 | { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, | 1548 | { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, |
| 1551 | { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, | 1549 | { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, |
| 1550 | { "ar", TCC_OPTION_ar, 0}, | ||
| 1551 | #ifdef TCC_TARGET_PE | ||
| 1552 | { "impdef", TCC_OPTION_impdef, 0}, | ||
| 1553 | #endif | ||
| 1552 | { NULL, 0, 0 }, | 1554 | { NULL, 0, 0 }, |
| 1553 | }; | 1555 | }; |
| 1554 | 1556 | ||
| @@ -1595,58 +1597,106 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 40 unmodified lines | |||
| 1595 | { | 1597 | { |
| 1596 | struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); | 1598 | struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); |
| 1597 | f->type = filetype; | 1599 | f->type = filetype; |
| 1600 | f->alacarte = s->alacarte_link; | ||
| 1598 | strcpy(f->name, filename); | 1601 | strcpy(f->name, filename); |
| 1599 | dynarray_add(&s->files, &s->nb_files, f); | 1602 | dynarray_add(&s->files, &s->nb_files, f); |
| 1600 | } | 1603 | } |
| 1601 | 1604 | ||
| 1605 | static int args_parser_make_argv(const char *r, int *argc, char ***argv) | ||
| 1606 | { | ||
| 1607 | int ret = 0, q, c; | ||
| 1608 | CString str; | ||
| 1609 | for(;;) { | ||
| 1610 | while (c = (unsigned char)*r, c && c <= ' ') | ||
| 1611 | ++r; | ||
| 1612 | if (c == 0) | ||
| 1613 | break; | ||
| 1614 | q = 0; | ||
| 1615 | cstr_new(&str); | ||
| 1616 | while (c = (unsigned char)*r, c) { | ||
| 1617 | ++r; | ||
| 1618 | if (c == '\\' && (*r == '"' || *r == '\\')) { | ||
| 1619 | c = *r++; | ||
| 1620 | } else if (c == '"') { | ||
| 1621 | q = !q; | ||
| 1622 | continue; | ||
| 1623 | } else if (q == 0 && c <= ' ') { | ||
| 1624 | break; | ||
| 1625 | } | ||
| 1626 | cstr_ccat(&str, c); | ||
| 1627 | } | ||
| 1628 | cstr_ccat(&str, 0); | ||
| 1629 | //printf("<%s>\n", str.data), fflush(stdout); | ||
| 1630 | dynarray_add(argv, argc, tcc_strdup(str.data)); | ||
| 1631 | cstr_free(&str); | ||
| 1632 | ++ret; | ||
| 1633 | } | ||
| 1634 | return ret; | ||
| 1635 | } | ||
| 1636 | |||
| 1602 | /* read list file */ | 1637 | /* read list file */ |
| 1603 | static void args_parser_listfile(TCCState *s, const char *filename) | 1638 | static void args_parser_listfile(TCCState *s, |
| 1639 | const char *filename, int optind, int *pargc, char ***pargv) | ||
| 1604 | { | 1640 | { |
| 1605 | int fd; | 1641 | int fd, i; |
| 1606 | size_t len; | 1642 | size_t len; |
| 1607 | char *p; | 1643 | char *p; |
| 1644 | int argc = 0; | ||
| 1645 | char **argv = NULL; | ||
| 1608 | 1646 | ||
| 1609 | fd = open(filename, O_RDONLY | O_BINARY); | 1647 | fd = open(filename, O_RDONLY | O_BINARY); |
| 1610 | if (fd < 0) | 1648 | if (fd < 0) |
| 1611 | tcc_error("file '%s' not found", filename); | 1649 | tcc_error("listfile '%s' not found", filename); |
| 1612 | 1650 | ||
| 1613 | len = lseek(fd, 0, SEEK_END); | 1651 | len = lseek(fd, 0, SEEK_END); |
| 1614 | p = tcc_malloc(len + 1), p[len] = 0; | 1652 | p = tcc_malloc(len + 1), p[len] = 0; |
| 1615 | lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); | 1653 | lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); |
| 1616 | tcc_set_options(s, p); | 1654 | |
| 1655 | for (i = 0; i < *pargc; ++i) | ||
| 1656 | if (i == optind) | ||
| 1657 | args_parser_make_argv(p, &argc, &argv); | ||
| 1658 | else | ||
| 1659 | dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i])); | ||
| 1660 | |||
| 1617 | tcc_free(p); | 1661 | tcc_free(p); |
| 1662 | dynarray_reset(&s->argv, &s->argc); | ||
| 1663 | *pargc = s->argc = argc, *pargv = s->argv = argv; | ||
| 1618 | } | 1664 | } |
| 1619 | 1665 | ||
| 1620 | PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) | 1666 | PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) |
| 1621 | { | 1667 | { |
| 1622 | const TCCOption *popt; | 1668 | const TCCOption *popt; |
| 1623 | const char *optarg, *r; | 1669 | const char *optarg, *r; |
| 1624 | const char *run = NULL; | 1670 | const char *run = NULL; |
| 1625 | int optind = 0; | ||
| 1626 | int x; | ||
| 1627 | int last_o = -1; | 1671 | int last_o = -1; |
| 1672 | int x; | ||
| 1628 | CString linker_arg; /* collect -Wl options */ | 1673 | CString linker_arg; /* collect -Wl options */ |
| 1629 | char buf[1024]; | 1674 | char buf[1024]; |
| 1675 | int tool = 0, arg_start = 0, noaction = optind; | ||
| 1676 | char **argv = *pargv; | ||
| 1677 | int argc = *pargc; | ||
| 1630 | 1678 | ||
| 1631 | cstr_new(&linker_arg); | 1679 | cstr_new(&linker_arg); |
| 1632 | 1680 | ||
| 1633 | while (optind < argc) { | 1681 | while (optind < argc) { |
| 1634 | 1682 | r = argv[optind]; | |
| 1635 | r = argv[optind++]; | ||
| 1636 | |||
| 1637 | reparse: | ||
| 1638 | if (r[0] == '@' && r[1] != '\0') { | 1683 | if (r[0] == '@' && r[1] != '\0') { |
| 1639 | args_parser_listfile(s, r + 1); | 1684 | args_parser_listfile(s, r + 1, optind, &argc, &argv); |
| 1640 | continue; | 1685 | continue; |
| 1641 | } | 1686 | } |
| 1642 | 1687 | optind++; | |
| 1688 | if (tool) { | ||
| 1689 | if (r[0] == '-' && r[1] == 'v' && r[2] == 0) | ||
| 1690 | ++s->verbose; | ||
| 1691 | continue; | ||
| 1692 | } | ||
| 1693 | reparse: | ||
| 1643 | if (r[0] != '-' || r[1] == '\0') { | 1694 | if (r[0] != '-' || r[1] == '\0') { |
| 1644 | if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ | 1695 | if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ |
| 1645 | args_parser_add_file(s, r, s->filetype); | 1696 | args_parser_add_file(s, r, s->filetype); |
| 1646 | if (run) { | 1697 | if (run) { |
| 1647 | tcc_set_options(s, run); | 1698 | tcc_set_options(s, run); |
| 1648 | optind--; | 1699 | arg_start = optind - 1; |
| 1649 | /* argv[0] will be this file */ | ||
| 1650 | break; | 1700 | break; |
| 1651 | } | 1701 | } |
| 1652 | continue; | 1702 | continue; |
| @@ -1675,7 +1725,7 @@ reparse: · 22 unmodified lines | |||
| 1675 | 1725 | ||
| 1676 | switch(popt->index) { | 1726 | switch(popt->index) { |
| 1677 | case TCC_OPTION_HELP: | 1727 | case TCC_OPTION_HELP: |
| 1678 | return 0; | 1728 | return OPT_HELP; |
| 1679 | case TCC_OPTION_I: | 1729 | case TCC_OPTION_I: |
| 1680 | tcc_add_include_path(s, optarg); | 1730 | tcc_add_include_path(s, optarg); |
| 1681 | break; | 1731 | break; |
| @@ -1693,7 +1743,7 @@ reparse: · 11 unmodified lines | |||
| 1693 | tcc_set_lib_path(s, optarg); | 1743 | tcc_set_lib_path(s, optarg); |
| 1694 | break; | 1744 | break; |
| 1695 | case TCC_OPTION_l: | 1745 | case TCC_OPTION_l: |
| 1696 | args_parser_add_file(s, optarg, AFF_TYPE_LIBWH - s->alacarte_link); | 1746 | args_parser_add_file(s, optarg, AFF_TYPE_LIB); |
| 1697 | s->nb_libraries++; | 1747 | s->nb_libraries++; |
| 1698 | break; | 1748 | break; |
| 1699 | case TCC_OPTION_pthread: | 1749 | case TCC_OPTION_pthread: |
| @@ -1774,9 +1824,6 @@ reparse: · 74 unmodified lines | |||
| 1774 | case TCC_OPTION_nostdlib: | 1824 | case TCC_OPTION_nostdlib: |
| 1775 | s->nostdlib = 1; | 1825 | s->nostdlib = 1; |
| 1776 | break; | 1826 | break; |
| 1777 | case TCC_OPTION_print_search_dirs: | ||
| 1778 | s->print_search_dirs = 1; | ||
| 1779 | break; | ||
| 1780 | case TCC_OPTION_run: | 1827 | case TCC_OPTION_run: |
| 1781 | #ifndef TCC_IS_NATIVE | 1828 | #ifndef TCC_IS_NATIVE |
| 1782 | tcc_error("-run is not available in a cross compiler"); | 1829 | tcc_error("-run is not available in a cross compiler"); |
| @@ -1786,6 +1833,7 @@ reparse: · 3 unmodified lines | |||
| 1786 | goto set_output_type; | 1833 | goto set_output_type; |
| 1787 | case TCC_OPTION_v: | 1834 | case TCC_OPTION_v: |
| 1788 | do ++s->verbose; while (*optarg++ == 'v'); | 1835 | do ++s->verbose; while (*optarg++ == 'v'); |
| 1836 | ++noaction; | ||
| 1789 | break; | 1837 | break; |
| 1790 | case TCC_OPTION_f: | 1838 | case TCC_OPTION_f: |
| 1791 | if (set_flag(s, options_f, optarg) < 0) | 1839 | if (set_flag(s, options_f, optarg) < 0) |
| @@ -1804,12 +1852,13 @@ reparse: · 12 unmodified lines | |||
| 1804 | break; | 1852 | break; |
| 1805 | #endif | 1853 | #endif |
| 1806 | case TCC_OPTION_m: | 1854 | case TCC_OPTION_m: |
| 1807 | if (set_flag(s, options_m, optarg) == 0) | 1855 | if (set_flag(s, options_m, optarg) < 0) { |
| 1808 | break; | 1856 | if (x = atoi(optarg), x != 32 && x != 64) |
| 1809 | else if (x = atoi(optarg), x == 32 || x == 64) | 1857 | goto unsupported_option; |
| 1810 | s->cross_target = x; | 1858 | if (PTR_SIZE != x/8) |
| 1811 | else | 1859 | return x; |
| 1812 | goto unsupported_option; | 1860 | ++noaction; |
| 1861 | } | ||
| 1813 | break; | 1862 | break; |
| 1814 | case TCC_OPTION_W: | 1863 | case TCC_OPTION_W: |
| 1815 | if (set_flag(s, options_W, optarg) < 0) | 1864 | if (set_flag(s, options_W, optarg) < 0) |
| @@ -1860,6 +1909,20 @@ reparse: · 44 unmodified lines | |||
| 1860 | case TCC_OPTION_O: | 1909 | case TCC_OPTION_O: |
| 1861 | last_o = atoi(optarg); | 1910 | last_o = atoi(optarg); |
| 1862 | break; | 1911 | break; |
| 1912 | case TCC_OPTION_print_search_dirs: | ||
| 1913 | x = OPT_PRINT_DIRS; | ||
| 1914 | goto extra_action; | ||
| 1915 | case TCC_OPTION_impdef: | ||
| 1916 | x = OPT_IMPDEF; | ||
| 1917 | goto extra_action; | ||
| 1918 | case TCC_OPTION_ar: | ||
| 1919 | x = OPT_AR; | ||
| 1920 | extra_action: | ||
| 1921 | arg_start = optind - 1; | ||
| 1922 | if (arg_start != noaction) | ||
| 1923 | tcc_error("cannot parse %s here", r); | ||
| 1924 | tool = x; | ||
| 1925 | break; | ||
| 1863 | case TCC_OPTION_traditional: | 1926 | case TCC_OPTION_traditional: |
| 1864 | case TCC_OPTION_pedantic: | 1927 | case TCC_OPTION_pedantic: |
| 1865 | case TCC_OPTION_pipe: | 1928 | case TCC_OPTION_pipe: |
| @@ -1873,53 +1936,32 @@ unsupported_option: · 7 unmodified lines | |||
| 1873 | break; | 1936 | break; |
| 1874 | } | 1937 | } |
| 1875 | } | 1938 | } |
| 1876 | |||
| 1877 | if (last_o > 0) | 1939 | if (last_o > 0) |
| 1878 | tcc_define_symbol(s, "__OPTIMIZE__", NULL); | 1940 | tcc_define_symbol(s, "__OPTIMIZE__", NULL); |
| 1879 | |||
| 1880 | if (linker_arg.size) { | 1941 | if (linker_arg.size) { |
| 1881 | r = linker_arg.data; | 1942 | r = linker_arg.data; |
| 1882 | goto arg_err; | 1943 | goto arg_err; |
| 1883 | } | 1944 | } |
| 1884 | 1945 | *pargc = argc - arg_start; | |
| 1885 | return optind; | 1946 | *pargv = argv + arg_start; |
| 1947 | if (tool) | ||
| 1948 | return tool; | ||
| 1949 | if (optind != noaction) | ||
| 1950 | return 0; | ||
| 1951 | if (s->verbose == 2) | ||
| 1952 | return OPT_PRINT_DIRS; | ||
| 1953 | if (s->verbose) | ||
| 1954 | return OPT_V; | ||
| 1955 | return OPT_HELP; | ||
| 1886 | } | 1956 | } |
| 1887 | 1957 | ||
| 1888 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) | 1958 | LIBTCCAPI void tcc_set_options(TCCState *s, const char *r) |
| 1889 | { | 1959 | { |
| 1890 | char **argv; | 1960 | char **argv = NULL; |
| 1891 | int argc; | 1961 | int argc = 0; |
| 1892 | int ret, q, c; | 1962 | args_parser_make_argv(r, &argc, &argv); |
| 1893 | CString str; | 1963 | tcc_parse_args(s, &argc, &argv, 0); |
| 1894 | |||
| 1895 | argc = 0, argv = NULL; | ||
| 1896 | for(;;) { | ||
| 1897 | while (c = (unsigned char)*r, c && c <= ' ') | ||
| 1898 | ++r; | ||
| 1899 | if (c == 0) | ||
| 1900 | break; | ||
| 1901 | q = 0; | ||
| 1902 | cstr_new(&str); | ||
| 1903 | while (c = (unsigned char)*r, c) { | ||
| 1904 | ++r; | ||
| 1905 | if (c == '\\' && (*r == '"' || *r == '\\')) { | ||
| 1906 | c = *r++; | ||
| 1907 | } else if (c == '"') { | ||
| 1908 | q = !q; | ||
| 1909 | continue; | ||
| 1910 | } else if (q == 0 && c <= ' ') { | ||
| 1911 | break; | ||
| 1912 | } | ||
| 1913 | cstr_ccat(&str, c); | ||
| 1914 | } | ||
| 1915 | cstr_ccat(&str, 0); | ||
| 1916 | //printf("<%s>\n", str.data), fflush(stdout); | ||
| 1917 | dynarray_add(&argv, &argc, tcc_strdup(str.data)); | ||
| 1918 | cstr_free(&str); | ||
| 1919 | } | ||
| 1920 | ret = tcc_parse_args(s, argc, argv); | ||
| 1921 | dynarray_reset(&argv, &argc); | 1964 | dynarray_reset(&argv, &argc); |
| 1922 | return ret; | ||
| 1923 | } | 1965 | } |
| 1924 | 1966 | ||
| 1925 | PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) | 1967 | 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) · 2 unmodified lines | |||
| 1928 | total_time = 1; | 1970 | total_time = 1; |
| 1929 | if (total_bytes < 1) | 1971 | if (total_bytes < 1) |
| 1930 | total_bytes = 1; | 1972 | total_bytes = 1; |
| 1931 | fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %u lines/s, %0.1f MB/s\n", | 1973 | fprintf(stderr, "* %d idents, %d lines, %d bytes\n" |
| 1974 | "* %0.3f s, %u lines/s, %0.1f MB/s\n", | ||
| 1932 | tok_ident - TOK_IDENT, total_lines, total_bytes, | 1975 | tok_ident - TOK_IDENT, total_lines, total_bytes, |
| 1933 | (double)total_time/1000, | 1976 | (double)total_time/1000, |
| 1934 | (unsigned)total_lines*1000/total_time, | 1977 | (unsigned)total_lines*1000/total_time, |
| 1935 | (double)total_bytes/1000/total_time); | 1978 | (double)total_bytes/1000/total_time); |
| 1979 | #ifdef MEM_DEBUG | ||
| 1980 | fprintf(stderr, "* %d bytes memory used\n", mem_max_size); | ||
| 1981 | #endif | ||
| 1936 | } | 1982 | } |
| 1937 | 1983 | ||
| 1938 | PUB_FUNC void tcc_set_environment(TCCState *s) | 1984 | PUB_FUNC void tcc_set_environment(TCCState *s) |
| @@ -27,7 +27,7 @@ LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, · 26 unmodified lines | |||
| 27 | void (*error_func)(void *opaque, const char *msg)); | 27 | void (*error_func)(void *opaque, const char *msg)); |
| 28 | 28 | ||
| 29 | /* set options as from command line (multiple supported) */ | 29 | /* set options as from command line (multiple supported) */ |
| 30 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); | 30 | LIBTCCAPI void tcc_set_options(TCCState *s, const char *str); |
| 31 | 31 | ||
| 32 | /*****************************/ | 32 | /*****************************/ |
| 33 | /* preprocessor */ | 33 | /* preprocessor */ |
| @@ -23,69 +23,7 @@ · 22 unmodified lines | |||
| 23 | #else | 23 | #else |
| 24 | #include "tcc.h" | 24 | #include "tcc.h" |
| 25 | #endif | 25 | #endif |
| 26 | 26 | #include "tcctools.c" | |
| 27 | static void print_paths(const char *msg, char **paths, int nb_paths) | ||
| 28 | { | ||
| 29 | int i; | ||
| 30 | printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); | ||
| 31 | for(i = 0; i < nb_paths; i++) | ||
| 32 | printf(" %s\n", paths[i]); | ||
| 33 | } | ||
| 34 | |||
| 35 | static void display_info(TCCState *s, int what) | ||
| 36 | { | ||
| 37 | switch (what) { | ||
| 38 | case 0: | ||
| 39 | printf("tcc version %s (" | ||
| 40 | #ifdef TCC_TARGET_I386 | ||
| 41 | "i386" | ||
| 42 | #elif defined TCC_TARGET_X86_64 | ||
| 43 | "x86-64" | ||
| 44 | #elif defined TCC_TARGET_C67 | ||
| 45 | "C67" | ||
| 46 | #elif defined TCC_TARGET_ARM | ||
| 47 | "ARM" | ||
| 48 | # ifdef TCC_ARM_HARDFLOAT | ||
| 49 | " Hard Float" | ||
| 50 | # endif | ||
| 51 | #elif defined TCC_TARGET_ARM64 | ||
| 52 | "AArch64" | ||
| 53 | # ifdef TCC_ARM_HARDFLOAT | ||
| 54 | " Hard Float" | ||
| 55 | # endif | ||
| 56 | #endif | ||
| 57 | #ifdef TCC_TARGET_PE | ||
| 58 | " Windows" | ||
| 59 | #elif defined(__APPLE__) | ||
| 60 | /* Current Apple OS name as of 2016 */ | ||
| 61 | " macOS" | ||
| 62 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | ||
| 63 | " FreeBSD" | ||
| 64 | #elif defined(__DragonFly__) | ||
| 65 | " DragonFly BSD" | ||
| 66 | #elif defined(__NetBSD__) | ||
| 67 | " NetBSD" | ||
| 68 | #elif defined(__OpenBSD__) | ||
| 69 | " OpenBSD" | ||
| 70 | #elif defined(__linux__) | ||
| 71 | " Linux" | ||
| 72 | #else | ||
| 73 | " Unidentified system" | ||
| 74 | #endif | ||
| 75 | ")\n", TCC_VERSION); | ||
| 76 | break; | ||
| 77 | case 1: | ||
| 78 | printf("install: %s\n", s->tcc_lib_path); | ||
| 79 | /* print_paths("programs", NULL, 0); */ | ||
| 80 | print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths); | ||
| 81 | print_paths("libraries", s->library_paths, s->nb_library_paths); | ||
| 82 | #ifndef TCC_TARGET_PE | ||
| 83 | print_paths("crt", s->crt_paths, s->nb_crt_paths); | ||
| 84 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); | ||
| 85 | #endif | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | 27 | ||
| 90 | static void help(void) | 28 | static void help(void) |
| 91 | { | 29 | { |
| @@ -100,7 +38,8 @@ static void help(void) · 8 unmodified lines | |||
| 100 | " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" | 38 | " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" |
| 101 | " -w disable all warnings\n" | 39 | " -w disable all warnings\n" |
| 102 | " -v show version\n" | 40 | " -v show version\n" |
| 103 | " -vv show included files (as sole argument: show search paths)\n" | 41 | " -vv show included files (as sole argument show search paths)\n" |
| 42 | " -h show this help\n" | ||
| 104 | " -bench show compilation statistics\n" | 43 | " -bench show compilation statistics\n" |
| 105 | "Preprocessor options:\n" | 44 | "Preprocessor options:\n" |
| 106 | " -Idir add include path 'dir'\n" | 45 | " -Idir add include path 'dir'\n" |
| @@ -146,115 +85,75 @@ static void help(void) · 39 unmodified lines | |||
| 146 | #endif | 85 | #endif |
| 147 | #ifdef TCC_TARGET_X86_64 | 86 | #ifdef TCC_TARGET_X86_64 |
| 148 | " -mno-sse disable floats on x86-64\n" | 87 | " -mno-sse disable floats on x86-64\n" |
| 88 | #endif | ||
| 89 | "Tools:\n" | ||
| 90 | " create library : tcc -ar [rcsv] lib.a files\n" | ||
| 91 | #ifdef TCC_TARGET_PE | ||
| 92 | " create .def file : tcc -impdef lib.dll [-v] [-o lib.def]\n" | ||
| 149 | #endif | 93 | #endif |
| 150 | ); | 94 | ); |
| 151 | } | 95 | } |
| 152 | 96 | ||
| 153 | /* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */ | ||
| 154 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | ||
| 155 | #ifdef _WIN32 | ||
| 156 | #include <process.h> | ||
| 157 | |||
| 158 | static char *str_replace(const char *str, const char *p, const char *r) | ||
| 159 | { | ||
| 160 | const char *s, *s0; | ||
| 161 | char *d, *d0; | ||
| 162 | int sl, pl, rl; | ||
| 163 | |||
| 164 | sl = strlen(str); | ||
| 165 | pl = strlen(p); | ||
| 166 | rl = strlen(r); | ||
| 167 | for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) { | ||
| 168 | for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) { | ||
| 169 | if (d) { | ||
| 170 | memcpy(d, s0, sl = s - s0), d += sl; | ||
| 171 | memcpy(d, r, rl), d += rl; | ||
| 172 | } else | ||
| 173 | sl += rl - pl; | ||
| 174 | } | ||
| 175 | if (d) { | ||
| 176 | strcpy(d, s0); | ||
| 177 | return d0; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | 97 | ||
| 182 | static int execvp_win32(const char *prog, char **argv) | 98 | static void version(void) |
| 183 | { | ||
| 184 | int ret; char **p; | ||
| 185 | /* replace all " by \" */ | ||
| 186 | for (p = argv; *p; ++p) | ||
| 187 | if (strchr(*p, '"')) | ||
| 188 | *p = str_replace(*p, "\"", "\\\""); | ||
| 189 | ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv); | ||
| 190 | if (-1 == ret) | ||
| 191 | return ret; | ||
| 192 | cwait(&ret, ret, WAIT_CHILD); | ||
| 193 | exit(ret); | ||
| 194 | } | ||
| 195 | #define execvp execvp_win32 | ||
| 196 | #endif | ||
| 197 | static void exec_other_tcc(TCCState *s, char **argv, int option) | ||
| 198 | { | 99 | { |
| 199 | char child_path[4096], *a0 = argv[0]; const char *target; | 100 | printf("tcc version %s (" |
| 200 | int l; | ||
| 201 | |||
| 202 | switch (option) { | ||
| 203 | |||
| 204 | #ifdef TCC_TARGET_I386 | 101 | #ifdef TCC_TARGET_I386 |
| 205 | case 32: break; | 102 | "i386" |
| 206 | case 64: target = "x86_64"; | 103 | #elif defined TCC_TARGET_X86_64 |
| 207 | #else | 104 | "x86-64" |
| 208 | case 64: break; | 105 | #elif defined TCC_TARGET_C67 |
| 209 | case 32: target = "i386"; | 106 | "C67" |
| 210 | 107 | #elif defined TCC_TARGET_ARM | |
| 108 | "ARM" | ||
| 109 | # ifdef TCC_ARM_HARDFLOAT | ||
| 110 | " Hard Float" | ||
| 111 | # endif | ||
| 112 | #elif defined TCC_TARGET_ARM64 | ||
| 113 | "AArch64" | ||
| 114 | # ifdef TCC_ARM_HARDFLOAT | ||
| 115 | " Hard Float" | ||
| 116 | # endif | ||
| 211 | #endif | 117 | #endif |
| 212 | l = tcc_basename(a0) - a0; | ||
| 213 | snprintf(child_path, sizeof child_path, | ||
| 214 | #ifdef TCC_TARGET_PE | 118 | #ifdef TCC_TARGET_PE |
| 215 | "%.*s%s-win32-tcc" | 119 | " Windows" |
| 120 | #elif defined(__APPLE__) | ||
| 121 | /* Current Apple OS name as of 2016 */ | ||
| 122 | " macOS" | ||
| 123 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | ||
| 124 | " FreeBSD" | ||
| 125 | #elif defined(__DragonFly__) | ||
| 126 | " DragonFly BSD" | ||
| 127 | #elif defined(__NetBSD__) | ||
| 128 | " NetBSD" | ||
| 129 | #elif defined(__OpenBSD__) | ||
| 130 | " OpenBSD" | ||
| 131 | #elif defined(__linux__) | ||
| 132 | " Linux" | ||
| 216 | #else | 133 | #else |
| 217 | "%.*s%s-tcc" | 134 | " Unidentified system" |
| 218 | #endif | 135 | #endif |
| 219 | , l, a0, target); | 136 | ")\n", TCC_VERSION); |
| 220 | if (strcmp(a0, child_path)) { | ||
| 221 | if (s->verbose > 0) | ||
| 222 | printf("tcc: using '%s'\n", child_path + l), fflush(stdout); | ||
| 223 | execvp(argv[0] = child_path, argv); | ||
| 224 | } | ||
| 225 | tcc_error("'%s' not found", child_path + l); | ||
| 226 | } | ||
| 227 | } | 137 | } |
| 228 | #else | ||
| 229 | #define exec_other_tcc(s, argv, option) | ||
| 230 | #endif | ||
| 231 | 138 | ||
| 232 | static void gen_makedeps(TCCState *s, const char *target, const char *filename) | 139 | static void print_dirs(const char *msg, char **paths, int nb_paths) |
| 233 | { | 140 | { |
| 234 | FILE *depout; | ||
| 235 | char buf[1024]; | ||
| 236 | int i; | 141 | int i; |
| 142 | printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); | ||
| 143 | for(i = 0; i < nb_paths; i++) | ||
| 144 | printf(" %s\n", paths[i]); | ||
| 145 | } | ||
| 237 | 146 | ||
| 238 | if (!filename) { | 147 | static void print_search_dirs(TCCState *s) |
| 239 | /* compute filename automatically: dir/file.o -> dir/file.d */ | 148 | { |
| 240 | snprintf(buf, sizeof buf, "%.*s.d", | 149 | printf("install: %s\n", s->tcc_lib_path); |
| 241 | (int)(tcc_fileextension(target) - target), target); | 150 | /* print_dirs("programs", NULL, 0); */ |
| 242 | filename = buf; | 151 | print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); |
| 243 | } | 152 | print_dirs("libraries", s->library_paths, s->nb_library_paths); |
| 244 | 153 | #ifndef TCC_TARGET_PE | |
| 245 | if (s->verbose) | 154 | print_dirs("crt", s->crt_paths, s->nb_crt_paths); |
| 246 | printf("<- %s\n", filename); | 155 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); |
| 247 | 156 | #endif | |
| 248 | /* XXX return err codes instead of error() ? */ | ||
| 249 | depout = fopen(filename, "w"); | ||
| 250 | if (!depout) | ||
| 251 | tcc_error("could not open '%s'", filename); | ||
| 252 | |||
| 253 | fprintf(depout, "%s: \\\n", target); | ||
| 254 | for (i=0; i<s->nb_target_deps; ++i) | ||
| 255 | fprintf(depout, " %s \\\n", s->target_deps[i]); | ||
| 256 | fprintf(depout, "\n"); | ||
| 257 | fclose(depout); | ||
| 258 | } | 157 | } |
| 259 | 158 | ||
| 260 | static char *default_outputfile(TCCState *s, const char *first_file) | 159 | static char *default_outputfile(TCCState *s, const char *first_file) |
| @@ -296,109 +195,113 @@ static unsigned getclock_ms(void) · 35 unmodified lines | |||
| 296 | int main(int argc, char **argv) | 195 | int main(int argc, char **argv) |
| 297 | { | 196 | { |
| 298 | TCCState *s; | 197 | TCCState *s; |
| 299 | int ret, optind, i; | 198 | int ret, opt, n = 0; |
| 300 | unsigned start_time = 0; | 199 | unsigned start_time = 0; |
| 301 | const char *first_file = NULL; | 200 | const char *first_file; |
| 302 | 201 | ||
| 202 | redo: | ||
| 303 | s = tcc_new(); | 203 | s = tcc_new(); |
| 204 | opt = tcc_parse_args(s, &argc, &argv, 1); | ||
| 205 | |||
| 206 | if (n == 0) { | ||
| 207 | if (opt == OPT_HELP) | ||
| 208 | return help(), 1; | ||
| 209 | if (opt == OPT_M32 || opt == OPT_M64) | ||
| 210 | tcc_tool_cross(s, argv, opt); /* never returns */ | ||
| 211 | if (s->verbose) | ||
| 212 | version(); | ||
| 213 | if (opt == OPT_AR) | ||
| 214 | return tcc_tool_ar(s, argc, argv); | ||
| 215 | #ifdef TCC_TARGET_PE | ||
| 216 | if (opt == OPT_IMPDEF) | ||
| 217 | return tcc_tool_impdef(s, argc, argv); | ||
| 218 | #endif | ||
| 219 | if (opt == OPT_V) | ||
| 220 | return 0; | ||
| 304 | 221 | ||
| 305 | optind = tcc_parse_args(s, argc - 1, argv + 1); | 222 | tcc_set_environment(s); |
| 306 | |||
| 307 | tcc_set_environment(s); | ||
| 308 | |||
| 309 | if (optind == 0) { | ||
| 310 | help(); | ||
| 311 | return 1; | ||
| 312 | } | ||
| 313 | |||
| 314 | if (s->cross_target) | ||
| 315 | exec_other_tcc(s, argv, s->cross_target); | ||
| 316 | 223 | ||
| 317 | if (s->verbose) | 224 | if (opt == OPT_PRINT_DIRS) { |
| 318 | display_info(s, 0); | 225 | /* initialize search dirs */ |
| 226 | tcc_set_output_type(s, TCC_OUTPUT_MEMORY); | ||
| 227 | print_search_dirs(s); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 319 | 230 | ||
| 320 | if (s->nb_files == 0) { | 231 | n = s->nb_files; |
| 321 | if (optind == 1) { | 232 | if (n == 0) |
| 322 | if (s->print_search_dirs || s->verbose == 2) { | 233 | tcc_error("no input files\n"); |
| 323 | tcc_set_output_type(s, TCC_OUTPUT_MEMORY); | 234 | |
| 324 | display_info(s, 1); | 235 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
| 325 | return 1; | 236 | if (!s->outfile) { |
| 237 | s->ppfp = stdout; | ||
| 238 | } else { | ||
| 239 | s->ppfp = fopen(s->outfile, "w"); | ||
| 240 | if (!s->ppfp) | ||
| 241 | tcc_error("could not write '%s'", s->outfile); | ||
| 326 | } | 242 | } |
| 327 | if (s->verbose) | 243 | } else if (s->output_type == TCC_OUTPUT_OBJ) { |
| 328 | return 1; | 244 | if (s->nb_libraries != 0 && !s->option_r) |
| 245 | tcc_error("cannot specify libraries with -c"); | ||
| 246 | if (n > 1 && s->outfile) | ||
| 247 | tcc_error("cannot specify output file with -c many files"); | ||
| 248 | } else { | ||
| 249 | if (s->option_pthread) | ||
| 250 | tcc_set_options(s, "-lpthread"); | ||
| 329 | } | 251 | } |
| 330 | tcc_error("no input files\n"); | ||
| 331 | } | ||
| 332 | 252 | ||
| 333 | /* check -c consistency : only single file handled. XXX: checks file type */ | 253 | if (s->do_bench) |
| 334 | if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { | 254 | start_time = getclock_ms(); |
| 335 | if (s->nb_libraries != 0) | ||
| 336 | tcc_error("cannot specify libraries with -c"); | ||
| 337 | /* accepts only a single input file */ | ||
| 338 | if (s->nb_files != 1) | ||
| 339 | tcc_error("cannot specify multiple files with -c"); | ||
| 340 | } | 255 | } |
| 341 | 256 | ||
| 342 | if (s->output_type == 0) | 257 | if (s->output_type == 0) |
| 343 | s->output_type = TCC_OUTPUT_EXE; | 258 | s->output_type = TCC_OUTPUT_EXE; |
| 344 | tcc_set_output_type(s, s->output_type); | 259 | tcc_set_output_type(s, s->output_type); |
| 345 | 260 | ||
| 346 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { | ||
| 347 | if (!s->outfile) { | ||
| 348 | s->ppfp = stdout; | ||
| 349 | } else { | ||
| 350 | s->ppfp = fopen(s->outfile, "w"); | ||
| 351 | if (!s->ppfp) | ||
| 352 | tcc_error("could not write '%s'", s->outfile); | ||
| 353 | } | ||
| 354 | } else if (s->output_type != TCC_OUTPUT_OBJ) { | ||
| 355 | if (s->option_pthread) | ||
| 356 | tcc_set_options(s, "-lpthread"); | ||
| 357 | } | ||
| 358 | |||
| 359 | if (s->do_bench) | ||
| 360 | start_time = getclock_ms(); | ||
| 361 | |||
| 362 | /* compile or add each files or library */ | 261 | /* compile or add each files or library */ |
| 363 | for(i = ret = 0; i < s->nb_files && ret == 0; i++) { | 262 | for (first_file = NULL, ret = 0;;) { |
| 364 | struct filespec *f = s->files[i]; | 263 | struct filespec *f = s->files[s->nb_files - n]; |
| 365 | if (f->type >= AFF_TYPE_LIB) { | 264 | s->filetype = f->type; |
| 366 | s->alacarte_link = f->type == AFF_TYPE_LIB; | 265 | s->alacarte_link = f->alacarte; |
| 266 | if (f->type == AFF_TYPE_LIB) { | ||
| 367 | if (tcc_add_library_err(s, f->name) < 0) | 267 | if (tcc_add_library_err(s, f->name) < 0) |
| 368 | ret = 1; | 268 | ret = 1; |
| 369 | } else { | 269 | } else { |
| 370 | if (1 == s->verbose) | 270 | if (1 == s->verbose) |
| 371 | printf("-> %s\n", f->name); | 271 | printf("-> %s\n", f->name); |
| 372 | s->filetype = f->type; | ||
| 373 | if (tcc_add_file(s, f->name) < 0) | ||
| 374 | ret = 1; | ||
| 375 | if (!first_file) | 272 | if (!first_file) |
| 376 | first_file = f->name; | 273 | first_file = f->name; |
| 274 | if (tcc_add_file(s, f->name) < 0) | ||
| 275 | ret = 1; | ||
| 377 | } | 276 | } |
| 378 | s->filetype = AFF_TYPE_NONE; | 277 | s->filetype = 0; |
| 379 | s->alacarte_link = 1; | 278 | s->alacarte_link = 1; |
| 279 | if (ret || --n == 0 || s->output_type == TCC_OUTPUT_OBJ) | ||
| 280 | break; | ||
| 380 | } | 281 | } |
| 381 | 282 | ||
| 382 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { | 283 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
| 383 | if (s->outfile) | 284 | if (s->outfile) |
| 384 | fclose(s->ppfp); | 285 | fclose(s->ppfp); |
| 385 | |||
| 386 | } else if (0 == ret) { | 286 | } else if (0 == ret) { |
| 387 | if (s->output_type == TCC_OUTPUT_MEMORY) { | 287 | if (s->output_type == TCC_OUTPUT_MEMORY) { |
| 388 | #ifdef TCC_IS_NATIVE | 288 | #ifdef TCC_IS_NATIVE |
| 389 | ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind); | 289 | ret = tcc_run(s, argc, argv); |
| 390 | #endif | 290 | #endif |
| 391 | } else { | 291 | } else { |
| 392 | if (!s->outfile) | 292 | if (!s->outfile) |
| 393 | s->outfile = default_outputfile(s, first_file); | 293 | s->outfile = default_outputfile(s, first_file); |
| 394 | ret = !!tcc_output_file(s, s->outfile); | 294 | if (tcc_output_file(s, s->outfile)) |
| 395 | if (s->gen_deps && !ret) | 295 | ret = 1; |
| 296 | else if (s->gen_deps) | ||
| 396 | gen_makedeps(s, s->outfile, s->deps_outfile); | 297 | gen_makedeps(s, s->outfile, s->deps_outfile); |
| 397 | } | 298 | } |
| 398 | } | 299 | } |
| 399 | 300 | ||
| 400 | if (s->do_bench) | 301 | if (s->do_bench && ret == 0 && n == 0) |
| 401 | tcc_print_stats(s, getclock_ms() - start_time); | 302 | tcc_print_stats(s, getclock_ms() - start_time); |
| 402 | tcc_delete(s); | 303 | tcc_delete(s); |
| 304 | if (ret == 0 && n) | ||
| 305 | goto redo; /* compile more files with -c */ | ||
| 403 | return ret; | 306 | return ret; |
| 404 | } | 307 | } |
| @@ -767,17 +767,19 @@ struct TCCState { · 766 unmodified lines | |||
| 767 | int nb_libraries; /* number of libs thereof */ | 767 | int nb_libraries; /* number of libs thereof */ |
| 768 | int filetype; | 768 | int filetype; |
| 769 | char *outfile; /* output filename */ | 769 | char *outfile; /* output filename */ |
| 770 | int cross_target; /* -m32/-m64 */ | ||
| 771 | int print_search_dirs; /* option */ | ||
| 772 | int option_r; /* option -r */ | 770 | int option_r; /* option -r */ |
| 773 | int do_bench; /* option -bench */ | 771 | int do_bench; /* option -bench */ |
| 774 | int gen_deps; /* option -MD */ | 772 | int gen_deps; /* option -MD */ |
| 775 | char *deps_outfile; /* option -MF */ | 773 | char *deps_outfile; /* option -MF */ |
| 776 | int option_pthread; /* -pthread option */ | 774 | int option_pthread; /* -pthread option */ |
| 775 | int argc; | ||
| 776 | char **argv; | ||
| 777 | }; | 777 | }; |
| 778 | 778 | ||
| 779 | struct filespec { | 779 | struct filespec { |
| 780 | char type, name[1]; | 780 | char type; |
| 781 | char alacarte; | ||
| 782 | char name[1]; | ||
| 781 | }; | 783 | }; |
| 782 | 784 | ||
| 783 | /* The current value can be: */ | 785 | /* The current value can be: */ |
| @@ -1091,7 +1093,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line); · 307 unmodified lines | |||
| 1091 | #define realloc(p, s) use_tcc_realloc(p, s) | 1093 | #define realloc(p, s) use_tcc_realloc(p, s) |
| 1092 | #undef strdup | 1094 | #undef strdup |
| 1093 | #define strdup(s) use_tcc_strdup(s) | 1095 | #define strdup(s) use_tcc_strdup(s) |
| 1094 | PUB_FUNC void tcc_memstats(int bench); | 1096 | PUB_FUNC void tcc_memcheck(void); |
| 1095 | PUB_FUNC void tcc_error_noabort(const char *fmt, ...); | 1097 | PUB_FUNC void tcc_error_noabort(const char *fmt, ...); |
| 1096 | PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); | 1098 | PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); |
| 1097 | PUB_FUNC void tcc_warning(const char *fmt, ...); | 1099 | 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) · 33 unmodified lines | |||
| 1131 | #define AFF_TYPE_ASMPP 3 | 1133 | #define AFF_TYPE_ASMPP 3 |
| 1132 | #define AFF_TYPE_BIN 4 | 1134 | #define AFF_TYPE_BIN 4 |
| 1133 | #define AFF_TYPE_LIB 5 | 1135 | #define AFF_TYPE_LIB 5 |
| 1134 | #define AFF_TYPE_LIBWH 6 | ||
| 1135 | /* values from tcc_object_type(...) */ | 1136 | /* values from tcc_object_type(...) */ |
| 1136 | #define AFF_BINTYPE_REL 1 | 1137 | #define AFF_BINTYPE_REL 1 |
| 1137 | #define AFF_BINTYPE_DYN 2 | 1138 | #define AFF_BINTYPE_DYN 2 |
| 1138 | #define AFF_BINTYPE_AR 3 | 1139 | #define AFF_BINTYPE_AR 3 |
| 1139 | #define AFF_BINTYPE_C67 4 | 1140 | #define AFF_BINTYPE_C67 4 |
| 1140 | 1141 | ||
| 1141 | |||
| 1142 | ST_FUNC int tcc_add_crt(TCCState *s, const char *filename); | 1142 | ST_FUNC int tcc_add_crt(TCCState *s, const char *filename); |
| 1143 | 1143 | ||
| 1144 | #ifndef TCC_TARGET_PE | 1144 | #ifndef TCC_TARGET_PE |
| @@ -1149,12 +1149,21 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1); · 4 unmodified lines | |||
| 1149 | PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); | 1149 | PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); |
| 1150 | 1150 | ||
| 1151 | PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); | 1151 | PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); |
| 1152 | PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv); | 1152 | PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); |
| 1153 | PUB_FUNC void tcc_set_environment(TCCState *s); | 1153 | PUB_FUNC void tcc_set_environment(TCCState *s); |
| 1154 | #ifdef _WIN32 | 1154 | #ifdef _WIN32 |
| 1155 | ST_FUNC char *normalize_slashes(char *path); | 1155 | ST_FUNC char *normalize_slashes(char *path); |
| 1156 | #endif | 1156 | #endif |
| 1157 | 1157 | ||
| 1158 | /* tcc_parse_args return codes: */ | ||
| 1159 | #define OPT_HELP 1 | ||
| 1160 | #define OPT_V 3 | ||
| 1161 | #define OPT_PRINT_DIRS 4 | ||
| 1162 | #define OPT_AR 5 | ||
| 1163 | #define OPT_IMPDEF 6 | ||
| 1164 | #define OPT_M32 32 | ||
| 1165 | #define OPT_M64 64 | ||
| 1166 | |||
| 1158 | /* ------------ tccpp.c ------------ */ | 1167 | /* ------------ tccpp.c ------------ */ |
| 1159 | 1168 | ||
| 1160 | ST_DATA struct BufferedFile *file; | 1169 | ST_DATA struct BufferedFile *file; |
| @@ -1567,6 +1576,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); · 406 unmodified lines | |||
| 1567 | #ifdef TCC_TARGET_X86_64 | 1576 | #ifdef TCC_TARGET_X86_64 |
| 1568 | ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack); | 1577 | ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack); |
| 1569 | #endif | 1578 | #endif |
| 1579 | PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp); | ||
| 1570 | /* symbol properties stored in Elf32_Sym->st_other */ | 1580 | /* symbol properties stored in Elf32_Sym->st_other */ |
| 1571 | # define ST_PE_EXPORT 0x10 | 1581 | # define ST_PE_EXPORT 0x10 |
| 1572 | # define ST_PE_IMPORT 0x20 | 1582 | # define ST_PE_IMPORT 0x20 |
| @@ -1595,6 +1605,16 @@ ST_FUNC void tcc_set_num_callers(int n); · 22 unmodified lines | |||
| 1595 | ST_FUNC void tcc_run_free(TCCState *s1); | 1605 | ST_FUNC void tcc_run_free(TCCState *s1); |
| 1596 | #endif | 1606 | #endif |
| 1597 | 1607 | ||
| 1608 | /* ------------ tcctools.c ----------------- */ | ||
| 1609 | #if 0 /* included in tcc.c */ | ||
| 1610 | ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv); | ||
| 1611 | #ifdef TCC_TARGET_PE | ||
| 1612 | ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv); | ||
| 1613 | #endif | ||
| 1614 | ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option); | ||
| 1615 | ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename); | ||
| 1616 | #endif | ||
| 1617 | |||
| 1598 | /********************************************************/ | 1618 | /********************************************************/ |
| 1599 | #undef ST_DATA | 1619 | #undef ST_DATA |
| 1600 | #ifdef ONE_SOURCE | 1620 | #ifdef ONE_SOURCE |
| @@ -1005,6 +1005,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) · 1004 unmodified lines | |||
| 1005 | /* default section is text */ | 1005 | /* default section is text */ |
| 1006 | cur_text_section = text_section; | 1006 | cur_text_section = text_section; |
| 1007 | ind = cur_text_section->data_offset; | 1007 | ind = cur_text_section->data_offset; |
| 1008 | nocode_wanted = 0; | ||
| 1008 | 1009 | ||
| 1009 | /* an elf symbol of type STT_FILE must be put so that STB_LOCAL | 1010 | /* an elf symbol of type STT_FILE must be put so that STB_LOCAL |
| 1010 | symbols can be safely used */ | 1011 | symbols can be safely used */ |
| @@ -962,7 +962,7 @@ static void pe_build_exports(struct pe_info *pe) · 961 unmodified lines | |||
| 962 | } else { | 962 | } else { |
| 963 | fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); | 963 | fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); |
| 964 | if (pe->s1->verbose) | 964 | if (pe->s1->verbose) |
| 965 | printf("<- %s (%d symbols)\n", buf, sym_count); | 965 | printf("<- %s (%d symbol%s)\n", buf, sym_count, "s" + (sym_count < 2)); |
| 966 | } | 966 | } |
| 967 | #endif | 967 | #endif |
| 968 | 968 | ||
| @@ -1543,6 +1543,102 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) · 574 unmodified lines | |||
| 1543 | return len == read(fd, buffer, len); | 1543 | return len == read(fd, buffer, len); |
| 1544 | } | 1544 | } |
| 1545 | 1545 | ||
| 1546 | /* ------------------------------------------------------------- */ | ||
| 1547 | |||
| 1548 | PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) | ||
| 1549 | { | ||
| 1550 | int l, i, n, n0, ret; | ||
| 1551 | char *p; | ||
| 1552 | int fd; | ||
| 1553 | |||
| 1554 | IMAGE_SECTION_HEADER ish; | ||
| 1555 | IMAGE_EXPORT_DIRECTORY ied; | ||
| 1556 | IMAGE_DOS_HEADER dh; | ||
| 1557 | IMAGE_FILE_HEADER ih; | ||
| 1558 | DWORD sig, ref, addr, ptr, namep; | ||
| 1559 | #ifdef TCC_TARGET_X86_64 | ||
| 1560 | IMAGE_OPTIONAL_HEADER64 oh; | ||
| 1561 | #else | ||
| 1562 | IMAGE_OPTIONAL_HEADER32 oh; | ||
| 1563 | #endif | ||
| 1564 | int pef_hdroffset, opt_hdroffset, sec_hdroffset; | ||
| 1565 | |||
| 1566 | n = n0 = 0; | ||
| 1567 | p = NULL; | ||
| 1568 | ret = -1; | ||
| 1569 | |||
| 1570 | fd = open(filename, O_RDONLY | O_BINARY); | ||
| 1571 | if (fd < 0) | ||
| 1572 | goto the_end_1; | ||
| 1573 | ret = 1; | ||
| 1574 | |||
| 1575 | if (!read_mem(fd, 0, &dh, sizeof dh)) | ||
| 1576 | goto the_end; | ||
| 1577 | if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) | ||
| 1578 | goto the_end; | ||
| 1579 | if (sig != 0x00004550) | ||
| 1580 | goto the_end; | ||
| 1581 | pef_hdroffset = dh.e_lfanew + sizeof sig; | ||
| 1582 | if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) | ||
| 1583 | goto the_end; | ||
| 1584 | if (IMAGE_FILE_MACHINE != ih.Machine) { | ||
| 1585 | if (ih.Machine == 0x014C) | ||
| 1586 | ret = 32; | ||
| 1587 | else if (ih.Machine == 0x8664) | ||
| 1588 | ret = 64; | ||
| 1589 | goto the_end; | ||
| 1590 | } | ||
| 1591 | opt_hdroffset = pef_hdroffset + sizeof ih; | ||
| 1592 | sec_hdroffset = opt_hdroffset + sizeof oh; | ||
| 1593 | if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) | ||
| 1594 | goto the_end; | ||
| 1595 | |||
| 1596 | if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | ||
| 1597 | goto the_end_0; | ||
| 1598 | |||
| 1599 | addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | ||
| 1600 | //printf("addr: %08x\n", addr); | ||
| 1601 | for (i = 0; i < ih.NumberOfSections; ++i) { | ||
| 1602 | if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) | ||
| 1603 | goto the_end; | ||
| 1604 | //printf("vaddr: %08x\n", ish.VirtualAddress); | ||
| 1605 | if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) | ||
| 1606 | goto found; | ||
| 1607 | } | ||
| 1608 | goto the_end_0; | ||
| 1609 | |||
| 1610 | found: | ||
| 1611 | ref = ish.VirtualAddress - ish.PointerToRawData; | ||
| 1612 | if (!read_mem(fd, addr - ref, &ied, sizeof ied)) | ||
| 1613 | goto the_end; | ||
| 1614 | |||
| 1615 | namep = ied.AddressOfNames - ref; | ||
| 1616 | for (i = 0; i < ied.NumberOfNames; ++i) { | ||
| 1617 | if (!read_mem(fd, namep, &ptr, sizeof ptr)) | ||
| 1618 | goto the_end; | ||
| 1619 | namep += sizeof ptr; | ||
| 1620 | for (l = 0;;) { | ||
| 1621 | if (n+1 >= n0) | ||
| 1622 | p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); | ||
| 1623 | if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { | ||
| 1624 | tcc_free(p), p = NULL; | ||
| 1625 | goto the_end; | ||
| 1626 | } | ||
| 1627 | if (p[n++] == 0) | ||
| 1628 | break; | ||
| 1629 | } | ||
| 1630 | } | ||
| 1631 | if (p) | ||
| 1632 | p[n] = 0; | ||
| 1633 | the_end_0: | ||
| 1634 | ret = 0; | ||
| 1635 | the_end: | ||
| 1636 | close(fd); | ||
| 1637 | the_end_1: | ||
| 1638 | *pp = p; | ||
| 1639 | return ret; | ||
| 1640 | } | ||
| 1641 | |||
| 1546 | /* ------------------------------------------------------------- | 1642 | /* ------------------------------------------------------------- |
| 1547 | * This is for compiled windows resources in 'coff' format | 1643 | * This is for compiled windows resources in 'coff' format |
| 1548 | * as generated by 'windres.exe -O coff ...'. | 1644 | * as generated by 'windres.exe -O coff ...'. |
| @@ -1660,20 +1756,20 @@ quit: · 111 unmodified lines | |||
| 1660 | } | 1756 | } |
| 1661 | 1757 | ||
| 1662 | /* ------------------------------------------------------------- */ | 1758 | /* ------------------------------------------------------------- */ |
| 1663 | #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY | 1759 | static int pe_load_dll(TCCState *s1, const char *filename) |
| 1664 | #include "win32/tools/tiny_impdef.c" | ||
| 1665 | |||
| 1666 | static int pe_load_dll(TCCState *s1, const char *dllname, int fd) | ||
| 1667 | { | 1760 | { |
| 1668 | char *p, *q; | 1761 | char *p, *q; |
| 1669 | int index; | 1762 | int index, ret; |
| 1670 | p = get_export_names(fd); | 1763 | |
| 1671 | if (!p) | 1764 | ret = tcc_get_dllexports(filename, &p); |
| 1765 | if (ret) { | ||
| 1672 | return -1; | 1766 | return -1; |
| 1673 | index = add_dllref(s1, dllname); | 1767 | } else if (p) { |
| 1674 | for (q = p; *q; q += 1 + strlen(q)) | 1768 | index = add_dllref(s1, tcc_basename(filename)); |
| 1675 | pe_putimport(s1, index, q, 0); | 1769 | for (q = p; *q; q += 1 + strlen(q)) |
| 1676 | tcc_free(p); | 1770 | pe_putimport(s1, index, q, 0); |
| 1771 | tcc_free(p); | ||
| 1772 | } | ||
| 1677 | return 0; | 1773 | return 0; |
| 1678 | } | 1774 | } |
| 1679 | 1775 | ||
| @@ -1687,7 +1783,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) · 7 unmodified lines | |||
| 1687 | else if (pe_load_res(s1, fd) == 0) | 1783 | else if (pe_load_res(s1, fd) == 0) |
| 1688 | ret = 0; | 1784 | ret = 0; |
| 1689 | else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4)) | 1785 | else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4)) |
| 1690 | ret = pe_load_dll(s1, tcc_basename(filename), fd); | 1786 | ret = pe_load_dll(s1, filename); |
| 1691 | return ret; | 1787 | return ret; |
| 1692 | } | 1788 | } |
| 1693 | 1789 | ||
| @@ -0,0 +1,547 @@ | |||
| 1 | /* -------------------------------------------------------------- */ | ||
| 2 | /* | ||
| 3 | * TCC - Tiny C Compiler | ||
| 4 | * | ||
| 5 | * tcctools.c - extra tools and and -m32/64 support | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* -------------------------------------------------------------- */ | ||
| 10 | /* | ||
| 11 | * This program is for making libtcc1.a without ar | ||
| 12 | * tiny_libmaker - tiny elf lib maker | ||
| 13 | * usage: tiny_libmaker [lib] files... | ||
| 14 | * Copyright (c) 2007 Timppa | ||
| 15 | * | ||
| 16 | * This library is free software; you can redistribute it and/or | ||
| 17 | * modify it under the terms of the GNU Lesser General Public | ||
| 18 | * License as published by the Free Software Foundation; either | ||
| 19 | * version 2 of the License, or (at your option) any later version. | ||
| 20 | * | ||
| 21 | * This library is distributed in the hope that it will be useful, | ||
| 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 24 | * Lesser General Public License for more details. | ||
| 25 | * | ||
| 26 | * You should have received a copy of the GNU Lesser General Public | ||
| 27 | * License along with this library; if not, write to the Free Software | ||
| 28 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "tcc.h" | ||
| 32 | |||
| 33 | //#define ARMAG "!<arch>\n" | ||
| 34 | #define ARFMAG "`\n" | ||
| 35 | |||
| 36 | typedef struct { | ||
| 37 | char ar_name[16]; | ||
| 38 | char ar_date[12]; | ||
| 39 | char ar_uid[6]; | ||
| 40 | char ar_gid[6]; | ||
| 41 | char ar_mode[8]; | ||
| 42 | char ar_size[10]; | ||
| 43 | char ar_fmag[2]; | ||
| 44 | } ArHdr; | ||
| 45 | |||
| 46 | static unsigned long le2belong(unsigned long ul) { | ||
| 47 | return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) + | ||
| 48 | ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8); | ||
| 49 | } | ||
| 50 | |||
| 51 | /* Returns 1 if s contains any of the chars of list, else 0 */ | ||
| 52 | static int contains_any(const char *s, const char *list) { | ||
| 53 | const char *l; | ||
| 54 | for (; *s; s++) { | ||
| 55 | for (l = list; *l; l++) { | ||
| 56 | if (*s == *l) | ||
| 57 | return 1; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static int ar_usage(int ret) { | ||
| 64 | fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n"); | ||
| 65 | fprintf(stderr, "create library ([abdioptxN] not supported).\n"); | ||
| 66 | return ret; | ||
| 67 | } | ||
| 68 | |||
| 69 | ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) | ||
| 70 | { | ||
| 71 | static ArHdr arhdr = { | ||
| 72 | "/ ", | ||
| 73 | " ", | ||
| 74 | "0 ", | ||
| 75 | "0 ", | ||
| 76 | "0 ", | ||
| 77 | " ", | ||
| 78 | ARFMAG | ||
| 79 | }; | ||
| 80 | |||
| 81 | static ArHdr arhdro = { | ||
| 82 | " ", | ||
| 83 | " ", | ||
| 84 | "0 ", | ||
| 85 | "0 ", | ||
| 86 | "0 ", | ||
| 87 | " ", | ||
| 88 | ARFMAG | ||
| 89 | }; | ||
| 90 | |||
| 91 | FILE *fi, *fh = NULL, *fo = NULL; | ||
| 92 | ElfW(Ehdr) *ehdr; | ||
| 93 | ElfW(Shdr) *shdr; | ||
| 94 | ElfW(Sym) *sym; | ||
| 95 | int i, fsize, i_lib, i_obj; | ||
| 96 | char *buf, *shstr, *symtab = NULL, *strtab = NULL; | ||
| 97 | int symtabsize = 0;//, strtabsize = 0; | ||
| 98 | char *anames = NULL; | ||
| 99 | int *afpos = NULL; | ||
| 100 | int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs; | ||
| 101 | char tfile[260], stmp[20]; | ||
| 102 | char *file, *name; | ||
| 103 | int ret = 2; | ||
| 104 | char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. | ||
| 105 | int verbose = 0; | ||
| 106 | |||
| 107 | i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj | ||
| 108 | for (i = 1; i < argc; i++) { | ||
| 109 | const char *a = argv[i]; | ||
| 110 | if (*a == '-' && strstr(a, ".")) | ||
| 111 | ret = 1; // -x.y is always invalid (same as gnu ar) | ||
| 112 | if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument | ||
| 113 | if (contains_any(a, ops_conflict)) | ||
| 114 | ret = 1; | ||
| 115 | if (strstr(a, "v")) | ||
| 116 | verbose = 1; | ||
| 117 | } else { // lib or obj files: don't abort - keep validating all args. | ||
| 118 | if (!i_lib) // first file is the lib | ||
| 119 | i_lib = i; | ||
| 120 | else if (!i_obj) // second file is the first obj | ||
| 121 | i_obj = i; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | if (!i_obj) // i_obj implies also i_lib. we require both. | ||
| 126 | ret = 1; | ||
| 127 | |||
| 128 | if (ret == 1) | ||
| 129 | return ar_usage(ret); | ||
| 130 | |||
| 131 | if ((fh = fopen(argv[i_lib], "wb")) == NULL) | ||
| 132 | { | ||
| 133 | fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]); | ||
| 134 | goto the_end; | ||
| 135 | } | ||
| 136 | |||
| 137 | sprintf(tfile, "%s.tmp", argv[i_lib]); | ||
| 138 | if ((fo = fopen(tfile, "wb+")) == NULL) | ||
| 139 | { | ||
| 140 | fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile); | ||
| 141 | goto the_end; | ||
| 142 | } | ||
| 143 | |||
| 144 | funcmax = 250; | ||
| 145 | afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func | ||
| 146 | memcpy(&arhdro.ar_mode, "100666", 6); | ||
| 147 | |||
| 148 | // i_obj = first input object file | ||
| 149 | while (i_obj < argc) | ||
| 150 | { | ||
| 151 | if (*argv[i_obj] == '-') { // by now, all options start with '-' | ||
| 152 | i_obj++; | ||
| 153 | continue; | ||
| 154 | } | ||
| 155 | if ((fi = fopen(argv[i_obj], "rb")) == NULL) { | ||
| 156 | fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]); | ||
| 157 | goto the_end; | ||
| 158 | } | ||
| 159 | if (verbose) | ||
| 160 | printf("a - %s\n", argv[i_obj]); | ||
| 161 | |||
| 162 | fseek(fi, 0, SEEK_END); | ||
| 163 | fsize = ftell(fi); | ||
| 164 | fseek(fi, 0, SEEK_SET); | ||
| 165 | buf = tcc_malloc(fsize + 1); | ||
| 166 | fread(buf, fsize, 1, fi); | ||
| 167 | fclose(fi); | ||
| 168 | |||
| 169 | // elf header | ||
| 170 | ehdr = (ElfW(Ehdr) *)buf; | ||
| 171 | if (ehdr->e_ident[4] != ELFCLASSW) | ||
| 172 | { | ||
| 173 | fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]); | ||
| 174 | goto the_end; | ||
| 175 | } | ||
| 176 | |||
| 177 | shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize); | ||
| 178 | shstr = (char *)(buf + shdr->sh_offset); | ||
| 179 | for (i = 0; i < ehdr->e_shnum; i++) | ||
| 180 | { | ||
| 181 | shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize); | ||
| 182 | if (!shdr->sh_offset) | ||
| 183 | continue; | ||
| 184 | if (shdr->sh_type == SHT_SYMTAB) | ||
| 185 | { | ||
| 186 | symtab = (char *)(buf + shdr->sh_offset); | ||
| 187 | symtabsize = shdr->sh_size; | ||
| 188 | } | ||
| 189 | if (shdr->sh_type == SHT_STRTAB) | ||
| 190 | { | ||
| 191 | if (!strcmp(shstr + shdr->sh_name, ".strtab")) | ||
| 192 | { | ||
| 193 | strtab = (char *)(buf + shdr->sh_offset); | ||
| 194 | //strtabsize = shdr->sh_size; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | if (symtab && symtabsize) | ||
| 200 | { | ||
| 201 | int nsym = symtabsize / sizeof(ElfW(Sym)); | ||
| 202 | //printf("symtab: info size shndx name\n"); | ||
| 203 | for (i = 1; i < nsym; i++) | ||
| 204 | { | ||
| 205 | sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym))); | ||
| 206 | if (sym->st_shndx && | ||
| 207 | (sym->st_info == 0x10 | ||
| 208 | || sym->st_info == 0x11 | ||
| 209 | || sym->st_info == 0x12 | ||
| 210 | )) { | ||
| 211 | //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name); | ||
| 212 | istrlen = strlen(strtab + sym->st_name)+1; | ||
| 213 | anames = tcc_realloc(anames, strpos+istrlen); | ||
| 214 | strcpy(anames + strpos, strtab + sym->st_name); | ||
| 215 | strpos += istrlen; | ||
| 216 | if (++funccnt >= funcmax) { | ||
| 217 | funcmax += 250; | ||
| 218 | afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more | ||
| 219 | } | ||
| 220 | afpos[funccnt] = fpos; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | file = argv[i_obj]; | ||
| 226 | for (name = strchr(file, 0); | ||
| 227 | name > file && name[-1] != '/' && name[-1] != '\\'; | ||
| 228 | --name); | ||
| 229 | istrlen = strlen(name); | ||
| 230 | if (istrlen >= sizeof(arhdro.ar_name)) | ||
| 231 | istrlen = sizeof(arhdro.ar_name) - 1; | ||
| 232 | memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name)); | ||
| 233 | memcpy(arhdro.ar_name, name, istrlen); | ||
| 234 | arhdro.ar_name[istrlen] = '/'; | ||
| 235 | sprintf(stmp, "%-10d", fsize); | ||
| 236 | memcpy(&arhdro.ar_size, stmp, 10); | ||
| 237 | fwrite(&arhdro, sizeof(arhdro), 1, fo); | ||
| 238 | fwrite(buf, fsize, 1, fo); | ||
| 239 | tcc_free(buf); | ||
| 240 | i_obj++; | ||
| 241 | fpos += (fsize + sizeof(arhdro)); | ||
| 242 | } | ||
| 243 | hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int); | ||
| 244 | fpos = 0; | ||
| 245 | if ((hofs & 1)) // align | ||
| 246 | hofs++, fpos = 1; | ||
| 247 | // write header | ||
| 248 | fwrite("!<arch>\n", 8, 1, fh); | ||
| 249 | sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int))); | ||
| 250 | memcpy(&arhdr.ar_size, stmp, 10); | ||
| 251 | fwrite(&arhdr, sizeof(arhdr), 1, fh); | ||
| 252 | afpos[0] = le2belong(funccnt); | ||
| 253 | for (i=1; i<=funccnt; i++) | ||
| 254 | afpos[i] = le2belong(afpos[i] + hofs); | ||
| 255 | fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh); | ||
| 256 | fwrite(anames, strpos, 1, fh); | ||
| 257 | if (fpos) | ||
| 258 | fwrite("", 1, 1, fh); | ||
| 259 | // write objects | ||
| 260 | fseek(fo, 0, SEEK_END); | ||
| 261 | fsize = ftell(fo); | ||
| 262 | fseek(fo, 0, SEEK_SET); | ||
| 263 | buf = tcc_malloc(fsize + 1); | ||
| 264 | fread(buf, fsize, 1, fo); | ||
| 265 | fwrite(buf, fsize, 1, fh); | ||
| 266 | tcc_free(buf); | ||
| 267 | ret = 0; | ||
| 268 | the_end: | ||
| 269 | if (anames) | ||
| 270 | tcc_free(anames); | ||
| 271 | if (afpos) | ||
| 272 | tcc_free(afpos); | ||
| 273 | if (fh) | ||
| 274 | fclose(fh); | ||
| 275 | if (fo) | ||
| 276 | fclose(fo), remove(tfile); | ||
| 277 | return ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* -------------------------------------------------------------- */ | ||
| 281 | /* | ||
| 282 | * tiny_impdef creates an export definition file (.def) from a dll | ||
| 283 | * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]" | ||
| 284 | * | ||
| 285 | * Copyright (c) 2005,2007 grischka | ||
| 286 | * | ||
| 287 | * This program is free software; you can redistribute it and/or modify | ||
| 288 | * it under the terms of the GNU General Public License as published by | ||
| 289 | * the Free Software Foundation; either version 2 of the License, or | ||
| 290 | * (at your option) any later version. | ||
| 291 | * | ||
| 292 | * This program is distributed in the hope that it will be useful, | ||
| 293 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 294 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 295 | * GNU General Public License for more details. | ||
| 296 | * | ||
| 297 | * You should have received a copy of the GNU General Public License | ||
| 298 | * along with this program; if not, write to the Free Software | ||
| 299 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 300 | */ | ||
| 301 | |||
| 302 | #ifdef TCC_TARGET_PE | ||
| 303 | |||
| 304 | ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv) | ||
| 305 | { | ||
| 306 | int ret, v, i; | ||
| 307 | char infile[MAX_PATH]; | ||
| 308 | char outfile[MAX_PATH]; | ||
| 309 | |||
| 310 | const char *file; | ||
| 311 | char *p, *q; | ||
| 312 | FILE *fp, *op; | ||
| 313 | |||
| 314 | #ifdef _WIN32 | ||
| 315 | char path[MAX_PATH]; | ||
| 316 | #endif | ||
| 317 | |||
| 318 | infile[0] = outfile[0] = 0; | ||
| 319 | fp = op = NULL; | ||
| 320 | ret = 1; | ||
| 321 | p = NULL; | ||
| 322 | v = 0; | ||
| 323 | |||
| 324 | for (i = 1; i < argc; ++i) { | ||
| 325 | const char *a = argv[i]; | ||
| 326 | if ('-' == a[0]) { | ||
| 327 | if (0 == strcmp(a, "-v")) { | ||
| 328 | v = 1; | ||
| 329 | } else if (0 == strcmp(a, "-o")) { | ||
| 330 | if (++i == argc) | ||
| 331 | goto usage; | ||
| 332 | strcpy(outfile, argv[i]); | ||
| 333 | } else | ||
| 334 | goto usage; | ||
| 335 | } else if (0 == infile[0]) | ||
| 336 | strcpy(infile, a); | ||
| 337 | else | ||
| 338 | goto usage; | ||
| 339 | } | ||
| 340 | |||
| 341 | if (0 == infile[0]) { | ||
| 342 | usage: | ||
| 343 | fprintf(stderr, | ||
| 344 | "usage: tcc -impdef library.dll [-v] [-o outputfile]\n" | ||
| 345 | "create export definition file (.def) from dll\n" | ||
| 346 | ); | ||
| 347 | goto the_end; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (0 == outfile[0]) { | ||
| 351 | strcpy(outfile, tcc_basename(infile)); | ||
| 352 | q = strrchr(outfile, '.'); | ||
| 353 | if (NULL == q) | ||
| 354 | q = strchr(outfile, 0); | ||
| 355 | strcpy(q, ".def"); | ||
| 356 | } | ||
| 357 | |||
| 358 | file = infile; | ||
| 359 | #ifdef _WIN32 | ||
| 360 | if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL)) | ||
| 361 | file = path; | ||
| 362 | #endif | ||
| 363 | ret = tcc_get_dllexports(file, &p); | ||
| 364 | if (ret || !p) { | ||
| 365 | fprintf(stderr, "tcc: impdef: %s '%s'\n", | ||
| 366 | ret == 32 ? "can't read symbols from 32bit" : | ||
| 367 | ret == 64 ? "can't read symbols from 64bit" : | ||
| 368 | ret == -1 ? "can't find file" : | ||
| 369 | ret == 0 ? "no symbols found in" : | ||
| 370 | "unknown file type", file); | ||
| 371 | ret = 1; | ||
| 372 | goto the_end; | ||
| 373 | } | ||
| 374 | |||
| 375 | if (v) | ||
| 376 | printf("-> %s\n", file); | ||
| 377 | |||
| 378 | op = fopen(outfile, "w"); | ||
| 379 | if (NULL == op) { | ||
| 380 | fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile); | ||
| 381 | goto the_end; | ||
| 382 | } | ||
| 383 | |||
| 384 | fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file)); | ||
| 385 | for (q = p, i = 0; *q; ++i) { | ||
| 386 | fprintf(op, "%s\n", q); | ||
| 387 | q += strlen(q) + 1; | ||
| 388 | } | ||
| 389 | |||
| 390 | if (v) | ||
| 391 | printf("<- %s (%d symbol%s)\n", outfile, i, "s" + (i<2)); | ||
| 392 | |||
| 393 | ret = 0; | ||
| 394 | |||
| 395 | the_end: | ||
| 396 | /* cannot free memory received from tcc_get_dllexports | ||
| 397 | if it came from a dll */ | ||
| 398 | /* if (p) | ||
| 399 | tcc_free(p); */ | ||
| 400 | if (fp) | ||
| 401 | fclose(fp); | ||
| 402 | if (op) | ||
| 403 | fclose(op); | ||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | |||
| 407 | #endif /* TCC_TARGET_PE */ | ||
| 408 | |||
| 409 | /* -------------------------------------------------------------- */ | ||
| 410 | /* | ||
| 411 | * TCC - Tiny C Compiler | ||
| 412 | * | ||
| 413 | * Copyright (c) 2001-2004 Fabrice Bellard | ||
| 414 | * | ||
| 415 | * This library is free software; you can redistribute it and/or | ||
| 416 | * modify it under the terms of the GNU Lesser General Public | ||
| 417 | * License as published by the Free Software Foundation; either | ||
| 418 | * version 2 of the License, or (at your option) any later version. | ||
| 419 | * | ||
| 420 | * This library is distributed in the hope that it will be useful, | ||
| 421 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 422 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 423 | * Lesser General Public License for more details. | ||
| 424 | * | ||
| 425 | * You should have received a copy of the GNU Lesser General Public | ||
| 426 | * License along with this library; if not, write to the Free Software | ||
| 427 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 428 | */ | ||
| 429 | |||
| 430 | /* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */ | ||
| 431 | |||
| 432 | #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 | ||
| 433 | |||
| 434 | ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option) | ||
| 435 | { | ||
| 436 | tcc_error("-m%d not implemented.", option); | ||
| 437 | } | ||
| 438 | |||
| 439 | #else | ||
| 440 | #ifdef _WIN32 | ||
| 441 | #include <process.h> | ||
| 442 | |||
| 443 | static char *str_replace(const char *str, const char *p, const char *r) | ||
| 444 | { | ||
| 445 | const char *s, *s0; | ||
| 446 | char *d, *d0; | ||
| 447 | int sl, pl, rl; | ||
| 448 | |||
| 449 | sl = strlen(str); | ||
| 450 | pl = strlen(p); | ||
| 451 | rl = strlen(r); | ||
| 452 | for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) { | ||
| 453 | for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) { | ||
| 454 | if (d) { | ||
| 455 | memcpy(d, s0, sl = s - s0), d += sl; | ||
| 456 | memcpy(d, r, rl), d += rl; | ||
| 457 | } else | ||
| 458 | sl += rl - pl; | ||
| 459 | } | ||
| 460 | if (d) { | ||
| 461 | strcpy(d, s0); | ||
| 462 | return d0; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 | static int execvp_win32(const char *prog, char **argv) | ||
| 468 | { | ||
| 469 | int ret; char **p; | ||
| 470 | /* replace all " by \" */ | ||
| 471 | for (p = argv; *p; ++p) | ||
| 472 | if (strchr(*p, '"')) | ||
| 473 | *p = str_replace(*p, "\"", "\\\""); | ||
| 474 | ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv); | ||
| 475 | if (-1 == ret) | ||
| 476 | return ret; | ||
| 477 | _cwait(&ret, ret, WAIT_CHILD); | ||
| 478 | exit(ret); | ||
| 479 | } | ||
| 480 | #define execvp execvp_win32 | ||
| 481 | #endif /* _WIN32 */ | ||
| 482 | |||
| 483 | ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target) | ||
| 484 | { | ||
| 485 | char program[4096]; | ||
| 486 | char *a0 = argv[0]; | ||
| 487 | int prefix = tcc_basename(a0) - a0; | ||
| 488 | |||
| 489 | snprintf(program, sizeof program, | ||
| 490 | "%.*s%s" | ||
| 491 | #ifdef TCC_TARGET_PE | ||
| 492 | "-win32" | ||
| 493 | #endif | ||
| 494 | "-tcc" | ||
| 495 | #ifdef _WIN32 | ||
| 496 | ".exe" | ||
| 497 | #endif | ||
| 498 | , prefix, a0, target == 64 ? "x86_64" : "i386"); | ||
| 499 | |||
| 500 | if (strcmp(a0, program)) | ||
| 501 | execvp(argv[0] = program, argv); | ||
| 502 | tcc_error("could not run '%s'", program); | ||
| 503 | } | ||
| 504 | |||
| 505 | #endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */ | ||
| 506 | /* -------------------------------------------------------------- */ | ||
| 507 | /* enable commandline wildcard expansion (tcc -o x.exe *.c) */ | ||
| 508 | |||
| 509 | #ifdef _WIN32 | ||
| 510 | int _CRT_glob = 1; | ||
| 511 | #ifndef _CRT_glob | ||
| 512 | int _dowildcard = 1; | ||
| 513 | #endif | ||
| 514 | #endif | ||
| 515 | |||
| 516 | /* -------------------------------------------------------------- */ | ||
| 517 | /* generate xxx.d file */ | ||
| 518 | |||
| 519 | ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) | ||
| 520 | { | ||
| 521 | FILE *depout; | ||
| 522 | char buf[1024]; | ||
| 523 | int i; | ||
| 524 | |||
| 525 | if (!filename) { | ||
| 526 | /* compute filename automatically: dir/file.o -> dir/file.d */ | ||
| 527 | snprintf(buf, sizeof buf, "%.*s.d", | ||
| 528 | (int)(tcc_fileextension(target) - target), target); | ||
| 529 | filename = buf; | ||
| 530 | } | ||
| 531 | |||
| 532 | if (s->verbose) | ||
| 533 | printf("<- %s\n", filename); | ||
| 534 | |||
| 535 | /* XXX return err codes instead of error() ? */ | ||
| 536 | depout = fopen(filename, "w"); | ||
| 537 | if (!depout) | ||
| 538 | tcc_error("could not open '%s'", filename); | ||
| 539 | |||
| 540 | fprintf(depout, "%s: \\\n", target); | ||
| 541 | for (i=0; i<s->nb_target_deps; ++i) | ||
| 542 | fprintf(depout, " %s \\\n", s->target_deps[i]); | ||
| 543 | fprintf(depout, "\n"); | ||
| 544 | fclose(depout); | ||
| 545 | } | ||
| 546 | |||
| 547 | /* -------------------------------------------------------------- */ | ||
| @@ -3431,7 +3431,7 @@ void builtin_test(void) · 3430 unmodified lines | |||
| 3431 | i = sizeof (__builtin_choose_expr (0, ll, s)); | 3431 | i = sizeof (__builtin_choose_expr (0, ll, s)); |
| 3432 | printf("bce: %d\n", i); | 3432 | printf("bce: %d\n", i); |
| 3433 | 3433 | ||
| 3434 | printf("bera: %p\n", __builtin_extract_return_addr((void*)43)); | 3434 | //printf("bera: %p\n", __builtin_extract_return_addr((void*)43)); |
| 3435 | } | 3435 | } |
| 3436 | 3436 | ||
| 3437 | #ifndef _WIN32 | 3437 | #ifndef _WIN32 |
| @@ -5,10 +5,6 @@ · 4 unmodified lines | |||
| 5 | @echo off | 5 | @echo off |
| 6 | setlocal | 6 | setlocal |
| 7 | 7 | ||
| 8 | set VSCOMNTOOLS=%VS150COMNTOOLS% | ||
| 9 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS% | ||
| 10 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS% | ||
| 11 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS% | ||
| 12 | set CC=gcc -Os -s | 8 | set CC=gcc -Os -s |
| 13 | set /p VERSION= < ..\VERSION | 9 | set /p VERSION= < ..\VERSION |
| 14 | set INST= | 10 | set INST= |
| @@ -70,10 +66,17 @@ goto :a1 · 55 unmodified lines | |||
| 70 | if not (%1)==() goto :usage | 66 | if not (%1)==() goto :usage |
| 71 | 67 | ||
| 72 | if not "%CC%"=="@call :cl" goto :p1 | 68 | if not "%CC%"=="@call :cl" goto :p1 |
| 69 | set VSCOMNTOOLS=%VS150COMNTOOLS% | ||
| 70 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS% | ||
| 71 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS% | ||
| 72 | if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS% | ||
| 73 | if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat" | 73 | if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat" |
| 74 | if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat" | 74 | if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat" |
| 75 | if %T%_==_ set T=32& if %Platform%_==X64_ set T=64 | 75 | if %T%_==_ set T=32& if %Platform%_==X64_ set T=64 |
| 76 | if %CLVARS%_==_ goto :p1 | ||
| 77 | if exist %CLVARS% call %CLVARS% | ||
| 76 | :p1 | 78 | :p1 |
| 79 | |||
| 77 | if not %T%_==_ goto :p2 | 80 | if not %T%_==_ goto :p2 |
| 78 | set T=32 | 81 | set T=32 |
| 79 | if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64 | 82 | if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64 |
| @@ -97,9 +100,6 @@ set PX=i386-win32 · 17 unmodified lines | |||
| 97 | 100 | ||
| 98 | @echo on | 101 | @echo on |
| 99 | 102 | ||
| 100 | @if %CLVARS%_==_ goto :config.h | ||
| 101 | call %CLVARS% | ||
| 102 | |||
| 103 | :config.h | 103 | :config.h |
| 104 | echo>..\config.h #define TCC_VERSION "%VERSION%" | 104 | echo>..\config.h #define TCC_VERSION "%VERSION%" |
| 105 | echo>> ..\config.h #ifdef TCC_TARGET_X86_64 | 105 | echo>> ..\config.h #ifdef TCC_TARGET_X86_64 |
| @@ -108,7 +108,7 @@ echo>> ..\config.h #else · 2 unmodified lines | |||
| 108 | echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib" | 108 | echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib" |
| 109 | echo>> ..\config.h #endif | 109 | echo>> ..\config.h #endif |
| 110 | 110 | ||
| 111 | @del /q *tcc.exe tiny_*.exe *tcc.dll | 111 | for %%f in (*tcc.exe *tcc.dll) do @del %%f |
| 112 | 112 | ||
| 113 | :compiler | 113 | :compiler |
| 114 | %CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL | 114 | %CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL |
| @@ -116,10 +116,6 @@ echo>> ..\config.h #endif · 1 unmodified line | |||
| 116 | %CC% -o tcc.exe ..\tcc.c libtcc.dll %D% | 116 | %CC% -o tcc.exe ..\tcc.c libtcc.dll %D% |
| 117 | %CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE | 117 | %CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE |
| 118 | 118 | ||
| 119 | :tools | ||
| 120 | %CC% -o tiny_impdef.exe tools\tiny_impdef.c %D% | ||
| 121 | %CC% -o tiny_libmaker.exe tools\tiny_libmaker.c %D% | ||
| 122 | |||
| 123 | @if (%TCC_FILES%)==(no) goto :files-done | 119 | @if (%TCC_FILES%)==(no) goto :files-done |
| 124 | 120 | ||
| 125 | if not exist libtcc mkdir libtcc | 121 | if not exist libtcc mkdir libtcc |
| @@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64 · 3 unmodified lines | |||
| 129 | copy>nul ..\include\*.h include | 125 | copy>nul ..\include\*.h include |
| 130 | copy>nul ..\tcclib.h include | 126 | copy>nul ..\tcclib.h include |
| 131 | copy>nul ..\libtcc.h libtcc | 127 | copy>nul ..\libtcc.h libtcc |
| 132 | tiny_impdef libtcc.dll -o libtcc\libtcc.def | ||
| 133 | copy>nul ..\tests\libtcc_test.c examples | 128 | copy>nul ..\tests\libtcc_test.c examples |
| 134 | copy>nul tcc-win32.txt doc | 129 | copy>nul tcc-win32.txt doc |
| 135 | 130 | ||
| 136 | copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe | 131 | .\tcc -impdef libtcc.dll -o libtcc\libtcc.def |
| 137 | %CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX% | 132 | @if errorlevel 1 goto :the_end |
| 138 | 133 | ||
| 139 | :libtcc1.a | 134 | :libtcc1.a |
| 140 | @set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o | 135 | @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 · 8 unmodified lines | |||
| 149 | .\tcc -m32 %D32% -w -c ../lib/bcheck.c | 144 | .\tcc -m32 %D32% -w -c ../lib/bcheck.c |
| 150 | .\tcc -m32 %D32% -c ../lib/alloca86.S | 145 | .\tcc -m32 %D32% -c ../lib/alloca86.S |
| 151 | .\tcc -m32 %D32% -c ../lib/alloca86-bt.S | 146 | .\tcc -m32 %D32% -c ../lib/alloca86-bt.S |
| 152 | tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o | 147 | .\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o |
| 153 | @if errorlevel 1 goto :the_end | 148 | @if errorlevel 1 goto :the_end |
| 154 | .\tcc -m64 %D64% -c ../lib/libtcc1.c | 149 | .\tcc -m64 %D64% -c ../lib/libtcc1.c |
| 155 | .\tcc -m64 %D64% -c lib/crt1.c | 150 | .\tcc -m64 %D64% -c lib/crt1.c |
| @@ -162,7 +157,7 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o · 6 unmodified lines | |||
| 162 | .\tcc -m64 %D64% -w -c ../lib/bcheck.c | 157 | .\tcc -m64 %D64% -w -c ../lib/bcheck.c |
| 163 | .\tcc -m64 %D64% -c ../lib/alloca86_64.S | 158 | .\tcc -m64 %D64% -c ../lib/alloca86_64.S |
| 164 | .\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S | 159 | .\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S |
| 165 | tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o | 160 | .\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o |
| 166 | @if errorlevel 1 goto :the_end | 161 | @if errorlevel 1 goto :the_end |
| 167 | 162 | ||
| 168 | :tcc-doc.html | 163 | :tcc-doc.html |
| @@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html · 3 unmodified lines | |||
| 172 | :doc-done | 167 | :doc-done |
| 173 | 168 | ||
| 174 | :files-done | 169 | :files-done |
| 175 | @del /q *.o *.def *-m??.exe | 170 | for %%f in (*.o *.def) do @del %%f |
| 176 | 171 | ||
| 177 | :copy-install | 172 | :copy-install |
| 178 | @if (%INST%)==() goto :the_end | 173 | @if (%INST%)==() goto :the_end |
| @@ -39,7 +39,7 @@ · 38 unmodified lines | |||
| 39 | For the 'Hello DLL' example type | 39 | For the 'Hello DLL' example type |
| 40 | 40 | ||
| 41 | tcc -shared dll.c | 41 | tcc -shared dll.c |
| 42 | tiny_impdef dll.dll (optional) | 42 | tcc -impdef dll.dll (optional) |
| 43 | tcc hello_dll.c dll.def | 43 | tcc hello_dll.c dll.def |
| 44 | 44 | ||
| 45 | 45 | ||
| @@ -66,10 +66,10 @@ · 20 unmodified lines | |||
| 66 | To link with Windows system DLLs, TCC uses import definition | 66 | To link with Windows system DLLs, TCC uses import definition |
| 67 | files (.def) instead of libraries. | 67 | files (.def) instead of libraries. |
| 68 | 68 | ||
| 69 | The included 'tiny_impdef' program may be used to make additional | 69 | The now built-in 'tiny_impdef' program may be used to make |
| 70 | .def files for any DLL. For example: | 70 | additional .def files for any DLL. For example |
| 71 | 71 | ||
| 72 | tiny_impdef.exe opengl32.dll | 72 | tcc -impdef [-v] opengl32.dll [-o opengl32.def] |
| 73 | 73 | ||
| 74 | Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at | 74 | Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at |
| 75 | the TCC commandline to link a program that uses opengl32.dll. | 75 | the TCC commandline to link a program that uses opengl32.dll. |
| @@ -98,10 +98,10 @@ · 22 unmodified lines | |||
| 98 | 98 | ||
| 99 | Tiny Libmaker: | 99 | Tiny Libmaker: |
| 100 | -------------- | 100 | -------------- |
| 101 | The included tiny_libmaker tool by Timovj Lahde can be used as | 101 | The now built-in tiny_libmaker tool by Timovj Lahde can be used as |
| 102 | 'ar' replacement to make a library from several object files: | 102 | 'ar' replacement to make a library from several object files: |
| 103 | 103 | ||
| 104 | tiny_libmaker [rcs] library objectfiles ... | 104 | tcc -ar [rcsv] library objectfiles ... |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | Compilation from source: | 107 | Compilation from source: |
| @@ -143,14 +143,12 @@ · 35 unmodified lines | |||
| 143 | ------------ | 143 | ------------ |
| 144 | - On the object file level, currently TCC supports only the ELF format, | 144 | - On the object file level, currently TCC supports only the ELF format, |
| 145 | not COFF as used by MinGW and MSVC. It is not possible to exchange | 145 | not COFF as used by MinGW and MSVC. It is not possible to exchange |
| 146 | object files or libraries between TCC and these compilers. However | 146 | object files or libraries between TCC and these compilers. |
| 147 | libraries for TCC from objects by TCC can be made using tiny_libmaker | ||
| 148 | or MinGW's ar. | ||
| 149 | 147 | ||
| 150 | - No leading underscore is generated in the ELF symbols. | 148 | However libraries for TCC from objects by TCC can be made using |
| 151 | 149 | tcc -ar lib.a files.o ,,, | |
| 152 | - Bounds checking (option -b) is not supported on 64-bit OS. | ||
| 153 | 150 | ||
| 151 | - No leading underscore is generated in the ELF symbols. | ||
| 154 | 152 | ||
| 155 | Documentation and License: | 153 | Documentation and License: |
| 156 | -------------------------- | 154 | -------------------------- |
| @@ -1,249 +0,0 @@ | |||
| 1 | /* -------------------------------------------------------------- */ | ||
| 2 | /* | ||
| 3 | * tiny_impdef creates an export definition file (.def) from a dll | ||
| 4 | * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]" | ||
| 5 | * | ||
| 6 | * Copyright (c) 2005,2007 grischka | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY | ||
| 24 | |||
| 25 | #define WIN32_LEAN_AND_MEAN | ||
| 26 | #include <windows.h> | ||
| 27 | #include <stdio.h> | ||
| 28 | #include <io.h> | ||
| 29 | #include <malloc.h> | ||
| 30 | |||
| 31 | static char *get_export_names(int fd); | ||
| 32 | #define tcc_free free | ||
| 33 | #define tcc_realloc realloc | ||
| 34 | |||
| 35 | /* extract the basename of a file */ | ||
| 36 | static char *file_basename(const char *name) | ||
| 37 | { | ||
| 38 | const char *p = strchr(name, 0); | ||
| 39 | while (p > name | ||
| 40 | && p[-1] != '/' | ||
| 41 | && p[-1] != '\\' | ||
| 42 | ) | ||
| 43 | --p; | ||
| 44 | return (char*)p; | ||
| 45 | } | ||
| 46 | |||
| 47 | int main(int argc, char **argv) | ||
| 48 | { | ||
| 49 | int ret, v, i; | ||
| 50 | char infile[MAX_PATH]; | ||
| 51 | char outfile[MAX_PATH]; | ||
| 52 | |||
| 53 | static const char *ext[] = { ".dll", ".exe", NULL }; | ||
| 54 | const char *file, **pp; | ||
| 55 | char path[MAX_PATH], *p, *q; | ||
| 56 | FILE *fp, *op; | ||
| 57 | |||
| 58 | infile[0] = 0; | ||
| 59 | outfile[0] = 0; | ||
| 60 | fp = op = NULL; | ||
| 61 | v = 0; | ||
| 62 | ret = 1; | ||
| 63 | p = NULL; | ||
| 64 | |||
| 65 | for (i = 1; i < argc; ++i) { | ||
| 66 | const char *a = argv[i]; | ||
| 67 | if ('-' == a[0]) { | ||
| 68 | if (0 == strcmp(a, "-v")) { | ||
| 69 | v = 1; | ||
| 70 | } else if (0 == strcmp(a, "-o")) { | ||
| 71 | if (++i == argc) | ||
| 72 | goto usage; | ||
| 73 | strcpy(outfile, argv[i]); | ||
| 74 | } else | ||
| 75 | goto usage; | ||
| 76 | } else if (0 == infile[0]) | ||
| 77 | strcpy(infile, a); | ||
| 78 | else | ||
| 79 | goto usage; | ||
| 80 | } | ||
| 81 | |||
| 82 | if (0 == infile[0]) { | ||
| 83 | usage: | ||
| 84 | fprintf(stderr, | ||
| 85 | "tiny_impdef: create export definition file (.def) from a dll\n" | ||
| 86 | "Usage: tiny_impdef library.dll [-o outputfile]\n" | ||
| 87 | ); | ||
| 88 | goto the_end; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (0 == outfile[0]) | ||
| 92 | { | ||
| 93 | strcpy(outfile, file_basename(infile)); | ||
| 94 | q = strrchr(outfile, '.'); | ||
| 95 | if (NULL == q) | ||
| 96 | q = strchr(outfile, 0); | ||
| 97 | strcpy(q, ".def"); | ||
| 98 | } | ||
| 99 | |||
| 100 | file = infile; | ||
| 101 | |||
| 102 | #ifdef _WIN32 | ||
| 103 | pp = ext; | ||
| 104 | do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) { | ||
| 105 | file = path; | ||
| 106 | break; | ||
| 107 | } while (*pp++); | ||
| 108 | #endif | ||
| 109 | |||
| 110 | fp = fopen(file, "rb"); | ||
| 111 | if (NULL == fp) { | ||
| 112 | fprintf(stderr, "tiny_impdef: no such file: %s\n", infile); | ||
| 113 | goto the_end; | ||
| 114 | } | ||
| 115 | if (v) | ||
| 116 | printf("--> %s\n", file); | ||
| 117 | |||
| 118 | p = get_export_names(fileno(fp)); | ||
| 119 | if (NULL == p) { | ||
| 120 | fprintf(stderr, "tiny_impdef: could not get exported function names.\n"); | ||
| 121 | goto the_end; | ||
| 122 | } | ||
| 123 | |||
| 124 | op = fopen(outfile, "w"); | ||
| 125 | if (NULL == op) { | ||
| 126 | fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile); | ||
| 127 | goto the_end; | ||
| 128 | } | ||
| 129 | |||
| 130 | fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file)); | ||
| 131 | for (q = p, i = 0; *q; ++i) { | ||
| 132 | fprintf(op, "%s\n", q); | ||
| 133 | q += strlen(q) + 1; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (v) { | ||
| 137 | printf("<-- %s\n", outfile); | ||
| 138 | printf("%d symbol(s) found\n", i); | ||
| 139 | } | ||
| 140 | |||
| 141 | ret = 0; | ||
| 142 | |||
| 143 | the_end: | ||
| 144 | if (p) | ||
| 145 | free(p); | ||
| 146 | if (fp) | ||
| 147 | fclose(fp); | ||
| 148 | if (op) | ||
| 149 | fclose(op); | ||
| 150 | return ret; | ||
| 151 | } | ||
| 152 | |||
| 153 | int read_mem(int fd, unsigned offset, void *buffer, unsigned len) | ||
| 154 | { | ||
| 155 | lseek(fd, offset, SEEK_SET); | ||
| 156 | return len == read(fd, buffer, len); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* -------------------------------------------------------------- */ | ||
| 160 | |||
| 161 | #if defined TCC_TARGET_X86_64 | ||
| 162 | # define IMAGE_FILE_MACHINE 0x8664 | ||
| 163 | #elif defined TCC_TARGET_ARM | ||
| 164 | # define IMAGE_FILE_MACHINE 0x01C0 | ||
| 165 | #elif 1 /* defined TCC_TARGET_I386 */ | ||
| 166 | # define IMAGE_FILE_MACHINE 0x014C | ||
| 167 | #endif | ||
| 168 | |||
| 169 | /* -------------------------------------------------------------- */ | ||
| 170 | #endif | ||
| 171 | |||
| 172 | static char *get_export_names(int fd) | ||
| 173 | { | ||
| 174 | int l, i, n, n0; | ||
| 175 | char *p; | ||
| 176 | |||
| 177 | IMAGE_SECTION_HEADER ish; | ||
| 178 | IMAGE_EXPORT_DIRECTORY ied; | ||
| 179 | IMAGE_DOS_HEADER dh; | ||
| 180 | IMAGE_FILE_HEADER ih; | ||
| 181 | DWORD sig, ref, addr, ptr, namep; | ||
| 182 | #ifdef TCC_TARGET_X86_64 | ||
| 183 | IMAGE_OPTIONAL_HEADER64 oh; | ||
| 184 | #else | ||
| 185 | IMAGE_OPTIONAL_HEADER32 oh; | ||
| 186 | #endif | ||
| 187 | int pef_hdroffset, opt_hdroffset, sec_hdroffset; | ||
| 188 | |||
| 189 | n = n0 = 0; | ||
| 190 | p = NULL; | ||
| 191 | |||
| 192 | if (!read_mem(fd, 0, &dh, sizeof dh)) | ||
| 193 | goto the_end; | ||
| 194 | if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) | ||
| 195 | goto the_end; | ||
| 196 | if (sig != 0x00004550) | ||
| 197 | goto the_end; | ||
| 198 | pef_hdroffset = dh.e_lfanew + sizeof sig; | ||
| 199 | if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) | ||
| 200 | goto the_end; | ||
| 201 | if (IMAGE_FILE_MACHINE != ih.Machine) | ||
| 202 | goto the_end; | ||
| 203 | opt_hdroffset = pef_hdroffset + sizeof ih; | ||
| 204 | sec_hdroffset = opt_hdroffset + sizeof oh; | ||
| 205 | if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) | ||
| 206 | goto the_end; | ||
| 207 | |||
| 208 | if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | ||
| 209 | goto the_end; | ||
| 210 | |||
| 211 | addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | ||
| 212 | //printf("addr: %08x\n", addr); | ||
| 213 | for (i = 0; i < ih.NumberOfSections; ++i) { | ||
| 214 | if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) | ||
| 215 | goto the_end; | ||
| 216 | //printf("vaddr: %08x\n", ish.VirtualAddress); | ||
| 217 | if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) | ||
| 218 | goto found; | ||
| 219 | } | ||
| 220 | goto the_end; | ||
| 221 | |||
| 222 | found: | ||
| 223 | ref = ish.VirtualAddress - ish.PointerToRawData; | ||
| 224 | if (!read_mem(fd, addr - ref, &ied, sizeof ied)) | ||
| 225 | goto the_end; | ||
| 226 | |||
| 227 | namep = ied.AddressOfNames - ref; | ||
| 228 | for (i = 0; i < ied.NumberOfNames; ++i) { | ||
| 229 | if (!read_mem(fd, namep, &ptr, sizeof ptr)) | ||
| 230 | goto the_end; | ||
| 231 | namep += sizeof ptr; | ||
| 232 | for (l = 0;;) { | ||
| 233 | if (n+1 >= n0) | ||
| 234 | p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); | ||
| 235 | if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { | ||
| 236 | tcc_free(p), p = NULL; | ||
| 237 | goto the_end; | ||
| 238 | } | ||
| 239 | if (p[n++] == 0) | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | } | ||
| 243 | if (p) | ||
| 244 | p[n] = 0; | ||
| 245 | the_end: | ||
| 246 | return p; | ||
| 247 | } | ||
| 248 | |||
| 249 | /* -------------------------------------------------------------- */ | ||
| @@ -1,278 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This program is for making libtcc1.a without ar | ||
| 3 | * tiny_libmaker - tiny elf lib maker | ||
| 4 | * usage: tiny_libmaker [lib] files... | ||
| 5 | * Copyright (c) 2007 Timppa | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 20 | */ | ||
| 21 | #include <stdio.h> | ||
| 22 | #include <stdlib.h> | ||
| 23 | #include <string.h> | ||
| 24 | #include "../../elf.h" | ||
| 25 | |||
| 26 | #ifdef TCC_TARGET_X86_64 | ||
| 27 | # define ELFCLASSW ELFCLASS64 | ||
| 28 | # define ElfW(type) Elf##64##_##type | ||
| 29 | # define ELFW(type) ELF##64##_##type | ||
| 30 | #else | ||
| 31 | # define ELFCLASSW ELFCLASS32 | ||
| 32 | # define ElfW(type) Elf##32##_##type | ||
| 33 | # define ELFW(type) ELF##32##_##type | ||
| 34 | #endif | ||
| 35 | |||
| 36 | #define ARMAG "!<arch>\n" | ||
| 37 | #define ARFMAG "`\n" | ||
| 38 | |||
| 39 | typedef struct ArHdr { | ||
| 40 | char ar_name[16]; | ||
| 41 | char ar_date[12]; | ||
| 42 | char ar_uid[6]; | ||
| 43 | char ar_gid[6]; | ||
| 44 | char ar_mode[8]; | ||
| 45 | char ar_size[10]; | ||
| 46 | char ar_fmag[2]; | ||
| 47 | } ArHdr; | ||
| 48 | |||
| 49 | unsigned long le2belong(unsigned long ul) { | ||
| 50 | return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) + | ||
| 51 | ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8); | ||
| 52 | } | ||
| 53 | |||
| 54 | ArHdr arhdr = { | ||
| 55 | "/ ", | ||
| 56 | " ", | ||
| 57 | "0 ", | ||
| 58 | "0 ", | ||
| 59 | "0 ", | ||
| 60 | " ", | ||
| 61 | ARFMAG | ||
| 62 | }; | ||
| 63 | |||
| 64 | ArHdr arhdro = { | ||
| 65 | " ", | ||
| 66 | " ", | ||
| 67 | "0 ", | ||
| 68 | "0 ", | ||
| 69 | "0 ", | ||
| 70 | " ", | ||
| 71 | ARFMAG | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* Returns 1 if s contains any of the chars of list, else 0 */ | ||
| 75 | int contains_any(const char *s, const char *list) { | ||
| 76 | const char *l; | ||
| 77 | for (; *s; s++) { | ||
| 78 | for (l = list; *l; l++) { | ||
| 79 | if (*s == *l) | ||
| 80 | return 1; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | int usage(int ret) { | ||
| 87 | fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n"); | ||
| 88 | fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n"); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | int main(int argc, char **argv) | ||
| 93 | { | ||
| 94 | FILE *fi, *fh = NULL, *fo = NULL; | ||
| 95 | ElfW(Ehdr) *ehdr; | ||
| 96 | ElfW(Shdr) *shdr; | ||
| 97 | ElfW(Sym) *sym; | ||
| 98 | int i, fsize, i_lib, i_obj; | ||
| 99 | char *buf, *shstr, *symtab = NULL, *strtab = NULL; | ||
| 100 | int symtabsize = 0;//, strtabsize = 0; | ||
| 101 | char *anames = NULL; | ||
| 102 | int *afpos = NULL; | ||
| 103 | int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs; | ||
| 104 | char tfile[260], stmp[20]; | ||
| 105 | char *file, *name; | ||
| 106 | int ret = 2; | ||
| 107 | char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. | ||
| 108 | int verbose = 0; | ||
| 109 | |||
| 110 | i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj | ||
| 111 | for (i = 1; i < argc; i++) { | ||
| 112 | const char *a = argv[i]; | ||
| 113 | if (*a == '-' && strstr(a, ".")) | ||
| 114 | return usage(1); // -x.y is always invalid (same as gnu ar) | ||
| 115 | if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument | ||
| 116 | if (contains_any(a, ops_conflict)) | ||
| 117 | return usage(1); | ||
| 118 | if (strstr(a, "v")) | ||
| 119 | verbose = 1; | ||
| 120 | } else { // lib or obj files: don't abort - keep validating all args. | ||
| 121 | if (!i_lib) // first file is the lib | ||
| 122 | i_lib = i; | ||
| 123 | else if (!i_obj) // second file is the first obj | ||
| 124 | i_obj = i; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | if (!i_obj) // i_obj implies also i_lib. we require both. | ||
| 128 | return usage(1); | ||
| 129 | |||
| 130 | if ((fh = fopen(argv[i_lib], "wb")) == NULL) | ||
| 131 | { | ||
| 132 | fprintf(stderr, "Can't open file %s \n", argv[i_lib]); | ||
| 133 | goto the_end; | ||
| 134 | } | ||
| 135 | |||
| 136 | sprintf(tfile, "%s.tmp", argv[i_lib]); | ||
| 137 | if ((fo = fopen(tfile, "wb+")) == NULL) | ||
| 138 | { | ||
| 139 | fprintf(stderr, "Can't create temporary file %s\n", tfile); | ||
| 140 | goto the_end; | ||
| 141 | } | ||
| 142 | |||
| 143 | funcmax = 250; | ||
| 144 | afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func | ||
| 145 | memcpy(&arhdro.ar_mode, "100666", 6); | ||
| 146 | |||
| 147 | // i_obj = first input object file | ||
| 148 | while (i_obj < argc) | ||
| 149 | { | ||
| 150 | if (*argv[i_obj] == '-') { // by now, all options start with '-' | ||
| 151 | i_obj++; | ||
| 152 | continue; | ||
| 153 | } | ||
| 154 | if (verbose) | ||
| 155 | printf("a - %s\n", argv[i_obj]); | ||
| 156 | |||
| 157 | if ((fi = fopen(argv[i_obj], "rb")) == NULL) | ||
| 158 | { | ||
| 159 | fprintf(stderr, "Can't open file %s \n", argv[i_obj]); | ||
| 160 | goto the_end; | ||
| 161 | } | ||
| 162 | fseek(fi, 0, SEEK_END); | ||
| 163 | fsize = ftell(fi); | ||
| 164 | fseek(fi, 0, SEEK_SET); | ||
| 165 | buf = malloc(fsize + 1); | ||
| 166 | fread(buf, fsize, 1, fi); | ||
| 167 | fclose(fi); | ||
| 168 | |||
| 169 | // elf header | ||
| 170 | ehdr = (ElfW(Ehdr) *)buf; | ||
| 171 | if (ehdr->e_ident[4] != ELFCLASSW) | ||
| 172 | { | ||
| 173 | fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]); | ||
| 174 | goto the_end; | ||
| 175 | } | ||
| 176 | |||
| 177 | shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize); | ||
| 178 | shstr = (char *)(buf + shdr->sh_offset); | ||
| 179 | for (i = 0; i < ehdr->e_shnum; i++) | ||
| 180 | { | ||
| 181 | shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize); | ||
| 182 | if (!shdr->sh_offset) | ||
| 183 | continue; | ||
| 184 | if (shdr->sh_type == SHT_SYMTAB) | ||
| 185 | { | ||
| 186 | symtab = (char *)(buf + shdr->sh_offset); | ||
| 187 | symtabsize = shdr->sh_size; | ||
| 188 | } | ||
| 189 | if (shdr->sh_type == SHT_STRTAB) | ||
| 190 | { | ||
| 191 | if (!strcmp(shstr + shdr->sh_name, ".strtab")) | ||
| 192 | { | ||
| 193 | strtab = (char *)(buf + shdr->sh_offset); | ||
| 194 | //strtabsize = shdr->sh_size; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | if (symtab && symtabsize) | ||
| 200 | { | ||
| 201 | int nsym = symtabsize / sizeof(ElfW(Sym)); | ||
| 202 | //printf("symtab: info size shndx name\n"); | ||
| 203 | for (i = 1; i < nsym; i++) | ||
| 204 | { | ||
| 205 | sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym))); | ||
| 206 | if (sym->st_shndx && | ||
| 207 | (sym->st_info == 0x10 | ||
| 208 | || sym->st_info == 0x11 | ||
| 209 | || sym->st_info == 0x12 | ||
| 210 | )) { | ||
| 211 | //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name); | ||
| 212 | istrlen = strlen(strtab + sym->st_name)+1; | ||
| 213 | anames = realloc(anames, strpos+istrlen); | ||
| 214 | strcpy(anames + strpos, strtab + sym->st_name); | ||
| 215 | strpos += istrlen; | ||
| 216 | if (++funccnt >= funcmax) { | ||
| 217 | funcmax += 250; | ||
| 218 | afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more | ||
| 219 | } | ||
| 220 | afpos[funccnt] = fpos; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | file = argv[i_obj]; | ||
| 226 | for (name = strchr(file, 0); | ||
| 227 | name > file && name[-1] != '/' && name[-1] != '\\'; | ||
| 228 | --name); | ||
| 229 | istrlen = strlen(name); | ||
| 230 | if (istrlen >= sizeof(arhdro.ar_name)) | ||
| 231 | istrlen = sizeof(arhdro.ar_name) - 1; | ||
| 232 | memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name)); | ||
| 233 | memcpy(arhdro.ar_name, name, istrlen); | ||
| 234 | arhdro.ar_name[istrlen] = '/'; | ||
| 235 | sprintf(stmp, "%-10d", fsize); | ||
| 236 | memcpy(&arhdro.ar_size, stmp, 10); | ||
| 237 | fwrite(&arhdro, sizeof(arhdro), 1, fo); | ||
| 238 | fwrite(buf, fsize, 1, fo); | ||
| 239 | free(buf); | ||
| 240 | i_obj++; | ||
| 241 | fpos += (fsize + sizeof(arhdro)); | ||
| 242 | } | ||
| 243 | hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int); | ||
| 244 | fpos = 0; | ||
| 245 | if ((hofs & 1)) // align | ||
| 246 | hofs++, fpos = 1; | ||
| 247 | // write header | ||
| 248 | fwrite("!<arch>\n", 8, 1, fh); | ||
| 249 | sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int))); | ||
| 250 | memcpy(&arhdr.ar_size, stmp, 10); | ||
| 251 | fwrite(&arhdr, sizeof(arhdr), 1, fh); | ||
| 252 | afpos[0] = le2belong(funccnt); | ||
| 253 | for (i=1; i<=funccnt; i++) | ||
| 254 | afpos[i] = le2belong(afpos[i] + hofs); | ||
| 255 | fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh); | ||
| 256 | fwrite(anames, strpos, 1, fh); | ||
| 257 | if (fpos) | ||
| 258 | fwrite("", 1, 1, fh); | ||
| 259 | // write objects | ||
| 260 | fseek(fo, 0, SEEK_END); | ||
| 261 | fsize = ftell(fo); | ||
| 262 | fseek(fo, 0, SEEK_SET); | ||
| 263 | buf = malloc(fsize + 1); | ||
| 264 | fread(buf, fsize, 1, fo); | ||
| 265 | fwrite(buf, fsize, 1, fh); | ||
| 266 | free(buf); | ||
| 267 | ret = 0; | ||
| 268 | the_end: | ||
| 269 | if (anames) | ||
| 270 | free(anames); | ||
| 271 | if (afpos) | ||
| 272 | free(afpos); | ||
| 273 | if (fh) | ||
| 274 | fclose(fh); | ||
| 275 | if (fo) | ||
| 276 | fclose(fo), remove(tfile); | ||
| 277 | return ret; | ||
| 278 | } | ||