home *** CD-ROM | disk | FTP | other *** search
- /* lispmach.c -- Interpreter for compiled Lisp forms
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #ifdef HAVE_ALLOCA
- # include <alloca.h>
- #endif
-
- _PR void lispmach_init(void);
-
- #define OP_CALL 0x08
- #define OP_PUSH 0x10
- #define OP_VREFC 0x18
- #define OP_VSETC 0x20
- #define OP_LIST 0x28
- #define OP_BIND 0x30
- #define OP_LAST_WITH_ARGS 0x38
-
- #define OP_VREF 0x40
- #define OP_VSET 0x41
- #define OP_FREF 0x42
- #define OP_FSET 0x43
- #define OP_INIT_BIND 0x44
- #define OP_UNBIND 0x45
- #define OP_DUP 0x46
- #define OP_SWAP 0x47
- #define OP_POP 0x48
-
- #define OP_NIL 0x49
- #define OP_T 0x4a
- #define OP_CONS 0x4b
- #define OP_CAR 0x4c
- #define OP_CDR 0x4d
- #define OP_RPLACA 0x4e
- #define OP_RPLACD 0x4f
- #define OP_NTH 0x50
- #define OP_NTHCDR 0x51
- #define OP_ASET 0x52
- #define OP_AREF 0x53
- #define OP_LENGTH 0x54
- #define OP_EVAL 0x55
- #define OP_PLUS_2 0x56
- #define OP_NEGATE 0x57
- #define OP_MINUS_2 0x58
- #define OP_PRODUCT_2 0x59
- #define OP_DIVIDE_2 0x5a
- #define OP_MOD_2 0x5b
- #define OP_BIT_NOT 0x5c
- #define OP_NOT 0x5d
- #define OP_BIT_OR_2 0x5e
- #define OP_BIT_AND_2 0x5f
- #define OP_EQUAL 0x60
- #define OP_EQ 0x61
- #define OP_NUM_EQ 0x62
- #define OP_NUM_NOTEQ 0x63
- #define OP_GTTHAN 0x64
- #define OP_GETHAN 0x65
- #define OP_LTTHAN 0x66
- #define OP_LETHAN 0x67
- #define OP_INC 0x68
- #define OP_DEC 0x69
- #define OP_LSH 0x6a
- #define OP_ZEROP 0x6b
- #define OP_NULL 0x6c
- #define OP_ATOM 0x6d
- #define OP_CONSP 0x6e
- #define OP_LISTP 0x6f
- #define OP_NUMBERP 0x70
- #define OP_STRINGP 0x71
- #define OP_VECTORP 0x72
- #define OP_CATCH_KLUDGE 0x73
- #define OP_THROW 0x74
- #define OP_UNWIND_PRO 0x75
- #define OP_UN_UNWIND_PRO 0x76
- #define OP_FBOUNDP 0x77
- #define OP_BOUNDP 0x78
- #define OP_SYMBOLP 0x79
- #define OP_GET 0x7a
- #define OP_PUT 0x7b
- #define OP_ERROR_PRO 0x7c
- #define OP_SIGNAL 0x7d
-
- #define OP_SET_CURRENT_BUFFER 0xb0
- #define OP_SWAP_BUFFER 0xb1
- #define OP_CURRENT_BUFFER 0xb2
- #define OP_BUFFERP 0xb3
- #define OP_MARK_P 0xb4
- #define OP_WINDOWP 0xb5
- #define OP_SWAP_WINDOW 0xb6
-
- #define OP_LAST_BEFORE_JMPS 0xfa
- #define OP_JMP 0xfb
- #define OP_JMP_NIL 0xfc
- #define OP_JMP_T 0xfd
- #define OP_JMP_NIL_ELSE_POP 0xfe
- #define OP_JMP_T_ELSE_POP 0xff
-
- #define TOP (*stackp)
- #define RET_POP (*stackp--)
- #define POP (stackp--)
- #define POPN(n) (stackp -= n)
- #define PUSH(v) (*(++stackp) = (v))
- #define STK_USE (stackp - (stackbase - 1))
-
- #define ARG_MASK 0x7f
- #define ARG_SHIFT 7
- #define OP_ARG_MASK 0x07
- #define OP_OP_MASK 0xf8
- #define OP_ARG_1BYTE 6
- #define OP_ARG_2BYTE 7
-
- _PR VALUE cmd_lisp_code(VALUE code, VALUE consts, VALUE stkreq);
- DEFUN("lisp-code", cmd_lisp_code, subr_lisp_code, (VALUE code, VALUE consts, VALUE stkreq), V_Subr3, DOC_lisp_code) /*
- ::doc:lisp_code::
- (lisp-code CODE-STRING CONST-VEC MAX-STACK)
- Evaluates the string of byte codes CODE-STRING, the constants that it
- references are contained in the vector CONST-VEC. MAX-STACK is a number
- defining how much stack space is required to evaluate the code.
-
- Do *not* attempt to call this function manually, the lisp file `compiler.jl'
- contains a simple compiler which translates files of lisp forms into files
- of byte code. See the functions `compile-file', `compile-directory' and
- `compile-lisp-lib' for more details.
- ::end:: */
- {
- VALUE *stackbase;
- register VALUE *stackp;
- /* This holds a list of sets of bindings, it can also hold the form of
- an unwind-protect that always gets eval'd (when the car is t). */
- VALUE bindstack = sym_nil;
- register u_char *pc;
- u_char c;
- GCVAL gcv_code, gcv_consts, gcv_bindstack;
- /* The `gcv_N' field is only filled in with the stack-size when there's
- a chance of gc. */
- GCVALN gcv_stackbase;
-
- DECLARE1(code, STRINGP);
- DECLARE2(consts, VECTORP);
- DECLARE3(stkreq, NUMBERP);
-
- #ifdef HAVE_ALLOCA
- stackbase = alloca(sizeof(VALUE) * VNUM(stkreq));
- #else
- if(!(stackbase = mystralloc(sizeof(VALUE) * VNUM(stkreq))))
- return(NULL);
- #endif
-
- stackp = stackbase - 1;
- PUSHGC(gcv_code, code);
- PUSHGC(gcv_consts, consts);
- PUSHGC(gcv_bindstack, bindstack);
- PUSHGCN(gcv_stackbase, stackbase, 0);
-
- pc = VSTR(code);
- while((c = *pc++) != 0)
- {
- if(c < OP_LAST_WITH_ARGS)
- {
- register short arg;
- switch(c & OP_ARG_MASK)
- {
- case OP_ARG_1BYTE:
- arg = *pc++ & ARG_MASK;
- break;
- case OP_ARG_2BYTE:
- arg = ((pc[0] & ARG_MASK) << ARG_SHIFT) | (pc[1] & ARG_MASK);
- pc += 2;
- break;
- default:
- arg = c & OP_ARG_MASK;
- }
- switch(c & OP_OP_MASK)
- {
- register VALUE tmp;
- VALUE tmp2;
- case OP_CALL:
- #ifdef MINSTACK
- if(STK_SIZE <= MINSTACK)
- {
- STK_WARN("lisp-code");
- TOP = cmd_signal(sym_stack_error, sym_nil);
- goto quit;
- }
- #endif
- if((DataAfterGC >= DataBeforeGC) && !GCinhibit)
- {
- gcv_stackbase.gcv_N = STK_USE;
- cmd_garbage_collect(sym_t);
- }
- /* args are still available above the top of the stack,
- this just makes things a bit easier. */
- POPN(arg);
- tmp = TOP;
- if(SYMBOLP(tmp))
- {
- if(VSYM(tmp)->sym_Flags & SF_DEBUG)
- SingleStepFlag = TRUE;
- /* The `+ arg' is to make sure that our args (which were
- sort of popped) are protected from gc as well. */
- if(!(tmp = cmd_symbol_function(tmp)))
- {
- cmd_signal(sym_void_function, LIST_1(TOP));
- goto error;
- }
- }
- gcv_stackbase.gcv_N = STK_USE;
- switch(VTYPE(tmp))
- {
- case V_Subr0:
- TOP = VSUBR0FUN(tmp)();
- break;
- case V_Subr1:
- TOP = VSUBR1FUN(tmp)(arg >= 1 ? stackp[1] : sym_nil);
- break;
- case V_Subr2:
- switch(arg)
- {
- case 0:
- TOP = VSUBR2FUN(tmp)(sym_nil, sym_nil);
- break;
- case 1:
- TOP = VSUBR2FUN(tmp)(stackp[1], sym_nil);
- break;
- default:
- TOP = VSUBR2FUN(tmp)(stackp[1], stackp[2]);
- break;
- }
- break;
- case V_Subr3:
- switch(arg)
- {
- case 0:
- TOP = VSUBR3FUN(tmp)(sym_nil, sym_nil, sym_nil);
- break;
- case 1:
- TOP = VSUBR3FUN(tmp)(stackp[1], sym_nil, sym_nil);
- break;
- case 2:
- TOP = VSUBR3FUN(tmp)(stackp[1], stackp[2], sym_nil);
- break;
- default:
- TOP = VSUBR3FUN(tmp)(stackp[1], stackp[2], stackp[3]);
- break;
- }
- break;
- case V_Subr4:
- switch(arg)
- {
- case 0:
- TOP = VSUBR4FUN(tmp)(sym_nil, sym_nil,
- sym_nil, sym_nil);
- break;
- case 1:
- TOP = VSUBR4FUN(tmp)(stackp[1], sym_nil,
- sym_nil, sym_nil);
- break;
- case 2:
- TOP = VSUBR4FUN(tmp)(stackp[1], stackp[2],
- sym_nil, sym_nil);
- break;
- case 3:
- TOP = VSUBR4FUN(tmp)(stackp[1], stackp[2],
- stackp[3], sym_nil);
- break;
- default:
- TOP = VSUBR4FUN(tmp)(stackp[1], stackp[2],
- stackp[3], stackp[4]);
- break;
- }
- break;
- case V_Subr5:
- switch(arg)
- {
- case 0:
- TOP = VSUBR5FUN(tmp)(sym_nil, sym_nil, sym_nil,
- sym_nil, sym_nil);
- break;
- case 1:
- TOP = VSUBR5FUN(tmp)(stackp[1], sym_nil, sym_nil,
- sym_nil, sym_nil);
- break;
- case 2:
- TOP = VSUBR5FUN(tmp)(stackp[1], stackp[2], sym_nil,
- sym_nil, sym_nil);
- break;
- case 3:
- TOP = VSUBR5FUN(tmp)(stackp[1], stackp[2], stackp[3],
- sym_nil, sym_nil);
- break;
- case 4:
- TOP = VSUBR5FUN(tmp)(stackp[1], stackp[2], stackp[3],
- stackp[4], sym_nil);
- default:
- TOP = VSUBR5FUN(tmp)(stackp[1], stackp[2], stackp[3],
- stackp[4], stackp[5]);
- break;
- }
- break;
- case V_SubrN:
- tmp2 = sym_nil;
- POPN(-arg); /* reclaim my args */
- while(arg--)
- tmp2 = cmd_cons(RET_POP, tmp2);
- TOP = VSUBRNFUN(tmp)(tmp2);
- break;
- case V_Cons:
- tmp2 = sym_nil;
- POPN(-arg);
- while(arg--)
- tmp2 = cmd_cons(RET_POP, tmp2);
- if(VCAR(tmp) == sym_lambda)
- {
- struct LispCall lc;
- lc.lc_Next = LispCallStack;
- lc.lc_Fun = TOP;
- lc.lc_Args = tmp2;
- lc.lc_ArgsEvalledP = sym_t;
- LispCallStack = &lc;
- if(!(TOP = evallambda(tmp, tmp2, FALSE))
- && ThrowValue && (VCAR(ThrowValue) == sym_defun))
- {
- TOP = VCDR(ThrowValue);
- ThrowValue = NULL;
- }
- LispCallStack = lc.lc_Next;
- }
- else if(VCAR(tmp) == sym_autoload)
- /* I can't be bothered to go to all the hassle
- of doing this here, it's going to be slow
- anyway so just pass it to funcall. */
- TOP = funcall(TOP, tmp2);
- else
- {
- cmd_signal(sym_invalid_function, LIST_1(TOP));
- goto error;
- }
- break;
- default:
- cmd_signal(sym_invalid_function, LIST_1(TOP));
- goto error;
- }
- if(!TOP)
- goto error;
- break;
- case OP_PUSH:
- PUSH(VVECT(consts)->vc_Array[arg]);
- break;
- case OP_VREFC:
- if(PUSH(cmd_symbol_value(VVECT(consts)->vc_Array[arg])))
- break;
- goto error;
- case OP_VSETC:
- if(cmd_set(VVECT(consts)->vc_Array[arg], RET_POP))
- break;
- goto error;
- case OP_LIST:
- tmp = sym_nil;
- while(arg--)
- tmp = cmd_cons(RET_POP, tmp);
- PUSH(tmp);
- break;
- case OP_BIND:
- tmp = VVECT(consts)->vc_Array[arg];
- if(SYMBOLP(tmp))
- {
- VCAR(bindstack) = bindsymbol(VCAR(bindstack), tmp, RET_POP);
- break;
- }
- goto error;
- }
- }
- else
- {
- switch(c)
- {
- register VALUE tmp;
- VALUE tmp2;
- int i;
- case OP_POP:
- POP;
- break;
- case OP_VREF:
- if((TOP = cmd_symbol_value(TOP)))
- break;
- goto error;
- case OP_VSET:
- tmp = RET_POP;
- if(cmd_set(tmp, RET_POP))
- break;
- goto error;
- case OP_FREF:
- if((TOP = cmd_symbol_function(TOP)))
- break;
- goto error;
- case OP_FSET:
- tmp = RET_POP;
- if(cmd_fset(tmp, RET_POP))
- break;
- goto error;
- case OP_INIT_BIND:
- bindstack = cmd_cons(sym_nil, bindstack);
- break;
- case OP_UNBIND:
- unbindsymbols(VCAR(bindstack));
- bindstack = VCDR(bindstack);
- break;
- case OP_DUP:
- tmp = TOP;
- PUSH(tmp);
- break;
- case OP_SWAP:
- tmp = TOP;
- TOP = stackp[-1];
- stackp[-1] = tmp;
- break;
- case OP_NIL:
- PUSH(sym_nil);
- break;
- case OP_T:
- PUSH(sym_t);
- break;
- case OP_CONS:
- tmp = RET_POP;
- if((TOP = cmd_cons(TOP, tmp)))
- break;
- goto error;
- case OP_CAR:
- tmp = TOP;
- if(CONSP(tmp))
- TOP = VCAR(tmp);
- else
- TOP = sym_nil;
- break;
- case OP_CDR:
- tmp = TOP;
- if(CONSP(tmp))
- TOP = VCDR(tmp);
- else
- TOP = sym_nil;
- break;
- case OP_RPLACA:
- tmp = RET_POP;
- if((TOP = cmd_rplaca(TOP, tmp)))
- break;
- goto error;
- case OP_RPLACD:
- tmp = RET_POP;
- if((TOP = cmd_rplacd(TOP, tmp)))
- break;
- goto error;
- case OP_NTH:
- tmp = RET_POP;
- if((TOP = cmd_nth(TOP, tmp)))
- break;
- goto error;
- case OP_NTHCDR:
- tmp = RET_POP;
- if((TOP = cmd_nthcdr(TOP, tmp)))
- break;
- goto error;
- case OP_ASET:
- tmp = RET_POP;
- tmp2 = RET_POP;
- if((TOP = cmd_aset(TOP, tmp2, tmp)))
- break;
- goto error;
- case OP_AREF:
- tmp = RET_POP;
- if((TOP = cmd_aref(TOP, tmp)))
- break;
- goto error;
- case OP_LENGTH:
- if(!(tmp = cmd_length(TOP)))
- goto error;
- TOP = tmp;
- break;
- case OP_EVAL:
- gcv_stackbase.gcv_N = STK_USE;
- if((TOP = cmd_eval(TOP)))
- break;
- goto error;
- case OP_PLUS_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) + VNUM(tmp));
- break;
- }
- goto error;
- case OP_NEGATE:
- if(NUMBERP(TOP))
- {
- TOP = newnumber(-VNUM(TOP));
- break;
- }
- goto error;
- case OP_MINUS_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) - VNUM(tmp));
- break;
- }
- goto error;
- case OP_PRODUCT_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) * VNUM(tmp));
- break;
- }
- goto error;
- case OP_DIVIDE_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) / VNUM(tmp));
- break;
- }
- goto error;
- case OP_MOD_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) % VNUM(tmp));
- break;
- }
- goto error;
- case OP_BIT_NOT:
- if(NUMBERP(TOP))
- {
- TOP = newnumber(~VNUM(TOP));
- break;
- }
- goto error;
- case OP_NOT:
- if(TOP == sym_nil)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_BIT_OR_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) | VNUM(tmp));
- break;
- }
- goto error;
- case OP_BIT_AND_2:
- tmp = RET_POP;
- if(NUMBERP(tmp) && NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) & VNUM(tmp));
- break;
- }
- goto error;
- case OP_EQUAL:
- tmp = RET_POP;
- if(!(VALUECMP(TOP, tmp)))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_EQ:
- tmp = RET_POP;
- if(TOP == tmp)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_NUM_EQ:
- tmp = RET_POP;
- if((TOP = cmd_num_eq(TOP, tmp)))
- break;
- goto error;
- case OP_NUM_NOTEQ:
- tmp = RET_POP;
- if((TOP = cmd_num_noteq(TOP, tmp)))
- break;
- goto error;
- case OP_GTTHAN:
- tmp = RET_POP;
- if(VALUECMP(TOP, tmp) > 0)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_GETHAN:
- tmp = RET_POP;
- if(VALUECMP(TOP, tmp) >= 0)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_LTTHAN:
- tmp = RET_POP;
- if(VALUECMP(TOP, tmp) < 0)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_LETHAN:
- tmp = RET_POP;
- if(VALUECMP(TOP, tmp) <= 0)
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_INC:
- if(NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) + 1);
- break;
- }
- goto error;
- case OP_DEC:
- if(NUMBERP(TOP))
- {
- TOP = newnumber(VNUM(TOP) - 1);
- break;
- }
- goto error;
- case OP_LSH:
- tmp = RET_POP;
- if((TOP = cmd_lsh(TOP, tmp)))
- break;
- goto error;
- case OP_ZEROP:
- if(NUMBERP(TOP) && (VNUM(TOP) == 0))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_NULL:
- if(NILP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_ATOM:
- if(!CONSP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_CONSP:
- if(CONSP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_LISTP:
- if(CONSP(TOP) || NILP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_NUMBERP:
- if(NUMBERP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_STRINGP:
- if(STRINGP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_VECTORP:
- if(VECTORP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_CATCH_KLUDGE:
- /* This is very crude. */
- tmp = RET_POP;
- tmp = cmd_cons(tmp, cmd_cons(TOP, sym_nil));
- gcv_stackbase.gcv_N = STK_USE;
- if((TOP = cmd_catch(tmp)))
- break;
- goto error;
- case OP_THROW:
- tmp = RET_POP;
- if(!ThrowValue)
- ThrowValue = cmd_cons(TOP, tmp);
- /* This isn't really an error :-) */
- goto error;
- case OP_UNWIND_PRO:
- tmp = RET_POP;
- bindstack = cmd_cons(cmd_cons(sym_t, tmp), bindstack);
- break;
- case OP_UN_UNWIND_PRO:
- gcv_stackbase.gcv_N = STK_USE;
- /* there will only be one form (a lisp-code) */
- cmd_eval(VCDR(VCAR(bindstack)));
- bindstack = VCDR(bindstack);
- break;
-
- case OP_FBOUNDP:
- if((TOP = cmd_fboundp(TOP)))
- break;
- goto error;
- case OP_BOUNDP:
- if((TOP = cmd_boundp(TOP)))
- break;
- goto error;
- case OP_SYMBOLP:
- if(SYMBOLP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_GET:
- tmp = RET_POP;
- if((TOP = cmd_get(TOP, tmp)))
- break;
- goto error;
- case OP_PUT:
- tmp = RET_POP;
- tmp2 = RET_POP;
- if((TOP = cmd_put(TOP, tmp2, tmp)))
- break;
- goto error;
-
- case OP_ERROR_PRO:
- /* bit of a kludge, this just calls the special-form, it
- takes an extra argument on top of the stack - the number
- of arguments that it has been given. */
- i = VNUM(RET_POP);
- tmp = sym_nil;
- while(i--)
- tmp = cmd_cons(RET_POP, tmp);
- gcv_stackbase.gcv_N = STK_USE;
- tmp = cmd_error_protect(tmp);
- if(tmp)
- {
- PUSH(tmp);
- break;
- }
- goto error;
- case OP_SIGNAL:
- tmp = RET_POP;
- cmd_signal(TOP, tmp);
- goto error;
-
- case OP_SET_CURRENT_BUFFER:
- tmp = RET_POP;
- if((TOP = cmd_set_current_buffer(TOP, tmp)))
- break;
- goto error;
- case OP_SWAP_BUFFER:
- if(!BUFFERP(TOP))
- goto error;
- TOP = swapvwfilesnd(CurrVW, TOP);
- break;
- case OP_CURRENT_BUFFER:
- if((TOP = cmd_current_buffer(TOP)))
- break;
- goto error;
- case OP_BUFFERP:
- if(BUFFERP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_MARK_P:
- if(MARKP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_WINDOWP:
- if(WINDOWP(TOP))
- TOP = sym_t;
- else
- TOP = sym_nil;
- break;
- case OP_SWAP_WINDOW:
- tmp = TOP;
- if(!WINDOWP(tmp))
- goto error;
- TOP = CurrVW;
- CurrVW = VWIN(tmp);
- break;
-
- case OP_JMP_NIL:
- if(NILP(RET_POP))
- goto do_jmp;
- pc += 2;
- break;
- case OP_JMP_T:
- if(!NILP(RET_POP))
- goto do_jmp;
- pc += 2;
- break;
- case OP_JMP_NIL_ELSE_POP:
- if(NILP(TOP))
- goto do_jmp;
- POP;
- pc += 2;
- break;
- case OP_JMP_T_ELSE_POP:
- if(NILP(TOP))
- {
- POP;
- pc += 2;
- break;
- }
- /* FALL THROUGH */
- case OP_JMP:
- do_jmp:
- pc = VSTR(code) + (((pc[0] & ARG_MASK) << ARG_SHIFT)
- | (pc[1] & ARG_MASK));
- break;
-
- default:
- cmd_signal(sym_error,
- LIST_1(MKSTR("Unknown lisp opcode")));
- error:
- while(CONSP(bindstack))
- {
- if(VCAR(VCAR(bindstack)) == sym_t)
- /* an unwind-pro */
- cmd_eval(VCDR(VCAR(bindstack)));
- else
- unbindsymbols(VCAR(bindstack));
- bindstack = VCDR(bindstack);
- }
- TOP = NULL;
- goto quit;
- }
- }
- #ifdef PARANOID
- if(stackp < (stackbase - 1))
- {
- fprintf(stderr, "jade: stack underflow in lisp-code: aborting...\n");
- abort();
- }
- if(stackp > (stackbase + VNUM(stkreq)))
- {
- fprintf(stderr, "jade: stack overflow in lisp-code: aborting...\n");
- abort();
- }
- #endif
- }
- #ifdef PARANOID
- if(stackp != stackbase)
- fprintf(stderr, "jade: (stackp != stackbase) at end of lisp-code\n");
- #endif
-
- quit:
- /* only use this var to save declaring another */
- bindstack = TOP;
- #ifndef HAVE_ALLOCA
- mystrfree(stackbase);
- #endif
- POPGCN; POPGC; POPGC; POPGC;
- return(bindstack);
- }
-
- void
- lispmach_init(void)
- {
- ADD_SUBR(subr_lisp_code);
- }
-