| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (lazy_str_get_trailing_list): Remove the spurious
empty string caused by splitting on the terminator.
Whenever the materialized prefix is not-empty, and there is
a non-empty terminator, the prefix necessarily ends in the
termintator. If we split on the terminator, the list of pieces
ends in in an empty string, which is undesirable.
This has to be subject to compat, unfortunately; it's a
very visible behavior that affects the continuation of
line-based matching after the @(freeform) directive.
* tests/006/freeform-5.txr: With this fix, we no longer have
to match the spurious blank line coming from @(freeform).
* tests/015/lazy-str.tl: New file.
* txr.1: Updated documentation with compat notes. There was
some outright incorrect text describing
lazy-str-get-trailing-list. Also, the lazy-str-force-upto
and lazy-str-force were under-documented. The return value of
the former was not completely described: that it returns t
in the other case when not returning nil. It wasn't mentioned
that the functions observe the limit-count. Moreover, the
exact algorithm for forcing is now documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register pairlis intrinsic.
* lib.c, lib.h (pairlis): New function.
* tests/012/seq.tl: New test cases.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register new intrinsics.
* lib.c, lib.h (subq, subql, subqual, subst): New functions.
* tests/012/seq.tl: New test cases.
* stdlib/optimize.tl (subst): Function removed. The new subst
drop-in replaces this one.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
| |
* lib.c (less_tab_init): Add missing initialization for VEC,
with a priority above CONS: all vectors are greater than
conses. The BUF priority is bumped to 7.
* test/012/less.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* tree.c (tr_insert): New argument for allowing duplicate.
If it is true, suppresses the case of replacing a node,
causing the logic to fall through to traversing right, so the
duplicate key effectively looks like it is greater than the
existing duplicates, and gets inserted as the rightmost
duplicate.
(tr_do_delete_specific, tr_delete_specific): New static functions.
(tree_insert_node): New parameter, passed to tr_insert.
(tree_insert): New parameter, passed to tree_insert_node.
(tree_delete_specific_node): New function.
(tree): New parameter to allow duplicate keys in the elements
sequence.
(tree_construct): Pass t to tree to allow duplicate elements.
(tree_init): Update registrations of tree, tree-insert and
tree-insert-node. Register tree-delete-specific-node function.
* tree.h (tree, tree_insert_node, tree_insert): Declarations
updated.
(tree_delete_specific_node): Declared.
* lib.c (seq): Pass t argument to tree_insert, allowing
duplicates.
* parser.c (circ_backpatch): Likewise.
* parser.y (tree): Pass t to new argument of tree, so
duplicates are preserved in the element list of the #T
literal.
* y.tab.c.shipped: Updated.
* tests/010/tree.tl: Test cases for duplicate keys.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* tree.c (tree_count): New function.
(tree_init): tree-count intrinsic registered.
* tree.h (tree_count): Declared.
* lib.c (length): Support search tree argument via tree_count.
* tests/010/tree.tl: Test cases for tree-count, indirectly via len.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (iter_reset): When we reinitialize the iterator, it can allocate
a new secondary object, e.g. using hash_begin, which is stored into the
iterator. This is potentially a wrong-way assignment in terms of GC
generations and so we must call mut(iter) to indicate that the object
has been suspiciously mutated. We only do this if the iterator has a
mark function. If it doesn't have one, then it isn't wrapping a heap
object, and so doesn't have this issue.
(seq_reset): This has the same issue, and the fix is the same. Since ths
function is obsolescent, we don't bother doing the si->ops->mark check;
we optimize for code size instead.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Issue 1: the seq_iter_init_with_info function potentially allocates
an object via hash_begin or tree_begin and installs it into the
iterator. The problem is that under iter_begin, the iterator is
a heaped object; this extra allocation can trigger gc which pushes the
iterator into the mature generation; yet the assignment in
seq_iter_init_with_info is just a plain assignment without using the set
macro.
Issue 2: when gc is triggered in the above situations, it crashes
due to the struct seq_iter being incompletely initialized. The
mark function tries to dereference the si->ops pointer. Alas, this
is initialized in the wrong order inside seq_iter_init_with_info.
Concretely, tree_begin is called first, and then the
it->ops = &si_tree_ops assignment is performed, which means that if
the garbage collector runs under tree_begin, it sees a null it->ops
pointer. However, this issue cannot just be fixed here by rearranging
the code because that leaves Issue 1 unsolved. Also, this initialization
order is not an issue for stack-allocated struct seq_iters.
The fix for Issue 1 and Issue 2 is to reorder things in iter_begin.
Initialize the iterator structure first, and then create the iterator
cobj. Now, of course, that goes against the usual correct protocol for
object initialization. If we just do this re-ordering naively,
we have Issue 3: the familiar problem that the cobj() call triggers gc,
and the iterator object (e.g. from tree_iter) that has been stored into
the seq_iter structure is not visible ot the GC, and is reclaimed.
* lib.c (iter_begin): reorder the calls so that seq_iter_init_with_info
is called first, and then the cobj to create from it the heap-allocated
iterator, taking care of Issue 1 and Issue 2. To avoid Issue 3,
after initializing the structure, we pull out the vulnerable iterator
object into a local variable, and pass it to gc_hint(), to ensure that
the variable is spilled into the stack, thereby protecting it from
reclamation.
(seq_begin): This function has exactly the same issue, fixed in the
same way.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): nrot, rot intrinsics registered.
* lib.c (nrot, rot): New functions.
* lib.h (nrot, rot): Declared.
* tests/012/seq.tl: New test cases.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register tuples* intrinsic.
* lib.c (tuples_star_func): New static function.
(tuples_star): New function.
* lib.h (tuples_star): Declared.
* tests/012/seq.tl: New test cases.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (make_like): In the COBJ case, recognize an iterator
object. Pull out the underlying object and recurse on it.
This is needed in tuples_func, where make_like will now be
called on the abstract iterator, rather than the actual
sequence object.
(tuples_func): The incoming object is now an iterator, and not
a sequence; we need to handle it with iter_more, iter_item and
iter_step.
(tuples): Instead of nullify, begin iteration with
iter_begin, and use iter_more to test for empty.
In non-empty case, put propagate the iterator thorugh the lazy
cons car field, rather than the sequence.
|
|
|
|
|
|
|
| |
* lib.c (tuples): Check that n argument giving tuple size is a
is a positive integer.
* tests/012/seql.tl: Test case added.
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (less): We cannot direclty access right->s.package
because the right operand can be nil. This causes a crash.
Furthermore, the separate NIL case is wrong. If the left
object is nil, the same logic must be carried out as for SYM.
The opposite operand might have the same name, and so packages
have to be compared. We simply merge the two cases, and make
sure we use the proper accessors symbol_name and
symbol_package to avoid blowing up on nil.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a basic read/print consistency problem. When a symbol
is printed that is anywhere in the fallback list of the
current package, we are dumping it unqualified, even if
it is hidden by a same-named symbol in the current package
itself or such a symbol occurring earlier in the fallback
list.
* lib.c (symbol_needs_prefix): When the to-be-printed symbol
is found in the fallback list, re-scan the current package
for a symbol having the same name, as well as the preceding
nodes in the fallback list. If such a symbol is found, then
the to-be printed symbol must be package-qualified.
* tests/012/syms.expected: New file.
* tests/012/syms.tl: Likewise.
* tests/012/compile.tl: Pull syms into compile job.
* txr.1: Clarify text about this. The existing text's
only reasonable interpretation supports the behavior which
this patch ensures (which is needed on grounds of read/print
consistency) but the text lacks precision.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Using this new function together with env, it's now possible
to save the set of environment variables, clobber it to a
specified set (possibly empty) and then restore it.
Useful for improved security in running child processes.
* lib.[ch] (chk_substrdup_utf8): New function.
* sysif.c (replace_env): New function.
(sysif_init): Register replace-env intrinsic.
* sysif.h (replace_env): Declared.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
| |
* lib.c (cmp_str): Fix self name and use it in uw_throwf call.
|
|
|
|
|
|
|
|
|
| |
* lib.c (si_vec_ops): This must be initialized with
seq_iter_ops_init_nomark, since it uses a cnum index, and not
a val iter; the seq_iter_mark_op will pass the cnum bit
pattern to gc_mark an cause a crash.
(si_null_ops): While we are at it, this should also use
seq_iter_ops_init_nomark, because it->ui.iter is always nil.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Basic idea: when we throw an exception that pertains to a
system error which has an errno code, we can stick the errno
into the memory area of the character string, into the wchar_t
that immediately follows the null terminator. We can do this
because strings track their actual allocation size.
A pair of setter/getter functions to set and retrieve this
value are provided, and all functions in the code which can
set such a code are updated to do so, simply by calling the
newly added uw_ethrowf that drop-in replaces for uw_throwf.
* lib.[ch] (string_set_code, string_get_code): New functions.
* unwind.[ch] (uw_ethrowf): New function.
* eval.c (eval_init): Register string-set-code and
string-get-code intrinsics.
* ftw.c (ftw_wrap): Switch to uw_ethrowf.
* parser.c (open_txr_file): Likewise.
* socket.c (dgram_overflow): Store the ENOBUFS error in errno,
and use uw_ethrowf instead uw_throwf.
(dgram_get_byte_callback, dgram_flush, sock_bind, to_connect,
open_sockfd, sock_connect, sock_listen, sock_accept,
sock_shutdown, sock_timeout, socketpair_wrap): Switch to
uw_ethrowf.
* stream.c (dev_null_get_fd, stdio_maybe_read_error,
stdio_maybe_error, stdio_close, pipe_close, open_directory,
open_file, open_fileno, open_tail, fds_subst,
open_subprocess, open_command, remove_path, rename_path,
tmpfile_wrap, mkdtemp_wrap, mkstemp_wrap): Switch to uw_ethrowf.
* sysif.c (mkdir_wrap, ensure_dir, chdir_wrap, getcwd_wrap,
rmdir_wrap, mknod_wrap, mkfifo_wrap, chmod_wrap, do_chown,
symlink_wrap, link_wrap, readlink_wrap, close_wrap, val
exec_wrap, stat_impl, do_utimes, pipe_wrap, poll_wrap,
getgroups_wrap, setuid_wrap, seteuid_wrap, setgid_wrap,
setegid_wrap, setgroups_wrap, getresuid_wrap, setresuid_wrap,
setresgid_wrap, crypt_wrap, uname_wrap, opendir_wrap,
getrlimit_wrap, setrlimit_wrap): Likewise.
* termios.c (tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap,
tcdrain_wrap, tcflush_wrap, tcflow_wrap): Likewise.
* tests/018/errno.tl: New file.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
| |
* lib.c (string_extend, string_finish): When we update the alloc value
in the string, we should be using num, because the cnum value is not
necessarily in the fixnum range. That's the whole reason we are using
the set macro: because the assigned value could be a heap-allocated
bignum. Which it will never be, if we use num_fast.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register string-finish intrinsic.
* lib.c (string_finish): New function.
* lib.h (string_finish): Declared.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A Boolean optional argument to string-extend indicates whether
this is likely the last call to string-extend, so memory can
be trimmed accordingly.
* eval.c (eval_init): Update string-extend registration.
* filter.c (trie_filter_string): Pass nil for new argument of
string_extend.
* lib.c (str_seq, replace_str,
lazy_str_force, lazy_str_force_upto): Pass nil for new
argument of string_extend.
(rem_impl, remove_if, separate): Pass t for new argument of
string_extend on last iteration, nil otherwise.
(string_extend): Implement new third argument, defaulted to
nil. Switch from chk_grow_vec to the more specific chk_wrealloc,
which simplifies the code.
* lib.h (string_extend): Declaration updated.
* parser.y (litchars): Pass t as last argument of
string_extend since we know syntactically that these
reductions finalize the string.
(restlitchar): Pass nil as the last argument of string_extend,
since we know syntactically that it isn't the last.
* regex.c (scan_until_common): Pass nil for new argument of
string_extend.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register delcons intrinsic.
* lib.[ch] (delcons): New function.
* tests/010/cons.tl: New file.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
| |
* lib.c (seq_iter_init_with_info): The to value in a range
could be a bignum, which we should treat as a bignum range,
rather than blowing up due to calling c_num on that value.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.h (struct seq_iter_ops): New operation, mark.
(seq_iter_ops_init): Default the mark operation to
seq_iter_mark_op.
(seq_iter_ops_init_nomark): New macro.
* lib.c (seq_iter_mark_op): New static function.
(si_range_cnum_ops, si_range_chr_ops, si_rev_range_cnum_ops,
si_rev_range_chr_ops, si_chr_ops): Initialize with
seq_iter_ops_init_nomark so that the iterator has no mark
operation. All other iterator types have the above new static
function as their mark op.
(seq_iter_mark): Simplified: if the iterator has a mark op,
call it.
(seq_next, iter_step): If the iterator has a mark op, that
means that the seq_get operation is likely replacing one heap
object with another, and so mut(iter) must be called to inform
the garbage collector of the assignment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is needed in preparation for fixing some gc
bugs in iteration in a less hacky way.
* lib.h (struct seq_iter): Members get and peek removed,
replaced by ops pointer.
(struct seq_iter_ops): New struct type.
(seq_get, seq_peek): Call get and peek through ops table.
* lib.c (seq_geti): Refer to get through ops.
(si_null_ops, si_list_ops, si_vec_ops, si_hash_ops,
si_tree_ops, si_range_cnum_ops, si_range_chr_ops,
si_range_bignum_ops, si_range_str_ops, si_rev_range_cnum_ops,
si_rev_range_chr_ops, si_rev_range_bignum_ops,
si_rev_range_str_ops, si_chr_ops, si_num_ops, si_oop_ops,
si_fast_oop_ops): New static structures.
(seq_iter_init_with_info): Point new ops member of seq_iter to
one of the new structures. Remove initializations of get and
peek.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In this patch we allow the s in (sub s from to) and [s from..to]
to be any iterable.
* lib.c (iter_dynamic, sub_iter): New static function.
(generic_funcall): Handle all objects via the sequence case:
ref, sub and all that. Unfortunately, we lose some error
handling at the level of the sub function. But we allow any
iterable to be passed through to sub.
(sub): Handle default case through sub_iter.
* tests/012/iter.tl: New cases.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* lib.c (seq_iter_init_with_info): Allow the iterated object
to be an iterator, in which case a copy of the iterator is
set up.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* lib.c (sub_list): If from is t, then just return nil.
Do not reset it to nil in this case. After this we know from
is not nil; we don't have to check for this inside one
loop. That loop was wastefully iterating over the list in the
from == nil case only to calculate nil.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Ranges like "AAA".."ZZZ" are now possible.
* lib.c (seq_iter_get_range_str, seq_iter_peek_range_str,
seq_iter_get_rev_range_str): New static functions.
(seq_iter_init_with_info): Support string ranges via above
new functions. Range direction test is now done with less
and equal rather than lt and gt.
* tests/012/iter.tl: New file.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (int_str): The problem here is that we are recognizing
and skipping the 0x prefix for all bases. So for instance
(int-str "0x123") produces 123. The correct requirement, and
the intent of the code, is that the C conventions are only
honored if the base is specified as the character #\c. In any
other base, including omitted base defaulting to 10, a leading
zero is just a leading zero, and 0x is a zero followed by the
junk character x. Therefore, if we have any valid base that
isn't #\c, and 0x has been seen, we must return zero. We must
not do this only in the base 16 case.
* tests/016/conv.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Update registrations of lazy-stream-cons
and get-lines with one more optional argument.
* lib.c (simple_lazy_stream_func_nt, lazy_stream_func_nt): New
static functions.
(lazy_stream_cons): Take a new argument, no_throw_close,
defaulting it to nil. When calling close_stream directly, pass
the inverted value of no_throw_close. Choose the new _nt
functions for the lazy list if no_throw_close is true; those
functions pass nil as the second argument of close_stream.
* lib.h (lazy_stream_cons): Declaration updated.
* match.c (v_next_impl, open_data_source, match_fun): Pass
down the nothrow value to lazy_stream_cons, or else nil in
situations when that is not applicable or there is no such
value. Thus the :nothrow feature of v_next will now not only
ensure that there is no exception when opening the stream but
also when closing it. Unusual situations encountered when
the lazy list reads from the stream still throw.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The functions copy-cons, copy-tree, copy-fun and copy-tnode have a
problem. They copy the original object bitwise with a structure
assignment, and then make some adjustments. The problem is that this
inappropriately copies the object's metadata related to gc, such as its
generation number or finalization count. To fix this, we introduce a
copy_obj function, which is a companion to make_obj. This performs a
shallow copy of an object without incorrectly propagating inappropriate
metadata.
* gc.c, gc.h (copy_obj): New function.
* lib.c (copy_fun, copy_cons, copy_tree): Use copy_obj, instead of
make_obj plus structure assignment.
* tree.c (copy_tnode): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The subtypep function has poor requirements, handling only type
symbols. Let's extend it to handle structure type objects.
* lib.c (subtypep): In all cases when an argument is considered to be a
possible structure symbol, and thus subject to find_struct_type,
consider whether it already is a struct type, and just take it as-is.
* tests/012/type.tl: New tests.
* txr.1: Updated.
|
|
|
|
|
| |
* lib.c (remql): Correct the rem_impl call's name argument from "remq"
to "remql".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Hash tables with weak keys and values now support a choice of both
possible semantics: under and-semantics, an entry lapses when both the
key and value are unreachable. Under or-semantics, an entry lapses if
either the key or value is unreachable.
The and-semantics is new. Until TXR 266, only or-semantics was
supported. This will be the default: when a hash table is specified
as :weak-keys and :weak-vals, it will have or-semantics.
The keywords :weak-or and :weak-and specify weak keys and values,
with the specific semantics. They are utually exclusive, but tolerate
the presence of :weak-keys and :weak-vals.
The make-hash function is being extended such that if its leftmost
argument, <weak-keys>, is specified as one of the keywords :weak-and
or :weak-or, then the hash table will have weak keys and values with the
specified semantics, and the <weak-vals> argument is ignored
(values are weak even if that argument is false).
* eval.c (eval_init): Initially register the top_vb,
top_mb, top_smb, special and builtin hashes as ordinary hashes: no weak
keys or values. Then use tweak_hash to switch to weak keys+vals
with and-semantics. We do it this way because the keywords are not yet
initialized; we cannot use them.
* hash.h (enum hash_flags, hash_flags_t): Moved to header. Member
hash_weak_both renamed to hash_weak_or. New member hash_weak_and.
(weak_and_k, weak_or_k): New keyword variables.
(hash_print_op): Handle hash_weak_and by printing :weak-and.
(hash_mark): Handle hash_weak_and by marking nothing, like hash_weak_or.
(do_make_hash): Check first argument against the two new keywords and
set flags accordingly. This function is called from eval_init before
the keywords have been initialized, in which case weak_keys ==
weak_and_k is true when both are nil; we watch for that.
(tweak_hash): Now returns void and takes a hash_flags_t argument which
is simply planted.
(do_wak_tables): Implement hash_weak_and case. Remove the compat 266
stuff from hash_weak_or. Compatibility is no longer required since we
are not changing the default semantics of hash tables. Phew; that's a
load of worry off the plate.
(hashv): Parse the two new keywords, validate and provide semantics.
(hash_init): Initialize weak_and_k and weak_or_k kewyords.
* hash.h (enum hash_flags, hash_flags_t): Moved here now.
(weak_and_k, weak_or_k): Declared.
* lib.c (compat_fixup): Remove call to parse_compat_fixup.
* parser.c (parse_init): Create stream_parser_hash with and-semantics.
(parse_compat_fixup): Function removed.
* parser.h (parse_compat_fixup): Declaration removed.
* txr.1: Hash documentation updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This addresses the problem that
a4c376979d15323ad729e92e41ba43768e8dc163
tried to fix.
* eval.c (eval_init): Make all the top-level binding tables,
top_fb, top_vb, top_mb, top_smb, special and builtin,
weak-both tables: keys and values are weak.
This way, the entries disappear if both key and value
are unreachable, even if they refer to each other.
(eval_compat_fixup): In 266 or earlier compat mode, weak-both
tables don't have the right semantics, so we tweak
the tables to weak-key tables.
* parser.c (parse_init): Same treatment for
stream_parser_hash. We want an entry to disappear from the
hash if neither the parser nor the stream are reachable.
(parse_compat_fixup): New function.
* parser.h (parse_compat_function): Declared.
* hash.c, hash.h (tweak_hash): New function.
* lib.c (compat_fixup): Call parse_compat_fixup.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c, lib.h (chk_substrdup): New function.
* stream.c, stream.h (trim_short_suffix, trim_long_suffix):
New functions.
(stream_init): trim-short-suffix and trim-long-suffix
intrinsics registered.
* tests/018/path.tl: New tests.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (separate): New function.
* lib.h (separate): Declared.
* eval.c (eval_init): Register separate intrinsic.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
| |
lib.c (built_in_type): Use i for stepping over the
enumeration, because type_t has no postfix ++ operator
for i++. The code2type function takes an int, and so no
cast is required.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register built-in-type-p intrinsic.
* lib.c (buitin_type_p): Rename to built_in_type_p since the
word built-in is hyphenated. The function also tests
whether the argument is a COBJ class.
(cobj_class_exists): Function removed.
* stdlib/doc-syms.tl: Updated.
* stdlib/struct.tl (defstruct): Add built-in-type-p check.
* struct.c (make_struct_type): Call only built_in_type_p;
cobj_class_exists is gone.
* txr.1: Document built-in-type-p.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (class_from_sym): New static function.
(subtypep): Remove special case handling of stream versus
stdio-stream. If the two types are not both structures, then
check whether they are both cobj classes. If so, check if they
are in an inheritance relationship via the cobj_hash.
(cobj_populate_hash): Map each symbol to a fixnum integer
which gives class handle'position in the cobj_class table.
(cobj_class_exists): Style: compare to nil instead of 0.
(obj_init): Do not call cobj_populate_hash here, it is far too
early: only a couple of COBJ types exist at this point.
Moreover, hash_init has not been called so hash_cls and
hash_iter_cls still have null symbols.
(init): Call obj_populate_hash here, as the last step.
* tests/012/type.tl: New file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
* lib.h (enum type): Change MAX_TYPE to correctly alias the
last type DARG, rather than the second-to-last TNOD type.
* lib.c (seq_kind_tab): Include an entry for DARG, mapping to
SEQ_NOTSEQ.
|
|
|
|
|
|
| |
* lib.c (find_symbol): This function is identical to
find_symbol_fb. The code for searching the fallback list must
be removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Numerous functions in TXR Lisp treat a nil argument for an
optional parameter as if it were omitted. In the case of
streams, this can cause problems. An accidental nil passed to
an input function can cause it to read from standard input and
hang. In this patch, argument defaulting is tighented for
functions that perform I/O. It's mostly stream parameters, but
not exclusively.
* eval.c (prinl, pprinl): Use default_arg_strict to default
the stream argument, and also re-use that value for the
put_char call.
* lib.c (lazy_stream_cons, print, pprint, put_json): Use
default_arg_strict rather than default_arg.
* parser.c (regex_parse, lisp_parse_impl, txr_parse): Tighten
the defaulting of the input stream and error stream arguments,
streamlining the logic at the same time.
* stream.c (do_parse_mode): Use default_arg_strict for the
mode string argument.
(record_adapter, get_line, get_char, get_byte, get_bytes,
unget_byte, put_buf, fill_buf, fill_buf_adjust,
get_line_as_buf, put_string, put_char, put_byte, put_line,
flush_stream, get_string): Use strict defaulting for stream
argument.
(mkstemp_wrap): Use strict defaulting for suffix.
|