commit 141cf68540cd77db87475942c5d979e07a97d00a
parent fd7addb2076da0cbf82a4f3530183e5fa6b026cb
Author: Sebastian <sebastian@sebsite.pw>
Date: Mon, 27 Nov 2023 01:19:26 -0500
wordexp: correctly handle string containing only whitespace
Turns out the "x" hack was necessary after all.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/wordexp/+test.ha b/wordexp/+test.ha
@@ -21,6 +21,7 @@ fn streq(a: []str, b: []str) bool = {
os::unsetenv("UNSET")!;
static const cases: [_](str, []str) = [
(``, []),
+ (" \t\n", []),
(`hello world`, ["hello", "world"]),
(`hello $TESTVAR`, ["hello", "test", "value"]),
(`hello "$TESTVAR"`, ["hello", "test value"]),
diff --git a/wordexp/wordexp.ha b/wordexp/wordexp.ha
@@ -28,16 +28,12 @@ export type flag = enum uint {
// Pass the return value to [[strings::freeall]] to free resources associated
// with the return value.
export fn wordexp(s: str, flags: flag) ([]str | error) = {
- if (s == "") {
- // Special case
- return [];
- };
-
const (rd, wr) = exec::pipe();
+ // "x" is added to handle the list of expanded words being empty
const cmd = exec::cmd("/bin/sh",
if (flags & flag::UNDEF != 0) "-uc" else "-c",
- `eval "printf %s\\\\0 $1"`, "sh", s)!;
+ `eval "printf %s\\\\0 x $1"`, "sh", s)!;
exec::unsetenv(&cmd, "IFS")!;
exec::addfile(&cmd, os::stdout_file, wr);
if (flags & flag::SHOWERR == 0) {
@@ -49,6 +45,12 @@ export fn wordexp(s: str, flags: flag) ([]str | error) = {
const scan = bufio::newscanner(rd, types::SIZE_MAX);
defer bufio::finish(&scan);
+ match (bufio::scan_string(&scan, "\0")?) {
+ case io::EOF =>
+ return sh_error;
+ case => void; // Discard the first "x" argument
+ };
+
let words: []str = [];
for (true) {
match (bufio::scan_string(&scan, "\0")?) {