History

Allow different names for pragma once

pragma once can now be used with test.h ./test.h and other references to the same file just like gcc/clang. On linux we can use stat and st_ino to check for the same file. On windows the st_ino does not work so we calculate a file hash if the size of the file differs and then compare the hash.

herman ten brugge committed 3 years ago

Commit 30fd24a1 parent 5077d4c5 files · +74 −12Browse files

Unified · Split

5 files
  1. tcc.h +5 −0
  2. tccpp.c +62 −12
  3. tests/tests2/18_include.c +4 −0
  4. tests/tests2/18_include.expect +1 −0
  5. tests/tests2/18_include2.h +2 −0
tcc.h+5−0
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#include <fcntl.h>38#include <fcntl.h>
39#include <setjmp.h>39#include <setjmp.h>
40#include <time.h>40#include <time.h>
41#include <sys/stat.h>
41 42
42#ifndef _WIN3243#ifndef _WIN32
43# include <unistd.h>44# include <unistd.h>
@@ -716,6 +717,10 @@ typedef struct InlineFunc { · 672 unmodified lines
716/* include file cache, used to find files faster and also to eliminate717/* include file cache, used to find files faster and also to eliminate
717 inclusion if the include file is protected by #ifndef ... #endif */718 inclusion if the include file is protected by #ifndef ... #endif */
718typedef struct CachedInclude {719typedef struct CachedInclude {
720 struct stat st;
721#ifdef _WIN32
722 unsigned long long hash;
723#endif
719 int ifndef_macro;724 int ifndef_macro;
720 int once;725 int once;
721 int hash_next; /* -1 if none */726 int hash_next; /* -1 if none */
tccpp.c+62−12
@@ -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
1611static 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
1610static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add)1634static 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 _WIN321640#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#endif1642#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 }
1683skip:
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);
tests/tests2/18_include.c+4−0
@@ -37,6 +37,10 @@ int main() · 36 unmodified lines
37#endif37#endif
38#endif38#endif
39 39
40#include "18_include2.h"
41#include "./18_include2.h"
42#include "../tests2/18_include2.h"
43
40 return 0;44 return 0;
41}45}
42 46
tests/tests2/18_include.expect+1−0
@@ -5,3 +5,4 @@ has_include · 4 unmodified lines
5has_include5has_include
6has_include_next6has_include_next
7has_include_next7has_include_next
8counter 0
tests/tests2/18_include2.h+2−0
@@ -0,0 +1,2 @@
1#pragma once
2printf ("counter %d\n", __COUNTER__);

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