diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | stream.c | 65 | ||||
-rw-r--r-- | utf8.c | 10 | ||||
-rw-r--r-- | utf8.h | 1 |
4 files changed, 85 insertions, 5 deletions
@@ -1,3 +1,17 @@ +2013-11-28 Kaz Kylheku <kaz@kylheku.com> + + * stream.c (struct stdio_handle): New member, mode. + (stdio_stream_mark): Mark the new member during gc. + (stdio_seek): When we seek, we should reset the utf8 machine. + (tail_strategy): New function. + (tail_get_line, tail_get_char, tail_get_byte): Use + tail_strategy for polling the file at EOF. + (open_tail): Store the mode in the file handle. + + * utf8.c (w_freopen): New function. + + * utf8.h (w_freopen): Declared. + 2013-11-27 Kaz Kylheku <kaz@kylheku.com> * Makefile (conftest.clean): Use @ to suppress output. @@ -91,6 +91,7 @@ static void common_destroy(val obj) struct stdio_handle { FILE *f; val descr; + val mode; /* used by tail */ utf8_decoder_t ud; #if HAVE_FORK_STUFF pid_t pid; @@ -119,6 +120,7 @@ static void stdio_stream_mark(val stream) { struct stdio_handle *h = (struct stdio_handle *) stream->co.handle; gc_mark(h->descr); + gc_mark(h->mode); } static val stdio_maybe_read_error(val stream) @@ -212,8 +214,10 @@ static val stdio_seek(val stream, cnum offset, enum strm_whence whence) if (where >= 0) return num(where); } else { - if (fseek(h->f, offset, whence) == 0) + if (fseek(h->f, offset, whence) == 0) { + utf8_decoder_init(&h->ud); return t; + } } } @@ -318,32 +322,78 @@ static struct strm_ops stdio_ops = { stdio_seek }; +static void tail_strategy(val stream, unsigned long *state) +{ + unsigned long count = (*state)++; + int sec, mod; + (void) stream; + + if (count > 32) + count = 32; + + sec = 1 << (count / 8); + mod = 8 >> (count / 8); + + if (mod == 0) + mod = 1; + + sleep(sec); + + if (*state % mod == 0) { + struct stdio_handle *h = (struct stdio_handle *) stream->co.handle; + long save_pos, size; + + if ((save_pos = ftell(h->f)) == -1) + return; + + if (!(h->f = w_freopen(c_str(h->descr), c_str(h->mode), h->f))) + uw_throwf(file_error_s, lit("error opening ~a: ~a/~s"), + h->descr, num(errno), string_utf8(strerror(errno)), nao); + + utf8_decoder_init(&h->ud); + + if ((fseek(h->f, 0, SEEK_END)) == -1) + return; + + if ((size = ftell(h->f)) == -1) + return; + + if (size >= save_pos) + fseek(h->f, save_pos, SEEK_SET); + else + rewind(h->f); + } +} + static val tail_get_line(val stream) { + unsigned long state = 0; val ret; while ((ret = stdio_get_line(stream)) == nil) - sleep(1); + tail_strategy(stream, &state); return ret; } static val tail_get_char(val stream) { + unsigned long state = 0; val ret; while ((ret = stdio_get_char(stream)) == nil) - sleep(1); + tail_strategy(stream, &state); return ret; } static val tail_get_byte(val stream) { + unsigned long state = 0; val ret; while ((ret = stdio_get_byte(stream)) == nil) - sleep(1); + tail_strategy(stream, &state); return ret; } @@ -1671,6 +1721,8 @@ val open_file(val path, val mode_str) val open_tail(val path, val mode_str, val seek_end_p) { FILE *f = w_fopen(c_str(path), c_str(mode_str)); + struct stdio_handle *h; + val stream; if (!f) uw_throwf(file_error_s, lit("error opening ~a: ~a/~s"), @@ -1681,7 +1733,10 @@ val open_tail(val path, val mode_str, val seek_end_p) 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); + stream = make_tail_stream(f, path); + h = (struct stdio_handle *) stream->co.handle; + h->mode = mode_str; + return stream; } val open_command(val path, val mode_str) @@ -371,3 +371,13 @@ FILE *w_popen(const wchar_t *wcmd, const wchar_t *wmode) free(mode); return f; } + +FILE *w_freopen(const wchar_t *wname, const wchar_t *wmode, FILE *fold) +{ + char *name = utf8_dup_to(wname); + char *mode = utf8_dup_to(wmode); + FILE *f = freopen(name, mode, fold); + free(name); + free(mode); + return f; +} @@ -48,3 +48,4 @@ wint_t utf8_decode(utf8_decoder_t *,int (*get)(mem_t *ctx), mem_t *ctx); FILE *w_fopen(const wchar_t *, const wchar_t *); FILE *w_popen(const wchar_t *, const wchar_t *); +FILE *w_freopen(const wchar_t *, const wchar_t *, FILE *); |