1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
/*
* functions.h -- header file for functions.c
*
* Copyright 1995, 2002 EPIC Software Labs
* See the COPYRIGHT file for copyright information
*/
#ifndef __functions_h__
#define __functions_h__
/*
* These are defined to make the construction of the built-in functions
* easier and less prone to bugs and unexpected behaviors. As long as
* you consistently use these macros to do the dirty work for you, you
* will never have to do bounds checking as the macros do that for you. >;-)
*
* Yes, i realize it makes the code slightly less efficient, but i feel that
* the cost is minimal compared to how much time i have spent over the last
* year debugging these functions and the fact i wont have to again. ;-)
*/
#define EMPTY empty_string
#define EMPTY_STRING malloc_strdup(EMPTY)
#define RETURN_EMPTY return EMPTY_STRING
#define RETURN_IF_EMPTY(x) if (empty( (x) )) RETURN_EMPTY
#define GET_INT_ARG(x, y) { \
const char *xxx; \
RETURN_IF_EMPTY((y)); \
xxx = next_func_arg((y), &(y)); \
if (!xxx) \
xxx = empty_string; \
x = strtoimax(xxx, NULL, 0); \
}
#define GET_FLOAT_ARG(x, y) { \
const char *xxx; \
RETURN_IF_EMPTY((y)); \
xxx = next_func_arg((y), &(y)); \
if (!xxx) \
xxx = empty_string; \
x = atof(xxx); \
}
#define GET_FUNC_ARG(x, y) { \
RETURN_IF_EMPTY((y)); \
x = next_func_arg((y), &(y)); \
}
#define GET_DWORD_ARG(x, y) { \
RETURN_IF_EMPTY((y)); \
x = new_next_arg((y), &(y)); \
}
#define GET_UWORD_ARG(x, y) { \
RETURN_IF_EMPTY((y)); \
x = next_arg((y), &(y)); \
}
#define RETURN_MSTR(x) return ((x) ? (x) : EMPTY_STRING)
#define RETURN_STR(x) return malloc_strdup((x) ? (x) : EMPTY)
#define RETURN_FSTR(x) return malloc_strdup( x ) /* Only fixed char arrays! */
#define RETURN_INT(x) return malloc_strdup(intmaxtoa((x)))
#define RETURN_FLOAT(x) return malloc_sprintf(NULL, "%.50g", (double) (x))
#define RETURN_FLOAT2(x) return malloc_sprintf(NULL, "%.2f", (double) (x))
/*
* XXXX REALLY REALLY REALLY REALLY REALLY REALLY REALLY IMPORTANT! XXXX
*
* Don't ever Ever EVER pass a function call to the RETURN_* macros.
* They _WILL_ evaluate the term twice, and for some function calls,
* that can result in a memory leak, or worse.
*/
#ifdef need_static_functions
#define BUILT_IN_FUNCTION(x, y) static char * x (char * y)
#else
#define BUILT_IN_FUNCTION(x, y) char * x (char * y)
#endif
struct kwargs {
const char * kwarg;
int type;
void * data;
int required;
};
#define KWARG_TYPE_SENTINAL 0
#define KWARG_TYPE_STRING 1
#define KWARG_TYPE_INTEGER 2
#define KWARG_TYPE_NUMBER 3
#define KWARG_TYPE_BOOL 4
int parse_kwargs (struct kwargs *kwargs, const char *input);
/*
* Examples for using the above:
* char *name1 = NULL, *flag = NULL;
* struct kwargs kwargs[] = {
* { "name1", KWARG_TYPE_STRING, &name1, 1 },
* { "flag", KWARG_TYPE_STRING, &flag, 1 },
* { NULL, KWARG_TYPE_SENTINAL, NULL, 0 }
* };
*
* if (input && *input == '{')
* parse_kwargs(kwargs, input);
*
* and
* @func({"name1": "value1", "flag": "booya"})
*/
#endif
|