History

Add __has_include and __has_include_next support

tcctok.h: - Add __has_include_next tccpp.c: - New functions parse_include and get_include_file - Changed expr_preprocess and preprocess

herman ten brugge committed 4 years ago

Commit 47dc6e61 parent 1de025c2 files · +136 −88Browse files

Unified · Split

2 files
  1. tccpp.c +135 −88
  2. tcctok.h +1 −0
tccpp.c+135−88
@@ -1494,8 +1494,98 @@ static void maybe_run_test(TCCState *s) · 1493 unmodified lines
1494 define_push(tok, MACRO_OBJ, NULL, NULL);1494 define_push(tok, MACRO_OBJ, NULL, NULL);
1495}1495}
1496 1496
1497static int parse_include(char *buf, size_t size_buf, int last)
1498{
1499 int c;
1500
1501 skip_spaces();
1502 if (ch == '<') {
1503 c = '>';
1504 goto read_name;
1505 } else if (ch == '\"') {
1506 char *q;
1507
1508 c = ch;
1509 read_name:
1510 inp();
1511 q = buf;
1512 while (ch != c && ch != '\n' && ch != CH_EOF) {
1513 if ((q - buf) < size_buf - 1)
1514 *q++ = ch;
1515 if (ch == '\\') {
1516 if (handle_stray_noerror() == 0)
1517 --q;
1518 } else
1519 inp();
1520 }
1521 if (ch != c)
1522 goto error;
1523 *q = '\0';
1524 minp();
1525#if 0
1526 /* eat all spaces and comments after include */
1527 /* XXX: slightly incorrect */
1528 while (ch1 != '\n' && ch1 != CH_EOF)
1529 inp();
1530#endif
1531 } else {
1532 int len;
1533 /* computed #include : concatenate everything up to linefeed,
1534 the result must be one of the two accepted forms.
1535 Don't convert pp-tokens to tokens here. */
1536 parse_flags = (PARSE_FLAG_PREPROCESS
1537 | PARSE_FLAG_LINEFEED
1538 | (parse_flags & PARSE_FLAG_ASM_FILE));
1539 next();
1540 buf[0] = '\0';
1541 while (tok != TOK_LINEFEED && tok != last) {
1542 pstrcat(buf, size_buf, get_tok_str(tok, &tokc));
1543 next();
1544 }
1545 len = strlen(buf);
1546 if (tok == last)
1547 unget_tok(0);
1548 /* check syntax and remove '<>|""' */
1549 if ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') &&
1550 (buf[0] != '<' || buf[len-1] != '>'))))
1551error:
1552 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
1553 c = buf[len-1];
1554 memmove(buf, buf + 1, len - 2);
1555 buf[len - 2] = '\0';
1556 }
1557 return c;
1558}
1559
1560static int get_include_file(TCCState *s1, int i, int c,
1561 char *buf, char *buf1, size_t size_buf1)
1562{
1563 const char *path;
1564
1565 if (i == 0) {
1566 /* check absolute include path */
1567 if (!IS_ABSPATH(buf))
1568 return -1;
1569 buf1[0] = 0;
1570 } else if (i == 1) {
1571 /* search in file's dir if "header.h" */
1572 if (c != '\"')
1573 return -1;
1574 path = file->true_filename;
1575 pstrncpy(buf1, path, tcc_basename(path) - path);
1576 } else {
1577 /* search in all the include paths */
1578 int j = i - 2, k = j - s1->nb_include_paths;
1579 path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
1580 pstrcpy(buf1, size_buf1, path);
1581 pstrcat(buf1, size_buf1, "/");
1582 }
1583 pstrcat(buf1, size_buf1, buf);
1584 return 0;
1585}
1586
1497/* eval an expression for #if/#elif */1587/* eval an expression for #if/#elif */
1498static int expr_preprocess(void)1588static int expr_preprocess(TCCState *s1)
1499{1589{
1500 int c, t;1590 int c, t;
1501 TokenString *str;1591 TokenString *str;
@@ -1510,11 +1600,15 @@ static int expr_preprocess(void) · 8 unmodified lines
1510 t = tok;1600 t = tok;
1511 if (t == '(') 1601 if (t == '(')
1512 next_nomacro();1602 next_nomacro();
1513 if (tok < TOK_IDENT)1603 if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
1514 expect("identifier");1604 c = 1;
1515 if (tcc_state->run_test)1605 else {
1516 maybe_run_test(tcc_state);1606 if (tok < TOK_IDENT)
1517 c = define_find(tok) != 0;1607 expect("identifier");
1608 if (tcc_state->run_test)
1609 maybe_run_test(tcc_state);
1610 c = define_find(tok) != 0;
1611 }
1518 if (t == '(') {1612 if (t == '(') {
1519 next_nomacro();1613 next_nomacro();
1520 if (tok != ')')1614 if (tok != ')')
@@ -1522,15 +1616,34 @@ static int expr_preprocess(void) · 1 unmodified line
1522 }1616 }
1523 tok = TOK_CINT;1617 tok = TOK_CINT;
1524 tokc.i = c;1618 tokc.i = c;
1525 } else if (1 && tok == TOK___HAS_INCLUDE) {1619 } else if (tok == TOK___HAS_INCLUDE ||
1526 next(); /* XXX check if correct to use expansion */1620 tok == TOK___HAS_INCLUDE_NEXT) {
1527 skip('(');1621 int c, n, i, fd, save_tok = tok;
1528 while (tok != ')' && tok != TOK_EOF)1622 char buf[1024];
1529 next();1623
1624 next_nomacro();
1625 if (tok != '(')
1626 expect("(");
1627 ch = file->buf_ptr[0];
1628 c = parse_include(buf, sizeof(buf), ')');
1629 next_nomacro();
1530 if (tok != ')')1630 if (tok != ')')
1531 expect("')'");1631 expect("')'");
1532 tok = TOK_CINT;1632 tok = TOK_CINT;
1533 tokc.i = 0;1633 tokc.i = 0;
1634 i = save_tok == TOK___HAS_INCLUDE_NEXT ? file->include_next_index + 1 : 0;
1635 n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
1636 for (; i < n; i++) {
1637 char buf1[sizeof file->filename];
1638
1639 if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
1640 continue;
1641 if ((fd = open(buf1, O_RDONLY | O_BINARY)) >= 0) {
1642 close(fd);
1643 tokc.i = 1;
1644 break;
1645 }
1646 }
1534 } else if (tok >= TOK_IDENT) {1647 } else if (tok >= TOK_IDENT) {
1535 /* if undefined macro, replace with zero, check for func-like */1648 /* if undefined macro, replace with zero, check for func-like */
1536 t = tok;1649 t = tok;
@@ -1842,55 +1955,8 @@ ST_FUNC void preprocess(int is_bof) · 305 unmodified lines
1842 case TOK_INCLUDE_NEXT:1955 case TOK_INCLUDE_NEXT:
1843 ch = file->buf_ptr[0];1956 ch = file->buf_ptr[0];
1844 /* XXX: incorrect if comments : use next_nomacro with a special mode */1957 /* XXX: incorrect if comments : use next_nomacro with a special mode */
1845 skip_spaces();1958
1846 if (ch == '<') {1959 c = parse_include(buf, sizeof(buf), 0);
1847 c = '>';
1848 goto read_name;
1849 } else if (ch == '\"') {
1850 c = ch;
1851 read_name:
1852 inp();
1853 q = buf;
1854 while (ch != c && ch != '\n' && ch != CH_EOF) {
1855 if ((q - buf) < sizeof(buf) - 1)
1856 *q++ = ch;
1857 if (ch == '\\') {
1858 if (handle_stray_noerror() == 0)
1859 --q;
1860 } else
1861 inp();
1862 }
1863 *q = '\0';
1864 minp();
1865#if 0
1866 /* eat all spaces and comments after include */
1867 /* XXX: slightly incorrect */
1868 while (ch1 != '\n' && ch1 != CH_EOF)
1869 inp();
1870#endif
1871 } else {
1872 int len;
1873 /* computed #include : concatenate everything up to linefeed,
1874 the result must be one of the two accepted forms.
1875 Don't convert pp-tokens to tokens here. */
1876 parse_flags = (PARSE_FLAG_PREPROCESS
1877 | PARSE_FLAG_LINEFEED
1878 | (parse_flags & PARSE_FLAG_ASM_FILE));
1879 next();
1880 buf[0] = '\0';
1881 while (tok != TOK_LINEFEED) {
1882 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
1883 next();
1884 }
1885 len = strlen(buf);
1886 /* check syntax and remove '<>|""' */
1887 if ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') &&
1888 (buf[0] != '<' || buf[len-1] != '>'))))
1889 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
1890 c = buf[len-1];
1891 memmove(buf, buf + 1, len - 2);
1892 buf[len - 2] = '\0';
1893 }
1894 1960
1895 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)1961 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1896 tcc_error("#include recursion too deep");1962 tcc_error("#include recursion too deep");
@@ -1899,31 +1965,9 @@ ST_FUNC void preprocess(int is_bof) · 2 unmodified lines
1899 for (; i < n; ++i) {1965 for (; i < n; ++i) {
1900 char buf1[sizeof file->filename];1966 char buf1[sizeof file->filename];
1901 CachedInclude *e;1967 CachedInclude *e;
1902 const char *path;
1903
1904 if (i == 0) {
1905 /* check absolute include path */
1906 if (!IS_ABSPATH(buf))
1907 continue;
1908 buf1[0] = 0;
1909
1910 } else if (i == 1) {
1911 /* search in file's dir if "header.h" */
1912 if (c != '\"')
1913 continue;
1914 /* https://savannah.nongnu.org/bugs/index.php?50847 */
1915 path = file->true_filename;
1916 pstrncpy(buf1, path, tcc_basename(path) - path);
1917
1918 } else {
1919 /* search in all the include paths */
1920 int j = i - 2, k = j - s1->nb_include_paths;
1921 path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
1922 pstrcpy(buf1, sizeof(buf1), path);
1923 pstrcat(buf1, sizeof(buf1), "/");
1924 }
1925 1968
1926 pstrcat(buf1, sizeof(buf1), buf);1969 if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
1970 continue;
1927 e = search_cached_include(s1, buf1, 0);1971 e = search_cached_include(s1, buf1, 0);
1928 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {1972 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
1929 /* no need to parse the include because the 'ifndef macro'1973 /* no need to parse the include because the 'ifndef macro'
@@ -1965,7 +2009,7 @@ include_done: · 35 unmodified lines
1965 c = 1;2009 c = 1;
1966 goto do_ifdef;2010 goto do_ifdef;
1967 case TOK_IF:2011 case TOK_IF:
1968 c = expr_preprocess();2012 c = expr_preprocess(s1);
1969 goto do_if;2013 goto do_if;
1970 case TOK_IFDEF:2014 case TOK_IFDEF:
1971 c = 0;2015 c = 0;
@@ -1981,7 +2025,10 @@ include_done: · 9 unmodified lines
1981 file->ifndef_macro = tok;2025 file->ifndef_macro = tok;
1982 }2026 }
1983 }2027 }
1984 c = (define_find(tok) != 0) ^ c;2028 if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
2029 c = 1 ^ c;
2030 else
2031 c = (define_find(tok) != 0) ^ c;
1985 do_if:2032 do_if:
1986 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)2033 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
1987 tcc_error("memory full (ifdef)");2034 tcc_error("memory full (ifdef)");
@@ -2004,7 +2051,7 @@ include_done: · 16 unmodified lines
2004 if (c == 1) {2051 if (c == 1) {
2005 c = 0;2052 c = 0;
2006 } else {2053 } else {
2007 c = expr_preprocess();2054 c = expr_preprocess(s1);
2008 s1->ifdef_stack_ptr[-1] = c;2055 s1->ifdef_stack_ptr[-1] = c;
2009 }2056 }
2010 test_else:2057 test_else:
tcctok.h+1−0
@@ -94,6 +94,7 @@ · 93 unmodified lines
94 DEF(TOK___VA_ARGS__, "__VA_ARGS__")94 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
95 DEF(TOK___COUNTER__, "__COUNTER__")95 DEF(TOK___COUNTER__, "__COUNTER__")
96 DEF(TOK___HAS_INCLUDE, "__has_include")96 DEF(TOK___HAS_INCLUDE, "__has_include")
97 DEF(TOK___HAS_INCLUDE_NEXT, "__has_include_next")
97 98
98/* special identifiers */99/* special identifiers */
99 DEF(TOK___FUNC__, "__func__")100 DEF(TOK___FUNC__, "__func__")

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