@q @program errorcheck.muf 1 99999 d i ( errorcheck.muf v1.0 Jessy @ FurryMUCK 11/99 A MUF error reporting utility. INSTALLATION: Set errorcheck.muf Wizard, so it can manipulate the .debug/ directory of programs. Create a global action and link it to the program. USE: <cmd> <prog> ............. Show detailed report for <prog> <cmd> #all ............... Scan db. List programs with error records <cmd> #clear <prog> ...... Clear error record for <prog> <cmd> #clear all ......... Clear error records on all progs you own <cmd> #clear dbase ....... Clear all error records in dbase [wiz only] <cmd> #track <command> ... Include username in <command> error records <cmd> #!track <command> .. Omit username from <command> error records The '#all', '#clear all', and '#clear dbase' options must scan the database, which may take a significant amount of time. #Option strings do not have to be typed completely. Errorcheck.muf may be freely ported. Please comment any changes. ) (2345678901234567890123456789012345678901234567890123456789012345678901) lvar ourArg (* str: cmd arg... may be modified *) lvar ourObj (* dbref: object to handle or report *) lvar ourOpt (* str: #option string *) $define Tell me @ swap notify $enddef : DoMatchObj ( s -- ) (* match s; store in ourObj *) #-1 ourObj ! ourArg @ match dup #-1 dbcmp if ">> I don't see that here." Tell pop pid kill then dup #-2 dbcmp if ">> Ambiguous. I don't know which one you mean." Tell pop pid kill then me @ over controls not if ">> Permission denied." Tell pop pid kill then ourObj ! ; : DoHelp ( -- ) (* show help screen *) " " Tell prog name " (#" strcat prog intostr strcat ")" strcat Tell " " Tell "This command reports errors for programs you control." Tell " " Tell " $command [<prog>] ........... Show detailed report for <prog>" command @ "$command" subst Tell " $command #all ............... Scan db. List programs with error records" command @ "$command" subst Tell " $command #clear <prog> ...... Clear error record for <prog>" command @ "$command" subst Tell " $command #clear all ......... Clear error records on all programs you own" command @ "$command" subst Tell " $command #clear dbase ....... Clear all error records in dbase (wiz only)" command @ "$command" subst Tell " $command #track <command> ... Include username in <cmd> error records" command @ "$command" subst Tell " $command #!track <command> .. Omit username from <cmd> error records" command @ "$command" subst Tell " " Tell "The '#all', '#clear all', and '#clear dbase' options must scan the " "database, which may take a significant amount of time. #Option strings " "do not have to be typed completely. Program to report defaults to the " "last program specified." strcat strcat strcat Tell " " Tell ; : DoAll ( -- ) (* scan db for .debug/ entries *) (* report all for progs controlled by user *) ":> Scanning dbase for .debug entries..." Tell background (* may take a while... go to background *) 0 begin (* scan db objects... *) dup dbref dup dbtop dbcmp not while (* more to check? *) dup ok? if (* ok dbref? *) me @ over controls if (* user controls? *) dup program? if (* it's a program? *) dup ".debug/errcount" getprop if (* has errors? *) dup unparseobj " " swap strcat " = " strcat (* show *) over ".debug/errcount" getprop intostr strcat Tell then then then then pop 1 + repeat pop ">> Done." Tell ; : DoClear ( -- ) (* clear what's specified by ourArg *) ourArg @ not if (* check syntax *) ">> Syntax: $command #clear <prog|all|dbase>" command @ "$command" subst Tell exit then (* clear all errors on objs *owned* by user *) (* this means wizzes can clear all, without clearing others' progs *) "all" ourArg @ smatch if ">> Clearing dbase of .debug entries for your programs..." Tell background 0 begin (* scan db... *) dup dbref dup dbtop dbcmp not while (* more to check? *) dup ok? if (* ok dbref? *) dup owner me @ dbcmp if (* user owns it? *) dup program? if (* it's a program? *) dup ".debug/errcount" remove_prop (* clear it *) dup ".debug/lastcrash" remove_prop dup ".debug/lasterr" remove_prop dup ".debug/lastuser" remove_prop dup ".debug/prevuser" remove_prop dup ".debug/prevuser" remove_prop then then then pop 1 + repeat pop ">> Done." Tell exit then (* this way clears all errors, regardless of ownership *) "dbase" ourArg @ smatch if me @ "W" flag? not if ">> Permission denied." Tell exit then ">> Clearing dbase of .debug entries..." Tell background 0 begin (* scan db... *) dup dbref dup dbtop dbcmp not while (* more to check? *) dup ok? if (* ok dbref? *) me @ over controls if (* user controls it? *) dup program? if (* it's a program? *) dup ".debug/errcount" remove_prop (* clear it *) dup ".debug/lastcrash" remove_prop dup ".debug/lasterr" remove_prop dup ".debug/lastuser" remove_prop dup ".debug/prevuser" remove_prop then then then pop 1 + repeat pop ">> Done." Tell exit then DoMatchObj (* this way for a single object *) ourObj @ program? not if ">> That's not a program." Tell pid kill then ourObj @ ".debug/errcount" remove_prop ourObj @ ".debug/lastcrash" remove_prop ourObj @ ".debug/lasterr" remove_prop ourObj @ ".debug/lastuser" remove_prop ourObj @ ".debug/prevuser" remove_prop ">> Cleared." Tell exit ; : DoTrack ( -- ) (* add props to track user when bug occurs *) (* if prevuser and lastcrash have the same systime, then prevuser holds dbref of player using program when it errored. move this to lastuser, to be included in reports *) trig getlink dup if ourObj ! ourObj @ ".debug/prevuser" getprop ourObj @ ".debug/lastcrash" getprop and if ourObj @ ".debug/prevuser" getprop ourObj @ ".debug/lastcrash" getprop intostr "::" swap strcat instr if ourObj @ ".debug/prevuser" getprop dup "::" instr 1 - strcut pop atoi dbref ourObj @ ".debug/lastuser" rot setprop then then ourObj @ ".debug/prevuser" (* now set current user as prevuser *) me @ intostr "::" strcat systime intostr strcat setprop else pop then ; : DoSetTrack ( s -- ) (* set MPI to trigger tracking for cmd s *) DoMatchObj ourObj @ exit? not if ">> That's not a command." Tell pid kill then ourObj @ getlink not if ">> Exit is not linked to a program." Tell pid kill then ourObj @ "_/sc" getpropstr "{null:{muf:#$prog,~&track&~}}" prog intostr "$prog" subst over over instr if (* just pretend if it's already set *) pop pop else strcat ourObj @ swap setsucc then ">> Set." Tell ; : DoNoTrack ( s -- ) (* remove MPI triggering tracking for cmd s *) DoMatchObj ourObj @ "_/sc" over over getpropstr "" "{null:{muf:#$prog,~&track&~}}" prog intostr "$prog" subst subst setprop ">> Set." Tell ; : DoCheck ( -- ) (* show report for a single program *) ourArg @ if (* if arg given, match and use that *) DoMatchObj else (* otherwise, use last prog we reported on *) me @ "_prefs/bcheck-last" getprop dup if ourObj ! else (* ... if we have one, that is *) pop DoHelp exit then then me @ ourObj @ controls if (* check permission; record report *) me @ "_prefs/bcheck-last" ourObj @ setprop else ">> Permission denied." Tell exit then ourObj @ ".debug/prevuser" getprop ourObj @ ".debug/lastcrash" getprop and if ourObj @ ".debug/prevuser" getprop ourObj @ ".debug/lastcrash" getprop intostr "::" swap strcat instr if ourObj @ ".debug/prevuser" getprop dup "::" instr 1 - strcut pop atoi dbref ourObj @ ".debug/lastuser" rot setprop then then (* show .debug/ info for our prog, nicely formatted *) ">> Error report for $program:" ourObj @ unparseobj "$program" subst Tell " " Tell " Error count: $count" ourObj @ ".debug/errcount" getprop intostr "$count" subst Tell ourObj @ ".debug/lastcrash" getprop if " Last crash: %C %r" ourObj @ ".debug/lastcrash" getprop timefmt Tell else " Last crash:" Tell then ourObj @ ".debug/lasterr" getpropstr if " Last error: $error" ourObj @ ".debug/lasterr" getprop dup "), " instr strcut swap pop strip 1 strcut swap pop strip "$error" subst Tell else " Last error:" Tell then ourObj @ ".debug/lastuser" getprop if " User: $user" ourObj @ ".debug/lastuser" getprop name "$user" subst Tell then ; : main "me" match me ! dup if "~&track&~" over smatch if DoTrack exit then dup "#*" smatch if dup " " instr if dup " " instr strcut strip ourArg ! strip ourOpt ! else strip dup ourOpt ! ourArg ! then "#help" ourOpt @ stringpfx if DoHelp else "#all" ourOpt @ stringpfx if DoAll else "#clear" ourOpt @ stringpfx if DoClear else "#track" ourOpt @ stringpfx if DoSetTrack else "#!track" ourOpt @ stringpfx if DoNoTrack else ourOpt @ ourArg ! DoCheck then then then then then else ourArg ! DoCheck then else ourArg ! DoCheck then ; . c q