From: Nicolas Williams Date: Sun, 26 Feb 2017 22:12:57 +0000 (-0600) Subject: fixup X-Git-Tag: jq-1.6rc1~53 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b279713e47c5950d786b84cb6f0c77fe1c691231;p=jq fixup --- diff --git a/src/compile.c b/src/compile.c index 8e2d09f..3b18bab 100644 --- a/src/compile.c +++ b/src/compile.c @@ -1002,16 +1002,8 @@ static int count_cfunctions(block b) { 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) +make_env(jv env) { if (jv_is_valid(env)) return jv_copy(env); @@ -1026,19 +1018,21 @@ make_env(void) 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)); + return jv_copy(r); } // Expands call instructions into a calling sequence -static int expand_call_arglist(block* b) { +static int expand_call_arglist(block* b, jv args, jv *env) { int errors = 0; block ret = gen_noop(); for (inst* curr; (curr = block_take(b));) { if (opcode_describe(curr->op)->flags & OP_HAS_BINDING) { if (!curr->bound_by && curr->op == LOADV && strcmp(curr->symbol, "ENV") == 0) { curr->op = LOADK; - curr->imm.constant = make_env(); + *env = curr->imm.constant = make_env(*env); + } else if (!curr->bound_by && curr->op == LOADV && jv_object_has(jv_copy(args), jv_string(curr->symbol))) { + curr->op = LOADK; + curr->imm.constant = jv_object_get(jv_copy(args), jv_string(curr->symbol)); } 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"); @@ -1096,7 +1090,7 @@ static int expand_call_arglist(block* b) { i->subfn = gen_noop(); inst_free(i); // arguments should be pushed in reverse order, prepend them to prelude - errors += expand_call_arglist(&body); + errors += expand_call_arglist(&body, args, env); prelude = BLOCK(gen_subexp(body), prelude); actual_args++; } @@ -1118,12 +1112,12 @@ static int expand_call_arglist(block* b) { return errors; } -static int compile(struct bytecode* bc, block b, struct locfile* lf) { +static int compile(struct bytecode* bc, block b, struct locfile* lf, jv args, jv *env) { int errors = 0; int pos = 0; int var_frame_idx = 0; bc->nsubfunctions = 0; - errors += expand_call_arglist(&b); + errors += expand_call_arglist(&b, args, env); b = BLOCK(b, gen_op_simple(RET)); jv localnames = jv_array(); for (inst* curr = b.first; curr; curr = curr->next) { @@ -1186,7 +1180,7 @@ static int compile(struct bytecode* bc, block b, struct locfile* lf) { params = jv_array_append(params, jv_string(param->symbol)); } subfn->debuginfo = jv_object_set(subfn->debuginfo, jv_string("params"), params); - errors += compile(subfn, curr->subfn, lf); + errors += compile(subfn, curr->subfn, lf, args, env); curr->subfn = gen_noop(); } } @@ -1251,7 +1245,7 @@ static int compile(struct bytecode* bc, block b, struct locfile* lf) { return errors; } -int block_compile(block b, struct bytecode** out, struct locfile* lf) { +int block_compile(block b, struct bytecode** out, struct locfile* lf, jv args) { struct bytecode* bc = jv_mem_alloc(sizeof(struct bytecode)); bc->parent = 0; bc->nclosures = 0; @@ -1261,7 +1255,10 @@ int block_compile(block b, struct bytecode** out, struct locfile* lf) { bc->globals->cfunctions = jv_mem_alloc(sizeof(struct cfunction) * ncfunc); bc->globals->cfunc_names = jv_array(); bc->debuginfo = jv_object_set(jv_object(), jv_string("name"), jv_null()); - int nerrors = compile(bc, b, lf); + jv env = jv_invalid(); + int nerrors = compile(bc, b, lf, args, &env); + jv_free(args); + jv_free(env); assert(bc->globals->ncfunctions == ncfunc); if (nerrors > 0) { bytecode_free(bc); diff --git a/src/compile.h b/src/compile.h index 6076551..b341ccf 100644 --- a/src/compile.h +++ b/src/compile.h @@ -77,7 +77,7 @@ block block_drop_unreferenced(block body); jv block_take_imports(block* body); jv block_list_funcs(block body, int omit_underscores); -int block_compile(block, struct bytecode**, struct locfile*); +int block_compile(block, struct bytecode**, struct locfile*, jv); void block_free(block); diff --git a/src/execute.c b/src/execute.c index e364da4..bc39c0c 100644 --- a/src/execute.c +++ b/src/execute.c @@ -1066,6 +1066,23 @@ static struct bytecode *optimize(struct bytecode *bc) { return optimize_code(bc); } +static jv +args2obj(jv args) +{ + if (jv_get_kind(args) == JV_KIND_OBJECT) + return args; + assert(jv_get_kind(args) == JV_KIND_ARRAY); + jv r = jv_object(); + jv kk = jv_string("name"); + jv vk = jv_string("value"); + jv_array_foreach(args, i, v) + r = jv_object_set(r, jv_object_get(jv_copy(v), kk), jv_object_get(v, vk)); + jv_free(args); + jv_free(kk); + jv_free(vk); + return r; +} + int jq_compile_args(jq_state *jq, const char* str, jv args) { jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data); assert(jv_get_kind(args) == JV_KIND_ARRAY || jv_get_kind(args) == JV_KIND_OBJECT); @@ -1079,49 +1096,21 @@ int jq_compile_args(jq_state *jq, const char* str, jv args) { } int nerrors = load_program(jq, locations, &program); if (nerrors == 0) { - /* - * jq_compile_args() is a public function. It should always have - * been the case that args was an object, but originally it was an - * array. - * - * We have to do an O(N) binding operation for each argument given. - * - * The best way to address this might be to have a bind function - * that takes an object instead of a const block and a varname. - * - * However, with `--args` this can be avoided, as one can have a - * single such binding then: $ARGS. - */ - if (jv_get_kind(args) == JV_KIND_ARRAY) { - jv_array_foreach(args, i, arg) { - jv name = jv_object_get(jv_copy(arg), jv_string("name")); - jv value = jv_object_get(arg, jv_string("value")); - program = gen_var_binding(gen_const(value), jv_string_value(name), program); - jv_free(name); - } - } else if (jv_get_kind(args) == JV_KIND_OBJECT) { - jv_object_foreach(args, name, value) { - program = gen_var_binding(gen_const(value), jv_string_value(name), program); - jv_free(name); - } - } - nerrors = builtins_bind(jq, &program); if (nerrors == 0) { - nerrors = block_compile(program, &jq->bc, locations); + nerrors = block_compile(program, &jq->bc, locations, args = args2obj(args)); } } if (nerrors) jq_report_error(jq, jv_string_fmt("jq: %d compile %s", nerrors, nerrors > 1 ? "errors" : "error")); if (jq->bc) jq->bc = optimize(jq->bc); - jv_free(args); locfile_free(locations); return jq->bc != NULL; } int jq_compile(jq_state *jq, const char* str) { - return jq_compile_args(jq, str, jv_array()); + return jq_compile_args(jq, str, jv_object()); } jv jq_get_jq_origin(jq_state *jq) {