| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The realpath function is called using FFI. One approach
passes a null pointer, so that the function dynamically
allocates. The return value is str-d, causing FFI to take
ownership of the pointer, freeing it. The other approach
is to pass a pointer to a large null-terminated character
array, marked for ownership transfer to the function. FFI
allocates it and puts the argument into it, which is just
a dummy empty string. The function fills that buffer and
returns it. The return is captured as a str-d, so FFI takes
ownership back, and frees the buffer.
* tests/017/realpath.tl: New function.
* tests/017/realpath.expected: Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
One approach captures the paths as a carray of
strings, and explicitly frees it with globfree.
The other approach uses a zarray, taking advantage
of null termination. globfree is elided because TXR FFI
does the freeing; the types used declare to it that it
is taking ownership of a dynamically allocated vector of
dynamically allocated strings, and so it performs the
equivalent of globfree.
* tests/017/glob-carray.expected: New file.
* tests/017/glob-carray.tl: Likewise.
* tests/017/glob-zarray.expected: Likewise.
* tests/017/glob-zarray.tl: Likewise.
|
|
|
|
|
|
|
|
| |
Materials specific to distribution building and packaging
systems should be maintained by distributions; they
don't belong in the projects themselves.
* txr.spec: File removed.
|
|
|
|
|
|
|
|
| |
* lisplib.c (ffi_set_entries): Autload entry for "deffi-var".
* share/txr/stdlib/ffi.tl (deffi-var): New macro.
* txr.1: Documented.
|
|
|
|
|
| |
* txr.1: typedef moved below deffi-cb, so it it is together
with sizeof.
|
|
|
|
|
|
|
| |
* share/txr/stdlib/ffi.tl (deffi): Since the arity of
a foreign function is fixed, generate a fixed-argument
defun. This provides a better check on the number of
arguments than letting ffi-call detect it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_call_wrap): Take struct args * parameters
rather than a list. Check that number of arguments
matches required number from call desc. No need
to build argument array any more; we just refer to
the one in args. Also, the first two parameters
are reversed for consistency with other functions.
(ffi_init): Update registration of ffi-call to
reflect type change.
* ffi.h (ffi_call_wrap): Declaration updated.
* txr.1: Documented ffi-call.
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (ffi_set_entries): Add carray-ref to list of
autoload names.
* share/txr/stdlib/ffi.tl (carray-ref, carray-refset):
Registered function pair as a simple accessor.
* txr.1: Updated carray-ref doc.
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_varray_null_term_in): New static function.
(ffi_type_compile): Wire in new function as in operation
of variable length zarray.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (carray_buf_sync): New function.
(ffi_init): carray-buf-sync intrinsic registered.
* ffi.h (carray_buf_sync): Declared.
* txr.1: Documented.
|
|
|
|
|
| |
* ffi.c (carray_buf): Do not allow an element type with
zero size; throw an exception.
|
|
|
|
|
|
|
| |
* ffi.c (carray_buf): Do the buf_get first, then
length_buf, since buf_get takes a self argument.
This way the diagnostic is better if the object
isn't a buf.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (carray_cptr): New function.
(ffi_init): Registered intrinsic.
* ffi.h (carray_cptr): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
| |
* txr.1: Fix misleading text which says that variable
arrays correspond to pointers. They do not; they must
be wrapped in expicit (ptr ...). Also documenting
new get operation of variable zarray.
|
|
|
|
|
|
| |
* ffi.c (ffi_varray_null_term_get): New static function.
(ffi_type_compile): Install the new get function for
variable length zarray.
|
|
|
|
|
|
|
|
|
| |
Ban types like (struct foo (bar void)) or
(array 3 (array int)).
* ffi.c (ffi_struct_compile): Check every element type for
zero size and diagnose.
(ffi_type_compile): Likewise, for arrays.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/awk.tl (sys:awk-state loop):
Wrap a loop around around the two forms that
split the record into fields and dispatch the main
rule function. The loop repeats if the named
block returns :awk-again.
(sys:awk-mac-let): New local macro (again)
which bails out of the :awk-rec block just like (next) does,
but specifies :awk-again as the return value.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Continuing on the topic of the previous commit, what if in a
callback an error occurs in the put operation that produces
the return value? In that case we end up clobbering with
the abort_retval or nulling out with zero bytes, either way
potentially leaking memory.
* ffi.c (ffi_closure_dispatch_safe): If the return value type
has release semantics, then as the very first thing, null out
the return value buffer. Then later if a dynamic control
transfer is intercepted, invoke the release semantics before
doing anything to the return value buffer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem is that the argument conversions in a FFI call can
bail due to an exception, leaving the argument space partially
initialized, and containing pointers to temporary buffers that
have been allocated with malloc.
In this change, we take care of this problem.
We introduce a new virtual function called release to the FFI
type hieararchy. Most types do not implement this: only types
that have something to free, or aggregates which have to
iterate over element types.
The release virtual relies on pointers being null if nothing
has been allocated. For this reason, we allocate the argument
space and all temporar areas with zero filling.
* ffi.c (zalloca): New macro.
(struct txr_ffi_type): New member function pointer, release.
(ffi_fixed_alloc): Use chk_calloc instead of chk_malloc,
so that any pointers in the area are null.
(ffi_varray_alloc): Use chk_calloc, which simplifies the
code.
(ffi_simple_release, ffi_ptr_in_release, ffi_struct_release):
New static functions.
(ffi_array_release_common, ffi_array_release,
ffi_varray_release): New static functions.
(make_ffi_type_pointer): New argument for specifying release
function.
(make_ffi_type_struct): Initialize release member of type
structure to ffi_struct_release.
(make_ffi_type_array): Initialize release member of type
structure to ffi_array_release.
(ffi_type_compile): Set up release function for varray,
several ptr variants and buf-d.
(ffi_init_types): Set up release function for string types.
(ffi_call_wrap): Internals restructured. Instead of repeatedly
processing type and arg lists, we now store them into arrays
allocated with alloca. We allocate the argument space with
zalloca instead of alloca. Allocating the arguments is
separated from the put conversions into two loops, because
the alloca calls must be outside of the unwind catching
block. This is because the unwind control transfer will roll
back the alloca allocation done since the establishment of
the catch block! A new unwind block now iterates over the
arguments and calls release on each one which has a release
function.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_buf_in): Only get the original pointer if obj
isn't nil; otherwise use a null pointer.
(ffi_buf_d_in): Don't refer to length_buf(obj); obj could
be nil. And anyway, we know the buffer size from the type.
|
|
|
|
| |
* txr.1: Documented the total current state of carray.
|
|
|
|
|
|
| |
* ffi.c (length_carray): Convert the internal representation
of unknown length, which is a -1 of type cnum, into a nil
return value.
|
|
|
|
|
|
| |
* ffi.c (carray_free): Don't just reset the pointer
to null, but also set the number of elements to zero.
That will prevent indexing operations from dereferencing null.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_buf_in): The bug in this one is that if *loc
has been mutated to a null pointer, we want to produce
a nil, rather than to try to duplicate the buffer.
(ffi_buf_d_in): The bug here is that *loc is always
different from origptr, because origptr is from the original
buffer object, whereas we placed a copy of it into *loc.
The semantics is changed. We take ownership of whatever
pointer is there. If it is null, then yield nil.
* txr.1: buf and buf-d documentation revised.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This issue was revealed as a garbage line number in
an unbound variable warning diagnostic, where the variable
occurs in a quasi word list literal. A small test case
is (list #`@var`) where var unbound.
The fix is, in the lexer, to set the yylval->lineno for all
tokens which are declared as <lineno> in the grammar file,
for which doing so has beens neglected. We do this even for
those tokens whose line number values are never accessd in any
rule; it could arise in the future.
* parser.l (grammar): Set the yylval->lineno for the tokens
HASH_BACKSLASH, HASH_B_QUOTE, HASH_SLASH, WORDS, WSPLICE,
QWORDS and QWSPLICE.
|
|
|
|
|
|
|
|
|
| |
Treat a buffer through a carray view.
* ffi.c (carray_buf): New function.
(ffi_init): Register carray-buf intrinsic.
* ffi.h (carray_buf): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The idea here is that carrays can have a pointer to some area
that is owned by another object. So that the area doesn't
disappear when the other object becomes garbage, a carray
which does this maintains a pointer to that other object.
* ffi.c (ffi_carray_get): Pass new parameter to make_carray.
(struct carray): New member, ref.
(carray_mark_op): Mark new ref member.
(make_carray): New parameter: the object which is stored in
the structure as ref.
(carray_dup): Null out the ref member. When a carray
is duplicated, it owns its own buffer, and henceforth mustn't
prevent the original object from being reclaimed.
(carray_own): Don't allow a carray to claim ownership
of the pointer if it references another object; we have
no protocol to inform that other object.
* ffi.h (make_carray): Declaration updated.
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (ffi_set_entries): Add "ffi" to autoload name
list.
* share/txr/stdlib/ffi.tl (ffi): New macro.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/ffi.tl (typedef): New macro.
* lisplib.c (ffi_set_entries): Add typedef to autoload
name list.
* txr.1: Doc update. Remove mentions of deffi-type,
though it continues to work.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The carray type deals with C array passing conventions
as a pointer to the first element of an array of
unknown size. It fills in the functionality gap not
covered by array and varray.
* ffi.c (carray_s): New symbol variable.
(ffi_carray_get, ffi_carray_put): New static functions.
(ffi_type_compile): Handle (carray <type>) syntax.
(struct carray): New struct type.
(carray_struct, carray_struct_checked, carray_print_op,
carray_mark_op, carray_destroy_op): New static functions.
(carray_borrowed_ops, carray_owned_ops): New static structs.
(make_carray, carray_set_length, carray_dup, carray_own,
carray_free, carray_type, length_carray, carray_get,
carray_vec, carray_blank, vec_carray, list_carray, carray_ref,
carray_refset): New functions.
(ffi_init): Initialize carray_s. Register
carray-set_length, carray_dup, carray_own,
carray-free, carray_type, length_carray,
carray-vec, array_blank, vec_carray, list_carray, carray_ref
and carray-refset intrinsics.
* ffi.h (carray_s): Declared.
(make_carray, carray_set_length, carray_dup, carray_own,
carray_free, carray_type, length_carray, carray_get,
carray_vec, carray_blank, vec_carray, list_carray, carray_ref,
carray_refset): Declared.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
The type compiler specifies cptr as the Lisp type for various
ptr types and the buf type. This will be misleading with the
increasing role of cptr.
* ffi.c (ffi_get_lisp_type): New static function.
(ffi_type_compile): Use buf as the Lisp type for the buf
and buf-d FFI types. For ptr and its variants, use the
target type's Lisp type as the pointer's Lisp type.
For instance (ptr int) has integer as its Lisp type.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In sysif.c, we have conditionally defined symbol variables.
This has to be reflected with #if directivec in protsym.c.
* genprotsym.txr: Associate each symbol with a list
of preprocessor symbols which controls it, via a hash.
All symbols coming from a conditional file are tagged with
a list which includes at least the controlling symbol.
If symbols are wrapped with #if <sym> directives, that
is added. Nesting is supported. We group the symbols
according to their controlling preprocessor symbol lists.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
CPTR shares representation and a lot of implementation with
COBJ. The COBJ class symbol is the CPTR type tag. There is no
hierarchy among CPTR tags. The nil tag is used for a modicum
of type looseness, so that we don't straitjacket ourselves
too much into this tag-based typing scheme.
All existing cptr objects are becoming CPTR, and all
get a nil tag, except for dlopen library handles, and
dlsym symbols, which are tagged as dlhandle and dlsym.
The FFI framework will support tag-declared cptr's. This will
help with safety. For instance, suppose an API has half a
dozen different kinds of opaque handles. If they are all just
cptr on the TXR Lisp side, it's easy to mix them up, passing
the wrong one to the wrong C function.
* lib.h (enum type): New enum member, CPTR.
(cptr_print_op, cptr_typed, cptrp, cptr_type, cptr_handle):
Declared.
(cptr_addr_of): Parameters added.
* lib.c (code2type): Map CPTR type code to cptr_s.
(equal): Handle CPTR objects. They are only equal to other
CPTR objects which have the same operations, and
are equal under the equal function of those operations.
(cptr_print_op): New function.
(cptr_ops): Use cptr_print_op rather than cobj_print_op.
(cptr_typed): New function.
(cptr): Use cptr_typed to make a cptr with tag nil,
rather than using cobj.
(cptrp, cptr_handle, cptr_type): New functions.
(cptr_get): Go through cptr_handle rather than cobj_handle.
(cptr_addr_of, cptr_zap, cptr_free): Use call to cptr_handle
rather than cobj_handle for the type checking side effect.
New parameters for type and parent function name.
(obj_print_impl): Handle CPTR with same case as COBJ.
* gc.c (finalize, mark_obj): Handle CPTR cases using
common code with COBJ.
* hash.c (equal_hash): Handle CPTR just like COBJ.
* eval.c (eval_init): Register cptrp and cptr-type intrinsic
functions.
* ffi.c (ffi_cptr_put, ffi_cptr_get, ffi_cptr_alloc): Use the
potentially type-safe cptr_handle, instead of cptr_get.
However, for an untagged cptr, there is no type safety because
tft->mtypes is nil. The argument can be any kind of cptr.
* sysif.c (dlhandle_s, dlsym_s): New symbol variables.
(cptr_dl_ops): Use cptr_print_op.
(dlopen_wrap, dlclose_wrap): Use typed cptr with
dlhandle as the type.
(dlsym_wrap, dlsym_checked, dlvsym_wrap, dlvsym_checked):
Recognize only a cptr of type dlhandle for the library.
Construct a typed cptr of type dlsym.
(sysif_init): Initialize dlhandle_s and dlsym_s.
Register dlsym function using dlsym_s.
|
|
|
|
|
|
|
|
|
|
| |
* lib.c (less_tab_init): The type_prec table initialization
will become incorrect if new type enums are added other than
at the end. Let's switch to assignments. Anything not
mentioned is zero.
* lib.h: Add more advice to comment about extending type_t:
consider all places where MAX_TYPE is used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Since cptr objects are equal if their handles are equal, they
must have a hashing function over the handle rather than over
their own address.
* lib.c (cobj_handle_hash_op): New function.
(cptr_ops): Use cobj_handle_hash_op instead of
cobj_eq_hash_op.
* lib.h (cobj_handle_hash_op): Declared.
* sysif.c (cptr_dl_ops): Use cobj_handle_hash_op instead of
cobj_eq_hash_op.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Renaming cobj_hash_op to cobj_eq_hash_op. This function is
only appropriate to use with COBJ objects which use
eq as their equal funtion. I've spotted one instance of an
inappropriate use which have to be addressed by a different
commit: the equal function is other than eq, but cobj_hash_op
is used for the equal hash.
* lib.h (cobj_hash_op): Declaration renamed to
cobj_eq_hash_op.
* hash.c (cobj_hash_op): Renamed to cobj_eq_hash_op.
(hash_iter_ops): Refer to renamed cobj_hash_eq_op.
* ffi.c (ffi_type_builtin_ops, ffi_type_struct_ops,
ffi_type_ptr_ops, ffi-closure_ops, ffi_call_desc_ops):
Likewise.
* lib.c (cptr_ops): Likewise.
* parser.c (parser_ops): Likewise.
* rand.c (random_state_ops): Likewise.
* regex.c (char_set_ops, regex_obj_ops): Likewise.
* socket.c (dgram_strm_ops): Likewise.
* stream.c (null_ops, stdio_ops, tail_ops, pipe_ops, dir_ops,
string_in_ops, byte_in_ops, strlist_in_ops, string_out_ops,
strlist_out_ops, cat_stream_ops, record_adapter_ops):
Likewise.
* struct.c (struct_type_ops): Likewise.
* sysif.c (cptr_dl_ops): Likewise.
* syslog.c (syslog_strm_ops): Likewise.
* unwind.c (cont_ops): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The protsym.c generated file refers to symbol variables
without regard for whether they actually exist.
Some symbol variables are defined in source files whose
object files are only linked in conditionally.
* genprotsym.txr: Update the logic to scan the Makefile
to determine which files are conditionally included, based on
what makefile flag, which is related to a preprocessor symbol.
Thus, with some hashes, for each symbolic variable we
subsequently scan, we know whether it came from a file that is
associated with a preprocessor symbol. We group the emitted
material accordingly, placing the conditionally existent
symbols into #if...#endif blocks.
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure, txr.1: Bumped version and date.
* share/txr/stdlib/ver.tl: Likewise.
* txr.vim, tl.vim, protsym.c: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_varray_alloc, ffi_char_array_put): Use cnum type
consistently to avoid signed/unsigned comparison warning from g++.
(ffi_closure_dispatch_safe): Put block of code into a braced
statement so that the macro-generated switch case branch isn't
crossing the initialization of a variable. Also, convert
cast added where we are passing a void * to a mem_* parameter.
* utf8.c (utf8_dup_from): Fix coerce macros being used to strip
qualifiers, not only convert type.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (make_catenated_stream): Fix incorrect order
of operations: list of streams stored into a structure
that is not yet visible to the garbage collector.
(Rules for coding this properly are explained in
HACKING.) This was found by running a test with --gc-debug
on 64 bit Darwin. The read_eval_stream function calls
make_catenated_stream with an argument that is freshly
constructed in the argument expression itself, triggering
the issue.
|
|
|
|
|
|
|
|
|
|
|
| |
* tests/017/qsort.expected: New file.
* tests/017/qsort.tl: New file.
* tests/common.tl (libc): New function.
* Makefile (tst/tests/017/%): Clear TXR_DBG_OPTS so the GC
stress test isn't applied to tests in this directory.
|
|
|
|
|
|
|
|
|
|
| |
* tests/common.tl (osname): Function based on calling
shell command removed.
(os-symbol): New symbol-returning function based on
uname system call.
* tests/014/dgram-stream.tl (dgram-test): Use os-symbol
function rather than osname.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When taking ownership of any pointer from FFI space, null it
out. This is safer in general and prevents corruption
problems in the callback interface when an exception is
thrown. For instance (ptr wstr-d) callback argument:
callback takes ownership of the pointer in a string object;
throws an exception. The FFI call dispatch runs the in
semantics to get the string value out; but the old pointer
is still there which may not be used.
* ffi.c (ffi_str_d_get, ffi_wstr_d_get, ffi_bstr_d_get,
ffi_buf_d_in, ffi_buf_d_get, ffi_ptr_d_get): Overwrite
the source location of a freed or owned pointer with
null.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The direct pointer use of the wstr type causes problems
for callbacks. Plus allowing the foreign world to retain
the pointers into string objects is inherenty unsafe.
We can introduce an "unsafe wstr" type in a later release
for efficiency.
* ffi.c (ffi_wstr_in): New function.
(ffi_wstr_put): Removed by ffi_wstr_d_put rename.
(ffi_wstr_d_put): Renamed to ffi_wstr_put: both wstr and
wstr-d strings have a dynamically-allocating put.
(ffi_init_types): Give wstr type ffi_wstr_in handler.
wstr-d type's registration switched to ffi_wstr_put,
which is just ffi_wstr_d_put renamed.
* txr.1: Memory management notes for wstr updated.
|
|
|
|
|
|
|
|
| |
* gc.c (gc_free_all): Mark defined the current block being
iterated, not the next one. Otherwise Valgrind generates
numerous false errors from accesses to free objects in the
first block. Not to mention that next is a null pointer in
the last iteration.
|
|
|
|
|
|
|
| |
* gc.c (mark_obj): The vector alloc size and length
which lie at negative indices should be accessed using
the index constants vec_alloc and vec_length, rather
than -2 and -1.
|
|
|
|
|
|
|
|
| |
* configure: detect clockid_t and loff_t, providing
HAVE_CLOCKID_T and HAVE_LOFF_T config macros.
* ffi.c (ffi_init_extra_types): Register clockid-t
and loff-t types only if available.
|
|
|
|
|
| |
* itypes.c (c_i64): Fix c_num being called on the function
pointer num rather than the correct operand n.
|
|
|
|
| |
* inst.nsi: Add cygffi-6.dll to package.
|