Subversion Repositories Kolibri OS

Rev

Blame | 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. ST_DATA int tok_flags;
  27. ST_DATA int parse_flags;
  28.  
  29. ST_DATA struct BufferedFile *file;
  30. ST_DATA int ch, tok;
  31. ST_DATA CValue tokc;
  32. ST_DATA const int *macro_ptr;
  33. ST_DATA CString tokcstr; /* current parsed string, if any */
  34.  
  35. /* display benchmark infos */
  36. ST_DATA int total_lines;
  37. ST_DATA int total_bytes;
  38. ST_DATA int tok_ident;
  39. ST_DATA TokenSym **table_ident;
  40.  
  41. ST_DATA TinyAlloc *toksym_alloc;
  42. ST_DATA TinyAlloc *tokstr_alloc;
  43. ST_DATA TinyAlloc *cstr_alloc;
  44.  
  45. /* ------------------------------------------------------------------------- */
  46.  
  47. static TokenSym *hash_ident[TOK_HASH_SIZE];
  48. static char token_buf[STRING_MAX_SIZE + 1];
  49. static CString cstr_buf;
  50. static TokenString tokstr_buf;
  51. static unsigned char isidnum_table[256 - CH_EOF];
  52. /* isidnum_table flags: */
  53. #define IS_SPC 1
  54. #define IS_ID  2
  55. #define IS_NUM 4
  56.  
  57. static TokenString *macro_stack;
  58.  
  59. static const char tcc_keywords[] =
  60. #define DEF(id, str) str "\0"
  61. #include "tcctok.h"
  62. #undef DEF
  63. ;
  64.  
  65. /* WARNING: the content of this string encodes token numbers */
  66. static const unsigned char tok_two_chars[] =
  67. /* outdated -- gr
  68.     "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
  69.     "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
  70. */{
  71.     '<','=', TOK_LE,
  72.     '>','=', TOK_GE,
  73.     '!','=', TOK_NE,
  74.     '&','&', TOK_LAND,
  75.     '|','|', TOK_LOR,
  76.     '+','+', TOK_INC,
  77.     '-','-', TOK_DEC,
  78.     '=','=', TOK_EQ,
  79.     '<','<', TOK_SHL,
  80.     '>','>', TOK_SAR,
  81.     '+','=', TOK_A_ADD,
  82.     '-','=', TOK_A_SUB,
  83.     '*','=', TOK_A_MUL,
  84.     '/','=', TOK_A_DIV,
  85.     '%','=', TOK_A_MOD,
  86.     '&','=', TOK_A_AND,
  87.     '^','=', TOK_A_XOR,
  88.     '|','=', TOK_A_OR,
  89.     '-','>', TOK_ARROW,
  90.     '.','.', 0xa8, // C++ token ?
  91.     '#','#', TOK_TWOSHARPS,
  92.     0
  93. };
  94.  
  95. static void next_nomacro_spc(void);
  96.  
  97. ST_FUNC void skip(int c)
  98. {
  99.     if (tok != c)
  100.         tcc_error("'%c' expected (got \"%s\")", c, get_tok_str(tok, &tokc));
  101.     next();
  102. }
  103.  
  104. ST_FUNC void expect(const char *msg)
  105. {
  106.     tcc_error("%s expected", msg);
  107. }
  108.  
  109. ST_FUNC void begin_macro(TokenString *str, int alloc)
  110. {
  111.     str->alloc = alloc;
  112.     str->prev = macro_stack;
  113.     str->prev_ptr = macro_ptr;
  114.     macro_ptr = str->str;
  115.     macro_stack = str;
  116. }
  117.  
  118. ST_FUNC void end_macro(void)
  119. {
  120.     TokenString *str = macro_stack;
  121.     macro_stack = str->prev;
  122.     macro_ptr = str->prev_ptr;
  123.     if (str->alloc == 2) {
  124.         str->alloc = 3; /* just mark as finished */
  125.     } else {
  126.         tok_str_free(str->str);
  127.         if (str->alloc == 1)
  128.             tcc_free(str);
  129.     }
  130. }
  131.  
  132. /* ------------------------------------------------------------------------- */
  133. /* Custom allocator for tiny objects */
  134.  
  135. ST_FUNC TinyAlloc *tal_new(TinyAlloc **pal, size_t limit, size_t size)
  136. {
  137.     TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc));
  138.     al->p = al->buffer = tcc_malloc(size);
  139.     al->limit = limit;
  140.     al->size = size;
  141.     if (pal) *pal = al;
  142.     return al;
  143. }
  144.  
  145. ST_FUNC void tal_delete(TinyAlloc *al)
  146. {
  147.     TinyAlloc *next;
  148.  
  149. tail_call:
  150.     if (!al)
  151.         return;
  152. #ifdef TAL_INFO
  153.     fprintf(stderr, "limit=%5d, size=%5g MB, nb_peak=%6d, nb_total=%8d, nb_missed=%6d, usage=%5.1f%%\n",
  154.             al->limit, al->size / 1024.0 / 1024.0, al->nb_peak, al->nb_total, al->nb_missed,
  155.             (al->peak_p - al->buffer) * 100.0 / al->size);
  156. #endif
  157. #ifdef TAL_DEBUG
  158.     if (al->nb_allocs > 0) {
  159.         fprintf(stderr, "TAL_DEBUG: mem leak %d chunks (limit= %d)\n",
  160.                 al->nb_allocs, al->limit);
  161.         uint8_t *p = al->buffer;
  162.         while (p < al->p) {
  163.             tal_header_t *header = (tal_header_t *)p;
  164.             if (header->line_num > 0) {
  165.                 fprintf(stderr, "  file %s, line %u: %u bytes\n",
  166.                         header->file_name, header->line_num, header->size);
  167.             }
  168.             p += header->size + sizeof(tal_header_t);
  169.         }
  170.     }
  171. #endif
  172.     next = al->next;
  173.     tcc_free(al->buffer);
  174.     tcc_free(al);
  175.     al = next;
  176.     goto tail_call;
  177. }
  178.  
  179. ST_FUNC void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS)
  180. {
  181.     if (!p)
  182.         return;
  183. tail_call:
  184.     if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) {
  185. #ifdef TAL_DEBUG
  186.         tal_header_t *header = (((tal_header_t *)p) - 1);
  187.         if (header->line_num < 0) {
  188.             fprintf(stderr, "TAL_DEBUG: file %s, line %u double frees chunk from\n",
  189.                     file, line);
  190.             fprintf(stderr, "  file %s, line %u: %u bytes\n",
  191.                     header->file_name, -header->line_num, header->size);
  192.         } else
  193.             header->line_num = -header->line_num;
  194. #endif
  195.         al->nb_allocs--;
  196.         if (!al->nb_allocs)
  197.             al->p = al->buffer;
  198.     } else if (al->next) {
  199.         al = al->next;
  200.         goto tail_call;
  201.     }
  202.     else
  203.         tcc_free(p);
  204. }
  205.  
  206. ST_FUNC void *tal_realloc_impl(TinyAlloc **pal, void *p, size_t size TAL_DEBUG_PARAMS)
  207. {
  208.     tal_header_t *header;
  209.     void *ret;
  210.     int is_own;
  211.     size_t adj_size = (size + 3) & -4;
  212.     TinyAlloc *al = *pal;
  213.  
  214. tail_call:
  215.     is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
  216.     if ((!p || is_own) && size <= al->limit) {
  217.         if (al->p + adj_size + sizeof(tal_header_t) < al->buffer + al->size) {
  218.             header = (tal_header_t *)al->p;
  219.             header->size = adj_size;
  220. #ifdef TAL_DEBUG
  221.             int ofs = strlen(file) - TAL_DEBUG_FILE_LEN;
  222.             strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN);
  223.             header->file_name[TAL_DEBUG_FILE_LEN] = 0;
  224.             header->line_num = line;
  225. #endif
  226.             ret = al->p + sizeof(tal_header_t);
  227.             al->p += adj_size + sizeof(tal_header_t);
  228.             if (is_own) {
  229.                 header = (((tal_header_t *)p) - 1);
  230.                 memcpy(ret, p, header->size);
  231. #ifdef TAL_DEBUG
  232.                 header->line_num = -header->line_num;
  233. #endif
  234.             } else {
  235.                 al->nb_allocs++;
  236.             }
  237. #ifdef TAL_INFO
  238.             if (al->nb_peak < al->nb_allocs)
  239.                 al->nb_peak = al->nb_allocs;
  240.             if (al->peak_p < al->p)
  241.                 al->peak_p = al->p;
  242.             al->nb_total++;
  243. #endif
  244.             return ret;
  245.         } else if (is_own) {
  246.             al->nb_allocs--;
  247.             ret = tal_realloc(*pal, 0, size);
  248.             header = (((tal_header_t *)p) - 1);
  249.             memcpy(ret, p, header->size);
  250. #ifdef TAL_DEBUG
  251.             header->line_num = -header->line_num;
  252. #endif
  253.             return ret;
  254.         }
  255.         if (al->next) {
  256.             al = al->next;
  257.         } else {
  258.             TinyAlloc *bottom = al, *next = al->top ? al->top : al;
  259.  
  260.             al = tal_new(pal, next->limit, next->size * 2);
  261.             al->next = next;
  262.             bottom->top = al;
  263.         }
  264.         goto tail_call;
  265.     }
  266.     if (is_own) {
  267.         al->nb_allocs--;
  268.         ret = tcc_malloc(size);
  269.         header = (((tal_header_t *)p) - 1);
  270.         memcpy(ret, p, header->size);
  271. #ifdef TAL_DEBUG
  272.         header->line_num = -header->line_num;
  273. #endif
  274.     } else if (al->next) {
  275.         al = al->next;
  276.         goto tail_call;
  277.     } else
  278.         ret = tcc_realloc(p, size);
  279. #ifdef TAL_INFO
  280.     al->nb_missed++;
  281. #endif
  282.     return ret;
  283. }
  284.  
  285. /* ------------------------------------------------------------------------- */
  286. /* CString handling */
  287. static void cstr_realloc(CString *cstr, int new_size)
  288. {
  289.     int size;
  290.     void *data;
  291.  
  292.     size = cstr->size_allocated;
  293.     if (size < 8)
  294.         size = 8; /* no need to allocate a too small first string */
  295.     while (size < new_size)
  296.         size = size * 2;
  297.     data = tal_realloc(cstr_alloc, cstr->data_allocated, size);
  298.     cstr->data_allocated = data;
  299.     cstr->size_allocated = size;
  300.     cstr->data = data;
  301. }
  302.  
  303. /* add a byte */
  304. ST_FUNC void cstr_ccat(CString *cstr, int ch)
  305. {
  306.     int size;
  307.     size = cstr->size + 1;
  308.     if (size > cstr->size_allocated)
  309.         cstr_realloc(cstr, size);
  310.     ((unsigned char *)cstr->data)[size - 1] = ch;
  311.     cstr->size = size;
  312. }
  313.  
  314. ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
  315. {
  316.     int size;
  317.     if (len <= 0)
  318.         len = strlen(str) + 1 + len;
  319.     size = cstr->size + len;
  320.     if (size > cstr->size_allocated)
  321.         cstr_realloc(cstr, size);
  322.     memmove(((unsigned char *)cstr->data) + cstr->size, str, len);
  323.     cstr->size = size;
  324. }
  325.  
  326. /* add a wide char */
  327. ST_FUNC void cstr_wccat(CString *cstr, int ch)
  328. {
  329.     int size;
  330.     size = cstr->size + sizeof(nwchar_t);
  331.     if (size > cstr->size_allocated)
  332.         cstr_realloc(cstr, size);
  333.     *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
  334.     cstr->size = size;
  335. }
  336.  
  337. ST_FUNC void cstr_new(CString *cstr)
  338. {
  339.     memset(cstr, 0, sizeof(CString));
  340. }
  341.  
  342. /* free string and reset it to NULL */
  343. ST_FUNC void cstr_free(CString *cstr)
  344. {
  345.     tal_free(cstr_alloc, cstr->data_allocated);
  346.     cstr_new(cstr);
  347. }
  348.  
  349. /* reset string to empty */
  350. ST_FUNC void cstr_reset(CString *cstr)
  351. {
  352.     cstr->size = 0;
  353. }
  354.  
  355. /* XXX: unicode ? */
  356. static void add_char(CString *cstr, int c)
  357. {
  358.     if (c == '\'' || c == '\"' || c == '\\') {
  359.         /* XXX: could be more precise if char or string */
  360.         cstr_ccat(cstr, '\\');
  361.     }
  362.     if (c >= 32 && c <= 126) {
  363.         cstr_ccat(cstr, c);
  364.     } else {
  365.         cstr_ccat(cstr, '\\');
  366.         if (c == '\n') {
  367.             cstr_ccat(cstr, 'n');
  368.         } else {
  369.             cstr_ccat(cstr, '0' + ((c >> 6) & 7));
  370.             cstr_ccat(cstr, '0' + ((c >> 3) & 7));
  371.             cstr_ccat(cstr, '0' + (c & 7));
  372.         }
  373.     }
  374. }
  375.  
  376. /* ------------------------------------------------------------------------- */
  377. /* allocate a new token */
  378. static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
  379. {
  380.     TokenSym *ts, **ptable;
  381.     int i;
  382.  
  383.     if (tok_ident >= SYM_FIRST_ANOM)
  384.         tcc_error("memory full (symbols)");
  385.  
  386.     /* expand token table if needed */
  387.     i = tok_ident - TOK_IDENT;
  388.     if ((i % TOK_ALLOC_INCR) == 0) {
  389.         ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
  390.         table_ident = ptable;
  391.     }
  392.  
  393.     ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len);
  394.     table_ident[i] = ts;
  395.     ts->tok = tok_ident++;
  396.     ts->sym_define = NULL;
  397.     ts->sym_label = NULL;
  398.     ts->sym_struct = NULL;
  399.     ts->sym_identifier = NULL;
  400.     ts->len = len;
  401.     ts->hash_next = NULL;
  402.     memcpy(ts->str, str, len);
  403.     ts->str[len] = '\0';
  404.     *pts = ts;
  405.     return ts;
  406. }
  407.  
  408. #define TOK_HASH_INIT 1
  409. #define TOK_HASH_FUNC(h, c) ((h) + ((h) << 5) + ((h) >> 27) + (c))
  410.  
  411.  
  412. /* find a token and add it if not found */
  413. ST_FUNC TokenSym *tok_alloc(const char *str, int len)
  414. {
  415.     TokenSym *ts, **pts;
  416.     int i;
  417.     unsigned int h;
  418.    
  419.     h = TOK_HASH_INIT;
  420.     for(i=0;i<len;i++)
  421.         h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
  422.     h &= (TOK_HASH_SIZE - 1);
  423.  
  424.     pts = &hash_ident[h];
  425.     for(;;) {
  426.         ts = *pts;
  427.         if (!ts)
  428.             break;
  429.         if (ts->len == len && !memcmp(ts->str, str, len))
  430.             return ts;
  431.         pts = &(ts->hash_next);
  432.     }
  433.     return tok_alloc_new(pts, str, len);
  434. }
  435.  
  436. /* XXX: buffer overflow */
  437. /* XXX: float tokens */
  438. ST_FUNC const char *get_tok_str(int v, CValue *cv)
  439. {
  440.     char *p;
  441.     int i, len;
  442.  
  443.     cstr_reset(&cstr_buf);
  444.     p = cstr_buf.data;
  445.  
  446.     switch(v) {
  447.     case TOK_CINT:
  448.     case TOK_CUINT:
  449.         /* XXX: not quite exact, but only useful for testing */
  450.         sprintf(p, "%llu", (unsigned long long)cv->i);
  451.         break;
  452.     case TOK_CLLONG:
  453.     case TOK_CULLONG:
  454.         /* XXX: not quite exact, but only useful for testing  */
  455. #ifdef _WIN32
  456.         sprintf(p, "%u", (unsigned)cv->i);
  457. #else
  458.         sprintf(p, "%llu", (unsigned long long)cv->i);
  459. #endif
  460.         break;
  461.     case TOK_LCHAR:
  462.         cstr_ccat(&cstr_buf, 'L');
  463.     case TOK_CCHAR:
  464.         cstr_ccat(&cstr_buf, '\'');
  465.         add_char(&cstr_buf, cv->i);
  466.         cstr_ccat(&cstr_buf, '\'');
  467.         cstr_ccat(&cstr_buf, '\0');
  468.         break;
  469.     case TOK_PPNUM:
  470.     case TOK_PPSTR:
  471.         return (char*)cv->str.data;
  472.     case TOK_LSTR:
  473.         cstr_ccat(&cstr_buf, 'L');
  474.     case TOK_STR:
  475.         cstr_ccat(&cstr_buf, '\"');
  476.         if (v == TOK_STR) {
  477.             len = cv->str.size - 1;
  478.             for(i=0;i<len;i++)
  479.                 add_char(&cstr_buf, ((unsigned char *)cv->str.data)[i]);
  480.         } else {
  481.             len = (cv->str.size / sizeof(nwchar_t)) - 1;
  482.             for(i=0;i<len;i++)
  483.                 add_char(&cstr_buf, ((nwchar_t *)cv->str.data)[i]);
  484.         }
  485.         cstr_ccat(&cstr_buf, '\"');
  486.         cstr_ccat(&cstr_buf, '\0');
  487.         break;
  488.  
  489.     case TOK_CFLOAT:
  490.         cstr_cat(&cstr_buf, "<float>", 0);
  491.         break;
  492.     case TOK_CDOUBLE:
  493.         cstr_cat(&cstr_buf, "<double>", 0);
  494.         break;
  495.     case TOK_CLDOUBLE:
  496.         cstr_cat(&cstr_buf, "<long double>", 0);
  497.         break;
  498.     case TOK_LINENUM:
  499.         cstr_cat(&cstr_buf, "<linenumber>", 0);
  500.         break;
  501.  
  502.     /* above tokens have value, the ones below don't */
  503.  
  504.     case TOK_LT:
  505.         v = '<';
  506.         goto addv;
  507.     case TOK_GT:
  508.         v = '>';
  509.         goto addv;
  510.     case TOK_DOTS:
  511.         return strcpy(p, "...");
  512.     case TOK_A_SHL:
  513.         return strcpy(p, "<<=");
  514.     case TOK_A_SAR:
  515.         return strcpy(p, ">>=");
  516.     default:
  517.         if (v < TOK_IDENT) {
  518.             /* search in two bytes table */
  519.             const unsigned char *q = tok_two_chars;
  520.             while (*q) {
  521.                 if (q[2] == v) {
  522.                     *p++ = q[0];
  523.                     *p++ = q[1];
  524.                     *p = '\0';
  525.                     return cstr_buf.data;
  526.                 }
  527.                 q += 3;
  528.             }
  529.         if (v >= 127) {
  530.             sprintf(cstr_buf.data, "<%02x>", v);
  531.             return cstr_buf.data;
  532.         }
  533.         addv:
  534.             *p++ = v;
  535.             *p = '\0';
  536.         } else if (v < tok_ident) {
  537.             return table_ident[v - TOK_IDENT]->str;
  538.         } else if (v >= SYM_FIRST_ANOM) {
  539.             /* special name for anonymous symbol */
  540.             sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
  541.         } else {
  542.             /* should never happen */
  543.             return NULL;
  544.         }
  545.         break;
  546.     }
  547.     return cstr_buf.data;
  548. }
  549.  
  550. /* return the current character, handling end of block if necessary
  551.    (but not stray) */
  552. ST_FUNC int handle_eob(void)
  553. {
  554.     BufferedFile *bf = file;
  555.     int len;
  556.  
  557.     /* only tries to read if really end of buffer */
  558.     if (bf->buf_ptr >= bf->buf_end) {
  559.         if (bf->fd != -1) {
  560. #if defined(PARSE_DEBUG)
  561.             len = 1;
  562. #else
  563.             len = IO_BUF_SIZE;
  564. #endif
  565.             len = read(bf->fd, bf->buffer, len);
  566.             if (len < 0)
  567.                 len = 0;
  568.         } else {
  569.             len = 0;
  570.         }
  571.         total_bytes += len;
  572.         bf->buf_ptr = bf->buffer;
  573.         bf->buf_end = bf->buffer + len;
  574.         *bf->buf_end = CH_EOB;
  575.     }
  576.     if (bf->buf_ptr < bf->buf_end) {
  577.         return bf->buf_ptr[0];
  578.     } else {
  579.         bf->buf_ptr = bf->buf_end;
  580.         return CH_EOF;
  581.     }
  582. }
  583.  
  584. /* read next char from current input file and handle end of input buffer */
  585. ST_INLN void inp(void)
  586. {
  587.     ch = *(++(file->buf_ptr));
  588.     /* end of buffer/file handling */
  589.     if (ch == CH_EOB)
  590.         ch = handle_eob();
  591. }
  592.  
  593. /* handle '\[\r]\n' */
  594. static int handle_stray_noerror(void)
  595. {
  596.     while (ch == '\\') {
  597.         inp();
  598.         if (ch == '\n') {
  599.             file->line_num++;
  600.             inp();
  601.         } else if (ch == '\r') {
  602.             inp();
  603.             if (ch != '\n')
  604.                 goto fail;
  605.             file->line_num++;
  606.             inp();
  607.         } else {
  608.         fail:
  609.             return 1;
  610.         }
  611.     }
  612.     return 0;
  613. }
  614.  
  615. static void handle_stray(void)
  616. {
  617.     if (handle_stray_noerror())
  618.         tcc_error("stray '\\' in program");
  619. }
  620.  
  621. /* skip the stray and handle the \\n case. Output an error if
  622.    incorrect char after the stray */
  623. static int handle_stray1(uint8_t *p)
  624. {
  625.     int c;
  626.  
  627.     file->buf_ptr = p;
  628.     if (p >= file->buf_end) {
  629.         c = handle_eob();
  630.         if (c != '\\')
  631.             return c;
  632.         p = file->buf_ptr;
  633.     }
  634.     ch = *p;
  635.     if (handle_stray_noerror()) {
  636.         if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
  637.             tcc_error("stray '\\' in program");
  638.         *--file->buf_ptr = '\\';
  639.     }
  640.     p = file->buf_ptr;
  641.     c = *p;
  642.     return c;
  643. }
  644.  
  645. /* handle just the EOB case, but not stray */
  646. #define PEEKC_EOB(c, p)\
  647. {\
  648.     p++;\
  649.     c = *p;\
  650.     if (c == '\\') {\
  651.         file->buf_ptr = p;\
  652.         c = handle_eob();\
  653.         p = file->buf_ptr;\
  654.     }\
  655. }
  656.  
  657. /* handle the complicated stray case */
  658. #define PEEKC(c, p)\
  659. {\
  660.     p++;\
  661.     c = *p;\
  662.     if (c == '\\') {\
  663.         c = handle_stray1(p);\
  664.         p = file->buf_ptr;\
  665.     }\
  666. }
  667.  
  668. /* input with '\[\r]\n' handling. Note that this function cannot
  669.    handle other characters after '\', so you cannot call it inside
  670.    strings or comments */
  671. ST_FUNC void minp(void)
  672. {
  673.     inp();
  674.     if (ch == '\\')
  675.         handle_stray();
  676. }
  677.  
  678. static void pp_line(TCCState *s1, BufferedFile *f, int level)
  679. {
  680.     if (s1->ppfp) {
  681.         int d = f->line_num - f->line_ref;
  682.         if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE
  683.             || (level == 0 && f->line_ref && d < 8)) {
  684.             while (d > 0)
  685.                 fputs("\n", s1->ppfp), --d;
  686.         } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) {
  687.             fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename);
  688.         } else {
  689.             fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename,
  690.                 level > 0 ? " 1" : level < 0 ? " 2" : "");
  691.         }
  692.     }
  693.     f->line_ref = f->line_num;
  694. }
  695.  
  696. static uint8_t *parse_print_comment(uint8_t *p, int is_line_comment)
  697. {
  698.     int c, star_count;
  699.     FILE *ppfp = tcc_state->ppfp;
  700.  
  701.     if ((file->line_num - file->line_ref) > 0) {
  702.         fputc('\n', ppfp);
  703.         file->line_ref++;
  704.         pp_line(tcc_state, file, 0);
  705.     }
  706.     if (is_line_comment)
  707.         fputs("//", ppfp); else
  708.         fputs("/*", ppfp);
  709.  
  710.     star_count = 0;
  711.     for(;;) {
  712.         c = *p;
  713.         if (c == '\\') {
  714.             file->buf_ptr = p;
  715.             c = handle_eob();
  716.             p = file->buf_ptr;
  717.         }
  718.         if (c == CH_EOF) {
  719.             if (is_line_comment) break;
  720.             tcc_error("unexpected end of file in comment");
  721.         }
  722.         if (c == '*')
  723.             star_count++;
  724.         else {
  725.             if ((c == '/') && star_count && !is_line_comment)
  726.                 break;
  727.             star_count = 0;
  728.             if (c == '\n') {
  729.                 if (is_line_comment) break;
  730.                 file->line_num++;
  731.             }
  732.         }
  733.         fputc(c, ppfp);
  734.         p++;
  735.     }
  736.     if (!is_line_comment) {
  737.         fputc('/', ppfp);
  738.         p++;
  739.         file->line_ref = file->line_num;
  740.     }
  741.     return p;
  742. }
  743.  
  744. /* single line C++ comments */
  745. static uint8_t *parse_line_comment(uint8_t *p, int skip)
  746. {
  747.     int c;
  748.  
  749.     p++;
  750.     if (tcc_state->option_C && !skip)
  751.         return parse_print_comment(p, 1);
  752.     for(;;) {
  753.         c = *p;
  754.     redo:
  755.         if (c == '\n' || c == CH_EOF) {
  756.             break;
  757.         } else if (c == '\\') {
  758.             file->buf_ptr = p;
  759.             c = handle_eob();
  760.             p = file->buf_ptr;
  761.             if (c == '\\') {
  762.                 PEEKC_EOB(c, p);
  763.                 if (c == '\n') {
  764.                     file->line_num++;
  765.                     PEEKC_EOB(c, p);
  766.                 } else if (c == '\r') {
  767.                     PEEKC_EOB(c, p);
  768.                     if (c == '\n') {
  769.                         file->line_num++;
  770.                         PEEKC_EOB(c, p);
  771.                     }
  772.                 }
  773.             } else {
  774.                 goto redo;
  775.             }
  776.         } else {
  777.             p++;
  778.         }
  779.     }
  780.     return p;
  781. }
  782.  
  783. /* C comments */
  784. ST_FUNC uint8_t *parse_comment(uint8_t *p, int skip)
  785. {
  786.     int c;
  787.  
  788.     p++;
  789.     if (tcc_state->option_C && !skip)
  790.         return parse_print_comment(p, 0);
  791.     for(;;) {
  792.         /* fast skip loop */
  793.         for(;;) {
  794.             c = *p;
  795.             if (c == '\n' || c == '*' || c == '\\')
  796.                 break;
  797.             p++;
  798.             c = *p;
  799.             if (c == '\n' || c == '*' || c == '\\')
  800.                 break;
  801.             p++;
  802.         }
  803.         /* now we can handle all the cases */
  804.         if (c == '\n') {
  805.             file->line_num++;
  806.             p++;
  807.         } else if (c == '*') {
  808.             p++;
  809.             for(;;) {
  810.                 c = *p;
  811.                 if (c == '*') {
  812.                     p++;
  813.                 } else if (c == '/') {
  814.                     goto end_of_comment;
  815.                 } else if (c == '\\') {
  816.                     file->buf_ptr = p;
  817.                     c = handle_eob();
  818.                     p = file->buf_ptr;
  819.                     if (c == CH_EOF)
  820.                         tcc_error("unexpected end of file in comment");
  821.                     if (c == '\\') {
  822.                         /* skip '\[\r]\n', otherwise just skip the stray */
  823.                         while (c == '\\') {
  824.                             PEEKC_EOB(c, p);
  825.                             if (c == '\n') {
  826.                                 file->line_num++;
  827.                                 PEEKC_EOB(c, p);
  828.                             } else if (c == '\r') {
  829.                                 PEEKC_EOB(c, p);
  830.                                 if (c == '\n') {
  831.                                     file->line_num++;
  832.                                     PEEKC_EOB(c, p);
  833.                                 }
  834.                             } else {
  835.                                 goto after_star;
  836.                             }
  837.                         }
  838.                     }
  839.                 } else {
  840.                     break;
  841.                 }
  842.             }
  843.         after_star: ;
  844.         } else {
  845.             /* stray, eob or eof */
  846.             file->buf_ptr = p;
  847.             c = handle_eob();
  848.             p = file->buf_ptr;
  849.             if (c == CH_EOF) {
  850.                 tcc_error("unexpected end of file in comment");
  851.             } else if (c == '\\') {
  852.                 p++;
  853.             }
  854.         }
  855.     }
  856.  end_of_comment:
  857.     p++;
  858.     return p;
  859. }
  860.  
  861. #define cinp minp
  862.  
  863. static inline void skip_spaces(void)
  864. {
  865.     while (isidnum_table[ch - CH_EOF] & IS_SPC)
  866.         cinp();
  867. }
  868.  
  869. static inline int check_space(int t, int *spc)
  870. {
  871.     if (t < 256 && (isidnum_table[t - CH_EOF] & IS_SPC)) {
  872.         if (*spc)
  873.             return 1;
  874.         *spc = 1;
  875.     } else
  876.         *spc = 0;
  877.     return 0;
  878. }
  879.  
  880. /* parse a string without interpreting escapes */
  881. static uint8_t *parse_pp_string(uint8_t *p,
  882.                                 int sep, CString *str)
  883. {
  884.     int c;
  885.     p++;
  886.     for(;;) {
  887.         c = *p;
  888.         if (c == sep) {
  889.             break;
  890.         } else if (c == '\\') {
  891.             file->buf_ptr = p;
  892.             c = handle_eob();
  893.             p = file->buf_ptr;
  894.             if (c == CH_EOF) {
  895.             unterminated_string:
  896.                 /* XXX: indicate line number of start of string */
  897.                 tcc_error("missing terminating %c character", sep);
  898.             } else if (c == '\\') {
  899.                 /* escape : just skip \[\r]\n */
  900.                 PEEKC_EOB(c, p);
  901.                 if (c == '\n') {
  902.                     file->line_num++;
  903.                     p++;
  904.                 } else if (c == '\r') {
  905.                     PEEKC_EOB(c, p);
  906.                     if (c != '\n')
  907.                         expect("'\n' after '\r'");
  908.                     file->line_num++;
  909.                     p++;
  910.                 } else if (c == CH_EOF) {
  911.                     goto unterminated_string;
  912.                 } else {
  913.                     if (str) {
  914.                         cstr_ccat(str, '\\');
  915.                         cstr_ccat(str, c);
  916.                     }
  917.                     p++;
  918.                 }
  919.             }
  920.         } else if (c == '\n') {
  921.             file->line_num++;
  922.             goto add_char;
  923.         } else if (c == '\r') {
  924.             PEEKC_EOB(c, p);
  925.             if (c != '\n') {
  926.                 if (str)
  927.                     cstr_ccat(str, '\r');
  928.             } else {
  929.                 file->line_num++;
  930.                 goto add_char;
  931.             }
  932.         } else {
  933.         add_char:
  934.             if (str)
  935.                 cstr_ccat(str, c);
  936.             p++;
  937.         }
  938.     }
  939.     p++;
  940.     return p;
  941. }
  942.  
  943. /* skip block of text until #else, #elif or #endif. skip also pairs of
  944.    #if/#endif */
  945. static void preprocess_skip(void)
  946. {
  947.     int a, start_of_line, c, in_warn_or_error;
  948.     uint8_t *p;
  949.  
  950.     p = file->buf_ptr;
  951.     a = 0;
  952. redo_start:
  953.     start_of_line = 1;
  954.     in_warn_or_error = 0;
  955.     for(;;) {
  956.     redo_no_start:
  957.         c = *p;
  958.         switch(c) {
  959.         case ' ':
  960.         case '\t':
  961.         case '\f':
  962.         case '\v':
  963.         case '\r':
  964.             p++;
  965.             goto redo_no_start;
  966.         case '\n':
  967.             file->line_num++;
  968.             p++;
  969.             goto redo_start;
  970.         case '\\':
  971.             file->buf_ptr = p;
  972.             c = handle_eob();
  973.             if (c == CH_EOF) {
  974.                 expect("#endif");
  975.             } else if (c == '\\') {
  976.                 ch = file->buf_ptr[0];
  977.                 handle_stray_noerror();
  978.             }
  979.             p = file->buf_ptr;
  980.             goto redo_no_start;
  981.         /* skip strings */
  982.         case '\"':
  983.         case '\'':
  984.             if (in_warn_or_error)
  985.                 goto _default;
  986.             p = parse_pp_string(p, c, NULL);
  987.             break;
  988.         /* skip comments */
  989.         case '/':
  990.             if (in_warn_or_error)
  991.                 goto _default;
  992.             file->buf_ptr = p;
  993.             ch = *p;
  994.             minp();
  995.             p = file->buf_ptr;
  996.             if (ch == '*') {
  997.                 p = parse_comment(p,1);
  998.             } else if (ch == '/') {
  999.                 p = parse_line_comment(p,1);
  1000.             }
  1001.             break;
  1002.         case '#':
  1003.             p++;
  1004.             if (start_of_line) {
  1005.                 file->buf_ptr = p;
  1006.                 next_nomacro();
  1007.                 p = file->buf_ptr;
  1008.                 if (a == 0 &&
  1009.                     (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
  1010.                     goto the_end;
  1011.                 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
  1012.                     a++;
  1013.                 else if (tok == TOK_ENDIF)
  1014.                     a--;
  1015.                 else if( tok == TOK_ERROR || tok == TOK_WARNING)
  1016.                     in_warn_or_error = 1;
  1017.                 else if (tok == TOK_LINEFEED)
  1018.                     goto redo_start;
  1019.                 else if (parse_flags & PARSE_FLAG_ASM_FILE)
  1020.                     p = parse_line_comment(p,0);
  1021.             } else if (parse_flags & PARSE_FLAG_ASM_FILE)
  1022.                 p = parse_line_comment(p,0);
  1023.             break;
  1024. _default:
  1025.         default:
  1026.             p++;
  1027.             break;
  1028.         }
  1029.         start_of_line = 0;
  1030.     }
  1031.  the_end: ;
  1032.     file->buf_ptr = p;
  1033. }
  1034.  
  1035. /* ParseState handling */
  1036.  
  1037. /* XXX: currently, no include file info is stored. Thus, we cannot display
  1038.    accurate messages if the function or data definition spans multiple
  1039.    files */
  1040.  
  1041. /* save current parse state in 's' */
  1042. ST_FUNC void save_parse_state(ParseState *s)
  1043. {
  1044.     s->line_num = file->line_num;
  1045.     s->macro_ptr = macro_ptr;
  1046.     s->tok = tok;
  1047.     s->tokc = tokc;
  1048. }
  1049.  
  1050. /* restore parse state from 's' */
  1051. ST_FUNC void restore_parse_state(ParseState *s)
  1052. {
  1053.     file->line_num = s->line_num;
  1054.     macro_ptr = s->macro_ptr;
  1055.     tok = s->tok;
  1056.     tokc = s->tokc;
  1057. }
  1058.  
  1059. /* return the number of additional 'ints' necessary to store the
  1060.    token */
  1061. static inline int tok_size(const int *p)
  1062. {
  1063.     switch(*p) {
  1064.         /* 4 bytes */
  1065.     case TOK_CINT:
  1066.     case TOK_CUINT:
  1067.     case TOK_CCHAR:
  1068.     case TOK_LCHAR:
  1069.     case TOK_CFLOAT:
  1070.     case TOK_LINENUM:
  1071.         return 1 + 1;
  1072.     case TOK_STR:
  1073.     case TOK_LSTR:
  1074.     case TOK_PPNUM:
  1075.     case TOK_PPSTR:
  1076.         return 1 + ((sizeof(CString) + ((CString *)(p+1))->size + 3) >> 2);
  1077.     case TOK_CDOUBLE:
  1078.     case TOK_CLLONG:
  1079.     case TOK_CULLONG:
  1080.         return 1 + 2;
  1081.     case TOK_CLDOUBLE:
  1082.         return 1 + LDOUBLE_SIZE / 4;
  1083.     default:
  1084.         return 1 + 0;
  1085.     }
  1086. }
  1087.  
  1088. /* token string handling */
  1089.  
  1090. ST_INLN void tok_str_new(TokenString *s)
  1091. {
  1092.     s->str = NULL;
  1093.     s->len = 0;
  1094.     s->allocated_len = 0;
  1095.     s->last_line_num = -1;
  1096. }
  1097.  
  1098. ST_FUNC int *tok_str_dup(TokenString *s)
  1099. {
  1100.     int *str;
  1101.  
  1102.     str = tal_realloc(tokstr_alloc, 0, s->len * sizeof(int));
  1103.     memcpy(str, s->str, s->len * sizeof(int));
  1104.     return str;
  1105. }
  1106.  
  1107. ST_FUNC void tok_str_free(int *str)
  1108. {
  1109.     tal_free(tokstr_alloc, str);
  1110. }
  1111.  
  1112. ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
  1113. {
  1114.     int *str, size;
  1115.  
  1116.     size = s->allocated_len;
  1117.     if (size < 16)
  1118.         size = 16;
  1119.     while (size < new_size)
  1120.         size = size * 2;
  1121.     TCC_ASSERT((size & (size -1)) == 0);
  1122.     if (size > s->allocated_len) {
  1123.         str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int));
  1124.         s->allocated_len = size;
  1125.         s->str = str;
  1126.     }
  1127.     return s->str;
  1128. }
  1129.  
  1130. ST_FUNC void tok_str_add(TokenString *s, int t)
  1131. {
  1132.     int len, *str;
  1133.  
  1134.     len = s->len;
  1135.     str = s->str;
  1136.     if (len >= s->allocated_len)
  1137.         str = tok_str_realloc(s, len + 1);
  1138.     str[len++] = t;
  1139.     s->len = len;
  1140. }
  1141.  
  1142. static void tok_str_add2(TokenString *s, int t, CValue *cv)
  1143. {
  1144.     int len, *str;
  1145.  
  1146.     len = s->len;
  1147.     str = s->str;
  1148.  
  1149.     /* allocate space for worst case */
  1150.     if (len + TOK_MAX_SIZE >= s->allocated_len)
  1151.         str = tok_str_realloc(s, len + TOK_MAX_SIZE + 1);
  1152.     str[len++] = t;
  1153.     switch(t) {
  1154.     case TOK_CINT:
  1155.     case TOK_CUINT:
  1156.     case TOK_CCHAR:
  1157.     case TOK_LCHAR:
  1158.     case TOK_CFLOAT:
  1159.     case TOK_LINENUM:
  1160.         str[len++] = cv->tab[0];
  1161.         break;
  1162.     case TOK_PPNUM:
  1163.     case TOK_PPSTR:
  1164.     case TOK_STR:
  1165.     case TOK_LSTR:
  1166.         {
  1167.             /* Insert the string into the int array. */
  1168.             size_t nb_words =
  1169.                 1 + (cv->str.size + sizeof(int) - 1) / sizeof(int);
  1170.             if (len + nb_words >= s->allocated_len)
  1171.                 str = tok_str_realloc(s, len + nb_words + 1);
  1172.             str[len] = cv->str.size;
  1173.             memcpy(&str[len + 1], cv->str.data, cv->str.size);
  1174.             len += nb_words;
  1175.         }
  1176.         break;
  1177.     case TOK_CDOUBLE:
  1178.     case TOK_CLLONG:
  1179.     case TOK_CULLONG:
  1180. #if LDOUBLE_SIZE == 8
  1181.     case TOK_CLDOUBLE:
  1182. #endif
  1183.         str[len++] = cv->tab[0];
  1184.         str[len++] = cv->tab[1];
  1185.         break;
  1186. #if LDOUBLE_SIZE == 12
  1187.     case TOK_CLDOUBLE:
  1188.         str[len++] = cv->tab[0];
  1189.         str[len++] = cv->tab[1];
  1190.         str[len++] = cv->tab[2];
  1191. #elif LDOUBLE_SIZE == 16
  1192.     case TOK_CLDOUBLE:
  1193.         str[len++] = cv->tab[0];
  1194.         str[len++] = cv->tab[1];
  1195.         str[len++] = cv->tab[2];
  1196.         str[len++] = cv->tab[3];
  1197. #elif LDOUBLE_SIZE != 8
  1198. #error add long double size support
  1199. #endif
  1200.         break;
  1201.     default:
  1202.         break;
  1203.     }
  1204.     s->len = len;
  1205. }
  1206.  
  1207. /* add the current parse token in token string 's' */
  1208. ST_FUNC void tok_str_add_tok(TokenString *s)
  1209. {
  1210.     CValue cval;
  1211.  
  1212.     /* save line number info */
  1213.     if (file->line_num != s->last_line_num) {
  1214.         s->last_line_num = file->line_num;
  1215.         cval.i = s->last_line_num;
  1216.         tok_str_add2(s, TOK_LINENUM, &cval);
  1217.     }
  1218.     tok_str_add2(s, tok, &tokc);
  1219. }
  1220.  
  1221. /* get a token from an integer array and increment pointer
  1222.    accordingly. we code it as a macro to avoid pointer aliasing. */
  1223. static inline void TOK_GET(int *t, const int **pp, CValue *cv)
  1224. {
  1225.     const int *p = *pp;
  1226.     int n, *tab;
  1227.  
  1228.     tab = cv->tab;
  1229.     switch(*t = *p++) {
  1230.     case TOK_CINT:
  1231.     case TOK_CUINT:
  1232.     case TOK_CCHAR:
  1233.     case TOK_LCHAR:
  1234.     case TOK_CFLOAT:
  1235.     case TOK_LINENUM:
  1236.         tab[0] = *p++;
  1237.         break;
  1238.     case TOK_STR:
  1239.     case TOK_LSTR:
  1240.     case TOK_PPNUM:
  1241.     case TOK_PPSTR:
  1242.         cv->str.size = *p++;
  1243.         cv->str.data = p;
  1244.         cv->str.data_allocated = 0;
  1245.         p += (cv->str.size + sizeof(int) - 1) / sizeof(int);
  1246.         break;
  1247.     case TOK_CDOUBLE:
  1248.     case TOK_CLLONG:
  1249.     case TOK_CULLONG:
  1250.         n = 2;
  1251.         goto copy;
  1252.     case TOK_CLDOUBLE:
  1253. #if LDOUBLE_SIZE == 16
  1254.         n = 4;
  1255. #elif LDOUBLE_SIZE == 12
  1256.         n = 3;
  1257. #elif LDOUBLE_SIZE == 8
  1258.         n = 2;
  1259. #else
  1260. # error add long double size support
  1261. #endif
  1262.     copy:
  1263.         do
  1264.             *tab++ = *p++;
  1265.         while (--n);
  1266.         break;
  1267.     default:
  1268.         break;
  1269.     }
  1270.     *pp = p;
  1271. }
  1272.  
  1273. /* Calling this function is expensive, but it is not possible
  1274.    to read a token string backwards. */
  1275. static int tok_last(const int *str0, const int *str1)
  1276. {
  1277.     const int *str = str0;
  1278.     int tok = 0;
  1279.     CValue cval;
  1280.  
  1281.     while (str < str1)
  1282.         TOK_GET(&tok, &str, &cval);
  1283.     return tok;
  1284. }
  1285.  
  1286. static int macro_is_equal(const int *a, const int *b)
  1287. {
  1288.     CValue cv;
  1289.     int t;
  1290.     while (*a && *b) {
  1291.         /* first time preallocate static cstr_buf, next time only reset position to start */
  1292.         cstr_reset(&cstr_buf);
  1293.         TOK_GET(&t, &a, &cv);
  1294.         cstr_cat(&cstr_buf, get_tok_str(t, &cv), 0);
  1295.         TOK_GET(&t, &b, &cv);
  1296.         if (strcmp(cstr_buf.data, get_tok_str(t, &cv)))
  1297.             return 0;
  1298.     }
  1299.     return !(*a || *b);
  1300. }
  1301.  
  1302. static void tok_print(const char *msg, const int *str)
  1303. {
  1304.     FILE *pr = tcc_state->dffp;
  1305.     int t;
  1306.     CValue cval;
  1307.  
  1308.     fprintf(pr, "%s ", msg);
  1309.     while (str) {
  1310.         TOK_GET(&t, &str, &cval);
  1311.         if (!t)
  1312.             break;
  1313.         fprintf(pr,"%s", get_tok_str(t, &cval));
  1314.     }
  1315.     fprintf(pr, "\n");
  1316. }
  1317.  
  1318. static int define_print_prepared(Sym *s)
  1319. {
  1320.     if (!s || !tcc_state->dffp || tcc_state->dflag == 0)
  1321.         return 0;
  1322.  
  1323.     if (s->v < TOK_IDENT || s->v >= tok_ident)
  1324.         return 0;
  1325.  
  1326.     if (file && tcc_state->dflag == 'D') {
  1327.         file->line_num--;
  1328.         pp_line(tcc_state, file, 0);
  1329.         file->line_ref = ++file->line_num;
  1330.     }
  1331.     return 1;
  1332. }
  1333.  
  1334. static void define_print(int v)
  1335. {
  1336.     FILE *pr = tcc_state->dffp;
  1337.     Sym *s, *a;
  1338.  
  1339.     s = define_find(v);
  1340.     if (define_print_prepared(s) == 0)
  1341.         return;
  1342.  
  1343.     fprintf(pr, "// #define %s", get_tok_str(v, NULL));
  1344.     if (s->type.t == MACRO_FUNC) {
  1345.         a = s->next;
  1346.         fprintf(pr,"(");
  1347.         if (a)
  1348.             for (;;) {
  1349.                 fprintf(pr,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL));
  1350.                 if (!(a = a->next))
  1351.                     break;
  1352.                 fprintf(pr,",");
  1353.             }
  1354.         fprintf(pr,")");
  1355.     }
  1356.     tok_print("", s->d);
  1357. }
  1358.  
  1359. static void undef_print(int v)
  1360. {
  1361.     FILE *pr = tcc_state->dffp;
  1362.     Sym *s;
  1363.  
  1364.     s = define_find(v);
  1365.     if (define_print_prepared(s) == 0)
  1366.         return;
  1367.  
  1368.     fprintf(pr, "// #undef %s\n", get_tok_str(s->v, NULL));
  1369. }
  1370.  
  1371. ST_FUNC void print_defines(void)
  1372. {
  1373.     Sym *top = define_stack;
  1374.     while (top) {
  1375.         define_print(top->v);
  1376.         top = top->prev;
  1377.     }
  1378. }
  1379.  
  1380. /* defines handling */
  1381. ST_INLN void define_push(int v, int macro_type, TokenString *str, Sym *first_arg)
  1382. {
  1383.     Sym *s;
  1384.  
  1385.     if (str) {
  1386.         s = define_find(v);
  1387.         if (s && !macro_is_equal(s->d, str->str))
  1388.             tcc_warning("%s redefined", get_tok_str(v, NULL));
  1389.     }
  1390.  
  1391.     s = sym_push2(&define_stack, v, macro_type, 0);
  1392.     s->d = str ? tok_str_dup(str) : NULL;
  1393.     s->next = first_arg;
  1394.     table_ident[v - TOK_IDENT]->sym_define = s;
  1395. }
  1396.  
  1397. /* undefined a define symbol. Its name is just set to zero */
  1398. ST_FUNC void define_undef(Sym *s)
  1399. {
  1400.     int v = s->v;
  1401.     undef_print(v);
  1402.     if (v >= TOK_IDENT && v < tok_ident)
  1403.         table_ident[v - TOK_IDENT]->sym_define = NULL;
  1404. }
  1405.  
  1406. ST_INLN Sym *define_find(int v)
  1407. {
  1408.     v -= TOK_IDENT;
  1409.     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
  1410.         return NULL;
  1411.     return table_ident[v]->sym_define;
  1412. }
  1413.  
  1414. /* free define stack until top reaches 'b' */
  1415. ST_FUNC void free_defines(Sym *b)
  1416. {
  1417.     Sym *top, *top1;
  1418.     int v;
  1419.  
  1420.     top = define_stack;
  1421.     while (top != b) {
  1422.         top1 = top->prev;
  1423.         /* do not free args or predefined defines */
  1424.         if (top->d)
  1425.             tok_str_free(top->d);
  1426.         v = top->v;
  1427.         if (v >= TOK_IDENT && v < tok_ident)
  1428.             table_ident[v - TOK_IDENT]->sym_define = NULL;
  1429.         sym_free(top);
  1430.         top = top1;
  1431.     }
  1432.     define_stack = b;
  1433. }
  1434.  
  1435. /* label lookup */
  1436. ST_FUNC Sym *label_find(int v)
  1437. {
  1438.     v -= TOK_IDENT;
  1439.     if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
  1440.         return NULL;
  1441.     return table_ident[v]->sym_label;
  1442. }
  1443.  
  1444. ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
  1445. {
  1446.     Sym *s, **ps;
  1447.     s = sym_push2(ptop, v, 0, 0);
  1448.     s->r = flags;
  1449.     ps = &table_ident[v - TOK_IDENT]->sym_label;
  1450.     if (ptop == &global_label_stack) {
  1451.         /* modify the top most local identifier, so that
  1452.            sym_identifier will point to 's' when popped */
  1453.         while (*ps != NULL)
  1454.             ps = &(*ps)->prev_tok;
  1455.     }
  1456.     s->prev_tok = *ps;
  1457.     *ps = s;
  1458.     return s;
  1459. }
  1460.  
  1461. /* pop labels until element last is reached. Look if any labels are
  1462.    undefined. Define symbols if '&&label' was used. */
  1463. ST_FUNC void label_pop(Sym **ptop, Sym *slast)
  1464. {
  1465.     Sym *s, *s1;
  1466.     for(s = *ptop; s != slast; s = s1) {
  1467.         s1 = s->prev;
  1468.         if (s->r == LABEL_DECLARED) {
  1469.             tcc_warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
  1470.         } else if (s->r == LABEL_FORWARD) {
  1471.                 tcc_error("label '%s' used but not defined",
  1472.                       get_tok_str(s->v, NULL));
  1473.         } else {
  1474.             if (s->c) {
  1475.                 /* define corresponding symbol. A size of
  1476.                    1 is put. */
  1477.                 put_extern_sym(s, cur_text_section, s->jnext, 1);
  1478.             }
  1479.         }
  1480.         /* remove label */
  1481.         table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
  1482.         sym_free(s);
  1483.     }
  1484.     *ptop = slast;
  1485. }
  1486.  
  1487. /* eval an expression for #if/#elif */
  1488. static int expr_preprocess(void)
  1489. {
  1490.     int c, t;
  1491.     TokenString str;
  1492.    
  1493.     tok_str_new(&str);
  1494.     while (tok != TOK_LINEFEED && tok != TOK_EOF) {
  1495.         next(); /* do macro subst */
  1496.         if (tok == TOK_DEFINED) {
  1497.             next_nomacro();
  1498.             t = tok;
  1499.             if (t == '(')
  1500.                 next_nomacro();
  1501.             c = define_find(tok) != 0;
  1502.             if (t == '(')
  1503.                 next_nomacro();
  1504.             tok = TOK_CINT;
  1505.             tokc.i = c;
  1506.         } else if (tok >= TOK_IDENT) {
  1507.             /* if undefined macro */
  1508.             tok = TOK_CINT;
  1509.             tokc.i = 0;
  1510.         }
  1511.         tok_str_add_tok(&str);
  1512.     }
  1513.     tok_str_add(&str, -1); /* simulate end of file */
  1514.     tok_str_add(&str, 0);
  1515.     /* now evaluate C constant expression */
  1516.     begin_macro(&str, 0);
  1517.     next();
  1518.     c = expr_const();
  1519.     end_macro();
  1520.     return c != 0;
  1521. }
  1522.  
  1523.  
  1524. /* parse after #define */
  1525. ST_FUNC void parse_define(void)
  1526. {
  1527.     Sym *s, *first, **ps;
  1528.     int v, t, varg, is_vaargs, spc;
  1529.     int saved_parse_flags = parse_flags;
  1530.  
  1531.     v = tok;
  1532.     if (v < TOK_IDENT)
  1533.         tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
  1534.     /* XXX: should check if same macro (ANSI) */
  1535.     first = NULL;
  1536.     t = MACRO_OBJ;
  1537.     /* '(' must be just after macro definition for MACRO_FUNC */
  1538.     parse_flags |= PARSE_FLAG_SPACES;
  1539.     next_nomacro_spc();
  1540.     if (tok == '(') {
  1541.         /* must be able to parse TOK_DOTS (in asm mode '.' can be part of identifier) */
  1542.         parse_flags &= ~PARSE_FLAG_ASM_FILE;
  1543.         isidnum_table['.' - CH_EOF] = 0;
  1544.         next_nomacro();
  1545.         ps = &first;
  1546.         if (tok != ')') for (;;) {
  1547.             varg = tok;
  1548.             next_nomacro();
  1549.             is_vaargs = 0;
  1550.             if (varg == TOK_DOTS) {
  1551.                 varg = TOK___VA_ARGS__;
  1552.                 is_vaargs = 1;
  1553.             } else if (tok == TOK_DOTS && gnu_ext) {
  1554.                 is_vaargs = 1;
  1555.                 next_nomacro();
  1556.             }
  1557.             if (varg < TOK_IDENT)
  1558.         bad_list:
  1559.                 tcc_error("bad macro parameter list");
  1560.             s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
  1561.             *ps = s;
  1562.             ps = &s->next;
  1563.             if (tok == ')')
  1564.                 break;
  1565.             if (tok != ',' || is_vaargs)
  1566.                 goto bad_list;
  1567.             next_nomacro();
  1568.         }
  1569.         next_nomacro_spc();
  1570.         t = MACRO_FUNC;
  1571.         parse_flags |= (saved_parse_flags & PARSE_FLAG_ASM_FILE);
  1572.         isidnum_table['.' - CH_EOF] =
  1573.             (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0;
  1574.     }
  1575.  
  1576.     tokstr_buf.len = 0;
  1577.     spc = 2;
  1578.     parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED;
  1579.     while (tok != TOK_LINEFEED && tok != TOK_EOF) {
  1580.         /* remove spaces around ## and after '#' */
  1581.         if (TOK_TWOSHARPS == tok) {
  1582.             if (2 == spc)
  1583.                 goto bad_twosharp;
  1584.             if (1 == spc)
  1585.                 --tokstr_buf.len;
  1586.             spc = 3;
  1587.         } else if ('#' == tok) {
  1588.             spc = 4;
  1589.         } else if (check_space(tok, &spc)) {
  1590.             goto skip;
  1591.         }
  1592.         tok_str_add2(&tokstr_buf, tok, &tokc);
  1593.     skip:
  1594.         next_nomacro_spc();
  1595.     }
  1596.  
  1597.     parse_flags = saved_parse_flags;
  1598.     if (spc == 1)
  1599.         --tokstr_buf.len; /* remove trailing space */
  1600.     tok_str_add(&tokstr_buf, 0);
  1601.     if (3 == spc)
  1602. bad_twosharp:
  1603.         tcc_error("'##' cannot appear at either end of macro");
  1604.     define_push(v, t, &tokstr_buf, first);
  1605.     define_print(v);
  1606. }
  1607.  
  1608. static inline int hash_cached_include(const char *filename)
  1609. {
  1610.     const unsigned char *s;
  1611.     unsigned int h;
  1612.  
  1613.     h = TOK_HASH_INIT;
  1614.     s = (unsigned char *) filename;
  1615.     while (*s) {
  1616.         h = TOK_HASH_FUNC(h, *s);
  1617.         s++;
  1618.     }
  1619.     h &= (CACHED_INCLUDES_HASH_SIZE - 1);
  1620.     return h;
  1621. }
  1622.  
  1623. static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
  1624. {
  1625.     CachedInclude *e;
  1626.     int i, h;
  1627.     h = hash_cached_include(filename);
  1628.     i = s1->cached_includes_hash[h];
  1629.     for(;;) {
  1630.         if (i == 0)
  1631.             break;
  1632.         e = s1->cached_includes[i - 1];
  1633.         if (0 == PATHCMP(e->filename, filename))
  1634.             return e;
  1635.         i = e->hash_next;
  1636.     }
  1637.     return NULL;
  1638. }
  1639.  
  1640. static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
  1641. {
  1642.     CachedInclude *e;
  1643.     int h;
  1644.  
  1645.     if (search_cached_include(s1, filename))
  1646.         return;
  1647. #ifdef INC_DEBUG
  1648.     printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
  1649. #endif
  1650.     e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
  1651.     strcpy(e->filename, filename);
  1652.     e->ifndef_macro = ifndef_macro;
  1653.     dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
  1654.     /* add in hash table */
  1655.     h = hash_cached_include(filename);
  1656.     e->hash_next = s1->cached_includes_hash[h];
  1657.     s1->cached_includes_hash[h] = s1->nb_cached_includes;
  1658. }
  1659.  
  1660. #define ONCE_PREFIX "#ONCE#"
  1661.  
  1662. static void pragma_parse(TCCState *s1)
  1663. {
  1664.     next_nomacro();
  1665.     if (tok == TOK_push_macro || tok == TOK_pop_macro) {
  1666.         int t = tok, v;
  1667.         Sym *s;
  1668.  
  1669.         if (next(), tok != '(')
  1670.             goto pragma_err;
  1671.         if (next(), tok != TOK_STR)
  1672.             goto pragma_err;
  1673.         v = tok_alloc(tokc.str.data, tokc.str.size - 1)->tok;
  1674.         if (next(), tok != ')')
  1675.             goto pragma_err;
  1676.         if (t == TOK_push_macro) {
  1677.             while (NULL == (s = define_find(v)))
  1678.                 define_push(v, 0, NULL, NULL);
  1679.             s->type.ref = s; /* set push boundary */
  1680.         } else {
  1681.             for (s = define_stack; s; s = s->prev)
  1682.                 if (s->v == v && s->type.ref == s) {
  1683.                     s->type.ref = NULL;
  1684.                     break;
  1685.                 }
  1686.         }
  1687.         if (s)
  1688.             table_ident[v - TOK_IDENT]->sym_define = s->d ? s : NULL;
  1689.         else
  1690.             tcc_warning("unbalanced #pragma pop_macro");
  1691.  
  1692.     } else if (tok == TOK_once) {
  1693.         char buf1[sizeof(file->filename) + sizeof(ONCE_PREFIX)];
  1694.         strcpy(buf1, ONCE_PREFIX);
  1695.         strcat(buf1, file->filename);
  1696. #ifdef PATH_NOCASE
  1697.         strupr(buf1);
  1698. #endif
  1699.         add_cached_include(s1, file->filename, tok_alloc(buf1, strlen(buf1))->tok);
  1700.     } else if (s1->ppfp) {
  1701.         /* tcc -E: keep pragmas below unchanged */
  1702.         unget_tok(' ');
  1703.         unget_tok(TOK_PRAGMA);
  1704.         unget_tok('#');
  1705.         unget_tok(TOK_LINEFEED);
  1706.  
  1707.     } else if (tok == TOK_pack) {
  1708.         /* This may be:
  1709.            #pragma pack(1) // set
  1710.            #pragma pack() // reset to default
  1711.            #pragma pack(push,1) // push & set
  1712.            #pragma pack(pop) // restore previous */
  1713.         next();
  1714.         skip('(');
  1715.         if (tok == TOK_ASM_pop) {
  1716.             next();
  1717.             if (s1->pack_stack_ptr <= s1->pack_stack) {
  1718.             stk_error:
  1719.                 tcc_error("out of pack stack");
  1720.             }
  1721.             s1->pack_stack_ptr--;
  1722.         } else {
  1723.             int val = 0;
  1724.             if (tok != ')') {
  1725.                 if (tok == TOK_ASM_push) {
  1726.                     next();
  1727.                     if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
  1728.                         goto stk_error;
  1729.                     s1->pack_stack_ptr++;
  1730.                     skip(',');
  1731.                 }
  1732.                 if (tok != TOK_CINT)
  1733.                     goto pragma_err;
  1734.                 val = tokc.i;
  1735.                 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
  1736.                     goto pragma_err;
  1737.                 next();
  1738.             }
  1739.             *s1->pack_stack_ptr = val;
  1740.         }
  1741.         if (tok != ')')
  1742.             goto pragma_err;
  1743.  
  1744.     } else if (tok == TOK_comment) {
  1745.         char *file;
  1746.         next();
  1747.         skip('(');
  1748.         if (tok != TOK_lib)
  1749.             goto pragma_warn;
  1750.         next();
  1751.         skip(',');
  1752.         if (tok != TOK_STR)
  1753.             goto pragma_err;
  1754.         file = tcc_strdup((char *)tokc.str.data);
  1755.         dynarray_add((void ***)&s1->pragma_libs, &s1->nb_pragma_libs, file);
  1756.         next();
  1757.         if (tok != ')')
  1758.             goto pragma_err;
  1759.     } else {
  1760. pragma_warn:
  1761.         if (s1->warn_unsupported)
  1762.             tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc));
  1763.     }
  1764.     return;
  1765.  
  1766. pragma_err:
  1767.     tcc_error("malformed #pragma directive");
  1768.     return;
  1769. }
  1770.  
  1771. /* is_bof is true if first non space token at beginning of file */
  1772. ST_FUNC void preprocess(int is_bof)
  1773. {
  1774.     TCCState *s1 = tcc_state;
  1775.     int i, c, n, saved_parse_flags;
  1776.     char buf[1024], *q;
  1777.     Sym *s;
  1778.  
  1779.     saved_parse_flags = parse_flags;
  1780.     parse_flags = PARSE_FLAG_PREPROCESS
  1781.         | PARSE_FLAG_TOK_NUM
  1782.         | PARSE_FLAG_TOK_STR
  1783.         | PARSE_FLAG_LINEFEED
  1784.         | (parse_flags & PARSE_FLAG_ASM_FILE)
  1785.         ;
  1786.  
  1787.     next_nomacro();
  1788.  redo:
  1789.     switch(tok) {
  1790.     case TOK_DEFINE:
  1791.         next_nomacro();
  1792.         parse_define();
  1793.         break;
  1794.     case TOK_UNDEF:
  1795.         next_nomacro();
  1796.         s = define_find(tok);
  1797.         /* undefine symbol by putting an invalid name */
  1798.         if (s)
  1799.             define_undef(s);
  1800.         break;
  1801.     case TOK_INCLUDE:
  1802.     case TOK_INCLUDE_NEXT:
  1803.         ch = file->buf_ptr[0];
  1804.         /* XXX: incorrect if comments : use next_nomacro with a special mode */
  1805.         skip_spaces();
  1806.         if (ch == '<') {
  1807.             c = '>';
  1808.             goto read_name;
  1809.         } else if (ch == '\"') {
  1810.             c = ch;
  1811.         read_name:
  1812.             inp();
  1813.             q = buf;
  1814.             while (ch != c && ch != '\n' && ch != CH_EOF) {
  1815.                 if ((q - buf) < sizeof(buf) - 1)
  1816.                     *q++ = ch;
  1817.                 if (ch == '\\') {
  1818.                     if (handle_stray_noerror() == 0)
  1819.                         --q;
  1820.                 } else
  1821.                     inp();
  1822.             }
  1823.             *q = '\0';
  1824.             minp();
  1825. #if 0
  1826.             /* eat all spaces and comments after include */
  1827.             /* XXX: slightly incorrect */
  1828.             while (ch1 != '\n' && ch1 != CH_EOF)
  1829.                 inp();
  1830. #endif
  1831.         } else {
  1832.             /* computed #include : either we have only strings or
  1833.                we have anything enclosed in '<>' */
  1834.             next();
  1835.             buf[0] = '\0';
  1836.             if (tok == TOK_STR) {
  1837.                 while (tok != TOK_LINEFEED) {
  1838.                     if (tok != TOK_STR) {
  1839.                     include_syntax:
  1840.                         tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
  1841.                     }
  1842.                     pstrcat(buf, sizeof(buf), (char *)tokc.str.data);
  1843.                     next();
  1844.                 }
  1845.                 c = '\"';
  1846.             } else {
  1847.                 int len;
  1848.                 while (tok != TOK_LINEFEED) {
  1849.                     pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
  1850.                     next();
  1851.                 }
  1852.                 len = strlen(buf);
  1853.                 /* check syntax and remove '<>' */
  1854.                 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
  1855.                     goto include_syntax;
  1856.                 memmove(buf, buf + 1, len - 2);
  1857.                 buf[len - 2] = '\0';
  1858.                 c = '>';
  1859.             }
  1860.         }
  1861.  
  1862.         if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
  1863.             tcc_error("#include recursion too deep");
  1864.         /* store current file in stack, but increment stack later below */
  1865.         *s1->include_stack_ptr = file;
  1866.         i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0;
  1867.         n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
  1868.         for (; i < n; ++i) {
  1869.             char buf1[sizeof file->filename];
  1870.             CachedInclude *e;
  1871.             const char *path;
  1872.  
  1873.             if (i == 0) {
  1874.                 /* check absolute include path */
  1875.                 if (!IS_ABSPATH(buf))
  1876.                     continue;
  1877.                 buf1[0] = 0;
  1878.  
  1879.             } else if (i == 1) {
  1880.                 /* search in current dir if "header.h" */
  1881.                 if (c != '\"')
  1882.                     continue;
  1883.                 path = file->filename;
  1884.                 pstrncpy(buf1, path, tcc_basename(path) - path);
  1885.  
  1886.             } else {
  1887.                 /* search in all the include paths */
  1888.                 int j = i - 2, k = j - s1->nb_include_paths;
  1889.                 path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
  1890.                 if (path == 0) continue;
  1891.                 pstrcpy(buf1, sizeof(buf1), path);
  1892.                 pstrcat(buf1, sizeof(buf1), "/");
  1893.             }
  1894.  
  1895.             pstrcat(buf1, sizeof(buf1), buf);
  1896.             e = search_cached_include(s1, buf1);
  1897.             if (e && define_find(e->ifndef_macro)) {
  1898.                 /* no need to parse the include because the 'ifndef macro'
  1899.                    is defined */
  1900. #ifdef INC_DEBUG
  1901.                 printf("%s: skipping cached %s\n", file->filename, buf1);
  1902. #endif
  1903.                 goto include_done;
  1904.             }
  1905.  
  1906.             if (tcc_open(s1, buf1) < 0)
  1907.                 continue;
  1908.  
  1909.             file->include_next_index = i + 1;
  1910. #ifdef INC_DEBUG
  1911.             printf("%s: including %s\n", file->prev->filename, file->filename);
  1912. #endif
  1913.             /* update target deps */
  1914.             dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
  1915.                     tcc_strdup(buf1));
  1916.             /* push current file in stack */
  1917.             ++s1->include_stack_ptr;
  1918.             /* add include file debug info */
  1919.             if (s1->do_debug)
  1920.                 put_stabs(file->filename, N_BINCL, 0, 0, 0);
  1921.             tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
  1922.             ch = file->buf_ptr[0];
  1923.             goto the_end;
  1924.         }
  1925.         tcc_error("include file '%s' not found", buf);
  1926. include_done:
  1927.         break;
  1928.     case TOK_IFNDEF:
  1929.         c = 1;
  1930.         goto do_ifdef;
  1931.     case TOK_IF:
  1932.         c = expr_preprocess();
  1933.         goto do_if;
  1934.     case TOK_IFDEF:
  1935.         c = 0;
  1936.     do_ifdef:
  1937.         next_nomacro();
  1938.         if (tok < TOK_IDENT)
  1939.             tcc_error("invalid argument for '#if%sdef'", c ? "n" : "");
  1940.         if (is_bof) {
  1941.             if (c) {
  1942. #ifdef INC_DEBUG
  1943.                 printf("#ifndef %s\n", get_tok_str(tok, NULL));
  1944. #endif
  1945.                 file->ifndef_macro = tok;
  1946.             }
  1947.         }
  1948.         c = (define_find(tok) != 0) ^ c;
  1949.     do_if:
  1950.         if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
  1951.             tcc_error("memory full (ifdef)");
  1952.         *s1->ifdef_stack_ptr++ = c;
  1953.         goto test_skip;
  1954.     case TOK_ELSE:
  1955.         if (s1->ifdef_stack_ptr == s1->ifdef_stack)
  1956.             tcc_error("#else without matching #if");
  1957.         if (s1->ifdef_stack_ptr[-1] & 2)
  1958.             tcc_error("#else after #else");
  1959.         c = (s1->ifdef_stack_ptr[-1] ^= 3);
  1960.         goto test_else;
  1961.     case TOK_ELIF:
  1962.         if (s1->ifdef_stack_ptr == s1->ifdef_stack)
  1963.             tcc_error("#elif without matching #if");
  1964.         c = s1->ifdef_stack_ptr[-1];
  1965.         if (c > 1)
  1966.             tcc_error("#elif after #else");
  1967.         /* last #if/#elif expression was true: we skip */
  1968.         if (c == 1)
  1969.             goto skip;
  1970.         c = expr_preprocess();
  1971.         s1->ifdef_stack_ptr[-1] = c;
  1972.     test_else:
  1973.         if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
  1974.             file->ifndef_macro = 0;
  1975.     test_skip:
  1976.         if (!(c & 1)) {
  1977.         skip:
  1978.             preprocess_skip();
  1979.             is_bof = 0;
  1980.             goto redo;
  1981.         }
  1982.         break;
  1983.     case TOK_ENDIF:
  1984.         if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
  1985.             tcc_error("#endif without matching #if");
  1986.         s1->ifdef_stack_ptr--;
  1987.         /* '#ifndef macro' was at the start of file. Now we check if
  1988.            an '#endif' is exactly at the end of file */
  1989.         if (file->ifndef_macro &&
  1990.             s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
  1991.             file->ifndef_macro_saved = file->ifndef_macro;
  1992.             /* need to set to zero to avoid false matches if another
  1993.                #ifndef at middle of file */
  1994.             file->ifndef_macro = 0;
  1995.             while (tok != TOK_LINEFEED)
  1996.                 next_nomacro();
  1997.             tok_flags |= TOK_FLAG_ENDIF;
  1998.             goto the_end;
  1999.         }
  2000.         break;
  2001.     case TOK_PPNUM:
  2002.         n = strtoul((char*)tokc.str.data, &q, 10);
  2003.         goto _line_num;
  2004.     case TOK_LINE:
  2005.         next();
  2006.         if (tok != TOK_CINT)
  2007. _line_err:
  2008.             tcc_error("wrong #line format");
  2009.         n = tokc.i;
  2010. _line_num:
  2011.         next();
  2012.         if (tok != TOK_LINEFEED) {
  2013.             if (tok == TOK_STR)
  2014.                 pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data);
  2015.             else if (parse_flags & PARSE_FLAG_ASM_FILE)
  2016.                 break;
  2017.             else
  2018.                 goto _line_err;
  2019.             --n;
  2020.         }
  2021.         if (file->fd > 0)
  2022.             total_lines += file->line_num - n;
  2023.         file->line_num = n;
  2024.         if (s1->do_debug)
  2025.             put_stabs(file->filename, N_BINCL, 0, 0, 0);
  2026.         break;
  2027.     case TOK_ERROR:
  2028.     case TOK_WARNING:
  2029.         c = tok;
  2030.         ch = file->buf_ptr[0];
  2031.         skip_spaces();
  2032.         q = buf;
  2033.         while (ch != '\n' && ch != CH_EOF) {
  2034.             if ((q - buf) < sizeof(buf) - 1)
  2035.                 *q++ = ch;
  2036.             if (ch == '\\') {
  2037.                 if (handle_stray_noerror() == 0)
  2038.                     --q;
  2039.             } else
  2040.                 inp();
  2041.         }
  2042.         *q = '\0';
  2043.         if (c == TOK_ERROR)
  2044.             tcc_error("#error %s", buf);
  2045.         else
  2046.             tcc_warning("#warning %s", buf);
  2047.         break;
  2048.     case TOK_PRAGMA:
  2049.         pragma_parse(s1);
  2050.         break;
  2051.     case TOK_LINEFEED:
  2052.         goto the_end;
  2053.     default:
  2054.         /* ignore gas line comment in an 'S' file. */
  2055.         if (saved_parse_flags & PARSE_FLAG_ASM_FILE)
  2056.             goto ignore;
  2057.         if (tok == '!' && is_bof)
  2058.             /* '!' is ignored at beginning to allow C scripts. */
  2059.             goto ignore;
  2060.         tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
  2061.     ignore:
  2062.         file->buf_ptr = parse_line_comment(file->buf_ptr,0);
  2063.         goto the_end;
  2064.     }
  2065.     /* ignore other preprocess commands or #! for C scripts */
  2066.     while (tok != TOK_LINEFEED)
  2067.         next_nomacro();
  2068.  the_end:
  2069.     parse_flags = saved_parse_flags;
  2070. }
  2071.  
  2072. /* evaluate escape codes in a string. */
  2073. static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
  2074. {
  2075.     int c, n;
  2076.     const uint8_t *p;
  2077.  
  2078.     p = buf;
  2079.     for(;;) {
  2080.         c = *p;
  2081.         if (c == '\0')
  2082.             break;
  2083.         if (c == '\\') {
  2084.             p++;
  2085.             /* escape */
  2086.             c = *p;
  2087.             switch(c) {
  2088.             case '0': case '1': case '2': case '3':
  2089.             case '4': case '5': case '6': case '7':
  2090.                 /* at most three octal digits */
  2091.                 n = c - '0';
  2092.                 p++;
  2093.                 c = *p;
  2094.                 if (isoct(c)) {
  2095.                     n = n * 8 + c - '0';
  2096.                     p++;
  2097.                     c = *p;
  2098.                     if (isoct(c)) {
  2099.                         n = n * 8 + c - '0';
  2100.                         p++;
  2101.                     }
  2102.                 }
  2103.                 c = n;
  2104.                 goto add_char_nonext;
  2105.             case 'x':
  2106.             case 'u':
  2107.             case 'U':
  2108.                 p++;
  2109.                 n = 0;
  2110.                 for(;;) {
  2111.                     c = *p;
  2112.                     if (c >= 'a' && c <= 'f')
  2113.                         c = c - 'a' + 10;
  2114.                     else if (c >= 'A' && c <= 'F')
  2115.                         c = c - 'A' + 10;
  2116.                     else if (isnum(c))
  2117.                         c = c - '0';
  2118.                     else
  2119.                         break;
  2120.                     n = n * 16 + c;
  2121.                     p++;
  2122.                 }
  2123.                 c = n;
  2124.                 goto add_char_nonext;
  2125.             case 'a':
  2126.                 c = '\a';
  2127.                 break;
  2128.             case 'b':
  2129.                 c = '\b';
  2130.                 break;
  2131.             case 'f':
  2132.                 c = '\f';
  2133.                 break;
  2134.             case 'n':
  2135.                 c = '\n';
  2136.                 break;
  2137.             case 'r':
  2138.                 c = '\r';
  2139.                 break;
  2140.             case 't':
  2141.                 c = '\t';
  2142.                 break;
  2143.             case 'v':
  2144.                 c = '\v';
  2145.                 break;
  2146.             case 'e':
  2147.                 if (!gnu_ext)
  2148.                     goto invalid_escape;
  2149.                 c = 27;
  2150.                 break;
  2151.             case '\'':
  2152.             case '\"':
  2153.             case '\\':
  2154.             case '?':
  2155.                 break;
  2156.             default:
  2157.             invalid_escape:
  2158.                 if (c >= '!' && c <= '~')
  2159.                     tcc_warning("unknown escape sequence: \'\\%c\'", c);
  2160.                 else
  2161.                     tcc_warning("unknown escape sequence: \'\\x%x\'", c);
  2162.                 break;
  2163.             }
  2164.         }
  2165.         p++;
  2166.     add_char_nonext:
  2167.         if (!is_long)
  2168.             cstr_ccat(outstr, c);
  2169.         else
  2170.             cstr_wccat(outstr, c);
  2171.     }
  2172.     /* add a trailing '\0' */
  2173.     if (!is_long)
  2174.         cstr_ccat(outstr, '\0');
  2175.     else
  2176.         cstr_wccat(outstr, '\0');
  2177. }
  2178.  
  2179. void parse_string(const char *s, int len)
  2180. {
  2181.     uint8_t buf[1000], *p = buf;
  2182.     int is_long, sep;
  2183.  
  2184.     if ((is_long = *s == 'L'))
  2185.         ++s, --len;
  2186.     sep = *s++;
  2187.     len -= 2;
  2188.     if (len >= sizeof buf)
  2189.         p = tcc_malloc(len + 1);
  2190.     memcpy(p, s, len);
  2191.     p[len] = 0;
  2192.  
  2193.     cstr_reset(&tokcstr);
  2194.     parse_escape_string(&tokcstr, p, is_long);
  2195.     if (p != buf)
  2196.         tcc_free(p);
  2197.  
  2198.     if (sep == '\'') {
  2199.         int char_size;
  2200.         /* XXX: make it portable */
  2201.         if (!is_long)
  2202.             char_size = 1;
  2203.         else
  2204.             char_size = sizeof(nwchar_t);
  2205.         if (tokcstr.size <= char_size)
  2206.             tcc_error("empty character constant");
  2207.         if (tokcstr.size > 2 * char_size)
  2208.             tcc_warning("multi-character character constant");
  2209.         if (!is_long) {
  2210.             tokc.i = *(int8_t *)tokcstr.data;
  2211.             tok = TOK_CCHAR;
  2212.         } else {
  2213.             tokc.i = *(nwchar_t *)tokcstr.data;
  2214.             tok = TOK_LCHAR;
  2215.         }
  2216.     } else {
  2217.         tokc.str.size = tokcstr.size;
  2218.         tokc.str.data = tokcstr.data;
  2219.         tokc.str.data_allocated = tokcstr.data_allocated;
  2220.         if (!is_long)
  2221.             tok = TOK_STR;
  2222.         else
  2223.             tok = TOK_LSTR;
  2224.     }
  2225. }
  2226.  
  2227. /* we use 64 bit numbers */
  2228. #define BN_SIZE 2
  2229.  
  2230. /* bn = (bn << shift) | or_val */
  2231. static void bn_lshift(unsigned int *bn, int shift, int or_val)
  2232. {
  2233.     int i;
  2234.     unsigned int v;
  2235.     for(i=0;i<BN_SIZE;i++) {
  2236.         v = bn[i];
  2237.         bn[i] = (v << shift) | or_val;
  2238.         or_val = v >> (32 - shift);
  2239.     }
  2240. }
  2241.  
  2242. static void bn_zero(unsigned int *bn)
  2243. {
  2244.     int i;
  2245.     for(i=0;i<BN_SIZE;i++) {
  2246.         bn[i] = 0;
  2247.     }
  2248. }
  2249.  
  2250. /* parse number in null terminated string 'p' and return it in the
  2251.    current token */
  2252. static void parse_number(const char *p)
  2253. {
  2254.     int b, t, shift, frac_bits, s, exp_val, ch;
  2255.     char *q;
  2256.     unsigned int bn[BN_SIZE];
  2257.     double d;
  2258.  
  2259.     /* number */
  2260.     q = token_buf;
  2261.     ch = *p++;
  2262.     t = ch;
  2263.     ch = *p++;
  2264.     *q++ = t;
  2265.     b = 10;
  2266.     if (t == '.') {
  2267.         goto float_frac_parse;
  2268.     } else if (t == '0') {
  2269.         if (ch == 'x' || ch == 'X') {
  2270.             q--;
  2271.             ch = *p++;
  2272.             b = 16;
  2273.         } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
  2274.             q--;
  2275.             ch = *p++;
  2276.             b = 2;
  2277.         }
  2278.     }
  2279.     /* parse all digits. cannot check octal numbers at this stage
  2280.        because of floating point constants */
  2281.     while (1) {
  2282.         if (ch >= 'a' && ch <= 'f')
  2283.             t = ch - 'a' + 10;
  2284.         else if (ch >= 'A' && ch <= 'F')
  2285.             t = ch - 'A' + 10;
  2286.         else if (isnum(ch))
  2287.             t = ch - '0';
  2288.         else
  2289.             break;
  2290.         if (t >= b)
  2291.             break;
  2292.         if (q >= token_buf + STRING_MAX_SIZE) {
  2293.         num_too_long:
  2294.             tcc_error("number too long");
  2295.         }
  2296.         *q++ = ch;
  2297.         ch = *p++;
  2298.     }
  2299.     if (ch == '.' ||
  2300.         ((ch == 'e' || ch == 'E') && b == 10) ||
  2301.         ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
  2302.         if (b != 10) {
  2303.             /* NOTE: strtox should support that for hexa numbers, but
  2304.                non ISOC99 libcs do not support it, so we prefer to do
  2305.                it by hand */
  2306.             /* hexadecimal or binary floats */
  2307.             /* XXX: handle overflows */
  2308.             *q = '\0';
  2309.             if (b == 16)
  2310.                 shift = 4;
  2311.             else
  2312.                 shift = 1;
  2313.             bn_zero(bn);
  2314.             q = token_buf;
  2315.             while (1) {
  2316.                 t = *q++;
  2317.                 if (t == '\0') {
  2318.                     break;
  2319.                 } else if (t >= 'a') {
  2320.                     t = t - 'a' + 10;
  2321.                 } else if (t >= 'A') {
  2322.                     t = t - 'A' + 10;
  2323.                 } else {
  2324.                     t = t - '0';
  2325.                 }
  2326.                 bn_lshift(bn, shift, t);
  2327.             }
  2328.             frac_bits = 0;
  2329.             if (ch == '.') {
  2330.                 ch = *p++;
  2331.                 while (1) {
  2332.                     t = ch;
  2333.                     if (t >= 'a' && t <= 'f') {
  2334.                         t = t - 'a' + 10;
  2335.                     } else if (t >= 'A' && t <= 'F') {
  2336.                         t = t - 'A' + 10;
  2337.                     } else if (t >= '0' && t <= '9') {
  2338.                         t = t - '0';
  2339.                     } else {
  2340.                         break;
  2341.                     }
  2342.                     if (t >= b)
  2343.                         tcc_error("invalid digit");
  2344.                     bn_lshift(bn, shift, t);
  2345.                     frac_bits += shift;
  2346.                     ch = *p++;
  2347.                 }
  2348.             }
  2349.             if (ch != 'p' && ch != 'P')
  2350.                 expect("exponent");
  2351.             ch = *p++;
  2352.             s = 1;
  2353.             exp_val = 0;
  2354.             if (ch == '+') {
  2355.                 ch = *p++;
  2356.             } else if (ch == '-') {
  2357.                 s = -1;
  2358.                 ch = *p++;
  2359.             }
  2360.             if (ch < '0' || ch > '9')
  2361.                 expect("exponent digits");
  2362.             while (ch >= '0' && ch <= '9') {
  2363.                 exp_val = exp_val * 10 + ch - '0';
  2364.                 ch = *p++;
  2365.             }
  2366.             exp_val = exp_val * s;
  2367.            
  2368.             /* now we can generate the number */
  2369.             /* XXX: should patch directly float number */
  2370.             d = (double)bn[1] * 4294967296.0 + (double)bn[0];
  2371.             d = ldexp(d, exp_val - frac_bits);
  2372.             t = toup(ch);
  2373.             if (t == 'F') {
  2374.                 ch = *p++;
  2375.                 tok = TOK_CFLOAT;
  2376.                 /* float : should handle overflow */
  2377.                 tokc.f = (float)d;
  2378.             } else if (t == 'L') {
  2379.                 ch = *p++;
  2380. #ifdef TCC_TARGET_PE
  2381.                 tok = TOK_CDOUBLE;
  2382.                 tokc.d = d;
  2383. #else
  2384.                 tok = TOK_CLDOUBLE;
  2385.                 /* XXX: not large enough */
  2386.                 tokc.ld = (long double)d;
  2387. #endif
  2388.             } else {
  2389.                 tok = TOK_CDOUBLE;
  2390.                 tokc.d = d;
  2391.             }
  2392.         } else {
  2393.             /* decimal floats */
  2394.             if (ch == '.') {
  2395.                 if (q >= token_buf + STRING_MAX_SIZE)
  2396.                     goto num_too_long;
  2397.                 *q++ = ch;
  2398.                 ch = *p++;
  2399.             float_frac_parse:
  2400.                 while (ch >= '0' && ch <= '9') {
  2401.                     if (q >= token_buf + STRING_MAX_SIZE)
  2402.                         goto num_too_long;
  2403.                     *q++ = ch;
  2404.                     ch = *p++;
  2405.                 }
  2406.             }
  2407.             if (ch == 'e' || ch == 'E') {
  2408.                 if (q >= token_buf + STRING_MAX_SIZE)
  2409.                     goto num_too_long;
  2410.                 *q++ = ch;
  2411.                 ch = *p++;
  2412.                 if (ch == '-' || ch == '+') {
  2413.                     if (q >= token_buf + STRING_MAX_SIZE)
  2414.                         goto num_too_long;
  2415.                     *q++ = ch;
  2416.                     ch = *p++;
  2417.                 }
  2418.                 if (ch < '0' || ch > '9')
  2419.                     expect("exponent digits");
  2420.                 while (ch >= '0' && ch <= '9') {
  2421.                     if (q >= token_buf + STRING_MAX_SIZE)
  2422.                         goto num_too_long;
  2423.                     *q++ = ch;
  2424.                     ch = *p++;
  2425.                 }
  2426.             }
  2427.             *q = '\0';
  2428.             t = toup(ch);
  2429.             errno = 0;
  2430.             if (t == 'F') {
  2431.                 ch = *p++;
  2432.                 tok = TOK_CFLOAT;
  2433.                 tokc.f = strtof(token_buf, NULL);
  2434.             } else if (t == 'L') {
  2435.                 ch = *p++;
  2436. #ifdef TCC_TARGET_PE
  2437.                 tok = TOK_CDOUBLE;
  2438.                 tokc.d = strtod(token_buf, NULL);
  2439. #else
  2440.                 tok = TOK_CLDOUBLE;
  2441.                 tokc.ld = strtold(token_buf, NULL);
  2442. #endif
  2443.             } else {
  2444.                 tok = TOK_CDOUBLE;
  2445.                 tokc.d = strtod(token_buf, NULL);
  2446.             }
  2447.         }
  2448.     } else {
  2449.         unsigned long long n, n1;
  2450.         int lcount, ucount, must_64bit;
  2451.         const char *p1;
  2452.  
  2453.         /* integer number */
  2454.         *q = '\0';
  2455.         q = token_buf;
  2456.         if (b == 10 && *q == '0') {
  2457.             b = 8;
  2458.             q++;
  2459.         }
  2460.         n = 0;
  2461.         while(1) {
  2462.             t = *q++;
  2463.             /* no need for checks except for base 10 / 8 errors */
  2464.             if (t == '\0')
  2465.                 break;
  2466.             else if (t >= 'a')
  2467.                 t = t - 'a' + 10;
  2468.             else if (t >= 'A')
  2469.                 t = t - 'A' + 10;
  2470.             else
  2471.                 t = t - '0';
  2472.             if (t >= b)
  2473.                 tcc_error("invalid digit");
  2474.             n1 = n;
  2475.             n = n * b + t;
  2476.             /* detect overflow */
  2477.             /* XXX: this test is not reliable */
  2478.             if (n < n1)
  2479.                 tcc_error("integer constant overflow");
  2480.         }
  2481.  
  2482.         /* Determine the characteristics (unsigned and/or 64bit) the type of
  2483.            the constant must have according to the constant suffix(es) */
  2484.         lcount = ucount = must_64bit = 0;
  2485.         p1 = p;
  2486.         for(;;) {
  2487.             t = toup(ch);
  2488.             if (t == 'L') {
  2489.                 if (lcount >= 2)
  2490.                     tcc_error("three 'l's in integer constant");
  2491.                 if (lcount && *(p - 1) != ch)
  2492.                     tcc_error("incorrect integer suffix: %s", p1);
  2493.                 lcount++;
  2494. #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
  2495.                 if (lcount == 2)
  2496. #endif
  2497.                     must_64bit = 1;
  2498.                 ch = *p++;
  2499.             } else if (t == 'U') {
  2500.                 if (ucount >= 1)
  2501.                     tcc_error("two 'u's in integer constant");
  2502.                 ucount++;
  2503.                 ch = *p++;
  2504.             } else {
  2505.                 break;
  2506.             }
  2507.         }
  2508.  
  2509.         /* Whether 64 bits are needed to hold the constant's value */
  2510.         if (n & 0xffffffff00000000LL || must_64bit) {
  2511.             tok = TOK_CLLONG;
  2512.             n1 = n >> 32;
  2513.         } else {
  2514.             tok = TOK_CINT;
  2515.             n1 = n;
  2516.         }
  2517.  
  2518.         /* Whether type must be unsigned to hold the constant's value */
  2519.         if (ucount || ((n1 >> 31) && (b != 10))) {
  2520.             if (tok == TOK_CLLONG)
  2521.                 tok = TOK_CULLONG;
  2522.             else
  2523.                 tok = TOK_CUINT;
  2524.         /* If decimal and no unsigned suffix, bump to 64 bits or throw error */
  2525.         } else if (n1 >> 31) {
  2526.             if (tok == TOK_CINT)
  2527.                 tok = TOK_CLLONG;
  2528.             else
  2529.                 tcc_error("integer constant overflow");
  2530.         }
  2531.  
  2532.         if (tok == TOK_CINT || tok == TOK_CUINT)
  2533.             tokc.i = n;
  2534.         else
  2535.             tokc.i = n;
  2536.     }
  2537.     if (ch)
  2538.         tcc_error("invalid number\n");
  2539. }
  2540.  
  2541.  
  2542. #define PARSE2(c1, tok1, c2, tok2)              \
  2543.     case c1:                                    \
  2544.         PEEKC(c, p);                            \
  2545.         if (c == c2) {                          \
  2546.             p++;                                \
  2547.             tok = tok2;                         \
  2548.         } else {                                \
  2549.             tok = tok1;                         \
  2550.         }                                       \
  2551.         break;
  2552.  
  2553. /* return next token without macro substitution */
  2554. static inline void next_nomacro1(void)
  2555. {
  2556.     int t, c, is_long, len;
  2557.     TokenSym *ts;
  2558.     uint8_t *p, *p1;
  2559.     unsigned int h;
  2560.  
  2561.     p = file->buf_ptr;
  2562.  redo_no_start:
  2563.     c = *p;
  2564. #if (__TINYC__ || __GNUC__)
  2565. #else
  2566.     if (c & 0x80)
  2567.         goto parse_ident_fast;
  2568. #endif
  2569.     switch(c) {
  2570.     case ' ':
  2571.     case '\t':
  2572.         tok = c;
  2573.         p++;
  2574.         if (parse_flags & PARSE_FLAG_SPACES)
  2575.             goto keep_tok_flags;
  2576.         while (isidnum_table[*p - CH_EOF] & IS_SPC)
  2577.             ++p;
  2578.         goto redo_no_start;
  2579.     case '\f':
  2580.     case '\v':
  2581.     case '\r':
  2582.         p++;
  2583.         goto redo_no_start;
  2584.     case '\\':
  2585.         /* first look if it is in fact an end of buffer */
  2586.         c = handle_stray1(p);
  2587.         p = file->buf_ptr;
  2588.         if (c == '\\')
  2589.             goto parse_simple;
  2590.         if (c != CH_EOF)
  2591.             goto redo_no_start;
  2592.         {
  2593.             TCCState *s1 = tcc_state;
  2594.             if ((parse_flags & PARSE_FLAG_LINEFEED)
  2595.                 && !(tok_flags & TOK_FLAG_EOF)) {
  2596.                 tok_flags |= TOK_FLAG_EOF;
  2597.                 tok = TOK_LINEFEED;
  2598.                 goto keep_tok_flags;
  2599.             } else if (!(parse_flags & PARSE_FLAG_PREPROCESS)) {
  2600.                 tok = TOK_EOF;
  2601.             } else if (s1->ifdef_stack_ptr != file->ifdef_stack_ptr) {
  2602.                 tcc_error("missing #endif");
  2603.             } else if (s1->include_stack_ptr == s1->include_stack) {
  2604.                 /* no include left : end of file. */
  2605.                 tok = TOK_EOF;
  2606.             } else {
  2607.                 tok_flags &= ~TOK_FLAG_EOF;
  2608.                 /* pop include file */
  2609.                
  2610.                 /* test if previous '#endif' was after a #ifdef at
  2611.                    start of file */
  2612.                 if (tok_flags & TOK_FLAG_ENDIF) {
  2613. #ifdef INC_DEBUG
  2614.                     printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
  2615. #endif
  2616.                     add_cached_include(s1, file->filename, file->ifndef_macro_saved);
  2617.                     tok_flags &= ~TOK_FLAG_ENDIF;
  2618.                 }
  2619.  
  2620.                 /* add end of include file debug info */
  2621.                 if (tcc_state->do_debug) {
  2622.                     put_stabd(N_EINCL, 0, 0);
  2623.                 }
  2624.                 /* pop include stack */
  2625.                 tcc_close();
  2626.                 s1->include_stack_ptr--;
  2627.                 p = file->buf_ptr;
  2628.                 goto redo_no_start;
  2629.             }
  2630.         }
  2631.         break;
  2632.  
  2633.     case '\n':
  2634.         file->line_num++;
  2635.         tok_flags |= TOK_FLAG_BOL;
  2636.         p++;
  2637. maybe_newline:
  2638.         if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
  2639.             goto redo_no_start;
  2640.         tok = TOK_LINEFEED;
  2641.         goto keep_tok_flags;
  2642.  
  2643.     case '#':
  2644.         /* XXX: simplify */
  2645.         PEEKC(c, p);
  2646.         if ((tok_flags & TOK_FLAG_BOL) &&
  2647.             (parse_flags & PARSE_FLAG_PREPROCESS)) {
  2648.             file->buf_ptr = p;
  2649.             preprocess(tok_flags & TOK_FLAG_BOF);
  2650.             p = file->buf_ptr;
  2651.             goto maybe_newline;
  2652.         } else {
  2653.             if (c == '#') {
  2654.                 p++;
  2655.                 tok = TOK_TWOSHARPS;
  2656.             } else {
  2657.                 if (parse_flags & PARSE_FLAG_ASM_FILE) {
  2658.                     p = parse_line_comment(p - 1,0);
  2659.                     goto redo_no_start;
  2660.                 } else {
  2661.                     tok = '#';
  2662.                 }
  2663.             }
  2664.         }
  2665.         break;
  2666.    
  2667.     /* dollar is allowed to start identifiers when not parsing asm */
  2668.     case '$':
  2669.         if (!(isidnum_table[c - CH_EOF] & IS_ID)
  2670.          || (parse_flags & PARSE_FLAG_ASM_FILE))
  2671.             goto parse_simple;
  2672.  
  2673. #if (__TINYC__ || __GNUC__)
  2674.     case 'a' ... 'z':
  2675.     case 'A' ... 'K':
  2676.     case 'M' ... 'Z':
  2677.     case '_':
  2678.     case 0x80 ... 0xFF:
  2679. #else
  2680.     case 'a': case 'b': case 'c': case 'd':
  2681.     case 'e': case 'f': case 'g': case 'h':
  2682.     case 'i': case 'j': case 'k': case 'l':
  2683.     case 'm': case 'n': case 'o': case 'p':
  2684.     case 'q': case 'r': case 's': case 't':
  2685.     case 'u': case 'v': case 'w': case 'x':
  2686.     case 'y': case 'z':
  2687.     case 'A': case 'B': case 'C': case 'D':
  2688.     case 'E': case 'F': case 'G': case 'H':
  2689.     case 'I': case 'J': case 'K':
  2690.     case 'M': case 'N': case 'O': case 'P':
  2691.     case 'Q': case 'R': case 'S': case 'T':
  2692.     case 'U': case 'V': case 'W': case 'X':
  2693.     case 'Y': case 'Z':
  2694.     case '_':
  2695. #endif
  2696.     parse_ident_fast:
  2697.         p1 = p;
  2698.         h = TOK_HASH_INIT;
  2699.         h = TOK_HASH_FUNC(h, c);
  2700.         while (c = *++p, isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
  2701.             h = TOK_HASH_FUNC(h, c);
  2702.         len = p - p1;
  2703.         if (c != '\\') {
  2704.             TokenSym **pts;
  2705.  
  2706.             /* fast case : no stray found, so we have the full token
  2707.                and we have already hashed it */
  2708.             h &= (TOK_HASH_SIZE - 1);
  2709.             pts = &hash_ident[h];
  2710.             for(;;) {
  2711.                 ts = *pts;
  2712.                 if (!ts)
  2713.                     break;
  2714.                 if (ts->len == len && !memcmp(ts->str, p1, len))
  2715.                     goto token_found;
  2716.                 pts = &(ts->hash_next);
  2717.             }
  2718.             ts = tok_alloc_new(pts, (char *) p1, len);
  2719.         token_found: ;
  2720.         } else {
  2721.             /* slower case */
  2722.             cstr_reset(&tokcstr);
  2723.             cstr_cat(&tokcstr, p1, len);
  2724.             p--;
  2725.             PEEKC(c, p);
  2726.         parse_ident_slow:
  2727.             while (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
  2728.             {
  2729.                 cstr_ccat(&tokcstr, c);
  2730.                 PEEKC(c, p);
  2731.             }
  2732.             ts = tok_alloc(tokcstr.data, tokcstr.size);
  2733.         }
  2734.         tok = ts->tok;
  2735.         break;
  2736.     case 'L':
  2737.         t = p[1];
  2738.         if (t != '\\' && t != '\'' && t != '\"') {
  2739.             /* fast case */
  2740.             goto parse_ident_fast;
  2741.         } else {
  2742.             PEEKC(c, p);
  2743.             if (c == '\'' || c == '\"') {
  2744.                 is_long = 1;
  2745.                 goto str_const;
  2746.             } else {
  2747.                 cstr_reset(&tokcstr);
  2748.                 cstr_ccat(&tokcstr, 'L');
  2749.                 goto parse_ident_slow;
  2750.             }
  2751.         }
  2752.         break;
  2753.  
  2754.     case '0': case '1': case '2': case '3':
  2755.     case '4': case '5': case '6': case '7':
  2756.     case '8': case '9':
  2757.         cstr_reset(&tokcstr);
  2758.         /* after the first digit, accept digits, alpha, '.' or sign if
  2759.            prefixed by 'eEpP' */
  2760.     parse_num:
  2761.         for(;;) {
  2762.             t = c;
  2763.             cstr_ccat(&tokcstr, c);
  2764.             PEEKC(c, p);
  2765.             if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
  2766.                   || c == '.'
  2767.                   || ((c == '+' || c == '-')
  2768.                       && (t == 'e' || t == 'E' || t == 'p' || t == 'P')
  2769.                       )))
  2770.                 break;
  2771.         }
  2772.         /* We add a trailing '\0' to ease parsing */
  2773.         cstr_ccat(&tokcstr, '\0');
  2774.         tokc.str.size = tokcstr.size;
  2775.         tokc.str.data = tokcstr.data;
  2776.         tokc.str.data_allocated = tokcstr.data_allocated;
  2777.         tok = TOK_PPNUM;
  2778.         break;
  2779.  
  2780.     case '.':
  2781.         /* special dot handling because it can also start a number */
  2782.         PEEKC(c, p);
  2783.         if (isnum(c)) {
  2784.             cstr_reset(&tokcstr);
  2785.             cstr_ccat(&tokcstr, '.');
  2786.             goto parse_num;
  2787.         } else if ((parse_flags & PARSE_FLAG_ASM_FILE)
  2788.                    && (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))) {
  2789.             *--p = c = '.';
  2790.             goto parse_ident_fast;
  2791.         } else if (c == '.') {
  2792.             PEEKC(c, p);
  2793.             if (c == '.') {
  2794.                 p++;
  2795.                 tok = TOK_DOTS;
  2796.             } else {
  2797.                 *--p = '.'; /* may underflow into file->unget[] */
  2798.                 tok = '.';
  2799.             }
  2800.         } else {
  2801.             tok = '.';
  2802.         }
  2803.         break;
  2804.     case '\'':
  2805.     case '\"':
  2806.         is_long = 0;
  2807.     str_const:
  2808.         cstr_reset(&tokcstr);
  2809.         if (is_long)
  2810.             cstr_ccat(&tokcstr, 'L');
  2811.         cstr_ccat(&tokcstr, c);
  2812.         p = parse_pp_string(p, c, &tokcstr);
  2813.         cstr_ccat(&tokcstr, c);
  2814.         cstr_ccat(&tokcstr, '\0');
  2815.         tokc.str.size = tokcstr.size;
  2816.         tokc.str.data = tokcstr.data;
  2817.         tokc.str.data_allocated = tokcstr.data_allocated;
  2818.         tok = TOK_PPSTR;
  2819.         break;
  2820.  
  2821.     case '<':
  2822.         PEEKC(c, p);
  2823.         if (c == '=') {
  2824.             p++;
  2825.             tok = TOK_LE;
  2826.         } else if (c == '<') {
  2827.             PEEKC(c, p);
  2828.             if (c == '=') {
  2829.                 p++;
  2830.                 tok = TOK_A_SHL;
  2831.             } else {
  2832.                 tok = TOK_SHL;
  2833.             }
  2834.         } else {
  2835.             tok = TOK_LT;
  2836.         }
  2837.         break;
  2838.     case '>':
  2839.         PEEKC(c, p);
  2840.         if (c == '=') {
  2841.             p++;
  2842.             tok = TOK_GE;
  2843.         } else if (c == '>') {
  2844.             PEEKC(c, p);
  2845.             if (c == '=') {
  2846.                 p++;
  2847.                 tok = TOK_A_SAR;
  2848.             } else {
  2849.                 tok = TOK_SAR;
  2850.             }
  2851.         } else {
  2852.             tok = TOK_GT;
  2853.         }
  2854.         break;
  2855.        
  2856.     case '&':
  2857.         PEEKC(c, p);
  2858.         if (c == '&') {
  2859.             p++;
  2860.             tok = TOK_LAND;
  2861.         } else if (c == '=') {
  2862.             p++;
  2863.             tok = TOK_A_AND;
  2864.         } else {
  2865.             tok = '&';
  2866.         }
  2867.         break;
  2868.        
  2869.     case '|':
  2870.         PEEKC(c, p);
  2871.         if (c == '|') {
  2872.             p++;
  2873.             tok = TOK_LOR;
  2874.         } else if (c == '=') {
  2875.             p++;
  2876.             tok = TOK_A_OR;
  2877.         } else {
  2878.             tok = '|';
  2879.         }
  2880.         break;
  2881.  
  2882.     case '+':
  2883.         PEEKC(c, p);
  2884.         if (c == '+') {
  2885.             p++;
  2886.             tok = TOK_INC;
  2887.         } else if (c == '=') {
  2888.             p++;
  2889.             tok = TOK_A_ADD;
  2890.         } else {
  2891.             tok = '+';
  2892.         }
  2893.         break;
  2894.        
  2895.     case '-':
  2896.         PEEKC(c, p);
  2897.         if (c == '-') {
  2898.             p++;
  2899.             tok = TOK_DEC;
  2900.         } else if (c == '=') {
  2901.             p++;
  2902.             tok = TOK_A_SUB;
  2903.         } else if (c == '>') {
  2904.             p++;
  2905.             tok = TOK_ARROW;
  2906.         } else {
  2907.             tok = '-';
  2908.         }
  2909.         break;
  2910.  
  2911.     PARSE2('!', '!', '=', TOK_NE)
  2912.     PARSE2('=', '=', '=', TOK_EQ)
  2913.     PARSE2('*', '*', '=', TOK_A_MUL)
  2914.     PARSE2('%', '%', '=', TOK_A_MOD)
  2915.     PARSE2('^', '^', '=', TOK_A_XOR)
  2916.        
  2917.         /* comments or operator */
  2918.     case '/':
  2919.         PEEKC(c, p);
  2920.         if (c == '*') {
  2921.             p = parse_comment(p,0);
  2922.             /* comments replaced by a blank */
  2923.             tok = ' ';
  2924.             if (tcc_state->option_C)
  2925.                 goto redo_no_start;
  2926.             goto keep_tok_flags;
  2927.         } else if (c == '/') {
  2928.             p = parse_line_comment(p,0);
  2929.             tok = ' ';
  2930.             if (tcc_state->option_C)
  2931.                 goto redo_no_start;
  2932.             goto keep_tok_flags;
  2933.         } else if (c == '=') {
  2934.             p++;
  2935.             tok = TOK_A_DIV;
  2936.         } else {
  2937.             tok = '/';
  2938.         }
  2939.         break;
  2940.        
  2941.         /* simple tokens */
  2942.     case '(':
  2943.     case ')':
  2944.     case '[':
  2945.     case ']':
  2946.     case '{':
  2947.     case '}':
  2948.     case ',':
  2949.     case ';':
  2950.     case ':':
  2951.     case '?':
  2952.     case '~':
  2953.     case '@': /* only used in assembler */
  2954.     parse_simple:
  2955.         tok = c;
  2956.         p++;
  2957.         break;
  2958.     default:
  2959.         if (parse_flags & PARSE_FLAG_ASM_FILE)
  2960.             goto parse_simple;
  2961.         tcc_error("unrecognized character \\x%02x", c);
  2962.         break;
  2963.     }
  2964.     tok_flags = 0;
  2965. keep_tok_flags:
  2966.     file->buf_ptr = p;
  2967. #if defined(PARSE_DEBUG)
  2968.     printf("token = %s\n", get_tok_str(tok, &tokc));
  2969. #endif
  2970. }
  2971.  
  2972. /* return next token without macro substitution. Can read input from
  2973.    macro_ptr buffer */
  2974. static void next_nomacro_spc(void)
  2975. {
  2976.     if (macro_ptr) {
  2977.     redo:
  2978.         tok = *macro_ptr;
  2979.         if (tok) {
  2980.             TOK_GET(&tok, &macro_ptr, &tokc);
  2981.             if (tok == TOK_LINENUM) {
  2982.                 file->line_num = tokc.i;
  2983.                 goto redo;
  2984.             }
  2985.         }
  2986.     } else {
  2987.         next_nomacro1();
  2988.     }
  2989. }
  2990.  
  2991. ST_FUNC void next_nomacro(void)
  2992. {
  2993.     do {
  2994.         next_nomacro_spc();
  2995.     } while (tok < 256 && (isidnum_table[tok - CH_EOF] & IS_SPC));
  2996. }
  2997.  
  2998.  
  2999. static void macro_subst(
  3000.     TokenString *tok_str,
  3001.     Sym **nested_list,
  3002.     const int *macro_str,
  3003.     int can_read_stream
  3004.     );
  3005.  
  3006. /* substitute arguments in replacement lists in macro_str by the values in
  3007.    args (field d) and return allocated string */
  3008. static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
  3009. {
  3010.     int t, t0, t1, spc;
  3011.     const int *st;
  3012.     Sym *s;
  3013.     CValue cval;
  3014.     TokenString str;
  3015.     CString cstr;
  3016.  
  3017.     tok_str_new(&str);
  3018.     t0 = t1 = 0;
  3019.     while(1) {
  3020.         TOK_GET(&t, &macro_str, &cval);
  3021.         if (!t)
  3022.             break;
  3023.         if (t == '#') {
  3024.             /* stringize */
  3025.             TOK_GET(&t, &macro_str, &cval);
  3026.             if (!t)
  3027.                 goto bad_stringy;
  3028.             s = sym_find2(args, t);
  3029.             if (s) {
  3030.                 cstr_new(&cstr);
  3031.                 cstr_ccat(&cstr, '\"');
  3032.                 st = s->d;
  3033.                 spc = 0;
  3034.                 while (*st) {
  3035.                     TOK_GET(&t, &st, &cval);
  3036.                     if (t != TOK_PLCHLDR
  3037.                      && t != TOK_NOSUBST
  3038.                      && 0 == check_space(t, &spc)) {
  3039.                         const char *s = get_tok_str(t, &cval);
  3040.                         while (*s) {
  3041.                             if (t == TOK_PPSTR && *s != '\'')
  3042.                                 add_char(&cstr, *s);
  3043.                             else
  3044.                                 cstr_ccat(&cstr, *s);
  3045.                             ++s;
  3046.                         }
  3047.                     }
  3048.                 }
  3049.                 cstr.size -= spc;
  3050.                 cstr_ccat(&cstr, '\"');
  3051.                 cstr_ccat(&cstr, '\0');
  3052. #ifdef PP_DEBUG
  3053.                 printf("\nstringize: <%s>\n", (char *)cstr.data);
  3054. #endif
  3055.                 /* add string */
  3056.                 cval.str.size = cstr.size;
  3057.                 cval.str.data = cstr.data;
  3058.                 cval.str.data_allocated = cstr.data_allocated;
  3059.                 tok_str_add2(&str, TOK_PPSTR, &cval);
  3060.                 cstr_free(&cstr);
  3061.             } else {
  3062.         bad_stringy:
  3063.                 expect("macro parameter after '#'");
  3064.             }
  3065.         } else if (t >= TOK_IDENT) {
  3066.             s = sym_find2(args, t);
  3067.             if (s) {
  3068.                 int l0 = str.len;
  3069.                 st = s->d;
  3070.                 /* if '##' is present before or after, no arg substitution */
  3071.                 if (*macro_str == TOK_TWOSHARPS || t1 == TOK_TWOSHARPS) {
  3072.                     /* special case for var arg macros : ## eats the ','
  3073.                        if empty VA_ARGS variable. */
  3074.                     if (t1 == TOK_TWOSHARPS && t0 == ',' && gnu_ext && s->type.t) {
  3075.                         if (*st == 0) {
  3076.                             /* suppress ',' '##' */
  3077.                             str.len -= 2;
  3078.                         } else {
  3079.                             /* suppress '##' and add variable */
  3080.                             str.len--;
  3081.                             goto add_var;
  3082.                         }
  3083.                     } else {
  3084.                         for(;;) {
  3085.                             int t1;
  3086.                             TOK_GET(&t1, &st, &cval);
  3087.                             if (!t1)
  3088.                                 break;
  3089.                             tok_str_add2(&str, t1, &cval);
  3090.                         }
  3091.                     }
  3092.  
  3093.                 } else {
  3094.             add_var:
  3095.                     /* NOTE: the stream cannot be read when macro
  3096.                        substituing an argument */
  3097.                     macro_subst(&str, nested_list, st, 0);
  3098.                 }
  3099.                 if (str.len == l0) /* exanded to empty string */
  3100.                     tok_str_add(&str, TOK_PLCHLDR);
  3101.             } else {
  3102.                 tok_str_add(&str, t);
  3103.             }
  3104.         } else {
  3105.             tok_str_add2(&str, t, &cval);
  3106.         }
  3107.         t0 = t1, t1 = t;
  3108.     }
  3109.     tok_str_add(&str, 0);
  3110.     return str.str;
  3111. }
  3112.  
  3113. static char const ab_month_name[12][4] =
  3114. {
  3115.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  3116.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  3117. };
  3118.  
  3119. /* peek or read [ws_str == NULL] next token from function macro call,
  3120.    walking up macro levels up to the file if necessary */
  3121. static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *ws_str)
  3122. {
  3123.     int t;
  3124.     const int *p;
  3125.     Sym *sa;
  3126.  
  3127.     for (;;) {
  3128.         if (macro_ptr) {
  3129.             p = macro_ptr, t = *p;
  3130.             if (ws_str) {
  3131.                 while (is_space(t) || TOK_LINEFEED == t)
  3132.                     tok_str_add(ws_str, t), t = *++p;
  3133.             }
  3134.             if (t == 0 && can_read_stream) {
  3135.                 end_macro();
  3136.                 /* also, end of scope for nested defined symbol */
  3137.                 sa = *nested_list;
  3138.                 while (sa && sa->v == 0)
  3139.                     sa = sa->prev;
  3140.                 if (sa)
  3141.                     sa->v = 0;
  3142.                 continue;
  3143.             }
  3144.         } else {
  3145.             ch = handle_eob();
  3146.             if (ws_str) {
  3147.                 while (is_space(ch) || ch == '\n' || ch == '/') {
  3148.                     if (ch == '/') {
  3149.                         int c;
  3150.                         uint8_t *p = file->buf_ptr;
  3151.                         PEEKC(c, p);
  3152.                         if (c == '*') {
  3153.                             p = parse_comment(p,0);
  3154.                             file->buf_ptr = p - 1;
  3155.                         } else if (c == '/') {
  3156.                             p = parse_line_comment(p,0);
  3157.                             file->buf_ptr = p - 1;
  3158.                         } else
  3159.                             break;
  3160.                         ch = ' ';
  3161.                     }
  3162.                     tok_str_add(ws_str, ch);
  3163.                     cinp();
  3164.                 }
  3165.             }
  3166.             t = ch;
  3167.         }
  3168.  
  3169.         if (ws_str)
  3170.             return t;
  3171.         next_nomacro_spc();
  3172.         return tok;
  3173.     }
  3174. }
  3175.  
  3176. /* do macro substitution of current token with macro 's' and add
  3177.    result to (tok_str,tok_len). 'nested_list' is the list of all
  3178.    macros we got inside to avoid recursing. Return non zero if no
  3179.    substitution needs to be done */
  3180. static int macro_subst_tok(
  3181.     TokenString *tok_str,
  3182.     Sym **nested_list,
  3183.     Sym *s,
  3184.     int can_read_stream)
  3185. {
  3186.     Sym *args, *sa, *sa1;
  3187.     int parlevel, *mstr, t, t1, spc;
  3188.     TokenString str;
  3189.     char *cstrval;
  3190.     CValue cval;
  3191.     CString cstr;
  3192.     char buf[32];
  3193.    
  3194.     /* if symbol is a macro, prepare substitution */
  3195.     /* special macros */
  3196.     if (tok == TOK___LINE__) {
  3197.         snprintf(buf, sizeof(buf), "%d", file->line_num);
  3198.         cstrval = buf;
  3199.         t1 = TOK_PPNUM;
  3200.         goto add_cstr1;
  3201.     } else if (tok == TOK___FILE__) {
  3202.         cstrval = file->filename;
  3203.         goto add_cstr;
  3204.     } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
  3205.         time_t ti;
  3206.         struct tm *tm;
  3207.  
  3208.         time(&ti);
  3209.         tm = localtime(&ti);
  3210.         if (tok == TOK___DATE__) {
  3211.             snprintf(buf, sizeof(buf), "%s %2d %d",
  3212.                      ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
  3213.         } else {
  3214.             snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
  3215.                      tm->tm_hour, tm->tm_min, tm->tm_sec);
  3216.         }
  3217.         cstrval = buf;
  3218.     add_cstr:
  3219.         t1 = TOK_STR;
  3220.     add_cstr1:
  3221.         cstr_new(&cstr);
  3222.         cstr_cat(&cstr, cstrval, 0);
  3223.         cval.str.size = cstr.size;
  3224.         cval.str.data = cstr.data;
  3225.         cval.str.data_allocated = cstr.data_allocated;
  3226.         tok_str_add2(tok_str, t1, &cval);
  3227.         cstr_free(&cstr);
  3228.     } else {
  3229.         int saved_parse_flags = parse_flags;
  3230.  
  3231.         mstr = s->d;
  3232.         if (s->type.t == MACRO_FUNC) {
  3233.             /* whitespace between macro name and argument list */
  3234.             TokenString ws_str;
  3235.             tok_str_new(&ws_str);
  3236.  
  3237.             spc = 0;
  3238.             parse_flags |= PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED
  3239.                 | PARSE_FLAG_ACCEPT_STRAYS;
  3240.  
  3241.             /* get next token from argument stream */
  3242.             t = next_argstream(nested_list, can_read_stream, &ws_str);
  3243.             if (t != '(') {
  3244.                 /* not a macro substitution after all, restore the
  3245.                  * macro token plus all whitespace we've read.
  3246.                  * whitespace is intentionally not merged to preserve
  3247.                  * newlines. */
  3248.                 parse_flags = saved_parse_flags;
  3249.                 tok_str_add(tok_str, tok);
  3250.                 if (parse_flags & PARSE_FLAG_SPACES) {
  3251.                     int i;
  3252.                     for (i = 0; i < ws_str.len; i++)
  3253.                         tok_str_add(tok_str, ws_str.str[i]);
  3254.                 }
  3255.                 tok_str_free(ws_str.str);
  3256.                 return 0;
  3257.             } else {
  3258.                 tok_str_free(ws_str.str);
  3259.             }
  3260.             next_nomacro(); /* eat '(' */
  3261.  
  3262.             /* argument macro */
  3263.             args = NULL;
  3264.             sa = s->next;
  3265.             /* NOTE: empty args are allowed, except if no args */
  3266.             for(;;) {
  3267.                 do {
  3268.                     next_argstream(nested_list, can_read_stream, NULL);
  3269.                 } while (is_space(tok) || TOK_LINEFEED == tok);
  3270.     empty_arg:
  3271.                 /* handle '()' case */
  3272.                 if (!args && !sa && tok == ')')
  3273.                     break;
  3274.                 if (!sa)
  3275.                     tcc_error("macro '%s' used with too many args",
  3276.                           get_tok_str(s->v, 0));
  3277.                 tok_str_new(&str);
  3278.                 parlevel = spc = 0;
  3279.                 /* NOTE: non zero sa->t indicates VA_ARGS */
  3280.                 while ((parlevel > 0 ||
  3281.                         (tok != ')' &&
  3282.                          (tok != ',' || sa->type.t)))) {
  3283.                     if (tok == TOK_EOF || tok == 0)
  3284.                         break;
  3285.                     if (tok == '(')
  3286.                         parlevel++;
  3287.                     else if (tok == ')')
  3288.                         parlevel--;
  3289.                     if (tok == TOK_LINEFEED)
  3290.                         tok = ' ';
  3291.                     if (!check_space(tok, &spc))
  3292.                         tok_str_add2(&str, tok, &tokc);
  3293.                     next_argstream(nested_list, can_read_stream, NULL);
  3294.                 }
  3295.                 if (parlevel)
  3296.                     expect(")");
  3297.                 str.len -= spc;
  3298.                 tok_str_add(&str, 0);
  3299.                 sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
  3300.                 sa1->d = str.str;
  3301.                 sa = sa->next;
  3302.                 if (tok == ')') {
  3303.                     /* special case for gcc var args: add an empty
  3304.                        var arg argument if it is omitted */
  3305.                     if (sa && sa->type.t && gnu_ext)
  3306.                         goto empty_arg;
  3307.                     break;
  3308.                 }
  3309.                 if (tok != ',')
  3310.                     expect(",");
  3311.             }
  3312.             if (sa) {
  3313.                 tcc_error("macro '%s' used with too few args",
  3314.                       get_tok_str(s->v, 0));
  3315.             }
  3316.  
  3317.             parse_flags = saved_parse_flags;
  3318.  
  3319.             /* now subst each arg */
  3320.             mstr = macro_arg_subst(nested_list, mstr, args);
  3321.             /* free memory */
  3322.             sa = args;
  3323.             while (sa) {
  3324.                 sa1 = sa->prev;
  3325.                 tok_str_free(sa->d);
  3326.                 sym_free(sa);
  3327.                 sa = sa1;
  3328.             }
  3329.         }
  3330.  
  3331.         sym_push2(nested_list, s->v, 0, 0);
  3332.         parse_flags = saved_parse_flags;
  3333.         macro_subst(tok_str, nested_list, mstr, can_read_stream | 2);
  3334.  
  3335.         /* pop nested defined symbol */
  3336.         sa1 = *nested_list;
  3337.         *nested_list = sa1->prev;
  3338.         sym_free(sa1);
  3339.         if (mstr != s->d)
  3340.             tok_str_free(mstr);
  3341.     }
  3342.     return 0;
  3343. }
  3344.  
  3345. int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
  3346. {
  3347.     CString cstr;
  3348.     int n;
  3349.  
  3350.     cstr_new(&cstr);
  3351.     if (t1 != TOK_PLCHLDR)
  3352.         cstr_cat(&cstr, get_tok_str(t1, v1), -1);
  3353.     n = cstr.size;
  3354.     if (t2 != TOK_PLCHLDR)
  3355.         cstr_cat(&cstr, get_tok_str(t2, v2), -1);
  3356.     cstr_ccat(&cstr, '\0');
  3357.  
  3358.     tcc_open_bf(tcc_state, ":paste:", cstr.size);
  3359.     memcpy(file->buffer, cstr.data, cstr.size);
  3360.     for (;;) {
  3361.         next_nomacro1();
  3362.         if (0 == *file->buf_ptr)
  3363.             break;
  3364.         if (is_space(tok))
  3365.             continue;
  3366.         tcc_warning("pasting <%.*s> and <%s> does not give a valid preprocessing token",
  3367.             n, cstr.data, (char*)cstr.data + n);
  3368.         break;
  3369.     }
  3370.     tcc_close();
  3371.  
  3372.     //printf("paste <%s>\n", (char*)cstr.data);
  3373.     cstr_free(&cstr);
  3374.     return 0;
  3375. }
  3376.  
  3377. /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
  3378.    return the resulting string (which must be freed). */
  3379. static inline int *macro_twosharps(const int *ptr0)
  3380. {
  3381.     int t;
  3382.     CValue cval;
  3383.     TokenString macro_str1;
  3384.     int start_of_nosubsts = -1;
  3385.     const int *ptr;
  3386.  
  3387.     /* we search the first '##' */
  3388.     for (ptr = ptr0;;) {
  3389.         TOK_GET(&t, &ptr, &cval);
  3390.         if (t == TOK_TWOSHARPS)
  3391.             break;
  3392.         if (t == 0)
  3393.             return NULL;
  3394.     }
  3395.  
  3396.     tok_str_new(&macro_str1);
  3397.  
  3398.     //tok_print(" $$$", ptr0);
  3399.     for (ptr = ptr0;;) {
  3400.         TOK_GET(&t, &ptr, &cval);
  3401.         if (t == 0)
  3402.             break;
  3403.         if (t == TOK_TWOSHARPS)
  3404.             continue;
  3405.         while (*ptr == TOK_TWOSHARPS) {
  3406.             int t1; CValue cv1;
  3407.             /* given 'a##b', remove nosubsts preceding 'a' */
  3408.             if (start_of_nosubsts >= 0)
  3409.                 macro_str1.len = start_of_nosubsts;
  3410.             /* given 'a##b', remove nosubsts preceding 'b' */
  3411.             while ((t1 = *++ptr) == TOK_NOSUBST)
  3412.                 ;
  3413.             if (t1 && t1 != TOK_TWOSHARPS
  3414.                 && t1 != ':') /* 'a##:' don't build a new token */
  3415.             {
  3416.                 TOK_GET(&t1, &ptr, &cv1);
  3417.                 if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) {
  3418.                     paste_tokens(t, &cval, t1, &cv1);
  3419.                     t = tok, cval = tokc;
  3420.                 }
  3421.             }
  3422.         }
  3423.         if (t == TOK_NOSUBST) {
  3424.             if (start_of_nosubsts < 0)
  3425.                 start_of_nosubsts = macro_str1.len;
  3426.         } else {
  3427.             start_of_nosubsts = -1;
  3428.         }
  3429.         tok_str_add2(&macro_str1, t, &cval);
  3430.     }
  3431.     tok_str_add(&macro_str1, 0);
  3432.     //tok_print(" ###", macro_str1.str);
  3433.     return macro_str1.str;
  3434. }
  3435.  
  3436. /* do macro substitution of macro_str and add result to
  3437.    (tok_str,tok_len). 'nested_list' is the list of all macros we got
  3438.    inside to avoid recursing. */
  3439. static void macro_subst(
  3440.     TokenString *tok_str,
  3441.     Sym **nested_list,
  3442.     const int *macro_str,
  3443.     int can_read_stream
  3444.     )
  3445. {
  3446.     Sym *s;
  3447.     const int *ptr;
  3448.     int t, spc, nosubst;
  3449.     CValue cval;
  3450.     int *macro_str1 = NULL;
  3451.    
  3452.     /* first scan for '##' operator handling */
  3453.     ptr = macro_str;
  3454.     spc = nosubst = 0;
  3455.  
  3456.     /* first scan for '##' operator handling */
  3457.     if (can_read_stream & 1) {
  3458.         macro_str1 = macro_twosharps(ptr);
  3459.         if (macro_str1)
  3460.             ptr = macro_str1;
  3461.     }
  3462.  
  3463.     while (1) {
  3464.         TOK_GET(&t, &ptr, &cval);
  3465.         if (t == 0)
  3466.             break;
  3467.  
  3468.         if (t >= TOK_IDENT && 0 == nosubst) {
  3469.             s = define_find(t);
  3470.             if (s == NULL)
  3471.                 goto no_subst;
  3472.  
  3473.             /* if nested substitution, do nothing */
  3474.             if (sym_find2(*nested_list, t)) {
  3475.                 /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */
  3476.                 tok_str_add2(tok_str, TOK_NOSUBST, NULL);
  3477.                 goto no_subst;
  3478.             }
  3479.  
  3480.             {
  3481.                 TokenString str;
  3482.                 str.str = (int*)ptr;
  3483.                 begin_macro(&str, 2);
  3484.  
  3485.                 tok = t;
  3486.                 macro_subst_tok(tok_str, nested_list, s, can_read_stream);
  3487.  
  3488.                 if (str.alloc == 3) {
  3489.                     /* already finished by reading function macro arguments */
  3490.                     break;
  3491.                 }
  3492.  
  3493.                 ptr = macro_ptr;
  3494.                 end_macro ();
  3495.             }
  3496.  
  3497.             spc = (tok_str->len &&
  3498.                    is_space(tok_last(tok_str->str,
  3499.                                      tok_str->str + tok_str->len)));
  3500.  
  3501.         } else {
  3502.  
  3503.             if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
  3504.                 tcc_error("stray '\\' in program");
  3505.  
  3506. no_subst:
  3507.             if (!check_space(t, &spc))
  3508.                 tok_str_add2(tok_str, t, &cval);
  3509.             nosubst = 0;
  3510.             if (t == TOK_NOSUBST)
  3511.                 nosubst = 1;
  3512.         }
  3513.     }
  3514.     if (macro_str1)
  3515.         tok_str_free(macro_str1);
  3516.  
  3517. }
  3518.  
  3519. /* return next token with macro substitution */
  3520. ST_FUNC void next(void)
  3521. {
  3522.  redo:
  3523.     if (parse_flags & PARSE_FLAG_SPACES)
  3524.         next_nomacro_spc();
  3525.     else
  3526.         next_nomacro();
  3527.  
  3528.     if (macro_ptr) {
  3529.         if (tok == TOK_NOSUBST || tok == TOK_PLCHLDR) {
  3530.         /* discard preprocessor markers */
  3531.             goto redo;
  3532.         } else if (tok == 0) {
  3533.             /* end of macro or unget token string */
  3534.             end_macro();
  3535.             goto redo;
  3536.         }
  3537.     } else if (tok >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) {
  3538.         Sym *s;
  3539.         /* if reading from file, try to substitute macros */
  3540.         s = define_find(tok);
  3541.         if (s) {
  3542.             Sym *nested_list = NULL;
  3543.             tokstr_buf.len = 0;
  3544.             nested_list = NULL;
  3545.             macro_subst_tok(&tokstr_buf, &nested_list, s, 1);
  3546.             tok_str_add(&tokstr_buf, 0);
  3547.             begin_macro(&tokstr_buf, 2);
  3548.             goto redo;
  3549.         }
  3550.     }
  3551.     /* convert preprocessor tokens into C tokens */
  3552.     if (tok == TOK_PPNUM) {
  3553.         if  (parse_flags & PARSE_FLAG_TOK_NUM)
  3554.             parse_number((char *)tokc.str.data);
  3555.     } else if (tok == TOK_PPSTR) {
  3556.         if (parse_flags & PARSE_FLAG_TOK_STR)
  3557.             parse_string((char *)tokc.str.data, tokc.str.size - 1);
  3558.     }
  3559. }
  3560.  
  3561. /* push back current token and set current token to 'last_tok'. Only
  3562.    identifier case handled for labels. */
  3563. ST_INLN void unget_tok(int last_tok)
  3564. {
  3565.     TokenString *str = tcc_malloc(sizeof *str);
  3566.     tok_str_new(str);
  3567.     tok_str_add2(str, tok, &tokc);
  3568.     tok_str_add(str, 0);
  3569.     begin_macro(str, 1);
  3570.     tok = last_tok;
  3571. }
  3572.  
  3573. /* better than nothing, but needs extension to handle '-E' option
  3574.    correctly too */
  3575. ST_FUNC void preprocess_init(TCCState *s1)
  3576. {
  3577.     s1->include_stack_ptr = s1->include_stack;
  3578.     /* XXX: move that before to avoid having to initialize
  3579.        file->ifdef_stack_ptr ? */
  3580.     s1->ifdef_stack_ptr = s1->ifdef_stack;
  3581.     file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
  3582.  
  3583.     pvtop = vtop = vstack - 1;
  3584.     s1->pack_stack[0] = 0;
  3585.     s1->pack_stack_ptr = s1->pack_stack;
  3586.  
  3587.     isidnum_table['$' - CH_EOF] =
  3588.         tcc_state->dollars_in_identifiers ? IS_ID : 0;
  3589.  
  3590.     isidnum_table['.' - CH_EOF] =
  3591.         (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0;
  3592. }
  3593.  
  3594. ST_FUNC void preprocess_new(void)
  3595. {
  3596.     int i, c;
  3597.     const char *p, *r;
  3598.  
  3599.     /* init isid table */
  3600.     for(i = CH_EOF; i<128; i++)
  3601.         isidnum_table[i - CH_EOF]
  3602.             = is_space(i) ? IS_SPC
  3603.             : isid(i) ? IS_ID
  3604.             : isnum(i) ? IS_NUM
  3605.             : 0;
  3606.  
  3607.     for(i = 128; i<256; i++)
  3608.         isidnum_table[i - CH_EOF] = IS_ID;
  3609.  
  3610.     /* init allocators */
  3611.     tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE);
  3612.     tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE);
  3613.     tal_new(&cstr_alloc, CSTR_TAL_LIMIT, CSTR_TAL_SIZE);
  3614.  
  3615.     memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
  3616.     cstr_new(&cstr_buf);
  3617.     cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
  3618.     tok_str_new(&tokstr_buf);
  3619.     tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);
  3620.    
  3621.     tok_ident = TOK_IDENT;
  3622.     p = tcc_keywords;
  3623.     while (*p) {
  3624.         r = p;
  3625.         for(;;) {
  3626.             c = *r++;
  3627.             if (c == '\0')
  3628.                 break;
  3629.         }
  3630.         tok_alloc(p, r - p - 1);
  3631.         p = r;
  3632.     }
  3633. }
  3634.  
  3635. ST_FUNC void preprocess_delete(void)
  3636. {
  3637.     int i, n;
  3638.  
  3639.     /* free -D and compiler defines */
  3640.     free_defines(NULL);
  3641.  
  3642.     /* cleanup from error/setjmp */
  3643.     while (macro_stack)
  3644.         end_macro();
  3645.     macro_ptr = NULL;
  3646.  
  3647.     /* free tokens */
  3648.     n = tok_ident - TOK_IDENT;
  3649.     for(i = 0; i < n; i++)
  3650.         tal_free(toksym_alloc, table_ident[i]);
  3651.     tcc_free(table_ident);
  3652.     table_ident = NULL;
  3653.  
  3654.     /* free static buffers */
  3655.     cstr_free(&tokcstr);
  3656.     cstr_free(&cstr_buf);
  3657.     tok_str_free(tokstr_buf.str);
  3658.  
  3659.     /* free allocators */
  3660.     tal_delete(toksym_alloc);
  3661.     toksym_alloc = NULL;
  3662.     tal_delete(tokstr_alloc);
  3663.     tokstr_alloc = NULL;
  3664.     tal_delete(cstr_alloc);
  3665.     cstr_alloc = NULL;
  3666. }
  3667.  
  3668. /* Preprocess the current file */
  3669. ST_FUNC int tcc_preprocess(TCCState *s1)
  3670. {
  3671.     BufferedFile **iptr;
  3672.     int token_seen, spcs, level;
  3673.  
  3674.     preprocess_init(s1);
  3675.     ch = file->buf_ptr[0];
  3676.     tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
  3677.     parse_flags = PARSE_FLAG_PREPROCESS
  3678.                 | (parse_flags & PARSE_FLAG_ASM_FILE)
  3679.                 | PARSE_FLAG_LINEFEED
  3680.                 | PARSE_FLAG_SPACES
  3681.                 | PARSE_FLAG_ACCEPT_STRAYS
  3682.                 ;
  3683.  
  3684. #ifdef PP_BENCH
  3685.     do next(); while (tok != TOK_EOF); return 0;
  3686. #endif
  3687.  
  3688.     token_seen = spcs = 0;
  3689.     pp_line(s1, file, 0);
  3690.  
  3691.     for (;;) {
  3692.         iptr = s1->include_stack_ptr;
  3693.         next();
  3694.         if (tok == TOK_EOF)
  3695.             break;
  3696.         level = s1->include_stack_ptr - iptr;
  3697.         if (level) {
  3698.             if (level > 0)
  3699.                 pp_line(s1, *iptr, 0);
  3700.             pp_line(s1, file, level);
  3701.         }
  3702.  
  3703.         if (0 == token_seen) {
  3704.             if (tok == ' ') {
  3705.                 ++spcs;
  3706.                 continue;
  3707.             }
  3708.             if (tok == TOK_LINEFEED) {
  3709.                 spcs = 0;
  3710.                 continue;
  3711.             }
  3712.             pp_line(s1, file, 0);
  3713.             while (s1->ppfp && spcs > 0)
  3714.                 fputs(" ", s1->ppfp), --spcs;
  3715.             spcs = 0;
  3716.             token_seen = 1;
  3717.  
  3718.         } else if (tok == TOK_LINEFEED) {
  3719.             ++file->line_ref;
  3720.             token_seen = 0;
  3721.         }
  3722.         if (s1->ppfp)
  3723.             fputs(get_tok_str(tok, &tokc), s1->ppfp);
  3724.     }
  3725.  
  3726.     return 0;
  3727. }
  3728.  
  3729. ST_FUNC char *trimfront(char *p)
  3730. {
  3731.     while (*p && (unsigned char)*p <= ' ')
  3732.         ++p;
  3733.     return p;
  3734. }
  3735.  
  3736. ST_FUNC char *trimback(char *a, char *e)
  3737. {
  3738.     while (e > a && (unsigned char)e[-1] <= ' ')
  3739.         --e;
  3740.     *e = 0;;
  3741.     return a;
  3742. }
  3743.