Example #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);
}
Example #2
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);
}