aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-09 14:48:33 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-09 14:48:33 -0400
commit6ea6aadd963a216e4e321e500515846201d213a5 (patch)
treeea85ac24f6dd479cd2f052b63c65dbe3e253b23e
parent43c595cafe3a09c52a098774671bb55c7e80f128 (diff)
Correctly clean up CLI args that are paths
-rw-r--r--builtins/path.c14
-rw-r--r--builtins/path.h1
-rw-r--r--compile.c5
3 files changed, 14 insertions, 6 deletions
diff --git a/builtins/path.c b/builtins/path.c
index fa09082a..e63e4e42 100644
--- a/builtins/path.c
+++ b/builtins/path.c
@@ -35,8 +35,12 @@ PUREFUNC public Path_t Path$escape_path(Path_t path)
return path;
}
-static Path_t Path$_cleanup(Path_t path)
+public Path_t Path$cleanup(Path_t path)
{
+ if (!Text$starts_with(path, Path("/")) && !Text$starts_with(path, Path("./"))
+ && !Text$starts_with(path, Path("../")) && !Text$starts_with(path, Path("~/")))
+ path = Text$concat(Text("./"), path);
+
// Not fully resolved, but at least get rid of some of the cruft like "/./"
// and "/foo/../" and "//"
bool trailing_slash = Text$ends_with(path, Path("/"));
@@ -119,7 +123,7 @@ public Path_t Path$_concat(int n, Path_t items[n])
.data=items,
.data_refcount=1,
};
- Path_t cleaned_up = Path$_cleanup(Text$join(Text("/"), items_array));
+ Path_t cleaned_up = Path$cleanup(Text$join(Text("/"), items_array));
if (cleaned_up.length > PATH_MAX)
fail("Path exceeds the maximum path length: %k", &cleaned_up);
return cleaned_up;
@@ -127,7 +131,7 @@ public Path_t Path$_concat(int n, Path_t items[n])
public Text_t Path$resolved(Path_t path, Path_t relative_to)
{
- path = Path$_cleanup(path);
+ path = Path$cleanup(path);
const char *path_str = Text$as_c_string(path);
const char *relative_to_str = Text$as_c_string(relative_to);
@@ -393,12 +397,12 @@ public Text_t Path$write_unique(Path_t path, Text_t text)
public Path_t Path$parent(Path_t path)
{
- return Path$_cleanup(Text$concat(path, Path("/../")));
+ return Path$cleanup(Text$concat(path, Path("/../")));
}
public Text_t Path$base_name(Path_t path)
{
- path = Path$_cleanup(path);
+ path = Path$cleanup(path);
if (Text$ends_with(path, Path("/")))
return Text$replace(path, Pattern("{0+..}/{!/}/{end}"), Text("@2"), Text("@"), false);
else
diff --git a/builtins/path.h b/builtins/path.h
index c5acbf34..06bc2ec6 100644
--- a/builtins/path.h
+++ b/builtins/path.h
@@ -13,6 +13,7 @@
#define Path(text) ((Path_t)Text(text))
#define Paths(...) Path$concat(__VA_ARGS__)
+Path_t Path$cleanup(Path_t path);
Path_t Path$_concat(int n, Path_t items[n]);
#define Path$concat(...) Path$_concat(sizeof((Path_t[]){__VA_ARGS__})/sizeof(Path_t), (Path_t[]){__VA_ARGS__})
PUREFUNC Path_t Path$escape_text(Text_t text);
diff --git a/compile.c b/compile.c
index c3b6325a..db2c6930 100644
--- a/compile.c
+++ b/compile.c
@@ -3222,7 +3222,7 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type)
}
case TextType: {
code = CORD_all(code, "else if (pop_flag(argv, &i, \"", flag, "\", &flag)) {\n",
- "$", arg->name, " = flag;\n",
+ "$", arg->name, " = ", streq(Match(t, TextType)->lang, "Path") ? "Path$cleanup(flag)" : "flag",";\n",
arg->name, "$is_set = yes;\n"
"}\n");
break;
@@ -3304,6 +3304,9 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type)
"if (i < argc) {");
if (t->tag == TextType) {
code = CORD_all(code, "$", arg->name, " = Text$from_str(argv[i]);\n");
+ if (streq(Match(t, TextType)->lang, "Path"))
+ code = CORD_all(code, "$", arg->name, " = Path$cleanup($", arg->name, ");\n");
+
} else if (t->tag == EnumType) {
env_t *enum_env = Match(t, EnumType)->env;
for (tag_t *tag = Match(t, EnumType)->tags; tag; tag = tag->next) {