- 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
Unified · Split
| @@ -891,6 +891,7 @@ ST_FUNC int set_idnum(int c, int val) · 890 unmodified lines | ||
| 891 | 891 | |
| 892 | 892 | static inline void skip_spaces(void) |
| 893 | 893 | { |
| 894 | + ch = file->buf_ptr[0]; | |
| 894 | 895 | while (isidnum_table[ch - CH_EOF] & IS_SPC) |
| 895 | 896 | cinp(); |
| 896 | 897 | } |
| @@ -1495,94 +1496,113 @@ static void maybe_run_test(TCCState *s) · 598 unmodified lines | ||
| 1495 | 1496 | define_push(tok, MACRO_OBJ, NULL, NULL); |
| 1496 | 1497 | } |
| 1497 | 1498 | |
| 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) | |
| 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(); | |
| 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); | |
| 1508 | 1538 | |
| 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, "/"); | |
| 1521 | 1565 | } |
| 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); | |
| 1531 | 1573 | #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; | |
| 1557 | 1578 | } |
| 1558 | − return c; | |
| 1559 | −} | |
| 1560 | 1579 | |
| 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(); | |
| 1577 | 1582 | } 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; | |
| 1583 | 1604 | } |
| 1584 | − pstrcat(buf1, size_buf1, buf); | |
| 1585 | − return 0; | |
| 1605 | + return 1; | |
| 1586 | 1606 | } |
| 1587 | 1607 | |
| 1588 | 1608 | /* eval an expression for #if/#elif */ |
| @@ -1601,15 +1621,15 @@ static int expr_preprocess(TCCState *s1) · 12 unmodified lines | ||
| 1601 | 1621 | t = tok; |
| 1602 | 1622 | if (t == '(') |
| 1603 | 1623 | 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; | |
| 1613 | 1633 | if (t == '(') { |
| 1614 | 1634 | next_nomacro(); |
| 1615 | 1635 | if (tok != ')') |
| @@ -1619,32 +1639,15 @@ static int expr_preprocess(TCCState *s1) · 3 unmodified lines | ||
| 1619 | 1639 | tokc.i = c; |
| 1620 | 1640 | } else if (tok == TOK___HAS_INCLUDE || |
| 1621 | 1641 | tok == TOK___HAS_INCLUDE_NEXT) { |
| 1622 | − int c, n, i, fd, save_tok = tok; | |
| 1623 | − char buf[1024]; | |
| 1624 | − | |
| 1642 | + t = tok; | |
| 1625 | 1643 | next_nomacro(); |
| 1626 | 1644 | if (tok != '(') |
| 1627 | 1645 | 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); | |
| 1631 | 1647 | if (tok != ')') |
| 1632 | 1648 | expect("')'"); |
| 1633 | 1649 | 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; | |
| 1648 | 1651 | } else if (tok >= TOK_IDENT) { |
| 1649 | 1652 | /* if undefined macro, replace with zero, check for func-like */ |
| 1650 | 1653 | t = tok; |
| @@ -1922,7 +1925,7 @@ pragma_err: · 271 unmodified lines | ||
| 1922 | 1925 | ST_FUNC void preprocess(int is_bof) |
| 1923 | 1926 | { |
| 1924 | 1927 | TCCState *s1 = tcc_state; |
| 1925 | − int i, c, n, saved_parse_flags; | |
| 1928 | + int c, n, saved_parse_flags; | |
| 1926 | 1929 | char buf[1024], *q; |
| 1927 | 1930 | Sym *s; |
| 1928 | 1931 | |
| @@ -1954,57 +1957,7 @@ ST_FUNC void preprocess(int is_bof) · 25 unmodified lines | ||
| 1954 | 1957 | break; |
| 1955 | 1958 | case TOK_INCLUDE: |
| 1956 | 1959 | 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); | |
| 2008 | 1961 | break; |
| 2009 | 1962 | case TOK_IFNDEF: |
| 2010 | 1963 | c = 1; |
| @@ -2026,10 +1979,10 @@ include_done: · 15 unmodified lines | ||
| 2026 | 1979 | file->ifndef_macro = tok; |
| 2027 | 1980 | } |
| 2028 | 1981 | } |
| 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; | |
| 2033 | 1986 | do_if: |
| 2034 | 1987 | if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) |
| 2035 | 1988 | tcc_error("memory full (ifdef)"); |
| @@ -2120,7 +2073,6 @@ include_done: · 84 unmodified lines | ||
| 2120 | 2073 | case TOK_ERROR: |
| 2121 | 2074 | case TOK_WARNING: |
| 2122 | 2075 | c = tok; |
| 2123 | − ch = file->buf_ptr[0]; | |
| 2124 | 2076 | skip_spaces(); |
| 2125 | 2077 | q = buf; |
| 2126 | 2078 | while (ch != '\n' && ch != CH_EOF) { |