aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/common/file.d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/common/file.d')
-rw-r--r--gcc/d/dmd/common/file.d171
1 files changed, 170 insertions, 1 deletions
diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d
index 80677f6..52da6ee 100644
--- a/gcc/d/dmd/common/file.d
+++ b/gcc/d/dmd/common/file.d
@@ -14,15 +14,23 @@
module dmd.common.file;
+import core.stdc.stdio;
+import core.stdc.stdlib;
+import core.stdc.string;
+import core.stdc.limits;
+
import core.stdc.errno : errno;
import core.stdc.stdio : fprintf, remove, rename, stderr;
import core.stdc.stdlib;
import core.stdc.string : strerror, strlen, memcpy;
import dmd.common.smallbuffer;
+import dmd.root.filename;
+import dmd.root.rmem;
version (Windows)
{
+ import core.stdc.wchar_;
import core.sys.windows.winbase;
import core.sys.windows.winnls : CP_ACP;
import core.sys.windows.winnt;
@@ -32,6 +40,7 @@ version (Windows)
}
else version (Posix)
{
+ import core.sys.posix.dirent;
import core.sys.posix.fcntl;
import core.sys.posix.sys.mman;
import core.sys.posix.sys.stat;
@@ -566,7 +575,7 @@ else version (Windows)
private ulong fileSize(HANDLE fd)
{
ulong result;
- if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
+ if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result))
return result;
return ulong.max;
}
@@ -587,3 +596,163 @@ private auto ref fakePure(F)(scope F fun) pure
mixin("alias PureFun = " ~ F.stringof ~ " pure;");
return (cast(PureFun) fun)();
}
+
+/***********************************
+ * Recursively search all the directories and files under dir_path
+ * for files that match one of the extensions in exts[].
+ * Pass the matches to sink.
+ * Params:
+ * dir_path = root of directories to search
+ * exts = array of filename extensions to match
+ * recurse = go into subdirectories
+ * filenameSink = accepts the resulting matches
+ * Returns:
+ * true for failed to open the directory
+ */
+bool findFiles(const char* dir_path, const char[][] exts, bool recurse, void delegate(const(char)[]) nothrow filenameSink)
+{
+ enum log = false;
+ if (log) printf("findFiles() dir_path: %s\n", dir_path);
+ version (Windows)
+ {
+ debug
+ enum BufLength = 10; // trigger any reallocation bugs
+ else
+ enum BufLength = 100;
+ char[BufLength + 1] buf = void;
+ char* fullPath = buf.ptr;
+ size_t fullPathLength = BufLength;
+
+ // fullPath = dir_path \ *.*
+ const dir_pathLength = strlen(dir_path);
+ auto count = dir_pathLength + 1 + 3;
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ memcpy(fullPath, dir_path, dir_pathLength);
+ strcpy(fullPath + dir_pathLength, "\\*.*".ptr);
+
+ if (log) printf("fullPath: %s\n", fullPath);
+
+ WIN32_FIND_DATAW ffd = void;
+ HANDLE hFind = fullPath[0 .. strlen(fullPath)].extendedPathThen!(p => FindFirstFileW(p.ptr, &ffd));
+ if (hFind == INVALID_HANDLE_VALUE)
+ return true;
+
+ do
+ {
+ if (log) wprintf("ffd.cFileName: %s\n", ffd.cFileName.ptr);
+ if (ffd.cFileName[0] == 0)
+ continue; // ignore
+
+ if (ffd.cFileName[0] == '.')
+ continue; // ignore files that start with a ., also ignore . and .. directories
+
+ const(char)[] name = toNarrowStringz(ffd.cFileName[0 .. wcslen(ffd.cFileName.ptr)], null);
+ if (log) printf("name: %s\n", name.ptr);
+
+ // fullPath = dir_path \ name.ptr
+ count = dir_pathLength + 1 + name.length;
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ strcpy(fullPath + dir_pathLength + 1, name.ptr);
+
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (recurse)
+ findFiles(fullPath, exts, recurse, filenameSink);
+ }
+ else
+ {
+ const(char)[] nameExt = FileName.ext(name);
+ foreach (ext; exts[])
+ {
+ if (nameExt == ext)
+ {
+ if (log) printf("adding %s\n", fullPath);
+ filenameSink(fullPath[0 .. count]);
+ }
+ }
+ }
+ mem.xfree(cast(void*)name.ptr);
+
+ } while (FindNextFileW(hFind, &ffd) != 0);
+
+ if (fullPath != buf.ptr)
+ mem.xfree(fullPath);
+ FindClose(hFind);
+ if (log) printf("findFiles() exit\n");
+ return false;
+ }
+ else version (Posix)
+ {
+ DIR* dir = opendir(dir_path);
+ if (!dir)
+ return true;
+
+ debug
+ enum BufLength = 10; // trigger any reallocation bugs
+ else
+ enum BufLength = 100;
+ char[BufLength + 1] buf = void;
+ char* fullPath = buf.ptr;
+ size_t fullPathLength = BufLength;
+
+ dirent* entry;
+ while ((entry = readdir(dir)) != null)
+ {
+ //printf("entry: %s\n", entry.d_name.ptr);
+ if (entry.d_name[0] == '.')
+ continue; // ignore files that start with a .
+
+ // fullPath = dir_path / entry.d_name.ptr
+ const dir_pathLength = strlen(dir_path);
+ const count = dir_pathLength + 1 + strlen(entry.d_name.ptr);
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ memcpy(fullPath, dir_path, dir_pathLength);
+ fullPath[dir_pathLength] = '/';
+ strcpy(fullPath + dir_pathLength + 1, entry.d_name.ptr);
+
+ stat_t statbuf;
+ if (lstat(fullPath, &statbuf) == -1)
+ continue;
+
+ const(char)[] name = entry.d_name.ptr[0 .. strlen(entry.d_name.ptr)]; // convert to D string
+ if (!name.length)
+ continue; // ignore
+
+ if (S_ISDIR(statbuf.st_mode))
+ {
+ if (recurse && !(name == "." || name == ".."))
+ findFiles(fullPath, exts, recurse, filenameSink);
+ }
+ else if (S_ISREG(statbuf.st_mode))
+ {
+ foreach (ext; exts)
+ {
+ if (FileName.ext(name) == ext)
+ {
+ //printf("%s\n", fullPath);
+ filenameSink(fullPath[0 .. count]);
+ }
+ }
+ }
+ }
+
+ if (fullPath != buf.ptr)
+ mem.xfree(fullPath);
+ closedir(dir);
+ return false;
+ }
+ else
+ static assert(0);
+}