summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog51
-rw-r--r--stream.c281
-rw-r--r--stream.h11
-rw-r--r--syslog.c53
4 files changed, 272 insertions, 124 deletions
diff --git a/ChangeLog b/ChangeLog
index cbec2a8c..2ae1af6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,56 @@
2015-07-29 Kaz Kylheku <kaz@kylheku.com>
+ Deriving streams from the same base, so
+ we can give streams some common slots.
+
+ * stream.c (strm_base_init, strm_base_cleanup, strm_base_mark,
+ stream_destroy_op, stream_mark_op): New functions.
+ (null_ops): Switch to stream_destroy_op and stream_mark_op.
+ (make_null_stream): Associate a strm_base instance with the
+ cobj handle rather than a null pointer.
+ (struct stdio_handle): Inherit struct strm_base.
+ (stdio_stream_destroy): Clean up the strm_base part.
+ (stdio_stream_mark): Mark the strm_base part.
+ (make_stdio_stream_common): Initialize the strm_base part.
+ (struct dir_handle): Inherit struct strm_base.
+ (dir_destroy): Clean up the strm_base part.
+ (dir_mark): Mark the strm_base part.
+ (make_dir_stream): Initialize the strm_base part.
+ (struct string_in): New structure. Replaces ad-hoc cons
+ cell used for string input streams.
+ (string_in_stream_mark): Mark new structure.
+ (string_in_get_line, string_in_get_char, string_in_unget_char,
+ string_in_get_prop, string_in_get_error, make_string_input_stream):
+ Convert to new structure.
+ (string_in_ops): Switch to stream_destroy_op.
+ (struct byte_input): Inherit struct strm_base.
+ (byte_in_stream_destroy): No need to check handle for null.
+ No need to set handle to null after freeing: gc does it.
+ Clean up the strm_base part.
+ (byte_in_ops): Switch to stream_mark_op.
+ (make_string_byte_input_stream): Initialize the strm_base part.
+ (struct string_output): Inherit struct strm_base.
+ (string_out_stream_destroy): No need to check handle for null
+ since the logic elsewhere has changed.
+ Clean up the strm_base part.
+ No need to set handle to null.
+ (string_out_ops): Switch to stream_mark_op.
+ (make_string_output_stream): Initialize the strm_base part.
+ (get_string_from_stream): Don't free the handle.
+ Null out the buffer so->buf whose ownership passes to the string.
+ (struct strlist_out): New structure. Replaces ad-hoc cons cell
+ used for string list output stream.
+ (strlist_mark): Renamed to strlist_out_mark. Mark the strm_base
+ part.
+ (strlist_out_put_string, strlist_out_put_char,
+ make_strlist_output_stream, get_list_from_stream):
+ Convert to new structure.
+ (strlist_out_ops): Switch to stream_destroy_op.
+ Follow rename of strlist_mark.
+ (struct cat_strm): New structure, replacing ad-hoc list pointer
+
+2015-07-29 Kaz Kylheku <kaz@kylheku.com>
+
* gc.c (finalize): Null out cobj handle after calling the
destructor. This can catch some use-after-free errors.
diff --git a/stream.c b/stream.c
index 67fcee0e..c01c3aca 100644
--- a/stream.c
+++ b/stream.c
@@ -67,12 +67,41 @@ val from_start_k, from_current_k, from_end_k;
val real_time_k, name_k, fd_k;
val format_s;
+void strm_base_init(struct strm_base *s)
+{
+ static struct strm_base init = { 0, 0, 0 };
+ *s = init;
+}
+
+void strm_base_cleanup(struct strm_base *s)
+{
+ (void) s;
+}
+
+void strm_base_mark(struct strm_base *s)
+{
+ (void) s;
+}
+
void stream_print_op(val stream, val out)
{
val name = stream_get_prop(stream, name_k);
format(out, lit("#<~a ~p>"), name, stream, nao);
}
+void stream_destroy_op(val stream)
+{
+ struct strm_base *s = coerce(struct strm_base *, stream->co.handle);
+ strm_base_cleanup(s);
+ free(s);
+}
+
+void stream_mark_op(val stream)
+{
+ struct strm_base *s = coerce(struct strm_base *, stream->co.handle);
+ strm_base_mark(s);
+}
+
static noreturn void unimpl(val stream, val op)
{
uw_throwf(file_error_s, lit("~a: not supported by stream ~s\n"),
@@ -239,8 +268,8 @@ void fill_stream_ops(struct strm_ops *ops)
static struct strm_ops null_ops =
strm_ops_init(cobj_ops_init(eq,
stream_print_op,
- cobj_destroy_stub_op,
- cobj_mark_op,
+ stream_destroy_op,
+ stream_mark_op,
cobj_hash_op),
wli("null-stream"),
null_put_string, null_put_char, null_put_byte, null_get_line,
@@ -252,10 +281,13 @@ static struct strm_ops null_ops =
val make_null_stream(void)
{
- return cobj(convert(mem_t *, 0), stream_s, &null_ops.cobj_ops);
+ struct strm_base *s = coerce(struct strm_base *, chk_malloc(sizeof *s));
+ strm_base_init(s);
+ return cobj(convert(mem_t *, s), stream_s, &null_ops.cobj_ops);
}
struct stdio_handle {
+ struct strm_base a;
FILE *f;
val descr;
val unget_c;
@@ -287,12 +319,14 @@ static void stdio_stream_destroy(val stream)
{
struct stdio_handle *h = coerce(struct stdio_handle *, stream->co.handle);
close_stream(stream, nil);
+ strm_base_cleanup(&h->a);
free(h);
}
static void stdio_stream_mark(val stream)
{
struct stdio_handle *h = coerce(struct stdio_handle *, stream->co.handle);
+ strm_base_mark(&h->a);
gc_mark(h->descr);
gc_mark(h->mode);
gc_mark(h->err);
@@ -1036,6 +1070,7 @@ static val make_stdio_stream_common(FILE *f, val descr, struct cobj_ops *ops)
{
struct stdio_handle *h = coerce(struct stdio_handle *, chk_malloc(sizeof *h));
val stream = cobj(coerce(mem_t *, h), stream_s, ops);
+ strm_base_init(&h->a);
h->f = f;
h->descr = descr;
h->unget_c = nil;
@@ -1081,6 +1116,7 @@ static val make_pipevp_stream(FILE *f, val descr, pid_t pid)
#endif
struct dir_handle {
+ struct strm_base a;
DIR *d;
val err;
};
@@ -1088,6 +1124,7 @@ struct dir_handle {
static void dir_destroy(val stream)
{
struct dir_handle *h = coerce(struct dir_handle *, stream->co.handle);
+ strm_base_cleanup(&h->a);
close_stream(stream, nil);
free(h);
}
@@ -1095,6 +1132,7 @@ static void dir_destroy(val stream)
static void dir_mark(val stream)
{
struct dir_handle *h = coerce(struct dir_handle *, stream->co.handle);
+ strm_base_mark(&h->a);
gc_mark(h->err);
}
@@ -1169,15 +1207,24 @@ static struct strm_ops dir_ops =
val make_dir_stream(DIR *dir)
{
struct dir_handle *h = coerce(struct dir_handle *, chk_malloc(sizeof *h));
+ strm_base_init(&h->a);
h->d = dir;
h->err = nil;
return cobj(coerce(mem_t *, h), stream_s, &dir_ops.cobj_ops);
}
+struct string_in {
+ struct strm_base a;
+ val string;
+ val pos;
+};
+
static void string_in_stream_mark(val stream)
{
- val stuff = coerce(val, stream->co.handle);
- gc_mark(stuff);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
+ strm_base_mark(&s->a);
+ gc_mark(s->string);
+ gc_mark(s->pos);
}
static val find_char(val string, val start, val ch)
@@ -1197,14 +1244,12 @@ static val find_char(val string, val start, val ch)
static val string_in_get_line(val stream)
{
- val pair = coerce(val, stream->co.handle);
- val string = car(pair);
- val pos = cdr(pair);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
- if (lt(pos, length_str(string))) {
- val nlpos = find_char(string, pos, chr('\n'));
- val result = sub_str(string, pos, nlpos);
- set(cdr_l(pair), nlpos ? plus(nlpos, one) : length_str(string));
+ if (lt(s->pos, length_str(s->string))) {
+ val nlpos = find_char(s->string, s->pos, chr('\n'));
+ val result = sub_str(s->string, s->pos, nlpos);
+ set(mkloc(s->pos, stream), nlpos ? plus(nlpos, one) : length_str(s->string));
return result;
}
@@ -1213,13 +1258,11 @@ static val string_in_get_line(val stream)
static val string_in_get_char(val stream)
{
- val pair = coerce(val, stream->co.handle);
- val string = car(pair);
- val pos = cdr(pair);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
- if (lt(pos, length_str(string))) {
- set(cdr_l(pair), plus(pos, one));
- return chr_str(string, pos);
+ if (lt(s->pos, length_str(s->string))) {
+ set(mkloc(s->pos, stream), plus(s->pos, one));
+ return chr_str(s->string, s->pos);
}
return nil;
@@ -1227,9 +1270,8 @@ static val string_in_get_char(val stream)
static val string_in_unget_char(val stream, val ch)
{
- val pair = coerce(val, stream->co.handle);
- val string = car(pair);
- val pos = cdr(pair);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
+ val pos = s->pos;
if (pos == zero)
uw_throwf(file_error_s,
@@ -1237,35 +1279,31 @@ static val string_in_unget_char(val stream, val ch)
pos = minus(pos, one);
- if (chr_str(string, pos) != ch)
+ if (chr_str(s->string, pos) != ch)
uw_throwf(file_error_s,
lit("unget-char: ~s doesn't match the character that was read"),
nao);
- set(cdr_l(pair), plus(pos, one));
+ set(mkloc(s->pos, stream), plus(pos, one));
return ch;
}
static val string_in_get_prop(val stream, val ind)
{
-
if (ind == name_k) {
- val pair = coerce(val, stream->co.handle);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
struct strm_ops *ops = coerce(struct strm_ops *, stream->co.ops);
val name = static_str(ops->name);
-
- return format(nil, lit("~a ~s ~p"), name, car(pair), stream, nao);
+ return format(nil, lit("~a ~s ~p"), name, s->string, stream, nao);
}
+
return nil;
}
static val string_in_get_error(val stream)
{
- val pair = coerce(val, stream->co.handle);
- val string = car(pair);
- val pos = cdr(pair);
-
- return if2(ge(pos, length_str(string)), t);
+ struct string_in *s = coerce(struct string_in *, stream->co.handle);
+ return if2(ge(s->pos, length_str(s->string)), t);
}
static val string_in_get_error_str(val stream)
@@ -1276,7 +1314,7 @@ static val string_in_get_error_str(val stream)
static struct strm_ops string_in_ops =
strm_ops_init(cobj_ops_init(eq,
stream_print_op,
- cobj_destroy_stub_op,
+ stream_destroy_op,
string_in_stream_mark,
cobj_hash_op),
wli("string-input-stream"),
@@ -1295,10 +1333,15 @@ static struct strm_ops string_in_ops =
val make_string_input_stream(val string)
{
- return cobj(coerce(mem_t *, cons(string, zero)), stream_s, &string_in_ops.cobj_ops);
+ struct string_in *s = coerce(struct string_in *, chk_malloc(sizeof *s));
+ strm_base_init(&s->a);
+ s->string = string;
+ s->pos = zero;
+ return cobj(coerce(mem_t *, s), stream_s, &string_in_ops.cobj_ops);
}
struct byte_input {
+ struct strm_base a;
unsigned char *buf;
size_t size;
size_t index;
@@ -1307,13 +1350,10 @@ struct byte_input {
static void byte_in_stream_destroy(val stream)
{
struct byte_input *bi = coerce(struct byte_input *, stream->co.handle);
-
- if (bi) {
- free(bi->buf);
- bi->buf = 0;
- free(bi);
- stream->co.handle = 0;
- }
+ strm_base_cleanup(&bi->a);
+ free(bi->buf);
+ bi->buf = 0;
+ free(bi);
}
static val byte_in_get_byte(val stream)
@@ -1353,7 +1393,7 @@ static struct strm_ops byte_in_ops =
strm_ops_init(cobj_ops_init(eq,
stream_print_op,
byte_in_stream_destroy,
- cobj_mark_op,
+ stream_mark_op,
cobj_hash_op),
wli("byte-input-stream"),
0, 0, 0, 0, 0,
@@ -1372,6 +1412,7 @@ val make_string_byte_input_stream(val string)
{
struct byte_input *bi = coerce(struct byte_input *, chk_malloc(sizeof *bi));
unsigned char *utf8 = utf8_dup_to_uc(c_str(string));
+ strm_base_init(&bi->a);
bi->buf = utf8;
bi->size = strlen(coerce(char *, utf8));
bi->index = 0;
@@ -1380,6 +1421,7 @@ val make_string_byte_input_stream(val string)
}
struct string_output {
+ struct strm_base a;
wchar_t *buf;
size_t size;
size_t fill;
@@ -1392,12 +1434,10 @@ static void string_out_stream_destroy(val stream)
{
struct string_output *so = coerce(struct string_output *, stream->co.handle);
- if (so) {
- free(so->buf);
- so->buf = 0;
- free(so);
- stream->co.handle = 0;
- }
+ strm_base_cleanup(&so->a);
+ free(so->buf);
+ so->buf = 0;
+ free(so);
}
static int string_out_byte_callback(mem_t *ctx)
@@ -1492,7 +1532,7 @@ static struct strm_ops string_out_ops =
strm_ops_init(cobj_ops_init(eq,
stream_print_op,
string_out_stream_destroy,
- cobj_mark_op,
+ stream_mark_op,
cobj_hash_op),
wli("string-output-stream"),
string_out_put_string,
@@ -1505,6 +1545,7 @@ static struct strm_ops string_out_ops =
val make_string_output_stream(void)
{
struct string_output *so = coerce(struct string_output *, chk_malloc(sizeof *so));
+ strm_base_init(&so->a);
so->size = 128;
so->buf = coerce(wchar_t *, chk_malloc(so->size * sizeof so->buf));
so->fill = 0;
@@ -1525,40 +1566,47 @@ val get_string_from_stream(val stream)
struct string_output *so = coerce(struct string_output *, stream->co.handle);
val out = nil;
- if (!so)
+ if (!so->buf)
return out;
while (so->head != so->tail)
out = string_out_byte_flush(so, stream);
- stream->co.handle = 0;
-
/* Trim to actual size */
so->buf = coerce(wchar_t *, chk_realloc(coerce(mem_t *, so->buf),
(so->fill + 1) * sizeof *so->buf));
out = string_own(so->buf);
- free(so);
+ so->buf = 0;
return out;
} else {
type_assert (stream->co.ops == &string_in_ops.cobj_ops,
(lit("~a is not a string stream"), stream, nao));
{
- val pair = coerce(val, stream->co.handle);
- return pair ? car(pair) : nil;
+ struct string_in *si = coerce(struct string_in *, stream->co.handle);
+ return si->string;
}
}
}
-static void strlist_mark(val stream)
+struct strlist_out {
+ struct strm_base a;
+ val lines;
+ val strstream;
+};
+
+static void strlist_out_mark(val stream)
{
- val stuff = coerce(val, stream->co.handle);
- gc_mark(stuff);
+ struct strlist_out *s = coerce(struct strlist_out *, stream->co.handle);
+ strm_base_mark(&s->a);
+ gc_mark(s->lines);
+ gc_mark(s->strstream);
}
static val strlist_out_put_string(val stream, val str)
{
- val cell = coerce(val, stream->co.handle);
- cons_bind (lines, strstream, cell);
+ struct strlist_out *s = coerce(struct strlist_out *, stream->co.handle);
+ val lines = s->lines;
+ val strstream = s->strstream;
for (;;) {
val length = length_str(str);
@@ -1577,35 +1625,37 @@ static val strlist_out_put_string(val stream, val str)
strstream = make_string_output_stream();
}
- set(car_l(cell), lines);
- set(cdr_l(cell), strstream);
+ if (s->lines != lines) {
+ set(mkloc(s->lines, stream), lines);
+ set(mkloc(s->strstream, stream), strstream);
+ }
return t;
}
static val strlist_out_put_char(val stream, val ch)
{
- val cell = coerce(val, stream->co.handle);
- cons_bind (lines, strstream, cell);
+ struct strlist_out *s = coerce(struct strlist_out *, stream->co.handle);
+ val lines = s->lines;
+ val strstream = s->strstream;
if (ch == chr('\n')) {
push(get_string_from_stream(strstream), &lines);
strstream = make_string_output_stream();
+ set(mkloc(s->lines, stream), lines);
+ set(mkloc(s->strstream, stream), strstream);
} else {
put_char(ch, strstream);
}
- set(car_l(cell), lines);
- set(cdr_l(cell), strstream);
-
return t;
}
static struct strm_ops strlist_out_ops =
strm_ops_init(cobj_ops_init(eq,
stream_print_op,
- cobj_destroy_stub_op,
- strlist_mark,
+ stream_destroy_op,
+ strlist_out_mark,
cobj_hash_op),
wli("strlist-output-stream"),
strlist_out_put_string,
@@ -1614,8 +1664,15 @@ static struct strm_ops strlist_out_ops =
val make_strlist_output_stream(void)
{
- return cobj(coerce(mem_t *, cons(nil, make_string_output_stream())),
- stream_s, &strlist_out_ops.cobj_ops);
+ struct strlist_out *s = coerce(struct strlist_out *, chk_malloc(sizeof *s));
+ val stream;
+ val strstream = make_string_output_stream();
+ strm_base_init(&s->a);
+ s->lines = nil;
+ s->strstream = nil;
+ stream = cobj(coerce(mem_t *, s), stream_s, &strlist_out_ops.cobj_ops);
+ s->strstream = strstream;
+ return stream;
}
val get_list_from_stream(val stream)
@@ -1625,9 +1682,9 @@ val get_list_from_stream(val stream)
(lit("~a is not a stream"), stream, nao));
if (stream->co.ops == &strlist_out_ops.cobj_ops) {
- val cell = coerce(val, stream->co.handle);
- cons_bind (lines, strstream, cell);
- val stray = get_string_from_stream(strstream);
+ struct strlist_out *s = coerce(struct strlist_out *, stream->co.handle);
+ val stray = get_string_from_stream(s->strstream);
+ val lines = s->lines;
if (!zerop(length_str(stray)))
push(stray, &lines);
return nreverse(lines);
@@ -1636,18 +1693,24 @@ val get_list_from_stream(val stream)
type_mismatch(lit("~s is not a string list stream"), stream);
}
+struct cat_strm {
+ struct strm_base a;
+ val streams;
+};
+
static void cat_stream_print(val stream, val out)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
struct strm_ops *ops = coerce(struct strm_ops *, stream->co.ops);
val name = static_str(ops->name);
- format(out, lit("#<~a ~s>"), name, streams, nao);
+ format(out, lit("#<~a ~s>"), name, s->streams, nao);
}
static val cat_get_line(val stream)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ val streams = s->streams;
while (streams) {
val fs = first(streams);
@@ -1656,7 +1719,7 @@ static val cat_get_line(val stream)
return line;
close_stream(fs, t);
if ((streams = rest(streams)) != nil)
- stream->co.handle = coerce(mem_t *, streams);
+ set(mkloc(s->streams, stream), streams);
}
return nil;
@@ -1664,7 +1727,8 @@ static val cat_get_line(val stream)
static val cat_get_char(val stream)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ val streams = s->streams;
while (streams) {
val fs = first(streams);
@@ -1673,7 +1737,7 @@ static val cat_get_char(val stream)
return ch;
close_stream(fs, t);
if ((streams = rest(streams)) != nil)
- stream->co.handle = coerce(mem_t *, streams);
+ set(mkloc(s->streams, stream), streams);
}
return nil;
@@ -1681,7 +1745,8 @@ static val cat_get_char(val stream)
static val cat_get_byte(val stream)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ val streams = s->streams;
while (streams) {
val fs = first(streams);
@@ -1690,7 +1755,7 @@ static val cat_get_byte(val stream)
return byte;
close_stream(fs, t);
if ((streams = rest(streams)) != nil)
- stream->co.handle = coerce(mem_t *, streams);
+ set(mkloc(s->streams, stream), streams);
}
return nil;
@@ -1698,14 +1763,14 @@ static val cat_get_byte(val stream)
static val cat_unget_byte(val stream, int byte)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
- if (!streams) {
+ if (!s->streams) {
uw_throwf(file_error_s,
lit("unget-byte on catenated stream ~a: stream list empty"),
stream, nao);
} else {
- val stream = car(streams);
+ val stream = car(s->streams);
return unget_byte(num_fast(byte), stream);
}
@@ -1714,54 +1779,57 @@ static val cat_unget_byte(val stream, int byte)
static val cat_unget_char(val stream, val ch)
{
- val streams = coerce(val, stream->co.handle);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
- if (!streams) {
+ if (!s->streams) {
uw_throwf(file_error_s,
lit("unget-char on catenated stream ~a: stream list empty"),
stream, nao);
} else {
- val stream = car(streams);
- return unget_char(ch, stream );
+ val stream = car(s->streams);
+ return unget_char(ch, stream);
}
}
static val cat_get_prop(val stream, val ind)
{
- val streams = coerce(val, stream->co.handle);
- if (streams)
- return stream_get_prop(first(streams), ind);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+
+ if (s->streams)
+ return stream_get_prop(first(s->streams), ind);
+
return nil;
}
static void cat_mark(val stream)
{
- val obj = coerce(val, stream->co.handle);
- gc_mark(obj);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ strm_base_mark(&s->a);
+ gc_mark(s->streams);
}
static val cat_get_error(val stream)
{
- val streams = coerce(val, stream->co.handle);
- return if3(streams, get_error(first(streams)), t);
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ return if3(s->streams, get_error(first(s->streams)), t);
}
static val cat_get_error_str(val stream)
{
- val streams = coerce(val, stream->co.handle);
- return if3(streams, get_error_str(first(streams)), lit("eof"));
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ return if3(s->streams, get_error_str(first(s->streams)), lit("eof"));
}
static val cat_clear_error(val stream)
{
- val streams = coerce(val, stream->co.handle);
- return if2(streams, clear_error(first(streams)));
+ struct cat_strm *s = coerce(struct cat_strm *, stream->co.handle);
+ return if2(s->streams, clear_error(first(s->streams)));
}
static struct strm_ops cat_stream_ops =
strm_ops_init(cobj_ops_init(eq,
cat_stream_print,
- cobj_destroy_stub_op,
+ stream_destroy_op,
cat_mark,
cobj_hash_op),
wli("catenated-stream"),
@@ -1780,7 +1848,10 @@ static struct strm_ops cat_stream_ops =
val make_catenated_stream(val stream_list)
{
- return cobj(coerce(mem_t *, stream_list), stream_s, &cat_stream_ops.cobj_ops);
+ struct cat_strm *s = coerce(struct cat_strm *, chk_malloc(sizeof *s));
+ strm_base_init(&s->a);
+ s->streams = stream_list;
+ return cobj(coerce(mem_t *, s), stream_s, &cat_stream_ops.cobj_ops);
}
val catenated_stream_p(val obj)
@@ -1797,10 +1868,8 @@ val catenated_stream_push(val new_stream, val cat_stream)
(lit("~a is not a stream"), cat_stream, nao));
{
- val streams = coerce(val, cat_stream->co.handle);
- loc l = mkloc(streams, cat_stream);
- set(l, cons(new_stream, streams));
- cat_stream->co.handle = coerce(mem_t *, deref(l));
+ struct cat_strm *s = coerce(struct cat_strm *, cat_stream->co.handle);
+ mpush(new_stream, mkloc(s->streams, cat_stream));
return nil;
}
}
diff --git a/stream.h b/stream.h
index 1d84e5b2..eff45f44 100644
--- a/stream.h
+++ b/stream.h
@@ -30,6 +30,12 @@ enum strm_whence {
strm_end = SEEK_SET
};
+struct strm_base {
+ unsigned int indent_on;
+ cnum indent_chars;
+ cnum column;
+};
+
struct strm_ops {
struct cobj_ops cobj_ops;
const wchli_t *name;
@@ -78,8 +84,13 @@ extern val format_s;
extern val stdin_s, stdout_s, stddebug_s, stderr_s, stdnull_s;
+void strm_base_init(struct strm_base *s);
+void strm_base_cleanup(struct strm_base *s);
+void strm_base_mark(struct strm_base *s);
void fill_stream_ops(struct strm_ops *ops);
void stream_print_op(val stream, val out);
+void stream_mark_op(val stream);
+void stream_destroy_op(val stream);
val make_null_stream(void);
val make_stdio_stream(FILE *, val descr);
val make_tail_stream(FILE *, val descr);
diff --git a/syslog.c b/syslog.c
index 4a603d2e..2f329fba 100644
--- a/syslog.c
+++ b/syslog.c
@@ -43,6 +43,12 @@
#include "eval.h"
#include "syslog.h"
+struct syslog_strm {
+ struct strm_base a;
+ val prio;
+ val strstream;
+};
+
val prio_k;
static struct strm_ops syslog_strm_ops;
@@ -119,14 +125,18 @@ val closelog_wrap(void)
static void syslog_mark(val stream)
{
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ strm_base_mark(&s->a);
+ gc_mark(s->prio);
+ gc_mark(s->strstream);
val stuff = coerce(val, stream->co.handle);
gc_mark(stuff);
}
static val syslog_put_string(val stream, val str)
{
- val cell = coerce(val, stream->co.handle);
- cons_bind (prio, strstream, cell);
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ val strstream = s->strstream;
for (;;) {
val length = length_str(str);
@@ -141,51 +151,51 @@ static val syslog_put_string(val stream, val str)
break;
str = sub_str(str, plus(span_to_newline, num(1)), nil);
- syslog_wrap(prio, lit("~a"), list(get_string_from_stream(strstream), nao));
+ syslog_wrap(s->prio, lit("~a"), list(get_string_from_stream(strstream), nao));
strstream = make_string_output_stream();
}
- set(cdr_l(cell), strstream);
+ set(mkloc(s->strstream, stream), strstream);
return t;
}
static val syslog_put_char(val stream, val ch)
{
- val cell = coerce(val, stream->co.handle);
- cons_bind (prio, strstream, cell);
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ val strstream = s->strstream;
if (ch == chr('\n')) {
- syslog_wrap(prio, lit("~a"), list(get_string_from_stream(strstream), nao));
+ syslog_wrap(s->prio, lit("~a"), list(get_string_from_stream(strstream), nao));
strstream = make_string_output_stream();
} else {
put_char(ch, strstream);
}
- set(cdr_l(cell), strstream);
+ set(mkloc(s->strstream, stream), strstream);
return t;
}
static val syslog_put_byte(val stream, int ch)
{
- val cell = coerce(val, stream->co.handle);
- cons_bind (prio, strstream, cell);
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ val strstream = s->strstream;
if (ch == '\n') {
- syslog_wrap(prio, lit("~a"), list(get_string_from_stream(strstream), nao));
+ syslog_wrap(s->prio, lit("~a"), list(get_string_from_stream(strstream), nao));
strstream = make_string_output_stream();
} else {
put_byte(num(ch), strstream);
}
- set(cdr_l(cell), strstream);
+ set(mkloc(s->strstream, stream), strstream);
return t;
}
static val syslog_get_prop(val stream, val ind)
{
if (ind == prio_k) {
- val cell = coerce(val, stream->co.handle);
- return car(cell);
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ return s->prio;
} else if (ind == name_k) {
return lit("syslog");
}
@@ -195,8 +205,8 @@ static val syslog_get_prop(val stream, val ind)
static val syslog_set_prop(val stream, val ind, val prop)
{
if (ind == prio_k) {
- val cell = coerce(val, stream->co.handle);
- set(car_l(cell), prop);
+ struct syslog_strm *s = coerce(struct syslog_strm *, stream->co.handle);
+ set(mkloc(s->prio, stream), prop);
return t;
}
return nil;
@@ -219,6 +229,13 @@ static struct strm_ops syslog_strm_ops =
val make_syslog_stream(val prio)
{
- return cobj(coerce(mem_t *, cons(prio, make_string_output_stream())),
- stream_s, &syslog_strm_ops.cobj_ops);
+ struct syslog_strm *s = coerce(struct syslog_strm *, chk_malloc(sizeof *s));
+ val stream;
+ val strstream = make_string_output_stream();
+ strm_base_init(&s->a);
+ s->prio = prio;
+ s->strstream = nil;
+ stream = cobj(coerce(mem_t *, s), stream_s, &syslog_strm_ops.cobj_ops);
+ s->strstream = strstream;
+ return stream;
}