/* Copyright (c) 1993 Stephen F. White */ #include "cool.h" #include "proto.h" #include "servers.h" #include "netio.h" #include "execute.h" void op_shutdown (void) { if (!is_wizard (frame.this)) { raise (E_PERM); } else { frame.pc++; /* ignore nargs */ server_running = 0; pushn (0); } } void op_dump (void) { frame.pc++; /* ignore nargs */ if (!is_wizard (frame.this)) { raise (E_PERM); } else { cache_sync (); pushn (0); } } void op_writelog (void) { Var arg; arg = pop (); frame.pc++; /* ignore nargs */ if (frame.this.id != SYS_OBJ && !is_wizard (frame.this)) { raise (E_PERM); } else if (arg.type != STR) { raise (E_ARGTYPE); } else { writelog (); fprintf (stderr, "%s\n", arg.v.str->str); pushn (0); } var_free (arg); } void op_boot (void) { frame.pc++; /* ignore nargs */ boot (frame.this.id); pushn (0); } void op_raise (void) { Var e; List *raise_args; frame.pc++; /* ignore nargs */ e = pop (); if (e.type != ERR) { var_free (e); raise (E_ARGTYPE); (void) pop (); } else { ex_state = RAISED; raise_args = make_raise_args (e.v.err); raise_args->el[1].v.str = add_traceback_header (raise_args->el[1].v.str, e.v.err); send_raise (raise_args); } } void op_pass (void) { int nargs; Objid parent; Var args; nargs = frame.m->code[frame.pc++]; parent.server = 0; parent.id = frame.m->code[frame.pc++]; args = pop_args (nargs); send_message_and_block (frame.this, frame.this, string_dup (sym_get (frame.on, frame.m->name)), args.v.list, parent); } void op_hasparent (void) { Var parent; frame.pc++; /* skip nargs */ parent = pop (); if (parent.type != OBJ) { var_free (parent); raise (E_ARGTYPE); } else { pushn (hasparent (this, parent.v.obj)); } } void op_objsize (void) { frame.pc++; /* skip nargs */ pushn (size_object (this)); } void op_spew_method (void) { Var name, ret; Method *m; frame.pc++; /* skip nargs */ name = pop (); if (name.type != STR) { var_free (name); raise (E_ARGTYPE); } else { if ((m = find_method (this, name.v.str->str))) { ret.type = STR; ret.v.str = decode_method (this, m, 2); push (ret); } else { raise (E_METHODNF); } } var_free (name); } void op_list_method (void) { int nargs = frame.m->code[frame.pc++]; Var name, lineno, brackets, indent, ret; Method *m; lineno.type = brackets.type = indent.type = NUM; lineno.v.num = 1; brackets.v.num = 0; indent.v.num = 2; switch (nargs) { case 4: indent = pop (); case 3: brackets = pop (); case 2: lineno = pop (); case 1: name = pop (); } if (name.type != STR || indent.type != NUM || brackets.type != NUM || lineno.type != NUM) { var_free (name); var_free (indent); var_free (brackets); var_free (lineno); raise (E_ARGTYPE); } else { if ((m = find_method (this, name.v.str->str))) { ret.type = STR; ret.v.str = string_new (0); ret.v.str = decompile_method (ret.v.str, this, m, lineno.v.num, brackets.v.num, indent.v.num, 0, 0, 0); push (ret); } else { raise (E_METHODNF); } } var_free (name); } void op_decompile (void) { Var ret; frame.pc++; /* skip nargs */ ret.type = STR; ret.v.str = decompile_object (this); push (ret); } void op_find_method (void) { Var arg, ret; Object *where; frame.pc++; /* skip nargs */ arg = pop (); if (arg.type != STR) { raise (E_ARGTYPE); } else { (void) find_method_recursive (this, arg.v.str->str, &where); ret.type = OBJ; if (where) { ret.v.obj = where->id; } else { ret.v.obj.server = 0; ret.v.obj.id = NOTHING; } push (ret); } /* if */ var_free (arg); } void op_this (void) { Var v; v.type = OBJ; v.v.obj = frame.this; push (v); } void op_player (void) { Var v; v.type = OBJ; v.v.obj = frame.player; push (v); } void op_caller (void) { Var v; v.type = OBJ; v.v.obj = frame.caller; push (v); } void op_args (void) { Var v; v.type = LIST; v.v.list = list_dup (frame.args); push (v); } void op_setplayer (void) { Var newplayer; newplayer = pop (); if (newplayer.type != OBJ) { raise (E_ARGTYPE); } else { frame.player = newplayer.v.obj; } var_free (newplayer); } static void do_programming (Playerid id, int what1, void *what2) { void **progwhat = MALLOC (void *, 2); progwhat[0] = (void *) what1; progwhat[1] = what2; if (start_programming (id, progwhat)) { tell (id, "Couldn't enter programming mode -- can't open temp file."); } else { tell (id, "Entering programming mode. Use \".\" to end input."); } } void op_program (void) { Var obj, method; switch (frame.m->code[frame.pc++]) { case 0: /* program some objects */ do_programming (frame.this.id, -1, 0); pushn (0); break; case 1: /* invalid */ method = pop (); var_free (method); raise (E_RANGE); break; case 2: /* program a single method */ method = pop (); obj = pop (); if (obj.type != OBJ || method.type != STR) { raise (E_ARGTYPE); } else if (!valid (obj.v.obj)) { raise (E_OBJNF); } else if (!can_program (frame.this, obj.v.obj)) { raise (E_PERM); } else if (!valid_ident (method.v.str->str)) { raise (E_METHODNF); /* not quite the right error, but hey */ } else { do_programming (frame.this.id, obj.v.obj.id, (void *) string_dup (method.v.str)); pushn (0); } var_free (obj); var_free (method); break; } } static Playerid progr; static const char *mem_code; static int code_pos, mem_eof; static int mem_getc (void); static void mem_ungetc (int c); static void mem_perror (const char *s); static int mem_getc (void) { if (mem_code[code_pos]) { return mem_code[code_pos++]; } else { mem_eof = 1; return EOF; } } static void mem_ungetc (int c) { if (code_pos > 0 && !mem_eof) { code_pos--; } } static void mem_perror (const char *s) { tell (progr, s); } void op_compile (void) { Var obj, method, pcode; int nargs = frame.m->code[frame.pc++]; Object *o; pcode = pop (); if (pcode.type != STR) { var_free (pcode); while (--nargs) { method = pop (); var_free (method); } raise (E_ARGTYPE); return; } mem_code = pcode.v.str->str; code_pos = 0; mem_eof = 0; progr = frame.this.id; switch (nargs) { case 1: /* program some objects */ pushn (compile (progr, mem_getc, mem_ungetc, mem_perror, 0, 0, 0, 0, 0)); break; case 2: /* invalid */ method = pop (); var_free (method); raise (E_RANGE); break; case 3: /* program a single method */ method = pop (); obj = pop (); if (obj.type != OBJ || method.type != STR) { raise (E_ARGTYPE); } else if (!(o = retrieve (obj.v.obj))) { raise (E_OBJNF); } else if (!can_program (frame.this, obj.v.obj)) { raise (E_PERM); } else if (!valid_ident (method.v.str->str)) { raise (E_METHODNF); /* not quite the right error, but hey */ } else { pushn (compile (progr, mem_getc, mem_ungetc, mem_perror, 1, o, method.v.str, 0, 0)); } var_free (obj); var_free (method); this = retrieve (frame.this); /* in case we recompiled "this" */ break; } var_free (pcode); } void op_verb (void) { Var verb, method, prep; int verbno, methodno, prepno; frame.pc++; /* ignore nargs */ method = pop (); prep = pop (); verb = pop (); if (verb.type != STR || prep.type != STR || method.type != STR) { var_free (verb); var_free (prep); var_free (method); raise (E_ARGTYPE); } else { verbno = sym_add (this, verb.v.str); if (prep.v.str->str[0]) { prepno = sym_add (this, prep.v.str); } else { string_free (prep.v.str); prepno = -1; } methodno = sym_add (this, method.v.str); verb_add (this, verbno, prepno, methodno); cache_put (this, frame.this.id); pushn (0); } } void op_rmverb (void) { Var verb; frame.pc++; verb = pop (); if (verb.type != STR) { raise (E_ARGTYPE); } else { pushn (verb_rm (this, verb.v.str->str)); cache_put (this, frame.this.id); } var_free (verb); } void op_rmmethod (void) { Var method; frame.pc++; method = pop (); if (method.type != STR) { raise (E_ARGTYPE); } else { raise (rm_method (this, method.v.str->str)); cache_put (this, frame.this.id); } var_free (method); } void op_rmvar (void) { Var varname; frame.pc++; varname = pop (); if (varname.type != STR) { raise (E_ARGTYPE); } else { raise (var_rm_global (this, varname.v.str->str)); cache_put (this, frame.this.id); } var_free (varname); } void op_listinsert (void) { int nargs = frame.m->code[frame.pc++]; Var list, value, pos; pos.type = NUM; pos.v.num = -1; if (nargs > 2) { pos = pop (); } value = pop (); list = pop (); if (list.type != LIST || pos.type != NUM) { var_free (pos); var_free (list); var_free (value); raise (E_ARGTYPE); } else if (pos.v.num > list.v.list->len) { raise (E_RANGE); } else { list.v.list = list_insert (list.v.list, value, pos.v.num); push (list); } } void op_listappend (void) { int nargs = frame.m->code[frame.pc++]; Var list, value, pos; pos.type = NUM; pos.v.num = -1; if (nargs > 2) { pos = pop (); } value = pop (); list = pop (); if (list.type != LIST || pos.type != NUM) { var_free (pos); var_free (list); var_free (value); raise (E_ARGTYPE); } else if (pos.v.num > list.v.list->len) { raise (E_RANGE); } else { list.v.list = list_append (list.v.list, value, pos.v.num); push (list); } } void op_listdelete (void) { Var pos; /* position to delete */ Var list; /* list to delete it from */ pos = pop (); list = pop (); frame.pc++; /* skip nargs */ if (list.type != LIST || pos.type != NUM) { var_free (pos); var_free (list); raise (E_ARGTYPE); } else if (pos.v.num < 1 || pos.v.num > list.v.list->len) { var_free (list); raise (E_RANGE); } else { list.v.list = list_delete (list.v.list, pos.v.num); push (list); } } void op_listassign (void) { Var pos; /* position to assign */ Var value; /* value to assign it */ Var list; /* list to modify */ pos = pop (); value = pop (); list = pop (); frame.pc++; /* skip nargs */ if (list.type != LIST || pos.type != NUM) { var_free (pos); var_free (list); var_free (value); raise (E_ARGTYPE); } else if (pos.v.num < 1 || pos.v.num > list.v.list->len) { var_free (list); var_free (value); raise (E_RANGE); } else { list.v.list = list_assign (list.v.list, value, pos.v.num); push (list); } } void op_strsub (void) { int nargs; Var source, what, with, caseflag, ret; caseflag.type = NUM; caseflag.v.num = 0; nargs = frame.m->code[frame.pc++]; if (nargs > 3) { caseflag = pop (); } with = pop (); what = pop (); source = pop (); if (source.type != STR || what.type != STR || with.type != STR) { raise (E_ARGTYPE); } else { ret.type = STR; ret.v.str = strsub (source.v.str->str, what.v.str->str, with.v.str->str, ISTRUE (caseflag)); push (ret); } var_free (source); var_free (what); var_free (with); var_free (caseflag); } void op_psub (void) { Var source, ret; source = pop (); frame.pc++; /* skip nargs */ if (source.type != STR) { raise (E_ARGTYPE); } else { ret.type = STR; ret.v.str = psub (source.v.str->str); push (ret); } var_free (source); } void op_servers (void) { Var servlist; servlist.type = LIST; servlist.v.list = list_dup (server_list); frame.pc++; /* skip nargs */ push (servlist); } void op_ps (void) { Var v; frame.pc++; /* skip nargs */ v.type = LIST; v.v.list = ps (); push (v); } /* op_ps() */ void op_kill (void) { Var pid; int r; frame.pc++; /* skip nargs */ pid = pop (); if (pid.type != NUM) { var_free (pid); raise (E_ARGTYPE); } else { r = cmkill (pid.v.num, frame.caller); switch (r) { case 0: case -1: pushn (r); break; case -2: raise (E_PERM); break; } } /* if */ } /* op_kill() */