#ifndef HONEYSUCKLE_H #define HONEYSUCKLE_H #include #include #include #include #include "va_nargs.h" /* type constants */ typedef enum { HS_BOOL, HS_INT, HS_NUM, HS_STR, HS_TBL, HS_FUNC, HS_CFUNC, HS_USER, HS_LIGHT, HS_NIL, HS_ANY, } hs_type; const char* hs_type_to_string(hs_type type); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * hs_parse_args and hs_parse_overloaded * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ struct hs_arg { hs_type type; union { bool *boolean; lua_Integer *integer; lua_Number *number; char **string; int *stack_index; lua_CFunction *function; void **userdata; } ptr; }; #define hs_bool(x) { .type=HS_BOOL, .ptr.boolean = &(x) } #define hs_int(x) { .type=HS_INT, .ptr.integer = &(x) } #define hs_num(x) { .type=HS_NUM, .ptr.number = &(x) } #define hs_str(x) { .type=HS_STR, .ptr.string = &(x) } #define hs_tbl(x) { .type=HS_TBL, .ptr.stack_index = &(x) } #define hs_func(x) { .type=HS_FUNC, .ptr.stack_index = &(x) } #define hs_cfunc(x) { .type=HS_CFUNC, .ptr.function = &(x) } #define hs_user(x) { .type=HS_USER, .ptr.userdata = &(x) } #define hs_light(x) { .type=HS_LIGHT, .ptr.userdata = &(x) } #define hs_nil(x) { .type=HS_NIL, .ptr.stack_index = &(x) } #define hs_any(x) { .type=HS_ANY, .ptr.stack_index = &(x) } void hs_parse_args_(lua_State *L, int n_args, struct hs_arg *arguments); #define hs_parse_args(L, ...) \ hs_parse_args_(L, \ VA_NARGS(__VA_ARGS__)/2, \ (struct hs_arg[]) { __VA_ARGS__ }) #define hs_overload(...) VA_NARGS(__VA_ARGS__)/2, (struct hs_arg[]) { __VA_ARGS__ } int hs_parse_overloaded_(lua_State *L, ...); #define hs_parse_overloaded(L, ...) \ hs_parse_overloaded_(L, __VA_ARGS__, -1) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * hs_create_table * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ typedef union { bool boolean; lua_Integer integer; lua_Number number; char *string; int stack_index; lua_CFunction function; void *userdata; } hs_value; struct hs_tbl_entry { hs_type key_type; hs_value key; hs_type value_type; hs_value value; }; #define hs_bool_bool(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_bool_int(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_INT, .value.integer=v } #define hs_bool_num(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_NUM, .value.number=v } #define hs_bool_str(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_STR, .value.string=v } #define hs_bool_tbl(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_bool_func(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_bool_cfunc(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_bool_user(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_bool_light(k, v) \ { .key_type=HS_BOOL, .key.boolean=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_int_bool(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_int_int(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_INT, .value.integer=v } #define hs_int_num(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_NUM, .value.number=v } #define hs_int_str(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_STR, .value.string=v } #define hs_int_tbl(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_int_func(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_int_cfunc(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_int_user(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_int_light(k, v) \ { .key_type=HS_INT, .key.integer=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_num_bool(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_num_int(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_INT, .value.integer=v } #define hs_num_num(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_NUM, .value.number=v } #define hs_num_str(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_STR, .value.string=v } #define hs_num_tbl(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_num_func(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_num_cfunc(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_num_user(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_num_light(k, v) \ { .key_type=HS_NUM, .key.number=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_str_bool(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_str_int(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_INT, .value.integer=v } #define hs_str_num(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_NUM, .value.number=v } #define hs_str_str(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_STR, .value.string=v } #define hs_str_tbl(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_str_func(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_str_cfunc(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_str_user(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_str_light(k, v) \ { .key_type=HS_STR, .key.string=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_tbl_bool(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_tbl_int(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_INT, .value.integer=v } #define hs_tbl_num(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_NUM, .value.number=v } #define hs_tbl_str(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_STR, .value.string=v } #define hs_tbl_tbl(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_tbl_func(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_tbl_cfunc(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_tbl_user(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_tbl_light(k, v) \ { .key_type=HS_TBL, .key.stack_index=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_func_bool(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_func_int(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_INT, .value.integer=v } #define hs_func_num(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_NUM, .value.number=v } #define hs_func_str(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_STR, .value.string=v } #define hs_func_tbl(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_func_func(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_func_cfunc(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_func_user(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_func_light(k, v) \ { .key_type=HS_FUNC, .key.stack_index=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_cfunc_bool(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_cfunc_int(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_INT, .value.integer=v } #define hs_cfunc_num(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_NUM, .value.number=v } #define hs_cfunc_str(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_STR, .value.string=v } #define hs_cfunc_tbl(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_cfunc_func(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_cfunc_cfunc(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_cfunc_user(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_cfunc_light(k, v) \ { .key_type=HS_CFUNC, .key.function=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_user_bool(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_user_int(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_INT, .value.integer=v } #define hs_user_num(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_NUM, .value.number=v } #define hs_user_str(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_STR, .value.string=v } #define hs_user_tbl(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_user_func(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_user_cfunc(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_user_user(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_user_light(k, v) \ { .key_type=HS_USER, .key.stack_index=k, \ .value_type=HS_LIGHT, .value.userdata=v } #define hs_light_bool(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_BOOL, .value.boolean=v } #define hs_light_int(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_INT, .value.integer=v } #define hs_light_num(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_NUM, .value.number=v } #define hs_light_str(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_STR, .value.string=v } #define hs_light_tbl(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_TBL, .value.stack_index=v } #define hs_light_func(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_FUNC, .value.stack_index=v } #define hs_light_cfunc(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_CFUNC, .value.function=v } #define hs_light_user(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_USER, .value.stack_index=v } #define hs_light_light(k, v) \ { .key_type=HS_LIGHT, .key.userdata=k, \ .value_type=HS_LIGHT, .value.userdata=v } int hs_create_table_(lua_State *L, int n_elements, struct hs_tbl_entry *elements); #define hs_create_table(L, ...) \ hs_create_table_(L, \ VA_NARGS(__VA_ARGS__)/4, \ (struct hs_tbl_entry[]) { __VA_ARGS__ }) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * hs_process_table * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ typedef void (*hs_pt_bool_callback)(bool, void *); typedef void (*hs_pt_int_callback)(lua_Integer, void *); typedef void (*hs_pt_num_callback)(lua_Number, void *); typedef void (*hs_pt_str_callback)(const char *, void *); // default processors void hs_pt_set_boolean(bool value, void *data); void hs_pt_set_integer(lua_Integer value, void *data); void hs_pt_set_number(lua_Number value, void *data); void hs_pt_set_string(const char *value, void *data); struct hs_table_processor { const char *key; hs_type type; union { hs_pt_bool_callback boolean; hs_pt_int_callback integer; hs_pt_num_callback number; hs_pt_str_callback string; } func; void *data; }; #define hs_process_bool(str, f, d) \ { .key=(str), .type=HS_BOOL, .func.boolean=(f), .data=(d) } #define hs_process_int(str, f, d) \ { .key=(str), .type=HS_INT, .func.integer=(f), .data=(d) } #define hs_process_num(str, f, d) \ { .key=(str), .type=HS_NUM, .func.number=(f), .data=(d) } #define hs_process_str(str, f, d) \ { .key=(str), .type=HS_STR, .func.string=(f), .data=(d) } void hs_process_table_(lua_State *L, int table_index, int n_processors, struct hs_table_processor *processors); #define hs_process_table(L, table_index, ...) \ hs_process_table_(L, table_index, \ VA_NARGS(__VA_ARGS__)/4, \ (struct hs_table_processor[]) {__VA_ARGS__}) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * hs_pushstring * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void hs_vpushstring(lua_State *L, const char *format_string, va_list args); void hs_pushstring(lua_State *L, const char *format_string, ...); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * error creation and handling * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void hs_throw_error(lua_State *L, const char *format_string, ...); int hs_traceback(lua_State *L); int hs_call(lua_State *L, int nargs, int nret); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * registry operations * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #define hs_rstore(L) luaL_ref(L, LUA_REGISTRYINDEX); #define hs_rload(L, ref) lua_rawgeti(L, LUA_REGISTRYINDEX, ref) #define hs_rdel(L, ref) luaL_unref(L, LUA_REGISTRYINDEX, ref) #endif