diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-08-14 11:46:36 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-08-14 11:46:36 -0700 |
commit | e2e64026eabaaf76dd7c1af8340670123db2f18a (patch) | |
tree | d756019a8e94118a575b94838f4421dd50a73a09 /match.c | |
parent | 7bd54dd6ecb2c7e1f9da760bbf4645af5f546d96 (diff) | |
download | txr-e2e64026eabaaf76dd7c1af8340670123db2f18a.tar.gz txr-e2e64026eabaaf76dd7c1af8340670123db2f18a.tar.bz2 txr-e2e64026eabaaf76dd7c1af8340670123db2f18a.zip |
match.c: revert bad commits.
This contains two reverts, folded into one.
"txr: spurious retention in @(next)."
commit fe1e960389a89f481d46c02aa040fdc762da735f.
"txr: avoid by-value match_files_ctx passing."
commit 3d7330b827d6e9cc0d9e87edd30388374cb45900.
These are dependent. The second of these two (i.e. the one
that was done first) is the problematic one. By-reference
passing of contexts means contexts become shared objects
between callers and callees. But this is incorrect, because
mutations are going on, like c->spec = rest(c->spec) or
c->data = rest(c->data). These mutations were done under the
assumption of safety: that the caller is not affected due to
by-value semantics of the entire context.
Diffstat (limited to 'match.c')
-rw-r--r-- | match.c | 276 |
1 files changed, 118 insertions, 158 deletions
@@ -1488,9 +1488,8 @@ typedef struct { val spec, files, curfile, bindings, data, data_lineno; } match_files_ctx; -static match_files_ctx *mf_all(match_files_ctx *nc, - val spec, val files, val bindings, - val data, val curfile); +static match_files_ctx mf_all(val spec, val files, val bindings, + val data, val curfile); static val v_fun(match_files_ctx *c); @@ -1514,11 +1513,11 @@ static val h_call(match_line_ctx *c) if (ret == decline_k) { val spec = cons(new_specline, nil); - match_files_ctx vcs, *vc = mf_all(&vcs, spec, nil, c->bindings, nil, c->file); - val vresult = v_fun(vc); + match_files_ctx vc = mf_all(spec, nil, c->bindings, nil, c->file); + val vresult = v_fun(&vc); if (vresult == next_spec_k) { - c->bindings = vc->bindings; + c->bindings = vc.bindings; return vresult; } else if (vresult == decline_k) { sem_error(elem, lit("call: function ~s not found"), funval, nao); @@ -1583,15 +1582,15 @@ static val do_match_line(match_line_ctx *c) continue; } else if (result == decline_k) { val spec = rlcp(cons(cons(elem, nil), nil), elem); - match_files_ctx vcs, *vc = mf_all(&vcs, spec, nil, c->bindings, - nil, c->file); - val vresult = v_fun(vc); + match_files_ctx vc = mf_all(spec, nil, c->bindings, + nil, c->file); + val vresult = v_fun(&vc); if (vresult == next_spec_k) { - c->bindings = vc->bindings; + c->bindings = vc.bindings; break; } else if (vresult == repeat_spec_k) { - c->bindings = vc->bindings; + c->bindings = vc.bindings; continue; } else if (vresult == decline_k) { if (gethash(v_directive_table, directive)) @@ -2275,93 +2274,78 @@ void do_output(val bindings, val specs, val filter, val out) } } -static match_files_ctx *mf_all(match_files_ctx *nc, - val spec, val files, val bindings, - val data, val curfile) +static match_files_ctx mf_all(val spec, val files, val bindings, + val data, val curfile) { - nc->spec = spec; - nc->files = files; - nc->curfile = curfile; - nc->bindings = bindings; - nc->data = data; - nc->data_lineno = if3(data, one, zero); - return nc; + match_files_ctx c; + c.spec = spec; + c.files = files; + c.curfile = curfile; + c.bindings = bindings; + c.data = data; + c.data_lineno = if3(data, one, zero); + return c; } -static match_files_ctx *mf_args(match_files_ctx *nc, match_files_ctx *c) +static match_files_ctx mf_args(match_files_ctx c) { - *nc = *c; - nc->data = c->files; - nc->curfile = lit("args"); - nc->data_lineno = one; + match_files_ctx nc = c; + nc.data = c.files; + nc.curfile = lit("args"); + nc.data_lineno = one; return nc; } -static match_files_ctx *mf_data(match_files_ctx *nc, match_files_ctx *c, - val data, val data_lineno) +static match_files_ctx mf_data(match_files_ctx c, val data, val data_lineno) { - *nc = *c; - nc->data = data; - nc->data_lineno = data_lineno; + match_files_ctx nc = c; + nc.data = data; + nc.data_lineno = data_lineno; return nc; } -static match_files_ctx *mf_spec(match_files_ctx *nc, - const match_files_ctx *c, val spec) +static match_files_ctx mf_spec(match_files_ctx c, val spec) { - *nc = *c; - nc->spec = spec; + match_files_ctx nc = c; + nc.spec = spec; return nc; } -static match_files_ctx *mf_spec_bindings(match_files_ctx *nc, - match_files_ctx *c, val spec, - val bindings) +static match_files_ctx mf_spec_bindings(match_files_ctx c, val spec, + val bindings) { - *nc = *c; - nc->spec = spec; - nc->bindings = bindings; + match_files_ctx nc = c; + nc.spec = spec; + nc.bindings = bindings; return nc; } -static match_files_ctx *mf_file_data(match_files_ctx *nc, - match_files_ctx *c, val file, - val data, val data_lineno) +static match_files_ctx mf_file_data(match_files_ctx c, val file, + val data, val data_lineno) { - *nc = *c; - nc->files = cons(file, c->files); - nc->curfile = file; - nc->data = data; - nc->data_lineno = data_lineno; + match_files_ctx nc = c; + nc.files = cons(file, c.files); + nc.curfile = file; + nc.data = data; + nc.data_lineno = data_lineno; return nc; } -NOINLINE static match_files_ctx *mf_file_lazy(match_files_ctx *nc, - match_files_ctx *c, val file, - val stream, val data_lineno) +static match_files_ctx mf_from_ml(match_line_ctx ml) { - *nc = *c; - nc->files = cons(file, c->files); - nc->curfile = file; - nc->data = lazy_stream_cons(stream); - nc->data_lineno = data_lineno; - return nc; -} + match_files_ctx mf; + mf.spec = cons(ml.specline, nil); + mf.files = nil; + mf.curfile = ml.file; + mf.bindings = ml.bindings; + mf.data = nil; + mf.data_lineno = ml.data_lineno; -static match_files_ctx *mf_from_ml(match_files_ctx *nc, match_line_ctx *ml) -{ - nc->spec = cons(ml->specline, nil); - nc->files = nil; - nc->curfile = ml->file; - nc->bindings = ml->bindings; - nc->data = nil; - nc->data_lineno = ml->data_lineno; - - return nc; + return mf; } -static val match_files(match_files_ctx *c); +static val match_files(match_files_ctx a); typedef val (*v_match_func)(match_files_ctx *cout); @@ -2417,7 +2401,7 @@ static val v_skip(match_files_ctx *c) } while (greedy || !max || reps_max++ < cmax) { - result = match_files(c); + result = match_files(*c); if (result) { if (greedy) { @@ -2484,7 +2468,7 @@ static val v_fuzz(match_files_ctx *c) cnum reps, good; for (reps = 0, good = 0; reps < cn; reps++) { - match_files_ctx fs, *fuzz_ctx = mf_spec(&fs, c, cons(first(c->spec), nil)); + match_files_ctx fuzz_ctx = mf_spec(*c, cons(first(c->spec), nil)); val result = match_files(fuzz_ctx); if (result) { @@ -2516,7 +2500,7 @@ static val v_fuzz(match_files_ctx *c) return nil; } - return match_files(c); + return match_files(*c); } } } @@ -2536,7 +2520,7 @@ static val v_trailer(match_files_ctx *c) if (!c->spec) { result = cons(c->bindings, cons(c->data, c->data_lineno)); } else { - cons_bind (new_bindings, success, match_files(c)); + cons_bind (new_bindings, success, match_files(*c)); result = if2(success, cons(new_bindings, cons(c->data, c->data_lineno))); } @@ -2673,8 +2657,7 @@ static val v_block(match_files_ctx *c) { uw_block_begin(name, result); - match_files_ctx cs; - result = match_files(mf_spec(&cs, c, spec)); + result = match_files(mf_spec(*c, spec)); uw_block_end; if (vectorp(result)) @@ -2730,9 +2713,8 @@ static val v_next_impl(match_files_ctx *c) if (rest(args)) { sem_error(specline, lit("(next :args) takes no additional arguments"), nao); } else { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_args(&cs, c))); + match_files(mf_args(*c))); if (success) return cons(new_bindings, @@ -2743,9 +2725,8 @@ static val v_next_impl(match_files_ctx *c) if (rest(args)) { sem_error(specline, lit("(next :env) takes no additional arguments"), nao); } else { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_data(&cs, c, lit("env"), env(), one))); + match_files(mf_file_data(*c, lit("env"), env(), one))); if (success) return cons(new_bindings, @@ -2757,9 +2738,8 @@ static val v_next_impl(match_files_ctx *c) if (sym == var_s || sym == expr_s) meta = t; } else if (!source) { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_all(&cs, c->spec, nil, c->bindings, nil, lit("empty")))); + match_files(mf_all(c->spec, nil, c->bindings, nil, lit("empty")))); if (success) return cons(new_bindings, @@ -2814,9 +2794,8 @@ static val v_next_impl(match_files_ctx *c) val existing = tx_lookup_var_ubc(from_var, c->bindings, first_spec); { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_data(&cs, c, lit("var"), + match_files(mf_file_data(*c, lit("var"), lazy_flatten(cdr(existing)), one))); if (success) @@ -2833,9 +2812,8 @@ static val v_next_impl(match_files_ctx *c) goto nothrow_lisp; { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_data(&cs, c, lit("var"), + match_files(mf_file_data(*c, lit("var"), lazy_flatten(list_val), one))); if (success) @@ -2845,9 +2823,8 @@ static val v_next_impl(match_files_ctx *c) } } else if (tlist_expr) { val list_val = txeval(specline, tlist_expr, c->bindings); - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_data(&cs, c, lit("var"), + match_files(mf_file_data(*c, lit("var"), lazy_flatten(list_val), one))); if (success) @@ -2864,9 +2841,8 @@ static val v_next_impl(match_files_ctx *c) sem_error(specline, lit(":string arg ~s evaluated to non-string ~s"), string_expr, str_val, nao); { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_data(&cs, c, lit("var"), + match_files(mf_file_data(*c, lit("var"), split_str(str_val, lit("\n")), one))); if (success) @@ -2898,10 +2874,9 @@ static val v_next_impl(match_files_ctx *c) val stream = complex_open(str, nil, nil, nothrow, nil); if (stream) { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_file_lazy(&cs, c, str, - stream, one))); + match_files(mf_file_data(*c, str, + lazy_stream_cons(stream), one))); if (success) return cons(new_bindings, @@ -2926,8 +2901,7 @@ static val v_next_impl(match_files_ctx *c) original file we we were called with. Hence, we can't make a straight tail call here. */ { - match_files_ctx cs; - cons_bind (new_bindings, success, match_files(mf_data(&cs, c, t, nil))); + cons_bind (new_bindings, success, match_files(mf_data(*c, t, nil))); if (success) return cons(new_bindings, @@ -3004,9 +2978,8 @@ static val v_parallel(match_files_ctx *c) for (iter = specs; iter != nil; iter = rest(iter)) { val nested_spec = first(iter); - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_spec(&cs, c, nested_spec))); + match_files(mf_spec(*c, nested_spec))); if (success) { some_match = t; @@ -3132,9 +3105,8 @@ static val v_gather(match_files_ctx *c) for (iter = specs, next = cdr(iter); iter != nil; iter = next, next = cdr(iter)) { val nested_spec = first(iter); - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_spec(&cs, c, nested_spec))); + match_files(mf_spec(*c, nested_spec))); if (!success) { rplacd(iter, nil); @@ -3154,9 +3126,8 @@ static val v_gather(match_files_ctx *c) if (until_last) { - match_files_ctx cs; cons_bind (until_last_bindings, success, - match_files(mf_spec(&cs, c, ul_spec))); + match_files(mf_spec(*c, ul_spec))); if (success) { debuglf(specline, lit("until/last matched ~a:~d"), @@ -3438,13 +3409,11 @@ static val v_collect(match_files_ctx *c) break; { - match_files_ctx cs; - if (counter) { rplacd(counter_binding, plus(num(timescounter), counter_base)); rplacd(bindings_with_counter, c->bindings); cons_set (new_bindings, success, - match_files(mf_spec_bindings(&cs, c, coll_spec, bindings_with_counter))); + match_files(mf_spec_bindings(*c, coll_spec, bindings_with_counter))); if (!new_bindings) { rplacd(counter_binding, nil); @@ -3452,7 +3421,7 @@ static val v_collect(match_files_ctx *c) } } else { cons_set (new_bindings, success, - match_files(mf_spec(&cs, c, coll_spec))); + match_files(mf_spec(*c, coll_spec))); } /* Until/last clause sees un-collated bindings from collect. */ @@ -3460,7 +3429,7 @@ static val v_collect(match_files_ctx *c) { uses_or2; cons_bind (until_last_bindings, success, - match_files(mf_spec_bindings(&cs, c, ul_spec, + match_files(mf_spec_bindings(*c, ul_spec, or2(new_bindings, c->bindings)))); if (success) { @@ -3745,7 +3714,7 @@ static val v_bind(match_files_ctx *c) static val hv_trampoline(match_line_ctx *c) { val ret; - match_files_ctx cs, *mf = mf_from_ml(&cs, c); + match_files_ctx mf = mf_from_ml(*c); val sym = first(first(c->specline)); val entry = gethash(v_directive_table, sym); @@ -3754,9 +3723,9 @@ static val hv_trampoline(match_line_ctx *c) { v_match_func vmf = coerce(v_match_func, cptr_get(entry)); - ret = vmf(mf); + ret = vmf(&mf); if (ret == next_spec_k) - c->bindings = mf->bindings; + c->bindings = mf.bindings; return ret; } } @@ -3960,11 +3929,10 @@ static val v_try(match_files_ctx *c) val finally_clause = nil; { - match_files_ctx cs; uw_block_begin(nil, result); uw_catch_begin(catch_syms, exsym, exvals); - result = match_files(mf_spec(&cs, c, try_clause)); + result = match_files(mf_spec(*c, try_clause)); uw_catch(exsym, exvals) { { @@ -4000,9 +3968,8 @@ static val v_try(match_files_ctx *c) } if (all_bind) { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_spec(&cs, c, body))); + match_files(mf_spec(*c, body))); if (success) { c->bindings = new_bindings; result = t; /* catch succeeded, so try succeeds */ @@ -4058,9 +4025,8 @@ static val v_try(match_files_ctx *c) v_take_accept(c, specline, ex->bl.result); if (finally_clause) { - match_files_ctx cs; cons_bind (new_bindings, success, - match_files(mf_spec(&cs, c, finally_clause))); + match_files(mf_spec(*c, finally_clause))); if (success) { c->bindings = new_bindings; @@ -4269,14 +4235,12 @@ static val v_fun(match_files_ctx *c) { args_decl_list(args, ARGS_MIN, bindings_cp); - match_files_ctx cs; - uw_block_begin(nil, result); uw_match_env_begin; uw_simple_catch_begin; - result = match_files(mf_spec_bindings(&cs, c, body, bindings_cp)); + result = match_files(mf_spec_bindings(*c, body, bindings_cp)); uw_unwind { fun_intercept_accept(c->bindings, ub_p_a_pairs, sym, specline); @@ -4350,10 +4314,8 @@ static val v_if(match_files_ctx *c) for (; args; args = cdr(args)) { cons_bind (expr, spec, car(args)); - if (tleval(c->spec, expr, c->bindings)) { - match_files_ctx cs; - return maybe_next(c, match_files(mf_spec(&cs, c, spec))); - } + if (tleval(c->spec, expr, c->bindings)) + return maybe_next(c, match_files(mf_spec(*c, spec))); } return next_spec_k; @@ -4374,7 +4336,7 @@ static val v_assert(match_files_ctx *c) { val args = rest(first_spec); val type = pop(&args); - val result = match_files(c); + val result = match_files(*c); if (result) { return result; @@ -4448,8 +4410,7 @@ static val v_load(match_files_ctx *c) ret = parser->syntax_tree; } else { val spec = parser->syntax_tree; - match_files_ctx cs; - val result = match_files(mf_spec(&cs, c, spec)); + val result = match_files(mf_spec(*c, spec)); if (!result) { debuglf(specline, lit("load: ~a failed"), path, nao); @@ -4590,8 +4551,8 @@ static val v_call(match_files_ctx *c) val argexprs = cdr(exprs); val call = cons(funval, argexprs); val spec = cons(cons(call, nil), nil); - match_files_ctx cs, *nc = mf_spec_bindings(&cs, c, spec, c->bindings); - val ret = v_fun(nc); + match_files_ctx ctx = mf_spec_bindings(*c, spec, c->bindings); + val ret = v_fun(&ctx); if (ret == nil) return nil; @@ -4599,7 +4560,7 @@ static val v_call(match_files_ctx *c) if (ret == decline_k) sem_error(nil, lit("call: function ~s not found"), funval, nao); - return cons(cs.bindings, if3(cs.data, cons(cs.data, cs.data_lineno), t)); + return cons(ctx.bindings, if3(ctx.data, cons(ctx.data, ctx.data_lineno), t)); } static val h_do(match_line_ctx *c) @@ -4630,7 +4591,7 @@ static val h_assert(match_line_ctx *c) abort(); } -NOINLINE static void open_data_source(match_files_ctx *c) +static void open_data_source(match_files_ctx *c) { spec_bind (specline, first_spec, c->spec); int non_matching_dir = (consp(first_spec) && @@ -4691,18 +4652,18 @@ NOINLINE static void open_data_source(match_files_ctx *c) } } -static val match_files(match_files_ctx *c) +static val match_files(match_files_ctx c) { - gc_hint(c->data); + gc_hint(c.data); - for (; c->spec; c->spec = rest(c->spec), - c->data = rest(c->data), - c->data_lineno = plus(c->data_lineno, one)) + for (; c.spec; c.spec = rest(c.spec), + c.data = rest(c.data), + c.data_lineno = plus(c.data_lineno, one)) repeat_spec_same_data: { - spec_bind (specline, first_spec, c->spec); + spec_bind (specline, first_spec, c.spec); - open_data_source(c); + open_data_source(&c); /* Line with nothing but a single directive or call: vertical mode. */ if (consp(first_spec) && !rest(specline)) { @@ -4714,12 +4675,12 @@ repeat_spec_same_data: /* It's actually a var or text; go to horizontal processing below */ } else if (entry) { v_match_func vmf = coerce(v_match_func, cptr_get(entry)); - val result = vmf(c); + val result = vmf(&c); set_last_form_evaled(lfe_save); if (result == next_spec_k) { - if ((c->spec = rest(c->spec)) == nil) + if ((c.spec = rest(c.spec)) == nil) break; goto repeat_spec_same_data; } else if (result == decline_k) { @@ -4730,12 +4691,12 @@ repeat_spec_same_data: } else if (gethash(h_directive_table,sym)) { /* Lone horizontal-only directive: go to horizontal processing */ } else { - val result = v_fun(c); + val result = v_fun(&c); set_last_form_evaled(lfe_save); if (result == next_spec_k) { - if ((c->spec = rest(c->spec)) == nil) + if ((c.spec = rest(c.spec)) == nil) break; goto repeat_spec_same_data; } else if (result == decline_k) { @@ -4751,22 +4712,22 @@ repeat_spec_same_data: } } - open_data_source(c); + open_data_source(&c); - if (consp(c->data) && car(c->data)) + if (consp(c.data) && car(c.data)) { - val dataline = car(c->data); + val dataline = car(c.data); cons_bind (new_bindings, success, - match_line_completely(ml_all(c->bindings, specline, + match_line_completely(ml_all(c.bindings, specline, dataline, zero, - c->data, c->data_lineno, c->curfile))); + c.data, c.data_lineno, c.curfile))); if (!success) return nil; - c->bindings = new_bindings; - } else if (consp(c->data) || nilp(c->data)) { + c.bindings = new_bindings; + } else if (consp(c.data) || nilp(c.data)) { debuglf(specline, lit("spec ran out of data"), nao); return nil; } else { @@ -4774,7 +4735,7 @@ repeat_spec_same_data: } } - return cons(c->bindings, if3(c->data, cons(c->data, c->data_lineno), t)); + return cons(c.bindings, if3(c.data, cons(c.data, c.data_lineno), t)); } val match_filter(val name, val arg, val other_args) @@ -4787,8 +4748,8 @@ val match_filter(val name, val arg, val other_args) val spec = cons(list(cons(name, cons(in_arg_sym, cons(out_arg_sym, other_args))), nao), nil); - match_files_ctx cs, *c = mf_all(&cs, spec, nil, bindings, nil, nil); - val ret = v_fun(c); + match_files_ctx c = mf_all(spec, nil, bindings, nil, nil); + val ret = v_fun(&c); (void) first_spec; rlcp(car(spec), specline); @@ -4801,7 +4762,7 @@ val match_filter(val name, val arg, val other_args) sem_error(specline, lit("filter: function ~s not found"), name, nao); { - val out = tx_lookup_var(out_arg_sym, cs.bindings); + val out = tx_lookup_var(out_arg_sym, c.bindings); if (!out) sem_error(specline, lit("filter: (~s ~s ~s) did not bind ~s"), name, @@ -4825,10 +4786,10 @@ val match_fun(val name, val args, val input_in, val files_in) lazy_stream_cons(input), input); /* TODO: pass through source location context */ - match_files_ctx cs, *c = mf_all(&cs, spec, files, in_bindings, data, curfile); + match_files_ctx c = mf_all(spec, files, in_bindings, data, curfile); val ret; - ret = v_fun(c); + ret = v_fun(&c); if (ret == nil) return nil; @@ -4836,20 +4797,19 @@ val match_fun(val name, val args, val input_in, val files_in) if (ret == decline_k) sem_error(nil, lit("match-fun: function ~s not found"), name, nao); - return cons(cs.bindings, if3(cs.data, cons(cs.data, cs.data_lineno), t)); + return cons(c.bindings, if3(c.data, cons(c.data, c.data_lineno), t)); } val include(val specline) { val spec = cons(specline, nil); - match_files_ctx cs, *c = mf_all(&cs, spec, nil, nil, nil, nil); - return v_load(c); + match_files_ctx c = mf_all(spec, nil, nil, nil, nil); + return v_load(&c); } val extract(val spec, val files, val predefined_bindings) { - match_files_ctx cs; - val result = match_files(mf_all(&cs, spec, files, predefined_bindings, + val result = match_files(mf_all(spec, files, predefined_bindings, t, nil)); cons_bind (bindings, success, result); |