summaryrefslogtreecommitdiffstats
path: root/ffi.c
Commit message (Collapse)AuthorAgeFilesLines
* ffi: pack: implement documented align transformation.Kaz Kylheku2022-05-201-19/+32
| | | | | | | | | | | * ffi.c (ffi_pack_members): Static function removed. (ffi_transform_pack): New static function. (ffi_type_compile): Rely on ffi_transform_pack to recognize and perform all necessary transformations. Cosmetic issue: when a struct is compiled, and the individual member types undergo transformation during member compilation, the syntax for the struct is nevertheless the original one with the untransformed members.
* ffi: bugfix: clone of type points to old self.Kaz Kylheku2022-05-201-2/+6
| | | | | | | | | | | | * ffi.c (ffi_type_copy, ffi_type_copy_new_ops): The cloned txr_ffi_type structure must have a self member which points to the new cobj, not the original one. Otherwise things are inconsistent. For instance if the clone is being made for the purposes of adjusting alignment, any operation which chases the self pointer will be accessing incorrect attributes. One example of this is (alignof foo.bar) where if bar is the clone of a type, this will incorrectly report the alignment of the original from which bar was cloned, and the original alignment, not the adjusted alignment is reported.
* ffi: new pack type operator; align increases only.Kaz Kylheku2022-05-201-14/+49
| | | | | | | | | | | | | | | | | * ffi.c (pack_s): New symbol variable. (ffi_type_compile): Handle new pack type operator together with align. Allow a one-argument form of align and pack in which the value is defaulted. The behavior of align changes: align can only increase alignment now, never decrease, so for instance (align 1 ...) does nothing. pack must be used to decrease alignment. Furthermore, for certain argument types, pack performs transformations of the type syntax, rather than compiling the argument type and producing a variant of it with altered alignment. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi: bugfix: transition between bitfield cell sizes.Kaz Kylheku2022-05-191-0/+10
| | | | | | | | | * ffi.c (make_ffi_type_struct): When a bitfield is declared for a type whose alignment is different from that of the previous member, then we start the new bitfield on a fresh alignment. As usual, if the previous member is a bitfield which left a partially filled byte, we skip to the next byte and then do the alignment. This seems to match GCC behavior.
* ffi: bitfield handling when storage cells are packed.Kaz Kylheku2022-05-191-11/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In gcc, bitfields can be declared with overridden alignment; for instance when the entire structure is packed. We must modify the algorithm to make this work. Firstly, we must must pretend that we are filling from the start of the containing alignment unit, not size based unit. For instance, if the cell is an 8 byte type, but the alignment is 1, then we are just filling the current byte, not the current 8 byte multiple. However, the number of bits left (room) is still calculated from the size: so if the byte has been filled with 3 bits, we have 4 left in that byte, and then 7 more bytes, and so 61 bits. Secondly, the case of the zero-bit field is special: it does perform an alignment calculation in terms of multiples of the size, ignoring the declared alignment of the field. Thirdly, when the bits do not fit into the existing room, the offset does not move by the size of the bitfield, but by the alignment unit. For instance, if we have 63 bits left in an 8 byte field that has alignment 1, and we want to place 64 bits into another 8 byte field, then we will just move to the next byte, not to the next 64 bit cell. Starting at the next byte, we pretend we have a fres 64 bit cell, albeit misaligned. * ffi.c (make_ffi_type_struct): Make the above adjustments to the algorithm. Some common values size, alignment, mask) are declared in a wider scope and adjustments made.
* ffi: bugfix: empty structs/unions have alignment of 1.Kaz Kylheku2022-05-191-2/+2
| | | | | | | | * ffi.c (make_ffi_type_struct, make_ffi_type_union): Initialize most_align local variable to 1, so the lower bound of alignment is that, rather than zero. * tests/017/ffi-misc.tl: Tests added.
* ffi: bugfix in fat bitfields.Kaz Kylheku2022-05-191-2/+2
| | | | | | | * ffi.c (make_ffi_type_struct, make_ffi_type_union): Do not fall back from the fat (64 bit) bitfield case to the regular (32 bit) case when the number of bits is less than 32. This is completely wrong.
* ffi: diagnose bitfields wider than type.Kaz Kylheku2022-05-191-6/+6
| | | | | | | | | * ffi.c (ffi_type_compile): Show the original bitfield syntax in the invalid size diagnostics. In the case of the (bit n type) syntax, restrict the maximum bits to the width of the type, not just to 32 or 64. I realize the 8 * tft->size calculation can overflow for huge array types, but it makes no sense to use them as bitfields.
* ffi: support 64 bit bitfields.Kaz Kylheku2022-05-191-22/+207
| | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (struct txr_ffi_type): Replace unsigned mask member with a union m which holds unsigned mask and 64-bit fmask (fat mask). (ffi_sbit_put, ffi_sbit_get, ffi_ubit_put, ffi_ubit_get): Refer to m.mask. (ffi_fat_sbit_put, ffi_fat_sbit_get, ffi_fat_ubit_put, ffi_fat_ubit_get): New static functions. (ffi_generic_fat_sbit_put, ffi_generic_fat_sbit_get, ffi_generic_fat_ubit_put, ffi_generic_fat_ubit_get): Likewise. (make_ffi_type_struct, make_ffi_type_union): Set up fat mask for bitfields that are wider than int. (ffi_type_compile): Refer to m.mask for the int and unsigned int based bitfields declared with sbit and ubit that don't mention a type. The bit operator now allows int64 and uint64 to be valid types for a bitfield. In this case, the "fat" get and put functions are selected which use 64 bit operations. Thus there is no efficiency impact on non-fat bitfields which continue to use code with 32 bit operands. (ffi_offsetof): Use the bitfield flag in the member's type structure to detect bitfields, rather than the mask.
* ffi: use longlong_t.Kaz Kylheku2022-05-191-4/+8
| | | | | | ffi.c (ffi_init_extra_types): Use longlong_t and ulonglong_t, subject to HAVE_LONGLONG_T. If there is no intmax_t and no longlong_t, don't define intmax-t and uintmax-t.
* ffi: eliminate trivial allocas in bitfield code.Kaz Kylheku2022-05-181-14/+14
| | | | | | * ffi.c (ffi_generic_sbit_put, ffi_generic_sbit_get, ffi_generic_ubit_put, ffi_generic_ubit_get): Replace int-sized alloca with declared int object.
* ffi: alignment bug in undimensioned arrays.Kaz Kylheku2022-05-181-6/+8
| | | | | | | | | | | | | | | | | | | | | | Because the varray behavior for undimensioned arrays was introduced in dubious commit 7880c9b565ab438e1bf0250a967acdbf8d04cb42 in 2017, which used make_ffi_type_pointer to register the type, claiming that the C representation is pointer (which was not true in that commit, nor ever since). As a result, though, undimensioned arrays received the alignment of pointers, rather than deriving it from the element type. Thus (array char) has 4 or 8 byte alignment whereas (array 4 char) correctly has 1 byte alignment. * ffi.c (ffi_type_compile): Use make_ffi_type_array for the two-element array syntax, just like for the dimensioned case with three elements. Then override some of the functions with the varray versions. * tests/017/ffi-misc.tl: Fix the test case which exposed this. In the type (struct flex (a char) (b (zarray char)), the array b must be at offset 1. I didn't notice that the offset of 4 being confirmed by the test case was wrong, but this showed up when running the test case on a platform with 8 byte pointers.
* ffi: bugfix: null terminated string as flexible member.Kaz Kylheku2022-05-171-38/+28
| | | | | | | | | | | | * ffi.c (ffi_char_array_get, ffi_zchar_array_get, ffi_wchar_array_get, ffi_bchar_array_get): Rearrange so that we test for tft->null_term first, and not nelem == 0. If nelem happens to be zero, but we are supposed to decode a null-terminated string, we will do the wrong thing and return the null string. (ffi_varray_in): The body can't be conditional on vec being non-nil, because then we do nothing if we don't have a Lisp object, which means we skip the cases when we should decode a null-terminated array. Now if vec is nil, we must guard against calling ffi_varray_dynsize.
* ffi: bugfix: unions are not unconditionally incomplete.Kaz Kylheku2022-05-171-1/+1
|
* ffi: fix broken on RISC-V.Kaz Kylheku2022-05-101-1/+1
| | | | | | | | | | | | | | * ffi.c (pad_retval): Remove the special case of zero mapping to zero, which occurs when the return type is void. It's not clear whether this is correct at all, on any platform. It hasn't showed up as a problem until now, but on RISC-V, we have hit a situation in which ffi_call writes a value into that zero-byte space for the void return value, causing that to overwrite values[0]: the first element of the argument array. For reasons not understood, this happens in the qsort test cases in which which the callback function performs a block return. It is strange because the block return is handled entirely in the closure dispatching function.
* New FFI types str-s, bstr-s and wstr-s.Kaz Kylheku2022-03-211-1/+24
| | | | | | | | | | | | | | | | | These types actually make it possible to receive a string by pointer from a C function, without trying to free it. It is now possible to write a FFI wrapper for strtol or wcstol, which is done in the new test case. * ffi.c (str_s_s, bstr_s_s, wstr_s_s): New symbol variables. (ffi_init_types): Register the types str-s, bstr-s and wstr-s. (ffi_init): Intern the new symbols. * tests/017/str-s.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi: minor code reordering in initialization.Kaz Kylheku2022-03-201-4/+6
| | | | | * ffi.c (ffi_init_types): Move initialization of str-d type from just before wstr to after, for consistency.
* ffi: after call, process args in reverse order.Kaz Kylheku2022-03-171-11/+10
| | | | | | | | | | | | | | | | | | | | | | | | | In FFI foreign function and closure calls, it behooves us to iterate over the arguments in the opposite order after the call is done. By doing that, any freeing of memory that will be done will be in the opposite order. And that is necessary if some left argument allocates a pointer that is shared with a right argument. An example of this occurs in the strtol function: long int strtol(const char *nptr, char **endptr, int base); Here, the function sets *endptr to a value derived by displacing ptr. If we call this function via FFI, then FFI will allocate memory for nptr. When the function returns, if we destroy that memory before processing *endptr then *endptr contains an invalid pointer. * ffi.c (ffi_call_wrap): In the in pass, iterate arguments in reverse. (ffi_closure_dispatch, ffi_closure_dispatch_safe): Stack-allocate an array for the argument types, so we don't have to pop the list twice, and to allow access in reverse order. In the out pass, iterate arguments in reverse.
* ffi: support intmax-t and uintmax-t types.Kaz Kylheku2022-03-151-0/+18
| | | | | | | | | | | | | * configure: detect intmax_t and place HAVE_INTMAX_T into config.h. * ffi.c (ffi_init_extra_types): register intmax-t and uintmax-t types. If HAVE_INTMAX_T is missing, then make them aliases for longlong and ulonglong. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi: move socket stuff to socket module.Kaz Kylheku2022-02-171-108/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * alloca.h (zalloca): Macro moved here from ffi.c; it's useful to any code that wants to do a zero-filled alloca, and socket.c needs it now. * ffi.c (HAVE_SOCKETS): All includes conditional on HAVE_SOCKETS removed. (zalloca): Macro removed; moved to alloca.h. (ffi_type_struct_checked, ffi_type_lookup): Static functions changed to external linkage. (ffi_type_size, ffi_type_put, ffi_type_get): New functions, used by external module that has incomplete definition of struct txr_ffi_type. (type_by_size): New static array, moved out of ffi_init_extra_types function. (ffi_type_by_size): New function. (ffi_init_extra_types): type_by_size array relocated to file scope. (sock_opt, sock_set_opt): Moved to socket.c, and adjusted to use newly developed external access to needed ffi mechanisms. (ffi_init): Numerous definitions related to sockets removed; these go to socket.c. * ffi.h (struct txr_ffi_type): Declared here now as incomplete type. (ffi_type_struct_checked, ffi_type_size, ffi_type_put, ffi_type_get, ffi_type_lookup, ffi_type_by_size): Declared. * lib.c (init): Call new function sock_init. * socket.c (sock_opt, sock_set_opt): New functions, moved from ffi.c, and slightly adapted to work with external interfaces exposed by ffi.c. (sock_init): New function. This performs unconditional initializations not keyed to the lazy loading lisplib.c mechanism. Here we create the socklen-t FFI type. FFI types lookup doesn't trigger lazy loading, so we do it this way; the alternative would be to introduce lazy load triggering to FFI type lookup, just for this one type. (sock_load_init): All the socket function and variable registrations move here from ffi_init.
* Fix more -fsanitize=implicit-conversion findings.Kaz Kylheku2022-02-141-1/+1
| | | | | | | | | | | | | | | | | | | | | * arith.c (highest_significant_bit): Bugfix: do not pass a negative value to highest_bit, where we will get then get the wrong idea about the number of significant bits in the value, since the __builtin_clz primitives will include the sign bit. We want to complement the all the bits, so that the sign bit will go to zero. We can do this arithmetically by taking the additive inverse (which is the two's complement (which is the complement plus one)) and subtracting one. (ash): Avoid left shifting a negative number in HAVE_UBSAN mode using the same trick as in num_fast. * ffi.c (ffi_swap_u16): Here the shift and or calculation is producing a value beyond 16 bits which we are relying on the implicit conversion back to uin16_t to trim away. We add the cast to uint16_t to make it explicit. * hash.c (equal_hash): Also handle the CHR and NUM cases here via c_u like in eql_hash and eq_hash.
* carray-replace: two overrun bugs.Kaz Kylheku2022-01-131-2/+2
| | | | | | | | | | | | | * ffi.c (carray_replace): In the case when we replace a larger range by a smaller one, when the upper part of the aray shifts down, we are not correctly clearing to zeros the vacated part of the array. The variable whole is a displacement from the base of the array, not from ptr. Secondly, the copying loop must go rom fr to below sn, not below vn; sn is derived from vn but truncated not to go past the array. * tests/017/carray.tl: New file. Several cases here fail before this fix.
* carray: allow t and floating 0 in sub and replace.Paul A. Patience2022-01-121-10/+15
| | | | | * ffi.c (carray_sub, carray_replace): Allow t as from or to value, and also implement the zero's end-of-range floating behavior.
* Copyright year bump 2022.Kaz Kylheku2022-01-111-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, 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, psquare.h, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.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.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 2022.
* Casts have crept into the code not wrapped by macros.Kaz Kylheku2022-01-061-10/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It is against TXR coding conventions to use the C cast notation. The usage creeps into the code. To find instances of this, we must compile using GNU g++, and add -Wold-style-cast via EXTRA_FLAGS. * eval.c (prof_call): Use macro instead of cast. * ffi.c (pad_retval, ffi_varray_alloc, make_ffi_type_union, carray_dup, carray_replace, uint_carray, int_carray, put_carray, fill_carray): Likewise. * itypes.c (c_i64, c_u64): Likewise. * lib.c (cyr, chk_xalloc, spilt_str_keep, vector, cobj_register): Likewise. * linenoise.c (record_undo): Likewise. Also, drop one superfluous cast: wstrdup_fn returns wchar_t *. (flash, edit_insert, edit_insert_str): Use macro instead of cast. * mpi/mpi.c (s_mp_ispow2d): Likewise. * parser.c (lino_getch): Likewise. * rand.c (make_random_state, random_buf): Likewise. * stream.c (generic_get_line, do_parse_mode): Likewise. * struct.c (get_duplicate_supers, call_initfun_chain, call_postinitfun_chain): Likewise. * sysif.c (c_time): Likewise. * tree.c (tr_insert): Likewise.
* ffi: allow enumed bitfield.Kaz Kylheku2022-01-021-22/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (ffi_type_copy): Function moved earlier in file without change. (ffi_type_copy_new_ops): New stati function. (make_ffi_type_enum): Do not create a new type object using cobj; copy the existing base_type, and then tweak its properties, just like what is done with bool. Thus if base_type is a bitfield, the enum will be a bitfield. Add check against doign this to anything but an FFI_KIND_NUM, with the awareness that this does include floating-point types. Since tft is now a copy, we no longer have to copy a number of things from btft. We do set he kind field to FFI_KIND_ENUM. (ffi_type_compile): In the two bitfield cases, we now calculate the mask field for the bitfield type (leaving the shift at zero). The struct or union type into which the bitfield is embedded will still re-calculate this. The reason is that when an (enumed (bit ...) ...) type is defined, it constructs hash tables for converting between the symbolic and numeric values. It calls the put function of the underlying type to test whether each enumeration value can be converted (i.e. is in range). So the bitfield type must have a valid mask at that time, or else it will reject every nonzero value as being out of range for the bitfield. I'm also replacing the max_int variable with bits_int. Since bitfields are restricted to no wider than int, why pretend? * tests/017/ffi-misc.tl: New test cases. * txr.1: Documented.
* Eliminate declaration-after-statement everywhere.Kaz Kylheku2021-12-291-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The use of -ansi doesn't by itself diagnose instances of some constructs we don't want in the project, like mixed declarations and statements. * configure (diag_flags): Add -Werror=declaration-after-statement. This is C only, so filter it out for C++. Also add -Werror=vla. * HACKING: Update inaccurate statements about what dialect we are using. TXR isn't pure C90: some GCC extensions are used. We even use long long if the configure script detects it as working, and some C99 library features. * buf.c (replace_buf, buf_list): Fix by reordering. * eval.c (op_dohash, op_load_time_lit): Fix by reordering. * ffi.c (ffi_simple_release): Fix by reordering. (align_sw_get): Fix empty macro to expand to dummy declaration so a semicolon after it isn't interpreted as a statement. On platforms with alignment, remove a semicolon from the macro so that it requires one. (ffi_i8_put, ffi_u8_put): Fix by reordering. * gc.c (gc_init): Fix with extra braces. * hash.c (hash_init): Fix by reordering. * lib.c (list_collect_revappend, sub_iter, replace_str, replace_vec, mapcar_listout, mappend, mapdo, window_map_list, subst): Fix by reordering. (gensym, find, rfind, pos, rpos, in, search_common): Fix by renaming optional argument and using declaration instead of assignment. * linenoise/linenoise.c (edit_in_editor): Fix by reordering. * parser.c (is_balanced_line): Fix by reordering. * regex.c (nfa_count_one, print_rec): Fix by reordering. * signal.c (sig_mask): Fix by reordering. * stream.c (get_string): Fix by renaming optional argument and using declaration instead of assignment. * struct.c (lookup_static_slot_desc): Fix by turning mutated variable into block local. (umethod_args_fun): Fix by reordering. (get_special_slot): Fix by new scope via braces. * sysif.c (usleep_wrap): Fix by new scope via braces. (setrlimit_wrap): Fix by new scope via braces. * time.c (time_string_meth, time_parse_meth): Fix by reordering. * tree.c (tr_do_delete_spec): Fix by new scope via braces. * unwind.h (uw_block_beg): New macro which doesn't define RESULTVAR but expects it to refers to an existing one. (uw_block_begin): Replace do while (0) with enum trick so that we have a declaration that requires a semicolon, rather than a statement, allowing declarations to follow. (uw_match_env_begin): Now opens a scope and features the same enum trick as in uw_block_begin. This fixes a declaration-follows-statement issue in the v_output function in match.c. (uw_match_env_end): Closes scope opened by uw_match_env_begin. * unwind.c (revive_cont): Fix by introducing variable, and using new uw_block_beg macro. * vm.c (vm_execute_closure): Fix using combination of local variable and reordering.
* ffi: implement in-semantics for carray, cptr.Kaz Kylheku2021-10-241-5/+68
| | | | | | | | | | | | | * ffi.c (ff_cptr_in, ffi_carray_in): New static functions. (ffi_type_compile): Wire in new functions for dynamically compiled cptr and carray types. (ffi_init_types): Also, wire in ffi_cptr_in function for the non-parametrized cptr type. (carray_set_ptr): New function. * ffi.h (carray_set_ptr): Declared. * txr.1: Documented.
* ffi: take advantage of hardware unaligned access.Kaz Kylheku2021-10-201-0/+11
| | | | | | | | | * ffi.c (align_sw_get, align_sw_end, align_sw_put_end, align_sw_put): On Intel, PowerPC and also on ARM if certain compiler options are in effect (set by the user building TXR, not us), define these macros to do nothing. This shrinks and speeds up all the functions which use these macros for handling unaligned accesses.
* ffi: fix broken range checks in enumed type.Kaz Kylheku2021-10-091-25/+22
| | | | | | | | | | | | | Reported by Paul A. Patience. * ffi.c (make_ffi_type_enum): Do not use the cnum native type for doing the member value calculations. Work with Lisp numbers, and verify their range by passing them into the put function of the underlying integer type. Duplicated code is merged, too. * tests/017/ffi-misc.tl: New tests. Two 64 bit ones fail due to conversion bugs.
* ffi: remove useless locals from enum constructor.Kaz Kylheku2021-10-091-8/+1
| | | | | * ffi.c (make_ffi_type_enum): the variables lowest, highest and count do not serve any purpose; they are hereby removed.
* ffi: insufficient format args in enum error handling.Kaz Kylheku2021-10-091-2/+2
| | | | | * ffi.c (make_ffi_type_enum): Add missing argument to two uw_throwf calls. Reported by Paul A. Patience.
* ffi: C++ upkeep.Kaz Kylheku2021-10-081-3/+3
| | | | | | * ffi.c (sock_opt, sock_set_opt): Fix a few integer conversions to use convert (mapping to static_cast) rather than coerce (reinterpret_cast).
* exceptions: fix leftover uw_throwfs with errno.Paul A. Patience2021-10-041-4/+4
| | | | | | * ffi.c (mmap_wrap, mmap_op): Switch to uw_ethrowf. * sysif.c (getresgid_wrap): Same.
* ffi: add cptr-carray function.Paul A. Patience2021-10-021-0/+9
| | | | | | | | | | | * ffi.c (cptr_carray): New function. (ffi_init): Register cptr-carray intrinsic. * ffi.h (cptr_carray): Declared. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* ffi, sockets: add sock-opt and sock-set-opt.Paul A. Patience2021-09-121-0/+94
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The new sock-opt and sock-set-opt functions are wrappers around getsockopt and setsockopt, respectively. All POSIX socket options are registered. Platform-specific options may be added in the future. * ffi.c (sock_opt, sock_set_opt): New functions. (ffi_init): Register sock-opt, sock-set-opt, sol-socket, ipproto-ip, ipproto-ipv6, ipproto-tcp, ipproto-udp, so-acceptconn, so-broadcast, so-debug, so-dontroute, so-error, so-keepalive, so-linger, so-oobinline, so-rcvbuf, so-rcvlowat, so-rcvtimeo, so-reuseaddr, so-sndbuf, so-sndlowat, so-sndtimeo, so-type, ipv6-join-group, ipv6-leave-group, ipv6-multicast-hops, ipv6-multicast-if, ipv6-multicast-loop, ipv6-unicast-hops, ipv6-v6only, tcp-nodelay. * lisplib.c (sock_set_entries): Add sock-opt and sock-set-opt. * stdlib/socket.tl (sock-opt): Define as syntactic place. * tests/014/socket-misc.tl: New cases, for sock-opt. (set-and-get): New macro. * txr.1: Documented. Also, mention that sock-bind enables so-reuseaddr. * stdlib/doc-syms.tl: Updated.
* mmap: fix typo in error message.Paul A. Patience2021-09-111-1/+1
| | | | * ffi.c (mmap_op): mmaped -> mmapped.
* gcc11: warnings related to struct args allocation..Kaz Kylheku2021-09-081-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As reported by Paul A. Patience, GCC 11 warns about situations in a few places where we do args_decl(args, 0) to allocate an absolutely empty argument list object. (This by the way, is only done in places where we are absolutely sure that the function we call will not be accessing the arguments. The usual rule is that there have to be at least ARGS_MIN arguments allocated, currently 4, and code relies on that being the case! So the places which call args_decl(args, 0) are coded carefully, checking that args is not passed anywhere where ARGS_MIN space is required.) Anyway, in the 0 case, the val arg[1] member of struct args is not allocated at all, because we call alloca(offsetof (struct args, arg)). Now GCC 11 notices this and complains that accesses to the other members like args->fill or args->list are using a struct that has not been entirely allocated. This, even though those members lie entirely within the allocated area. The fix for this is two faceted. Firstly, on C99, this diagnostic goes away if we make one simple change: declare the arg array as a flexible array member: val arg[]. However, we still support C90 in maintainer mode. So in maintainer mode, we stick with the 1. But we ensure that the places which call args_decl(args, 0) will pass 1 instead of 0, so the whole structure is allocated. * lib.h (FLEX_ARRAY): New macro: empty definition in C99 or later, otherwise 1. * args.h (struct args): Declare the size of the arg member using the new FLEX_ARRAY macro from lib.h. (ARGS_ABS_MIN): New macro, the absolute args minimum: zero in C99 mode, 1 in maintainer C90 mode. * ffi.c (ffi_struct_in, ffi_struct_get, make_zstruct): Use ARGS_ABS_MIN instead of 0 when preparing dummy args for make_struct call. * struct.c (struct_from_plist, struct_from_args, make_struct_lit): Use ARGS_ABS_MIN instead of zero when preparing dummy args for make_struct_impl or make_struct call.
* ffi: add socklen-t type.Paul A. Patience2021-09-061-0/+9
| | | | | | | | | | * ffi.c: Include <sys/socket.h> if we HAVE_SOCKETS. (ffi_init_extra_types): Initialize socklen-t type if we HAVE_SOCKETS. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* 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.