summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure20
-rw-r--r--eval.c1
-rw-r--r--match.c60
-rw-r--r--parser.l2
-rw-r--r--stream.c134
-rw-r--r--stream.h6
-rw-r--r--txr.c4
7 files changed, 155 insertions, 72 deletions
diff --git a/configure b/configure
index 22b61cdc..b184d6c4 100755
--- a/configure
+++ b/configure
@@ -1278,6 +1278,26 @@ int x = sizeof ((struct tm *) 0)->$try_field;
fi
done
+printf "Checking for POSIX sleep function ... "
+
+cat > conftest.c <<!
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+ sleep(42);
+ return 0;
+}
+!
+rm -f conftest
+if ! $make conftest > conftest.err 2>&1 || ! [ -x conftest ] ; then
+ printf "no\n"
+else
+ printf "yes\n"
+ printf "#define HAVE_POSIX_SLEEP 1\n" >> config.h
+fi
+
+
printf "done\n"
#
diff --git a/eval.c b/eval.c
index 1bbab315..003a0623 100644
--- a/eval.c
+++ b/eval.c
@@ -2366,6 +2366,7 @@ void eval_init(void)
reg_fun(intern(lit("open-directory"), user_package), func_n1(open_directory));
reg_fun(intern(lit("open-file"), user_package), func_n2(open_file));
+ reg_fun(intern(lit("open-tail"), user_package), func_n3(open_tail));
reg_fun(intern(lit("open-command"), user_package), func_n2(open_command));
reg_fun(intern(lit("open-pipe"), user_package), func_n2(open_command));
reg_fun(intern(lit("open-process"), user_package), func_n3o(open_process, 2));
diff --git a/match.c b/match.c
index c8517201..100089b7 100644
--- a/match.c
+++ b/match.c
@@ -1521,9 +1521,9 @@ static val complex_snarf(fpip_t fp, val name)
{
switch (fp.close) {
case fpip_fclose:
- return lazy_stream_cons(make_stdio_stream(fp.f, name, t, nil));
+ return lazy_stream_cons(make_stdio_stream(fp.f, name));
case fpip_pclose:
- return lazy_stream_cons(make_pipe_stream(fp.f, name, t, nil));
+ return lazy_stream_cons(make_pipe_stream(fp.f, name));
case fpip_closedir:
return lazy_stream_cons(make_dir_stream(fp.d));
}
@@ -1535,9 +1535,9 @@ static val complex_stream(fpip_t fp, val name)
{
switch (fp.close) {
case fpip_fclose:
- return make_stdio_stream(fp.f, name, t, nil);
+ return make_stdio_stream(fp.f, name);
case fpip_pclose:
- return make_pipe_stream(fp.f, name, t, nil);
+ return make_pipe_stream(fp.f, name);
case fpip_closedir:
uw_throwf(query_error_s, lit("cannot output to directory: ~a"), name, nao);
}
@@ -3650,37 +3650,45 @@ static val match_files(match_files_ctx c)
gc_hint(c.data);
if (listp(c.data)) { /* recursive call with lazy list */
- ; /* no specia initialization */
+ ; /* no special initialization */
} else if (c.files) { /* c.data == t: toplevel call with file list */
val source_spec = first(c.files);
val name = consp(source_spec) ? cdr(source_spec) : source_spec;
- fpip_t fp = (errno = 0, complex_open(name, nil, nil));
- spec_bind (specline, first_spec, c.spec);
- if (consp(first_spec) && eq(first(first_spec), next_s) && !rest(specline)) {
- debuglf(first_spec, lit("not opening source ~a "
- "since query starts with next directive"), name, nao);
- } else {
- val spec = first(c.spec);
- debuglf(spec, lit("opening data source ~a"), name, nao);
+ if (stringp(name)) {
+ fpip_t fp = (errno = 0, complex_open(name, nil, nil));
+ spec_bind (specline, first_spec, c.spec);
+
+ if (consp(first_spec) && eq(first(first_spec), next_s) && !rest(specline)) {
+ debuglf(first_spec, lit("not opening source ~a "
+ "since query starts with next directive"), name, nao);
+ } else {
+ val spec = first(c.spec);
+ debuglf(spec, lit("opening data source ~a"), name, nao);
- if (complex_open_failed(fp)) {
- if (consp(source_spec) && car(source_spec) == nothrow_k) {
- debuglf(spec, lit("could not open ~a: "
- "treating as failed match due to nothrow"), name, nao);
+ if (complex_open_failed(fp)) {
+ if (consp(source_spec) && car(source_spec) == nothrow_k) {
+ debuglf(spec, lit("could not open ~a: "
+ "treating as failed match due to nothrow"), name, nao);
+ debug_return (nil);
+ } else if (errno != 0)
+ file_err(spec, lit("could not open ~a (error ~a/~a)"), name,
+ num(errno), string_utf8(strerror(errno)), nao);
+ else
+ file_err(spec, lit("could not open ~a"), name, nao);
debug_return (nil);
- } else if (errno != 0)
- file_err(spec, lit("could not open ~a (error ~a/~a)"), name,
- num(errno), string_utf8(strerror(errno)), nao);
- else
- file_err(spec, lit("could not open ~a"), name, nao);
- debug_return (nil);
- }
+ }
- c.files = cons(name, cdr(c.files)); /* Get rid of cons and nothrow */
+ c.files = cons(name, cdr(c.files)); /* Get rid of cons and nothrow */
- if ((c.data = complex_snarf(fp, name)) != nil)
+ if ((c.data = complex_snarf(fp, name)) != nil)
+ c.data_lineno = num(1);
+ }
+ } else if (streamp(name)) {
+ if ((c.data = lazy_stream_cons(name)))
c.data_lineno = num(1);
+ } else {
+ c.data = nil;
}
} else { /* toplevel call with no data or file list */
c.data = nil;
diff --git a/parser.l b/parser.l
index 8a95d2ec..c1013c87 100644
--- a/parser.l
+++ b/parser.l
@@ -818,6 +818,6 @@ void parse_reset(val spec_file)
if (in == 0)
uw_throwf(file_error_s, lit("unable to open ~a"), spec_file, nao);
}
- yyin_stream = make_stdio_stream(in, spec_file_str, t, nil);
+ yyin_stream = make_stdio_stream(in, spec_file_str);
}
}
diff --git a/stream.c b/stream.c
index 5734c34e..53ab04c4 100644
--- a/stream.c
+++ b/stream.c
@@ -34,9 +34,11 @@
#include <errno.h>
#include <ctype.h>
#include <wchar.h>
+#include "config.h"
+#if HAVE_SYS_WAIT || HAVE_SYS_STAT || HAVE_FORK_STUFF || HAVE_POSIX_SLEEP
#include <unistd.h>
+#endif
#include <float.h>
-#include "config.h"
#if HAVE_SYS_WAIT
#include <sys/wait.h>
#endif
@@ -90,7 +92,11 @@ struct stdio_handle {
FILE *f;
val descr;
utf8_decoder_t ud;
+#if HAVE_FORK_STUFF
pid_t pid;
+#else
+ int pid;
+#endif
};
static void stdio_stream_print(val stream, val out)
@@ -312,6 +318,55 @@ static struct strm_ops stdio_ops = {
stdio_seek
};
+static val tail_get_line(val stream)
+{
+ val ret;
+
+ while ((ret = stdio_get_line(stream)) == nil)
+ sleep(1);
+
+ return ret;
+}
+
+static val tail_get_char(val stream)
+{
+ val ret;
+
+ while ((ret = stdio_get_char(stream)) == nil)
+ sleep(1);
+
+ return ret;
+}
+
+static val tail_get_byte(val stream)
+{
+ val ret;
+
+ while ((ret = stdio_get_byte(stream)) == nil)
+ sleep(1);
+
+ return ret;
+}
+
+
+static struct strm_ops tail_ops = {
+ { cobj_equal_op,
+ stdio_stream_print,
+ stdio_stream_destroy,
+ stdio_stream_mark,
+ cobj_hash_op },
+ stdio_put_string,
+ stdio_put_char,
+ stdio_put_byte,
+ tail_get_line,
+ tail_get_char,
+ tail_get_byte,
+ stdio_close,
+ stdio_flush,
+ stdio_seek
+};
+
+
#if HAVE_FORK_STUFF
static int pipevp_close(FILE *f, pid_t pid)
{
@@ -762,10 +817,10 @@ static struct strm_ops dir_ops = {
};
-val make_stdio_stream(FILE *f, val descr, val input, val output)
+static val make_stdio_stream_common(FILE *f, val descr, struct cobj_ops *ops)
{
struct stdio_handle *h = (struct stdio_handle *) chk_malloc(sizeof *h);
- val stream = cobj((mem_t *) h, stream_s, &stdio_ops.cobj_ops);
+ val stream = cobj((mem_t *) h, stream_s, ops);
h->f = f;
h->descr = descr;
utf8_decoder_init(&h->ud);
@@ -773,25 +828,26 @@ val make_stdio_stream(FILE *f, val descr, val input, val output)
return stream;
}
-val make_pipe_stream(FILE *f, val descr, val input, val output)
+val make_stdio_stream(FILE *f, val descr)
{
- struct stdio_handle *h = (struct stdio_handle *) chk_malloc(sizeof *h);
- val stream = cobj((mem_t *) h, stream_s, &pipe_ops.cobj_ops);
- h->f = f;
- h->descr = descr;
- utf8_decoder_init(&h->ud);
- h->pid = 0;
- return stream;
+ return make_stdio_stream_common(f, descr, &stdio_ops.cobj_ops);
+}
+
+val make_tail_stream(FILE *f, val descr)
+{
+ return make_stdio_stream_common(f, descr, &tail_ops.cobj_ops);
+}
+
+val make_pipe_stream(FILE *f, val descr)
+{
+ return make_stdio_stream_common(f, descr, &pipe_ops.cobj_ops);
}
#if HAVE_FORK_STUFF
static val make_pipevp_stream(FILE *f, val descr, pid_t pid)
{
- struct stdio_handle *h = (struct stdio_handle *) chk_malloc(sizeof *h);
- val stream = cobj((mem_t *) h, stream_s, &pipe_ops.cobj_ops);
- h->f = f;
- h->descr = descr;
- utf8_decoder_init(&h->ud);
+ val stream = make_stdio_stream_common(f, descr, &pipe_ops.cobj_ops);
+ struct stdio_handle *h = (struct stdio_handle *) stream->co.handle;
h->pid = pid;
return stream;
}
@@ -1604,43 +1660,39 @@ val open_directory(val path)
val open_file(val path, val mode_str)
{
FILE *f = w_fopen(c_str(path), c_str(mode_str));
- val input = nil, output = nil;
if (!f)
uw_throwf(file_error_s, lit("error opening ~a: ~a/~s"),
path, num(errno), string_utf8(strerror(errno)), nao);
- if (break_str(mode_str, lit("w")))
- output = t;
- if (break_str(mode_str, lit("a")))
- output = t;
- if (break_str(mode_str, lit("r")))
- input = t;
- if (break_str(mode_str, lit("+")))
- input = output = t;
+ return make_stdio_stream(f, path);
+}
- return make_stdio_stream(f, path, input, output);
+val open_tail(val path, val mode_str, val seek_end_p)
+{
+ FILE *f = w_fopen(c_str(path), c_str(mode_str));
+
+ if (!f)
+ uw_throwf(file_error_s, lit("error opening ~a: ~a/~s"),
+ path, num(errno), string_utf8(strerror(errno)), nao);
+
+ if (seek_end_p)
+ if (fseek(f, 0, SEEK_END) < 0)
+ uw_throwf(file_error_s, lit("error seeking to end of ~a: ~a/~s"),
+ path, num(errno), string_utf8(strerror(errno)), nao);
+
+ return make_tail_stream(f, path);
}
val open_command(val path, val mode_str)
{
FILE *f = w_popen(c_str(path), c_str(mode_str));
- val input = nil, output = nil;
if (!f)
uw_throwf(file_error_s, lit("error opening pipe ~a: ~a/~s"),
path, num(errno), string_utf8(strerror(errno)), nao);
- if (break_str(mode_str, lit("w")))
- output = t;
- if (break_str(mode_str, lit("a")))
- output = t;
- if (break_str(mode_str, lit("r")))
- input = t;
- if (break_str(mode_str, lit("+")))
- input = output = t;
-
- return make_pipe_stream(f, path, input, output);
+ return make_pipe_stream(f, path);
}
#if HAVE_FORK_STUFF
@@ -1775,10 +1827,10 @@ val open_process(val name, val mode_str, val args)
void stream_init(void)
{
protect(&std_input, &std_output, &std_debug, &std_error, (val *) 0);
- std_input = make_stdio_stream(stdin, string(L"stdin"), t, nil);
- std_output = make_stdio_stream(stdout, string(L"stdout"), nil, t);
- std_debug = make_stdio_stream(stdout, string(L"debug"), nil, t);
- std_error = make_stdio_stream(stderr, string(L"stderr"), nil, t);
+ std_input = make_stdio_stream(stdin, string(L"stdin"));
+ std_output = make_stdio_stream(stdout, string(L"stdout"));
+ std_debug = make_stdio_stream(stdout, string(L"debug"));
+ std_error = make_stdio_stream(stderr, string(L"stderr"));
detect_format_string();
dev_k = intern(lit("dev"), keyword_package);
diff --git a/stream.h b/stream.h
index 1cf0281d..efd3e912 100644
--- a/stream.h
+++ b/stream.h
@@ -37,8 +37,9 @@ extern val s_ifchr, s_ififo, s_isuid, s_isgid, s_isvtx, s_irwxu;
extern val s_irusr, s_iwusr, s_ixusr, s_irwxg, s_irgrp, s_iwgrp;
extern val s_ixgrp, s_irwxo, s_iroth, s_iwoth, s_ixoth;
-val make_stdio_stream(FILE *, val descr, val input, val output);
-val make_pipe_stream(FILE *, val descr, val input, val output);
+val make_stdio_stream(FILE *, val descr);
+val make_tail_stream(FILE *, val descr);
+val make_pipe_stream(FILE *, val descr);
val make_string_input_stream(val);
val make_string_byte_input_stream(val);
val make_string_output_stream(void);
@@ -64,6 +65,7 @@ val seek_stream(val stream, val offset, val whence);
val statf(val path);
val open_directory(val path);
val open_file(val path, val mode_str);
+val open_tail(val path, val mode_str, val seek_end_p);
val open_command(val path, val mode_str);
val open_process(val path, val mode_str, val args);
diff --git a/txr.c b/txr.c
index 2edfb80d..5f423b03 100644
--- a/txr.c
+++ b/txr.c
@@ -389,7 +389,7 @@ int txr_main(int argc, char **argv)
FILE *in = w_fopen(c_str(spec_file_str), L"r");
if (in == 0)
uw_throwf(file_error_s, lit("unable to open ~a"), spec_file_str, nao);
- yyin_stream = make_stdio_stream(in, spec_file_str, t, nil);
+ yyin_stream = make_stdio_stream(in, spec_file_str);
} else {
spec_file = L"stdin";
}
@@ -404,7 +404,7 @@ int txr_main(int argc, char **argv)
val name = string_utf8(*argv);
if (in == 0)
uw_throwf(file_error_s, lit("unable to open ~a"), name, nao);
- yyin_stream = make_stdio_stream(in, name, t, nil);
+ yyin_stream = make_stdio_stream(in, name);
spec_file = utf8_dup_from(*argv);
} else {
spec_file = L"stdin";