Ignore:
Timestamp:
Jan 21, 2018, 12:10:09 AM (6 years ago)
Author:
coas-nagasima
Message:

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

Location:
EcnlProtoTool/trunk/tcc-0.9.27
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/tcc-0.9.27/libtcc.c

    r321 r331  
    11/*
    22 *  TCC - Tiny C Compiler
    3  * 
     3 *
    44 *  Copyright (c) 2001-2004 Fabrice Bellard
    55 *
     
    3333ST_DATA struct TCCState *tcc_state;
    3434
     35static int nb_states;
     36
    3537/********************************************************/
    3638
    37 #ifdef ONE_SOURCE
     39#if ONE_SOURCE
    3840#include "tccpp.c"
    3941#include "tccgen.c"
     
    4244#ifdef TCC_TARGET_I386
    4345#include "i386-gen.c"
     46#include "i386-link.c"
     47#include "i386-asm.c"
    4448#endif
    4549#ifdef TCC_TARGET_ARM
    4650#include "arm-gen.c"
     51#include "arm-link.c"
     52#include "arm-asm.c"
     53#endif
     54#ifdef TCC_TARGET_ARM64
     55#include "arm64-gen.c"
     56#include "arm64-link.c"
    4757#endif
    4858#ifdef TCC_TARGET_C67
    4959#include "c67-gen.c"
     60#include "c67-link.c"
     61#include "tcccoff.c"
    5062#endif
    5163#ifdef TCC_TARGET_X86_64
    5264#include "x86_64-gen.c"
    53 #endif
    54 #ifdef TCC_TARGET_IL
    55 #include "il-gen.c"
     65#include "x86_64-link.c"
     66#include "i386-asm.c"
    5667#endif
    5768#ifdef CONFIG_TCC_ASM
    5869#include "tccasm.c"
    59 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
    60 #include "i386-asm.c"
    61 #endif
    62 #endif
    63 #ifdef TCC_TARGET_COFF
    64 #include "tcccoff.c"
    6570#endif
    6671#ifdef TCC_TARGET_PE
     
    8287
    8388/********************************************************/
    84 
    8589#ifdef _WIN32
    86 char *normalize_slashes(char *path)
     90ST_FUNC char *normalize_slashes(char *path)
    8791{
    8892    char *p;
     
    9397}
    9498
    95 #if 0
    9699static HMODULE tcc_module;
    97100
     
    102105    GetModuleFileNameA(tcc_module, path, sizeof path);
    103106    p = tcc_basename(normalize_slashes(strlwr(path)));
    104     if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
    105         p -= 5;
    106     else if (p > path)
    107         p--;
     107    if (p > path)
     108        --p;
    108109    *p = 0;
    109110    tcc_set_lib_path(s, path);
     
    119120#endif
    120121
    121 #ifndef CONFIG_TCC_STATIC
    122 void dlclose(void *p)
    123 {
    124     FreeLibrary((HMODULE)p);
    125 }
    126 #endif
    127 #else
    128 extern void tcc_set_lib_path_w32(TCCState *s);
    129 extern void dlclose(void *p);
    130 #endif
    131 
    132122#ifdef LIBTCC_AS_DLL
    133 BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
     123BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
    134124{
    135125    if (DLL_PROCESS_ATTACH == dwReason)
     
    142132/********************************************************/
    143133/* copy a string and truncate it. */
    144 PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)
     134ST_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)
    145135{
    146136    char *q, *q_end;
     
    162152
    163153/* strcat and truncate. */
    164 PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)
     154ST_FUNC char *pstrcat(char *buf, int buf_size, const char *s)
    165155{
    166156    int len;
    167157    len = strlen(buf);
    168     if (len < buf_size) 
     158    if (len < buf_size)
    169159        pstrcpy(buf + len, buf_size - len, s);
    170160    return buf;
    171161}
    172162
    173 PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num)
     163ST_FUNC char *pstrncpy(char *out, const char *in, size_t num)
    174164{
    175165    memcpy(out, in, num);
     
    205195#undef realloc
    206196
    207 #ifdef MEM_DEBUG
    208 ST_DATA int mem_cur_size;
    209 ST_DATA int mem_max_size;
    210 unsigned malloc_usable_size(void*);
    211 #endif
     197#ifndef MEM_DEBUG
    212198
    213199PUB_FUNC void tcc_free(void *ptr)
    214200{
    215 #ifdef MEM_DEBUG
    216     mem_cur_size -= malloc_usable_size(ptr);
    217 #endif
    218         free(ptr);
     201    free(ptr);
    219202}
    220203
     
    224207    ptr = malloc(size);
    225208    if (!ptr && size)
    226         tcc_error("memory full");
    227 #ifdef MEM_DEBUG
    228     mem_cur_size += malloc_usable_size(ptr);
    229     if (mem_cur_size > mem_max_size)
    230         mem_max_size = mem_cur_size;
    231 #endif
     209        tcc_error("memory full (malloc)");
    232210    return ptr;
    233211}
     
    244222{
    245223    void *ptr1;
    246 #ifdef MEM_DEBUG
    247     mem_cur_size -= malloc_usable_size(ptr);
    248 #endif
    249224    ptr1 = realloc(ptr, size);
    250225    if (!ptr1 && size)
    251         tcc_error("memory full");
    252 #ifdef MEM_DEBUG
    253     /* NOTE: count not correct if alloc error, but not critical */
    254     mem_cur_size += malloc_usable_size(ptr1);
    255     if (mem_cur_size > mem_max_size)
    256         mem_max_size = mem_cur_size;
    257 #endif
     226        tcc_error("memory full (realloc)");
    258227    return ptr1;
    259228}
     
    267236}
    268237
    269 PUB_FUNC void tcc_memstats(void)
    270 {
    271 #ifdef MEM_DEBUG
    272     printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
    273 #endif
    274 }
     238PUB_FUNC void tcc_memcheck(void)
     239{
     240}
     241
     242#else
     243
     244#define MEM_DEBUG_MAGIC1 0xFEEDDEB1
     245#define MEM_DEBUG_MAGIC2 0xFEEDDEB2
     246#define MEM_DEBUG_MAGIC3 0xFEEDDEB3
     247#define MEM_DEBUG_FILE_LEN 40
     248#define MEM_DEBUG_CHECK3(header) \
     249    ((mem_debug_header_t*)((char*)header + header->size))->magic3
     250#define MEM_USER_PTR(header) \
     251    ((char *)header + offsetof(mem_debug_header_t, magic3))
     252#define MEM_HEADER_PTR(ptr) \
     253    (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3))
     254
     255struct mem_debug_header {
     256    unsigned magic1;
     257    unsigned size;
     258    struct mem_debug_header *prev;
     259    struct mem_debug_header *next;
     260    int line_num;
     261    char file_name[MEM_DEBUG_FILE_LEN + 1];
     262    unsigned magic2;
     263    ALIGNED(16) unsigned magic3;
     264};
     265
     266typedef struct mem_debug_header mem_debug_header_t;
     267
     268static mem_debug_header_t *mem_debug_chain;
     269static unsigned mem_cur_size;
     270static unsigned mem_max_size;
     271
     272static mem_debug_header_t *malloc_check(void *ptr, const char *msg)
     273{
     274    mem_debug_header_t * header = MEM_HEADER_PTR(ptr);
     275    if (header->magic1 != MEM_DEBUG_MAGIC1 ||
     276        header->magic2 != MEM_DEBUG_MAGIC2 ||
     277        MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 ||
     278        header->size == (unsigned)-1) {
     279        fprintf(stderr, "%s check failed\n", msg);
     280        if (header->magic1 == MEM_DEBUG_MAGIC1)
     281            fprintf(stderr, "%s:%u: block allocated here.\n",
     282                header->file_name, header->line_num);
     283        exit(1);
     284    }
     285    return header;
     286}
     287
     288PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
     289{
     290    int ofs;
     291    mem_debug_header_t *header;
     292
     293    header = malloc(sizeof(mem_debug_header_t) + size);
     294    if (!header)
     295        tcc_error("memory full (malloc)");
     296
     297    header->magic1 = MEM_DEBUG_MAGIC1;
     298    header->magic2 = MEM_DEBUG_MAGIC2;
     299    header->size = size;
     300    MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3;
     301    header->line_num = line;
     302    ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
     303    strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
     304    header->file_name[MEM_DEBUG_FILE_LEN] = 0;
     305
     306    header->next = mem_debug_chain;
     307    header->prev = NULL;
     308    if (header->next)
     309        header->next->prev = header;
     310    mem_debug_chain = header;
     311
     312    mem_cur_size += size;
     313    if (mem_cur_size > mem_max_size)
     314        mem_max_size = mem_cur_size;
     315
     316    return MEM_USER_PTR(header);
     317}
     318
     319PUB_FUNC void tcc_free_debug(void *ptr)
     320{
     321    mem_debug_header_t *header;
     322    if (!ptr)
     323        return;
     324    header = malloc_check(ptr, "tcc_free");
     325    mem_cur_size -= header->size;
     326    header->size = (unsigned)-1;
     327    if (header->next)
     328        header->next->prev = header->prev;
     329    if (header->prev)
     330        header->prev->next = header->next;
     331    if (header == mem_debug_chain)
     332        mem_debug_chain = header->next;
     333    free(header);
     334}
     335
     336PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line)
     337{
     338    void *ptr;
     339    ptr = tcc_malloc_debug(size,file,line);
     340    memset(ptr, 0, size);
     341    return ptr;
     342}
     343
     344PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line)
     345{
     346    mem_debug_header_t *header;
     347    int mem_debug_chain_update = 0;
     348    if (!ptr)
     349        return tcc_malloc_debug(size, file, line);
     350    header = malloc_check(ptr, "tcc_realloc");
     351    mem_cur_size -= header->size;
     352    mem_debug_chain_update = (header == mem_debug_chain);
     353    header = realloc(header, sizeof(mem_debug_header_t) + size);
     354    if (!header)
     355        tcc_error("memory full (realloc)");
     356    header->size = size;
     357    MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3;
     358    if (header->next)
     359        header->next->prev = header;
     360    if (header->prev)
     361        header->prev->next = header;
     362    if (mem_debug_chain_update)
     363        mem_debug_chain = header;
     364    mem_cur_size += size;
     365    if (mem_cur_size > mem_max_size)
     366        mem_max_size = mem_cur_size;
     367    return MEM_USER_PTR(header);
     368}
     369
     370PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
     371{
     372    char *ptr;
     373    ptr = tcc_malloc_debug(strlen(str) + 1, file, line);
     374    strcpy(ptr, str);
     375    return ptr;
     376}
     377
     378PUB_FUNC void tcc_memcheck(void)
     379{
     380    if (mem_cur_size) {
     381        mem_debug_header_t *header = mem_debug_chain;
     382        fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
     383            mem_cur_size, mem_max_size);
     384        while (header) {
     385            fprintf(stderr, "%s:%u: error: %u bytes leaked\n",
     386                header->file_name, header->line_num, header->size);
     387            header = header->next;
     388        }
     389#if MEM_DEBUG-0 == 2
     390        exit(2);
     391#endif
     392    }
     393}
     394#endif /* MEM_DEBUG */
    275395
    276396#define free(p) use_tcc_free(p)
     
    281401/* dynarrays */
    282402
    283 ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
     403ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
    284404{
    285405    int nb, nb_alloc;
    286406    void **pp;
    287    
     407
    288408    nb = *nb_ptr;
    289     pp = *ptab;
     409    pp = *(void ***)ptab;
    290410    /* every power of two we double array size */
    291411    if ((nb & (nb - 1)) == 0) {
     
    295415            nb_alloc = nb * 2;
    296416        pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
    297         *ptab = pp;
     417        *(void***)ptab = pp;
    298418    }
    299419    pp[nb++] = data;
     
    311431}
    312432
    313 static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
     433static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
    314434{
    315435    const char *p;
     
    319439
    320440        cstr_new(&str);
    321         for (p = in; c = *p, c != '\0' && c != PATHSEP; ++p) {
     441        for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) {
    322442            if (c == '{' && p[1] && p[2] == '}') {
    323443                c = p[1], p += 2;
    324444                if (c == 'B')
    325                     cstr_cat(&str, s->tcc_lib_path);
     445                    cstr_cat(&str, s->tcc_lib_path, -1);
    326446            } else {
    327447                cstr_ccat(&str, c);
    328448            }
    329449        }
    330         cstr_ccat(&str, '\0');
    331         dynarray_add(p_ary, p_nb_ary, str.data);
     450        if (str.size) {
     451            cstr_ccat(&str, '\0');
     452            dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
     453        }
     454        cstr_free(&str);
    332455        in = p+1;
    333456    } while (*p);
    334 }
    335 
    336 /********************************************************/
    337 
    338 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
    339 {
    340     Section *sec;
    341 
    342     sec = tcc_mallocz(sizeof(Section) + strlen(name));
    343     strcpy(sec->name, name);
    344     sec->sh_type = sh_type;
    345     sec->sh_flags = sh_flags;
    346     switch(sh_type) {
    347     case SHT_HASH:
    348     case SHT_REL:
    349     case SHT_RELA:
    350     case SHT_DYNSYM:
    351     case SHT_SYMTAB:
    352     case SHT_DYNAMIC:
    353         sec->sh_addralign = 4;
    354         break;
    355     case SHT_STRTAB:
    356         sec->sh_addralign = 1;
    357         break;
    358     default:
    359         sec->sh_addralign = 32; /* default conservative alignment */
    360         break;
    361     }
    362 
    363     if (sh_flags & SHF_PRIVATE) {
    364         dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
    365     } else {
    366         sec->sh_num = s1->nb_sections;
    367         dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
    368     }
    369 
    370     return sec;
    371 }
    372 
    373 static void free_section(Section *s)
    374 {
    375     tcc_free(s->data);
    376 }
    377 
    378 /* realloc section and set its content to zero */
    379 ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
    380 {
    381     unsigned long size;
    382     unsigned char *data;
    383    
    384     size = sec->data_allocated;
    385     if (size == 0)
    386         size = 1;
    387     while (size < new_size)
    388         size = size * 2;
    389     data = tcc_realloc(sec->data, size);
    390     memset(data + sec->data_allocated, 0, size - sec->data_allocated);
    391     sec->data = data;
    392     sec->data_allocated = size;
    393 }
    394 
    395 /* reserve at least 'size' bytes in section 'sec' from
    396    sec->data_offset. */
    397 ST_FUNC void *section_ptr_add(Section *sec, unsigned long size)
    398 {
    399     unsigned long offset, offset1;
    400 
    401     offset = sec->data_offset;
    402     offset1 = offset + size;
    403     if (offset1 > sec->data_allocated)
    404         section_realloc(sec, offset1);
    405     sec->data_offset = offset1;
    406     return sec->data + offset;
    407 }
    408 
    409 /* reserve at least 'size' bytes from section start */
    410 ST_FUNC void section_reserve(Section *sec, unsigned long size)
    411 {
    412     if (size > sec->data_allocated)
    413         section_realloc(sec, size);
    414     if (size > sec->data_offset)
    415         sec->data_offset = size;
    416 }
    417 
    418 /* return a reference to a section, and create it if it does not
    419    exists */
    420 ST_FUNC Section *find_section(TCCState *s1, const char *name)
    421 {
    422     Section *sec;
    423     int i;
    424     for(i = 1; i < s1->nb_sections; i++) {
    425         sec = s1->sections[i];
    426         if (!strcmp(name, sec->name))
    427             return sec;
    428     }
    429     /* sections are created as PROGBITS */
    430     return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
    431 }
    432 
    433 /* update sym->c so that it points to an external symbol in section
    434    'section' with value 'value' */
    435 ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
    436                             addr_t value, unsigned long size,
    437                             int can_add_underscore)
    438 {
    439     int sym_type, sym_bind, sh_num, info, other;
    440     ElfW(Sym) *esym;
    441     const char *name;
    442     char buf1[256];
    443 
    444     if (section == NULL)
    445         sh_num = SHN_UNDEF;
    446     else if (section == SECTION_ABS)
    447         sh_num = SHN_ABS;
    448     else
    449         sh_num = section->sh_num;
    450 
    451     if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
    452         sym_type = STT_FUNC;
    453     } else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
    454         sym_type = STT_NOTYPE;
    455     } else {
    456         sym_type = STT_OBJECT;
    457     }
    458 
    459     if (sym->type.t & VT_STATIC)
    460         sym_bind = STB_LOCAL;
    461     else {
    462         if (sym->type.t & VT_WEAK)
    463             sym_bind = STB_WEAK;
    464         else
    465             sym_bind = STB_GLOBAL;
    466     }
    467 
    468     if (!sym->c) {
    469         name = get_tok_str(sym->v, NULL);
    470 #ifdef CONFIG_TCC_BCHECK
    471         if (tcc_state->do_bounds_check) {
    472             char buf[32];
    473 
    474             /* XXX: avoid doing that for statics ? */
    475             /* if bound checking is activated, we change some function
    476                names by adding the "__bound" prefix */
    477             switch(sym->v) {
    478 #ifdef TCC_TARGET_PE
    479             /* XXX: we rely only on malloc hooks */
    480             case TOK_malloc:
    481             case TOK_free:
    482             case TOK_realloc:
    483             case TOK_memalign:
    484             case TOK_calloc:
    485 #endif
    486             case TOK_memcpy:
    487             case TOK_memmove:
    488             case TOK_memset:
    489             case TOK_strlen:
    490             case TOK_strcpy:
    491 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
    492             case TOK_alloca:
    493 #endif
    494                 strcpy(buf, "__bound_");
    495                 strcat(buf, name);
    496                 name = buf;
    497                 break;
    498             }
    499         }
    500 #endif
    501         other = 0;
    502 
    503 #ifdef TCC_TARGET_PE
    504         if (sym->type.t & VT_EXPORT)
    505             other |= 1;
    506         if (sym_type == STT_FUNC && sym->type.ref) {
    507             int attr = sym->type.ref->r;
    508             if (FUNC_EXPORT(attr))
    509                 other |= 1;
    510             if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
    511                 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
    512                 name = buf1;
    513                 other |= 2;
    514                 can_add_underscore = 0;
    515             }
    516         } else {
    517             if (find_elf_sym(tcc_state->dynsymtab_section, name))
    518                 other |= 4;
    519             if (sym->type.t & VT_IMPORT)
    520                 other |= 4;
    521         }
    522 #endif
    523         if (tcc_state->leading_underscore && can_add_underscore) {
    524             buf1[0] = '_';
    525             pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
    526             name = buf1;
    527         }
    528         if (sym->asm_label) {
    529             name = sym->asm_label;
    530         }
    531         info = ELFW(ST_INFO)(sym_bind, sym_type);
    532         sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
    533     } else {
    534         esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
    535         esym->st_value = value;
    536         esym->st_size = size;
    537         esym->st_shndx = sh_num;
    538     }
    539 }
    540 
    541 ST_FUNC void put_extern_sym(Sym *sym, Section *section,
    542                            addr_t value, unsigned long size)
    543 {
    544     put_extern_sym2(sym, section, value, size, 1);
    545 }
    546 
    547 /* add a new relocation entry to symbol 'sym' in section 's' */
    548 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
    549 {
    550     int c = 0;
    551     if (sym) {
    552         if (0 == sym->c)
    553             put_extern_sym(sym, NULL, 0, 0);
    554         c = sym->c;
    555     }
    556     /* now we can add ELF relocation info */
    557     put_elf_reloc(symtab_section, s, offset, type, c);
    558457}
    559458
     
    579478    char buf[2048];
    580479    BufferedFile **pf, *f;
    581    
     480
    582481    buf[0] = '\0';
    583482    /* use upper file if inline ":asm:" or token ":paste:" */
    584     for (f = file; f && f->filename[0] == ':'; f = f->prev);
     483    for (f = file; f && f->filename[0] == ':'; f = f->prev)
     484     ;
    585485    if (f) {
    586486        for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
    587487            strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
    588488                (*pf)->filename, (*pf)->line_num);
    589         if (f->line_num > 0) {
     489        if (s1->error_set_jmp_enabled) {
    590490            strcat_printf(buf, sizeof(buf), "%s:%d: ",
    591                 f->filename, f->line_num);
     491                f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
    592492        } else {
    593493            strcat_printf(buf, sizeof(buf), "%s: ",
     
    605505    if (!s1->error_func) {
    606506        /* default case: stderr */
     507        if (s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout)
     508            /* print a newline during tcc -E */
     509            printf("\n"), fflush(stdout);
     510        fflush(stdout); /* flush -v output */
    607511        fprintf(stderr, "%s\n", buf);
     512        fflush(stderr); /* print error/warning now (win32) */
    608513    } else {
    609514        s1->error_func(s1->error_opaque, buf);
     
    669574    int buflen = initlen ? initlen : IO_BUF_SIZE;
    670575
    671     bf = tcc_malloc(sizeof(BufferedFile) + buflen);
     576    bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
    672577    bf->buf_ptr = bf->buffer;
    673578    bf->buf_end = bf->buffer + initlen;
    674579    bf->buf_end[0] = CH_EOB; /* put eob symbol */
    675580    pstrcpy(bf->filename, sizeof(bf->filename), filename);
    676 #ifdef _WIN32
    677     normalize_slashes(bf->filename);
    678 #endif
     581    bf->true_filename = bf->filename;
    679582    bf->line_num = 1;
    680     bf->ifndef_macro = 0;
    681583    bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
    682584    bf->fd = -1;
    683585    bf->prev = file;
    684586    file = bf;
     587    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
    685588}
    686589
     
    692595        total_lines += bf->line_num;
    693596    }
     597    if (bf->true_filename != bf->filename)
     598        tcc_free(bf->true_filename);
    694599    file = bf->prev;
    695600    tcc_free(bf);
     
    700605    int fd;
    701606    if (strcmp(filename, "-") == 0)
    702         fd = 0, filename = "stdin";
     607        fd = 0, filename = "<stdin>";
    703608    else
    704609        fd = open(filename, O_RDONLY | O_BINARY);
     
    708613    if (fd < 0)
    709614        return -1;
    710 
    711615    tcc_open_bf(s1, filename, 0);
     616#ifdef _WIN32
     617    normalize_slashes(file->filename);
     618#endif
    712619    file->fd = fd;
    713620    return fd;
    714621}
    715622
    716 /* compile the C file opened in 'file'. Return non zero if errors. */
     623/* compile the file opened in 'file'. Return non zero if errors. */
    717624static int tcc_compile(TCCState *s1)
    718625{
    719626    Sym *define_start;
    720     SValue *pvtop;
    721     char buf[512];
    722     volatile int section_sym;
    723 
    724 #ifdef INC_DEBUG
    725     printf("%s: **** new file\n", file->filename);
    726 #endif
    727     preprocess_init(s1);
    728 
    729     cur_text_section = NULL;
    730     funcname = "";
    731     anon_sym = SYM_FIRST_ANOM;
    732 
    733     /* file info: full path + filename */
    734     section_sym = 0; /* avoid warning */
    735     if (s1->do_debug) {
    736         section_sym = put_elf_sym(symtab_section, 0, 0,
    737                                   ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
    738                                   text_section->sh_num, NULL);
    739         getcwd(buf, sizeof(buf));
    740 #ifdef _WIN32
    741         normalize_slashes(buf);
    742 #endif
    743         pstrcat(buf, sizeof(buf), "/");
    744         put_stabs_r(buf, N_SO, 0, 0,
    745                     text_section->data_offset, text_section, section_sym);
    746         put_stabs_r(file->filename, N_SO, 0, 0,
    747                     text_section->data_offset, text_section, section_sym);
    748     }
    749     /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
    750        symbols can be safely used */
    751     put_elf_sym(symtab_section, 0, 0,
    752                 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
    753                 SHN_ABS, file->filename);
    754 
    755     /* define some often used types */
    756     int_type.t = VT_INT;
    757 
    758     char_pointer_type.t = VT_BYTE;
    759     mk_pointer(&char_pointer_type);
    760 
    761 #if PTR_SIZE == 4
    762     size_type.t = VT_INT;
    763 #else
    764     size_type.t = VT_LLONG;
    765 #endif
    766 
    767     func_old_type.t = VT_FUNC;
    768     func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
    769 #ifdef TCC_TARGET_ARM
    770     arm_init_types();
    771 #endif
    772 
    773 #if 0
    774     /* define 'void *alloca(unsigned int)' builtin function */
    775     {
    776         Sym *s1;
    777 
    778         p = anon_sym++;
    779         sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
    780         s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
    781         s1->next = NULL;
    782         sym->next = s1;
    783         sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
    784     }
    785 #endif
     627    int filetype, is_asm;
    786628
    787629    define_start = define_stack;
    788     nocode_wanted = 1;
     630    filetype = s1->filetype;
     631    is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP;
     632    tccelf_begin_file(s1);
    789633
    790634    if (setjmp(s1->error_jmp_buf) == 0) {
     
    792636        s1->error_set_jmp_enabled = 1;
    793637
    794         ch = file->buf_ptr[0];
    795         tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
    796         parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
    797         pvtop = vtop;
    798         next();
    799         decl(VT_CONST);
    800         if (tok != TOK_EOF)
    801             expect("declaration");
    802         if (pvtop != vtop)
    803             tcc_warning("internal compiler error: vstack leak? (%d)", vtop - pvtop);
    804 
    805         /* end of translation unit info */
    806         if (s1->do_debug) {
    807             put_stabs_r(NULL, N_SO, 0, 0,
    808                         text_section->data_offset, text_section, section_sym);
     638        preprocess_start(s1, is_asm);
     639        if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
     640            tcc_preprocess(s1);
     641        } else if (is_asm) {
     642#ifdef CONFIG_TCC_ASM
     643            tcc_assemble(s1, filetype == AFF_TYPE_ASMPP);
     644#else
     645            tcc_error_noabort("asm not supported");
     646#endif
     647        } else {
     648            tccgen_compile(s1);
    809649        }
    810650    }
    811 
    812651    s1->error_set_jmp_enabled = 0;
    813652
    814     /* reset define stack, but leave -Dsymbols (may be incorrect if
    815        they are undefined) */
    816     free_defines(define_start);
    817 
    818     gen_inline_functions();
    819 
    820     sym_pop(&global_stack, NULL);
    821     sym_pop(&local_stack, NULL);
    822 
     653    preprocess_end(s1);
     654    free_inline_functions(s1);
     655    /* reset define stack, but keep -D and built-ins */
     656    free_defines(define_start);
     657    sym_pop(&global_stack, NULL, 0);
     658    sym_pop(&local_stack, NULL, 0);
     659    tccelf_end_file(s1);
    823660    return s1->nb_errors != 0 ? -1 : 0;
    824661}
     
    827664{
    828665    int len, ret;
     666
    829667    len = strlen(str);
    830 
    831668    tcc_open_bf(s, "<string>", len);
    832669    memcpy(file->buffer, str, len);
     
    853690
    854691    /* parse with define parser */
    855     ch = file->buf_ptr[0];
    856692    next_nomacro();
    857693    parse_define();
    858 
    859694    tcc_close();
    860695}
     
    875710static void tcc_cleanup(void)
    876711{
    877     int i, n;
    878712    if (NULL == tcc_state)
    879713        return;
     714    while (file)
     715        tcc_close();
     716    tccpp_delete(tcc_state);
    880717    tcc_state = NULL;
    881 
    882     /* free -D defines */
    883     free_defines(NULL);
    884 
    885     /* free tokens */
    886     n = tok_ident - TOK_IDENT;
    887     for(i = 0; i < n; i++)
    888         tcc_free(table_ident[i]);
    889     tcc_free(table_ident);
    890 
    891718    /* free sym_pools */
    892719    dynarray_reset(&sym_pools, &nb_sym_pools);
    893     /* string buffer */
    894     cstr_free(&tokcstr);
    895720    /* reset symbol stack */
    896721    sym_free_first = NULL;
    897     /* cleanup from error/setjmp */
    898     macro_ptr = NULL;
    899722}
    900723
     
    902725{
    903726    TCCState *s;
    904     char buffer[100];
    905     int a,b,c;
    906727
    907728    tcc_cleanup();
     
    911732        return NULL;
    912733    tcc_state = s;
     734    ++nb_states;
     735
     736    s->alacarte_link = 1;
     737    s->nocommon = 1;
     738    s->warn_implicit_function_declaration = 1;
     739    s->ms_extensions = 1;
     740
     741#ifdef CHAR_IS_UNSIGNED
     742    s->char_is_unsigned = 1;
     743#endif
     744#ifdef TCC_TARGET_I386
     745    s->seg_size = 32;
     746#endif
     747    /* enable this if you want symbols with leading underscore on windows: */
     748#if 0 /* def TCC_TARGET_PE */
     749    s->leading_underscore = 1;
     750#endif
    913751#ifdef _WIN32
    914752    tcc_set_lib_path_w32(s);
     
    916754    tcc_set_lib_path(s, CONFIG_TCCDIR);
    917755#endif
    918     s->output_type = TCC_OUTPUT_MEMORY;
    919     preprocess_new();
    920     s->include_stack_ptr = s->include_stack;
     756    tccelf_new(s);
     757    tccpp_new(s);
    921758
    922759    /* we add dummy defines for some special macros to speed up tests
     
    926763    define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
    927764    define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
    928 
    929     /* define __TINYC__ 92X  */
    930     sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
    931     sprintf(buffer, "%d", a*10000 + b*100 + c);
    932     tcc_define_symbol(s, "__TINYC__", buffer);
     765    define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
     766    {
     767        /* define __TINYC__ 92X  */
     768        char buffer[32]; int a,b,c;
     769        sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
     770        sprintf(buffer, "%d", a*10000 + b*100 + c);
     771        tcc_define_symbol(s, "__TINYC__", buffer);
     772    }
    933773
    934774    /* standard defines */
    935775    tcc_define_symbol(s, "__STDC__", NULL);
    936776    tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
     777    tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
    937778
    938779    /* target defines */
     
    952793    tcc_define_symbol(s, "arm", NULL);
    953794    tcc_define_symbol(s, "__APCS_32__", NULL);
     795    tcc_define_symbol(s, "__ARMEL__", NULL);
     796#if defined(TCC_ARM_EABI)
     797    tcc_define_symbol(s, "__ARM_EABI__", NULL);
     798#endif
     799#if defined(TCC_ARM_HARDFLOAT)
     800    s->float_abi = ARM_HARD_FLOAT;
     801    tcc_define_symbol(s, "__ARM_PCS_VFP", NULL);
     802#else
     803    s->float_abi = ARM_SOFTFP_FLOAT;
     804#endif
     805#elif defined(TCC_TARGET_ARM64)
     806    tcc_define_symbol(s, "__aarch64__", NULL);
     807#elif defined TCC_TARGET_C67
     808    tcc_define_symbol(s, "__C67__", NULL);
    954809#endif
    955810
     
    963818    tcc_define_symbol(s, "__unix", NULL);
    964819    tcc_define_symbol(s, "unix", NULL);
    965 # if defined(__linux)
     820# if defined(__linux__)
    966821    tcc_define_symbol(s, "__linux__", NULL);
    967822    tcc_define_symbol(s, "__linux", NULL);
    968823# endif
    969824# if defined(__FreeBSD__)
    970 #  define str(s) #s
    971     tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
    972 #  undef str
     825    tcc_define_symbol(s, "__FreeBSD__", "__FreeBSD__");
     826    /* No 'Thread Storage Local' on FreeBSD with tcc */
     827    tcc_define_symbol(s, "__NO_TLS", NULL);
    973828# endif
    974829# if defined(__FreeBSD_kernel__)
    975830    tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
    976831# endif
     832# if defined(__NetBSD__)
     833    tcc_define_symbol(s, "__NetBSD__", "__NetBSD__");
     834# endif
     835# if defined(__OpenBSD__)
     836    tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__");
     837# endif
    977838#endif
    978839
    979840    /* TinyCC & gcc defines */
    980 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
     841#if PTR_SIZE == 4
     842    /* 32bit systems. */
     843    tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
     844    tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
     845    tcc_define_symbol(s, "__ILP32__", NULL);
     846#elif LONG_SIZE == 4
     847    /* 64bit Windows. */
    981848    tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
    982849    tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
     850    tcc_define_symbol(s, "__LLP64__", NULL);
    983851#else
     852    /* Other 64bit systems. */
    984853    tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long");
    985854    tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long");
     855    tcc_define_symbol(s, "__LP64__", NULL);
    986856#endif
    987857
    988858#ifdef TCC_TARGET_PE
    989859    tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
     860    tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short");
    990861#else
    991862    tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
    992 #endif
    993 
    994 #ifndef TCC_TARGET_PE
     863    /* wint_t is unsigned int by default, but (signed) int on BSDs
     864       and unsigned short on windows.  Other OSes might have still
     865       other conventions, sigh.  */
     866# if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) \
     867  || defined(__NetBSD__) || defined(__OpenBSD__)
     868    tcc_define_symbol(s, "__WINT_TYPE__", "int");
     869#  ifdef __FreeBSD__
     870    /* define __GNUC__ to have some useful stuff from sys/cdefs.h
     871       that are unconditionally used in FreeBSDs other system headers :/ */
     872    tcc_define_symbol(s, "__GNUC__", "2");
     873    tcc_define_symbol(s, "__GNUC_MINOR__", "7");
     874    tcc_define_symbol(s, "__builtin_alloca", "alloca");
     875#  endif
     876# else
     877    tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
    995878    /* glibc defines */
    996     tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
    997     tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
    998     /* default library paths */
    999     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
    1000     /* paths for crt objects */
    1001     tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
    1002 #endif
    1003 
    1004     /* no section zero */
    1005     dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
    1006 
    1007     /* create standard sections */
    1008     text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
    1009     data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
    1010     bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
    1011 
    1012     /* symbols are always generated for linking stage */
    1013     symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
    1014                                 ".strtab",
    1015                                 ".hashtab", SHF_PRIVATE);
    1016     strtab_section = symtab_section->link;
    1017     s->symtab = symtab_section;
    1018    
    1019     /* private symbol table for dynamic symbols */
    1020     s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
    1021                                       ".dynstrtab",
    1022                                       ".dynhashtab", SHF_PRIVATE);
    1023     s->alacarte_link = 1;
    1024     s->nocommon = 1;
    1025     s->section_align = ELF_PAGE_SIZE;
    1026 
    1027 #ifdef CHAR_IS_UNSIGNED
    1028     s->char_is_unsigned = 1;
    1029 #endif
    1030     /* enable this if you want symbols with leading underscore on windows: */
    1031 #if 0 //def TCC_TARGET_PE
    1032     s->leading_underscore = 1;
    1033 #endif
    1034 #ifdef TCC_TARGET_I386
    1035     s->seg_size = 32;
    1036 #endif
     879    tcc_define_symbol(s, "__REDIRECT(name, proto, alias)",
     880        "name proto __asm__ (#alias)");
     881    tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
     882        "name proto __asm__ (#alias) __THROW");
     883# endif
     884# if defined(TCC_MUSL)
     885    tcc_define_symbol(s, "__DEFINED_va_list", "");
     886    tcc_define_symbol(s, "__DEFINED___isoc_va_list", "");
     887    tcc_define_symbol(s, "__isoc_va_list", "void *");
     888# endif /* TCC_MUSL */
     889    /* Some GCC builtins that are simple to express as macros.  */
     890    tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
     891#endif /* ndef TCC_TARGET_PE */
    1037892    return s;
    1038893}
     
    1040895LIBTCCAPI void tcc_delete(TCCState *s1)
    1041896{
    1042     int i;
    1043 
    1044897    tcc_cleanup();
    1045898
    1046     /* free all sections */
    1047     for(i = 1; i < s1->nb_sections; i++)
    1048         free_section(s1->sections[i]);
    1049     dynarray_reset(&s1->sections, &s1->nb_sections);
    1050 
    1051     for(i = 0; i < s1->nb_priv_sections; i++)
    1052         free_section(s1->priv_sections[i]);
    1053     dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
    1054        
    1055     /* free any loaded DLLs */
    1056     for ( i = 0; i < s1->nb_loaded_dlls; i++) {
    1057         DLLReference *ref = s1->loaded_dlls[i];
    1058         if ( ref->handle )
    1059             dlclose(ref->handle);
    1060     }
    1061    
    1062     /* free loaded dlls array */
    1063     dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
     899    /* free sections */
     900    tccelf_delete(s1);
    1064901
    1065902    /* free library paths */
     
    1071908    dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
    1072909    dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
     910    dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files);
    1073911
    1074912    tcc_free(s1->tcc_lib_path);
     
    1081919    dynarray_reset(&s1->files, &s1->nb_files);
    1082920    dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
     921    dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
     922    dynarray_reset(&s1->argv, &s1->argc);
    1083923
    1084924#ifdef TCC_IS_NATIVE
    1085 # ifdef HAVE_SELINUX
    1086     munmap (s1->write_mem, s1->mem_size);
    1087     munmap (s1->runtime_mem, s1->mem_size);   
    1088 # else
    1089     tcc_free(s1->runtime_mem);
     925    /* free runtime memory */
     926    tcc_run_free(s1);
     927#endif
     928
     929    tcc_free(s1);
     930    if (0 == --nb_states)
     931        tcc_memcheck();
     932}
     933
     934LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
     935{
     936    s->output_type = output_type;
     937
     938    /* always elf for objects */
     939    if (output_type == TCC_OUTPUT_OBJ)
     940        s->output_format = TCC_OUTPUT_FORMAT_ELF;
     941
     942    if (s->char_is_unsigned)
     943        tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
     944
     945    if (!s->nostdinc) {
     946        /* default include paths */
     947        /* -isystem paths have already been handled */
     948        tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
     949    }
     950
     951#ifdef CONFIG_TCC_BCHECK
     952    if (s->do_bounds_check) {
     953        /* if bound checking, then add corresponding sections */
     954        tccelf_bounds_new(s);
     955        /* define symbol */
     956        tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
     957    }
     958#endif
     959    if (s->do_debug) {
     960        /* add debug sections */
     961        tccelf_stab_new(s);
     962    }
     963
     964    tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
     965
     966#ifdef TCC_TARGET_PE
     967# ifdef _WIN32
     968    if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ)
     969        tcc_add_systemdir(s);
    1090970# endif
    1091 #endif
    1092 
    1093     tcc_free(s1);
     971#else
     972    /* paths for crt objects */
     973    tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
     974    /* add libc crt1/crti objects */
     975    if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
     976        !s->nostdlib) {
     977        if (output_type != TCC_OUTPUT_DLL)
     978            tcc_add_crt(s, "crt1.o");
     979        tcc_add_crt(s, "crti.o");
     980    }
     981#endif
     982    return 0;
    1094983}
    1095984
    1096985LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
    1097986{
    1098     tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);
     987    tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
    1099988    return 0;
    1100989}
     
    1102991LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
    1103992{
    1104     tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
     993    tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
    1105994    return 0;
    1106995}
     
    1108997ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
    1109998{
    1110     const char *ext;
    1111     ElfW(Ehdr) ehdr;
    1112     int fd, ret, size;
    1113 
    1114     /* find source file type with extension */
    1115     ext = tcc_fileextension(filename);
    1116     if (ext[0])
    1117         ext++;
    1118 
    1119 #ifdef CONFIG_TCC_ASM
    1120     /* if .S file, define __ASSEMBLER__ like gcc does */
    1121     if (!strcmp(ext, "S"))
    1122         tcc_define_symbol(s1, "__ASSEMBLER__", NULL);
    1123 #endif
     999    int ret;
    11241000
    11251001    /* open the file */
     
    11321008
    11331009    /* update target deps */
    1134     dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
     1010    dynarray_add(&s1->target_deps, &s1->nb_target_deps,
    11351011            tcc_strdup(filename));
    11361012
    1137     if (flags & AFF_PREPROCESS) {
    1138         ret = tcc_preprocess(s1);
    1139         goto the_end;
    1140     }
    1141 
    1142     if (!ext[0] || !PATHCMP(ext, "c")) {
    1143         /* C file assumed */
    1144         ret = tcc_compile(s1);
    1145         goto the_end;
    1146     }
    1147 
    1148 #ifdef CONFIG_TCC_ASM
    1149     if (!strcmp(ext, "S")) {
    1150         /* preprocessed assembler */
    1151         ret = tcc_assemble(s1, 1);
    1152         goto the_end;
    1153     }
    1154 
    1155     if (!strcmp(ext, "s")) {
    1156         /* non preprocessed assembler */
    1157         ret = tcc_assemble(s1, 0);
    1158         goto the_end;
    1159     }
    1160 #endif
    1161 
    1162     fd = file->fd;
    1163     /* assume executable format: auto guess file type */
    1164     size = read(fd, &ehdr, sizeof(ehdr));
    1165     lseek(fd, 0, SEEK_SET);
    1166     if (size <= 0) {
    1167         tcc_error_noabort("could not read header");
    1168         goto the_end;
    1169     }
    1170 
    1171     if (size == sizeof(ehdr) &&
    1172         ehdr.e_ident[0] == ELFMAG0 &&
    1173         ehdr.e_ident[1] == ELFMAG1 &&
    1174         ehdr.e_ident[2] == ELFMAG2 &&
    1175         ehdr.e_ident[3] == ELFMAG3) {
    1176 
    1177         /* do not display line number if error */
    1178         file->line_num = 0;
    1179         if (ehdr.e_type == ET_REL) {
     1013    if (flags & AFF_TYPE_BIN) {
     1014        ElfW(Ehdr) ehdr;
     1015        int fd, obj_type;
     1016
     1017        fd = file->fd;
     1018        obj_type = tcc_object_type(fd, &ehdr);
     1019        lseek(fd, 0, SEEK_SET);
     1020
     1021#ifdef TCC_TARGET_MACHO
     1022        if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib"))
     1023            obj_type = AFF_BINTYPE_DYN;
     1024#endif
     1025
     1026        switch (obj_type) {
     1027        case AFF_BINTYPE_REL:
    11801028            ret = tcc_load_object_file(s1, fd, 0);
    1181             goto the_end;
    1182 
    1183         }
     1029            break;
    11841030#ifndef TCC_TARGET_PE
    1185         if (ehdr.e_type == ET_DYN) {
     1031        case AFF_BINTYPE_DYN:
    11861032            if (s1->output_type == TCC_OUTPUT_MEMORY) {
     1033                ret = 0;
    11871034#ifdef TCC_IS_NATIVE
    1188                 void *h;
    1189                 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
    1190                 if (h)
    1191 #endif
    1192                     ret = 0;
     1035                if (NULL == dlopen(filename, RTLD_GLOBAL | RTLD_LAZY))
     1036                    ret = -1;
     1037#endif
    11931038            } else {
    1194                 ret = tcc_load_dll(s1, fd, filename, 
     1039                ret = tcc_load_dll(s1, fd, filename,
    11951040                                   (flags & AFF_REFERENCED_DLL) != 0);
    11961041            }
    1197             goto the_end;
     1042            break;
     1043#endif
     1044        case AFF_BINTYPE_AR:
     1045            ret = tcc_load_archive(s1, fd);
     1046            break;
     1047#ifdef TCC_TARGET_COFF
     1048        case AFF_BINTYPE_C67:
     1049            ret = tcc_load_coff(s1, fd);
     1050            break;
     1051#endif
     1052        default:
     1053#ifdef TCC_TARGET_PE
     1054            ret = pe_load_file(s1, filename, fd);
     1055#else
     1056            /* as GNU ld, consider it is an ld script if not recognized */
     1057            ret = tcc_load_ldscript(s1);
     1058#endif
     1059            if (ret < 0)
     1060                tcc_error_noabort("unrecognized file type");
     1061            break;
    11981062        }
    1199 #endif
    1200         tcc_error_noabort("unrecognized ELF file");
    1201         goto the_end;
    1202     }
    1203 
    1204     if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
    1205         file->line_num = 0; /* do not display line number if error */
    1206         ret = tcc_load_archive(s1, fd);
    1207         goto the_end;
    1208     }
    1209 
    1210 #ifdef TCC_TARGET_COFF
    1211     if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
    1212         ret = tcc_load_coff(s1, fd);
    1213         goto the_end;
    1214     }
    1215 #endif
    1216 
    1217 #ifdef TCC_TARGET_PE
    1218     ret = pe_load_file(s1, filename, fd);
    1219 #else
    1220     /* as GNU ld, consider it is an ld script if not recognized */
    1221     ret = tcc_load_ldscript(s1);
    1222 #endif
    1223     if (ret < 0)
    1224         tcc_error_noabort("unrecognized file type");
    1225 
    1226 the_end:
     1063    } else {
     1064        ret = tcc_compile(s1);
     1065    }
    12271066    tcc_close();
    12281067    return ret;
     
    12311070LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
    12321071{
    1233     if (s->output_type == TCC_OUTPUT_PREPROCESS)
    1234         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS);
    1235     else
    1236         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
     1072    int filetype = s->filetype;
     1073    int flags = AFF_PRINT_ERROR;
     1074    if (filetype == 0) {
     1075        /* use a file extension to detect a filetype */
     1076        const char *ext = tcc_fileextension(filename);
     1077        if (ext[0]) {
     1078            ext++;
     1079            if (!strcmp(ext, "S"))
     1080                filetype = AFF_TYPE_ASMPP;
     1081            else if (!strcmp(ext, "s"))
     1082                filetype = AFF_TYPE_ASM;
     1083            else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i"))
     1084                filetype = AFF_TYPE_C;
     1085            else
     1086                flags |= AFF_TYPE_BIN;
     1087        } else {
     1088            filetype = AFF_TYPE_C;
     1089        }
     1090        s->filetype = filetype;
     1091    }
     1092    return tcc_add_file_internal(s, filename, flags);
    12371093}
    12381094
    12391095LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
    12401096{
    1241     tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);
     1097    tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
    12421098    return 0;
    12431099}
     
    12511107    for(i = 0; i < nb_paths; i++) {
    12521108        snprintf(buf, sizeof(buf), fmt, paths[i], filename);
    1253         if (tcc_add_file_internal(s, buf, flags) == 0)
     1109        if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
    12541110            return 0;
    12551111    }
     
    12761132LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
    12771133{
    1278 #ifdef TCC_TARGET_PE
     1134#if defined TCC_TARGET_PE
    12791135    const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
    12801136    const char **pp = s->static_link ? libs + 4 : libs;
     1137#elif defined TCC_TARGET_MACHO
     1138    const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
     1139    const char **pp = s->static_link ? libs + 1 : libs;
    12811140#else
    12821141    const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
     
    12921151}
    12931152
     1153PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
     1154{
     1155    int ret = tcc_add_library(s, libname);
     1156    if (ret < 0)
     1157        tcc_error_noabort("library '%s' not found", libname);
     1158    return ret;
     1159}
     1160
     1161/* handle #pragma comment(lib,) */
     1162ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
     1163{
     1164    int i;
     1165    for (i = 0; i < s1->nb_pragma_libs; i++)
     1166        tcc_add_library_err(s1, s1->pragma_libs[i]);
     1167}
     1168
    12941169LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
    12951170{
     
    12991174    pe_putimport(s, 0, name, (uintptr_t)val);
    13001175#else
    1301     /* XXX: Same problem on linux but currently "solved" elsewhere
    1302        via the rather dirty 'runtime_plt_and_got' hack. */
    1303     add_elf_sym(symtab_section, (uintptr_t)val, 0,
     1176    set_elf_sym(symtab_section, (uintptr_t)val, 0,
    13041177        ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
    13051178        SHN_ABS, name);
    1306 #endif
    1307     return 0;
    1308 }
    1309 
    1310 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
    1311 {
    1312     s->output_type = output_type;
    1313 
    1314     if (!s->nostdinc) {
    1315         /* default include paths */
    1316         /* -isystem paths have already been handled */
    1317         tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
    1318     }
    1319 
    1320     /* if bound checking, then add corresponding sections */
    1321 #ifdef CONFIG_TCC_BCHECK
    1322     if (s->do_bounds_check) {
    1323         /* define symbol */
    1324         tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
    1325         /* create bounds sections */
    1326         bounds_section = new_section(s, ".bounds",
    1327                                      SHT_PROGBITS, SHF_ALLOC);
    1328         lbounds_section = new_section(s, ".lbounds",
    1329                                       SHT_PROGBITS, SHF_ALLOC);
    1330     }
    1331 #endif
    1332 
    1333     if (s->char_is_unsigned) {
    1334         tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
    1335     }
    1336 
    1337     /* add debug sections */
    1338     if (s->do_debug) {
    1339         /* stab symbols */
    1340         stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
    1341         stab_section->sh_entsize = sizeof(Stab_Sym);
    1342         stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
    1343         put_elf_str(stabstr_section, "");
    1344         stab_section->link = stabstr_section;
    1345         /* put first entry */
    1346         put_stabs("", 0, 0, 0, 0);
    1347     }
    1348 
    1349 #ifdef TCC_TARGET_PE
    1350     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
    1351 # ifdef _WIN32
    1352     tcc_add_systemdir(s);
    1353 # endif
    1354 #else
    1355     /* add libc crt1/crti objects */
    1356     if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
    1357         !s->nostdlib) {
    1358         if (output_type != TCC_OUTPUT_DLL)
    1359             tcc_add_crt(s, "crt1.o");
    1360         tcc_add_crt(s, "crti.o");
    1361     }
    13621179#endif
    13631180    return 0;
     
    13791196} FlagDef;
    13801197
    1381 static const FlagDef warning_defs[] = {
    1382     { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
    1383     { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
    1384     { offsetof(TCCState, warn_error), 0, "error" },
    1385     { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
    1386       "implicit-function-declaration" },
    1387 };
    1388 
    1389 ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
    1390                     const char *name, int value)
    1391 {
    1392     int i;
     1198static int no_flag(const char **pp)
     1199{
     1200    const char *p = *pp;
     1201    if (*p != 'n' || *++p != 'o' || *++p != '-')
     1202        return 0;
     1203    *pp = p + 1;
     1204    return 1;
     1205}
     1206
     1207ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name)
     1208{
     1209    int value, ret;
    13931210    const FlagDef *p;
    13941211    const char *r;
    13951212
     1213    value = 1;
    13961214    r = name;
    1397     if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
    1398         r += 3;
    1399         value = !value;
    1400     }
    1401     for(i = 0, p = flags; i < nb_flags; i++, p++) {
    1402         if (!strcmp(r, p->name))
    1403             goto found;
    1404     }
    1405     return -1;
    1406  found:
    1407     if (p->flags & FD_INVERT)
    1408         value = !value;
    1409     *(int *)((uint8_t *)s + p->offset) = value;
    1410     return 0;
    1411 }
    1412 
    1413 /* set/reset a warning */
    1414 static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
    1415 {
    1416     int i;
    1417     const FlagDef *p;
    1418 
    1419     if (!strcmp(warning_name, "all")) {
    1420         for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
    1421             if (p->flags & WD_ALL)
    1422                 *(int *)((uint8_t *)s + p->offset) = 1;
     1215    if (no_flag(&r))
     1216        value = 0;
     1217
     1218    for (ret = -1, p = flags; p->name; ++p) {
     1219        if (ret) {
     1220            if (strcmp(r, p->name))
     1221                continue;
     1222        } else {
     1223            if (0 == (p->flags & WD_ALL))
     1224                continue;
    14231225        }
    1424         return 0;
    1425     } else {
    1426         return set_flag(s, warning_defs, countof(warning_defs),
    1427                         warning_name, value);
    1428     }
    1429 }
    1430 
    1431 static const FlagDef flag_defs[] = {
    1432     { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
    1433     { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
    1434     { offsetof(TCCState, nocommon), FD_INVERT, "common" },
    1435     { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
    1436 };
    1437 
    1438 /* set/reset a flag */
    1439 static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
    1440 {
    1441     return set_flag(s, flag_defs, countof(flag_defs),
    1442                     flag_name, value);
    1443 }
    1444 
     1226        if (p->offset) {
     1227            *(int*)((char *)s + p->offset) =
     1228                p->flags & FD_INVERT ? !value : value;
     1229            if (ret)
     1230                return 0;
     1231        } else {
     1232            ret = 0;
     1233        }
     1234    }
     1235    return ret;
     1236}
    14451237
    14461238static int strstart(const char *val, const char **str)
     
    14701262{
    14711263    const char *p, *q;
     1264    int ret;
    14721265
    14731266    /* there should be 1 or 2 dashes */
     
    14771270        str++;
    14781271
    1479     /* then str & val should match (potentialy up to '=') */
     1272    /* then str & val should match (potentially up to '=') */
    14801273    p = str;
    14811274    q = val;
     1275
     1276    ret = 1;
     1277    if (q[0] == '?') {
     1278        ++q;
     1279        if (no_flag(&p))
     1280            ret = -1;
     1281    }
    14821282
    14831283    while (*q != '\0' && *q != '=') {
     
    14901290    /* '=' near eos means ',' or '=' is ok */
    14911291    if (*q == '=') {
     1292        if (*p == 0)
     1293            *ptr = p;
    14921294        if (*p != ',' && *p != '=')
    14931295            return 0;
    14941296        p++;
    1495         q++;
    1496     }
    1497 
    1498     if (ptr)
    1499         *ptr = p;
    1500     return 1;
     1297    } else if (*p) {
     1298        return 0;
     1299    }
     1300    *ptr = p;
     1301    return ret;
    15011302}
    15021303
     
    15091310}
    15101311
    1511 static char *copy_linker_arg(const char *p)
    1512 {
    1513     const char *q = p;
     1312static void copy_linker_arg(char **pp, const char *s, int sep)
     1313{
     1314    const char *q = s;
     1315    char *p = *pp;
     1316    int l = 0;
     1317    if (p && sep)
     1318        p[l = strlen(p)] = sep, ++l;
    15141319    skip_linker_arg(&q);
    1515     return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
     1320    pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s);
    15161321}
    15171322
     
    15191324static int tcc_set_linker(TCCState *s, const char *option)
    15201325{
    1521     while (option && *option) {
    1522 
    1523         const char *p = option;
     1326    while (*option) {
     1327
     1328        const char *p = NULL;
    15241329        char *end = NULL;
    15251330        int ignoring = 0;
     1331        int ret;
    15261332
    15271333        if (link_option(option, "Bsymbolic", &p)) {
     
    15301336            s->nostdlib = 1;
    15311337        } else if (link_option(option, "fini=", &p)) {
    1532             s->fini_symbol = copy_linker_arg(p);
     1338            copy_linker_arg(&s->fini_symbol, p, 0);
    15331339            ignoring = 1;
    15341340        } else if (link_option(option, "image-base=", &p)
     
    15371343            s->has_text_addr = 1;
    15381344        } else if (link_option(option, "init=", &p)) {
    1539             s->init_symbol = copy_linker_arg(p);
     1345            copy_linker_arg(&s->init_symbol, p, 0);
    15401346            ignoring = 1;
    15411347        } else if (link_option(option, "oformat=", &p)) {
    15421348#if defined(TCC_TARGET_PE)
    15431349            if (strstart("pe-", &p)) {
    1544 #elif defined(TCC_TARGET_X86_64)
     1350#elif PTR_SIZE == 8
    15451351            if (strstart("elf64-", &p)) {
    15461352#else
     
    15571363                goto err;
    15581364
     1365        } else if (link_option(option, "as-needed", &p)) {
     1366            ignoring = 1;
     1367        } else if (link_option(option, "O", &p)) {
     1368            ignoring = 1;
     1369        } else if (link_option(option, "export-all-symbols", &p)) {
     1370            s->rdynamic = 1;
    15591371        } else if (link_option(option, "rpath=", &p)) {
    1560             s->rpath = copy_linker_arg(p);
     1372            copy_linker_arg(&s->rpath, p, ':');
     1373        } else if (link_option(option, "enable-new-dtags", &p)) {
     1374            s->enable_new_dtags = 1;
    15611375        } else if (link_option(option, "section-alignment=", &p)) {
    15621376            s->section_align = strtoul(p, &end, 16);
    15631377        } else if (link_option(option, "soname=", &p)) {
    1564             s->soname = copy_linker_arg(p);
     1378            copy_linker_arg(&s->soname, p, 0);
    15651379#ifdef TCC_TARGET_PE
     1380        } else if (link_option(option, "large-address-aware", &p)) {
     1381            s->pe_characteristics |= 0x20;
    15661382        } else if (link_option(option, "file-alignment=", &p)) {
    15671383            s->pe_file_align = strtoul(p, &end, 16);
     
    15741390            } else if (!strcmp(p, "console")) {
    15751391                s->pe_subsystem = 3;
    1576             } else if (!strcmp(p, "gui")) {
     1392            } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) {
    15771393                s->pe_subsystem = 2;
    15781394            } else if (!strcmp(p, "posix")) {
     
    15931409                goto err;
    15941410#endif
    1595         } else
    1596             goto err;
    1597 
    1598         if (ignoring && s->warn_unsupported) err: {
    1599             char buf[100], *e;
    1600             pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
    1601             if (ignoring)
    1602                 tcc_warning("unsupported linker option '%s'", buf);
    1603             else
    1604                 tcc_error("unsupported linker option '%s'", buf);
     1411        } else if (ret = link_option(option, "?whole-archive", &p), ret) {
     1412            s->alacarte_link = ret < 0;
     1413        } else if (p) {
     1414            return 0;
     1415        } else {
     1416    err:
     1417            tcc_error("unsupported linker option '%s'", option);
    16051418        }
     1419
     1420        if (ignoring && s->warn_unsupported)
     1421            tcc_warning("unsupported linker option '%s'", option);
     1422
    16061423        option = skip_linker_arg(&p);
    16071424    }
    1608     return 0;
     1425    return 1;
    16091426}
    16101427
     
    16171434enum {
    16181435    TCC_OPTION_HELP,
     1436    TCC_OPTION_HELP2,
     1437    TCC_OPTION_v,
    16191438    TCC_OPTION_I,
    16201439    TCC_OPTION_D,
    16211440    TCC_OPTION_U,
     1441    TCC_OPTION_P,
    16221442    TCC_OPTION_L,
    16231443    TCC_OPTION_B,
     
    16281448    TCC_OPTION_g,
    16291449    TCC_OPTION_c,
     1450    TCC_OPTION_dumpversion,
     1451    TCC_OPTION_d,
    16301452    TCC_OPTION_static,
     1453    TCC_OPTION_std,
    16311454    TCC_OPTION_shared,
    16321455    TCC_OPTION_soname,
     
    16341457    TCC_OPTION_r,
    16351458    TCC_OPTION_s,
     1459    TCC_OPTION_traditional,
    16361460    TCC_OPTION_Wl,
     1461    TCC_OPTION_Wp,
    16371462    TCC_OPTION_W,
    16381463    TCC_OPTION_O,
     1464    TCC_OPTION_mfloat_abi,
    16391465    TCC_OPTION_m,
    16401466    TCC_OPTION_f,
    16411467    TCC_OPTION_isystem,
     1468    TCC_OPTION_iwithprefix,
     1469    TCC_OPTION_include,
    16421470    TCC_OPTION_nostdinc,
    16431471    TCC_OPTION_nostdlib,
    16441472    TCC_OPTION_print_search_dirs,
    16451473    TCC_OPTION_rdynamic,
     1474    TCC_OPTION_param,
    16461475    TCC_OPTION_pedantic,
    16471476    TCC_OPTION_pthread,
    16481477    TCC_OPTION_run,
    1649     TCC_OPTION_v,
    16501478    TCC_OPTION_w,
    16511479    TCC_OPTION_pipe,
     
    16541482    TCC_OPTION_MF,
    16551483    TCC_OPTION_x,
    1656     TCC_OPTION_dumpversion,
     1484    TCC_OPTION_ar,
     1485    TCC_OPTION_impdef
    16571486};
    16581487
     
    16641493    { "-help", TCC_OPTION_HELP, 0 },
    16651494    { "?", TCC_OPTION_HELP, 0 },
     1495    { "hh", TCC_OPTION_HELP2, 0 },
     1496    { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16661497    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
    16671498    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
    16681499    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
     1500    { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16691501    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
    16701502    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
     
    16791511    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16801512    { "c", TCC_OPTION_c, 0 },
     1513    { "dumpversion", TCC_OPTION_dumpversion, 0},
     1514    { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16811515    { "static", TCC_OPTION_static, 0 },
     1516    { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16821517    { "shared", TCC_OPTION_shared, 0 },
    16831518    { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
    16841519    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
     1520    { "-param", TCC_OPTION_param, TCC_OPTION_HAS_ARG },
    16851521    { "pedantic", TCC_OPTION_pedantic, 0},
    16861522    { "pthread", TCC_OPTION_pthread, 0},
     
    16891525    { "r", TCC_OPTION_r, 0 },
    16901526    { "s", TCC_OPTION_s, 0 },
     1527    { "traditional", TCC_OPTION_traditional, 0 },
    16911528    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
     1529    { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16921530    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16931531    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    1694     { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
     1532#ifdef TCC_TARGET_ARM
     1533    { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG },
     1534#endif
     1535    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16951536    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
    16961537    { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
     1538    { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG },
    16971539    { "nostdinc", TCC_OPTION_nostdinc, 0 },
    16981540    { "nostdlib", TCC_OPTION_nostdlib, 0 },
    1699     { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
    1700     { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
     1541    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
    17011542    { "w", TCC_OPTION_w, 0 },
    17021543    { "pipe", TCC_OPTION_pipe, 0},
     
    17051546    { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
    17061547    { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
    1707     { "dumpversion", TCC_OPTION_dumpversion, 0},
     1548    { "ar", TCC_OPTION_ar, 0},
     1549#ifdef TCC_TARGET_PE
     1550    { "impdef", TCC_OPTION_impdef, 0},
     1551#endif
    17081552    { NULL, 0, 0 },
     1553};
     1554
     1555static const FlagDef options_W[] = {
     1556    { 0, 0, "all" },
     1557    { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
     1558    { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
     1559    { offsetof(TCCState, warn_error), 0, "error" },
     1560    { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" },
     1561    { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
     1562      "implicit-function-declaration" },
     1563    { 0, 0, NULL }
     1564};
     1565
     1566static const FlagDef options_f[] = {
     1567    { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
     1568    { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
     1569    { offsetof(TCCState, nocommon), FD_INVERT, "common" },
     1570    { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
     1571    { offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
     1572    { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
     1573    { 0, 0, NULL }
     1574};
     1575
     1576static const FlagDef options_m[] = {
     1577    { offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" },
     1578#ifdef TCC_TARGET_X86_64
     1579    { offsetof(TCCState, nosse), FD_INVERT, "sse" },
     1580#endif
     1581    { 0, 0, NULL }
    17091582};
    17101583
     
    17191592}
    17201593
    1721 PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
     1594static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
     1595{
     1596    struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
     1597    f->type = filetype;
     1598    f->alacarte = s->alacarte_link;
     1599    strcpy(f->name, filename);
     1600    dynarray_add(&s->files, &s->nb_files, f);
     1601}
     1602
     1603static int args_parser_make_argv(const char *r, int *argc, char ***argv)
     1604{
     1605    int ret = 0, q, c;
     1606    CString str;
     1607    for(;;) {
     1608        while (c = (unsigned char)*r, c && c <= ' ')
     1609            ++r;
     1610        if (c == 0)
     1611            break;
     1612        q = 0;
     1613        cstr_new(&str);
     1614        while (c = (unsigned char)*r, c) {
     1615            ++r;
     1616            if (c == '\\' && (*r == '"' || *r == '\\')) {
     1617                c = *r++;
     1618            } else if (c == '"') {
     1619                q = !q;
     1620                continue;
     1621            } else if (q == 0 && c <= ' ') {
     1622                break;
     1623            }
     1624            cstr_ccat(&str, c);
     1625        }
     1626        cstr_ccat(&str, 0);
     1627        //printf("<%s>\n", str.data), fflush(stdout);
     1628        dynarray_add(argv, argc, tcc_strdup(str.data));
     1629        cstr_free(&str);
     1630        ++ret;
     1631    }
     1632    return ret;
     1633}
     1634
     1635/* read list file */
     1636static void args_parser_listfile(TCCState *s,
     1637    const char *filename, int optind, int *pargc, char ***pargv)
     1638{
     1639    int fd, i;
     1640    size_t len;
     1641    char *p;
     1642    int argc = 0;
     1643    char **argv = NULL;
     1644
     1645    fd = open(filename, O_RDONLY | O_BINARY);
     1646    if (fd < 0)
     1647        tcc_error("listfile '%s' not found", filename);
     1648
     1649    len = lseek(fd, 0, SEEK_END);
     1650    p = tcc_malloc(len + 1), p[len] = 0;
     1651    lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd);
     1652
     1653    for (i = 0; i < *pargc; ++i)
     1654        if (i == optind)
     1655            args_parser_make_argv(p, &argc, &argv);
     1656        else
     1657            dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
     1658
     1659    tcc_free(p);
     1660    dynarray_reset(&s->argv, &s->argc);
     1661    *pargc = s->argc = argc, *pargv = s->argv = argv;
     1662}
     1663
     1664PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
    17221665{
    17231666    const TCCOption *popt;
    17241667    const char *optarg, *r;
    1725     int run = 0;
    1726     int pthread = 0;
    1727     int optind = 0;
    1728 
    1729     /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
    1730     CString linker_arg;
     1668    const char *run = NULL;
     1669    int last_o = -1;
     1670    int x;
     1671    CString linker_arg; /* collect -Wl options */
     1672    int tool = 0, arg_start = 0, noaction = optind;
     1673    char **argv = *pargv;
     1674    int argc = *pargc;
     1675
    17311676    cstr_new(&linker_arg);
    17321677
    17331678    while (optind < argc) {
    1734 
    1735         r = argv[optind++];
     1679        r = argv[optind];
     1680        if (r[0] == '@' && r[1] != '\0') {
     1681            args_parser_listfile(s, r + 1, optind, &argc, &argv);
     1682            continue;
     1683        }
     1684        optind++;
     1685        if (tool) {
     1686            if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
     1687                ++s->verbose;
     1688            continue;
     1689        }
     1690reparse:
    17361691        if (r[0] != '-' || r[1] == '\0') {
    1737             /* add a new file */
    1738             dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
     1692            if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
     1693                args_parser_add_file(s, r, s->filetype);
    17391694            if (run) {
    1740                 optind--;
    1741                 /* argv[0] will be this file */
     1695                tcc_set_options(s, run);
     1696                arg_start = optind - 1;
    17421697                break;
    17431698            }
     
    17571712                if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
    17581713                    if (optind >= argc)
     1714                arg_err:
    17591715                        tcc_error("argument to '%s' is missing", r);
    17601716                    optarg = argv[optind++];
     
    17671723        switch(popt->index) {
    17681724        case TCC_OPTION_HELP:
    1769             return 0;
     1725            return OPT_HELP;
     1726        case TCC_OPTION_HELP2:
     1727            return OPT_HELP2;
    17701728        case TCC_OPTION_I:
    1771             if (tcc_add_include_path(s, optarg) < 0)
    1772                 tcc_error("too many include paths");
     1729            tcc_add_include_path(s, optarg);
    17731730            break;
    17741731        case TCC_OPTION_D:
     
    17861743            break;
    17871744        case TCC_OPTION_l:
    1788             dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
     1745            args_parser_add_file(s, optarg, AFF_TYPE_LIB);
    17891746            s->nb_libraries++;
    17901747            break;
    17911748        case TCC_OPTION_pthread:
    17921749            parse_option_D(s, "_REENTRANT");
    1793             pthread = 1;
     1750            s->option_pthread = 1;
    17941751            break;
    17951752        case TCC_OPTION_bench:
     
    18111768            break;
    18121769        case TCC_OPTION_c:
    1813             s->output_type = TCC_OUTPUT_OBJ;
     1770            x = TCC_OUTPUT_OBJ;
     1771        set_output_type:
     1772            if (s->output_type)
     1773                tcc_warning("-%s: overriding compiler action already specified", popt->name);
     1774            s->output_type = x;
     1775            break;
     1776        case TCC_OPTION_d:
     1777            if (*optarg == 'D')
     1778                s->dflag = 3;
     1779            else if (*optarg == 'M')
     1780                s->dflag = 7;
     1781            else if (*optarg == 't')
     1782                s->dflag = 16;
     1783            else if (isnum(*optarg))
     1784                g_debug = atoi(optarg);
     1785            else
     1786                goto unsupported_option;
    18141787            break;
    18151788        case TCC_OPTION_static:
    18161789            s->static_link = 1;
    18171790            break;
     1791        case TCC_OPTION_std:
     1792            /* silently ignore, a current purpose:
     1793               allow to use a tcc as a reference compiler for "make test" */
     1794            break;
    18181795        case TCC_OPTION_shared:
    1819             s->output_type = TCC_OUTPUT_DLL;
    1820             break;
     1796            x = TCC_OUTPUT_DLL;
     1797            goto set_output_type;
    18211798        case TCC_OPTION_soname:
    18221799            s->soname = tcc_strdup(optarg);
    18231800            break;
    1824         case TCC_OPTION_m:
    1825             s->option_m = tcc_strdup(optarg);
    1826             break;
    18271801        case TCC_OPTION_o:
     1802            if (s->outfile) {
     1803                tcc_warning("multiple -o option");
     1804                tcc_free(s->outfile);
     1805            }
    18281806            s->outfile = tcc_strdup(optarg);
    18291807            break;
     
    18311809            /* generate a .o merging several output files */
    18321810            s->option_r = 1;
    1833             s->output_type = TCC_OUTPUT_OBJ;
    1834             break;
     1811            x = TCC_OUTPUT_OBJ;
     1812            goto set_output_type;
    18351813        case TCC_OPTION_isystem:
    18361814            tcc_add_sysinclude_path(s, optarg);
    18371815            break;
     1816        case TCC_OPTION_include:
     1817            dynarray_add(&s->cmd_include_files,
     1818                         &s->nb_cmd_include_files, tcc_strdup(optarg));
     1819            break;
    18381820        case TCC_OPTION_nostdinc:
    18391821            s->nostdinc = 1;
     
    18421824            s->nostdlib = 1;
    18431825            break;
    1844         case TCC_OPTION_print_search_dirs:
    1845             s->print_search_dirs = 1;
    1846             break;
    18471826        case TCC_OPTION_run:
    1848             s->output_type = TCC_OUTPUT_MEMORY;
    1849             tcc_set_options(s, optarg);
    1850             run = 1;
    1851             break;
     1827#ifndef TCC_IS_NATIVE
     1828            tcc_error("-run is not available in a cross compiler");
     1829#endif
     1830            run = optarg;
     1831            x = TCC_OUTPUT_MEMORY;
     1832            goto set_output_type;
    18521833        case TCC_OPTION_v:
    18531834            do ++s->verbose; while (*optarg++ == 'v');
     1835            ++noaction;
    18541836            break;
    18551837        case TCC_OPTION_f:
    1856             if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
     1838            if (set_flag(s, options_f, optarg) < 0)
    18571839                goto unsupported_option;
    18581840            break;
     1841#ifdef TCC_TARGET_ARM
     1842        case TCC_OPTION_mfloat_abi:
     1843            /* tcc doesn't support soft float yet */
     1844            if (!strcmp(optarg, "softfp")) {
     1845                s->float_abi = ARM_SOFTFP_FLOAT;
     1846                tcc_undefine_symbol(s, "__ARM_PCS_VFP");
     1847            } else if (!strcmp(optarg, "hard"))
     1848                s->float_abi = ARM_HARD_FLOAT;
     1849            else
     1850                tcc_error("unsupported float abi '%s'", optarg);
     1851            break;
     1852#endif
     1853        case TCC_OPTION_m:
     1854            if (set_flag(s, options_m, optarg) < 0) {
     1855                if (x = atoi(optarg), x != 32 && x != 64)
     1856                    goto unsupported_option;
     1857                if (PTR_SIZE != x/8)
     1858                    return x;
     1859                ++noaction;
     1860            }
     1861            break;
    18591862        case TCC_OPTION_W:
    1860             if (tcc_set_warning(s, optarg, 1) < 0 &&
    1861                 s->warn_unsupported)
     1863            if (set_flag(s, options_W, optarg) < 0)
    18621864                goto unsupported_option;
    18631865            break;
     
    18711873            if (linker_arg.size)
    18721874                --linker_arg.size, cstr_ccat(&linker_arg, ',');
    1873             cstr_cat(&linker_arg, optarg);
    1874             cstr_ccat(&linker_arg, '\0');
    1875             break;
     1875            cstr_cat(&linker_arg, optarg, 0);
     1876            if (tcc_set_linker(s, linker_arg.data))
     1877                cstr_free(&linker_arg);
     1878            break;
     1879        case TCC_OPTION_Wp:
     1880            r = optarg;
     1881            goto reparse;
    18761882        case TCC_OPTION_E:
    1877             s->output_type = TCC_OUTPUT_PREPROCESS;
     1883            x = TCC_OUTPUT_PREPROCESS;
     1884            goto set_output_type;
     1885        case TCC_OPTION_P:
     1886            s->Pflag = atoi(optarg) + 1;
    18781887            break;
    18791888        case TCC_OPTION_MD:
     
    18861895            printf ("%s\n", TCC_VERSION);
    18871896            exit(0);
     1897            break;
     1898        case TCC_OPTION_x:
     1899            if (*optarg == 'c')
     1900                s->filetype = AFF_TYPE_C;
     1901            else if (*optarg == 'a')
     1902                s->filetype = AFF_TYPE_ASMPP;
     1903            else if (*optarg == 'n')
     1904                s->filetype = AFF_TYPE_NONE;
     1905            else
     1906                tcc_warning("unsupported language '%s'", optarg);
     1907            break;
    18881908        case TCC_OPTION_O:
     1909            last_o = atoi(optarg);
     1910            break;
     1911        case TCC_OPTION_print_search_dirs:
     1912            x = OPT_PRINT_DIRS;
     1913            goto extra_action;
     1914        case TCC_OPTION_impdef:
     1915            x = OPT_IMPDEF;
     1916            goto extra_action;
     1917        case TCC_OPTION_ar:
     1918            x = OPT_AR;
     1919        extra_action:
     1920            arg_start = optind - 1;
     1921            if (arg_start != noaction)
     1922                tcc_error("cannot parse %s here", r);
     1923            tool = x;
     1924            break;
     1925        case TCC_OPTION_traditional:
    18891926        case TCC_OPTION_pedantic:
    18901927        case TCC_OPTION_pipe:
    18911928        case TCC_OPTION_s:
    1892         case TCC_OPTION_x:
    18931929            /* ignored */
    18941930            break;
    18951931        default:
    1896             if (s->warn_unsupported) {
    1897             unsupported_option:
     1932unsupported_option:
     1933            if (s->warn_unsupported)
    18981934                tcc_warning("unsupported option '%s'", r);
    1899             }
    19001935            break;
    19011936        }
    19021937    }
    1903 
    1904     if (pthread && s->output_type != TCC_OUTPUT_OBJ)
    1905         tcc_set_options(s, "-lpthread");
    1906 
    1907     tcc_set_linker(s, (const char *)linker_arg.data);
    1908     cstr_free(&linker_arg);
    1909 
    1910     return optind;
    1911 }
    1912 
    1913 LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
    1914 {
    1915     const char *s1;
    1916     char **argv, *arg;
    1917     int argc, len;
    1918     int ret;
    1919 
    1920     argc = 0, argv = NULL;
    1921     for(;;) {
    1922         while (is_space(*str))
    1923             str++;
    1924         if (*str == '\0')
    1925             break;
    1926         s1 = str;
    1927         while (*str != '\0' && !is_space(*str))
    1928             str++;
    1929         len = str - s1;
    1930         arg = tcc_malloc(len + 1);
    1931         pstrncpy(arg, s1, len);
    1932         dynarray_add((void ***)&argv, &argc, arg);
    1933     }
    1934     ret = tcc_parse_args(s, argc, argv);
     1938    if (last_o > 0)
     1939        tcc_define_symbol(s, "__OPTIMIZE__", NULL);
     1940    if (linker_arg.size) {
     1941        r = linker_arg.data;
     1942        goto arg_err;
     1943    }
     1944    *pargc = argc - arg_start;
     1945    *pargv = argv + arg_start;
     1946    if (tool)
     1947        return tool;
     1948    if (optind != noaction)
     1949        return 0;
     1950    if (s->verbose == 2)
     1951        return OPT_PRINT_DIRS;
     1952    if (s->verbose)
     1953        return OPT_V;
     1954    return OPT_HELP;
     1955}
     1956
     1957LIBTCCAPI void tcc_set_options(TCCState *s, const char *r)
     1958{
     1959    char **argv = NULL;
     1960    int argc = 0;
     1961    args_parser_make_argv(r, &argc, &argv);
     1962    tcc_parse_args(s, &argc, &argv, 0);
    19351963    dynarray_reset(&argv, &argc);
    1936     return ret;
    1937 }
    1938 
    1939 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
    1940 {
    1941     double tt;
    1942     tt = (double)total_time / 1000000.0;
    1943     if (tt < 0.001)
    1944         tt = 0.001;
     1964}
     1965
     1966PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
     1967{
     1968    if (total_time < 1)
     1969        total_time = 1;
    19451970    if (total_bytes < 1)
    19461971        total_bytes = 1;
    1947     printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
     1972    fprintf(stderr, "* %d idents, %d lines, %d bytes\n"
     1973                    "* %0.3f s, %u lines/s, %0.1f MB/s\n",
    19481974           tok_ident - TOK_IDENT, total_lines, total_bytes,
    1949            tt, (int)(total_lines / tt),
    1950            total_bytes / tt / 1000000.0);
    1951 }
     1975           (double)total_time/1000,
     1976           (unsigned)total_lines*1000/total_time,
     1977           (double)total_bytes/1000/total_time);
     1978#ifdef MEM_DEBUG
     1979    fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
     1980#endif
     1981}
Note: See TracChangeset for help on using the changeset viewer.