summaryrefslogtreecommitdiffstats
path: root/parser.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 /parser.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 'parser.c')
-rw-r--r--parser.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/parser.c b/parser.c
index 331e6b7f..0deb3867 100644
--- a/parser.c
+++ b/parser.c
@@ -75,6 +75,9 @@ val listener_pprint_s, listener_greedy_eval_s;
val rec_source_loc_s, read_unknown_structs_s;
val json_s;
val intr_s;
+
+struct cobj_class *parser_cls;
+
static lino_t *lino_ctx;
static int repl_level = 0;
@@ -172,7 +175,7 @@ val parser(val stream, val name, val lineno)
parser_t *p = coerce(parser_t *, chk_malloc(sizeof *p));
val parser;
parser_common_init(p);
- parser = cobj(coerce(mem_t *, p), parser_s, &parser_ops);
+ parser = cobj(coerce(mem_t *, p), parser_cls, &parser_ops);
p->parser = parser;
p->lineno = c_num(default_arg(lineno, one), self);
p->name = name;
@@ -183,7 +186,7 @@ val parser(val stream, val name, val lineno)
parser_t *parser_get_impl(val self, val parser)
{
- return coerce(parser_t *, cobj_handle(self, parser, parser_s));
+ return coerce(parser_t *, cobj_handle(self, parser, parser_cls));
}
val ensure_parser(val stream, val name)
@@ -655,7 +658,7 @@ static val lisp_parse_impl(val self, enum prime_parser prime,
error_stream = default_arg_strict(error_stream, std_null);
error_stream = if3(error_stream == t, std_output, error_stream);
- class_check (self, error_stream, stream_s);
+ class_check (self, error_stream, stream_cls);
if (lineno && !missingp(lineno))
pi->lineno = c_num(lineno, self);
@@ -830,7 +833,7 @@ val txr_parse(val source_in, val error_stream,
dyn_env = make_env(nil, nil, dyn_env);
error_stream = default_arg_strict(error_stream, std_null);
error_stream = if3(error_stream == t, std_output, error_stream);
- class_check (self, error_stream, stream_s);
+ class_check (self, error_stream, stream_cls);
parse_once(self, input_stream, name);
@@ -1675,7 +1678,7 @@ val repl(val bindings, val in_stream, val out_stream, val env)
val parser_errors(val parser)
{
val self = lit("parser-errors");
- parser_t *p = coerce(parser_t *, cobj_handle(self, parser, parser_s));
+ parser_t *p = coerce(parser_t *, cobj_handle(self, parser, parser_cls));
return num(p->errors);
}
@@ -1685,7 +1688,7 @@ val parse_errors(val stream)
val errors = nil;
val parser = gethash(stream_parser_hash, stream);
if (parser) {
- parser_t *p = coerce(parser_t *, cobj_handle(self, parser, parser_s));
+ parser_t *p = coerce(parser_t *, cobj_handle(self, parser, parser_cls));
if (p->errors)
errors = num(p->errors);
}
@@ -1871,11 +1874,17 @@ void parse_init(void)
read_unknown_structs_s = intern(lit("*read-unknown-structs*"), user_package);
json_s = intern(lit("json"), user_package);
unique_s = gensym(nil);
+
+ parser_cls = cobj_register(parser_s);
+
protect(&stream_parser_hash, &unique_s, &catch_all, convert(val *, 0));
stream_parser_hash = make_hash(t, nil, nil);
catch_all = cons(t, nil);
+
parser_l_init();
+
lino_init(&linenoise_txr_binding);
+
reg_var(listener_hist_len_s, num_fast(500));
reg_var(listener_multi_line_p_s, t);
reg_var(listener_sel_inclusive_p_s, nil);