"Output code lines in traceback stacks @property $prog_options.show_tb_lines {"Do not display traceback code stack.", "Display tracebacking code."} "rc" $hacker @property $prog_options.show_bf_in_tbs {"Do not show bf wrappers in tracebacks.", "Show bf wrappers in tracebacks."} "rc" $hacker ;$prog_options:add("tb_lines"); ;$prog_options:add("bf_in_tbs"); @verb #0:handle_uncaught_error tnt rdx @program #0:handle_uncaught_error {code, msg, value, traceback, formatted} = args; perms = callers() ? caller_perms() | player; if (!callers() && !(player.wizard && player:prog_option("nolog"))) data = {@formatted, tostr("Player location: ", player.location), tostr("Other objects: ", $string_utils:nn_list(player.location.contents)), tostr("Last command: ", player.last_command)}; $mail_agent:send_message(player, $traceback_log, "traceback", data); endif set_task_perms(perms); if ($object_utils:has_verb(player, verb)) try result = player:(verb)(@args); return result; except (ANY) " skip return, keep going"; endtry endif if (`value[1] == $error ! ANY') "check for a list of options, convert it if neccessary"; value = {value}; endif show_code = 0; show_wrappers = 0; if ($object_utils:isa(player, $prog)) show_code = player:prog_option("tb_lines"); show_wrappers = player:prog_option("bf_in_tbs"); endif opts = {code, msg, value, traceback, show_code, show_wrappers, task_id()}; player:notify_lines($code_utils:format_traceback(@opts)); return 1; . @verb $code_utils:format_traceback tnt rdx @program $code_utils:format_traceback ":format_traceback(CODE, MSG, VALUE, TRACEBACK, ?SHOW_CODE, ?SHOW_WRAPPER, ?task_id)"; "formats TRACEBACK, which is a list given to you by the server as the result of catching an error."; "CODE and MSG are needed, since they are what caused the traceback"; "{, , , , , }"; "{code, msg, value, traceback, ?who = player} = args;"; "show_code = `who:prog_option(\"tb_lines\") || 0 ! ANY => 0';"; {code, msg, value, traceback, ?show_code = 0, ?show_wrapper = 0, ?task_id = task_id()} = args; set_task_perms(caller_perms()); if (`code[1] == $error ! ANY') if (msg == "{list}") msg = $error:message(code); endif code = $error:code(code); endif typeof(code) == STR || (code = toliteral(code)); sys = #0; if (!show_wrapper) for line in [1..length(traceback)] x = {__this, __verb} = traceback[line][1..2]; if (__this == sys && __verb[1..3] == "bf_") traceback[line] = 0; endif endfor traceback = $list_utils:setremove_all(traceback, 0); endif first = traceback[1]; traceback = listdelete(traceback, 1); su = $string_utils; nothing = $nothing; {__this, __verb, programmer, verb_loc, user, lineno} = first; verblocstr = __verb == "" ? "Input to EVAL" | tostr(su:matchable_string(verb_loc), ":", __verb); line = tostr(verblocstr, verb_loc != __this ? tostr(" (this == ", __this:reference(), ")") | "", ", line ", lineno, ": ", msg, " (", code, ")"); lines = {line}; if (show_code && valid(verb_loc)) lines = {@lines, this:_tb_code_line(verb_loc, __verb, lineno)}; endif hidden = 0; for line in (traceback) {__this, __verb, programmer, verb_loc, user, lineno} = line; line = "... called from "; if (verb_loc == nothing && programmer == nothing && __verb != "") line = tostr(line, "built-in function ", __verb, "()"); lines = {@lines, line}; else " __verb = ``verb_info(verb_loc, __verb)[3] ! E_VERBNF => \"huh\"' ! ANY => \"\"';"; full_verb_name = `verb_info(verb_loc, __verb)[3] ! ANY => __verb'; __verb == "" && (full_verb_name = "Input to EVAL"); verblocstr = __verb == "" ? full_verb_name | tostr(verb_loc:reference(), ":", full_verb_name); line = tostr(line, verblocstr, verb_loc != __this ? tostr(" (this == ", __this:reference(), ")") | "", ", line ", lineno); lines = {@lines, line}; if (show_code && valid(verb_loc)) lines = {@lines, this:_tb_code_line(verb_loc, __verb, lineno)}; endif endif endfor lines = {@lines, tostr("(End of traceback for task ", task_id, "; ", length(traceback) + 1, " total frames", hidden ? tostr("; ", hidden, " hidden") | "", ")")}; return lines; "(VERB-LOC == #-1 && PROGRAMMER == #-1 && VERB-NAME != \"\")"; "#-1:Input to EVAL, line 18: Variable not found"; "... called from built-in function eval()"; "... called from #59:eval_cmd_string* (this == #2), line 7"; "... called from #59:eval*-d d; (this == #2), line 9"; "(End of traceback)"; . @verb $code_utils:_tb_code_line tnt rdx @program $code_utils:_tb_code_line {vbloc, __verb, lineno, ?color = 0} = args; su = $string_utils; set_task_perms(caller_perms()); try code_line = verb_code(vbloc, __verb)[lineno]; except (E_PERM) code_line = ">>>Method is unreadable<<<"; except (E_VERBNF) code_line = ">>>Can't find method<<<"; except (E_RANGE) if (__verb == "eval_tmp") code_line = ">>>tmp_eval code was deleted<<<"; else code_line = ">>>Line out of range (code modified?)<<<"; endif endtry code_line = tostr(" [ ", su:trim(code_line), " ]"); return code_line; .