summaryrefslogtreecommitdiffstats
path: root/ffi.c
Commit message (Collapse)AuthorAgeFilesLines
* ffi: improve support for big/little-endian types.Kaz Kylheku2021-08-261-232/+187
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of byte reads/writes, we use byte order swapping. Reads and writes that are aligned take place as a single data transfer, which makes it possible to use these be/le types for accessing hardware registers. This is useful in systems where the host processor accesses the bus in opposite endian relative to some peripheral. Moreover, when the functions match the local endian, we just use the native get/put functions via #define macro redirection. The source code size is reduced. * ffi.c (ffi_swap_u16, ffi_swap_u32, ffi_swap_u64, ffi_swap_i16, ffi_swap_i32, ffi_swap_i64): New static functions. (ffi_swap_i16_put, ffi_swap_i16_get, ffi_swap_u16_put, ffi_swap_u16_get, ffi_swap_i32_put, ffi_swap_i32_get, ffi_swap_u32_put, ffi_swap_u32_get, ffi_swap_i64_put, ffi_swap_i64_get, ffi_swap_u64_put, ffi_swap_u64_get): New static functions. (ffi_be_i16_put, ffi_be_i16_get, ffi_be_u16_put, ffi_be_u16_get, ffi_be_i32_put, ffi_be_i32_get, ffi_be_u32_put, ffi_be_u32_get, ffi_be_i64_put, ffi_be_i64_get, ffi_be_u64_put, ffi_be_u64_get, ffi_le_i16_put, ffi_le_i16_get, ffi_le_u16_put, ffi_le_u16_get, ffi_le_i32_put, ffi_le_i32_get, ffi_le_u32_put, ffi_le_u32_get, ffi_le_i64_put, ffi_le_i64_get, ffi_le_u64_put, ffi_le_u64_get): Functions deleted, replaced by same-named #define macros to redirect to the native functions or the _swap_ functions based on the endian. (ffi_be_i16_rput, ffi_be_i16_rget, ffi_be_u16_rput, ffi_be_u16_rget, ffi_be_i32_rput, ffi_be_i32_rget, ffi_be_u32_rput, ffi_be_u32_rget, ffi_le_i16_rput, ffi_le_i16_rget, ffi_le_u16_rput, ffi_le_u16_rget, ffi_le_i32_rput, ffi_le_i32_rget, ffi_le_u32_rput, ffi_le_u32_rget): Functions wrapped with #if in case these exact width types don't exist. (ffi_init_types): Wrap some exact-width-type type definitions with #if in case the types don't exist.
* carray: allow displacement in carray-pun.Kaz Kylheku2021-08-251-6/+20
| | | | | | | | | | * ffi.c (carray_pun): Takes two new arguments to specify displacement and size. (ffi_init): Registration of carray-pun adjusted. * ffi.h (carray_pun): Declaration updated. * txr.1: Documented.
* ffi: provide mmap through carray.Kaz Kylheku2021-08-221-0/+345
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * configure: configure test for mmap depositing HAVE_MMAP into config.h. * ffi.c (struct carray): Subject to HAVE_MMAP, new mm_len member which keeps track of the size of an underlying mapping so that we can unmap it, as well as peform operations like msync on it. (make_carray): Initialize mm_len to 0. (MAP_GROWSDOWN, MAP_LOCKED, MAP_NORESERVE, MAP_POPULATE, MAP_NONBLOCK, MAP_STACK, MAP_HUGETLB, MAP_SHARED, MAP_PRIVATE, MAP_FIXED, MAP_ANON, MAP_HUGE_SHIFT, MAP_HUGE_MASK, PROT_READ, PROT_WRITE, PROT_EXEC, PROT_NONE, PROT_GROWSDOWN, PROT_GROWSUP, MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, MADV_WILLNEED, MADV_DONTNEED, MADV_FREE, MADV_REMOVE, MADV_DONTFORK, MADV_DOFORK, MADV_MERGEABLE, MADV_UNMERGEABLE, MADV_HUGEPAGE, MADV_NOHUGEPAGE, MADV_DONTDUMP, MADV_DODUMP, MADV_WIPEONFORK, MADV_KEEPONFORK, MADV_HWPOISON, MS_ASYNC, MS_SYNC, MS_INVALIDATE): #define as 0 if missing. (carray_munmap_op): New static function. (carray_mmap_ops): New static structure. (mmap_wrap, munmap_wrap): New functions. (mmap_op): New static function. (mprotect_wrap, madvise_wrap, msync_wrap): New functions. (ffi_init): Register mmap, munmap, mprotect, madvise and msync as well as numerous integer variables: map-growsdown, map-locked, map-noreserve, map-populate, map-nonblock, map-stack, map-hugetlb, map-shared, map-private, map-fixed, map-anon, map-huge-shift, map-huge-mask, prot-read, prot-write, prot-exec, prot-none, prot-growsdown, prot-growsup, madv-normal, madv-random, madv-sequential, madv-willneed, madv-dontneed, madv-free, madv-remove, madv-dontfork, madv-dofork, madv-mergeable, madv-unmergeable, madv-hugepage, madv-nohugepage, madv-dontdump, madv-dodump, madv-wipeonfork, madv-keeponfork, madv-hwpoison, ms-async, ms-sync, ms-invalidate, page-size. * ffi.h (mmap_wrap, munmap_wrap, mprotect_wrap madvise_wrap, msync_wrap): Declared. * tests/017/mmap.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* license: reformat to fit 80 columns.Kaz Kylheku2021-08-161-12/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl, stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h: License reformatted. * lex.yy.c.shipped, y.tab.c.shipped, y.tab.h.shipped: Updated.
* ffi: remove redundant assignment.Paul A. Patience2021-08-141-1/+0
| | | | * ffi.c (int8_s): Remove redundant assignment.
* hash: change make_hash interface.Kaz Kylheku2021-07-221-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The make_hash function now takes the hash_weak_opt_t enumeration instead of a pair of flags. * hash.c (do_make_hash): Take enum argument instead of pair of flags. Just store the option; nothing to calculate. (weak_opt_from_flags): New static function. (tweak_hash): Function removed. (make_seeded_hash): Adjust to new do_make_hash interface with help from weak_opt_from_flags. (make_hash, make_eq_hash): Take enum argument instead of pair of flags. (hashv): Calculate hash_weak_opt_t enum from the extracted flags, pass down to make_eq_hash or make_hash. * hash.h (tweak_hash): Declration removed. (make_hash, make_eq_hash): Declarations updated. * eval.c (me_case, expand_switch): Update make_hash calls to new style. (eval_init): Update make_hash calls and get rid of tweak_hash calls. This renders the tweak_hash function unused. * ffi.c (make_ffi_type_enum, ffi_init): Update make_hash calls to new style. * filter.c (make_trie, trie_add, filter_init): Likewise. * lib.c (make_package_common, obj_init, obj_print): Likewise. * lisplib.c (lisplib_init): Likewise. * match.c (dir_tables_init): Likewise. * parser.c (parser_circ_def, repl, parse_init): Likewise. * parser.l (parser_l_init): Likewise. * struct.c (struct_init, get_slot_syms): Likewise. * sysif.c (get_env_hash): Likewise. * lex.yy.c.shipped, y.tab.c.shipped: Updated.
* carray: add missing argument type checking.Kaz Kylheku2021-07-211-2/+2
| | | | | | * ffi.c (carray_uint, carray_int): We must use ffi_type_struct_checked here, otherwise we are blindly assuming that the element type is a FFI type.
* compat: fix glaringly broken init-time handling.Kaz Kylheku2021-07-211-7/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We are doing numerous compat_ver checks in various init functions, to enact alternative symbol registrations. Only problem is, compat_ver is always zero during initialization; it is not set until the -C option is processed in txr_main. Registrations must be fixed up after initialization; that's what the compat_fixup mechanism is for. This is an long-standing problem which affects compatibility operation going back over 150 versions. * arith.c (arith_init): Move compat logic to arith_compat_fixup. (arith_compat_fixup): New function. * arith.h (arith_compat_fixup): Declared. * eval.c (eval_init): Move compat logic to eval_compat_fixup. * ffi.c (ffi_init): Move compat logic to ffi_compat_fixup. (ffi_compat_fixup): New function. * ffi.h (ffi_compat_fixup): Declared. * regex.c (regex_init): Move compat logic to regex_compat_fixup. (regex_compat_fixup): New function. * regex.h (regex_compat_fixup): Declared. * stream.c (stream_init): Move compat logic to stream_compat_fixup. (stream_compat_fixup): New function. * stream.h (stream_compat_fixup): Declared. * struct.c (struct_init): Move compat logic to struct_compat_fixup. (struct_compat_fixup): New function. * struct.h (stream_compat_fixup): Declared. * lib.c (compat_fixup): Call arith_compat_fixup, ffi_compat_fixup, regex_compat_fixup, stream_compat_fixup and struct_compat_fixup.
* type: disallow structs using built-in type names.Kaz Kylheku2021-07-081-22/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* c_str now takes a self argument.Kaz Kylheku2021-06-231-15/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Adding a self parameter to c_str so that when a non-string occurs, the error is reported against a function. Legend: A - Pass existing self to c_str. B - Define self and pass to c_str and possibly other functions. C - Take new self parameter and pass to c_str and possibly other functions. D - Pass existing self to c_str and/or other functions. E - Define self and pass to other functions, not c_str. X - Pass nil to c_str. * buf.c (buf_strm_put_string, buf_str): B. * chksum.c (sha256_str, md5_str): C. (sha256_hash, md5_hash): D. * eval.c (load): D. * ffi.c (ffi_varray_dynsize, ffi_str_put, ffi_wstr_put, ffi_bstr_put): A. (ffi_char_array_put, ffi_wchar_array_put): C. (ffi_bchar_array_put): A. (ffi_array_put, ffi_array_out, ffi_varray_put): D. * ftw.c (ftw_wrap): A. * glob.c (glob_wrap): A. * lib.c (copy_str, length_str, coded_length,split_str_set, list_str, cmp_str, num_str, out_json_str, out_json_rec, display_width): B. (upcase_str, downcase_str, string_extend, search_str, do_match_str, do_rmatch_str, sub_str, replace_str, cat_str_append, split_str_keep, trim_str, int_str, chr_str, span_str, compl_span_str, break_str, length_str_gt, length_str_ge, length_str_lt, length_str_le, find, rfind, pos, rpos, mismatch, rmismatch): A. (c_str): Add self parameter and use in type mismatch diagnostic. If the parameter is nil, use "internal error". (flo_str): B, and correction to "flot-str" typo. (out_lazy_str, out_quasi_str, obj_print_impl): D. * lib.h (c_str): Declaration updated. * match.c (dump_var): X. (v_load): D. * parser.c (open_txr_file): C. (load_rcfile): E. (find_matching_syms, provide_atom): X. (hist_save, repl): B. * parser.h (open_txr_file): Declaration updated. * parser.y (chrlit): X. * regex.c (search_regex): A. * socket.c (getaddrinfo_wrap, sockaddr_pack): A. (dgram_put_string): B. (open_sockfd): D. (sock_connect): E. * stream.c (stdio_put_string, tail_strategy, vformat_str, open_directory, open_file, open_tail, remove_path, rename_path, tmpfile_wrap, mkdtemp_wrap, mkstemp_wrap): B. (do_parse_mode, parse_mode, make_string_byte_input_stream): B. (normalize_mode, normalize_mode_no_bin): E. (string_out_put_string, formatv, put_string, open_fileno, open_subprocess, open_command, base_name, dir_name, short_suffix, long_suffix): A. (run): D. (win_escape_cmd, win_escape_arg): X. * stream.h (parse_mode, normalize_mode, normalize_mode_no_bin): Declarations updated. * sysif.c (mkdir_wrap, do_utimes, dlopen_wrap, dlsym_wrap, dlvsym_wrap): A. (do_stat, do_lstat): C. (mkdir_nothrow_exists, ensure_dir): E. (chdir_wrap, rmdir_wrap, mkfifo_wrap, chmod_wrap, symlink_wrap, link_wrap, readlink_wrap, exec_wrap, getenv_wrap, setenv_wrap, unsetenv_wrap, getpwnam_wrap, getgrnam_wrap, crypt_wrap, fnmatch_wrap, realpath_wrap, opendir_wrap): B. (stat_impl): statfn pointer-to-function argument now takes self parameter. When calling it, we pass name. * syslog.c (openlog_wrap, syslog_wrapv): A. * time.c (time_string_local, time_string_utc, time_string_meth, time_parse_meth): A. (strptime_wrap): B. * txr.c (txr_main): D. * y.tab.c.shipped: Updated.
* ffi: lazily calculate libffi type descriptors.Kaz Kylheku2021-06-101-122/+110
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I think this is a nicer treatment of the libffi situation. We only need the type descriptors for arrays, structs and unions if they are ever used as return values or arguments in a libffi call descriptor. We don't have to waste time and memory allocating them otherwise, and in the case of arrays, we can allocate the full descriptor that includes every member, when that is needed. Structures that are involved in calls, but are passed and returned by pointer, not directly, will not have this cruft instantiated at all. * ffi.c (struct txr_ffi_type): New function pointer member calcft. This specifies the lazy initialization funtion for the libffi stuff. Only arrays, structs and unions have a non-null pointer here. If the pointer is null, it indicates that the type doesn't require lazy initialization: either because it was initialized eagerly, or because lazy initialization was already done. (ffi_get_type): If the type has a calcft, then call it and null it out, to ensure tffi->ft. (ffi_struct_clone): Do not deal with ft and elements here at all. (ffi_union_clone): Short-lived static function removed, because it is identical to ffi_struct_clone again. (ffi_struct_calcft, ffi_union_calcft, ffi_array_calcft): New static functions, implementing different strategies for calculating the libffi elements array. For unions, I invented this strategy: we pretend that a union is atually a structure made of repetitions of the type which has the strictest alignment. This is uncharted territory because libffi doesn't support unions at all. (make_ffi_type_struct, make_ffi_type_union, make_ffi_type_array): Do not deal with tf or elems, except for deleting them if we are re-initializing the object. Leave these pointers null. Install the appropriate calcft function. (ffi_array_clone): Function removed; the array type can use ffi_simple_clone, since the clone function doesn't deal with the libffi stuff. Why was that needed until several commits ago? Because, subject to HAVE_FFI, it performed the assignment ft->elements = copy->elements.
* ffi: bug: always using ffi_prep_cif_var.Kaz Kylheku2021-06-091-2/+2
| | | | | | | | | | | | | | | * share/txr/stdlib/ffi.c (deffi): Fix misnamed variable. The second value coming from sys:analyze-argtypes is the number of fixed arguments, not the number of variadic arguments. Furthermore, if this number is equal to nargs, we were supposed to have been passing nil instead to ffi-make-call-desc, which indicates the ordinary non-variadic function. We were always always passing a non-nil value, so always requesting variadic. That is fixed now thanks to the change to ffi_make_call_desc. * ffi.c (ffi_make_call_desc): Register the function as variadic if either nfixed is specified as nil, or if it is equal to ntotal. * txr.1: Document the convention change for ffi-make-call-desc.
* ffi: earnest implementation of FFI struct elements.Kaz Kylheku2021-06-091-23/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit tries to address a flaw in our use of libffi. When we construct a structure type, we do not fill in the "elements" array of the libffi type to describe every element. Instead we calculate the size and alignment ourselves. This breaks when passing small structures by value on some platforms. There are some areas where we are still winging it. We allow passing of arrays by value, which are simulated using FFI structure types. To allocate the descriptor earnestly for such an object means allocating an array of ffi_type pointers as large as the array, which is wasteful. So we cap it to 20. This 20 comes form the idea that anything bigger than a 16 byte structure is passed on the stack rather than in registers. For unions, we choose the largest member and inform libffi of its type. * ffi.c (struct txr_ffi_type): elements member changes to from array of 1 to pointer. (ffi_type_struct_destroy_op): Consolidate HAVE_LIBFFI code. Don't bother setting tft->ft->elements to null. Free tft->elements. (ffi_struct_clone): Clone the elements array. (ffi_union_clonse): New static function. Unions need their own clone function now because their elements array has a size not related to the number of members. It contains two pointers, including the null terminating one. (make_ffi_type_struct): Allocate the elements array, and fill it. We wing it around bitfields, which libffi doesn't support. This will be revisited, but it's likely a bad idea to be passing bitfield-endowed structures by value. (make_ffi_type_union): Allocate the elements array to a fixed size of two pointers. Fill it in with the largest member's type. (ffi_array_clone): Clone the elements array, which is up two 20 pointers plus a null terminator. (make_ffi_type_array): Allocate the elements array up to 20 elements plus null pointer, and fill it with repetitions of the element libffi type.
* ffi: fix leak on struct/union redefinition.Kaz Kylheku2021-06-091-0/+6
| | | | | | | * ffi.c (make_ffi_type_struct, make_ffi_type_union): When we are replacing the existing type, if HAVE_FFI is true, we must free the tft->ft object before clobbering the tft with zeros.
* ffi: leak fix on !HAVE_FFI builds.Kaz Kylheku2021-06-091-2/+18
| | | | | | | | | | The ffi_type_struct_destroy_op only frees tft->ft if HAVE_FFI is true. But the object is allocated in several places without regard for HAVE_FFI. * ffi.c (ffi_struct_clone, make_ffi_type_struct, make_ffi_type_union, ffi_array_clone, make_ffi_type_array): Do not allocate a ffi_type object if HAVE_FFI is false.
* ffi: allow conversion of carray objects under cptr.Kaz Kylheku2021-06-061-2/+9
| | | | | | | | | | | | | | * ffi.c (ffi_cptr_put): If the object is not a cptr, try it as a carray. This requires the tft to have an eltype, requiring a change in ffi_type_compile. (ffi_type_compile): When compiling a parametrized cptr object, we now look up the type symbol as a FFI type, and store the result as the tft->eltype. If the symbol is not an FFI type, then this lookup returns nil. If the eltype is non-nil, then there is the possibility it can match the element type of a carray. * txr.1: Documented.
* ffi: allow nil object to convert under closure type.Kaz Kylheku2021-06-061-1/+1
| | | | | | | | * ffi.c (ffi_closure_put): Only diagnose a bad object if it's not nil, otherwise let the null value of p through. This is useful because there are sometimes C interfaces which take an optional function pointer, whereby a null value indicates that the pointer is not specified.
* ffi: add space in ffi-call-desc's printed rep.Kaz Kylheku2021-06-061-1/+1
| | | | | * ffi.c (ffi_call_desc_print_op): Print a space between the class symbol and name so they are not run together.
* FFI: big improvement in bad call diagnosis.Kaz Kylheku2021-06-041-10/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | FFI has the problem that when things go wrong in calls, or in specifications of functions, the diagnostics refer to an internal function like ffi-call or ffi-make-call-desc, which is not helpful in identifying the error. We want the diagnostics to refer to the foreign function, or foreignb callback wrapper, to which the problem pertains. The approach taken is to stick the name symbol into the ffi-call-desc object. Functions which work with a ffi-call-desc can pull out the name and use it for reporting. * ffi.c (struct txr_ffi_call_desc): Add name member. (ffi_call_desc_print_op): Include name in printed representation. (ffi_desc_mark_op): Mark the name. (ffi_make_call_desc): Take new argument to specify the name, storing it into the structure. If it is specified,then use that name for reporting errors, otherwise stick with ffi-make-call-desc. (ffi_call_wrap, ffi_closure_dispatch, ffi_closure_dispatch_safe, ffi_make_closure): Use the name from the call descriptor, or else the function's own name if that is nil. (ffi_init): Update registration of ffi-make-call-desc intrinsic to five arguments with four required. * ffi.h (ffi_make_call_desc): Declaration updated. * share/txr/stdlib/ffi.tl (deffi, deffi-cb-expander): Pass the name symbol down to ffi-make-call-desc. * txr.1: Documented.
* ffi: fix crash: carray argument type.Kaz Kylheku2021-05-221-1/+1
| | | | | | * ffi.c (make_ffi_type_pointer): Set the by_value_in flag only if the in function has been specified. Otherwise tft->in is a null pointer and will be used if this pointer type appears as an argument.
* ffi: fix missing support for misaligned ushort.Kaz Kylheku2021-03-221-0/+2
| | | | | | | | | * ffi.c (ffi_ushort_get): Add the missing align_sw_get macro that checks for and handles misalignment. Commit e539fbc2af3bd4a5bd4ca3d9b567862005509aa1 made on 2017-06-05 added these macros and fixes to numerous functions. The commit message claims that ffi_ushort_get was among the functions fixed, but no change was made to the function.
* ffi: ffi_uchar_put: statement after declaration.Kaz Kylheku2021-03-221-1/+1
| | | | * ffi.c (ffi_uchar_put): Fix for C90 compat and consistency.
* Copyright year bump 2021.Kaz Kylheku2021-01-141-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * METALICENSE: 2020 copyrights bumped to 2021. Added note about SHA-256 routines from Colin Percival. * LICENSE, LICENSE-CYG, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/copy-file.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/each-prod.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/quips.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr, y.tab.c.shipped: Copyright year bumped to 2021.
* ffi/doc: bugfixes to bitfield alignment.Kaz Kylheku2020-08-241-12/+17
| | | | | | | | | | | | | | | | | | | | | | | | | Three issues issues. The documentation is wrong about the concept of a "leading bitfield" whose alignment matters. The alignment of all named bitfields matters. Secondly, the alignment of unnamed bitfields doesn't matter. Thirdly, there is a flaw in the treatment of bitfields in unions, from both alignment and sizing. * ffi.c (make_ffi_type_struct): A bitfield member contributes to alignment regardless of its offset within an allocation unit: no bits_alloc == 0 check should be applied. Secondly, a bitfield member that is unnamed has an alignment of 1, otherwise the alignment of its declared type. (make_ffi_type_union): The size and alignment of a bitfield member is not simply that of its type. The size of a bitfield is the number of bytes required to store all of the bits. The alignment is 1 if it is unnamed, otherwise that of its type. The sizing of bitfields now means that alignment can add padding to a union. For instance, a uint32_t x : 17 bitfield has size 3, but alignment 4, requiring one byte of alignment padding in the union so that its size is 4. This means that we must now do the padding alignment calculation for unions to adjust the size, just like we do for structures.
* ffi: bugfix: zero-width bitfield offset problem.Kaz Kylheku2020-08-241-1/+1
| | | | | | | | | | | | | | | | * ffi.c (make_ffi_type_struct): Fix incorrect condition for determining whether the zero-width bitfield allocates a unit or not. We must take into account the bit_offs, because it's possible that unit_offs and offs are the same, yet a previous bitfield has allocated some bits into the current allocation unit. For instance struct { char a : 1; uint32 : 0; char b } has size 5, but the equivalent FFI struct type ends up with size 1. After char a : 1, the byte offset is still zero, so if we don't look at the bit offset of 1, it looks like the allocation offset is aligned to the start of a uint32 cell, which then means that the zero-width bitfield is ignored. What's worse, the char b is then also allocated over top of the a : 1 bitfield.
* ffi: correct tft->nmemb under zero-bit fields.Kaz Kylheku2020-08-241-2/+4
| | | | | | | | | * ffi.c (make_ffi_type_struct, make_ffi_type_union): Assign tft->memb = memb after the loop which compiles the member types, because memb is decremented in the case of the zero-width bitfield. This hasn't cause an issue because the extra members are all zero, so their slot symbol is nil, and all the relevant operations skip a nil named member.
* cptr: bugfix: cptr-out must fall back on tft->put.Kaz Kylheku2020-07-131-1/+4
| | | | | * ffi.c (cptr_out): tft->out may be null, in which case tft->put must be used.
* cptr: new cptr-get and cptr-out functions.Kaz Kylheku2020-07-131-0/+35
| | | | | | | | | | | | | | | | | These functions are quite helpful in dealing with semi-opaque types, like the xmlNode type of libxml2. Such types must be treated as an opaque handle when passed to and returned from the API, and not subject to any encoding or decoding, which means that the appropriate representation for them is via the cptr family of types. However, semi-opaque types also have client-visible members that must be accessed directly. These new functions provide for that access in a convenient way. * ffi.c (ffi_type_lookup_checked): New static function. (cptr_getobj, cptr_out): New static functions. (ffi_init): Register cptr-get and cptr-out. * txr.1: Documented.
* c_num: now takes self argument.Kaz Kylheku2020-06-291-75/+83
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The c_num and c_unum functions now take a self argument for identifying the calling function. This requires changes in a large number of places. In a few places, additional functions acquire a self argument. The ffi module has the most extensive example of this. Some functions mention their name in a larger string, or have scattered literals giving their name; with the introduction of the self local variable, these are replaced by references to self. In the following changelog, the notation TS stands for "take self argument", meaning that the functions acquires a new "val self" argument. The notation DS means "define self": the functions in question defines a self variable, which they pass down. The notation PS means that the functions pass down an existing self variable to functions that now require it. * args.h (args_count): TS. * arith.c (c_unum, c_num): TS. (toint, exptv): DS. * buf.c (buf_check_len, buf_check_alloc_size, buf_check_index, buf_do_set_len, replace_buf, buf_put_buf, buf_put_i8, buf_put_u8, buf_put_char, buf_put_uchar, buf_get_bytes, buf_get_i8, buf_get_u8, buf_get_cptr, buf_strm_get_byte_callback, buf_strm_unget_byte, buf_swap32, str_buf, buf_int, buf_uint, int_buf, uint_buf): PS. (make_duplicate_buf, buf_shrink, sub_buf, buf_print, buf_pprint): DS. * chskum.c (sha256_stream_impl, sha256_buf, crc32_buf, md5_stream_impl, md5_buf): TS. (chksum_ensure_buf, sha256_stream, sha256, sha256_hash, md5_stream, md5, md5_hash): PS. (crc32_stream): DS. * combi.c (perm_while_fun, perm_gen_fun_common, perm_str_gen_fun, rperm_gen_fun, comb_vec_gen_fun, comb_str_gen_fun, rcomb_vec_gen_fun, rcomb_str_gen_fun): DS. * diff.c (dbg_clear, dbg_set, dbg_restore): DS. * eval.c (do_eval, gather_free_refs, maprodv, maprendv, maprodo, do_args_apf, do_args_ipf): DS. (op_dwim, me_op, map_common): PS. (prod_common): TS. * ffi.c (struct txr_ffi_type): release member TS. (make_ffi_type_pointer): PS and release argument TS. (ffi_varray_dynsize, ffi_array_in, ffi_array_put_common, ffi_array_get_common, ffi_varray_in, ffi_varray_null_term): PS. (ffi_simple_release, ffi_ptr_in_release, ffi_struct_release, ffi_wchar_array_get, ffi_array_release_common, ffi_array_release, ffi_varray_release): TS. (ffi_float_put, double_put, ffi_be_i16_put, ffi_be_u16_put, ffi_le_i16_put, ffi_le_u16_put, ffi_be_i32_put, ffi_be_u32_put, ffi_le_i32_put, ffi_sbit_put, ffi_ubit_put, ffi_buf_d_put, make_ffi_type_array, make_ffi_type_enum, ffi_type_compile, make_ffi_type_desc, ffi_make_call_desc, ffi_call_wrap, ffi_closure_dispatch_save, ffi_put_into, ffi_in, ffi_get, ffi_put, carray_set_length, carray_blank, carray_buf, carray_buf_sync, carray_cptr, carray_refset, carray_sub, carray_replace, carray_uint, carray_int): PS. (carray_vec, carray_list): DS. * filter.c (url_encode, url_decode, base64_stream_enc_impl): DS. * ftw.c (ftw_callback, ftw_wrap): DS. * gc.c (mark_obj, gc_set_delta): DS. * glob.c (glob_wrap): DS. * hash.c (equal_hash, eql_hash, eq_hash, do_make_hash, hash_equal, set_hash_traversal_limit, gen_hash_seed): DS. * itypes.c (c_i8, c_u8, c_i16, c_u16, c_i32, c_u32, c_i64, c_u64, c_short, c_ushort, c_int, c_uint, c_long, c_ulong): PS. * lib.c (seq_iter_rewind): TS and becomes internal. (seq_iter_init_with_info, seq_setpos, replace_str, less, replace_vec, diff, isec, obj_print_impl): PS. (nthcdr, equal, mkstring, mkustring, upcase_str, downcase_str, search_str, sub_str, cat_str, scat2, scat3, fmt_join, split_str_keep, split_str_set, trim_str, int_str, chr_int, chr_str, chr_str_set, vector, vecref, vecref_l, list_vec, copy_vec, sub_vec, cat_vec, lazy_str_put, lazy_str_gt, length_str_ge, length_str_lt, length_str_le, cptr_size_hint, cptr_int, out_lazy_str, out_quasi_str, time_string_local_time, time_string_utc, time_fields_local_time, time_fields_utc, time_struct_local, time_struct_utc, make_time, time_meth, time_parse_meth): DS. (init_str, cat_str_init, cat_str_measure, cat_str_append, vscat, time_fields_to_tm, time_struct_to_tm, make_time_impl): TS. * lib.h (seq_iter_rewind): Declaration removed. (c_num, c_unum, init_str): Declarations updated. * match.c (LOG_MISMATCH, LOG_MATCH): PS. (h_skip, h_coll, do_output_line, do_output, v_skip, v_fuzz, v_collect): DS. * parser.c (parser, circ_backpatch, report_security_problem, hist_save, repl, lino_fileno, lino_getch, lineno_getl, lineno_gets, lineno_open): DS. (parser_set_lineno, lisp_parse_impl): PS. * parser.l (YY_INPUT): PS. * rand.c (make_random_state): PS. * regex.c (print_rec): DS. (search_regex): PS. * signal.c (kill_wrap, raise_wrap, get_sig_handler, getitimer_wrap, setitimer_wrap): DS. * socket.c (addrinfo_in, sockaddr_pack, fd_timeout, to_connect, open_sockfd, sock_mark_connected, sock_timeout): TS. (getaddrinfo_wrap, dgram_set_sock_peer, sock_bind, sock_connect, sock_listen, sock_accept, sock_shutdown, sock_send_timeout, sock_recv_timeout, socketpair_wrap): DS. * stream.c (generic_fill_buf, errno_to_string, stdio_truncate, string_out_put_string, open_fileno, open_command, base_name, dir-name): DS. (unget_byte, put_buf, fill_buf, fill_buf_adjust, get_line_as_buf, formatv, put_byte, test_set_indent_mode, test_neq_set_indent_mode, set_indent_mode, set_indent, inc_indent, set_max_length, set_max_depth, open_subprocess, run ): PS. (fds_subst, fds_swizzle): TS. * struct.c (make_struct_type, super, umethod_args_fun): PS. (method_args_fun): DS. * strudel.c (strudel_put_buf, strudel_fill_buf): DS. * sysif.c (errno_wrap, exit_wrap, usleep_wrap, mkdir_wrap, ensure_dir, makedev_wrap, minor_wrap, major_wrap, mknod_wrap, mkfifo_wrap, wait_wrap, wifexited, wexitstatus, wifsignaled, wtermsig, wcoredump, wifstopped, wstopsig, wifcontinued, dup_wrap, close_wrap, exit_star_wrap, umask_wrap, setuid_wrap, seteuid_wrap, setgid_wrap, setegid_wrap, simulate_setuid_setgid, getpwuid_wrap, fnmatch_wrap, dlopen_wrap): DS. (chmod_wrap, do_chown, flock_pack, do_utimes, poll_wrap, setgroups_wrap, setresuid_wrap, setresgid_wrap, getgrgid_wrap): PS. (c_time): TS. * sysif.h (c_time): Declaration updated. * syslog.c (openlog_wrap, syslog_wrap): DS. * termios.c (termios_pack): TS. (tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap, tcdrain_wrap, tcflush_wrap, tcflow_rap, encode_speeds, decode_speeds): DS. * txr.c (compato, array_dim, gc_delta): DS. * unwind.c (uw_find_frames_by_mask): DS. * vm.c (vm_make_desc): PS. (vm_make_closure, vm_swtch): DS.
* ffi: big-endian: unused parameter warnings.Kaz Kylheku2020-04-281-1/+55
| | | | | | | | | | | | | * ffi.c (ffi_i8_rput, ffi_i8_rget, ffi_u8_rput, ffi_u8_rget, ffi_i16_rput, ffi_i16_rget, ffi_u16_rput, ffi_u16_rget, ffi_i32_rput, ffi_i32_rget, ffi_u32_rput, ffi_u32_rget, ffi_char_rput, ffi_char_rget, ffi_uchar_rput, ffi_uchar_rget, ffi_bchar_rget, ffi_short_rput, ffi_short_rget, ffi_ushort_rput, ffi_ushort_rget, ffi_int_rput, ffi_int_rget, ffi_uint_rput, ffi_uint_rget, ffi_long_rput, ffi_long_rget, ffi_ulong_rput, ffi_ulong_rget, ffi_wchar_rput, ffi_wchar_rget, ffi_be_i16_rput): Add casts to suppress warnings about unused tft and self.
* carray: revise carray diagnostics.Kaz Kylheku2020-04-241-8/+8
| | | | | | | * ffi.c (carray_dup, carray_blank, carray_ref, carray_refset, carray_replace, carray_pun): Refer to "carray" rather than "array" in diagnostic messages, which is more accurate and consistent with newer diagnostics added in previous patch.
* carray: bug sweep.Kaz Kylheku2020-04-241-28/+62
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The carray type is hereby reviewed for and repaired of issues related to the nelem member of struct carray using negative values to indicate "unknown carray size". * ffi.c (struct carray): The artype becomes a two-element array of values, so a carray can have a cache of separate null-terminated and non-null-terminated array type descriptors. This way, we get rid of the dirty trick of mutating one type. (carray_mark_op): Mark the two-element artype. (make_carray): Initialize two-element artype to nil. (carray_set_length): Cache invalidation: reset both elements of artype to nil, because the type includes length information, which may now be wrong. (copy_carray): Throw exception if asked to copy carray of unknown length. This would happen in carray_dup anyway, but at least the diagnostic refers to copy-carray. (buf_carray): Avoid calling make_duplicate_buf with negative bytes value when the carray has unknown length; diagnose. (carray_ref, carray_refset): Don't translate negative index values if the length is unknown. (carray_sub, carray_replace): If the operation requires use of the length, and it is unknown, throw an exception. (carray_ensure_artype): Take a null_term paramter that is 0 or 1, and use it as an array index into artype to set up the correct type, with the correct value of the null_term member that is henceforth not mutated. (carray_get_common, carray_put_common): Pass the null_term argument down to carray_ensure_artype. Remove the mutation of the null_term member of the type structure.
* warning cleanup: signed/unsigned in ternaries.Kaz Kylheku2020-04-051-1/+1
| | | | | | | | | | | | | | | | | | | | | This is the third round of an effort to enable GCC's -Wextra option. Instances of signed/unsigned mismatch between the branches of ternary conditionals are addressed. * ffi.c (pad_retval): Add cast into the consequent of the conditional so it yields size_t, like the alternative. * lib.c (split_str_keep): Likewise. (vector): Cast -1 to ucnum so it has the same type as the alloc_plus opposite to it. * parser.c (lino_getch): Add a cast to wint_t to match return value and opposite WEOF operand. * stream.c (generic_get_line): Likewise. * sysif.c (c_time): Convert both consequent and alternative to time_t to silence warning.
* warning cleanup: add casts for unused parameters.Kaz Kylheku2020-04-051-1/+195
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is the first round of an effort to enable GCC's -Wextra option. All function parameters that are unused an that we cannot eliminate are treated with a cast to void in the function body. * args.c (args_key_check_store): Cast unused param to void. * combi.c (perm_list_gen_fill): Likewise. * eval.c (op_error, op_meta_error, op_quote op_qquote_error, op_unquote_error, op_load_time_lit, me_each, me_for, me_quasilist, me_flet_labels, hash_min_max, me_ignerr, me_whilet, me_iflet_whenlet, me_dotimes, me_mlet, me_load_time, me_load_for): Likewise. * ffi.c (ffi_void_put, ffi_fixed_dynsize, *ffi_fixed_alloc, ffi_noop_free, ffi_void_get, ffi_simple_release, ffi_i8_put, ffi_i8_get, ffi_u8_put, ffi_u8_get, ffi_i16_put, ffi_i16_get, ffi_u16_put, ffi_u16_get, ffi_i32_put, ffi_i32_get, ffi_u32_put, ffi_u32_get, ffi_i64_put, ffi_i64_get, ffi_u64_put, ffi_u64_get, ffi_char_put, ffi_char_get, ffi_uchar_put, ffi_uchar_get, ffi_bchar_get, ffi_short_put, ffi_short_get, ffi_ushort_put, ffi_ushort_get, ffi_int_put, ffi_int_get, ffi_uint_put, ffi_uint_get, ffi_long_put, ffi_long_get, ffi_ulong_put, ffi_ulong_get, ffi_float_put, ffi_float_get, ffi_double_put, ffi_double_get, ffi_val_put, ffi_val_get, ffi_be_i16_put, ffi_be_i16_get, ffi_be_u16_put, ffi_be_u16_get, ffi_le_i16_put, ffi_le_i16_get, ffi_le_u16_put, ffi_le_u16_get, ffi_be_i32_put, ffi_be_i32_get, ffi_be_u32_put, ffi_be_u32_get, ffi_le_i32_put, ffi_le_i32_get, ffi_le_u32_put, ffi_le_u32_get, ffi_be_i64_put, ffi_be_i64_get, ffi_be_u64_put, ffi_be_u64_get, ffi_le_i64_put, ffi_le_i64_get, ffi_le_u64_put, ffi_le_u64_get, ffi_wchar_put, ffi_wchar_get, ffi_sbit_get, ffi_ubit_get, ffi_cptr_get, ffi_str_in, ffi_str_put, ffi_str_get, ffi_str_d_get, ffi_wstr_in, ffi_wstr_get, ffi_wstr_put, ffi_wstr_d_get, ffi_bstr_in, ffi_bstr_put, ffi_bstr_get, ffi_bstr_d_get, ffi_buf_in, ffi_buf_put, ffi_buf_get, ffi_buf_d_in, ffi_buf_d_put, ffi_buf_d_get, ffi_closure_put, ffi_ptr_in_in, ffi_ptr_in_d_in, ffi_ptr_in_out, ffi_ptr_out_in, ffi_ptr_out_out, ffi_ptr_out_null_put, ffi_ptr_out_s_in, ffi_flex_struct_in, ffi_carray_get, ffi_union_get, make_ffi_type_builtin, make_ffi_type_array, ffi_closure_dispatch, ffi_closure_dispatch_safe): Likewise. * gc.c (cobj_destroy_stub_op, cobj_destroy_free_op, cobj_mark_op): Likewise. * lib.c (seq_iter_get_nil, seq_iter_peek_nil): Likewise. * linenoise/linenoise.c (sigwinch_handler): Likewise. * parser.c (repl_intr, read_eval_ret_last, repl_warning, is_balanced_line): Likewise. * parser.y (yydebug_onoff): Likewise. * socket.c (dgram_close): Likewise. * stream.c (unimpl_put_string, unimpl_put_char, unimpl_put_byte, unimpl_unget_char, unimpl_unget_byte, unimpl_put_buf, unimpl_fill_buf, unimpl_seek, unimpl_truncate, unimpl_set_sock_peer, null_put_string, null_put_char, null_put_byte, null_get_line, null_get_char, null_get_byte, null_close, null_flush, null_seek, null_set_prop, null_get_error, null_get_error_str, null_clear_error, null_get_fd, dir_close): Likewise. * struct.c (struct_type_print): Likewise. * unwind.c (me_defex): Likewise.
* ffi: varray: g++ signed/unsigned warning.Kaz Kylheku2020-02-081-1/+1
| | | | | | * ffi.c (ffi_varray_alloc): Add cast to this conversion. The idea here is we are checking for truncation when cnum is converted to size_t.
* ffi: fix broken char handling in undimensioned arrays.Kaz Kylheku2020-01-171-36/+99
| | | | | | | | | | | | | | | | | | | | | | | | | | | The undimensioned (array <type>) and (zarray <type>) types are not doing UTF-8 conversion when <type> is char or zchar, or doing what they are supposed to with the FFI character types, which is inconsistent from their dimensioned counterparts. * ffi.c (ffi_varray_dynsize): if the element type is marked for character conversion, then do the size calculation for char and zchar by measuring the UTF-8 coded size. (ffi_varray_alloc): Call ffi_varray_dynsize to get the size, to benefit from the char handling. Thus when FFI allocates buffers for a variable length array, it will allocate correct size required for the UTF-8 encoded string. (ffi_varray_put, ffi_varray_in): Here we must call ffi_varray_dynsize and divide by the element type to get the proper numer of elements. Then we must check for character conversion and handle the cases. (ffi_varray_null_term_in): Check for character conversion cases and route those through ffi_varray_in, which handles null-terminated strings. * tests/017/ffi-misc.tl: New file. * tests/017/ffi-misc.expected: New file.
* ffi: fix non-libffi build on big endian.Kaz Kylheku2020-01-061-0/+1
| | | | | | | | This is cribbed from a patch by q66 <daniel@oct***rge.org>, commited recently to the Void Linux distro. * ffi.c (ffi_arg): Define this type when HAVE_FFI is not enabled. Some big-endian-specific code refers to it.
* Copyright year bump 2020.Kaz Kylheku2019-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended copyright notices to 2020.
* ffi: bug: zchar not handled in array out semantics.Kaz Kylheku2019-12-161-0/+1
| | | | * ffi.c (ffi_array_out): Add missing zchar case.
* ffi: shut up gcc7 warnings about switch case.Kaz Kylheku2019-12-161-0/+7
| | | | | | * ffi.c (ffi_array_put, ffi_array_out): Handle conv_none in the switch, even though the whole switch is conditional on the value being other than conv_none.
* ffi: new type zcharKaz Kylheku2019-12-141-1/+41
| | | | | | | | | | | | | | | | | | | The zchar type, when used as an array element, specifies an optionally null-terminated or padded field, which is subject to UTF-8 conversion. * ffi.c (zchar_s): New symbol variable. (enum char_conv): New member, conv_zchar. (ffi_zchar_array_get): New static function. (ffi_array_in, ffi_array_get_common): Handle conv_zchar via ffi_zchar_array_get. (ffi_array_put): Handle conv_char together with conv_zchar. (ffi_type_compile): Handle zchar array element type, mapping to conv_zchar. (ffi_init_types): Register zhar type. (ffi_init): Initialize zchar_s symbol variable. * txr.1: Documented.
* ffi: turn char conversion flags into enum.Kaz Kylheku2019-12-141-52/+85
| | | | | | | | | | | | | | | | | | The three flags controlling character array conversion semantics are mutually exclusive. Let's turn them into an enumeration, so we can (1) test that a conversion is in effect by testing a single value and (2) switch on the conversion type instead of successively testing the flags and (3) assure the aforementioned mutual exclusion. * ffi.c (enum char_conv): New enum. (struct txr_ffi_type): Members char_conv, wchar_conv and bchar_conv gone, replaced by ch_conv. (ffi_array_in, ffi_array_put, ffi_array_out, ffi_array_get_common, ffi_array_release_common, ffi_varray_null_term_get, ffi_type_compile, carray_ensure_artype): Work with ch_conv instead of three flags.
* ffi: allow init-forms for slots.Kaz Kylheku2019-12-061-9/+40
| | | | | | | | | | | | | | | * ffi.c (ffi_memb_compile): Don't complain about three-argument slot specifiers, only about longer ones. (ffi_struct_init): New static function. (ffi_type_compile): Deal with third element in the slot syntax. If there are any non-nil initializing expressions, then we when we call make_struct_type, we specify an initfun, which will plant the values into the slots, using logic similar to that of the initfun generated defstruct, except that the init-forms are reduced to values up-front. * txr.1: Specify optional init-form for slots in FFI struct syntax.
* ffi: rename functions in the carray-num group.Kaz Kylheku2019-11-181-12/+27
| | | | | | | | | | | | | | * ffi.c (carray_unum, carray_num, unum_carray, num_carray): Functions renamed to carray_uint, carray_int, uint_carray, int_carray. (ffi_init): Functions registered under new names: carray-uint, carray-int, uint-carray, int-carray. Compat values of 227 or less provide the old old names. * ffi.h (carray_unum, carray_num, unum_carray, num_carray): Declarations renamed. * txr.1: Updated to new names; compat note added.
* ffi: carray-num using wrong function name.Kaz Kylheku2019-11-181-1/+1
| | | | | * ffi.c (carray_num): Use the correct name carray-num rather than carray-unum in diagnostics.
* safety: fix type tests that code can subvert.Kaz Kylheku2019-09-301-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch fixes numerous instances of a safety hole which involves the type of a COBJ object being tested to be of a given class using logic that can be subverted by the definition of a like-named struct. Specifically logic like (typeof(obj) == hash_s) is broken, because if a struct type called hash is defined, then the test will yield true for instances of that struct type. Those instances can then be passed into code that only works on COBJ hashes, and relies on this test to reject invalid objects. * ffi.c (make_carray): Replace fragile test with strong one, using new cobjclassp function. * hash.c (hashp): Likewise. * lib.c (class_check): The expression used here for the type test moves into the new function cobjclassp and so is replaced by a call to that function. (cobjclassp): New function. * lib.h (cobjclassp): Declared. * rand.c (random_state_p): Replace fragile test using cobjclassp. * regex.c (char_set_compile): Replace fragile typeof tests for character type with is_chr. (reg_derivative, regexp): Replace fragile test with cobjclassp. * struct.c (struct_type_p): Replace fragile test with cobjclassp.
* lib: access special methods via special slot mechanism.Kaz Kylheku2019-09-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (ffi_flex_struct_in): Use get_special_slot to obtain length method. * lib.c (nullify_s, from_list_s, lambda_set_s): Definitions removed from here. (seq_info, car, cdr, rplaca, rplacd, make_like, nullify, replace_obj, length, empty, sub, ref, refset, dwim_set): Use get_special_slot to obtain special method from object, rather than maybe_slot. (obj_init): Remove initializations of nullify_s, from_list_s and lambda_set_s from here. * struct.c (enum special_slot): Definition removed from here. (nullify_s, from_list_s, lambda_set_s): Definitions moved here from lib.c. (special_sym): New static array. (struct_init): Initializations of nullify_s, from_list_s and lambda_set_s moved here from lib.c. (get_special_slot): New function. * struct.h (lambda_set_s): Declared. (enum special_slot): Definition moved here. (get_special_slot): Declared. * txr.1: Added compat note, since get_special_slot behaves like maybe_slot under 224 compatibility.
* ffi: bugfix: kind enum in wrong argument positions.Kaz Kylheku2019-07-301-10/+14
| | | | | | | | | | | | * ffi.c (ffi_type_compile, ffi_init_types): Fixed a number of instances of make_ffi_type_builtin being passed the type kind as the fourth rather than the third argument. The strange fluke here is that FFI_KIND_NUM is 1, so this actually made no difference in all the case in ffi_init_types! However in ffi_type_compile, it would have set the type of cptr-s to struct, and its size to 3. Anyway, we were saved from a regression by the good pre-release habit of compiling as C++!
* FFI: bugfix: GC-correctness of assignments.Kaz Kylheku2019-07-281-0/+11
| | | | | | | | | | | Recent work has introduced wrong-way assignments. When we compile the slots after we have created the type object, the slot types may be in a newer generation than the type object. If we are reusing an old type object, it can be older than the syntax, or the Lisp object being stored in it. * ffi.c (make_ffi_type_struct, make_ffi_type_union): add some setcheck calls to handle anti-generational assignments.
* FFI: bugfix: properly re-use existing struct type.Kaz Kylheku2019-07-281-2/+6
| | | | | | | | | This is a bug in the prior commit's change. * ffi.c (make_ffi_type_struct, make_ffi_type_union): When using an existing type, do not call cobj to make a new Lisp object for the type structure; pull the existing one out from tft->self.