MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
sys.cpp
Go to the documentation of this file.
1#include "mim/util/sys.h"
2
3#include <filesystem>
4#include <iostream>
5
6#include "mim/config.h"
7
8#include "mim/util/dbg.h"
9
10#ifdef _WIN32
11# include <windows.h>
12# define popen _popen
13# define pclose _pclose
14# define WEXITSTATUS
15#elif defined(__APPLE__) || defined(__linux__)
16# include <dlfcn.h>
17#endif
18
19using namespace std::string_literals;
20
21extern "C" MIM_EXPORT void mim_lib_anchor() {}
22
23namespace mim::sys {
24
25namespace {
26
27bool has_plugin_dir(const fs::path& libmim_path) {
28 std::error_code ignore;
29 return fs::is_directory(libmim_path.parent_path() / "mim", ignore) && !ignore;
30}
31
32fs::path adjust_libmim_path(const fs::path& libmim_path) {
33 if (has_plugin_dir(libmim_path)) return libmim_path;
34
35 auto dir = libmim_path.parent_path();
36 auto lib_name = libmim_path.filename();
37 while (!dir.empty()) {
38 if (dir == dir.root_path()) break;
39
40 std::error_code ignore;
41 auto candidate = dir / MIM_LIBDIR / "mim";
42 if (fs::is_directory(candidate, ignore) && !ignore) return candidate.parent_path() / lib_name;
43
44 dir = dir.parent_path();
45 }
46
47 return libmim_path;
48}
49
50} // namespace
51
52std::optional<fs::path> path_to_libmim() {
53#if defined(_WIN32)
54 HMODULE mod = nullptr;
55 auto flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
56 if (!GetModuleHandleExW(flags, reinterpret_cast<LPCWSTR>(&mim_lib_anchor), &mod)) return {};
57
58 std::wstring buf;
59 buf.resize(512);
60 while (true) {
61 DWORD len = GetModuleFileNameW(mod, buf.data(), (DWORD)buf.size());
62 if (len == 0) return {};
63
64 if (len < buf.size() - 1) {
65 buf.resize(len);
66 break;
67 }
68
69 buf.resize(buf.size() * 2); // buffer too small
70 }
71
72 return adjust_libmim_path(fs::weakly_canonical(fs::path(buf)));
73#elif defined(__APPLE__) || defined(__linux__)
74 Dl_info info;
75 if (dladdr((void*)&mim_lib_anchor, &info) == 0) return {};
76 return adjust_libmim_path(fs::weakly_canonical(info.dli_fname));
77#else
78 return {};
79#endif
80}
81
82// see https://stackoverflow.com/a/478960
83std::string exec(std::string cmd) {
84 using PipeCloser = int (*)(FILE*); // spell out type explicitly to get rid of warning
85 if (auto pipe = std::unique_ptr<FILE, PipeCloser>(popen(cmd.c_str(), "r"), pclose)) {
86 std::array<char, 128> buffer;
87 std::string result;
88 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
89 result += buffer.data();
90 return result;
91 } else
92 error("popen() failed!");
93}
94
95std::string find_cmd(std::string cmd) {
96 auto out = exec(MIM_WHICH " "s + cmd);
97 if (auto it = out.find('\n'); it != std::string::npos) out.erase(it);
98 return out;
99}
100
101int system(std::string cmd) {
102 std::cout << cmd << std::endl;
103 int status = std::system(cmd.c_str());
104 return WEXITSTATUS(status);
105}
106
107int run(std::string cmd, std::string args /* = {}*/) {
108#ifdef _WIN32
109 cmd += ".exe";
110#else
111 cmd = "./"s + cmd;
112#endif
113 return sys::system(cmd + " "s + args);
114}
115
116std::string escape(const std::filesystem::path& path) {
117 std::string str;
118 for (char c : path.string()) {
119 if (isspace(c)) str += '\\';
120 str += c;
121 }
122 return str;
123}
124
125} // namespace mim::sys
#define MIM_LIBDIR
Definition config.h:13
#define MIM_EXPORT
Definition config.h:19
Definition sys.h:17
int run(std::string cmd, std::string args={})
Wraps sys::system and puts .exe at the back (Windows) and ./ at the front (otherwise) of cmd.
Definition sys.cpp:107
int system(std::string)
Wraps std::system and makes the return value usable.
Definition sys.cpp:101
std::string escape(const std::filesystem::path &path)
Returns the path as std::string and escapes all whitespaces with backslash.
Definition sys.cpp:116
std::string find_cmd(std::string)
Definition sys.cpp:95
std::optional< fs::path > path_to_libmim()
Yields std::nullopt if an error occurred.
Definition sys.cpp:52
std::string exec(std::string cmd)
Executes command cmd.
Definition sys.cpp:83
void error(std::format_string< Args... > fmt, Args &&... args)
Wraps std::format to throw T with a formatted message.
Definition dbg.h:17
void mim_lib_anchor()
Definition sys.cpp:21
#define MIM_WHICH
Definition sys.h:10