History

tcctools.c: integrate tiny_libmaker/_impdef

usage: tcc -ar [rcsv] lib files... tcc -impdef lib.dll [-v] [-o lib.def] also: - support more files with -c: tcc -c f1.c f2.c ... - fix a bug which caused tcc f1.c f2.S to produce no asm - allow tcc -ar @listfile too - change prototype: _void_ tcc_set_options(...) - apply -Wl,-whole-archive when a librariy is given as libxxx.a also (not just for -lxxx)

grischka committed 9 years ago

Commit 2d3b9551 parent f34b1fe17 files · +996 −915Browse files

Unified · Split

17 files
  1. Changelog +1 −0
  2. Makefile +10 −10
  3. TODO +1 −0
  4. conftest.c +16 −6
  5. lib/Makefile +10 −20
  6. libtcc.c +128 −82
  7. libtcc.h +1 −1
  8. tcc.c +121 −218
  9. tcc.h +27 −7
  10. tccasm.c +1 −0
  11. tccpe.c +109 −13
  12. tcctools.c +547 −0
  13. tests/tcctest.c +1 −1
  14. win32/build-tcc.bat +13 −18
  15. win32/tcc-win32.txt +10 −12
  16. win32/tools/tiny_impdef.c +0 −249
  17. win32/tools/tiny_libmaker.c +0 −278
Changelog+1−0
@@ -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 support11- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
11 (Andrew Aladjev, Urs Janssen)12 (Andrew Aladjev, Urs Janssen)
12 13
Makefile+10−10
@@ -28,6 +28,7 @@ LIBS = · 27 unmodified lines
28ifdef CONFIG_WIN3228ifdef CONFIG_WIN32
29 ifneq ($(DISABLE_STATIC),no)29 ifneq ($(DISABLE_STATIC),no)
30 LIBTCC = libtcc.dll30 LIBTCC = libtcc.dll
31 LIBTCCDEF = libtcc.def
31 endif32 endif
32else33else
33 LIBS=-lm34 LIBS=-lm
@@ -82,7 +83,7 @@ ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CRO · 48 unmodified lines
82ARM64_CROSS = arm64-tcc$(EXESUF)83ARM64_CROSS = arm64-tcc$(EXESUF)
83C67_CROSS = c67-tcc$(EXESUF)84C67_CROSS = c67-tcc$(EXESUF)
84 85
85CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c86CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
86CORE_FILES += tcc.h config.h libtcc.h tcctok.h87CORE_FILES += tcc.h config.h libtcc.h tcctok.h
87I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h88I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
88WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c89WIN32_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
94C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c95C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
95 96
96ifdef CONFIG_WIN3297ifdef 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
124PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)124PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)
125endif125endif
126 126
127ifeq ($(TARGETOS),Darwin)127TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
128 PROGS += tiny_libmaker$(EXESUF)
129endif
130
131TCCLIBS = $(LIBTCC1) $(LIBTCC)
132TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info128TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
133 129
134ifdef CONFIG_CROSS130ifdef CONFIG_CROSS
@@ -179,7 +175,7 @@ $(ARM64_CROSS): $(ARM64_FILES) · 44 unmodified lines
179 175
180# libtcc generation and test176# libtcc generation and test
181ifndef ONE_SOURCE177ifndef ONE_SOURCE
182LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))178LIBTCC_OBJ = $(filter-out tcc.o tcctools.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
183LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))179LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
184else180else
185LIBTCC_OBJ = libtcc.o181LIBTCC_OBJ = libtcc.o
@@ -187,6 +183,8 @@ LIBTCC_INC = $(NATIVE_FILES) · 1 unmodified line
187libtcc.o : NATIVE_DEFINES += -DONE_SOURCE183libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
188endif184endif
189 185
186tcc.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
199libtcc.so: CFLAGS+=-fPIC197libtcc.so: CFLAGS+=-fPIC
200 198
201# windows : libtcc.dll199# windows : libtcc.dll
202libtcc.dll : $(LIBTCC_OBJ) tiny_impdef$(EXESUF)200libtcc.dll : $(LIBTCC_OBJ)
203 $(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)201 $(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)
204 ./tiny_impdef $@202
203libtcc.def : libtcc.dll tcc$(EXESUF)
204 ./tcc$(EXESUF) -impdef $< -o $@
205 205
206libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL206libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL
207 207
TODO+1−0
@@ -2,6 +2,7 @@ TODO list: · 1 unmodified line
2 2
3Bugs:3Bugs:
4 4
5- i386 fastcall is mostly wrong
5- FPU st(0) is left unclean (kwisatz haderach). Incompatible with6- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
6 optimized gcc/msc code7 optimized gcc/msc code
7- see transparent union pb in /urs/include/sys/socket.h8- see transparent union pb in /urs/include/sys/socket.h
conftest.c+16−6
@@ -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#endif25#endif
@@ -33,7 +35,9 @@ · 9 unmodified lines
33# define TRIPLET_ABI "gnu"35# define TRIPLET_ABI "gnu"
34#endif36#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_ABI41# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
38#else42#else
39# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI43# 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#else73#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;
lib/Makefile+10−20
@@ -20,9 +20,6 @@ ifndef TARGET · 19 unmodified lines
20 TARGET = x86_6420 TARGET = x86_64
21 else ifeq ($(ARCH),arm)21 else ifeq ($(ARCH),arm)
22 TARGET = arm22 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 = arm6424 TARGET = arm64
28 endif25 endif
@@ -37,6 +34,9 @@ cross : $(DIR)/libtcc1.a · 8 unmodified lines
37native : TCC = $(TOP)/tcc$(EXESUF)34native : TCC = $(TOP)/tcc$(EXESUF)
38cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)35cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
39 36
37XCC = $(TCC) -B$(TOPSRC)
38XAR = $(TCC) -ar
39
40I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)40I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
41X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)41X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
42ARM_O = libtcc1.o armeabi.o alloca-arm.o42ARM_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_PE48 TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
49 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include49 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
50 XAR = $(DIR)/tiny_libmaker$(EXESUF)
51else ifeq "$(TARGET)" "x86_64-win32"50else 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_PE52 TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
54 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include53 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
55 XAR = $(DIR)/tiny_libmaker$(EXESUF)
56else ifeq "$(TARGET)" "i386"54else ifeq "$(TARGET)" "i386"
57 OBJ = $(addprefix $(DIR)/,$(I386_O))55 OBJ = $(addprefix $(DIR)/,$(I386_O))
58 TGT = -DTCC_TARGET_I38656 TGT = -DTCC_TARGET_I386
59 XCC ?= $(TCC) -B$(TOPSRC)
60else ifeq "$(TARGET)" "x86_64"57else ifeq "$(TARGET)" "x86_64"
61 OBJ = $(addprefix $(DIR)/,$(X86_64_O))58 OBJ = $(addprefix $(DIR)/,$(X86_64_O))
62 TGT = -DTCC_TARGET_X86_6459 TGT = -DTCC_TARGET_X86_64
63 XCC ?= $(TCC) -B$(TOPSRC)
64else ifeq "$(TARGET)" "arm"60else ifeq "$(TARGET)" "arm"
65 OBJ = $(addprefix $(DIR)/,$(ARM_O))61 OBJ = $(addprefix $(DIR)/,$(ARM_O))
66 TGT = -DTCC_TARGET_ARM62 TGT = -DTCC_TARGET_ARM
67 XCC ?= $(TCC) -B$(TOPSRC)63 # using gcc, need asm
64 XCC = $(CC)
65 XFLAGS = $(CFLAGS) -fPIC
66 XAR = $(AR)
68else ifeq "$(TARGET)" "arm64"67else ifeq "$(TARGET)" "arm64"
69 OBJ = $(addprefix $(DIR)/,$(ARM64_O))68 OBJ = $(addprefix $(DIR)/,$(ARM64_O))
70 TGT = -DTCC_TARGET_ARM6469 TGT = -DTCC_TARGET_ARM64
71 XCC ?= $(TCC) -B$(TOPSRC)
72else70else
73 $(error libtcc1.a not supported on target '$(TARGET)')71 $(error libtcc1.a not supported on target '$(TARGET)')
74endif72endif
75 73
76ifeq ($(TARGETOS),Darwin)74ifeq ($(TARGETOS),Darwin)
77 XAR = $(DIR)/tiny_libmaker$(EXESUF)
78 XFLAGS += -D_ANSI_SOURCE75 XFLAGS += -D_ANSI_SOURCE
79 BCHECK_O =76 BCHECK_O =
80endif77endif
81 78
82ifdef XAR79$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ)
83AR = $(XAR)80 $(XAR) rcs $@ $(OBJ)
84endif
85
86$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
87 $(AR) rcs $@ $(OBJ)
88$(DIR)/%.o : %.c81$(DIR)/%.o : %.c
89 $(XCC) -c $< -o $@ $(TGT) $(XFLAGS)82 $(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
90$(DIR)/%.o : %.S83$(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)/exists86$(OBJ) : $(DIR)/exists
97 87
98%/exists :88%/exists :
99 mkdir -p $(DIR)89 mkdir -p $(DIR)
libtcc.c+128−82
@@ -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
242PUB_FUNC void tcc_memstats(int bench)242PUB_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
382PUB_FUNC void tcc_memstats(int bench)382PUB_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 == 2393#if MEM_DEBUG-0 == 2
394 exit(2);394 exit(2);
395#endif395#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
438static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)437static 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# endif879# 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
889LIBTCCAPI void tcc_delete(TCCState *s1)886LIBTCCAPI 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_NATIVE915#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
929LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)925LIBTCCAPI 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# endif961# endif
966#else962#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
980LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)976LIBTCCAPI 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
986LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)982LIBTCCAPI 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
1107LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)1103LIBTCCAPI 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
1441enum {1437enum {
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_x1485 TCC_OPTION_x,
1486 TCC_OPTION_ar,
1487 TCC_OPTION_impdef
1490};1488};
1491 1489
1492#define TCC_OPTION_HAS_ARG 0x00011490#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
1605static 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 */
1603static void args_parser_listfile(TCCState *s, const char *filename)1638static 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
1620PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)1666PUB_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
1637reparse:
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 }
1693reparse:
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_NATIVE1828#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#endif1853#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 else1859 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
1888LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)1958LIBTCCAPI 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
1925PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)1967PUB_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
1938PUB_FUNC void tcc_set_environment(TCCState *s)1984PUB_FUNC void tcc_set_environment(TCCState *s)
libtcc.h+1−1
@@ -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) */
30LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);30LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
31 31
32/*****************************/32/*****************************/
33/* preprocessor */33/* preprocessor */
tcc.c+121−218
@@ -23,69 +23,7 @@ · 22 unmodified lines
23#else23#else
24#include "tcc.h"24#include "tcc.h"
25#endif25#endif
26 26#include "tcctools.c"
27static 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
35static 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
90static void help(void)28static 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#endif85#endif
147#ifdef TCC_TARGET_X86_6486#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#endif93#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
158static 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
182static int execvp_win32(const char *prog, char **argv)98static 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
197static 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_I386101#ifdef TCC_TARGET_I386
205 case 32: break;102 "i386"
206 case 64: target = "x86_64";103#elif defined TCC_TARGET_X86_64
207#else104 "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#endif117#endif
212 l = tcc_basename(a0) - a0;
213 snprintf(child_path, sizeof child_path,
214#ifdef TCC_TARGET_PE118#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#else133#else
217 "%.*s%s-tcc"134 " Unidentified system"
218#endif135#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
232static void gen_makedeps(TCCState *s, const char *target, const char *filename)139static 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) {147static 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
260static char *default_outputfile(TCCState *s, const char *first_file)159static char *default_outputfile(TCCState *s, const char *first_file)
@@ -296,109 +195,113 @@ static unsigned getclock_ms(void) · 35 unmodified lines
296int main(int argc, char **argv)195int 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
202redo:
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_NATIVE288#ifdef TCC_IS_NATIVE
389 ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);289 ret = tcc_run(s, argc, argv);
390#endif290#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}
tcc.h+27−7
@@ -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
779struct filespec {779struct 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 strdup1094#undef strdup
1093#define strdup(s) use_tcc_strdup(s)1095#define strdup(s) use_tcc_strdup(s)
1094PUB_FUNC void tcc_memstats(int bench);1096PUB_FUNC void tcc_memcheck(void);
1095PUB_FUNC void tcc_error_noabort(const char *fmt, ...);1097PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
1096PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);1098PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
1097PUB_FUNC void tcc_warning(const char *fmt, ...);1099PUB_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 31133#define AFF_TYPE_ASMPP 3
1132#define AFF_TYPE_BIN 41134#define AFF_TYPE_BIN 4
1133#define AFF_TYPE_LIB 51135#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 11137#define AFF_BINTYPE_REL 1
1137#define AFF_BINTYPE_DYN 21138#define AFF_BINTYPE_DYN 2
1138#define AFF_BINTYPE_AR 31139#define AFF_BINTYPE_AR 3
1139#define AFF_BINTYPE_C67 41140#define AFF_BINTYPE_C67 4
1140 1141
1141
1142ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);1142ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
1143 1143
1144#ifndef TCC_TARGET_PE1144#ifndef TCC_TARGET_PE
@@ -1149,12 +1149,21 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1); · 4 unmodified lines
1149PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);1149PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
1150 1150
1151PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);1151PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
1152PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);1152PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
1153PUB_FUNC void tcc_set_environment(TCCState *s);1153PUB_FUNC void tcc_set_environment(TCCState *s);
1154#ifdef _WIN321154#ifdef _WIN32
1155ST_FUNC char *normalize_slashes(char *path);1155ST_FUNC char *normalize_slashes(char *path);
1156#endif1156#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
1160ST_DATA struct BufferedFile *file;1169ST_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_641576#ifdef TCC_TARGET_X86_64
1568ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);1577ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
1569#endif1578#endif
1579PUB_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 0x101581# define ST_PE_EXPORT 0x10
1572# define ST_PE_IMPORT 0x201582# define ST_PE_IMPORT 0x20
@@ -1595,6 +1605,16 @@ ST_FUNC void tcc_set_num_callers(int n); · 22 unmodified lines
1595ST_FUNC void tcc_run_free(TCCState *s1);1605ST_FUNC void tcc_run_free(TCCState *s1);
1596#endif1606#endif
1597 1607
1608/* ------------ tcctools.c ----------------- */
1609#if 0 /* included in tcc.c */
1610ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
1611#ifdef TCC_TARGET_PE
1612ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
1613#endif
1614ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
1615ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
1616#endif
1617
1598/********************************************************/1618/********************************************************/
1599#undef ST_DATA1619#undef ST_DATA
1600#ifdef ONE_SOURCE1620#ifdef ONE_SOURCE
tccasm.c+1−0
@@ -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_LOCAL1010 /* 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 */
tccpe.c+109−13
@@ -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#endif967#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
1548PUB_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
1610found:
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;
1633the_end_0:
1634 ret = 0;
1635the_end:
1636 close(fd);
1637the_end_1:
1638 *pp = p;
1639 return ret;
1640}
1641
1546/* -------------------------------------------------------------1642/* -------------------------------------------------------------
1547 * This is for compiled windows resources in 'coff' format1643 * 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_ONLY1759static int pe_load_dll(TCCState *s1, const char *filename)
1664#include "win32/tools/tiny_impdef.c"
1665
1666static 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
tcctools.c+547−0
@@ -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
36typedef 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
46static 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 */
52static 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
63static 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
69ST_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;
268the_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
304ST_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]) {
342usage:
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
395the_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
434ST_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
443static 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
467static 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
483ST_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
510int _CRT_glob = 1;
511#ifndef _CRT_glob
512int _dowildcard = 1;
513#endif
514#endif
515
516/* -------------------------------------------------------------- */
517/* generate xxx.d file */
518
519ST_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/* -------------------------------------------------------------- */
tests/tcctest.c+1−1
@@ -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 _WIN323437#ifndef _WIN32
win32/build-tcc.bat+13−18
@@ -5,10 +5,6 @@ · 4 unmodified lines
5@echo off5@echo off
6setlocal6setlocal
7 7
8set VSCOMNTOOLS=%VS150COMNTOOLS%
9if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
10if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
11if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
12set CC=gcc -Os -s8set CC=gcc -Os -s
13set /p VERSION= < ..\VERSION9set /p VERSION= < ..\VERSION
14set INST=10set INST=
@@ -70,10 +66,17 @@ goto :a1 · 55 unmodified lines
70if not (%1)==() goto :usage66if not (%1)==() goto :usage
71 67
72if not "%CC%"=="@call :cl" goto :p168if not "%CC%"=="@call :cl" goto :p1
69set VSCOMNTOOLS=%VS150COMNTOOLS%
70if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
71if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
72if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
73if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"73if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
74if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"74if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
75if %T%_==_ set T=32& if %Platform%_==X64_ set T=6475if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
76if %CLVARS%_==_ goto :p1
77if exist %CLVARS% call %CLVARS%
76:p178:p1
79
77if not %T%_==_ goto :p280if not %T%_==_ goto :p2
78set T=3281set T=32
79if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=6482if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
@@ -97,9 +100,6 @@ set PX=i386-win32 · 17 unmodified lines
97 100
98@echo on101@echo on
99 102
100@if %CLVARS%_==_ goto :config.h
101call %CLVARS%
102
103:config.h103:config.h
104echo>..\config.h #define TCC_VERSION "%VERSION%"104echo>..\config.h #define TCC_VERSION "%VERSION%"
105echo>> ..\config.h #ifdef TCC_TARGET_X86_64105echo>> ..\config.h #ifdef TCC_TARGET_X86_64
@@ -108,7 +108,7 @@ echo>> ..\config.h #else · 2 unmodified lines
108echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"108echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
109echo>> ..\config.h #endif109echo>> ..\config.h #endif
110 110
111@del /q *tcc.exe tiny_*.exe *tcc.dll111for %%f in (*tcc.exe *tcc.dll) do @del %%f
112 112
113:compiler113:compiler
114%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL114%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_SOURCE117%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-done119@if (%TCC_FILES%)==(no) goto :files-done
124 120
125if not exist libtcc mkdir libtcc121if not exist libtcc mkdir libtcc
@@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64 · 3 unmodified lines
129copy>nul ..\include\*.h include125copy>nul ..\include\*.h include
130copy>nul ..\tcclib.h include126copy>nul ..\tcclib.h include
131copy>nul ..\libtcc.h libtcc127copy>nul ..\libtcc.h libtcc
132tiny_impdef libtcc.dll -o libtcc\libtcc.def
133copy>nul ..\tests\libtcc_test.c examples128copy>nul ..\tests\libtcc_test.c examples
134copy>nul tcc-win32.txt doc129copy>nul tcc-win32.txt doc
135 130
136copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe131.\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.a134:libtcc1.a
140@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o135@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.c144.\tcc -m32 %D32% -w -c ../lib/bcheck.c
150.\tcc -m32 %D32% -c ../lib/alloca86.S145.\tcc -m32 %D32% -c ../lib/alloca86.S
151.\tcc -m32 %D32% -c ../lib/alloca86-bt.S146.\tcc -m32 %D32% -c ../lib/alloca86-bt.S
152tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o147.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
153@if errorlevel 1 goto :the_end148@if errorlevel 1 goto :the_end
154.\tcc -m64 %D64% -c ../lib/libtcc1.c149.\tcc -m64 %D64% -c ../lib/libtcc1.c
155.\tcc -m64 %D64% -c lib/crt1.c150.\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.c157.\tcc -m64 %D64% -w -c ../lib/bcheck.c
163.\tcc -m64 %D64% -c ../lib/alloca86_64.S158.\tcc -m64 %D64% -c ../lib/alloca86_64.S
164.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S159.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
165tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o160.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
166@if errorlevel 1 goto :the_end161@if errorlevel 1 goto :the_end
167 162
168:tcc-doc.html163: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-done167:doc-done
173 168
174:files-done169:files-done
175@del /q *.o *.def *-m??.exe170for %%f in (*.o *.def) do @del %%f
176 171
177:copy-install172:copy-install
178@if (%INST%)==() goto :the_end173@if (%INST%)==() goto :the_end
win32/tcc-win32.txt+10−12
@@ -39,7 +39,7 @@ · 38 unmodified lines
39 For the 'Hello DLL' example type39 For the 'Hello DLL' example type
40 40
41 tcc -shared dll.c41 tcc -shared dll.c
42 tiny_impdef dll.dll (optional)42 tcc -impdef dll.dll (optional)
43 tcc hello_dll.c dll.def43 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 definition66 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.dll72 tcc -impdef [-v] opengl32.dll [-o opengl32.def]
73 73
74 Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at74 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 as101 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 exchange145 not COFF as used by MinGW and MSVC. It is not possible to exchange
146 object files or libraries between TCC and these compilers. However146 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 --------------------------
win32/tools/tiny_impdef.c+0−249
@@ -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
31static char *get_export_names(int fd);
32#define tcc_free free
33#define tcc_realloc realloc
34
35/* extract the basename of a file */
36static 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
47int 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]) {
83usage:
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
143the_end:
144 if (p)
145 free(p);
146 if (fp)
147 fclose(fp);
148 if (op)
149 fclose(op);
150 return ret;
151}
152
153int 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
172static 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
222found:
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;
245the_end:
246 return p;
247}
248
249/* -------------------------------------------------------------- */
win32/tools/tiny_libmaker.c+0−278
@@ -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
39typedef 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
49unsigned long le2belong(unsigned long ul) {
50 return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
51 ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
52}
53
54ArHdr arhdr = {
55 "/ ",
56 " ",
57 "0 ",
58 "0 ",
59 "0 ",
60 " ",
61 ARFMAG
62 };
63
64ArHdr 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 */
75int 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
86int 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
92int 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;
268the_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}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t