diff options
author | Hadriel Kaplan <hadrielk@yahoo.com> | 2014-02-19 03:22:55 -0500 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2014-02-21 02:05:35 +0000 |
commit | 9246a709bf826f2cc64581b25fbf1ebafa330db6 (patch) | |
tree | b63eb4c55d7e1673f98a371d8787de906807baaf /epan/wslua/wslua.h | |
parent | c65fbffc95b5e6b0caff6952faea8e8c9350cf7d (diff) |
Cleanup on aisle 5: normalizes the Lua code to follow common schema/model
Over time the various wslua classes/functions have gotten moldy, with different
ways of doing similar things. Some of it can't be changed without breaking
backwards compatibility for Lua scripts, so I didn't do that. But I did what
I could. The biggest change is a refactoring of how accessors/attributes
are handled in the code, so that most of them work the same way using the
same code.
Specific changes made:
* Added null/expired checking macro to class declarations for many classes
* Removed extraneous pointer/expired checking, since checkFoo() does that already
* Fixed "errors" reported by clang static analyzer; they were false positives, but it was easier to get it to stop complaining by changing the code
* Moved internal wslua functions from wslua_utils.c into a new 'wslua_internals.c' file
* Changed Listener/NSTime/Pinfo/Proto to use a common setter/getter accessor/attribute code model, instead of each of them doing their own
* Fixed some API doc mistakes, mostly around attributes that were documented as read-only but were actually read-write
Change-Id: Idddafc5fbd3545ebff29e063acc767e1c743a1a9
Reviewed-on: https://code.wireshark.org/review/271
Reviewed-by: Evan Huus <eapache@gmail.com>
Tested-by: Evan Huus <eapache@gmail.com>
Diffstat (limited to 'epan/wslua/wslua.h')
-rw-r--r-- | epan/wslua/wslua.h | 144 |
1 files changed, 117 insertions, 27 deletions
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h index 6deef65468..1b6011b8bc 100644 --- a/epan/wslua/wslua.h +++ b/epan/wslua/wslua.h @@ -198,7 +198,7 @@ struct _wslua_tap { lua_State* L; int packet_ref; int draw_ref; - int init_ref; + int reset_ref; }; # define DIRECTORY_T GDir @@ -312,8 +312,39 @@ C shift##C(lua_State* L,int i) { \ } \ typedef int dummy##C +typedef struct _wslua_attribute_table { + const gchar *fieldname; + lua_CFunction getfunc; + lua_CFunction setfunc; +} wslua_attribute_table; +extern int wslua_reg_attributes(lua_State *L, const wslua_attribute_table *t, gboolean is_getter); + +#define WSLUA_TYPEOF_FIELD "__typeof" + #ifdef HAVE_LUA +#define WSLUA_REGISTER_META(C) { \ + /* check for existing metatable in registry */ \ + luaL_getmetatable(L, #C); \ + if (!lua_isnil (L, -1)) { \ + fprintf(stderr, "ERROR: Attempt to register metatable '%s' which already exists in Lua registry\n", #C); \ + exit(1); \ + } \ + lua_pop (L, 1); \ + /* create a new metatable and register metamethods into it */ \ + luaL_newmetatable (L, #C); \ + wslua_setfuncs (L, C ## _meta, 0); \ + /* add a metatable field named '__typeof' = the class name, this is used by the typeof() Lua func */ \ + lua_pushstring(L, #C); \ + lua_setfield(L, -2, WSLUA_TYPEOF_FIELD); \ + /* add the '__gc' metamethod with a C-function named Class__gc */ \ + /* this will force ALL wslua classes to have a Class__gc function defined, which is good */ \ + lua_pushcfunction(L, C ## __gc); \ + lua_setfield(L, -2, "__gc"); \ + /* pop the metatable */ \ + lua_pop(L, 1); \ +} + #define WSLUA_REGISTER_CLASS(C) { \ /* check for existing class table in global */ \ lua_getglobal (L, #C); \ @@ -327,14 +358,10 @@ typedef int dummy##C wslua_setfuncs (L, C ## _methods, 0); \ /* add a method-table field named '__typeof' = the class name, this is used by the typeof() Lua func */ \ lua_pushstring(L, #C); \ - lua_setfield(L, -2, "__typeof"); \ - /* create a new metatable and register metamethods into it */ \ - luaL_newmetatable (L, #C); \ - wslua_setfuncs (L, C ## _meta, 0); \ - /* add the '__gc' metamethod with a C-function named Class__gc */ \ - /* this will force ALL wslua classes to have a Class__gc function defined, which is good */ \ - lua_pushcfunction(L, C ## __gc); \ - lua_setfield(L, -2, "__gc"); \ + lua_setfield(L, -2, WSLUA_TYPEOF_FIELD); \ + /* setup the meta table */ \ + WSLUA_REGISTER_META(C); \ + luaL_getmetatable(L, #C); \ /* push a copy of the class methods table, and set it to be the metatable's __index field */ \ lua_pushvalue (L, -2); \ lua_setfield (L, -2, "__index"); \ @@ -344,26 +371,18 @@ typedef int dummy##C lua_setglobal (L, #C); \ } -#define WSLUA_REGISTER_META(C) { \ - /* check for existing metatable in registry */ \ +/* see comments for wslua_reg_attributes and wslua_attribute_dispatcher to see how this attribute stuff works */ +#define WSLUA_REGISTER_ATTRIBUTES(C) { \ + /* get metatable from Lua registry */ \ luaL_getmetatable(L, #C); \ - if (!lua_isnil (L, -1)) { \ - fprintf(stderr, "ERROR: Attempt to register metatable '%s' which already exists in Lua registry\n", #C); \ + if (lua_isnil(L, -1)) { \ + fprintf(stderr, "ERROR: Attempt to register attributes without a pre-existing metatable for '%s' in Lua registry\n", #C); \ exit(1); \ } \ - lua_pop (L, 1); \ - /* create a new metatable and register metamethods into it */ \ - luaL_newmetatable (L, #C); \ - wslua_setfuncs (L, C ## _meta, 0); \ - /* add a metatable field named '__typeof' = the class name, this is used by the typeof() Lua func */ \ - lua_pushstring(L, #C); \ - lua_setfield(L, -2, "__typeof"); \ - /* add the '__gc' metamethod with a C-function named Class__gc */ \ - /* this will force ALL wslua classes to have a Class__gc function defined, which is good */ \ - lua_pushcfunction(L, C ## __gc); \ - lua_setfield(L, -2, "__gc"); \ - /* pop the metatable */ \ - lua_pop(L, 1); \ + /* register the getters/setters in their tables */ \ + wslua_reg_attributes(L, C##_attributes, TRUE); \ + wslua_reg_attributes(L, C##_attributes, FALSE); \ + lua_pop(L, 1); /* pop the metatable */ \ } #define WSLUA_INIT(L) \ @@ -389,6 +408,68 @@ typedef int dummy##C #define WSLUA_META static const luaL_Reg #define WSLUA_CLASS_FNREG(class,name) { #name, class##_##name } #define WSLUA_CLASS_FNREG_ALIAS(class,aliasname,name) { #aliasname, class##_##name } +#define WSLUA_CLASS_MTREG(class,name) { "__" #name, class##__##name } + +#define WSLUA_ATTRIBUTES static const wslua_attribute_table +/* following are useful macros for the rows in the array created by above */ +#define WSLUA_ATTRIBUTE_RWREG(class,name) { #name, class##_get_##name, class##_set_##name } +#define WSLUA_ATTRIBUTE_ROREG(class,name) { #name, class##_get_##name, NULL } +#define WSLUA_ATTRIBUTE_WOREG(class,name) { #name, NULL, class##_set_##name } + +#define WSLUA_ATTRIBUTE_FUNC_SETTER(C,field) \ + static int C##_set_##field (lua_State* L) { \ + C obj = check##C (L,1); \ + if (! lua_isfunction(L,-1) ) \ + return luaL_error(L, "%s's attribute `%s' must be a function", #C , #field ); \ + obj->field##_ref = luaL_ref(L, LUA_REGISTRYINDEX); \ + return 0; \ + } + +#define WSLUA_ATTRIBUTE_GET(C,name,block) \ + static int C##_get_##name (lua_State* L) { \ + C obj = check##C (L,1); \ + block \ + return 1; \ + } + +#define WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(C,name,member) \ + WSLUA_ATTRIBUTE_GET(C,name,{lua_pushboolean(L, obj->member );}) + +#define WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(C,name,member) \ + WSLUA_ATTRIBUTE_GET(C,name,{lua_pushnumber(L,(lua_Number)(obj->member));}) + +#define WSLUA_ATTRIBUTE_NUMBER_GETTER(C,member) \ + WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(C,member,member) + +#define WSLUA_ATTRIBUTE_BLOCK_NUMBER_GETTER(C,name,block) \ + WSLUA_ATTRIBUTE_GET(C,name,{lua_pushnumber(L,(lua_Number)(block));}) + +#define WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(C,name,member) \ + WSLUA_ATTRIBUTE_GET(C,name, { \ + lua_pushstring(L,obj->member); /* this pushes nil if obj->member is null */ \ + }) + +#define WSLUA_ATTRIBUTE_STRING_GETTER(C,member) \ + WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(C,member,member) + + +#define WSLUA_ATTRIBUTE_SET(C,name,block) \ + static int C##_set_##name (lua_State* L) { \ + C obj = check##C (L,1); \ + block; \ + return 0; \ + } + +#define WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(C,name,member,cast) \ + WSLUA_ATTRIBUTE_SET(C,name, { \ + if (! lua_isnumber(L,-1) ) \ + return luaL_error(L, "%s's attribute `%s' must be a number", #C , #name ); \ + obj->member = (cast) lua_tointeger(L,-1); \ + }) + +#define WSLUA_ATTRIBUTE_NUMBER_SETTER(C,member,cast) \ + WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(C,member,member,cast) + #define WSLUA_ERROR(name,error) { luaL_error(L, ep_strdup_printf("%s%s", #name ": " ,error) ); return 0; } #define WSLUA_ARG_ERROR(name,attr,error) { luaL_argerror(L,WSLUA_ARG_ ## name ## _ ## attr, #name ": " error); return 0; } @@ -403,7 +484,12 @@ typedef int dummy##C #define WSLUA_API extern #define NOP -#define FAIL_ON_NULL(s) if (! *p) luaL_argerror(L,idx,s) +#define FAIL_ON_NULL(s) if (! *p) luaL_argerror(L,idx,"null " s) +#define FAIL_ON_NULL_OR_EXPIRED(s) if (!*p) { \ + luaL_argerror(L,idx,"null " s); \ + } else if ((*p)->expired) { \ + luaL_argerror(L,idx,"expired " s); \ + } /* Clears or marks references that connects Lua to Wireshark structures */ #define CLEAR_OUTSTANDING(C, marker, marker_val) void clear_outstanding_##C(void) { \ @@ -440,8 +526,12 @@ extern lua_State* wslua_state(void); extern int wslua__concat(lua_State* L); extern gboolean wslua_optbool(lua_State* L, int n, gboolean def); +extern int wslua_optboolint(lua_State* L, int n, int def); extern const gchar* lua_shiftstring(lua_State* L,int idx); extern void wslua_setfuncs(lua_State *L, const luaL_Reg *l, int nup); +extern const gchar* wslua_typeof_unknown; +extern const gchar* wslua_typeof(lua_State *L, int idx); +extern void wslua_assert_table_field_new(lua_State *L, int idx, const gchar *name); extern int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data); extern void wslua_prefs_changed(void); extern void proto_register_lua(void); |