// File: /workspace/github_c_makefile_star2_O2/BernardTatin[P]s7sh/s7.c
// Function: catch_1_function
static bool catch_1_function(s7_scheme *sc, s7_int i, s7_pointer type, s7_pointer info, bool *reset_hook)
                {
                    s7_pointer x;
                    x = stack_code(sc->stack, i);
                    if ((catch_tag(x) == sc->T) ||
                            (catch_tag(x) == type) ||
                            (type == sc->T))
                    {
                        uint64_t loc;
                        opcode_t op;
                        s7_pointer catcher, error_func, error_body, error_args;

                        op = stack_op(sc->stack, i);
                        sc->temp4 = stack_let(sc->stack, i); /* GC protect this, since we're moving the stack top below */
                        catcher = x;
                        loc = catch_goto_loc(catcher);
                        sc->op_stack_now = (s7_pointer *)(sc->op_stack + catch_op_loc(catcher));
                        sc->stack_end = (s7_pointer *)(sc->stack_start + loc);
                        error_func = catch_handler(catcher);

                        /* very often the error handler just returns either a constant ('error or #f), or
                         *   the args passed to it, so there's no need to laboriously make a closure,
                         *   and apply it -- just set sc->value to the closure body (or the args) and return.
                         * so first examine closure_body(error_func)
                         *   if it is a constant, or quoted symbol, return that,
                         *   if it is the args symbol, return (list type info)
                         */

                        /* if OP_CATCH_1, we deferred making the error handler until it is actually needed */
                        if (op == OP_CATCH_1)
                        {
                            error_body = cdr(error_func);
                            error_args = car(error_func);
                        }
                        else
                        {
                            if (is_closure(error_func))
                            {
                                error_body = closure_body(error_func);
                                error_args = closure_args(error_func);
                            }
                            else
                            {
                                error_body = NULL;
                                error_args = NULL;
                            }
                        }

                        if ((error_body) && (is_null(cdr(error_body))))
                        {
                            s7_pointer y = NULL;
                            error_body = car(error_body);
                            if (is_pair(error_body))
                            {
                                if (car(error_body) == sc->quote_symbol)
                                    y = cadr(error_body);
                                else
                                {
                                    if ((car(error_body) == sc->car_symbol) &&
                                            (cadr(error_body) == error_args))
                                        y = type;
                                }
                            }
                            else
                            {
                                if (is_symbol(error_body))
                                {
                                    if (error_body == error_args)
                                        y = list_2(sc, type, info);
                                    else
                                    {
                                        if (is_keyword(error_body))
                                            y = error_body;
                                        else
                                        {
                                            if ((is_pair(error_args)) &&
                                                    (error_body == car(error_args)))
                                                y = type;
                                        }
                                    }
                                }
                                else y = error_body; /* not pair or symbol */
                            }
                            if (y)
                            {
                                if (loc > 4)
                                    pop_stack(sc);
                                /* we're at OP_CATCH, normally we want to pop that away, but (handwaving...) if we're coming
                                 *   from s7_eval (indirectly perhaps through s7_eval_c_string), we might push the OP_EVAL_DONE
                                 *   to end that call, but it's pushed at the precatch stack end (far beyond the catch loc).
                                 *   If we catch an error, catch unwinds to its starting point, and the pop_stack above
                                 *   puts us at the bottom of the stack (i.e. stack_end == stack_start), OP_EVAL_DONE.
                                 *   Now we return true, ending up back in eval, because the error handler jumped out of eval,
                                 *   back to wherever we were in eval when we hit the error.  eval jumps back to the start
                                 *   of its loop, and pops the stack to see what to do next!  So the (loc > 4) at least
                                 *   protects against stack underflow, but ideally we'd know we came from OP_CATCH+s7_eval.
                                 *   We can't do anything fancy here because we have to unwind the C stack as well as s7's stack.
                                 *   s7_eval doesn't know anything about the catches on the stack.  We can't look back for
                                 *   OP_EVAL_DONE -- segfault in OP_BEGIN.  Hmmmm.  Perhaps catch should not unwind until the
                                 *   end?  But we want the error handler to run as a part of the calling expression, and
                                 *   in any case the OP_EVAL_DONE is not useful (it marks the end of the no-error case).
                                 */
                                sc->value = y;
                                sc->temp4 = sc->nil;
                                if (loc == 4)
                                    sc->code = cons(sc, sc->value, sc->nil); /* if we end up at op_begin, give it something it can handle */
                                return(true);
                            }
                        }
                        if (op == OP_CATCH_1)
                        {
                            s7_pointer p;
                            new_cell(sc, p, T_CLOSURE | T_COPY_ARGS); /* never a safe_closure, apparently */
                            closure_set_args(p, car(error_func));
                            closure_set_body(p, cdr(error_func));
                            closure_set_setter(p, sc->F);
                            closure_set_arity(p, CLOSURE_ARITY_NOT_SET);
                            closure_set_let(p, sc->temp4);
                            sc->code = p;
                        }
                        else sc->code = error_func;
                        sc->temp4 = sc->nil;

                        /* if user (i.e. yers truly!) copies/pastes the preceding lambda () into the
                         *   error handler portion of the catch, he gets the inexplicable message:
                         *       ;(): too many arguments: (a1 ())
                         *   when this apply tries to call the handler.  So, we need a special case error check here!
                         */

                        if (!s7_is_aritable(sc, sc->code, 2))
                            s7_wrong_number_of_args_error(sc, "catch error handler should accept 2 args: ~S", sc->code);

                        sc->args = list_2(sc, type, info); /* almost never able to skip this -- costs more to check! */
                        sc->cur_op = OP_APPLY;
                        /* explicit eval needed if s7_call called into scheme where a caught error occurred (ex6 in exs7.c)
                         *  but putting it here (via eval(sc, OP_APPLY)) means the C stack is not cleared correctly in non-s7-call cases,
                         *  so defer it until s7_call
                         */
                        return(true);
                    }
                    return(false);
                }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r14
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x118(%rdi), %rdx
movq 0x10(%rax), %rax
movq -0x18(%rax,%rsi,8), %r9
movq 0x18(%r9), %rdi
cmpq %rdx, %rdi
sete %r8b
cmpq %r14, %rdi
sete %dil
orb %r8b, %dil
cmpq %r14, %rdx
sete %bpl
orb %dil, %bpl
cmpb $0x1, %bpl
jne 0xc6970
movq -0x10(%rax,%rsi,8), %rdx
movq (%rax,%rsi,8), %rax
movq %rdx, 0x510(%rbx)
movq 0x8(%r9), %r13
movq 0x10(%r9), %rdx
shlq $0x3, %rdx
addq 0x60(%rbx), %rdx
movq %rdx, 0x68(%rbx)
leaq (,%r13,8), %rdx
addq 0x48(%rbx), %rdx
movq %rdx, 0x50(%rbx)
movq 0x20(%r9), %r12
cmpq $0x216, %rax            # imm = 0x216
je 0xc6837
cmpb $0x28, (%r12)
jne 0xc685a
movq 0x10(%r12), %rdx
testq %rdx, %rdx
je 0xc6852
movq 0x110(%rbx), %r15
cmpq %r15, 0x10(%rdx)
je 0xc6981
cmpq $0x216, %rax            # imm = 0x216
je 0xc685f
movq %rcx, %r13
jmp 0xc68c9
movq %rcx, %r13
movq 0x90(%rbx), %rax
cmpq 0x98(%rbx), %rax
ja 0xc6881
movq %rbx, %rdi
callq 0x9c27
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %rax
movq $0x10000028, (%rax)     # imm = 0x10000028
movq 0x8(%r12), %rcx
movq %rcx, 0x8(%rax)
movq 0x10(%r12), %rcx
movq %rcx, 0x10(%rax)
movq 0x120(%rbx), %rcx
movq %rcx, 0x20(%rax)
movl $0x40000000, 0x28(%rax) # imm = 0x40000000
movq 0x510(%rbx), %rcx
movq %rcx, 0x18(%rax)
movq %rax, %r12
movq %r12, (%rbx)
movq 0x110(%rbx), %rax
movq %rax, 0x510(%rbx)
pushq $0x2
popq %rdx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x32378
testb %al, %al
jne 0xc68fe
movq (%rbx), %rdx
leaq 0x20847(%rip), %rsi     # 0xe713d
movq %rbx, %rdi
callq 0x2e40a
movq 0x90(%rbx), %rax
movq 0x110(%rbx), %r15
cmpq 0x98(%rbx), %rax
ja 0xc6924
movq %rbx, %rdi
callq 0x9c27
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %rax
movl $0x200001, %ecx         # imm = 0x200001
movq %rcx, (%rax)
movq %r13, 0x8(%rax)
movq %r15, 0x10(%rax)
movq 0x90(%rbx), %rdx
leaq -0x8(%rdx), %rsi
movq %rsi, 0x90(%rbx)
movq -0x8(%rdx), %rdx
movq %rcx, (%rdx)
movq %r14, 0x8(%rdx)
movq %rax, 0x10(%rdx)
movq %rdx, 0x10(%rbx)
movq $0x198, 0x18(%rbx)      # imm = 0x198
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r12), %rsi
movq 0x8(%rdx), %r8
movzbl (%r8), %edx
cmpl $0xa, %edx
je 0xc69c9
cmpl $0x1, %edx
jne 0xc6a68
movq 0x8(%r8), %rdx
cmpq 0x17b0(%rbx), %rdx
je 0xc69f1
cmpq 0xd20(%rbx), %rdx
jne 0xc6852
movq 0x10(%r8), %rdx
movq %r14, %r8
cmpq %rsi, 0x8(%rdx)
jne 0xc6852
jmp 0xc69f9
cmpq %rsi, %r8
je 0xc6a03
testb $-0x80, 0x6(%r8)
jne 0xc6a68
cmpb $0x1, (%rsi)
jne 0xc6852
cmpq 0x8(%rsi), %r8
movq %r14, %r8
jne 0xc6852
jmp 0xc69f9
movq 0x10(%r8), %rdx
movq 0x8(%rdx), %r8
testq %r8, %r8
jne 0xc6a68
jmp 0xc6852
movq 0x90(%rbx), %rax
cmpq 0x98(%rbx), %rax
ja 0xc6a28
movq %rbx, %rdi
movq %rcx, %r12
callq 0x9c27
movq %r12, %rcx
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rdx
movq %rdx, 0x90(%rbx)
movq -0x8(%rax), %rax
movl $0x200001, %edi         # imm = 0x200001
movq %rdi, (%rax)
movq %rcx, 0x8(%rax)
movq %r15, 0x10(%rax)
movq 0x90(%rbx), %rdx
leaq -0x8(%rdx), %rsi
movq %rsi, 0x90(%rbx)
movq -0x8(%rdx), %r8
movq %rdi, (%r8)
movq %r14, 0x8(%r8)
movq %rax, 0x10(%r8)
cmpq $0x5, %r13
jb 0xc6a89
movq 0x50(%rbx), %rax
leaq -0x20(%rax), %rcx
movq %rcx, 0x50(%rbx)
movups -0x20(%rax), %xmm0
movups -0x10(%rax), %xmm1
movups %xmm0, (%rbx)
movups %xmm1, 0x10(%rbx)
movq %r8, 0x20(%rbx)
movq 0x110(%rbx), %r14
movq %r14, 0x510(%rbx)
cmpq $0x4, %r13
jne 0xc6970
movq 0x90(%rbx), %rax
cmpq 0x98(%rbx), %rax
ja 0xc6aca
movq %rbx, %rdi
movq %r8, %r15
callq 0x9c27
movq %r15, %r8
movq 0x90(%rbx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rbx)
movq -0x8(%rax), %rax
movq $0x200001, (%rax)       # imm = 0x200001
movq %r8, 0x8(%rax)
movq %r14, 0x10(%rax)
movq %rax, (%rbx)
jmp 0xc6970