summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* 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.
* poll: allow execution of async signal handlers.Kaz Kylheku2020-04-231-8/+7
| | | | | | | * sysif.c (poll_wrap): Allocate poll array using alloca so it will be disposed of naturally if an exception occurs. Place sig_save_enable and sig_restore_disable around poll call to allow non-deferred handler execution.
* sockets: connect bugfix and use poll in preference to select.Kaz Kylheku2020-04-232-37/+73
| | | | | | | | | | | | | | | * configure: cosmetics: change HAVE_SYS_SELECT to HAVE_SELECT, and log that the function rather than the header is being detected. * socket.c (fd_timeout): New function, implemented using poll or select. (to_connect): select logic replaced with fd_timeout. Bug fixed: connect requires polling for writability, not readability. If poll and select are not available, ignore timeout argument. (sock_accept): Use fd_timeout; fall back on non-timed-out accept if poll or select not available.
* ifa: fix broken/invalid test case.Kaz Kylheku2020-04-232-4/+7
| | | | | | | | | | | | | | | | | | * tests/012/ifa.tl: The "ambiguous" test case is not ambiguous at all. The reason it was yielding :error previously was not due to the ifa macro identifying an ambiguity but due to the funcion < not accepting nil arguments. Since < now does accept nil arguments, this test broke. Fixing this test, and adding one that tests for the ambiguous case: multiple it-candidates being rejected by ifa at expansion time. * tests/common.tl (vtest): This macro requires maintenance. To test for expansion-time failure, we must use expand, not just macroexpand. In this case, the (ifa ...) macro call is wrapped in a (let ...) so macroexpand won't do it. Secondly, the expected value is an quote expression that must be evaluated if we need its value in vtest itself. Otherwise it won't compare equal to :error, since it is actually (quote :error).
* Remove unnecessary #include directives.Kaz Kylheku2020-04-2225-54/+0
| | | | | | | | | | Time for some spring cleaning. * args.c, arith.c, buf.c, cadr.c, chksum.c, debug.c, ftw.c, gc.c, gencadr.txr, glob.c, hash.c, lisplib.c, match.c, parser.c, parser.l, parser.y, rand.c, signal.c, stream.c, strudel.c, syslog.c, tree.c, unwind.c, utf8.c, vm.c: Numerous unnecessary #include directives removed.
* mpi: remove dubious MP_DEBUG cruft.Kaz Kylheku2020-04-223-17/+0
| | | | | | | | | | | | | The MP_DEBUG macro controls the visibility of definitions that are not used anywhere. * mpi/mpi-config.h (MP_DEBUG): Removed. * mpi/mpi.c (DIAG): Macro and surrounding section controlled by #if MP_DEBUG removed. * mpi/mpi.h (MP_IOFUNC): Definition controlled by MP_DEBUG removed.
* arith: move c_unum and unum declaration into lib.hKaz Kylheku2020-04-228-8/+2
| | | | | | | | | | | | | | | | The c_unum and unum functions are fairly often needed and and are closely related to c_num and num, which have always been declared in lib.h even though they live in arith.c. Files not doing arithmetic are including "arith.h" just for the sake of c_num or unum. * arith.h (c_unum, unum): Declarations removed. * lib.h (c_unum, unum): Declarations moved here. * chksum.c, debug.c, stream.c, strudel.c, sysif.c, vm.c: These files no longer require #include "arith.h" as a result, which is therefore removed.
* printer: add package prefix on symbols with zero-length name.Kaz Kylheku2020-04-221-0/+3
| | | | | | * lib.c (symbol_needs_prefix): If the name is an empty string, the symbol needs a prefix. Otherwise it disappears in the output.
* tags: bugfix: file-opening logic in simulated load.Kaz Kylheku2020-04-221-1/+2
| | | | | | | | * tags.tl (fake-load): When the file doesn't end in .tl, we are only trying it with the .tl suffix, without falling back on the original name. And we are doing that in an ignerr, so the nil object will be used as a stream. This cause stdin to be read when the function encounters a dangling symlink.
* parser: C++ cast fix.Kaz Kylheku2020-04-221-1/+1
| | | | | * parser.l (YY_INPUT): Must use coerce because we are changing from char * to unsigned char *.
* parser: batched read operation for speed.Kaz Kylheku2020-04-223-7/+14
| | | | | | | | | | | | | | | | As a result of this change, the startup time is reduced. The command txr -e '(compile-toplevel nil)' shows a 54% speedup: around 110 milliseconds down from around 170. Programs that read large amounts of TXR Lisp data will benefit. * parser.l (YY_INPUT): Use new get_bytes function instead of get_byte to read a buffer at a time. * stream.c (get_bytes): New function. * stream.h (get_bytes): Declared.
* streams: put_buf and fill_buf become lower-level.Kaz Kylheku2020-04-224-46/+78
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this commit, the put_buf and fill_buf stream virtual functions are changed to operate directly on a low-level buffer, rather than a stream. This will allow these functions to be used for improving the performance of I/O operations that are not related to buffer objects. * stream.h (struct strm_ops): Change type signature of put_buf and fill_buf members. The lengths and iszes are ucnum. The return value is ucnum. The buffer is passed as a pointer and length, rather than a buffer object. * stream.c (unimpl_put_buf, unimpl_fill_buf, generic_put_buf, generic_fill_buf, stdio_put_buf, stdio_fill_buf, delegate_put_buf, delegate_fill_buf): Adjust to new interface. (put_buf, fill_buf, fill_buf_adjust): Pull the poitner and size from the buffer and pass those down to the virtual functions rather than the buffer itself. Convert ucnum return value to val. * strudel.c (strudel_put_buf, strudel_get_buf): The struct delegate interface doesn't change. The put-buf and fill-buf methods still operate on buffer objects. To glue that with the new low-level interface, we use the init_borrowed_buf trick that is was first used in ffi.c: temporary buf objects are efficiently allocated on the stack, pointing to the same memory that is coming down from the stream operation. * txr.1: Document the new restrictions on the buf argument of the put-buf and fill-buf stream delegate methods. Since the buf not a heap object, it cannot be used after the method returns.
* Reduce consing in /= function.Kaz Kylheku2020-04-211-10/+25
| | | | | | | | * arith.c (numneqv): Do not unconditionally cons all the arguments into a list. If the arguments structure has no trailing list, then just loop over the arguments in the arg array. Only cons all the arguments into a list if there is a trailing list.
* Extending =, <, >, <= and >= to work on sequences.Kaz Kylheku2020-04-212-16/+207
| | | | | | | | | | | | | * arith.c (seq_nueq, seq_lt, seq_le): New static functions. (gt, lt): Handle sequences via seq_lt. (ge, le): Handle sequences via seq_le. (numeq): Handle sequences via seq_eq. * txr.1: Documented, and also added missing documentation about comparison of ranges by these functions, fixed mistake in the syntax (> listed twice) and added some notes about symmetry of > >= and < <=.
* seq_info: bugfix: uninitialized type field.Kaz Kylheku2020-04-201-1/+1
| | | | | | | | | | | * lib.c (seq_info): Ensure the type field in the returned structure is inintialized. We are neglecting this when the type is COBJ, initializing only the kind field. This makes the in function behave unreliably over arguments that are hash tables, or vector-like sequences (objects with a length function or the carray type). Several other functions will behave unreliably for vector-like sequences: reverse, find, rfind, pos, rpos and tprint.
* compiler: avoid wasteful substitution via %bin-op%.Kaz Kylheku2020-04-201-1/+1
| | | | | | | | * share/txr/stdlib/compiler.tl (%bin-op%): Specify default value argument to relate so that arguments not found in %nary-ops% will match to nil. Otherwise the code in comp-fun-form rewrites all two-argument function calls through this relation, resulting in a bit of wasted consing.
* compiler: bugfix: constant test in 2 or 3 arg if.Kaz Kylheku2020-04-201-2/+2
| | | | | | | | | | | | | | | | * share/txr/stdlib/compiler.tl (compiler comp-if): The two and three argument cases assume that if the test is a constant expression, the consequent "then" should be unconditionally taken. The correct behavior is to evaluate the constant, which could yield nil. I checked which library code changes after this fix, and found that a number of (defset ...) forms are generating different, shorter code. This is due to (if ',restpar (if (consp ,restpar) ...)) in defset-expander. The intent there was to eliminate the inner if code entirely if respar is nil (there is no rest parameter); due to this bug, the code elimination didn't happen. The behavior is nevertheless correct because the code does nothing if restpar is nil.
* New function: get-line-as-bufKaz Kylheku2020-04-195-2/+60
| | | | | | | | | | | | | | * buf.c (buf_put_bytes, buf_get_bytes): static functions become external. * buf.h (buf_put_bytes, buf_get_bytes): Declared. * stream.c (get_line_as_buf): New fucntnion. (stream_init): Registered get-line-as-buf intrinsic. * stream.h (get_line_as_buf): Declared. * txr.1: Documented.
* Version 236.txr-236Kaz Kylheku2020-04-186-287/+332
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* genvim: work around Vim "contains" bug.Kaz Kylheku2020-04-181-1/+3
| | | | | | | * genvim.txr (tl-sym): Recognize the contains symbol and render it as the string "contain[s]". Vim thinks that contains is reserved a keyword, anywhere in the syn keyword line, and throws an error.
* path-testing functions: accept file descriptor.Kaz Kylheku2020-04-182-5/+5
| | | | | | | * share/txr/stdlib/path-test.tl (do-path-test): Pass all argument types to statfun, except if they are of type stat. * txr.1: Documented.
* configure: simplify shell viability test.Kaz Kylheku2020-04-181-14/+6
| | | | | | | | | | | | | * configure: the golden trick is simply to test whether PS4 contains "+ ". PS2 is not a useful variable, because even crappy old 1980's vintage System V shells set that up. It turns out that Zsh in POSIX mode (when run as /bin/sh) handles configuring and building TXR just fine. And Zsh does set PS4 to "+ " in that mode. However, it does not set PS2, unless run interactively. When run interactively as /bin/sh, Zsh sets PS2 to "> ". So, let us drop the Bash variable tests, and the test for PS2 being "> " and only test PS4.
* configure: include ksh in search.Kaz Kylheku2020-04-181-0/+1
| | | | | * configure: everything works fine with ksh93, so let's add ksh to list of shell to look for.
* configure: detect more good shells.Kaz Kylheku2020-04-171-0/+7
| | | | | | | * configure: There is a clue in the PS2 and PS4 variables. If these are present and have the values "> " and "+ " the shell could be Dash or newer NetBSD Ash, which got PS4 circa 2004. The Solaris XPG shell also has these.
* open-file: fix broken append mode.Kaz Kylheku2020-04-171-0/+2
| | | | | | | * stream.c (w_fopen_mode): Add O_APPEND flag if m.append is set. (do_parse_mode): Set m.notrunc flag for append mode, so O_TRUNC won't be added in w_fopen_mode.
* listener: completion for Unicode identifiers.Kaz Kylheku2020-04-171-2/+4
| | | | | | * parser.c (provide_completions): Recognize U+0080 and higer characters as token constituents, allowing completion to work for symbols which use these characters.
* configure: improve shell search-and-re-execute logic.Kaz Kylheku2020-04-171-16/+46
| | | | | | | | | | | | | | | | | | | | | | | * configure: If we determine we are running on Bash, then do not re-execute. If re-executing, then look for CONFIG_SHELL first, which is an Autoconf convention that some distros rely on. Include dash in the fallback shell list because dash works fine. Include more places in which to look for bash and dash. Uses of txr_shell must be quoted now because it could take on the value of CONFIG_SHELL which we don't control. Print a trace message about re-executing. Print the message about which shell we are running on earlier, before parsing the variables and printing the baner. Since we might not re-execute any more, we might not know the exact name of the shell we are running on. That is difficult and hacky to obtain, so instead we print an alternative message that we are running on the original shell. (gen_config_make): Only generate the SHELL Makefile variable if txr_shell is set. If whatever shell we were run with is good enough for the configure script, it's good enough for Makefile recipes. Likely, the configure script was executed directly, so that /bin/sh is that default shell and that is what GNU Make will use by default.
* regex: duplicate character range crash fix.Kaz Kylheku2020-04-171-6/+12
| | | | | | | | | | * regex.c (L1_fill_range, L2_fill_range, L3_fill_range): Bug: when the arguments ch0 and ch1 indicate that a block is to be filled entirely, we assume that the pointer is either null or else a pointer to an allocated block, either of which we can free and replace with a -1 pointer to indicate a full block. However the pointer may already be -1, in which case we wrongly pass that to free(). We must check for it.
* unicode: wide character upkeep 3.Kaz Kylheku2020-04-171-0/+7
| | | | | | * regex.c (create_wide_cs): Add some Emoji ranges from Plane 1, loosely following the Unicode 13.0 data given in https://en.wikipedia.org/wiki/Emoji.
* unicode: wide character upkeep 2.Kaz Kylheku2020-04-171-2/+2
| | | | | | * regex.c (create_wide_cs): Extend over the entire supplementary ideographic plane U+2XXXX and the tertiary one: U+3XXXX.
* unicode: character width upkeep.Kaz Kylheku2020-04-171-5/+4
| | | | | | | | | | | | | | | | | Updating the regex for matching code points corresponding to wide and full width characters, with regard to the old 1998 document: http://www.unicode.org/reports/tr11-2/ More to follow. I neglected to comment where the original data came from, and neglected to comment it. In some cases it has more coverage than the 1998 document; in some cases less. * regex.c (create_wide_cs): Extending the 1100-115F range to 11F9 to cover all of Korean Hangeul. Replace two occurrences of 3000-303E with one 3000-303F. Merge 3250-32FE with 3300-4DB5, and extend to 4DBF. Add private use range E000-E757.
* open-file: allow async signals.Kaz Kylheku2020-04-161-14/+20
| | | | | | | | | | | | | | | | With this patch, if open-file blocks (for instance on a FIFO or device), it is interruptible. In the listener, the operation can be aborted with Ctrl-C now. * stream.c (w_fopen_mode): If we HAVE_FCNTL, then handle all file opening via open + fdopen, rather than fopen. On platforms where we use fopen, interruptibility won't work. The fopen function cannot be abandoned via an exception thrown from a signal handler because it performs memory allocation. Because we need a temporary UTF-8 string to do the open, which might be abandoned by a signal, let's move the string to the stack via alloca, and free the original, so we don't have to set up unwinding to free it.
* New function: touch.Kaz Kylheku2020-04-153-1/+39
| | | | | | | | | * lisplib.c (copy_file_set_entries): Register autoload for touch. * share/txr/stdlib/copy-file.tl (touch): New function. * txr.1: Documented.
* New "n" open file mode option: nonblocking.Kaz Kylheku2020-04-153-9/+19
| | | | | | | | | | | | | | | | | * stream.c (w_fopen_mode): Special handling via open and fdopen is now required if either the m.notrunc or m.nonblock is present. Since m.nonblock is just an option that can be used with any open mode, we must handle the mode flags more fully, to generate more possible combinations of open flags. (do_parse_mode): Check for 'n', and set nonblock flag. * stream.h (struct stdio_mode): New member, nonblock. (stdio_moe_init_blank, stdio_mode_init_r, stdio_mode_init_rpb): Update initalizers to set nonblock to zero. * txr.1: Documented, and also added missing i option to the mode string syntax grammar summary.
* streams: bugfix: "m" mode: use 0666 in open.Kaz Kylheku2020-04-151-1/+1
| | | | | | | | | * stream.c (w_fopen_mode): When the "m" mode is present such that we resort to a combination of POSIX open and fdopen, we must use the 0666 mode for open, not 0777. This will create a file with execute permissions, if the umask doesn't block it. It went unnoticed because umask is usually 022.
* txr-parse: release deferred warnings.Kaz Kylheku2020-04-141-2/+11
| | | | | | | * parser.c (txr_parse): The function must ensure that deferred warnings are released, if it is not wrapped in a larger translation unit. If *load-recursive* is false, we release the warnings after the parser.
* load: release warnings before throwing exception.Kaz Kylheku2020-04-142-4/+7
| | | | | | | | | | | | * eval.c (load): When we parse TXR code, let's not release warnings unconditionally. Let's do that when throwing an exception though due to parse errors. If the load is not recursed it will release warnings at the bottom of the function. * match.c (v_load): Consistently with load, release deferred warnings if throwing exception due to the parse having failed.
* unwind: regression: signal mask restoring.Kaz Kylheku2020-04-141-1/+0
| | | | | | | | | | | | | | | | | | | | We have a regression introduced in TXR 230, as part of the bugfix for the extended_setjmp crash caused by PIE executables. This bug (for instance) causes signal handling to misbehave after TXR handles a single asynchronous signal. In the REPL, if the user interrupts a (usleep ...) operation with Ctrl-C, it is afterward not possible to issue any more Ctrl-C interrupts, asynchronous or not. The reason is that an asynchronous interrupt directly throws an exception out of the signal handler. Then the botched restoring of the signal mask in extjmp_restore will install the wrong signal mask, causing the signal to be blocked. * unwind.c (extjmp_restore): Remove stray statement that clobbers the saved mask of blocked signals. This was accidentally been copy-and-pasted from extjmp_save.
* sockets: missing shut-rd, shut-wr, shut-rdwr.Kaz Kylheku2020-04-133-1/+5
| | | | | | | | | | | | * socket.c (sock_load_init): Register documented but completely missing intrinsic variables shut-rd, shut-wr, shut-rdwr. * lisplib.c (sock_set_entries): Register autoload for shut-rd, shut-wr, shut-rdwr. * txr.1: In sock-shutdown description, fix shut-rw typo that should be shut-wr.
* streams: fix reversed order of items in error diagnostic.Kaz Kylheku2020-04-131-2/+2
| | | | | | | * stream.c (stdio_maybe_error): We want to say "error whatever-ing #<stream ....>": the action has to come first, and from the format specifiers being ~a ~s, that was clearly the intent.
* open-socket-pair: bugfix.Kaz Kylheku2020-04-131-5/+7
| | | | | | * socket.c (socketpair_wrap): Don't close descriptors unconditionally in unwind case; only if the list to be returned has not been created.
* bugfix: definitions must trigger autoload.Kaz Kylheku2020-04-132-1/+8
| | | | | | | | | | | | | | When a function, macro, variale, symbol macro or struct is being defined, we must trigger any auto-load for that symbol. If the definition is redefining a library symbol, then if the autoload is later triggered, it will surprisingly reinstate the library definition. * eval.c (rt_defvarl, op_defsymacro, rt_defsymacro, rt_defun, rt_defmacro): Insert calls to lisplib_try_load against the symbol being defined. * struct.c (make_struct_type): Likewise.
* ignwarn: handle warnings with multiple args.Kaz Kylheku2020-04-131-1/+1
| | | | | | * share/txr/stdlib/except.tl (ignwarn): Warnings have more than one argument; the handling lambda must take variable args.
* Version 235.txr-235Kaz Kylheku2020-04-126-81/+133
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* txr: spurious retention in @(next).Kaz Kylheku2020-04-111-3/+16
| | | | | | | | | | | | | | * match.c (mf_file_lazy): New static function. The lazy list is created here and stored directly into the data field of the context structure. Function is marked NOINLINE because on an older system with gcc 4.4.5, it didn't solve the problem. We need the function to have a stack frame so any spurious copies of the linked list go into a frame that disappears when the function returns. (v_next_impl): Use mf_file_lazy instead of mf_file_data. (open_data_source): Also make this function INLINE just in case because it contains calls to lazy_stream_cons.
* txr: avoid by-value match_files_ctx passing.Kaz Kylheku2020-04-111-117/+144
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Passing the match_files_ctx structure by value looks nice in the code, but it is contributing to a long standing false retention issue. This test case runs in constant memory: $ yes | txr -c '@(skip) n' skip scans through the lazy list of "y" lines looking for an "n" that never comes. This version should also run in constant memory, but shows unbounded memory growth. $ yes | txr -c '@(next *stdin*) @(skip) n' This patch doesn't fix it, but it moves things in that direction. * match.c (mf_all, mf_args, mf_data, mf_spec, mf_spec_bindings, mf_file_data, mf_from_ml): Take pointer to structure which to initialize and return that pointer, instead of initializing a local structure and returning it by value. (match_files): Take pointer to context rather than copy. (h_call, do_match_line, v_fuzz, v_block, v_next_impl, v_parallel, v_gather, v_collect, v_bind, hv_trampoline, v_try, v_fun, v_if, v_assesrt, v_load, v_call, match_filter, match_fun, extract): Adjust to by-pointer context handling of mf_all, match_files and other functions.
* hash: bugfix: spurious retention in weak processing.Kaz Kylheku2020-04-112-38/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The algorithm for weak processing is not correct. In hash_mark, we must must simply not mark any of the entries, keys or values, of a weak table regardless of what type of weak table it is. If we do that, we cause spurious retention in situations that the keys and values have some kind of link together other than through the table. For instance, suppose keys are weak, but values happen to have references to keys. If we mark the values, we mark the keys and nothing will expire from the table. Such a situation happens in stream_parser_hash, which associates streams with parsers, and has weak keys. Parsers have references to streams. So entries in the hash never expire. Any stream that gets a parser is retained forever. The weak hashes used for binding in eval.c (top_vb, ...) are also affected, because the key is some symbol <sym> and the value is (<sym> . <val>). The key is weak, but the value references the sym. So these hashes also will not expire the keys: unreachable variable bindings will stick around. * hash.c (hash_mark): If a hash table has weak keys, values, or both, then only mark its vector if the count is zero. If it has one or more entries, we just add it to the reachable_weak_hashes list to be processed in do_weak_tables.
* gc: add argument to sys:gc.Kaz Kylheku2020-04-102-3/+16
| | | | | | | | * gc.c (gc_wrap): Takes argument for requesting full garbage collection. (gc_late_init): Update registration of gc intrinsic. * txr.1: Documented.
* parser: eliminate struct list_accum.Kaz Kylheku2020-04-102-47/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | As a final round of this recent work, we observe that since the accumulator structure has been reduced to two members, we can eliminate one of them by using a cons cell as the accumulator, and threading the second value through the cdr. That is to say, the listacc grammar rule's semantic value will now be the tail cons of the list being constructed. The cdr of this cons will, temporarily, be a back pointer to the head (making the list temporarily circular). The n_exprs reduction will fix this up; it will put the correct terminating atom in place of the head (either nil, or the dotted item if there is one), and yield the head as the semantic value. * lib.h (struct list_accum): Removed. (Thus, finding a better home for this would, after all, have been a waste of time). * parser.y (lacc, splacc): Static functions removed. (union YYSTYPE): lacc membber removed. (n_exprs): Adjust to new semantic value coming from listacc. (listacc): Now of type val again. Yields pointer to tail cons as semantic value, whose cdr points to the head of the list.