Subversion Repositories Kolibri OS

Rev

Rev 9153 | Rev 9305 | 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. #else
  1185.     tcc_define_symbol(s, "__unix__", NULL);
  1186.     tcc_define_symbol(s, "__unix", NULL);
  1187.     tcc_define_symbol(s, "unix", NULL);
  1188. # if defined(__linux__)
  1189.     tcc_define_symbol(s, "__linux__", NULL);
  1190.     tcc_define_symbol(s, "__linux", NULL);
  1191. # endif
  1192. # if defined(__FreeBSD__)
  1193. #  define str(s) #s
  1194.     tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
  1195. #  undef str
  1196. # endif
  1197. # if defined(__FreeBSD_kernel__)
  1198.     tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
  1199. # endif
  1200. #endif
  1201. # if defined(__NetBSD__)
  1202. #  define str(s) #s
  1203.     tcc_define_symbol(s, "__NetBSD__", str( __NetBSD__));
  1204. #  undef str
  1205. # endif
  1206.    
  1207.     /* TinyCC & gcc defines */
  1208. #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
  1209.     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
  1210.     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
  1211. #else
  1212.     tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long");
  1213.     tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long");
  1214. #endif
  1215.  
  1216. #ifdef TCC_TARGET_PE
  1217.     tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
  1218.     tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short");
  1219. #else
  1220.     tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
  1221.     /* wint_t is unsigned int by default, but (signed) int on BSDs
  1222.        and unsigned short on windows.  Other OSes might have still
  1223.        other conventions, sigh.  */
  1224. #if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__)
  1225.     tcc_define_symbol(s, "__WINT_TYPE__", "int");
  1226. #else
  1227.     tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
  1228. #endif
  1229. #endif
  1230.  
  1231. #ifndef TCC_TARGET_PE
  1232.     /* glibc defines */
  1233.     tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
  1234.     tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
  1235.     /* paths for crt objects */
  1236.     tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
  1237. #endif
  1238.  
  1239.     /* no section zero */
  1240.     dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
  1241.  
  1242.     /* create standard sections */
  1243.     text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
  1244.     data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
  1245.     bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
  1246.  
  1247.     /* symbols are always generated for linking stage */
  1248.     symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
  1249.                                 ".strtab",
  1250.                                 ".hashtab", SHF_PRIVATE);
  1251.     strtab_section = symtab_section->link;
  1252.     s->symtab = symtab_section;
  1253.  
  1254.     /* private symbol table for dynamic symbols */
  1255.     s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
  1256.                                       ".dynstrtab",
  1257.                                       ".dynhashtab", SHF_PRIVATE);
  1258.     s->alacarte_link = 1;
  1259.     s->nocommon = 1;
  1260.     s->warn_implicit_function_declaration = 1;
  1261.  
  1262. #ifdef CHAR_IS_UNSIGNED
  1263.     s->char_is_unsigned = 1;
  1264. #endif
  1265.     /* enable this if you want symbols with leading underscore on windows: */
  1266. #if 0 /* def TCC_TARGET_PE */
  1267.     s->leading_underscore = 1;
  1268. #endif
  1269. #if 0 /* TCC_TARGET_MEOS */
  1270.     s->leading_underscore = 1;
  1271. #endif
  1272. #ifdef TCC_TARGET_I386
  1273.     s->seg_size = 32;
  1274. #endif
  1275. #ifdef TCC_IS_NATIVE
  1276.     s->runtime_main = "main";
  1277. #endif
  1278.     return s;
  1279. }
  1280.  
  1281. LIBTCCAPI void tcc_delete(TCCState *s1)
  1282. {
  1283.     int i;
  1284.     int bench = s1->do_bench;
  1285.  
  1286.     tcc_cleanup();
  1287.  
  1288.     /* close a preprocessor output */
  1289.     if (s1->ppfp && s1->ppfp != stdout)
  1290.         fclose(s1->ppfp);
  1291.     if (s1->dffp && s1->dffp != s1->ppfp)
  1292.         fclose(s1->dffp);
  1293.  
  1294.     /* free all sections */
  1295.     for(i = 1; i < s1->nb_sections; i++)
  1296.         free_section(s1->sections[i]);
  1297.     dynarray_reset(&s1->sections, &s1->nb_sections);
  1298.  
  1299.     for(i = 0; i < s1->nb_priv_sections; i++)
  1300.         free_section(s1->priv_sections[i]);
  1301.     dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
  1302.  
  1303.     /* free any loaded DLLs */
  1304. #ifdef TCC_IS_NATIVE
  1305.     for ( i = 0; i < s1->nb_loaded_dlls; i++) {
  1306.         DLLReference *ref = s1->loaded_dlls[i];
  1307.         if ( ref->handle )
  1308.             dlclose(ref->handle);
  1309.     }
  1310. #endif
  1311.  
  1312.     /* free loaded dlls array */
  1313.     dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
  1314.  
  1315.     /* free library paths */
  1316.     dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
  1317.     dynarray_reset(&s1->crt_paths, &s1->nb_crt_paths);
  1318.  
  1319.     /* free include paths */
  1320.     dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
  1321.     dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
  1322.     dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
  1323.  
  1324.     tcc_free(s1->tcc_lib_path);
  1325.     tcc_free(s1->soname);
  1326.     tcc_free(s1->rpath);
  1327.     tcc_free(s1->init_symbol);
  1328.     tcc_free(s1->fini_symbol);
  1329.     tcc_free(s1->outfile);
  1330.     tcc_free(s1->deps_outfile);
  1331.     dynarray_reset(&s1->files, &s1->nb_files);
  1332.     dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
  1333.     dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
  1334.  
  1335. #ifdef TCC_IS_NATIVE
  1336. # ifdef HAVE_SELINUX
  1337.     munmap (s1->write_mem, s1->mem_size);
  1338.     munmap (s1->runtime_mem, s1->mem_size);
  1339. # else
  1340.     tcc_free(s1->runtime_mem);
  1341. # endif
  1342. #endif
  1343.  
  1344.     tcc_free(s1->sym_attrs);
  1345.     tcc_free(s1);
  1346.     tcc_memstats(bench);
  1347. }
  1348.  
  1349. LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
  1350. {
  1351.     tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);
  1352.     return 0;
  1353. }
  1354.  
  1355. LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
  1356. {
  1357.     tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
  1358.     return 0;
  1359. }
  1360.  
  1361. ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags, int filetype)
  1362. {
  1363.     ElfW(Ehdr) ehdr;
  1364.     int fd, ret, size;
  1365.  
  1366.     parse_flags = 0;
  1367. #ifdef CONFIG_TCC_ASM
  1368.     /* if .S file, define __ASSEMBLER__ like gcc does */
  1369.     if ((filetype == TCC_FILETYPE_ASM) || (filetype == TCC_FILETYPE_ASM_PP)) {
  1370.         tcc_define_symbol(s1, "__ASSEMBLER__", NULL);
  1371.         parse_flags = PARSE_FLAG_ASM_FILE;
  1372.     }
  1373. #endif
  1374.  
  1375.     /* open the file */
  1376.     ret = tcc_open(s1, filename);
  1377.     if (ret < 0) {
  1378.         if (flags & AFF_PRINT_ERROR)
  1379.             tcc_error_noabort("file '%s' not found", filename);
  1380.         return ret;
  1381.     }
  1382.  
  1383.     /* update target deps */
  1384.     dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
  1385.             tcc_strdup(filename));
  1386.  
  1387.     if (flags & AFF_PREPROCESS) {
  1388.         ret = tcc_preprocess(s1);
  1389.         goto the_end;
  1390.     }
  1391.  
  1392.     if (filetype == TCC_FILETYPE_C) {
  1393.         /* C file assumed */
  1394.         ret = tcc_compile(s1);
  1395.         goto the_end;
  1396.     }
  1397.  
  1398. #ifdef CONFIG_TCC_ASM
  1399.     if (filetype == TCC_FILETYPE_ASM_PP) {
  1400.         /* non preprocessed assembler */
  1401.         ret = tcc_assemble(s1, 1);
  1402.         goto the_end;
  1403.     }
  1404.  
  1405.     if (filetype == TCC_FILETYPE_ASM) {
  1406.         /* preprocessed assembler */
  1407.         ret = tcc_assemble(s1, 0);
  1408.         goto the_end;
  1409.     }
  1410. #endif
  1411.  
  1412.     fd = file->fd;
  1413.     /* assume executable format: auto guess file type */
  1414.     size = read(fd, &ehdr, sizeof(ehdr));
  1415.     lseek(fd, 0, SEEK_SET);
  1416.     if (size <= 0) {
  1417.         tcc_error_noabort("could not read header");
  1418.         goto the_end;
  1419.     }
  1420.  
  1421.     if (size == sizeof(ehdr) &&
  1422.         ehdr.e_ident[0] == ELFMAG0 &&
  1423.         ehdr.e_ident[1] == ELFMAG1 &&
  1424.         ehdr.e_ident[2] == ELFMAG2 &&
  1425.         ehdr.e_ident[3] == ELFMAG3) {
  1426.  
  1427.         /* do not display line number if error */
  1428.         file->line_num = 0;
  1429.         if (ehdr.e_type == ET_REL) {
  1430.             ret = tcc_load_object_file(s1, fd, 0);
  1431.             goto the_end;
  1432.  
  1433.         }
  1434. #if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS)
  1435.         if (ehdr.e_type == ET_DYN) {
  1436.             if (s1->output_type == TCC_OUTPUT_MEMORY) {
  1437. #ifdef TCC_IS_NATIVE
  1438.                 void *h;
  1439.                 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
  1440.                 if (h)
  1441. #endif
  1442.                     ret = 0;
  1443.             } else {
  1444.                 ret = tcc_load_dll(s1, fd, filename,
  1445.                                    (flags & AFF_REFERENCED_DLL) != 0);
  1446.             }
  1447.             goto the_end;
  1448.         }
  1449. #endif
  1450.         tcc_error_noabort("unrecognized ELF file");
  1451.         goto the_end;
  1452.     }
  1453.  
  1454.     if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
  1455.         file->line_num = 0; /* do not display line number if error */
  1456.         ret = tcc_load_archive(s1, fd);
  1457.         goto the_end;
  1458.     }
  1459.  
  1460. #ifdef TCC_TARGET_COFF
  1461.     if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
  1462.         ret = tcc_load_coff(s1, fd);
  1463.         goto the_end;
  1464.     }
  1465. #endif
  1466.  
  1467. #if defined (TCC_TARGET_PE) ||  (defined(TCC_TARGET_MEOS)  && !defined(TCC_TARGET_KX))
  1468.     ret = pe_load_file(s1, filename, fd);
  1469. #elif defined(TCC_TARGET_KX)
  1470.     ret = pe_load_def(s1, fd);
  1471. #else
  1472.     /* as GNU ld, consider it is an ld script if not recognized */
  1473.     ret = tcc_load_ldscript(s1);
  1474. #endif
  1475.     if (ret < 0)
  1476.         tcc_error_noabort("unrecognized file type");
  1477.  
  1478. the_end:
  1479.     tcc_close();
  1480.     return ret;
  1481. }
  1482.  
  1483. LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename, int filetype)
  1484. {
  1485.     if (s->output_type == TCC_OUTPUT_PREPROCESS)
  1486.         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS, filetype);
  1487.     else
  1488.         return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR, filetype);
  1489. }
  1490.  
  1491. LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
  1492. {
  1493.     tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);
  1494.     return 0;
  1495. }
  1496.  
  1497. static int tcc_add_library_internal(TCCState *s, const char *fmt,
  1498.     const char *filename, int flags, char **paths, int nb_paths)
  1499. {
  1500.     char buf[1024];
  1501.     int i;
  1502.  
  1503.     for(i = 0; i < nb_paths; i++) {
  1504.         snprintf(buf, sizeof(buf), fmt, paths[i], filename);
  1505. //printf("tcc_add_library_internal::added lib [%s]\n", buf);
  1506.         if (tcc_add_file_internal(s, buf, flags, TCC_FILETYPE_BINARY) == 0)
  1507.             return 0;
  1508.     }
  1509.     return -1;
  1510. }
  1511.  
  1512. #if !defined(TCC_TARGET_PE) && !defined(TCC_TARGET_MEOS)
  1513. /* find and load a dll. Return non zero if not found */
  1514. /* XXX: add '-rpath' option support ? */
  1515. ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
  1516. {
  1517.     return tcc_add_library_internal(s, "%s/%s", filename, flags,
  1518.         s->library_paths, s->nb_library_paths);
  1519. }
  1520. #endif
  1521.  
  1522. ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
  1523. {
  1524.     if (-1 == tcc_add_library_internal(s, "%s/%s",
  1525.         filename, 0, s->crt_paths, s->nb_crt_paths))
  1526.         tcc_error_noabort("file '%s' not found", filename);
  1527.     return 0;
  1528. }
  1529.  
  1530. /* the library name is the same as the argument of the '-l' option */
  1531. LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
  1532. {
  1533. #if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS)
  1534.     const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
  1535.     const char **pp = s->static_link ? libs + 4 : libs;
  1536. #else
  1537.     const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
  1538.     const char **pp = s->static_link ? libs + 1 : libs;
  1539. #endif
  1540.     while (*pp) {
  1541.         if (0 == tcc_add_library_internal(s, *pp,
  1542.             libraryname, 0, s->library_paths, s->nb_library_paths))
  1543.             return 0;
  1544.         ++pp;
  1545.     }
  1546.     return -1;
  1547. }
  1548.  
  1549. PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
  1550. {
  1551.     int ret = tcc_add_library(s, libname);
  1552.     if (ret < 0)
  1553.         tcc_error_noabort("cannot find library 'lib%s'", libname);
  1554.     return ret;
  1555. }
  1556.  
  1557. /* habdle #pragma comment(lib,) */
  1558. ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
  1559. {
  1560.     int i;
  1561.     for (i = 0; i < s1->nb_pragma_libs; i++)
  1562.         tcc_add_library_err(s1, s1->pragma_libs[i]);
  1563. }
  1564.  
  1565. LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
  1566. {
  1567. #if defined(TCC_TARGET_PE) || defined(TCC_TARGET_MEOS)
  1568.     /* On x86_64 'val' might not be reachable with a 32bit offset.
  1569.        So it is handled here as if it were in a DLL. */
  1570.     pe_putimport(s, 0, name, (uintptr_t)val);
  1571. #else
  1572.     add_elf_sym(symtab_section, (uintptr_t)val, 0,
  1573.         ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
  1574.         SHN_ABS, name);
  1575. #endif
  1576.     return 0;
  1577. }
  1578.  
  1579.  
  1580. /* Windows stat* ( https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ):
  1581.  * - st_gid, st_ino, st_uid: only valid on "unix" file systems (not FAT, NTFS, etc)
  1582.  * - st_atime, st_ctime: not valid on FAT, valid on NTFS.
  1583.  * - Other fields should be reasonably compatible (and S_ISDIR should work).
  1584.  *
  1585.  * BY_HANDLE_FILE_INFORMATION ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788%28v=vs.85%29.aspx ):
  1586.  * - File index (combined nFileIndexHigh and nFileIndexLow) _may_ change when the file is opened.
  1587.  *   - But on NTFS: it's guaranteed to be the same value until the file is deleted.
  1588.  * - On windows server 2012 there's a 128b file id, and the 64b one via
  1589.  *   nFileIndex* is not guaranteed to be unique.
  1590.  *
  1591.  * - MS Docs suggest to that volume number with the file index could be used to
  1592.  *   check if two handles refer to the same file.
  1593.  */
  1594. #ifndef _WIN32
  1595. typedef struct stat                file_info_t;
  1596. #else
  1597. typedef BY_HANDLE_FILE_INFORMATION file_info_t;
  1598. #endif
  1599.  
  1600. int get_file_info(const char *fname, file_info_t *out_info)
  1601. {
  1602. #ifndef _WIN32
  1603.     return stat(fname, out_info);
  1604. #else
  1605.     int rv = 1;
  1606.     HANDLE h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  1607.                           FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL);
  1608.  
  1609.     if (h != INVALID_HANDLE_VALUE) {
  1610.         rv = !GetFileInformationByHandle(h, out_info);
  1611.         CloseHandle(h);
  1612.     }
  1613.     return rv;
  1614. #endif
  1615. }
  1616.  
  1617. int is_dir(file_info_t *info)
  1618. {
  1619. #ifndef _WIN32
  1620.     return S_ISDIR(info->st_mode);
  1621. #else
  1622.     return (info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
  1623.            FILE_ATTRIBUTE_DIRECTORY;
  1624. #endif
  1625. }
  1626.  
  1627. int is_same_file(const file_info_t *fi1, const file_info_t *fi2)
  1628. {
  1629. #ifndef _WIN32
  1630.     return fi1->st_dev == fi2->st_dev &&
  1631.            fi1->st_ino == fi2->st_ino;
  1632. #else
  1633.     return fi1->dwVolumeSerialNumber == fi2->dwVolumeSerialNumber &&
  1634.            fi1->nFileIndexHigh       == fi2->nFileIndexHigh &&
  1635.            fi1->nFileIndexLow        == fi2->nFileIndexLow;
  1636. #endif
  1637. }
  1638.  
  1639. static void
  1640. tcc_normalize_inc_dirs_aux(file_info_t *stats, size_t *pnum, char **path)
  1641. {
  1642.     size_t i, num = *pnum;
  1643.     if (get_file_info(*path, &stats[num]) || !is_dir(&stats[num]))
  1644.         goto remove;
  1645.     for (i = 0; i < num; i++)
  1646.         if (is_same_file(&stats[i], &stats[num]))
  1647.             goto remove;
  1648.     *pnum = num + 1;
  1649.     return;
  1650.  remove:
  1651.     tcc_free(*path);
  1652.     *path = 0;
  1653. }
  1654.  
  1655. /* Remove non-existent and duplicate directories from include paths. */
  1656. ST_FUNC void tcc_normalize_inc_dirs(TCCState *s)
  1657. {
  1658.     file_info_t *stats =
  1659.         tcc_malloc(((size_t)s->nb_sysinclude_paths + s->nb_include_paths) *
  1660.                    sizeof(*stats));
  1661.     size_t i, num = 0;
  1662.     for (i = 0; i < s->nb_sysinclude_paths; i++)
  1663.         tcc_normalize_inc_dirs_aux(stats, &num, &s->sysinclude_paths[i]);
  1664.     for (i = 0; i < s->nb_include_paths; i++)
  1665.         tcc_normalize_inc_dirs_aux(stats, &num, &s->include_paths[i]);
  1666.     tcc_free(stats);
  1667. }
  1668.  
  1669. LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
  1670. {
  1671.     s->output_type = output_type;
  1672.  
  1673.     if (s->output_type == TCC_OUTPUT_PREPROCESS) {
  1674.         if (!s->outfile) {
  1675.             s->ppfp = stdout;
  1676.         } else {
  1677.             s->ppfp = fopen(s->outfile, "w");
  1678.             if (!s->ppfp)
  1679.                 tcc_error("could not write '%s'", s->outfile);
  1680.         }
  1681.         s->dffp = s->ppfp;
  1682.         if (s->dflag == 'M')
  1683.             s->ppfp = NULL;
  1684.     }
  1685.     if (s->option_C && !s->ppfp)
  1686.         s->option_C = 0;
  1687.  
  1688.     if (!s->nostdinc) {
  1689.         /* default include paths */
  1690.         /* -isystem paths have already been handled */
  1691.         tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
  1692.     }
  1693.  
  1694.     /* if bound checking, then add corresponding sections */
  1695. #ifdef CONFIG_TCC_BCHECK
  1696.     if (s->do_bounds_check) {
  1697.         /* define symbol */
  1698.         tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
  1699.         /* create bounds sections */
  1700.         bounds_section = new_section(s, ".bounds",
  1701.                                      SHT_PROGBITS, SHF_ALLOC);
  1702.         lbounds_section = new_section(s, ".lbounds",
  1703.                                       SHT_PROGBITS, SHF_ALLOC);
  1704.     }
  1705. #endif
  1706.  
  1707.     if (s->char_is_unsigned) {
  1708.         tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
  1709.     }
  1710.  
  1711.     /* add debug sections */
  1712.     if (s->do_debug) {
  1713.         /* stab symbols */
  1714.         stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
  1715.         stab_section->sh_entsize = sizeof(Stab_Sym);
  1716.         stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
  1717.         put_elf_str(stabstr_section, "");
  1718.         stab_section->link = stabstr_section;
  1719.         /* put first entry */
  1720.         put_stabs("", 0, 0, 0, 0);
  1721.     }
  1722.  
  1723.     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
  1724. #ifdef TCC_TARGET_PE
  1725. # ifdef _WIN32
  1726.     tcc_add_systemdir(s);
  1727. # endif
  1728. #elif defined(TCC_TARGET_MEOS)
  1729.     if (s->output_type != TCC_OUTPUT_OBJ && !s->nostdlib)
  1730.     {
  1731.         tcc_add_crt(s,"crt0.o");
  1732.         //tcc_add_library(s,"lc.obj"); // adding libck.a dont work, because need to be added last
  1733.     }
  1734. #else
  1735.     /* add libc crt1/crti objects */
  1736.     if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
  1737.         !s->nostdlib) {
  1738.         if (output_type != TCC_OUTPUT_DLL)
  1739.             tcc_add_crt(s, "crt1.o");
  1740.         tcc_add_crt(s, "crti.o");
  1741.     }
  1742. #endif
  1743.  
  1744. #ifdef CONFIG_TCC_BCHECK
  1745.     if (s->do_bounds_check && (output_type == TCC_OUTPUT_EXE))
  1746.     {
  1747.         /* force a bcheck.o linking */
  1748.         addr_t func = TOK___bound_init;
  1749.         Sym *sym = external_global_sym(func, &func_old_type, 0);
  1750.         if (!sym->c)
  1751.             put_extern_sym(sym, NULL, 0, 0);
  1752.     }
  1753. #endif
  1754.  
  1755.     if (s->normalize_inc_dirs)
  1756.         tcc_normalize_inc_dirs(s);
  1757.     if (s->output_type == TCC_OUTPUT_PREPROCESS)
  1758.         print_defines();
  1759.  
  1760.     return 0;
  1761. }
  1762.  
  1763. LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
  1764. {
  1765.     tcc_free(s->tcc_lib_path);
  1766.     s->tcc_lib_path = tcc_strdup(path);
  1767. }
  1768.  
  1769. #define WD_ALL    0x0001 /* warning is activated when using -Wall */
  1770. #define FD_INVERT 0x0002 /* invert value before storing */
  1771.  
  1772. typedef struct FlagDef {
  1773.     uint16_t offset;
  1774.     uint16_t flags;
  1775.     const char *name;
  1776. } FlagDef;
  1777.  
  1778. static const FlagDef warning_defs[] = {
  1779.     { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
  1780.     { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
  1781.     { offsetof(TCCState, warn_error), 0, "error" },
  1782.     { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
  1783.       "implicit-function-declaration" },
  1784. };
  1785.  
  1786. ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
  1787.                     const char *name, int value)
  1788. {
  1789.     int i;
  1790.     const FlagDef *p;
  1791.     const char *r;
  1792.  
  1793.     r = name;
  1794.     if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
  1795.         r += 3;
  1796.         value = !value;
  1797.     }
  1798.     for(i = 0, p = flags; i < nb_flags; i++, p++) {
  1799.         if (!strcmp(r, p->name))
  1800.             goto found;
  1801.     }
  1802.     return -1;
  1803.  found:
  1804.     if (p->flags & FD_INVERT)
  1805.         value = !value;
  1806.     *(int *)((uint8_t *)s + p->offset) = value;
  1807.     return 0;
  1808. }
  1809.  
  1810. /* set/reset a warning */
  1811. static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
  1812. {
  1813.     int i;
  1814.     const FlagDef *p;
  1815.  
  1816.     if (!strcmp(warning_name, "all")) {
  1817.         for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
  1818.             if (p->flags & WD_ALL)
  1819.                 *(int *)((uint8_t *)s + p->offset) = 1;
  1820.         }
  1821.                 s->warn_unsupported = 1;  // siemargl. was unused flag about compiler features
  1822.         return 0;
  1823.     } else {
  1824.         return set_flag(s, warning_defs, countof(warning_defs),
  1825.                         warning_name, value);
  1826.     }
  1827. }
  1828.  
  1829. static const FlagDef flag_defs[] = {
  1830.     { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
  1831.     { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
  1832.     { offsetof(TCCState, nocommon), FD_INVERT, "common" },
  1833.     { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
  1834.     { offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
  1835.     { offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" },
  1836.     { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
  1837.     { offsetof(TCCState, normalize_inc_dirs), 0, "normalize-inc-dirs" },
  1838. };
  1839.  
  1840. /* set/reset a flag */
  1841. static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
  1842. {
  1843.     return set_flag(s, flag_defs, countof(flag_defs),
  1844.                     flag_name, value);
  1845. }
  1846.  
  1847.  
  1848. static int strstart(const char *val, const char **str)
  1849. {
  1850.     const char *p, *q;
  1851.     p = *str;
  1852.     q = val;
  1853.     while (*q) {
  1854.         if (*p != *q)
  1855.             return 0;
  1856.         p++;
  1857.         q++;
  1858.     }
  1859.     *str = p;
  1860.     return 1;
  1861. }
  1862.  
  1863. /* Like strstart, but automatically takes into account that ld options can
  1864.  *
  1865.  * - start with double or single dash (e.g. '--soname' or '-soname')
  1866.  * - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so'
  1867.  *   or '-Wl,-soname=x.so')
  1868.  *
  1869.  * you provide `val` always in 'option[=]' form (no leading -)
  1870.  */
  1871. static int link_option(const char *str, const char *val, const char **ptr)
  1872. {
  1873.     const char *p, *q;
  1874.  
  1875.     /* there should be 1 or 2 dashes */
  1876.     if (*str++ != '-')
  1877.         return 0;
  1878.     if (*str == '-')
  1879.         str++;
  1880.  
  1881.     /* then str & val should match (potentialy up to '=') */
  1882.     p = str;
  1883.     q = val;
  1884.  
  1885.     while (*q != '\0' && *q != '=') {
  1886.         if (*p != *q)
  1887.             return 0;
  1888.         p++;
  1889.         q++;
  1890.     }
  1891.  
  1892.     /* '=' near eos means ',' or '=' is ok */
  1893.     if (*q == '=') {
  1894.         if (*p != ',' && *p != '=')
  1895.             return 0;
  1896.         p++;
  1897.         q++;
  1898.     }
  1899.  
  1900.     if (ptr)
  1901.         *ptr = p;
  1902.     return 1;
  1903. }
  1904.  
  1905. static const char *skip_linker_arg(const char **str)
  1906. {
  1907.     const char *s1 = *str;
  1908.     const char *s2 = strchr(s1, ',');
  1909.     *str = s2 ? s2++ : (s2 = s1 + strlen(s1));
  1910.     return s2;
  1911. }
  1912.  
  1913. static char *copy_linker_arg(const char *p)
  1914. {
  1915.     const char *q = p;
  1916.     skip_linker_arg(&q);
  1917.     return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
  1918. }
  1919.  
  1920. /* set linker options */
  1921. static int tcc_set_linker(TCCState *s, const char *option)
  1922. {
  1923.     while (option && *option) {
  1924.  
  1925.         const char *p = option;
  1926.         char *end = NULL;
  1927.         int ignoring = 0;
  1928.  
  1929.         if (link_option(option, "Bsymbolic", &p)) {
  1930.             s->symbolic = 1;
  1931.         } else if (link_option(option, "nostdlib", &p)) {
  1932.             s->nostdlib = 1;
  1933.         } else if (link_option(option, "fini=", &p)) {
  1934.             s->fini_symbol = copy_linker_arg(p);
  1935.             ignoring = 1;
  1936.         } else if (link_option(option, "image-base=", &p)
  1937.                 || link_option(option, "Ttext=", &p)) {
  1938.             s->text_addr = strtoull(p, &end, 16);
  1939.             s->has_text_addr = 1;
  1940.         } else if (link_option(option, "init=", &p)) {
  1941.             s->init_symbol = copy_linker_arg(p);
  1942.             ignoring = 1;
  1943.         } else if (link_option(option, "oformat=", &p)) {
  1944. #if defined(TCC_TARGET_PE)
  1945.             if (strstart("pe-", &p)) {
  1946. #elif defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
  1947.             if (strstart("elf64-", &p)) {
  1948. #else
  1949.             if (strstart("elf32-", &p)) {
  1950. #endif
  1951.                 s->output_format = TCC_OUTPUT_FORMAT_ELF;
  1952.             } else if (!strcmp(p, "binary")) {
  1953.                 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
  1954. #ifdef TCC_TARGET_COFF
  1955.             } else if (!strcmp(p, "coff")) {
  1956.                 s->output_format = TCC_OUTPUT_FORMAT_COFF;
  1957. #endif
  1958.             } else
  1959.                 goto err;
  1960.  
  1961.         } else if (link_option(option, "as-needed", &p)) {
  1962.             ignoring = 1;
  1963.         } else if (link_option(option, "O", &p)) {
  1964.             ignoring = 1;
  1965.         } else if (link_option(option, "rpath=", &p)) {
  1966.             s->rpath = copy_linker_arg(p);
  1967.         } else if (link_option(option, "section-alignment=", &p)) {
  1968.             s->section_align = strtoul(p, &end, 16);
  1969.         } else if (link_option(option, "soname=", &p)) {
  1970.             s->soname = copy_linker_arg(p);
  1971. #ifdef TCC_TARGET_PE
  1972.         } else if (link_option(option, "file-alignment=", &p)) {
  1973.             s->pe_file_align = strtoul(p, &end, 16);
  1974.         } else if (link_option(option, "stack=", &p)) {
  1975.             s->pe_stack_size = strtoul(p, &end, 10);
  1976.         } else if (link_option(option, "subsystem=", &p)) {
  1977. #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
  1978.             if (!strcmp(p, "native")) {
  1979.                 s->pe_subsystem = 1;
  1980.             } else if (!strcmp(p, "console")) {
  1981.                 s->pe_subsystem = 3;
  1982.             } else if (!strcmp(p, "gui")) {
  1983.                 s->pe_subsystem = 2;
  1984.             } else if (!strcmp(p, "posix")) {
  1985.                 s->pe_subsystem = 7;
  1986.             } else if (!strcmp(p, "efiapp")) {
  1987.                 s->pe_subsystem = 10;
  1988.             } else if (!strcmp(p, "efiboot")) {
  1989.                 s->pe_subsystem = 11;
  1990.             } else if (!strcmp(p, "efiruntime")) {
  1991.                 s->pe_subsystem = 12;
  1992.             } else if (!strcmp(p, "efirom")) {
  1993.                 s->pe_subsystem = 13;
  1994. #elif defined(TCC_TARGET_ARM)
  1995.             if (!strcmp(p, "wince")) {
  1996.                 s->pe_subsystem = 9;
  1997. #endif
  1998.             } else
  1999.                 goto err;
  2000. #endif
  2001.         } else
  2002.             goto err;
  2003.  
  2004.         if (ignoring && s->warn_unsupported) err: {
  2005.             char buf[100], *e;
  2006.             pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
  2007.             if (ignoring)
  2008.                 tcc_warning("unsupported linker option '%s'", buf);
  2009.             else
  2010.                 tcc_error("unsupported linker option '%s'", buf);
  2011.         }
  2012.         option = skip_linker_arg(&p);
  2013.     }
  2014.     return 0;
  2015. }
  2016.  
  2017. typedef struct TCCOption {
  2018.     const char *name;
  2019.     uint16_t index;
  2020.     uint16_t flags;
  2021. } TCCOption;
  2022.  
  2023. enum {
  2024.     TCC_OPTION_HELP,
  2025.     TCC_OPTION_I,
  2026.     TCC_OPTION_D,
  2027.     TCC_OPTION_U,
  2028.     TCC_OPTION_P,
  2029.     TCC_OPTION_L,
  2030.     TCC_OPTION_B,
  2031.     TCC_OPTION_l,
  2032.     TCC_OPTION_bench,
  2033.     TCC_OPTION_bt,
  2034.     TCC_OPTION_b,
  2035.     TCC_OPTION_g,
  2036.     TCC_OPTION_c,
  2037.     TCC_OPTION_C,
  2038.     TCC_OPTION_dumpversion,
  2039.     TCC_OPTION_d,
  2040.     TCC_OPTION_float_abi,
  2041.     TCC_OPTION_static,
  2042.     TCC_OPTION_std,
  2043.     TCC_OPTION_shared,
  2044.     TCC_OPTION_soname,
  2045.     TCC_OPTION_o,
  2046.     TCC_OPTION_r,
  2047.     TCC_OPTION_s,
  2048.     TCC_OPTION_traditional,
  2049.     TCC_OPTION_Wl,
  2050.     TCC_OPTION_W,
  2051.     TCC_OPTION_O,
  2052.     TCC_OPTION_m,
  2053.     TCC_OPTION_f,
  2054.     TCC_OPTION_isystem,
  2055.     TCC_OPTION_iwithprefix,
  2056.     TCC_OPTION_nostdinc,
  2057.     TCC_OPTION_nostdlib,
  2058.     TCC_OPTION_print_search_dirs,
  2059.     TCC_OPTION_rdynamic,
  2060.     TCC_OPTION_pedantic,
  2061.     TCC_OPTION_pthread,
  2062.     TCC_OPTION_run,
  2063.     TCC_OPTION_v,
  2064.     TCC_OPTION_w,
  2065.     TCC_OPTION_pipe,
  2066.     TCC_OPTION_E,
  2067.     TCC_OPTION_MD,
  2068.     TCC_OPTION_MF,
  2069.     TCC_OPTION_x,
  2070.     TCC_OPTION_stack,
  2071.     TCC_OPTION_nobss
  2072. };
  2073.  
  2074. #define TCC_OPTION_HAS_ARG 0x0001
  2075. #define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
  2076.  
  2077. static const TCCOption tcc_options[] = {
  2078.     { "h", TCC_OPTION_HELP, 0 },
  2079.     { "-help", TCC_OPTION_HELP, 0 },
  2080.     { "?", TCC_OPTION_HELP, 0 },
  2081.     { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
  2082.     { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
  2083.     { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
  2084.     { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2085.     { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
  2086.     { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
  2087.     { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2088.     { "bench", TCC_OPTION_bench, 0 },
  2089. #ifdef CONFIG_TCC_BACKTRACE
  2090.     { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
  2091. #endif
  2092. #ifdef CONFIG_TCC_BCHECK
  2093.     { "b", TCC_OPTION_b, 0 },
  2094. #endif
  2095.     { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2096.     { "c", TCC_OPTION_c, 0 },
  2097.     { "C", TCC_OPTION_C, 0 },
  2098.     { "dumpversion", TCC_OPTION_dumpversion, 0},
  2099.     { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2100. #ifdef TCC_TARGET_ARM
  2101.     { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG },
  2102. #endif
  2103.     { "static", TCC_OPTION_static, 0 },
  2104.     { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2105.     { "shared", TCC_OPTION_shared, 0 },
  2106.     { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
  2107.     { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
  2108.     { "pedantic", TCC_OPTION_pedantic, 0},
  2109.     { "pthread", TCC_OPTION_pthread, 0},
  2110.     { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2111.     { "rdynamic", TCC_OPTION_rdynamic, 0 },
  2112.     { "r", TCC_OPTION_r, 0 },
  2113.     { "s", TCC_OPTION_s, 0 },
  2114.     { "traditional", TCC_OPTION_traditional, 0 },
  2115.     { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2116.     { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2117.     { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2118.     { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
  2119.     { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2120.     { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
  2121.     { "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG },
  2122.     { "nostdinc", TCC_OPTION_nostdinc, 0 },
  2123.     { "nostdlib", TCC_OPTION_nostdlib, 0 },
  2124.     { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
  2125.     { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
  2126.     { "w", TCC_OPTION_w, 0 },
  2127.     { "pipe", TCC_OPTION_pipe, 0},
  2128.     { "E", TCC_OPTION_E, 0},
  2129.     { "MD", TCC_OPTION_MD, 0},
  2130.     { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
  2131.     { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
  2132.     { "stack", TCC_OPTION_stack, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
  2133. #if defined(TCC_TARGET_MEOS) && !defined (TCC_TARGET_KX)
  2134.     { "nobss", TCC_OPTION_nobss, 0 },
  2135. #endif
  2136.     { NULL, 0, 0 },
  2137. };
  2138.  
  2139. static void parse_option_D(TCCState *s1, const char *optarg)
  2140. {
  2141.     char *sym = tcc_strdup(optarg);
  2142.     char *value = strchr(sym, '=');
  2143.     if (value)
  2144.         *value++ = '\0';
  2145.     tcc_define_symbol(s1, sym, value);
  2146.     tcc_free(sym);
  2147. }
  2148.  
  2149. static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
  2150. {
  2151.     int len = strlen(filename);
  2152.     char *p = tcc_malloc(len + 2);
  2153.     if (filetype) {
  2154.         *p = filetype;
  2155.     }
  2156.     else {
  2157.         /* use a file extension to detect a filetype */
  2158.         const char *ext = tcc_fileextension(filename);
  2159.         if (ext[0]) {
  2160.             ext++;
  2161.             if (!strcmp(ext, "S"))
  2162.                 *p = TCC_FILETYPE_ASM_PP;
  2163.             else
  2164.             if (!strcmp(ext, "s"))
  2165.                 *p = TCC_FILETYPE_ASM;
  2166.             else
  2167.             if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i"))
  2168.                 *p = TCC_FILETYPE_C;
  2169.             else
  2170.                 *p = TCC_FILETYPE_BINARY;
  2171.         }
  2172.         else {
  2173.             *p = TCC_FILETYPE_C;
  2174.         }
  2175.     }
  2176.     strcpy(p+1, filename);
  2177.     dynarray_add((void ***)&s->files, &s->nb_files, p);
  2178. }
  2179.  
  2180. ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
  2181. {
  2182.     const TCCOption *popt;
  2183.     const char *optarg, *r;
  2184.     int optind = 0;
  2185.     ParseArgsState *pas = s->parse_args_state;
  2186.  
  2187. /*
  2188. #ifdef TCC_TARGET_MEOS
  2189. // siemargl testing
  2190.         s->output_format = TCC_OUTPUT_FORMAT_COFF;
  2191. #endif
  2192. */
  2193.     while (optind < argc) {
  2194.  
  2195.         r = argv[optind++];
  2196.         if (r[0] != '-' || r[1] == '\0') {
  2197.             /* handle list files */
  2198.             if (r[0] == '@' && r[1]) {
  2199.                 char buf[sizeof file->filename], *p;
  2200.                 char **argv = NULL;
  2201.                 int argc = 0;
  2202.                 FILE *fp;
  2203.  
  2204.                 fp = fopen(r + 1, "rb");
  2205.                 if (fp == NULL)
  2206.                     tcc_error("list file '%s' not found", r + 1);
  2207.                 while (fgets(buf, sizeof buf, fp)) {
  2208.                     p = trimfront(trimback(buf, strchr(buf, 0)));
  2209.                     if (0 == *p || ';' == *p)
  2210.                         continue;
  2211.                     dynarray_add((void ***)&argv, &argc, tcc_strdup(p));
  2212.                 }
  2213.                 fclose(fp);
  2214.                 tcc_parse_args1(s, argc, argv);
  2215.                 dynarray_reset(&argv, &argc);
  2216.             } else {
  2217.                 args_parser_add_file(s, r, pas->filetype);
  2218.                 if (pas->run) {
  2219.                     optind--;
  2220.                     /* argv[0] will be this file */
  2221.                     break;
  2222.                 }
  2223.             }
  2224.             continue;
  2225.         }
  2226.  
  2227.         /* find option in table */
  2228.         for(popt = tcc_options; ; ++popt) {
  2229.             const char *p1 = popt->name;
  2230.             const char *r1 = r + 1;
  2231.             if (p1 == NULL)
  2232.                 tcc_error("invalid option -- '%s'", r);
  2233.             if (!strstart(p1, &r1))
  2234.                 continue;
  2235.             optarg = r1;
  2236.             if (popt->flags & TCC_OPTION_HAS_ARG) {
  2237.                 if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
  2238.                     if (optind >= argc)
  2239.                         tcc_error("argument to '%s' is missing", r);
  2240.                     optarg = argv[optind++];
  2241.                 }
  2242.             } else if (*r1 != '\0')
  2243.                 continue;
  2244.             break;
  2245.         }
  2246.  
  2247.         switch(popt->index) {
  2248.         case TCC_OPTION_HELP:
  2249.             return 0;
  2250.         case TCC_OPTION_I:
  2251.             tcc_add_include_path(s, optarg);
  2252.             break;
  2253.         case TCC_OPTION_D:
  2254.             parse_option_D(s, optarg);
  2255.             break;
  2256.         case TCC_OPTION_U:
  2257.             tcc_undefine_symbol(s, optarg);
  2258.             break;
  2259.         case TCC_OPTION_L:
  2260.             tcc_add_library_path(s, optarg);
  2261.             break;
  2262.         case TCC_OPTION_B:
  2263.             /* set tcc utilities path (mainly for tcc development) */
  2264.             tcc_set_lib_path(s, optarg);
  2265.             break;
  2266.         case TCC_OPTION_l:
  2267.             args_parser_add_file(s, r, TCC_FILETYPE_BINARY);
  2268.             s->nb_libraries++;
  2269.             break;
  2270.         case TCC_OPTION_pthread:
  2271.             parse_option_D(s, "_REENTRANT");
  2272.             pas->pthread = 1;
  2273.             break;
  2274.         case TCC_OPTION_bench:
  2275.             s->do_bench = 1;
  2276.             break;
  2277. #ifdef CONFIG_TCC_BACKTRACE
  2278.         case TCC_OPTION_bt:
  2279.             tcc_set_num_callers(atoi(optarg));
  2280.             break;
  2281. #endif
  2282. #ifdef CONFIG_TCC_BCHECK
  2283.         case TCC_OPTION_b:
  2284.             s->do_bounds_check = 1;
  2285.             s->do_debug = 1;
  2286.             break;
  2287. #endif
  2288.         case TCC_OPTION_g:
  2289.             s->do_debug = 1;
  2290.             break;
  2291.         case TCC_OPTION_c:
  2292.             if (s->output_type)
  2293.                 tcc_warning("-c: some compiler action already specified (%d)", s->output_type);
  2294.             s->output_type = TCC_OUTPUT_OBJ;
  2295.             break;
  2296.         case TCC_OPTION_C:
  2297.             s->option_C = 1;
  2298.             break;
  2299.         case TCC_OPTION_d:
  2300.             if (*optarg == 'D' || *optarg == 'M')
  2301.                 s->dflag = *optarg;
  2302.             else {
  2303.                 if (s->warn_unsupported)
  2304.                     goto unsupported_option;
  2305.                 tcc_error("invalid option -- '%s'", r);
  2306.             }
  2307.             break;
  2308. #ifdef TCC_TARGET_ARM
  2309.         case TCC_OPTION_float_abi:
  2310.             /* tcc doesn't support soft float yet */
  2311.             if (!strcmp(optarg, "softfp")) {
  2312.                 s->float_abi = ARM_SOFTFP_FLOAT;
  2313.                 tcc_undefine_symbol(s, "__ARM_PCS_VFP");
  2314.             } else if (!strcmp(optarg, "hard"))
  2315.                 s->float_abi = ARM_HARD_FLOAT;
  2316.             else
  2317.                 tcc_error("unsupported float abi '%s'", optarg);
  2318.             break;
  2319. #endif
  2320.         case TCC_OPTION_static:
  2321.             s->static_link = 1;
  2322.             break;
  2323.         case TCC_OPTION_std:
  2324.             /* silently ignore, a current purpose:
  2325.                allow to use a tcc as a reference compiler for "make test" */
  2326.             break;
  2327.         case TCC_OPTION_shared:
  2328.             if (s->output_type)
  2329.                 tcc_warning("-shared: some compiler action already specified (%d)", s->output_type);
  2330.             s->output_type = TCC_OUTPUT_DLL;
  2331.             break;
  2332.         case TCC_OPTION_soname:
  2333.             s->soname = tcc_strdup(optarg);
  2334.             break;
  2335.         case TCC_OPTION_m:
  2336.             s->option_m = tcc_strdup(optarg);
  2337.             break;
  2338.         case TCC_OPTION_o:
  2339.             if (s->outfile) {
  2340.                 tcc_warning("multiple -o option");
  2341.                 tcc_free(s->outfile);
  2342.             }
  2343.             s->outfile = tcc_strdup(optarg);
  2344.             break;
  2345.         case TCC_OPTION_r:
  2346.             /* generate a .o merging several output files */
  2347.             if (s->output_type)
  2348.                 tcc_warning("-r: some compiler action already specified (%d)", s->output_type);
  2349.             s->option_r = 1;
  2350.             s->output_type = TCC_OUTPUT_OBJ;
  2351.             break;
  2352.         case TCC_OPTION_isystem:
  2353.             tcc_add_sysinclude_path(s, optarg);
  2354.             break;
  2355.         case TCC_OPTION_iwithprefix:
  2356.             if (1) {
  2357.                 char buf[1024];
  2358.                 int buf_size = sizeof(buf)-1;
  2359.                 char *p = &buf[0];
  2360.  
  2361.                 char *sysroot = "{B}/";
  2362.                 int len = strlen(sysroot);
  2363.                 if (len > buf_size)
  2364.                     len = buf_size;
  2365.                 strncpy(p, sysroot, len);
  2366.                 p += len;
  2367.                 buf_size -= len;
  2368.  
  2369.                 len = strlen(optarg);
  2370.                 if (len > buf_size)
  2371.                     len = buf_size;
  2372.                 strncpy(p, optarg, len+1);
  2373.                 tcc_add_sysinclude_path(s, buf);
  2374.             }
  2375.             break;
  2376.         case TCC_OPTION_nostdinc:
  2377.             s->nostdinc = 1;
  2378.             break;
  2379.         case TCC_OPTION_nostdlib:
  2380.             s->nostdlib = 1;
  2381.             break;
  2382.         case TCC_OPTION_print_search_dirs:
  2383.             s->print_search_dirs = 1;
  2384.             break;
  2385.         case TCC_OPTION_run:
  2386.             if (s->output_type)
  2387.                 tcc_warning("-run: some compiler action already specified (%d)", s->output_type);
  2388.             s->output_type = TCC_OUTPUT_MEMORY;
  2389.             tcc_set_options(s, optarg);
  2390.             pas->run = 1;
  2391.             break;
  2392.         case TCC_OPTION_v:
  2393.             do ++s->verbose; while (*optarg++ == 'v');
  2394.             break;
  2395.         case TCC_OPTION_f:
  2396.             if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
  2397.                 goto unsupported_option;
  2398.             break;
  2399.         case TCC_OPTION_W:
  2400.             if (tcc_set_warning(s, optarg, 1) < 0 &&
  2401.                 s->warn_unsupported)
  2402.                 goto unsupported_option;
  2403.             break;
  2404.         case TCC_OPTION_w:
  2405.             s->warn_none = 1;
  2406.             break;
  2407.         case TCC_OPTION_rdynamic:
  2408.             s->rdynamic = 1;
  2409.             break;
  2410.         case TCC_OPTION_Wl:
  2411.             if (pas->linker_arg.size)
  2412.                 --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ',');
  2413.             cstr_cat(&pas->linker_arg, optarg, 0);
  2414.             break;
  2415.         case TCC_OPTION_E:
  2416.             if (s->output_type)
  2417.                 tcc_warning("-E: some compiler action already specified (%d)", s->output_type);
  2418.             s->output_type = TCC_OUTPUT_PREPROCESS;
  2419.             break;
  2420.         case TCC_OPTION_P:
  2421.             s->Pflag = atoi(optarg) + 1;
  2422.             break;
  2423.         case TCC_OPTION_MD:
  2424.             s->gen_deps = 1;
  2425.             break;
  2426.         case TCC_OPTION_MF:
  2427.             s->deps_outfile = tcc_strdup(optarg);
  2428.             break;
  2429.         case TCC_OPTION_dumpversion:
  2430.             printf ("%s\n", TCC_VERSION);
  2431.             exit(0);
  2432.         case TCC_OPTION_s:
  2433.             s->do_strip = 1;
  2434.             break;
  2435.         case TCC_OPTION_traditional:
  2436.             break;
  2437.         case TCC_OPTION_x:
  2438.             if (*optarg == 'c')
  2439.                 pas->filetype = TCC_FILETYPE_C;
  2440.             else
  2441.             if (*optarg == 'a')
  2442.                 pas->filetype = TCC_FILETYPE_ASM_PP;
  2443.             else
  2444.             if (*optarg == 'n')
  2445.                 pas->filetype = 0;
  2446.             else
  2447.                 tcc_warning("unsupported language '%s'", optarg);
  2448.             break;
  2449.         case TCC_OPTION_O:
  2450.             if (1) {
  2451.                 int opt = atoi(optarg);
  2452.                 char *sym = "__OPTIMIZE__";
  2453.                 if (opt)
  2454.                     tcc_define_symbol(s, sym, 0);
  2455.                 else
  2456.                     tcc_undefine_symbol(s, sym);
  2457.             }
  2458.             break;
  2459.         case TCC_OPTION_pedantic:
  2460.         case TCC_OPTION_pipe:
  2461.             /* ignored */
  2462.             break;
  2463.         case TCC_OPTION_stack:
  2464. #ifdef TCC_TARGET_MEOS
  2465.             s->pe_stack_size = strtoul(optarg+1, NULL, 10);
  2466. #endif
  2467.             break;
  2468. #if defined(TCC_TARGET_MEOS) && !defined (TCC_TARGET_KX)
  2469.         case TCC_OPTION_nobss:
  2470.             s->nobss = 1;
  2471.             break;
  2472. #endif
  2473.         default:
  2474.             if (s->warn_unsupported) {
  2475.             unsupported_option:
  2476.                 tcc_warning("unsupported option '%s'", r);
  2477.             }
  2478.             break;
  2479.         }
  2480.     }
  2481.     return optind;
  2482. }
  2483.  
  2484. PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
  2485. {
  2486.     ParseArgsState *pas;
  2487.     int ret, is_allocated = 0;
  2488.  
  2489.     if (!s->parse_args_state) {
  2490.         s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState));
  2491.         cstr_new(&s->parse_args_state->linker_arg);
  2492.         is_allocated = 1;
  2493.     }
  2494.     pas = s->parse_args_state;
  2495.  
  2496.     ret = tcc_parse_args1(s, argc, argv);
  2497.  
  2498.     if (s->output_type == 0)
  2499.         s->output_type = TCC_OUTPUT_EXE;
  2500.  
  2501.     if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ)
  2502.         tcc_set_options(s, "-lpthread");
  2503.  
  2504.     if (s->output_type == TCC_OUTPUT_EXE)
  2505.         tcc_set_linker(s, (const char *)pas->linker_arg.data);
  2506.  
  2507.     if (is_allocated) {
  2508.         cstr_free(&pas->linker_arg);
  2509.         tcc_free(pas);
  2510.         s->parse_args_state = NULL;
  2511.     }
  2512.     return ret;
  2513. }
  2514.  
  2515. LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
  2516. {
  2517.     const char *s1;
  2518.     char **argv, *arg;
  2519.     int argc, len;
  2520.     int ret;
  2521.  
  2522.     argc = 0, argv = NULL;
  2523.     for(;;) {
  2524.         while (is_space(*str))
  2525.             str++;
  2526.         if (*str == '\0')
  2527.             break;
  2528.         s1 = str;
  2529.         while (*str != '\0' && !is_space(*str))
  2530.             str++;
  2531.         len = str - s1;
  2532.         arg = tcc_malloc(len + 1);
  2533.         pstrncpy(arg, s1, len);
  2534.         dynarray_add((void ***)&argv, &argc, arg);
  2535.     }
  2536.     ret = tcc_parse_args(s, argc, argv);
  2537.     dynarray_reset(&argv, &argc);
  2538.     return ret;
  2539. }
  2540.  
  2541. PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
  2542. {
  2543.     double tt;
  2544.     tt = (double)total_time / 1000000.0;
  2545.     if (tt < 0.001)
  2546.         tt = 0.001;
  2547.     if (total_bytes < 1)
  2548.         total_bytes = 1;
  2549.     fprintf(stdout, "%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
  2550.            tok_ident - TOK_IDENT, total_lines, total_bytes,
  2551.            tt, (int)(total_lines / tt),
  2552.            total_bytes / tt / 1000000.0);
  2553. }
  2554.  
  2555. PUB_FUNC void tcc_set_environment(TCCState *s)
  2556. {
  2557.     char * path;
  2558.  
  2559.     path = getenv("C_INCLUDE_PATH");
  2560.     if(path != NULL) {
  2561.         tcc_add_include_path(s, path);
  2562.     }
  2563.     path = getenv("CPATH");
  2564.     if(path != NULL) {
  2565.         tcc_add_include_path(s, path);
  2566.     }
  2567.     path = getenv("LIBRARY_PATH");
  2568.     if(path != NULL) {
  2569.         tcc_add_library_path(s, path);
  2570.     }
  2571. }
  2572.