summaryrefslogtreecommitdiff
path: root/src/util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cc')
-rw-r--r--src/util.cc310
1 files changed, 241 insertions, 69 deletions
diff --git a/src/util.cc b/src/util.cc
index 92560b6..a4abd23 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -5,105 +5,70 @@
#include <iostream>
#include <fstream>
+#include <algorithm>
+#include <sstream>
+#include <cctype>
+#include <cstdlib>
+
+std::string to_lower(std::string str)
+{
+ std::transform(str.begin(), str.end(), str.begin(),
+ [](unsigned char c)
+ {
+ return std::tolower(c);
+ });
+ return str;
+}
std::string readFile(const std::string& fileName)
{
std::ifstream ifs(fileName.c_str(),
std::ios::in | std::ios::binary | std::ios::ate);
- std::ifstream::pos_type fileSize = ifs.tellg();
+ auto size = ifs.tellg();
+ if(size < 0)
+ {
+ return {};
+ }
ifs.seekg(0, std::ios::beg);
- std::vector<char> bytes(fileSize);
- ifs.read(bytes.data(), fileSize);
+ std::string bytes(static_cast<std::size_t>(size), '\0');
+ ifs.read(bytes.data(), static_cast<std::streamsize>(bytes.size()));
- return std::string(bytes.data(), fileSize);
+ return bytes;
}
-std::vector<std::string> readDeps(const std::string& depFile)
+ctor::language languageFromExtension(const std::filesystem::path& file)
{
- if(!std::filesystem::exists(depFile))
- {
- return {};
- }
-
- auto str = readFile(depFile);
+ auto ext = file.extension().string();
- std::vector<std::string> output;
- std::string tmp;
- bool start{false};
- bool in_whitespace{false};
- for(const auto& c : str)
+ // First a few case sensitive comparisons
+ if(ext == ".c")
{
- if(c == '\\' || c == '\n')
- {
- continue;
- }
-
- if(c == ':')
- {
- start = true;
- continue;
- }
-
- if(!start)
- {
- continue;
- }
-
- if(c == ' ' || c == '\t')
- {
- if(in_whitespace)
- {
- continue;
- }
-
- if(!tmp.empty())
- {
- output.push_back(tmp);
- }
- tmp.clear();
- in_whitespace = true;
- }
- else
- {
- in_whitespace = false;
- tmp += c;
- }
+ return ctor::language::c;
}
- if(!tmp.empty())
+ if(ext == ".C")
{
- output.push_back(tmp);
+ return ctor::language::cpp;
}
- return output;
-}
-
-Language languageFromExtension(const std::filesystem::path& file)
-{
- auto ext = file.extension().string();
- if(ext == ".c")
- {
- return Language::C;
- }
+ // The rest are compared in lowercase
+ ext = to_lower(ext);
- if(ext == ".C" ||
- ext == ".cc" ||
+ if(ext == ".cc" ||
ext == ".cpp" ||
- ext == ".CPP" ||
ext == ".c++" ||
ext == ".cp" ||
ext == ".cxx")
{
- return Language::Cpp;
+ return ctor::language::cpp;
}
if(ext == ".s" ||
- ext == ".S" ||
ext == ".asm")
{
- return Language::Asm;
+ return ctor::language::assembler;
}
std::cerr << "Could not deduce language from " << file.string() << "\n";
@@ -135,3 +100,210 @@ std::string cleanUp(const std::string& path)
}
return cleaned;
}
+
+std::string esc(const std::string& in)
+{
+ std::string out;
+ for(auto c : in)
+ {
+ switch(c)
+ {
+ case '\\': out += "\\\\"; break;
+ case '"': out += "\\\""; break;
+ default:
+ out += c;
+ break;
+ }
+ }
+ return out;
+}
+
+std::vector<std::string> get_paths(const std::string& path_env_)
+{
+ std::string path_env;
+ if(!path_env_.empty())
+ {
+ path_env = path_env_;
+ }
+ else
+ {
+ get_env("PATH", path_env);
+ }
+
+ std::vector<std::string> paths;
+
+#ifdef _WIN32
+ const char sep{';'};
+#else
+ const char sep{':'};
+#endif
+
+ std::stringstream ss(path_env);
+ std::string path;
+ while (std::getline(ss, path, sep))
+ {
+ paths.push_back(path);
+ }
+
+ return paths;
+}
+
+bool check_executable(const std::filesystem::path& prog)
+{
+ auto perms = std::filesystem::status(prog).permissions();
+
+ if((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none)
+ {
+ return true;
+ }
+
+ if((perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none)
+ {
+ return true;
+ }
+
+ if((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+std::string locate(const std::string& prog,
+ const std::vector<std::string>& paths,
+ const std::string& arch)
+{
+ std::string program = prog;
+ if(!arch.empty())
+ {
+ program = arch + "-" + prog;
+ }
+
+ // first check if arch contains an absolute path to prog
+ if(std::filesystem::exists(program))
+ {
+ if(check_executable(program))
+ {
+ return program;
+ }
+ }
+
+ for(const auto& path_str : paths)
+ {
+ std::filesystem::path path(path_str);
+ auto prog_path = path / program;
+ if(std::filesystem::exists(prog_path))
+ {
+ if(check_executable(prog_path))
+ {
+ return prog_path.string();
+ }
+ }
+ }
+
+ return {};
+}
+
+std::vector<std::string> argsplit(const std::string& str)
+{
+ enum class state
+ {
+ normal,
+ in_quot,
+ in_apotrophe,
+ } state{state::normal};
+ bool esc{false};
+
+ std::string token;
+ std::vector<std::string> tokens;
+ for(auto c : str)
+ {
+ switch(state)
+ {
+ case state::normal:
+ if(esc)
+ {
+ esc = false;
+ }
+ else
+ {
+ if(c == ' ')
+ {
+ tokens.push_back(token);
+ token.clear();
+ continue;
+ }
+ if(c == '\\')
+ {
+ esc = true;
+ }
+ if(c == '"')
+ {
+ state = state::in_quot;
+ }
+ if(c == '\'')
+ {
+ state = state::in_apotrophe;
+ }
+ }
+
+ token += c;
+ break;
+ case state::in_quot:
+ if(esc)
+ {
+ esc = false;
+ }
+ else
+ {
+ if(c == '\\')
+ {
+ esc = true;
+ }
+ if(c == '"')
+ {
+ state = state::normal;
+ }
+ }
+
+ token += c;
+ break;
+ case state::in_apotrophe:
+ if(esc)
+ {
+ esc = false;
+ }
+ else
+ {
+ if(c == '\\')
+ {
+ esc = true;
+ }
+ if(c == '\'')
+ {
+ state = state::normal;
+ }
+ }
+
+ token += c;
+ break;
+ }
+ }
+ if(!token.empty())
+ {
+ tokens.push_back(token);
+ }
+ return tokens;
+}
+
+bool get_env(std::string_view name, std::string& value)
+{
+ auto var = getenv(name.data());
+ if(var)
+ {
+ value = var;
+ return true;
+ }
+ return false;
+}