summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
* ffi: rename ptr-in-out to just ptr.Kaz Kylheku2017-04-292-7/+7
| | | | | | | | | | | | Why have this verbose naming for the most basic case. Rather, ptr-in and ptr-out are optimizations of ptr which just avoid copying the object in one direction. * ffi.c (ptr_in_out_s): Renamed to ptr_s. (ffi_ptr_in_out_put): Renamed to ffi_ptr_put. (ffi_type_compile, ffi_init): Follow rename. * ffi.h (ptr_in_out_s): Declaration updated
* ffi: malloc-free variants for str, dstr and buf.Kaz Kylheku2017-04-292-8/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The FFI types str-d, wstr-d and buf-d are like their unsuffixed counterparts, but indicate that ownership of a dynamically allocated object is being passed which the receiver is responsible for freeing. If we pass a str, wstr or buf into a foreign function, we are generally only guaranteeing the lifetime of the buffer over the function call. If we pass a str-d or buf-d, then the callee keeps the pointer indefinitely, and must free it. If we get str or buf return value from a function, it is assumed that the pointer is static or something borrowed with some limited lifetime. A copy of it is made. If we get a str-d, wstr-d or buf-d, it is assumed that the pointer has been malloc-ed for us. The object is either duplicated, and the original one immediately freed, or else the pointer is retained directly in the Lisp object and freed if that object becomes garbage. * ffi.c (str_d_s, wstr_d_s, buf_d_s): New symbol variables. (ffi_str_get): Coalesce assignment with declaration. (ffi_str_d_get, ffi_str_d_put): New static functions. (ffi_buf_d_get, ffi_buf_d_put): New static functions. (ffi_type_compile): Handle buf_d_s, str_d_s and wstr_d_s. (ffi_init): Initialize str_d_s, wstr_d_s and buf_d_s. * ffi.c (str_d_s, wstr_d_s, buf_d_s): Declared.
* ffi: correct treatment of (ptr buf).Kaz Kylheku2017-04-293-1/+8
| | | | | | | | | | | | | | The buf FFI type's alloc virtual should return a pointer to the buffer's pointer, not the buffer itself. What's currently going on is something silly, whereby the pointer to the buffer is stored into the buffer itself. * buf.c (buf_addr_of): New function. * buf.c (buf_addr_of): Declared. * ffi.c (ffi_buf_alloc): Use buf_addr_of instead of buf_get.
* ffi: bugfix: ptr-in doesn't write pointer.Kaz Kylheku2017-04-281-0/+1
| | | | | | * ffi.c (ffi_ptr_in_put): We must write the allocated buffer's pointer to the destination memory location, otherwise nothing is passed, but garbage.
* ffi: drop obsolete restrictions in type compiler.Kaz Kylheku2017-04-281-8/+0
| | | | | | * ffi.c (ffi_type_compile): The ptr-out and ptr-in-out types can work with target types that don't have a fill function and fixed allocation.
* ffi: sane calculation of rtsize.Kaz Kylheku2017-04-281-9/+7
| | | | | | | | | | | | | | | | | | | | | | | | | We are wastefully giving structs and arrays a position in the rtvec. They do not need one. Let's calculate like this. During compilation, let's assign a rtsize value of 1 to types which need to occupy a position. During the tree walk which assigns the positions, let's use this as a Boolean value indicating whether to assign and index or not. After the tree walk, the final counter value indictates the rtsize for the whole aggregate, and we store that in the rtsize of the root type node. * ffi.c (make_ffi_type_struct, make_ffi_type_array): Do not add up the rtsizes of the elements/members and thus do not install the total size as this type's rtsize. Leave the rtsize zero. We revert to a variation of the previous method of determining whether to install the in handler, but using a slightly different criterion: if any child element has a nonzero rtsize or if it has an in handler. (assign_rtindices_visit): Use nonzero rtsize as the condition for whether to give the node an rtindex or not. (ffi_type_assign_rtindices): Store the final count as the rtsize of the root type node. This is then used to allocate the rtvec for that type in ffi_call_wrap.
* ffi: assign better Lisp types to some ffi types.Kaz Kylheku2017-04-281-4/+4
| | | | | | * ffi.c (ffi_type_compile): Type descriptors for str, wstr, buf and void are being tagged with the Lisp type cptr. Let's give them str, str, buf and null, respectively.
* ffi: move run-time state out of txr_ffi_type.Kaz Kylheku2017-04-281-112/+200
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The txr_ffi_type has the buf member, which is manipulated when FFI calls are being dispatched. That is wrongly non-reentrant; it will interfere with the same type structure being used recursively. The objects describing FFI types must be treated as immutable with respect to dynamic FFI processing. The approach here is is to move these buf pointers into a a run-time vector ("rtvec"). The types whose handling requires the temporary buf pointer are assigned a position in that vector (the "rtidx"). These positions are assigned to the nodes of a type by a tree walking step after compilation. When performing a FFI call, we allocate space for the rtvec for each argument type. This is vector is passed down into the data transfer calls, and is used wherever needed, using a type's rtidx to find its buffer pointer location. * ffi.c (struct txr_ffi_type): function functoin poiner member, walk. The put and in functions get a new argument: the rtvec. New members rtidx and rtsize. The buf member is removed. (ffi_builtin_type_destruct_destroy_op): Static function removed. There is no need to clean any run-time buffer from a type, since types are no longer associated with any such thing. And that leaves the function just freeing the obj->co.handle which is already done by cobj_destroy_free_op. (ffi_type_struct_destroy_op, ffi_type_struct_destroy_op): Remove the call to the in virtual function for the same reason. (ffi_type_builtin_ops, ffi_type_ptr_ops): Replace removed ffi_builtin_type_struct_destroy_op with cobj_destroy_free_op. (ffi_void_put, ffi_i8_put, ffi_u8_put, ffi_i16_put, ffi_u16_put, ffi_i32_put, ffi_u32_put, ffi_i64_put, ffi_u64_put, ffi_char_put, ffi_uchar_put, ffi_short_put, ffi_ushort_put, ffi_int_put, ffi_uint_put, ffi_long_put, ffi_ulong_put, ffi_float_put, ffi_double_put, ffi_cptr_put): Conform to new put interface with the rtvec argument. It is ignored in all these functions. (ffi_freeing_in, ffi_str_put, ffi_wstr_put, ffi_buf_put, ffi_ptr_in_in, ffi_ptr_in_put, ffi_ptr_out_in, ffi_ptr_out_put, ffi_ptr_in_out_put, ffi_struct_in, ffi_struct_put, ffi_array_in, ffi_array_put) Conform to new function interface with the rtvec and use it together with the rtidx from the type to store and retrieve the buf, if necessary. (ffi_ptr_walk, ffi_struct_walk): New functions. (make_ffi_type_builtin): Parameter declaration updated due to changes in put and in function pointer types. (make_ffi_type_pointer): Configure pointer's rtsize to 1 since pointers manage temporary buffers, and give it the ffi_ptr_walk function, since it has a subordinate type which it must visit. (make_ffi_type_struct): Calculate the size of the rtvec which a struct's members need. Use the nonzero value of this as the indication that the structure need's an in function, thus eliminating the loop flag being used for this purpose. Install the ffi_struct_walk function for walk. (make_ffi_type_array): Similar changes as in make_ffi_type_struct. Calculate rtsize from element rtsize times number of elements. If that is nonzero wire in ffi_array_in. Also wire in ffi_struct_walk. (ffi_type_walk): New static function. (assign_rtindices_visit, ffi_type_assign_rtindices): New functions. (ffi_type_compile): Set the rtsize for the str type to 1, because it manages a temporary buffer across the FFI call, and thus needs a slot in the rtvec. (ffi_type_compile_toplevel): New function. (ffi_call_wrap): Allocate vector of rtvectors based on total number of arguments. For each argument allocate an rtvector in this vector, if necessary and pass down to the put calls. Then pass to the in calls after the FFI call returns. Thus the framework has the proper environment where to store all the temporary buffer pointers that need to be communicated from the pre-call data transfer pass to the subsequent cleanup. (ffi_init): Register the ffi_type_compile_toplevel function as the ffi-type-compile intrinsic, rather than the ffi_type_compile function. Application space probably doesn't need to have exposure to compiler output which doesn't have the correct rtidx values, and there is a risk it could be accidentally used.
* ffi: setup in functions at type compile time.Kaz Kylheku2017-04-281-18/+19
| | | | | | | | | | | | | | | | | | | | * 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.
* ffi: rename cptr-related functions.Kaz Kylheku2017-04-281-5/+5
| | | | | | | | | | 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: allow ptr-in-out passing of cptr.Kaz Kylheku2017-04-283-3/+27
| | | | | | | | | | | | | | | * 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.
* ffi: use chk_calloc for txr_ffi_type.Kaz Kylheku2017-04-281-4/+2
| | | | | | | | | 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.
* ffi: buf type doesn't need fill function.Kaz Kylheku2017-04-281-11/+2
| | | | | | | | | | | | | 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.
* ffi: properly recurse the handling of pointers.Kaz Kylheku2017-04-271-18/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: fix problems caught by g++.Kaz Kylheku2017-04-272-8/+5
| | | | | | | | | | | | | | * 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.
* ffi: sane in/out protocol; buffers work directly.Kaz Kylheku2017-04-271-6/+46
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: array support.Kaz Kylheku2017-04-262-0/+98
| | | | | | | | | | | * 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: incorrect handling of struct element array.Kaz Kylheku2017-04-261-6/+11
| | | | | | | | | | | | | | | * 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: no memcpy for string pointers.Kaz Kylheku2017-04-261-7/+6
| | | | | | 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.
* ffi: support buf objects.Kaz Kylheku2017-04-263-0/+66
| | | | | | | | | | | | | | | | * 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.
* Provide access to dlopen.Kaz Kylheku2017-04-254-2/+141
| | | | | | | | | | | | | | | | | | | | * 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.
* Start of FFI implementation based on libffi.Kaz Kylheku2017-04-245-0/+1225
| | | | | | | | | | | | * 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.
* Buffers: missing float and cptr.Kaz Kylheku2017-04-242-0/+46
| | | | | | | | | | | | | * 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.
* Buffers implementation, part three: get functions.Kaz Kylheku2017-04-213-17/+129
| | | | | | | | | | | | | * 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.
* Rename c_uint_ptr_num; introduce cunum typedef.Kaz Kylheku2017-04-215-6/+7
| | | | | | | | | | | | | | | 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.
* Continuing implementation of buffers.Kaz Kylheku2017-04-219-4/+1071
| | | | | | | | | | | | | | | | | | | | | | | | | | * 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.
* Bugfix: ash: right shifts of fixnums broken.Kaz Kylheku2017-04-201-1/+2
| | | | | | | | * 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.
* Use TAG_SHFIT instead of hard-coded 2.Kaz Kylheku2017-04-201-3/+3
| | | | | | | * 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.
* Makefile: detect when y.tab.h doesn't change.Kaz Kylheku2017-04-191-0/+5
| | | | | | | | | | | | | | | | 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.
* New buffer data type.Kaz Kylheku2017-04-164-4/+71
| | | | | | | | | | | | | | | | | | | | | | | 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.
* Bugfix: incorrect substitution in suspend macro.Kaz Kylheku2017-04-151-1/+1
| | | | | | * 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.
* Bugfix expansion: return-from, sys:abscond-from, block*.Kaz Kylheku2017-04-151-3/+8
| | | | | | | | | | | | | | 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).
* Protect internal symbols from uninterning.Kaz Kylheku2017-04-154-3/+273
| | | | | | | | | | | | | | | | | | | | 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.
* Make it a warning only when built-ins redefined.Kaz Kylheku2017-04-141-4/+4
| | | | | | | * 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.
* Honor *print-circle* disabling in print methods.Kaz Kylheku2017-04-121-6/+10
| | | | | | * 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.
* Bugfix: missing usr:end and usr:single symbols.Kaz Kylheku2017-04-111-0/+6
| | | | | | | | | | | | | | 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.
* New path slot in stat struct.Kaz Kylheku2017-04-085-15/+40
| | | | | | | | | | | | | | | | | | | | | | | | * 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.
* parser: add some error cases to hash notations.Kaz Kylheku2017-04-081-1/+9
| | | | | | | | Produce better diagnostics for expressions like #[... or #Habc. * parser.y (vector, hash, struct, range): Add error productions.
* parser: refactor grammar to banish #[] etc.Kaz Kylheku2017-04-071-16/+26
| | | | | | | | | | | | | | | | | | | | 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.
* listener: :p and :prompt commands.Kaz Kylheku2017-04-062-0/+42
| | | | | | | | | * 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.
* Indexing in variable subst applies to any sequence.Kaz Kylheku2017-04-053-14/+47
| | | | | | | | | | | | | | | | | | | | 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.
* quasiliterals: issue in printing embedded syms.Kaz Kylheku2017-04-051-28/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Version 174.txr-174Kaz Kylheku2017-04-046-78/+118
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* parser: C++ regression.Kaz Kylheku2017-04-041-30/+30
| | | | | | | * 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.
* Connect -n option to linenoise noninteractive mode.Kaz Kylheku2017-04-043-1/+21
| | | | | | | | | | * 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: support forcing of noninteractive mode.Kaz Kylheku2017-04-042-1/+14
| | | | | | | | | | | | * 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.
* parser: bugfix: don't scan @NUM in QSPECIAL state.Kaz Kylheku2017-04-041-3/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* New time-parse-local and time-parse-utc functions.Kaz Kylheku2017-04-044-6/+56
| | | | | | | | | | | | | | | * 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.
* linenoise: bugfix: use persistent stream for non-tty.Kaz Kylheku2017-04-031-12/+18
| | | | | | | | | | | | | | 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.
* apply and iapply bugfix: split sequences into args.Kaz Kylheku2017-04-032-3/+21
| | | | | | | | | | | | | | | | | | | | | 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.