diff options
author | Thomas Preud'homme <robotux@celest.fr> | 2018-02-21 23:16:20 +0000 |
---|---|---|
committer | Thomas Preud'homme <robotux@celest.fr> | 2018-02-21 23:16:20 +0000 |
commit | e2ccf3981d78dfeb390d22c74625b60310100abb (patch) | |
tree | fc30b3b3fe20cc005634818512dab3514acf8ef4 /libtcc.c | |
parent | 3f2e65a51523fbb98a44b71c29ae3a3fcc13854b (diff) |
New upstream version 0.9.27
Diffstat (limited to 'libtcc.c')
-rw-r--r-- | libtcc.c | 800 |
1 files changed, 397 insertions, 403 deletions
@@ -32,9 +32,11 @@ ST_DATA int tcc_ext = 1; /* XXX: get rid of this ASAP */ ST_DATA struct TCCState *tcc_state; +static int nb_states; + /********************************************************/ -#ifdef ONE_SOURCE +#if ONE_SOURCE #include "tccpp.c" #include "tccgen.c" #include "tccelf.c" @@ -42,10 +44,12 @@ ST_DATA struct TCCState *tcc_state; #ifdef TCC_TARGET_I386 #include "i386-gen.c" #include "i386-link.c" +#include "i386-asm.c" #endif #ifdef TCC_TARGET_ARM #include "arm-gen.c" #include "arm-link.c" +#include "arm-asm.c" #endif #ifdef TCC_TARGET_ARM64 #include "arm64-gen.c" @@ -54,19 +58,15 @@ ST_DATA struct TCCState *tcc_state; #ifdef TCC_TARGET_C67 #include "c67-gen.c" #include "c67-link.c" +#include "tcccoff.c" #endif #ifdef TCC_TARGET_X86_64 #include "x86_64-gen.c" #include "x86_64-link.c" +#include "i386-asm.c" #endif #ifdef CONFIG_TCC_ASM #include "tccasm.c" -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -#include "i386-asm.c" -#endif -#endif -#ifdef TCC_TARGET_COFF -#include "tcccoff.c" #endif #ifdef TCC_TARGET_PE #include "tccpe.c" @@ -104,10 +104,8 @@ static void tcc_set_lib_path_w32(TCCState *s) char path[1024], *p; GetModuleFileNameA(tcc_module, path, sizeof path); p = tcc_basename(normalize_slashes(strlwr(path))); - if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) - p -= 5; - else if (p > path) - p--; + if (p > path) + --p; *p = 0; tcc_set_lib_path(s, path); } @@ -133,7 +131,7 @@ BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) /********************************************************/ /* copy a string and truncate it. */ -PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) +ST_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) { char *q, *q_end; int c; @@ -153,7 +151,7 @@ PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) } /* strcat and truncate. */ -PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s) +ST_FUNC char *pstrcat(char *buf, int buf_size, const char *s) { int len; len = strlen(buf); @@ -162,7 +160,7 @@ PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s) return buf; } -PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num) +ST_FUNC char *pstrncpy(char *out, const char *in, size_t num) { memcpy(out, in, num); out[num] = '\0'; @@ -237,7 +235,7 @@ PUB_FUNC char *tcc_strdup(const char *str) return ptr; } -PUB_FUNC void tcc_memstats(int bench) +PUB_FUNC void tcc_memcheck(void) { } @@ -245,94 +243,96 @@ PUB_FUNC void tcc_memstats(int bench) #define MEM_DEBUG_MAGIC1 0xFEEDDEB1 #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 -#define MEM_DEBUG_FILE_LEN 15 +#define MEM_DEBUG_MAGIC3 0xFEEDDEB3 +#define MEM_DEBUG_FILE_LEN 40 +#define MEM_DEBUG_CHECK3(header) \ + ((mem_debug_header_t*)((char*)header + header->size))->magic3 +#define MEM_USER_PTR(header) \ + ((char *)header + offsetof(mem_debug_header_t, magic3)) +#define MEM_HEADER_PTR(ptr) \ + (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3)) struct mem_debug_header { - size_t magic1; - size_t size; + unsigned magic1; + unsigned size; struct mem_debug_header *prev; struct mem_debug_header *next; - size_t line_num; - char file_name[MEM_DEBUG_FILE_LEN + 1]; - size_t magic2; + int line_num; + char file_name[MEM_DEBUG_FILE_LEN + 1]; + unsigned magic2; + ALIGNED(16) unsigned magic3; }; typedef struct mem_debug_header mem_debug_header_t; static mem_debug_header_t *mem_debug_chain; -static size_t mem_cur_size; -static size_t mem_max_size; +static unsigned mem_cur_size; +static unsigned mem_max_size; + +static mem_debug_header_t *malloc_check(void *ptr, const char *msg) +{ + mem_debug_header_t * header = MEM_HEADER_PTR(ptr); + if (header->magic1 != MEM_DEBUG_MAGIC1 || + header->magic2 != MEM_DEBUG_MAGIC2 || + MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 || + header->size == (unsigned)-1) { + fprintf(stderr, "%s check failed\n", msg); + if (header->magic1 == MEM_DEBUG_MAGIC1) + fprintf(stderr, "%s:%u: block allocated here.\n", + header->file_name, header->line_num); + exit(1); + } + return header; +} PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) { - void *ptr; int ofs; - mem_debug_header_t *header; - ptr = malloc(sizeof(mem_debug_header_t) + size); - if (!ptr) + header = malloc(sizeof(mem_debug_header_t) + size); + if (!header) tcc_error("memory full (malloc)"); - mem_cur_size += size; - if (mem_cur_size > mem_max_size) - mem_max_size = mem_cur_size; - - header = (mem_debug_header_t *)ptr; - header->magic1 = MEM_DEBUG_MAGIC1; header->magic2 = MEM_DEBUG_MAGIC2; header->size = size; + MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; header->line_num = line; - ofs = strlen(file) - MEM_DEBUG_FILE_LEN; strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); header->file_name[MEM_DEBUG_FILE_LEN] = 0; header->next = mem_debug_chain; header->prev = NULL; - if (header->next) header->next->prev = header; - mem_debug_chain = header; - ptr = (char *)ptr + sizeof(mem_debug_header_t); - return ptr; + mem_cur_size += size; + if (mem_cur_size > mem_max_size) + mem_max_size = mem_cur_size; + + return MEM_USER_PTR(header); } PUB_FUNC void tcc_free_debug(void *ptr) { mem_debug_header_t *header; - if (!ptr) return; - - ptr = (char *)ptr - sizeof(mem_debug_header_t); - header = (mem_debug_header_t *)ptr; - if (header->magic1 != MEM_DEBUG_MAGIC1 || - header->magic2 != MEM_DEBUG_MAGIC2 || - header->size == (size_t)-1 ) - { - tcc_error("tcc_free check failed"); - } - + header = malloc_check(ptr, "tcc_free"); mem_cur_size -= header->size; - header->size = (size_t)-1; - + header->size = (unsigned)-1; if (header->next) header->next->prev = header->prev; - if (header->prev) header->prev->next = header->next; - if (header == mem_debug_chain) mem_debug_chain = header->next; - - free(ptr); + free(header); } - PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) { void *ptr; @@ -345,52 +345,26 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file { mem_debug_header_t *header; int mem_debug_chain_update = 0; - - if (!ptr) { - ptr = tcc_malloc_debug(size, file, line); - return ptr; - } - - ptr = (char *)ptr - sizeof(mem_debug_header_t); - header = (mem_debug_header_t *)ptr; - if (header->magic1 != MEM_DEBUG_MAGIC1 || - header->magic2 != MEM_DEBUG_MAGIC2 || - header->size == (size_t)-1 ) - { - check_error: - tcc_error("tcc_realloc check failed"); - } - - mem_debug_chain_update = (header == mem_debug_chain); - - mem_cur_size -= header->size; - ptr = realloc(ptr, sizeof(mem_debug_header_t) + size); if (!ptr) + return tcc_malloc_debug(size, file, line); + header = malloc_check(ptr, "tcc_realloc"); + mem_cur_size -= header->size; + mem_debug_chain_update = (header == mem_debug_chain); + header = realloc(header, sizeof(mem_debug_header_t) + size); + if (!header) tcc_error("memory full (realloc)"); - - header = (mem_debug_header_t *)ptr; - if (header->magic1 != MEM_DEBUG_MAGIC1 || - header->magic2 != MEM_DEBUG_MAGIC2) - { - goto check_error; - } - - mem_cur_size += size; - if (mem_cur_size > mem_max_size) - mem_max_size = mem_cur_size; - header->size = size; + MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; if (header->next) header->next->prev = header; - if (header->prev) header->prev->next = header; - if (mem_debug_chain_update) mem_debug_chain = header; - - ptr = (char *)ptr + sizeof(mem_debug_header_t); - return ptr; + mem_cur_size += size; + if (mem_cur_size > mem_max_size) + mem_max_size = mem_cur_size; + return MEM_USER_PTR(header); } PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) @@ -401,29 +375,23 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) return ptr; } -PUB_FUNC void tcc_memstats(int bench) +PUB_FUNC void tcc_memcheck(void) { if (mem_cur_size) { mem_debug_header_t *header = mem_debug_chain; - fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", mem_cur_size, mem_max_size); - while (header) { fprintf(stderr, "%s:%u: error: %u bytes leaked\n", header->file_name, header->line_num, header->size); header = header->next; } +#if MEM_DEBUG-0 == 2 + exit(2); +#endif } - else if (bench) - fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size); } - -#undef MEM_DEBUG_MAGIC1 -#undef MEM_DEBUG_MAGIC2 -#undef MEM_DEBUG_FILE_LEN - -#endif +#endif /* MEM_DEBUG */ #define free(p) use_tcc_free(p) #define malloc(s) use_tcc_malloc(s) @@ -432,13 +400,13 @@ PUB_FUNC void tcc_memstats(int bench) /********************************************************/ /* dynarrays */ -ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data) +ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) { int nb, nb_alloc; void **pp; nb = *nb_ptr; - pp = *ptab; + pp = *(void ***)ptab; /* every power of two we double array size */ if ((nb & (nb - 1)) == 0) { if (!nb) @@ -446,7 +414,7 @@ ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data) else nb_alloc = nb * 2; pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); - *ptab = pp; + *(void***)ptab = pp; } pp[nb++] = data; *nb_ptr = nb; @@ -462,7 +430,7 @@ ST_FUNC void dynarray_reset(void *pp, int *n) *(void**)pp = NULL; } -static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in) +static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in) { const char *p; do { @@ -470,7 +438,7 @@ static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char CString str; cstr_new(&str); - for (p = in; c = *p, c != '\0' && c != PATHSEP; ++p) { + for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) { if (c == '{' && p[1] && p[2] == '}') { c = p[1], p += 2; if (c == 'B') @@ -518,7 +486,7 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", (*pf)->filename, (*pf)->line_num); - if (f->line_num > 0) { + if (s1->error_set_jmp_enabled) { strcat_printf(buf, sizeof(buf), "%s:%d: ", f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL)); } else { @@ -536,8 +504,10 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) if (!s1->error_func) { /* default case: stderr */ - if (s1->ppfp) /* print a newline during tcc -E */ - fprintf(s1->ppfp, "\n"), fflush(s1->ppfp); + if (s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) + /* print a newline during tcc -E */ + printf("\n"), fflush(stdout); + fflush(stdout); /* flush -v output */ fprintf(stderr, "%s\n", buf); fflush(stderr); /* print error/warning now (win32) */ } else { @@ -608,14 +578,13 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) bf->buf_end = bf->buffer + initlen; bf->buf_end[0] = CH_EOB; /* put eob symbol */ pstrcpy(bf->filename, sizeof(bf->filename), filename); -#ifdef _WIN32 - normalize_slashes(bf->filename); -#endif + bf->true_filename = bf->filename; bf->line_num = 1; bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; bf->fd = -1; bf->prev = file; file = bf; + tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; } ST_FUNC void tcc_close(void) @@ -625,6 +594,8 @@ ST_FUNC void tcc_close(void) close(bf->fd); total_lines += bf->line_num; } + if (bf->true_filename != bf->filename) + tcc_free(bf->true_filename); file = bf->prev; tcc_free(bf); } @@ -641,44 +612,51 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) (int)(s1->include_stack_ptr - s1->include_stack), "", filename); if (fd < 0) return -1; - tcc_open_bf(s1, filename, 0); +#ifdef _WIN32 + normalize_slashes(file->filename); +#endif file->fd = fd; return fd; } -/* compile the C file opened in 'file'. Return non zero if errors. */ +/* compile the file opened in 'file'. Return non zero if errors. */ static int tcc_compile(TCCState *s1) { Sym *define_start; + int filetype, is_asm; - preprocess_start(s1); define_start = define_stack; + filetype = s1->filetype; + is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP; + tccelf_begin_file(s1); if (setjmp(s1->error_jmp_buf) == 0) { s1->nb_errors = 0; s1->error_set_jmp_enabled = 1; - tccgen_start(s1); -#ifdef INC_DEBUG - printf("%s: **** new file\n", file->filename); + preprocess_start(s1, is_asm); + if (s1->output_type == TCC_OUTPUT_PREPROCESS) { + tcc_preprocess(s1); + } else if (is_asm) { +#ifdef CONFIG_TCC_ASM + tcc_assemble(s1, filetype == AFF_TYPE_ASMPP); +#else + tcc_error_noabort("asm not supported"); #endif - ch = file->buf_ptr[0]; - tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; - parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; - next(); - decl(VT_CONST); - if (tok != TOK_EOF) - expect("declaration"); - /* reset define stack, but keep -D and built-ins */ - free_defines(define_start); - tccgen_end(s1); + } else { + tccgen_compile(s1); + } } s1->error_set_jmp_enabled = 0; + preprocess_end(s1); free_inline_functions(s1); + /* reset define stack, but keep -D and built-ins */ + free_defines(define_start); sym_pop(&global_stack, NULL, 0); sym_pop(&local_stack, NULL, 0); + tccelf_end_file(s1); return s1->nb_errors != 0 ? -1 : 0; } @@ -711,10 +689,8 @@ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *valu memcpy(file->buffer + len1 + 1, value, len2); /* parse with define parser */ - ch = file->buf_ptr[0]; next_nomacro(); parse_define(); - tcc_close(); } @@ -735,6 +711,8 @@ static void tcc_cleanup(void) { if (NULL == tcc_state) return; + while (file) + tcc_close(); tccpp_delete(tcc_state); tcc_state = NULL; /* free sym_pools */ @@ -753,11 +731,12 @@ LIBTCCAPI TCCState *tcc_new(void) if (!s) return NULL; tcc_state = s; + ++nb_states; s->alacarte_link = 1; s->nocommon = 1; s->warn_implicit_function_declaration = 1; - s->ms_bitfields = 0; + s->ms_extensions = 1; #ifdef CHAR_IS_UNSIGNED s->char_is_unsigned = 1; @@ -765,9 +744,6 @@ LIBTCCAPI TCCState *tcc_new(void) #ifdef TCC_TARGET_I386 s->seg_size = 32; #endif -#ifdef TCC_IS_NATIVE - s->runtime_main = "main"; -#endif /* enable this if you want symbols with leading underscore on windows: */ #if 0 /* def TCC_TARGET_PE */ s->leading_underscore = 1; @@ -786,6 +762,7 @@ LIBTCCAPI TCCState *tcc_new(void) define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); + define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); { /* define __TINYC__ 92X */ char buffer[32]; int a,b,c; @@ -827,6 +804,8 @@ LIBTCCAPI TCCState *tcc_new(void) #endif #elif defined(TCC_TARGET_ARM64) tcc_define_symbol(s, "__aarch64__", NULL); +#elif defined TCC_TARGET_C67 + tcc_define_symbol(s, "__C67__", NULL); #endif #ifdef TCC_TARGET_PE @@ -850,30 +829,30 @@ LIBTCCAPI TCCState *tcc_new(void) # if defined(__FreeBSD_kernel__) tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); # endif -#endif # if defined(__NetBSD__) tcc_define_symbol(s, "__NetBSD__", "__NetBSD__"); # endif # if defined(__OpenBSD__) tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__"); # endif +#endif /* TinyCC & gcc defines */ -#if defined(TCC_TARGET_PE) && defined(TCC_TARGET_X86_64) +#if PTR_SIZE == 4 + /* 32bit systems. */ + tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); + tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); + tcc_define_symbol(s, "__ILP32__", NULL); +#elif LONG_SIZE == 4 /* 64bit Windows. */ tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long"); tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long"); tcc_define_symbol(s, "__LLP64__", NULL); -#elif defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64) +#else /* Other 64bit systems. */ tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); tcc_define_symbol(s, "__LP64__", NULL); -#else - /* Other 32bit systems. */ - tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); - tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); - tcc_define_symbol(s, "__ILP32__", NULL); #endif #ifdef TCC_TARGET_PE @@ -902,18 +881,19 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); # endif -#endif /* ndef TCC_TARGET_PE */ - +# if defined(TCC_MUSL) + tcc_define_symbol(s, "__DEFINED_va_list", ""); + tcc_define_symbol(s, "__DEFINED___isoc_va_list", ""); + tcc_define_symbol(s, "__isoc_va_list", "void *"); +# endif /* TCC_MUSL */ /* Some GCC builtins that are simple to express as macros. */ tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); - +#endif /* ndef TCC_TARGET_PE */ return s; } LIBTCCAPI void tcc_delete(TCCState *s1) { - int bench = s1->do_bench; - tcc_cleanup(); /* free sections */ @@ -927,6 +907,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); dynarray_reset(&s1->include_paths, &s1->nb_include_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); + dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); tcc_free(s1->tcc_lib_path); tcc_free(s1->soname); @@ -938,6 +919,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dynarray_reset(&s1->files, &s1->nb_files); dynarray_reset(&s1->target_deps, &s1->nb_target_deps); dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); + dynarray_reset(&s1->argv, &s1->argc); #ifdef TCC_IS_NATIVE /* free runtime memory */ @@ -945,7 +927,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1) #endif tcc_free(s1); - tcc_memstats(bench); + if (0 == --nb_states) + tcc_memcheck(); } LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) @@ -987,7 +970,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) # endif #else /* paths for crt objects */ - tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); + tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); /* add libc crt1/crti objects */ if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && !s->nostdlib) { @@ -1001,38 +984,19 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) { - tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname); + tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); return 0; } LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) { - tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); + tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); return 0; } ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) { - int ret, filetype; - - filetype = flags & 0x0F; - if (filetype == 0) { - /* use a file extension to detect a filetype */ - const char *ext = tcc_fileextension(filename); - if (ext[0]) { - ext++; - if (!strcmp(ext, "S")) - filetype = AFF_TYPE_ASMPP; - else if (!strcmp(ext, "s")) - filetype = AFF_TYPE_ASM; - else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i")) - filetype = AFF_TYPE_C; - else - filetype = AFF_TYPE_BIN; - } else { - filetype = AFF_TYPE_C; - } - } + int ret; /* open the file */ ret = tcc_open(s1, filename); @@ -1043,29 +1007,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) } /* update target deps */ - dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, + dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename)); - parse_flags = 0; - /* if .S file, define __ASSEMBLER__ like gcc does */ - if (filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP) { - tcc_define_symbol(s1, "__ASSEMBLER__", NULL); - parse_flags = PARSE_FLAG_ASM_FILE; - } - - if (flags & AFF_PREPROCESS) { - ret = tcc_preprocess(s1); - } else if (filetype == AFF_TYPE_C) { - ret = tcc_compile(s1); -#ifdef CONFIG_TCC_ASM - } else if (filetype == AFF_TYPE_ASMPP) { - /* non preprocessed assembler */ - ret = tcc_assemble(s1, 1); - } else if (filetype == AFF_TYPE_ASM) { - /* preprocessed assembler */ - ret = tcc_assemble(s1, 0); -#endif - } else { + if (flags & AFF_TYPE_BIN) { ElfW(Ehdr) ehdr; int fd, obj_type; @@ -1073,8 +1018,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) obj_type = tcc_object_type(fd, &ehdr); lseek(fd, 0, SEEK_SET); - /* do not display line number if error */ - file->line_num = 0; +#ifdef TCC_TARGET_MACHO + if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib")) + obj_type = AFF_BINTYPE_DYN; +#endif switch (obj_type) { case AFF_BINTYPE_REL: @@ -1113,6 +1060,8 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) tcc_error_noabort("unrecognized file type"); break; } + } else { + ret = tcc_compile(s1); } tcc_close(); return ret; @@ -1120,15 +1069,32 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) { - if (s->output_type == TCC_OUTPUT_PREPROCESS) - return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS | s->filetype); - else - return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | s->filetype); + int filetype = s->filetype; + int flags = AFF_PRINT_ERROR; + if (filetype == 0) { + /* use a file extension to detect a filetype */ + const char *ext = tcc_fileextension(filename); + if (ext[0]) { + ext++; + if (!strcmp(ext, "S")) + filetype = AFF_TYPE_ASMPP; + else if (!strcmp(ext, "s")) + filetype = AFF_TYPE_ASM; + else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i")) + filetype = AFF_TYPE_C; + else + flags |= AFF_TYPE_BIN; + } else { + filetype = AFF_TYPE_C; + } + s->filetype = filetype; + } + return tcc_add_file_internal(s, filename, flags); } LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) { - tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname); + tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); return 0; } @@ -1146,7 +1112,6 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt, return -1; } -#ifndef TCC_TARGET_PE /* find and load a dll. Return non zero if not found */ /* XXX: add '-rpath' option support ? */ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) @@ -1154,7 +1119,6 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) return tcc_add_library_internal(s, "%s/%s", filename, flags, s->library_paths, s->nb_library_paths); } -#endif ST_FUNC int tcc_add_crt(TCCState *s, const char *filename) { @@ -1167,9 +1131,12 @@ ST_FUNC int tcc_add_crt(TCCState *s, const char *filename) /* the library name is the same as the argument of the '-l' option */ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) { -#ifdef TCC_TARGET_PE +#if defined TCC_TARGET_PE const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; const char **pp = s->static_link ? libs + 4 : libs; +#elif defined TCC_TARGET_MACHO + const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL }; + const char **pp = s->static_link ? libs + 1 : libs; #else const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; const char **pp = s->static_link ? libs + 1 : libs; @@ -1187,11 +1154,11 @@ PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname) { int ret = tcc_add_library(s, libname); if (ret < 0) - tcc_error_noabort("library 'lib%s' not found", libname); + tcc_error_noabort("library '%s' not found", libname); return ret; } -/* habdle #pragma comment(lib,) */ +/* handle #pragma comment(lib,) */ ST_FUNC void tcc_add_pragma_libs(TCCState *s1) { int i; @@ -1228,14 +1195,6 @@ typedef struct FlagDef { const char *name; } FlagDef; -static const FlagDef warning_defs[] = { - { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, - { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, - { offsetof(TCCState, warn_error), 0, "error" }, - { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, - "implicit-function-declaration" }, -}; - static int no_flag(const char **pp) { const char *p = *pp; @@ -1245,73 +1204,35 @@ static int no_flag(const char **pp) return 1; } -ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, - const char *name, int value) +ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) { - int i; + int value, ret; const FlagDef *p; const char *r; + value = 1; r = name; if (no_flag(&r)) - value = !value; - - for(i = 0, p = flags; i < nb_flags; i++, p++) { - if (!strcmp(r, p->name)) - goto found; - } - return -1; - found: - if (p->flags & FD_INVERT) - value = !value; - *(int *)((uint8_t *)s + p->offset) = value; - return 0; -} - -/* set/reset a warning */ -static int tcc_set_warning(TCCState *s, const char *warning_name, int value) -{ - int i; - const FlagDef *p; + value = 0; - if (!strcmp(warning_name, "all")) { - for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { - if (p->flags & WD_ALL) - *(int *)((uint8_t *)s + p->offset) = 1; + for (ret = -1, p = flags; p->name; ++p) { + if (ret) { + if (strcmp(r, p->name)) + continue; + } else { + if (0 == (p->flags & WD_ALL)) + continue; + } + if (p->offset) { + *(int*)((char *)s + p->offset) = + p->flags & FD_INVERT ? !value : value; + if (ret) + return 0; + } else { + ret = 0; } - return 0; - } else { - return set_flag(s, warning_defs, countof(warning_defs), - warning_name, value); } -} - -static const FlagDef flag_defs[] = { - { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, - { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, - { offsetof(TCCState, nocommon), FD_INVERT, "common" }, - { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, - { offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, - { offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" }, - { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, -}; - -/* set/reset a flag */ -static int tcc_set_flag(TCCState *s, const char *flag_name, int value) -{ - return set_flag(s, flag_defs, countof(flag_defs), - flag_name, value); -} - -static const FlagDef m_defs[] = { -#ifdef TCC_TARGET_X86_64 - { offsetof(TCCState, nosse), FD_INVERT, "sse" }, -#endif - { 0, 0, " no flag" }, -}; -static int tcc_set_m_flag(TCCState *s, const char *flag_name, int value) -{ - return set_flag(s, m_defs, countof(m_defs), flag_name, value); + return ret; } static int strstart(const char *val, const char **str) @@ -1348,7 +1269,7 @@ static int link_option(const char *str, const char *val, const char **ptr) if (*str == '-') str++; - /* then str & val should match (potentialy up to '=') */ + /* then str & val should match (potentially up to '=') */ p = str; q = val; @@ -1373,6 +1294,8 @@ static int link_option(const char *str, const char *val, const char **ptr) if (*p != ',' && *p != '=') return 0; p++; + } else if (*p) { + return 0; } *ptr = p; return ret; @@ -1386,11 +1309,15 @@ static const char *skip_linker_arg(const char **str) return s2; } -static char *copy_linker_arg(const char *p) +static void copy_linker_arg(char **pp, const char *s, int sep) { - const char *q = p; + const char *q = s; + char *p = *pp; + int l = 0; + if (p && sep) + p[l = strlen(p)] = sep, ++l; skip_linker_arg(&q); - return pstrncpy(tcc_malloc(q - p + 1), p, q - p); + pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s); } /* set linker options */ @@ -1408,19 +1335,19 @@ static int tcc_set_linker(TCCState *s, const char *option) } else if (link_option(option, "nostdlib", &p)) { s->nostdlib = 1; } else if (link_option(option, "fini=", &p)) { - s->fini_symbol = copy_linker_arg(p); + copy_linker_arg(&s->fini_symbol, p, 0); ignoring = 1; } else if (link_option(option, "image-base=", &p) || link_option(option, "Ttext=", &p)) { s->text_addr = strtoull(p, &end, 16); s->has_text_addr = 1; } else if (link_option(option, "init=", &p)) { - s->init_symbol = copy_linker_arg(p); + copy_linker_arg(&s->init_symbol, p, 0); ignoring = 1; } else if (link_option(option, "oformat=", &p)) { #if defined(TCC_TARGET_PE) if (strstart("pe-", &p)) { -#elif defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) +#elif PTR_SIZE == 8 if (strstart("elf64-", &p)) { #else if (strstart("elf32-", &p)) { @@ -1439,13 +1366,19 @@ static int tcc_set_linker(TCCState *s, const char *option) ignoring = 1; } else if (link_option(option, "O", &p)) { ignoring = 1; + } else if (link_option(option, "export-all-symbols", &p)) { + s->rdynamic = 1; } else if (link_option(option, "rpath=", &p)) { - s->rpath = copy_linker_arg(p); + copy_linker_arg(&s->rpath, p, ':'); + } else if (link_option(option, "enable-new-dtags", &p)) { + s->enable_new_dtags = 1; } else if (link_option(option, "section-alignment=", &p)) { s->section_align = strtoul(p, &end, 16); } else if (link_option(option, "soname=", &p)) { - s->soname = copy_linker_arg(p); + copy_linker_arg(&s->soname, p, 0); #ifdef TCC_TARGET_PE + } else if (link_option(option, "large-address-aware", &p)) { + s->pe_characteristics |= 0x20; } else if (link_option(option, "file-alignment=", &p)) { s->pe_file_align = strtoul(p, &end, 16); } else if (link_option(option, "stack=", &p)) { @@ -1456,7 +1389,7 @@ static int tcc_set_linker(TCCState *s, const char *option) s->pe_subsystem = 1; } else if (!strcmp(p, "console")) { s->pe_subsystem = 3; - } else if (!strcmp(p, "gui")) { + } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) { s->pe_subsystem = 2; } else if (!strcmp(p, "posix")) { s->pe_subsystem = 7; @@ -1500,6 +1433,8 @@ typedef struct TCCOption { enum { TCC_OPTION_HELP, + TCC_OPTION_HELP2, + TCC_OPTION_v, TCC_OPTION_I, TCC_OPTION_D, TCC_OPTION_U, @@ -1514,7 +1449,6 @@ enum { TCC_OPTION_c, TCC_OPTION_dumpversion, TCC_OPTION_d, - TCC_OPTION_float_abi, TCC_OPTION_static, TCC_OPTION_std, TCC_OPTION_shared, @@ -1527,7 +1461,7 @@ enum { TCC_OPTION_Wp, TCC_OPTION_W, TCC_OPTION_O, - TCC_OPTION_mms_bitfields, + TCC_OPTION_mfloat_abi, TCC_OPTION_m, TCC_OPTION_f, TCC_OPTION_isystem, @@ -1541,13 +1475,14 @@ enum { TCC_OPTION_pedantic, TCC_OPTION_pthread, TCC_OPTION_run, - TCC_OPTION_v, TCC_OPTION_w, TCC_OPTION_pipe, TCC_OPTION_E, TCC_OPTION_MD, TCC_OPTION_MF, - TCC_OPTION_x + TCC_OPTION_x, + TCC_OPTION_ar, + TCC_OPTION_impdef }; #define TCC_OPTION_HAS_ARG 0x0001 @@ -1557,6 +1492,8 @@ static const TCCOption tcc_options[] = { { "h", TCC_OPTION_HELP, 0 }, { "-help", TCC_OPTION_HELP, 0 }, { "?", TCC_OPTION_HELP, 0 }, + { "hh", TCC_OPTION_HELP2, 0 }, + { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, @@ -1575,9 +1512,6 @@ static const TCCOption tcc_options[] = { { "c", TCC_OPTION_c, 0 }, { "dumpversion", TCC_OPTION_dumpversion, 0}, { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, -#ifdef TCC_TARGET_ARM - { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG }, -#endif { "static", TCC_OPTION_static, 0 }, { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "shared", TCC_OPTION_shared, 0 }, @@ -1595,25 +1529,58 @@ static const TCCOption tcc_options[] = { { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, - { "mms-bitfields", TCC_OPTION_mms_bitfields, 0}, /* must go before option 'm' */ - { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, +#ifdef TCC_TARGET_ARM + { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG }, +#endif + { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, - { "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG }, { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG }, { "nostdinc", TCC_OPTION_nostdinc, 0 }, { "nostdlib", TCC_OPTION_nostdlib, 0 }, { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, - { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "w", TCC_OPTION_w, 0 }, { "pipe", TCC_OPTION_pipe, 0}, { "E", TCC_OPTION_E, 0}, { "MD", TCC_OPTION_MD, 0}, { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, + { "ar", TCC_OPTION_ar, 0}, +#ifdef TCC_TARGET_PE + { "impdef", TCC_OPTION_impdef, 0}, +#endif { NULL, 0, 0 }, }; +static const FlagDef options_W[] = { + { 0, 0, "all" }, + { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, + { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, + { offsetof(TCCState, warn_error), 0, "error" }, + { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, + { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, + "implicit-function-declaration" }, + { 0, 0, NULL } +}; + +static const FlagDef options_f[] = { + { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, + { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, + { offsetof(TCCState, nocommon), FD_INVERT, "common" }, + { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, + { offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, + { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, + { 0, 0, NULL } +}; + +static const FlagDef options_m[] = { + { offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" }, +#ifdef TCC_TARGET_X86_64 + { offsetof(TCCState, nosse), FD_INVERT, "sse" }, +#endif + { 0, 0, NULL } +}; + static void parse_option_D(TCCState *s1, const char *optarg) { char *sym = tcc_strdup(optarg); @@ -1628,56 +1595,105 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype { struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); f->type = filetype; + f->alacarte = s->alacarte_link; strcpy(f->name, filename); - dynarray_add((void ***)&s->files, &s->nb_files, f); + dynarray_add(&s->files, &s->nb_files, f); +} + +static int args_parser_make_argv(const char *r, int *argc, char ***argv) +{ + int ret = 0, q, c; + CString str; + for(;;) { + while (c = (unsigned char)*r, c && c <= ' ') + ++r; + if (c == 0) + break; + q = 0; + cstr_new(&str); + while (c = (unsigned char)*r, c) { + ++r; + if (c == '\\' && (*r == '"' || *r == '\\')) { + c = *r++; + } else if (c == '"') { + q = !q; + continue; + } else if (q == 0 && c <= ' ') { + break; + } + cstr_ccat(&str, c); + } + cstr_ccat(&str, 0); + //printf("<%s>\n", str.data), fflush(stdout); + dynarray_add(argv, argc, tcc_strdup(str.data)); + cstr_free(&str); + ++ret; + } + return ret; } /* read list file */ -static void args_parser_listfile(TCCState *s, const char *filename) +static void args_parser_listfile(TCCState *s, + const char *filename, int optind, int *pargc, char ***pargv) { - int fd; + int fd, i; size_t len; char *p; + int argc = 0; + char **argv = NULL; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) - tcc_error("file '%s' not found", filename); + tcc_error("listfile '%s' not found", filename); len = lseek(fd, 0, SEEK_END); p = tcc_malloc(len + 1), p[len] = 0; lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); - tcc_set_options(s, p); + + for (i = 0; i < *pargc; ++i) + if (i == optind) + args_parser_make_argv(p, &argc, &argv); + else + dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i])); + tcc_free(p); + dynarray_reset(&s->argv, &s->argc); + *pargc = s->argc = argc, *pargv = s->argv = argv; } -PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) +PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) { const TCCOption *popt; const char *optarg, *r; - int optind = 0; - int run = 0; - int x; + const char *run = NULL; int last_o = -1; + int x; CString linker_arg; /* collect -Wl options */ - char buf[1024]; + int tool = 0, arg_start = 0, noaction = optind; + char **argv = *pargv; + int argc = *pargc; cstr_new(&linker_arg); while (optind < argc) { - - r = argv[optind++]; - -reparse: + r = argv[optind]; if (r[0] == '@' && r[1] != '\0') { - args_parser_listfile(s, r + 1); + args_parser_listfile(s, r + 1, optind, &argc, &argv); continue; } - + optind++; + if (tool) { + if (r[0] == '-' && r[1] == 'v' && r[2] == 0) + ++s->verbose; + continue; + } +reparse: if (r[0] != '-' || r[1] == '\0') { - args_parser_add_file(s, r, s->filetype); + if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ + args_parser_add_file(s, r, s->filetype); if (run) { - optind--; - /* argv[0] will be this file */ + tcc_set_options(s, run); + arg_start = optind - 1; break; } continue; @@ -1706,7 +1722,9 @@ reparse: switch(popt->index) { case TCC_OPTION_HELP: - return 0; + return OPT_HELP; + case TCC_OPTION_HELP2: + return OPT_HELP2; case TCC_OPTION_I: tcc_add_include_path(s, optarg); break; @@ -1724,7 +1742,7 @@ reparse: tcc_set_lib_path(s, optarg); break; case TCC_OPTION_l: - args_parser_add_file(s, optarg, AFF_TYPE_LIBWH - s->alacarte_link); + args_parser_add_file(s, optarg, AFF_TYPE_LIB); s->nb_libraries++; break; case TCC_OPTION_pthread: @@ -1760,21 +1778,13 @@ reparse: s->dflag = 3; else if (*optarg == 'M') s->dflag = 7; + else if (*optarg == 't') + s->dflag = 16; + else if (isnum(*optarg)) + g_debug = atoi(optarg); else goto unsupported_option; break; -#ifdef TCC_TARGET_ARM - case TCC_OPTION_float_abi: - /* tcc doesn't support soft float yet */ - if (!strcmp(optarg, "softfp")) { - s->float_abi = ARM_SOFTFP_FLOAT; - tcc_undefine_symbol(s, "__ARM_PCS_VFP"); - } else if (!strcmp(optarg, "hard")) - s->float_abi = ARM_HARD_FLOAT; - else - tcc_error("unsupported float abi '%s'", optarg); - break; -#endif case TCC_OPTION_static: s->static_link = 1; break; @@ -1788,12 +1798,6 @@ reparse: case TCC_OPTION_soname: s->soname = tcc_strdup(optarg); break; - case TCC_OPTION_m: - if (!strcmp(optarg, "32") || !strcmp(optarg, "64")) - s->option_m = tcc_strdup(optarg); - else if (tcc_set_m_flag(s, optarg, 1) < 0) - goto unsupported_option; - break; case TCC_OPTION_o: if (s->outfile) { tcc_warning("multiple -o option"); @@ -1809,12 +1813,8 @@ reparse: case TCC_OPTION_isystem: tcc_add_sysinclude_path(s, optarg); break; - case TCC_OPTION_iwithprefix: - snprintf(buf, sizeof buf, "{B}/%s", optarg); - tcc_add_sysinclude_path(s, buf); - break; case TCC_OPTION_include: - dynarray_add((void ***)&s->cmd_include_files, + dynarray_add(&s->cmd_include_files, &s->nb_cmd_include_files, tcc_strdup(optarg)); break; case TCC_OPTION_nostdinc: @@ -1823,26 +1823,44 @@ reparse: case TCC_OPTION_nostdlib: s->nostdlib = 1; break; - case TCC_OPTION_print_search_dirs: - s->print_search_dirs = 1; - break; case TCC_OPTION_run: #ifndef TCC_IS_NATIVE tcc_error("-run is not available in a cross compiler"); #endif - tcc_set_options(s, optarg); - run = 1; + run = optarg; x = TCC_OUTPUT_MEMORY; goto set_output_type; case TCC_OPTION_v: do ++s->verbose; while (*optarg++ == 'v'); + ++noaction; break; case TCC_OPTION_f: - if (tcc_set_flag(s, optarg, 1) < 0) + if (set_flag(s, options_f, optarg) < 0) goto unsupported_option; break; +#ifdef TCC_TARGET_ARM + case TCC_OPTION_mfloat_abi: + /* tcc doesn't support soft float yet */ + if (!strcmp(optarg, "softfp")) { + s->float_abi = ARM_SOFTFP_FLOAT; + tcc_undefine_symbol(s, "__ARM_PCS_VFP"); + } else if (!strcmp(optarg, "hard")) + s->float_abi = ARM_HARD_FLOAT; + else + tcc_error("unsupported float abi '%s'", optarg); + break; +#endif + case TCC_OPTION_m: + if (set_flag(s, options_m, optarg) < 0) { + if (x = atoi(optarg), x != 32 && x != 64) + goto unsupported_option; + if (PTR_SIZE != x/8) + return x; + ++noaction; + } + break; case TCC_OPTION_W: - if (tcc_set_warning(s, optarg, 1) < 0) + if (set_flag(s, options_W, optarg) < 0) goto unsupported_option; break; case TCC_OPTION_w: @@ -1890,8 +1908,19 @@ reparse: case TCC_OPTION_O: last_o = atoi(optarg); break; - case TCC_OPTION_mms_bitfields: - s->ms_bitfields = 1; + case TCC_OPTION_print_search_dirs: + x = OPT_PRINT_DIRS; + goto extra_action; + case TCC_OPTION_impdef: + x = OPT_IMPDEF; + goto extra_action; + case TCC_OPTION_ar: + x = OPT_AR; + extra_action: + arg_start = optind - 1; + if (arg_start != noaction) + tcc_error("cannot parse %s here", r); + tool = x; break; case TCC_OPTION_traditional: case TCC_OPTION_pedantic: @@ -1906,53 +1935,32 @@ unsupported_option: break; } } - if (last_o > 0) tcc_define_symbol(s, "__OPTIMIZE__", NULL); - if (linker_arg.size) { r = linker_arg.data; goto arg_err; } - - return optind; + *pargc = argc - arg_start; + *pargv = argv + arg_start; + if (tool) + return tool; + if (optind != noaction) + return 0; + if (s->verbose == 2) + return OPT_PRINT_DIRS; + if (s->verbose) + return OPT_V; + return OPT_HELP; } -LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) +LIBTCCAPI void tcc_set_options(TCCState *s, const char *r) { - char **argv; - int argc; - int ret, q, c; - CString str; - - argc = 0, argv = NULL; - for(;;) { - while (c = (unsigned char)*r, c && c <= ' ') - ++r; - if (c == 0) - break; - q = 0; - cstr_new(&str); - while (c = (unsigned char)*r, c) { - ++r; - if (c == '\\' && (*r == '"' || *r == '\\')) { - c = *r++; - } else if (c == '"') { - q = !q; - continue; - } else if (q == 0 && c <= ' ') { - break; - } - cstr_ccat(&str, c); - } - cstr_ccat(&str, 0); - //printf("<%s>\n", str.data), fflush(stdout); - dynarray_add((void ***)&argv, &argc, tcc_strdup(str.data)); - cstr_free(&str); - } - ret = tcc_parse_args(s, argc, argv); + char **argv = NULL; + int argc = 0; + args_parser_make_argv(r, &argc, &argv); + tcc_parse_args(s, &argc, &argv, 0); dynarray_reset(&argv, &argc); - return ret; } PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) @@ -1961,27 +1969,13 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) total_time = 1; if (total_bytes < 1) total_bytes = 1; - fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %u lines/s, %0.1f MB/s\n", + fprintf(stderr, "* %d idents, %d lines, %d bytes\n" + "* %0.3f s, %u lines/s, %0.1f MB/s\n", tok_ident - TOK_IDENT, total_lines, total_bytes, (double)total_time/1000, (unsigned)total_lines*1000/total_time, (double)total_bytes/1000/total_time); -} - -PUB_FUNC void tcc_set_environment(TCCState *s) -{ - char * path; - - path = getenv("C_INCLUDE_PATH"); - if(path != NULL) { - tcc_add_include_path(s, path); - } - path = getenv("CPATH"); - if(path != NULL) { - tcc_add_include_path(s, path); - } - path = getenv("LIBRARY_PATH"); - if(path != NULL) { - tcc_add_library_path(s, path); - } +#ifdef MEM_DEBUG + fprintf(stderr, "* %d bytes memory used\n", mem_max_size); +#endif } |