Navigation
Site
|
I'm a little terse and assume you kinda know
what you're doing and have skimmed the Guide For
Gods.
Much of this is also relevant to new
commands, and to other hacking of the code. I'll rename the
page one of these days, and give most of this information to
Javelin to put in the Guide.
Where to put new functions
Preferrably, in src/funlocal.c, as
any changes you make there are far less likely to break
future patches. However, anything that must access the
descriptors of connected players must go in
src/bsd.c. You can also add the functions to the
function table from there without messing with
src/function.c. See the comments in the file.
Arguments and returning values
Softcode Function implementation functions
take a lot of arguments. For that, and so various tools used
in building the mush can recognize them, use
FUNCTION to define the function. See the source
for the many examples, as well as the Guide For
Gods.
The arguments passed to the function when
it's called in softcode are in the args array,
and the number of arguments is in nargs. The
length of each corresponding element of args is
in arglens (arglens[0] ==
strlen(args[0])). buff and bp
are used to return a value from the function, using the
safe_XXX functions described below. All these
arguments are strings. There's others, the dbrefs of the
executor, enactor, and such.
Datatypes
There are 6 main data types in softcode:
Booleans, which are true/false values. Integers, which are
whole numbers. Unsigned integers, which are integers that
can't have a value less than 0. Numbers, which are
floating-point numbers. Integers can be used in place of
Numbers, but not the other way around. Dbrefs, like
#1234, and strings - everything else. Since all
arguments are passed to functions as strings, and they
return strings, there are routines available for converting
between string and native format and back.
For each datatype, there are a pair of
functions to convert a string to the C type, and the C type
to a string (Stored in a static buffer, so it will be
overwritten by the next call to the conversion
function). There are no conversions for strings, since
they're not needed, because strings are strings. There are
also functions for appending a datatype onto the function's
return buff. They all take three arguments - the
data, buff, and bp. There is also a
predicate function, which returns a true value if the string
argument represents the given data type.
| Datatype |
Predicate |
String -> C |
C ->String |
safe_XXX() |
Boolean (C int) |
is_boolean() |
parse_boolean() |
unparse_boolean() |
safe_boolean() |
Integer (C int) |
is_integer() |
parse_integer() |
unparse_integer() |
safe_integer() |
Unsigned Integer (C unsigned int) |
is_uinteger() |
parse_uinteger() |
unparse_uinteger() |
None |
Number (C NVAL [really double]) |
is_number() |
parse_number() |
unparse_number() |
safe_number() |
Dbref (C dbref) |
is_dbref() |
parse_dbref() |
unparse_dbref() |
safe_dbref() |
String (C char *) |
None |
None |
None |
safe_str()/safe_strl() |
- This table and notes are current for
1.7.5p5
- Single characters can be placed on the output
buffer with
safe_chr(chr, buff,
bp). This is a macro, so no side-effects
should be in its arguments!
- For datatypes without a safe_XXX() function,
safe_str(unparse_XXX(), buff, bp) can
be used.
- There's also a
safe_format(buff, bp,
"printf-style format", ...) function to
replace use of safe_str(tprintf(format,
...), buff, bp).
safe_strl(const char *str, size_t n,
buff, bp) will append n characters from str
to buff. str must be n or more characters
long.
|
Lists
A lot of functions take at least one
argument that's a list with a arbitrary seperator, usually
with a default of space. Here's some functions to make
manipulating those lists easier.
int delim_check(char *buff, char **bp, int
nargs, char *args[], int seperator_position, int
*seperator_var)
- This function will check for the presence of an
optional delimiter argument to the softcode function
(Based on the position given in the
seperator_position argument, with the first
argument 1, the second 2, and so on), and if it's valid,
set seperator_var to the right value, and
return 1. If the argument isn't given, the variable is set
to space, and it still returns 1. If it's an invalid
argument - like one that's not just one character, an
error message will be appended to buff, and it
will return 0. It's commonly used as follows:
if (!delim_check(buff, bp, nargs, args, 3, &some_char_variable))
return;
int list2arr(char *array[], int max_size, char
*list, char sep)
- This function will break list up into
sep-delimited chunks, placing the first
max_size entries into array, which
must be big enough to hold max_size character
pointers. list is destructively
modified. array's elements end up pointing into
it, so the variables share the same memory. It returns the
number of items stored in array.
char *trim_space_sep(char *str, char
sep)
- If sep is a space, this function trims
trailing spaces from str, and returns a pointer
to the first non-space character in
str. Otherwise it returns str.
char *split_token(char **sp, char
sep)
- This function advances *sp to the next
occurance of sep, sets it to
nul,
and returns a pointer to the start of
*sp. Basically, it returns the next item from
the list, and advances the list beyond that item. It
returns NULL when the list is empty.
|