| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
| |
* eval.c (eval_init): Register "use" as alias for identity.
* txr.1: Documented use function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Avoids consing up list of strings.
* lib.c (vscat): New static function.
(scat): New function.
(lazy_str): Use scat instead of cat_str.
* lib.h (scat): Declared.
* eval.c (format_field): Use scat instead of cat_str.
* parser.c (open_txr_file, read_eval_stream): Likewise.
|
|
|
|
|
|
|
| |
* eval.c (set_origin): Add form != origin
to the condition for recording the ancestry.
(expand_macro): Use set_origin function instead
of direct call to sethash.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It was a mistake to change the semantics of the return value
of chr-isdigit and chr-isdigit. It breaks code like
[partition-by chr-isdigit ...]. The behavior of chr-isdigit
and chr-isxdigit is restored to returning t and nil. New
chr-digit and chr-xdigit functions are introduced for
returning the digit value or nil.
* eval.c (eval_init): Register chr-digit and chr-xdigit
intrinsics.
* lib.c (chr_isdigit, chr_isxdigit): Restore old behavior.
(chr_digit, chr_xdigit): New functions.
* lib.h (chr_digit, chr_xdigit): Declared.
* txr.1: Everything documented.
|
|
|
|
|
| |
* eval.c (error_trace): Change "possibly triggered by"
to "during evaluation of".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We need this now, since file system errors aren't
handled in the pattern language any more, after
the complex_open refactoring.
* eval.c (set_last_form_evaled): New function.
* eval.h (set_last_form_evaled): Declared.
* match.c (do_match_line, match_files):
Save, set up and restore last_form_evaled
via set_last_form_evaled function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, METALICENSE, Makefile, args.c, args.h, arith.c,
arith.h, cadr.c, cadr.h, combi.c, combi.h, configure,
debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, gc.c,
gc.h, glob.c, glob.h, hash.c, hash.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,
share/txr/stdlib/cadr.tl, share/txr/stdlib/except.tl,
share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl,
share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl,
share/txr/stdlib/struct.tl, share/txr/stdlib/txr-case.tl,
share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl,
share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl,
signal.c, signal.h, stream.c, stream.h, struct.c, struct.h,
sysif.c, sysif.h, syslog.c, syslog.h, txr.1, txr.c, txr.h,
unwind.c, unwind.h, utf8.c, utf8.h: Add 2016 copyright.
* linenoise/LICENSE, linenoise/linenoise.c,
linenoise/linenoise.h: Bump one principal author's copyright
from 2014 to 2015. The code is based on a snapshot of 2015
upstream work.
|
|
|
|
|
|
|
|
|
|
|
| |
Same issue as with Vim syntax highlighting.
* eval.c (mboundp): Externalize static function.
* eval.h (mboundp): Declared.
* parser.c (find_matching_syms): Expand fboundp check to encompass
mboundp and special_operator_p.
|
|
|
|
|
|
|
| |
* eval.c (do_eval): Set last_form_evaled to form before
evaluating the arguments, so that any errors which are
not attributed to their own sub forms (such as unbound
symbols) are attributed to this form.
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_macrolet): Install a macro ancestor for the
expansion of the macrolet. If the original form has a macro
ancestor, then use that grandparent ancestor. Otherwise
use the original form itself. This way intermediate macrolets
which are generated by macros are abbreviated out of ancestry
traces.
|
|
|
|
|
|
| |
* eval.c (error_trace): If a form has itself as its macro
ancestor, bail the loop. (This only happens in deliberately
contrived pathological cases, useful for testing).
|
|
|
|
|
| |
* eval.c (error_trace): If info is nil, print alternative
message about the location being unavailable.
|
|
|
|
|
|
|
|
| |
* eval.c (error_trace): The original idea behind the
eval_error_s check is that eval errors already carry line
number info, so we don't want to print redundant information.
However, the scope of the detailed information has greatly
increased, so we need to do this check in the loop.
|
|
|
|
|
| |
* eval.c (set_origin): Don't store nil value
in the origin_hash.
|
|
|
|
|
| |
* eval.c (error_trace): Don't check exsym for exact equality
to eval-error, but whether it is a subtype.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (format_field): Function moved here from match.c,
along with the introduction of a new behavior: if a meta-expr
occurs among the modifiers, its constituent expression
is evaluated in its place. This allows for @{a @[expr]}
which was previously not allowed in Lisp quasiliterals,
but worked in TXR quasiliterals due to the treatment
of @ by txeval.
(subst_vars): Static function turns external, so code in
match.c can call it instead of the subst_vars in that module.
For that purpose, it needs to take a filter argument and
process filters, like the match.c subst_vars.
(op_quasi_lit): Pass nil as filter argument to subst_vars.
* eval.h (format_field, subst_vars): Declared.
* match.c (format_field): Function removed, moved to
eval.c and slightly changed.
(subst_vars): Renamed to tx_subst_vars. By default, now just a
wrapper for subst_vars. In compatibility mode, invokes the
old logic.
(do_txeval, do_output_line): Call tx_subst_vars rather than
subst_vars.
* match.h (format_field): Declaration removed.
* parser.y (expr): Grammar production removed: no longer
referenced.
(o_var): Braced variable case now parsed as n_expr, and
expanded as expr by default, since this is Lisp now. In
compatibility mode, expanded using expand_meta.
Also SYMTOK case must be subject to expansion; an output
var can now be a symbol macro.
(expand_meta): Expand a quasi-literal as Lisp, except
in compatibility mode.
* txr.1: Bit of a documentation update. Existing doc isn't
totally clear.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_iflet_whenlet): Allow the test form
to be an atomic expression instead of bindings.
This allows iflet to be used as the sole target
construct of condlet, while allowing condlet to
have a fallback clause with t. It also means that
an empty list of bindings is allowed (since it
is the atom nil).
* lisplib.c (ifa_set_entries): Add "condlet" to
the autoload names for the ifa module. That's
where we are adding condlet.
* share/txr/stdlib/ifa.tl (sys:if-to-cond): New
macro expander helper function, generalizing the writing
cond-like macros based on if-like operators.
(conda): Rewritten using sys:if-to-cond.
(condlet): New macro.
* txr.1: Documented change in iflet/whenlet.
Documented condlet.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (set_origin): New static function.
(eval_init): Register set_origin as sys:set-macro-ancestor.
* share/txr/stdlib/place.tl (sys:pl-expand): Set macro
ancestry when expanding a place macro.
(sys:cp-origin): New function.
(call-update-expander, call-clobber-expander,
call-delete-expander): Use sys:cp-origin to walk through
expanded code and attach the place form as the macro
ancestor of all the getter, setter or deleter calls,
effectively to say that those calls are expansions of
the place, which is approximately the case.
|
|
|
|
|
|
|
|
|
| |
* eval.c (bind_macro_params): Remove the restriction that the
:whole and :form do not allow a destructuring pattern,
requring strictly a symbol. Common Lisp's &whole also
does destructuring. As a side effect of this change, the :env
parameter also supports destructuring, thought this isn't
going to be meaningful since macro environments aren't lists.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (symbol_function): Only retrieve function binding,
and not macro or operator bindings, unless compatibility
<= 127 is in effect.
(symbol_macro): New function.
(fboundp): Only test for existence of function, not
macro or operator, unless <= 127 compatibility is in effect.
(fmakunbound): Do not remove macro binding, unless
compatibility <= 127 is in effect.
(eval_init): Register sys:top-mb variable for use in place.tl
library module. Register symbol-macro intrinsic function.
* share/txr/stdlib/place.tl (sys:get-mb): New function
(symbol-macro): New syntactic place.
* txr.1: Updated incorrect documentation about environments
from the perspective that macros and functions coexist.
Documented symbol-macro. Updated symbol-function, fboundp
and fmakunbound documentation. Added missing documentation
for mmakunbound. Reference to fboundp under define-place-macro
revised to mboundp. Added compatibility notes.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (expand_macro): The expander argument is now
a macro binding, which is a cons cell for built-in
macros written in C also, not only for Lisp-defined
macros.
(symbol_function): Dereference macro binding.
(reg_mac): Construct cons cell binding for built-in
macro instead of sticking it into the table directly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Already we have the situation that there is an if function and
an if macro, and same for and and or.
This change allows such situations to be programmer-defined.
* eval.c (op_defun): Don't remhash the name from the toplevel
macro bindings.
(op-defmacro): Don't remhash the name from the toplevel
function bindings.
* txr.1: Document the permissive behavior as dialect notes
under defmacro and defun.
|
|
|
|
|
|
|
|
|
| |
* eval.c (mboundp, mmakunbound): New static functions.
(eval_init): Registering mboundp and mmakunbound intrinsics.
* txr.1: Documenting new functions. Also clarifying that
fboundp checks for an operator macro binding (not a symbol
macro binding).
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register lookup_origin as macro-ancestor
intrinsic.
* txr.1: Documented.
|
|
|
|
|
| |
* eval.c (error_trace): Restructure loop. Suppress
"which is located at" message in first iteration.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (op_defun): Handle (meth type name) syntax
in place of name via sys:defmeth function, which
is dynamically resolved and autoloaded as necessary.
(builtin_reject_test): When defun is being checked,
recognize a (method ...) form and allow it.
* struct.h (meth_s): Declaration added.
* txr.1: Documented new defun capability.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The context form arguments become just context objects in
various places. When a context form is actually needed, or the
context's symbolic name, they must be retrieved via functions
applied to a context.
* debug.c (debug): form argument is now a context. Use
the ctx_form function to retrieve the form.
* debug.h (debug_check): Rename form parameter to ctx.
* eval.c (ctx_form, ctx_name): New functions.
(eval_error): Leftmost parameter is a context now.
Use ctx_form API to obtain the context form from
this object, from which the source location info
can then be retrieved as before.
(abbrev_ctx): Function removed.
(bind_args, bindings_helper, fbindings_helper): Convert
ctx_form argument to
ctx, and use the API to access name or form.
(do_eval, do_eval_args, eval, eval_args_lisp1,
eval_lisp1, eval_progn, eval_prog1): ctx_form param
renamed to ctx.
(funcall_interp): Pass the original interpreted
function as the context to bind_args, not the
extracted code. When ctx_name sees this object, it
will compute the function name, which was not possible
from the code being used as the context. This
is the big reason for all these changes.
* eval.h (eval_error): Declaration updated.
(ctx_form, ctx_name): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (env_vbind_special): Remove unused ctx_form
parameter.
(bind_args, bind_macro_params): Don't pass ctx_form to
env_vbind_special.
(apply): Remove unused ctx_form parameter.
(apply_intrinsic, applyv, mapcarv, mappendv,
lazy_mapcarv_func, mapdov, do_mapf): Don't pass nil third
argument to apply.
* eval.h (apply): Declaration updated.
* lib.c (do_juxt): Do not bind third argument of apply
to lin when currying; curry as two argument function.
(do_not): Do not pass third nil argument to apply.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (funcall_interp): Drop the env argument.
The fun argument is now the whole function object, not the
encapsulated code to be interpreted. We pull the
environment and code out of the object locally
and interpret as before.
* eval.h (funcall_interp): Declaration updated.
* lib.c (generic_funcall, funcall, funcall1, funcall2,
* funcall3, funcall4): Calls to funcall_interp simplified,
just passing fun.
|
|
|
|
|
|
|
|
|
| |
* eval.c (interp_fun): Function renamed to funcall_interp.
* eval.h (interp_fun): Declaration updated.
* lib.c (generic_funcall, funcall, funcall1, funcall2,
funcall3, funcall4): Calls to interp_fun updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (func_get_name): Use try to use new method_name
function, if unable to get name from the lexical or
global environment for functions.
* struct.c (meth_s): New symbol variable.
(struct_init): Initialize meth_s variable.
(method_name): New function.
* struct.h (method_name): Declared.
* txr.1: Re-documented func-get-name.
|
|
|
|
|
|
|
| |
* eval.c (bind_macro_params): On mismatch between atom
and param list, or insufficient parameters for list, report
which params are mismatched. In a nested destructuring
syntax, it is difficult to know.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (error_trace): New function. Consolidates
error reporting between unhandled exception handling
in uw_throw, and the catcher in the repl.
(op_defmacro, expand_macrolet): Propagate location info from
body to wrapping block, and to the macro binding. In the
latter function, also to the body that is wrapped by local
macros.
(do_expand, macroexpand_1): Propagate location info from macro
expander to expansion, only taking it from the form if the
macro doesn't supply it.
* eval.h (error_trace): Declared.
* parser.c (repl): Replace error reporting code with call to
error_trace.
* unwind.c (uw_throw): uw_throw: likewise.
|
|
|
|
| |
* eval.c (maybe_progn): rlcp info to generated progn cons.
|
|
|
|
|
|
| |
* eval.c (expand_qquote): Use rlcp_tree to propagate
source location more completely. Also, it was missing
in the quote case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (origin_hash): New global variable.
(lookup_origin): New function.
(expand_macro): Enter original form into origin hash, keyed by
new form.
(eval_init): gc-protect and initialize origin_hash.
* eval.h (lookup_origin): Declared.
* parser.c (repl): Report chain of expansions from
last_form_evaled.
* unwind.c (uw_throw): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* args.h (args_set_fill): New inline function.
* eval.c (eval_init): Register window-map and window-mappend
intrinics.
* lib.c (wrap_k, reflect_k): New keyword variables.
(calc_win_size): New static function.
(window_map_list, window_map_vec): New static functions.
(window_map, window_mappend): New functions.
(obj_init): Initialize wrap_k and reflect_k.
* lib.h (window_map, window_mappend): Declared.
* txr.1: Documented window-map and window-mappend
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Registered butlast intrinsic.
* lib.c (butlast): New function.
* lib.h (butlast): Declared.
* txr.1: Documented butlast.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register revappend and nreconc
intrinsics.
* lib.c (list_collect_nreconc): New function.
(revlist): New static function.
(list_collect_revappend): New function.
(revappend, nreconc): New functions.
* lib.h (revappend, nreconc): Declared.
(list_collect_nreconc, list_collect_revappend): Declared.
* txr.1: Documented revappend and nreconc.
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register group-reduce intrinsic.
* hash.c (group_reduce): New function.
* hash.h (group_reduce): Declared.
* txr.1: Documented group-reduce.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (block_star_s): New symbol variable.
(op_block_star): New static function.
(do_expand): Handle block* symbol.
(return_star, abscond_star): New static functions.
(eval_init): Initialize block_star_s variable.
Register block* operator and return* and sys:abscond*
functions.
* txr.1: Documented new operator and functions.
|
|
|
|
|
|
|
|
| |
* eval.c (op_for): Establish the block before doing any
evaluation, subject to the compatibility option.
* txr.1: Updated documentation for for, exchanging
steps 1 and 2. Added compatibility notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The read function no longer works like it used to on an
interactive terminal because of the support for .. and .
syntax on a top-level expression.
The iread function is provided which uses a modified syntax
that doesn't support these operators on a top-level
expression. The parser thus doesn't look one token ahead,
and so iread can return immediately.
* eval.c (eval_init): Register iread intrinsic function.
* parser.c (prime_parser): Only push back the recently seen
token when priming for a regular Lisp read. Handle
the prime_interactive method by preparing a SECRET_ESCAPE_I
token.
(lisp_parse_impl): New static function, formed from previous
lisp_parse. Takes a boolean argument indicating interactive
mode.
(prime_parser_post): New function.
(lisp_parse): Now a wrapper for lisp_parse_impl which
passes a nil to indicate noninteractive read.
(iread): New function.
* parser.h (enum prime_parser): New member, prime_interactive.
(scrub_scanner, iread, prime_parser_post): Declared.
* parser.l (prime_scanner): Handle the prime_interactive case
the same way as prime_lisp.
(scrub_scanner): New function.
* parser.y (SECRET_ESCAPE_I): New token type.
(i_expr): New nonterminal symbol. Like n_expr, but doesn't
support dot or dotdot operators, except in nested
subexpressions.
(spec): Handle SECRET_ESCAPE_I by way of i_expr.
(sym_helper): Before freeing the token lexeme, call
scrub_scanner. If the token is registered as the scanner's
most recently seen token, the scanner must forget that
registration, because it is no longer valid.
(parse): Call prime_parser_post.
* txr.1: Documented iread.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When continuations are captured/restored in the middle of
variable binding constructs, a hidden problem occurs.
Binding constructs work by allocating an empty environment
and then destructively extending it. Since the environment
is not on the stack, but a referenced object, it doesn't
get deep copied into a continuation. As the continuation is
revived repeatedly, parts of the variable binding code are
repeatedly re-executed, and keep pushing fresh bindings into
the same environment object. Though the new bindings
correctly shadow the old, the old bindings are there and
potentially hang on to garbage.
The solution taken here is to introduce a new kind of frame
for handling the situation: a continuation copy handling
frame. This frame allows functions to register objects to
be copied more deeply if a continuation is captured/revived
across them.
* eval.c (copy_env): New static function.
(copy_env_handler): New static function.
(bind_args, bind_macro_params): Install continuation copy
handling frame for cloning new_env.
(struct bindings_helper_vars): New struct type.
(copy_bh_env_handler): New static function.
(bindings_helper): Install continuation copy handling frame
for de and ne variables which hold environments. The variables
are moved to a struct to facilitate access from the handler.
* eval.h (copy_env): Declared.
* unwind.c (uw_push_cont_copy): New function.
(call_copy_handler): New static function.
(revive_cont): When a continuation is being revived invoke the
copying actions in its continuation copy handling frames,
but not if it is only being temporarily revived for immediate
unwinding.
(capture_cont): After copying the continuation, invoke any
continuation copying frames in the "parent": the original
frames that were captured.
* unwind.h (enum uw_frtype): New type, UW_CONT_COPY.
(struct uw_cont_copy): New struct type.
(union uw_frame): New member cp.
(uw_push_cont_copy): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (set_dyn_env): Static function becomes external.
* eval.h (set_dyn_env): Declared.
* match.c (eval_with_bindings, eval_progn_with_bindings):
Evaluate Lisp code in null lexical environment. Instead
install the pattern variables as dynamic, so they shadow
global variables. A compatibility check for 121 or earlier
provides the old behavior.
* txr.1: Document scoping rules, and added compatibility
notes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (eval_init): Register intrinsic functions rcons,
rangep from and to.
(eval_init): Register rangep intrinsic.
* gc.c (mark_obj): Traverse RNG objects.
(finalize): Handle RNG in switch.
* hash.c (equal_hash, eql_hash): Hashing for for RNG objects.
* lib.c (range_s, rcons_s): New symbol variables.
(code2type): Handle RNG type.
(eql, equal): Equality for ranges.
(less_tab_init): Table extended to cover RNG.
(less): Semantics defined for ranges.
(rcons, rangep, from, to): New functions.
(obj_init): range_s and rcons_s variables initialized.
(obj_print_impl): Produce #R notation for ranges.
(generic_funcall, dwim_set): Recognize range objects for indexing
* lib.h (enum type): New enum member, RNG. MAXTYPE redefined
to RNG value.
(TYPE_SHIFT): Increased to 5 since there are now 16 type
codes.
(struct range): New struct type.
(union obj): New member rn, of type struct range.
(range_s, rcons_s, rcons, rangep, from, to): Declared.
(range_bind): New macro.
* parser.l (grammar): New rule for recognizing
the #R sequence as HASH_R token.
* parser.y (HASH_R): New terminal symbol.
(range): New nonterminal symbol.
(n_expr): Derives the new range symbol.
The n_expr DOTDOT n_expr rule produces rcons expression rather
than const.
* match.c (format_field): Recognize rcons syntax in fields
which is now what ranges translate to. Also recognize range
object.
* tests/013/maze.tl (neigh): Fix code which destructures
range as a cons. That can't be done any more.
* txr.1: Document ranges.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (sys_abscond_from_s): New symbol variable.
(op_abscond_from): New static function.
(do_expand): Handle abscond-from like return-from.
(eval_init): Initialize sys_abscond_from_s and
register sys:abscond-from operator.
* share/txr/stdlib/yield.tl (yield-from): Use
sys:abscond-from instead of return-from, to avoid
tearing down the continuation's resources that it may
need when restarted.
* txr.1: Documented sys:abscond-from and added
a mention to the Delimited Continuations introduction.
* unwind.c (uw_abscond_to_exit_point): New static function.
(uw_block_abscond): New function.
* unwind.h (uw_block_abscond): Declared.
|
|
|
|
|
|
| |
* eval.c (eval_error): Static function made external.
* eval.h (eval_error): Declared.
|
|
|
|
|
|
|
|
| |
* eval.c (form_k): New keyword symbol variable.
(bind_macro_params): Implement form_k.
(eval_init): Initialize form_k.
* txr.1: Documented :form parameter.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
TXR is moving to custom assembly-language routines.
This is mainly motivated by a very dubious thing done in the
GNU C Library setjmp and longjmp in the name of security.
Evidently, glibc's setjmp "mangles" certain pointer values
which are stored into the jmp_buf buffer. It's been that way
since 2005, evidently. This means that, firstly, all along,
the use of setjmp in gc.c to get registers into a buffer so
they can be scanned has not actually worked properly. More
importantly, this pointer mangling in setjmp and longjmp is
very hostile to a stack copying implementation of delimited
continuations. The reason is that continuations contain
jmp_buf buffers, which get relocated in the process of
capturing and reviving a continuation. Any pointers in a
jmp_buf which point into the captured stack segment have to be
fixed up to point into the relocated location. Mangled
pointers make this difficult, requiring hacks which are
specific to glibc and the machine architecture. We might as
well implement a clean, well-behaved setjmp and longjmp.
* Makefile (jmp.o): New object file.
(dbg/%.o, opt/%.o): New rules for .S prerequisites.
* args.c, arith.c, cadr.c, combi.c, cadr.c, combi.c, debug.c,
eval.c, filter.c, glob.c, hash.c, lib.c, match.c, parser.c,
rand.c, regex.c, signal.c, stream.c, struct.c, sysif.c,
syslog.c, txr.c, unwind.c, utf8.c: Removed <setjmp.h>
include.
* gc.c: Switch to struct jmp and jmp_save, instead
of jmp_buf and setjmp.
* jmp.S: New source file.
* signal.h (struct jmp): New struct type.
(jmp_save, jmp_restore): New function declarations
denoting assembly language routines in jmp.S.
(extended_jmp_buf): Uses struct jmp instead of
setjmp.
(extended_setjmp): Use jmp_save instead of setjmp.
(extended_longjmp): Use jmp_restore instead of
longjmp.
|