/* 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" #include "externs.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); }