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
891891
892892 static inline void skip_spaces(void)
893893 {
894+ ch = file->buf_ptr[0];
894895 while (isidnum_table[ch - CH_EOF] & IS_SPC)
895896 cinp();
896897 }
@@ -1495,94 +1496,113 @@ static void maybe_run_test(TCCState *s) · 598 unmodified lines
14951496 define_push(tok, MACRO_OBJ, NULL, NULL);
14961497 }
14971498
1498−static int parse_include(char *buf, size_t size_buf, int last)
1499+static CachedInclude *
1500+search_cached_include(TCCState *s1, const char *filename, int add);
1501+
1502+static int parse_include(TCCState *s1, int do_next, int test)
14991503 {
1500− int c;
1504+ int c, i;
1505+ CString cs;
1506+ char name[1024], buf[1024], *p;
1507+ CachedInclude *e;
15011508
1502− skip_spaces();
1503− if (ch == '<') {
1504− c = '>';
1505− goto read_name;
1506− } else if (ch == '\"') {
1507− char *q;
1509+ cstr_new(&cs);
1510+ skip_spaces(), c = ch;
1511+ if (c == '<' || c == '\"') {
1512+ file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &cs);
1513+ next_nomacro();
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);
15081538
1509− c = ch;
1510− read_name:
1511− inp();
1512− q = buf;
1513− while (ch != c && ch != '\n' && ch != CH_EOF) {
1514− if ((q - buf) < size_buf - 1)
1515− *q++ = ch;
1516− if (ch == '\\') {
1517− if (handle_stray_noerror() == 0)
1518− --q;
1519− } else
1520− inp();
1539+ i = do_next ? file->include_next_index : -1;
1540+ for (;;) {
1541+ ++i;
1542+ if (i == 0) {
1543+ /* check absolute include path */
1544+ if (!IS_ABSPATH(name))
1545+ continue;
1546+ buf[0] = '\0';
1547+ } else if (i == 1) {
1548+ /* search in file's dir if "header.h" */
1549+ if (c != '\"')
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, "/");
15211565 }
1522− if (ch != c)
1523− goto error;
1524− *q = '\0';
1525− minp();
1526−#if 0
1527− /* eat all spaces and comments after include */
1528− /* XXX: slightly incorrect */
1529− while (ch1 != '\n' && ch1 != CH_EOF)
1530− inp();
1566+ pstrcat(buf, sizeof buf, name);
1567+ e = search_cached_include(s1, buf, 0);
1568+ if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
1569+ /* no need to parse the include because the 'ifndef macro'
1570+ is defined (or had #pragma once) */
1571+#ifdef INC_DEBUG
1572+ printf("%s: skipping cached %s\n", file->filename, buf);
15311573 #endif
1532− } else {
1533− int len;
1534− /* computed #include : concatenate everything up to linefeed,
1535− the result must be one of the two accepted forms.
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] != '>'))))
1552−error:
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';
1574+ return 1;
1575+ }
1576+ if (tcc_open(s1, buf) >= 0)
1577+ break;
15571578 }
1558− return c;
1559−}
15601579
1561−static int get_include_file(TCCState *s1, int i, int c,
1562− char *buf, char *buf1, size_t size_buf1)
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);
1580+ if (test) {
1581+ tcc_close();
15771582 } else {
1578− /* search in all the include paths */
1579− int j = i - 2, k = j - s1->nb_include_paths;
1580− path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
1581− pstrcpy(buf1, size_buf1, path);
1582− pstrcat(buf1, size_buf1, "/");
1583+ if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1584+ tcc_error("#include recursion too deep");
1585+ /* push previous file on stack */
1586+ *s1->include_stack_ptr++ = file->prev;
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;
15831604 }
1584− pstrcat(buf1, size_buf1, buf);
1585− return 0;
1605+ return 1;
15861606 }
15871607
15881608 /* eval an expression for #if/#elif */
@@ -1601,15 +1621,15 @@ static int expr_preprocess(TCCState *s1) · 12 unmodified lines
16011621 t = tok;
16021622 if (t == '(')
16031623 next_nomacro();
1604− if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
1605− c = 1;
1606− else {
1607− if (tok < TOK_IDENT)
1608− expect("identifier");
1609− if (tcc_state->run_test)
1610− maybe_run_test(tcc_state);
1611− c = define_find(tok) != 0;
1612− }
1624+ if (tok < TOK_IDENT)
1625+ expect("identifier");
1626+ if (s1->run_test)
1627+ maybe_run_test(s1);
1628+ c = 0;
1629+ if (define_find(tok)
1630+ || tok == TOK___HAS_INCLUDE
1631+ || tok == TOK___HAS_INCLUDE_NEXT)
1632+ c = 1;
16131633 if (t == '(') {
16141634 next_nomacro();
16151635 if (tok != ')')
@@ -1619,32 +1639,15 @@ static int expr_preprocess(TCCState *s1) · 3 unmodified lines
16191639 tokc.i = c;
16201640 } else if (tok == TOK___HAS_INCLUDE ||
16211641 tok == TOK___HAS_INCLUDE_NEXT) {
1622− int c, n, i, fd, save_tok = tok;
1623− char buf[1024];
1624−
1642+ t = tok;
16251643 next_nomacro();
16261644 if (tok != '(')
16271645 expect("(");
1628− ch = file->buf_ptr[0];
1629− c = parse_include(buf, sizeof(buf), ')');
1630− next_nomacro();
1646+ c = parse_include(s1, t - TOK___HAS_INCLUDE, 1);
16311647 if (tok != ')')
16321648 expect("')'");
16331649 tok = TOK_CINT;
1634− tokc.i = 0;
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− }
1650+ tokc.i = c;
16481651 } else if (tok >= TOK_IDENT) {
16491652 /* if undefined macro, replace with zero, check for func-like */
16501653 t = tok;
@@ -1922,7 +1925,7 @@ pragma_err: · 271 unmodified lines
19221925 ST_FUNC void preprocess(int is_bof)
19231926 {
19241927 TCCState *s1 = tcc_state;
1925− int i, c, n, saved_parse_flags;
1928+ int c, n, saved_parse_flags;
19261929 char buf[1024], *q;
19271930 Sym *s;
19281931
@@ -1954,57 +1957,7 @@ ST_FUNC void preprocess(int is_bof) · 25 unmodified lines
19541957 break;
19551958 case TOK_INCLUDE:
19561959 case TOK_INCLUDE_NEXT:
1957− ch = file->buf_ptr[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);
2007−include_done:
1960+ parse_include(s1, tok - TOK_INCLUDE, 0);
20081961 break;
20091962 case TOK_IFNDEF:
20101963 c = 1;
@@ -2026,10 +1979,10 @@ include_done: · 15 unmodified lines
20261979 file->ifndef_macro = tok;
20271980 }
20281981 }
2029− if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
2030− c = 1 ^ c;
2031− else
2032− c = (define_find(tok) != 0) ^ c;
1982+ if (define_find(tok)
1983+ || tok == TOK___HAS_INCLUDE
1984+ || tok == TOK___HAS_INCLUDE_NEXT)
1985+ c ^= 1;
20331986 do_if:
20341987 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
20351988 tcc_error("memory full (ifdef)");
@@ -2120,7 +2073,6 @@ include_done: · 84 unmodified lines
21202073 case TOK_ERROR:
21212074 case TOK_WARNING:
21222075 c = tok;
2123− ch = file->buf_ptr[0];
21242076 skip_spaces();
21252077 q = buf;
21262078 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