// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include "util.h" #include #include #include std::string to_lower(const std::string& str) { std::string out{str}; std::transform(out.begin(), out.end(), out.begin(), ::tolower); return out; } 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(); ifs.seekg(0, std::ios::beg); std::vector bytes(static_cast(fileSize)); ifs.read(bytes.data(), fileSize); return {bytes.data(), static_cast(fileSize)}; } std::vector readDeps(const std::string& depFile) { if(!std::filesystem::exists(depFile)) { return {}; } auto str = readFile(depFile); std::vector output; std::string tmp; bool start{false}; bool in_whitespace{false}; for(const auto& c : str) { 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; } } if(!tmp.empty()) { output.push_back(tmp); } return output; } ctor::language languageFromExtension(const std::filesystem::path& file) { auto ext = file.extension().string(); // First a few case sensitive comparisons if(ext == ".c") { return ctor::language::c; } if(ext == ".C") { return ctor::language::cpp; } // The rest are compared in lowercase ext = to_lower(ext); if(ext == ".cc" || ext == ".cpp" || ext == ".c++" || ext == ".cp" || ext == ".cxx") { return ctor::language::cpp; } if(ext == ".s" || ext == ".asm") { return ctor::language::assembler; } std::cerr << "Could not deduce language from " << file.string() << "\n"; exit(1); return {}; } namespace { bool isClean(char c) { return c != '.' && c != '/'; } } std::string cleanUp(const std::string& path) { std::string cleaned; for(const auto& c : path) { if(isClean(c)) { cleaned += c; } else { cleaned += '_'; } } 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 get_paths(const std::string& path_env) { std::vector 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& 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 {}; }