diff options
author | Nicolas Williams <nico@cryptonector.com> | 2017-02-26 00:28:12 -0600 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2017-02-26 00:39:24 -0600 |
commit | 3504bd9a2a9e9cb1e4864b69821b446d15fab85d (patch) | |
tree | ce8e9d14641eb1791a7b623275178451f1e454cb | |
parent | 1a8a0ae0f55858a8f0a5e8c73f71e1e609b820f4 (diff) |
Add $ENV builtin variable to access environment
-rw-r--r-- | docs/content/3.manual/manual.yml | 14 | ||||
-rw-r--r-- | jq.1.prebuilt | 14 | ||||
-rw-r--r-- | src/compile.c | 37 |
3 files changed, 60 insertions, 5 deletions
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index a0d713e7..84675182 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -1666,12 +1666,22 @@ sections: output: - '[{"a":{"b":2}}]' - - title: "`env`" + - title: "`$ENV`, `env`" body: | - Outputs an object representing jq's environment. + `$ENV` is an object representing the environment variables as + set when the jq program started. + + `env` outputs an object representing jq's current environment. + + At the moment there is no builtin for setting environment + variables. examples: + - program: '$ENV.PAGER' + input: 'null' + output: ['"less"'] + - program: 'env.PAGER' input: 'null' output: ['"less"'] diff --git a/jq.1.prebuilt b/jq.1.prebuilt index c4d25ea7..04b90715 100644 --- a/jq.1.prebuilt +++ b/jq.1.prebuilt @@ -1830,13 +1830,23 @@ jq \'walk( if type == "object" then with_entries( \.key |= sub( "^_+"; "") ) els . .IP "" 0 . -.SS "env" -Outputs an object representing jq\'s environment\. +.SS "$ENV, env" +\fB$ENV\fR is an object representing the environment variables as set when the jq program started\. +. +.P +\fBenv\fR outputs an object representing jq\'s current environment\. +. +.P +At the moment there is no builtin for setting environment variables\. . .IP "" 4 . .nf +jq \'$ENV\.PAGER\' + null +=> "less" + jq \'env\.PAGER\' null => "less" diff --git a/src/compile.c b/src/compile.c index 5b408e0d..8e2d09f2 100644 --- a/src/compile.c +++ b/src/compile.c @@ -5,6 +5,7 @@ #include <math.h> #include <string.h> #include <stdlib.h> +#include <unistd.h> #include "compile.h" #include "bytecode.h" #include "locfile.h" @@ -997,6 +998,37 @@ static int count_cfunctions(block b) { return n; } +#ifdef WIN32 +extern const char **environ; +#endif + +static jv env = {JV_KIND_INVALID, 0, 0, 0, {0}}; + +static void +free_env(void) +{ + jv_free(env); +} + +static jv +make_env(void) +{ + if (jv_is_valid(env)) + return jv_copy(env); + jv r = jv_object(); + if (environ == NULL) + return r; + for (size_t i = 0; environ[i] != NULL; i++) { + const char *eq; + + if ((eq = strchr(environ[i], '=')) == NULL) + r = jv_object_delete(r, jv_string(environ[i])); + else + r = jv_object_set(r, jv_string_sized(environ[i], eq - environ[i]), jv_string(eq + 1)); + } + atexit(free_env); + return (env = jv_copy(r)); +} // Expands call instructions into a calling sequence static int expand_call_arglist(block* b) { @@ -1004,7 +1036,10 @@ static int expand_call_arglist(block* b) { block ret = gen_noop(); for (inst* curr; (curr = block_take(b));) { if (opcode_describe(curr->op)->flags & OP_HAS_BINDING) { - if (!curr->bound_by) { + if (!curr->bound_by && curr->op == LOADV && strcmp(curr->symbol, "ENV") == 0) { + curr->op = LOADK; + curr->imm.constant = make_env(); + } else if (!curr->bound_by) { if (curr->symbol[0] == '*' && curr->symbol[1] >= '1' && curr->symbol[1] <= '3' && curr->symbol[2] == '\0') locfile_locate(curr->locfile, curr->source, "jq: error: break used outside labeled control structure"); else if (curr->op == LOADV) |