/* Copyright (c) 1993 Stephen F. White */ #include <stdio.h> #ifdef SYSV #include <string.h> #else #include <strings.h> #endif #include <ctype.h> #include <sys/time.h> #include "config.h" #include "cool.h" #include "proto.h" #include "sys_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, GENPTR what2) { GENPTR *progwhat = MALLOC(GENPTR, 2); progwhat[0] = (GENPTR) 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, (GENPTR) 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() */