code utilities (#60)(an instance of Generic Utilities Package made by Hacker)     parse_propref("foo.bar") => {"foo","bar"} (or 0 if arg. isn't a property ref.)      parse_verbref("foo:bar") => {"foo","bar"} (or 0 if arg. isn't a verb ref.)      parse_argspec("any","in","front","of","this","baz"...)       => {{"any", "in front of", "this"},{"baz"...}}       (or string if args don't parse)            tonum(string) => number (or E_TYPE if string is not a number)      toobj(string) => object (or E_TYPE if string is not an object)      toerr(number or string) => error value (or 1 if out of range or unrecognized)      error_name(error value) => name of error (e.g., error_name(E_PERM) => "E_PERM")            verb_perms() => the current task_perms (as set by set_task_perms()).      verb_location() => the object where the current verb is defined.      verb_documentation([object,verbname]) => documentation at beginning of       verb code, if any -- default is the calling verb             Preposition routines            prepositions() => full list of prepostions      full_prep ("in") => "in/inside/into"      short_prep("into") => "in"      short_prep("in/inside/into") => "in"      get_prep ("off", "of", "the", "table") => {"off of", "the", "table"}             Verb routines            verbname_match (fullname,name) => can `name' be used to call `fullname'      find_verb_named (object,name[,n]) => verb number or -1 if not found      find_callable_verb_named (object,name[,n]) => verb number or -1 if not found      find_verbs_containing (pattern[,object|objlist])             Verbs that do the actual dirty work for @show:            show_object (object)      show_property(object,propname)      show_verbdef (object,verbname)             Dirty work for explain_syntax            explain_verb_syntax(thisname,verbname,@verbargs)             A random but useful verb            verb_or_property(object,name[,@args]) => result of verb or property call,       or E_PROPNF VERB SOURCE CODE: eval_d:
":eval_d(code...) => {compiled?,result}";
"This works exactly like the builtin eval() except that the code is evaluated ";
"as if the d flag were unset.";
code = {"set_verb_code(this,\"1\",{\"\\\"Do not remove this verb! This is an auxiliary
verb for :eval_d().\\\";\"});", "dobj=iobj=this=#-1;", "dobjstr=iobjstr=prepstr=argstr=verb=\"\";",
tostr("caller=", caller, ";"), "set_task_perms(caller_perms());", @args};
if (!caller_perms().programmer)
return E_PERM;
elseif (svc = set_verb_code(this, "1", code))
lines = {};
for line in (svc)
if ((index(line, "Line ") == 1) && (n = tonum(line[6..(colon = index(line
+ ":", ":")) - 1])))
lines = {@lines, tostr("Line ", n - 5, line[colon..length(line)])};
else
lines = {@lines, line};
endif
endfor
return {0, lines};
else
set_task_perms(caller_perms());
return {1, this:("1")()};
endif
.
1: "Do not remove this verb! This is an auxiliary verb for :eval_d()."; . tonum: ":tonum(number as string) => number"; return match(s = args[1], "^ *[-+]?[0-9]+ *$") ? tonum(s) | E_TYPE; . toobj: ":toobj(objectid as string) => objectid"; return match(s = args[1], "^ *#[-+]?[0-9]+ *$") ? toobj(s) | E_TYPE; . toerr:
"toerr(n), toerr(\"E_FOO\"), toerr(\"FOO\") => E_FOO.";
if (typeof(s = args[1]) != STR)
n = tonum(s) + 1;
if (n > length(this.error_list))
return 1;
endif
elseif (!(n = (s in this.error_names) || (("E_" + s) in this.error_names)))
return 1;
endif
return this.error_list[n];
.
error_name: "error_name(E_FOO) => \"E_FOO\""; return this.error_names[tonum(args[1]) + 1]; . show_object:
set_task_perms(caller_perms());
object = args[1];
what = {@args, {"props", "verbs"}}[2];
player:notify(tostr("Object ID: ", object));
player:notify(tostr("Name: ", object.name));
names = {"Parent", "Location", "Owner"};
vals = {parent(object), object.location, object.owner};
for i in [1..length(vals)]
if (!valid(vals[i]))
val = "*** NONE ***";
else
val = ((vals[i].name + " (") + tostr(vals[i])) + ")";
endif
player:notify(tostr(names[i], ": "[1..12 - length(names[i])], val));
endfor
line = "Flags: ";
if (is_player(object))
line = line + " player";
endif
for flag in ({"programmer", "wizard", "r", "w", "f"})
if (object.(flag))
line = (line + " ") + flag;
endif
endfor
player:notify(line);
if (player.programmer && ((player.wizard || (player == object.owner)) || object.r))
if (("verbs" in what) && verbs(object))
player:notify("Verb definitions:");
for v in (verbs(object))
$command_utils:suspend_if_needed(0);
player:notify(tostr(" ", v));
endfor
endif
if ("props" in what)
if (properties(object))
player:notify("Property definitions:");
for p in (properties(object))
$command_utils:suspend_if_needed(0);
player:notify(tostr(" ", p));
endfor
endif
all_props = $object_utils:all_properties(object);
if (all_props != {})
player:notify("Properties:");
for p in (all_props)
$command_utils:suspend_if_needed(0);
val = object.(p);
if (val == E_PERM)
STR = "(Permission denied.)";
else
STR = $string_utils:from_value_suspended(val, 1, -1);
endif
player:notify(tostr(" ", p, ": ", STR));
endfor
endif
endif
elseif (player.programmer)
player:notify("** Can't list properties or verbs: permission denied.");
endif
if (object.contents)
player:notify("Contents:");
for o in (object.contents)
$command_utils:suspend_if_needed(0);
player:notify(tostr(" ", o.name, " (", o, ")"));
endfor
endif
.
show_property:
set_task_perms(caller_perms());
object = args[1];
pname = args[2];
if (pname in this.builtin_props)
player:notify(tostr(object, ".", pname));
player:notify("Built-in property.");
else
info = property_info(object, pname);
if (typeof(info) == ERR)
player:notify(tostr(info));
return;
endif
owner = info[1];
perms = info[2];
player:notify(tostr(object, ".", pname));
player:notify(tostr("Owner: ", valid(owner) ? tostr(owner.name, " (",
owner, ")") | "*** NONE ***"));
player:notify(tostr("Permissions: ", perms));
endif
player:notify(tostr("Value: ", $string_utils:print(object.(pname))));
.
show_verbdef:
set_task_perms(caller_perms());
object = args[1];
vname = args[2];
if (!(hv = $object_utils:has_verb(object, vname)))
player:notify("That object does not define that verb.");
return;
elseif (hv[1] != object)
player:notify(tostr("Object ", object, " does not define that verb, but its ancestor
", hv[1], " does."));
object = hv[1];
endif
info = verb_info(object, vname);
if (typeof(info) == ERR)
player:notify(tostr(info));
return;
endif
owner = info[1];
perms = info[2];
names = info[3];
arg_specs = verb_args(object, vname);
player:notify(tostr(object, ":", names));
player:notify(tostr("Owner: ", valid(owner) ? tostr(owner.name, " (",
owner, ")") | "*** NONE ***"));
player:notify(tostr("Permissions: ", perms));
player:notify(tostr("Direct Object: ", arg_specs[1]));
player:notify(tostr("Preposition: ", arg_specs[2]));
player:notify(tostr("Indirect Object: ", arg_specs[3]));
.
explain_verb_syntax:
if (args[4..5] == {"none", "this"})
return 0;
endif
thisobj = args[1];
verb = args[2];
adobj = args[3];
aprep = args[4];
aiobj = args[5];
prep_part = (aprep == "any") ? "to" | this:short_prep(aprep);
".........`any' => `to' (arbitrary),... `none' => empty string...";
if ((adobj == "this") && (dobj == thisobj))
dobj_part = dobjstr;
iobj_part = ((!prep_part) || (aiobj == "none")) ? "" | ((aiobj == "this") ? dobjstr
| iobjstr);
elseif ((aiobj == "this") && (iobj == thisobj))
dobj_part = (adobj == "any") ? dobjstr | ((adobj == "this") ? iobjstr | "");
iobj_part = iobjstr;
elseif (!("this" in args[3..5]))
dobj_part = (adobj == "any") ? dobjstr | "";
iobj_part = (prep_part && (aiobj == "any")) ? iobjstr | "";
else
return 0;
endif
return tostr(verb, dobj_part ? " " + dobj_part | "", prep_part ? " " + prep_part
| "", iobj_part ? " " + iobj_part | "");
.
verb_p*erms verb_permi*ssions: "returns the permissions of the current verb (either the owner or the result of the most recent set_task_perms())."; return caller_perms(); . verb_loc*ation: "returns the object where the current verb is defined."; return callers()[1][4]; . verb_documentation:
":verb_documentation([object,verbname]) => documentation at beginning of verb code,
if any";
"default is the calling verb";
set_task_perms(caller_perms());
if (args)
object = args[1];
vname = args[2];
else
c = callers()[1];
object = c[4];
vname = c[2];
endif
if (typeof(code = verb_code(object, vname)) == ERR)
return tostr(code);
else
doc = {};
for line in (code)
if (match(line, "^\"%([^\\\"]%|\\.%)*\";$"))
"... now that we're sure `line' is just a string, eval() is safe...";
doc = {@doc, $no_one:eval("; return " + line)[2]};
else
return doc;
endif
endfor
return doc;
endif
.
set_verb_documentation:
":set_verb_documentation(object,verbname,text)";
" changes documentation at beginning of verb code";
" text is either a string or a list of strings";
" returns a non-1 value if anything bad happens...";
set_task_perms(caller_perms());
if (typeof(code = verb_code(object = args[1], vname = args[2])) == ERR)
return code;
elseif (typeof(vd = $code_utils:verb_documentation(object, vname)) == ERR)
return vd;
elseif (!(typeof(text = args[3]) in {LIST, STR}))
return E_INVARG;
else
newdoc = {};
for l in ((typeof(text) == LIST) ? text | {text})
if (typeof(l) != STR)
return E_INVARG;
endif
newdoc = {@newdoc, $string_utils:print(l) + ";"};
endfor
if ((ERR == typeof(svc = set_verb_code(object, vname, {@newdoc, @code[length(vd)
+ 1..length(code)]}))) || svc)
"... this shouldn't happen. I'm not setting this code -d just yet...";
return svc;
else
return 1;
endif
endif
.
parse_propref:
"$code_utils:parse_propref(string)";
"Parses string as a MOO-code property reference, returning {object-string, prop-name-string}
for a successful parse and false otherwise. It always returns the right object-string
to pass to, for example, this-room:match_object.";
s = args[1];
if (dot = index(s, "."))
object = s[1..dot - 1];
prop = s[dot + 1..length(s)];
if ((object == "") || (prop == ""))
return 0;
elseif (object[1] == "$")
object = #0.(object[2..length(object)]);
if (typeof(object) != OBJ)
return 0;
endif
object = tostr(object);
endif
elseif (index(s, "$") == 1)
object = "#0";
prop = s[2..length(s)];
else
return 0;
endif
return {object, prop};
.
parse_verbref:
"$code_utils:parse_verbref(string)";
"Parses string as a MOO-code verb reference, returning {object-string, verb-name-string}
for a successful parse and false otherwise. It always returns the right object-string
to pass to, for example, this-room:match_object().";
s = args[1];
if (colon = index(s, ":"))
object = s[1..colon - 1];
verbname = s[colon + 1..length(s)];
if (!(object && verbname))
return 0;
elseif ((object[1] == "$") && 0)
"Why was this check taking place here? -- from jhm";
pname = object[2..length(object)];
if ((!(pname in properties(#0))) || (typeof(object = #0.(pname)) != OBJ))
return 0;
endif
object = tostr(object);
endif
return {object, verbname};
else
return 0;
endif
.
parse_argspec:
":parse_arg_spec(@args)";
" attempts to parse the given sequence of args into a verb_arg specification";
"returns {verb_args,remaining_args} if successful.";
" e.g., :parse_arg_spec(\"this\",\"in\",\"front\",\"of\",\"any\",\"foo\"..)";
" => {{\"this\",\"in front of\",\"any\"},{\"foo\"..}}";
"returns a string error message if parsing fails.";
nargs = length(args);
if (nargs < 1)
return {{}, {}};
elseif ((ds = args[1]) == "tnt")
return {{"this", "none", "this"}, listdelete(args, 1)};
elseif (!(ds in {"this", "any", "none"}))
return tostr("\"", ds, "\" is not a valid direct object specifier.");
elseif ((nargs < 2) || (args[2] in {"none", "any"}))
verbargs = args[1..min(3, nargs)];
rest = args[4..nargs];
elseif (!(gp = $code_utils:get_prep(@args[2..nargs]))[1])
return tostr("\"", args[2], "\" is not a valid preposition.");
else
verbargs = {ds, @gp[1..min(2, nargs = length(gp))]};
rest = gp[3..nargs];
endif
if ((length(verbargs) >= 3) && (!(verbargs[3] in {"this", "any", "none"})))
return tostr("\"", verbargs[3], "\" is not a valid indirect object specifier.");
endif
return {verbargs, rest};
.
prepositions:
if (server_version() != this._version)
this:_fix_preps();
endif
return this.prepositions;
.
short_prep:
":short_prep(p) => shortest preposition equivalent to p";
"p may be a single word or one of the strings returned by verb_args().";
if (server_version() != this._version)
this:_fix_preps();
endif
word = args[1];
word = word[1..index(word + "/", "/") - 1];
if (p = word in this._other_preps)
return this._short_preps[this._other_preps_n[p]];
elseif (word in this._short_preps)
return word;
else
return "";
endif
.
full_prep:
if (server_version() != this._version)
this:_fix_preps();
endif
prep = args[1];
if (p = prep in this._short_preps)
return this.prepositions[p];
elseif (p = prep in this._other_preps)
return this.prepositions[this._other_preps_n[p]];
else
return "";
endif
.
get_prep:
":get_prep(@args) extracts the prepositional phrase from the front of args, returning
a list consisting of the preposition (or \"\", if none) followed by the unused args.";
":get_prep(\"in\",\"front\",\"of\",...) => {\"in front of\",...}";
":get_prep(\"inside\",...) => {\"inside\",...}";
":get_prep(\"frabulous\",...} => {\"\", \"frabulous\",...}";
prep = "";
allpreps = {@this._short_preps, @this._other_preps};
rest = 1;
for i in [1..length(args)]
try_ = (i == 1) ? args[1] | tostr(try_, " ", args[i]);
if (try_ in allpreps)
prep = try_;
rest = i + 1;
endif
if (!(try_ in this._multi_preps))
return {prep, @args[rest..length(args)]};
endif
endfor
return {prep, @args[rest..length(args)]};
.
_fix_preps:
":_fix_preps() updates the properties on this having to do with prepositions.";
"_fix_preps should be called whenever we detect that a new server version has been
installed.";
orig_args = verb_args(this, verb);
multis = nothers = others = shorts = longs = {};
i = 0;
while (typeof(set_verb_args(this, verb, {"this", tostr(i), "this"})) != ERR)
l = verb_args(this, verb)[2];
all = $string_utils:explode(l, "/");
s = all[1];
for p in (listdelete(all, 1))
if (length(p) <= length(s))
s = p;
endif
endfor
for p in (all)
while (j = rindex(p, " "))
multis = {p = p[1..j - 1], @multis};
endwhile
endfor
longs = {@longs, l};
shorts = {@shorts, s};
others = {@others, @setremove(all, s)};
nothers = {@nothers, @$list_utils:make(length(all) - 1, length(shorts))};
i = i + 1;
endwhile
set_verb_args(this, verb, orig_args);
this.prepositions = longs;
this._short_preps = shorts;
this._other_preps = others;
this._other_preps_n = nothers;
this._multi_preps = multis;
this._version = server_version();
return;
.
find_verb_named:
":find_verb_named(object,name[,n])";
" returns the *number* of the first verb on object matching the given name.";
" optional argument n, if given, starts the search with verb n,";
" causing the first n verbs (0..n-1) to be ignored.";
" -1 is returned if no verb is found.";
" This routine does not find inherited verbs.";
object = args[1];
name = args[2];
for i in [{@args, 0}[3]..length(verbs(object)) - 1]
verbinfo = verb_info(object, tostr(i));
if (this:verbname_match(verbinfo[3], name))
return i;
endif
endfor
return -1;
.
find_last_verb_named:
":find_verb_named(object,name[,n])";
" returns the *number* of the last verb on object matching the given name.";
" optional argument n, if given, starts the search with verb n-1,";
" causing verbs (n..length(verbs(object))) to be ignored.";
" -1 is returned if no verb is found.";
" This routine does not find inherited verbs.";
object = args[1];
name = args[2];
last = {@args, -1}[3];
if (last < 0)
last = length(verbs(object));
endif
for i in [1..last]
verbinfo = verb_info(object, tostr(last - i));
if (this:verbname_match(verbinfo[3], name))
return last - i;
endif
endfor
return -1;
.
find_callable_verb_named:
":find_callable_verb_named(object,name[,n])";
" returns the *number* of the first verb on object that matches the given";
" name and has the x flag set.";
" optional argument n, if given, starts the search with verb n,";
" causing the first n verbs (0..n-1) to be ignored.";
" -1 is returned if no verb is found.";
" This routine does not find inherited verbs.";
object = args[1];
name = args[2];
for i in [{@args, 0}[3]..length(verbs(object)) - 1]
verbinfo = verb_info(object, tostr(i));
if (index(verbinfo[2], "x") && this:verbname_match(verbinfo[3], name))
return i;
endif
endfor
return -1;
.
find_verbs_containing:
"$code_utils:find_verbs_containing(pattern[,object|object-list])";
"";
"Print (to player) the name and owner of every verb in the database whose code contains
PATTERN as a substring. Optional second argument limits the search to the specified
object or objects.";
"";
"Because it searches the entire database, this function may suspend the task several
times before returning.";
"";
set_task_perms(caller_perms());
"... puts the task in a player's own job queue and prevents someone from learning
about verbs that are otherwise unreadable to him/her.";
pattern = args[1];
where = {@args, 0}[2];
count = 0;
if (typeof(where) == NUM)
for i in [where..tonum(max_object())]
if (valid(o = toobj(i)))
count = count + this:_find_verbs_containing(pattern, o);
endif
if ($command_utils:running_out_of_time())
player:notify(tostr("...", o));
suspend(0);
endif
endfor
elseif (typeof(where) == LIST)
for o in (where)
count = count + this:_find_verbs_containing(pattern, o);
endfor
else
"...typeof(where) == OBJ...";
count = this:_find_verbs_containing(pattern, where);
endif
player:notify("");
player:notify(tostr("Total: ", count, " verbs."));
.
_find_verbs_containing:
":_find_verbs_containing(pattern,object)";
"number of verbs in object with code having a line containing pattern";
"prints verbname and offending line to player";
set_task_perms(caller_perms());
pattern = args[1];
count = 0;
verbs = verbs(o = args[2]);
if (typeof(verbs) == ERR)
player:notify(tostr("verbs(", o, ") => ", verbs));
return 0;
endif
for vnum in [0..length(verbs) - 1]
if (l = this:_grep_verb_code(pattern, o, vname = tostr(vnum)))
owner = verb_info(o, vname)[1];
player:notify(tostr(o, ":", verbs[vnum + 1], " [", valid(owner) ? owner.name
| "Recycled Player", " (", owner, ")]: ", l));
count = count + 1;
endif
if ($command_utils:running_out_of_time())
player:notify(tostr("...", o));
suspend(0);
endif
endfor
return count;
.
find_verbs_matching:
"$code_utils:find_verbs_matching(pattern[,object|object-list])";
"";
"Print (to player) the name and owner of every verb in the database whose code has
a substring matches the regular expression PATTERN. Optional second argument limits
the search to the specified object or objects.";
"";
"Because it searches the entire database, this function may suspend the task several
times before returning.";
"";
set_task_perms(caller_perms());
"... puts the task in a player's own job queue and prevents someone from learning
about verbs that are otherwise unreadable to him/her.";
pattern = args[1];
where = {@args, 0}[2];
count = 0;
if (typeof(where) == NUM)
for i in [where..tonum(max_object())]
if (valid(o = toobj(i)))
count = count + this:_find_verbs_matching(pattern, o);
endif
if ($command_utils:running_out_of_time())
player:notify(tostr("...", o));
suspend(0);
endif
endfor
elseif (typeof(where) == LIST)
for o in (where)
count = count + this:_find_verbs_matching(pattern, o);
endfor
else
count = this:_find_verbs_matching(pattern, args[2]);
endif
player:notify("");
player:notify(tostr("Total: ", count, " verbs."));
.
_find_verbs_matching:
":_find_verbs_matching(regexp,object)";
"number of verbs in object with code having a line matching regexp";
"prints verbname and offending line to player";
set_task_perms(caller_perms());
pattern = args[1];
count = 0;
verbs = verbs(o = args[2]);
if (typeof(verbs) == ERR)
player:notify(tostr("verbs(", o, ") => ", verbs));
return 0;
endif
for vnum in [0..length(verbs) - 1]
if (l = this:_egrep_verb_code(pattern, o, vname = tostr(vnum)))
owner = verb_info(o, vname)[1];
player:notify(tostr(o, ":", verbs[vnum + 1], " [", valid(owner) ? owner.name
| "Recycled Player", " (", owner, ")]: ", l));
count = count + 1;
endif
if ($command_utils:running_out_of_time())
player:notify(tostr("...", o));
suspend(0);
endif
endfor
return count;
.
_grep_verb_code:
":_grep_verb_code(pattern,object,verbname) => line number or 0";
" returns line number on which pattern occurs in code for object:verbname";
set_task_perms(caller_perms());
pattern = args[1];
for line in (vc = verb_code(@listdelete(args, 1)))
if (index(line, pattern))
return line;
endif
endfor
return 0;
.
_egrep_verb_code:
":_egrep_verb_code(regexp,object,verbname) => 0 or line number";
" returns line number of first line matching regexp in object:verbname code";
set_task_perms(caller_perms());
pattern = args[1];
for line in (vc = verb_code(@listdelete(args, 1)))
if (match(line, pattern))
return line;
endif
endfor
return 0;
.
_parse_audit_args: "Parse [from help_db_list:
olist = {player, @$object_utils:ancestors(player)};
if (valid(player.location))
olist = {@olist, player.location, @$object_utils:ancestors(player.location)};
endif
dbs = {};
for o in (olist)
h = o.help;
if (typeof(h) == OBJ)
h = {h};
endif
for db in (h)
if ((typeof(db) == OBJ) && (valid(db) && (!(db in dbs))))
dbs = {@dbs, db};
endif
endfor
endfor
return {@dbs, $help};
.
help_db_search:
":help_db_search(string,dblist)";
" searches each of the help db's in dblist for a topic matching string.";
" Returns {db,topic} or {$ambiguous_match,{topic...}} or {}";
what = args[1];
dblist = args[2];
topics = {};
help = 1;
for db in (dblist)
if ({what} == (ts = db:find_topics(what)))
return {db, ts[1]};
elseif (ts && (typeof(ts) == LIST))
if (help)
help = db;
endif
for t in (ts)
topics = setadd(topics, t);
endfor
endif
endfor
if (length(topics) > 1)
return {$ambiguous_match, topics};
elseif (topics)
return {help, topics[1]};
else
return {};
endif
.
corify_object:
":corify_object(object) => string representing object";
" usually just returns tostr(object), but in the case of objects that have";
" corresponding #0 properties, return the appropriate $-string.";
object = args[1];
for p in (properties(#0))
if (#0.(p) == object)
return "$" + p;
endif
endfor
return tostr(object);
.
substitute:
"$code_utils:substitute(string,subs) => new line";
"Subs are a list of lists, {{\"target\",\"sub\"},{...}...}";
"Substitutes targets for subs in a delimited string fashion, avoiding substituting
anything inside quotes, e.g. player:tell(\"don't sub here!\")";
s = args[1];
subs = args[2];
lets = "abcdefghijklmnopqrstuvwxyz0123456789";
for x in (subs)
len = length(sub = x[1]);
delimited = index(lets, sub[1]) && index(lets, sub[len]);
prefix = "";
while (i = index(s, sub))
prefix = prefix + s[1..i - 1];
if ((((prefix == "") || ((!delimited) || (!index(lets, prefix[length(prefix)]))))
&& ((!delimited) || (((i + len) > length(s)) || (!index(lets, s[i + len]))))) &&
(!this:inside_quotes(prefix)))
prefix = prefix + x[2];
else
prefix = prefix + s[i..(i + len) - 1];
endif
s = s[i + len..length(s)];
endwhile
s = prefix + s;
endfor
return s;
.
inside_quotes:
"See if the end of the string passed as args[1] ends 'inside' a doublequote. Used
by $code_utils:substitute.";
string = args[1];
quoted = 0;
for i in [1..length(string)]
if ((string[i] == "\"") && ((!quoted) || (string[i - 1] != "\\")))
quoted = !quoted;
endif
endfor
return quoted;
.
verb_or_property: "verb_or_property( task_valid: "task_valid(NUM id)"; "Return true iff there is currently a valid task with the given id."; set_task_perms($no_one); id = args[1]; return (id == task_id()) || (E_PERM == kill_task(id)); . task_owner:
if (a = $list_utils:assoc(args[1], queued_tasks()))
return a[5];
else
return E_INVARG;
endif
.
argstr:
":argstr(verb,args[,argstr]) => what argstr should have been. ";
"Recall that the command line is parsed into a sequence of words; `verb' is";
"assigned the first word, `args' is assigned the remaining words, and argstr";
"is assigned a substring of the command line, which *should* be the one";
"starting first nonblank character after the verb, but is instead (because";
"the parser is BROKEN!) the one starting with the first nonblank character";
"after the first space in the line, which is not necessarily after the verb.";
"Clearly, if the verb contains spaces --- which can happen if you use";
"backslashes and quotes --- this loses, and argstr will then erroneously";
"have extra junk at the beginning. This verb, given verb, args, and the";
"actual argstr, returns what argstr should have been.";
verb = args[1];
argstr = {@args, argstr}[3];
n = length(args = args[2]);
if (!index(verb, " "))
return argstr;
elseif (!args)
return "";
endif
"space in verb => two possible cases:";
"(1) first space was not in a quoted string.";
" first word of argstr == rest of verb unless verb ended on this space.";
if ((nqargs = $string_utils:words(argstr)) == args)
return argstr;
elseif (((nqn = length(nqargs)) == (n + 1)) && (nqargs[2..nqn] == args))
return argstr[$string_utils:word_start(argstr)[2][1]..length(argstr)];
else
"(2) first space was in a quoted string.";
" argstr starts with rest of string";
qs = $string_utils:word_start("\"" + argstr);
return argstr[qs[(length(qs) - length(args)) + 1][1] - 1..length(argstr)];
endif
.
verbname_match:
":verbname_match(fullverbname,name) => TRUE iff `name' is a valid name for a verb
with the given `fullname'";
verblist = (" " + args[1]) + " ";
if (index(verblist, (" " + (name = args[2])) + " ") && (!(index(name, "*") || index(name,
" "))))
"Note that if name has a * or a space in it, then it can only match one of the
* verbnames";
return 1;
else
namelen = length(name);
while (star = index(verblist, "*"))
vstart = rindex(verblist[1..star], " ") + 1;
vlast = (vstart + index(verblist[vstart..length(verblist)], " ")) - 2;
if ((namelen >= (star - vstart)) && ((!(v = strsub(verblist[vstart..vlast],
"*", ""))) || (index(v, (verblist[vlast] == "*") ? name[1..min(namelen, length(v))]
| name) == 1)))
return 1;
endif
verblist = verblist[vlast + 1..length(verblist)];
endwhile
endif
return 0;
.
show_who_listing:
":show_who_listing(players[,more_players])";
" prints a listing of the indicated players.";
" For players in the first list, idle/connected times are shown if the player is
logged in, otherwise the last_disconnect_time is shown. For players in the second
list, last_disconnect_time is shown, no matter whether the player is logged in.";
idles = itimes = offs = otimes = {};
for p in (args[2])
if (!valid(p))
caller:notify(tostr(p, "
_egrep_verb_code_all:
":_egrep_verb_code(regexp,object,verbname) => list of lines number";
" returns list of all lines matching regexp in object:verbname code";
set_task_perms(caller_perms());
pattern = args[1];
lines = {};
for line in (vc = verb_code(@args[2..3], 1, 0))
if (match(line, pattern))
lines = {@lines, line};
endif
endfor
return lines;
.
_grep_verb_code_all:
":_grep_verb_code_all(pattern,object,verbname) => list of lines";
" returns list of lines on which pattern occurs in code for object:verbname";
set_task_perms(caller_perms());
pattern = args[1];
lines = {};
for line in (vc = verb_code(@args[2..3]))
if (index(line, pattern))
lines = {@lines, line};
endif
endfor
return lines;
.
verb_usage:
":verb_usage([object,verbname]) => usage string at beginning of verb code, if any";
"default is the calling verb";
set_task_perms(caller_perms());
if (args)
object = args[1];
vname = args[2];
else
c = callers()[1];
object = c[4];
vname = c[2];
endif
if (typeof(code = verb_code(object, vname)) == ERR)
return code;
else
doc = {};
for line in (code)
if (match(line, "^\"%([^\\\"]%|\\.%)*\";$"))
"... now that we're sure `line' is just a string, eval() is safe...";
e = $no_one:eval(line)[2];
if (subs = match(e, "^%(Usage: +%)%([^ ]+%)%(.*$%)"))
"Server is broken, hence the next three lines:";
if (subs[3][3][1] > subs[3][3][2])
subs[3][3] = {0, -1};
endif
indent = ("^%(" + $string_utils:space(length(substitute("%1", subs))))
+ " *%)%([^ ]+%)%(.*$%)";
docverb = substitute("%2", subs);
if (match(vname, "^[0-9]+$"))
vname = docverb;
endif
doc = {@doc, (substitute("%1", subs) + vname) + substitute("%3",
subs)};
elseif (subs = match(e, indent))
if (substitute("%2", subs) == docverb)
doc = {@doc, (substitute("%1", subs) + vname) + substitute("%3",
subs)};
else
doc = {@doc, e};
endif
elseif (indent)
return doc;
endif
else
return doc;
endif
endfor
return doc;
endif
.
PROPERTY DATA:       prepositions       _version       _multi_preps       _other_preps_n       _other_preps       _short_preps       _all_preps       builtin_props       error_names       error_list |