diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | lib.c | 36 | ||||
-rw-r--r-- | lib.h | 3 | ||||
-rw-r--r-- | match.c | 11 |
4 files changed, 55 insertions, 10 deletions
@@ -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. @@ -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); } @@ -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); @@ -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, |