From dda95e9b0b30771369efe66b4a47e94cf0ca7dc0 Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 1 Aug 2021 20:04:46 +0200 Subject: [PATCH] WAIT/POST_SEM(): generalize interface (and more) Currently used only with 'tcc_compile_sem' to protect tcc_compile(), but can be used with other semaphores Also fix deadlock when tcc_enter_state() is called recursively for the same state, for example with tcc_warning() from #pragma comment(option,"...") Also: - libtcc.c: error1(): use cstr_[v]printf() - tcc.h: set TCC_USING_DOUBLE_FOR_LDOUBLE for macho-arm64 (rather than for macho-X86_64) - tcc.h: define TCC_TARGET_MACHO on __APPLE__ by default - tcc.h: cleanup TCCState, move DEFASM token stuff to tcctok.h - tccgen.c: more static - Makefile/tcc.c: review githash - tccpe/tcctools: use read() instead of fgets() in pe_load_def() (all files opened by tcc for reading are now read via 'int fd') - configure/win32: don't preset CONFIG_TCCDIR (to allow to override it) - tcc.c -bench: do not include output/run-time --- Makefile | 10 +-- configure | 4 +- i386-tok.h | 76 ++++++++++++++++++ libtcc.c | 179 +++++++++++++++++++---------------------- tcc.c | 17 ++-- tcc.h | 210 ++++++++++++++++++------------------------------- tccasm.c | 17 ++++ tccgen.c | 34 +++----- tccmacho.c | 2 +- tccpe.c | 92 ++++++++++++---------- tccpp.c | 13 ++- tcctok.h | 16 +++- tcctools.c | 6 +- tests/libtcc_test_mt.c | 9 ++- 14 files changed, 362 insertions(+), 323 deletions(-) diff --git a/Makefile b/Makefile index 5ed0be4b..fca50dd4 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,7 @@ all: $(PROGS) $(TCCLIBS) $(TCCDOCS) # cross compiler targets to build TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67 -TCC_X += riscv64 +TCC_X += riscv64 arm64-osx # TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi # cross libtcc1.a targets to build @@ -222,10 +222,9 @@ $(TCC_FILES) : DEFINES += -DONE_SOURCE=0 $(X)tccpp.o : $(TCCDEFS_H) endif -TCC_GIT_HASH=$(shell git rev-parse > /dev/null 2>&1 && git rev-parse --short HEAD || echo no) -ifneq ($(TCC_GIT_HASH),no) -MODIFIED = $(shell git diff | grep -q +++ && echo "modified ") -$(X)tcc.o : DEFINES += -DTCC_GIT_HASH="\"$(MODIFIED)$(TCC_GIT_HASH)\"" +GITHASH := $(shell git rev-parse >/dev/null 2>&1 && git rev-parse --short HEAD || echo no) +ifneq ($(GITHASH),no) +DEF_GITHASH := -DTCC_GITHASH="\"$(GITHASH)$(shell git diff --quiet || echo '-mod')\"" endif ifeq ($(CONFIG_debug),yes) @@ -247,6 +246,7 @@ $(X)%.o : %.c $(LIBTCC_INC) # additional dependencies $(X)tcc.o : tcctools.c +$(X)tcc.o : DEFINES += $(DEF_GITHASH) # Host Tiny C Compiler tcc$(EXESUF): tcc.o $(LIBTCC) diff --git a/configure b/configure index 1618570c..2a003981 100755 --- a/configure +++ b/configure @@ -238,7 +238,7 @@ if test "$mingw32" = "yes" ; then source_path="." fi test -z "$prefix" && prefix="C:/Program Files/tcc" - test -z "$tccdir" && tccdir="${prefix}" + test -z "$tccdir" && tccdir="${prefix}" && tccdir_auto="yes" test -z "$bindir" && bindir="${tccdir}" test -z "$docdir" && docdir="${tccdir}/doc" test -z "$libdir" && libdir="${tccdir}/libtcc" @@ -483,7 +483,7 @@ print_mak() { echo "/* Automatically generated by configure - do not modify */" > $TMPH print_inc CONFIG_SYSROOT "$sysroot" -print_inc CONFIG_TCCDIR "$tccdir" +test "$tccdir_auto" = "yes" || print_inc CONFIG_TCCDIR "$tccdir" print_mak CONFIG_USR_INCLUDE "$tcc_usrinclude" print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths" print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths" diff --git a/i386-tok.h b/i386-tok.h index 8c25af09..e3ef2c75 100644 --- a/i386-tok.h +++ b/i386-tok.h @@ -1,6 +1,82 @@ /* ------------------------------------------------------------------ */ /* WARNING: relative order of tokens is important. */ +#define DEF_BWL(x) \ + DEF(TOK_ASM_ ## x ## b, #x "b") \ + DEF(TOK_ASM_ ## x ## w, #x "w") \ + DEF(TOK_ASM_ ## x ## l, #x "l") \ + DEF(TOK_ASM_ ## x, #x) +#define DEF_WL(x) \ + DEF(TOK_ASM_ ## x ## w, #x "w") \ + DEF(TOK_ASM_ ## x ## l, #x "l") \ + DEF(TOK_ASM_ ## x, #x) +#ifdef TCC_TARGET_X86_64 +# define DEF_BWLQ(x) \ + DEF(TOK_ASM_ ## x ## b, #x "b") \ + DEF(TOK_ASM_ ## x ## w, #x "w") \ + DEF(TOK_ASM_ ## x ## l, #x "l") \ + DEF(TOK_ASM_ ## x ## q, #x "q") \ + DEF(TOK_ASM_ ## x, #x) +# define DEF_WLQ(x) \ + DEF(TOK_ASM_ ## x ## w, #x "w") \ + DEF(TOK_ASM_ ## x ## l, #x "l") \ + DEF(TOK_ASM_ ## x ## q, #x "q") \ + DEF(TOK_ASM_ ## x, #x) +# define DEF_BWLX DEF_BWLQ +# define DEF_WLX DEF_WLQ +/* number of sizes + 1 */ +# define NBWLX 5 +#else +# define DEF_BWLX DEF_BWL +# define DEF_WLX DEF_WL +/* number of sizes + 1 */ +# define NBWLX 4 +#endif + +#define DEF_FP1(x) \ + DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \ + DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \ + DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \ + DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s") + +#define DEF_FP(x) \ + DEF(TOK_ASM_ ## f ## x, "f" #x ) \ + DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \ + DEF_FP1(x) + +#define DEF_ASMTEST(x,suffix) \ + DEF_ASM(x ## o ## suffix) \ + DEF_ASM(x ## no ## suffix) \ + DEF_ASM(x ## b ## suffix) \ + DEF_ASM(x ## c ## suffix) \ + DEF_ASM(x ## nae ## suffix) \ + DEF_ASM(x ## nb ## suffix) \ + DEF_ASM(x ## nc ## suffix) \ + DEF_ASM(x ## ae ## suffix) \ + DEF_ASM(x ## e ## suffix) \ + DEF_ASM(x ## z ## suffix) \ + DEF_ASM(x ## ne ## suffix) \ + DEF_ASM(x ## nz ## suffix) \ + DEF_ASM(x ## be ## suffix) \ + DEF_ASM(x ## na ## suffix) \ + DEF_ASM(x ## nbe ## suffix) \ + DEF_ASM(x ## a ## suffix) \ + DEF_ASM(x ## s ## suffix) \ + DEF_ASM(x ## ns ## suffix) \ + DEF_ASM(x ## p ## suffix) \ + DEF_ASM(x ## pe ## suffix) \ + DEF_ASM(x ## np ## suffix) \ + DEF_ASM(x ## po ## suffix) \ + DEF_ASM(x ## l ## suffix) \ + DEF_ASM(x ## nge ## suffix) \ + DEF_ASM(x ## nl ## suffix) \ + DEF_ASM(x ## ge ## suffix) \ + DEF_ASM(x ## le ## suffix) \ + DEF_ASM(x ## ng ## suffix) \ + DEF_ASM(x ## nle ## suffix) \ + DEF_ASM(x ## g ## suffix) + +/* ------------------------------------------------------------------ */ /* register */ DEF_ASM(al) DEF_ASM(cl) diff --git a/libtcc.c b/libtcc.c index e1976816..949a7ced 100644 --- a/libtcc.c +++ b/libtcc.c @@ -21,6 +21,7 @@ #if !defined ONE_SOURCE || ONE_SOURCE #include "tccpp.c" #include "tccgen.c" +#include "tccasm.c" #include "tccelf.c" #include "tccrun.c" #ifdef TCC_TARGET_I386 @@ -50,9 +51,6 @@ #else #error unknown target #endif -#ifdef CONFIG_TCC_ASM -#include "tccasm.c" -#endif #ifdef TCC_TARGET_PE #include "tccpe.c" #endif @@ -68,6 +66,7 @@ /* XXX: get rid of this ASAP (or maybe not) */ ST_DATA struct TCCState *tcc_state; +TCC_SEM(static tcc_compile_sem); #ifdef MEM_DEBUG static int nb_states; @@ -84,19 +83,23 @@ ST_FUNC char *normalize_slashes(char *path) return path; } +/* NULL if this is tcc.exe, HINSTANCE if this is libtcc.dll */ static HMODULE tcc_module; +#ifndef CONFIG_TCCDIR /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ -static void tcc_set_lib_path_w32(TCCState *s) +static inline char *config_tccdir_w32(char *path) { - char path[1024], *p; - GetModuleFileNameA(tcc_module, path, sizeof path); + char *p; + GetModuleFileName(tcc_module, path, MAX_PATH); p = tcc_basename(normalize_slashes(strlwr(path))); if (p > path) --p; *p = 0; - tcc_set_lib_path(s, path); + return path; } +#define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH)) +#endif #ifdef TCC_TARGET_PE static void tcc_add_systemdir(TCCState *s) @@ -118,47 +121,60 @@ BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) #endif /********************************************************/ -#if CONFIG_TCC_SEMLOCK == 0 -#define WAIT_SEM() -#define POST_SEM() -#elif defined _WIN32 -static int tcc_sem_init; -static CRITICAL_SECTION tcc_cr; -static void wait_sem(void) -{ - if (!tcc_sem_init) - InitializeCriticalSection(&tcc_cr), tcc_sem_init = 1; - EnterCriticalSection(&tcc_cr); -} -#define WAIT_SEM() wait_sem() -#define POST_SEM() LeaveCriticalSection(&tcc_cr); +#if CONFIG_TCC_SEMLOCK +#if defined _WIN32 +ST_FUNC void wait_sem(TCCSem *p) +{ + if (!p->init) + InitializeCriticalSection(&p->cr), p->init = 1; + EnterCriticalSection(&p->cr); +} +ST_FUNC void post_sem(TCCSem *p) +{ + LeaveCriticalSection(&p->cr); +} #elif defined __APPLE__ /* Half-compatible MacOS doesn't have non-shared (process local) semaphores. Use the dispatch framework for lightweight locks. */ -#include -static int tcc_sem_init; -static dispatch_semaphore_t tcc_sem; -static void wait_sem(void) +ST_FUNC void wait_sem(TCCSem *p) { - if (!tcc_sem_init) - tcc_sem = dispatch_semaphore_create(1), tcc_sem_init = 1; - dispatch_semaphore_wait(tcc_sem, DISPATCH_TIME_FOREVER); + if (!p->init) + p->sem = dispatch_semaphore_create(1), p->init = 1; + dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER); +} +ST_FUNC void post_sem(TCCSem *p) +{ + dispatch_semaphore_signal(p->sem); } -#define WAIT_SEM() wait_sem() -#define POST_SEM() dispatch_semaphore_signal(tcc_sem) #else -#include -static int tcc_sem_init; -static sem_t tcc_sem; -static void wait_sem(void) +ST_FUNC void wait_sem(TCCSem *p) +{ + if (!p->init) + sem_init(&p->sem, 0, 1), p->init = 1; + while (sem_wait(&p->sem) < 0 && errno == EINTR); +} +ST_FUNC void post_sem(TCCSem *p) { - if (!tcc_sem_init) - sem_init(&tcc_sem, 0, 1), tcc_sem_init = 1; - while (sem_wait (&tcc_sem) < 0 && errno == EINTR); + sem_post(&p->sem); } -#define WAIT_SEM() wait_sem() -#define POST_SEM() sem_post(&tcc_sem) #endif +#endif + +PUB_FUNC void tcc_enter_state(TCCState *s1) +{ + if (s1->error_set_jmp_enabled) + return; + WAIT_SEM(&tcc_compile_sem); + tcc_state = s1; +} + +PUB_FUNC void tcc_exit_state(TCCState *s1) +{ + if (s1->error_set_jmp_enabled) + return; + tcc_state = NULL; + POST_SEM(&tcc_compile_sem); +} /********************************************************/ /* copy a string and truncate it. */ @@ -494,52 +510,29 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char * } /********************************************************/ +/* warning / error */ -static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) -{ - int len; - len = strlen(buf); - vsnprintf(buf + len, buf_size - len, fmt, ap); -} - -static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - strcat_vprintf(buf, buf_size, fmt, ap); - va_end(ap); -} +/* warn_... option bits */ +#define WARN_ON 1 /* warning is on (-Woption) */ +#define WARN_ERR 2 /* warning is an error (-Werror=option) */ +#define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */ -PUB_FUNC void tcc_enter_state(TCCState *s1) -{ - WAIT_SEM(); - tcc_state = s1; -} - -PUB_FUNC void tcc_exit_state(void) -{ - tcc_state = NULL; - POST_SEM(); -} - -#define ERROR_WARN 0 -#define ERROR_NOABORT 1 -#define ERROR_ERROR 2 +/* error1() modes */ +enum { ERROR_WARN, ERROR_NOABORT, ERROR_ERROR }; static void error1(int mode, const char *fmt, va_list ap) { - char buf[2048]; BufferedFile **pf, *f; TCCState *s1 = tcc_state; + CString cs; + + cstr_new(&cs); - buf[0] = '\0'; if (s1 == NULL) /* can happen only if called from tcc_malloc(): 'out of memory' */ goto no_file; - if (!s1->error_set_jmp_enabled) - /* tcc_state just was set by tcc_enter_state() */ - tcc_exit_state(); + tcc_exit_state(s1); if (mode == ERROR_WARN) { if (s1->warn_error) @@ -567,33 +560,30 @@ static void error1(int mode, const char *fmt, va_list ap) } if (f) { for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) - strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", + cstr_printf(&cs, "In file included from %s:%d:\n", (*pf)->filename, (*pf)->line_num); - strcat_printf(buf, sizeof(buf), "%s:%d: ", + cstr_printf(&cs, "%s:%d: ", f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL)); } else if (s1->current_filename) { - strcat_printf(buf, sizeof(buf), "%s: ", s1->current_filename); + cstr_printf(&cs, "%s: ", s1->current_filename); } no_file: - if (0 == buf[0]) - strcat_printf(buf, sizeof(buf), "tcc: "); - if (mode == ERROR_WARN) - strcat_printf(buf, sizeof(buf), "warning: "); - else - strcat_printf(buf, sizeof(buf), "error: "); - strcat_vprintf(buf, sizeof(buf), fmt, ap); + if (0 == cs.size) + cstr_printf(&cs, "tcc: "); + cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: "); + cstr_vprintf(&cs, fmt, ap); if (!s1 || !s1->error_func) { /* default case: stderr */ if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) - /* print a newline during tcc -E */ - printf("\n"), fflush(stdout); + printf("\n"); /* print a newline during tcc -E */ fflush(stdout); /* flush -v output */ - fprintf(stderr, "%s\n", buf); + fprintf(stderr, "%s\n", (char*)cs.data); fflush(stderr); /* print error/warning now (win32) */ } else { - s1->error_func(s1->error_opaque, buf); + s1->error_func(s1->error_opaque, (char*)cs.data); } + cstr_free(&cs); if (s1) { if (mode != ERROR_WARN) s1->nb_errors++; @@ -718,9 +708,9 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) variables, which may or may not have advantages */ tcc_enter_state(s1); + s1->error_set_jmp_enabled = 1; if (setjmp(s1->error_jmp_buf) == 0) { - s1->error_set_jmp_enabled = 1; s1->nb_errors = 0; if (fd == -1) { @@ -738,19 +728,16 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) if (s1->output_type == TCC_OUTPUT_PREPROCESS) { tcc_preprocess(s1); } else if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP)) { -#ifdef CONFIG_TCC_ASM tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP)); -#else - tcc_error_noabort("asm not supported"); -#endif } else { tccgen_compile(s1); } } - s1->error_set_jmp_enabled = 0; tccgen_finish(s1); preprocess_end(s1); - tcc_exit_state(); + + s1->error_set_jmp_enabled = 0; + tcc_exit_state(s1); tccelf_end_file(s1); return s1->nb_errors != 0 ? -1 : 0; @@ -821,11 +808,7 @@ LIBTCCAPI TCCState *tcc_new(void) tccelf_new(s); -#ifdef _WIN32 - tcc_set_lib_path_w32(s); -#else tcc_set_lib_path(s, CONFIG_TCCDIR); -#endif return s; } diff --git a/tcc.c b/tcc.c index 893cdac8..481eb27c 100644 --- a/tcc.c +++ b/tcc.c @@ -154,10 +154,8 @@ static const char help2[] = static const char version[] = "tcc version "TCC_VERSION -#ifdef TCC_GIT_HASH - " - " TCC_GIT_HASH -#else - " - unknown hash" +#ifdef TCC_GITHASH + " "TCC_GITHASH #endif " (" #ifdef TCC_TARGET_I386 @@ -276,7 +274,7 @@ int main(int argc0, char **argv0) { TCCState *s, *s1; int ret, opt, n = 0, t = 0, done; - unsigned start_time = 0; + unsigned start_time = 0, end_time = 0; const char *first_file; int argc; char **argv; FILE *ppfp = stdout; @@ -372,6 +370,9 @@ redo: done = ret || ++n >= s->nb_files; } while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r)); + if (s->do_bench) + end_time = getclock_ms(); + if (s->run_test) { t = 0; } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { @@ -391,13 +392,15 @@ redo: } } - if (s->do_bench && done && !(t | ret)) - tcc_print_stats(s, getclock_ms() - start_time); + if (done && 0 == t && 0 == ret && s->do_bench) + tcc_print_stats(s, end_time - start_time); + tcc_delete(s); if (!done) goto redo; /* compile more files with -c */ if (t) goto redo; /* run more tests with -dt -run */ + if (ppfp && ppfp != stdout) fclose(ppfp); return ret; diff --git a/tcc.h b/tcc.h index 96615696..ef69ef59 100644 --- a/tcc.h +++ b/tcc.h @@ -55,6 +55,7 @@ extern long double strtold (const char *__nptr, char **__endptr); # include # include /* open, close etc. */ # include /* getcwd */ +# include /* alloca */ # ifdef __GNUC__ # include # endif @@ -91,6 +92,9 @@ extern long double strtold (const char *__nptr, char **__endptr); # define __x86_64__ 1 # endif # endif +# ifndef va_copy +# define va_copy(a,b) a = b +# endif # undef CONFIG_TCC_STATIC #endif @@ -124,7 +128,6 @@ extern long double strtold (const char *__nptr, char **__endptr); # define PRINTF_LIKE(x,y) __attribute__ ((format (printf, (x), (y)))) #endif - #ifdef _WIN32 # define IS_DIRSEP(c) (c == '/' || c == '\\') # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) @@ -179,6 +182,9 @@ extern long double strtold (const char *__nptr, char **__endptr); # ifdef _WIN32 # define TCC_TARGET_PE 1 # endif +# ifdef __APPLE__ +# define TCC_TARGET_MACHO 1 +# endif #endif /* only native compiler supports -run */ @@ -226,7 +232,7 @@ extern long double strtold (const char *__nptr, char **__endptr); /* No ten-byte long doubles on window and macos except in cross-compilers made by a mingw-GCC */ #if defined TCC_TARGET_PE \ - || (defined TCC_TARGET_MACHO && defined TCC_TARGET_X86_64) \ + || (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64) \ || (defined _WIN32 && !defined __GNUC__) # define TCC_USING_DOUBLE_FOR_LDOUBLE 1 #endif @@ -236,7 +242,7 @@ extern long double strtold (const char *__nptr, char **__endptr); #ifndef CONFIG_SYSROOT # define CONFIG_SYSROOT "" #endif -#ifndef CONFIG_TCCDIR +#if !defined CONFIG_TCCDIR && !defined _WIN32 # define CONFIG_TCCDIR "/usr/local/lib/tcc" #endif #ifndef CONFIG_LDDIR @@ -751,15 +757,6 @@ struct TCCState { unsigned char enable_new_dtags; /* -Wl,--enable-new-dtags */ unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */ - char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ - char *soname; /* as specified on the command line (-soname) */ - char *rpath; /* as specified on the command line (-Wl,-rpath=) */ - - /* output type, see TCC_OUTPUT_XXX */ - int output_type; - /* output format, see TCC_OUTPUT_FORMAT_xxx */ - int output_format; - /* C language options */ unsigned char char_is_unsigned; unsigned char leading_underscore; @@ -776,10 +773,14 @@ struct TCCState { unsigned char warn_implicit_function_declaration; unsigned char warn_discarded_qualifiers; #define WARN_ON 1 /* warning is on (-Woption) */ - #define WARN_ERR 2 /* warning is an error (-Werror=option) */ - #define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */ unsigned char warn_num; /* temp var for tcc_warning_c() */ + unsigned char option_r; /* option -r */ + unsigned char do_bench; /* option -bench */ + unsigned char just_deps; /* option -M */ + unsigned char gen_deps; /* option -MD */ + unsigned char include_sys_deps; /* option -MD */ + /* compile with debug symbol (and use them if error during execution) */ unsigned char do_debug; unsigned char do_backtrace; @@ -789,30 +790,41 @@ struct TCCState { #endif unsigned char test_coverage; /* generate test coverage code */ + /* use GNU C extensions */ + unsigned char gnu_ext; + /* use TinyCC extensions */ + unsigned char tcc_ext; + + unsigned char dflag; /* -dX value */ + unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */ + +#ifdef TCC_TARGET_X86_64 + unsigned char nosse; /* For -mno-sse support. */ +#endif #ifdef TCC_TARGET_ARM - enum float_abi float_abi; /* float ABI of the generated code*/ + unsigned char float_abi; /* float ABI of the generated code*/ #endif - int run_test; /* nth test to run with -dt -run */ - addr_t text_addr; /* address of text section */ unsigned char has_text_addr; - + addr_t text_addr; /* address of text section */ unsigned section_align; /* section alignment */ +#ifdef TCC_TARGET_I386 + int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ +#endif - /* use GNU C extensions */ - unsigned char gnu_ext; - /* use TinyCC extensions */ - unsigned char tcc_ext; + char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ + char *soname; /* as specified on the command line (-soname) */ + char *rpath; /* as specified on the command line (-Wl,-rpath=) */ char *init_symbol; /* symbols to call at load-time (not used currently) */ char *fini_symbol; /* symbols to call at unload-time (not used currently) */ -#ifdef TCC_TARGET_I386 - int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ -#endif -#ifdef TCC_TARGET_X86_64 - unsigned char nosse; /* For -mno-sse support. */ -#endif + /* output type, see TCC_OUTPUT_XXX */ + int output_type; + /* output format, see TCC_OUTPUT_FORMAT_xxx */ + int output_format; + /* nth test to run with -dt -run */ + int run_test; /* array of all loaded dlls (including those referenced by loaded dlls) */ DLLReference **loaded_dlls; @@ -847,13 +859,6 @@ struct TCCState { /* output file for preprocessing (-E) */ FILE *ppfp; - enum { - LINE_MACRO_OUTPUT_FORMAT_GCC, - LINE_MACRO_OUTPUT_FORMAT_NONE, - LINE_MACRO_OUTPUT_FORMAT_STD, - LINE_MACRO_OUTPUT_FORMAT_P10 = 11 - } Pflag; /* -P switch */ - char dflag; /* -dX value */ /* for -MD/-MF: collected dependencies for this compilation */ char **target_deps; @@ -922,11 +927,11 @@ struct TCCState { int nb_sym_attrs; /* ptr to next reloc entry reused */ ElfW_Rel *qrel; -# define qrel s1->qrel + #define qrel s1->qrel #ifdef TCC_TARGET_RISCV64 struct pcrel_hi { addr_t addr, val; } last_hi; -# define last_hi s1->last_hi + #define last_hi s1->last_hi #endif #ifdef TCC_TARGET_PE @@ -963,8 +968,6 @@ struct TCCState { int rt_num_callers; #endif - int fd, cc; /* used by tcc_load_ldscript */ - /* benchmark info */ int total_idents; int total_lines; @@ -974,7 +977,10 @@ struct TCCState { /* option -dnum (for general development purposes) */ int g_debug; - /* for warnings/errors for object files*/ + /* used by tcc_load_ldscript */ + int fd, cc; + + /* for warnings/errors for object files */ const char *current_filename; /* used by main and tcc_parse_args only */ @@ -982,11 +988,6 @@ struct TCCState { int nb_files; /* number thereof */ int nb_libraries; /* number of libs thereof */ char *outfile; /* output filename */ - unsigned char option_r; /* option -r */ - unsigned char do_bench; /* option -bench */ - int just_deps; /* option -M */ - int gen_deps; /* option -MD */ - int include_sys_deps; /* option -MD */ char *deps_outfile; /* option -MF */ int argc; char **argv; @@ -1161,91 +1162,6 @@ struct filespec { /* all identifiers and strings have token above that */ #define TOK_IDENT 256 -#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x) -#define TOK_ASM_int TOK_INT -#define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x) -#define TOK_ASMDIR_FIRST TOK_ASMDIR_byte -#define TOK_ASMDIR_LAST TOK_ASMDIR_section - -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -/* only used for i386 asm opcodes definitions */ -#define DEF_BWL(x) \ - DEF(TOK_ASM_ ## x ## b, #x "b") \ - DEF(TOK_ASM_ ## x ## w, #x "w") \ - DEF(TOK_ASM_ ## x ## l, #x "l") \ - DEF(TOK_ASM_ ## x, #x) -#define DEF_WL(x) \ - DEF(TOK_ASM_ ## x ## w, #x "w") \ - DEF(TOK_ASM_ ## x ## l, #x "l") \ - DEF(TOK_ASM_ ## x, #x) -#ifdef TCC_TARGET_X86_64 -# define DEF_BWLQ(x) \ - DEF(TOK_ASM_ ## x ## b, #x "b") \ - DEF(TOK_ASM_ ## x ## w, #x "w") \ - DEF(TOK_ASM_ ## x ## l, #x "l") \ - DEF(TOK_ASM_ ## x ## q, #x "q") \ - DEF(TOK_ASM_ ## x, #x) -# define DEF_WLQ(x) \ - DEF(TOK_ASM_ ## x ## w, #x "w") \ - DEF(TOK_ASM_ ## x ## l, #x "l") \ - DEF(TOK_ASM_ ## x ## q, #x "q") \ - DEF(TOK_ASM_ ## x, #x) -# define DEF_BWLX DEF_BWLQ -# define DEF_WLX DEF_WLQ -/* number of sizes + 1 */ -# define NBWLX 5 -#else -# define DEF_BWLX DEF_BWL -# define DEF_WLX DEF_WL -/* number of sizes + 1 */ -# define NBWLX 4 -#endif - -#define DEF_FP1(x) \ - DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \ - DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \ - DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \ - DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s") - -#define DEF_FP(x) \ - DEF(TOK_ASM_ ## f ## x, "f" #x ) \ - DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \ - DEF_FP1(x) - -#define DEF_ASMTEST(x,suffix) \ - DEF_ASM(x ## o ## suffix) \ - DEF_ASM(x ## no ## suffix) \ - DEF_ASM(x ## b ## suffix) \ - DEF_ASM(x ## c ## suffix) \ - DEF_ASM(x ## nae ## suffix) \ - DEF_ASM(x ## nb ## suffix) \ - DEF_ASM(x ## nc ## suffix) \ - DEF_ASM(x ## ae ## suffix) \ - DEF_ASM(x ## e ## suffix) \ - DEF_ASM(x ## z ## suffix) \ - DEF_ASM(x ## ne ## suffix) \ - DEF_ASM(x ## nz ## suffix) \ - DEF_ASM(x ## be ## suffix) \ - DEF_ASM(x ## na ## suffix) \ - DEF_ASM(x ## nbe ## suffix) \ - DEF_ASM(x ## a ## suffix) \ - DEF_ASM(x ## s ## suffix) \ - DEF_ASM(x ## ns ## suffix) \ - DEF_ASM(x ## p ## suffix) \ - DEF_ASM(x ## pe ## suffix) \ - DEF_ASM(x ## np ## suffix) \ - DEF_ASM(x ## po ## suffix) \ - DEF_ASM(x ## l ## suffix) \ - DEF_ASM(x ## nge ## suffix) \ - DEF_ASM(x ## nl ## suffix) \ - DEF_ASM(x ## ge ## suffix) \ - DEF_ASM(x ## le ## suffix) \ - DEF_ASM(x ## ng ## suffix) \ - DEF_ASM(x ## nle ## suffix) \ - DEF_ASM(x ## g ## suffix) - -#endif /* defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 */ - enum tcc_token { TOK_LAST = TOK_IDENT - 1 #define DEF(id, str) ,id @@ -1306,6 +1222,7 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch); ST_FUNC void cstr_new(CString *cstr); ST_FUNC void cstr_free(CString *cstr); ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3); +ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); ST_FUNC void cstr_reset(CString *cstr); ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen); @@ -1397,6 +1314,13 @@ ST_DATA TokenSym **table_ident; #define IS_ID 2 #define IS_NUM 4 +enum line_macro_output_format { + LINE_MACRO_OUTPUT_FORMAT_GCC, + LINE_MACRO_OUTPUT_FORMAT_NONE, + LINE_MACRO_OUTPUT_FORMAT_STD, + LINE_MACRO_OUTPUT_FORMAT_P10 = 11 +}; + ST_FUNC TokenSym *tok_alloc(const char *str, int len); ST_FUNC int tok_alloc_const(const char *str); ST_FUNC const char *get_tok_str(int v, CValue *cv); @@ -1770,12 +1694,12 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd); /* ------------ tccasm.c ------------ */ ST_FUNC void asm_instr(void); ST_FUNC void asm_global_instr(void); +ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess); #ifdef CONFIG_TCC_ASM ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); ST_FUNC Sym* get_asm_sym(int name, Sym *csym); ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); ST_FUNC int asm_int_expr(TCCState *s1); -ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess); /* ------------ i386-asm.c ------------ */ ST_FUNC void gen_expr32(ExprValue *pe); #ifdef TCC_TARGET_X86_64 @@ -1845,6 +1769,28 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) #endif /********************************************************/ +#if CONFIG_TCC_SEMLOCK +#if defined _WIN32 +typedef struct { int init; CRITICAL_SECTION cr; } TCCSem; +#elif defined __APPLE__ +#include +typedef struct { int init; dispatch_semaphore_t sem; } TCCSem; +#else +#include +typedef struct { int init; sem_t sem; } TCCSem; +#endif +ST_FUNC void wait_sem(TCCSem *p); +ST_FUNC void post_sem(TCCSem *p); +#define TCC_SEM(s) TCCSem s +#define WAIT_SEM wait_sem +#define POST_SEM post_sem +#else +#define TCC_SEM(s) +#define WAIT_SEM(p) +#define POST_SEM(p) +#endif + +/********************************************************/ #undef ST_DATA #if ONE_SOURCE #define ST_DATA static @@ -1875,7 +1821,7 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) #define total_bytes TCC_STATE_VAR(total_bytes) PUB_FUNC void tcc_enter_state(TCCState *s1); -PUB_FUNC void tcc_exit_state(void); +PUB_FUNC void tcc_exit_state(TCCState *s1); /* conditional warning depending on switch */ #define tcc_warning_c(sw) TCC_SET_STATE((\ diff --git a/tccasm.c b/tccasm.c index aabb66fe..2dd8921b 100644 --- a/tccasm.c +++ b/tccasm.c @@ -1298,4 +1298,21 @@ ST_FUNC void asm_global_instr(void) cstr_free(&astr); nocode_wanted = saved_nocode_wanted; } + +/********************************************************/ +#else +ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) +{ + tcc_error("asm not supported"); +} + +ST_FUNC void asm_instr(void) +{ + tcc_error("inline asm() not supported"); +} + +ST_FUNC void asm_global_instr(void) +{ + tcc_error("inline asm() not supported"); +} #endif /* CONFIG_TCC_ASM */ diff --git a/tccgen.c b/tccgen.c index a2efee6a..e0b5fd6f 100644 --- a/tccgen.c +++ b/tccgen.c @@ -97,7 +97,7 @@ static CString initstr; #define VT_PTRDIFF_T (VT_LONG | VT_LLONG) #endif -ST_DATA struct switch_t { +static struct switch_t { struct case_t { int64_t v1, v2; int sym; @@ -111,12 +111,12 @@ ST_DATA struct switch_t { #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 /*list of temporary local variables on the stack in current function. */ -ST_DATA struct temp_local_variable { +static struct temp_local_variable { int location; //offset on stack. Svalue.c.i short size; short align; } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER]; -short nb_temp_local_vars; +static int nb_temp_local_vars; static struct scope { struct scope *prev; @@ -132,6 +132,11 @@ typedef struct { Sym *flex_array_ref; } init_params; +#if 1 +#define precedence_parser +static void init_prec(void); +#endif + /********************************************************/ /* stab debug support */ @@ -215,23 +220,6 @@ static struct { } tcov_data; /********************************************************/ -#if 1 -#define precedence_parser -static void init_prec(void); -#endif -/********************************************************/ -#ifndef CONFIG_TCC_ASM -ST_FUNC void asm_instr(void) -{ - tcc_error("inline asm() not supported"); -} -ST_FUNC void asm_global_instr(void) -{ - tcc_error("inline asm() not supported"); -} -#endif - -/* ------------------------------------------------------------------------- */ static void gen_cast(CType *type); static void gen_cast_s(int t); static inline CType *pointed_type(CType *type); @@ -7247,7 +7235,7 @@ static void vla_leave(struct scope *o) /* ------------------------------------------------------------------------- */ /* local scopes */ -void new_scope(struct scope *o) +static void new_scope(struct scope *o) { /* copy and link previous scope */ *o = *cur_scope; @@ -7264,7 +7252,7 @@ void new_scope(struct scope *o) tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind); } -void prev_scope(struct scope *o, int is_expr) +static void prev_scope(struct scope *o, int is_expr) { vla_leave(o->prev); @@ -7292,7 +7280,7 @@ void prev_scope(struct scope *o, int is_expr) } /* leave a scope via break/continue(/goto) */ -void leave_scope(struct scope *o) +static void leave_scope(struct scope *o) { if (!o) return; diff --git a/tccmacho.c b/tccmacho.c index 083fb1a3..57c62c32 100644 --- a/tccmacho.c +++ b/tccmacho.c @@ -517,7 +517,7 @@ static void create_symtab(TCCState *s1, struct macho *mo) } tcc_enter_state(s1); /* qsort needs global state */ qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp); - tcc_exit_state(); + tcc_exit_state(s1); mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym)); mo->e2msym[0] = -1; for (sym_index = 1; sym_index < sym_end; ++sym_index) { diff --git a/tccpe.c b/tccpe.c index df57f71c..07501a96 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1543,8 +1543,6 @@ static int pe_add_dllref(TCCState *s1, const char *dllname) return s1->nb_loaded_dlls; } -/* ------------------------------------------------------------- */ - static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) { lseek(fd, offset, SEEK_SET); @@ -1553,11 +1551,10 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) /* ------------------------------------------------------------- */ -PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) +static int get_dllexports(int fd, char **pp) { int l, i, n, n0, ret; char *p; - int fd; IMAGE_SECTION_HEADER ish; IMAGE_EXPORT_DIRECTORY ied; @@ -1569,11 +1566,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) n = n0 = 0; p = NULL; - ret = -1; - - fd = open(filename, O_RDONLY | O_BINARY); - if (fd < 0) - goto the_end_1; ret = 1; if (!read_mem(fd, 0, &dh, sizeof dh)) goto the_end; @@ -1640,8 +1632,6 @@ found: the_end_0: ret = 0; the_end: - close(fd); -the_end_1: *pp = p; return ret; } @@ -1694,47 +1684,53 @@ quit: static char *trimfront(char *p) { - while (*p && (unsigned char)*p <= ' ') + while ((unsigned char)*p <= ' ' && *p && *p != '\n') ++p; return p; } +/* static char *trimback(char *a, char *e) { while (e > a && (unsigned char)e[-1] <= ' ') --e; *e = 0;; return a; +}*/ + +static char *get_token(char **s, char *f) +{ + char *p = *s, *e; + p = e = trimfront(p); + while ((unsigned char)*e > ' ') + ++e; + *s = trimfront(e); + *f = **s; *e = 0; + return p; } -/* ------------------------------------------------------------- */ static int pe_load_def(TCCState *s1, int fd) { int state = 0, ret = -1, dllindex = 0, ord; - char line[400], dllname[80], *p, *x; - FILE *fp; - - fp = fdopen(dup(fd), "rb"); - while (fgets(line, sizeof line, fp)) - { - p = trimfront(trimback(line, strchr(line, 0))); - if (0 == *p || ';' == *p) - continue; + char dllname[80], *buf, *line, *p, *x, next; + buf = tcc_load_text(fd); + for (line = buf;; ++line) { + p = get_token(&line, &next); + if (!(*p && *p != ';')) + goto skip; switch (state) { case 0: - if (0 != strnicmp(p, "LIBRARY", 7)) + if (0 != stricmp(p, "LIBRARY") || next == '\n') goto quit; - pstrcpy(dllname, sizeof dllname, trimfront(p+7)); + pstrcpy(dllname, sizeof dllname, get_token(&line, &next)); ++state; - continue; - + break; case 1: if (0 != stricmp(p, "EXPORTS")) goto quit; ++state; - continue; - + break; case 2: dllindex = pe_add_dllref(s1, dllname); ++state; @@ -1742,33 +1738,34 @@ static int pe_load_def(TCCState *s1, int fd) default: /* get ordinal and will store in sym->st_value */ ord = 0; - x = strchr(p, ' '); - if (x) { - *x = 0, x = strrchr(x + 1, '@'); - if (x) { - char *d; - ord = (int)strtol(x + 1, &d, 10); - if (*d) - ord = 0; - } + if (next == '@') { + x = get_token(&line, &next); + ord = (int)strtol(x + 1, &x, 10); } + //printf("token %s ; %s : %d\n", dllname, p, ord); pe_putimport(s1, dllindex, p, ord); - continue; + break; } +skip: + while ((unsigned char)next > ' ') + get_token(&line, &next); + if (next != '\n') + break; } ret = 0; quit: - fclose(fp); + tcc_free(buf); return ret; } /* ------------------------------------------------------------- */ -static int pe_load_dll(TCCState *s1, const char *filename) + +static int pe_load_dll(TCCState *s1, int fd, const char *filename) { char *p, *q; int index, ret; - ret = tcc_get_dllexports(filename, &p); + ret = get_dllexports(fd, &p); if (ret) { return -1; } else if (p) { @@ -1780,7 +1777,6 @@ static int pe_load_dll(TCCState *s1, const char *filename) return 0; } -/* ------------------------------------------------------------- */ ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename) { int ret = -1; @@ -1790,7 +1786,17 @@ ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename) else if (pe_load_res(s1, fd) == 0) ret = 0; else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2)) - ret = pe_load_dll(s1, filename); + ret = pe_load_dll(s1, fd, filename); + return ret; +} + +PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) +{ + int ret, fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; + ret = get_dllexports(fd, pp); + close(fd); return ret; } diff --git a/tccpp.c b/tccpp.c index 4a423879..897ef151 100644 --- a/tccpp.c +++ b/tccpp.c @@ -404,7 +404,7 @@ ST_FUNC void cstr_reset(CString *cstr) cstr->size = 0; } -ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) +ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) { va_list v; int len, size = 80; @@ -413,7 +413,7 @@ ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) if (size > cstr->size_allocated) cstr_realloc(cstr, size); size = cstr->size_allocated - cstr->size; - va_start(v, fmt); + va_copy(v, ap); len = vsnprintf((char*)cstr->data + cstr->size, size, fmt, v); va_end(v); if (len > 0 && len < size) @@ -424,6 +424,15 @@ ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) return len; } +ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) +{ + va_list ap; int len; + va_start(ap, fmt); + len = cstr_vprintf(cstr, fmt, ap); + va_end(ap); + return len; +} + /* XXX: unicode ? */ static void add_char(CString *cstr, int c) { diff --git a/tcctok.h b/tcctok.h index e5bc5fbe..d4c1ef5c 100644 --- a/tcctok.h +++ b/tcctok.h @@ -1,3 +1,4 @@ +/*********************************************************************/ /* keywords */ DEF(TOK_INT, "int") DEF(TOK_VOID, "void") @@ -343,8 +344,17 @@ DEF(TOK_longjmp, "longjmp") #endif + +/*********************************************************************/ /* Tiny Assembler */ - DEF_ASMDIR(byte) /* must be first directive */ +#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x) +#define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x) +#define TOK_ASM_int TOK_INT + +#define TOK_ASMDIR_FIRST TOK_ASMDIR_byte +#define TOK_ASMDIR_LAST TOK_ASMDIR_section + + DEF_ASMDIR(byte) /* must be first directive */ DEF_ASMDIR(word) DEF_ASMDIR(align) DEF_ASMDIR(balign) @@ -383,14 +393,16 @@ DEF_ASMDIR(short) DEF_ASMDIR(long) DEF_ASMDIR(int) - DEF_ASMDIR(section) /* must be last directive */ + DEF_ASMDIR(section) /* must be last directive */ #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 #include "i386-tok.h" #endif + #if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 #include "arm-tok.h" #endif + #if defined TCC_TARGET_RISCV64 #include "riscv64-tok.h" #endif diff --git a/tcctools.c b/tcctools.c index 7d074c7b..cf174965 100644 --- a/tcctools.c +++ b/tcctools.c @@ -385,10 +385,8 @@ usage: ret = 0; the_end: - /* cannot free memory received from tcc_get_dllexports - if it came from a dll */ - /* if (p) - tcc_free(p); */ + if (p) + tcc_free(p); if (fp) fclose(fp); if (op) diff --git a/tests/libtcc_test_mt.c b/tests/libtcc_test_mt.c index 47d493d8..6892bfef 100644 --- a/tests/libtcc_test_mt.c +++ b/tests/libtcc_test_mt.c @@ -220,9 +220,10 @@ TF_TYPE(thread_test_complex, vn) void time_tcc(int n, const char *src) { TCCState *s; - int ret; - while (--n >= 0) { + int ret, i = 0; + while (i++ < n) { s = new_state(1); + printf(" %d", i), fflush(stdout); ret = tcc_add_file(s, src); tcc_delete(s); if (ret < 0) @@ -277,10 +278,10 @@ int main(int argc, char **argv) printf("\n (%u ms)\n", getclock_ms() - t); #endif #if 1 - printf("compiling tcc.c 10 times\n"), fflush(stdout); + printf("compiling tcc.c 10 times\n "), fflush(stdout); t = getclock_ms(); time_tcc(10, argv[1]); - printf(" (%u ms)\n", getclock_ms() - t), fflush(stdout); + printf("\n (%u ms)\n", getclock_ms() - t), fflush(stdout); #endif return 0; } -- 2.11.4.GIT