/** * Print variable information * * Takes an argument string which is parsed to determine what to display. * Argument can look like: * * * a variable name * * L<num> or LV<num> * * L<name> or LV<name> * * S<num> or SV<num> * * V<num> * * L / LV is for local variables. Just a name, or S / SV searches scoped * variables. And finally V is for global variables. * * @private * @param player the player to show variable information * @param program the program that is running * @param fr the frame pointer * @param arg the argument as described above */ 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) { notify_nolisten(player, "I don't know which variable you mean.", 1); return; } /* * If 'sflag' is set, we will be looking up a scoped variable * If 'lflag' is set, we will be looking up a local variable * If neither is set, then we will be looking up a global variable. * * This code figures out the variable number (varnum) we will look up. */ 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, then we have found it and we need not do more * searching. * * If it is -1, we'll try to turn the remainder of 'arg' into a number * and see if that matches. * * Otherwise, error. */ 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; } /* Out of bounds */ if (i >= MAX_VAR || i < 0) { notify_nolisten(player, "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), 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), 1); } else { notify_nolisten(player, insttotext(fr, 0, &(fr->variables[i]), buf, sizeof(buf), 4000, -1, 1), 1); } }
/** * Push something into the stack from the debugger * * This can be a number, float, string, dbref, or variable. * * Variables are parsed almost the same as debug_printvar. In fact, it * looks pretty copy-pasty. For variable formating rules, * @see debug_printvar * * @private * @param player the player doing the pushing * @param fr the frame pointer * @param arg the argument which is a string containing something to push */ static void push_arg(dbref player, struct frame *fr, const char *arg) { int num, lflag = 0; int sflag = 0; double inum; if (fr->argument.top >= STACK_SIZE) { notify_nolisten(player, "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); notify_nolisten(player, "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)) { notify_nolisten(player, "I don't understand that dbref.", 1); return; } num = atoi(arg + 1); push(fr->argument.st, &fr->argument.top, PROG_OBJECT, MIPSCAST & num); notify_nolisten(player, "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)); notify_nolisten(player, "String pushed.", 1); } else { /* * @TODO This is basically copy/pasted from debug_printvar. * The variable resolution should probably be a common * function. */ 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 { notify_nolisten(player, "I don't understand what you want to push.", 1); return; } if (lflag) { push(fr->argument.st, &fr->argument.top, PROG_LVAR, MIPSCAST & num); notify_nolisten(player, "Local variable pushed.", 1); } else if (sflag) { push(fr->argument.st, &fr->argument.top, PROG_SVAR, MIPSCAST & num); notify_nolisten(player, "Scoped variable pushed.", 1); } else { push(fr->argument.st, &fr->argument.top, PROG_VAR, MIPSCAST & num); notify_nolisten(player, "Global variable pushed.", 1); } } }
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); } }