| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_str_put, ffi_ptr_in_put, ffi_ptr_out_put,
ffi_ptr_in_out_put): Don't set up tft->in pointer at dynamic
time; this is now being done at static time, in
ffi_type_compile.
(ff_struct_put, ffi_array_put): Similarly, don't calculate
whether an in handler is needed or not based on the child type
elements; this is determined statically.
(make_ffi_type_pointer): Take an in function pointer argument,
since all callers need to set this up.
(make_ffi_type_struct): Set up an in handler for this type
if any of the structure element types need one.
(make_ffi_type_array): Set up an in handler for this type
if the element type needs it.
(ffi_type_compile): For the three ptr types, pass the
appropriate in function to make_ffi_type_pointer.
For the str type, set up the in pointer to ffi_freeing_in,
after constructing as a builtin type.
|
|
|
|
|
|
|
|
|
|
| |
This naming is confusing because a ptr is something else and
other functions with _ptr_ in their name pertain to the ptr
-type for referential passing.
* ffi.c (ffi_ptr_put, ffi_ptr_get, ffi_ptr_alloc):
Rename to ffi_cptr_put, ffi_cptr_get, ffi_cptr_alloc.
(ffi_type_compile): Follow rename.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_ptr_alloc): New static function.
(ffi_type_compile): Give the cptr type alloc and free
functions: alloc just retrives the address of the pointer
inside the cptr object (pointer to pointer); free is a noop.
(cptr_make): New static function.
(ffi_init): Register cptr_make as cptr intrinsic. Register
cptr-null intrinsic variable denoting a ready-made null
pointer.
* lib.c (cptr_addr_of): New function.
* lib.h (cptr_addr_of): Declared.
|
|
|
|
|
|
|
|
|
| |
Let's defend against uninitialized struct member bugs over
this type which has grown somewhat complicated.
* ffi.c (make_ffi_type_struct): Use chk_calloc for tft.
(make_ffi_type_array): Likewise, and remove a couple of
explicit zero initializations.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The fill function is useless, because the object is already filled
directly. It's just performing an exactly overlapping memcpy.
* ffi.c (ffi_buf_alloc): Function removed.
(ffi_type_compile): We can't use the presence or absence of
the fill function as the test whether a type can be passed
by ptr-in-out or ptr-out, since buf can be passed that way
and has no fill. A better criterion is "has no fill and
use the fixed size allocation". Removing the assignment
statements which set up the fill function for buffers.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The FFI type system needs to handle out and in-out pointers at
nested levels. We are only doing the tft->in(...) calls on
the top-level parameters so this doesn't happen. What's worse,
because the tft->put(...) calls recurse, they prepare buffers
which are not being freed because freeing is the
responsibility of tft->in(...) calls.
Because the type descriptor structures also store run-time
state, this change requires us to change how arrays are
treated. The array elements cannot share the same type
descriptor since each could hold a different buffer.
* ffi.c (ffi_struct_in): New static function.
(ffi_struct_put): Determine whether any of the members
need their in function called. If so, set this struct
type's in to point to ffi_struct_in.
(ffi_array_in): New static function.
(ffi_array_put): Determine whether any of the array elements
need their in function called. If so, set this struct type's
in to point to ffi_array_in. Treat tft->mtypes as a type
descriptor list, rather than a single type.
(ffi_array_get, ffi_array_fill, make_ffi_type_array): Treat
tft->mtypes as a type descriptor list, rather than a single type.
(ffi_type_compile): Compile the type expression of an array
as many times as the number of dimensions and gather into
a list, then pass that list to make_ffi_type_array.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (float_s): Variable removed. This is a duplicate
definition; we already have this symbol in lib.c.
(ffi_type_s): Duplicate definition removed; it is
repeated two lines below.
(ffi_str_put): Remove pointless const qualifier on u8s
variable.
(ffi_call_wrap): Cast return value of alloca. Also,
rc pointer needs to be cast to mem_t *.
(ffi_init): Remove initialization of float_s.
* ffi.h (float_s): Declaration removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix incorrect memory allocation in (ptr-in buf)
and (ptr-in-out buf) passing.
Buffer arguments passed to a function as
(ptr-in buf) or (ptr-in-out buf) now pass the buffer
directly without allocating another copy, as in the
case of arrays or structs.
* ffi.c (struct txr_ffi_type): New members alloc, free.
The pointer types use these functions, together with fill,
for the management of the buffering of their target type.
(ffi_fixed_alloc, ffi_noop_free, ffi_buf_alloc,
ffi_ptr_in_in): New static functions.
(ffi_ptr_in_put): Use target type's alloc function,
rather than chk_malloc. A struct or array will actually
allocate the buffer needed for their C version. A buffer
will not; it will just return its internal pointer,
just like what the wstr type does with strings.
This function now sets up ffi_ptr_in_in as the in handler
for this pointer type, rather than ffi_freeing_in,
because the freeing has to go through the target type
interface, and not directly to free. Buffers use the
no-op free function.
(ffi_ptr_out_in): Use the target type's free function
rathr than free.
(ffi_ptr_out_put, ffi_ptr_in_out_put): Use the target type's
allocator instead of chk_malloc.
(make_ffi_type_pointer, make_ffi_type_struct,
make_ffi_type_array): Initialize the alloc and free function
pointer members of the txr_ffi_type struct.
(ffi_type_compile): Set up alloc and free for buffers.
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (array_s): New symbol variable.
(ffi_array_put, ffi_array_get, ffi_array_fill,
make_ffi_type_array): New static functions.
(ffi_type_compile): Support (array <dim> <type>)
syntax.
(ffi_init): Initialize array_s.
* ffi.h (array_s): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_struct_destroy_op): Fix silly code.
The size field most certainly doesn't indicate the number
of elements, but rather the byte size. The array is
documented by libffi as null-pointer terminated, so let's take
advantage of that.
(make_ffi_type_struct): Speaking of the array being
null-terminated, it is we who are required to ensure this
representation and we are not. Let's fix it.
Also, we are here wrongly storing the number of elements
into the struct type's size field, which is the basis for
misusing that in the destroy op. The documentation says
that the size field should be initialized to zero.
|
|
|
|
|
|
| |
ffi.c (ffi_str_put, ffi_str_get, ffi_wstr_put, ffi_wstr_get):
Use assignment instead of memcpy to move the string pointer to
and from the buffer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* buf.c (make_duplicate_buf, buf_get, buf_fill): New
functions.
* buf.h (make_duplicate_buf, buf_get, buf_fill): Declared.
* ffi.c (struct txr_ffi_type): New member, nelem.
Keeps track of number of elements, for types that are
FFI pointers. This lets us support the get method so that
a buf can be a C function return value, if its size is
declared in our FFI type system.
(ffi_buf_put, ffi_buf_get, ffi_buf_fill): New functions.
(ffi_type_compile): Handle two new cases of syntax for
buffers: (buf <size>) and buf.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* configure: New test for dlopen.
* lib.c (cptr_equal_op): Function renamed to
cobj_equal_handle_op, to reflect what it's really
doing; it is not specifically to cptr objects.
Also changed from static to extern.
(cptr_ops): Follow rename.
* lib.h (cobj_equal_handle_op): Declared.
* sysif.c (cptr_dl_destroy_op): New static function.
(dlopen_wrap, dlclose_wrap, dlsym_wrap, dlvsym_wrap): New
static functions.
(sysif_init): Register new intrinsic functions dlopen,
dlclose, dlsym, dlvsym. New variables rtld-lazy, rtld-now,
rtld-global, rtld-local, rtld-nodelete, rtld-noload,
rtld-deepbind.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Makefile (OBJS): Add ffi.o.
* configure (have_libffi): New variable.
(gen_config_make): Generate have_libffi make variable.
New check for availability of libffi.
* ffi.c, ffi.h: New files.
* lib.c (init): Call ffi_init.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* buf.c (buf_put_float, buf_put_cptr, buf_get_float,
buf_get_cptr, align_float, align_cptr, size_float, size_cptr):
New functions.
(buf_init): Registered intrinsics buf-put-float, buf-put-cptr,
buf-get-float, buf-get-cptr, align-float, align-cptr,
size-float, size_cptr.
* buf.h (buf_put_float, buf_put_cptr, buf_get_float,
buf_get_cptr, align_float, align_cptr, size_float, size_cptr):
Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* arith.c (unum): New function.
* arith.h (unum): Declared.
* buf.c (buf_get_bytes): New static function.
(buf_get_i8, buf_get_u8, buf_get_i16, buf_get_u16,
buf_get_i32, buf_get_u32, buf_get_i64, buf_get_u64,
buf_get_char, buf_get_uchar, buf_get_short, buf_get_ushort,
buf_get_int, buf_get_uint, buf_get_long, buf_get_ulong,
buf_get_double): Stubs implemented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unsigned version of cnum becomes less verbose.
* arith.c (c_uint_ptr_num): Renamed to c_unum.
* arith.h (c_uint_ptr_num): Declaration removed.
(c_unum): Declared.
* itypes.c (c_u32, c_u64, c_uint): Follow rename.
* lib.h (ucnum): New typedef.
* rand.c (make_random_state): Follow rename.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Makefile (OBJS): New objects itypes.o and buf.o.
* buf.c, buf.h: New files.
* itypes.c, itypes.h: New files.
* lib.c (obj_print_impl): Handle BUF via buf_print and
buf_pprint.
(init): Call itypes_init and buf_init.
* parser.h (end_of_buflit): Declared.
* parser.l (BUFLIT): New exclusive state.
(grammar): New rules for recognizing start of buffer
literal and its interior.
(end_of_buflit): New function.
* parser.y (HASH_B_QUOTE): New token.
(buflit, buflit_items, buflit_item): New nonterminals
and corresponding grammar rules.
(i_expr, n_expr): These symbols now generate a buflit;
a buffer literal is a kind of expression.
(yybadtoken): Handle HASH_B_QUOTE case.
|
|
|
|
|
|
|
|
| |
* arith.c (ash): The bn <= num_bits comparison
here is always true because bn < 0, leading
to undefined behavior when bn is sufficiently
negative, due to the shift being as wide or
wider than the number of bits in a cnum.
|
|
|
|
|
|
|
| |
* arith.c (comp_trunc, logtrunc, ash): The constant 2
appears here, which corresponds to TAG_SHIFT: the number
of tag bits in an int_ptr_t word. It must be replaced
by TAG_SHIFT.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When we touch the parser.y file, yacc regenerates
y.tab.h. Then everything which depends on that is
rebuilt. However, this is not necessary if the parser.y
change doesn't actually modify the contents of y.tab.h.
A build system based on file hashes wouldn't have this
problem, but make works strictly with modification
timestamps.
* Makefile (y.tab.c): Preserve the old y.tab.h, if
it exists, as y.tab.h.old. Then if the new y.tab.h
is exactly the same according to cmp, restore the
old y.tab.h in its place.
(clean): Remove y.tab.h.old.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Work in progress.
* gc.c (finalize): Add cast to switch expression so gcc
flags when we are missing one of the enumerations.
Handle new BUF enum to free dynamic buffers.
(mark_obj): Mark len and size fields of buf, in case
they aren't just nil or integers.
* hash.c (hash_buf): New static function.
(equal_hash): Route BUF type to hash_buf.
* lib.c (buf_s): New symbol variable.
(code2type): Handle BUF.
(equal): Handle BUF using memcmp on the data.
(obj_init): Intern buf symbol and initialize buf_s.
* lib.h (type_t): New enum member BUF.
(struct buf): New type.
(union obj): New member b, of struct buf type.
(buf_s): Declared.
|
|
|
|
|
|
| |
* share/txr/stdlib/yield.tl (suspend): The body forms
must be inserted into a progn, because sys:abscond-from
just takes one optional value to evaluate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These three forms are not being traversed properly by the
macro expander.
* eval.c (do_expand): Do not treat return-from,
sys:abscond-from and block* in the same case as block.
block* evaluates all of its forms and so can just be walked
as a function call in the fallback case. The other two
must be in their own case because we must not use
expand_progn on them; they do not evaluate a progn-like
list of forms. This leads to inappropriate optimizations
like (return-from x (progn a b c)) -> (return-from x a b c).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Issue: TXR holds numerous symbol references in global
variables, like list_s. These variables are not registered as
root pointers with the garbage collector. This is normally
okay because symbols are reachable via packages. However,
if such a symbol is uninterned, that causes an integrity problem.
Solution: protect those symbols from being removed from their
packages.
* Makefile (OBJS): Add protsym.o.
* genprotsym.txr, protsym.c: New files.
* lib.c (prot_sym_check): New static function.
(use_sym, uintern, rehome_sym): Use prot_sym_check to
implement a defense against internal symbols being booted
out of their package.
|
|
|
|
|
|
|
| |
* eval.c (builtin_reject_test): Issue warnings rather than
errors when built-in macros, functions or operators are
redefined. For now, we don't provide any way to suppress the
warning.
|
|
|
|
|
|
| |
* lib.c (obj_print): Don't assume that if we have a circle
printing context in the stream, circle printing is
enabled. Check the variable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When TXR pattern language code is canned in the context of
an alternative *package* which uses the usr package,
the scanner will throw false errors on @(end) and @(single).
This is because these symbols don't exist in the usr
package and will get interned in the current package.
The scanner will then complain that they are not in the
usr package.
* match.c (syms_init): Intern end and single in the
usr package, but don't store the return value in any
variable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ftw.c (ftw_callback): Pass path to stat_to_struct function.
* socket.c (path_s): Variable definition removed from here.
(sock_load_init): Do not intern path symbol here.
* sysif.c (path_s): Variable definition moved here.
(stat_to_struct): New parameter, path. Store its argument in
the path slot of the structure.
(stat_impl): New parameter, path. Pass argument to
stat_to_struct.
(statp, statl): Pass path down to stat_impl.
(statf): Pass nil down as path argument of stat_impl.
(sysif_init): Intern path symbol here.
Add path_s to the slot list in the make_struct_type
call which creates the stat structure type.
* sysif.h (path_s): Declared here now.
(stat_to_struct): Declaration updated.
* txr.1: Documented new slot of stat structure and
behavior of stat, lstat and fstat w.r.t. this slot.
|
|
|
|
|
|
|
|
| |
Produce better diagnostics for expressions like #[...
or #Habc.
* parser.y (vector, hash, struct, range): Add error
productions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Turns out we have an over-eager parser whcih recognizes
invalid notion such as #[...], #S[...] and others.
This is because the grammar nonterminal list is overloaded
with phrase structures. The syntax of a vector literal,
for instance, is '#' list, but a list can be '[' ...
and other expressions.
* parser.y (dwim, meta, compound): New non-terminal symbols.
Dwim derives the square bracketed "dwim" expressons that were
previously overloaded into list. Meta derives the @ exprs.
compound is what list used to be.
(list): Handle only (...) list expressions.
(o_elem, modifiers): Derives compound rather than list, thus
preserving existing behavior.
(i_expr, n_expr): Likewise.
All other uses references to the list nonterminal
stay, thereby trimming the grammar of dubious expressions.
|
|
|
|
|
|
|
|
|
| |
* parser.c (repl): Support :p and :prompt commands for
printing the current prompt, which is useful in plain mode.
* txr.1: Document the new commands under Interactive Listener.
Also plain mode is documented again here, though it is
described for -n/--noninteractive.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The @{a [3]} syntax in quasiliterals and @(output) now
indexes into the original object a if it is any sequence
kind, not specifically a list. Otherwise it indexes into
its string representation.
* eval.c (format_field): Combine the elements of the
object with the separator if it is any sequence type other
than a string. Subject to compat option.
(subst_vars): Avoid converting any kind of sequence to
string, rather than just lists. After any field formatting
is applied, if the object is any sequence (not just alist),
combine the elements with a space. All subect to compat
option.
* match.c (tx_subst_vars): Same treatment as subst_vars.
* txr.1: Compatibility notes added.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The op macro replaces syntax like @3 with gensyms.
The problem is these genyms are not wrapped with
(sys:var ...). For instance:
`foo@{1}bar` ;; (sys:quasi "foo" (sys:var 1 () ()) "bar")
might, inside an op expression turn into:
(sys:quasi "foo" #:arg001 "bar")
If this object is printed, it renders as
`foo#:arg001bar`
which is garbage syntax. After this fix, that will come
out as:
`foo@{#:arg001}bar`
It is not read/print consistent, but it has the same
meaning under evaluation.
* lib.c (out_quasi_str_sym): New static function.
Formed out of a block of code taken from out_quasi_str.
(out_quasi_str): Print (sys:var ...) symbols via a
call to out_quasi_str_sym, eliminating a block of
code. If an element itself is a symbol, then print
that using out_quasi_str_sym also.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
| |
* parser.l (grammar): Pass yyg to directive_tok
rather than yyscanner. It has the yyguts_t *
type, whereas yyscanner is a void * version of
the same pointer.
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (repl): Set noninteractive mode from noninteractive
option.
* txr.c (help): Mention effect of -n upon listener.
* txr.1: Documented effect of -n/--noninteractive on the
listener.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* linenoise/linenoise.c (struct lino_state): New member,
noninteractive.
(lino_set_noninteractive, lino_get_noninteractive): New
functions.
(linenoise): Check noninteractive flag; if set, treat the
situation like !isatty(ls->ifd).
* linenoise/linenoise.h (lino_set_noninteractive,
lino_get_noninteractive): Delared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem is syntax like `@@12a` being scanned
as if it were `@{@12}a` rather than @{@12a}`.
When the scanner is in the middle of a quasiliteral, in the
QSILIT state and sees a @, it transitions to the QSPECIAL
state.
In the QSPECIAL state, the METANUM token syntax is recognized
consisting of @ followed by a decimal, octal or hex number.
In the same QSPECIAL state, however, a meta-variable like @abc
is not recognized as a unit; rather, a @ is recognized by
itself, and abc by itself. Thus when @12a is seen in the
QSPECIAL state, the @12 is the longest match.
The fix is to treat METANUM tokens the same way in the
QSPECIAL state: just recognize a number without the @
prefix, and report as a METANUM.
* parser.l (grammar): Split the pattern in all four
METANUM rules so that in the NESTED, BRACED,
QSLIT and QWLIT states, the number is recognized
together with the @ prefix. But in the QSPECIAL
state, indicating that one or more @ characters have
been seen, just recognize a number without the prefix
as a METANUM.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register intrinsic functions
time-parse-local and time-parse-utc.
* lib.c (strptime_wrap): New static function.
(time_parse): Now implemented as by call to strptime_wrap.
(time_parse_local, time_parse_utc): New functions.
These get the time_t time from struct tm without
constructing the intermediate Lisp structure.
* lib.h (time_parse_local, time_parse_utc): Declared.
* txr.1: Documented new functions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This bug causes data to be thrown away after reading
one line.
* linenoise/linenoise.c (struct lino_state): New member, ifs.
(linenoise): Do not fdopen a new stream on each call, because
this will read a buffer full of data, from which it will just
read one line, and then throw the rest of away when fclose
is called on the stream. Open the stream once and store it
in the ifs member.
(lino_cleanup): If the ifs member is non-null, then
call fclose on it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These functions don't conform with the documentation. For
instance [apply list "abc"] yields "abc". It is supposed to
yield (#\a #\b #\c), since the characters of "abc" must become
individual arguments to list. Part of the fix is in the
apply_frob_args logic; however, we have to clone that function
because it is used for implementing other things which
will break: we cannot, for for example, have (list* 1 "ab")
producing (1 #\a #\b).
* eval.c (apply_intrisic_frob_args): New static function.
Differs from apply_frob_args in that it calls tolist
on the final element.
(apply_intrinsic): Use apply_intrinsic_frob_args
instead of apply_frob_args.
(iapply): Invoke tolist on the value assigned to last_arg.
* txr.1: Add a clarifying note for iapply that the terminating
atom is not split into arguments if it is a sequence.
|
|
|
|
|
|
| |
* txr.1: copy-struct is a low-level mechanism. Higher
level object cloning must be built on top of it, if
required. This is now noted in the documentation.
|
|
|
|
| |
* txr.1: number agreement: "each values" -> "each value".
|
|
|
|
|
| |
* txr.1: Under the description of the car, cdr and nullify
methods, the description of car must start a new paragraph.
|
|
|
|
|
|
|
|
|
|
|
| |
* txr.1: Under description of the equal method, replace the
text about a hash table "not working reliably" with proper
"unspecified behavior" terminology. Add some paragraphs to the
introduction to hash tables about the issue of modifying the
car fields of hash entry cells, or mutating the keys in
equal-based hash tables such that their equality is affected.
Re-iterate some of these points in a few other places under
the descriptions of some hash-related functions.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This issue has implications mainly for read/print consistency.
The (rcons a .b) expression prints a...b, but that doesn't
read back. The reason is that the . on .b isn't preceded by
whitespace, and so isn't the UREFDOT token recognized in
a n_expr. It's just the '.' token which is a syntax error
in that situation.
* parser.y (n_expr): New special case rule to handle the
phrase pattern n_expr DOTDOT '.' n_expr which is now
a syntax error.
|
|
|
|
|
| |
* parser.l: Remove the pattern match which causes 0.1..0
to be rejected.
|
|
|
|
|
|
|
|
|
| |
Currently (list .1.1) yields (0.1 0.1). This is evading the
rule for catching cramped floating-point literals.
* parser.l (grammar): Carefully weaken the pattern match in
the relevant rule for catching cramped floating-point
literals, so it matches these cases.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some recent work in supporting .slot syntax (uref dot) broke
the treatment of floating point literals. This is because part
of the trick is that a uref dot is recognized with leading
whitespace as part of the token. But that of course means
it steals the match for some floating-point tokens; oops!
* parser.l (grammar): All rules for floating-point tokens
which can match a leading decimal point now munch optional
whitespace first.
|