summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog25
-rw-r--r--lib.c26
-rw-r--r--lib.h4
-rw-r--r--match.c189
4 files changed, 166 insertions, 78 deletions
diff --git a/ChangeLog b/ChangeLog
index 05883385..b2ecc470 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2011-10-17 Kaz Kylheku <kaz@kylheku.com>
+
+ Task #11425.
+
+ Vertical skip directive moved into function dispatched
+ via hash table. Test suite passes.
+
+ * lib.c (cptr_s): New symbol variable.
+ (cptr_equal_op): New static function.
+ (cptr_equal_op, cptr, cptr_get): New functions.
+ (cptr_ops): New static structure.
+ (obj_init): New variable initialized.
+
+ * lib.h (cptr_s, cptr, cptr_get): Declared.
+
+ * match.c (decline_k, same_data_k): New symbol variables.
+ (v_match_func): New typedef.
+ (v_skip): New function.
+ (match_files): Check symbol in v_directive_table and dispatch
+ the associated function if an entry exists.
+ Skip directive handling moved to v_skip function.
+ (syms_init): Initialize new symbol variables.
+ (dir_tables_init): Enter v_skip into v_directive_table under
+ skip_s symbol.
+
2011-10-16 Kaz Kylheku <kaz@kylheku.com>
Quick and dirty port to MinGW.
diff --git a/lib.c b/lib.c
index 87a03c06..e490228c 100644
--- a/lib.c
+++ b/lib.c
@@ -51,7 +51,7 @@ val packages;
val system_package, keyword_package, user_package;
val null, t, cons_s, str_s, chr_s, num_s, sym_s, pkg_s, fun_s, vec_s;
-val stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s;
+val stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s, cptr_s;
val var_s, expr_s, regex_s, chset_s, set_s, cset_s, wild_s, oneplus_s;
val nongreedy_s, compiled_regex_s;
val zeroplus_s, optional_s, compl_s, compound_s, or_s, and_s, quasi_s;
@@ -1872,6 +1872,29 @@ void cobj_print_op(val obj, val out)
format(out, lit(": ~p>"), obj->co.handle, nao);
}
+static val cptr_equal_op(val left, val right)
+{
+ return (left->co.handle == right->co.handle) ? t : nil;
+}
+
+static struct cobj_ops cptr_ops = {
+ cptr_equal_op,
+ cobj_print_op,
+ cobj_destroy_stub_op,
+ cobj_mark_op,
+ cobj_hash_op
+};
+
+val cptr(mem_t *ptr)
+{
+ return cobj(ptr, cptr_s, &cptr_ops);
+}
+
+mem_t *cptr_get(val cptr)
+{
+ return cobj_handle(cptr, cptr_s);
+}
+
val assoc(val list, val key)
{
while (list) {
@@ -2160,6 +2183,7 @@ static void obj_init(void)
lcons_s = intern(lit("lcons"), user_package);
lstr_s = intern(lit("lstr"), user_package);
cobj_s = intern(lit("cobj"), user_package);
+ cptr_s = intern(lit("cptr"), user_package);
var_s = intern(lit("var"), system_package);
expr_s = intern(lit("expr"), system_package);
regex_s = intern(lit("regex"), system_package);
diff --git a/lib.h b/lib.h
index 7255e4f1..a132296c 100644
--- a/lib.h
+++ b/lib.h
@@ -240,7 +240,7 @@ INLINE val chr(wchar_t ch)
extern val keyword_package, system_package, user_package;
extern val null, t, cons_s, str_s, chr_s, num_s, sym_s, pkg_s, fun_s, vec_s;
-extern val stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s;
+extern val stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s, cptr_s;
extern val var_s, expr_s, regex_s, chset_s, set_s, cset_s, wild_s, oneplus_s;
extern val nongreedy_s, compiled_regex_s;
extern val zeroplus_s, optional_s, compl_s, compound_s, or_s, and_s, quasi_s;
@@ -403,6 +403,8 @@ val length_str_le(val str, val len);
val cobj(mem_t *handle, val cls_sym, struct cobj_ops *ops);
val cobjp(val obj);
mem_t *cobj_handle(val cobj, val cls_sym);
+val cptr(mem_t *ptr);
+mem_t *cptr_get(val cptr);
val assoc(val list, val key);
val acons(val list, val car, val cdr);
val acons_new(val list, val key, val value);
diff --git a/match.c b/match.c
index f3ca2818..644387f1 100644
--- a/match.c
+++ b/match.c
@@ -48,6 +48,7 @@
int output_produced;
+val decline_k, same_data_k;
val mingap_k, maxgap_k, gap_k, mintimes_k, maxtimes_k, times_k;
val lines_k, chars_k;
val choose_s, longest_k, shortest_k, greedy_k;
@@ -1309,9 +1310,100 @@ static match_files_ctx mf_spec_bindings(match_files_ctx c, val spec,
}
-
static val match_files(match_files_ctx a);
+typedef val (*v_match_func)(match_files_ctx c, match_files_ctx *cout);
+
+static val v_skip(match_files_ctx c, match_files_ctx *cout)
+{
+ val specline = rest(first(c.spec));
+ val other_specs = rest(c.spec);
+
+ if (other_specs == nil) {
+ *cout = c;
+ return same_data_k;
+ }
+
+ if (rest(specline) == nil) {
+ val spec_linenum = first(first(c.spec));
+ val first_spec = first(specline);
+ val args = rest(first_spec);
+ val max = first(args);
+ val min = second(args);
+ cnum cmax = nump(max) ? c_num(max) : 0;
+ cnum cmin = nump(min) ? c_num(min) : 0;
+ val greedy = eq(max, greedy_k);
+ val last_good_result = nil;
+ val last_good_line = num(0);
+
+ {
+ cnum reps_max = 0, reps_min = 0;
+ uw_block_begin(nil, result);
+
+ while (c.data && min && reps_min < cmin) {
+ c.data = rest(c.data);
+ c.data_lineno = plus(c.data_lineno, num(1));
+ reps_min++;
+ }
+
+ if (min) {
+ if (reps_min != cmin) {
+ debuglf(spec_linenum, lit("skipped only ~a/~a lines to ~a:~a"),
+ num(reps_min), num(cmin),
+ first(c.files), c.data_lineno, nao);
+ uw_block_return(nil, nil);
+ }
+
+ debuglf(spec_linenum, lit("skipped ~a lines to ~a:~a"),
+ num(reps_min), first(c.files),
+ c.data_lineno, nao);
+ }
+
+ while (greedy || !max || reps_max++ < cmax) {
+ result = match_files(mf_spec(c, other_specs));
+
+ if (result) {
+ if (greedy) {
+ last_good_result = result;
+ last_good_line = c.data_lineno;
+ } else {
+ debuglf(spec_linenum, lit("skip matched ~a:~a"), first(c.files),
+ c.data_lineno, nao);
+ break;
+ }
+ } else {
+ debuglf(spec_linenum, lit("skip didn't match ~a:~a"),
+ first(c.files), c.data_lineno, nao);
+ }
+
+ if (!c.data)
+ break;
+
+ debuglf(spec_linenum, lit("skip didn't match ~a:~a"), first(c.files),
+ c.data_lineno, nao);
+
+ c.data = rest(c.data);
+ c.data_lineno = plus(c.data_lineno, num(1));
+ }
+
+ uw_block_end;
+
+ if (result)
+ return result;
+ if (last_good_result) {
+ debuglf(spec_linenum, lit("greedy skip matched ~a:~a"),
+ first(c.files), last_good_line, nao);
+ return last_good_result;
+ }
+ }
+
+ debuglf(spec_linenum, lit("skip failed"), nao);
+ return nil;
+ }
+
+ return decline_k;
+}
+
static val match_files(match_files_ctx c)
{
gc_hint(c.data);
@@ -1363,85 +1455,26 @@ repeat_spec_same_data:
if (consp(first_spec)) {
val sym = first(first_spec);
+ val entry = gethash(v_directive_table, sym);
+ if (entry) {
+ v_match_func vmf = (v_match_func) cptr_get(entry);
+ match_files_ctx nc;
+ val result = vmf(c, &nc);
- if (sym == skip_s && rest(specline) == nil) {
- val args = rest(first_spec);
- val max = first(args);
- val min = second(args);
- cnum cmax = nump(max) ? c_num(max) : 0;
- cnum cmin = nump(min) ? c_num(min) : 0;
- val greedy = eq(max, greedy_k);
- val last_good_result = nil;
- val last_good_line = num(0);
-
- if ((c.spec = rest(c.spec)) == nil)
- break;
-
- {
- cnum reps_max = 0, reps_min = 0;
- uw_block_begin(nil, result);
-
- while (c.data && min && reps_min < cmin) {
- c.data = rest(c.data);
- c.data_lineno = plus(c.data_lineno, num(1));
- reps_min++;
- }
-
- if (min) {
- if (reps_min != cmin) {
- debuglf(spec_linenum, lit("skipped only ~a/~a lines to ~a:~a"),
- num(reps_min), num(cmin),
- first(c.files), c.data_lineno, nao);
- uw_block_return(nil, nil);
- }
-
- debuglf(spec_linenum, lit("skipped ~a lines to ~a:~a"),
- num(reps_min), first(c.files),
- c.data_lineno, nao);
- }
-
- while (greedy || !max || reps_max++ < cmax) {
- result = match_files(c);
-
- if (result) {
- if (greedy) {
- last_good_result = result;
- last_good_line = c.data_lineno;
- } else {
- debuglf(spec_linenum, lit("skip matched ~a:~a"), first(c.files),
- c.data_lineno, nao);
- break;
- }
- } else {
- debuglf(spec_linenum, lit("skip didn't match ~a:~a"),
- first(c.files), c.data_lineno, nao);
- }
-
- if (!c.data)
- break;
-
- debuglf(spec_linenum, lit("skip didn't match ~a:~a"), first(c.files),
- c.data_lineno, nao);
-
- c.data = rest(c.data);
- c.data_lineno = plus(c.data_lineno, num(1));
- }
-
- uw_block_end;
-
- if (result)
- return result;
- if (last_good_result) {
- debuglf(spec_linenum, lit("greedy skip matched ~a:~a"),
- first(c.files), last_good_line, nao);
- return last_good_result;
- }
+ if (result == same_data_k) {
+ c = nc;
+ if ((c.spec = rest(c.spec)) == nil)
+ break;
+ goto repeat_spec_same_data;
+ } else if (result == decline_k) {
+ /* go on to other processing below */
+ } else {
+ return result;
}
+ }
- debuglf(spec_linenum, lit("skip failed"), nao);
- return nil;
- } else if (sym == trailer_s && !rest(specline)) {
+ if (sym == trailer_s && !rest(specline)) {
if ((c.spec = rest(c.spec)) == nil)
break;
@@ -2400,6 +2433,8 @@ int extract(val spec, val files, val predefined_bindings)
static void syms_init(void)
{
+ decline_k = intern(lit("decline"), keyword_package);
+ same_data_k = intern(lit("same_data"), keyword_package);
mingap_k = intern(lit("mingap"), keyword_package);
maxgap_k = intern(lit("maxgap"), keyword_package);
gap_k = intern(lit("gap"), keyword_package);
@@ -2419,6 +2454,8 @@ static void dir_tables_init(void)
{
h_directive_table = make_hash(nil, nil);
v_directive_table = make_hash(nil, nil);
+
+ sethash(v_directive_table, skip_s, cptr((mem_t *) v_skip));
}
void match_init(void)