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
14941494 define_push(tok, MACRO_OBJ, NULL, NULL);
14951495 }
14961496
1497+static 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] != '>'))))
1551+error:
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+
1560+static 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+
14971587 /* eval an expression for #if/#elif */
1498−static int expr_preprocess(void)
1588+static int expr_preprocess(TCCState *s1)
14991589 {
15001590 int c, t;
15011591 TokenString *str;
@@ -1510,11 +1600,15 @@ static int expr_preprocess(void) · 8 unmodified lines
15101600 t = tok;
15111601 if (t == '(')
15121602 next_nomacro();
1513− if (tok < TOK_IDENT)
1514− expect("identifier");
1515− if (tcc_state->run_test)
1516− maybe_run_test(tcc_state);
1517− c = define_find(tok) != 0;
1603+ if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
1604+ c = 1;
1605+ else {
1606+ if (tok < TOK_IDENT)
1607+ expect("identifier");
1608+ if (tcc_state->run_test)
1609+ maybe_run_test(tcc_state);
1610+ c = define_find(tok) != 0;
1611+ }
15181612 if (t == '(') {
15191613 next_nomacro();
15201614 if (tok != ')')
@@ -1522,15 +1616,34 @@ static int expr_preprocess(void) · 1 unmodified line
15221616 }
15231617 tok = TOK_CINT;
15241618 tokc.i = c;
1525− } else if (1 && tok == TOK___HAS_INCLUDE) {
1526− next(); /* XXX check if correct to use expansion */
1527− skip('(');
1528− while (tok != ')' && tok != TOK_EOF)
1529− next();
1619+ } else if (tok == TOK___HAS_INCLUDE ||
1620+ tok == TOK___HAS_INCLUDE_NEXT) {
1621+ int c, n, i, fd, save_tok = tok;
1622+ char buf[1024];
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();
15301630 if (tok != ')')
1531− expect("')'");
1631+ expect("')'");
15321632 tok = TOK_CINT;
15331633 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+ }
15341647 } else if (tok >= TOK_IDENT) {
15351648 /* if undefined macro, replace with zero, check for func-like */
15361649 t = tok;
@@ -1842,55 +1955,8 @@ ST_FUNC void preprocess(int is_bof) · 305 unmodified lines
18421955 case TOK_INCLUDE_NEXT:
18431956 ch = file->buf_ptr[0];
18441957 /* XXX: incorrect if comments : use next_nomacro with a special mode */
1845− skip_spaces();
1846− if (ch == '<') {
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− }
1958+
1959+ c = parse_include(buf, sizeof(buf), 0);
18941960
18951961 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
18961962 tcc_error("#include recursion too deep");
@@ -1899,31 +1965,9 @@ ST_FUNC void preprocess(int is_bof) · 2 unmodified lines
18991965 for (; i < n; ++i) {
19001966 char buf1[sizeof file->filename];
19011967 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− }
19251968
1926− pstrcat(buf1, sizeof(buf1), buf);
1969+ if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
1970+ continue;
19271971 e = search_cached_include(s1, buf1, 0);
19281972 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
19291973 /* no need to parse the include because the 'ifndef macro'
@@ -1965,7 +2009,7 @@ include_done: · 35 unmodified lines
19652009 c = 1;
19662010 goto do_ifdef;
19672011 case TOK_IF:
1968− c = expr_preprocess();
2012+ c = expr_preprocess(s1);
19692013 goto do_if;
19702014 case TOK_IFDEF:
19712015 c = 0;
@@ -1981,7 +2025,10 @@ include_done: · 9 unmodified lines
19812025 file->ifndef_macro = tok;
19822026 }
19832027 }
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;
19852032 do_if:
19862033 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
19872034 tcc_error("memory full (ifdef)");
@@ -2004,7 +2051,7 @@ include_done: · 16 unmodified lines
20042051 if (c == 1) {
20052052 c = 0;
20062053 } else {
2007− c = expr_preprocess();
2054+ c = expr_preprocess(s1);
20082055 s1->ifdef_stack_ptr[-1] = c;
20092056 }
20102057 test_else:
tcctok.h+1−0
@@ -94,6 +94,7 @@ · 93 unmodified lines
9494 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
9595 DEF(TOK___COUNTER__, "__COUNTER__")
9696 DEF(TOK___HAS_INCLUDE, "__has_include")
97+ DEF(TOK___HAS_INCLUDE_NEXT, "__has_include_next")
9798
9899 /* special identifiers */
99100 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