Ejemplo n.º 1
0
/**
 * Displays a MUF Backtrace message.
 *
 * This is used when a MUF program is aborted, if someone who has 'controls'
 * permissions was running it, or if you type 'where' in the debugger.
 * Shows a fairly straight forward backtrace, going 'count' deep.  If
 * 'count' is 0, it will display up to STACK_SIZE depth.
 *
 * @param player the player getting the backtrace
 * @param program the program being backtraced
 * @param count the depth of the trace, or 0 for STACK_SIZE
 * @param fr the frame pointer
 */
void
muf_backtrace(dbref player, dbref program, int count, struct frame *fr)
{
    char buf2[BUFFER_LEN];
    char buf3[BUFFER_LEN];
    char *ptr;
    dbref ref;
    int i, j, cnt, flag;
    struct inst *pinst, *lastinst;
    int lev;

    notify_nolisten(player, "\033[1;33;40mSystem stack backtrace:\033[0m", 1);
    i = count;

    if (!i)
        i = STACK_SIZE;

    ref = program;
    pinst = NULL;
    j = fr->system.top + 1;

    /*
     * i is our depth; iterate until we've run out of depth or we have
     * broken out of the loop
     */
    while (j > 1 && i-- > 0) {
        cnt = 0;

        do {
            lastinst = pinst;

            if (--j == fr->system.top) {
                pinst = fr->pc;
            } else {
                ref = fr->system.st[j].progref;
                pinst = fr->system.st[j].offset;
            }

            ptr = unparse_sysreturn(&ref, pinst);
            cnt++;
        } while (pinst == lastinst && j > 1);

        if (cnt > 1) {
            notifyf_nolisten(player, "     [repeats %d times]", cnt);
        }

        lev = fr->system.top - j;

        if (ptr) {
            int snplen;
            char *bufend = buf2;
            struct inst *fntop = fr->pc;
            struct inst *varinst;

            while (fntop->type != PROG_FUNCTION)
                fntop--;

            snplen = snprintf(buf2, sizeof(buf2), "%.512s\033[1m(\033[0m", ptr);

            if (snplen == -1) {
                buf2[sizeof(buf2) - 1] = '\0';
                snplen = sizeof(buf2) - 1;
            }

            bufend += snplen;

            for (int k = 0; k < fntop->data.mufproc->args; k++) {
                const char *nam = scopedvar_getname(fr, lev, k);
                char *val;

                if (!nam) {
                    break;
                }

                varinst = scopedvar_get(fr, lev, k);
                val = insttotext(fr, lev, varinst, buf3, sizeof(buf3), 30, program, 1);

                if (k) {
                    bufend += snprintf(bufend, buf2 - bufend - 18, "\033[1m, %s=\033[0m%s", nam, val);
                } else {
                    bufend += snprintf(bufend, buf2 - bufend - 18, "\033[1m%s=\033[0m%s", nam, val);
                }
            }

            ptr = buf2;
        }

        if (pinst != lastinst) {
            notifyf_nolisten(player, "\033[1;33;40m%3d)\033[0m \033[1m%s(#%d)\033[0m %s:", lev,
                             NAME(ref), ref, ptr);
            flag = ((FLAGS(player) & INTERNAL) ? 1 : 0);
            FLAGS(player) &= ~INTERNAL;
            list_proglines(player, ref, fr, pinst->line, 0);

            if (flag) {
                FLAGS(player) |= INTERNAL;
            }
        }
    }

    notify_nolisten(player, "\033[1;33;40m*done*\033[0m", 1);
}
Ejemplo n.º 2
0
static void
push_arg(dbref player, struct frame *fr, const char *arg)
{
    int num = 0, lflag = 0, sflag = 0;
    double inum = 0.0;


    if (fr->argument.top >= STACK_SIZE) {
        anotify_nolisten(player, CFAIL "That would overflow the stack.", 1);
        return;
    }
    if (number(arg)) {
        /* push a number */
        num = atoi(arg);
        push(fr->argument.st, &fr->argument.top, PROG_INTEGER, MIPSCAST & num);
        anotify_nolisten(player, CSUCC "Integer pushed.", 1);
    } else if (ifloat(arg)) {
        /* push a float */
        inum = atof(arg);
        push(fr->argument.st, &fr->argument.top, PROG_FLOAT, MIPSCAST & inum);
        notify_nolisten(player, "Float pushed.", 1);
    } else if (*arg == NUMBER_TOKEN) {
        /* push a dbref */
        if (!number(arg + 1)) {
            anotify_nolisten(player, CINFO "I don't understand that dbref.", 1);
            return;
        }
        num = atoi(arg + 1);
        push(fr->argument.st, &fr->argument.top, PROG_OBJECT, MIPSCAST & num);
        anotify_nolisten(player, CSUCC "Dbref pushed.", 1);
    } else if (*arg == '"') {
        /* push a string */
        char buf[BUFFER_LEN];
        char *ptr;
        const char *ptr2;

        for (ptr = buf, ptr2 = arg + 1; *ptr2; ptr2++) {
            if (*ptr2 == '\\') {
                if (!*(++ptr2))
                    break;
                *ptr++ = *ptr2;
            } else if (*ptr2 == '"') {
                break;
            } else {
                *ptr++ = *ptr2;
            }
        }
        *ptr = '\0';
        push(fr->argument.st, &fr->argument.top, PROG_STRING,
             MIPSCAST alloc_prog_string(buf));
        anotify_nolisten(player, CSUCC "String pushed.", 1);
    } else {
        int varnum = scopedvar_getnum(fr, 0, arg);

        if (varnum != -1) {
            sflag = 1;
        } else {
            if (*arg == 'S' || *arg == 's') {
                ++arg;
                if (*arg == 'V' || *arg == 'v') {
                    arg++;
                }
                sflag = 1;
                varnum = scopedvar_getnum(fr, 0, arg);
            } else if (*arg == 'L' || *arg == 'l') {
                ++arg;
                if (*arg == 'V' || *arg == 'v') {
                    ++arg;
                }
                lflag = 1;
            } else if (*arg == 'V' || *arg == 'v') {
                ++arg;
            }
        }
        if (varnum > -1) {
            num = varnum;
        } else if (number(arg)) {
            num = atoi(arg);
        } else {
            anotify_nolisten(player,
                             CINFO "I don't understand what you want to push.",
                             1);
            return;
        }
        if (lflag) {
            push(fr->argument.st, &fr->argument.top, PROG_LVAR, MIPSCAST & num);
            anotify_nolisten(player, CSUCC "Local variable pushed.", 1);
        } else if (sflag) {
            push(fr->argument.st, &fr->argument.top, PROG_SVAR, MIPSCAST & num);
            anotify_nolisten(player, CSUCC "Scoped variable pushed.", 1);
        } else {
            push(fr->argument.st, &fr->argument.top, PROG_VAR, MIPSCAST & num);
            anotify_nolisten(player, CSUCC "Global variable pushed.", 1);
        }
    }
}
Ejemplo n.º 3
0
int
muf_debugger(int descr, dbref player, dbref program, const char *text,
             struct frame *fr)
{
    char cmd[BUFFER_LEN];
    char buf[BUFFER_LEN];
    char buf2[BUFFER_LEN];
    char *ptr, *ptr2, *arg;
    struct inst *pinst;
    dbref ref;
    int i, j, cnt;

    while (isspace(*text))
        text++;
    strcpy(cmd, text);
    ptr = cmd + strlen(cmd);
    if (ptr > cmd)
        ptr--;
    while (ptr >= cmd && isspace(*ptr))
        *ptr-- = '\0';
    for (arg = cmd; *arg && !isspace(*arg); arg++) ;
    if (*arg)
        *arg++ = '\0';
    if (!*cmd && fr->brkpt.lastcmd) {
        strcpy(cmd, fr->brkpt.lastcmd);
    } else {
        if (fr->brkpt.lastcmd)
            free(fr->brkpt.lastcmd);
        if (*cmd)
            fr->brkpt.lastcmd = string_dup(cmd);
    }
    /* delete triggering breakpoint, if it's only temp. */
    j = fr->brkpt.breaknum;
    if (j >= 0 && fr->brkpt.temp[j]) {
        for (j++; j < fr->brkpt.count; j++) {
            fr->brkpt.temp[j - 1] = fr->brkpt.temp[j];
            fr->brkpt.level[j - 1] = fr->brkpt.level[j];
            fr->brkpt.line[j - 1] = fr->brkpt.line[j];
            fr->brkpt.linecount[j - 1] = fr->brkpt.linecount[j];
            fr->brkpt.pc[j - 1] = fr->brkpt.pc[j];
            fr->brkpt.pccount[j - 1] = fr->brkpt.pccount[j];
            fr->brkpt.prog[j - 1] = fr->brkpt.prog[j];
        }
        fr->brkpt.count--;
    }
    fr->brkpt.breaknum = -1;

    if (!string_compare(cmd, "cont")) {
    } else if (!string_compare(cmd, "finish")) {
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player, CFAIL
                             "Cannot finish because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = fr->system.top - 1;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = program;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "stepi")) {
        i = atoi(arg);
        if (!i)
            i = 1;
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot stepi because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = -1;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = i;
        fr->brkpt.prog[j] = NOTHING;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "step")) {
        i = atoi(arg);
        if (!i)
            i = 1;
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot step because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = -1;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = i;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = NOTHING;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "nexti")) {
        i = atoi(arg);
        if (!i)
            i = 1;
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot nexti because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = fr->system.top;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = i;
        fr->brkpt.prog[j] = program;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "next")) {
        i = atoi(arg);
        if (!i)
            i = 1;
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot next because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = fr->system.top;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = i;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = program;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "exec")) {
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot finish because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        if (!(pinst = funcname_to_pc(program, arg))) {
            anotify_nolisten(player,
                             CINFO "I don't know a function by that name.", 1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        if (fr->system.top >= STACK_SIZE) {
            anotify_nolisten(player,
                             CFAIL
                             "That would exceed the system stack size for this program.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        fr->system.st[fr->system.top].progref = program;
        fr->system.st[fr->system.top++].offset = fr->pc;
        fr->pc = pinst;
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = fr->system.top - 1;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = program;
        fr->brkpt.bypass = 1;
        return 0;
    } else if (!string_compare(cmd, "prim")) {
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player,
                             CFAIL
                             "Cannot finish because there are too many breakpoints set.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        if (!(i = primitive(arg))) {
            anotify_nolisten(player, CINFO "I don't recognize that primitive.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }
        if (fr->system.top >= STACK_SIZE) {
            anotify_nolisten(player,
                             CFAIL
                             "That would exceed the system stack size for this program.",
                             1);
            add_muf_read_event(descr, player, program, fr);
            return 0;
        }

        primset[0].type = PROG_FUNCTION;
        primset[0].line = 0;
        primset[0].data.mufproc = &temp_muf_proc_data;
        primset[0].data.mufproc->vars = 0;

        primset[0].data.mufproc->args = 0;
        primset[0].data.mufproc->varnames = NULL;
        primset[1].type = PROG_PRIMITIVE;
        primset[1].line = 0;
        primset[1].data.number = get_primitive(arg);
        primset[2].type = PROG_PRIMITIVE;
        primset[2].line = 0;
        primset[2].data.number = IN_RET;
        /* primset[3].data.number = primitive("EXIT"); */

        fr->system.st[fr->system.top].progref = program;
        fr->system.st[fr->system.top++].offset = fr->pc;
        fr->pc = &primset[1];
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 1;
        fr->brkpt.level[j] = -1;
        fr->brkpt.line[j] = -1;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = &primset[2];
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = program;
        fr->brkpt.bypass = 1;
        fr->brkpt.dosyspop = 1;
        return 0;
    } else if (!string_compare(cmd, "break")) {
        add_muf_read_event(descr, player, program, fr);
        if (fr->brkpt.count >= MAX_BREAKS) {
            anotify_nolisten(player, CFAIL "Too many breakpoints set.", 1);
            return 0;
        }
        if (number(arg)) {
            i = atoi(arg);
        } else {
            if (!(pinst = funcname_to_pc(program, arg))) {
                anotify_nolisten(player,
                                 CINFO "I don't know a function by that name.",
                                 1);
                return 0;
            } else {
                i = pinst->line;
            }
        }
        if (!i)
            i = fr->pc->line;
        j = fr->brkpt.count++;
        fr->brkpt.temp[j] = 0;
        fr->brkpt.level[j] = -1;
        fr->brkpt.line[j] = i;
        fr->brkpt.linecount[j] = -2;
        fr->brkpt.pc[j] = NULL;
        fr->brkpt.pccount[j] = -2;
        fr->brkpt.prog[j] = program;
        anotify_nolisten(player, CSUCC "Breakpoint set.", 1);
        return 0;
    } else if (!string_compare(cmd, "delete")) {
        add_muf_read_event(descr, player, program, fr);
        i = atoi(arg);
        if (!i) {
            anotify_nolisten(player,
                             CINFO "Which breakpoint did you want to delete?",
                             1);
            return 0;
        }
        if (i < 1 || i > fr->brkpt.count) {
            anotify_nolisten(player, CFAIL "No such breakpoint.", 1);
            return 0;
        }
        j = i - 1;
        for (j++; j < fr->brkpt.count; j++) {
            fr->brkpt.temp[j - 1] = fr->brkpt.temp[j];
            fr->brkpt.level[j - 1] = fr->brkpt.level[j];
            fr->brkpt.line[j - 1] = fr->brkpt.line[j];
            fr->brkpt.linecount[j - 1] = fr->brkpt.linecount[j];
            fr->brkpt.pc[j - 1] = fr->brkpt.pc[j];
            fr->brkpt.pccount[j - 1] = fr->brkpt.pccount[j];
            fr->brkpt.prog[j - 1] = fr->brkpt.prog[j];
        }
        fr->brkpt.count--;
        anotify_nolisten(player, CSUCC "Breakpoint deleted.", 1);
        return 0;
    } else if (!string_compare(cmd, "breaks")) {
        anotify_nolisten(player, CINFO "Breakpoints:", 1);
        for (i = 0; i < fr->brkpt.count; i++) {
            ptr = unparse_breakpoint(fr, i);
            notify_nolisten(player, ptr, 1);
        }
        anotify_nolisten(player, CINFO "Done.", 1);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "where")) {
        i = atoi(arg);
        muf_backtrace(player, program, i, fr);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "stack")) {
        anotify_nolisten(player, CINFO "*Argument stack top*", 1);
        i = atoi(arg);
        if (!i)
            i = STACK_SIZE;
        ptr = "";
        ref = program;
        for (j = fr->argument.top; j > 0 && i-- > 0;) {
            cnt = 0;
            do {
                strcpy(buf, ptr);
                ptr =
                    insttotext(NULL, 0, &fr->argument.st[--j], buf2,
                               sizeof(buf2), 4000, program);
                cnt++;
            } while (!string_compare(ptr, buf) && j > 0);
            if (cnt > 1)
                notify_fmt(player, "     [repeats %d times]", cnt);
            if (string_compare(ptr, buf))
                notify_fmt(player, "%3d) %s", j + 1, ptr);
        }
        anotify_nolisten(player, CINFO "Done.", 1);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "list") || !string_compare(cmd, "listi")) {
        int startline, endline;

        startline = endline = 0;
        add_muf_read_event(descr, player, program, fr);
        if ((ptr2 = (char *) index(arg, ','))) {
            *ptr2++ = '\0';
        } else {
            ptr2 = "";
        }
        if (!*arg) {
            if (fr->brkpt.lastlisted) {
                startline = fr->brkpt.lastlisted + 1;
            } else {
                startline = fr->pc->line;
            }
            endline = startline + 15;
        } else {
            if (!number(arg)) {
                if (!(pinst = funcname_to_pc(program, arg))) {
                    anotify_nolisten(player,
                                     CINFO
                                     "I don't know a function by that name. (starting arg, 1)",
                                     1);
                    return 0;
                } else {
                    startline = pinst->line;
                    endline = startline + 15;
                }
            } else {
                if (*ptr2) {
                    endline = startline = atoi(arg);
                } else {
                    startline = atoi(arg) - 7;
                    endline = startline + 15;
                }
            }
        }
        if (*ptr2) {
            if (!number(ptr2)) {
                if (!(pinst = funcname_to_pc(program, ptr2))) {
                    anotify_nolisten(player,
                                     CINFO
                                     "I don't know a function by that name. (ending arg, 1)",
                                     1);
                    return 0;
                } else {
                    endline = pinst->line;
                }
            } else {
                endline = atoi(ptr2);
            }
        }
        i = (DBFETCH(program)->sp.program.code +
             DBFETCH(program)->sp.program.siz - 1)->line;
        if (startline > i) {
            anotify_nolisten(player,
                             CFAIL "Starting line is beyond end of program.",
                             1);
            return 0;
        }
        if (startline < 1)
            startline = 1;
        if (endline > i)
            endline = i;
        if (endline < startline)
            endline = startline;
        anotify_nolisten(player, CINFO "Listing:", 1);
        if (!string_compare(cmd, "listi")) {
            for (i = startline; i <= endline; i++) {
                pinst = linenum_to_pc(program, i);
                if (pinst) {
                    sprintf(buf, "line %d: %s", i, (i == fr->pc->line) ?
                            show_line_prims(fr, program, fr->pc, STACK_SIZE,
                                            1) : show_line_prims(fr, program,
                                                                 pinst,
                                                                 STACK_SIZE,
                                                                 0));
                    notify_nolisten(player, buf, 1);
                }
            }
        } else {
            list_proglines(player, program, fr, startline, endline);
        }
        fr->brkpt.lastlisted = endline;
        anotify_nolisten(player, CINFO "Done.", 1);
        return 0;
    } else if (!string_compare(cmd, "quit")) {
        anotify_nolisten(player, CINFO "Halting execution.", 1);
        return 1;
    } else if (!string_compare(cmd, "trace")) {
        add_muf_read_event(descr, player, program, fr);
        if (!string_compare(arg, "on")) {
            fr->brkpt.showstack = 1;
            anotify_nolisten(player, CSUCC "Trace turned on.", 1);
        } else if (!string_compare(arg, "off")) {
            fr->brkpt.showstack = 0;
            anotify_nolisten(player, CSUCC "Trace turned off.", 1);
        } else {
            sprintf(buf, CINFO "Trace is currently %s.",
                    fr->brkpt.showstack ? "on" : "off");
            anotify_nolisten(player, buf, 1);
        }
        return 0;
    } else if (!string_compare(cmd, "words")) {
        list_program_functions(player, program, arg);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "print")) {
        debug_printvar(player, program, fr, arg);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "push")) {
        push_arg(player, fr, arg);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else if (!string_compare(cmd, "pop")) {
        add_muf_read_event(descr, player, program, fr);
        if (fr->argument.top < 1) {
            notify_nolisten(player, "Nothing to pop.", 1);
            return 0;
        }
        fr->argument.top--;
        CLEAR(fr->argument.st + fr->argument.top);
        notify_nolisten(player, "Stack item popped.", 1);
        return 0;
    } else if (!string_compare(cmd, "help")) {
        notify_nolisten(player,
                        "cont            continues execution until a breakpoint is hit.",
                        1);
        notify_nolisten(player,
                        "finish          completes execution of current function.",
                        1);
        notify_nolisten(player,
                        "step [NUM]      executes one (or NUM, 1) lines of muf.",
                        1);
        notify_nolisten(player,
                        "stepi [NUM]     executes one (or NUM, 1) muf instructions.",
                        1);
        notify_nolisten(player,
                        "next [NUM]      like step, except skips CALL and EXECUTE.",
                        1);
        notify_nolisten(player,
                        "nexti [NUM]     like stepi, except skips CALL and EXECUTE.",
                        1);
        notify_nolisten(player,
                        "break LINE#     sets breakpoint at given LINE number.",
                        1);
        notify_nolisten(player,
                        "break FUNCNAME  sets breakpoint at start of given function.",
                        1);
        notify_nolisten(player,
                        "breaks          lists all currently set breakpoints.",
                        1);
        notify_nolisten(player,
                        "delete NUM      deletes breakpoint by NUM, as listed by 'breaks'",
                        1);
        notify_nolisten(player,
                        "where [LEVS]    displays function call backtrace of up to num levels deep.",
                        1);
        notify_nolisten(player,
                        "stack [NUM]     shows the top num items on the stack.",
                        1);
        notify_nolisten(player,
                        "print v#        displays the value of given global variable #.",
                        1);
        notify_nolisten(player,
                        "print lv#       displays the value of given local variable #.",
                        1);
        notify_nolisten(player,
                        "trace [on|off]  turns on/off debug stack tracing.", 1);
        notify_nolisten(player,
                        "list [L1,[L2]]  lists source code of given line range.",
                        1);
        notify_nolisten(player,
                        "list FUNCNAME   lists source code of given function.",
                        1);
        notify_nolisten(player,
                        "listi [L1,[L2]] lists instructions in given line range.",
                        1);
        notify_nolisten(player,
                        "listi FUNCNAME  lists instructions in given function.",
                        1);
        notify_nolisten(player,
                        "words           lists all function word names in program.",
                        1);
        notify_nolisten(player,
                        "words PATTERN   lists all function word names that match PATTERN.",
                        1);
        notify_nolisten(player,
                        "exec FUNCNAME   calls given function with the current stack data.",
                        1);
        notify_nolisten(player,
                        "prim PRIMITIVE  executes given primitive with current stack data.",
                        1);
        notify_nolisten(player,
                        "push DATA       pushes an int, dbref, var, or string onto the stack.",
                        1);
        notify_nolisten(player,
                        "pop             pops top data item off the stack.", 1);
        notify_nolisten(player, "help            displays this help screen.",
                        1);
        notify_nolisten(player, "quit            stop execution here.", 1);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    } else {
        anotify_nolisten(player,
                         CINFO
                         "I don't understand that debugger command. Type 'help' for help.",
                         1);
        add_muf_read_event(descr, player, program, fr);
        return 0;
    }
    return 0;
}
Ejemplo n.º 4
0
void
muf_backtrace(dbref player, dbref program, int count, struct frame *fr)
{
    char buf[BUFFER_LEN];
    char buf2[BUFFER_LEN];
    char buf3[BUFFER_LEN];
    char *ptr;
    dbref ref;
    int i, j, cnt, flag;
    struct inst *pinst, *lastinst;
    int lev;

    anotify_nolisten(player, CINFO "System stack backtrace:", 1);
    i = count;
    if (!i)
        i = STACK_SIZE;
    ref = program;
    pinst = NULL;
    j = fr->system.top + 1;
    while (j > 1 && i-- > 0) {
        cnt = 0;
        do {
            lastinst = pinst;
            if (--j == fr->system.top) {
                pinst = fr->pc + 1;
            } else {
                ref = fr->system.st[j].progref;
                pinst = fr->system.st[j].offset;
            }
            ptr = unparse_sysreturn(&ref, pinst);
            cnt++;
        } while (pinst == lastinst && j > 1);
        if (cnt > 1) {
            sprintf(buf, "     [repeats %d times]", cnt);
            notify_nolisten(player, buf, 1);
        }
        lev = fr->system.top - j;
        if (ptr) {
            int k;
            char *bufend = buf2;
            struct inst *fntop = fr->pc;
            struct inst *varinst;

            while (fntop->type != PROG_FUNCTION)
                --fntop;

            bufend += sprintf(buf2, "%.512s" SYSWHITE "(" SYSNORMAL, ptr);
            for (k = 0; k < fntop->data.mufproc->args; ++k) {
                const char *nam = scopedvar_getname(fr, lev, k);
                char *val;
                const char *fmt;

                if (!nam) {
                    break;
                }
                varinst = scopedvar_get(fr, lev, k);
                val = insttotext(fr, lev, varinst, buf3, sizeof(buf3), 30,
                                 program);

                if (k) {
                    fmt = SYSWHITE ", %s=" SYSNORMAL "%s";
                } else {
                    fmt = SYSWHITE "%s=" SYSNORMAL "%s";
                }
                bufend += snprintf(bufend, buf2 - bufend - 18, fmt, nam, val);
            }
            bufend += snprintf(bufend, buf2 - bufend - 1, SYSWHITE ")" SYSNORMAL,
                               ptr);
            ptr = buf2;
        }


        if (pinst != lastinst) {
            sprintf(buf, "%3d) %s(#%d) %s:", j, NAME(ref), ref, ptr);
            notify_nolisten(player, buf, 1);
            flag = ((FLAGS(player) & INTERNAL) ? 1 : 0);
            FLAGS(player) &= ~INTERNAL;
            list_proglines(player, ref, fr, (pinst - 1)->line, 0);
            if (flag) {
                FLAGS(player) |= INTERNAL;
            }
        }
    }
    anotify_nolisten(player, CINFO "Done.", 1);
}
Ejemplo n.º 5
0
static void
debug_printvar(dbref player, dbref program, struct frame *fr, const char *arg)
{
    int i;
    int lflag = 0;
    int sflag = 0;
    int varnum = -1;
    char buf[BUFFER_LEN];

    if (!arg || !*arg) {
        anotify_nolisten(player,
                         CINFO "I don't know which variable you mean.", 1);
        return;
    }
    varnum = scopedvar_getnum(fr, 0, arg);
    if (varnum != -1) {
        sflag = 1;
    } else if (*arg == 'L' || *arg == 'l') {
        arg++;
        if (*arg == 'V' || *arg == 'v') {
            arg++;
        }
        lflag = 1;
        varnum = scopedvar_getnum(fr, 0, arg);
    } else if (*arg == 'S' || *arg == 's') {
        arg++;
        if (*arg == 'V' || *arg == 'v') {
            arg++;
        }
        sflag = 1;
    } else if (*arg == 'V' || *arg == 'v') {
        arg++;
    }
    if (varnum > -1) {
        i = varnum;
    } else if (number(arg)) {
        i = atoi(arg);
    } else {
        notify_nolisten(player, "I don't know which variable you mean.", 1);
        return;
    }

    if (i >= MAX_VAR || i < 0) {
        anotify_nolisten(player, CINFO "Variable number out of range.", 1);
        return;
    }
    if (sflag) {
        struct inst *tmp = scopedvar_get(fr, 0, i);

        if (!tmp) {
            notify_nolisten(player, "Scoped variable number out of range.", 1);
            return;
        }
        notify_nolisten(player,
                        insttotext(fr, 0, tmp, buf, sizeof(buf), 4000, -1), 1);
    } else if (lflag) {
        struct localvars *lvars = localvars_get(fr, program);

        notify_nolisten(player, insttotext(fr, 0, &(lvars->lvars[i]),
                                           buf, sizeof(buf), 4000, -1), 1);
    } else {
        notify_nolisten(player, insttotext(fr, 0, &(fr->variables[i]),
                                           buf, sizeof(buf), 4000, -1), 1);
    }
}
Ejemplo n.º 6
0
void
list_events(dbref player)
{
	char buf[BUFFER_LEN];
	char pidstr[128];
	char duestr[128];
	char runstr[128];
	char inststr[128];
	char cpustr[128];
	char progstr[128];
	char prognamestr[128];
	int count = 0;
	timequeue ptr = tqhead;
	time_t rtime = time((time_t *) NULL);
	time_t etime;
	double pcnt;
	const char* strfmt = "%10s %4s %4s %6s %4s %7s %-10.10s %-12s %.512s";

	(void)snprintf(buf, sizeof(buf), strfmt, "PID", "Next", "Run", "KInst", "%CPU", "Prog#", "ProgName", "Player", "");
	notify_nolisten(player, buf, 1);

	while (ptr) {
		/* pid */
		snprintf(pidstr, sizeof(pidstr), "%d", ptr->eventnum);
		/* next due */
		strcpyn(duestr, sizeof(duestr), ((ptr->when - rtime) > 0) ?
				time_format_2((long) (ptr->when - rtime)) : "Due");
		/* Run length */
		strcpyn(runstr, sizeof(runstr), ptr->fr ?
				time_format_2((long) (rtime - ptr->fr->started)): "0s");
		/* Thousand Instructions executed */
		snprintf(inststr, sizeof(inststr), "%d", ptr->fr? (ptr->fr->instcnt / 1000) : 0);

		/* If it's actually a program, instead of MPI... */
		/* we need to figure out how much CPU it's used */
		if (ptr->fr) {
			etime = rtime - ptr->fr->started;
			if (etime > 0) {
				pcnt = ptr->fr->totaltime.tv_sec;
				pcnt += ptr->fr->totaltime.tv_usec / 1000000;
				pcnt = pcnt * 100 / etime;
				if (pcnt > 99.9) {
					pcnt = 99.9;
				}
			} else {
				pcnt = 0.0;
			}
		} else {
			pcnt = 0.0;
		}
		snprintf(cpustr, sizeof(cpustr), "%4.1f", pcnt);
		/* Get the dbref! */
		if (ptr->fr) {
			/* if it's a program... */
			snprintf(progstr, sizeof(progstr), "#%d", ptr->fr->caller.st[1]);
			snprintf(prognamestr, sizeof(prognamestr), "%s", NAME(ptr->fr->caller.st[1]));
		} else if (ptr->typ == TQ_MPI_TYP) {
			/* if it's MPI... */
			snprintf(progstr, sizeof(progstr), "#%d", ptr->trig);
			snprintf(prognamestr, sizeof(prognamestr), "%s", "");
		} else {
			/* if it's anything else... */
			snprintf(progstr, sizeof(progstr), "#%d", ptr->called_prog);
			snprintf(prognamestr, sizeof(prognamestr), "%s", NAME(ptr->called_prog));
		}

		/* Now, the next due is based on if it's waiting on a READ */
		if (ptr->typ == TQ_MUF_TYP && ptr->subtyp == TQ_MUF_READ) {
			strcpyn(duestr, sizeof(duestr), "--");
		} else if (ptr->typ == TQ_MUF_TYP && ptr->subtyp == TQ_MUF_TIMER) {
			/* if it's a timer event, it gives the eventnum */
			snprintf(pidstr, sizeof(pidstr), "(%d)", ptr->eventnum);
		} else if (ptr->typ == TQ_MPI_TYP) {
			/* and if it's MPI, undo most of the stuff we did
			 * before, and set it up for mostly MPI stuff */
			strcpyn(runstr, sizeof(runstr), "--");
			strcpyn(inststr, sizeof(inststr), "MPI");
			strcpyn(cpustr, sizeof(cpustr), "--");
		}
		(void) snprintf(buf, sizeof(buf), strfmt, pidstr, duestr, runstr,
						inststr, cpustr, progstr, prognamestr, NAME(ptr->uid), 
						(ptr->called_data? ptr->called_data : ""));
		if (Wizard(OWNER(player)) || ptr->uid == player) {
			notify_nolisten(player, buf, 1);
		} else if (ptr->called_prog != NOTHING &&
					 OWNER(ptr->called_prog) == OWNER(player)) {
			notify_nolisten(player, buf, 1);
		}
		ptr = ptr->next;
		count++;
	}
	count += muf_event_list(player, strfmt);
	snprintf(buf, sizeof(buf), "%d events.", count);
	notify_nolisten(player, buf, 1);
}
Ejemplo n.º 7
0
void
handle_read_event(int descr, dbref player, const char *command)
{
	struct frame *fr;
	timequeue ptr, lastevent;
	int flag, typ, nothing_flag;
	int oldflags;
	dbref prog;

	nothing_flag = 0;
	if (command == NULL) {
		nothing_flag = 1;
	}
	oldflags = FLAGS(player);
	FLAGS(player) &= ~(INTERACTIVE | READMODE);

	ptr = tqhead;
	lastevent = NULL;
	while (ptr) {
		if (ptr->typ == TQ_MUF_TYP && (ptr->subtyp == TQ_MUF_READ ||
									   ptr->subtyp == TQ_MUF_TREAD) && ptr->uid == player) {
			break;
		}
		lastevent = ptr;
		ptr = ptr->next;
	}

	/*
	 * When execution gets to here, either ptr will point to the
	 * READ event for the player, or else ptr will be NULL.
	 */

	if (ptr) {
		/* remember our program, and our execution frame. */
		fr = ptr->fr;
		if (fr == NULL) {
			log_status("WARNING: handle_read_event(): NULL frame !  Ignored.");
			return;
		}
		if (!fr->brkpt.debugging || fr->brkpt.isread) {
			if (!fr->wantsblanks && command && !*command) {
				FLAGS(player) = oldflags;
				return;
			}
		}
		typ = ptr->subtyp;
		prog = ptr->called_prog;
		if (command) {
			/* remove the READ timequeue node from the timequeue */
			process_count--;
			if (lastevent) {
				lastevent->next = ptr->next;
			} else {
				tqhead = ptr->next;
			}
		}
		/* remember next timequeue node, to check for more READs later */
		lastevent = ptr;
		ptr = ptr->next;

		/* Make SURE not to let the program frame get freed.  We need it. */
		lastevent->fr = NULL;
		if (command) {
			/*
			 * Free up the READ timequeue node
			 * we just removed from the queue.
			 */
			free_timenode(lastevent);
		}

		if (fr->brkpt.debugging && !fr->brkpt.isread) {

			/* We're in the MUF debugger!  Call it with the input line. */
			if (command) {
				if (muf_debugger(descr, player, prog, command, fr)) {
					/* MUF Debugger exited.  Free up the program frame & exit */
					prog_clean(fr);
					return;
				}
			} else {
				if (muf_debugger(descr, player, prog, "", fr)) {
					/* MUF Debugger exited.  Free up the program frame & exit */
					prog_clean(fr);
					return;
				}
			}
		} else {
			/* This is a MUF READ event. */
			if (command && !string_compare(command, BREAK_COMMAND)) {

				/* Whoops!  The user typed @Q.  Free the frame and exit. */
				prog_clean(fr);
				return;
			}

			if ((fr->argument.top >= STACK_SIZE) ||
				(nothing_flag && fr->argument.top >= STACK_SIZE - 1)) {

				/*
				 * Uh oh! That MUF program's stack is full!
				 * Print an error, free the frame, and exit.
				 */
				notify_nolisten(player, "Program stack overflow.", 1);
				prog_clean(fr);
				return;
			}

			/*
			 * Everything looks okay.  Lets stuff the input line
			 * on the program's argument stack as a string item.
			 */
			fr->argument.st[fr->argument.top].type = PROG_STRING;
			fr->argument.st[fr->argument.top++].data.string =
					alloc_prog_string(command ? command : "");
			if (typ == TQ_MUF_TREAD) {
				if (nothing_flag) {
					fr->argument.st[fr->argument.top].type = PROG_INTEGER;
					fr->argument.st[fr->argument.top++].data.number = 0;
				} else {
					fr->argument.st[fr->argument.top].type = PROG_INTEGER;
					fr->argument.st[fr->argument.top++].data.number = 1;
				}
			}
		}

		/*
		 * When using the MUF Debugger, the debugger will set the
		 * INTERACTIVE bit on the user, if it does NOT want the MUF
		 * program to resume executing.
		 */
		flag = (FLAGS(player) & INTERACTIVE);

		if (!flag && fr) {
			interp_loop(player, prog, fr, 0);
			/* WORK: if more input is pending, send the READ mufevent again. */
			/* WORK: if no input is pending, clear READ mufevent from all of this player's programs. */
		}

		/*
		 * Check for any other READ events for this player.
		 * If there are any, set the READ related flags.
		 */
		while (ptr) {
			if (ptr->typ == TQ_MUF_TYP && (ptr->subtyp == TQ_MUF_READ ||
										   ptr->subtyp == TQ_MUF_TREAD)) {
				if (ptr->uid == player) {
					FLAGS(player) |= (INTERACTIVE | READMODE);
				}
			}
			ptr = ptr->next;
		}
	}
}
Ejemplo n.º 8
0
int
add_event(int event_typ, int subtyp, int dtime, int descr, dbref player, dbref loc,
		  dbref trig, dbref program, struct frame *fr,
		  const char *strdata, const char *strcmd, const char *str3)
{
	timequeue ptr = tqhead;
	timequeue lastevent = NULL;
	time_t rtime = time((time_t *) NULL) + (time_t) dtime;
	int mypids = 0;

	if (tqhead) {
		for (ptr = tqhead, mypids = 0; ptr; ptr = ptr->next) {
			if (ptr->uid == player)
				mypids++;
			lastevent = ptr;
		}
	}

	if (event_typ == TQ_MUF_TYP && subtyp == TQ_MUF_READ) {
		process_count++;
		if (lastevent) {
			lastevent->next = alloc_timenode(event_typ, subtyp, rtime, descr,
											 player, loc, trig, program, fr,
											 strdata, strcmd, str3, NULL);
			return (lastevent->next->eventnum);
		} else {
			tqhead = alloc_timenode(event_typ, subtyp, rtime, descr,
									player, loc, trig, program, fr,
									strdata, strcmd, str3, NULL);
			return (tqhead->eventnum);
		}
	}
	if (!(event_typ == TQ_MUF_TYP && subtyp == TQ_MUF_TREAD)) {
		if (process_count > tp_max_process_limit ||
			(mypids > tp_max_plyr_processes && !Wizard(OWNER(player)))) {
			if (fr) {
				if (fr->multitask != BACKGROUND)
					PLAYER_SET_BLOCK(player, 0);
				prog_clean(fr);
			}
			notify_nolisten(player, "Event killed.  Timequeue table full.", 1);
			return 0;
		}
	}
	process_count++;

	if (!tqhead) {
		tqhead = alloc_timenode(event_typ, subtyp, rtime, descr, player, loc, trig,
								program, fr, strdata, strcmd, str3, NULL);
		return (tqhead->eventnum);
	}
	if (rtime < tqhead->when || (tqhead->typ == TQ_MUF_TYP && tqhead->subtyp == TQ_MUF_READ)
			) {
		tqhead = alloc_timenode(event_typ, subtyp, rtime, descr, player, loc, trig,
								program, fr, strdata, strcmd, str3, tqhead);
		return (tqhead->eventnum);
	}

	ptr = tqhead;
	while (ptr && ptr->next && rtime >= ptr->next->when &&
		   !(ptr->next->typ == TQ_MUF_TYP &&
			 ptr->next->subtyp == TQ_MUF_READ)) {
		ptr = ptr->next;
	}

	ptr->next = alloc_timenode(event_typ, subtyp, rtime, descr, player, loc, trig,
							   program, fr, strdata, strcmd, str3, ptr->next);
	return (ptr->next->eventnum);
}
Ejemplo n.º 9
0
void
propqueue(int descr, dbref player, dbref where, dbref trigger, dbref what, dbref xclude,
		  const char *propname, const char *toparg, int mlev, int mt)
{
	const char *tmpchar;
	const char *pname;
	dbref the_prog;
	char buf[BUFFER_LEN];
	char exbuf[BUFFER_LEN];

	the_prog = NOTHING;
	tmpchar = NULL;

	/* queue up program referred to by the given property */
	if (((the_prog = get_property_dbref(what, propname)) != NOTHING) ||
		(tmpchar = get_property_class(what, propname))) {

		if ((tmpchar && *tmpchar) || the_prog != NOTHING) {
			if (tmpchar) {
				if (*tmpchar == '&') {
					the_prog = AMBIGUOUS;
				} else if (*tmpchar == NUMBER_TOKEN && number(tmpchar + 1)) {
					the_prog = (dbref) atoi(++tmpchar);
				} else if (*tmpchar == REGISTERED_TOKEN) {
					the_prog = find_registered_obj(what, tmpchar);
				} else if (number(tmpchar)) {
					the_prog = (dbref) atoi(tmpchar);
				} else {
					the_prog = NOTHING;
				}
			} else {
				if (the_prog == AMBIGUOUS)
					the_prog = NOTHING;
			}
			if (the_prog != AMBIGUOUS) {
				if (the_prog < 0 || the_prog >= db_top) {
					the_prog = NOTHING;
				} else if (Typeof(the_prog) != TYPE_PROGRAM) {
					the_prog = NOTHING;
				} else if ((OWNER(the_prog) != OWNER(player)) && !(FLAGS(the_prog) & LINK_OK)) {
					the_prog = NOTHING;
				} else if (MLevel(the_prog) < mlev) {
					the_prog = NOTHING;
				} else if (MLevel(OWNER(the_prog)) < mlev) {
					the_prog = NOTHING;
				} else if (the_prog == xclude) {
					the_prog = NOTHING;
				}
			}
			if (propq_level < 8) {
				propq_level++;
				if (the_prog == AMBIGUOUS) {
					char cbuf[BUFFER_LEN];
					int ival;

					strcpyn(match_args, sizeof(match_args), "");
					strcpyn(match_cmdname, sizeof(match_cmdname), toparg);
					ival = (mt == 0) ? MPI_ISPUBLIC : MPI_ISPRIVATE;
					if (Prop_Blessed(what, propname))
						ival |= MPI_ISBLESSED;
					do_parse_mesg(descr, player, what, tmpchar + 1, "(MPIqueue)", cbuf, sizeof(cbuf), ival);
					if (*cbuf) {
						if (mt) {
							notify_filtered(player, player, cbuf, 1);
						} else {
							char bbuf[BUFFER_LEN];
							dbref plyr;

							snprintf(bbuf, sizeof(bbuf), ">> %.4000s",
									pronoun_substitute(descr, player, cbuf));
							plyr = DBFETCH(where)->contents;
							while (plyr != NOTHING) {
								if (Typeof(plyr) == TYPE_PLAYER && plyr != player)
									notify_filtered(player, plyr, bbuf, 0);
								plyr = DBFETCH(plyr)->next;
							}
						}
					}
				} else if (the_prog != NOTHING) {
					struct frame *tmpfr;

					strcpyn(match_args, sizeof(match_args), toparg ? toparg : "");
					strcpyn(match_cmdname, sizeof(match_cmdname), "Queued event.");
					tmpfr = interp(descr, player, where, the_prog, trigger,
								   BACKGROUND, STD_HARDUID, 0);
					if (tmpfr) {
						interp_loop(player, the_prog, tmpfr, 0);
					}
				}
				propq_level--;
			} else {
				notify_nolisten(player, "Propqueue stopped to prevent infinite loop.", 1);
			}
		}
	}
	strcpyn(buf, sizeof(buf), propname);
	if (is_propdir(what, buf)) {
		strcatn(buf, sizeof(buf), "/");
		while ((pname = next_prop_name(what, exbuf, sizeof(exbuf), buf))) {
			strcpyn(buf, sizeof(buf), pname);
			propqueue(descr, player, where, trigger, what, xclude, buf, toparg, mlev, mt);
		}
	}
}
Ejemplo n.º 10
0
void
do_dequeue(int descr, dbref player, const char *arg1)
{
	char buf[BUFFER_LEN];
	int count;
	dbref match;
	struct match_data md;
	timequeue tmp, ptr = tqhead;


	if (*arg1 == '\0') {
		notify_nolisten(player, "What event do you want to dequeue?", 1);
	} else {
		if (!string_compare(arg1, "all")) {
			if (!Wizard(OWNER(player))) {
				notify_nolisten(player, "Permission denied", 1);
				return;
			}
			while (ptr) {
				tmp = ptr;
				tqhead = ptr = ptr->next;
				free_timenode(tmp);
				process_count--;
			}
			tqhead = NULL;
			muf_event_dequeue(NOTHING, 0);
			notify_nolisten(player, "Time queue cleared.", 1);
		} else {
			if (!number(arg1)) {
				init_match(descr, player, arg1, NOTYPE, &md);
				match_absolute(&md);
				match_everything(&md);

				match = noisy_match_result(&md);
				if (match == NOTHING) {
					notify_nolisten(player, "I don't know what you want to dequeue!", 1);
					return;
				}
				if (!valid_objref(match)) {
					notify_nolisten(player, "I don't recognize that object.", 1);
					return;
				}
				if ((!Wizard(OWNER(player))) && (OWNER(match) != OWNER(player))) {
					notify_nolisten(player, "Permission denied.", 1);
					return;
				}
				count = dequeue_prog(match, 0);
				if (!count) {
					notify_nolisten(player, "That program wasn't in the time queue.", 1);
					return;
				}
				if (count > 1) {
					snprintf(buf, sizeof(buf), "%d processes dequeued.", count);
				} else {
					snprintf(buf, sizeof(buf), "Process dequeued.");
				}
				notify_nolisten(player, buf, 1);
			} else {
				if ((count = atoi(arg1))) {
					if (!(control_process(player, count))) {
						notify_nolisten(player, "Permission denied.", 1);
						return;
					}
					if (!(dequeue_process(count))) {
						notify_nolisten(player, "No such process!", 1);
						return;
					}
					process_count--;
					notify_nolisten(player, "Process dequeued.", 1);
				} else {
					notify_nolisten(player, "What process do you want to dequeue?", 1);
				}
			}
		}
	}
	return;
}