summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-02-21 22:32:18 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-02-21 22:32:18 -0800
commitfdf5459d3cae955aec6de756c4549de96105efe0 (patch)
tree651da4d587c3039492024c707f85b7c2f1442598
parent835eb2a789b734be42b3e3479fe7c8da0d959e62 (diff)
downloadtxr-fdf5459d3cae955aec6de756c4549de96105efe0.tar.gz
txr-fdf5459d3cae955aec6de756c4549de96105efe0.tar.bz2
txr-fdf5459d3cae955aec6de756c4549de96105efe0.zip
txr: pattern function calls are non-matching.
This patch causes TXR to treat calls to verticatl functions, as well as the @(call) directive to be considered non-matching directives, so that opening the data source is deferred. This allows included .txr files to call the funtions that they define, without the side effect of standard input being read. * match.c (open_data_source): Function refactored to reduce duplication. c->data is checked first, and if it is not t, nothing is done, making the function cheaper in the frequent case. The non_matching_dir condition changes. We now check that the first element of the first spec is a non-nil symbol. If it has a function binding as a vertical function, then that is considered non_matching. (dir_tables_init): Treat @(call) as a non-matching directive. * Makefile (tst/tests/008/no-stdin-hang.ok): Add -n argument for non-interactive, which will cause stdin to be read in that test case if there is a regression in this change. If make tests is run in a terminal, this will hang make tests. * tests/no-stdin-hang.txr: New file. * tests/no-stdin-hang.expected: New file.
-rw-r--r--Makefile1
-rw-r--r--match.c45
-rw-r--r--tests/008/no-stdin-hang.expected0
-rw-r--r--tests/008/no-stdin-hang.txr5
4 files changed, 29 insertions, 22 deletions
diff --git a/Makefile b/Makefile
index a7d71143..d0970049 100644
--- a/Makefile
+++ b/Makefile
@@ -390,6 +390,7 @@ tst/tests/008/configfile.ok: TXR_ARGS := tests/008/configfile
tst/tests/008/students.ok: TXR_ARGS := tests/008/students.xml
tst/tests/008/soundex.ok: TXR_ARGS := soundex sowndex lloyd lee jackson robert
tst/tests/008/filtenv.ok: TXR_OPTS := -B
+tst/tests/008/no-stdin-hang.ok: TXR_OPTS := -n
tst/tests/009/json.ok: TXR_ARGS := $(addprefix tests/009/,webapp.json pass1.json)
tst/tests/010/align-columns.ok: TXR_ARGS := tests/010/align-columns.dat
tst/tests/010/block.ok: TXR_OPTS := -B
diff --git a/match.c b/match.c
index 9782c937..ef2daf9d 100644
--- a/match.c
+++ b/match.c
@@ -4550,27 +4550,40 @@ static val h_assert(match_line_ctx *c)
static void open_data_source(match_files_ctx *c)
{
- spec_bind (specline, first_spec, c->spec);
- int non_matching_dir = (consp(first_spec) &&
- (gethash(non_matching_directive_table,
- first(first_spec))) &&
- !rest(specline));
-
/* c->data == t is set up by the top level call to match_files.
* It indicates that we have not yet opened any data source.
*/
- if (c->data == t && c->files) {
+ if (c->data == t) {
+ spec_bind (specline, first_spec, c->spec);
+
val source_spec = first(c->files);
val ss_consp = consp(source_spec);
val name = ss_consp ? cdr(source_spec) : source_spec;
- val nothrow = tnil(ss_consp && car(source_spec) == nothrow_k);
+ val op = if2(consp(first_spec), first(first_spec));
+ int non_matching_dir = (!rest(specline) && op && symbolp(op) &&
+ (gethash(non_matching_directive_table, op) ||
+ car(uw_get_func(op))));
- if (non_matching_dir) {
+ if (c->files == nil) {
+ if (opt_compat && opt_compat <= 170) {
+ c->data = nil;
+ } else if (non_matching_dir) {
+ debuglf(first_spec, lit("not opening standard input "
+ "since query starts with non-matching "
+ "directive."), nao);
+ } else {
+ debuglf(first_spec, lit("opening standard input as data source"), nao);
+ c->curfile = lit("-");
+ c->data = lazy_stream_cons(std_input);
+ c->data_lineno = one;
+ }
+ } else if (non_matching_dir) {
debuglf(first_spec, lit("not opening source ~a "
"since query starts with non-matching "
"directive."), name, nao);
} else if (stringp(name)) {
+ val nothrow = tnil(ss_consp && car(source_spec) == nothrow_k);
val stream = complex_open(name, nil, nil, nothrow, t);
debuglf(specline, lit("opening data source ~a"), name, nao);
@@ -4593,19 +4606,6 @@ static void open_data_source(match_files_ctx *c)
} else {
sem_error(specline, lit("~s doesn't denote a valid data source"), name, nao);
}
- } else if (c->data == t && c->files == nil) {
- if (opt_compat && opt_compat <= 170) {
- c->data = nil;
- } else if (non_matching_dir) {
- debuglf(first_spec, lit("not opening standard input "
- "since query starts with non-matching "
- "directive."), nao);
- } else {
- debuglf(first_spec, lit("opening standard input as data source"), nao);
- c->curfile = lit("-");
- c->data = lazy_stream_cons(std_input);
- c->data_lineno = one;
- }
}
}
@@ -5007,6 +5007,7 @@ static void dir_tables_init(void)
sethash(non_matching_directive_table, do_s, t);
sethash(non_matching_directive_table, load_s, t);
sethash(non_matching_directive_table, close_s, t);
+ sethash(non_matching_directive_table, call_s, t);
sethash(binding_directive_table, var_s, one);
sethash(binding_directive_table, merge_s, one);
diff --git a/tests/008/no-stdin-hang.expected b/tests/008/no-stdin-hang.expected
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/008/no-stdin-hang.expected
diff --git a/tests/008/no-stdin-hang.txr b/tests/008/no-stdin-hang.txr
new file mode 100644
index 00000000..4b29f021
--- /dev/null
+++ b/tests/008/no-stdin-hang.txr
@@ -0,0 +1,5 @@
+@(define foo (var))
+@(next :list '("a"))
+@var
+@(end)
+@(foo x)