summaryrefslogtreecommitdiff
path: root/libtcc.c
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2018-02-21 23:16:20 +0000
committerThomas Preud'homme <robotux@celest.fr>2018-02-21 23:16:20 +0000
commite2ccf3981d78dfeb390d22c74625b60310100abb (patch)
treefc30b3b3fe20cc005634818512dab3514acf8ef4 /libtcc.c
parent3f2e65a51523fbb98a44b71c29ae3a3fcc13854b (diff)
New upstream version 0.9.27
Diffstat (limited to 'libtcc.c')
-rw-r--r--libtcc.c800
1 files changed, 397 insertions, 403 deletions
diff --git a/libtcc.c b/libtcc.c
index 68c3f9d..1e9dd97 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -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
}