From fce7c87fa0099e5414607676fc73c9dfa9d7649c Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sat, 11 Feb 2012 23:51:05 -0800 Subject: Task #11486: continuation. Now able to @(skip) through a large file horizontally under @(freeform) in constant memory. Position reporting is incorrect. * match.c (match_line_ctx): New member, base. (ml_all): Initialize new member to zero. (consume_prefix): New static function. (do_match_line): New static function, contains implementation of match_line. Calls consume_prefix. (match_line): Becomes a wrapper for do_match_line. (search_form, h_skip): Call consume_prefix. (freeform_prepare): New function. External to avoid inlining. (v_freeform): Uses do_match_line, to down context by reference, and also refactored to avoid spurious retention of c->data. * unwind.c (uw_push-block, uw_push_env, uw_push_debug, uw_push_catch): Zero out the structure, otherwise the unused fields can cause spurious retention. --- ChangeLog | 21 ++++++++++++++++ match.c | 86 ++++++++++++++++++++++++++++++++++++++++++++------------------- unwind.c | 5 ++++ 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13f9fd16..7355f133 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2012-02-11 Kaz Kylheku + + Task #11486: continuation. Now able to @(skip) through + a large file horizontally under @(freeform) in constant memory. + Position reporting is incorrect. + + * match.c (match_line_ctx): New member, base. + (ml_all): Initialize new member to zero. + (consume_prefix): New static function. + (do_match_line): New static function, contains implementation of + match_line. Calls consume_prefix. + (match_line): Becomes a wrapper for do_match_line. + (search_form, h_skip): Call consume_prefix. + (freeform_prepare): New function. External to avoid inlining. + (v_freeform): Uses do_match_line, to down context by reference, + and also refactored to avoid spurious retention of c->data. + + * unwind.c (uw_push-block, uw_push_env, uw_push_debug, + uw_push_catch): Zero out the structure, otherwise the unused + fields can cause spurious retention. + 2012-02-09 Kaz Kylheku Task #11486: preparatory refactoring. diff --git a/match.c b/match.c index 93d57c70..6fe35112 100644 --- a/match.c +++ b/match.c @@ -337,14 +337,14 @@ static val vars_to_bindings(val spec, val vars, val bindings) } typedef struct { - val bindings, specline, dataline, pos, data_lineno, file; + val bindings, specline, dataline, base, pos, data_lineno, file; } match_line_ctx; static match_line_ctx ml_all(val bindings, val specline, val dataline, val pos, val data_lineno, val file) { match_line_ctx c = { bindings, specline, dataline, - pos, data_lineno, file }; + zero, pos, data_lineno, file }; return c; } @@ -373,6 +373,7 @@ static match_line_ctx ml_bindings_specline(match_line_ctx c, val bindings, return nc; } +static val do_match_line(match_line_ctx *c); static val match_line(match_line_ctx c); typedef val (*h_match_func)(match_line_ctx *c); @@ -410,6 +411,19 @@ static val h_text(match_line_ctx *c) return nil; } +static void consume_prefix(match_line_ctx *c) +{ + const val shift_hiwater = num_fast(4000); + const val shift_amount = num_fast(3900); + + if (gt(c->pos, shift_hiwater)) { + c->base = plus(c->base, shift_amount); + c->pos = minus(c->pos, shift_amount); + c->dataline = sub_str(c->dataline, shift_amount, t); + } +} + + static val search_form(match_line_ctx *c, val needle_form, val from_end) { if (regexp(first(needle_form))) { @@ -431,6 +445,8 @@ static val search_form(match_line_ctx *c, val needle_form, val from_end) c->bindings = new_bindings; return cons(pos, minus(new_pos, pos)); } + + consume_prefix(c); } return nil; @@ -636,6 +652,7 @@ static val h_skip(match_line_ctx *c) while (length_str_gt(c->dataline, c->pos) && min && reps_min < cmin) { c->pos = plus(c->pos, one); reps_min++; + consume_prefix(c); } if (min) { @@ -673,6 +690,7 @@ static val h_skip(match_line_ctx *c) } c->pos = plus(c->pos, one); + consume_prefix(c); } } @@ -1078,18 +1096,18 @@ static match_files_ctx mf_all(val spec, val files, val bindings, static val v_fun(match_files_ctx *c); -static val match_line(match_line_ctx cin) +static val do_match_line(match_line_ctx *c) { debug_enter; - match_line_ctx *c = &cin; - for (;;) { val elem; if (c->specline == nil) break; + consume_prefix(c); + elem = first(c->specline); debug_check(elem, c->bindings, c->dataline, c->data_lineno, c->pos); @@ -1191,6 +1209,11 @@ static val match_line(match_line_ctx cin) debug_leave; } +static val match_line(match_line_ctx c) +{ + return do_match_line(&c); +} + val format_field(val obj, val modifier, val filter, val eval_fun) { val n = zero, sep = lit(" "); @@ -2014,6 +2037,8 @@ static val v_trailer(match_files_ctx *c) } } +void freeform_prepare(val vals, match_files_ctx *c, match_line_ctx *mlc); + static val v_freeform(match_files_ctx *c) { spec_bind (specline, first_spec, c->spec); @@ -2029,34 +2054,43 @@ static val v_freeform(match_files_ctx *c) debuglf(specline, lit("freeform match failure: no data"), nao); return nil; } else { - uses_or2; - val limit = or2(if2(fixnump(first(vals)), first(vals)), - if2(fixnump(second(vals)), second(vals))); - val term = or2(if2(stringp(first(vals)), first(vals)), - if2(stringp(second(vals)), second(vals))); - val ff_specline = first(c->spec); - val ff_dataline = lazy_str(c->data, term, limit); - - cons_bind (new_bindings, success, - match_line(ml_all(c->bindings, ff_specline, ff_dataline, zero, - c->data_lineno, first(c->files)))); - - if (!success) { - debuglf(specline, lit("freeform match failure"), nao); - return nil; - } + match_line_ctx mlc; + freeform_prepare(vals, c, &mlc); + c->data = nil; - if (fixnump(success)) { - c->data = lazy_str_get_trailing_list(ff_dataline, success); - c->data_lineno = plus(c->data_lineno, num(1)); - } + { + cons_bind (new_bindings, success, do_match_line(&mlc)); + + if (!success) { + debuglf(specline, lit("freeform match failure"), nao); + return nil; + } - c->bindings = new_bindings; + if (fixnump(success)) { + c->data = lazy_str_get_trailing_list(mlc.dataline, success); + c->data_lineno = plus(c->data_lineno, one); + } + + c->bindings = new_bindings; + } } return next_spec_k; } +void freeform_prepare(val vals, match_files_ctx *c, match_line_ctx *mlc) +{ + uses_or2; + val first_spec = first(c->spec); + val limit = or2(if2(fixnump(first(vals)), first(vals)), + if2(fixnump(second(vals)), second(vals))); + val term = or2(if2(stringp(first(vals)), first(vals)), + if2(stringp(second(vals)), second(vals))); + val dataline = lazy_str(c->data, term, limit); + *mlc = ml_all(c->bindings, first_spec, dataline, zero, c->data_lineno, first(c->files)); +} + + static val v_block(match_files_ctx *c) { spec_bind (specline, first_spec, c->spec); diff --git a/unwind.c b/unwind.c index bb081994..ac99665a 100644 --- a/unwind.c +++ b/unwind.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -98,6 +99,7 @@ static void uw_unwind_to_exit_point(void) void uw_push_block(uw_frame_t *fr, val tag) { + memset(fr, 0, sizeof *fr); fr->bl.type = UW_BLOCK; fr->bl.tag = tag; fr->bl.result = nil; @@ -113,6 +115,7 @@ static uw_frame_t *uw_find_env(void) void uw_push_env(uw_frame_t *fr) { uw_frame_t *prev_env = uw_find_env(); + memset(fr, 0, sizeof *fr); fr->ev.type = UW_ENV; fr->ev.up_env = prev_env; fr->ev.func_bindings = nil; @@ -161,6 +164,7 @@ void uw_push_debug(uw_frame_t *fr, val func, val args, val ub_p_a_pairs, val env, val data, val line, val chr) { + memset(fr, 0, sizeof *fr); fr->db.type = UW_DBG; fr->db.func = func; fr->db.args = args; @@ -208,6 +212,7 @@ val uw_block_return(val tag, val result) void uw_push_catch(uw_frame_t *fr, val matches) { + memset(fr, 0, sizeof *fr); fr->ca.type = UW_CATCH; fr->ca.matches = matches; fr->ca.exception = nil; -- cgit v1.2.3