summaryrefslogtreecommitdiffstats
path: root/parser.c
Commit message (Collapse)AuthorAgeFilesLines
* listener: if no new lines, don't save history.Kaz Kylheku2020-02-181-1/+1
| | | | | | | | | * linenoise/linenoise.c (lino_have_new_lines): New function. * linenoise/linenoise.h (lino_have_new_lines): Declared. * parser.c (hist_save): Do nothing if lino_have_new_lines returns false.
* listener: save history early with :save command.Kaz Kylheku2020-02-181-15/+26
| | | | | | | | | * parser.c (hist_save): New static function. (repl): Logic for savingn history when terminating has moved into hist_save. New save command also calls this function. * txr.1: Documented.
* listener: append to .txr_history instead of clobbering.Kaz Kyheku2020-02-181-4/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch addresses the problem of history loss that occurs when a user juggles multiple TXR sessions that all clobber the same history file. * linenoise/linenoise.c (struct lino_state): New member, loaded_lines, keeping track of how many of the lines in the history came from loading the history file. Lines between [0] and [loaded_lines - 1] are loaded lines. New lines occur between [loaded_lines] and [history_len - 1]. (lino_hist_add): Reset loaded_lines to zero when creating history for the first time. Not really necessary since the structure starts zero-filled. When a line of history is erased, then it must be a loaded line, unless loaded_lines is zero. Thus, then decrement loaded_lines to account for a loss of a loaded line, but don't decrement below zero. (lino_hist_set_max_len): Setting the max length can cause history to be trimmed, so we must adjust loaded_lines to account for any loaded lines that get discarded. (lino_hist_save): Takes a new parameter which indicates whether to just save the new history by appending it to the given file, or to overwrite the file with the entire history. In either case, once we save the history, we assume that all of our lines are loaded lines and set loaded_lines to hist_len. In the future, this last step will help implement incremental saving mid-way through a sesssion. (lino_hist_load): Error out if there is already a history. With this loaded_lines logic, it really wouldn't make sense to read history more than once. After loading, set loaded_lines to hist_len. * linenoise/linenoise.h (enum lino_file_mode): New enumeration lino_append. (lino_hist_save): Declaration updated. * parser.c (repl): Implement new history saving protocol. The history file is read using a temporary instance of linenoise, which has the effect of trimming it to the required number of lines. This is written to a temporary file, to which the newly entered lines are appended, and which is finally renamed to replace the history file. (lino_mode_str): Add "a" entry corresponding to lino_append. (lino_open): Do the fchmod in the lino_append case also. * txr.1: Documented the new handling of the history file.
* repl: catch exceptions during completion.Kaz Kylheku2020-02-041-2/+14
| | | | | | | | | | | This fixes the issue that TXR exits if an exception occurs during Tab completion in the interactive listener. This could happen when loading a file fails for whatever reason, such as a corrupt or incomplete installation of the library files or whatever. * parser.c (provide_completions): Set up a catch all handler here around everything, like we already did in provide_atom.
* fstat: turn into true alias.Kaz Kylheku2020-02-041-1/+1
| | | | | | | | | | | | | | | | | | We can get rid of fstat_wrap entirely and make the lstat and fstat function bindings point to the same function. * parser.c (load_rcfile): Call stat_wrap instead of fstat_wrap. * sysif.c (stat_wrap): Static function becomes extern. Useless forward declaration removed. (fstat_wrap): Static function removed. (sysif_init): Bind fstat and lstat to the same function object. * sysif.h (fstat_wrap): Declaration removed. (stat_wrap): Declaration added.
* sysif: fix inappropriate use of w_ convention.Kaz Kylheku2020-01-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | Some functions in utf8.c have w_ prefixes. They are wide character wrappers for functions that take multi-byte string inputs. The prefix is being inappropriately used in the names of a few sysif functions that should be named _wrap. * sysif.c (w_stat, w_lstat, w_fstat): Rename to do_stat, do_lstat and do_fstat, respectively. These are callbacks used with stat_impl. (statp, statl, statf): Rename to stat_wrap, lstat_wrap and fstat_wrap, following existing convention. Additionally, stat_wrap becomes static since nothing outside this file calls it. (sysif_init): Follow renames of statp, statl and statf. * sysif.h (statp): Declaration removed. (statf): Renamed to fstat_wrap. * parser.c (load_rcfile): Follow statf rename.
* Copyright year bump 2020.Kaz Kylheku2019-12-311-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, 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, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.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: Extended copyright notices to 2020.
* listener: C++ enum issue.Kaz Kylheku2019-12-131-1/+1
| | | | | | * parser.c (is_balanced_line): don't initialize an "enum state" variable with 0, but with the equivalent enum constant.
* load: bug: source loc gathered for .tlo files.Kaz Kylheku2019-11-291-1/+3
| | | | | | | | | | | | Contrary to the belief expressed in the commit message of June 2018's 46480c25e62f60c761088c561d90b0f2f5a3143f, source location info is being recorded during the loading of compiled files. The reason is that the function used for processing the forms, lisp_parse_impl, overrides it. * parser.c (read_file_common): Use lisp_parse_impl directly, rather than lisp_parse. Specify that function's rlcp_p argument as false when processing compiled code.
* listener: fix buggy balanced line check.Kaz Kylheku2019-11-241-2/+7
| | | | | | | | | | * parser.c (is_balanced_line): When handling the closing characters, we must look for the state type which matches the character type, not state[sp]. Of course state[sp] == match, since we initialized it that way, and so state[sp] != match is always false. We want match to be derived from the character ch, not from state[sp]. Also, the polarity in the match-not-found return case is wrong; we must return 0.
* lib: use stack-allocated hash iterators everywhere.Kaz Kylheku2019-11-011-4/+9
| | | | | | | | | | | | | | | | | * eval.c (op_dohash): Use hash_iter instead of consing up heap-allocated hash iterator. * filter.c (trie_compress, regex_from_trie): Likewise. * hash.c (hash_equal_op, hash_hash_op, hash_print_op): Likewise. * lib.c (package_local_symbols, package_foreign_symbols, find_max, find_if, rfind_if, populate_obj_hash): Likewise. * parser.c (circ_backpatch, get_visible_syms): Likewise. * struct.c (method_name, get_slot_syms): Likewise.
* circle notation: use faster access in backpatch.Kaz Kylheku2019-10-251-7/+5
| | | | | | * parser.c (circ_backpatch): Since we know that we have a CONS or VEC object, use direct access instead of going through type-safe accessors.
* circle notation: recycle conses in backpatching.Kaz Kylheku2019-10-241-2/+8
| | | | | | * parser.c (circ_backpatch): Recycle the conses belonging to the temporary linked list allocated during hash table and tree backpatching.
* circle notation: some backpatching optimizations.Kaz Kylheku2019-10-211-6/+13
| | | | | | | * parser.c (circ_backpatch): For hashes and trees, if the count has not changed while traversing the elements, then it means nothing was backpatched: there is no need to do the extra expensive step of rebuilding the hash or tree.
* parser: use eq-based hash for circular notation.Kaz Kylheku2019-10-111-1/+1
| | | | | * parser.c (parser_circ_def): Instantiate p->circ_ref_hash as eq-based hash, not eql-based.
* tree: circular notation support.Kaz Kylheku2019-10-071-0/+25
| | | | | | * lib.c (populate_obj_hash): Handle tree object. * parser.c (circ_backpatch): Likewise.
* circle notation: bugfix for hash_userdata.Kaz Kylheku2019-10-071-0/+3
| | | | | | * parser.c (circ_backpatch): Fix neglect to recurse into hash table's userdata object to look for circle notation references.
* New data type: tnode.Kaz Kylheku2019-09-221-0/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Binary search tree nodes are being added as a basic heap data type. The C type tag is TNOD, and the Lisp type is tnode. Binary search tree nodes have three elements: a key, a left child and a right child. The printed notation is #N(key left right). Quasiquoting is supported: ^#N(,foo ,bar) but not splicing. Because tnodes have three elements, they they fit into TXR's four-word heap cell, not requiring any additional memory allocation. These nodes are going to be the basis for a binary search tree container, which will use the scapegoat tree algorithm for maintaining balance. * tree.c, tree.h: New files. * Makefile (OBJS): Adding tree.o. * eval.c (expand_qquote_rec): Recurse through tnode cells, so unquotes work inside #N syntax. * gc.c (finalize): Add TNOD to no-op case in switch; tnodes don't require finalization. (mark_obj): Traverse tnode cell. * hash.c (equal_hash): Add TNOD case. * lib.c (tnode_s): New symbol variable. (seq_kind_tab): New entry for TNOD, mapping to SEQ_NOTSEQ. (code2type, equal): Handle TNOD. (obj_init): Initialize tnode_s variable. (obj_print_impl, populate_obj_hash): Handle TNOD. (init): Call tree_init function in tree.c. * lib.h (enum type, type_t): New enumeration TNOD. (struct tnod): New struct type. (union obj, obj_t): New union member tn of type struct tnod. (tnode_s): Declard. * parserc.c (circ_backpatch): Handle TNOD, so circular notation works through tnode cells. * parser.l (grammar): Recognize #N prefix, mapping to HASH_N token. * parser.y (HASH_N): New grammar terminal symbol. (tnode): New nonterminal symbol. (i_expr, n_expr): Add tnode cases to productions. (yybadtoken): Map HASH_N to "#N" string.
* parser: bugfix: uninitialized ignore flag.Kaz Kylheku2019-08-201-0/+1
| | | | | | | | | | | | | | | * parser.c (parser_common_init): Initialize the ignore flag, which was until recently called circ_suppress. When the parser is invoked via parse_once or parse_once_noerror, rather than parse, the state of the flag is indeterminate. Thus this only affects the TXR Pattern Language, not TXR Lisp. As a result of this bug, which affects releases 157 through 223, if the circle notation like #1=(foo #1#) is used in Pattern Language syntax, it may not be handled properly. I discovered this bug now because there are new behaviors connected to the flag; it doesn't just affect the processing of the circle notation, but is involved in all symbol handling in the parser.
* parser: rename circ_suppress flag.Kaz Kylheku2019-08-181-1/+1
| | | | | | | | | | | * parser.h (struct parser): eof flag changed to unsigned char. circ_suppress flag renamed to ignore, changed to unsigned char and relocated next to eof to compact together. * parser.c (parser_circ_ref): Follow rename. * parser.y (hash_semi_or_n_expr, hash_semi_or_i_expr, n_exprs, parse): Likewise.
* listener: don't flush lines when writing files.Kaz Kylheku2019-08-121-1/+11
| | | | | | | | | | | | | | | | * linenoise/linenoise.h (struct lino_os): New virtual operation, puts_file_fn: like puts_fn, but not display-oriented: doesn't check for and ignore padding characters, and doesn't flush after each line. (lino_os_init): Initializer macro updated. * linenoise/linenoise.c (edit_it_editor): Use puts_file_fn to write to temporary file. (lino_hist_save): Likewise, when writing out history. * parser.c (lino_puts_file): New static function. (linenoise_txr_binding): Add lino_puts_file to initializer to wire in the operation.
* txr: regression: lack of file name in error messages.Kaz Kylheku2019-07-221-6/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was broken on April 21, 2019 in commit 2e36e0feae8d1dd75c8410b365d7dc33b30ce66b (April 21, 2019) which changed parse_once in such a way that the name being passed down was no longer stored in the parser. The ensure_parser function being relied upon doesn't take on the responsibility of propagating the name from the stream to the parser, so the parser ends up with a nil name. Let's just smooth this over by having ensure_parser take a name parameter. If ensure_parser creates a new parser, it puts in the name. If the name is nil, then it is taken from the stream. * eval.c (load): Pass name to ensure_parser. * match.c (v_load): Likewise. * parser.c (parser): Take name parameter, and plant into newly constructed parser. (ensure_parser): Take name parameter. When creating a parser, give it that name, or if name is specified as nil, then give it the name taken from the stream. (parser_set_lineno): Pass nil name to ensure_parser. (lisp_parse_impl, read_file_common): Pass name to ensure_parser. * parser.h (parser, ensure_parser): Declarations updated. * parser.y (parse_once): Pass name to ensure_parser. * txr.c (txr_main): Pass spec_file_str to ensure_parser.
* regression: unsuffixed cmdline arg treated as Lisp.Kaz Kylheku2019-06-101-8/+14
| | | | | | | | | | | | | | | | | | This broke in TXR 216. TXR files with no suffix run using #!/path/to/txr stopped working due to being interpreted as Lisp. The rearrangement done in open_txr_file function didn't respect the hacky treatment of the *txr_lisp_p flag, which depended on the original order. The flag ends up being set to t, because we tried (unsuccessfully) opening a .tl suffix, and that then falsely indicates "Lisp" when the unsuffixed file is open. That logic worked when we tried the unsuffixed file first, and fell back on the added suffixes last. * parser.c (open-txr_file): Instead of repeatedly testing for in == 0, we execute a forward goto when we successfully open a file. Only in those successful cases, set *txr_lisp_p to the appropriate value, not touching it otherwise.
* loading: try unsuffixed files directly last.Kaz Kylheku2019-05-011-34/+41
| | | | | | | | | | | | | | | | | | | | | | | | | In this patch we change the strategy for resolving unsuffixed paths in load and @(load). In load, an unsuffixed name is tried with a .tlo suffix, then .tl and only if those don't resolve to a file it is tried as-is. The previous order is as-is, .tlo, .tl. Similarly in @(load), but unsuffixed paths are tried as .txr, then .tlo, then .tl. The motivation for this is to avoid probing the filesystem multiple times the optimized case that we care about: loading .tlo files from Lisp. * parser.c (open_txr_file): Rearrange the probing strategy. Also recognize .txr_profile as a suffix, treating it like .tl. This is so that we don't probe for .txr_profile.tlo and .txr_profile.tl before finding the profile. (load_rcfile): Take advantage of the new path-not-found exception. We avoid wastefully checking with path-exists-p to avoid calling open_txr_file. We just let open_txr_file throw an exception if the file doesn't exist, and then distinguish the non-existence case in the handler. * txr.1: Updated @(load) and load documentation.
* lib: more nuanced file access errors.Kaz Kylheku2019-05-011-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Several new more specific exception types are derived from file-error and used. Error handlers can distinguish unexpected non-existence, unexpected existence and permission errors from each other and other errors. * lib.c (path_not_found_s, path_exists_s, path_permission_s): New symbol variables. (obj_init): New variables initialized. * lib.h (path_not_found_s, path_exists_s, path_permission_s): Declared. * parser.c (open_txr_file): Use new errno_to_file_error function to convert errno to exception symbol. * socket.c (open_sockfd): Likewise. * stream.c (open_directory, open_file, open_fileno, open_command, open_process, run, remove_path, rename_path): Likewise, and process-error is used in open_process and run instead of file-error for problems related to creating the process. * sysif.c (errno_to_file_error): New function. (mkdir_wrap, ensure_dir, chdir_wrap, getcwd_wrap, mknod_wrap, chmod_wrap, symlink_wrap, link_wrap, readlink_wrap, stat_impl, umask_wrap, ): Use errno_to_file_error to convert errno to exception symbol. (exec_wrap): Use process-error instead of file-error. * sysif.c (errno_to_file_error): Declared. * unwind.c (uw_init): Register path-not-found, path-exists and path-permission as subtypes of file-error. * txr.1: Documented.
* bugfix: source lineno off by one under hash bang.Kaz Kylheku2019-04-211-0/+8
| | | | | | | | | | | | | | * eval.c (load): When we read and discard a hash bang line, we must set the parser line number to two. * parser.c (parser_set_lineno): New function. * parser.h (parser_set_lineno): Declared. * txr.c (check_hash_bang): New argument, occurs. (txr_main): Track whether hash bang has occurred in a new local variable hb_occurs. Then, before parsing, if hash bang has occurred, set the line number to two.
* parser: always use stream-associated parser for parse_once.Kaz Kylheku2019-04-211-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This refactoring is needed for fixing the off-by-one line number bug when the hash bang line is processed. * eval.c (load): Don't define parser locally; ensure there is one in the stream and use it. * match.c (v_load): Likewise. * parser.c (get_parser_impl): Renamed to parser_get_impl and changed from internal to external linkage. (ensure_parser): Changed to external linkage. (lisp_parser_impl, read_file_common): Follow rename of get_parser_impl. * parser.h (parse_once): Declaration updated. (parser_get_impl, ensure_parser): Declared. * parser.y (parse_once): Take self parameter; drop parser parameter. Ensure a parser to the stream, rather than declaring one locally. Don't clean up the parser when done, just let the stream clean it up. * txr.c (parse_once_noerr): Parser argument is dropped and not passed to parse_once. Program name is passed as self argument to parse_once. (txr_main): When parsing the TXR pattern query, don't define a parser locally; ensure there is one in the stream and use it, like in load and v_load.
* exceptions: allow description field in catch frames.Kaz Kylheku2019-04-101-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (op_catch): Extra argument in sys:catch syntax specifies an expression that evaluates to a description field. (expand_catch): Expand the desc expression in sys:catch syntax. * parser.c (read_file_common): Increase acceptance of compiled files from versions 1-4 to 1-5, since we are now marking compiled files with version 5.0 rather than 4.0. * share/txr/stdlib/asm.tl (op-catch catch): Support new argument in the opcode syntax. Turns out we have a spare field in the instruction format which was previously set to zero We can use that for the description. Thus, the instruction set and VM remain backward compatible: old code works. * share/txr/stdlib/compiler.tl (compiler comp-catch): Handle the desc argument introduced into the sys:catch form. We must compile it as an expression, then inject the code into the instruction template, and reference the output register of that code block in the catch instruction. (%tlo-ver%): Bump up the compiled file version to 5.0. * share/txr/stdlib/except.tl (usr:catch, catch*): Add desc argument to generated sys:catch form, specifying it as nil. * unwind.c (desc_s): New symbol variable. (uw_find_frames_impl): Set the desc member of the extracted catch structure from the corresponding field in the catch frame. (uw_late_init): Initialize desc_s with interned symbol. Add desc slot to catch-frame type. * unwind.h (struct uw_catch): New member, desc. (uw_catch_begin_w_desc): New macro. * vm.c (vm_catch): Extract the desc field from the catch instruction, and use uw_catch_begin_w_desc to propagate that to the catch frame.
* repl: groundwork for recursive listener invocation.Kaz Kylheku2019-04-081-7/+17
| | | | | | | | | | | | | | | | | * parser.c (lino_ctx, repl_level): New static variable. (repl): Increment repl_level on entry and decrement on exit. On the initial entry, allocate the lino_t object, storing it in the new static variable. Free it on outermost exit. The number of > characters in the prompt indicates the nesting level. The function now takes an environment parameter, which is applied to the evaluation of the input form. The intent is to be able to supply symbol macros which expand to function calls implementing debugger commands. (parser_init): Register sys:repl intrinsic. * parser.h (repl): Declaration updated. * txr.c (txr_main): Pass nil environment parameter to repl
* listener: ensure history and temp files are rw-------.Kaz Kylheku2019-03-261-3/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | For security, the temporary files used by the "edit in external editor" feature of the listener, as well as the listener history file, should be readable and writable only to the owner. This relates to Debian bug 832460 against the Linenoise library: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832460 In the TXR fork of the linenoise library, since we have an OS abstraction invoked by callback functions, we fix this entirely outside of linenoise. I don't agree with the upstream approach of fiddling with the umask and doing a chmod on the path. Since we are truncating and overwriting the file, all we have to do is, before writing any data, fchmod it to the required permissions. * parser.c (lino_open): If the file is being open for overwriting, then let's set its permissions so that it's readable and writable for the user only.
* listener: return value regression.Kaz Kylheku2019-03-011-2/+2
| | | | | * parser.c (lino_getl, lino_gets): Return null pointer on EOF, restoring original behavior that was broken by recent patches.
* listener: fix buffer overflow loading overlong history line.Kaz Kylheku2019-03-011-6/+1
| | | | | * parser.c (lino_getl): Same fixes that were applied two weeks ago to lino_gets in commit b76c5760. Always check for copy and paste!
* parser: gc bug in handling circular notation.Kaz Kylheku2019-02-241-1/+3
| | | | | | | * parser.c (parser_circ_def): When we lazily add the circ_ref_hash to the parser, this is possibly a wrong-way assignment (pointer to a baby object being stored into a mature object). The handling for this is missing.
* listener: fix hang when stringifying output.Kaz Kylheku2019-02-211-1/+2
| | | | | | | | | | | | | | | | | | The issue is that when *listener-pprint-p* is set, then the evaluation is printed using pprinl. The user may have arranged for that to safely work when there are circular objects in the print. But then the listener ignores *listener-pprint-p* when saving the output object as a string (which is done for the sake of the Ctrl-X Ctrl-P paste-previous-output feature). The tostring function is used which can blow up on an object containing circular structure, even though the object was successfully printed. The user is puzzled: why was the result of the evaluation printed completely and perfectly, yet the image has hanged? * parser.c (repl): Do not use tostring for converting the evaluated output to a string. Choose between tostring and tostringp based on the *listener-pprint-p* variable.
* listener: fix buffer overflow reading external file.Kaz Kylheku2019-02-151-6/+1
| | | | | | | | | When an external file is edited, and is longer than the listener's buffer allows, the buffer overflows, trashing the other fields in the linenoise structure, and memory beyond. * parser.c (lino_gets): Decrement nchar in the loop. Also, eliminate useless return case.
* Optimize hash operation with unsafe car/cdr.Kaz Kylheku2019-02-141-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The associative lists that make up the chains of a hash table are guaranteed to be made of conses. We can use unsafe versions of car, cdr, rplaca and rplacd to speed up hash operations. * eval.c (op_dohash): Use unsafe operations on hash cell. * filter.c (trie_compress, regex_from_trie): Likewise. * hash.c (hash_equal_op, hash_print_op, hash_mark, hash_grow, hash_assoc, hash_assql, copy_hash_chain, gethash, inhash, gethash_n, sethash, remhash, hash_next, maphash, do_weak_tables, group_by, group_reduce, hash_keys_lazy, hash_keys, hash_values_lazy, hash_values, hash_pairs_lazy, hash_pairs, hash_alist_lazy, hash_uni, hash_diff, hash_symdiff, hash_isec, hash_subset, hash_update, hash_update_1, hash_revget): Likewise. * lib.c (us_rplaca, us_rplacd): New functions. (package_local_symbols, package_foreign_symbols, where, populate_obj_hash, obj_hash_merge): Use unsafe operations on hash cell * lib.h (us_rplaca, us_rplacd): Declared. * parser.c (circ_backpatch, get_visible_syms): Use unsafe operations on hash cell. * struct.c (method_name, get_slot_syms): Likewise.
* gethash_c: review uses and improve or replace.Kaz Kylheku2019-02-141-8/+8
| | | | | | | | | | | | | | | | | | | | * eval.c (env_fbind, env_vbind, reg_symacro): Use gethash_l instead of gethash_c to eliminate repeated cdr operations on the same cell. * hash.c (sethash): Since new_p is never used, eliminated it and use nulloc. (group_reduce): Use gethash_l instead of gethash_c. * lib.c (obj_init): Replace rplacd(gethash_c(...)) pattern whose return value is not used with with sethash. We lose some diagnosability here since sethash doesn't take a "self" argument. (obj_print_impl, obj_hash_merge): Use gethash_l instead of gethash_c. * parser.y (ensure_parser, parser_circ_def, get_visible_syms, rlset): Use gethash_l instead of gethash_c.
* Copyright year bump 2019.Kaz Kylheku2019-01-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, 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, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended Copyright line to 2018.
* Eliminate ALLOCA_H.Kaz Kylheku2018-12-311-1/+1
| | | | | | | | | | | | | * configure: Instead of generating a definition of ALLOCA_H, generate the variable HAVE_ALLOCA_<name> with a value of 1, where <name> is one of stdlib, alloca or malloc. * alloca.h: New header. * args.c, eval.c, ffi.c ffi.c, ftw.c, hash.c, lib.c, match.c, parser.c, parser.y, regex.c, socket.c, stream.c, struct.c, sysif.c, syslog.c, termios.c, unwind.c, vm.c: Include "alloca.h" instead of ALLOCA_H.
* Drastically reduce inclusion of <dirent.h>.Kaz Kylheku2018-12-111-1/+0
| | | | | | | | | | | | | | | | | | | The <dirent.h> header is included all over the place because it is needed by a single declaration in stream.h. That declaration is for a function that is only called within stream.c, so we make it internal. Now only stream.c has to include <dirent.h>. * buf.c, debug.c, eval.c, ffi.c, filter.c, gc.c, gencadr.txr, hash.c, lib.c, lisplib.c, match.c, parser.c, regex.c, socket.c, struct.c, strudel.c, sysif.c, syslog.c, termios.c, txr.c, unwind.c, vm.c: Remove #include <dirent.h>. * cadr.c: Regenerated. * stream.c (make_dir_stream): Make external function static. * stream.h (make_dir_stream): Declaration updated.
* Better identify functions that misuse COBJ-s and hashes.Kaz Kylheku2018-11-071-23/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this patch, the cobj_handle, cobj_ops and variants of gethash get an additional argument to identify the caller. Many functions are updated to pass this down. * buf.c (buf_strm): Pass self name to cobj_handle. * eval.c (env_fbind, env_vbind, rt_defvarl, me_case): Pass self name to gethash_c or gethash_e. (load): Pass self name to read_eval_stream and read_compiled_file. (reg_symacro): Pass situation-identifying string to gethash_c. * ffi.c (ffi_type_struct_checked, ffi_closure_struct_checked, ffi_call_desc_checked, uni_struct_checked): Take self name parameter, and pass down to cobj_handle. (ffi_get_type, ffi_get_lisp_type): Take self name and pass down to ffi_type_struct_checked. (union_get_ptr): Take self name and pass to uni_struct_checked. (ffi_union_in, ffi_union_put): Pass self name to union_get_ptr. (ffi_type_compile): Pass self name to ffi_get_lisp_type. (ffi_make_call_desc): Pass self name to ffi_type_struct_checked, ffi_get_type and ffi_call_desc_checked. (ffi_make_closure): Pass self name to ffi_call_desc_checked. (ffi_closure_get_fptr): Take self name, pass to ffi_closure_struct_checked. (ffi_typedef, ffi_size, ffi_alignof, ffi_offsetof, ffi_arraysize, ffi_elemsize, ffi_elemtype, ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out, make_carray): Pass self name to ffi_closure_struct_checked. (carray_struct_checked): Take self name, pass to cobj_handle. (carray_set_length, carray_dup, carray_own, carray_free, carray_type, length_carray, copy_carray, carray_ptr, buf_carray, vec_carray, list_carray, carray_ref, carray_refset, carray_sub, carray_replace, carray_get_common, carray_put_common, unum_carray, num_carray, put_carray, fill_carray): Pass self name to carray_struct_checked. (carray_blank, carray_buf, carray_cptr): Pass self name ffi_type_struct_checked. (carray_pun): Pass self name to carray_struct_checked and ffi_type_struct_checked. (make_union): Pass self name to ffi_type_struct_checked. (union_members, union_get, union_put, union_in, union_out): Pass self name to uni_struct_checked. (make_zstruct, zero_fill, put_obj, get_obj, fill_obj): Pass self-name to ffi_type_struct_checked. * ffi.h (ffi_closure_get_fptr, union_get_ptr): Declarations updated. * filter.c (trie_add): Pass self-name to gethash_l. * hash.c (make_similar_hash, copy_hash, hash_count, get_hash_userdata, set_hash_userdata, hash_begin, hash_next, hash_uni, hash_diff, hash_isec): Pass self name to cobj_handle. (gethash_c, gethash_e): Take self name parameter and pass down to cobj_handle. (gethash_f): Take self parameter and pass down to gethash_e. (gethash, inhash, gethash_n, sethash, pushhash, remhash, clearhash, hash_update_1): Pass self name to gethash_e or gethash_c. * hash.h (gethash_c, gethash_e, gethash_f): Declarations updated. (gethash_l): Take self name, and pass down to gethash_c. * lib.c (class_check): Take self name parameter and use in type mismatch diagnostic. (use_sym, unuse_sym, symbol_needs_prefix, find_symbol, intern, unintern, intern_fallback, unique, in, sel, obj_print_impl, populate_obj_hash, obj_hash_merge): Pass self name to gethash_f or gethash_l. (symbol_visible, obj_init): Pass situation-identifying string to gethash_e. (cobj_handle, cobj_ops): Take self name parameter and pass down to class_check. * lib.h (class_check, cobj_handle, cobj_ops): Declarations updated. * match.c (v_load): Pass self name to read_compiled_file and read_eval_stream. * parser.c (get_parser_impl): Take self name and pass to cobj_handle. (ensure_parser): Pass situation-identifying string to gethash_c. (parser_circ_def): Pass self-name to gethash_c. (lisp_parser_impl): Pass self name to get_parser_impl and class_check. (lisp_parse, nread, iread): Pass self-name to lisp_parser_impl. (read_file_common): Take self name parameter and pass down to get_parser_impl. (read_eval_stream, read_compiled_file): Take self name and pass down to read_file_common. (load_rcfile): Pass situation-identifying string to read_eval_streem. (get_visible_syms): Pass situation-identifying string to gethash_c. (parser_errors, parser_eof): Pass self name to cobj_handle. * parser.h (read_eval_stream, read_compiled_file): Declarations updated. * parser.y (rlset): Pass self name to gethash_c. * rand.c (make_random_state, random_state_get_vec,l random_fixnum, random_float): Pass self name to cobj_handle. * regex.c (regex_source, regex_print, regex_run): Pass self-name to cobj_handle. (regex_machine_init): Take self name param and pass to cobj_handle. (search_regex, match_regex, match_regex_right, regex_prefix_match, read_until_match): Pass self-name to regex_machine_init. * stream.c (stdio_get_fd): Pass self name to cobj_handle. (generic_get_line): Get COBJ operations via unsafe, diret object access rather than cobj_ops. (set_mode_props): Get object handle via unsafe, direct object access. (stream_fd, sock_family, sock_type, sock_peer, set_sock_peer, get_string_from_stream, get_list_from_stream, stream_set_prop, stream_get_prop, close_stream, get_error, get_error_str, clear_error, get_line, get_char, get_byte, unget_char, unget_byte, put_buf, fill_buf, put_string, put_char, put_byte, flush_stream, seek_stream, truncate_stream, get_indent_mode, test_set_indent_mode, set_indent_mode, get_indent, set_indent, inc_indent, width_check, force_break, get_set_ctx, get_ctx): Pass self name to cobj_ops. (make_delegate_stream): Take self name parameter, pass down to cobj_ops. (record_adapter): Pass self name down to make_delegate_stream. (format): Pass self name to class_check. * struct.c (stype_handle): Pass self name to cobj_handle. (make_struct_type): Pass self name to class_check. * txr.c (read_eval_stream_noerr): Take self name parameter, pass to read_eval_stream. (txr_main): Pass istuation-identifying string to read_compiled_file and read_eval_stream_noerr. * unwind.c (revive_cont): Pass self-name to cobj_handle. * vm.c (vm_desc_struct): Take self name parameter, pass to cobj_handle. (vm_desc_nlevels, vm_desc_nregs, vm_desc_bytecode, vm_desc_datavec, vm_desc_symvec, vm_execute_toplevel, vm_execute_closure, vm_closure_entry): Pass self name to vm_desc_struct. (vm_closure_struct): Take self name parameter, pass to cobj_handle.
* compiler: optimize dwim.Kaz Kylheku2018-11-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * share/txr/stdlib/asm.tl (op-getf): Rename to op-oldgetf. This opcode becomes obsolescent. (op-getf): New opcode. * share/txr/stdlib/compiler.tl (assumed-fun): New global variable. (compiler comp-fun): Use the new getf instruction which takes a function table index instead of a data table index. (compiler comp-lisp1-value): Don't use getl1 opcode any more for dynamic lisp1-style lookup. Instead, we bake the behavior at compile time perform a function lookup if the symbol is completely unbound, a variable lookup if it is bound to a variable (where we decide at compile tie whether it is lexical or dynamic) or else a function if a function binding exists at compile time. Also, if we assume that an unbound symbol is a function, put it on the assumed-fun list. (compiler comp-dwim): If the first argument is a symbol with no lexical binding, and is not bound as a variable, then treat it as a function by transforming the form into a function call form with that symbol in the car position. Put the symbol on the assumed-fun list. (compiler-emit-warnings): New function. (with-compilation-unit): Call compiler-emit-warnings when bailing out of most enclosing compilation unit. (%tlo-ver%): Bump compiled file version to 4, since we added an opcode. * vm.c (vm_execute): Follow rename of GETF to OLDGETF. Implement the new GETF. * parser.c (read_file_common): Extend version range to allow version 4 compiled files. * txr.1: Documented everything.
* listener: use temp file when saving history.Kaz Kylheku2018-11-021-2/+8
| | | | | | | | | We don't want ot overwrite the history file in-place; if something goes wrong, we will lose half of it. * parser.c (repl): Save the history to a .tmp file, and then rename that to the target name, if the write is successful.
* listener: avoid unnecessary string duplication.Kaz Kylheku2018-11-021-2/+1
| | | | | | | | | | * parser.c (repl): There is no need to use chk_strdup on the string inside histfile. We can just use the original string, since it won't be garbage collected. The existing gc_hint(histfile) at the end of the function ensures this. The reason the chk_strdup was done is that originally this was a utf8_dup_to that I just blindly replaced when the listener Unicode conversion took place.
* repl: bugfix: abort on window size change.Kaz Kylheku2018-10-311-3/+21
| | | | | | * parser.c (lino_getch): Catch the exception that is thrown by get_char when the read fails with EINTR due to the SIGWINCH interrupt. Convert exception to WEOF return.
* repl: allocate the "catch all" exception list once.Kaz Kylheku2018-10-311-5/+3
| | | | | | * parser.c (catch_all): New static variable. (provide_atom, repl): Use static catch_all. (parse_init): Protect catch_all from GC reclamation.
* compiler: use symtab caching for global lexicals.Kaz Kylheku2018-10-261-1/+1
| | | | | | | | | | | | | | | | * parser.c (read_file_common): Allow version three object files. * share/txr/stdlib/compiler.tl (compiler comp-var): If a global variable isn't special, then treat it via the getlx instruction. The symbol gets added to the symtab, and referenced by index number. (compiler comp-setq): Similarly, treat a non-special global variable using the setlx instruction. (%tlo-ver%): We bump the major version of .tlo files from 2 to 3, since old txr executables won't recognize these new instructions. However, we are backward compatible; hence read_file_common still allows version 2.
* load: do not record source location for compiled files.Kaz Kylheku2018-06-211-1/+6
| | | | | | | * parser.c (read_file_common): When reading a compiled file, turn off the rec_source_loc flag in the parser, since the forms are just data, and not source code for which we need error reporting.
* bugfix: fatal exception on missing .txr_history.Kaz Kylheku2018-05-271-2/+10
| | | | | | | | | | | The new abstraction layer used by linenoise throws exceptions, but linenoise excpects a null pointer when a file open fails. * parser.c (lino_open, lino_open8): Catch error exceptions and convert to null return, using new macros to reduce repetitive coding. * unwind.h (ignerr_begin, ignerr_end): New macros.
* listener: Cygwin fix.Kaz Kylheku2018-05-181-6/+10
| | | | | | | | | | | | | | | | | | | | | | | | We cannot pass raw C wide literals to static_str; this breaks on platforms where wchar_t is two bytes and strings are aligned to only two byte boundaries. That's why TXR has the wli() macro. We don't want to introduce the wli() macro into linenoise, so the two choices are: duplicate the incoming mode strings into dynamic storage with string(), or pass some enum to specify file mode and locally convert to static mode string. Let's go with the latter. * linenoise.c (edit_in_editor, lino_hist_save): Use enum constant for file mode instead of mode string. * linenoise.h (enum lino_file_mode, line_file_mode_t): New enum. (struct lino_os): File opening functions use lino_file_mode_t instead of mode string. * parser.c (lino_mode_str): New static array. (lino_open, lino_open8, lino_fdopen): Take enum mode instead of string. Convert to literal through lino_mode_str table, and pass that literal to static_str.