/* Copyright 1989, 1990 by James Aspnes, David Applegate, and Bennet Yee */ /* See the file COPYING for distribution information */ #include "db.h" #include "bytecode.h" #include "set.h" #include "globals.h" #define BINOP(token, op) case token: sp--; *sp = sp[0] op sp[1]; break; #define FUNC1(token, f) case token: *sp = f(*sp); break; #define FUNC2(token, f) case token: sp--; *sp = f(sp[0], sp[1]); break; #define FUNC3(token, f) \ case token: sp-=2; *sp = f(sp[0], sp[1], sp[2]); break; #define VALUE(token, v) case token: *++sp = v; break; #define SLOT(token, s) case token: *sp = safe_get(*sp, s); break; #define PROC1(token, f) case token: f(*sp--); break; extern set lookup_setvar(datum, datum); int run_code(byte *c) { datum next; byte *pc; datum stack[STACKSIZE]; datum *sp; int count; set savelist; set_iterator next_iterator; if(c == 0) return -1; next = NOTHING; savelist = empty_set(); for(sp = stack, pc = c, count = 0; *pc != RETURN_OP; pc++, count++) { switch(*pc) { FUNC2(MOVE_OP, move); FUNC2(MATCHES_OP, matches); FUNC2(UNSET_OP, unset); FUNC3(SET_OP, set_variable); FUNC3(SET_STRING_OP, set_string); FUNC2(UNSET_ACTION_OP, unset_action); FUNC3(SET_ACTION_OP, set_action); FUNC2(LOOKUP_OP, lookup); FUNC2(LOOKUP_ACTION_OP, lookup_action); FUNC1(NOT_OP, !); VALUE(TRUE_OP, 1); VALUE(FALSE_OP, 0); VALUE(ME_OP, me); VALUE(YOU_OP, you); VALUE(NEXT_OP, next); VALUE(TEXT_OP, text); VALUE(MTEXT_OP, mtext); SLOT(LOC_OP, location); VALUE(TELL_OP, do_tell()); VALUE(CREATE_OP, create()); FUNC1(DESTROY_OP, destroy); PROC1(TELL_INIT_OP, tell_init); PROC1(ADD_BUF_OP, add_buffer); PROC1(ADD_NUM_BUF_OP, add_num_buffer); PROC1(ADD_TIME_BUF_OP, add_time_buffer); FUNC1(SYSCALL_OP, do_syscall); FUNC1(NEGATE_OP, -); FUNC2(CLEAR_SET_OP, clear_set_var); FUNC3(ADD_SET_OP, add_to); FUNC3(DEL_SET_OP, take_from); FUNC2(COUNT_OP, count_set_var); FUNC3(CONTAINS_OP, contains); VALUE(TIME_OP, time(0)); FUNC1(DELAY_OP, delay); FUNC2(CONCAT_OP, concat); FUNC1(NUM_TO_STRING_OP, num_to_string); /* binary numeric operations */ BINOP(PLUS_OP, +); BINOP(MINUS_OP, -); BINOP(TIMES_OP, *); BINOP(DIV_OP, /); BINOP(MOD_OP, %); BINOP(LT_OP, <); BINOP(GT_OP, >); BINOP(LEQ_OP, <=); BINOP(GEQ_OP, >=); BINOP(EQ_OP, ==); BINOP(NEQ_OP, !=); case EXIT_OP: goto exit; case JUMP_OP: pc += ARG_VALUE(pc+1); break; case JUMP_BACK_OP: pc -= ARG_VALUE(pc+1); break; case JUMP_IF_OP: if(*sp-- != NOTHING) { pc += ARG_VALUE(pc+1); } else { pc += ARG_WIDTH; } break; case DO_SET_INIT_OP: free_set(savelist); sp -= 2; savelist = copy_set(lookup_setvar(sp[1], sp[2])); next = set_first(savelist, &next_iterator); break; case MATCHING_DO_SET_INIT_OP: free_set(savelist); sp -= 3; savelist = lookup_setvar(sp[1], sp[2]); set_build_name_list(savelist); /* build before copy */ savelist = copy_set(savelist); next = set_first_match(savelist, &next_iterator, sp[3]); break; case DO_NEXT_OP: next = set_next(savelist, &next_iterator); break; case MATCHING_DO_NEXT_OP: next = set_next_match(savelist, &next_iterator); break; case LITERAL_OP: *++sp = ARG_VALUE(pc+1); pc += ARG_WIDTH; break; case DROP_OP: sp--; break; case DUP_OP: sp[1] = sp[0]; sp++; break; case RANDOM_OP: *++sp = RAND(); break; default: abort(); } } exit: return count; } int run_action(datum action) { const char *s; datum *code; char buf[MAX_STRLEN]; if((code = get_compiled_string(action)) == 0) { /* try compiling it */ if((s = string(action)) == 0) { return -1; /* we lose completely */ } else { code = compile(s); if(code == 0) { sprintf(buf, LOSE_CODE, compile_error); code = compile(buf); } set_compiled_string(action, code); } } return run_code(code); }