summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--stream.c65
-rw-r--r--utf8.c10
-rw-r--r--utf8.h1
4 files changed, 85 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 8878d73f..d6266302 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/stream.c b/stream.c
index e4e0bed2..c90d4c18 100644
--- a/stream.c
+++ b/stream.c
@@ -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)
diff --git a/utf8.c b/utf8.c
index 27550be2..99e21978 100644
--- a/utf8.c
+++ b/utf8.c
@@ -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;
+}
diff --git a/utf8.h b/utf8.h
index ce147fb6..134af026 100644
--- a/utf8.h
+++ b/utf8.h
@@ -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 *);