summaryrefslogtreecommitdiffstats
path: root/lib.c
Commit message (Collapse)AuthorAgeFilesLines
...
* Bugfix: incorrect appending to improper lists.Kaz Kylheku2019-09-091-9/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* subtypep: structs with car or length method are sequences.Kaz Kylheku2019-09-061-0/+7
| | | | | | | | | | | | | * lib.c (subtypep): For the sequence supertype, check whether the subtype is a structure that has a length or car method, returning t if so. * struct.c (get_special_slot_by_type): New function. * struct.h (get_special_slot_by_type): Declared. * txr.1: Add <structures with cars or length methods> to the type hierarchy diagram.
* seq_info: bug: nil for objects with only length method.Kaz Kylheku2019-09-061-1/+1
| | | | | | * lib.c (seq_info): Add missing else, which makes the function return nil for objects that have a length method, but not a car method.
* subtypep: remove useless eq.Kaz Kylheku2019-09-061-1/+1
| | | | | | * lib.c (subtypep): The sub and sup parameters are compared for equality early in the function; byt the time we get here, we know they are not eq, so nil can be returned.
* lib: access special methods via special slot mechanism.Kaz Kylheku2019-09-061-26/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ffi.c (ffi_flex_struct_in): Use get_special_slot to obtain length method. * lib.c (nullify_s, from_list_s, lambda_set_s): Definitions removed from here. (seq_info, car, cdr, rplaca, rplacd, make_like, nullify, replace_obj, length, empty, sub, ref, refset, dwim_set): Use get_special_slot to obtain special method from object, rather than maybe_slot. (obj_init): Remove initializations of nullify_s, from_list_s and lambda_set_s from here. * struct.c (enum special_slot): Definition removed from here. (nullify_s, from_list_s, lambda_set_s): Definitions moved here from lib.c. (special_sym): New static array. (struct_init): Initializations of nullify_s, from_list_s and lambda_set_s moved here from lib.c. (get_special_slot): New function. * struct.h (lambda_set_s): Declared. (enum special_slot): Definition moved here. (get_special_slot): Declared. * txr.1: Added compat note, since get_special_slot behaves like maybe_slot under 224 compatibility.
* seq_info: remove redundant car slot lookup.Kaz Kylheku2019-09-041-2/+0
| | | | | | * lib.c (seq_info): Due to a copy-paste error maybe_slot is being accidentally called here twice for the same slot. Removing.
* type: lcons and string are subtypes of sequence.Kaz Kylheku2019-09-041-1/+1
| | | | | | | Omissions reported by user vapnik spaknik. * lib.c (subtypepe): The lcons type and string type must report as subtypes of sequence.
* New function: tailp.Kaz Kylheku2019-09-031-0/+10
| | | | | | | | | | * eval.c (eval_init): Register tailp intrinsic. * lib.c (tailp): New function. * lib.h (tailp): Declared. * txr.1: Documented.
* New function: cptr-buf.Kaz Kylheku2019-08-211-0/+7
| | | | | | | | | | * eval.c (eval_init): Register cptr-buf intrinsic. * lib.c (cptr_buf): New function. * lib.h (cptr_buf): Declared. * txr.1: Documented.
* New function: intern-fb.Kaz Kylheku2019-08-201-0/+11
| | | | | | | | | | | | | | | To accompany find-symbol-fb, there is intern-fb, which is like intern, but searches the fallback list. * eval.c (eval_init): Register intern-fb intrinsic. * lib.c (intern_fallback_intrinsic): New function. Does defaulting and error checks, then calls intern_fallback, just like intern_intrinsic calls intern. * lib.h (intern_fallback_intrinsic): Declared. * txr.1: Documented.
* lib: streamline interning slightly.Kaz Kylheku2019-08-201-13/+14
| | | | | | | | | | | | | | | | | | | | | We get rid of some defaulting and error checks from interning. This saves a few cycles on startup in the large number of intern calls that are performed. * eval.c (eval_init): Wire the intern intrinsic to the new intern_intrinsic function rather than intern. * lib.c (intern): Remove package lookup and error check on str argument. (intern_intrinsic): New function, which has the package lookup and error check. (intern_fallback): Remove package lookup and error check. * lib.h (intern_intrinsic): Declared. * txr.c (txr_main): Fix one instance of an intern call that relies on defaulting of the second argument, by passing cur_package.
* new functions: find-symbol and find-symbol-fb.Kaz Kylheku2019-08-191-8/+49
| | | | | | | | | | | | | | | | | | Turns out, there is already a find_symbol in lib.c, completely unused. * eval.c (eval_init): Register find-symbol and find-symbol-fb intrinsics. * lib.c (find_symbol): Fix this hitherto unused function to do correct defaulting of the package argument and, to accept an additional argument specifying the not-found value. (find_symbol_fb): New function. * lib.c (find_symbol): Declaration updated. (find_symbol_fb): Declared. * txr.1: Documented.
* seq_iter: remove pointless one-member union.Kaz Kylheku2019-08-141-6/+6
| | | | | | | | * lib.h (struct seq_iter): union ul with just one member replaced by that member itself. * lib.c (seq_iter_get_vec, seq_iter_peek_vec, seq_iter_init): refer to it->len instead of it->ul.len.
* where: bugfix: doesn't work for non-list sequence.Kaz Kylheku2019-08-141-13/+7
| | | | | | | | * lib.c (lazy_where_func, where): We have a regression here due to strangely trying to smuggle the predicate function in si->inf.obj, which cannot possibly work other than for lists whose seq iterators ignore that field. We switch to the trick of using the cdr field of the lazy cons to carry that forward.
* reverse: bugfix: garbage object in error message.Kaz Kylheku2019-08-091-1/+1
| | | | | * lib.c (reverse): pointer to the C function in is being used as a value; the correct expression is seq_in.
* lib: don't GC-protect two non-heap objects.Kaz Kylheku2019-08-061-1/+1
| | | | | | | | | | * lib.c (obj_init): The null string literal and "nil" do not require gc protection; they cannot be reclaimed by the garbage collector, which ignores them. Don't waste two slots in the prot_stack on them. This is a remnant from ancient TXR; these variables were protected already in Version 11 from September 2009. At that time, there were no built-in string literal objects; these two objects were heap-allocated.
* relate: optimize with hashes.Kaz Kylheku2019-07-171-3/+27
| | | | | | | | | | | * lib.c (do_relate_hash, do_relate_hash_dfl): New static functions. (relate): If the number of keys and values is the same, and there are more than ten, then use hashing. If the default value is specified, and it is nil, then a hash table can be returned directly, instead of a function. * txr.1: Note added that relate may return a hash.
* chk_calloc: use unsigned arithmetic.Kaz Kylheku2019-07-111-1/+1
| | | | | | | * lib.c (chk_calloc): Use unsigned arithmetic to figure out the total, which is only used for incrementing the malloc_bytes counter. The unsigned arithmetic is performed in the same type as that counter.
* replace: deal with overlapping.Kaz Kylheku2019-07-051-3/+3
| | | | | | | | | | | | | * buf.c (replace_buf): In the same-type case, use memmove rather than memcpy in case the objects overlap, so we don't invoke C undefined behavior. * lib.c (replace_str, replace_vec): Likewise. * txr.1: Specify that if the replacement sequence overlaps with the target range of the destination sequence, or with any portion that has to be relocated if range changes size, then the behavior is unspecified.
* empty: handle buffers.Kaz Kylheku2019-06-301-0/+2
| | | | * lib.c (empty): Handle BUF in switch.
* seq_info: nullify bugfix.Kaz Kylheku2019-06-281-13/+19
| | | | | | | | | | | | | | | | | | | | | A change in the nullify function to support hash tables has broken various functions which classify an object using seq_info, obtainig a SEQ_HASHLIKE kind, and then work with si.obj using hash functions. But si.obj has been nullified. An example of a broken function is find-max. Basically, this can be attributed to a careless use of nullify in seq_info. The purpose of nullify is to support code which treats any sequence as if it were a list. But seq_info doesn't do that; it classifies sequences and treats them according to their kind. Under seq_info, the only non-list objects that get treated as lists are list-like structures. For these it makes sense to call nullify, in case they have a nullify method. * lib.c (seq_info): Don't unconditionally call nullify on all COBJ objects. Only call nullify on struct objects. If that returns nil, then treat the object as SEQ_NIL; and if it returns an object different from the original, then recurse.
* seq-begin: bugfix: non-lists don't work.Kaz Kylheku2019-06-281-1/+0
| | | | | | | | | | | | | * lib.c (seq_begin): Do not null out si->inf.obj; it's needed for accessing hashes and vector-like objects. This bug means that seq-begin iteration has only worked correctly for lists. The original motivation was not to have spurious retention of the head of a lazy list, which is hereby reintroduced. But iterators can be rewound. Let's just document this away and leave it as a to-do item. * txr.1: Document the limitation of seq-begin w.r.t. lazy lists.
* in: allow hash with keyfun and testfun.Kaz Kylheku2019-06-251-1/+3
| | | | | | | * lib.c (in): A simple check and fallthrough lets this function process hash tables more generally in this function. * txr.1: Documented.
* in: use seq_infoKaz Kylheku2019-06-251-26/+28
| | | | | * lib.c (in): Keep the existing specialized cases, but use seq_info in the fallback.
* Factor function name into self variable.Kaz Kylheku2019-06-251-10/+15
| | | | | * lib.c (take, take_while, take_until, drop_while, drop_until): Move repeated function name into self variable.
* drop-{while,until}: convert to seq_info.Kaz Kylheku2019-06-251-16/+16
| | | | | | * lib.c (drop_while, drop_until): Use seq_info, so these functions work with all sequences. Thus now for instance [drop-while zerop #b'0000f00d'] yields #b'f00d'.
* empty: handle carray.Kaz Kylheku2019-06-251-0/+2
| | | | * lib.c (empty): Add carray sub case to COBJ case.
* nullify: handle carray and hashes.Kaz Kylheku2019-06-251-0/+4
| | | | | * lib.c (nullify): Add carray and hash subcases into the COBJ case.
* Handle buffers in list collector functions.Kaz Kylheku2019-06-251-0/+19
| | | | | | * lib.c (nullify, list_collect, list_collect_nconc, list_collect_append, list_collect_nreconc, list_collect_revappend): Handle buffer type.
* list_collect: handle objects.Kaz Kylheku2019-06-251-1/+10
| | | | | | | | | * lib.c (list_collect): Handle sequence-like COBJ objects. We can add an item to using their respective replace functions. (replace_obj): Change to external linkage. * lib.h (replace_obj): Declared.
* Code clean-up in list collector functions.Kaz Kylheku2019-06-251-19/+23
| | | | | | | * lib.c (list_collect, list_collect_append, list_collect_revappend): Use local variables to avoid repeated expressions. (list_collect_nconc): Only call nullify in necessary cases.
* seqp: expand definition of sequences.Kaz Kylheku2019-06-251-12/+2
| | | | | | | * lib.c (seqp): Use seq_info to classify the object as a sequence. * txr.1: Update description of seqp.
* replace: fix strange diagnostic from bad fallthrough.Kaz Kylheku2019-06-241-2/+2
| | | | | | | | | * lib.c (replace): If a COBJ is passed to replace which doesn't support the operation, we wrongly pass it to replace_buf because the BUF case was added into the fallthrough pass. The end result is that length_buf blows up on the object, resulting in a strange diagnostic. The BUF case must be moved above COBJ.
* * Makefile (OBJS): New objects chksum.o and chksums/sha256.o.Kaz Kylheku2019-06-231-0/+2
| | | | | | | | | | * chksum.c, chksum.h, chksums/sha256.c, chksums/sha256.h: New files. * lib.c (init): Call chksum_init. * txr.1: Documented. * LICENSE: Add SHA-256 copyright notice.
* packages: generational gc bug.Kaz Kylheku2019-06-191-4/+4
| | | | | | | | | | | | * lib.c (make_package_common): The way the two hashes are assigned into the new package here is not correct. The problem is that the first make_hash can trigger gc. Then it is possible that the package object will move into the mature generation, after which the assignment of the second package is a wrong-way assignment requiring the set macro. Instead of bringing in that macro, the obvious way to solve it is to just allocate the hashes first, and then the package: exactly the way we build a cons cell from existing values.
* Replace lt(x, zero) pattern.Kaz Kylheku2019-06-151-19/+19
| | | | | | | | | | | | | | | | | | | | | | | | | This slight inefficiency occurs in some 37 places in the code. In most places we replace lt(x, zero) with minusp(x). In a few places, !plusp(x) is used and surrounding logic is simplified. In one case, the silly pattern lt(x, zero) ? t : nil is replaced with just minusp(x). * buf.c (sub_buf, replace_buf): Replace lt. * combi.c (perm, rperm, comb, rcomb): Likewise. * eval.c (do_format_field): Likewise. * lib.c (listref, sub_list, replace_list, split_func, split_star_func, match_str, lazy_sub-str, sub_str, replace_str, sub_vec, replace_vec): Likewise. * match.c (weird_merge): Likewise. * regex.c (match_regex, match_regex_right_old, match_regex_right, regex_prefix_match, regex_range_left, regex_range_right): Likewise.
* cat-str, split-str: sep can be character.Kaz Kylheku2019-06-141-2/+22
| | | | | | | * lib.c (cat_str, split_str_keep): Support single character separator. * txr.1: Documented.
* select: maintenance.Kaz Kylheku2019-06-141-33/+39
| | | | | | | | | * lib.c (sel): Function converted to seq_info and iterators. Negative indices handled in list case. Self-name corrected to select; the C function is called sel just to avoid clashing with POSIX select. * txr.1: Documentation updated.
* replace-list: negatives in index-list follow convention.Kaz Kylheku2019-06-141-0/+2
| | | | | | | | | | The index-list replacement isn't following the convention that negative index values reference from the end of the target sequence. Let's fix that. * lib.c (replace_list): Likewise. * txr.1: Documentation updated.
* replace-str, replace-vec: remove call to len.Kaz Kylheku2019-06-131-2/+2
| | | | | | * lib.c (replace_str, replace_vec): Remove redundant calculation of input sequence length; there is a len variable bound on entry into the function.
* buffers: replace operation.Kaz Kylheku2019-06-121-1/+1
| | | | | | | | * buf.c (replace_buf): New function. * buf.h (replace_buf): Declared. * lib.c (replace): Wire in.
* sub-vec: optimize no-op case.Kaz Kylheku2019-06-121-0/+2
| | | | | | | | | | * lib.c (sub_vec): If range covers entire vector, just return it. * txr.1: Clarify that the output of sub may share structure with the input regardless of type, not only when the input is a list. This should have been updated when the optimizatin was done in sub-str.
* toseq: remove unused function.Kaz Kylheku2019-06-121-15/+0
| | | | | | * lib.c (toseq): Function removed. * lib.h (toseq): Declaration removed.
* replace-vec, replace-str: refactor with sequence iteration.Kaz Kylheku2019-06-121-97/+53
| | | | | | | * lib.c (replace_vec, replace_str): Don't use dubious toseq on input items, which converts non-sequence atoms into lists of one. Use sequence iterators to reduce number of cases in the code.
* replace_list: revise, fixing several bugs.Kaz Kylheku2019-06-121-49/+37
| | | | | | | | | | | * lib.c (replace_list): Avoid using the dubious toseq function which turns a non-sequence object into a list of one item. This is not documented. Rewrite the assign-to-multiple-indices logic into one loop that uses sequence iterators. A bug is fixed here: failing to step the indices and items in parallel. Don't use list_vec on items; it fails on strings. Strings are now supported properly: they expand into a list of items that is spliced.
* seq iterators: new peek operation.Kaz Kylheku2019-06-121-0/+39
| | | | | | | | | | | | * lib.c (seq_iter_peek_nil, seq_iter_peek_list, seq_iter_peek_vec, seq_iter_peek_hash): New static functions. (seq_geti): New function. (seq_iter_init): Initialize new peek member of seq_iter structure. * lib.h (struct seq_iter): New member, peek. (seq_peek): New inline function. (seq_geti): Declared.
* buffers: allow sub operation.Kaz Kylheku2019-06-111-1/+7
| | | | | | | | | * buf.c (sub_buf): New function. * buf.h (sub_buf): Declared. * lib.c (sub): Hook in BUF type. (replace): Diagnose BUF specially as unsupported.
* bugfix: list length: off-by-one error huge lists.Kaz Kylheku2019-05-311-0/+2
| | | | | | | | | | | | * lib.c (length_list, length_proper_list): Fix off-by-one bug when calculating lengths of lists that overflow the cnum type. Note that we will never see regular lists which hit this situation, because there are more values in the range [0, INT_PTR_MAX] then there are possible pointers in the system, However, lazy lists can be that long or longer, because as we calculate the length of a lazy list, the part we have already traversed can be garbage-collected under the right circumstances.
* C99: get rid of useless inline instantiations.Kaz Kylheku2019-05-021-21/+0
| | | | | | | | | | | * hash.c, lib.c, parser.y, unwind.c: Remove useless declarations that were believed to be C99 inline instantiations. This was mistakenly added at the time the Solaris issue was discovered that _XOPEN_SOURCE values of 600 or greater require compiling in C99 mode. We use "static inline" under C99 for inline functions; instantiation is not applicable at all to inline functions that don't have external linkage.
* lib: more nuanced file access errors.Kaz Kylheku2019-05-011-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Several new more specific exception types are derived from file-error and used. Error handlers can distinguish unexpected non-existence, unexpected existence and permission errors from each other and other errors. * lib.c (path_not_found_s, path_exists_s, path_permission_s): New symbol variables. (obj_init): New variables initialized. * lib.h (path_not_found_s, path_exists_s, path_permission_s): Declared. * parser.c (open_txr_file): Use new errno_to_file_error function to convert errno to exception symbol. * socket.c (open_sockfd): Likewise. * stream.c (open_directory, open_file, open_fileno, open_command, open_process, run, remove_path, rename_path): Likewise, and process-error is used in open_process and run instead of file-error for problems related to creating the process. * sysif.c (errno_to_file_error): New function. (mkdir_wrap, ensure_dir, chdir_wrap, getcwd_wrap, mknod_wrap, chmod_wrap, symlink_wrap, link_wrap, readlink_wrap, stat_impl, umask_wrap, ): Use errno_to_file_error to convert errno to exception symbol. (exec_wrap): Use process-error instead of file-error. * sysif.c (errno_to_file_error): Declared. * unwind.c (uw_init): Register path-not-found, path-exists and path-permission as subtypes of file-error. * txr.1: Documented.