TinyMUSH 3.3
TinyMUSH Server
|
Functions for user-defined iterations over lists. More...
#include "config.h"
#include "constants.h"
#include "typedefs.h"
#include "macros.h"
#include "externs.h"
#include "prototypes.h"
#include <stdbool.h>
#include <string.h>
Functions | |
void | perform_loop (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
backwards-compatible looping constructs: LOOP, PARSE More... | |
void | perform_iter (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
Looping constructs. More... | |
void | fun_ilev (char *buff, char **bufc, dbref player __attribute__((unused)), dbref caller __attribute__((unused)), dbref cause __attribute__((unused)), char *fargs[] __attribute__((unused)), int nfargs __attribute__((unused)), char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Obtain nested iter tokens (#!) More... | |
void | fun_inum (char *buff, char **bufc, dbref player __attribute__((unused)), dbref caller __attribute__((unused)), dbref cause __attribute__((unused)), char *fargs[], int nfargs __attribute__((unused)), char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Obtain nested iter tokens (#@) More... | |
void | fun_itext (char *buff, char **bufc, dbref player __attribute__((unused)), dbref caller __attribute__((unused)), dbref cause __attribute__((unused)), char *fargs[], int nfargs __attribute__((unused)), char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Obtain nested iter tokens (##) More... | |
void | fun_itext2 (char *buff, char **bufc, dbref player __attribute__((unused)), dbref caller __attribute__((unused)), dbref cause __attribute__((unused)), char *fargs[], int nfargs __attribute__((unused)), char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Two-list version of iter. More... | |
void | fun_ibreak (char *buff __attribute__((unused)), char **bufc __attribute__((unused)), dbref player __attribute__((unused)), dbref caller __attribute__((unused)), dbref cause __attribute__((unused)), char *fargs[], int nfargs __attribute__((unused)), char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Break out of an iter. More... | |
void | fun_fold (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
iteratively eval an attrib with a list of arguments and an optional base case. With no base case, the first list element is passed as %0 and the second is %1. The attrib is then evaluated with these args, the result is then used as %0 and the next arg is %1 and so it goes as there are elements left in the list. The optinal base case gives the user a nice starting point. More... | |
void | handle_filter (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
iteratively perform a function with a list of arguments and return the arg, if the function evaluates to TRUE using the arg. More... | |
void | fun_map (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
Iteratively evaluate an attribute with a list of arguments. More... | |
void | fun_mix (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
Like map, but operates on two lists or more lists simultaneously, passing the elements as %0, %1, %2, etc. More... | |
void | fun_step (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
A little like a fusion of iter() and mix(), it takes elements of a list X at a time and passes them into a single function as %0, %1, etc. step(<attribute>,<list>,<step size>,<delim>,<outdelim>) More... | |
void | fun_foreach (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[] __attribute__((unused)), int ncargs __attribute__((unused))) |
Like map(), but it operates on a string, rather than on a list, calling a user-defined function for each character in the string. No delimiter is inserted between the results. More... | |
void | fun_munge (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
Combines two lists in an arbitrary manner. More... | |
void | fun_while (char *buff, char **bufc, dbref player, dbref caller, dbref cause, char *fargs[], int nfargs, char *cargs[], int ncargs) |
Evaluate a list until a termination condition is met: while(EVAL_FN,CONDITION_FN,foo|flibble|baz|meep,1,|,-) where EVAL_FN is "[strlen(%0)]" and CONDITION_FN is "[strmatch(%0,baz)]" would result in '3-7-3' being returned. The termination condition is an EXACT not wild match. More... | |
Functions for user-defined iterations over lists.
void fun_fold | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
iteratively eval an attrib with a list of arguments and an optional base case. With no base case, the first list element is passed as %0 and the second is %1. The attrib is then evaluated with these args, the result is then used as %0 and the next arg is %1 and so it goes as there are elements left in the list. The optinal base case gives the user a nice starting point.
&REP_NUM object=[%0][repeat(%1,%1)] say fold(OBJECT/REP_NUM,1 2 3 4 5,->) You say "->122333444455555"
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
We need two to four arguments only
Two possibilities for the first arg: <obj>/<attr> and <attr>.
Evaluate it using the rest of the passed function args
may as well handle first case now
void fun_foreach | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Like map(), but it operates on a string, rather than on a list, calling a user-defined function for each character in the string. No delimiter is inserted between the results.
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Not used |
ncargs | Not used |
first letter in string is 0, not 1
Look for a start token.
Skip to the next character. Don't copy the start token.
We've found an end token. Skip over it. Note that it's possible to have a start and end token next to one another.
void fun_ibreak | ( | char *buff | __attribute__(unused), |
char **bufc | __attribute__(unused), | ||
dbref player | __attribute__(unused), | ||
dbref caller | __attribute__(unused), | ||
dbref cause | __attribute__(unused), | ||
char * | fargs[], | ||
int nfargs | __attribute__(unused), | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Break out of an iter.
buff | Not used |
bufc | Not used |
player | Not used |
caller | Not used |
cause | Not used |
fargs | Function arguments |
nfargs | Not used |
cargs | Not used |
ncargs | Not used |
void fun_ilev | ( | char * | buff, |
char ** | bufc, | ||
dbref player | __attribute__(unused), | ||
dbref caller | __attribute__(unused), | ||
dbref cause | __attribute__(unused), | ||
char *fargs[] | __attribute__(unused), | ||
int nfargs | __attribute__(unused), | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Obtain nested iter tokens (#!)
buff | Output buffer |
bufc | Output buffer tracker |
player | Not used |
caller | Not used |
cause | Not used |
fargs | Not used |
nfargs | Not used |
cargs | Not used |
ncargs | Not used |
void fun_inum | ( | char * | buff, |
char ** | bufc, | ||
dbref player | __attribute__(unused), | ||
dbref caller | __attribute__(unused), | ||
dbref cause | __attribute__(unused), | ||
char * | fargs[], | ||
int nfargs | __attribute__(unused), | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Obtain nested iter tokens (#@)
buff | Output buffer |
bufc | Output buffer tracker |
player | Not used |
caller | Not used |
cause | Not used |
fargs | Function arguments |
nfargs | Not used |
cargs | Not used |
ncargs | Not used |
void fun_itext | ( | char * | buff, |
char ** | bufc, | ||
dbref player | __attribute__(unused), | ||
dbref caller | __attribute__(unused), | ||
dbref cause | __attribute__(unused), | ||
char * | fargs[], | ||
int nfargs | __attribute__(unused), | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Obtain nested iter tokens (##)
buff | Output buffer |
bufc | Output buffer tracker |
player | Not used |
caller | Not used |
cause | Not used |
fargs | Function arguments |
nfargs | Not used |
cargs | Not used |
ncargs | Not used |
void fun_itext2 | ( | char * | buff, |
char ** | bufc, | ||
dbref player | __attribute__(unused), | ||
dbref caller | __attribute__(unused), | ||
dbref cause | __attribute__(unused), | ||
char * | fargs[], | ||
int nfargs | __attribute__(unused), | ||
char *cargs[] | __attribute__(unused), | ||
int ncargs | __attribute__(unused) | ||
) |
Two-list version of iter.
buff | Output buffer |
bufc | Output buffer tracker |
player | Not used |
caller | Not used |
cause | Not used |
fargs | Function arguments |
nfargs | Not used |
cargs | Not used |
ncargs | Not used |
void fun_map | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Iteratively evaluate an attribute with a list of arguments.
&DIV_TWO object=fdiv(%0,2) say map(1 2 3 4 5,object/div_two) You say "0.5 1 1.5 2 2.5" say map(object/div_two,1-2-3-4-5,-) You say "0.5-1-1.5-2-2.5"
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
If we don't have anything for a second arg, don't bother.
Two possibilities for the second arg: <obj>/<attr> and <attr>.
now process the list one element at a time
void fun_mix | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Like map, but operates on two lists or more lists simultaneously, passing the elements as %0, %1, %2, etc.
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
Check to see if we have an appropriate number of arguments. If there are more than three arguments, the last argument is ALWAYS assumed to be a delimiter.
Get the attribute, check the permissions.
process the lists, one element at a time.
void fun_munge | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Combines two lists in an arbitrary manner.
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Not used |
ncargs | Not used |
Find our object and attribute
Copy our lists and chop them up.
Call the u-function with the first list as %0. Pass the input separator as %1, which makes sorting, etc. easier.
Now that we have our result, put it back into array form. Search through list1 until we find the element position, then copy the corresponding element from list2.
void fun_step | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
A little like a fusion of iter() and mix(), it takes elements of a list X at a time and passes them into a single function as %0, %1, etc. step(<attribute>,<list>,<step size>,<delim>,<outdelim>)
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
Get attribute. Check permissions.
void fun_while | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Evaluate a list until a termination condition is met: while(EVAL_FN,CONDITION_FN,foo|flibble|baz|meep,1,|,-) where EVAL_FN is "[strlen(%0)]" and CONDITION_FN is "[strmatch(%0,baz)]" would result in '3-7-3' being returned. The termination condition is an EXACT not wild match.
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Not used |
ncargs | Not used |
If our third arg is null (empty list), don't bother.
Our first and second args can be <obj>/<attr> or just <attr>. Use them if we can access them, otherwise return an empty string.
Note that for user-defined attributes, atr_str() returns a pointer to a static, and that therefore we have to be careful about what we're doing.
If our evaluation and condition are the same, we can save ourselves some time later. There are two possibilities: we have the exact same obj/attr pair, or the attributes contain identical text.
Process the list one element at a time.
void handle_filter | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
iteratively perform a function with a list of arguments and return the arg, if the function evaluates to TRUE using the arg.
&IS_ODD object=mod(%0,2) say filter(object/is_odd,1 2 3 4 5) You say "1 3 5" say filter(object/is_odd,1-2-3-4-5,-) You say "1-3-5"
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
< 0 is filter(), 1 is filterbool()
Two possibilities for the first arg: <obj>/<attr> and <attr>.
Now iteratively eval the attrib with the argument list
void perform_iter | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Looping constructs.
whentrue() and whenfalse() work similarly to iter(). whentrue() loops as long as the expression evaluates to true. whenfalse() loops as long as the expression evaluates to false.
istrue() and isfalse() are inline filterbool() equivalents returning the elements of the list which are true or false, respectively.
iter2(), list2(), etc. are two-list versions of all of the above.
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
< 0 is iter(), 1 is list()
Enforce maximum nesting level.
Figure out what functionality we're getting.
The list argument is unevaluated. Go evaluate it.
Same thing for the second list arg, if we have it
If both lists are empty, we're done
we might nibble this
void perform_loop | ( | char * | buff, |
char ** | bufc, | ||
dbref | player, | ||
dbref | caller, | ||
dbref | cause, | ||
char * | fargs[], | ||
int | nfargs, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
backwards-compatible looping constructs: LOOP, PARSE
buff | Output buffer |
bufc | Output buffer tracker |
player | DBref of player |
caller | DBref of caller |
cause | DBref of cause |
fargs | Function arguments |
nfargs | Number of function arguments |
cargs | Command arguments |
ncargs | Number of command arguments |
< 0 is parse(), 1 is loop()