| @@ -1607,38 +1607,88 @@ bad_twosharp: · 1606 unmodified lines |
| 1607 | define_push(v, t, tok_str_dup(&tokstr_buf), first); | 1607 | define_push(v, t, tok_str_dup(&tokstr_buf), first); |
| 1608 | } | 1608 | } |
| 1609 | | 1609 | |
| | 1610 | #ifdef _WIN32 |
| | 1611 | static unsigned long long calc_file_hash(const char *filename) |
| | 1612 | { |
| | 1613 | unsigned long long hash = 14695981039346656037ull; // FNV_offset_basis; |
| | 1614 | FILE *fp = fopen (filename, "rb"); |
| | 1615 | |
| | 1616 | if (fp == NULL) |
| | 1617 | return 0; |
| | 1618 | for (;;) { |
| | 1619 | unsigned char temp[IO_BUF_SIZE]; |
| | 1620 | int i, n = fread(temp, 1, sizeof(temp), fp); |
| | 1621 | |
| | 1622 | if (n <= 0) |
| | 1623 | break; |
| | 1624 | for (i = 0; i < n; i++) |
| | 1625 | hash = hash * 1099511628211ull + temp[i]; // FNV_prime |
| | 1626 | } |
| | 1627 | fclose(fp); |
| | 1628 | if (hash == 0) |
| | 1629 | hash = 1; |
| | 1630 | return hash; |
| | 1631 | } |
| | 1632 | #endif |
| | 1633 | |
| 1610 | static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add) | 1634 | static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add) |
| 1611 | { | 1635 | { |
| 1612 | const unsigned char *s; | 1636 | unsigned int h = 0; |
| 1613 | unsigned int h; | | |
| 1614 | CachedInclude *e; | 1637 | CachedInclude *e; |
| 1615 | int i; | 1638 | int i; |
| 1616 | | 1639 | struct stat st; |
| 1617 | h = TOK_HASH_INIT; | | |
| 1618 | s = (unsigned char *) filename; | | |
| 1619 | while (*s) { | | |
| 1620 | #ifdef _WIN32 | 1640 | #ifdef _WIN32 |
| 1621 | h = TOK_HASH_FUNC(h, toup(*s)); | 1641 | unsigned long long hash = 0; |
| 1622 | #else | | |
| 1623 | h = TOK_HASH_FUNC(h, *s); | | |
| 1624 | #endif | 1642 | #endif |
| 1625 | s++; | 1643 | |
| | 1644 | /* This is needed for #pragmae once |
| | 1645 | * We cannot use stat on windows because st_ino is not set correctly |
| | 1646 | * so we calculate a hash of file contents. |
| | 1647 | * This also works for hard/soft links as in gcc/clang. |
| | 1648 | */ |
| | 1649 | memset (&st, 0, sizeof(st)); |
| | 1650 | if (stat (filename, &st)) |
| | 1651 | goto skip; |
| | 1652 | h = st.st_size & (CACHED_INCLUDES_HASH_SIZE - 1); |
| | 1653 | #ifdef _WIN32 |
| | 1654 | /* Only calculate file hash if file size same. */ |
| | 1655 | i = s1->cached_includes_hash[h]; |
| | 1656 | for(;;) { |
| | 1657 | if (i == 0) |
| | 1658 | break; |
| | 1659 | e = s1->cached_includes[i - 1]; |
| | 1660 | if (e->st.st_size == st.st_size) { |
| | 1661 | if (e->hash == 0) |
| | 1662 | e->hash = calc_file_hash(e->filename); |
| | 1663 | hash = calc_file_hash(filename); |
| | 1664 | break; |
| | 1665 | } |
| | 1666 | i = e->hash_next; |
| 1626 | } | 1667 | } |
| 1627 | h &= (CACHED_INCLUDES_HASH_SIZE - 1); | 1668 | #endif |
| 1628 | | 1669 | |
| 1629 | i = s1->cached_includes_hash[h]; | 1670 | i = s1->cached_includes_hash[h]; |
| 1630 | for(;;) { | 1671 | for(;;) { |
| 1631 | if (i == 0) | 1672 | if (i == 0) |
| 1632 | break; | 1673 | break; |
| 1633 | e = s1->cached_includes[i - 1]; | 1674 | e = s1->cached_includes[i - 1]; |
| 1634 | if (0 == PATHCMP(e->filename, filename)) | 1675 | #ifdef _WIN32 |
| | 1676 | if (e->st.st_size == st.st_size && e->hash == hash) |
| | 1677 | #else |
| | 1678 | if (st.st_dev == e->st.st_dev && st.st_ino == e->st.st_ino) |
| | 1679 | #endif |
| 1635 | return e; | 1680 | return e; |
| 1636 | i = e->hash_next; | 1681 | i = e->hash_next; |
| 1637 | } | 1682 | } |
| | 1683 | skip: |
| 1638 | if (!add) | 1684 | if (!add) |
| 1639 | return NULL; | 1685 | return NULL; |
| 1640 | | 1686 | |
| 1641 | e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); | 1687 | e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); |
| | 1688 | e->st = st; |
| | 1689 | #ifdef _WIN32 |
| | 1690 | e->hash = hash; |
| | 1691 | #endif |
| 1642 | strcpy(e->filename, filename); | 1692 | strcpy(e->filename, filename); |
| 1643 | e->ifndef_macro = e->once = 0; | 1693 | e->ifndef_macro = e->once = 0; |
| 1644 | dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e); | 1694 | dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e); |