tcc_normalize_inc_dirs: normally no problem to be absolutly gcc compatible as long as it can be done the tiny way. This reverts to the state before recent related commits and reimplements a (small) part of it to fix the reported problem. Also: Revert "parsing "..." sequence" c3975cf27c792d493e76a2058a1eaf588324053e && p[1] == '.' is not a reliable way to lookahead
Unified · Split
| @@ -841,7 +841,6 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) · 840 unmodified lines | ||
| 841 | 841 | normalize_slashes(bf->filename); |
| 842 | 842 | #endif |
| 843 | 843 | bf->line_num = 1; |
| 844 | − bf->inc_path_index = -2; | |
| 845 | 844 | bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; |
| 846 | 845 | bf->fd = -1; |
| 847 | 846 | bf->prev = file; |
| @@ -1509,96 +1508,6 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) · 661 unmodified lines | ||
| 1509 | 1508 | return 0; |
| 1510 | 1509 | } |
| 1511 | 1510 | |
| 1512 | − | |
| 1513 | −/* Windows stat* ( https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ): | |
| 1514 | − * - st_gid, st_ino, st_uid: only valid on "unix" file systems (not FAT, NTFS, etc) | |
| 1515 | − * - st_atime, st_ctime: not valid on FAT, valid on NTFS. | |
| 1516 | − * - Other fields should be reasonably compatible (and S_ISDIR should work). | |
| 1517 | − * | |
| 1518 | − * BY_HANDLE_FILE_INFORMATION ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788%28v=vs.85%29.aspx ): | |
| 1519 | − * - File index (combined nFileIndexHigh and nFileIndexLow) _may_ change when the file is opened. | |
| 1520 | − * - But on NTFS: it's guaranteed to be the same value until the file is deleted. | |
| 1521 | − * - On windows server 2012 there's a 128b file id, and the 64b one via | |
| 1522 | − * nFileIndex* is not guaranteed to be unique. | |
| 1523 | − * | |
| 1524 | − * - MS Docs suggest to that volume number with the file index could be used to | |
| 1525 | − * check if two handles refer to the same file. | |
| 1526 | − */ | |
| 1527 | −#ifndef _WIN32 | |
| 1528 | −typedef struct stat file_info_t; | |
| 1529 | −#else | |
| 1530 | −typedef BY_HANDLE_FILE_INFORMATION file_info_t; | |
| 1531 | −#endif | |
| 1532 | − | |
| 1533 | −int get_file_info(const char *fname, file_info_t *out_info) | |
| 1534 | −{ | |
| 1535 | −#ifndef _WIN32 | |
| 1536 | − return stat(fname, out_info); | |
| 1537 | −#else | |
| 1538 | − int rv = 1; | |
| 1539 | − HANDLE h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, | |
| 1540 | − FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL); | |
| 1541 | − | |
| 1542 | − if (h != INVALID_HANDLE_VALUE) { | |
| 1543 | − rv = !GetFileInformationByHandle(h, out_info); | |
| 1544 | − CloseHandle(h); | |
| 1545 | − } | |
| 1546 | − return rv; | |
| 1547 | −#endif | |
| 1548 | −} | |
| 1549 | − | |
| 1550 | −int is_dir(file_info_t *info) | |
| 1551 | −{ | |
| 1552 | −#ifndef _WIN32 | |
| 1553 | − return S_ISDIR(info->st_mode); | |
| 1554 | −#else | |
| 1555 | − return (info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == | |
| 1556 | − FILE_ATTRIBUTE_DIRECTORY; | |
| 1557 | −#endif | |
| 1558 | −} | |
| 1559 | − | |
| 1560 | −int is_same_file(const file_info_t *fi1, const file_info_t *fi2) | |
| 1561 | −{ | |
| 1562 | −#ifndef _WIN32 | |
| 1563 | − return fi1->st_dev == fi2->st_dev && | |
| 1564 | − fi1->st_ino == fi2->st_ino; | |
| 1565 | −#else | |
| 1566 | − return fi1->dwVolumeSerialNumber == fi2->dwVolumeSerialNumber && | |
| 1567 | − fi1->nFileIndexHigh == fi2->nFileIndexHigh && | |
| 1568 | − fi1->nFileIndexLow == fi2->nFileIndexLow; | |
| 1569 | −#endif | |
| 1570 | −} | |
| 1571 | − | |
| 1572 | −static void | |
| 1573 | −tcc_normalize_inc_dirs_aux(file_info_t *stats, size_t *pnum, char **path) | |
| 1574 | −{ | |
| 1575 | − size_t i, num = *pnum; | |
| 1576 | − if (get_file_info(*path, &stats[num]) || !is_dir(&stats[num])) | |
| 1577 | − goto remove; | |
| 1578 | − for (i = 0; i < num; i++) | |
| 1579 | − if (is_same_file(&stats[i], &stats[num])) | |
| 1580 | − goto remove; | |
| 1581 | − *pnum = num + 1; | |
| 1582 | − return; | |
| 1583 | − remove: | |
| 1584 | − tcc_free(*path); | |
| 1585 | − *path = 0; | |
| 1586 | −} | |
| 1587 | − | |
| 1588 | −/* Remove non-existent and duplicate directories from include paths. */ | |
| 1589 | −ST_FUNC void tcc_normalize_inc_dirs(TCCState *s) | |
| 1590 | −{ | |
| 1591 | − file_info_t *stats = | |
| 1592 | − tcc_malloc(((size_t)s->nb_sysinclude_paths + s->nb_include_paths) * | |
| 1593 | − sizeof(*stats)); | |
| 1594 | − size_t i, num = 0; | |
| 1595 | − for (i = 0; i < s->nb_sysinclude_paths; i++) | |
| 1596 | − tcc_normalize_inc_dirs_aux(stats, &num, &s->sysinclude_paths[i]); | |
| 1597 | − for (i = 0; i < s->nb_include_paths; i++) | |
| 1598 | − tcc_normalize_inc_dirs_aux(stats, &num, &s->include_paths[i]); | |
| 1599 | − tcc_free(stats); | |
| 1600 | −} | |
| 1601 | − | |
| 1602 | 1511 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) |
| 1603 | 1512 | { |
| 1604 | 1513 | s->output_type = output_type; |
| @@ -1664,7 +1573,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 59 unmodified lines | ||
| 1664 | 1573 | } |
| 1665 | 1574 | #endif |
| 1666 | 1575 | |
| 1667 | − tcc_normalize_inc_dirs(s); | |
| 1668 | 1576 | if (s->output_type == TCC_OUTPUT_PREPROCESS) |
| 1669 | 1577 | print_defines(); |
| 1670 | 1578 | |
| @@ -536,10 +536,10 @@ typedef struct BufferedFile { · 535 unmodified lines | ||
| 536 | 536 | struct BufferedFile *prev; |
| 537 | 537 | int line_num; /* current line number - here to simplify code */ |
| 538 | 538 | int line_ref; /* tcc -E: last printed line */ |
| 539 | − int inc_path_index; | |
| 540 | 539 | int ifndef_macro; /* #ifndef macro / #endif search */ |
| 541 | 540 | int ifndef_macro_saved; /* saved ifndef_macro */ |
| 542 | 541 | int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ |
| 542 | + int include_next_index; /* next search path */ | |
| 543 | 543 | char filename[1024]; /* filename */ |
| 544 | 544 | unsigned char unget[4]; |
| 545 | 545 | unsigned char buffer[1]; /* extra size for CH_EOB char */ |
| @@ -1578,13 +1578,14 @@ ST_FUNC void preprocess(int is_bof) · 1577 unmodified lines | ||
| 1578 | 1578 | case TOK_INCLUDE: |
| 1579 | 1579 | case TOK_INCLUDE_NEXT: |
| 1580 | 1580 | ch = file->buf_ptr[0]; |
| 1581 | − skip_spaces(); /* XXX: incorrect if comments : use next_nomacro with a special mode */ | |
| 1582 | − c = 0; | |
| 1583 | − if (ch == '<') | |
| 1581 | + /* XXX: incorrect if comments : use next_nomacro with a special mode */ | |
| 1582 | + skip_spaces(); | |
| 1583 | + if (ch == '<') { | |
| 1584 | 1584 | c = '>'; |
| 1585 | − if (ch == '\"') | |
| 1585 | + goto read_name; | |
| 1586 | + } else if (ch == '\"') { | |
| 1586 | 1587 | c = ch; |
| 1587 | − if (c) { | |
| 1588 | + read_name: | |
| 1588 | 1589 | inp(); |
| 1589 | 1590 | q = buf; |
| 1590 | 1591 | while (ch != c && ch != '\n' && ch != CH_EOF) { |
| @@ -1598,6 +1599,12 @@ ST_FUNC void preprocess(int is_bof) · 7 unmodified lines | ||
| 1598 | 1599 | } |
| 1599 | 1600 | *q = '\0'; |
| 1600 | 1601 | minp(); |
| 1602 | +#if 0 | |
| 1603 | + /* eat all spaces and comments after include */ | |
| 1604 | + /* XXX: slightly incorrect */ | |
| 1605 | + while (ch1 != '\n' && ch1 != CH_EOF) | |
| 1606 | + inp(); | |
| 1607 | +#endif | |
| 1601 | 1608 | } else { |
| 1602 | 1609 | /* computed #include : either we have only strings or |
| 1603 | 1610 | we have anything enclosed in '<>' */ |
| @@ -1631,25 +1638,22 @@ ST_FUNC void preprocess(int is_bof) · 27 unmodified lines | ||
| 1631 | 1638 | |
| 1632 | 1639 | if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE) |
| 1633 | 1640 | tcc_error("#include recursion too deep"); |
| 1634 | − | |
| 1635 | − i = -2; | |
| 1636 | − if (tok == TOK_INCLUDE_NEXT) | |
| 1637 | − i = file->inc_path_index + 1; | |
| 1638 | − | |
| 1639 | − n = s1->nb_include_paths + s1->nb_sysinclude_paths; | |
| 1641 | + /* store current file in stack, but increment stack later below */ | |
| 1642 | + *s1->include_stack_ptr = file; | |
| 1643 | + i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0; | |
| 1644 | + n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths; | |
| 1640 | 1645 | for (; i < n; ++i) { |
| 1641 | 1646 | char buf1[sizeof file->filename]; |
| 1642 | 1647 | CachedInclude *e; |
| 1643 | 1648 | const char *path; |
| 1644 | 1649 | |
| 1645 | − if (i == -2) { | |
| 1650 | + if (i == 0) { | |
| 1646 | 1651 | /* check absolute include path */ |
| 1647 | 1652 | if (!IS_ABSPATH(buf)) |
| 1648 | 1653 | continue; |
| 1649 | 1654 | buf1[0] = 0; |
| 1650 | − i = n - 1; /* force end loop */ | |
| 1651 | 1655 | |
| 1652 | − } else if (i == -1) { | |
| 1656 | + } else if (i == 1) { | |
| 1653 | 1657 | /* search in current dir if "header.h" */ |
| 1654 | 1658 | if (c != '\"') |
| 1655 | 1659 | continue; |
| @@ -1658,40 +1662,45 @@ ST_FUNC void preprocess(int is_bof) · 2 unmodified lines | ||
| 1658 | 1662 | |
| 1659 | 1663 | } else { |
| 1660 | 1664 | /* search in all the include paths */ |
| 1661 | − if (i < s1->nb_include_paths) | |
| 1662 | − path = s1->include_paths[i]; | |
| 1663 | − else | |
| 1664 | − path = s1->sysinclude_paths[i - s1->nb_include_paths]; | |
| 1665 | − if (path == 0) continue; | |
| 1665 | + int j = i - 2, k = j - s1->nb_include_paths; | |
| 1666 | + path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k]; | |
| 1666 | 1667 | pstrcpy(buf1, sizeof(buf1), path); |
| 1667 | 1668 | pstrcat(buf1, sizeof(buf1), "/"); |
| 1668 | 1669 | } |
| 1669 | 1670 | |
| 1670 | 1671 | pstrcat(buf1, sizeof(buf1), buf); |
| 1671 | 1672 | e = search_cached_include(s1, buf1); |
| 1672 | − if (e && (define_find(e->ifndef_macro) || e->ifndef_macro == TOK_once)) | |
| 1673 | − break; /* no need to parse the include */ | |
| 1673 | + if (e && (define_find(e->ifndef_macro) || e->ifndef_macro == TOK_once)) { | |
| 1674 | + /* no need to parse the include because the 'ifndef macro' | |
| 1675 | + is defined */ | |
| 1676 | +#ifdef INC_DEBUG | |
| 1677 | + printf("%s: skipping cached %s\n", file->filename, buf1); | |
| 1678 | +#endif | |
| 1679 | + goto include_done; | |
| 1680 | + } | |
| 1674 | 1681 | |
| 1675 | 1682 | if (tcc_open(s1, buf1) < 0) |
| 1676 | 1683 | continue; |
| 1677 | 1684 | |
| 1678 | − file->inc_path_index = i; | |
| 1679 | − *(s1->include_stack_ptr++) = file->prev; | |
| 1680 | − | |
| 1685 | + file->include_next_index = i + 1; | |
| 1686 | +#ifdef INC_DEBUG | |
| 1687 | + printf("%s: including %s\n", file->prev->filename, file->filename); | |
| 1688 | +#endif | |
| 1681 | 1689 | /* update target deps */ |
| 1682 | 1690 | dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, |
| 1683 | − tcc_strdup(buf1)); | |
| 1684 | − | |
| 1691 | + tcc_strdup(buf1)); | |
| 1692 | + /* push current file in stack */ | |
| 1693 | + ++s1->include_stack_ptr; | |
| 1685 | 1694 | /* add include file debug info */ |
| 1686 | 1695 | if (s1->do_debug) |
| 1687 | 1696 | put_stabs(file->filename, N_BINCL, 0, 0, 0); |
| 1688 | − | |
| 1689 | 1697 | tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL; |
| 1690 | 1698 | ch = file->buf_ptr[0]; |
| 1691 | − break; | |
| 1699 | + goto the_end; | |
| 1692 | 1700 | } |
| 1693 | − if (i >= n) tcc_error("include file '%s' not found", buf); | |
| 1694 | − goto the_end; | |
| 1701 | + tcc_error("include file '%s' not found", buf); | |
| 1702 | +include_done: | |
| 1703 | + break; | |
| 1695 | 1704 | case TOK_IFNDEF: |
| 1696 | 1705 | c = 1; |
| 1697 | 1706 | goto do_ifdef; |
| @@ -1706,9 +1715,9 @@ ST_FUNC void preprocess(int is_bof) · 8 unmodified lines | ||
| 1706 | 1715 | tcc_error("invalid argument for '#if%sdef'", c ? "n" : ""); |
| 1707 | 1716 | if (is_bof) { |
| 1708 | 1717 | if (c) { |
| 1709 | − #ifdef INC_DEBUG | |
| 1710 | − printf("#ifndef %s\n", get_tok_str(tok, NULL)); | |
| 1711 | − #endif | |
| 1718 | +#ifdef INC_DEBUG | |
| 1719 | + printf("#ifndef %s\n", get_tok_str(tok, NULL)); | |
| 1720 | +#endif | |
| 1712 | 1721 | file->ifndef_macro = tok; |
| 1713 | 1722 | } |
| 1714 | 1723 | } |
| @@ -2538,8 +2547,10 @@ maybe_newline: · 823 unmodified lines | ||
| 2538 | 2547 | cstr_reset(&tokcstr); |
| 2539 | 2548 | cstr_ccat(&tokcstr, '.'); |
| 2540 | 2549 | goto parse_num; |
| 2541 | − } else if ((c == '.') && (p[1] == '.')){ | |
| 2550 | + } else if (c == '.') { | |
| 2542 | 2551 | PEEKC(c, p); |
| 2552 | + if (c != '.') | |
| 2553 | + expect("'.'"); | |
| 2543 | 2554 | PEEKC(c, p); |
| 2544 | 2555 | tok = TOK_DOTS; |
| 2545 | 2556 | } else { |