summaryrefslogtreecommitdiffstats
path: root/stream.c
Commit message (Collapse)AuthorAgeFilesLines
* cobj: clone method streamlines copy; structs get copy method.Kaz Kylheku2024-06-171-12/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.h (struct cobj_ops): New function pointer, clone. (cobj_ops_init, cobj_ops_init_ex): Add clone argument to macros. * lib.c (seq_iter_cobj_ops): Use copy_iter as the clone operation. (cptr_ops): Use copy_cptr as clone operation. (copy): Replace if statements by check whether COBJ has a clone operation. If so, we use it to copy the object. * struct.h (enum special_slot): New member, copy_m. * struct.c (copy_s): New symbol variable. (special_sym): Associate copy_m enum value with copy symbol. (struct_init): Initialize copy_s with interned symbol. (struct_inst_clone): New static function. (struct_type_ops): Specify no clone operation via null pointer. (struct_inst_ops): Specify struct_inst_clone as clone operation. * arith.c (psq_ops): Indicate no clone operation via null pointer. * buf.c (buf_strm_ops): Likewise. * chksum.c (sha1_ops, sha256_ops, md5_ops): Likewise. * ffi.c (ffi_type_builtin_ops, ffi_type_struct_ops, ffi_type_ptr_ops, ffi_type_enum_ops, ffi_closure_ops, union_ops): Likewise. (carray_borrowed_ops, carry_owned_ops, carray_mmap_ops): Specify copy_carray as clone operation. * gc.c (prot_array_ops): Indicate no clone operation via null pointer. * gzip.c (gzio_ops_rd, gzip_ops_wr): Likewise. * hash.c (hash_iter_ops): Likewise. (hash_ops): Specify copy_hash as clone operation. * parser.c (parser_ops): Indicate no clone operation via null pointer. * rand.c (random_state_clone): New static function. (random_state_ops): Use random_state_clone as clone function. * regex.c (char_set_obj_ops, regex_obj_ops): Indicate no clone operation via null pointer. * 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. * strudel.c (strudel_ops): Likewise. * sysif.c (cptr_dl_ops, opendir_ops): Likewise. * syslog.c (syslog_strm_ops): Likewise. * unwind.c (cont_ops): Likewise. * vm.c (vm_desc_ops, vm_closure_ops): Likewise. * tree.c (tree_ops): Use copy_search_tree for clone operation. (tree_iter_ops): Use copy_tree_iter for clone operation. * genchksum.txr: Changes in chksum.c specified in one place here. * tests/012/oop.tl: Couple of new tests. * txr.1: Documented.
* Copyright year bump 2024.Kaz Kylheku2024-01-181-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, 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/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 year bumped to 2024.
* lib: review cobj calls for gc incorrectness and fix.Kaz Kylheku2024-01-061-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | I looked at all cobj calls to see if there is a potential problem, looking for situations whereby the cobj call could trigger a gc that would destroy Lisp objects that the new object either stores, or that its continued initialization depends on. * stream.c (make_strlist_input_stream): call cobj earlier, then fill in the structure. Use chk_calloc to allocate the structure so any Lisp objects in it look like nil until it is initialized. * struct.c (make_struct_impl, make_lazy_struct): Use gc_hint on the type argument, to pin down the st structure that we use in initializations after the cobj call. If the type object were to disappear, the st structure would become invalid. * tree.c (copy_search_tree, make_similar_tree): Use gc_hint on the tree argument to pin down the otr structure that we reference in initializations (copy_tree_iter): Use gc_hint on iter, for similar reasons. * vm.c (vm_copy_closure): Use gc_hint on oclosure, to pin down the environment we are copying from it.
* cygwin: run, sh: mangle termination status word.Kaz Kylheku2023-12-281-0/+10
| | | | | | | | | | * stream.c (run): On Cygwin, the spawnvp function is returning a 16 bit termination status word where the upper 8 bits is the termination status if the termination is normal, otherwise the lower 8 bits holds a termination signal. Let's massage it so that the function returns an integer termnation status, or nil if the termination was abnormal, same as we do on POSIX platforms with fork/wait.
* sh-esc: clean up mess I made.Kaz Kylheku2023-11-251-8/+39
| | | | | | | | | | | | | | | | | | | | | | Not all special characters can just be backslash escaped. Spaces and newlines must be quoted. * stream.c (sh_esc_common): New function. Handles both sh-esc and sh-esc-all logic, distinguished by a flag. Quoting is used, rather than backslash escaping. If the string contains no special characters, it is just erturned. If it can be double quoted, it is double quoted. Otherwise it is single quoted and any contained single quotes are replaced by '\''. (sh_esc, sh_esc_all): Now just wrap sh_esc_common. (sh_esc_dq): Remove the newline from the set of escaped characters. Escaping a newline generates a continuation sequence which eats the newline. * tests/018/sh-esc.tl: Most test cases deleted; many new test cases added. * txr.1: Documentation revised.
* New T mode for open-file.Kaz Kylheku2023-09-231-0/+13
| | | | | | | | | | | | | | | The T mode uses O_TMPFILE to create an unlinkd temporary file. * stream.h (struct stdio_mode): New flag, tmpfile. (stdio_mode_init_blank, stdio_mode_init_r, stdio_mode_init_rpb): Updated to cover new bitfield member. * stream.c (w_open_mode): If tmpfile flag is on, add O_TMPFILE. (do_parse_mode): Recognize "T" mode selector and set all appropriate mode bits. If we are not on a platform that has O_TMPFILE, set the maformed flag. * txr.1: Documented.
* Use vargs typedef instead of struct args *.Kaz Kylheku2023-09-051-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | The vargs typedef is underused. Let's use it consistently everywhere. * args.c, * args.h, * args.c, * args.h, * arith.c, * eval.c * ffi.c, * gc.c, * hash.c, * lib.c, * lib.h, * parser.c, * stream.c, * struct.c, * struct.h, * syslog.c, * syslog.h, * unwind.c, * vm.c, * vm.h: All "struct args * declarations replaced with existing "varg" typedef that comes from lib.h.
* New functions for shell escaping.Kaz Kylheku2023-09-011-0/+24
| | | | | | | | | | | * stream.c (sh_esc, sh_esc_all, sh_esc_dq, sh_esc_sq): New static functions. (stream_init): sh-esc, sh-esc-all, sh-esc-dq, sh-esc-sq: Intrinsics registered. * tests/018/sh-esc.tl: New file. * txr.1: Documented.
* close-stream: new : protocol from close method.Kaz Kylheku2023-08-071-3/+10
| | | | | | | | | | | | | * stream.c (close_stream): If the underlying method returns the colon symbol :, then keep the cached close_result as nil, so that the method can be called again, but return t to the caller to indicate success. * tests/018/close-delegate.tl: Test case added. * tests/018/close-delegate.expected: Updated. * txr.1: Documented.
* streams: a few close funtions should return t.Kaz Kylheku2023-08-071-0/+2
| | | | | | | | * socket.c (dgram_close): Return t when a descriptor is closed, returning nil only when the object is already in a closed state. * stream.c (dev_null_close, dir_close): Likewise.
* streams: close-stream only caches non-nil result.Kaz Kylheku2023-08-071-3/+3
| | | | | | | | | | | | | | | | | | | | This is motivated by trying to implement a struct delegate stream which performs reference counting in close, in order to close the real stream when the count hits zero. The caching behavior of close-stream is a problem. * stream.c (strm_base_init): Initialize close_result to nil, rather than nao. (strm_base_mark): Don't check close_result for nao. (close_stream): Suppress the call to op->close if close_result has a non-nil value, rather than a value other than nao. * tests/018/close-delegate.tl, * tests/018/close-delegate.expected: New files. * txr.1: Document that only a non-nil return is cached by close-stream.
* Copyright year bump 2023.Kaz Kylheku2023-01-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.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 year bumped to 2023.
* streams: fixes in few type error diagnostics.Kaz Kylheku2022-11-211-5/+7
| | | | | | | | | | | * stream.c (make_string_byte_input_stream, get_string_from_stream): Use self in diagnostic, and print bad object using ~s rather than ~a. (get_list_from_stream): Likewise, and add missing nao as well. (catenated_stream_push): Add self string, use in diagnostics, print bad object using ~s.
* args: don't use alloca for const size cases.Kaz Kylheku2022-10-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * args.h (args_decl_list): This macro now handles only constant values of N. It declares an anonyous container struct type which juxtaposes the struc args header with exactly N values. This is simply defined as a local variable without alloca. (args_decl_constsize): Like args_decl, but requiring a constant N; implemented via args_decl_list. (args_decl_list_dyn): New name for the old args_decl_list which calls alloca. No places in the code depend on this at all, except the definition of args_decl. (args_decl): Retargeted to args_decl_list_dyn. There is some inconsistency in the macro naming in that args_decl_constsize depends on args_decl_list, and args_decl depends on arg_decl_list_dyn. This was done to minimize diffs. Most direct uses of args_decl_list have a constant size, but a large number of args_decl uses do not have a constant size. * eval.c (op_catch): Use args_decl_constsize. * ffi.c (ffi_struct_in, ffi_struct_get, union_out): Likewise. * ftw.c (ftw_callback): Likewise. * lib.c (funcall, funcall1, funcall2, funcall3, funcall4, uniq, relate): Likewise. * socket.c (sockaddr_in_unpack, sockaddr_in6_unpack, sockaddr_un_unpack): Likewise. * stream.c (formatv): Likewise. * struct.c (struct_from_plist, struct_from_args, make_struct_lit): Likewise. * sysif.c (termios_unpack): Likewise. * time.c (broken_time_struct): Likewise.
* json: support standard-style formatting.Kaz Kylheku2022-10-111-0/+4
| | | | | | | | | | | | | | | | | | | | * stream.c (standard_k, print_json_format_s): New symbol variables. (stream_init): New variables initialized. * stream.h (enum json_fmt): New enum. (standard_k, print_json_format_s): Declared. * lib.c (out_json_rec): Take enum json_fmt param, and pass it recursively. Printing for vector and dictionaries reacts to argument value. (out_json, put_json): Examine value of special var *print-json-format* and calculate enum json_fmt value from this. Pass to out_json_rec. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* streams: new function inc-indent-abs.Kaz Kylheku2022-10-111-0/+13
| | | | | | | | | | | * stream.c (inc_indent_abs): New function. (stream_init): inc-init-abs intrinsic registered. * stream.h (inc_indent_abs): Declared. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* Implement NaN boxing.Kaz Kylheku2022-09-131-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On platforms with 64 bit pointers, and therefore 64-bit-wide TXR values, we can use a representation technique which allows double floating-point values to be unboxed. Fixnum integers are reduced from 62 bits to 50, and there is a little more complexity in the run-time type checking and dispatch which costs extra cycles. The support is currently off by default; it must be explicitly enabled with ./configure --nan-boxing. * lib.h (NUM_MAX, NUM_MIN, NUM_BIT): Define separately for NaN boxing. (TAG_FLNUM, TAG_WIDTH, NAN_TAG_BIT, NAN_TAG_MASK, TAG_BIGMASK, TAG_BIGSHIFT, NAN_FLNUM_DELTA): New preprocessor symbols. (enum type, type_t): The FLNUM enumeration constant moves to just after LIT, so that its value is the same as TAG_FLNUM. (struct flonum): Does not exist under NaN boxing. (union obj): No fl member under NaN boxing. (tag, is_ptr): Separately defined for NaN boxing. (is_flo): New function under NaN boxing. (tag_ex): New function. It's like tag, but identifies floating-point values as TAG_FLNUM. The tag function continues to map them to TAG_PTR, which is wrong under NaN boxing, but needed in order not to separately write tons of cases in the arith.c module. (type): Use tag_ex, so TAG_FLNUM is handled, if it exists. (auto_str, static_str, litptr, num_fast, chr, c_n, c_u): Different definition for NaN boxing. (c_ch, c_f): New function. (throw_mismatch): Attribute with NORETURN. (nao): Separate definition for NaN boxing. * lib.c (seq_kind_tab): Reorder initializer to follow enum reordering. (seq_iter_rewind): use c_n and c_ch functions, since type checking has been done in those cases. The self parameter is no longer needed. (iter_more): use c_ch on CHR object. (equal): Use c_f accessor to get double value rather than assuming there is a struct flonum representation. (stringp): Use tag_ex, otherwise a floating-point number is identified as TAG_PTR. (diff, isec, isecp): Don't pass removed self parameter to seq_iter_rewind. * arith.c (c_unum, c_dbl_num, c_dbl_unum, plus, minus, signum, gt, lt, ge, le, numeq, logand, logior, logxor, logxor_old, bit, bitset, tofloat, toint, width, c_num, c_fixnum): Extract floating-point value using c_f accessor. Handle CHR type separately from NUM because the storage representation is no longer identical; CHR values have a two bit tag over bits where NUM has ordinary value bits. NUM is tagged at the NaN level with the upper 14 bits being 0xFFFC. The remaining 50 bits are the value. (flo): Construct unboxed float under NaN boxing by taking image of double as a 64 bit value, and adding the delta offset, then casting to the val pointer type. (c_flo): Separate implementation for NaN boxing. (integerp, numberp): Use tag_ex. * buf.c (str_buf, buf_int): Separate CHR and NUM cases, like in numerous arith.c functions. * chksum.c (sha256_hash, md5_hash): Use c_ch accessor for CHR value. * hash.c (equal_hash, eql_hash): Handle CHR separately. Use c_f accessor for floating-point value. (eq_hash): Use tag_ex and handle TAG_FLNUM value under NaN boxing. Handle CHR separately from NUM. * ffi.c (ffi_float_put, ffi_double_put, carray_uint, carray_int): Handle CHR and NUM separately. * stream.c (formatv): Use c_f accessor. * configure: disable automatic selection of NaN boxing on 64 bit platforms, for now. Add test whether -Wno-strict-aliasing is supported by the compiler, performed only if NaN boxing is enabled. We need to disable this warning because it goes off on the code that reinterprets an integer as a double and vice versa.
* close-stream: process wait cleanup.Kaz Kylheku2022-06-241-18/+6
| | | | | | | | | * stream.c (pipe_close_status_helper): Revise error messages. Get rid of impossible cases: we will not get WIFSTOPPED or WIFCONTINUED unless we used the WUNTRACED option in waitpid, which we don't. No platforms without HAVE_SYS_WAIT, don't throw if the status is nonzero; just return nil. It could be a normal termination.
* More HAVE_FORK_STUFF cleanup.Kaz Kylheku2022-06-241-3/+3
| | | | | | * stream.c (pipe_close_status_helper, pipe_close, pipe_ops): Included in #if HAVE_FORK_STUFF block. (stream_init): Refer to pipe ops only if HAVE_FORK_STUFF is true.
* streams: remove old code for popen on MingGW.Kaz Kylheku2022-06-211-156/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is vestigial code from a time when TXR supported being compiled with MinGW. Except in the case of the functions run and sh, which are implementable without fork on Cygwin using the spawn family of functions, there won't be any fallback; if HAVE_FORK_STUFF is zero or missing, then certain functions will be absent. * stream.c (struct stdio_handle): Do not define a pid member if we don't HAVE_FORK_STUFF. (se_pclose): Function removed; we won't be using any non-POSIX platforms popen/pclose. (pipe_close): Don't call the removed se_pclose. (make_pipe_stream): Function removed. (fds_subst, fds_swizzle): Don't define these if HAVE_FORK_STUFF is absent, and so is HAVE_WSPAWN and HAVE_SPAWN. They are now only needed by the version of the run function that uses spawn or wspawn. (open_command, open_process): Remove the versions of these function based on popen. (string_extend_count, win_escape_cmd, win_escape_arg, win_make_cmdline): Remove these functions used by the above open_process; we have no need for encoding arguments into a Windows command line string, since the Cygwin/Cygnal libraries do that for us in their spawn and exec functions. * stream.h (make_pipe_stream): Function removed. * utf8.[ch] (w_popen): Function removed.
* bugfix: missing gzip support in open-command.Kaz Kylheku2022-06-211-52/+74
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * stream.c (pipe_close_status_helper): New function, factored out of pipe_close and used by it, and also by gzio_close. (pipe_close): Call pipe_close, which now contains the classification of process wait status codes. (open_fileno): Now takes optional pid argument. If this specified, then make_pipevp_stream is used. (open_subprocess): Use the open_fileno function, rather than fopen. This simplifies things too, except that we have to catch exception. Pass pid to the newly added parameter of open_fileno so that we obtain a proper pipe stream that will wait for the process to terminate when closed. (mkstemp_wrap): Pass nil for pid argument of open_fileno. (stream_init): Update registration of open-fileno. * gzio.c (struct gzio_handle): New member, pid. (gzio_close): If there is a nonzero pid, wait for the process to terminate. (make_gzio_stream): Initialize h->pid to zero. (make_gzio_pipe_stream): New function. * parser.c (lino_fdopen): Pass nil for pid argument of open_fileno. * gzio.h (make_gzio_pipe_stream): Declared. * tests/018/gzip.tl: New test.
* string-out-stream: gc issue.Kaz Kylheku2022-06-061-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The problem being addressed here showed up for me when compiling with either gcc-7 or gcc-11 on Ubuntu 18, using -fsanitize-undefined. A few test test cases run under --gc-debug were crashing. I narrowed it down to this small test case, whose correct output would be "1": ./txr --gc-debug -p '(sys:fmt-simple 1 : : : :)' "\x6700ACB0缻\x6700ACB0缻 " The issue doesn't have anything to do with -fsanitize-undefined; that just how it got reproduced by chance. I'm reasonably certain that in builds for which "make tests" passes, and the above test case doesn't repro, this issue is absent: the code got generated in such a way that it the string_own call doesn't cause the stream object to be reclaimed. * stream.c (get_string_from_stream): change the order of operations in the ownership transfer of the string from the stream to the returned string object. We capture the string in a local variable, and null out so->buf before calling string_own. The problem is that get_string_from_stream is called in a way where the caller no longer has any use for the stream, and so the object is no longer live. It's possible for the string_own call to cause the stream object to be garbage collected. Therefore, the object must not still be hanging on to the wchar_t * string, which was already transferred to the string object.
* build: fix broken build when we don't HAVE_ZLIB.Kaz Kylheku2022-05-311-0/+2
| | | | | | | | | | | * parser.c (open_txr_file): Use liberal heaps of #if HAVE_ZLIB. If there is no Zlib, and the caller explicitly requests a .tlo.gz file to be loaded, then throw. Do not implicitly look for a .tlo.gz file. * stream.c (open_file): #if HAVE_ZLIB around a goto label that is only used out of HAVE_ZLIB code, to eliminate unused label warning.
* streams: use ~a for self string.Kaz Kylheku2022-05-311-3/+3
| | | | | | * stream.c (parse_mode, open_file, open_fileno): Since self is a string, use ~a to print it, or else quotes will appear.
* cygwin: bug: sh always uses cmd.exe.Kaz Kylheku2022-05-311-9/+4
| | | | | | | | | | * stream.c (sh): Use a single definition for this function, which uses the shell and shell_arg variables to use either /bin/sh -c or cmd.exe /c. We only want to use cmd.exe when running as a Windows native program on Cygnal. * tests/018/process.tl: Remove workaround from test case. This is what was causing the weirdness.
* streams: remove workaround for older Cygwin bug.Kaz Kylheku2022-05-271-7/+0
| | | | | | * stream.c (se_putc): Remove a workaround for a Cygwin bug that was fixed in 2016 in 2.5.0. Here is the mailing list thread: https://sourceware.org/pipermail/cygwin/2016-March/226554.html
* open-fileno: support "z" flag for gzip.Kaz Kylheku2022-05-261-12/+27
| | | | | * stream.c (open_fileno): Use w_gzdopen_mode and make_gzio_stream to make a gzio stream if the gzip flag is present.
* gzio: support more modes in open-file.Kaz Kylheku2022-05-261-3/+11
| | | | | | | | | | | | * gzio.c (w_gzopen_mode): Use w_open_mode if available, in order to support most of the flags (including "x" which Zlib has, but which we are not passing through). * stream.c (w_open_mode): New function formed from w_fopen_mode content. (w_fopen_mode): Call w_open_mode. * stream.c (w_open_mode): Declared.
* First cut at new feature: gzip streams.Kaz Kylheku2022-05-261-6/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Makefile (OBJS): Conditionally include new gzio.o object file. * configure: Detect external zlib, setting up new have_zlib variable in config.make, HAVE_ZLIB in config.h, and also -lz in conf_ldlibs. * gzio.[ch]: New files, implementing the stream abstraction over the gzip file I/O routines in zlib. * stream.h (struct stdio_mode): New gzip flag and gzlevel bitfield to hold a value 0 to 9. (stdio_mode_init_blank, stdio_mode_init_r, stdio_mode_init_rpb): Update intializers to cover new bitfield members. * stream.c: Include <zlib.h> and "gzio.h" if HAVE_ZLIB. (do_parse_mode): Recognize new mode modifier letter "z", setting the gzip flag in the mode structure. If it's followed by a digit, set the gziplevel to that value. (format_mode): Don't output "b" letter for binary mode if gzip is set, because gzopen interprets "b" differently. Don't put out "t" if gzip is set. If gzip mode is specified, do put out the level. If gzip is set, and gziplevel is nonzero then encode the level: gzopen will understand it. (open_file): If gzip mode is requested, then open the file using gzopen mode, a new function in gzio.c. The return a gzio stream based on the returned gzip file handle. However, if we are reading, and the gzip stream indicates that it's not decompressing anything, then we close it and open the file using an ordinary stream. (stream_init): Call gzio_init if HAVE_ZLIB is true. This is done here because the module is integrated with stream.c, and also so that lib.c doesn't have to know about HAVE_ZLIB and <zlib.h>.
* open-file: show function name in bad modes diagnostic.Kaz Kylheku2022-05-261-1/+2
| | | | | | * stream.c (normalize_mode): Include the self symbol in the error message being thrown. This was not forgotten in the sister function normalize_mode_no_bin.
* stream-set-prop: return t on successful :name set.Kaz Kylheku2022-05-261-0/+1
| | | | | | * stream.c (stdio_set_prop): When setting the :name property, return t, to indicate it was recognized and stored, as is documented.
* streams: avoid double access to errno.Kaz Kylheku2022-05-261-2/+3
| | | | | * stream.c (stdio_maybe_read_error): Access errno once, and refer to the value.
* New function: trim-path-sepsKaz Kylheku2022-05-201-0/+19
| | | | | | | | | | | | | * stream.c (trim_path_seps): New function. (stream_init): trim-path-seps intrinsic registered. * stream.c (trim_path_seps): Declared. * tests/018/path.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* subprocesses: don't unnecessarily flush *stdout*.Kaz Kylheku2022-04-241-2/+4
| | | | | | * stream.c (open_subprocess, open_commad): Only flush standard output for non-input pipes. If we are capturing the output of the process, then it is unrelated to our standard output.
* subprocesses: flush *stdout*.Kaz Kylheku2022-04-231-0/+8
| | | | | | * stream.c (open-subprocess, open_command, run): Flush the standard output stream before forking or spawning the child process. This gets tests/018/forkflush.tl to pass.
* Use null_string throughout code base.Kaz Kylheku2022-02-051-1/+1
| | | | | | | | | | | | | | | | * eval.c (load): Use null_string instead of lit(""). * lib.c (obj_init): Likewise. * match.c (LOG_MATCH, LOG_MISMATCH, do_txeval): Likewise. * parser.c (regex_parse, lisp_parse_impl, find_matching_syms): Likewise. * stream.c (do_parse_mode): Likewise. * txr.c (sysroot_init): Likewise. (txr_main): Replace string(L"") with null_string.
* Copyright year bump 2022.Kaz Kylheku2022-01-111-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | *LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.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, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.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/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.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 year bumped to 2022.
* Casts have crept into the code not wrapped by macros.Kaz Kylheku2022-01-061-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It is against TXR coding conventions to use the C cast notation. The usage creeps into the code. To find instances of this, we must compile using GNU g++, and add -Wold-style-cast via EXTRA_FLAGS. * eval.c (prof_call): Use macro instead of cast. * ffi.c (pad_retval, ffi_varray_alloc, make_ffi_type_union, carray_dup, carray_replace, uint_carray, int_carray, put_carray, fill_carray): Likewise. * itypes.c (c_i64, c_u64): Likewise. * lib.c (cyr, chk_xalloc, spilt_str_keep, vector, cobj_register): Likewise. * linenoise.c (record_undo): Likewise. Also, drop one superfluous cast: wstrdup_fn returns wchar_t *. (flash, edit_insert, edit_insert_str): Use macro instead of cast. * mpi/mpi.c (s_mp_ispow2d): Likewise. * parser.c (lino_getch): Likewise. * rand.c (make_random_state, random_buf): Likewise. * stream.c (generic_get_line, do_parse_mode): Likewise. * struct.c (get_duplicate_supers, call_initfun_chain, call_postinitfun_chain): Likewise. * sysif.c (c_time): Likewise. * tree.c (tr_insert): Likewise.
* Eliminate declaration-after-statement everywhere.Kaz Kylheku2021-12-291-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The use of -ansi doesn't by itself diagnose instances of some constructs we don't want in the project, like mixed declarations and statements. * configure (diag_flags): Add -Werror=declaration-after-statement. This is C only, so filter it out for C++. Also add -Werror=vla. * HACKING: Update inaccurate statements about what dialect we are using. TXR isn't pure C90: some GCC extensions are used. We even use long long if the configure script detects it as working, and some C99 library features. * buf.c (replace_buf, buf_list): Fix by reordering. * eval.c (op_dohash, op_load_time_lit): Fix by reordering. * ffi.c (ffi_simple_release): Fix by reordering. (align_sw_get): Fix empty macro to expand to dummy declaration so a semicolon after it isn't interpreted as a statement. On platforms with alignment, remove a semicolon from the macro so that it requires one. (ffi_i8_put, ffi_u8_put): Fix by reordering. * gc.c (gc_init): Fix with extra braces. * hash.c (hash_init): Fix by reordering. * lib.c (list_collect_revappend, sub_iter, replace_str, replace_vec, mapcar_listout, mappend, mapdo, window_map_list, subst): Fix by reordering. (gensym, find, rfind, pos, rpos, in, search_common): Fix by renaming optional argument and using declaration instead of assignment. * linenoise/linenoise.c (edit_in_editor): Fix by reordering. * parser.c (is_balanced_line): Fix by reordering. * regex.c (nfa_count_one, print_rec): Fix by reordering. * signal.c (sig_mask): Fix by reordering. * stream.c (get_string): Fix by renaming optional argument and using declaration instead of assignment. * struct.c (lookup_static_slot_desc): Fix by turning mutated variable into block local. (umethod_args_fun): Fix by reordering. (get_special_slot): Fix by new scope via braces. * sysif.c (usleep_wrap): Fix by new scope via braces. (setrlimit_wrap): Fix by new scope via braces. * time.c (time_string_meth, time_parse_meth): Fix by reordering. * tree.c (tr_do_delete_spec): Fix by new scope via braces. * unwind.h (uw_block_beg): New macro which doesn't define RESULTVAR but expects it to refers to an existing one. (uw_block_begin): Replace do while (0) with enum trick so that we have a declaration that requires a semicolon, rather than a statement, allowing declarations to follow. (uw_match_env_begin): Now opens a scope and features the same enum trick as in uw_block_begin. This fixes a declaration-follows-statement issue in the v_output function in match.c. (uw_match_env_end): Closes scope opened by uw_match_env_begin. * unwind.c (revive_cont): Fix by introducing variable, and using new uw_block_beg macro. * vm.c (vm_execute_closure): Fix using combination of local variable and reordering.
* cygwin: environment-related fixes.Kaz Kylheku2021-10-051-2/+2
| | | | | | | * stream.c (run): replace_env takes only one argument. * tests/018/process.tl: *child-env* tests are reporting some extra environment variables on Windows; let's just disable them.
* New variable: *child-env*.Kaz Kylheku2021-09-261-3/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | This specifies the environment to be used for executing programs. * stream.c (open_subprocess, run): Check *child-env* variable and if other than t, then install the environment before execvp. In the spawn-based version of run, we save and restore the environment around the spawn call, if *child-env* is in effect. * sysif.c (child_env_s): New symbol variable. (exec_wrap): If *child-env* is other than t, then save the environment in a list, and install the specified environment before calling execvp. If that function returns, restore the environbment. * sysif.h (child_env_s): Declared. (child_env): New macro. * tests/018/process.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* path-search: rewrite in C with saner semantics.Kaz Kylheku2021-09-251-2/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | The new function: - just returns the name if it contains path name components. - returns nil if the name is "." or "..". - tests for existence only, not permission to execute. * lisplib.c (path_test_set_entries): Do not auto-load path-test module on the path-search symbol, since it is no longer implemented there. * stdlib/path-test.tl (path-search): Function removed. * stream.c (path_var_sep_char): New global variable. (path_search): New function. (detect_path_separators): Also set path_var_sep_char to semicolon on Cygnal. (stream-init): Register path-search intrinsic here now. * stream.h (path_var_sep_char, path_search): Declared. * tests/018/path-test.tl: New tests. * txr.1: Documentation revised for path-search.
* exceptions: hack to store errno in string object.Kaz Kylheku2021-09-071-47/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Basic idea: when we throw an exception that pertains to a system error which has an errno code, we can stick the errno into the memory area of the character string, into the wchar_t that immediately follows the null terminator. We can do this because strings track their actual allocation size. A pair of setter/getter functions to set and retrieve this value are provided, and all functions in the code which can set such a code are updated to do so, simply by calling the newly added uw_ethrowf that drop-in replaces for uw_throwf. * lib.[ch] (string_set_code, string_get_code): New functions. * unwind.[ch] (uw_ethrowf): New function. * eval.c (eval_init): Register string-set-code and string-get-code intrinsics. * ftw.c (ftw_wrap): Switch to uw_ethrowf. * parser.c (open_txr_file): Likewise. * socket.c (dgram_overflow): Store the ENOBUFS error in errno, and use uw_ethrowf instead uw_throwf. (dgram_get_byte_callback, dgram_flush, sock_bind, to_connect, open_sockfd, sock_connect, sock_listen, sock_accept, sock_shutdown, sock_timeout, socketpair_wrap): Switch to uw_ethrowf. * stream.c (dev_null_get_fd, stdio_maybe_read_error, stdio_maybe_error, stdio_close, pipe_close, open_directory, open_file, open_fileno, open_tail, fds_subst, open_subprocess, open_command, remove_path, rename_path, tmpfile_wrap, mkdtemp_wrap, mkstemp_wrap): Switch to uw_ethrowf. * sysif.c (mkdir_wrap, ensure_dir, chdir_wrap, getcwd_wrap, rmdir_wrap, mknod_wrap, mkfifo_wrap, chmod_wrap, do_chown, symlink_wrap, link_wrap, readlink_wrap, close_wrap, val exec_wrap, stat_impl, do_utimes, pipe_wrap, poll_wrap, getgroups_wrap, setuid_wrap, seteuid_wrap, setgid_wrap, setegid_wrap, setgroups_wrap, getresuid_wrap, setresuid_wrap, setresgid_wrap, crypt_wrap, uname_wrap, opendir_wrap, getrlimit_wrap, setrlimit_wrap): Likewise. * termios.c (tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap, tcdrain_wrap, tcflush_wrap, tcflow_wrap): Likewise. * tests/018/errno.tl: New file. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* open-file: improvement: "a" mode sets create flag.Kaz Kylheku2021-08-291-2/+2
| | | | | | | * stream.c (w_fopen_mode): Only test the m.create flag as the basis for O_CREAT, not m.append. (do_parse_mode): In the 'a' case, set m.create = 1, since all variants of append mode create the file.
* open-file: add mode option "x".Paul A. Patience2021-08-291-1/+11
| | | | | | | | | | | | * stream.h (struct stdio_mode): New member, excl flag. (stdio_mode_init_blank, stdio_mode_init_r, stdio_mode_init_rpb): Add initializer for excl flag. * stream.c (do_parse_mode): Handle 'x' in mode string. (w_fopen_mode): Add O_EXCL flag if m.excl is set. Throw an error if we don't HAVE_FCNTL and m.excl is set. * txr.1: Document mode option "x".
* open-file: fix broken file-creation modes.Paul A. Patience2021-08-291-2/+3
| | | | | | | | The "w+", "m+" and "a+" modes wouldn't create the file. * stream.c (w_fopen_mode): Add O_TRUNC and O_CREAT flags if m.create or m.append is set, rather than if m.read is unset and m.write is set.
* open-file: fix broken "+" mode string.Paul A. Patience2021-08-281-2/+1
| | | | | | | | The "+" mode string should be equivalent to "r+", according to the manual, but before this change it was equivalent to "r". * stream.c (do_parse_mode): Unconditionally set m.write to 1 when "+" is present in the mode string.
* license: reformat to fit 80 columns.Kaz Kylheku2021-08-161-12/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, 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, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, socket.c, socket.h, stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl, stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.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.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h: License reformatted. * lex.yy.c.shipped, y.tab.c.shipped, y.tab.h.shipped: Updated.
* format: bug: sign not reset before each conversion.Kaz Kylheku2021-08-161-11/+8
| | | | | | | | | | | | | | | | | | For instance, this bad output is produced: (pic "+0####.## <<<<<" 123 1) -> "+00123.00 +1 " The second argument should not have any leading + sign. * stream.c (formatv): For each new conversion specifier introduced by ~, reset the sign variable to zero also. That's the semantic change here, occluded by the fact that I'm rearranging the declaration of the variables, adding comments, and condensing the assignments while also getting them into the same order as the declarations, in order that this sort of bug does not creep in in the future, should another such variable be added. * tests/018/format.tl: Adding correct version of above test case.
* close-stream: make idemponent.Kaz Kylheku2021-08-041-5/+11
| | | | | | | | | | | | | | | | | | * stream.c (strm_base_init): Add new element to the initializer to initialize the close_result member to nao, indicating that the close operation has not been invoked. (strm_base_mark): Mark the close_result value, if it isn't nao. This is just in case it is a heap object. The structure delegate mechanism opens the possibility that the stream is actually user code that can return anything so we have to be careful. (close_stream): Only call ops->close if close_result is nao, indicating that close had never been called (or possibly that it had been called bu threw an exception) and store the return value in close_result, otherwise return the previously stored value. * stream.h (struct strm_base): New member, close_result. * txr.1: Documented.