diff options
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | match.c | 60 | ||||
-rw-r--r-- | parser.l | 2 | ||||
-rw-r--r-- | stream.c | 134 | ||||
-rw-r--r-- | stream.h | 6 | ||||
-rw-r--r-- | txr.c | 4 |
7 files changed, 155 insertions, 72 deletions
@@ -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" # @@ -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)); @@ -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; @@ -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); } } @@ -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); @@ -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); @@ -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"; |