summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-08 19:17:39 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-08 19:17:39 -0700
commitfc22de3079459193253522efccdd7519879e34b7 (patch)
tree6c665cc9b800b81827a2a5214ed1125cb0dd49f3 /stream.c
parentc0a9036d15d9f0a910aab82905e6b5e7d6ce71da (diff)
downloadtxr-fc22de3079459193253522efccdd7519879e34b7.tar.gz
txr-fc22de3079459193253522efccdd7519879e34b7.tar.bz2
txr-fc22de3079459193253522efccdd7519879e34b7.zip
type: disallow structs using built-in type names.
This is a big commit motivated by the need to clean up the situation with built-in type symbols, COBJ objects and structs. The struct type system allows struct types to be defined for symbols like regex or str, which are used by built-in or cobj types. This is a bad thing. What is worse, structure instances are COBJ types which identify their type using the COBJ class symbol mechanism. There are places in the C implementation which assume that when a COBJ has a certain class symbol, it is of a certain expected type, which is totally different from and incompatible form a struct instance. User code can define a structure object which will fool that code. There are multiple things going on in this patch. The major theme is that the COBJ representation is changing. Instead of a class symbol, COBJ instances now carry a "struct cobj_class *" pointer. This pointer is obtained by registration via the cobj_register function. All modules must register their class symbols to obtain these class handles, which are then used in cobj() calls for instantiation. The CPTR type was identical to COBJ until now, except for the type tag. This is changing; CPTR objects will keep the old representation with the class symbol. commit 20fdfc6008297001491308849c17498c006fe7b4 Author: Kaz Kylheku <kaz@kylheku.com> Date: Thu Jul 8 19:17:39 2021 -0700 * ffi.h (carray_cls): Declared. * hash.h (hash_cls): Declared. (hash_early_init): Declared. * lib.h (struct cobj_class): New struct. (struct cobj): cls member changing to struct cobj_class *. (struct cptr): New struct, same as previous struct cobj. (union obj): New member cp of type struct cptr, for CPTR. (builtin_type): Declared. (class_check): Declaration moved closer to COBJ-related functions and updated. (cobj_register, cobj_register_super, cobj_class_exists): New functions declared. (cobjclassp, cobj_handle, cobj_ops): Declarations updated. * parser.h (parser_cls): Declared. * rand.h (random_state_cls): Declared. * regex.h (regex_cls): Declared. * stream.h (stream_cls, stdio_stream_cls): Declared. * struct.h (struct_cls): Declared. * tree.h (tree_cls, tree_iter_cls): Declared. * vm.h (vm_desc_cls): Declared. * buf.c (buf_strm, make_buf_stream): Pass stream_cls functions instead of stream_s class symbol. * chksum.c (sha256_ctx_cls, md5_ctx_cls): New static class handles. (sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash, md5_end): Pass class handles to instead of class symbols. (chksum_init): Initialize class handle variables. * ffi.c (ffi_type_cls, ffi_call_desc_cls, ffi_closure_cls, union_cls): New static class handles. (carray_cls): New global variable. (ffi_type_struct_checked, ffi_type_print_op, ffi_closure_struct_checked, ffi_closure_print_op, make_ffi_type_builtin, make_ffi_type_pointer, make_ffi_type_struct, make_ffi_type_union, make_ffi_type_array, make_ffi_type_enum, ffi_call_desc_checked, ffi_call_desc_print_op, ffi_make_call_desc, ffi_make_closure, carray_struct_checked, carray_print_op, make_carray, cptr_getobj, cptr_out, uni_struct_checked, make_union_common): Pass class handles instead of class symbols. (ffi_init): Initialize class handle variables. * filter.c (regex_from_trie): Use hash_cls class handle instead of hash_s. * gc.c (mark_obj): Split COBJ and CPTR cases since the representation is different. * hash.c (hash_cls, hash_iter_cls): New class handles. (make_similar_hash, copy_hash, gethash_c, gethash_e, remhash, clearhash, hash_count, get_hash_userdata, set_hash_userdata, hashp, hash_iter_init, hash_begin, hash_next, hash_peek, hash_reset, hash_reset, hash_uni, hash_diff, hash_symdiff, hash_isec): Pass class handles instead of class symbols. (hash_early_init): New function. (hash_init): Set the class symbols in the class handles that were created in hash_early_init at a time when these symbols did not exist. * lib.c (nelem): New macro. (cobj_class): New static array. (cobj_ptr): New static pointer. (cobj_hash): New static hash. (seq_iter_cls): New static class handle. (builtin_type_p): New function. (typeof): Struct instances now all carry the same symbol, struct, as their COBJ class symbol. To get their type, we must call struct_type_name. (subtypep): Rearrangement of two cases: let's make the reflexive case first. Adjust code for different location of COBJ class symbol. (seq_iter_init_with_info, seq_begin, seq_next, seq_reset, iter_begin, iter_more, iter_item, iter_step, iter_reset, make_like, list_collect, do_generic_funcall): Use class handles instead of class symbols. (class_check, cobj, cobjclassp, cobj_handle, cobj_ops): Take class handle argument instead of class symbol. (cobj_register, cobj_register_super, cobj_class_exists): New functions. (cobj_populate_hash): New static function. (cobj_print_op): Adjust for different location of class (cptr_print_op, cptr_typed, cptr_type, cptr_handle, cptr_get): cptr functions now refer to obj->cp rather than obj->co. (copy, length, sub, ref, refset, replace, dwim_set, dwim_del, obj_print): Use class handles for various COBJ types rather than class symbols. (obj_init): gc-protect cobj_hash. Initialize seq_iter_cls class symbol and cobj_hash. Populate cobj_hash as the last initialization step. (init): Call hash_early_init immediately after gc_init. diff --git a/lib.c b/lib.c * match.c (do_match_line): Refer to regex_cls class handle instead of regex_s.. * parser.c (parser_cls): New global class handle. (parse, parser_get_impl, lisp_parse_impl, txr_parse, parser_errors): Use class handles instead of class symbols. (parse_init): Initialize parser_cls. * rand.c (random_state_cls): New global class handle. (make_state, random_state_p, make_random_state, random_state_get_vec, random_fixnum, random_float, random): Use class handles instead of class symbols. (rand_init): Initialize random_state_cls. * regex.c (regex_cls): New global class handle. (chset_cls): New static class handle. (reg_compile_csets, reg_derivative, regex_compile, regexp, regex_source, regex_print, regex_run, regex_machine_init): Use class handles instead of class symbols. (regex_init): Initialize regex_cls and chset_cls. * socket.c (make_dgram_sock_stream): Use stream_cls class symbol instead of stream_s. * stream.c (stream_cls, stdio_stream_cls): New class handles. (make_null_stream, stdio_get_fd, make_stdio_stream_common, stream_fd, sock_family, sock_type, sock_peer, sock_set_peer, make_dir_stream, make_string_input_stream, make_string_byte_input_stream, make_strlist_input_stream, make_string_output_stream, make_strlist_output_stream, get_list_from_stream, make_catenated_stream, make_delegate_stream, make_delegate_stream, stream_set_prop, stream_get_prop, close_stream, get_error, get_error_str, clear_error, get_line, get_char, get_byte, get_bytes, unget_char, unget_byte, put_buf, fill_buf, fill_buf_adjust, get_line_as_buf, format, put_string, put_char, put_byte, flush_stream, seek_stream, truncate_stream, get_indent_mode, test_set_indent_mode, test_neq_set_indent_mode, set_indent_mode, get_indent, set_indent, inc_indent, width_check, force_break, set_max_length, set_max_depth): Use class handle instead of symbol. (stream_init): Initialize stream_cls and stdio_stream_cls. * struct.c (struct_type_cls, struct_cls): New class handles. (struct_init): Initialize struct_type_cls and struct_cls. (struct_handle): Static function moved to avoid forward declaration. (stype_handle): Refer to struct_type_cls class handle instead of struct_type_s symbol. Handle instance objects in addition to types. (make_struct_type): Throw error if a built-in type is being defined as a struct type. Refer to class handle instead of class symbol. (find_struct_type, allocate_struct, make_struct_impl, make_lazy_struct, copy_struct): Refer to class handle instead of class symbol. * strudel.c (make_struct_delegate_stream): Refer to stream_cls class handle instead of stream_s symbol. * sysif.c (dir_cls): New class handle. (poll_wrap): Use typep instead of subtypep, eliminating access to class symbol. (opendir_wrap, closedir_wrap, readdir_wrap): Use class handles instead of class symbols. (sysif_init): Initialize dir_cls. * syslog.c (make_syslog_stream): Refer to stream_cls class handle instead of stream_s symbol. * tree.c (tree_cls, tree_iter_cls): New class handles. (tree_insert_node, tree_lookup_node, tree_delete_node, tree_root, tree_equal_op, tree, copy_search_tree, make_similar_tree, treep, tree_begin, copy_tree_iter, replace_tree_iter, tree_reset, tree_next, tree_peek, tree_clear): Use class handle instead of class symbol. (tree_init): Initialize tree_cls and tree_iter_cls. * unwind.c (sys_cont_cls): New static class handle. (revive_cont, capture_cont): Use class handle instead of class symbol. (uw_late_init): Initialize sys_cont_cls. * vm.c (vm_desc_cls): New global class handle. (vm_closure_cls): New static class handle. (vm_desc_struct, vm_make_desc, vm_closure_struct, vm_make_closure, vm_copy_closure): Use class handle instead of class symbol. (vm_init): Initialize vm_desc_cls and vm_closure_cls.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c115
1 files changed, 60 insertions, 55 deletions
diff --git a/stream.c b/stream.c
index 338a1e8e..1227113e 100644
--- a/stream.c
+++ b/stream.c
@@ -99,6 +99,8 @@ val stdio_stream_s;
val socket_error_s;
#endif
+struct cobj_class *stream_cls, *stdio_stream_cls;
+
const wchli_t *path_sep_chars = wli("/");
val top_stderr;
@@ -493,7 +495,7 @@ val make_null_stream(void)
struct dev_null *n = coerce(struct dev_null *, chk_malloc(sizeof *n));
strm_base_init(&n->a);
n->fd = -1;
- return cobj(coerce(mem_t *, n), stream_s, &null_ops.cobj_ops);
+ return cobj(coerce(mem_t *, n), stream_cls, &null_ops.cobj_ops);
}
#if CONFIG_STDIO_STRICT
@@ -821,7 +823,7 @@ static val stdio_get_fd(val stream)
{
val self = lit("stream-fd");
struct stdio_handle *h = coerce(struct stdio_handle *,
- cobj_handle(self, stream, stdio_stream_s));
+ cobj_handle(self, stream, stdio_stream_cls));
return h->f ? num(fileno(h->f)) : nil;
}
@@ -1673,7 +1675,7 @@ val set_mode_props(const struct stdio_mode m, val stream)
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), stdio_stream_s, ops);
+ val stream = cobj(coerce(mem_t *, h), stdio_stream_cls, ops);
strm_base_init(&h->a);
h->f = f;
h->descr = descr;
@@ -1737,7 +1739,7 @@ val stream_fd(val stream)
{
val self = lit("fileno");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_fd(stream);
}
@@ -1746,7 +1748,7 @@ val sock_family(val stream)
{
val self = lit("sock-family");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_sock_family(stream);
}
@@ -1754,7 +1756,7 @@ val sock_type(val stream)
{
val self = lit("sock-type");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_sock_type(stream);
}
@@ -1762,7 +1764,7 @@ val sock_peer(val stream)
{
val self = lit("sock-peer");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_sock_peer(stream);
}
@@ -1770,7 +1772,7 @@ val sock_set_peer(val stream, val peer)
{
val self = lit("sock-set-peer");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->set_sock_peer(stream, peer);
}
#endif
@@ -1882,7 +1884,7 @@ static val make_dir_stream(DIR *dir)
strm_base_init(&h->a);
h->d = dir;
h->err = nil;
- return cobj(coerce(mem_t *, h), stream_s, &dir_ops.cobj_ops);
+ return cobj(coerce(mem_t *, h), stream_cls, &dir_ops.cobj_ops);
}
struct string_in {
@@ -2005,7 +2007,7 @@ val make_string_input_stream(val string)
strm_base_init(&s->a);
s->string = string;
s->pos = zero;
- return cobj(coerce(mem_t *, s), stream_s, &string_in_ops.cobj_ops);
+ return cobj(coerce(mem_t *, s), stream_cls, &string_in_ops.cobj_ops);
}
struct byte_input {
@@ -2084,7 +2086,7 @@ val make_string_byte_input_stream(val string)
strm_base_init(&bi->a);
bi->buf = utf8_dup_to_buf(wstring, &bi->size, 0);
bi->index = 0;
- return cobj(coerce(mem_t *, bi), stream_s, &byte_in_ops.cobj_ops);
+ return cobj(coerce(mem_t *, bi), stream_cls, &byte_in_ops.cobj_ops);
}
}
@@ -2220,7 +2222,7 @@ val make_strlist_input_stream(val list)
s->string = car(list);
s->pos = zero;
s->list = cdr(list);
- return cobj(coerce(mem_t *, s), stream_s, &strlist_in_ops.cobj_ops);
+ return cobj(coerce(mem_t *, s), stream_cls, &strlist_in_ops.cobj_ops);
}
struct string_out {
@@ -2365,14 +2367,14 @@ val make_string_output_stream(void)
so->buf[0] = 0;
utf8_decoder_init(&so->ud);
so->head = so->tail = 0;
- return cobj(coerce(mem_t *, so), stream_s, &string_out_ops.cobj_ops);
+ return cobj(coerce(mem_t *, so), stream_cls, &string_out_ops.cobj_ops);
}
val get_string_from_stream(val stream)
{
val self = lit("get-string-from-stream");
struct string_out *so = coerce(struct string_out *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
if (stream->co.ops == &string_out_ops.cobj_ops) {
val out = nil;
@@ -2481,7 +2483,7 @@ val make_strlist_output_stream(void)
strm_base_init(&s->a);
s->lines = nil;
s->strstream = nil;
- stream = cobj(coerce(mem_t *, s), stream_s, &strlist_out_ops.cobj_ops);
+ stream = cobj(coerce(mem_t *, s), stream_cls, &strlist_out_ops.cobj_ops);
s->strstream = strstream;
return stream;
}
@@ -2490,7 +2492,7 @@ val get_list_from_stream(val stream)
{
val self = lit("get-list-from-stream");
struct strlist_out *s = coerce(struct strlist_out *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
if (stream->co.ops == &strlist_out_ops.cobj_ops) {
val stray = get_string_from_stream(s->strstream);
@@ -2671,7 +2673,7 @@ val make_catenated_stream(val stream_list)
val catstrm = nil;
strm_base_init(&s->a);
s->streams = nil;
- catstrm = cobj(coerce(mem_t *, s), stream_s, &cat_stream_ops.cobj_ops);
+ catstrm = cobj(coerce(mem_t *, s), stream_cls, &cat_stream_ops.cobj_ops);
s->streams = stream_list;
return catstrm;
}
@@ -2858,7 +2860,7 @@ static val make_delegate_stream(val self, val orig_stream, size_t handle_size,
struct cobj_ops *ops)
{
struct strm_ops *orig_ops = coerce(struct strm_ops *,
- cobj_ops(self, orig_stream, stream_s));
+ cobj_ops(self, orig_stream, stream_cls));
struct delegate_base *db = coerce(struct delegate_base *,
chk_calloc(1, handle_size));
val delegate_stream;
@@ -2867,7 +2869,7 @@ static val make_delegate_stream(val self, val orig_stream, size_t handle_size,
db->target_stream = nil;
db->target_ops = orig_ops;
- delegate_stream = cobj(coerce(mem_t *, db), stream_s, ops);
+ delegate_stream = cobj(coerce(mem_t *, db), stream_cls, ops);
db->target_stream = orig_stream;
@@ -2940,7 +2942,7 @@ val stream_set_prop(val stream, val ind, val prop)
{
val self = lit("stream-set-prop");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->set_prop(stream, ind, prop);
}
@@ -2948,7 +2950,7 @@ val stream_get_prop(val stream, val ind)
{
val self = lit("stream-get-prop");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
if (ind == fd_k && ops->get_fd != null_get_fd)
return ops->get_fd(stream);
@@ -2970,7 +2972,7 @@ val close_stream(val stream, val throw_on_error)
{
val self = lit("close-stream");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->close(stream, throw_on_error);
}
@@ -2978,7 +2980,7 @@ val get_error(val stream)
{
val self = lit("get-error");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_error(stream);
}
@@ -2986,7 +2988,7 @@ val get_error_str(val stream)
{
val self = lit("get-error-str");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_error_str(stream);
}
@@ -2994,7 +2996,7 @@ val clear_error(val stream)
{
val self = lit("clear-error");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->clear_error(stream);
}
@@ -3003,7 +3005,7 @@ val get_line(val stream_in)
val self = lit("get-line");
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_line(stream);
}
@@ -3012,7 +3014,7 @@ val get_char(val stream_in)
val self = lit("get-char");
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_char(stream);
}
@@ -3021,7 +3023,7 @@ val get_byte(val stream_in)
val self = lit("get-byte");
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->get_byte(stream);
}
@@ -3029,7 +3031,7 @@ val get_bytes(val self, val stream_in, mem_t *ptr, ucnum len)
{
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return unum(ops->fill_buf(stream, ptr, len, 0));
}
@@ -3038,7 +3040,7 @@ val unget_char(val ch, val stream_in)
val self = lit("unget-char");
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
if (!is_chr(ch))
type_mismatch(lit("~a: ~s is not a character"), self, ch, nao);
return ops->unget_char(stream, ch);
@@ -3050,7 +3052,7 @@ val unget_byte(val byte, val stream_in)
cnum b = c_num(byte, self);
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
if (b < 0 || b > 255)
uw_throwf(file_error_s, lit("~a: stream ~s: byte value ~a out of range"),
@@ -3067,7 +3069,7 @@ val put_buf(val buf, val pos_in, val stream_in)
ucnum len = c_unum(length_buf(buf), self);
mem_t *ptr = buf_get(buf, self);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return unum(ops->put_buf(stream, ptr, len, pos));
}
@@ -3080,7 +3082,7 @@ val fill_buf(val buf, val pos_in, val stream_in)
ucnum len = c_unum(length_buf(buf), self);
mem_t *ptr = buf_get(buf, self);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return unum(ops->fill_buf(stream, ptr, len, pos));
}
@@ -3094,7 +3096,7 @@ val fill_buf_adjust(val buf, val pos_in, val stream_in)
mem_t *ptr = buf_get(buf, self);
val readpos;
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
buf_set_length(buf, alloc_size, zero);
readpos = unum(ops->fill_buf(stream, ptr, len, pos));
buf_set_length(buf, readpos, zero);
@@ -3106,7 +3108,7 @@ val get_line_as_buf(val stream_in)
val self = lit("get-line-as-buf");
val stream = default_arg_strict(stream_in, std_input);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
val buf = make_buf(zero, nil, num_fast(128));
unsigned char bytes[128];
size_t count = 0;
@@ -3826,7 +3828,7 @@ val format(val stream, val str, ...)
val st = if3(stream == t,
std_output,
or2(stream, make_string_output_stream()));
- class_check(self, st, stream_s);
+ class_check(self, st, stream_cls);
{
va_list vl;
@@ -3856,13 +3858,13 @@ val put_string(val string, val stream_in)
val self = lit("put-string");
val stream = default_arg_strict(stream_in, std_output);
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
if (lazy_stringp(string)) {
return lazy_str_put(string, stream_in, s);
} else {
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
cnum col = s->column;
const wchar_t *str = c_str(string, self), *p = str;
@@ -3900,9 +3902,9 @@ val put_char(val ch, val stream_in)
val self = lit("put-char");
val stream = default_arg_strict(stream_in, std_output);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
wint_t cch = c_chr(ch);
switch (cch) {
@@ -3943,7 +3945,7 @@ val put_byte(val byte, val stream_in)
val self = lit("put-byte");
val stream = default_arg_strict(stream_in, std_output);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
cnum b = c_num(byte, self);
if (b < 0 || b > 255)
@@ -3983,7 +3985,7 @@ val flush_stream(val stream_in)
val self = lit("flush-stream");
val stream = default_arg_strict(stream_in, std_output);
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
return ops->flush(stream);
}
@@ -3991,7 +3993,7 @@ val seek_stream(val stream, val offset, val whence)
{
val self = lit("seek-stream");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
enum strm_whence w;
if (whence == from_start_k)
@@ -4011,7 +4013,7 @@ val truncate_stream(val stream, val len)
{
val self = lit("truncate-stream");
struct strm_ops *ops = coerce(struct strm_ops *,
- cobj_ops(self, stream, stream_s));
+ cobj_ops(self, stream, stream_cls));
if (missingp(len))
len = ops->seek(stream, zero, strm_cur);
return ops->truncate(stream, len);
@@ -4021,7 +4023,7 @@ val get_indent_mode(val stream)
{
val self = lit("get-indent-mode");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
return num_fast(s->indent_mode);
}
@@ -4029,7 +4031,7 @@ val test_set_indent_mode(val stream, val compare, val mode)
{
val self = lit("test-set-indent-mode");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
val oldval = num_fast(s->indent_mode);
if (oldval == compare)
s->indent_mode = convert(enum indent_mode, c_num(mode, self));
@@ -4040,7 +4042,7 @@ val test_neq_set_indent_mode(val stream, val compare, val mode)
{
val self = lit("test-neq-set-indent-mode");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
val oldval = num_fast(s->indent_mode);
if (oldval != compare)
s->indent_mode = convert(enum indent_mode, c_num(mode, self));
@@ -4051,7 +4053,7 @@ val set_indent_mode(val stream, val mode)
{
val self = lit("set-indent-mode");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
val oldval = num_fast(s->indent_mode);
s->indent_mode = convert(enum indent_mode, c_num(mode, self));
return oldval;
@@ -4061,7 +4063,7 @@ val get_indent(val stream)
{
val self = lit("get-indent");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
return num(s->indent_chars);
}
@@ -4069,7 +4071,7 @@ val set_indent(val stream, val indent)
{
val self = lit("set-indent");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
val oldval = num(s->indent_chars);
s->indent_chars = c_num(indent, self);
if (s->indent_chars < 0)
@@ -4081,7 +4083,7 @@ val inc_indent(val stream, val delta)
{
val self = lit("inc-indent");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
val oldval = num(s->indent_chars);
val col = num(s->column);
s->indent_chars = c_num(plus(delta, col), self);
@@ -4094,7 +4096,7 @@ val width_check(val stream, val alt)
{
val self = lit("width-check");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
if ((s->indent_mode == indent_code &&
s->column >= s->indent_chars + s->code_width) ||
@@ -4117,7 +4119,7 @@ val force_break(val stream)
{
val self = lit("force-break");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
s->force_break = 1;
return stream;
}
@@ -4126,7 +4128,7 @@ val set_max_length(val stream, val length)
{
val self = lit("set-max-length");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
cnum old_max = s->max_length;
s->max_length = c_num(length, self);
return num(old_max);
@@ -4136,7 +4138,7 @@ val set_max_depth(val stream, val depth)
{
val self = lit("set-max-depth");
struct strm_base *s = coerce(struct strm_base *,
- cobj_handle(self, stream, stream_s));
+ cobj_handle(self, stream, stream_cls));
cnum old_max = s->max_depth;
s->max_depth = c_num(depth, self);
return num(old_max);
@@ -5296,6 +5298,9 @@ void stream_init(void)
clear_error_s = intern(lit("clear-error"), user_package);
get_fd_s = intern(lit("get-fd"), user_package);
+ stream_cls = cobj_register(stream_s);
+ stdio_stream_cls = cobj_register_super(stdio_stream_s, stream_cls);
+
reg_var(stdin_s = intern(lit("*stdin*"), user_package),
make_stdio_stream(stdin, lit("stdin")));
reg_var(stdout_s = intern(lit("*stdout*"), user_package),