summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2012-02-11 23:51:05 -0800
committerKaz Kylheku <kaz@kylheku.com>2012-02-11 23:51:05 -0800
commitfce7c87fa0099e5414607676fc73c9dfa9d7649c (patch)
tree6b080b309e798196061f8ad7e9a0c6ea6cbaa24b /match.c
parentaa2516fecfd6857206756efa891b058deceeb8dd (diff)
downloadtxr-fce7c87fa0099e5414607676fc73c9dfa9d7649c.tar.gz
txr-fce7c87fa0099e5414607676fc73c9dfa9d7649c.tar.bz2
txr-fce7c87fa0099e5414607676fc73c9dfa9d7649c.zip
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.
Diffstat (limited to 'match.c')
-rw-r--r--match.c86
1 files changed, 60 insertions, 26 deletions
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);