summaryrefslogtreecommitdiff
path: root/tiger-compiler/lib/misc/file-library.cc
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/lib/misc/file-library.cc
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/lib/misc/file-library.cc')
-rw-r--r--tiger-compiler/lib/misc/file-library.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/tiger-compiler/lib/misc/file-library.cc b/tiger-compiler/lib/misc/file-library.cc
new file mode 100644
index 0000000..fe344d0
--- /dev/null
+++ b/tiger-compiler/lib/misc/file-library.cc
@@ -0,0 +1,152 @@
+/**
+ ** \file misc/file-library.cc
+ ** \brief Implements misc::file_library.
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include <stdexcept>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <misc/contract.hh>
+#include <misc/file-library.hh>
+
+namespace misc
+{
+ void file_library::push_cwd()
+ {
+ // Store the working directory
+ char cwd[MAXPATHLEN + 1];
+
+ if (nullptr == getcwd(cwd, MAXPATHLEN + 1))
+ throw std::runtime_error("working directory name too long");
+
+ push_current_directory(path(std::string(cwd)));
+ }
+
+ file_library::file_library() { push_cwd(); }
+
+ file_library::file_library(path p)
+ {
+ push_cwd();
+ // Then only process given path.
+ search_path_.emplace_back(p);
+ }
+
+ void file_library::append_dir_list(std::string path_list)
+ {
+ std::string::size_type pos;
+
+ while ((pos = path_list.find(':')) != std::string::npos)
+ {
+ append_dir(path_list.substr(0, pos));
+ path_list.erase(0, pos + 1);
+ }
+ append_dir(path_list);
+ }
+
+ path file_library::ensure_absolute_path(path p) const
+ {
+ if (p.is_absolute())
+ return p;
+ else
+ return current_directory_get() / p;
+ }
+
+ void file_library::append_dir(path p)
+ {
+ search_path_.emplace_back(ensure_absolute_path(p));
+ }
+
+ void file_library::prepend_dir(path p)
+ {
+ search_path_.insert(search_path_.begin(), ensure_absolute_path(p));
+ }
+
+ void file_library::push_current_directory(path p)
+ {
+ // Ensure that path is absolute.
+ if (!p.is_absolute())
+ p = current_directory_get() / p;
+
+ current_directory_.insert(current_directory_.begin(), p);
+ }
+
+ void file_library::pop_current_directory()
+ {
+ precondition(!current_directory_.empty());
+
+ current_directory_.erase(current_directory_.begin());
+ }
+
+ path file_library::current_directory_get() const
+ {
+ precondition(!current_directory_.empty());
+
+ return current_directory_.front();
+ }
+
+ path file_library::find_file(const std::string& file)
+ {
+ // Split file in two components, basename and basedir.
+ path p = path(file);
+ path directory = p.filename();
+
+ if (directory.is_absolute())
+ {
+ // If file is absolute, just check that it exists.
+ if (!std::filesystem::exists(path(file)))
+ return path();
+ }
+ else
+ {
+ // Does the file can be found in current directory?
+ if (find_in_directory(current_directory_get(), file))
+ return (current_directory_get() / file).parent_path();
+
+ directory = find_in_search_path(directory, p.filename().string());
+ }
+
+ return directory;
+ }
+
+ bool file_library::find_in_directory(const path& dir,
+ const std::string& file) const
+ {
+ return std::filesystem::exists(path(dir / file));
+ }
+
+ path file_library::find_in_search_path(const path& relative_path,
+ const std::string& filename) const
+ {
+ path checked_dir;
+
+ // Otherwise start scanning the search path.
+ for (const path& p : search_path_)
+ {
+ if (p.is_absolute())
+ checked_dir = p;
+ else
+ checked_dir = current_directory_get() / p;
+
+ checked_dir /= relative_path;
+
+ if (find_in_directory(checked_dir, filename))
+ return checked_dir;
+ }
+
+ // File not found in search path.
+ return path();
+ }
+
+ std::ostream& file_library::dump(std::ostream& ostr) const
+ {
+ ostr << ".";
+ for (const path& p : search_path_)
+ ostr << ":" << p;
+ return ostr;
+ }
+
+} // namespace misc