The standard database and package of programs includes the following
programming libraries:
Note: Since the libararies were written, many of the functions they
provide have been defined as MUF
primitives. The libraries
are retained in their current form for compatibility with existing
programs. If a primitive providing the functionality you want is
available, it will be more efficient than a library call. For more
information on using libraries, see Section
3.2.2.
EDITORloop ( range s1 i1 -- range' s1 i2 s2 i3 i4 s3
)
Puts the user in the list editor, using range
as the
values for the lines of the list. The list can be interactively edited
as with command lsedit.
The EDITOR
function provides similar
functionality; EDITORloop
gives greater control over data
passed to and from the editor.
EDITORloop
takes a range, a space-separated string
s1
containing any commands that can be used to return from
the editor in addition to end
and abort,
cursor position i1,
and the first editor command to be
executed.
EDITORloop
returns the modified range, the string
s1,
the cursor postion at time-of-exit, exit arguments
s2,
i3,
and i4,
and the command
string used to exit the editor on the stack. Exit arguments are
parameters returned to the program when EDITORloop
exits.
They follow the syntax of other editor commands:
command start_line end_line = argument_string
start_line
is i3.
end_line
is
i4.
argument_string
is s2.
Example: Suppose you create a program that allows players included in a
list holding their dbrefs to update documents in a news reader program.
The program includes and #admin
function that puts the user
into the editor to modify this list. You want to include, in your
version of the editor, a command that shows the names of the players who
are currently in the list, optionally followed by information such as
the last time they logged on or their position/title in the
MUCK
news staff. The user could then display the names (and
other information) for players whose dbrefs are in the list, or a range
from the list, by entering .names
or .names
<range>
or .names [<range>] =
<field>.
You could do this by reading the list onto the
stack and supplying names
as a command string that would
cause EDITORloop
to return, with code such as the
following:
"_staff" trig LMGR-Getlist (*read list onto stack as a range*)
"names" over 1 + ".i" EDITORloop (*put user in editor, ready to insert
text, at the next free line, with
`names' defined as a .command that
will cause EDITORloop to return*)
If the user typed .names
while at line 6 of a 12-line
list of dbrefs, the following would be put on the stack:
... #123, 12, "names", 6, "", 0, 0, "names"
Using comparison primitives such as SMATCH
or STRINGCMP,
you could check the top value on the stack and, if it is the string "names"
(as it is here), execute a ShowNames
function in your program, then return to the editor with another instance of EDITORloop.
If the user had typed .names 1 8,
the following would be
put on the stack:
... #123, 12, "names", 6, "", 1, 8, "names"
Your ShowNames
function would need to use the values
1
and 8
to show only names for the dbrefs in
lines 1 - 8.
If the user had typed .names 1 - 8 = title,
the
following would be put on the stack:
... #123, 12, "names", 6, "title", 1, 8, "names"
ShowNames
would use this information to show the names
of players listed in lines 1 - 8 of the list, concattenated with their
title... perhaps a value stored in their _news/title
property. See also EDITOR.
(Lib-Editor) [top]
Indexes
"In theory, there's no difference between theory and practice. But in
practice, there is." Keep this firmly in mind when working with
Lib-Index functions. The following is a brief discussion of how
Lib-Index functions are supposed to work. However, several do not behave
as advertised. Such cases are noted in the entries for specific
Lib-Index functions.
An index is a set of name/value pairs. The index as a whole is stored
as a set of associated properties, in a single propdir, consisting of a
list of all elements (stored as a single string) and a property for each
`name', which holds a `value' associated with the name.
Most routines are also available in `std-'
form (the
routine name is prefaced with std-,
such as
.index-add
to .std-index-add
). Routines which
store information (add members to the index) have the following stack
effect:
( d s1 s2 s3 -- d s1 s2 s3 i )
where d
is the object the index is stored on, s1
is the name of the index, s2
is the `name' value, and s3
is the `value' value. All four items are left on the stack unchanged, and an integer error code is returned: 1
for `no error: item successfully added',
and 0
for `error: s2 is already a member of the index; index unchanged'.
Routines that retrieve information (perform matches) have the
following stack effect:
( d s1 s2 s3 -- d s1 s2' s4 i )
where d
is the object the index is stored on,
s1
is the name of the index, s2
is the name to
be matched, and s3
is a string holding 1 - 3 characters
specifying matching criteria:
x: exact match only, ignores the index itself
e: exit-style match: exact match of ;-separated value, and select the
first match found if there are more than one
w: normal operation: match the beginning of a space separated word,
and fail if more than one matched. So, `mat' matches `mattress'
and `lit match', but not `rematch'.
Arguments d
and s1
are left on the stack
unchanged. The name to be matched is, if found, returned as
s2'.
If the match was unsuccessful, s2'
will
be a null string. If s2
were a partial match,
s2'
would be returned as the full name. The match criteria
paramters, s3,
are returned as null string s4.
Finally, an error code is returned (1
is no error, match
successful; 0
is error, match unsuccessful).
The default matching criteria (employed with routines called
without the std-
prefix) is xew
: all
three criteria are used, and the first match made by any of the criteria
will be returned. [top]
MSG-create ( range s1 s2 d -- )
Creates a new message with the items in a stringe range and the
information string s1,
stored as list properties with base
s2
on object d.
Example: The following code reads list _staff
from the
trigger action onto the stack as a range, and creates a message with the
contents of lvar ourString for each staff member.
"_staff" trig LMGR-Getlist (*read list onto stack as range*)
ourString @ (*put message on stack *)
"st-msgs/" dup trig LMGR-Getcount (*get next available line number*)
1 + intostr strcat (*use count to create message base*)
trig MSG-create (*create message, stored on trig*)
(*note: this same effect could be
achieved more efficiently with
MSG-append or MBOX-append*)
Assume that a staff memeber uses the stnews
command
(#555
) with the message "Please check `+read
17'";
that list _staff
contains 5 lines, each
holding a staff member's dbref in string form (2, 3, 13, 99, and
244
); and that there are currently two other staff messages. In
this case, the code would put the following values on the stack:
"2", "3", "13", "99", "244", 5, "Please check `+read 17'",
"st-msgs/3", #555
Then, MSG-create
would be called, creating propdir
st-msgs/3#/,
which other functions could use to relay the
message to staff members online, at log-in, or when they check staff
news. Ex #555 = st-news/3#/
would show the following
values:
str /st-msgs/3#/1:2
str /st-msgs/3#/2:3
str /st-msgs/3#/3:13
str /st-msgs/3#/4:99
str /st-msgs/3#/5:244
str /st-msgs/3#/i:Please check `news staff'
The data passed to MSG-create
would be cleared from the
stack. (Lib-Mesg) [top]
sr-copyrng ( range ... offset number position -- range
... range2 )
Copies a subrange of number
items out of a range in the
stack, beginning with the item at position.
For
example,
"a" "b" "c" "d" 4 0 3 2 sr-copyrng
would make take the 4-item stack "a" "b" "c" "d",
and
copy from it, making a new, 3-item range, beginning with the second item
in the 4-item range.
"a" "b" "c" "d" 4 "b" "c" "d" 3
would be left on the stack. (Lib-Stackrng) [top]
sr-swaprng ( range1 range2 -- i range2 range1
)
Swaps two ranges on the stack, inserting a 0-length range before the
two ranges. There must be x
items on the stack below
range1,
where x
is equal to the larger of
range1's
count or range2's
count. That is,
"" "a" "b" 2 "c" "d" "e" 3 sr-swaprng
would crash due to stack underflow, but
"" "null" "null" "null" "a" "b" 2 "c" "d" "e" 3 sr-swaprng
would put
"" "null" "null" "null" 0 "c" "d" "e" 3 "a "b" 2
on the stack. For this reason, it will often be necessary to copy a
`work space' range with sr-copyrng
before using
sr-swaprng.
(Lib-Stackrng) [top]
.table_match ( x1 x2 cn pn ... c1 p1 i x3 address -- cx
px )
This function tests successive pairs of `comparator' and `data'
elements with a separate function (that you create), returning the pair
that (according to your function's criteria) `matches'. Although
.table_match
is supplied as a matching function, it can
have other applications: the comparator/data pairs in effect constitute
a hash table, and the `matching' function can perform whatever
operations you require.
.Table_match
takes parameters x1
the
item to be returned if no match is found and x2
the item to be returned if more than one pair matches.
x1
and x2
can be of any type. Example:
#-1
and #-2
are the conventional items used to
indicate negative or ambiguous match results for objects of type dbref.
These parameters are followed by comparator/data pairs: the comparator
is the item to be tested for a match; the data item is a stack item
associated with the comparator. An integer specifying the number of such
pairs to be tested is then supplied, followed by the value
x3
which will be used to test the match and
the address of the testing function. The testing function should return
1
for true results and 0
for false results.
.Table_match
returns the comparator/data pair that matches
(cx px
), or the paramters for negative or ambiguous results
(x1
or x2
)
Example: Suppose you want a function supplementing
.pmatch
and .noisy_pmatch
that can find
players by `nicknames', which are often set as a player's
%n
property. One way (among many possibilities) to create
such a function would be to supply comparator/data pairs of players'
%n
properties and their dbrefs, and calling
.table_match.
The nickname to be matched is stored in
lvar ourString.
Function GetPairs
puts the
prop/dbref pairs and their count on the stack. Function
CheckNick
performs a SMATCH,
returning
1
if a comparator matches ourString, and 0
if
it does not. Code for calling .table_match
might then look
like this:
#-1 #-2 GetPairs ourString @ `CheckNick .table_match
If a player calls the program with a search for "Dr.
Cat",
and GetPairs
returns three players who have
%n
nicknames (and thus are candidates for possible matches)
the stack created by this code might have values such as the following
immediately before .table_match
is called:
#-1, #-2, "the Scamper Gal", #2, "the terribly velvet-furred linsang",
#13, "Dr. Cat" #244, "Dr. Cat", `CheckNick
#-1
and #-2
are the codes
.table_match
is to return for negative and ambiguous
matches. The next six items on the stack are three comparator/data
pairs: The dbrefs of players #2,
#13,
and
#244,
paired with their nicknames. The next item (the
second occurance of string "Dr. Cat"
) is the string to be
matched, which was fetched from lvar ourString.
`CheckNick
a function name preceded by an
`
apostrophe is a pointer to the address for the
CheckNick
function.
In this case, the results are not negative or ambiguous: one of the
players does have the nickname to be matched: player #244
is Dr. Cat. .Table_match
would clear all the above data
from the stack, and return...
"Dr. Cat", #244
See also .std_table_match.
(Lib-Match)
[top]