summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Version 243txr-243Kaz Kylheku2020-09-016-425/+453
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* oop: add tests for diamond problem.Kaz Kylheku2020-09-012-2/+23
| | | | | | | | * tests/012/oop-mi.tl (grand, base1, base2): Add list slot li to grand, targeted by :init and :fini handlers in all three structs. Added test case which triggers finalization. * tests/012/oop-mi.expected: Updated.
* tags: address small issue with tag lookup.Kaz Kylheku2020-09-013-8/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Exuberant Ctags uses the full content of one line as the key to find a tag. A function declaration that is split into multiple lines can have a first line which is identical to the definition, as in: static int add(int a, int b); static int add(int a, int b) { return a + b; } Here, the search key which ctags uses for the add function is "static int add(int a,", taken from the definition. But it's exactly the same as a the first line of the declaration, and that is what Vim jumps to for that tag. A few function declarations in TXR have this issue. * eval.c (expand_params_rec, do_eval): Make the first line of the forward declaration different from the first line of the definition. * match.c (mf_all): Likewise. * struct.c (make_struct_type_compat): Likewise.
* New function: reject.Kaz Kylheku2020-09-014-0/+117
| | | | | | | | | | | * eval.c (eva_init): Register reject intrinsic. * lib.c (appendl): New static function. (reject): New function. * lib.h (reject): Declared. * txr.1: Documented.
* doc: minor flaw in select syntax markup.Kaz Kylheku2020-08-301-1/+1
| | | | * txr.1: remove space between | and "function".
* doc: rewrite multiple inheritance intro paragraph.Kaz Kylheku2020-08-281-9/+3
| | | | | | * txr.1: Simplify the paragraph, and eliminate the introduction of the unnecessary term "strict single inheritance".
* doc: :fini also affected by diamond problem.Kaz Kylheku2020-08-281-4/+25
| | | | | | * txr.1: Document that the change in behavior to initialize a duplicate base just once also affects :fini, not only initialization. Example expanded.
* OOP: use chk_calloc for objects.Kaz Kylheku2020-08-271-9/+4
| | | | | | | * struct.c (make_struct_impl, make_lazy_struct): Use chk_calloc instead of chk_malloc for allocating objects. Remove the loops that initialize slots to nil. Remove the initialization of the lazy flag to zero.
* OOP: bugfix: lazy object uninitialized dirty flag.Kaz Kylheku2020-08-271-0/+1
| | | | | | * struct.c (make_lazy_struct): Initialize dirty flag to 1, as required by the documentation, since all newly instantiated objects are dirty.
* OOP: optimization in dupe base check.Kaz Kylheku2020-08-271-7/+7
| | | | | | | | | | | | | | | | | | | | Hypothesis: the majority of struct types will not be used as inheritance bases, and most of those that are bases will not be appear as duplicate bases. If we put a flag into a type which indicates that it has been used as a duplicate base, we can check that flag to do less work when initializing an object. * struct.c (struct struct_type): New flag, dupe. (get_duplicate_supers): Each time we find a duplicate supertype, we set its dupe flag. (make_struct_type): Allocate the struct type with chk_calloc instead of chk_malloc, so the flag is initialized to zero. Remove initializations of some members to zero: those of nslots, ntslots, stslot and spslot. (call_initfun_chain, call_postinitfun_chain): Don't bother search for st in the root's array of duplicates if st is not marked with the dupe flag.
* structs: deal with initialization diamond problem.Kaz Kylheku2020-08-272-13/+201
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Until now it has been documented that if a struct type inherits a supertype two or more times, then the supertype initialization occurs that many times. This change fixes the behavior: bases are initialized once. * struct.c (struct struct_type): New members, ndsupers, dsus providing a flat array for tracking duplicate supertypes. (get_all_supers, get_duplicate_supers): New static functions. (make_struct_type): Calculate the duplicate supers, and store them in the dsus array. Under 242 or lower compat mode, pretend there are duplicates, which defeats the duplicate detecting mechanism (struct_type_destroy): Free the dsus array. (call_inittfun_chain, call_postinitfun_chain): Take new arguments: the root type from which the recursion started, and a stack-allocated bit vector indicating which duplicate bases have already been initialized. If the given type appears in the duplicate bases list of the root type, and its bit is already set, then skip all initialization for it. Otherwise set its bit and proceed. (alloc_seen, clear_seen): New macros to help with allocating the bitvector of duplicate bases. (make_struct_impl, lazy_struct_init, reset_struct): Use alloc_seen and clear_seen macros to manage the bitvector of duplicate bases for calling call_initfun_chain and call_postinitfun_chain. * txr.1: Updated doc with new paragraph about duplicated supertypes, and compat note added.
* ffi/doc: bugfixes to bitfield alignment.Kaz Kylheku2020-08-242-22/+24
| | | | | | | | | | | | | | | | | | | | | | | | | 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.
* doc: ffi: struct size with only zero-width field.Kaz Kylheku2020-08-241-1/+2
| | | | | * txr.1: Document that the size of a struct that contains nothing but a zero-width field is zero.
* 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.
* doc: clarify *load-path* treatment under @(load)Kaz Kylheku2020-08-191-1/+3
| | | | | | * txr.1: Make it clear that pure-rel-path-p is applied to the target path coming from the @(load) directive, and not to the value in *load-path*.
* txr: repeat ferrets out Lisp-embedded vars.Kaz Kylheku2020-08-174-46/+87
| | | | | | | | | | | | | | | Gone is the need for :vars to inform @(repeat)/@(rep) about variable references buried in Lisp. * eval.c (expand_with_free_refs): Change to external linkage. * eval.h (expand_with_free_refs): Declared. * parser.y (extract_vars): Handle sys:expr forms, which are embedded Lisp via expand_with_free_refs to uncover their free variables. * txr.1: Redocumented this area.
* txr: identify output repeat vars at parse timeKaz Kylheku2020-08-172-52/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | Up to now the @(repeat) and @(rep) directives have scanned their interior to find output variables. We now hoist that into the parser; the variables are found up-front and integrated into the abstract syntax. This work anticipates doing a more proper job of identifying free variables in Lisp expressions. * match.c (extract_vars): Delete static this function here. It moves into parser.y. (extract_bindings): Don't call extract_vars to obtain the variables occurring in the repeat body. Get it as a new argument, occur_vars. (do_output_line, do_repeat): Extract the new occur_vars element of the abstract syntax node and pass it to extract_bindings. * parser.y (extract_vars): New static function, moved here from match.c. (repeat_rep_helper): Scan over each of the repeat subclauses with extract vars. Catenate the resulting lists together and pass through uniq to squash repeated symbols. Then add the resulting vars as a new element of the returned syntax node.
* Remove unnecessary forward declarations.Kaz Kylheku2020-08-172-3/+0
| | | | | | * lib.c (length_proper_list): Forward decl removed. * match.c (do_match_line): Likewise.
* Version 242txr-242Kaz Kylheku2020-08-144-5/+18
| | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise.
* match.c: revert bad commits.Kaz Kylheku2020-08-141-158/+118
| | | | | | | | | | | | | | | | | | | This contains two reverts, folded into one. "txr: spurious retention in @(next)." commit fe1e960389a89f481d46c02aa040fdc762da735f. "txr: avoid by-value match_files_ctx passing." commit 3d7330b827d6e9cc0d9e87edd30388374cb45900. These are dependent. The second of these two (i.e. the one that was done first) is the problematic one. By-reference passing of contexts means contexts become shared objects between callers and callees. But this is incorrect, because mutations are going on, like c->spec = rest(c->spec) or c->data = rest(c->data). These mutations were done under the assumption of safety: that the caller is not affected due to by-value semantics of the entire context.
* doc: listener: undo over history clarifications.Kaz Kylheku2020-08-141-6/+12
| | | | | | * txr.1: Document that all the edits done to a history line are committed as a single undo item when navigating away from it. Clarify some text related to undo over a history line.
* listener: fix completion regression.Kaz Kylheku2020-08-121-1/+1
| | | | | | | | | This problem was was introduced in TXR 239 in commit 1f54ad5cc1d384d0818a6bf6cec20a95ecc5a5ae. The completion for package-qualified symbols and keywords is wonky. * parser.c (find_matching_syms): The first argument to scat is the separator, so we must specify it as nil.
* scanner: use %option never-interactiveKaz Kylheku2020-08-081-24/+2
| | | | | | | | | | | | | | | | | | | | It looks like Flex has a "never-interactive" option which does what the batch option should be doing: it removes the use of isatty. Historically, it was an %option only with no corresponding command-line option; newer Flex has a --never-interactive command line option also. The batch option actually makes very little difference in the output. If never-interactive is used, then the batch option makes no difference. * parser.l (%option): Add never-interactive option, remove batch. (VER, FLEX_VER, YY_NO_UNISTD_H, isatty, no_isatty): Remove all these macros: under the never-interactive option, there are no isatty calls and no inclusion of <unistd.h>.
* Version 241txr-241Kaz Kylheku2020-08-077-1101/+1184
| | | | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated. * protsym.c: Likewise.
* scanner: backport isatty hack to Flex 2.5.x.Kaz Kylheku2020-08-071-1/+18
| | | | | | | | | * parser.l (VER, FLEX_VER): New macros. (isatty): Define the macro differently for Flex 2.5.36 and older, to counteract the skeleton's "extern int isatty(int)" declaration. This involves a dummy global variable. (no_isatty): New dummy global, only under Flex 2.5.36 and older.
* cygwin: bugs in string catenation and splitting.Kaz Kylheku2020-08-071-4/+4
| | | | | | | | | | | | | | | | | | This looks like it originates in June 19, 2019 commit 28c6225fec6ce999806e9c077f08ed0e668646c4, before Version 218. The commit introduced the ability to use a character object as a separator in cat_str and split_str_keep. The implementation was broken as written for Cygwin. This finally showed up for me today as a failure in the new in6addr-str test cases. By chance, I noticed at the same time that tab completion in the listener was acting strangely on packag prefix symbols; that issue also went away with this fix. * lib.c (cat_str, vscat, scat3, split_str_keep): We must use wref on the array initialized using the wini macro, because on Cygwin, the string starts at [1] not [0].
* cygwin: build fixes.Kaz Kylheku2020-08-072-1/+2
| | | | | | | * stream.c (run): Pass self to fds_swizzle. * sysif.c (getpwuid_wrap): Declare self variable and pass to c_num.
* doc: fix under define-option-structKaz Kylheku2020-08-071-1/+1
| | | | * txr.1: Clarifying comma and number agreement.
* Change noreturn to NORETURN.Kaz Kylheku2020-08-0710-44/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The noreturn macro is respelled to harmonize with the upper-case INLINE and NOINLINE. * lib.h (noreturn): Rename to NORETURN. * arith.c (not_number, not_integer, invalid_ops, invalid_op): Declaration updated. * arith.c (do_mp_error): Likewise. * eval.c (eval_error, no_bindable_error, dotted_form_error): Likewise. * eval.h (eval_error): Likewise. * lib.c (unsup_obj, callerror, wrongargs): Likewise. * match.c (sem_error): Likewise. * stream.c (unimpl, unimpl_put_string, unimpl_put_char, unimpl_put_byte, unimpl_get_line, unimpl_get_char, unimpl_get_byte, unimpl_unget_char, unimpl_unget_byte, unimpl_put_buf, unimpl_fill_buf, unimpl_seek, unimpl_truncate, unimpl_get_sock_family, unimpl_get_sock_type, unimpl_get_sock_peer, unimpl_set_sock_peer): Likewise. * struct.c (no_such_struct, no_such_slot, no_such_static_slot): Likewise. * unwind.h (jmp_restore, uw_throw, uw_throwf, uw_errorf, uw_errorfv, type_mismatch): Likewise.
* scanner: use batch mode; nuke isatty calls.Kaz Kylheku2020-08-061-4/+5
| | | | | | | | | | | | | | | | The flex-generated scanner wastefully calls isatty(0) whenever it is initialized, even though we don't read from a stdio stream. Even (read "abc") will call isatty(0), which is unacceptable. Moreover, this happens even if Flex is told to operate in batch mode rather than interactive. With the following change, the isatty calls are gone. Let's switch Flex to batch mode, too. * parser.l: Remove <unistd.h> inclusion. Define isatty as a macro that returns zero. Add the batch option to the scanner.
* scanner: issue with <unistd.h> header.Kaz Kylheku2020-08-031-0/+5
| | | | | | | | | | | | | | | | | | | Flex-generated scanners contain a #include <unistd.h> directive, whose purpose seems to be to ensure that isatty is declared. This #include is in a bad place, long after all our headers have been declared. We define macros in lib.h and elsewhere that can interfere with system headers. The Homebrew distro people have run into this problem on OS/X. Our lib.h defines a "noreturn" macro (that should arguably be named NORETURN, to match the style for INLINE). A "noreturn" macro interferes with __attribute__((noreturn)) syntax in system headers. Our main strategy for not causing that problem is to include all system headers first, before local headers. * parser.l: include <unistd.h> right after "config.h", if HAVE_UNISTD_H is defined. Define YY_NO_UNISTD_H to suppress the flex-generated #include.
* Different banner text for plain mode.Kaz Kylheku2020-07-241-2/+6
| | | | | | * txr.c (banner): In plain mode, indicate that the mode is in effect. Do not suggest any Ctrl-X commands, since they are not recognized.
* New inaddr-str and in6addr-str functions.Kaz Kylheku2020-07-247-2/+435
| | | | | | | | | | | | | | | | | * lisplib.c (sock_set_entries): Register autoload entries for inaddr-str and in6addr-str. Register prefix symbol to be interned. * share/txr/stdlib/socket.tl (sockaddr-in, sockaddr-in6): Both structs get a new member, prefix, defaulting to the respective number of bits in the address. (inaddr-str, in6addr-str): New functions. * tests/014/iaddr-str, tests/014/inaddr-str.expected, tests/014/in6addr-str.tl, tests/014/in6addr-str.expected: New files * txr.1: Documented.
* New sspl function.Kaz Kylheku2020-07-224-1/+17
| | | | | | | | | | | * eval (eval_init): Register sspl, an argument-reversed interface to split-str-set. * lib.c (sspl): New function. * lib.h (sspl): Declared. * txr.1: Documented.
* distat: bugfix: use lstat.Kaz Kylheku2020-07-202-9/+8
| | | | | | | | | | * sysif.c (dirstat): Call lstat_wrap, rather than stat_wrap. This function must report about the directory entry itself, not about what that entry points to if it happens to be a symlink. The d-type member of the dirent structure representing a symlink must be set to dt-lnk. * txr.1: Updated.
* stat, lstat and dirstat now take struct param.Kaz Kylheku2020-07-204-23/+41
| | | | | | | | | | | | | | | * ftw.c (ftw_callback): Pass nil to new parameter of stat_to_struct, to have a new stat struct allocated as before. * sysif.c (stat_to_struct, stat_impl, stat_wrap, lstat_wrap dirstat): New optional parameter that lets caller specify an existing struct object to fill. (sysif_init): Adjust registrations of stat, fstat, lstat and dirstat for new optional parameter. * sysif.h (stat_to_struct, stat_wrap): Declarations updated. * txr.1: Documented.
* doc: add an implementation note for exceptions.Kaz Kylheku2020-07-171-0/+24
| | | | | | * txr.1: Add remarks on the differences between how TXR Lisp and ANSI CL deal with unhandled exceptions/conditions of type error and warning.
* doc: exception handling wording improvements.Kaz Kylheku2020-07-171-9/+19
| | | | | * txr.1: Improved wording and fixed some grammar issues in the the paragraphs that introduce TXR Lisp exception handling.
* More reasonable fallback for self path: revisited.Kaz Kylheku2020-07-141-0/+5
| | | | | | | | | | | | | | | | This partially reverts and reworks commit c5afb01548c5b6bf4ec83373b5e2e09f14690b01 from May 4, 2018. I have no idea why I replaced fallback code which does something quite reasonable: invokes realpath on the value from argv[0]. The commit comment claims that this breaks when the program is not invoked with an absolute path, but how can that be, if realpath is used? * txr.c (get_self_path): Let's keep TXR_INST_PATH, and return that in the case that progname_u8 is null, because of a null argv[0]. Otherwise, let's revert to the original strategy of calling realpath on progname_u8.
* doc: wrong symbol under cptr-buf.Kaz Kylheku2020-07-131-1/+1
| | | | * txr.1: cptr-buf syntax wrongly refers to cptr-obj.
* 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.
* doc: spurious word under Variables.Kaz Kylheku2020-07-131-1/+1
| | | | | * txr.1: "two three" should be three. Found thanks to the keen eyes of Ivor Horton.
* doc: fix some mistakes in ffi-get and ffi-out.Kaz Kylheku2020-07-131-9/+7
| | | | | | * txr.1: Fix repeated "this this", and an an incorrect insinuation that the ffi-get has an obj argument. Rather, it returns an object.
* cptr: new cptr-get and cptr-out functions.Kaz Kylheku2020-07-132-0/+166
| | | | | | | | | | | | | | | | | 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.
* tags: take advantage of weak packages.Kaz Kylheku2020-07-121-1/+1
| | | | | | | * tags.tl (in-anon-package): Pass t to sys:make-anon-package, so the resulting package won't hold on to symbols that the utility isn't interested in, just because it's holding on to other symbols that come from the smae package.
* Support weak semantics in symbol packages.Kaz Kylheku2020-07-124-16/+35
| | | | | | | | | | | | | | | | | | | | | A package is weak if it holds weak references to symbols, meaning that if there are no references to a symbol other than its entry in a weak package, it can be removed from the package and reclaimed by the garbage collector. * eval.c (eval_init): Update registrations for make-package and sys:make-anon-package to reflect new optional argument. * lib.c (make_package_common): New argument weak. If it is true then both the hashes will have weak values. (make_package, make_anon_package): New optional argument weak. (obj_init): Add nil argument to calls to make_package. All the standard packages are regular, not weak. * lib.h (make_package, make_anon_package): Declarations updated. * txr.1: Documented.
* listener: new *-1, *-2 ... *-20 macros.Kaz Kylheku2020-07-115-2/+36
| | | | | | | | | | | | * arith.h (minus_s): Declared. * eval.c (reg_symacro): Changing to external linkage. * eval.h (macro_time_s, reg_symacro): Declared. * parser.c (repl): Bind the *-1 to *-20 symbol macros. * txr.1: Documented.
* Add dirstat function.Kaz Kylheku2020-07-092-24/+130
| | | | | | | | | | | | | | | | | | | This function back-fills the missing d-type information in a dirent on platforms that don't provide d_type in the native dirent. * sysif.c (DT_FIFO, DT_CHR, DT_DIR, DT_BLK, DT_REG, DT_LNK, DT_SOCK): Define all these preprocessor symbols to their Linux values on platforms where DT_DIR is not defined. (DT_UNKNOWN): Make sure this symbol is #undef-d if DT_DIR is not defined, so the corresponding dt-unknown variable does not exist. (dirstat): New static function. (sysif_init): Register dirstat intrinsic. Register dt-fifo and the rest unconditionally now. Changing their order to increasing numeric. * txr.1: Documented.
* Add missing closedir.Kaz Kylheku2020-07-092-3/+57
| | | | | | | | | | | | | * sysif.c (opendir_free): Since d->dir may now be null, avoid calling closedir on it in that situation. Also, set d->dir to null after closedir. (closedir_wrap): New static function. (readdir_wrap): If the d->dir is null, safely treat that as a directory entry not being available; do not pass a null DIR pointer to readdir. (sysif_init): Register intrinsic function closedir. * txr.1: Documented, plus spelling error fix under readdir.