4 * Wireshark's interface to the Lua Programming Language
6 * This file is for internal WSLUA functions - not ones exposed into Lua.
8 * (c) 2013, Hadriel Kaplan <hadrielk@yahoo.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
18 #define WS_LOG_DOMAIN LOG_DOMAIN_WSLUA
22 /* Several implementation details (__getters, __setters, __methods) were exposed
23 * to Lua code. These are normally not used by dissectors, just for debugging
24 * (and the "wslua global" test). Enable by setting WSLUA_WITH_INTROSPECTION */
25 #define WSLUA_WITH_INTROSPECTION
27 WSLUA_API
int wslua__concat(lua_State
* L
) {
28 /* Concatenate two objects to a string */
29 if (!luaL_callmeta(L
,1,"__tostring"))
31 if (!luaL_callmeta(L
,2,"__tostring"))
39 /* like lua_toboolean, except only coerces int, nil, and bool, and errors on other types.
40 note that normal lua_toboolean returns 1 for any Lua value different from false and
41 nil; otherwise it returns 0. So a string would give a 0, as would a number of 1.
42 This function errors if the arg is a string, and sets the boolean to 1 for any
43 number other than 0. Like toboolean, this returns false if the arg was missing. */
44 WSLUA_API
bool wslua_toboolean(lua_State
* L
, int n
) {
47 if ( lua_isboolean(L
,n
) || lua_isnil(L
,n
) || lua_gettop(L
) < n
) {
48 val
= lua_toboolean(L
,n
);
49 } else if ( lua_type(L
,n
) == LUA_TNUMBER
) {
50 int num
= (int)luaL_checkinteger(L
,n
);
51 val
= num
!= 0 ? true : false;
53 luaL_argerror(L
,n
,"must be a boolean or number");
59 /* like luaL_checkinteger, except for booleans - this does not coerce other types */
60 WSLUA_API
bool wslua_checkboolean(lua_State
* L
, int n
) {
62 if (!lua_isboolean(L
,n
) ) {
63 luaL_argerror(L
,n
,"must be a boolean");
66 return lua_toboolean(L
,n
);
69 WSLUA_API
bool wslua_optbool(lua_State
* L
, int n
, bool def
) {
72 if ( lua_isboolean(L
,n
) ) {
73 val
= lua_toboolean(L
,n
);
74 } else if ( lua_isnil(L
,n
) || lua_gettop(L
) < n
){
77 luaL_argerror(L
,n
,"must be a boolean");
83 /* like lua_tointeger, except only coerces int, nil, and bool, and errors on other types.
84 note that normal lua_tointeger does not coerce nil or bool, but does coerce strings. */
85 WSLUA_API lua_Integer
wslua_tointeger(lua_State
* L
, int n
) {
88 if ( lua_type(L
,n
) == LUA_TNUMBER
) {
89 val
= lua_tointeger(L
,n
);
90 } else if ( lua_isboolean(L
,n
) ) {
91 val
= (lua_Integer
) (lua_toboolean(L
,n
));
92 } else if ( lua_isnil(L
,n
) ) {
95 luaL_argerror(L
,n
,"must be a integer, boolean or nil");
101 /* like luaL_optint, except converts/handles Lua booleans as well */
102 WSLUA_API
int wslua_optboolint(lua_State
* L
, int n
, int def
) {
105 if ( lua_isnumber(L
,n
) ) {
106 val
= (int)lua_tointeger(L
,n
);
107 } else if ( lua_isboolean(L
,n
) ) {
108 val
= lua_toboolean(L
,n
) ? 1 : 0;
109 } else if ( lua_isnil(L
,n
) || lua_gettop(L
) < n
){
112 luaL_argerror(L
,n
,"must be a boolean or integer");
118 /* like luaL_checklstring, except no coercion */
119 WSLUA_API
const char* wslua_checklstring_only(lua_State
* L
, int n
, size_t *l
) {
121 if (lua_type(L
,n
) != LUA_TSTRING
) {
122 luaL_argerror(L
,n
,"must be a Lua string");
125 return luaL_checklstring(L
, n
, l
);
128 /* like luaL_checkstring, except no coercion */
129 WSLUA_API
const char* wslua_checkstring_only(lua_State
* L
, int n
) {
130 return wslua_checklstring_only(L
, n
, NULL
);
133 /* following is based on the luaL_setfuncs() from Lua 5.2, so we can use it in pre-5.2 */
134 WSLUA_API
void wslua_setfuncs(lua_State
*L
, const luaL_Reg
*l
, int nup
) {
135 luaL_checkstack(L
, nup
, "too many upvalues");
136 for (; l
->name
!= NULL
; l
++) { /* fill the table with given functions */
138 for (i
= 0; i
< nup
; i
++) /* copy upvalues to the top */
139 lua_pushvalue(L
, -nup
);
140 lua_pushcclosure(L
, l
->func
, nup
); /* closure with those upvalues */
141 lua_setfield(L
, -(nup
+ 2), l
->name
);
143 lua_pop(L
, nup
); /* remove upvalues */
147 * Identical to lua_getfield, but without triggering the __newindex metamethod.
148 * The resulting value is returned on the Lua stack.
150 static void lua_rawgetfield(lua_State
*L
, int idx
, const char *k
) {
151 idx
= lua_absindex(L
, idx
);
152 lua_pushstring(L
, k
);
157 * Identical to lua_setfield, but without triggering the __newindex metamethod.
158 * The value to be set is taken from the Lua stack.
160 static void lua_rawsetfield (lua_State
*L
, int idx
, const char *k
) {
161 idx
= lua_absindex(L
, idx
);
162 lua_pushstring(L
, k
);
167 WSLUA_API
void wslua_print_stack(char* s
, lua_State
* L
) {
170 for (i
=1;i
<=lua_gettop(L
);i
++) {
171 printf("%s-%i: %s\n",s
,i
,lua_typename (L
,lua_type(L
, i
)));
176 /* C-code function equivalent of the typeof() function we created in Lua.
177 * The Lua one is for Lua scripts to use, this one is for C-code to use.
179 const char* wslua_typeof_unknown
= "UNKNOWN";
180 const char* wslua_typeof(lua_State
*L
, int idx
) {
181 const char *classname
= wslua_typeof_unknown
;
182 /* we'll try getting the class name for error reporting*/
183 if (luaL_getmetafield(L
, idx
, WSLUA_TYPEOF_FIELD
)) {
184 classname
= luaL_optstring(L
, -1, wslua_typeof_unknown
);
185 lua_pop(L
,1); /* pop __typeof result */
187 else if (lua_type(L
,idx
) == LUA_TTABLE
) {
188 lua_rawgetfield(L
, idx
, WSLUA_TYPEOF_FIELD
);
189 classname
= luaL_optstring(L
, -1, wslua_typeof_unknown
);
190 lua_pop(L
,1); /* pop __typeof result */
195 /* this gets a Lua table of the given name, from the table at the given
196 * location idx. If it does not get a table, it pops whatever it got
199 bool wslua_get_table(lua_State
*L
, int idx
, const char *name
) {
201 lua_rawgetfield(L
, idx
, name
);
202 if (!lua_istable(L
,-1)) {
209 /* this gets a table field of the given name, from the table at the given
210 * location idx. If it does not get a field, it pops whatever it got
213 bool wslua_get_field(lua_State
*L
, int idx
, const char *name
) {
215 lua_rawgetfield(L
, idx
, name
);
216 if (lua_isnil(L
,-1)) {
224 * The __index metamethod for classes. Expected upvalues: class name.
226 static int wslua_classmeta_index(lua_State
*L
) {
227 const char *fieldname
= luaL_checkstring(L
, 2);
228 const char *classname
= luaL_checkstring(L
, lua_upvalueindex(1));
230 return luaL_error(L
, "No such '%s' function/property for object type '%s'", fieldname
, classname
);
234 * The __index/__newindex metamethod for class instances. Expected upvalues:
235 * class name, getters/getters, __index/__newindex class instance metamethod,
236 * class methods (getters only). See wslua_register_classinstance_meta.
238 * It first tries to find an attribute getter/setter, then an instance method
239 * (getters only), then the __index/__newindex metamethod of the class instance
240 * metatable and finally it gives up with an error.
242 * Getters are invoked with the table as parameter. Setters are invoked with the
243 * table and the value as parameter.
245 static int wslua_instancemeta_index_impl(lua_State
*L
, bool is_getter
)
247 const char *fieldname
= luaL_checkstring(L
, 2);
248 const int attr_idx
= lua_upvalueindex(2);
249 const int fallback_idx
= lua_upvalueindex(3);
250 const int methods_idx
= lua_upvalueindex(4);
252 /* Check for getter/setter */
253 if (lua_istable(L
, attr_idx
)) {
254 lua_rawgetfield(L
, attr_idx
, fieldname
);
255 if (lua_iscfunction(L
, -1)) {
256 lua_CFunction cfunc
= lua_tocfunction(L
, -1);
257 lua_pop(L
, 1); /* Remove cfunction from stack */
258 lua_remove(L
, 2); /* Remove key from stack */
260 * Note: This re-uses the current closure as optimization, exposing
261 * its upvalues via pseudo-indices. The alternative is to create a
262 * new C closure (via lua_call), but this is more expensive.
263 * Callees should not rely on the availability of the upvalues.
269 /* If this is a getter, and the getter has methods, try them. */
270 if (is_getter
&& lua_istable(L
, methods_idx
)) {
271 lua_rawgetfield(L
, methods_idx
, fieldname
);
272 if (!lua_isnil(L
, -1)) {
273 /* Return method from methods table. */
276 lua_pop(L
, 1); /* Remove nil from stack. */
279 /* Use function from the class instance metatable (if any). */
280 if (lua_iscfunction(L
, fallback_idx
)) {
281 lua_CFunction cfunc
= lua_tocfunction(L
, fallback_idx
);
282 /* Note, unlike getters/setters functions, the key must be preserved! */
286 const char *classname
= luaL_checkstring(L
, lua_upvalueindex(1));
287 return luaL_error(L
, "No such '%s' method/field for object type '%s'", fieldname
, classname
);
290 static int wslua_instancemeta_index(lua_State
*L
)
292 return wslua_instancemeta_index_impl(L
, true);
295 static int wslua_instancemeta_newindex(lua_State
*L
)
297 return wslua_instancemeta_index_impl(L
, false);
300 /* Pushes a hex string of the binary data argument. */
301 int wslua_bin2hex(lua_State
* L
, const uint8_t* data
, const unsigned len
, const bool lowercase
, const char* sep
) {
304 static const char byte_to_str_upper
[256][3] = {
305 "00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
306 "10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
307 "20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
308 "30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
309 "40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
310 "50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
311 "60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
312 "70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
313 "80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
314 "90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
315 "A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
316 "B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
317 "C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
318 "D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
319 "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
320 "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
322 static const char byte_to_str_lower
[256][3] = {
323 "00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
324 "10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
325 "20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
326 "30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
327 "40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
328 "50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
329 "60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
330 "70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
331 "80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
332 "90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
333 "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
334 "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
335 "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
336 "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
337 "e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
338 "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff"
340 const char (*byte_to_str
)[3] = byte_to_str_upper
;
341 const unsigned last
= len
- 1;
343 if (lowercase
) byte_to_str
= byte_to_str_lower
;
345 luaL_buffinit(L
, &b
);
347 for (i
= 0; i
< len
; i
++) {
348 luaL_addlstring(&b
, &(*byte_to_str
[data
[i
]]), 2);
349 if (sep
&& i
< last
) luaL_addstring(&b
, sep
);
357 /* Pushes a binary string of the hex-ascii data argument. */
358 int wslua_hex2bin(lua_State
* L
, const char* data
, const unsigned len
, const char* sep
) {
364 static const int8_t str_to_nibble
[256] = {
365 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
366 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
367 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
368 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
369 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
370 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
371 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
372 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
373 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
374 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
375 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
376 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
377 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
378 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
379 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
380 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
383 if (sep
) seplen
= (unsigned) strlen(sep
);
385 luaL_buffinit(L
, &b
);
387 for (i
= 0; i
< len
;) {
388 c
= str_to_nibble
[(unsigned char)data
[i
]];
390 if (seplen
&& strncmp(&data
[i
], sep
, seplen
) == 0) {
397 d
= str_to_nibble
[(unsigned char)data
[++i
]];
399 luaL_addchar(&b
, (c
* 16) + d
);
409 * Creates a table of getters/setters and pushes it on the Lua stack.
411 * Additionally, a sanity check is performed to detect colliding getters/setters
414 static void wslua_push_attributes(lua_State
*L
, const wslua_attribute_table
*t
, bool is_getter
, int methods_idx
)
417 /* No property accessors? Nothing to do. */
419 lua_newtable(L
); /* wslua_reg_attributes requires a table for the moment. */
423 /* If there is a methods table, prepare for a collision check. */
424 if (lua_istable(L
, methods_idx
)) {
425 methods_idx
= lua_absindex(L
, methods_idx
);
431 /* Fill the getter/setter table with given functions. */
432 for (; t
->fieldname
!= NULL
; t
++) {
433 lua_CFunction cfunc
= is_getter
? t
->getfunc
: t
->setfunc
;
435 /* if there's a previous methods table, make sure this attribute name doesn't collide */
437 lua_rawgetfield(L
, methods_idx
, t
->fieldname
);
438 if (!lua_isnil(L
, -1)) {
439 ws_error("'%s' attribute name already exists as method name for class\n", t
->fieldname
);
441 lua_pop(L
,1); /* pop the nil */
443 lua_pushcfunction(L
, cfunc
);
444 lua_rawsetfield(L
, -2, t
->fieldname
);
450 * Registers the metatable for class instances. See the documentation of
451 * wslua_register_class for the exact metatable.
453 void wslua_register_classinstance_meta(lua_State
*L
, const wslua_class
*cls_def
)
455 /* Register metatable for use by class instances. STACK = { MT } */
456 /* NOTE: The name can be changed as long as luaL_checkudata is also adapted */
457 luaL_newmetatable(L
, cls_def
->name
);
458 if (cls_def
->instance_meta
) {
459 wslua_setfuncs(L
, cls_def
->instance_meta
, 0);
462 /* Set the __typeof attribute to the class name (for use by "typeof" in Lua code). */
463 lua_pushstring(L
, cls_def
->name
);
464 lua_rawsetfield(L
, -2, WSLUA_TYPEOF_FIELD
);
466 /* Create table to store method names. STACK = { MT, methods } */
467 if (cls_def
->instance_methods
) {
469 wslua_setfuncs(L
, cls_def
->instance_methods
, 0);
474 /* Prepare __index method on metatable. */
475 lua_pushstring(L
, cls_def
->name
); /* upval 1: class name */
476 wslua_push_attributes(L
, cls_def
->attrs
, true, -2); /* upval 2: getters table */
477 #ifdef WSLUA_WITH_INTROSPECTION
478 lua_pushvalue(L
, -1);
479 lua_rawsetfield(L
, -5, "__getters"); /* set (transition) property on mt, remove later! */
481 lua_rawgetfield(L
, -4, "__index"); /* upval 3: fallback __index method from metatable */
482 lua_pushvalue(L
, -4); /* upval 4: class methods table */
483 lua_pushcclosure(L
, wslua_instancemeta_index
, 4);
484 lua_rawsetfield(L
, -3, "__index");
486 /* Prepare __newindex method on metatable. */
487 lua_pushstring(L
, cls_def
->name
); /* upval 1: class name */
488 wslua_push_attributes(L
, cls_def
->attrs
, false, -2); /* upval 2: setters table */
489 #ifdef WSLUA_WITH_INTROSPECTION
490 lua_pushvalue(L
, -1);
491 lua_rawsetfield(L
, -5, "__setters"); /* set (transition) property on mt, remove later! */
493 lua_rawgetfield(L
, -4, "__newindex"); /* upval 3: fallback __newindex method from metatable */
494 lua_pushcclosure(L
, wslua_instancemeta_newindex
, 3);
495 lua_rawsetfield(L
, -3, "__newindex");
497 /* Pop metatable + methods table. STACK = { } */
502 * Registers a new class for use in Lua with the specified properties. The
503 * metatable for the class instance is internally registered with the given
506 * This functions basically creates a class (type table) with this structure:
508 * Class = { class_methods }
509 * Class.__typeof = "Class" -- NOTE: Might be removed in future
510 * Class.__metatable = { class_meta }
511 * Class.__metatable.__typeof = "Class" -- NOTE: Might be removed in future
512 * Class.__metatable.__index = function_that_errors_out
513 * Class.__metatable.__newindex = function_that_errors_out
515 * It also registers another metatable for class instances (type userdata):
517 * mt = { instance_meta }
518 * mt.__typeof = "Class"
519 * -- will be passed upvalues (see wslua_instancemeta_index_impl).
520 * mt.__index = function_that_finds_right_property_or_method_getter
521 * mt.__newindex = function_thaon_that_finds_right_property_or_method_setter
523 * For backwards compatibility, introspection is still possible (this detail
524 * might be removed in the future though, do not rely on this!):
526 * Class.__metatable.__methods = Class
527 * Class.__metatable.__getters = { __typeof = "getter", getter_attrs }
528 * Class.__metatable.__setters = { __typeof = "setter", setter_attrs }
530 void wslua_register_class(lua_State
*L
, const wslua_class
*cls_def
)
532 /* Check for existing global variables/classes with the same name. */
533 lua_getglobal(L
, cls_def
->name
);
534 if (!lua_isnil (L
, -1)) {
535 ws_error("Attempt to register class '%s' which already exists in global Lua table\n", cls_def
->name
);
539 /* Create new table for class. STACK = { table } */
541 if (cls_def
->class_methods
) {
542 wslua_setfuncs(L
, cls_def
->class_methods
, 0);
545 #ifdef WSLUA_WITH_INTROSPECTION
546 /* Set __typeof to the class name, used by wslua_typeof. Might be removed in
547 * the future as the type can already be determined from the metatable. */
548 lua_pushstring(L
, cls_def
->name
);
549 lua_rawsetfield(L
, -2, WSLUA_TYPEOF_FIELD
);
552 /* Create new metatable for class. STACK = { table, CLASSMT } */
554 if (cls_def
->class_meta
) {
555 /* Set metamethods on metatable for class. */
556 wslua_setfuncs(L
, cls_def
->class_meta
, 0);
558 #ifdef WSLUA_WITH_INTROSPECTION
559 /* Set __typeof to the class name. Might be removed in the future, a "class"
560 * is not of the type "(name of class)", instead it is of type "class".
561 * Instances of this class should be of type "(name of class)". */
562 lua_pushstring(L
, cls_def
->name
);
563 lua_rawsetfield(L
, -2, WSLUA_TYPEOF_FIELD
);
566 /* For backwards compatibility, error out when a non-existing property is being accessed. */
567 lua_pushstring(L
, cls_def
->name
);
568 lua_pushcclosure(L
, wslua_classmeta_index
, 1);
569 lua_rawsetfield(L
, -2, "__index");
571 /* Prevent properties from being set on classes. Previously this was always
572 * forbidden for classes with attributes (such as Listener), this extends
573 * the restriction to all classes. */
574 lua_pushstring(L
, cls_def
->name
);
575 lua_pushcclosure(L
, wslua_classmeta_index
, 1);
576 lua_rawsetfield(L
, -2, "__newindex");
578 /* Set metatable on class. STACK = { table } */
579 lua_setmetatable(L
, -2);
581 wslua_register_classinstance_meta(L
, cls_def
);
583 #ifdef WSLUA_WITH_INTROSPECTION
584 /* XXX remove these? It looks like an internal implementation detail that is
585 * no longer needed but is added here to pass the wslua tests (API check) */
586 lua_getmetatable(L
, -1); /* Stack = { table, CLASSMT } */
587 luaL_getmetatable(L
, cls_def
->name
); /* Stack = { table, CLASSMT, MT } */
589 lua_rawgetfield(L
, -1, "__getters"); /* __getters from instance MT */
590 lua_pushstring(L
, "getter");
591 lua_rawsetfield(L
, -2, WSLUA_TYPEOF_FIELD
);
592 lua_rawsetfield(L
, -3, "__getters"); /* Set property on class MT */
594 lua_rawgetfield(L
, -1, "__setters"); /* setters from instance MT */
595 lua_pushstring(L
, "setter");
596 lua_rawsetfield(L
, -2, WSLUA_TYPEOF_FIELD
);
597 lua_rawsetfield(L
, -3, "__setters"); /* Set property on class MT */
598 lua_pop(L
, 1); /* Stack = { table, CLASSMT } */
600 lua_pushvalue(L
, -2);
601 lua_rawsetfield(L
, -2, "__methods"); /* CLASSMT.__methods = Class */
602 lua_pop(L
, 1); /* Stack = { table } */
605 /* Set the class methods table as global name. STACK = { } */
606 lua_setglobal(L
, cls_def
->name
);
610 * Editor modelines - https://www.wireshark.org/tools/modelines.html
615 * indent-tabs-mode: nil
618 * vi: set shiftwidth=4 tabstop=8 expandtab:
619 * :indentSize=4:tabSize=8:noTabs=true: