Subversion Repositories Kolibri OS

Rev

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