return result.empty() ? "." : result;
}
-std::optional<size_t>
-is_absolute_path_with_prefix(std::string_view path)
-{
-#ifdef _WIN32
- const char delim[] = "/\\";
-#else
- const char delim[] = "/";
-#endif
- auto split_pos = path.find_first_of(delim);
- if (split_pos != std::string::npos) {
-#ifdef _WIN32
- // -I/C:/foo and -I/c/foo will already be handled by delim_pos correctly
- // resulting in -I and /C:/foo or /c/foo respectively. -IC:/foo will not as
- // we would get -IC: and /foo.
- if (split_pos > 0 && path[split_pos - 1] == ':') {
- split_pos = split_pos - 2;
- }
-#endif
- // This is not redundant on some platforms, so nothing to simplify.
- // NOLINTNEXTLINE(readability-simplify-boolean-expr)
- return split_pos;
- }
- return std::nullopt;
-}
-
std::string
make_relative_path(const std::string& base_dir,
const std::string& actual_cwd,
// resolve to the same file as `path`.
std::string get_relative_path(std::string_view dir, std::string_view path);
-// Determine if `path` is an absolute path with prefix, returning the split
-// point.
-std::optional<size_t> is_absolute_path_with_prefix(std::string_view path);
-
// Construct a normalized native path.
//
// Example:
// Potentially rewrite concatenated absolute path argument to relative.
if (arg[0] == '-') {
- const auto path_pos = Util::is_absolute_path_with_prefix(arg);
- if (path_pos) {
- const std::string option = args[i].substr(0, *path_pos);
+ const auto [option, path] = util::split_option_with_concat_path(arg);
+ if (path) {
if (compopt_takes_concat_arg(option) && compopt_takes_path(option)) {
- const auto relpath = Util::make_relative_path(
- ctx, std::string_view(arg).substr(*path_pos));
- std::string new_option = option + relpath;
+ const auto relpath = Util::make_relative_path(ctx, *path);
+ std::string new_option = FMT("{}{}", option, relpath);
if (compopt_affects_cpp_output(option)) {
- state.cpp_args.push_back(new_option);
+ state.cpp_args.push_back(std::move(new_option));
} else {
- state.common_args.push_back(new_option);
+ state.common_args.push_back(std::move(new_option));
}
return Statistic::none;
}
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
}
}
+std::pair<std::string_view, std::optional<std::string_view>>
+split_option_with_concat_path(std::string_view string)
+{
+#ifdef _WIN32
+ const char delim[] = "/\\";
+#else
+ const char delim[] = "/";
+#endif
+ size_t split_pos = string.find_first_of(delim);
+ if (split_pos == std::string_view::npos) {
+ return std::make_pair(string, std::nullopt);
+ }
+
+#ifdef _WIN32
+ // -I/C:/foo and -I/c/foo will already be handled by delim_pos correctly
+ // resulting in -I and /C:/foo or /c/foo respectively. -IC:/foo will not as
+ // we would get -IC: and /foo.
+ if (split_pos >= 2 && string[split_pos - 1] == ':') {
+ split_pos -= 2;
+ }
+#endif
+
+ return std::make_pair(string.substr(0, split_pos), string.substr(split_pos));
+}
+
std::vector<std::filesystem::path>
split_path_list(std::string_view path_list)
{
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
std::pair<std::string_view, std::optional<std::string_view>>
split_once(std::string_view string, char split_char);
+// Split `string` into two parts where the split point is before a potential
+// absolute path. The second part will be `nullopt` if no absolute path
+// candidate was found.
+std::pair<std::string_view, std::optional<std::string_view>>
+split_option_with_concat_path(std::string_view string);
+
// Split a list of paths (such as the content of $PATH on Unix platforms or
// %PATH% on Windows platforms) into paths.
std::vector<std::filesystem::path> split_path_list(std::string_view path_list);
#endif
}
-TEST_CASE("Util::is_absolute_path_with_prefix")
-{
- CHECK(*Util::is_absolute_path_with_prefix("-I/c/foo") == 2);
- CHECK(*Util::is_absolute_path_with_prefix("-W,path/c/foo") == 7);
- CHECK(!Util::is_absolute_path_with_prefix("-DMACRO"));
-#ifdef _WIN32
- CHECK(*Util::is_absolute_path_with_prefix("-I/C:/foo") == 2);
- CHECK(*Util::is_absolute_path_with_prefix("-IC:/foo") == 2);
- CHECK(*Util::is_absolute_path_with_prefix("-W,path/c:/foo") == 7);
- CHECK(*Util::is_absolute_path_with_prefix("-W,pathc:/foo") == 7);
- CHECK(!Util::is_absolute_path_with_prefix("-opt:value"));
-#endif
-}
-
TEST_CASE("Util::make_relative_path")
{
using Util::make_relative_path;
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
}
}
+TEST_CASE("util::split_option_with_concat_path")
+{
+ using std::make_pair;
+ using std::nullopt;
+ const auto split = util::split_option_with_concat_path;
+
+ CHECK(split("-I/c/foo") == make_pair("-I", "/c/foo"));
+ CHECK(split("-W,path/c/foo") == make_pair("-W,path", "/c/foo"));
+ CHECK(split("-DMACRO") == make_pair("-DMACRO", nullopt));
+#ifdef _WIN32
+ CHECK(split("-I/C:/foo") == make_pair("-I", "/C:/foo"));
+ CHECK(split("-IC:/foo") == make_pair("-I", "C:/foo"));
+ CHECK(split("-W,path/c:/foo") == make_pair("-W,path", "/c:/foo"));
+ CHECK(split("-W,pathc:/foo") == make_pair("-W,path", "c:/foo"));
+ CHECK(split("-opt:value") == make_pair("-opt:value", nullopt));
+#endif
+}
+
TEST_CASE("util::split_path_list")
{
CHECK(util::split_path_list("").empty());