summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--lib.c67
-rw-r--r--tests/custom/03_stdlib/05_getenv7
-rw-r--r--tests/custom/03_stdlib/18_split4
4 files changed, 66 insertions, 17 deletions
diff --git a/README.md b/README.md
index bd7d0c4..f09c71d 100644
--- a/README.md
+++ b/README.md
@@ -736,9 +736,10 @@ a = filter(["foo", 1, true, null, 2.2], function(v) {
// a = [1, 2.2]
```
-#### 6.10. `getenv(name)`
+#### 6.10. `getenv([name])`
-Return the value of the given environment variable.
+Return the value of the given environment variable. If the variable name is
+omitted, returns a dictionary containing all environment variables.
#### 6.11. `hex(x)`
diff --git a/lib.c b/lib.c
index 37563c2..d5e02a5 100644
--- a/lib.c
+++ b/lib.c
@@ -560,11 +560,34 @@ uc_exit(uc_vm_t *vm, size_t nargs)
static uc_value_t *
uc_getenv(uc_vm_t *vm, size_t nargs)
{
- uc_value_t *key = uc_fn_arg(0);
- char *k = ucv_string_get(key);
- char *val = k ? getenv(k) : NULL;
+ uc_value_t *key = uc_fn_arg(0), *rv = NULL;
+ extern char **environ;
+ char *k, *v;
- return val ? ucv_string_new(val) : NULL;
+ if (!key) {
+ rv = ucv_object_new(vm);
+
+ while (*environ) {
+ v = strchr(*environ, '=');
+
+ if (v) {
+ xasprintf(&k, "%.*s", (int)(v - *environ), *environ);
+ ucv_object_add(rv, k, ucv_string_new(v + 1));
+ free(k);
+ }
+
+ environ++;
+ }
+ }
+ else if (ucv_type(key) == UC_STRING) {
+ k = ucv_string_get(key);
+ v = getenv(k);
+
+ if (v)
+ rv = ucv_string_new(v);
+ }
+
+ return rv;
}
static uc_value_t *
@@ -1002,16 +1025,17 @@ uc_split(uc_vm_t *vm, size_t nargs)
uc_value_t *sep = uc_fn_arg(1);
uc_value_t *arr = NULL;
const char *p, *sepstr, *splitstr;
+ size_t seplen, splitlen;
int eflags = 0, res;
regmatch_t pmatch;
uc_regexp_t *re;
- size_t seplen;
if (!sep || ucv_type(str) != UC_STRING)
return NULL;
arr = ucv_array_new(vm);
- splitstr = ucv_string_get(str);
+ splitlen = ucv_string_length(str);
+ p = splitstr = ucv_string_get(str);
if (ucv_type(sep) == UC_REGEXP) {
re = (uc_regexp_t *)sep;
@@ -1041,18 +1065,35 @@ uc_split(uc_vm_t *vm, size_t nargs)
}
else if (ucv_type(sep) == UC_STRING) {
sepstr = ucv_string_get(sep);
+ seplen = ucv_string_length(sep);
- for (p = splitstr, seplen = strlen(sepstr); *p; p++) {
- if (!strncmp(p, sepstr, seplen)) {
- if (*sepstr || p > splitstr)
- ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr));
+ if (splitlen == 0) {
+ ucv_array_push(arr, ucv_string_new_length("", 0));
+ }
+ else if (seplen == 0) {
+ while (splitlen > 0) {
+ ucv_array_push(arr, ucv_string_new_length(p, 1));
- splitstr = p + seplen;
- p = splitstr - (*sepstr ? 1 : 0);
+ splitlen--;
+ p++;
}
}
+ else {
+ while (splitlen >= seplen) {
+ if (!memcmp(p, sepstr, seplen)) {
+ ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr));
- ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr));
+ p = splitstr = p + seplen;
+ splitlen -= seplen;
+ continue;
+ }
+
+ splitlen--;
+ p++;
+ }
+
+ ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr + splitlen));
+ }
}
else {
ucv_put(arr);
diff --git a/tests/custom/03_stdlib/05_getenv b/tests/custom/03_stdlib/05_getenv
index 350e952..064add0 100644
--- a/tests/custom/03_stdlib/05_getenv
+++ b/tests/custom/03_stdlib/05_getenv
@@ -2,6 +2,9 @@ The `getenv()` function returns the value of the given environment variable
or `null` if either the given variable does not exist or if the given name
argument is not a string.
+If the variable name argument is omitted, getenv() returns a dictionary
+containing all environment variables.
+
-- Testcase --
{%
printf("%.J\n", [
@@ -9,7 +12,7 @@ argument is not a string.
getenv("EMPTY_VARIABLE"),
getenv("THIS_LIKELY_DOES_NOT_EXIST"),
getenv(123),
- getenv(null)
+ type(getenv())
]);
%}
-- End --
@@ -25,6 +28,6 @@ EMPTY_VARIABLE=
"",
null,
null,
- null
+ "object"
]
-- End --
diff --git a/tests/custom/03_stdlib/18_split b/tests/custom/03_stdlib/18_split
index e31ce78..5ee35a2 100644
--- a/tests/custom/03_stdlib/18_split
+++ b/tests/custom/03_stdlib/18_split
@@ -40,6 +40,9 @@ argument is neither a string nor a regular expression.
// leading and trailing empty substrings are retained
split("|abc|def|", "|"),
split(",foo;bar:", /[,;:]/),
+
+ // subject and split strings handle embedded \0
+ split("foo=1\0bar=2\0baz=3", "\0"),
]), "\n");
%}
-- End --
@@ -58,6 +61,7 @@ argument is neither a string nor a regular expression.
[ "foo", "bar", "", "baz" ]
[ "", "abc", "def", "" ]
[ "", "foo", "bar", "" ]
+[ "foo=1", "bar=2", "baz=3" ]
-- End --