summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-02-22 16:34:51 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-02-22 16:34:51 -0800
commit77791d10d0143c991262697e099efc2db1a7f4a1 (patch)
tree1b092914dd66317fdffe3bdcc2f095b8686a5939
parentf526353736b4fa30115ee6cf64142bdad794e4c9 (diff)
downloadtxr-77791d10d0143c991262697e099efc2db1a7f4a1.tar.gz
txr-77791d10d0143c991262697e099efc2db1a7f4a1.tar.bz2
txr-77791d10d0143c991262697e099efc2db1a7f4a1.zip
txr: tighten keyword arg parsing in @(next).
This fixes the bug of not allowing @(next :list nil). Also the bug of @(next :string) or @(next :string nil) reporting a nonsensical error message, instead of correctly complaining that nil isn't a string. * match.c (v_next_impl): Capture the conses returned by assoc, so we know whether a keyword is present. Then use those conses in tests which detect whether the keyword is present, rather than the values, which could be nil.
-rw-r--r--match.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/match.c b/match.c
index aa9a0f74..d95331e3 100644
--- a/match.c
+++ b/match.c
@@ -2718,24 +2718,28 @@ static val v_next_impl(match_files_ctx *c)
{
int old_hacky_open = opt_compat && opt_compat <= 142;
val alist = improper_plist_to_alist(args, list(nothrow_k, nao));
- val from_var = cdr(assoc(var_k, alist));
- val list_expr = cdr(assoc(list_k, alist));
- val tlist_expr = cdr(assoc(tlist_k, alist));
- val string_expr = cdr(assoc(string_k, alist));
+ val from_var_p = assoc(var_k, alist);
+ val from_var = cdr(from_var_p);
+ val list_p = assoc(list_k, alist);
+ val list_expr = cdr(list_p);
+ val tlist_p = assoc(tlist_k, alist);
+ val tlist_expr = cdr(tlist_p);
+ val string_p = assoc(string_k, alist);
+ val string_expr = cdr(string_p);
val nothrow = cdr(assoc(nothrow_k, alist));
val str = if3(meta,
txeval(specline, source, c->bindings),
tleval_nothrow(specline, source, c->bindings, nothrow));
- if (!from_var && !source && !string_expr && !list_expr && !tlist_expr)
+ if (!from_var_p && !source && !string_p && !list_p && !tlist_p)
sem_error(specline, lit("next: source required before keyword arguments"), nao);
{
int count = (source != nil) +
- (from_var != nil) +
- (list_expr != nil) +
- (tlist_expr != nil) +
- (string_expr != nil);
+ (from_var_p != nil) +
+ (list_p != nil) +
+ (tlist_p != nil) +
+ (string_p != nil);
if (count > 1)
{
@@ -2746,7 +2750,7 @@ static val v_next_impl(match_files_ctx *c)
if (!meta && source && nothrow && str == colon_k)
goto nothrow_lisp;
- if (from_var) {
+ if (from_var_p) {
val existing = tx_lookup_var_ubc(from_var, c->bindings, first_spec);
{
@@ -2759,7 +2763,7 @@ static val v_next_impl(match_files_ctx *c)
if3(c->data, cons(c->data, c->data_lineno), t));
return nil;
}
- } else if (list_expr) {
+ } else if (list_p) {
val list_val = if3(opt_compat && opt_compat <= 143,
txeval(specline, list_expr, c->bindings),
tleval_nothrow(specline, list_expr, c->bindings, nothrow));
@@ -2777,7 +2781,7 @@ static val v_next_impl(match_files_ctx *c)
if3(c->data, cons(c->data, c->data_lineno), t));
return nil;
}
- } else if (tlist_expr) {
+ } else if (tlist_p) {
val list_val = txeval(specline, tlist_expr, c->bindings);
cons_bind (new_bindings, success,
match_files(mf_file_data(*c, lit("var"),
@@ -2787,7 +2791,7 @@ static val v_next_impl(match_files_ctx *c)
return cons(new_bindings,
if3(c->data, cons(c->data, c->data_lineno), t));
return nil;
- } else if (string_expr) {
+ } else if (string_p) {
val str_val = tleval_144_nothrow(specline, string_expr, c->bindings, nothrow);
if (nothrow && str_val == colon_k)