diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-12-09 18:59:38 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-12-11 17:17:58 +0100 |
commit | 6d799f0aed18be25a5c908499b6411ab6d06b78c (patch) | |
tree | 3e6a91048c7fe3e78bae9f75b24eb37c5504681b /gcc/d/dmd/file_manager.d | |
parent | cc7f509d3c0b3ab63891cf7ca2def0fdfb3642c4 (diff) | |
download | gcc-6d799f0aed18be25a5c908499b6411ab6d06b78c.zip gcc-6d799f0aed18be25a5c908499b6411ab6d06b78c.tar.gz gcc-6d799f0aed18be25a5c908499b6411ab6d06b78c.tar.bz2 |
d: Merge upstream dmd, druntime c8ae4adb2e, phobos 792c8b7c1.
D front-end changes:
- Import dmd v2.101.0.
- Deprecate the ability to call `__traits(getAttributes)' on
overload sets.
- Deprecate non-empty `for' statement increment clause with no
effect.
- Array literals assigned to `scope' array variables can now be
allocated on the stack.
D runtime changes:
- Import druntime v2.101.0.
Phobos changes:
- Import phobos v2.101.0.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd c8ae4adb2e.
* typeinfo.cc (check_typeinfo_type): Update for new front-end
interface.
(TypeInfoVisitor::visit (TypeInfoStructDeclaration *)): Remove warning
that toHash() must be declared 'nothrow @safe`.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime c8ae4adb2e.
* src/MERGE: Merge upstream phobos 792c8b7c1.
Diffstat (limited to 'gcc/d/dmd/file_manager.d')
-rw-r--r-- | gcc/d/dmd/file_manager.d | 138 |
1 files changed, 116 insertions, 22 deletions
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d index 0ea7303..a941115 100644 --- a/gcc/d/dmd/file_manager.d +++ b/gcc/d/dmd/file_manager.d @@ -12,7 +12,7 @@ module dmd.file_manager; import dmd.root.stringtable : StringTable; import dmd.root.file : File, Buffer; -import dmd.root.filename : FileName; +import dmd.root.filename : FileName, isDirSeparator; import dmd.root.string : toDString; import dmd.globals; import dmd.identifier; @@ -26,14 +26,86 @@ bool isPackageFileName(scope FileName fileName) nothrow return FileName.equals(fileName.name, package_d) || FileName.equals(fileName.name, package_di); } +// A path stack that allows one to go up and down the path using directory +// separators. `cur` is the current path, `up` goes up one path, `down` goes +// down one path. if `up` or `down` return false, there are no further paths. +private struct PathStack +{ + private const(char)[] path; + private size_t pos; + + @safe @nogc nothrow pure: + + this(const(char)[] p) + { + path = p; + pos = p.length; + } + + const(char)[] cur() + { + return path[0 .. pos]; + } + + bool up() + { + if (pos == 0) + return false; + while (--pos != 0) + if (isDirSeparator(path[pos])) + return true; + return false; + } + + bool down() + { + if (pos == path.length) + return false; + while (++pos != path.length) + if (isDirSeparator(path[pos])) + return true; + return false; + } +} + final class FileManager { private StringTable!(const(ubyte)[]) files; + private StringTable!(bool) packageStatus; + + // check if the package path of the given path exists. The input path is + // expected to contain the full path to the module, so the parent + // directories of that path are checked. + private bool packageExists(const(char)[] p) nothrow + { + // step 1, look for the closest parent path that is cached + bool exists = true; + auto st = PathStack(p); + while (st.up) { + if (auto cached = packageStatus.lookup(st.cur)) { + exists = cached.value; + break; + } + } + // found a parent that is cached (or reached the end of the stack). + // step 2, traverse back up the stack storing either false if the + // parent doesn't exist, or the result of the `exists` call if it does. + while (st.down) { + if (!exists) + packageStatus.insert(st.cur, false); + else + exists = packageStatus.insert(st.cur, FileName.exists(st.cur) == 2).value; + } + + // at this point, exists should be the answer. + return exists; + } /// public this () nothrow { this.files._init(); + this.packageStatus._init(); } nothrow: @@ -48,13 +120,15 @@ nothrow: * the found file name or * `null` if it is not different from filename. */ - static const(char)[] lookForSourceFile(const char[] filename, const char*[] path) + const(char)[] lookForSourceFile(const char[] filename, const char*[] path) { //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr); /* Search along path[] for .di file, then .d file, then .i file, then .c file. */ + // see if we should check for the module locally. + bool checkLocal = packageExists(filename); const sdi = FileName.forceExt(filename, hdr_ext); - if (FileName.exists(sdi) == 1) + if (checkLocal && FileName.exists(sdi) == 1) return sdi; scope(exit) FileName.free(sdi.ptr); @@ -62,36 +136,43 @@ nothrow: // Special file name representing `stdin`, always assume its presence if (sd == "__stdin.d") return sd; - if (FileName.exists(sd) == 1) + if (checkLocal && FileName.exists(sd) == 1) return sd; scope(exit) FileName.free(sd.ptr); const si = FileName.forceExt(filename, i_ext); - if (FileName.exists(si) == 1) + if (checkLocal && FileName.exists(si) == 1) return si; scope(exit) FileName.free(si.ptr); const sc = FileName.forceExt(filename, c_ext); - if (FileName.exists(sc) == 1) + if (checkLocal && FileName.exists(sc) == 1) return sc; scope(exit) FileName.free(sc.ptr); - if (FileName.exists(filename) == 2) + if (checkLocal) { - /* The filename exists and it's a directory. - * Therefore, the result should be: filename/package.d - * iff filename/package.d is a file - */ - const ni = FileName.combine(filename, package_di); - if (FileName.exists(ni) == 1) - return ni; - FileName.free(ni.ptr); - - const n = FileName.combine(filename, package_d); - if (FileName.exists(n) == 1) - return n; - FileName.free(n.ptr); + auto cached = packageStatus.lookup(filename); + if (!cached) + cached = packageStatus.insert(filename, FileName.exists(filename) == 2); + if (cached.value) + { + /* The filename exists and it's a directory. + * Therefore, the result should be: filename/package.d + * iff filename/package.d is a file + */ + const ni = FileName.combine(filename, package_di); + if (FileName.exists(ni) == 1) + return ni; + FileName.free(ni.ptr); + + const n = FileName.combine(filename, package_d); + if (FileName.exists(n) == 1) + return n; + FileName.free(n.ptr); + } } + if (FileName.absolute(filename)) return null; if (!path.length) @@ -101,6 +182,11 @@ nothrow: const p = entry.toDString(); const(char)[] n = FileName.combine(p, sdi); + + if (!packageExists(n)) { + FileName.free(n.ptr); + continue; // no need to check for anything else. + } if (FileName.exists(n) == 1) { return n; } @@ -127,7 +213,16 @@ nothrow: const b = FileName.removeExt(filename); n = FileName.combine(p, b); FileName.free(b.ptr); - if (FileName.exists(n) == 2) + + scope(exit) FileName.free(n.ptr); + + // also cache this if we are looking for package.d[i] + auto cached = packageStatus.lookup(n); + if (!cached) { + cached = packageStatus.insert(n, FileName.exists(n) == 2); + } + + if (cached.value) { const n2i = FileName.combine(n, package_di); if (FileName.exists(n2i) == 1) @@ -139,7 +234,6 @@ nothrow: } FileName.free(n2.ptr); } - FileName.free(n.ptr); } return null; } |