History

tccpp: integrate __has_include() more nicely

- make only one function from previously four pieces - use parse_pp_string() for the normal cases "..." and <...> - use the sanity check for computed include as end-condition too. - use 's1' instead of 'tcc_state' when possible 117 insertions(+), 165 deletions(-), less 48 lines

grischka committed 4 years ago

Commit 85c32dd1 parent 0f72db01 file · +117 −165Browse files

Unified · Split

tccpp.c+117−165
@@ -891,6 +891,7 @@ ST_FUNC int set_idnum(int c, int val) · 890 unmodified lines
891 891
892static inline void skip_spaces(void)892static inline void skip_spaces(void)
893{893{
894 ch = file->buf_ptr[0];
894 while (isidnum_table[ch - CH_EOF] & IS_SPC)895 while (isidnum_table[ch - CH_EOF] & IS_SPC)
895 cinp();896 cinp();
896}897}
@@ -1495,94 +1496,113 @@ static void maybe_run_test(TCCState *s) · 598 unmodified lines
1495 define_push(tok, MACRO_OBJ, NULL, NULL);1496 define_push(tok, MACRO_OBJ, NULL, NULL);
1496}1497}
1497 1498
1498static int parse_include(char *buf, size_t size_buf, int last)1499static CachedInclude *
1500search_cached_include(TCCState *s1, const char *filename, int add);
1501
1502static int parse_include(TCCState *s1, int do_next, int test)
1499{1503{
1500 int c;1504 int c, i;
1505 CString cs;
1506 char name[1024], buf[1024], *p;
1507 CachedInclude *e;
1501 1508
1502 skip_spaces();1509 cstr_new(&cs);
1503 if (ch == '<') {1510 skip_spaces(), c = ch;
1504 c = '>';1511 if (c == '<' || c == '\"') {
1505 goto read_name;1512 file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &cs);
1506 } else if (ch == '\"') {1513 next_nomacro();
1507 char *q;1514 } else {
1515 /* computed #include : concatenate tokens until result is one of
1516 the two accepted forms. Don't convert pp-tokens to tokens here. */
1517 parse_flags = PARSE_FLAG_PREPROCESS
1518 | PARSE_FLAG_LINEFEED
1519 | (parse_flags & PARSE_FLAG_ASM_FILE);
1520 for (;;) {
1521 next();
1522 p = cs.data, i = cs.size - 1;
1523 if (i > 0
1524 && ((p[0] == '"' && p[i] == '"')
1525 || (p[0] == '<' && p[i] == '>')))
1526 break;
1527 if (tok == TOK_LINEFEED)
1528 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
1529 cstr_cat(&cs, get_tok_str(tok, &tokc), -1);
1530 }
1531 c = p[0];
1532 /* remove '<>|""' */
1533 memmove(p, p + 1, cs.size -= 2);
1534 }
1535 cstr_ccat(&cs, '\0');
1536 pstrcpy(name, sizeof name, cs.data);
1537 cstr_free(&cs);
1508 1538
1509 c = ch;1539 i = do_next ? file->include_next_index : -1;
1510 read_name:1540 for (;;) {
1511 inp();1541 ++i;
1512 q = buf;1542 if (i == 0) {
1513 while (ch != c && ch != '\n' && ch != CH_EOF) {1543 /* check absolute include path */
1514 if ((q - buf) < size_buf - 1)1544 if (!IS_ABSPATH(name))
1515 *q++ = ch;1545 continue;
1516 if (ch == '\\') {1546 buf[0] = '\0';
1517 if (handle_stray_noerror() == 0)1547 } else if (i == 1) {
1518 --q;1548 /* search in file's dir if "header.h" */
1519 } else1549 if (c != '\"')
1520 inp();1550 continue;
1551 p = file->true_filename;
1552 pstrncpy(buf, p, tcc_basename(p) - p);
1553 } else {
1554 int j = i - 2, k = j - s1->nb_include_paths;
1555 if (k < 0)
1556 p = s1->include_paths[j];
1557 else if (k < s1->nb_sysinclude_paths)
1558 p = s1->sysinclude_paths[k];
1559 else if (test)
1560 return 0;
1561 else
1562 tcc_error("include file '%s' not found", name);
1563 pstrcpy(buf, sizeof buf, p);
1564 pstrcat(buf, sizeof buf, "/");
1521 }1565 }
1522 if (ch != c)1566 pstrcat(buf, sizeof buf, name);
1523 goto error;1567 e = search_cached_include(s1, buf, 0);
1524 *q = '\0';1568 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
1525 minp();1569 /* no need to parse the include because the 'ifndef macro'
1526#if 01570 is defined (or had #pragma once) */
1527 /* eat all spaces and comments after include */1571#ifdef INC_DEBUG
1528 /* XXX: slightly incorrect */1572 printf("%s: skipping cached %s\n", file->filename, buf);
1529 while (ch1 != '\n' && ch1 != CH_EOF)
1530 inp();
1531#endif1573#endif
1532 } else {1574 return 1;
1533 int len;1575 }
1534 /* computed #include : concatenate everything up to linefeed,1576 if (tcc_open(s1, buf) >= 0)
1535 the result must be one of the two accepted forms.1577 break;
1536 Don't convert pp-tokens to tokens here. */
1537 parse_flags = (PARSE_FLAG_PREPROCESS
1538 | PARSE_FLAG_LINEFEED
1539 | (parse_flags & PARSE_FLAG_ASM_FILE));
1540 next();
1541 buf[0] = '\0';
1542 while (tok != TOK_LINEFEED && tok != last) {
1543 pstrcat(buf, size_buf, get_tok_str(tok, &tokc));
1544 next();
1545 }
1546 len = strlen(buf);
1547 if (tok == last)
1548 unget_tok(0);
1549 /* check syntax and remove '<>|""' */
1550 if ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') &&
1551 (buf[0] != '<' || buf[len-1] != '>'))))
1552error:
1553 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
1554 c = buf[len-1];
1555 memmove(buf, buf + 1, len - 2);
1556 buf[len - 2] = '\0';
1557 }1578 }
1558 return c;
1559}
1560 1579
1561static int get_include_file(TCCState *s1, int i, int c,1580 if (test) {
1562 char *buf, char *buf1, size_t size_buf1)1581 tcc_close();
1563{
1564 const char *path;
1565
1566 if (i == 0) {
1567 /* check absolute include path */
1568 if (!IS_ABSPATH(buf))
1569 return -1;
1570 buf1[0] = 0;
1571 } else if (i == 1) {
1572 /* search in file's dir if "header.h" */
1573 if (c != '\"')
1574 return -1;
1575 path = file->true_filename;
1576 pstrncpy(buf1, path, tcc_basename(path) - path);
1577 } else {1582 } else {
1578 /* search in all the include paths */1583 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1579 int j = i - 2, k = j - s1->nb_include_paths;1584 tcc_error("#include recursion too deep");
1580 path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];1585 /* push previous file on stack */
1581 pstrcpy(buf1, size_buf1, path);1586 *s1->include_stack_ptr++ = file->prev;
1582 pstrcat(buf1, size_buf1, "/");1587 file->include_next_index = i;
1588#ifdef INC_DEBUG
1589 printf("%s: including %s\n", file->prev->filename, file->filename);
1590#endif
1591 /* update target deps */
1592 if (s1->gen_deps) {
1593 BufferedFile *bf = file;
1594 while (i == 1 && (bf = bf->prev))
1595 i = bf->include_next_index;
1596 /* skip system include files */
1597 if (s1->include_sys_deps || i - 2 < s1->nb_include_paths)
1598 dynarray_add(&s1->target_deps, &s1->nb_target_deps,
1599 tcc_strdup(buf));
1600 }
1601 /* add include file debug info */
1602 tcc_debug_bincl(s1);
1603 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
1583 }1604 }
1584 pstrcat(buf1, size_buf1, buf);1605 return 1;
1585 return 0;
1586}1606}
1587 1607
1588/* eval an expression for #if/#elif */1608/* eval an expression for #if/#elif */
@@ -1601,15 +1621,15 @@ static int expr_preprocess(TCCState *s1) · 12 unmodified lines
1601 t = tok;1621 t = tok;
1602 if (t == '(') 1622 if (t == '(')
1603 next_nomacro();1623 next_nomacro();
1604 if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)1624 if (tok < TOK_IDENT)
1605 c = 1;1625 expect("identifier");
1606 else {1626 if (s1->run_test)
1607 if (tok < TOK_IDENT)1627 maybe_run_test(s1);
1608 expect("identifier");1628 c = 0;
1609 if (tcc_state->run_test)1629 if (define_find(tok)
1610 maybe_run_test(tcc_state);1630 || tok == TOK___HAS_INCLUDE
1611 c = define_find(tok) != 0;1631 || tok == TOK___HAS_INCLUDE_NEXT)
1612 }1632 c = 1;
1613 if (t == '(') {1633 if (t == '(') {
1614 next_nomacro();1634 next_nomacro();
1615 if (tok != ')')1635 if (tok != ')')
@@ -1619,32 +1639,15 @@ static int expr_preprocess(TCCState *s1) · 3 unmodified lines
1619 tokc.i = c;1639 tokc.i = c;
1620 } else if (tok == TOK___HAS_INCLUDE ||1640 } else if (tok == TOK___HAS_INCLUDE ||
1621 tok == TOK___HAS_INCLUDE_NEXT) {1641 tok == TOK___HAS_INCLUDE_NEXT) {
1622 int c, n, i, fd, save_tok = tok;1642 t = tok;
1623 char buf[1024];
1624
1625 next_nomacro();1643 next_nomacro();
1626 if (tok != '(')1644 if (tok != '(')
1627 expect("(");1645 expect("(");
1628 ch = file->buf_ptr[0];1646 c = parse_include(s1, t - TOK___HAS_INCLUDE, 1);
1629 c = parse_include(buf, sizeof(buf), ')');
1630 next_nomacro();
1631 if (tok != ')')1647 if (tok != ')')
1632 expect("')'");1648 expect("')'");
1633 tok = TOK_CINT;1649 tok = TOK_CINT;
1634 tokc.i = 0;1650 tokc.i = c;
1635 i = save_tok == TOK___HAS_INCLUDE_NEXT ? file->include_next_index + 1 : 0;
1636 n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
1637 for (; i < n; i++) {
1638 char buf1[sizeof file->filename];
1639
1640 if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
1641 continue;
1642 if ((fd = open(buf1, O_RDONLY | O_BINARY)) >= 0) {
1643 close(fd);
1644 tokc.i = 1;
1645 break;
1646 }
1647 }
1648 } else if (tok >= TOK_IDENT) {1651 } else if (tok >= TOK_IDENT) {
1649 /* if undefined macro, replace with zero, check for func-like */1652 /* if undefined macro, replace with zero, check for func-like */
1650 t = tok;1653 t = tok;
@@ -1922,7 +1925,7 @@ pragma_err: · 271 unmodified lines
1922ST_FUNC void preprocess(int is_bof)1925ST_FUNC void preprocess(int is_bof)
1923{1926{
1924 TCCState *s1 = tcc_state;1927 TCCState *s1 = tcc_state;
1925 int i, c, n, saved_parse_flags;1928 int c, n, saved_parse_flags;
1926 char buf[1024], *q;1929 char buf[1024], *q;
1927 Sym *s;1930 Sym *s;
1928 1931
@@ -1954,57 +1957,7 @@ ST_FUNC void preprocess(int is_bof) · 25 unmodified lines
1954 break;1957 break;
1955 case TOK_INCLUDE:1958 case TOK_INCLUDE:
1956 case TOK_INCLUDE_NEXT:1959 case TOK_INCLUDE_NEXT:
1957 ch = file->buf_ptr[0];1960 parse_include(s1, tok - TOK_INCLUDE, 0);
1958 /* XXX: incorrect if comments : use next_nomacro with a special mode */
1959
1960 c = parse_include(buf, sizeof(buf), 0);
1961
1962 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1963 tcc_error("#include recursion too deep");
1964 i = tok == TOK_INCLUDE_NEXT ? file->include_next_index + 1 : 0;
1965 n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
1966 for (; i < n; ++i) {
1967 char buf1[sizeof file->filename];
1968 CachedInclude *e;
1969
1970 if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
1971 continue;
1972 e = search_cached_include(s1, buf1, 0);
1973 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
1974 /* no need to parse the include because the 'ifndef macro'
1975 is defined (or had #pragma once) */
1976#ifdef INC_DEBUG
1977 printf("%s: skipping cached %s\n", file->filename, buf1);
1978#endif
1979 goto include_done;
1980 }
1981
1982 if (tcc_open(s1, buf1) < 0)
1983 continue;
1984 /* push previous file on stack */
1985 *s1->include_stack_ptr++ = file->prev;
1986 file->include_next_index = i;
1987#ifdef INC_DEBUG
1988 printf("%s: including %s\n", file->prev->filename, file->filename);
1989#endif
1990 /* update target deps */
1991 if (s1->gen_deps) {
1992 BufferedFile *bf = file;
1993 while (i == 1 && (bf = bf->prev))
1994 i = bf->include_next_index;
1995 /* skip system include files */
1996 if (s1->include_sys_deps || n - i > s1->nb_sysinclude_paths)
1997 dynarray_add(&s1->target_deps, &s1->nb_target_deps,
1998 tcc_strdup(buf1));
1999 }
2000 /* add include file debug info */
2001 tcc_debug_bincl(tcc_state);
2002 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2003 ch = file->buf_ptr[0];
2004 goto the_end;
2005 }
2006 tcc_error("include file '%s' not found", buf);
2007include_done:
2008 break;1961 break;
2009 case TOK_IFNDEF:1962 case TOK_IFNDEF:
2010 c = 1;1963 c = 1;
@@ -2026,10 +1979,10 @@ include_done: · 15 unmodified lines
2026 file->ifndef_macro = tok;1979 file->ifndef_macro = tok;
2027 }1980 }
2028 }1981 }
2029 if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)1982 if (define_find(tok)
2030 c = 1 ^ c;1983 || tok == TOK___HAS_INCLUDE
2031 else1984 || tok == TOK___HAS_INCLUDE_NEXT)
2032 c = (define_find(tok) != 0) ^ c;1985 c ^= 1;
2033 do_if:1986 do_if:
2034 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)1987 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2035 tcc_error("memory full (ifdef)");1988 tcc_error("memory full (ifdef)");
@@ -2120,7 +2073,6 @@ include_done: · 84 unmodified lines
2120 case TOK_ERROR:2073 case TOK_ERROR:
2121 case TOK_WARNING:2074 case TOK_WARNING:
2122 c = tok;2075 c = tok;
2123 ch = file->buf_ptr[0];
2124 skip_spaces();2076 skip_spaces();
2125 q = buf;2077 q = buf;
2126 while (ch != '\n' && ch != CH_EOF) {2078 while (ch != '\n' && ch != CH_EOF) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t