/* * TCC - Tiny C Compiler * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined ONE_SOURCE || ONE_SOURCE#include "tccpp.c"#include "tccgen.c"#include "tccelf.c"#include "tccrun.c"#ifdef TCC_TARGET_I386#include "i386-gen.c"#include "i386-link.c"#include "i386-asm.c"#elif defined(TCC_TARGET_ARM)#include "arm-gen.c"#include "arm-link.c"#include "arm-asm.c"#elif defined(TCC_TARGET_ARM64)#include "arm64-gen.c"#include "arm64-link.c"#include "arm-asm.c"#elif defined(TCC_TARGET_C67)#include "c67-gen.c"#include "c67-link.c"#include "tcccoff.c"#elif defined(TCC_TARGET_X86_64)#include "x86_64-gen.c"#include "x86_64-link.c"#include "i386-asm.c"#elif defined(TCC_TARGET_RISCV64)#include "riscv64-gen.c"#include "riscv64-link.c"#include "riscv64-asm.c"#else#error unknown target#endif#ifdef CONFIG_TCC_ASM#include "tccasm.c"#endif#ifdef TCC_TARGET_PE#include "tccpe.c"#endif#ifdef TCC_TARGET_MACHO#include "tccmacho.c"#endif#endif /* ONE_SOURCE */ #include "tcc.h" /********************************************************//* global variables */ /* XXX: get rid of this ASAP (or maybe not) */ST_DATA struct TCCState *tcc_state; #ifdef MEM_DEBUGstatic int nb_states;#endif /********************************************************/#ifdef _WIN32ST_FUNC char *normalize_slashes(char *path){ char *p; for (p = path; *p; ++p) if (*p == '\\') *p = '/'; return path;} static HMODULE tcc_module; /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */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 > path) --p; *p = 0; tcc_set_lib_path(s, path);} #ifdef TCC_TARGET_PEstatic void tcc_add_systemdir(TCCState *s){ char buf[1000]; GetSystemDirectory(buf, sizeof buf); tcc_add_library_path(s, normalize_slashes(buf));}#endif #ifdef LIBTCC_AS_DLLBOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved){ if (DLL_PROCESS_ATTACH == dwReason) tcc_module = hDll; return TRUE;}#endif#endif /********************************************************/#ifndef CONFIG_TCC_SEMLOCK#define WAIT_SEM()#define POST_SEM()#elif defined _WIN32static 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);#elif defined __APPLE__/* Half-compatible MacOS doesn't have non-shared (process local) semaphores. Use the dispatch framework for lightweight locks. */#include <dispatch/dispatch.h>static int tcc_sem_init;static dispatch_semaphore_t tcc_sem;static void wait_sem(void){ if (!tcc_sem_init) tcc_sem = dispatch_semaphore_create(1), tcc_sem_init = 1; dispatch_semaphore_wait(tcc_sem, DISPATCH_TIME_FOREVER);}#define WAIT_SEM() wait_sem()#define POST_SEM() dispatch_semaphore_signal(tcc_sem)#else#include <semaphore.h>static int tcc_sem_init;static sem_t tcc_sem;static void wait_sem(void){ if (!tcc_sem_init) sem_init(&tcc_sem, 0, 1), tcc_sem_init = 1; while (sem_wait (&tcc_sem) < 0 && errno == EINTR);}#define WAIT_SEM() wait_sem()#define POST_SEM() sem_post(&tcc_sem)#endif /********************************************************//* copy a string and truncate it. */ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s){ char *q, *q_end; int c; if (buf_size > 0) { q = buf; q_end = buf + buf_size - 1; while (q < q_end) { c = *s++; if (c == '\0') break; *q++ = c; } *q = '\0'; } return buf;} /* strcat and truncate. */ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s){ size_t len; len = strlen(buf); if (len < buf_size) pstrcpy(buf + len, buf_size - len, s); return buf;} ST_FUNC char *pstrncpy(char *out, const char *in, size_t num){ memcpy(out, in, num); out[num] = '\0'; return out;} /* extract the basename of a file */PUB_FUNC char *tcc_basename(const char *name){ char *p = strchr(name, 0); while (p > name && !IS_DIRSEP(p[-1])) --p; return p;} /* extract extension part of a file * * (if no extension, return pointer to end-of-string) */PUB_FUNC char *tcc_fileextension (const char *name){ char *b = tcc_basename(name); char *e = strrchr(b, '.'); return e ? e : strchr(b, 0);} /********************************************************//* memory management */ #undef free#undef malloc#undef realloc #ifndef MEM_DEBUG PUB_FUNC void tcc_free(void *ptr){ free(ptr);} PUB_FUNC void *tcc_malloc(unsigned long size){ void *ptr; ptr = malloc(size); if (!ptr && size) _tcc_error("memory full (malloc)"); return ptr;} PUB_FUNC void *tcc_mallocz(unsigned long size){ void *ptr; ptr = tcc_malloc(size); if (size) memset(ptr, 0, size); return ptr;} PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size){ void *ptr1; ptr1 = realloc(ptr, size); if (!ptr1 && size) _tcc_error("memory full (realloc)"); return ptr1;} PUB_FUNC char *tcc_strdup(const char *str){ char *ptr; ptr = tcc_malloc(strlen(str) + 1); strcpy(ptr, str); return ptr;} #else #define MEM_DEBUG_MAGIC1 0xFEEDDEB1#define MEM_DEBUG_MAGIC2 0xFEEDDEB2#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 { unsigned magic1; unsigned size; struct mem_debug_header *prev; struct mem_debug_header *next; 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 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){ int ofs; mem_debug_header_t *header; header = malloc(sizeof(mem_debug_header_t) + size); if (!header) _tcc_error("memory full (malloc)"); 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; 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; header = malloc_check(ptr, "tcc_free"); mem_cur_size -= header->size; 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(header);} PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line){ void *ptr; ptr = tcc_malloc_debug(size,file,line); memset(ptr, 0, size); return ptr;} PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line){ mem_debug_header_t *header; int mem_debug_chain_update = 0; 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->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; 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){ char *ptr; ptr = tcc_malloc_debug(strlen(str) + 1, file, line); strcpy(ptr, str); return ptr;} 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 }}#endif /* MEM_DEBUG */ #define free(p) use_tcc_free(p)#define malloc(s) use_tcc_malloc(s)#define realloc(p, s) use_tcc_realloc(p, s) /********************************************************//* dynarrays */ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data){ int nb, nb_alloc; void **pp; nb = *nb_ptr; pp = *(void ***)ptab; /* every power of two we double array size */ if ((nb & (nb - 1)) == 0) { if (!nb) nb_alloc = 1; else nb_alloc = nb * 2; pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); *(void***)ptab = pp; } pp[nb++] = data; *nb_ptr = nb;} ST_FUNC void dynarray_reset(void *pp, int *n){ void **p; for (p = *(void***)pp; *n; ++p, --*n) if (*p) tcc_free(*p); tcc_free(*(void**)pp); *(void**)pp = NULL;} static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in){ const char *p; do { int c; CString str; cstr_new(&str); 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') cstr_cat(&str, s->tcc_lib_path, -1); if (c == 'f' && file) { /* substitute current file's dir */ const char *f = file->true_filename; const char *b = tcc_basename(f); if (b > f) cstr_cat(&str, f, b - f - 1); else cstr_cat(&str, ".", 1); } } else { cstr_ccat(&str, c); } } if (str.size) { cstr_ccat(&str, '\0'); dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data)); } cstr_free(&str); in = p+1; } while (*p);} /********************************************************/ static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap){ int len;Lines 1–500 of 2124. Load more
/* * TCC - Tiny C Compiler * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined ONE_SOURCE || ONE_SOURCE #include "tccpp.c" #include "tccgen.c" #include "tccelf.c" #include "tccrun.c" #ifdef TCC_TARGET_I386 #include "i386-gen.c" #include "i386-link.c" #include "i386-asm.c" #elif defined(TCC_TARGET_ARM) #include "arm-gen.c" #include "arm-link.c" #include "arm-asm.c" #elif defined(TCC_TARGET_ARM64) #include "arm64-gen.c" #include "arm64-link.c" #include "arm-asm.c" #elif defined(TCC_TARGET_C67) #include "c67-gen.c" #include "c67-link.c" #include "tcccoff.c" #elif defined(TCC_TARGET_X86_64) #include "x86_64-gen.c" #include "x86_64-link.c" #include "i386-asm.c" #elif defined(TCC_TARGET_RISCV64) #include "riscv64-gen.c" #include "riscv64-link.c" #include "riscv64-asm.c" #else #error unknown target #endif #ifdef CONFIG_TCC_ASM #include "tccasm.c" #endif #ifdef TCC_TARGET_PE #include "tccpe.c" #endif #ifdef TCC_TARGET_MACHO #include "tccmacho.c" #endif #endif /* ONE_SOURCE */ #include "tcc.h" /********************************************************/ /* global variables */ /* XXX: get rid of this ASAP (or maybe not) */ ST_DATA struct TCCState *tcc_state; #ifdef MEM_DEBUG static int nb_states; #endif /********************************************************/ #ifdef _WIN32 ST_FUNC char *normalize_slashes(char *path) { char *p; for (p = path; *p; ++p) if (*p == '\\') *p = '/'; return path; } static HMODULE tcc_module; /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ 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 > path) --p; *p = 0; tcc_set_lib_path(s, path); } #ifdef TCC_TARGET_PE static void tcc_add_systemdir(TCCState *s) { char buf[1000]; GetSystemDirectory(buf, sizeof buf); tcc_add_library_path(s, normalize_slashes(buf)); } #endif #ifdef LIBTCC_AS_DLL BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) { if (DLL_PROCESS_ATTACH == dwReason) tcc_module = hDll; return TRUE; } #endif #endif /********************************************************/ #ifndef CONFIG_TCC_SEMLOCK #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); #elif defined __APPLE__ /* Half-compatible MacOS doesn't have non-shared (process local) semaphores. Use the dispatch framework for lightweight locks. */ #include <dispatch/dispatch.h> static int tcc_sem_init; static dispatch_semaphore_t tcc_sem; static void wait_sem(void) { if (!tcc_sem_init) tcc_sem = dispatch_semaphore_create(1), tcc_sem_init = 1; dispatch_semaphore_wait(tcc_sem, DISPATCH_TIME_FOREVER); } #define WAIT_SEM() wait_sem() #define POST_SEM() dispatch_semaphore_signal(tcc_sem) #else #include <semaphore.h> static int tcc_sem_init; static sem_t tcc_sem; static void wait_sem(void) { if (!tcc_sem_init) sem_init(&tcc_sem, 0, 1), tcc_sem_init = 1; while (sem_wait (&tcc_sem) < 0 && errno == EINTR); } #define WAIT_SEM() wait_sem() #define POST_SEM() sem_post(&tcc_sem) #endif /********************************************************/ /* copy a string and truncate it. */ ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) { char *q, *q_end; int c; if (buf_size > 0) { q = buf; q_end = buf + buf_size - 1; while (q < q_end) { c = *s++; if (c == '\0') break; *q++ = c; } *q = '\0'; } return buf; } /* strcat and truncate. */ ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s) { size_t len; len = strlen(buf); if (len < buf_size) pstrcpy(buf + len, buf_size - len, s); return buf; } ST_FUNC char *pstrncpy(char *out, const char *in, size_t num) { memcpy(out, in, num); out[num] = '\0'; return out; } /* extract the basename of a file */ PUB_FUNC char *tcc_basename(const char *name) { char *p = strchr(name, 0); while (p > name && !IS_DIRSEP(p[-1])) --p; return p; } /* extract extension part of a file * * (if no extension, return pointer to end-of-string) */ PUB_FUNC char *tcc_fileextension (const char *name) { char *b = tcc_basename(name); char *e = strrchr(b, '.'); return e ? e : strchr(b, 0); } /********************************************************/ /* memory management */ #undef free #undef malloc #undef realloc #ifndef MEM_DEBUG PUB_FUNC void tcc_free(void *ptr) { free(ptr); } PUB_FUNC void *tcc_malloc(unsigned long size) { void *ptr; ptr = malloc(size); if (!ptr && size) _tcc_error("memory full (malloc)"); return ptr; } PUB_FUNC void *tcc_mallocz(unsigned long size) { void *ptr; ptr = tcc_malloc(size); if (size) memset(ptr, 0, size); return ptr; } PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) { void *ptr1; ptr1 = realloc(ptr, size); if (!ptr1 && size) _tcc_error("memory full (realloc)"); return ptr1; } PUB_FUNC char *tcc_strdup(const char *str) { char *ptr; ptr = tcc_malloc(strlen(str) + 1); strcpy(ptr, str); return ptr; } #else #define MEM_DEBUG_MAGIC1 0xFEEDDEB1 #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 #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 { unsigned magic1; unsigned size; struct mem_debug_header *prev; struct mem_debug_header *next; 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 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) { int ofs; mem_debug_header_t *header; header = malloc(sizeof(mem_debug_header_t) + size); if (!header) _tcc_error("memory full (malloc)"); 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; 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; header = malloc_check(ptr, "tcc_free"); mem_cur_size -= header->size; 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(header); } PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) { void *ptr; ptr = tcc_malloc_debug(size,file,line); memset(ptr, 0, size); return ptr; } PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line) { mem_debug_header_t *header; int mem_debug_chain_update = 0; 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->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; 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) { char *ptr; ptr = tcc_malloc_debug(strlen(str) + 1, file, line); strcpy(ptr, str); return ptr; } 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 } } #endif /* MEM_DEBUG */ #define free(p) use_tcc_free(p) #define malloc(s) use_tcc_malloc(s) #define realloc(p, s) use_tcc_realloc(p, s) /********************************************************/ /* dynarrays */ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) { int nb, nb_alloc; void **pp; nb = *nb_ptr; pp = *(void ***)ptab; /* every power of two we double array size */ if ((nb & (nb - 1)) == 0) { if (!nb) nb_alloc = 1; else nb_alloc = nb * 2; pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); *(void***)ptab = pp; } pp[nb++] = data; *nb_ptr = nb; } ST_FUNC void dynarray_reset(void *pp, int *n) { void **p; for (p = *(void***)pp; *n; ++p, --*n) if (*p) tcc_free(*p); tcc_free(*(void**)pp); *(void**)pp = NULL; } static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in) { const char *p; do { int c; CString str; cstr_new(&str); 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') cstr_cat(&str, s->tcc_lib_path, -1); if (c == 'f' && file) { /* substitute current file's dir */ const char *f = file->true_filename; const char *b = tcc_basename(f); if (b > f) cstr_cat(&str, f, b - f - 1); else cstr_cat(&str, ".", 1); } } else { cstr_ccat(&str, c); } } if (str.size) { cstr_ccat(&str, '\0'); dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data)); } cstr_free(&str); in = p+1; } while (*p); } /********************************************************/ static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) { int len;