| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
| |
* stdlib/place.tl (sys:placelet-1): Fix a misindented
call-update-expander function call. Also indent its
arguments in function style.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (glob_set_entries): Remove autoload on
sys:brace-expand. Add usr:exp.
* stdlib/glob.tl (brace-expand): Renamed to usr:bexp.
(glob*): Call bexp rather than brace-expand.
* tests/018/glob.tl: Rename references to sys:brace
expand to bexp.
* txr.1: Add section describing the bexp function.
Move brace expansion documentation from glob* to this
new section, adjusting the wording a little bit, mainly
to avoid referring to "patterns". Point glob* documentation
to bexp, which also in turn references glob*.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlb/glob.tl (bexp-parse): Recognize .. as a token.
(bexp-parse-brace): If a brace expansion doesn't contain
commas, then check whether it contains .. and that its elements
are all strings. In that case it is a possible range expansion
and we thus transform it to a (- ...) node, subject to
more validation in bexp-expand.
(bexp-expand): Add casees to handle range expansion,
taking care that invalid forms translate to verbatim
syntax.
* tests/018/glob.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a problem caused by b7a7370a921bbc02b54d87600ff74d5cb9efde28,
on Feb 4, 2020, which adds unwinding logic into the
provide_completions function. Two return statements are
correctly turned into "goto out", but one is overlooked.
When this stray return statement is executed, it leaves
dangling unwind frames in the unwind stack, causing
an assertion when control returns to the repl function
which calls uw_pop_frame to remove an unwind frame
that it pushed.
Steps to reproduce:
1. complete a symbol with a nonexistent package
1> (foo:bar[Tab]
2. Backspace over it (or use Ctrl-U) and hit Enter:
1>
txr: unwind.c:296: uw_pop_frame: Assertion `fr == uw_stack' failed.
Aborted (core dumped)
* parser.c (provide_completions): When find_package fails,
return by executing goto out, rather than return, so
that the catch frame is removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The notation X..Y..Z now denotes an iterable range,
if X..Y is a valid iterable range on its own, and Z is a
positive integer. Z gives a step size: 1 takes every
element, 2 every other and so on.
* lib.c (seq_iter_get_skip, set_iter_peek_skip): New static
functions.
(si_skip_ops): New static structure.
(iter_dynamic): Function relocated earlier in file to avoid
forward declaration.
(seq_iter_init_with_info): When the iterated object is a
range, check for the to element itself being a range.
If so, it is potentially a skip iteration. Validate it
and implement via a skip iterator referencing a dynamic
range iterator.
* lib.h (struct seq_iter): New sub-union member, ul.skip.
We could use an existing member of type cnum;
this is for naming clarity.
* tests/012/iter.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register iterp intrinsic.
* lib.[ch] (iterp): New function.
* tests/012/iter.tl: New tests.
* txr.1: Document iterp. Update documentation for iter-more,
iter-item and iter-step to more precisely identify which
objects are valid arguments in terms of iterp and additional
conditions, and that other objects throw a type-error
exception. Fix wrong references to iter-more under
documentation for iter-item. Removed obsolete text specifying
that iter-step uses car on list-like sequences, a dubious
behavior removed in the previous commit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (iter_more): Do not return t for unrecognized
objects, but thrown an exception. Do return t for
conses, which is necessary since they are iterators
for lists. Also, as a special case, we return t for
struct objects that don't have an iter-more method.
This is needed for the documented fast protocol.
Iterator objects implementing the fast protocol
still get iter-more invoked on them. The client
usually doesn't know that the iterator implements
the fast protocol, and so calls iter-more, which
unconditionally has to returns true.
(iter_item): Do not fall back on car(iter) for all
unhandled objects. Only conses are handled
via car. All unrecognized objects trigger an
exception.
(iter_step): Do not try to handle list-like
objects via cdr, only lists.
Improve the diagnostic for hitting the end of
an improper list: diagnostic shows the cons
cell rather than just the terminating atom.
* tests/012/iter.tl: Some test cases validating
that the functions error out for strings and
vectors. Much more coverage is possible here but
doesn't seem worth it; e.g. that the functions
reject a buffer, regex, function, ...
|
|
|
|
|
|
|
|
|
|
| |
* Makefile: put the current build_id into the .build_id
file only if it is nonblank. If it is blank, then delete
the file if it exists. This handles the case when the
build_id user removes the build_id. A rebuild of txr.o is
forced one last time, and the .build_id is removed.
Users who don't know about build_id or don't use it will
no longer see a blank .build_id file being created.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* configure: The way the verison is represented in the output
of gcc varies. A vendor build version may be indicated in
parentheses, and that may precede or follow the version number
by itself. I don't know all the variations. What I'm
implementing here is looping over the white-space separated
output of gcc --version, looking for an item of the form
number.number.number where number is any decimal string from 0
to 99 with no leading zero, except for zero itself. If we find
this item, we assume that is the gcc version, and break it up
and process it as before, terminating the loop. We print
the parsed gcc version in parentheses to help with spotting
problems.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_be_i16_rput, ffi_be_i16_rget, ffi_be_u16_rput,
ffi_be_u16_rget, ffi_be_i32_rput, ffi_be_i32_rget, ffi_be_u32_rput,
ffi_be_u32_rget, ffi_le_i16_rput, ffi_le_i16_rget, ffi_le_u16_rput,
ffi_le_u16_rget, ffi_le_i32_rput, ffi_le_i32_rget, ffi_le_u32_rput,
ffi_le_u32_rget): Rewriten to avoid memory clearing,
memsets, pointer arithmetic and use of helper functions. The big endian rput
and rget functions just wrap the non-endian versions.
The ones which need byte swapping work in terms of a full ffi_arg
word. For instance to prepare a 16 bit big endian unsigned return
value we byte swap the uin16_t, then convert fo ffi_arg.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_be_i16_rput): We need to memset the remaining
parts of the 64 bit word to 0, like in all the other
ffi_be_xxx_put functions that are less than 64 bits wide. Also
removing the (void) tft cast is removed since tft is used.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_i8_rput, ffi_i8_rget, ffi_u8_rput, ffi_u8_rget):
These functions are not doing the correct job; they are just
casting the pointer to the target type, like on little endian.
The big endian rget must fetch the entire 64 bit word
(ffi_arg) and convert its value to the target type. If
it's a character value, the actual bits are found at
*(src + 7) not at *src. The rput function must do the
reverse; convert the value to the 64 bit ffi_arg and
store that.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Only the JMP instruction is checking for a backwards branch
and calling sig_check_fast() so that a loop can be interrupted
by Ctrl-C. The compiler can optimize that so that a backwards
jump is performed by an instruction in the IF family.
* vm.c (vm_if, vm_ifq, vm_ifql): Check for a backwards
branch and call sig_check_fast. Also, eliminate the redundant
call to vm_insn_bigop, which is just a masking macro.
The ip variable is already the result of vm_insn_bigop.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Similarly to what was done in get_csv, we optimize he
use of get_char and unget_char. I see a 7.5% speed
improvement in a simple benchmark of the awk macro
with the record separator rs set to #/\n/.
* regex.c (scan_until_common): Obtain the strm_ops
operations of the stream, and pull the low level
get_char and unget_char virtual operations from it.
Call these directly in the loop. Thereby, we avoid
all the type checking overhead in these functions.
|
|
|
|
|
|
|
|
|
|
|
| |
Another 5-6% gained form this.
* stream.c (us_get_char, us_unget_char): Static functions
removed.
(get_csv): Retrieve the get_char and unget_char pointers from
the strm_ops structure outside of the loop, and then just
call these pointers. Careful: the unget_char virtual has
reversed parameters compared to the global function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Another almost 16% speedup.
* lib.c (us_length_STR): New static function.
(string_extend): Use us_length_STR, since we know the
object is of type STR.
(us_string_extend_STR_CHR): New function.
(length_str): Handle STR case via use_length_STR.
* lib.h (us_string_extend_STR_CHR): Declared.
* stream.c (get_csv): Use us_string_extend_STR_CHR
instead of string_extend.
|
|
|
|
|
|
|
| |
* lib.c (string_extend): We know that num_fast + delta is in
the fixnum range, because we checked this condition. So
we can just assign it without informing the garbage collector.
This yields about a 16% speedup in get-csv.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/awk (awk-state upd-rec-to-f): Handle a new case
of fs being the keyword symbol :csv, producing a
field-splitting lambda that calls get-csv.
* tests/015/awk-basic.tl: Several new test cases for
this CSV feature.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
I'm seeing about a 6% improvement in get-csv from this.
* stream.c (us_get_char, us_unget_char): New static functions,
which assume all arguments have correct type.
(get_csv): If we use source_opt, validate that it's a stream
with class_check. Use us_get_char and use_unget_char.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Nowhere in the image do we have cobj_class inheritance
deeper than one. No class has a superclass which itself
has a superclass. Based on this, we can eliminate loops
coded to handle the general case.
* lib.c (sutypep, cobjclassp): Do not iterate to chase
the chain of super pointers. Do the subclass check
based on the assumption that there is at most a super
pointer to class which itself then has no super.
(cobj_register_super): Assert if the situation occurs
that a class is registered with a super that is not
a root. All these calls take place on startup, so if
the assumption is wrong, the assert will be 100%
reproducible.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Like in a recent commit for mkstring, we impose a minimum
allocation size of 6 for vectors, which means 8 cells
together with the two informaton words at the base of
the vector.
* lib.c (vec_own): Take an alloc parameter in addition
to the length, which is stored in v[vec_alloc].
(vector): Impose a minimum alloc size of 6.
(copy_vec, nested_vec_of_v): Pass alloc parameter
to vec_own which is the same as the length parameter;
i.e. no behavior change for these functions.
|
|
|
|
|
|
|
| |
* lib.c (string_extend): When more space is needed in the
string, grow by 50% rather than 25%. This speeds up code
at the expense of some wasted space. Waste space can be
dealt with by the final flag in programs where it matters.
|
|
|
|
|
|
| |
* lib.c (mkstring): Do not allocate less than 8 characters,
including null terminator, to the string. This speeds up code
which builds up strings from empty, one character at a time.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The malloc_usable_size use in the STR type actually makes
operations like string_extend substantially slower. It is
faster to store the allocated size locally.
Originally, on platforms that have malloc_usable_size,
we were able to use the word of memory reclaimed from
the string type to store a cached hash code. But that logic
was revereted in 2022, so there is no such benefit.
* configure (have_malloc_usable_size): Variable
removed. Test for the malloc_usable_size function
removed.
(HAVE_MALLOC_USABLE_SIZE, HAVE_MALLOC_NP): Do not define
these preprocessor symbols.
* lib.c (HAVE_MALLOC_NP_H): Do not test for this variale
to include <malloc_np.h>
(string-own, string, string_utf8, mkstring, mkustring,
string_extend, string_finish, string_set_code,
string_get_code, length_str): Eliminate #ifdefs
on HAVE_MALLOC_USABLE_SIZE.
* lib.h (struct wstring): Eliminate #ifdef on
MALLOC_USABLE_SIZE, so alloc member is unconditionally
defined on all platforms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Handle field separations with lambdas, similarly to record
separation. The idea is that we replace the rec-to-f method,
which contains a cond statement checking the variables for
which field separation discipline applies, with a lambda which
is updated whenever any of those ariables change.
* awk.tl (awk-state): New instance slot, rec-to-f.
(awk-state :postinit): Call new upd-rec-to-f method
so that rec-to-f is populated with the default field
separating lambda.
(awk-state rec-to-f): Method removed.
(awk-state upd-rec-to-f): New method, based on rec-to-f.
This doesn't perform the field separation, but returns
a lambda which will perform it.
(awk-state loop): We must call upd-rec-to-f whenever
we change par-mode, because it influences field separation.
(awk-mac-let): Replace the symbol macros fs, ft, fw and
kfs with new implementations that use the reactive slot
mechanism provided by rslot. Whenever the awk macro assigns
any of these, the upd-rec-to-f method will be called.
* tests/015/awk-basic.tl: New file. These basic tests of
field separation pass before and after this change.
* tests/common.tl (otest, motest): New macros.
|
|
|
|
|
| |
* txr.1: The example possible value "~3,4f" should be shown
as a string literal in quotes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (get_csv): Let's add a new state init. If get_char
returns nil and we are in the init state, let's bail to a
nil return. While we are at it, let's not allocate the record
or string until we read at least one character. If we read
a character in the init state, let's allocate those two
objects, and then change to the rfield state and fall through
to it to handle the character.
* tests/010/csv.tl: Fix one incorrect test: (tocsv "") now
returns nil, as it should. Add tests for multiple record
extraction, also covering missing line termination on the last
record as well as CR-LF termination.
* txr.1: Documented nil return conditions.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (put_csv, tocsv): New functions.
(stream_init): put-csv and tocsv intrinsics registered.
* stream.h (put_csv, tocsv): Declared.
* tests/010/csv.tl (mtest-pcsv): New macro.
New test cases.
* txr.1: Documented.
|
|
|
|
| |
* txr.1: Split Data Interchange Support into JSON and CSV.
|
|
|
|
|
|
|
| |
* stream.c (get_csv): All cases handle end-of-stream
the same way, so we check for nil outside of the case
switch. Then only characters need to be handled, so we
can call c_chr(ch) and switch on it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autload.c (csv_set_entries, csv_instantiate): Functions
removed.
(autoload_init): Autoload registration for stdlib/csv
removed.
* stdlib/csv.tl: File removed.
* stream.c (get_csv): New function.
(stream_init): Register get-csv intrinsic.
* stream.h (get_csv): Declared.
|
|
|
|
|
|
| |
* csv.tl (get-csv): Since there are only three states, there
is no jump table optimization. We might as well use keyword
symbols for the states rather than integers.
|
|
|
|
|
|
|
|
|
| |
* stdlib/csv.tl (get-csv): Pre-process the input by a small
state machine that maps CR-LF sequences to LF. Then
we don't have to recognize #\return anywhere in the state
machine and can delete the cr and qcr states, as well
as all the code recognizing #\return and branching to those
states.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autloload.c (csv_set_entries, csv_instantiate): New
static funtions.
(autoload_init): Register autoload of stdlib/csv
module via new functions.
* stdlib/csv.tl: New file.
* tests/010/csv.tl: Likewise.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (enum_set_entries, enum_instantiate): New static
functions.
(autoload_init): Register autoload of stdlib/enum module
via new functions.
* stdlib/enum.tl: New file.
* tests/016/enum.tl: Likewise.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Makefile (clean): Do not remove the run.sh file here.
That is a temporary file that install-tests should be cleaning
away when done, which we can remove in distclean.
(clean-doc, clean-tests): New targets, which let us clean
up generated documentation files and the test-generated
state information in tst.
(distclean): Do not remove the documentation stuff here; rely
on clean-doc. Also depend on clean-tests.
Do remove run.sh here.
(install-tests): Add missing .PHONY. Remove run.sh.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In an opip pipeline, only the first pipeline element can
receive multiple arguments. The subsequent elements
receive the single return value from the previous element.
Therefore if it is a left-inserting pipeline created
by lopip, only the first element needs to use lop.
The others can use lop1, resulting in an optimization.
Furthermore in the flow/lflow macros, even the first
function in the pipeline is called with one argument:
the result of the input expression. So the case of lflow,
every element of the pipe that would translate to lop
can go to lop1 instead.
* stdlib/opt.tl (sys:opip-expand): Calculate a local
variable called opsym-rest which determines which op
symbol we use for the recursive call. This is the
same as the incoming opsym, except in the case when
opsym is lop, in which case we substitute lop1.
(sys:lopip1): New macro, like lopip but uses lop1
for the first element also.
(lflow): Expand to sys:lopip1 rather than lopip.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (op_set_entries): Autoload on lop1 symbol.
* stldlib/op.tl (sys:op-expand): Add lop1 case.
(sys:opip-expand): Add lop1 to the list of operators
that are recgonized and specially treated.
(lop1): New macro.
* tests/012/op.tl: New tests.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.h (struct json_opts): Member flat removed.
I noticed that !jo.flat was always being tested together
with jo.fmt == json_fmt_standard. Except for a few
places where the code only tested for json_fmt_standard,
resulting in flat output, but some extra spaces.
What distiguishes flat mode now is simply that we
disable stream indentation.
* lib.c (out_json_rec): Remove tests for !jo.flat.
(out_json): Remove initialization of jo.flat member.
In this function we set up indentation on the stream
resulting in multi-line mode (existing behavior).
(put_json): Remove initialization of jo.flat member.
If flat mode is requested, then it overrides the
format to json_fmt_default. I.e. json_fmt_standard
coresponding to :standard is only in effect if flat
is not requested.
In this function we set up indentation on the stream
if flat mode isn't requested, otherwise we disable
indentation (existing behavior, enough to make flat
work).
* tests/010/json.tl: Tests for flat mode, :standard
formatting, and combinaton of both.
|
|
|
|
|
|
|
|
|
|
| |
this also affects put_jsonl and tojson.
* lib.c (put_json): The flat argument must be properly
defaulted. Without this we are treating it as true when it
is missing due to the convention that missing args are
signaled by the : symbol. This bugs breaks the ability
to use the :standard value for *print-json-format*.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The lop macro is inconsistent from op in that it
inserts the trailing function arguments on the
left even if arguments are explicitly given in the
form via @1, @2, ... or @rest. This change makes
lop is equivalent to op in all situations when these
metas are given.
* stdlib/op.tl (compat-225, compat-298): New top-level
variables.
(op-expand): local variable compat replaced by references to
compat-225. If compat-298 is *not* in effect, then metas
are checked for first in the cond, preventing the lop
transformation from taking place.
* tests/012/op.tl: Test cases for lop, combinations of
do with lop and a few for op also.
* txr.1: Redocumented, added compat notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h,
args.c, args.h, arith.c, arith.h, autoload.c, autoload.h,
buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h,
chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure,
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, gzio.c,
gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S,
lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c,
linenoise/linenoise.h, match.c, match.h, parser.c, parser.h,
parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h,
regex.c, regex.h, signal.c, signal.h, socket.c, socket.h,
stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl,
stdlib/build.tl, stdlib/cadr.tl, stdlib/comp-opts.tl,
stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl,
stdlib/copy-file.tl, stdlib/csort.tl, stdlib/debugger.tl,
stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl,
stdlib/error.tl, stdlib/except.tl, stdlib/expander-let.tl,
stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl,
stdlib/glob.tl, stdlib/hash.tl, stdlib/ifa.tl,
stdlib/keyparams.tl, stdlib/load-args.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.1, txr.c, txr.h, unwind.c, unwind.h,
utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr,
y.tab.c.shipped: Copyright bumped to 2025.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/match.tl (match-case-to-casequal): the (do inc
dfl-cnt) action has a problem: it inserts an implicit extra
parameter to the invocation of inc, which crashes the +
addition due to that parameter being the matching @nil object.
We don't need this entire case because it handles @nil,
which also matches the following case for (sys:var ...),
since @nil is (sys:var nil). That case ahs the same action
of incrementing dfl-cnt.
* tests/011/patmatch.tl: Test case added.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
|
|
|
|
|
| |
* parser.c (load_rcfile): When neither ~/.txr-profile nor ~/.txr_profile
exist, then bail. Do not pass nil to abs-path-p and other functions.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
|
| |
* lib.c (length_str_range): On platforms where wchar_t is
unsigned, we calculate bogus values for reversed ranges.
On Android, gcc warns about the code, and the recently
added tests fail. Let's cast the characters to long before
doing the subtraction, which is the argument type of labs.
|
|
|
|
|
|
|
|
|
| |
* lib.c (seq_iter_init_with_info): String ranges are
inclusive. We must not assume at a range whose endpoints are
the same is empty; we must check that case for the endpoints
being strings.
* tests/012/seq.tl: New tests.
|
|
|
|
| |
* tests/012/seq.tl: New tests.
|