Subversion Repositories Kolibri OS

Rev

Rev 9284 | Rev 9513 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  TCC - Tiny C Compiler
  3.  *
  4.  *  Copyright (c) 2001-2004 Fabrice Bellard
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include "tcc.h"
  22.  
  23. /********************************************************/
  24. /* global variables */
  25.  
  26. /* use GNU C extensions */
  27. ST_DATA int gnu_ext = 1;
  28.  
  29. /* use TinyCC extensions */
  30. ST_DATA int tcc_ext = 1;
  31.  
  32. /* XXX: get rid of this ASAP */
  33. ST_DATA struct TCCState *tcc_state;
  34.  
  35. /********************************************************/
  36.  
  37. #ifdef ONE_SOURCE
  38. #include "tccpp.c"
  39. #include "tccgen.c"
  40. #include "tccelf.c"
  41. #ifdef TCC_IS_NATIVE
  42. # include "tccrun.c"
  43. #endif
  44. #ifdef TCC_TARGET_I386
  45. #include "i386-gen.c"
  46. #endif
  47. #ifdef TCC_TARGET_ARM
  48. #include "arm-gen.c"
  49. #endif
  50. #ifdef TCC_TARGET_ARM64
  51. #include "arm64-gen.c"
  52. #endif
  53. #ifdef TCC_TARGET_C67
  54. #include "c67-gen.c"
  55. #endif
  56. #ifdef TCC_TARGET_X86_64
  57. #include "x86_64-gen.c"
  58. #endif
  59. #ifdef CONFIG_TCC_ASM
  60. #include "tccasm.c"
  61. #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
  62. #include "i386-asm.c"
  63. #endif
  64. #endif
  65. #ifdef TCC_TARGET_COFF
  66. #include "tcccoff.c"
  67. #endif
  68. #if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS)
  69. #include "tccpe.c"
  70. #endif
  71. #ifdef TCC_TARGET_MEOS
  72. #include "tccmeos.c"
  73. #endif
  74. #ifdef TCC_TARGET_KX
  75. #include "tcckx.c"
  76. #endif
  77. #ifdef TCC_TARGET_MEOS_LINUX
  78. #include <libgen.h>
  79. #endif
  80.  
  81.  
  82. #endif /* ONE_SOURCE */
  83.  
  84. /********************************************************/
  85. #ifndef CONFIG_TCC_ASM
  86. ST_FUNC void asm_instr(void)
  87. {
  88.     tcc_error("inline asm() not supported");
  89. }
  90. ST_FUNC void asm_global_instr(void)
  91. {
  92.     tcc_error("inline asm() not supported");
  93. }
  94. #endif
  95.  
  96.  
  97.  
  98. /********************************************************/
  99. #ifdef _WIN32
  100. static char *normalize_slashes(char *path)
  101. {
  102.     char *p;
  103.     for (p = path; *p; ++p)
  104.         if (*p == '\\')
  105.             *p = '/';
  106.     return path;
  107. }
  108.  
  109. static HMODULE tcc_module;
  110.  
  111. /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
  112. static void tcc_set_lib_path_w32(TCCState *s)
  113. {
  114.     char path[1024], *p;
  115.     GetModuleFileNameA(tcc_module, path, sizeof path);
  116.     p = tcc_basename(normalize_slashes(strlwr(path)));
  117.     if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
  118.         p -= 5;
  119.     else if (p > path)
  120.         p--;
  121.     *p = 0;
  122.     tcc_set_lib_path(s, path);
  123. }
  124.  
  125. #ifdef TCC_TARGET_PE
  126. static void tcc_add_systemdir(TCCState *s)
  127. {
  128.     char buf[1000];
  129.     GetSystemDirectory(buf, sizeof buf);
  130.     tcc_add_library_path(s, normalize_slashes(buf));
  131. }
  132. #endif
  133.  
  134. #ifndef CONFIG_TCC_STATIC
  135. void dlclose(void *p)
  136. {
  137.     FreeLibrary((HMODULE)p);
  138. }
  139. #endif
  140.  
  141. #ifdef LIBTCC_AS_DLL
  142. BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
  143. {
  144.     if (DLL_PROCESS_ATTACH == dwReason)
  145.         tcc_module = hDll;
  146.     return TRUE;
  147. }
  148. #endif
  149. #else // _WIN32
  150. #if defined TCC_TARGET_MEOS
  151. /* on Kolibri host, we suppose the lib and includes are at the location of 'tcc' /lib, /include */
  152. static void tcc_set_lib_path_kos(TCCState *s)
  153. {
  154.         char** argv0 = (char**)0x20; // path in kolibri header
  155.     char path[1024], *p;
  156.         strncpy(path, *argv0, sizeof path);
  157.         p = tcc_basename(path);
  158.     if (p > path) p--;
  159.     *p = 0;
  160.     tcc_set_lib_path(s, path);
  161. }
  162.  
  163. #if defined TCC_TARGET_MEOS_LINUX
  164. static void tcc_set_lib_path_linux(TCCState *s)
  165. {
  166.     char buff[4096+1];
  167.     readlink("/proc/self/exe", buff, 4096);
  168.     const char *path = dirname(buff);
  169.     tcc_set_lib_path(s, path);
  170. }
  171.  
  172. #endif
  173. #endif
  174. #endif
  175. /********************************************************/
  176. /* copy a string and truncate it. */
  177. PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)
  178. {
  179.     char *q, *q_end;
  180.     int c;
  181.  
  182.     if (buf_size > 0) {
  183.         q = buf;
  184.         q_end = buf + buf_size - 1;
  185.         while (q < q_end) {
  186.             c = *s++;
  187.             if (c == '\0')
  188.                 break;
  189.             *q++ = c;
  190.         }
  191.         *q = '\0';
  192.     }
  193.     return buf;
  194. }
  195.  
  196. /* strcat and truncate. */
  197. PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)
  198. {
  199.     int len;
  200.     len = strlen(buf);
  201.     if (len < buf_size)
  202.         pstrcpy(buf + len, buf_size - len, s);
  203.     return buf;
  204. }
  205.  
  206. PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num)
  207. {
  208.     memcpy(out, in, num);
  209.     out[num] = '\0';
  210.     return out;
  211. }
  212.  
  213. /* extract the basename of a file */
  214. PUB_FUNC char *tcc_basename(const char *name)
  215. {
  216.     char *p = strchr(name, 0);
  217.     while (p > name && !IS_DIRSEP(p[-1]))
  218.         --p;
  219.     return p;
  220. }
  221.  
  222. /* extract extension part of a file
  223.  *
  224.  * (if no extension, return pointer to end-of-string)
  225.  */
  226. PUB_FUNC char *tcc_fileextension (const char *name)
  227. {
  228.     char *b = tcc_basename(name);
  229.     char *e = strrchr(b, '.');
  230.     return e ? e : strchr(b, 0);
  231. }
  232.  
  233. /********************************************************/
  234. /* memory management */
  235.  
  236. #undef free
  237. #undef malloc
  238. #undef realloc
  239.  
  240. #ifndef MEM_DEBUG
  241.  
  242. PUB_FUNC void tcc_free(void *ptr)
  243. {
  244.     free(ptr);
  245. }
  246.  
  247. PUB_FUNC void *tcc_malloc(unsigned long size)
  248. {
  249.     void *ptr;
  250.     ptr = malloc(size);
  251.     if (!ptr && size)
  252.         tcc_error("memory full (malloc)");
  253.     return ptr;
  254. }
  255.  
  256. PUB_FUNC void *tcc_mallocz(unsigned long size)
  257. {
  258.     void *ptr;
  259.     ptr = tcc_malloc(size);
  260.     memset(ptr, 0, size);
  261.     return ptr;
  262. }
  263.  
  264. PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
  265. {
  266.     void *ptr1;
  267.     ptr1 = realloc(ptr, size);
  268.     if (!ptr1 && size)
  269.         tcc_error("memory full (realloc)");
  270.     return ptr1;
  271. }
  272.  
  273. PUB_FUNC char *tcc_strdup(const char *str)
  274. {
  275.     char *ptr;
  276.     ptr = tcc_malloc(strlen(str) + 1);
  277.     strcpy(ptr, str);
  278.     return ptr;
  279. }
  280.  
  281. PUB_FUNC void tcc_memstats(int bench)
  282. {
  283. }
  284.  
  285. #else
  286.  
  287. #define MEM_DEBUG_MAGIC1 0xFEEDDEB1
  288. #define MEM_DEBUG_MAGIC2 0xFEEDDEB2
  289. #define MEM_DEBUG_FILE_LEN 15
  290.  
  291. struct mem_debug_header {
  292.     size_t      magic1;
  293.     size_t      size;
  294.     struct mem_debug_header *prev;
  295.     struct mem_debug_header *next;
  296.     size_t      line_num;
  297.     char        file_name[MEM_DEBUG_FILE_LEN + 1];
  298.     size_t      magic2;
  299. };
  300.  
  301. typedef struct mem_debug_header mem_debug_header_t;
  302.  
  303. static mem_debug_header_t *mem_debug_chain;
  304. static size_t mem_cur_size;
  305. static size_t mem_max_size;
  306.  
  307. PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
  308. {
  309.     void *ptr;
  310.     int ofs;
  311.  
  312.     mem_debug_header_t *header;
  313.  
  314.     ptr = malloc(sizeof(mem_debug_header_t) + size);
  315.     if (!ptr)
  316.         tcc_error("memory full (malloc)");
  317.  
  318.     mem_cur_size += size;
  319.     if (mem_cur_size > mem_max_size)
  320.         mem_max_size = mem_cur_size;
  321.  
  322.     header = (mem_debug_header_t *)ptr;
  323.  
  324.     header->magic1 = MEM_DEBUG_MAGIC1;
  325.     header->magic2 = MEM_DEBUG_MAGIC2;
  326.     header->size = size;
  327.     header->line_num = line;
  328.  
  329.     ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
  330.     strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
  331.     header->file_name[MEM_DEBUG_FILE_LEN] = 0;
  332.  
  333.     header->next = mem_debug_chain;
  334.     header->prev = NULL;
  335.  
  336.     if (header->next)
  337.         header->next->prev = header;
  338.  
  339.     mem_debug_chain = header;
  340.  
  341.     ptr = (char *)ptr + sizeof(mem_debug_header_t);
  342.     return ptr;
  343. }
  344.  
  345. PUB_FUNC void tcc_free_debug(void *ptr)
  346. {
  347.     mem_debug_header_t *header;
  348.  
  349.     if (!ptr)
  350.         return;
  351.  
  352.     ptr = (char *)ptr - sizeof(mem_debug_header_t);
  353.     header = (mem_debug_header_t *)ptr;
  354.     if (header->magic1 != MEM_DEBUG_MAGIC1 ||
  355.         header->magic2 != MEM_DEBUG_MAGIC2 ||
  356.         header->size == (size_t)-1 )
  357.     {
  358.         tcc_error("tcc_free check failed");
  359.     }
  360.  
  361.     mem_cur_size -= header->size;
  362.     header->size = (size_t)-1;
  363.  
  364.     if (header->next)
  365.         header->next->prev = header->prev;
  366.  
  367.     if (header->prev)
  368.         header->prev->next = header->next;
  369.  
  370.     if (header == mem_debug_chain)
  371.         mem_debug_chain = header->next;
  372.  
  373.     free(ptr);
  374. }
  375.  
  376.  
  377. PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line)
  378. {
  379.     void *ptr;
  380.     ptr = tcc_malloc_debug(size,file,line);
  381.     memset(ptr, 0, size);
  382.     return ptr;
  383. }
  384.  
  385. PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line)
  386. {
  387.     mem_debug_header_t *header;
  388.     int mem_debug_chain_update = 0;
  389.  
  390.     if (!ptr) {
  391.         ptr = tcc_malloc_debug(size, file, line);
  392.         return ptr;
  393.     }
  394.  
  395.     ptr = (char *)ptr - sizeof(mem_debug_header_t);
  396.     header = (mem_debug_header_t *)ptr;
  397.     if (header->magic1 != MEM_DEBUG_MAGIC1 ||
  398.         header->magic2 != MEM_DEBUG_MAGIC2 ||
  399.         header->size == (size_t)-1 )
  400.     {
  401.         check_error:
  402.             tcc_error("tcc_realloc check failed");
  403.     }
  404.  
  405.     mem_debug_chain_update = (header == mem_debug_chain);
  406.  
  407.     mem_cur_size -= header->size;
  408.     ptr = realloc(ptr, sizeof(mem_debug_header_t) + size);
  409.     if (!ptr)
  410.         tcc_error("memory full (realloc)");
  411.  
  412.     header = (mem_debug_header_t *)ptr;
  413.     if (header->magic1 != MEM_DEBUG_MAGIC1 ||
  414.         header->magic2 != MEM_DEBUG_MAGIC2)
  415.     {
  416.         goto check_error;
  417.     }
  418.  
  419.     mem_cur_size += size;
  420.     if (mem_cur_size > mem_max_size)
  421.         mem_max_size = mem_cur_size;
  422.  
  423.     header->size = size;
  424.     if (header->next)
  425.         header->next->prev = header;
  426.  
  427.     if (header->prev)
  428.         header->prev->next = header;
  429.  
  430.     if (mem_debug_chain_update)
  431.         mem_debug_chain = header;
  432.  
  433.     ptr = (char *)ptr + sizeof(mem_debug_header_t);
  434.     return ptr;
  435. }
  436.  
  437. PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
  438. {
  439.     char *ptr;
  440.     ptr = tcc_malloc_debug(strlen(str) + 1, file, line);
  441.     strcpy(ptr, str);
  442.     return ptr;
  443. }
  444.  
  445. PUB_FUNC void tcc_memstats(int bench)
  446. {
  447.     if (mem_cur_size) {
  448.         mem_debug_header_t *header = mem_debug_chain;
  449.  
  450.         fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
  451.             mem_cur_size, mem_max_size);
  452.  
  453.         while (header) {
  454.             fprintf(stderr, "  file %s, line %u: %u bytes\n",
  455.                 header->file_name, header->line_num, header->size);
  456.             header = header->next;
  457.         }
  458.     }
  459.     else if (bench)
  460.         fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size);
  461. }
  462.  
  463. #undef MEM_DEBUG_MAGIC1
  464. #undef MEM_DEBUG_MAGIC2
  465. #undef MEM_DEBUG_FILE_LEN
  466.  
  467. #endif
  468.  
  469. #define free(p) use_tcc_free(p)
  470. #define malloc(s) use_tcc_malloc(s)
  471. #define realloc(p, s) use_tcc_realloc(p, s)
  472.  
  473. /********************************************************/
  474. /* dynarrays */
  475.  
  476. ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
  477. {
  478.     int nb, nb_alloc;
  479.     void **pp;
  480.  
  481.     nb = *nb_ptr;
  482.     pp = *ptab;
  483.     /* every power of two we double array size */
  484.     if ((nb & (nb - 1)) == 0) {
  485.         if (!nb)
  486.             nb_alloc = 1;
  487.         else
  488.             nb_alloc = nb * 2;
  489.         pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
  490.         *ptab = pp;
  491.     }
  492.     pp[nb++] = data;
  493.     *nb_ptr = nb;
  494. }
  495.  
  496. ST_FUNC void dynarray_reset(void *pp, int *n)
  497. {
  498.     void **p;
  499.     for (p = *(void***)pp; *n; ++p, --*n)
  500.         if (*p)
  501.             tcc_free(*p);
  502.     tcc_free(*(void**)pp);
  503.     *(void**)pp = NULL;
  504. }
  505.  
  506. static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
  507. {
  508.     const char *p;
  509.     do {
  510.         int c;
  511.         CString str;
  512.  
  513.         cstr_new(&str);
  514.         for (p = in; c = *p, c != '\0' && c != PATHSEP; ++p) {
  515.             if (c == '{' && p[1] && p[2] == '}') {
  516.                 c = p[1], p += 2;
  517.                 if (c == 'B')
  518.                     cstr_cat(&str, s->tcc_lib_path, -1);
  519.             } else {
  520.                 cstr_ccat(&str, c);
  521.             }
  522.         }
  523.         cstr_ccat(&str, '\0');
  524.         dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
  525.         cstr_free(&str);
  526.         in = p+1;
  527.     } while (*p);
  528. }
  529.  
  530. /********************************************************/
  531.  
  532. ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
  533. {
  534.     Section *sec;
  535.  
  536.     sec = tcc_mallocz(sizeof(Section) + strlen(name));
  537.     strcpy(sec->name, name);
  538.     sec->sh_type = sh_type;
  539.     sec->sh_flags = sh_flags;
  540.     switch(sh_type) {
  541.     case SHT_HASH:
  542.     case SHT_REL:
  543.     case SHT_RELA:
  544.     case SHT_DYNSYM:
  545.     case SHT_SYMTAB:
  546.     case SHT_DYNAMIC:
  547.         sec->sh_addralign = 4;
  548.         break;
  549.     case SHT_STRTAB:
  550.         sec->sh_addralign = 1;
  551.         break;
  552.     default:
  553.         sec->sh_addralign =  PTR_SIZE; /* gcc/pcc default aligment */
  554.         break;
  555.     }
  556.  
  557.     if (sh_flags & SHF_PRIVATE) {
  558.         dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
  559.     } else {
  560.         sec->sh_num = s1->nb_sections;
  561.         dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
  562.     }
  563.  
  564.     return sec;
  565. }
  566.  
  567. static void free_section(Section *s)
  568. {
  569.     tcc_free(s->data);
  570. }
  571.  
  572. /* realloc section and set its content to zero */
  573. ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
  574. {
  575.     unsigned long size;
  576.     unsigned char *data;
  577.  
  578.     size = sec->data_allocated;
  579.     if (size == 0)
  580.         size = 1;
  581.     while (size < new_size)
  582.         size = size * 2;
  583.     data = tcc_realloc(sec->data, size);
  584.     memset(data + sec->data_allocated, 0, size - sec->data_allocated);
  585.     sec->data = data;
  586.     sec->data_allocated = size;
  587. }
  588.  
  589. /* reserve at least 'size' bytes in section 'sec' from
  590.    sec->data_offset. */
  591. ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
  592. {
  593.     size_t offset, offset1;
  594.  
  595.     offset = sec->data_offset;
  596.     offset1 = offset + size;
  597.     if (offset1 > sec->data_allocated)
  598.         section_realloc(sec, offset1);
  599.     sec->data_offset = offset1;
  600.     return sec->data + offset;
  601. }
  602.  
  603. /* reserve at least 'size' bytes from section start */
  604. ST_FUNC void section_reserve(Section *sec, unsigned long size)
  605. {
  606.     if (size > sec->data_allocated)
  607.         section_realloc(sec, size);
  608.     if (size > sec->data_offset)
  609.         sec->data_offset = size;
  610. }
  611.  
  612. /* return a reference to a section, and create it if it does not
  613.    exists */
  614. ST_FUNC Section *find_section(TCCState *s1, const char *name)
  615. {
  616.     Section *sec;
  617.     int i;
  618.     for(i = 1; i < s1->nb_sections; i++) {
  619.         sec = s1->sections[i];
  620.         if (!strcmp(name, sec->name))
  621.             return sec;
  622.     }
  623.     /* sections are created as PROGBITS */
  624.     return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
  625. }
  626.  
  627. /* update sym->c so that it points to an external symbol in section
  628.    'section' with value 'value' */
  629. ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
  630.                             addr_t value, unsigned long size,
  631.                             int can_add_underscore)
  632. {
  633.     int sym_type, sym_bind, sh_num, info, other;
  634.     ElfW(Sym) *esym;
  635.     const char *name;
  636.     char buf1[256];
  637.  
  638. #ifdef CONFIG_TCC_BCHECK
  639.     char buf[32];
  640. #endif
  641.  
  642.     if (section == NULL)
  643.         sh_num = SHN_UNDEF;
  644.     else if (section == SECTION_ABS)
  645.         sh_num = SHN_ABS;
  646.     else
  647.         sh_num = section->sh_num;
  648.  
  649.     if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
  650.         sym_type = STT_FUNC;
  651.     } else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
  652.         sym_type = STT_NOTYPE;
  653.     } else {
  654.         sym_type = STT_OBJECT;
  655.     }
  656.  
  657.     if (sym->type.t & VT_STATIC)
  658.         sym_bind = STB_LOCAL;
  659.     else {
  660.         if (sym->type.t & VT_WEAK)
  661.             sym_bind = STB_WEAK;
  662.         else
  663.             sym_bind = STB_GLOBAL;
  664.     }
  665.  
  666.     if (!sym->c) {
  667.         name = get_tok_str(sym->v, NULL);
  668. #ifdef CONFIG_TCC_BCHECK
  669.         if (tcc_state->do_bounds_check) {
  670.             /* XXX: avoid doing that for statics ? */
  671.             /* if bound checking is activated, we change some function
  672.                names by adding the "__bound" prefix */
  673.             switch(sym->v) {
  674. #ifdef TCC_TARGET_PE
  675.             /* XXX: we rely only on malloc hooks */
  676.             case TOK_malloc:
  677.             case TOK_free:
  678.             case TOK_realloc:
  679.             case TOK_memalign:
  680.             case TOK_calloc:
  681. #endif
  682.             case TOK_memcpy:
  683.             case TOK_memmove:
  684.             case TOK_memset:
  685.             case TOK_strlen:
  686.             case TOK_strcpy:
  687.             case TOK_alloca:
  688.                 strcpy(buf, "__bound_");
  689.                 strcat(buf, name);
  690.                 name = buf;
  691.                 break;
  692.             }
  693.         }
  694. #endif
  695.         other = 0;
  696.  
  697. #ifdef TCC_TARGET_PE
  698.         if (sym->type.t & VT_EXPORT)
  699.             other |= ST_PE_EXPORT;
  700.         if (sym_type == STT_FUNC && sym->type.ref) {
  701.             Sym *ref = sym->type.ref;
  702.             if (ref->a.func_export)
  703.                 other |= ST_PE_EXPORT;
  704.             if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) {
  705.                 sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE);
  706.                 name = buf1;
  707.                 other |= ST_PE_STDCALL;
  708.                 can_add_underscore = 0;
  709.             }
  710.         } else {
  711.             if (find_elf_sym(tcc_state->dynsymtab_section, name))
  712.                 other |= ST_PE_IMPORT;
  713.             if (sym->type.t & VT_IMPORT)
  714.                 other |= ST_PE_IMPORT;
  715.         }
  716. #else
  717.         if (! (sym->type.t & VT_STATIC))
  718.             other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT;
  719. #endif
  720.         if (tcc_state->leading_underscore && can_add_underscore) {
  721.             buf1[0] = '_';
  722.             pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
  723.             name = buf1;
  724.         }
  725.         if (sym->asm_label) {
  726.             name = get_tok_str(sym->asm_label, NULL);
  727.         }
  728.         info = ELFW(ST_INFO)(sym_bind, sym_type);
  729.         sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
  730.     } else {
  731.         esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
  732.         esym->st_value = value;
  733.         esym->st_size = size;
  734.         esym->st_shndx = sh_num;
  735.     }
  736. }
  737.  
  738. ST_FUNC void put_extern_sym(Sym *sym, Section *section,
  739.                            addr_t value, unsigned long size)
  740. {
  741.     put_extern_sym2(sym, section, value, size, 1);
  742. }
  743.  
  744. /* add a new relocation entry to symbol 'sym' in section 's' */
  745. ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
  746.                      addr_t addend)
  747. {
  748.     int c = 0;
  749.     if (sym) {
  750.         if (0 == sym->c)
  751.             put_extern_sym(sym, NULL, 0, 0);
  752.         c = sym->c;
  753.     }
  754.     /* now we can add ELF relocation info */
  755.     put_elf_reloca(symtab_section, s, offset, type, c, addend);
  756. }
  757.  
  758. ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
  759. {
  760.     greloca(s, sym, offset, type, 0);
  761. }
  762.  
  763. /********************************************************/
  764.  
  765. static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
  766. {
  767.     int len;
  768.     len = strlen(buf);
  769.     vsnprintf(buf + len, buf_size - len, fmt, ap);
  770. }
  771.  
  772. static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
  773. {
  774.     va_list ap;
  775.     va_start(ap, fmt);
  776.     strcat_vprintf(buf, buf_size, fmt, ap);
  777.     va_end(ap);
  778. }
  779.  
  780. static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
  781. {
  782.     char buf[2048];
  783.     BufferedFile **pf, *f;
  784.  
  785.     buf[0] = '\0';
  786.     /* use upper file if inline ":asm:" or token ":paste:" */
  787.     for (f = file; f && f->filename[0] == ':'; f = f->prev)
  788.      ;
  789.     if (f) {
  790.         for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
  791.             strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
  792.                 (*pf)->filename, (*pf)->line_num);
  793.         if (f->line_num > 0) {
  794.             strcat_printf(buf, sizeof(buf), "%s:%d: ",
  795.                 f->filename, f->line_num);
  796.         } else {
  797.             strcat_printf(buf, sizeof(buf), "%s: ",
  798.                 f->filename);
  799.         }
  800.     } else {
  801.         strcat_printf(buf, sizeof(buf), "tcc: ");
  802.     }
  803.     if (is_warning)
  804.         strcat_printf(buf, sizeof(buf), "warning: ");
  805.     else
  806.         strcat_printf(buf, sizeof(buf), "error: ");
  807.     strcat_vprintf(buf, sizeof(buf), fmt, ap);
  808.  
  809.     if (!s1->error_func) {
  810.         /* default case: stderr */
  811.         if (s1->ppfp) /* print a newline during tcc -E */
  812.             fprintf(s1->ppfp, "\n"), fflush(s1->ppfp);
  813. #ifndef TCC_TARGET_MEOS
  814.         fprintf(stderr, "%s\n", buf);
  815.         fflush(stderr); /* print error/warning now (win32) */
  816. #else
  817.         fprintf(stdout, "%s\n", buf);
  818.         fflush(stdout); /* print error/warning now (win32) */
  819. #endif
  820.     } else {
  821.         s1->error_func(s1->error_opaque, buf);
  822.     }
  823.     if (!is_warning || s1->warn_error)
  824.         s1->nb_errors++;
  825. }
  826.  
  827. LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
  828.                         void (*error_func)(void *opaque, const char *msg))
  829. {
  830.     s->error_opaque = error_opaque;
  831.     s->error_func = error_func;
  832. }
  833.  
  834. /* error without aborting current compilation */
  835. PUB_FUNC void tcc_error_noabort(const char *fmt, ...)
  836. {
  837.     TCCState *s1 = tcc_state;
  838.     va_list ap;
  839.  
  840.     va_start(ap, fmt);
  841.     error1(s1, 0, fmt, ap);
  842.     va_end(ap);
  843. }
  844.  
  845. PUB_FUNC void tcc_error(const char *fmt, ...)
  846. {
  847.     TCCState *s1 = tcc_state;
  848.     va_list ap;
  849.  
  850.     va_start(ap, fmt);
  851.     error1(s1, 0, fmt, ap);
  852.     va_end(ap);
  853.     /* better than nothing: in some cases, we accept to handle errors */
  854.     if (s1->error_set_jmp_enabled) {
  855.         longjmp(s1->error_jmp_buf, 1);
  856.     } else {
  857.         /* XXX: eliminate this someday */
  858.         exit(1);
  859.     }
  860. }
  861.  
  862. PUB_FUNC void tcc_warning(const char *fmt, ...)
  863. {
  864.     TCCState *s1 = tcc_state;
  865.     va_list ap;
  866.  
  867.     if (s1->warn_none)
  868.         return;
  869.  
  870.     va_start(ap, fmt);
  871.     error1(s1, 1, fmt, ap);
  872.     va_end(ap);
  873. }
  874.  
  875. /********************************************************/
  876. /* I/O layer */
  877.  
  878. ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
  879. {
  880.     BufferedFile *bf;
  881.     int buflen = initlen ? initlen : IO_BUF_SIZE;
  882.  
  883.     bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
  884.     bf->buf_ptr = bf->buffer;
  885.     bf->buf_end = bf->buffer + initlen;
  886.     bf->buf_end[0] = CH_EOB; /* put eob symbol */
  887.     pstrcpy(bf->filename, sizeof(bf->filename), filename);
  888. #ifdef _WIN32
  889.     normalize_slashes(bf->filename);
  890. #endif
  891.     bf->line_num = 1;
  892.     bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
  893.     bf->fd = -1;
  894.     bf->prev = file;
  895.     file = bf;
  896. }
  897.  
  898. ST_FUNC void tcc_close(void)
  899. {
  900.     BufferedFile *bf = file;
  901.     if (bf->fd > 0) {
  902.         close(bf->fd);
  903.         total_lines += bf->line_num;
  904.     }
  905.     file = bf->prev;
  906.     tcc_free(bf);
  907. }
  908.  
  909. ST_FUNC int tcc_open(TCCState *s1, const char *filename)
  910. {
  911.     int fd;
  912.     if (strcmp(filename, "-") == 0)
  913.         fd = 0, filename = "<stdin>";
  914.     else
  915.         fd = open(filename, O_RDONLY | O_BINARY);
  916.     if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3)
  917.         printf("%s %*s%s\n", fd < 0 ? "nf":"->",
  918.                (int)(s1->include_stack_ptr - s1->include_stack), "", filename);
  919.     if (fd < 0)
  920.         return -1;
  921.  
  922.     tcc_open_bf(s1, filename, 0);
  923.     file->fd = fd;
  924.     return fd;
  925. }
  926.  
  927. /* compile the C file opened in 'file'. Return non zero if errors. */
  928. static int tcc_compile(TCCState *s1)
  929. {
  930.     Sym *define_start;
  931.     char buf[512];
  932.     volatile int section_sym;
  933.  
  934. #ifdef INC_DEBUG
  935.     printf("%s: **** new file\n", file->filename);
  936. #endif
  937.     preprocess_init(s1);
  938.  
  939.     cur_text_section = NULL;
  940.     funcname = "";
  941.     anon_sym = SYM_FIRST_ANOM;
  942.  
  943.     /* file info: full path + filename */
  944.     section_sym = 0; /* avoid warning */
  945.     if (s1->do_debug) {
  946.         section_sym = put_elf_sym(symtab_section, 0, 0,
  947.                                   ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
  948.                                   text_section->sh_num, NULL);
  949.         getcwd(buf, sizeof(buf));
  950. #ifdef _WIN32
  951.         normalize_slashes(buf);
  952. #endif
  953.         pstrcat(buf, sizeof(buf), "/");
  954.         put_stabs_r(buf, N_SO, 0, 0,
  955.                     text_section->data_offset, text_section, section_sym);
  956.         put_stabs_r(file->filename, N_SO, 0, 0,
  957.                     text_section->data_offset, text_section, section_sym);
  958.     }
  959.     /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
  960.        symbols can be safely used */
  961.     put_elf_sym(symtab_section, 0, 0,
  962.                 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
  963.                 SHN_ABS, file->filename);
  964.  
  965.     /* define some often used types */
  966.     int_type.t = VT_INT;
  967.  
  968.     char_pointer_type.t = VT_BYTE;
  969.     mk_pointer(&char_pointer_type);
  970.  
  971. #if PTR_SIZE == 4
  972.     size_type.t = VT_INT;
  973. #else
  974.     size_type.t = VT_LLONG;
  975. #endif
  976.  
  977.     func_old_type.t = VT_FUNC;
  978.     func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
  979. #ifdef TCC_TARGET_ARM
  980.     arm_init(s1);
  981. #endif
  982.  
  983. #if 0
  984.     /* define 'void *alloca(unsigned int)' builtin function */
  985.     {
  986.         Sym *s1;
  987.  
  988.         p = anon_sym++;
  989.         sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
  990.         s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
  991.         s1->next = NULL;
  992.         sym->next = s1;
  993.         sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
  994.     }
  995. #endif
  996.  
  997.     define_start = define_stack;
  998.     nocode_wanted = 1;
  999.  
  1000.     if (setjmp(s1->error_jmp_buf) == 0) {
  1001.         s1->nb_errors = 0;
  1002.         s1->error_set_jmp_enabled = 1;
  1003.  
  1004.         ch = file->buf_ptr[0];
  1005.         tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
  1006.         parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR;
  1007.         next();
  1008.         decl(VT_CONST);
  1009.         if (tok != TOK_EOF)
  1010.             expect("declaration");
  1011.         check_vstack();
  1012.  
  1013.         /* end of translation unit info */
  1014.         if (s1->do_debug) {
  1015.             put_stabs_r(NULL, N_SO, 0, 0,
  1016.                         text_section->data_offset, text_section, section_sym);
  1017.         }
  1018.     }
  1019.  
  1020.     s1->error_set_jmp_enabled = 0;
  1021.  
  1022.     /* reset define stack, but leave -Dsymbols (may be incorrect if
  1023.        they are undefined) */
  1024.     free_defines(define_start);
  1025.  
  1026.     gen_inline_functions();
  1027.  
  1028.     sym_pop(&global_stack, NULL);
  1029.     sym_pop(&local_stack, NULL);
  1030.  
  1031.     return s1->nb_errors != 0 ? -1 : 0;
  1032. }
  1033.  
  1034. LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
  1035. {
  1036.     int len, ret;
  1037.  
  1038.     len = strlen(str);
  1039.     tcc_open_bf(s, "<string>", len);
  1040.     memcpy(file->buffer, str, len);
  1041.     ret = tcc_compile(s);
  1042.     tcc_close();
  1043.     return ret;
  1044. }
  1045.  
  1046. /* define a preprocessor symbol. A value can also be provided with the '=' operator */
  1047. LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
  1048. {
  1049.     int len1, len2;
  1050.     /* default value */
  1051.     if (!value)
  1052.         value = "1";
  1053.     len1 = strlen(sym);
  1054.     len2 = strlen(value);
  1055.  
  1056.     /* init file structure */
  1057.     tcc_open_bf(s1, "<define>", len1 + len2 + 1);
  1058.     memcpy(file->buffer, sym, len1);
  1059.     file->buffer[len1] = ' ';
  1060.     memcpy(file->buffer + len1 + 1, value, len2);
  1061.  
  1062.     /* parse with define parser */
  1063.     ch = file->buf_ptr[0];
  1064.     next_nomacro();
  1065.     parse_define();
  1066.  
  1067.     tcc_close();
  1068. }
  1069.  
  1070. /* undefine a preprocessor symbol */
  1071. LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
  1072. {
  1073.     TokenSym *ts;
  1074.     Sym *s;
  1075.     ts = tok_alloc(sym, strlen(sym));
  1076.     s = define_find(ts->tok);
  1077.     /* undefine symbol by putting an invalid name */
  1078.     if (s)
  1079.         define_undef(s);
  1080. }
  1081.  
  1082. /* cleanup all static data used during compilation */
  1083. static void tcc_cleanup(void)
  1084. {
  1085.     if (NULL == tcc_state)
  1086.         return;
  1087.     tcc_state = NULL;
  1088.  
  1089.     preprocess_delete();
  1090.  
  1091.     /* free sym_pools */
  1092.     dynarray_reset(&sym_pools, &nb_sym_pools);
  1093.     /* reset symbol stack */
  1094.     sym_free_first = NULL;
  1095. }
  1096.  
  1097. LIBTCCAPI TCCState *tcc_new(void)
  1098. {
  1099.     TCCState *s;
  1100.     char buffer[100];
  1101.     int a,b,c;
  1102.  
  1103.     tcc_cleanup();
  1104.  
  1105.     s = tcc_mallocz(sizeof(TCCState));
  1106.     if (!s)
  1107.         return NULL;
  1108.     tcc_state = s;
  1109. #ifdef _WIN32
  1110.     tcc_set_lib_path_w32(s);
  1111. #else
  1112.  
  1113. #if defined TCC_TARGET_MEOS && ! TCC_TARGET_MEOS_LINUX
  1114.     tcc_set_lib_path_kos(s);
  1115. #else
  1116.    
  1117. #ifdef TCC_TARGET_MEOS_LINUX
  1118.     tcc_set_lib_path_linux(s);
  1119. #else
  1120.     tcc_set_lib_path(s, CONFIG_TCCDIR);
  1121. #endif
  1122. #endif
  1123. #endif
  1124.     s->output_type = 0;
  1125.     preprocess_new();
  1126.     s->include_stack_ptr = s->include_stack;
  1127.  
  1128.     /* we add dummy defines for some special macros to speed up tests
  1129.        and to have working defined() */
  1130.     define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
  1131.     define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
  1132.     define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
  1133.     define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
  1134.  
  1135.     /* define __TINYC__ 92X  */
  1136.     sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
  1137.     sprintf(buffer, "%d", a*10000 + b*100 + c);
  1138.     tcc_define_symbol(s, "__TINYC__", buffer);
  1139.  
  1140.     /* standard defines */
  1141.     tcc_define_symbol(s, "__STDC__", NULL);
  1142.     tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
  1143.     tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
  1144.  
  1145.     /* target defines */
  1146. #if defined(TCC_TARGET_I386)
  1147.     tcc_define_symbol(s, "__i386__", NULL);
  1148.     tcc_define_symbol(s, "__i386", NULL);
  1149.     tcc_define_symbol(s, "i386", NULL);
  1150. #elif defined(TCC_TARGET_X86_64)
  1151.     tcc_define_symbol(s, "__x86_64__", NULL);
  1152. #elif defined(TCC_TARGET_ARM)
  1153.     tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
  1154.     tcc_define_symbol(s, "__arm_elf__", NULL);
  1155.     tcc_define_symbol(s, "__arm_elf", NULL);
  1156.     tcc_define_symbol(s, "arm_elf", NULL);
  1157.     tcc_define_symbol(s, "__arm__", NULL);
  1158.     tcc_define_symbol(s, "__arm", NULL);
  1159.     tcc_define_symbol(s, "arm", NULL);
  1160.     tcc_define_symbol(s, "__APCS_32__", NULL);
  1161.     tcc_define_symbol(s, "__ARMEL__", NULL);
  1162. #if defined(TCC_ARM_EABI)
  1163.     tcc_define_symbol(s, "__ARM_EABI__", NULL);
  1164. #endif
  1165. #if defined(TCC_ARM_HARDFLOAT)
  1166.     s->float_abi = ARM_HARD_FLOAT;
  1167.     tcc_define_symbol(s, "__ARM_PCS_VFP", NULL);
  1168. #else
  1169.     s->float_abi = ARM_SOFTFP_FLOAT;
  1170. #endif
  1171. #elif defined(TCC_TARGET_ARM64)
  1172.     tcc_define_symbol(s, "__aarch64__", NULL);
  1173. #endif
  1174.  
  1175. #ifdef TCC_TARGET_PE
  1176.     tcc_define_symbol(s, "_WIN32", NULL);
  1177. # ifdef TCC_TARGET_X86_64
  1178.     tcc_define_symbol(s, "_WIN64", NULL);
  1179. # endif
  1180. #elif defined(TCC_TARGET_MEOS) || defined(TCC_TARGET_MEOS_LINUX)
  1181.     tcc_define_symbol(s, "KOLIBRI",  NULL);
  1182.     tcc_define_symbol(s, "_KOLIBRI", NULL);
  1183.     tcc_define_symbol(s, "_KOLIBRI_",NULL);
  1184. #ifdef TCC_TARGET_KX
  1185.         tcc_define_symbol(s, "__KX__", NULL);
  1186. #endif
  1187. #else
  1188.     tcc_define_symbol(s, "__unix__", NULL);
  1189.     tcc_define_symbol(s, "__unix", NULL);
  1190.     tcc_define_symbol(s, "unix", NULL);
  1191. # if defined(__linux__)
  1192.     tcc_define_symbol(s, "__linux__", NULL);
  1193.     tcc_define_symbol(s, "__linux", NULL);
  1194. # endif
  1195. # if defined(__FreeBSD__)
  1196. #  define str(s) #s
  1197.     tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
  1198. #  undef str
  1199. # endif
  1200. # if defined(__FreeBSD_kernel__)
  1201.     tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
  1202. # endif
  1203. #endif
  1204. # if defined(__NetBSD__)
  1205. #  define str(s) #s
  1206.     tcc_define_symbol(s, "__NetBSD__", str( __NetBSD__));
  1207. #  undef str
  1208. # endif
  1209.    
  1210.     /* TinyCC & gcc defines */
  1211. #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
  1212.     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
  1213.     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
  1214. #else
  1215.     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long");
  1216.     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long");
  1217. #endif
  1218.  
  1219. #ifdef TCC_TARGET_PE
  1220.     tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
  1221.     tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short");
  1222. #else
  1223.     tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
  1224.     /* wint_t is unsigned int by default, but (signed) int on BSDs
  1225.        and unsigned short on windows.  Other OSes might have still
  1226.        other conventions, sigh.  */
  1227. #if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__)
  1228.     tcc_define_symbol(s, "__WINT_TYPE__", "int");
  1229. #else
  1230.     tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
  1231. #endif
  1232. #endif
  1233.  
  1234. #ifndef TCC_TARGET_PE
  1235.     /* glibc defines */
  1236.     tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
  1237.     tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
  1238.     /* paths for crt objects */
  1239.     tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
  1240. #endif
  1241.  
  1242.     /* no section zero */
  1243.     dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
  1244.  
  1245.     /* create standard sections */
  1246.     text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
  1247.     data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
  1248.     bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
  1249.  
  1250.     /* symbols are always generated for linking stage */
  1251.     symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
  1252.                                 ".strtab",
  1253.                                 ".hashtab", SHF_PRIVATE);
  1254.     strtab_section = symtab_section->link;
  1255.     s->symtab = symtab_section;
  1256.  
  1257.     /* private symbol table for dynamic symbols */
  1258.     s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
  1259.                                       ".dynstrtab",
  1260.                                       ".dynhashtab", SHF_PRIVATE);
  1261.     s->alacarte_link = 1;
  1262.     s->nocommon = 1;
  1263.     s->warn_implicit_function_declaration = 1;
  1264.  
  1265. #ifdef CHAR_IS_UNSIGNED
  1266.     s->char_is_unsigned = 1;
  1267. #endif
  1268.     /* enable this if you want symbols with leading underscore on windows: */
  1269. #if 0 /* def TCC_TARGET_PE */
  1270.     s->leading_underscore = 1;
  1271. #endif
  1272. #if 0 /* TCC_TARGET_MEOS */
  1273.     s->leading_underscore = 1;
  1274. #endif
  1275. #ifdef TCC_TARGET_I386
  1276.     s->seg_size = 32;
  1277. #endif
  1278. #ifdef TCC_IS_NATIVE
  1279.     s->runtime_main = "main";
  1280. #endif
  1281.     return s;
  1282. }
  1283.  
  1284. LIBTCCAPI void tcc_delete(TCCState *s1)
  1285. {
  1286.     int i;
  1287.     int bench = s1->do_bench;
  1288.  
  1289.     tcc_cleanup();
  1290.  
  1291.     /* close a preprocessor output */
  1292.     if (s1->ppfp && s1->ppfp != stdout)
  1293.         fclose(s1->ppfp);
  1294.     if (s1->dffp && s1->dffp != s1->ppfp)
  1295.         fclose(s1->dffp);
  1296.  
  1297.     /* free all sections */
  1298.     for(i = 1; i < s1->nb_sections; i++)
  1299.         free_section(s1->sections[i]);
  1300.     dynarray_reset(&s1->sections, &s1->nb_sections);
  1301.  
  1302.     for(i = 0; i < s1->nb_priv_sections; i++)
  1303.         free_section(s1->priv_sections[i]);
  1304.     dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
  1305.  
  1306.     /* free any loaded DLLs */
  1307. #ifdef TCC_IS_NATIVE
  1308.     for ( i = 0; i < s1->nb_loaded_dlls; i++) {
  1309.         DLLReference *ref = s1->loaded_dlls[i];
  1310.         if ( ref->handle )
  1311.             dlclose(ref->handle);
  1312.     }
  1313. #endif
  1314.  
  1315.     /* free loaded dlls array */
  1316.     dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
  1317.  
  1318.     /* free library paths */
  1319.     dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
  1320.     dynarray_reset(&s1->crt_paths, &s1->nb_crt_paths);
  1321.  
  1322.     /* free include paths */
  1323.     dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
  1324.     dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
  1325.     dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
  1326.  
  1327.     tcc_free(s1->tcc_lib_path);
  1328.     tcc_free(s1->soname);
  1329.     tcc_free(s1->rpath);
  1330.     tcc_free(s1->init_symbol);
  1331.     tcc_free(s1->fini_symbol);
  1332.     tcc_free(s1->outfile);
  1333.     tcc_free(s1->deps_outfile);
  1334.     dynarray_reset(&s1->files, &s1->nb_files);
  1335.     dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
  1336.     dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
  1337.  
  1338. #ifdef TCC_IS_NATIVE
  1339. # ifdef HAVE_SELINUX
  1340.     munmap (s1->write_mem, s1->mem_size);
  1341.     munmap (s1->runtime_mem, s1->mem_size);
  1342. # else
  1343.     tcc_free(s1->runtime_mem);
  1344. # endif
  1345. #endif
  1346.  
  1347.     tcc_free(s1->sym_attrs);
  1348.     tcc_free(s1);
  1349.     tcc_memstats(bench);
  1350. }
  1351.  
  1352. LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
  1353. {
  1354.     tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);
  1355.     return 0;
  1356. }
  1357.  
  1358. LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
  1359. {
  1360.     tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
  1361.     return 0;
  1362. }
  1363.  
  1364. ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags, int filetype)
  1365. {
  1366.     ElfW(Ehdr) ehdr;
  1367.     int fd, ret, size;
  1368.  
  1369.     parse_flags = 0;
  1370. #ifdef CONFIG_TCC_ASM
  1371.     /* if .S file, define __ASSEMBLER__ like gcc does */
  1372.     if ((filetype == TCC_FILETYPE_ASM) || (filetype == TCC_FILETYPE_ASM_PP)) {
  1373.         tcc_define_symbol(s1, "__ASSEMBLER__", NULL);
  1374.         parse_flags = PARSE_FLAG_ASM_FILE;
  1375.     }
  1376. #endif
  1377.  
  1378.     /* open the file */
  1379.     ret = tcc_open(s1, filename);
  1380.     if (ret < 0) {
  1381.         if (flags & AFF_PRINT_ERROR)
  1382.             tcc_error_noabort("file '%s' not found", filename);
  1383.         return ret;
  1384.     }
  1385.  
  1386.     /* update target deps */
  1387.     dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
  1388.             tcc_strdup(filename));
  1389.  
  1390.     if (flags & AFF_PREPROCESS) {
  1391.         ret = tcc_preprocess(s1);
  1392.         goto the_end;
  1393.     }
  1394.  
  1395.     if (filetype == TCC_FILETYPE_C) {
  1396.         /* C file assumed */
  1397.         ret = tcc_compile(s1);
  1398.         goto the_end;
  1399.     }
  1400.  
  1401. #ifdef CONFIG_TCC_ASM
  1402.     if (filetype == TCC_FILETYPE_ASM_PP) {
  1403.         /* non preprocessed assembler */
  1404.         ret = tcc_assemble(s1, 1);
  1405.         goto the_end;
  1406.     }
  1407.  
  1408.     if (filetype == TCC_FILETYPE_ASM) {
  1409.         /* preprocessed assembler */
  1410.         ret = tcc_assemble(s1, 0);
  1411.         goto the_end;
  1412.     }
  1413. #endif
  1414.  
  1415.     fd = file->fd;
  1416.     /* assume executable format: auto guess file type */
  1417.     size = read(fd, &ehdr, sizeof(ehdr));
  1418.     lseek(fd, 0, SEEK_SET);
  1419.     if (size <= 0) {
  1420.         tcc_error_noabort("could not read header");
  1421.         goto the_end;
  1422.     }
  1423.  
  1424.     if (size == sizeof(ehdr) &&
  1425.         ehdr.e_ident[0] == ELFMAG0 &&
  1426.         ehdr.e_ident[1] == ELFMAG1 &&
  1427.         ehdr.e_ident[2] == ELFMAG2 &&
  1428.         ehdr.e_ident[3] == ELFMAG3) {
  1429.  
  1430.         /* do not display line number if error */
  1431.         file->line_num = 0;
  1432.         if (ehdr.e_type == ET_REL) {
  1433.             ret = tcc_load_object_file(s1, fd, 0);
  1434.             goto the_end;
  1435.  
  1436.         }
  1437. #if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS)
  1438.         if (ehdr.e_type == ET_DYN) {
  1439.             if (s1->output_type == TCC_OUTPUT_MEMORY) {
  1440. #ifdef TCC_IS_NATIVE
  1441.                 void *h;
  1442.                 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
  1443.                 if (h)
  1444. #endif
  1445.                     ret = 0;
  1446.             } else {
  1447.                 ret = tcc_load_dll(s1, fd, filename,
  1448.                                    (flags & AFF_REFERENCED_DLL) != 0);
  1449.             }
  1450.             goto the_end;
  1451.         }
  1452. #endif
  1453.         tcc_error_noabort("unrecognized ELF file");
  1454.         goto the_end;
  1455.     }
  1456.  
  1457.     if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
  1458.         file->line_num = 0; /* do not display line number if error */
  1459.         ret = tcc_load_archive(s1, fd);
  1460.         goto the_end;
  1461.     }
  1462.  
  1463. #ifdef TCC_TARGET_COFF
  1464.     if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
  1465.         ret = tcc_load_coff(s1, fd);
  1466.         goto the_end;
  1467.     }
  1468. #endif
  1469.  
  1470. #if defined (TCC_TARGET_PE) ||  (defined(TCC_TARGET_MEOS)  && !defined(TCC_TARGET_KX))
  1471.     ret = pe_load_file(s1, filename, fd);
  1472. #elif defined(TCC_TARGET_KX)
  1473.     ret = pe_load_def(s1, fd);
  1474. #else
  1475.     /* as GNU ld, consider it is an ld script if not recognized */
  1476.     ret = tcc_load_ldscript(s1);
  1477. #endif
  1478.     if (ret < 0)
  1479.         tcc_error_noabort("unrecognized file type");
  1480.  
  1481. the_end:
  1482.     tcc_close();
  1483.     return ret;
  1484. }
  1485.  
  1486. LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename, int filetype)
  1487. {
  1488.     if (s->output_type == TCC_OUTPUT_PREPROCESS)
  1489.         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS, filetype);
  1490.     else
  1491.         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR, filetype);
  1492. }
  1493.  
  1494. LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
  1495. {
  1496.     tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);
  1497.     return 0;
  1498. }
  1499.  
  1500. static int tcc_add_library_internal(TCCState *s, const char *fmt,
  1501.     const char *filename, int flags, char **paths, int nb_paths)
  1502. {
  1503.     char buf[1024];
  1504.     int i;
  1505.  
  1506.     for(i = 0; i < nb_paths; i++) {
  1507.         snprintf(buf, sizeof(buf), fmt, paths[i], filename);
  1508. //printf("tcc_add_library_internal::added lib [%s]\n", buf);
  1509.         if (tcc_add_file_internal(s, buf, flags, TCC_FILETYPE_BINARY) == 0)
  1510.             return 0;
  1511.     }
  1512.     return -1;
  1513. }
  1514.  
  1515. #if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS)
  1516. /* find and load a dll. Return non zero if not found */
  1517. /* XXX: add '-rpath' option support ? */
  1518. ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
  1519. {
  1520.     return tcc_add_library_internal(s, "%s/%s", filename, flags,
  1521.         s->library_paths, s->nb_library_paths);
  1522. }
  1523. #endif
  1524.  
  1525. ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
  1526. {
  1527.     if (-1 == tcc_add_library_internal(s, "%s/%s",
  1528.         filename, 0, s->crt_paths, s->nb_crt_paths))
  1529.         tcc_error_noabort("file '%s' not found", filename);
  1530.     return 0;
  1531. }
  1532.  
  1533. /* the library name is the same as the argument of the '-l' option */
  1534. LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
  1535. {
  1536. #if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS)
  1537.     const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
  1538.     const char **pp = s->static_link ? libs + 4 : libs;
  1539. #else
  1540.     const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
  1541.     const char **pp = s->static_link ? libs + 1 : libs;
  1542. #endif
  1543.     while (*pp) {
  1544.         if (0 == tcc_add_library_internal(s, *pp,
  1545.             libraryname, 0, s->library_paths, s->nb_library_paths))
  1546.             return 0;
  1547.         ++pp;
  1548.     }
  1549.     return -1;
  1550. }
  1551.  
  1552. PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
  1553. {
  1554.     int ret = tcc_add_library(s, libname);
  1555.     if (ret < 0)
  1556.         tcc_error_noabort("cannot find library 'lib%s'", libname);
  1557.     return ret;
  1558. }
  1559.  
  1560. /* habdle #pragma comment(lib,) */
  1561. ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
  1562. {
  1563.     int i;
  1564.     for (i = 0; i < s1->nb_pragma_libs; i++)
  1565.         tcc_add_library_err(s1, s1->pragma_libs[i]);
  1566. }
  1567.  
  1568. LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
  1569. {
  1570. #if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS)
  1571.     /* On x86_64 'val' might not be reachable with a 32bit offset.
  1572.        So it is handled here as if it were in a DLL. */
  1573.     pe_putimport(s, 0, name, (uintptr_t)val);
  1574. #else
  1575.     add_elf_sym(symtab_section, (uintptr_t)val, 0,
  1576.         ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
  1577.         SHN_ABS, name);
  1578. #endif
  1579.     return 0;
  1580. }
  1581.  
  1582.  
  1583. /* Windows stat* ( https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ):
  1584.  * - st_gid, st_ino, st_uid: only valid on "unix" file systems (not FAT, NTFS, etc)
  1585.  * - st_atime, st_ctime: not valid on FAT, valid on NTFS.
  1586.  * - Other fields should be reasonably compatible (and S_ISDIR should work).
  1587.  *
  1588.  * BY_HANDLE_FILE_INFORMATION ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788%28v=vs.85%29.aspx ):
  1589.  * - File index (combined nFileIndexHigh and nFileIndexLow) _may_ change when the file is opened.
  1590.  *   - But on NTFS: it's guaranteed to be the same value until the file is deleted.
  1591.  * - On windows server 2012 there's a 128b file id, and the 64b one via
  1592.  *   nFileIndex* is not guaranteed to be unique.
  1593.  *
  1594.  * - MS Docs suggest to that volume number with the file index could be used to
  1595.  *   check if two handles refer to the same file.
  1596.  */
  1597. #ifndef _WIN32
  1598. typedef struct stat                file_info_t;
  1599. #else
  1600. typedef BY_HANDLE_FILE_INFORMATION file_info_t;
  1601. #endif
  1602.  
  1603. int get_file_info(const char *fname, file_info_t *out_info)
  1604. {
  1605. #ifndef _WIN32
  1606.     return stat(fname, out_info);
  1607. #else
  1608.     int rv = 1;
  1609.     HANDLE h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  1610.                           FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL);
  1611.  
  1612.     if (h != INVALID_HANDLE_VALUE) {
  1613.         rv = !GetFileInformationByHandle(h, out_info);
  1614.         CloseHandle(h);
  1615.     }
  1616.     return rv;
  1617. #endif
  1618. }
  1619.  
  1620. int is_dir(file_info_t *info)
  1621. {
  1622. #ifndef _WIN32
  1623.     return S_ISDIR(info->st_mode);
  1624. #else
  1625.     return (info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
  1626.            FILE_ATTRIBUTE_DIRECTORY;
  1627. #endif
  1628. }
  1629.  
  1630. int is_same_file(const file_info_t *fi1, const file_info_t *fi2)
  1631. {
  1632. #ifndef _WIN32
  1633.     return fi1->st_dev == fi2->st_dev &&
  1634.            fi1->st_ino == fi2->st_ino;
  1635. #else
  1636.     return fi1->dwVolumeSerialNumber == fi2->dwVolumeSerialNumber &&
  1637.            fi1->nFileIndexHigh       == fi2->nFileIndexHigh &&
  1638.            fi1->nFileIndexLow        == fi2->nFileIndexLow;
  1639. #endif
  1640. }
  1641.  
  1642. static void
  1643. tcc_normalize_inc_dirs_aux(file_info_t *stats, size_t *pnum, char **path)
  1644. {
  1645.     size_t i, num = *pnum;
  1646.     if (get_file_info(*path, &stats[num]) || !is_dir(&stats[num]))
  1647.         goto remove;
  1648.     for (i = 0; i < num; i++)
  1649.         if (is_same_file(&stats[i], &stats[num]))
  1650.             goto remove;
  1651.     *pnum = num + 1;
  1652.     return;
  1653.  remove:
  1654.     tcc_free(*path);
  1655.     *path = 0;
  1656. }
  1657.  
  1658. /* Remove non-existent and duplicate directories from include paths. */
  1659. ST_FUNC void tcc_normalize_inc_dirs(TCCState *s)
  1660. {
  1661.     file_info_t *stats =
  1662.         tcc_malloc(((size_t)s->nb_sysinclude_paths + s->nb_include_paths) *
  1663.                    sizeof(*stats));
  1664.     size_t i, num = 0;
  1665.     for (i = 0; i < s->nb_sysinclude_paths; i++)
  1666.         tcc_normalize_inc_dirs_aux(stats, &num, &s->sysinclude_paths[i]);
  1667.     for (i = 0; i < s->nb_include_paths; i++)
  1668.         tcc_normalize_inc_dirs_aux(stats, &num, &s->include_paths[i]);
  1669.     tcc_free(stats);
  1670. }
  1671.  
  1672. LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
  1673. {
  1674.     s->output_type = output_type;
  1675.  
  1676.     if (s->output_type == TCC_OUTPUT_PREPROCESS) {
  1677.         if (!s->outfile) {
  1678.             s->ppfp = stdout;
  1679.         } else {
  1680.             s->ppfp = fopen(s->outfile, "w");
  1681.             if (!s->ppfp)
  1682.                 tcc_error("could not write '%s'", s->outfile);
  1683.         }
  1684.         s->dffp = s->ppfp;
  1685.         if (s->dflag == 'M')
  1686.             s->ppfp = NULL;
  1687.     }
  1688.     if (s->option_C && !s->ppfp)
  1689.         s->option_C = 0;
  1690.  
  1691.     if (!s->nostdinc) {
  1692.         /* default include paths */
  1693.         /* -isystem paths have already been handled */
  1694.         tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
  1695.     }
  1696.  
  1697.     /* if bound checking, then add corresponding sections */
  1698. #ifdef CONFIG_TCC_BCHECK
  1699.     if (s->do_bounds_check) {
  1700.         /* define symbol */
  1701.         tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
  1702.         /* create bounds sections */
  1703.         bounds_section = new_section(s, ".bounds",
  1704.                                      SHT_PROGBITS, SHF_ALLOC);
  1705.         lbounds_section = new_section(s, ".lbounds",
  1706.                                       SHT_PROGBITS, SHF_ALLOC);
  1707.     }
  1708. #endif
  1709.  
  1710.     if (s->char_is_unsigned) {
  1711.         tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
  1712.     }
  1713.  
  1714.     /* add debug sections */
  1715.     if (s->do_debug) {
  1716.         /* stab symbols */
  1717.         stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
  1718.         stab_section->sh_entsize = sizeof(Stab_Sym);
  1719.         stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
  1720.         put_elf_str(stabstr_section, "");
  1721.         stab_section->link = stabstr_section;
  1722.         /* put first entry */
  1723.         put_stabs("", 0, 0, 0, 0);
  1724.     }
  1725.  
  1726.     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
  1727. #ifdef TCC_TARGET_PE
  1728. # ifdef _WIN32
  1729.     tcc_add_systemdir(s);
  1730. # endif
  1731. #elif defined(TCC_TARGET_MEOS)
  1732.     if (s->output_type != TCC_OUTPUT_OBJ && !s->nostdlib)
  1733.     {
  1734.         tcc_add_crt(s,"crt0.o");
  1735.         //tcc_add_library(s,"lc.obj"); // adding libck.a dont work, because need to be added last
  1736.     }
  1737. #else
  1738.     /* add libc crt1/crti objects */
  1739.     if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
  1740.         !s->nostdlib) {
  1741.         if (output_type != TCC_OUTPUT_DLL)
  1742.             tcc_add_crt(s, "crt1.o");
  1743.         tcc_add_crt(s, "crti.o");
  1744.     }
  1745. #endif
  1746.  
  1747. #ifdef CONFIG_TCC_BCHECK
  1748.     if (s->do_bounds_check && (output_type == TCC_OUTPUT_EXE))
  1749.     {
  1750.         /* force a bcheck.o linking */
  1751.         addr_t func = TOK___bound_init;
  1752.         Sym *sym = external_global_sym(func, &func_old_type, 0);
  1753.         if (!sym->c)
  1754.             put_extern_sym(sym, NULL, 0, 0);
  1755.     }
  1756. #endif
  1757.  
  1758.     if (s->normalize_inc_dirs)
  1759.         tcc_normalize_inc_dirs(s);
  1760.     if (s->output_type == TCC_OUTPUT_PREPROCESS)
  1761.         print_defines();
  1762.  
  1763.     return 0;
  1764. }
  1765.  
  1766. LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
  1767. {
  1768.     tcc_free(s->tcc_lib_path);
  1769.     s->tcc_lib_path = tcc_strdup(path);
  1770. }
  1771.  
  1772. #define WD_ALL    0x0001 /* warning is activated when using -Wall */
  1773. #define FD_INVERT 0x0002 /* invert value before storing */
  1774.  
  1775. typedef struct FlagDef {
  1776.     uint16_t offset;
  1777.     uint16_t flags;
  1778.     const char *name;
  1779. } FlagDef;
  1780.  
  1781. static const FlagDef warning_defs[] = {
  1782.     { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
  1783.     { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
  1784.     { offsetof(TCCState, warn_error), 0, "error" },
  1785.     { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
  1786.       "implicit-function-declaration" },
  1787. };
  1788.  
  1789. ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
  1790.                     const char *name, int value)
  1791. {
  1792.     int i;
  1793.     const FlagDef *p;
  1794.     const char *r;
  1795.  
  1796.     r = name;
  1797.     if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
  1798.         r += 3;
  1799.         value = !value;
  1800.     }
  1801.     for(i = 0, p = flags; i < nb_flags; i++, p++) {
  1802.         if (!strcmp(r, p->name))
  1803.             goto found;
  1804.     }
  1805.     return -1;
  1806.  found:
  1807.     if (p->flags & FD_INVERT)
  1808.         value = !value;
  1809.     *(int *)((uint8_t *)s + p->offset) = value;
  1810.     return 0;
  1811. }
  1812.  
  1813. /* set/reset a warning */
  1814. static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
  1815. {
  1816.     int i;
  1817.     const FlagDef *p;
  1818.  
  1819.     if (!strcmp(warning_name, "all")) {
  1820.         for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
  1821.             if (p->flags & WD_ALL)
  1822.                 *(int *)((uint8_t *)s + p->offset) = 1;
  1823.         }
  1824.                 s->warn_unsupported = 1;  // siemargl. was unused flag about compiler features
  1825.         return 0;
  1826.     } else {
  1827.         return set_flag(s, warning_defs, countof(warning_defs),
  1828.                         warning_name, value);
  1829.     }
  1830. }
  1831.  
  1832. static const FlagDef flag_defs[] = {
  1833.     { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
  1834.     { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
  1835.     { offsetof(TCCState, nocommon), FD_INVERT, "common" },
  1836.     { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
  1837.     { offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
  1838.     { offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" },
  1839.     { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
  1840.     { offsetof(TCCState, normalize_inc_dirs), 0, "normalize-inc-dirs" },
  1841. };
  1842.  
  1843. /* set/reset a flag */
  1844. static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
  1845. {
  1846.     return set_flag(s, flag_defs, countof(flag_defs),
  1847.                     flag_name, value);
  1848. }
  1849.  
  1850.  
  1851. static int strstart(const char *val, const char **str)
  1852. {
  1853.     const char *p, *q;
  1854.     p = *str;
  1855.     q = val;
  1856.     while (*q) {
  1857.         if (*p != *q)
  1858.             return 0;
  1859.         p++;
  1860.         q++;
  1861.     }
  1862.     *str = p;
  1863.     return 1;
  1864. }
  1865.  
  1866. /* Like strstart, but automatically takes into account that ld options can
  1867.  *
  1868.  * - start with double or single dash (e.g. '--soname' or '-soname')
  1869.  * - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so'
  1870.  *   or '-Wl,-soname=x.so')
  1871.  *
  1872.  * you provide `val` always in 'option[=]' form (no leading -)
  1873.  */
  1874. static int link_option(const char *str, const char *val, const char **ptr)
  1875. {
  1876.     const char *p, *q;
  1877.  
  1878.     /* there should be 1 or 2 dashes */
  1879.     if (*str++ != '-')
  1880.         return 0;
  1881.     if (*str == '-')
  1882.         str++;
  1883.  
  1884.     /* then str & val should match (potentialy up to '=') */
  1885.     p = str;
  1886.     q = val;
  1887.  
  1888.     while (*q != '\0' && *q != '=') {
  1889.         if (*p != *q)
  1890.             return 0;
  1891.         p++;
  1892.         q++;
  1893.     }
  1894.  
  1895.     /* '=' near eos means ',' or '=' is ok */
  1896.     if (*q == '=') {
  1897.         if (*p != ',' && *p != '=')
  1898.             return 0;
  1899.         p++;
  1900.         q++;
  1901.     }
  1902.  
  1903.     if (ptr)
  1904.         *ptr = p;
  1905.     return 1;
  1906. }
  1907.  
  1908. static const char *skip_linker_arg(const char **str)
  1909. {
  1910.     const char *s1 = *str;
  1911.     const char *s2 = strchr(s1, ',');
  1912.     *str = s2 ? s2++ : (s2 = s1 + strlen(s1));
  1913.     return s2;
  1914. }
  1915.  
  1916. static char *copy_linker_arg(const char *p)
  1917. {
  1918.     const char *q = p;
  1919.     skip_linker_arg(&q);
  1920.     return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
  1921. }
  1922.  
  1923. /* set linker options */
  1924. static int tcc_set_linker(TCCState *s, const char *option)
  1925. {
  1926.     while (option && *option) {
  1927.  
  1928.         const char *p = option;
  1929.         char *end = NULL;
  1930.         int ignoring = 0;
  1931.  
  1932.         if (link_option(option, "Bsymbolic", &p)) {
  1933.             s->symbolic = 1;
  1934.         } else if (link_option(option, "nostdlib", &p)) {
  1935.             s->nostdlib = 1;
  1936.         } else if (link_option(option, "fini=", &p)) {
  1937.             s->fini_symbol = copy_linker_arg(p);
  1938.             ignoring = 1;
  1939.         } else if (link_option(option, "image-base=", &p)
  1940.                 || link_option(option, "Ttext=", &p)) {
  1941.             s->text_addr = strtoull(p, &end, 16);
  1942.             s->has_text_addr = 1;
  1943.         } else if (link_option(option, "init=", &p)) {
  1944.             s->init_symbol = copy_linker_arg(p);
  1945.             ignoring = 1;
  1946.         } else if (link_option(option, "oformat=", &p)) {
  1947. #if defined(TCC_TARGET_PE)
  1948.             if (strstart("pe-", &p)) {
  1949. #elif defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
  1950.             if (strstart("elf64-", &p)) {
  1951. #else
  1952.             if (strstart("elf32-", &p)) {
  1953. #endif
  1954.                 s->output_format = TCC_OUTPUT_FORMAT_ELF;
  1955.             } else if (!strcmp(p, "binary")) {
  1956.                 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
  1957. #ifdef TCC_TARGET_COFF
  1958.             } else if (!strcmp(p, "coff")) {
  1959.                 s->output_format = TCC_OUTPUT_FORMAT_COFF;
  1960. #endif
  1961.             } else
  1962.                 goto err;
  1963.  
  1964.         } else if (link_option(option, "as-needed", &p)) {
  1965.             ignoring = 1;
  1966.         } else if (link_option(option, "O", &p)) {
  1967.             ignoring = 1;
  1968.         } else if (link_option(option, "rpath=", &p)) {
  1969.             s->rpath = copy_linker_arg(p);
  1970.         } else if (link_option(option, "section-alignment=", &p)) {
  1971.             s->section_align = strtoul(p, &end, 16);
  1972.         } else if (link_option(option, "soname=", &p)) {
  1973.             s->soname = copy_linker_arg(p);
  1974. #ifdef TCC_TARGET_PE
  1975.         } else if (link_option(option, "file-alignment=", &p)) {
  1976.             s->pe_file_align = strtoul(p, &end, 16);
  1977.         } else if (link_option(option, "stack=", &p)) {
  1978.             s->pe_stack_size = strtoul(p, &end, 10);
  1979.         } else if (link_option(option, "subsystem=", &p)) {
  1980. #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
  1981.             if (!strcmp(p, "native")) {
  1982.                 s->pe_subsystem = 1;
  1983.             } else if (!strcmp(p, "console")) {
  1984.                 s->pe_subsystem = 3;
  1985.             } else if (!strcmp(p, "gui")) {
  1986.                 s->pe_subsystem = 2;
  1987.             } else if (!strcmp(p, "posix")) {
  1988.                 s->pe_subsystem = 7;
  1989.             } else if (!strcmp(p, "efiapp")) {
  1990.                 s->pe_subsystem = 10;
  1991.             } else if (!strcmp(p, "efiboot")) {
  1992.                 s->pe_subsystem = 11;
  1993.             } else if (!strcmp(p, "efiruntime")) {
  1994.                 s->pe_subsystem = 12;
  1995.             } else if (!strcmp(p, "efirom")) {
  1996.                 s->pe_subsystem = 13;
  1997. #elif defined(TCC_TARGET_ARM)
  1998.             if (!strcmp(p, "wince")) {
  1999.                 s->pe_subsystem = 9;
  2000. #endif
  2001.             } else
  2002.                 goto err;
  2003. #endif
  2004.         } else
  2005.             goto err;
  2006.  
  2007.         if (ignoring && s->warn_unsupported) err: {
  2008.             char buf[100], *e;
  2009.             pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
  2010.             if (ignoring)
  2011.                 tcc_warning("unsupported linker option '%s'", buf);
  2012.             else
  2013.                 tcc_error("unsupported linker option '%s'", buf);
  2014.         }
  2015.         option = skip_linker_arg(&p);
  2016.     }
  2017.     return 0;
  2018. }
  2019.  
  2020. typedef struct TCCOption {
  2021.     const char *name;
  2022.     uint16_t index;
  2023.     uint16_t flags;
  2024. } TCCOption;
  2025.  
  2026. enum {
  2027.     TCC_OPTION_HELP,
  2028.     TCC_OPTION_I,
  2029.     TCC_OPTION_D,
  2030.     TCC_OPTION_U,
  2031.     TCC_OPTION_P,
  2032.     TCC_OPTION_L,
  2033.     TCC_OPTION_B,
  2034.     TCC_OPTION_l,
  2035.     TCC_OPTION_bench,
  2036.     TCC_OPTION_bt,
  2037.     TCC_OPTION_b,
  2038.     TCC_OPTION_g,
  2039.     TCC_OPTION_c,
  2040.     TCC_OPTION_C,
  2041.     TCC_OPTION_dumpversion,
  2042.     TCC_OPTION_d,
  2043.     TCC_OPTION_float_abi,
  2044.     TCC_OPTION_static,
  2045.     TCC_OPTION_std,
  2046.     TCC_OPTION_shared,
  2047.     TCC_OPTION_soname,
  2048.     TCC_OPTION_o,
  2049.     TCC_OPTION_r,
  2050.     TCC_OPTION_s,
  2051.     TCC_OPTION_traditional,
  2052.     TCC_OPTION_Wl,
  2053.     TCC_OPTION_W,
  2054.     TCC_OPTION_O,
  2055.     TCC_OPTION_m,
  2056.     TCC_OPTION_f,
  2057.     TCC_OPTION_isystem,
  2058.     TCC_OPTION_iwithprefix,
  2059.     TCC_OPTION_nostdinc,
  2060.     TCC_OPTION_nostdlib,
  2061.     TCC_OPTION_print_search_dirs,
  2062.     TCC_OPTION_rdynamic,
  2063.     TCC_OPTION_pedantic,
  2064.     TCC_OPTION_pthread,
  2065.     TCC_OPTION_run,
  2066.     TCC_OPTION_v,
  2067.     TCC_OPTION_w,
  2068.     TCC_OPTION_pipe,
  2069.     TCC_OPTION_E,
  2070.     TCC_OPTION_MD,
  2071.     TCC_OPTION_MF,
  2072.     TCC_OPTION_x,
  2073.     TCC_OPTION_stack,
  2074.     TCC_OPTION_nobss
  2075. };
  2076.  
  2077. #define TCC_OPTION_HAS_ARG 0x0001
  2078. #define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
  2079.  
  2080. static const TCCOption tcc_options[] = {
  2081.     { "h", TCC_OPTION_HELP, 0 },
  2082.     { "-help", TCC_OPTION_HELP, 0 },
  2083.     { "?", TCC_OPTION_HELP, 0 },
  2084.     { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
  2085.     { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
  2086.     { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
  2087.     { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2088.     { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
  2089.     { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
  2090.     { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2091.     { "bench", TCC_OPTION_bench, 0 },
  2092. #ifdef CONFIG_TCC_BACKTRACE
  2093.     { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
  2094. #endif
  2095. #ifdef CONFIG_TCC_BCHECK
  2096.     { "b", TCC_OPTION_b, 0 },
  2097. #endif
  2098.     { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2099.     { "c", TCC_OPTION_c, 0 },
  2100.     { "C", TCC_OPTION_C, 0 },
  2101.     { "dumpversion", TCC_OPTION_dumpversion, 0},
  2102.     { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2103. #ifdef TCC_TARGET_ARM
  2104.     { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG },
  2105. #endif
  2106.     { "static", TCC_OPTION_static, 0 },
  2107.     { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2108.     { "shared", TCC_OPTION_shared, 0 },
  2109.     { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
  2110.     { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
  2111.     { "pedantic", TCC_OPTION_pedantic, 0},
  2112.     { "pthread", TCC_OPTION_pthread, 0},
  2113.     { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2114.     { "rdynamic", TCC_OPTION_rdynamic, 0 },
  2115.     { "r", TCC_OPTION_r, 0 },
  2116.     { "s", TCC_OPTION_s, 0 },
  2117.     { "traditional", TCC_OPTION_traditional, 0 },
  2118.     { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2119.     { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2120.     { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2121.     { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
  2122.     { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2123.     { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
  2124.     { "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG },
  2125.     { "nostdinc", TCC_OPTION_nostdinc, 0 },
  2126.     { "nostdlib", TCC_OPTION_nostdlib, 0 },
  2127.     { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
  2128.     { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2129.     { "w", TCC_OPTION_w, 0 },
  2130.     { "pipe", TCC_OPTION_pipe, 0},
  2131.     { "E", TCC_OPTION_E, 0},
  2132.     { "MD", TCC_OPTION_MD, 0},
  2133.     { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
  2134.     { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
  2135.     { "stack", TCC_OPTION_stack, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
  2136. #if defined(TCC_TARGET_MEOS) && !defined (TCC_TARGET_KX)
  2137.     { "nobss", TCC_OPTION_nobss, 0 },
  2138. #endif
  2139.     { NULL, 0, 0 },
  2140. };
  2141.  
  2142. static void parse_option_D(TCCState *s1, const char *optarg)
  2143. {
  2144.     char *sym = tcc_strdup(optarg);
  2145.     char *value = strchr(sym, '=');
  2146.     if (value)
  2147.         *value++ = '\0';
  2148.     tcc_define_symbol(s1, sym, value);
  2149.     tcc_free(sym);
  2150. }
  2151.  
  2152. static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
  2153. {
  2154.     int len = strlen(filename);
  2155.     char *p = tcc_malloc(len + 2);
  2156.     if (filetype) {
  2157.         *p = filetype;
  2158.     }
  2159.     else {
  2160.         /* use a file extension to detect a filetype */
  2161.         const char *ext = tcc_fileextension(filename);
  2162.         if (ext[0]) {
  2163.             ext++;
  2164.             if (!strcmp(ext, "S"))
  2165.                 *p = TCC_FILETYPE_ASM_PP;
  2166.             else
  2167.             if (!strcmp(ext, "s"))
  2168.                 *p = TCC_FILETYPE_ASM;
  2169.             else
  2170.             if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i"))
  2171.                 *p = TCC_FILETYPE_C;
  2172.             else
  2173.                 *p = TCC_FILETYPE_BINARY;
  2174.         }
  2175.         else {
  2176.             *p = TCC_FILETYPE_C;
  2177.         }
  2178.     }
  2179.     strcpy(p+1, filename);
  2180.     dynarray_add((void ***)&s->files, &s->nb_files, p);
  2181. }
  2182.  
  2183. ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
  2184. {
  2185.     const TCCOption *popt;
  2186.     const char *optarg, *r;
  2187.     int optind = 0;
  2188.     ParseArgsState *pas = s->parse_args_state;
  2189.  
  2190. /*
  2191. #ifdef TCC_TARGET_MEOS
  2192. // siemargl testing
  2193.         s->output_format = TCC_OUTPUT_FORMAT_COFF;
  2194. #endif
  2195. */
  2196.     while (optind < argc) {
  2197.  
  2198.         r = argv[optind++];
  2199.         if (r[0] != '-' || r[1] == '\0') {
  2200.             /* handle list files */
  2201.             if (r[0] == '@' && r[1]) {
  2202.                 char buf[sizeof file->filename], *p;
  2203.                 char **argv = NULL;
  2204.                 int argc = 0;
  2205.                 FILE *fp;
  2206.  
  2207.                 fp = fopen(r + 1, "rb");
  2208.                 if (fp == NULL)
  2209.                     tcc_error("list file '%s' not found", r + 1);
  2210.                 while (fgets(buf, sizeof buf, fp)) {
  2211.                     p = trimfront(trimback(buf, strchr(buf, 0)));
  2212.                     if (0 == *p || ';' == *p)
  2213.                         continue;
  2214.                     dynarray_add((void ***)&argv, &argc, tcc_strdup(p));
  2215.                 }
  2216.                 fclose(fp);
  2217.                 tcc_parse_args1(s, argc, argv);
  2218.                 dynarray_reset(&argv, &argc);
  2219.             } else {
  2220.                 args_parser_add_file(s, r, pas->filetype);
  2221.                 if (pas->run) {
  2222.                     optind--;
  2223.                     /* argv[0] will be this file */
  2224.                     break;
  2225.                 }
  2226.             }
  2227.             continue;
  2228.         }
  2229.  
  2230.         /* find option in table */
  2231.         for(popt = tcc_options; ; ++popt) {
  2232.             const char *p1 = popt->name;
  2233.             const char *r1 = r + 1;
  2234.             if (p1 == NULL)
  2235.                 tcc_error("invalid option -- '%s'", r);
  2236.             if (!strstart(p1, &r1))
  2237.                 continue;
  2238.             optarg = r1;
  2239.             if (popt->flags & TCC_OPTION_HAS_ARG) {
  2240.                 if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
  2241.                     if (optind >= argc)
  2242.                         tcc_error("argument to '%s' is missing", r);
  2243.                     optarg = argv[optind++];
  2244.                 }
  2245.             } else if (*r1 != '\0')
  2246.                 continue;
  2247.             break;
  2248.         }
  2249.  
  2250.         switch(popt->index) {
  2251.         case TCC_OPTION_HELP:
  2252.             return 0;
  2253.         case TCC_OPTION_I:
  2254.             tcc_add_include_path(s, optarg);
  2255.             break;
  2256.         case TCC_OPTION_D:
  2257.             parse_option_D(s, optarg);
  2258.             break;
  2259.         case TCC_OPTION_U:
  2260.             tcc_undefine_symbol(s, optarg);
  2261.             break;
  2262.         case TCC_OPTION_L:
  2263.             tcc_add_library_path(s, optarg);
  2264.             break;
  2265.         case TCC_OPTION_B:
  2266.             /* set tcc utilities path (mainly for tcc development) */
  2267.             tcc_set_lib_path(s, optarg);
  2268.             break;
  2269.         case TCC_OPTION_l:
  2270.             args_parser_add_file(s, r, TCC_FILETYPE_BINARY);
  2271.             s->nb_libraries++;
  2272.             break;
  2273.         case TCC_OPTION_pthread:
  2274.             parse_option_D(s, "_REENTRANT");
  2275.             pas->pthread = 1;
  2276.             break;
  2277.         case TCC_OPTION_bench:
  2278.             s->do_bench = 1;
  2279.             break;
  2280. #ifdef CONFIG_TCC_BACKTRACE
  2281.         case TCC_OPTION_bt:
  2282.             tcc_set_num_callers(atoi(optarg));
  2283.             break;
  2284. #endif
  2285. #ifdef CONFIG_TCC_BCHECK
  2286.         case TCC_OPTION_b:
  2287.             s->do_bounds_check = 1;
  2288.             s->do_debug = 1;
  2289.             break;
  2290. #endif
  2291.         case TCC_OPTION_g:
  2292.             s->do_debug = 1;
  2293.             break;
  2294.         case TCC_OPTION_c:
  2295.             if (s->output_type)
  2296.                 tcc_warning("-c: some compiler action already specified (%d)", s->output_type);
  2297.             s->output_type = TCC_OUTPUT_OBJ;
  2298.             break;
  2299.         case TCC_OPTION_C:
  2300.             s->option_C = 1;
  2301.             break;
  2302.         case TCC_OPTION_d:
  2303.             if (*optarg == 'D' || *optarg == 'M')
  2304.                 s->dflag = *optarg;
  2305.             else {
  2306.                 if (s->warn_unsupported)
  2307.                     goto unsupported_option;
  2308.                 tcc_error("invalid option -- '%s'", r);
  2309.             }
  2310.             break;
  2311. #ifdef TCC_TARGET_ARM
  2312.         case TCC_OPTION_float_abi:
  2313.             /* tcc doesn't support soft float yet */
  2314.             if (!strcmp(optarg, "softfp")) {
  2315.                 s->float_abi = ARM_SOFTFP_FLOAT;
  2316.                 tcc_undefine_symbol(s, "__ARM_PCS_VFP");
  2317.             } else if (!strcmp(optarg, "hard"))
  2318.                 s->float_abi = ARM_HARD_FLOAT;
  2319.             else
  2320.                 tcc_error("unsupported float abi '%s'", optarg);
  2321.             break;
  2322. #endif
  2323.         case TCC_OPTION_static:
  2324.             s->static_link = 1;
  2325.             break;
  2326.         case TCC_OPTION_std:
  2327.             /* silently ignore, a current purpose:
  2328.                allow to use a tcc as a reference compiler for "make test" */
  2329.             break;
  2330.         case TCC_OPTION_shared:
  2331.             if (s->output_type)
  2332.                 tcc_warning("-shared: some compiler action already specified (%d)", s->output_type);
  2333.             s->output_type = TCC_OUTPUT_DLL;
  2334.             break;
  2335.         case TCC_OPTION_soname:
  2336.             s->soname = tcc_strdup(optarg);
  2337.             break;
  2338.         case TCC_OPTION_m:
  2339.             s->option_m = tcc_strdup(optarg);
  2340.             break;
  2341.         case TCC_OPTION_o:
  2342.             if (s->outfile) {
  2343.                 tcc_warning("multiple -o option");
  2344.                 tcc_free(s->outfile);
  2345.             }
  2346.             s->outfile = tcc_strdup(optarg);
  2347.             break;
  2348.         case TCC_OPTION_r:
  2349.             /* generate a .o merging several output files */
  2350.             if (s->output_type)
  2351.                 tcc_warning("-r: some compiler action already specified (%d)", s->output_type);
  2352.             s->option_r = 1;
  2353.             s->output_type = TCC_OUTPUT_OBJ;
  2354.             break;
  2355.         case TCC_OPTION_isystem:
  2356.             tcc_add_sysinclude_path(s, optarg);
  2357.             break;
  2358.         case TCC_OPTION_iwithprefix:
  2359.             if (1) {
  2360.                 char buf[1024];
  2361.                 int buf_size = sizeof(buf)-1;
  2362.                 char *p = &buf[0];
  2363.  
  2364.                 char *sysroot = "{B}/";
  2365.                 int len = strlen(sysroot);
  2366.                 if (len > buf_size)
  2367.                     len = buf_size;
  2368.                 strncpy(p, sysroot, len);
  2369.                 p += len;
  2370.                 buf_size -= len;
  2371.  
  2372.                 len = strlen(optarg);
  2373.                 if (len > buf_size)
  2374.                     len = buf_size;
  2375.                 strncpy(p, optarg, len+1);
  2376.                 tcc_add_sysinclude_path(s, buf);
  2377.             }
  2378.             break;
  2379.         case TCC_OPTION_nostdinc:
  2380.             s->nostdinc = 1;
  2381.             break;
  2382.         case TCC_OPTION_nostdlib:
  2383.             s->nostdlib = 1;
  2384.             break;
  2385.         case TCC_OPTION_print_search_dirs:
  2386.             s->print_search_dirs = 1;
  2387.             break;
  2388.         case TCC_OPTION_run:
  2389.             if (s->output_type)
  2390.                 tcc_warning("-run: some compiler action already specified (%d)", s->output_type);
  2391.             s->output_type = TCC_OUTPUT_MEMORY;
  2392.             tcc_set_options(s, optarg);
  2393.             pas->run = 1;
  2394.             break;
  2395.         case TCC_OPTION_v:
  2396.             do ++s->verbose; while (*optarg++ == 'v');
  2397.             break;
  2398.         case TCC_OPTION_f:
  2399.             if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
  2400.                 goto unsupported_option;
  2401.             break;
  2402.         case TCC_OPTION_W:
  2403.             if (tcc_set_warning(s, optarg, 1) < 0 &&
  2404.                 s->warn_unsupported)
  2405.                 goto unsupported_option;
  2406.             break;
  2407.         case TCC_OPTION_w:
  2408.             s->warn_none = 1;
  2409.             break;
  2410.         case TCC_OPTION_rdynamic:
  2411.             s->rdynamic = 1;
  2412.             break;
  2413.         case TCC_OPTION_Wl:
  2414.             if (pas->linker_arg.size)
  2415.                 --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ',');
  2416.             cstr_cat(&pas->linker_arg, optarg, 0);
  2417.             break;
  2418.         case TCC_OPTION_E:
  2419.             if (s->output_type)
  2420.                 tcc_warning("-E: some compiler action already specified (%d)", s->output_type);
  2421.             s->output_type = TCC_OUTPUT_PREPROCESS;
  2422.             break;
  2423.         case TCC_OPTION_P:
  2424.             s->Pflag = atoi(optarg) + 1;
  2425.             break;
  2426.         case TCC_OPTION_MD:
  2427.             s->gen_deps = 1;
  2428.             break;
  2429.         case TCC_OPTION_MF:
  2430.             s->deps_outfile = tcc_strdup(optarg);
  2431.             break;
  2432.         case TCC_OPTION_dumpversion:
  2433.             printf ("%s\n", TCC_VERSION);
  2434.             exit(0);
  2435.         case TCC_OPTION_s:
  2436.             s->do_strip = 1;
  2437.             break;
  2438.         case TCC_OPTION_traditional:
  2439.             break;
  2440.         case TCC_OPTION_x:
  2441.             if (*optarg == 'c')
  2442.                 pas->filetype = TCC_FILETYPE_C;
  2443.             else
  2444.             if (*optarg == 'a')
  2445.                 pas->filetype = TCC_FILETYPE_ASM_PP;
  2446.             else
  2447.             if (*optarg == 'n')
  2448.                 pas->filetype = 0;
  2449.             else
  2450.                 tcc_warning("unsupported language '%s'", optarg);
  2451.             break;
  2452.         case TCC_OPTION_O:
  2453.             if (1) {
  2454.                 int opt = atoi(optarg);
  2455.                 char *sym = "__OPTIMIZE__";
  2456.                 if (opt)
  2457.                     tcc_define_symbol(s, sym, 0);
  2458.                 else
  2459.                     tcc_undefine_symbol(s, sym);
  2460.             }
  2461.             break;
  2462.         case TCC_OPTION_pedantic:
  2463.         case TCC_OPTION_pipe:
  2464.             /* ignored */
  2465.             break;
  2466.         case TCC_OPTION_stack:
  2467. #ifdef TCC_TARGET_MEOS
  2468.             s->pe_stack_size = strtoul(optarg+1, NULL, 10);
  2469. #endif
  2470.             break;
  2471. #if defined(TCC_TARGET_MEOS) && !defined (TCC_TARGET_KX)
  2472.         case TCC_OPTION_nobss:
  2473.             s->nobss = 1;
  2474.             break;
  2475. #endif
  2476.         default:
  2477.             if (s->warn_unsupported) {
  2478.             unsupported_option:
  2479.                 tcc_warning("unsupported option '%s'", r);
  2480.             }
  2481.             break;
  2482.         }
  2483.     }
  2484.     return optind;
  2485. }
  2486.  
  2487. PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
  2488. {
  2489.     ParseArgsState *pas;
  2490.     int ret, is_allocated = 0;
  2491.  
  2492.     if (!s->parse_args_state) {
  2493.         s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState));
  2494.         cstr_new(&s->parse_args_state->linker_arg);
  2495.         is_allocated = 1;
  2496.     }
  2497.     pas = s->parse_args_state;
  2498.  
  2499.     ret = tcc_parse_args1(s, argc, argv);
  2500.  
  2501.     if (s->output_type == 0)
  2502.         s->output_type = TCC_OUTPUT_EXE;
  2503.  
  2504.     if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ)
  2505.         tcc_set_options(s, "-lpthread");
  2506.  
  2507.     if (s->output_type == TCC_OUTPUT_EXE)
  2508.         tcc_set_linker(s, (const char *)pas->linker_arg.data);
  2509.  
  2510.     if (is_allocated) {
  2511.         cstr_free(&pas->linker_arg);
  2512.         tcc_free(pas);
  2513.         s->parse_args_state = NULL;
  2514.     }
  2515.     return ret;
  2516. }
  2517.  
  2518. LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
  2519. {
  2520.     const char *s1;
  2521.     char **argv, *arg;
  2522.     int argc, len;
  2523.     int ret;
  2524.  
  2525.     argc = 0, argv = NULL;
  2526.     for(;;) {
  2527.         while (is_space(*str))
  2528.             str++;
  2529.         if (*str == '\0')
  2530.             break;
  2531.         s1 = str;
  2532.         while (*str != '\0' && !is_space(*str))
  2533.             str++;
  2534.         len = str - s1;
  2535.         arg = tcc_malloc(len + 1);
  2536.         pstrncpy(arg, s1, len);
  2537.         dynarray_add((void ***)&argv, &argc, arg);
  2538.     }
  2539.     ret = tcc_parse_args(s, argc, argv);
  2540.     dynarray_reset(&argv, &argc);
  2541.     return ret;
  2542. }
  2543.  
  2544. PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
  2545. {
  2546.     double tt;
  2547.     tt = (double)total_time / 1000000.0;
  2548.     if (tt < 0.001)
  2549.         tt = 0.001;
  2550.     if (total_bytes < 1)
  2551.         total_bytes = 1;
  2552.     fprintf(stdout, "%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
  2553.            tok_ident - TOK_IDENT, total_lines, total_bytes,
  2554.            tt, (int)(total_lines / tt),
  2555.            total_bytes / tt / 1000000.0);
  2556. }
  2557.  
  2558. PUB_FUNC void tcc_set_environment(TCCState *s)
  2559. {
  2560.     char * path;
  2561.  
  2562.     path = getenv("C_INCLUDE_PATH");
  2563.     if(path != NULL) {
  2564.         tcc_add_include_path(s, path);
  2565.     }
  2566.     path = getenv("CPATH");
  2567.     if(path != NULL) {
  2568.         tcc_add_include_path(s, path);
  2569.     }
  2570.     path = getenv("LIBRARY_PATH");
  2571.     if(path != NULL) {
  2572.         tcc_add_library_path(s, path);
  2573.     }
  2574. }
  2575.