summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-11-27 21:05:51 -0800
committerKaz Kylheku <kaz@kylheku.com>2013-11-27 21:05:51 -0800
commit5285db54f7199cf75c0b740faaeee15cc9cc8c6a (patch)
tree98afe773267c450f14759e02724a0fa9c2b89c7d /stream.c
parent6fedaccfe790e33bb7a71d8a5f776e4cfa7e6c62 (diff)
downloadtxr-5285db54f7199cf75c0b740faaeee15cc9cc8c6a.tar.gz
txr-5285db54f7199cf75c0b740faaeee15cc9cc8c6a.tar.bz2
txr-5285db54f7199cf75c0b740faaeee15cc9cc8c6a.zip
* configure: Added check to detect POSIX sleep function.
* eval.c (eval_init): Register new open_tail function as intrinsic. * match.c (complex_snarf, complex_stream): Update calls to make_stdio_stream and make_pipe_stream to take fewer arguments. (match_files): Support a stream object as a data source specification in place of a string. * parser.l (parse_reset): Update call to make_stdio_stream to take fewer arguments. * stream.c: Inclusion of <unistd.h> made properly conditional. (struct stdio_handle): pid member defined as pid_t only if we have fork functionality, otherwise defined as int. (tail_get_line, tail_get_char, tail_get_byte): New static functions. (tail_ops): New static structure. (make_stdio_stream_common): New static structure. (make_stdio_stream, make_pipe_stream): These functions lose the input and output parameters, which ended up never used. Reimplemented in terms of new common function. (make_tail_stream): New function. (make_pipevp_stream): Reimplemented in terms of new common function. (open_file, open_command): Simplified by removal of useless local variables and their computation, which used to be extra arguments to make_stdio_stream and make_pipe_stream. (open_tail): New function. (stream_init): Calls to make_stdio_stream updated. * stream.h (make_stdio_stream, make_pipe_stream): Declarations updated. (make_tail_stream, open_tail): Declared. * txr.c (txr_main): Calls to make_stdio_stream updated.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c134
1 files changed, 93 insertions, 41 deletions
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);