From 5be97463ecd4f93fdfbaec457d9100beeb9dc603 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Mon, 6 May 2013 14:21:00 +0100 Subject: [PATCH] Add a --arg option to allow variables to be passed from the cmdline. Closes #107 --- compile.c | 6 ++++++ compile.h | 2 ++ docs/content/3.manual/manual.yml | 6 ++++++ execute.c | 15 ++++++++++++++- execute.h | 4 ++++ main.c | 15 +++++++++++++-- parser.y | 4 +--- 7 files changed, 46 insertions(+), 6 deletions(-) diff --git a/compile.c b/compile.c index 6904462..77dfd90 100644 --- a/compile.c +++ b/compile.c @@ -371,6 +371,12 @@ block gen_or(block a, block b) { gen_const(jv_false()))))); } +block gen_var_binding(block var, const char* name, block body) { + return BLOCK(gen_op_simple(DUP), var, + block_bind(gen_op_var_unbound(STOREV, name), + body, OP_HAS_VARIABLE)); +} + block gen_cond(block cond, block iftrue, block iffalse) { return BLOCK(gen_op_simple(DUP), cond, gen_condbranch(BLOCK(gen_op_simple(POP), iftrue), diff --git a/compile.h b/compile.h index f982e3b..00a863c 100644 --- a/compile.h +++ b/compile.h @@ -40,6 +40,8 @@ block gen_condbranch(block iftrue, block iffalse); block gen_and(block a, block b); block gen_or(block a, block b); +block gen_var_binding(block var, const char* name, block body); + block gen_cond(block cond, block iftrue, block iffalse); block gen_cbinding(const struct cfunction* functions, int nfunctions, block b); diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 7b49065..c85fcd5 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -121,6 +121,12 @@ sections: formatted as a JSON string with quotes. This can be useful for making jq filters talk to non-JSON-based systems. + * `--arg name value`: + + This option passes a value to the jq program as a predefined + variable. If you run jq with `--arg foo bar`, then `$foo` is + available in the program and has the value `"bar"`. + - title: Basic filters entries: - title: "`.`" diff --git a/execute.c b/execute.c index 22ffadb..5651dcf 100644 --- a/execute.c +++ b/execute.c @@ -506,13 +506,22 @@ void jq_teardown(jq_state **jq) { jv_mem_free(old_jq); } -struct bytecode* jq_compile(const char* str) { +struct bytecode* jq_compile_args(const char* str, jv args) { + assert(jv_get_kind(args) == JV_KIND_ARRAY); struct locfile locations; locfile_init(&locations, str, strlen(str)); block program; struct bytecode* bc = 0; int nerrors = jq_parse(&locations, &program); if (nerrors == 0) { + for (int i=0; i= argc - 2) { + fprintf(stderr, "%s: --arg takes two parameters (e.g. -a varname value)\n", progname); + die(); + } + jv arg = jv_object(); + arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1])); + arg = jv_object_set(arg, jv_string("value"), jv_string(argv[i+2])); + program_arguments = jv_array_append(program_arguments, arg); + i += 2; // skip the next two arguments } else if (isoption(argv[i], 0, "debug-dump-disasm")) { options |= DUMP_DISASM; } else if (isoption(argv[i], 0, "debug-trace")) { @@ -214,10 +225,10 @@ int main(int argc, char* argv[]) { jv_free(data); return 1; } - bc = jq_compile(jv_string_value(data)); + bc = jq_compile_args(jv_string_value(data), program_arguments); jv_free(data); } else { - bc = jq_compile(program); + bc = jq_compile_args(program, program_arguments); } if (!bc) return 1; diff --git a/parser.y b/parser.y index 92cd9db..8c663b9 100644 --- a/parser.y +++ b/parser.y @@ -201,9 +201,7 @@ FuncDef Exp %prec ';' { } | Term "as" '$' IDENT '|' Exp { - $$ = BLOCK(gen_op_simple(DUP), $1, - block_bind(gen_op_var_unbound(STOREV, jv_string_value($4)), - $6, OP_HAS_VARIABLE)); + $$ = gen_var_binding($1, jv_string_value($4), $6); jv_free($4); } | -- 2.40.0