summaryrefslogtreecommitdiffstats
path: root/lisplib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-09-09 06:52:02 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-09-09 06:52:02 -0700
commit229de13e3ddaaf1ead3f0c09be87abcd97be61bf (patch)
tree07569d8036f2de7b8fa7b7c2b7d9136acaf5bb08 /lisplib.c
parentb2739251281d7f6ef4d30164101bdf2a8d537a72 (diff)
downloadtxr-229de13e3ddaaf1ead3f0c09be87abcd97be61bf.tar.gz
txr-229de13e3ddaaf1ead3f0c09be87abcd97be61bf.tar.bz2
txr-229de13e3ddaaf1ead3f0c09be87abcd97be61bf.zip
Bugfix: incorrect appending to improper lists.
The list building framework underlying the list_collect_decl macro has a flaw: if the current list ends in an non-nil terminating atom, and the tail pointer isn't directly aiming at that atom, then a subsequent operation to add an item or append a suffix will just overwrite the atom. The correct behavior is to execute the same logic as if the tail pointer pointed at that atom on entry into the function: switch on the type of the atom, and append to it, if possible, or else throw an error. Thus, for instance, (append '(1 2 3 . 42) '(4)) wrongly returns (1 2 3 4), instead of producing an error. The 42 atom has disappeared. The example (append '(1 2 . "ab") "c") -> (1 2 . "abc") given in the man page doesn't work; it yields (1 2 . "c"). * lib.c (list_collect, list_collect_nconc, list_collect_append, list_collect_revappend, list_collect_nreconc): In the cases when the current tail object is a CONS and LCONS, and we move the tail, we must branch backwards and process the tail atom as if the tail had been that way on entry into the function. Doing this with a tail call would be nice, but in some of the functions, we hold a local resource already, so we simulate a local tail call by updating the tailobj variable and doing a backwards goto.
Diffstat (limited to 'lisplib.c')
0 files changed, 0 insertions, 0 deletions