/* parse.h - parser declarations and macros * Written by T. Alexander Popiel, 13 May 1995 * Last modified by T. Alexander Popiel, 26 May 1995 * * Copyright (c) 1995 by T. Alexander Popiel * See copyrite.h for details. */ #ifndef _PARSE_H_ #define _PARSE_H_ #include "copyrite.h" #include "config.h" #ifdef I_STDLIB #include <stdlib.h> #endif #ifdef I_LIMITS #include <limits.h> #else #ifdef I_VALUES #include <values.h> #endif #endif #include <math.h> #include "dbdefs.h" #include "confmagic.h" /* This is the type to be used for numbers which may be non-integral. */ #ifdef FLOATING_POINTS #define NVAL double #define HUGE_NVAL HUGE_DOUBLE #else #define NVAL int #define HUGE_NVAL HUGE_INT #endif /* These are some common error messages. */ extern char e_int[]; /* #-1 ARGUMENT MUST BE INTEGER */ extern char e_ints[]; /* #-1 ARGUMENTS MUST BE INTEGERS */ #ifdef FLOATING_POINTS extern char e_num[]; /* #-1 ARGUMENT MUST BE NUMBER */ extern char e_nums[]; /* #-1 ARGUMENTS MUST BE NUMBERS */ #else #define e_num e_int /* #-1 ARGUMENT MUST BE INTEGER */ #define e_nums e_ints /* #-1 ARGUMENTS MUST BE INTEGERS */ #endif /* This type is used by process_expression(). In all but parse.c, * this should be left as an incompletely-specified type, making it * impossible to declare anything but pointers to it. */ typedef struct pe_info PE_Info; /* The following routines all take strings as arguments, and return * data of the appropriate types. */ int parse_boolean _((char const *str)); #define parse_integer(str) atoi(str) #ifdef FLOATING_POINTS #define parse_number(str) atof(str) #else #define parse_number(str) atoi(str) #endif /* The following routines all take varoius arguments, and return * string representations of same. The string representations * are stored in static buffers, so the next call to each function * will destroy any old string that was there. */ #define unparse_boolean(x) ((x) ? "1" : "0") char *unparse_dbref _((dbref num)); char *unparse_integer _((int num)); char *unparse_number _((NVAL num)); /* The following routines all take strings as arguments, and return * true iff the string is a valid representation of the appropriate type. */ int is_dbref _((char const *str)); int is_integer _((char const *str)); int is_boolean _((char const *str)); /* All function declarations follow the format: */ #ifdef CAN_NEWSTYLE #define FUNCTION(fun_name) \ /* ARGSUSED */ /* try to keep lint happy */ \ void fun_name _((char *buff, char **bp, int nargs, char *args[], \ dbref executor, dbref caller, dbref enactor, \ char const *called_as, PE_Info *pe_info)); \ void fun_name(char *buff, char **bp, int nargs, char *args[], \ dbref executor, dbref caller, dbref enactor, \ char const *called_as, PE_Info *pe_info) #else #define FUNCTION(fun_name) \ /* ARGSUSED */ /* try to make lint happy */ \ void fun_name _((char *buff, char **bp, int nargs, char *args[], \ dbref executor, dbref caller, dbref enactor, \ char const *called_as, PE_Info *pe_info)); \ void fun_name(buff, bp, nargs, args, executor, caller, enactor, \ called_as, pe_info) \ char *buff; \ char **bp; \ int nargs; \ char *args[]; \ dbref executor; \ dbref caller; \ dbref enactor; \ char const *called_as; \ PE_Info *pe_info; #endif /* All results are returned in buff, at the point *bp. *bp is likely * not equal to buff, so make no assumptions about writing at the * start of the buffer. *bp must be updated to point at the next * place to be filled (ala safe_str() and safe_chr()). Be very * careful about not overflowing buff; use of safe_str() and safe_chr() * for all writes into buff is highly recommended. * * nargs is the count of the number of arguments passed to the function, * and args is an array of pointers to them. args will have at least * nargs elements, or 10 elements, whichever is greater. The first ten * elements are initialized to NULL for ease of porting functions from * the old style, but relying on such is considered bad form. * The argument strings are stored in BUFFER_LEN buffers, but reliance * on that size is also considered bad form. The argument strings may * be modified, but modifying the pointers to the argument strings will * cause crashes. * * executor corresponds to %!, the object invoking the function. * caller corresponds to %@, the last object to do a U() or similar. * enactor corresponds to %#, the object that started the whole mess. * Note that fun_ufun() and similar must swap around these parameters * in calling process_expression(); no checks are made in the parser * itself to maintain these values. * * called_as contains a pointer to the name of the function called * (taken from the function table). This may be used to distinguish * multiple functions which use the same C function for implementation. * * pe_info holds context information used by the parser. It should * be passed untouched to process_expression(), if it is called. * pe_info should be treated as a black box; its structure and contents * may change without notice. */ /* process_expression() evaluates expressions. What a concept. */ void process_expression _((char *buff, char **bp, char const **str, dbref executor, dbref caller, dbref enactor, int eflags, int tflags, PE_Info * pe_info)); /* buff is a pointer to a BUFFER_LEN string to contain the expression * result. *bp is the point in buff at which the result should be written. * *bp will be updated to point one past the result of the expression, * and the result will _NOT_ be null-terminated. * For top-level calls to process_expression(), *bp should probably equal * buff. For calls to process_expression() inside function implementations, * buff and bp should probably be the values passed into the implementation. * * *str is a pointer to a string containing the expression to evaluate. * *str will be updated to point at the terminator which caused return * from process_expression(). The string pointed to by *str will not * be modified. * * executor, caller, and enactor represent %!, %@, and %#, respectively. * No validity checking of any sort is done on these parameters, so please * be careful with them. * * eflags consists of one or more of the following evaluation flags: */ #define PE_NOTHING 0 #define PE_COMPRESS_SPACES 0x00000001 #define PE_STRIP_BRACES 0x00000002 #define PE_EVALUATE 0x00000010 #define PE_FUNCTION_CHECK 0x00000020 #define PE_FUNCTION_MANDATORY 0x00000040 #define PE_LITERAL 0x00000100 #define PE_DEFAULT (PE_COMPRESS_SPACES | PE_STRIP_BRACES | \ PE_EVALUATE | PE_FUNCTION_CHECK) /* PE_COMPRESS_SPACES strips leading and trailing spaces, and reduces sets * of internal spaces to one space. * * PE_STRIP_BRACES strips off top-level braces. * * PE_EVALUATE allows %-substitutions, []-evaluation, function evaluation, * and \-stripping. * * PE_FUNCTION_CHECK allows function evaluation. Note that both PE_EVALUATE * and PE_FUNCTION_CHECK must be active for function evaluation to occur. * * PE_FUNCTION_MANDATORY causes an error to be reported if a function call * is attempted for a non-existant function. Otherwise, the function call * is not evaluated, but rather treated as normal text. * * PE_LITERAL prevents { and [ from being recognized and causing recursion. * * PE_DEFAULT is the most commonly used set of flags, normally sufficient * for calls to process_expression(). * * * tflags consists of one or more of the following termination flags: */ #define PT_NOTHING 0 #define PT_BRACE 0x00000001 #define PT_BRACKET 0x00000002 #define PT_PAREN 0x00000004 #define PT_COMMA 0x00000008 #define PT_SEMI 0x00000010 #define PT_EQUALS 0x00000020 #define PT_SPACE 0x00000040 /* These represent '\0', '}', ']', ')', ',', ';', '=', and ' ', respectively. * If the character corresponding to a set flag is encountered, then * process_expression() will exit, with *str pointing at the terminating * charater. '\0' is always a terminating character. * * PT_DEFAULT, below, is provided as syntactic sugar. */ #define PT_DEFAULT PT_NOTHING /* pe_info is a pointer to a structure of internal state information * for process_expression(). Top-level calls to process_expression() * should pass a NULL as pe_info. Calls to process_expression() from * function implementations should pass their pe_info as pe_info. * In no case should any other pe_info be passed to process_expression(). */ /* Miscellany */ void do_userfn _((char *buff, char **bp, dbref obj, ATTR *attrib, int nargs, char **args, dbref executor, dbref caller, dbref enactor, PE_Info * pe_info)); void init_process_expression _((void)); #endif /* !_PARSE_H_ */