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
77 - -mms-bitfields option (David Mertens)
88 - -include <file> option (Michael Matz)
99 - @listfile support (Vlad Vissoultchev)
10+- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
1011 - CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
1112 (Andrew Aladjev, Urs Janssen)
1213
Makefile+10−10
@@ -28,6 +28,7 @@ LIBS = · 27 unmodified lines
2828 ifdef CONFIG_WIN32
2929 ifneq ($(DISABLE_STATIC),no)
3030 LIBTCC = libtcc.dll
31+ LIBTCCDEF = libtcc.def
3132 endif
3233 else
3334 LIBS=-lm
@@ -82,7 +83,7 @@ ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CRO · 48 unmodified lines
8283 ARM64_CROSS = arm64-tcc$(EXESUF)
8384 C67_CROSS = c67-tcc$(EXESUF)
8485
85−CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
86+CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
8687 CORE_FILES += tcc.h config.h libtcc.h tcctok.h
8788 I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
8889 WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
@@ -94,7 +95,6 @@ ARM64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c · 5 unmodified lines
9495 C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
9596
9697 ifdef CONFIG_WIN32
97− PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
9898 ifeq ($(ARCH),x86-64)
9999 NATIVE_FILES=$(WIN64_FILES)
100100 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
124124 PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)
125125 endif
126126
127−ifeq ($(TARGETOS),Darwin)
128− PROGS += tiny_libmaker$(EXESUF)
129−endif
130−
131−TCCLIBS = $(LIBTCC1) $(LIBTCC)
127+TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
132128 TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
133129
134130 ifdef CONFIG_CROSS
@@ -179,7 +175,7 @@ $(ARM64_CROSS): $(ARM64_FILES) · 44 unmodified lines
179175
180176 # libtcc generation and test
181177 ifndef ONE_SOURCE
182−LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
178+LIBTCC_OBJ = $(filter-out tcc.o tcctools.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
183179 LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
184180 else
185181 LIBTCC_OBJ = libtcc.o
@@ -187,6 +183,8 @@ LIBTCC_INC = $(NATIVE_FILES) · 1 unmodified line
187183 libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
188184 endif
189185
186+tcc.o : tcctools.c
187+
190188 $(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
191189 $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS)
192190
@@ -199,9 +197,11 @@ libtcc.so: $(LIBTCC_OBJ) · 6 unmodified lines
199197 libtcc.so: CFLAGS+=-fPIC
200198
201199 # windows : libtcc.dll
202−libtcc.dll : $(LIBTCC_OBJ) tiny_impdef$(EXESUF)
200+libtcc.dll : $(LIBTCC_OBJ)
203201 $(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)
204− ./tiny_impdef $@
202+
203+libtcc.def : libtcc.dll tcc$(EXESUF)
204+ ./tcc$(EXESUF) -impdef $< -o $@
205205
206206 libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL
207207
TODO+1−0
@@ -2,6 +2,7 @@ TODO list: · 1 unmodified line
22
33 Bugs:
44
5+- i386 fastcall is mostly wrong
56 - FPU st(0) is left unclean (kwisatz haderach). Incompatible with
67 optimized gcc/msc code
78 - see transparent union pb in /urs/include/sys/socket.h
conftest.c+16−6
@@ -1,9 +1,9 @@
11 #include <stdio.h>
22
33 /* Define architecture */
4−#if defined(__i386__)
4+#if defined(__i386__) || defined _M_IX86
55 # define TRIPLET_ARCH "i386"
6−#elif defined(__x86_64__)
6+#elif defined(__x86_64__) || defined _M_AMD64
77 # define TRIPLET_ARCH "x86_64"
88 #elif defined(__arm__)
99 # define TRIPLET_ARCH "arm"
@@ -18,6 +18,8 @@ · 8 unmodified lines
1818 # define TRIPLET_OS "linux"
1919 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
2020 # define TRIPLET_OS "kfreebsd"
21+#elif defined _WIN32
22+# define TRIPLET_OS "win32"
2123 #elif !defined (__GNU__)
2224 # define TRIPLET_OS "unknown"
2325 #endif
@@ -33,7 +35,9 @@ · 9 unmodified lines
3335 # define TRIPLET_ABI "gnu"
3436 #endif
3537
36−#ifdef __GNU__
38+#if defined _WIN32
39+# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS
40+#elif defined __GNU__
3741 # define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
3842 #else
3943 # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
@@ -59,6 +63,13 @@ int main(int argc, char *argv[]) · 19 unmodified lines
5963 case 'v':
6064 printf("%d\n", __GNUC__);
6165 break;
66+#elif defined __TINYC__
67+ case 'v':
68+ puts("0");
69+ break;
70+ case 'm':
71+ printf("%d\n", __TINYC__);
72+ break;
6273 #else
6374 case 'm':
6475 case 'v':
@@ -68,9 +79,8 @@ int main(int argc, char *argv[]) · 3 unmodified lines
6879 case 't':
6980 puts(TRIPLET);
7081 break;
71− case -1:
72− /* to test -Wno-unused-result */
73− fread(NULL, 1, 1, NULL);
82+
83+ default:
7484 break;
7585 }
7686 return 0;
lib/Makefile+10−20
@@ -20,9 +20,6 @@ ifndef TARGET · 19 unmodified lines
2020 TARGET = x86_64
2121 else ifeq ($(ARCH),arm)
2222 TARGET = arm
23− # using gcc, need asm
24− XCC = $(CC)
25− XFLAGS = $(CFLAGS) -fPIC
2623 else ifeq ($(ARCH),arm64)
2724 TARGET = arm64
2825 endif
@@ -37,6 +34,9 @@ cross : $(DIR)/libtcc1.a · 8 unmodified lines
3734 native : TCC = $(TOP)/tcc$(EXESUF)
3835 cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
3936
37+XCC = $(TCC) -B$(TOPSRC)
38+XAR = $(TCC) -ar
39+
4040 I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
4141 X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
4242 ARM_O = libtcc1.o armeabi.o alloca-arm.o
@@ -47,53 +47,43 @@ ifeq "$(TARGET)" "i386-win32" · 4 unmodified lines
4747 OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
4848 TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
4949 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
50− XAR = $(DIR)/tiny_libmaker$(EXESUF)
5150 else ifeq "$(TARGET)" "x86_64-win32"
5251 OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O))
5352 TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
5453 XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
55− XAR = $(DIR)/tiny_libmaker$(EXESUF)
5654 else ifeq "$(TARGET)" "i386"
5755 OBJ = $(addprefix $(DIR)/,$(I386_O))
5856 TGT = -DTCC_TARGET_I386
59− XCC ?= $(TCC) -B$(TOPSRC)
6057 else ifeq "$(TARGET)" "x86_64"
6158 OBJ = $(addprefix $(DIR)/,$(X86_64_O))
6259 TGT = -DTCC_TARGET_X86_64
63− XCC ?= $(TCC) -B$(TOPSRC)
6460 else ifeq "$(TARGET)" "arm"
6561 OBJ = $(addprefix $(DIR)/,$(ARM_O))
6662 TGT = -DTCC_TARGET_ARM
67− XCC ?= $(TCC) -B$(TOPSRC)
63+ # using gcc, need asm
64+ XCC = $(CC)
65+ XFLAGS = $(CFLAGS) -fPIC
66+ XAR = $(AR)
6867 else ifeq "$(TARGET)" "arm64"
6968 OBJ = $(addprefix $(DIR)/,$(ARM64_O))
7069 TGT = -DTCC_TARGET_ARM64
71− XCC ?= $(TCC) -B$(TOPSRC)
7270 else
7371 $(error libtcc1.a not supported on target '$(TARGET)')
7472 endif
7573
7674 ifeq ($(TARGETOS),Darwin)
77− XAR = $(DIR)/tiny_libmaker$(EXESUF)
7875 XFLAGS += -D_ANSI_SOURCE
7976 BCHECK_O =
8077 endif
8178
82−ifdef XAR
83−AR = $(XAR)
84−endif
85−
86−$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
87− $(AR) rcs $@ $(OBJ)
79+$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ)
80+ $(XAR) rcs $@ $(OBJ)
8881 $(DIR)/%.o : %.c
8982 $(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
9083 $(DIR)/%.o : %.S
9184 $(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
92−# windows : utilities
93−$(DIR)/tiny_%$(EXESUF) : $(TOPSRC)/win32/tools/tiny_%.c
94− $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(TGT)
9585
96−$(OBJ) $(XAR) : $(DIR)/exists
86+$(OBJ) : $(DIR)/exists
9787
9888 %/exists :
9989 mkdir -p $(DIR)
libtcc.c+128−82
@@ -239,7 +239,7 @@ PUB_FUNC char *tcc_strdup(const char *str) · 238 unmodified lines
239239 return ptr;
240240 }
241241
242−PUB_FUNC void tcc_memstats(int bench)
242+PUB_FUNC void tcc_memcheck(void)
243243 {
244244 }
245245
@@ -379,7 +379,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) · 133 unmodified lines
379379 return ptr;
380380 }
381381
382−PUB_FUNC void tcc_memstats(int bench)
382+PUB_FUNC void tcc_memcheck(void)
383383 {
384384 if (mem_cur_size) {
385385 mem_debug_header_t *header = mem_debug_chain;
@@ -393,8 +393,7 @@ PUB_FUNC void tcc_memstats(int bench) · 7 unmodified lines
393393 #if MEM_DEBUG-0 == 2
394394 exit(2);
395395 #endif
396− } else if (bench)
397− fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size);
396+ }
398397 }
399398 #endif /* MEM_DEBUG */
400399
@@ -435,7 +434,7 @@ ST_FUNC void dynarray_reset(void *pp, int *n) · 34 unmodified lines
435434 *(void**)pp = NULL;
436435 }
437436
438−static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
437+static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
439438 {
440439 const char *p;
441440 do {
@@ -878,18 +877,14 @@ LIBTCCAPI TCCState *tcc_new(void) · 436 unmodified lines
878877 tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
879878 "name proto __asm__ (#alias) __THROW");
880879 # endif
881−#endif /* ndef TCC_TARGET_PE */
882−
883880 /* Some GCC builtins that are simple to express as macros. */
884881 tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
885−
882+#endif /* ndef TCC_TARGET_PE */
886883 return s;
887884 }
888885
889886 LIBTCCAPI void tcc_delete(TCCState *s1)
890887 {
891− int bench = s1->do_bench;
892−
893888 tcc_cleanup();
894889
895890 /* free sections */
@@ -915,6 +910,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 19 unmodified lines
915910 dynarray_reset(&s1->files, &s1->nb_files);
916911 dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
917912 dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
913+ dynarray_reset(&s1->argv, &s1->argc);
918914
919915 #ifdef TCC_IS_NATIVE
920916 /* free runtime memory */
@@ -923,7 +919,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 2 unmodified lines
923919
924920 tcc_free(s1);
925921 if (0 == --nb_states)
926− tcc_memstats(bench);
922+ tcc_memcheck();
927923 }
928924
929925 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
@@ -965,7 +961,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 35 unmodified lines
965961 # endif
966962 #else
967963 /* 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);
969965 /* add libc crt1/crti objects */
970966 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
971967 !s->nostdlib) {
@@ -979,13 +975,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 7 unmodified lines
979975
980976 LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
981977 {
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);
983979 return 0;
984980 }
985981
986982 LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
987983 {
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);
989985 return 0;
990986 }
991987
@@ -1106,7 +1102,7 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) · 114 unmodified lines
11061102
11071103 LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
11081104 {
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);
11101106 return 0;
11111107 }
11121108
@@ -1440,6 +1436,7 @@ typedef struct TCCOption { · 327 unmodified lines
14401436
14411437 enum {
14421438 TCC_OPTION_HELP,
1439+ TCC_OPTION_v,
14431440 TCC_OPTION_I,
14441441 TCC_OPTION_D,
14451442 TCC_OPTION_U,
@@ -1480,13 +1477,14 @@ enum { · 34 unmodified lines
14801477 TCC_OPTION_pedantic,
14811478 TCC_OPTION_pthread,
14821479 TCC_OPTION_run,
1483− TCC_OPTION_v,
14841480 TCC_OPTION_w,
14851481 TCC_OPTION_pipe,
14861482 TCC_OPTION_E,
14871483 TCC_OPTION_MD,
14881484 TCC_OPTION_MF,
1489− TCC_OPTION_x
1485+ TCC_OPTION_x,
1486+ TCC_OPTION_ar,
1487+ TCC_OPTION_impdef
14901488 };
14911489
14921490 #define TCC_OPTION_HAS_ARG 0x0001
@@ -1496,6 +1494,7 @@ static const TCCOption tcc_options[] = { · 3 unmodified lines
14961494 { "h", TCC_OPTION_HELP, 0 },
14971495 { "-help", TCC_OPTION_HELP, 0 },
14981496 { "?", TCC_OPTION_HELP, 0 },
1497+ { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
14991498 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
15001499 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
15011500 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
@@ -1542,13 +1541,16 @@ static const TCCOption tcc_options[] = { · 40 unmodified lines
15421541 { "nostdinc", TCC_OPTION_nostdinc, 0 },
15431542 { "nostdlib", TCC_OPTION_nostdlib, 0 },
15441543 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
1545− { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
15461544 { "w", TCC_OPTION_w, 0 },
15471545 { "pipe", TCC_OPTION_pipe, 0},
15481546 { "E", TCC_OPTION_E, 0},
15491547 { "MD", TCC_OPTION_MD, 0},
15501548 { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
15511549 { "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
15521554 { NULL, 0, 0 },
15531555 };
15541556
@@ -1595,58 +1597,106 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 40 unmodified lines
15951597 {
15961598 struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
15971599 f->type = filetype;
1600+ f->alacarte = s->alacarte_link;
15981601 strcpy(f->name, filename);
15991602 dynarray_add(&s->files, &s->nb_files, f);
16001603 }
16011604
1605+static int args_parser_make_argv(const char *r, int *argc, char ***argv)
1606+{
1607+ int ret = 0, q, c;
1608+ CString str;
1609+ for(;;) {
1610+ while (c = (unsigned char)*r, c && c <= ' ')
1611+ ++r;
1612+ if (c == 0)
1613+ break;
1614+ q = 0;
1615+ cstr_new(&str);
1616+ while (c = (unsigned char)*r, c) {
1617+ ++r;
1618+ if (c == '\\' && (*r == '"' || *r == '\\')) {
1619+ c = *r++;
1620+ } else if (c == '"') {
1621+ q = !q;
1622+ continue;
1623+ } else if (q == 0 && c <= ' ') {
1624+ break;
1625+ }
1626+ cstr_ccat(&str, c);
1627+ }
1628+ cstr_ccat(&str, 0);
1629+ //printf("<%s>\n", str.data), fflush(stdout);
1630+ dynarray_add(argv, argc, tcc_strdup(str.data));
1631+ cstr_free(&str);
1632+ ++ret;
1633+ }
1634+ return ret;
1635+}
1636+
16021637 /* read list file */
1603−static void args_parser_listfile(TCCState *s, const char *filename)
1638+static void args_parser_listfile(TCCState *s,
1639+ const char *filename, int optind, int *pargc, char ***pargv)
16041640 {
1605− int fd;
1641+ int fd, i;
16061642 size_t len;
16071643 char *p;
1644+ int argc = 0;
1645+ char **argv = NULL;
16081646
16091647 fd = open(filename, O_RDONLY | O_BINARY);
16101648 if (fd < 0)
1611− tcc_error("file '%s' not found", filename);
1649+ tcc_error("listfile '%s' not found", filename);
16121650
16131651 len = lseek(fd, 0, SEEK_END);
16141652 p = tcc_malloc(len + 1), p[len] = 0;
16151653 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+
16171661 tcc_free(p);
1662+ dynarray_reset(&s->argv, &s->argc);
1663+ *pargc = s->argc = argc, *pargv = s->argv = argv;
16181664 }
16191665
1620−PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
1666+PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
16211667 {
16221668 const TCCOption *popt;
16231669 const char *optarg, *r;
16241670 const char *run = NULL;
1625− int optind = 0;
1626− int x;
16271671 int last_o = -1;
1672+ int x;
16281673 CString linker_arg; /* collect -Wl options */
16291674 char buf[1024];
1675+ int tool = 0, arg_start = 0, noaction = optind;
1676+ char **argv = *pargv;
1677+ int argc = *pargc;
16301678
16311679 cstr_new(&linker_arg);
16321680
16331681 while (optind < argc) {
1634−
1635− r = argv[optind++];
1636−
1637−reparse:
1682+ r = argv[optind];
16381683 if (r[0] == '@' && r[1] != '\0') {
1639− args_parser_listfile(s, r + 1);
1684+ args_parser_listfile(s, r + 1, optind, &argc, &argv);
16401685 continue;
16411686 }
1642−
1687+ optind++;
1688+ if (tool) {
1689+ if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
1690+ ++s->verbose;
1691+ continue;
1692+ }
1693+reparse:
16431694 if (r[0] != '-' || r[1] == '\0') {
16441695 if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
16451696 args_parser_add_file(s, r, s->filetype);
16461697 if (run) {
16471698 tcc_set_options(s, run);
1648− optind--;
1649− /* argv[0] will be this file */
1699+ arg_start = optind - 1;
16501700 break;
16511701 }
16521702 continue;
@@ -1675,7 +1725,7 @@ reparse: · 22 unmodified lines
16751725
16761726 switch(popt->index) {
16771727 case TCC_OPTION_HELP:
1678− return 0;
1728+ return OPT_HELP;
16791729 case TCC_OPTION_I:
16801730 tcc_add_include_path(s, optarg);
16811731 break;
@@ -1693,7 +1743,7 @@ reparse: · 11 unmodified lines
16931743 tcc_set_lib_path(s, optarg);
16941744 break;
16951745 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);
16971747 s->nb_libraries++;
16981748 break;
16991749 case TCC_OPTION_pthread:
@@ -1774,9 +1824,6 @@ reparse: · 74 unmodified lines
17741824 case TCC_OPTION_nostdlib:
17751825 s->nostdlib = 1;
17761826 break;
1777− case TCC_OPTION_print_search_dirs:
1778− s->print_search_dirs = 1;
1779− break;
17801827 case TCC_OPTION_run:
17811828 #ifndef TCC_IS_NATIVE
17821829 tcc_error("-run is not available in a cross compiler");
@@ -1786,6 +1833,7 @@ reparse: · 3 unmodified lines
17861833 goto set_output_type;
17871834 case TCC_OPTION_v:
17881835 do ++s->verbose; while (*optarg++ == 'v');
1836+ ++noaction;
17891837 break;
17901838 case TCC_OPTION_f:
17911839 if (set_flag(s, options_f, optarg) < 0)
@@ -1804,12 +1852,13 @@ reparse: · 12 unmodified lines
18041852 break;
18051853 #endif
18061854 case TCC_OPTION_m:
1807− if (set_flag(s, options_m, optarg) == 0)
1808− break;
1809− else if (x = atoi(optarg), x == 32 || x == 64)
1810− s->cross_target = x;
1811− else
1812− goto unsupported_option;
1855+ if (set_flag(s, options_m, optarg) < 0) {
1856+ if (x = atoi(optarg), x != 32 && x != 64)
1857+ goto unsupported_option;
1858+ if (PTR_SIZE != x/8)
1859+ return x;
1860+ ++noaction;
1861+ }
18131862 break;
18141863 case TCC_OPTION_W:
18151864 if (set_flag(s, options_W, optarg) < 0)
@@ -1860,6 +1909,20 @@ reparse: · 44 unmodified lines
18601909 case TCC_OPTION_O:
18611910 last_o = atoi(optarg);
18621911 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;
18631926 case TCC_OPTION_traditional:
18641927 case TCC_OPTION_pedantic:
18651928 case TCC_OPTION_pipe:
@@ -1873,53 +1936,32 @@ unsupported_option: · 7 unmodified lines
18731936 break;
18741937 }
18751938 }
1876−
18771939 if (last_o > 0)
18781940 tcc_define_symbol(s, "__OPTIMIZE__", NULL);
1879−
18801941 if (linker_arg.size) {
18811942 r = linker_arg.data;
18821943 goto arg_err;
18831944 }
1884−
1885− return optind;
1945+ *pargc = argc - arg_start;
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;
18861956 }
18871957
1888−LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
1958+LIBTCCAPI void tcc_set_options(TCCState *s, const char *r)
18891959 {
1890− char **argv;
1891− int argc;
1892− int ret, q, c;
1893− CString str;
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);
1960+ char **argv = NULL;
1961+ int argc = 0;
1962+ args_parser_make_argv(r, &argc, &argv);
1963+ tcc_parse_args(s, &argc, &argv, 0);
19211964 dynarray_reset(&argv, &argc);
1922− return ret;
19231965 }
19241966
19251967 PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
@@ -1928,11 +1970,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) · 2 unmodified lines
19281970 total_time = 1;
19291971 if (total_bytes < 1)
19301972 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",
19321975 tok_ident - TOK_IDENT, total_lines, total_bytes,
19331976 (double)total_time/1000,
19341977 (unsigned)total_lines*1000/total_time,
19351978 (double)total_bytes/1000/total_time);
1979+#ifdef MEM_DEBUG
1980+ fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
1981+#endif
19361982 }
19371983
19381984 PUB_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
2727 void (*error_func)(void *opaque, const char *msg));
2828
2929 /* set options as from command line (multiple supported) */
30−LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
30+LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
3131
3232 /*****************************/
3333 /* preprocessor */
tcc.c+121−218
@@ -23,69 +23,7 @@ · 22 unmodified lines
2323 #else
2424 #include "tcc.h"
2525 #endif
26−
27−static void print_paths(const char *msg, char **paths, int nb_paths)
28−{
29− int i;
30− printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
31− for(i = 0; i < nb_paths; i++)
32− printf(" %s\n", paths[i]);
33−}
34−
35−static void display_info(TCCState *s, int what)
36−{
37− switch (what) {
38− case 0:
39− printf("tcc version %s ("
40−#ifdef TCC_TARGET_I386
41− "i386"
42−#elif defined TCC_TARGET_X86_64
43− "x86-64"
44−#elif defined TCC_TARGET_C67
45− "C67"
46−#elif defined TCC_TARGET_ARM
47− "ARM"
48−# ifdef TCC_ARM_HARDFLOAT
49− " Hard Float"
50−# endif
51−#elif defined TCC_TARGET_ARM64
52− "AArch64"
53−# ifdef TCC_ARM_HARDFLOAT
54− " Hard Float"
55−# endif
56−#endif
57−#ifdef TCC_TARGET_PE
58− " Windows"
59−#elif defined(__APPLE__)
60− /* Current Apple OS name as of 2016 */
61− " macOS"
62−#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
63− " FreeBSD"
64−#elif defined(__DragonFly__)
65− " DragonFly BSD"
66−#elif defined(__NetBSD__)
67− " NetBSD"
68−#elif defined(__OpenBSD__)
69− " OpenBSD"
70−#elif defined(__linux__)
71− " Linux"
72−#else
73− " Unidentified system"
74−#endif
75− ")\n", TCC_VERSION);
76− break;
77− case 1:
78− printf("install: %s\n", s->tcc_lib_path);
79− /* print_paths("programs", NULL, 0); */
80− print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
81− print_paths("libraries", s->library_paths, s->nb_library_paths);
82−#ifndef TCC_TARGET_PE
83− print_paths("crt", s->crt_paths, s->nb_crt_paths);
84− printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
85−#endif
86− break;
87− }
88−}
26+#include "tcctools.c"
8927
9028 static void help(void)
9129 {
@@ -100,7 +38,8 @@ static void help(void) · 8 unmodified lines
10038 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10139 " -w disable all warnings\n"
10240 " -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"
10443 " -bench show compilation statistics\n"
10544 "Preprocessor options:\n"
10645 " -Idir add include path 'dir'\n"
@@ -146,115 +85,75 @@ static void help(void) · 39 unmodified lines
14685 #endif
14786 #ifdef TCC_TARGET_X86_64
14887 " -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"
14993 #endif
15094 );
15195 }
15296
153−/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
154−#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
155−#ifdef _WIN32
156−#include <process.h>
157−
158−static char *str_replace(const char *str, const char *p, const char *r)
159−{
160− const char *s, *s0;
161− char *d, *d0;
162− int sl, pl, rl;
163−
164− sl = strlen(str);
165− pl = strlen(p);
166− rl = strlen(r);
167− for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
168− for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
169− if (d) {
170− memcpy(d, s0, sl = s - s0), d += sl;
171− memcpy(d, r, rl), d += rl;
172− } else
173− sl += rl - pl;
174− }
175− if (d) {
176− strcpy(d, s0);
177− return d0;
178− }
179− }
180−}
18197
182−static int execvp_win32(const char *prog, char **argv)
183−{
184− int ret; char **p;
185− /* replace all " by \" */
186− for (p = argv; *p; ++p)
187− if (strchr(*p, '"'))
188− *p = str_replace(*p, "\"", "\\\"");
189− ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
190− if (-1 == ret)
191− return ret;
192− cwait(&ret, ret, WAIT_CHILD);
193− exit(ret);
194−}
195−#define execvp execvp_win32
196−#endif
197−static void exec_other_tcc(TCCState *s, char **argv, int option)
98+static void version(void)
19899 {
199− char child_path[4096], *a0 = argv[0]; const char *target;
200− int l;
201−
202− switch (option) {
203−
100+ printf("tcc version %s ("
204101 #ifdef TCC_TARGET_I386
205− case 32: break;
206− case 64: target = "x86_64";
207−#else
208− case 64: break;
209− case 32: target = "i386";
210−
102+ "i386"
103+#elif defined TCC_TARGET_X86_64
104+ "x86-64"
105+#elif defined TCC_TARGET_C67
106+ "C67"
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
211117 #endif
212− l = tcc_basename(a0) - a0;
213− snprintf(child_path, sizeof child_path,
214118 #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"
216133 #else
217− "%.*s%s-tcc"
134+ " Unidentified system"
218135 #endif
219− , l, a0, target);
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− }
136+ ")\n", TCC_VERSION);
227137 }
228−#else
229−#define exec_other_tcc(s, argv, option)
230−#endif
231138
232−static void gen_makedeps(TCCState *s, const char *target, const char *filename)
139+static void print_dirs(const char *msg, char **paths, int nb_paths)
233140 {
234− FILE *depout;
235− char buf[1024];
236141 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+}
237146
238− if (!filename) {
239− /* compute filename automatically: dir/file.o -> dir/file.d */
240− snprintf(buf, sizeof buf, "%.*s.d",
241− (int)(tcc_fileextension(target) - target), target);
242− filename = buf;
243− }
244−
245− if (s->verbose)
246− printf("<- %s\n", filename);
247−
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);
147+static void print_search_dirs(TCCState *s)
148+{
149+ printf("install: %s\n", s->tcc_lib_path);
150+ /* print_dirs("programs", NULL, 0); */
151+ print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
152+ print_dirs("libraries", s->library_paths, s->nb_library_paths);
153+#ifndef TCC_TARGET_PE
154+ print_dirs("crt", s->crt_paths, s->nb_crt_paths);
155+ printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
156+#endif
258157 }
259158
260159 static char *default_outputfile(TCCState *s, const char *first_file)
@@ -296,109 +195,113 @@ static unsigned getclock_ms(void) · 35 unmodified lines
296195 int main(int argc, char **argv)
297196 {
298197 TCCState *s;
299− int ret, optind, i;
198+ int ret, opt, n = 0;
300199 unsigned start_time = 0;
301− const char *first_file = NULL;
200+ const char *first_file;
302201
202+redo:
303203 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;
304221
305− optind = tcc_parse_args(s, argc - 1, argv + 1);
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);
222+ tcc_set_environment(s);
316223
317− if (s->verbose)
318− display_info(s, 0);
224+ if (opt == OPT_PRINT_DIRS) {
225+ /* initialize search dirs */
226+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
227+ print_search_dirs(s);
228+ return 0;
229+ }
319230
320− if (s->nb_files == 0) {
321− if (optind == 1) {
322− if (s->print_search_dirs || s->verbose == 2) {
323− tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
324− display_info(s, 1);
325− return 1;
231+ n = s->nb_files;
232+ if (n == 0)
233+ tcc_error("no input files\n");
234+
235+ if (s->output_type == TCC_OUTPUT_PREPROCESS) {
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);
326242 }
327− if (s->verbose)
328− return 1;
243+ } else if (s->output_type == TCC_OUTPUT_OBJ) {
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");
329251 }
330− tcc_error("no input files\n");
331− }
332252
333− /* check -c consistency : only single file handled. XXX: checks file type */
334− if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
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");
253+ if (s->do_bench)
254+ start_time = getclock_ms();
340255 }
341256
342257 if (s->output_type == 0)
343258 s->output_type = TCC_OUTPUT_EXE;
344259 tcc_set_output_type(s, s->output_type);
345260
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−
362261 /* compile or add each files or library */
363− for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
364− struct filespec *f = s->files[i];
365− if (f->type >= AFF_TYPE_LIB) {
366− s->alacarte_link = f->type == AFF_TYPE_LIB;
262+ for (first_file = NULL, ret = 0;;) {
263+ struct filespec *f = s->files[s->nb_files - n];
264+ s->filetype = f->type;
265+ s->alacarte_link = f->alacarte;
266+ if (f->type == AFF_TYPE_LIB) {
367267 if (tcc_add_library_err(s, f->name) < 0)
368268 ret = 1;
369269 } else {
370270 if (1 == s->verbose)
371271 printf("-> %s\n", f->name);
372− s->filetype = f->type;
373− if (tcc_add_file(s, f->name) < 0)
374− ret = 1;
375272 if (!first_file)
376273 first_file = f->name;
274+ if (tcc_add_file(s, f->name) < 0)
275+ ret = 1;
377276 }
378− s->filetype = AFF_TYPE_NONE;
277+ s->filetype = 0;
379278 s->alacarte_link = 1;
279+ if (ret || --n == 0 || s->output_type == TCC_OUTPUT_OBJ)
280+ break;
380281 }
381282
382283 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
383284 if (s->outfile)
384285 fclose(s->ppfp);
385−
386286 } else if (0 == ret) {
387287 if (s->output_type == TCC_OUTPUT_MEMORY) {
388288 #ifdef TCC_IS_NATIVE
389− ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
289+ ret = tcc_run(s, argc, argv);
390290 #endif
391291 } else {
392292 if (!s->outfile)
393293 s->outfile = default_outputfile(s, first_file);
394− ret = !!tcc_output_file(s, s->outfile);
395− if (s->gen_deps && !ret)
294+ if (tcc_output_file(s, s->outfile))
295+ ret = 1;
296+ else if (s->gen_deps)
396297 gen_makedeps(s, s->outfile, s->deps_outfile);
397298 }
398299 }
399300
400− if (s->do_bench)
301+ if (s->do_bench && ret == 0 && n == 0)
401302 tcc_print_stats(s, getclock_ms() - start_time);
402303 tcc_delete(s);
304+ if (ret == 0 && n)
305+ goto redo; /* compile more files with -c */
403306 return ret;
404307 }
tcc.h+27−7
@@ -767,17 +767,19 @@ struct TCCState { · 766 unmodified lines
767767 int nb_libraries; /* number of libs thereof */
768768 int filetype;
769769 char *outfile; /* output filename */
770− int cross_target; /* -m32/-m64 */
771− int print_search_dirs; /* option */
772770 int option_r; /* option -r */
773771 int do_bench; /* option -bench */
774772 int gen_deps; /* option -MD */
775773 char *deps_outfile; /* option -MF */
776774 int option_pthread; /* -pthread option */
775+ int argc;
776+ char **argv;
777777 };
778778
779779 struct filespec {
780− char type, name[1];
780+ char type;
781+ char alacarte;
782+ char name[1];
781783 };
782784
783785 /* 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
10911093 #define realloc(p, s) use_tcc_realloc(p, s)
10921094 #undef strdup
10931095 #define strdup(s) use_tcc_strdup(s)
1094−PUB_FUNC void tcc_memstats(int bench);
1096+PUB_FUNC void tcc_memcheck(void);
10951097 PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
10961098 PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
10971099 PUB_FUNC void tcc_warning(const char *fmt, ...);
@@ -1131,14 +1133,12 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 33 unmodified lines
11311133 #define AFF_TYPE_ASMPP 3
11321134 #define AFF_TYPE_BIN 4
11331135 #define AFF_TYPE_LIB 5
1134−#define AFF_TYPE_LIBWH 6
11351136 /* values from tcc_object_type(...) */
11361137 #define AFF_BINTYPE_REL 1
11371138 #define AFF_BINTYPE_DYN 2
11381139 #define AFF_BINTYPE_AR 3
11391140 #define AFF_BINTYPE_C67 4
11401141
1141−
11421142 ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
11431143
11441144 #ifndef TCC_TARGET_PE
@@ -1149,12 +1149,21 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1); · 4 unmodified lines
11491149 PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
11501150
11511151 PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
1152−PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
1152+PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
11531153 PUB_FUNC void tcc_set_environment(TCCState *s);
11541154 #ifdef _WIN32
11551155 ST_FUNC char *normalize_slashes(char *path);
11561156 #endif
11571157
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+
11581167 /* ------------ tccpp.c ------------ */
11591168
11601169 ST_DATA struct BufferedFile *file;
@@ -1567,6 +1576,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); · 406 unmodified lines
15671576 #ifdef TCC_TARGET_X86_64
15681577 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
15691578 #endif
1579+PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
15701580 /* symbol properties stored in Elf32_Sym->st_other */
15711581 # define ST_PE_EXPORT 0x10
15721582 # define ST_PE_IMPORT 0x20
@@ -1595,6 +1605,16 @@ ST_FUNC void tcc_set_num_callers(int n); · 22 unmodified lines
15951605 ST_FUNC void tcc_run_free(TCCState *s1);
15961606 #endif
15971607
1608+/* ------------ tcctools.c ----------------- */
1609+#if 0 /* included in tcc.c */
1610+ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
1611+#ifdef TCC_TARGET_PE
1612+ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
1613+#endif
1614+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
1615+ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
1616+#endif
1617+
15981618 /********************************************************/
15991619 #undef ST_DATA
16001620 #ifdef ONE_SOURCE
tccasm.c+1−0
@@ -1005,6 +1005,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) · 1004 unmodified lines
10051005 /* default section is text */
10061006 cur_text_section = text_section;
10071007 ind = cur_text_section->data_offset;
1008+ nocode_wanted = 0;
10081009
10091010 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
10101011 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
962962 } else {
963963 fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
964964 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));
966966 }
967967 #endif
968968
@@ -1543,6 +1543,102 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) · 574 unmodified lines
15431543 return len == read(fd, buffer, len);
15441544 }
15451545
1546+/* ------------------------------------------------------------- */
1547+
1548+PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
1549+{
1550+ int l, i, n, n0, ret;
1551+ char *p;
1552+ int fd;
1553+
1554+ IMAGE_SECTION_HEADER ish;
1555+ IMAGE_EXPORT_DIRECTORY ied;
1556+ IMAGE_DOS_HEADER dh;
1557+ IMAGE_FILE_HEADER ih;
1558+ DWORD sig, ref, addr, ptr, namep;
1559+#ifdef TCC_TARGET_X86_64
1560+ IMAGE_OPTIONAL_HEADER64 oh;
1561+#else
1562+ IMAGE_OPTIONAL_HEADER32 oh;
1563+#endif
1564+ int pef_hdroffset, opt_hdroffset, sec_hdroffset;
1565+
1566+ n = n0 = 0;
1567+ p = NULL;
1568+ ret = -1;
1569+
1570+ fd = open(filename, O_RDONLY | O_BINARY);
1571+ if (fd < 0)
1572+ goto the_end_1;
1573+ ret = 1;
1574+
1575+ if (!read_mem(fd, 0, &dh, sizeof dh))
1576+ goto the_end;
1577+ if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
1578+ goto the_end;
1579+ if (sig != 0x00004550)
1580+ goto the_end;
1581+ pef_hdroffset = dh.e_lfanew + sizeof sig;
1582+ if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
1583+ goto the_end;
1584+ if (IMAGE_FILE_MACHINE != ih.Machine) {
1585+ if (ih.Machine == 0x014C)
1586+ ret = 32;
1587+ else if (ih.Machine == 0x8664)
1588+ ret = 64;
1589+ goto the_end;
1590+ }
1591+ opt_hdroffset = pef_hdroffset + sizeof ih;
1592+ sec_hdroffset = opt_hdroffset + sizeof oh;
1593+ if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
1594+ goto the_end;
1595+
1596+ if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
1597+ goto the_end_0;
1598+
1599+ addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
1600+ //printf("addr: %08x\n", addr);
1601+ for (i = 0; i < ih.NumberOfSections; ++i) {
1602+ if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
1603+ goto the_end;
1604+ //printf("vaddr: %08x\n", ish.VirtualAddress);
1605+ if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
1606+ goto found;
1607+ }
1608+ goto the_end_0;
1609+
1610+found:
1611+ ref = ish.VirtualAddress - ish.PointerToRawData;
1612+ if (!read_mem(fd, addr - ref, &ied, sizeof ied))
1613+ goto the_end;
1614+
1615+ namep = ied.AddressOfNames - ref;
1616+ for (i = 0; i < ied.NumberOfNames; ++i) {
1617+ if (!read_mem(fd, namep, &ptr, sizeof ptr))
1618+ goto the_end;
1619+ namep += sizeof ptr;
1620+ for (l = 0;;) {
1621+ if (n+1 >= n0)
1622+ p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
1623+ if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
1624+ tcc_free(p), p = NULL;
1625+ goto the_end;
1626+ }
1627+ if (p[n++] == 0)
1628+ break;
1629+ }
1630+ }
1631+ if (p)
1632+ p[n] = 0;
1633+the_end_0:
1634+ ret = 0;
1635+the_end:
1636+ close(fd);
1637+the_end_1:
1638+ *pp = p;
1639+ return ret;
1640+}
1641+
15461642 /* -------------------------------------------------------------
15471643 * This is for compiled windows resources in 'coff' format
15481644 * as generated by 'windres.exe -O coff ...'.
@@ -1660,20 +1756,20 @@ quit: · 111 unmodified lines
16601756 }
16611757
16621758 /* ------------------------------------------------------------- */
1663−#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
1664−#include "win32/tools/tiny_impdef.c"
1665−
1666−static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
1759+static int pe_load_dll(TCCState *s1, const char *filename)
16671760 {
16681761 char *p, *q;
1669− int index;
1670− p = get_export_names(fd);
1671− if (!p)
1762+ int index, ret;
1763+
1764+ ret = tcc_get_dllexports(filename, &p);
1765+ if (ret) {
16721766 return -1;
1673− index = add_dllref(s1, dllname);
1674− for (q = p; *q; q += 1 + strlen(q))
1675− pe_putimport(s1, index, q, 0);
1676− tcc_free(p);
1767+ } else if (p) {
1768+ index = add_dllref(s1, tcc_basename(filename));
1769+ for (q = p; *q; q += 1 + strlen(q))
1770+ pe_putimport(s1, index, q, 0);
1771+ tcc_free(p);
1772+ }
16771773 return 0;
16781774 }
16791775
@@ -1687,7 +1783,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) · 7 unmodified lines
16871783 else if (pe_load_res(s1, fd) == 0)
16881784 ret = 0;
16891785 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);
16911787 return ret;
16921788 }
16931789
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+
36+typedef struct {
37+ char ar_name[16];
38+ char ar_date[12];
39+ char ar_uid[6];
40+ char ar_gid[6];
41+ char ar_mode[8];
42+ char ar_size[10];
43+ char ar_fmag[2];
44+} ArHdr;
45+
46+static unsigned long le2belong(unsigned long ul) {
47+ return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
48+ ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
49+}
50+
51+/* Returns 1 if s contains any of the chars of list, else 0 */
52+static int contains_any(const char *s, const char *list) {
53+ const char *l;
54+ for (; *s; s++) {
55+ for (l = list; *l; l++) {
56+ if (*s == *l)
57+ return 1;
58+ }
59+ }
60+ return 0;
61+}
62+
63+static int ar_usage(int ret) {
64+ fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n");
65+ fprintf(stderr, "create library ([abdioptxN] not supported).\n");
66+ return ret;
67+}
68+
69+ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
70+{
71+ static ArHdr arhdr = {
72+ "/ ",
73+ " ",
74+ "0 ",
75+ "0 ",
76+ "0 ",
77+ " ",
78+ ARFMAG
79+ };
80+
81+ static ArHdr arhdro = {
82+ " ",
83+ " ",
84+ "0 ",
85+ "0 ",
86+ "0 ",
87+ " ",
88+ ARFMAG
89+ };
90+
91+ FILE *fi, *fh = NULL, *fo = NULL;
92+ ElfW(Ehdr) *ehdr;
93+ ElfW(Shdr) *shdr;
94+ ElfW(Sym) *sym;
95+ int i, fsize, i_lib, i_obj;
96+ char *buf, *shstr, *symtab = NULL, *strtab = NULL;
97+ int symtabsize = 0;//, strtabsize = 0;
98+ char *anames = NULL;
99+ int *afpos = NULL;
100+ int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
101+ char tfile[260], stmp[20];
102+ char *file, *name;
103+ int ret = 2;
104+ char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
105+ int verbose = 0;
106+
107+ i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
108+ for (i = 1; i < argc; i++) {
109+ const char *a = argv[i];
110+ if (*a == '-' && strstr(a, "."))
111+ ret = 1; // -x.y is always invalid (same as gnu ar)
112+ if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
113+ if (contains_any(a, ops_conflict))
114+ ret = 1;
115+ if (strstr(a, "v"))
116+ verbose = 1;
117+ } else { // lib or obj files: don't abort - keep validating all args.
118+ if (!i_lib) // first file is the lib
119+ i_lib = i;
120+ else if (!i_obj) // second file is the first obj
121+ i_obj = i;
122+ }
123+ }
124+
125+ if (!i_obj) // i_obj implies also i_lib. we require both.
126+ ret = 1;
127+
128+ if (ret == 1)
129+ return ar_usage(ret);
130+
131+ if ((fh = fopen(argv[i_lib], "wb")) == NULL)
132+ {
133+ fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]);
134+ goto the_end;
135+ }
136+
137+ sprintf(tfile, "%s.tmp", argv[i_lib]);
138+ if ((fo = fopen(tfile, "wb+")) == NULL)
139+ {
140+ fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile);
141+ goto the_end;
142+ }
143+
144+ funcmax = 250;
145+ afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
146+ memcpy(&arhdro.ar_mode, "100666", 6);
147+
148+ // i_obj = first input object file
149+ while (i_obj < argc)
150+ {
151+ if (*argv[i_obj] == '-') { // by now, all options start with '-'
152+ i_obj++;
153+ continue;
154+ }
155+ if ((fi = fopen(argv[i_obj], "rb")) == NULL) {
156+ fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]);
157+ goto the_end;
158+ }
159+ if (verbose)
160+ printf("a - %s\n", argv[i_obj]);
161+
162+ fseek(fi, 0, SEEK_END);
163+ fsize = ftell(fi);
164+ fseek(fi, 0, SEEK_SET);
165+ buf = tcc_malloc(fsize + 1);
166+ fread(buf, fsize, 1, fi);
167+ fclose(fi);
168+
169+ // elf header
170+ ehdr = (ElfW(Ehdr) *)buf;
171+ if (ehdr->e_ident[4] != ELFCLASSW)
172+ {
173+ fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]);
174+ goto the_end;
175+ }
176+
177+ shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
178+ shstr = (char *)(buf + shdr->sh_offset);
179+ for (i = 0; i < ehdr->e_shnum; i++)
180+ {
181+ shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
182+ if (!shdr->sh_offset)
183+ continue;
184+ if (shdr->sh_type == SHT_SYMTAB)
185+ {
186+ symtab = (char *)(buf + shdr->sh_offset);
187+ symtabsize = shdr->sh_size;
188+ }
189+ if (shdr->sh_type == SHT_STRTAB)
190+ {
191+ if (!strcmp(shstr + shdr->sh_name, ".strtab"))
192+ {
193+ strtab = (char *)(buf + shdr->sh_offset);
194+ //strtabsize = shdr->sh_size;
195+ }
196+ }
197+ }
198+
199+ if (symtab && symtabsize)
200+ {
201+ int nsym = symtabsize / sizeof(ElfW(Sym));
202+ //printf("symtab: info size shndx name\n");
203+ for (i = 1; i < nsym; i++)
204+ {
205+ sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
206+ if (sym->st_shndx &&
207+ (sym->st_info == 0x10
208+ || sym->st_info == 0x11
209+ || sym->st_info == 0x12
210+ )) {
211+ //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
212+ istrlen = strlen(strtab + sym->st_name)+1;
213+ anames = tcc_realloc(anames, strpos+istrlen);
214+ strcpy(anames + strpos, strtab + sym->st_name);
215+ strpos += istrlen;
216+ if (++funccnt >= funcmax) {
217+ funcmax += 250;
218+ afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
219+ }
220+ afpos[funccnt] = fpos;
221+ }
222+ }
223+ }
224+
225+ file = argv[i_obj];
226+ for (name = strchr(file, 0);
227+ name > file && name[-1] != '/' && name[-1] != '\\';
228+ --name);
229+ istrlen = strlen(name);
230+ if (istrlen >= sizeof(arhdro.ar_name))
231+ istrlen = sizeof(arhdro.ar_name) - 1;
232+ memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
233+ memcpy(arhdro.ar_name, name, istrlen);
234+ arhdro.ar_name[istrlen] = '/';
235+ sprintf(stmp, "%-10d", fsize);
236+ memcpy(&arhdro.ar_size, stmp, 10);
237+ fwrite(&arhdro, sizeof(arhdro), 1, fo);
238+ fwrite(buf, fsize, 1, fo);
239+ tcc_free(buf);
240+ i_obj++;
241+ fpos += (fsize + sizeof(arhdro));
242+ }
243+ hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
244+ fpos = 0;
245+ if ((hofs & 1)) // align
246+ hofs++, fpos = 1;
247+ // write header
248+ fwrite("!<arch>\n", 8, 1, fh);
249+ sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
250+ memcpy(&arhdr.ar_size, stmp, 10);
251+ fwrite(&arhdr, sizeof(arhdr), 1, fh);
252+ afpos[0] = le2belong(funccnt);
253+ for (i=1; i<=funccnt; i++)
254+ afpos[i] = le2belong(afpos[i] + hofs);
255+ fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
256+ fwrite(anames, strpos, 1, fh);
257+ if (fpos)
258+ fwrite("", 1, 1, fh);
259+ // write objects
260+ fseek(fo, 0, SEEK_END);
261+ fsize = ftell(fo);
262+ fseek(fo, 0, SEEK_SET);
263+ buf = tcc_malloc(fsize + 1);
264+ fread(buf, fsize, 1, fo);
265+ fwrite(buf, fsize, 1, fh);
266+ tcc_free(buf);
267+ ret = 0;
268+the_end:
269+ if (anames)
270+ tcc_free(anames);
271+ if (afpos)
272+ tcc_free(afpos);
273+ if (fh)
274+ fclose(fh);
275+ if (fo)
276+ fclose(fo), remove(tfile);
277+ return ret;
278+}
279+
280+/* -------------------------------------------------------------- */
281+/*
282+ * tiny_impdef creates an export definition file (.def) from a dll
283+ * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
284+ *
285+ * Copyright (c) 2005,2007 grischka
286+ *
287+ * This program is free software; you can redistribute it and/or modify
288+ * it under the terms of the GNU General Public License as published by
289+ * the Free Software Foundation; either version 2 of the License, or
290+ * (at your option) any later version.
291+ *
292+ * This program is distributed in the hope that it will be useful,
293+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
294+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
295+ * GNU General Public License for more details.
296+ *
297+ * You should have received a copy of the GNU General Public License
298+ * along with this program; if not, write to the Free Software
299+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
300+ */
301+
302+#ifdef TCC_TARGET_PE
303+
304+ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
305+{
306+ int ret, v, i;
307+ char infile[MAX_PATH];
308+ char outfile[MAX_PATH];
309+
310+ const char *file;
311+ char *p, *q;
312+ FILE *fp, *op;
313+
314+#ifdef _WIN32
315+ char path[MAX_PATH];
316+#endif
317+
318+ infile[0] = outfile[0] = 0;
319+ fp = op = NULL;
320+ ret = 1;
321+ p = NULL;
322+ v = 0;
323+
324+ for (i = 1; i < argc; ++i) {
325+ const char *a = argv[i];
326+ if ('-' == a[0]) {
327+ if (0 == strcmp(a, "-v")) {
328+ v = 1;
329+ } else if (0 == strcmp(a, "-o")) {
330+ if (++i == argc)
331+ goto usage;
332+ strcpy(outfile, argv[i]);
333+ } else
334+ goto usage;
335+ } else if (0 == infile[0])
336+ strcpy(infile, a);
337+ else
338+ goto usage;
339+ }
340+
341+ if (0 == infile[0]) {
342+usage:
343+ fprintf(stderr,
344+ "usage: tcc -impdef library.dll [-v] [-o outputfile]\n"
345+ "create export definition file (.def) from dll\n"
346+ );
347+ goto the_end;
348+ }
349+
350+ if (0 == outfile[0]) {
351+ strcpy(outfile, tcc_basename(infile));
352+ q = strrchr(outfile, '.');
353+ if (NULL == q)
354+ q = strchr(outfile, 0);
355+ strcpy(q, ".def");
356+ }
357+
358+ file = infile;
359+#ifdef _WIN32
360+ if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
361+ file = path;
362+#endif
363+ ret = tcc_get_dllexports(file, &p);
364+ if (ret || !p) {
365+ fprintf(stderr, "tcc: impdef: %s '%s'\n",
366+ ret == 32 ? "can't read symbols from 32bit" :
367+ ret == 64 ? "can't read symbols from 64bit" :
368+ ret == -1 ? "can't find file" :
369+ ret == 0 ? "no symbols found in" :
370+ "unknown file type", file);
371+ ret = 1;
372+ goto the_end;
373+ }
374+
375+ if (v)
376+ printf("-> %s\n", file);
377+
378+ op = fopen(outfile, "w");
379+ if (NULL == op) {
380+ fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
381+ goto the_end;
382+ }
383+
384+ fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file));
385+ for (q = p, i = 0; *q; ++i) {
386+ fprintf(op, "%s\n", q);
387+ q += strlen(q) + 1;
388+ }
389+
390+ if (v)
391+ printf("<- %s (%d symbol%s)\n", outfile, i, "s" + (i<2));
392+
393+ ret = 0;
394+
395+the_end:
396+ /* cannot free memory received from tcc_get_dllexports
397+ if it came from a dll */
398+ /* if (p)
399+ tcc_free(p); */
400+ if (fp)
401+ fclose(fp);
402+ if (op)
403+ fclose(op);
404+ return ret;
405+}
406+
407+#endif /* TCC_TARGET_PE */
408+
409+/* -------------------------------------------------------------- */
410+/*
411+ * TCC - Tiny C Compiler
412+ *
413+ * Copyright (c) 2001-2004 Fabrice Bellard
414+ *
415+ * This library is free software; you can redistribute it and/or
416+ * modify it under the terms of the GNU Lesser General Public
417+ * License as published by the Free Software Foundation; either
418+ * version 2 of the License, or (at your option) any later version.
419+ *
420+ * This library is distributed in the hope that it will be useful,
421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423+ * Lesser General Public License for more details.
424+ *
425+ * You should have received a copy of the GNU Lesser General Public
426+ * License along with this library; if not, write to the Free Software
427+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
428+ */
429+
430+/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
431+
432+#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
433+
434+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option)
435+{
436+ tcc_error("-m%d not implemented.", option);
437+}
438+
439+#else
440+#ifdef _WIN32
441+#include <process.h>
442+
443+static char *str_replace(const char *str, const char *p, const char *r)
444+{
445+ const char *s, *s0;
446+ char *d, *d0;
447+ int sl, pl, rl;
448+
449+ sl = strlen(str);
450+ pl = strlen(p);
451+ rl = strlen(r);
452+ for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
453+ for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
454+ if (d) {
455+ memcpy(d, s0, sl = s - s0), d += sl;
456+ memcpy(d, r, rl), d += rl;
457+ } else
458+ sl += rl - pl;
459+ }
460+ if (d) {
461+ strcpy(d, s0);
462+ return d0;
463+ }
464+ }
465+}
466+
467+static int execvp_win32(const char *prog, char **argv)
468+{
469+ int ret; char **p;
470+ /* replace all " by \" */
471+ for (p = argv; *p; ++p)
472+ if (strchr(*p, '"'))
473+ *p = str_replace(*p, "\"", "\\\"");
474+ ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
475+ if (-1 == ret)
476+ return ret;
477+ _cwait(&ret, ret, WAIT_CHILD);
478+ exit(ret);
479+}
480+#define execvp execvp_win32
481+#endif /* _WIN32 */
482+
483+ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
484+{
485+ char program[4096];
486+ char *a0 = argv[0];
487+ int prefix = tcc_basename(a0) - a0;
488+
489+ snprintf(program, sizeof program,
490+ "%.*s%s"
491+#ifdef TCC_TARGET_PE
492+ "-win32"
493+#endif
494+ "-tcc"
495+#ifdef _WIN32
496+ ".exe"
497+#endif
498+ , prefix, a0, target == 64 ? "x86_64" : "i386");
499+
500+ if (strcmp(a0, program))
501+ execvp(argv[0] = program, argv);
502+ tcc_error("could not run '%s'", program);
503+}
504+
505+#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
506+/* -------------------------------------------------------------- */
507+/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
508+
509+#ifdef _WIN32
510+int _CRT_glob = 1;
511+#ifndef _CRT_glob
512+int _dowildcard = 1;
513+#endif
514+#endif
515+
516+/* -------------------------------------------------------------- */
517+/* generate xxx.d file */
518+
519+ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
520+{
521+ FILE *depout;
522+ char buf[1024];
523+ int i;
524+
525+ if (!filename) {
526+ /* compute filename automatically: dir/file.o -> dir/file.d */
527+ snprintf(buf, sizeof buf, "%.*s.d",
528+ (int)(tcc_fileextension(target) - target), target);
529+ filename = buf;
530+ }
531+
532+ if (s->verbose)
533+ printf("<- %s\n", filename);
534+
535+ /* XXX return err codes instead of error() ? */
536+ depout = fopen(filename, "w");
537+ if (!depout)
538+ tcc_error("could not open '%s'", filename);
539+
540+ fprintf(depout, "%s: \\\n", target);
541+ for (i=0; i<s->nb_target_deps; ++i)
542+ fprintf(depout, " %s \\\n", s->target_deps[i]);
543+ fprintf(depout, "\n");
544+ fclose(depout);
545+}
546+
547+/* -------------------------------------------------------------- */
tests/tcctest.c+1−1
@@ -3431,7 +3431,7 @@ void builtin_test(void) · 3430 unmodified lines
34313431 i = sizeof (__builtin_choose_expr (0, ll, s));
34323432 printf("bce: %d\n", i);
34333433
3434− printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
3434+ //printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
34353435 }
34363436
34373437 #ifndef _WIN32
win32/build-tcc.bat+13−18
@@ -5,10 +5,6 @@ · 4 unmodified lines
55 @echo off
66 setlocal
77
8−set VSCOMNTOOLS=%VS150COMNTOOLS%
9−if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
10−if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
11−if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
128 set CC=gcc -Os -s
139 set /p VERSION= < ..\VERSION
1410 set INST=
@@ -70,10 +66,17 @@ goto :a1 · 55 unmodified lines
7066 if not (%1)==() goto :usage
7167
7268 if not "%CC%"=="@call :cl" goto :p1
69+set VSCOMNTOOLS=%VS150COMNTOOLS%
70+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
71+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
72+if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
7373 if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
7474 if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
7575 if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
76+if %CLVARS%_==_ goto :p1
77+if exist %CLVARS% call %CLVARS%
7678 :p1
79+
7780 if not %T%_==_ goto :p2
7881 set T=32
7982 if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
@@ -97,9 +100,6 @@ set PX=i386-win32 · 17 unmodified lines
97100
98101 @echo on
99102
100−@if %CLVARS%_==_ goto :config.h
101−call %CLVARS%
102−
103103 :config.h
104104 echo>..\config.h #define TCC_VERSION "%VERSION%"
105105 echo>> ..\config.h #ifdef TCC_TARGET_X86_64
@@ -108,7 +108,7 @@ echo>> ..\config.h #else · 2 unmodified lines
108108 echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
109109 echo>> ..\config.h #endif
110110
111−@del /q *tcc.exe tiny_*.exe *tcc.dll
111+for %%f in (*tcc.exe *tcc.dll) do @del %%f
112112
113113 :compiler
114114 %CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL
@@ -116,10 +116,6 @@ echo>> ..\config.h #endif · 1 unmodified line
116116 %CC% -o tcc.exe ..\tcc.c libtcc.dll %D%
117117 %CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE
118118
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−
123119 @if (%TCC_FILES%)==(no) goto :files-done
124120
125121 if not exist libtcc mkdir libtcc
@@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64 · 3 unmodified lines
129125 copy>nul ..\include\*.h include
130126 copy>nul ..\tcclib.h include
131127 copy>nul ..\libtcc.h libtcc
132−tiny_impdef libtcc.dll -o libtcc\libtcc.def
133128 copy>nul ..\tests\libtcc_test.c examples
134129 copy>nul tcc-win32.txt doc
135130
136−copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
137−%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX%
131+.\tcc -impdef libtcc.dll -o libtcc\libtcc.def
132+@if errorlevel 1 goto :the_end
138133
139134 :libtcc1.a
140135 @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
149144 .\tcc -m32 %D32% -w -c ../lib/bcheck.c
150145 .\tcc -m32 %D32% -c ../lib/alloca86.S
151146 .\tcc -m32 %D32% -c ../lib/alloca86-bt.S
152−tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
147+.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
153148 @if errorlevel 1 goto :the_end
154149 .\tcc -m64 %D64% -c ../lib/libtcc1.c
155150 .\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
162157 .\tcc -m64 %D64% -w -c ../lib/bcheck.c
163158 .\tcc -m64 %D64% -c ../lib/alloca86_64.S
164159 .\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
165−tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
160+.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
166161 @if errorlevel 1 goto :the_end
167162
168163 :tcc-doc.html
@@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html · 3 unmodified lines
172167 :doc-done
173168
174169 :files-done
175−@del /q *.o *.def *-m??.exe
170+for %%f in (*.o *.def) do @del %%f
176171
177172 :copy-install
178173 @if (%INST%)==() goto :the_end
win32/tcc-win32.txt+10−12
@@ -39,7 +39,7 @@ · 38 unmodified lines
3939 For the 'Hello DLL' example type
4040
4141 tcc -shared dll.c
42− tiny_impdef dll.dll (optional)
42+ tcc -impdef dll.dll (optional)
4343 tcc hello_dll.c dll.def
4444
4545
@@ -66,10 +66,10 @@ · 20 unmodified lines
6666 To link with Windows system DLLs, TCC uses import definition
6767 files (.def) instead of libraries.
6868
69− The included 'tiny_impdef' program may be used to make additional
70− .def files for any DLL. For example:
69+ The now built-in 'tiny_impdef' program may be used to make
70+ additional .def files for any DLL. For example
7171
72− tiny_impdef.exe opengl32.dll
72+ tcc -impdef [-v] opengl32.dll [-o opengl32.def]
7373
7474 Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
7575 the TCC commandline to link a program that uses opengl32.dll.
@@ -98,10 +98,10 @@ · 22 unmodified lines
9898
9999 Tiny Libmaker:
100100 --------------
101− The included tiny_libmaker tool by Timovj Lahde can be used as
101+ The now built-in tiny_libmaker tool by Timovj Lahde can be used as
102102 'ar' replacement to make a library from several object files:
103103
104− tiny_libmaker [rcs] library objectfiles ...
104+ tcc -ar [rcsv] library objectfiles ...
105105
106106
107107 Compilation from source:
@@ -143,14 +143,12 @@ · 35 unmodified lines
143143 ------------
144144 - On the object file level, currently TCC supports only the ELF format,
145145 not COFF as used by MinGW and MSVC. It is not possible to exchange
146− object files or libraries between TCC and these compilers. However
147− libraries for TCC from objects by TCC can be made using tiny_libmaker
148− or MinGW's ar.
146+ object files or libraries between TCC and these compilers.
149147
150− - No leading underscore is generated in the ELF symbols.
151−
152− - Bounds checking (option -b) is not supported on 64-bit OS.
148+ However libraries for TCC from objects by TCC can be made using
149+ tcc -ar lib.a files.o ,,,
153150
151+ - No leading underscore is generated in the ELF symbols.
154152
155153 Documentation and License:
156154 --------------------------
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−
31−static char *get_export_names(int fd);
32−#define tcc_free free
33−#define tcc_realloc realloc
34−
35−/* extract the basename of a file */
36−static char *file_basename(const char *name)
37−{
38− const char *p = strchr(name, 0);
39− while (p > name
40− && p[-1] != '/'
41− && p[-1] != '\\'
42− )
43− --p;
44− return (char*)p;
45−}
46−
47−int main(int argc, char **argv)
48−{
49− int ret, v, i;
50− char infile[MAX_PATH];
51− char outfile[MAX_PATH];
52−
53− static const char *ext[] = { ".dll", ".exe", NULL };
54− const char *file, **pp;
55− char path[MAX_PATH], *p, *q;
56− FILE *fp, *op;
57−
58− infile[0] = 0;
59− outfile[0] = 0;
60− fp = op = NULL;
61− v = 0;
62− ret = 1;
63− p = NULL;
64−
65− for (i = 1; i < argc; ++i) {
66− const char *a = argv[i];
67− if ('-' == a[0]) {
68− if (0 == strcmp(a, "-v")) {
69− v = 1;
70− } else if (0 == strcmp(a, "-o")) {
71− if (++i == argc)
72− goto usage;
73− strcpy(outfile, argv[i]);
74− } else
75− goto usage;
76− } else if (0 == infile[0])
77− strcpy(infile, a);
78− else
79− goto usage;
80− }
81−
82− if (0 == infile[0]) {
83−usage:
84− fprintf(stderr,
85− "tiny_impdef: create export definition file (.def) from a dll\n"
86− "Usage: tiny_impdef library.dll [-o outputfile]\n"
87− );
88− goto the_end;
89− }
90−
91− if (0 == outfile[0])
92− {
93− strcpy(outfile, file_basename(infile));
94− q = strrchr(outfile, '.');
95− if (NULL == q)
96− q = strchr(outfile, 0);
97− strcpy(q, ".def");
98− }
99−
100− file = infile;
101−
102−#ifdef _WIN32
103− pp = ext;
104− do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
105− file = path;
106− break;
107− } while (*pp++);
108−#endif
109−
110− fp = fopen(file, "rb");
111− if (NULL == fp) {
112− fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
113− goto the_end;
114− }
115− if (v)
116− printf("--> %s\n", file);
117−
118− p = get_export_names(fileno(fp));
119− if (NULL == p) {
120− fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
121− goto the_end;
122− }
123−
124− op = fopen(outfile, "w");
125− if (NULL == op) {
126− fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
127− goto the_end;
128− }
129−
130− fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
131− for (q = p, i = 0; *q; ++i) {
132− fprintf(op, "%s\n", q);
133− q += strlen(q) + 1;
134− }
135−
136− if (v) {
137− printf("<-- %s\n", outfile);
138− printf("%d symbol(s) found\n", i);
139− }
140−
141− ret = 0;
142−
143−the_end:
144− if (p)
145− free(p);
146− if (fp)
147− fclose(fp);
148− if (op)
149− fclose(op);
150− return ret;
151−}
152−
153−int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
154−{
155− lseek(fd, offset, SEEK_SET);
156− return len == read(fd, buffer, len);
157−}
158−
159−/* -------------------------------------------------------------- */
160−
161−#if defined TCC_TARGET_X86_64
162−# define IMAGE_FILE_MACHINE 0x8664
163−#elif defined TCC_TARGET_ARM
164−# define IMAGE_FILE_MACHINE 0x01C0
165−#elif 1 /* defined TCC_TARGET_I386 */
166−# define IMAGE_FILE_MACHINE 0x014C
167−#endif
168−
169−/* -------------------------------------------------------------- */
170−#endif
171−
172−static char *get_export_names(int fd)
173−{
174− int l, i, n, n0;
175− char *p;
176−
177− IMAGE_SECTION_HEADER ish;
178− IMAGE_EXPORT_DIRECTORY ied;
179− IMAGE_DOS_HEADER dh;
180− IMAGE_FILE_HEADER ih;
181− DWORD sig, ref, addr, ptr, namep;
182−#ifdef TCC_TARGET_X86_64
183− IMAGE_OPTIONAL_HEADER64 oh;
184−#else
185− IMAGE_OPTIONAL_HEADER32 oh;
186−#endif
187− int pef_hdroffset, opt_hdroffset, sec_hdroffset;
188−
189− n = n0 = 0;
190− p = NULL;
191−
192− if (!read_mem(fd, 0, &dh, sizeof dh))
193− goto the_end;
194− if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
195− goto the_end;
196− if (sig != 0x00004550)
197− goto the_end;
198− pef_hdroffset = dh.e_lfanew + sizeof sig;
199− if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
200− goto the_end;
201− if (IMAGE_FILE_MACHINE != ih.Machine)
202− goto the_end;
203− opt_hdroffset = pef_hdroffset + sizeof ih;
204− sec_hdroffset = opt_hdroffset + sizeof oh;
205− if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
206− goto the_end;
207−
208− if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
209− goto the_end;
210−
211− addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
212− //printf("addr: %08x\n", addr);
213− for (i = 0; i < ih.NumberOfSections; ++i) {
214− if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
215− goto the_end;
216− //printf("vaddr: %08x\n", ish.VirtualAddress);
217− if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
218− goto found;
219− }
220− goto the_end;
221−
222−found:
223− ref = ish.VirtualAddress - ish.PointerToRawData;
224− if (!read_mem(fd, addr - ref, &ied, sizeof ied))
225− goto the_end;
226−
227− namep = ied.AddressOfNames - ref;
228− for (i = 0; i < ied.NumberOfNames; ++i) {
229− if (!read_mem(fd, namep, &ptr, sizeof ptr))
230− goto the_end;
231− namep += sizeof ptr;
232− for (l = 0;;) {
233− if (n+1 >= n0)
234− p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
235− if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
236− tcc_free(p), p = NULL;
237− goto the_end;
238− }
239− if (p[n++] == 0)
240− break;
241− }
242− }
243− if (p)
244− p[n] = 0;
245−the_end:
246− return p;
247−}
248−
249−/* -------------------------------------------------------------- */
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−
39−typedef struct ArHdr {
40− char ar_name[16];
41− char ar_date[12];
42− char ar_uid[6];
43− char ar_gid[6];
44− char ar_mode[8];
45− char ar_size[10];
46− char ar_fmag[2];
47−} ArHdr;
48−
49−unsigned long le2belong(unsigned long ul) {
50− return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
51− ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
52−}
53−
54−ArHdr arhdr = {
55− "/ ",
56− " ",
57− "0 ",
58− "0 ",
59− "0 ",
60− " ",
61− ARFMAG
62− };
63−
64−ArHdr arhdro = {
65− " ",
66− " ",
67− "0 ",
68− "0 ",
69− "0 ",
70− " ",
71− ARFMAG
72− };
73−
74−/* Returns 1 if s contains any of the chars of list, else 0 */
75−int contains_any(const char *s, const char *list) {
76− const char *l;
77− for (; *s; s++) {
78− for (l = list; *l; l++) {
79− if (*s == *l)
80− return 1;
81− }
82− }
83− return 0;
84−}
85−
86−int usage(int ret) {
87− fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n");
88− fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n");
89− return ret;
90−}
91−
92−int main(int argc, char **argv)
93−{
94− FILE *fi, *fh = NULL, *fo = NULL;
95− ElfW(Ehdr) *ehdr;
96− ElfW(Shdr) *shdr;
97− ElfW(Sym) *sym;
98− int i, fsize, i_lib, i_obj;
99− char *buf, *shstr, *symtab = NULL, *strtab = NULL;
100− int symtabsize = 0;//, strtabsize = 0;
101− char *anames = NULL;
102− int *afpos = NULL;
103− int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
104− char tfile[260], stmp[20];
105− char *file, *name;
106− int ret = 2;
107− char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
108− int verbose = 0;
109−
110− i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
111− for (i = 1; i < argc; i++) {
112− const char *a = argv[i];
113− if (*a == '-' && strstr(a, "."))
114− return usage(1); // -x.y is always invalid (same as gnu ar)
115− if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
116− if (contains_any(a, ops_conflict))
117− return usage(1);
118− if (strstr(a, "v"))
119− verbose = 1;
120− } else { // lib or obj files: don't abort - keep validating all args.
121− if (!i_lib) // first file is the lib
122− i_lib = i;
123− else if (!i_obj) // second file is the first obj
124− i_obj = i;
125− }
126− }
127− if (!i_obj) // i_obj implies also i_lib. we require both.
128− return usage(1);
129−
130− if ((fh = fopen(argv[i_lib], "wb")) == NULL)
131− {
132− fprintf(stderr, "Can't open file %s \n", argv[i_lib]);
133− goto the_end;
134− }
135−
136− sprintf(tfile, "%s.tmp", argv[i_lib]);
137− if ((fo = fopen(tfile, "wb+")) == NULL)
138− {
139− fprintf(stderr, "Can't create temporary file %s\n", tfile);
140− goto the_end;
141− }
142−
143− funcmax = 250;
144− afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
145− memcpy(&arhdro.ar_mode, "100666", 6);
146−
147− // i_obj = first input object file
148− while (i_obj < argc)
149− {
150− if (*argv[i_obj] == '-') { // by now, all options start with '-'
151− i_obj++;
152− continue;
153− }
154− if (verbose)
155− printf("a - %s\n", argv[i_obj]);
156−
157− if ((fi = fopen(argv[i_obj], "rb")) == NULL)
158− {
159− fprintf(stderr, "Can't open file %s \n", argv[i_obj]);
160− goto the_end;
161− }
162− fseek(fi, 0, SEEK_END);
163− fsize = ftell(fi);
164− fseek(fi, 0, SEEK_SET);
165− buf = malloc(fsize + 1);
166− fread(buf, fsize, 1, fi);
167− fclose(fi);
168−
169− // elf header
170− ehdr = (ElfW(Ehdr) *)buf;
171− if (ehdr->e_ident[4] != ELFCLASSW)
172− {
173− fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]);
174− goto the_end;
175− }
176−
177− shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
178− shstr = (char *)(buf + shdr->sh_offset);
179− for (i = 0; i < ehdr->e_shnum; i++)
180− {
181− shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
182− if (!shdr->sh_offset)
183− continue;
184− if (shdr->sh_type == SHT_SYMTAB)
185− {
186− symtab = (char *)(buf + shdr->sh_offset);
187− symtabsize = shdr->sh_size;
188− }
189− if (shdr->sh_type == SHT_STRTAB)
190− {
191− if (!strcmp(shstr + shdr->sh_name, ".strtab"))
192− {
193− strtab = (char *)(buf + shdr->sh_offset);
194− //strtabsize = shdr->sh_size;
195− }
196− }
197− }
198−
199− if (symtab && symtabsize)
200− {
201− int nsym = symtabsize / sizeof(ElfW(Sym));
202− //printf("symtab: info size shndx name\n");
203− for (i = 1; i < nsym; i++)
204− {
205− sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
206− if (sym->st_shndx &&
207− (sym->st_info == 0x10
208− || sym->st_info == 0x11
209− || sym->st_info == 0x12
210− )) {
211− //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
212− istrlen = strlen(strtab + sym->st_name)+1;
213− anames = realloc(anames, strpos+istrlen);
214− strcpy(anames + strpos, strtab + sym->st_name);
215− strpos += istrlen;
216− if (++funccnt >= funcmax) {
217− funcmax += 250;
218− afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
219− }
220− afpos[funccnt] = fpos;
221− }
222− }
223− }
224−
225− file = argv[i_obj];
226− for (name = strchr(file, 0);
227− name > file && name[-1] != '/' && name[-1] != '\\';
228− --name);
229− istrlen = strlen(name);
230− if (istrlen >= sizeof(arhdro.ar_name))
231− istrlen = sizeof(arhdro.ar_name) - 1;
232− memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
233− memcpy(arhdro.ar_name, name, istrlen);
234− arhdro.ar_name[istrlen] = '/';
235− sprintf(stmp, "%-10d", fsize);
236− memcpy(&arhdro.ar_size, stmp, 10);
237− fwrite(&arhdro, sizeof(arhdro), 1, fo);
238− fwrite(buf, fsize, 1, fo);
239− free(buf);
240− i_obj++;
241− fpos += (fsize + sizeof(arhdro));
242− }
243− hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
244− fpos = 0;
245− if ((hofs & 1)) // align
246− hofs++, fpos = 1;
247− // write header
248− fwrite("!<arch>\n", 8, 1, fh);
249− sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
250− memcpy(&arhdr.ar_size, stmp, 10);
251− fwrite(&arhdr, sizeof(arhdr), 1, fh);
252− afpos[0] = le2belong(funccnt);
253− for (i=1; i<=funccnt; i++)
254− afpos[i] = le2belong(afpos[i] + hofs);
255− fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
256− fwrite(anames, strpos, 1, fh);
257− if (fpos)
258− fwrite("", 1, 1, fh);
259− // write objects
260− fseek(fo, 0, SEEK_END);
261− fsize = ftell(fo);
262− fseek(fo, 0, SEEK_SET);
263− buf = malloc(fsize + 1);
264− fread(buf, fsize, 1, fo);
265− fwrite(buf, fsize, 1, fh);
266− free(buf);
267− ret = 0;
268−the_end:
269− if (anames)
270− free(anames);
271− if (afpos)
272− free(afpos);
273− if (fh)
274− fclose(fh);
275− if (fo)
276− fclose(fo), remove(tfile);
277− return ret;
278−}

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