summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--lib.c36
-rw-r--r--lib.h3
-rw-r--r--match.c11
4 files changed, 55 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 314b26a9..dbe446c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2009-10-20 Kaz Kylheku <kkylheku@gmail.com>
+ Implement custom separator and limit in freeform.
+
+ * lib.h (lazy_string): New struct member, opts.
+ (lazy_str): Declaration updated.
+
+ * lib.c (lazy_str): New constructor parameters to set the
+ seprator string and numeric line limit.
+ (lazy_str_force, lazy_str_upto): Honor the line limit,
+ and use the separator string if provided.
+
+ * match.c (match_files): Process the arguments for freeform
+ directive.
+
+2009-10-20 Kaz Kylheku <kkylheku@gmail.com>
+
* lib.c (sub_str): Avoid invoking c_str which forces the
lazy string.
diff --git a/lib.c b/lib.c
index 8bb72dc1..b942703a 100644
--- a/lib.c
+++ b/lib.c
@@ -1357,7 +1357,7 @@ obj_t *lazy_stream_cons(obj_t *stream)
lazy_stream_func));
}
-obj_t *lazy_str(obj_t *list)
+obj_t *lazy_str(obj_t *list, obj_t *sep, obj_t *limit)
{
obj_t *obj = make_obj();
obj->ls.type = LSTR;
@@ -1368,19 +1368,31 @@ obj_t *lazy_str(obj_t *list)
} else {
obj->ls.prefix = first(list);
obj->ls.list = rest(list);
+ limit = if2(limit, minus(limit, one));
}
+ obj->ls.opts = cons(sep, limit);
+
return obj;
}
obj_t *lazy_str_force(obj_t *lstr)
{
+ obj_t *lim;
type_check(lstr, LSTR);
-
- if (lstr->ls.list) {
- lstr->ls.prefix = cat_str(cons(lstr->ls.prefix, lstr->ls.list),
- string("\n"));
+ lim = cdr(lstr->ls.opts);
+
+ if (!lim) {
+ if (lstr->ls.list) {
+ lstr->ls.prefix = cat_str(cons(lstr->ls.prefix, lstr->ls.list),
+ or2(car(lstr->ls.opts), string("\n")));
+ lstr->ls.list = nil;
+ }
+ } else while (gt(lim, zero) && lstr->ls.list) {
+ lstr->ls.prefix = cat_str(list(lstr->ls.prefix, car(lstr->ls.list), nao),
+ or2(car(lstr->ls.opts), string("\n")));
lstr->ls.list = nil;
+ lim = minus(lim, one);
}
return lstr->ls.prefix;
@@ -1388,14 +1400,22 @@ obj_t *lazy_str_force(obj_t *lstr)
obj_t *lazy_str_force_upto(obj_t *lstr, obj_t *index)
{
+ obj_t *lim;
type_check(lstr, LSTR);
+ lim = cdr(lstr->ls.opts);
- while (gt(index, length_str(lstr->ls.prefix)) && lstr->ls.list) {
+ while (gt(index, length_str(lstr->ls.prefix)) && lstr->ls.list &&
+ or2(nullp(lim),gt(lim,zero)))
+ {
obj_t *next = pop(&lstr->ls.list);
lstr->ls.prefix = cat_str(cons(lstr->ls.prefix, cons(next, nil)),
- string("\n"));
+ or2(car(lstr->ls.opts), string("\n")));
+ if (lim)
+ lim = minus(lim, one);
}
+ if (lim)
+ *cdr_l(lstr->ls.opts) = lim;
return lt(index, length_str(lstr->ls.prefix));
}
@@ -1469,7 +1489,7 @@ obj_t *lazy_str_get_trailing_list(obj_t *lstr, obj_t *index)
{
obj_t *split_suffix = split_str(sub_str(lstr->ls.prefix, index, nil),
- string("\n"));
+ or2(car(lstr->ls.opts), string("\n")));
return nappend2(split_suffix, lstr->ls.list);
}
diff --git a/lib.h b/lib.h
index e1282ed1..cff8d9bd 100644
--- a/lib.h
+++ b/lib.h
@@ -121,6 +121,7 @@ struct lazy_string {
type_t type;
obj_t *prefix; /* actual string part */
obj_t *list; /* remaining list */
+ obj_t *opts; /* ( limit . sepstring ) */
};
struct cobj {
@@ -288,7 +289,7 @@ obj_t *vec_set_fill(obj_t *vec, obj_t *fill);
obj_t **vecref_l(obj_t *vec, obj_t *ind);
obj_t *vec_push(obj_t *vec, obj_t *item);
obj_t *lazy_stream_cons(obj_t *stream);
-obj_t *lazy_str(obj_t *list);
+obj_t *lazy_str(obj_t *list, obj_t *sep, obj_t *limit);
obj_t *lazy_str_force_upto(obj_t *lstr, obj_t *index);
obj_t *lazy_str_force(obj_t *lstr);
obj_t *lazy_str_get_trailing_list(obj_t *lstr, obj_t *index);
diff --git a/match.c b/match.c
index e90d3d6f..675e3d0f 100644
--- a/match.c
+++ b/match.c
@@ -984,12 +984,21 @@ repeat_spec_same_data:
return nil;
}
} else if (sym == freeform) {
+ obj_t *args = rest(rest(first_spec));
+ obj_t *vals = mapcar(func_n1(cdr),
+ mapcar(bind2other(func_n2(eval_form),
+ bindings), args));
+
if ((spec = rest(spec)) == nil) {
sem_error(spec_linenum,
"freeform must be followed by a query line", nao);
} else {
+ obj_t *limit = or2(if2(nump(first(vals)), first(vals)),
+ if2(nump(second(vals)), second(vals)));
+ obj_t *sep = or2(if2(stringp(first(vals)), first(vals)),
+ if2(stringp(second(vals)), second(vals)));
obj_t *ff_specline = rest(first(spec));
- obj_t *ff_dataline = lazy_str(data);
+ obj_t *ff_dataline = lazy_str(data, sep, limit);
cons_bind (new_bindings, success,
match_line(bindings, ff_specline, ff_dataline, zero,