/* functions.h - declarations for functions & function processing */ /* $Id: functions.h,v 1.66 2003/02/24 18:05:23 rmg Exp $ */ #include "copyright.h" #ifndef __FUNCTIONS_H #define __FUNCTIONS_H /* --------------------------------------------------------------------------- * Type definitions. */ #define MAX_NFARGS 30 typedef struct fun { const char *name; /* Function name */ void (*fun)(); /* Handler */ int nargs; /* Number of args needed or expected */ unsigned int flags; /* Function flags */ int perms; /* Access to function */ EXTFUNCS *xperms; /* Extended access to function */ } FUN; typedef struct ufun { char *name; /* Function name */ dbref obj; /* Object ID */ int atr; /* Attribute ID */ unsigned int flags; /* Function flags */ int perms; /* Access to function */ struct ufun *next; /* Next ufun in chain */ } UFUN; typedef struct delim { size_t len; char str[MAX_DELIM_LEN]; } Delim; typedef struct var_entry VARENT; struct var_entry { char *text; /* variable text */ }; typedef struct component_def COMPONENT; struct component_def { int (*typer_func)(); /* type-checking handler */ char *def_val; /* default value */ }; typedef struct structure_def STRUCTDEF; struct structure_def { char *s_name; /* name of the structure */ char **c_names; /* array of component names */ COMPONENT **c_array; /* array of pointers to components */ int c_count; /* number of components */ char delim; /* output delimiter when unloading */ int need_typecheck; /* any components without types of any? */ int n_instances; /* number of instances out there */ char *names_base; /* pointer for later freeing */ char *defs_base; /* pointer for later freeing */ }; typedef struct instance_def INSTANCE; struct instance_def { STRUCTDEF *datatype; /* pointer to structure data type def */ }; typedef struct data_def STRUCTDATA; struct data_def { char *text; }; typedef struct object_stack OBJSTACK; struct object_stack { char *data; OBJSTACK *next; }; #ifdef FLOATING_POINTS #ifndef linux /* linux defines atof as a macro */ double atof(); #endif /* ! linux */ #define aton atof typedef double NVAL; #else #define aton atoi typedef int NVAL; #endif /* FLOATING_POINTS */ /* --------------------------------------------------------------------------- * Constants used in delimiter macros. */ #define DELIM_EVAL 0x001 /* Must eval delimiter. */ #define DELIM_NULL 0x002 /* Null delimiter okay. */ #define DELIM_CRLF 0x004 /* '%r' delimiter okay. */ #define DELIM_STRING 0x008 /* Multi-character delimiter okay. */ /* --------------------------------------------------------------------------- * Function declarations. */ extern const Delim SPACE_DELIM; extern char *FDECL(trim_space_sep, (char *, const Delim *)); extern char *FDECL(next_token, (char *, const Delim *)); extern char *FDECL(split_token, (char **, const Delim *)); extern char *FDECL(next_token_ansi, (char *, const Delim *, int *)); extern int FDECL(countwords, (char *, const Delim *)); extern int FDECL(list2arr, (char ***, int, char *, const Delim *)); extern void FDECL(arr2list, (char **, int, char *, char **, const Delim *)); extern int FDECL(list2ansi, (int *, int *, int, char *, const Delim *)); extern INLINE void FDECL(do_reverse, (char *, char *)); extern int FDECL(fn_range_check, (const char *, int, int, int, char *, char **)); extern int FDECL(delim_check, ( char *, char **, dbref, dbref, dbref, char **, int, char **, int, int, Delim *, int )); /* --------------------------------------------------------------------------- * Function prototype macro. */ #define FUNCTION_ARGLIST buff, bufc, player, caller, cause, fargs, nfargs, cargs, ncargs #define FUNCTION(x) \ void x( FUNCTION_ARGLIST ) \ char *buff, **bufc; \ dbref player, caller, cause; \ char *fargs[], *cargs[]; \ int nfargs, ncargs; /* --------------------------------------------------------------------------- * Delimiter macros for functions that take an optional delimiter character. */ /* Minimum work needed to copy a delimiter. Assumes that the "str" member * of the Delim struct is last. */ #define Delim_Copy(sep_dest, sep_src) \ memcpy((sep_dest), (sep_src), \ sizeof(Delim) - MAX_DELIM_LEN + 1 + (sep_src)->len) /* Separator checking "helper" macros. * VaChk_Sep(sep_ptr, sep_len, arg_n, flags): Use arg_n as separator. * VaChk_InSep(arg_number, flags): Use arg_number as input sep. * VaChk_DefaultOut(arg_number): If nfargs less than arg_number, * use the input separator. DO NOT PUT A SEMI-COLON AFTER THIS MACRO. * VaChk_OutSep(arg_number, flags): Use arg_number as output sep. */ #define VaChk_Sep(xsep, xargnum, xflags) \ if (!delim_check( FUNCTION_ARGLIST, xargnum, xsep, xflags)) \ return #define VaChk_InSep(xargnum, xflags) \ VaChk_Sep(&isep, xargnum, (xflags)|DELIM_STRING) #define VaChk_DefaultOut(xargnum) \ if (nfargs < xargnum) { \ Delim_Copy(&osep, &isep); \ } else #define VaChk_OutSep(xargnum, xflags) \ VaChk_Sep(&osep, xargnum, (xflags)|DELIM_STRING|DELIM_NULL|DELIM_CRLF) /* * VaChk_Range(min_args, max_args): Functions which take * between min_args and max_args. Don't check for delimiters. * * VaChk_Only_InPure(max_args): Functions which take max_args - 1 * args or, with a delimiter, max_args args. No special stuff. * * VaChk_Only_In(max_args): Functions which take max_args - 1 args * or, with a delimiter, max_args args. * * VaChk_Only_Out(max_args): Functions which take max_args - 1 args * or, with a delimiter, max_args args. The one delimiter is an output delim. * * VaChk_InPure(max_args): Functions which take max_args - 1 * args or, with a delimiter, max_args args. No special stuff. * * VaChk_In(min_args, max_args): Functions which take * between min_args and max_args, with max_args as a delimiter. * * VaChk_Out(min_args, max_args): Functions which take * between min_args and max_args, with max_args as an output delimiter. * * VaChk_Only_In_Out(max_args): Functions which take at least * max_args - 2, with max_args - 1 as an input delimiter, and max_args as * an output delimiter. * * VaChk_In_Out(min_args, max_args): Functions which take at * least min_args, with max_args - 1 as an input delimiter, and max_args * as an output delimiter. * * VaChk_InEval_OutEval(min_args, max_args): Functions which * take at least min_args, with max_args - 1 as an input delimiter that * must be evaluated, and max_args as an output delimiter which must * be evaluated. */ #define VaChk_Range(xminargs,xnargs) \ if (!fn_range_check(((FUN *)fargs[-1])->name, nfargs, xminargs, xnargs, \ buff, bufc)) \ return #define VaChk_Only_InPure(xnargs) \ VaChk_Range(xnargs-1, xnargs); \ if (!delim_check( FUNCTION_ARGLIST, xnargs, &isep, 0)) \ return #define VaChk_Only_In(xnargs) \ VaChk_Range(xnargs-1, xnargs); \ VaChk_InSep(xnargs, 0) #define VaChk_Only_Out(xnargs) \ VaChk_Range(xnargs-1, xnargs); \ VaChk_OutSep(xnargs, 0) #define VaChk_InPure(xminargs, xnargs) \ VaChk_Range(xminargs, xnargs); \ if (!delim_check( FUNCTION_ARGLIST, xnargs, &isep, 0)) \ return #define VaChk_In(xminargs, xnargs) \ VaChk_Range(xminargs, xnargs); \ VaChk_InSep(xnargs, 0) #define VaChk_Out(xminargs, xnargs) \ VaChk_Range(xminargs, xnargs); \ VaChk_OutSep(xnargs, 0) #define VaChk_Only_In_Out(xnargs) \ VaChk_Range(xnargs-2, xnargs); \ VaChk_InSep(xnargs-1, 0); \ VaChk_DefaultOut(xnargs) { \ VaChk_OutSep(xnargs, 0); \ } #define VaChk_In_Out(xminargs, xnargs) \ VaChk_Range(xminargs, xnargs); \ VaChk_InSep(xnargs-1, 0); \ VaChk_DefaultOut(xnargs) { \ VaChk_OutSep(xnargs, 0); \ } #define VaChk_InEval_OutEval(xminargs, xnargs) \ VaChk_Range(xminargs, xnargs); \ VaChk_InSep(xnargs-1, DELIM_EVAL); \ VaChk_OutSep(xnargs, DELIM_EVAL) /* --------------------------------------------------------------------------- * Miscellaneous macros. */ /* Get function flags. Note that Is_Func() and Func_Mask() are identical; * they are given specific names for code clarity. */ #define Func_Flags(x) (((FUN *)(x)[-1])->flags) #define Is_Func(x) (((FUN *)fargs[-1])->flags & (x)) #define Func_Mask(x) (((FUN *)fargs[-1])->flags & (x)) /* Check access to built-in function. */ #define Check_Func_Access(p,f) \ (check_access(p,(f)->perms) && \ (!((f)->xperms) || check_mod_access(p,(f)->xperms))) /* Trim spaces. */ #define Eat_Spaces(x) trim_space_sep((x), &SPACE_DELIM) /* Special handling of separators. */ #define print_sep(s,b,p) \ if ((s)->len == 1) { \ if ((s)->str[0] == '\r') { \ safe_crlf((b),(p)); \ } else if ((s)->str[0] != '\0') { \ safe_chr((s)->str[0],(b),(p)); \ } \ } else { \ safe_known_str((s)->str, (s)->len, (b), (p)); \ } /* Macro for finding an <attr> or <obj>/<attr> */ #define Parse_Uattr(p,s,t,n,a) \ if (parse_attrib((p), (s), &(t), &(n), 0)) { \ if (((n) == NOTHING) || !(Good_obj(t))) \ (a) = NULL; \ else \ (a) = atr_num(n); \ } else { \ (t) = (p); \ (a) = atr_str(s); \ } /* Macro for obtaining an attrib. */ #define Get_Uattr(p,t,a,b,o,f,l) \ if (!(a)) { \ return; \ } \ (b) = atr_pget(t, (a)->number, &(o), &(f), &(l)); \ if (!*(b) || !(See_attr((p), (t), (a), (o), (f)))) { \ free_lbuf(b); \ return; \ } /* Macro for writing a certain amount of padding into a buffer. * l is the number of characters left to write. * m is a throwaway integer for holding the maximum. * c is the separator character to use. */ #define print_padding(l,m,c) \ if ((l) > 0) { \ (m) = LBUF_SIZE - 1 - (*bufc - buff); \ (l) = ((l) > (m)) ? (m) : (l); \ memset(*bufc, (c), (l)); \ *bufc += (l); \ **bufc = '\0'; \ } /* Handling CPU time checking. */ /* * CPU time "clock()" compatibility notes: * * Linux clock() doesn't necessarily start at 0. * BSD clock() does appear to always start at 0. * * Linux sets CLOCKS_PER_SEC to 1000000, citing POSIX, so its clock() * will wrap around from (32-bit) INT_MAX to INT_MIN every 72 cpu-minutes * or so. The actual clock resolution is low enough that, for example, * it probably never returns odd numbers. * * BSD sets CLOCKS_PER_SEC to 100, so theoretically I could hose a cpu * for 250 days and see what it does when it hits INT_MAX. Any bets? Any * possible reason to care? * * NetBSD clock() can occasionally decrease as the scheduler's estimate of * how much cpu the mush will use during the current timeslice is revised, * so we can't use subtraction. * * BSD clock() returns -1 if there is an error. */ /* * CPU time logic notes: * * B = mudstate.cputime_base * L = mudstate.cputime_base + mudconf.func_cpu_lim * N = mudstate.cputime_now * * Assuming B != -1 and N != -1 to catch errors on BSD, the possible * combinations of these values are as follows (note >> means "much * greater than", not right shift): * * 1. B < L normal -- limit should be checked, and is not wrapped yet * 2. B == L disabled -- limit should not be checked * 3. B > L strange -- probably misconfigured * 4. B >> L wrapped -- limit should be checked, and note L wrapped * * 1. normal: * 1a. N << B -- too much, N wrapped * 1b. N < B -- fine, NetBSD counted backwards * 1c. N >= B, N <= L -- fine * 1d. N > L -- too much * * 2. disabled: * 2a. always -- fine, not checking * * 3. strange: * 3a. always -- fine, I guess we shouldn't check * * 4. wrapped: * 4a. N <= L -- fine, N wrapped but not over limit yet * 4b. N > L, N << B -- too much, N wrapped * 4c. N < B -- fine, NetBSD counted backwards * 4d. N >= B -- fine * * Note that 1a, 1d, and 4b are the cases where we can be certain that * too much cpu has been used. The code below only checks for 1d. The * other two are corner cases that require some distinction between * "x > y" and "x >> y". */ #define Too_Much_CPU() \ ((mudstate.cputime_now = clock()), \ ((mudstate.cputime_now > mudstate.cputime_base + mudconf.func_cpu_lim) && \ (mudstate.cputime_base + mudconf.func_cpu_lim > mudstate.cputime_base) && \ (mudstate.cputime_base != -1) && \ (mudstate.cputime_now != -1))) /* --------------------------------------------------------------------------- * Function-specific flags used in the function table. */ /* from handle_sets (setunion, setdiff, setinter, lunion, ldiff, linter): */ #define SET_OPER 0x0f /* mask to select set operation bits */ #define SET_UNION 0 #define SET_INTERSECT 1 #define SET_DIFF 2 #define SET_TYPE 0x10 /* set type is given, don't autodetect */ /* from process_tables (tables, rtables, ctables): */ /* from perform_border (border, rborder, cborder): */ #define JUST_TYPE 0x0f /* mask to select justification bits */ #define JUST_LEFT 0 #define JUST_RIGHT 1 #define JUST_CENTER 2 /* from handle_logic (and, or, andbool, orbool, land, lor, landbool, lorbool, * cand, cor, candbool, corbool, xor, xorbool): */ /* from handle_flaglists (andflags, orflags): */ /* from handle_filter (filter, filterbool): */ #define LOGIC_OPER 0x0f /* mask to select boolean operation bits */ #define LOGIC_AND 0 #define LOGIC_OR 1 #define LOGIC_XOR 2 #define LOGIC_BOOL 0x10 /* interpret operands as boolean, not int */ #define LOGIC_LIST 0x40 /* operands come in a list, not separately */ /* from handle_vectors (vadd, vsub, vmul, vdot): */ #define VEC_OPER 0x0f /* mask to select vector operation bits */ #define VEC_ADD 0 #define VEC_SUB 1 #define VEC_MUL 2 #define VEC_DOT 3 /* #define VEC_CROSS 4 -- not implemented */ /* from handle_vector (vmag, vunit): */ #define VEC_MAG 5 #define VEC_UNIT 6 /* from perform_loop (loop, parse): */ /* from perform_iter (list, iter, whentrue, whenfalse, istrue, isfalse): */ #define BOOL_COND_TYPE 0x0f /* mask to select exit-condition bits */ #define BOOL_COND_NONE 1 /* loop until end of list */ #define BOOL_COND_FALSE 2 /* loop until true */ #define BOOL_COND_TRUE 3 /* loop until false */ #define FILT_COND_TYPE 0x0f0 /* mask to select filter bits */ #define FILT_COND_NONE 0x010 /* show all results */ #define FILT_COND_FALSE 0x020 /* show only false results */ #define FILT_COND_TRUE 0x030 /* show only true results */ #define LOOP_NOTIFY 0x100 /* send loop results directly to enactor */ /* from handle_okpres (hears, moves, knows): */ #define PRESFN_OPER 0x0f /* Mask to select bits */ #define PRESFN_HEARS 0x01 /* Detect hearing */ #define PRESFN_MOVES 0x02 /* Detect movement */ #define PRESFN_KNOWS 0x04 /* Detect knows */ /* from perform_get (get, get_eval, xget, eval(a,b)): */ #define GET_EVAL 0x01 /* evaluate the attribute */ #define GET_XARGS 0x02 /* obj and attr are two separate args */ /* from handle_pop (pop, peek, toss): */ #define POP_PEEK 0x01 /* don't remove item from stack */ #define POP_TOSS 0x02 /* don't display item from stack */ /* from perform_regedit (regedit, regediti, regeditall, regeditalli): */ /* from perform_regparse (regparse, regparsei): */ /* from perform_regrab (regrab, regrabi, regraball, regraballi): */ /* from perform_regmatch (regmatch, regmatchi): */ /* from perform_grep (grep, grepi, wildgrep, regrep, regrepi): */ #define REG_CASELESS 0x01 /* XXX must equal PCRE_CASELESS */ #define REG_MATCH_ALL 0x02 /* operate on all matches in a list */ #define REG_TYPE 0x0c /* mask to select grep type bits */ #define GREP_EXACT 0 #define GREP_WILD 4 #define GREP_REGEXP 8 /* from handle_trig (sin, cos, tan, asin, acos, atan, sind, cosd, tand, * asind, acosd, atand): */ #define TRIG_OPER 0x0f /* mask to select trig function bits */ #define TRIG_CO 0x01 /* co-function, like cos as opposed to sin */ #define TRIG_TAN 0x02 /* tan-function, like cot as opposed to cos */ #define TRIG_ARC 0x04 /* arc-function, like asin as opposed to sin */ /* #define TRIG_REC 0x08 -- reciprocal, like sec as opposed to sin */ #define TRIG_DEG 0x10 /* angles are in degrees, not radians */ /* from handle_pronoun (obj, poss, subj, aposs): */ #define PRONOUN_OBJ 0 #define PRONOUN_POSS 1 #define PRONOUN_SUBJ 2 #define PRONOUN_APOSS 3 /* Miscellaneous */ #define LATTR_COUNT 0x01 /* nattr: just return attribute count */ #define LOCFN_WHERE 0x01 /* loc: where() vs. loc() */ #define NAMEFN_FULLNAME 0x01 /* name: fullname() vs. name() */ #define CHECK_PARENTS 0x01 /* hasattrp: recurse up the parent chain */ #define U_LOCAL 0x01 /* ulocal: preserve global registers */ #define TIMESTAMP_MOD 0x01 /* timestamp: lastmod() vs. lastaccess() */ #define CONNINFO_IDLE 0x01 /* conninfo: idle() vs. conn() */ #endif /* __FUNCTIONS_H */