5 # By Gerald Combs <gerald@wireshark.org>
6 # Based on make-taps.pl by Luis E. Garcia Onatnon <luis.ontanon@gmail.com>
8 # Wireshark - Network traffic analyzer
9 # By Gerald Combs <gerald@wireshark.org>
10 # Copyright 1998 Gerald Combs
12 # SPDX-License-Identifier: GPL-2.0-or-later
14 Extract structs from C headers to generate a function that pushes a lua table
15 into the stack containing the elements of the struct.
25 this_dir
= os
.path
.dirname(__file__
)
28 def get_tap_info(tap_name
, header_file
, struct_name
, enum_types
):
29 code
= f
'#include "{header_file}"\n'
30 doc
= f
'Tap: {tap_name}\n'
35 'gchar[]': 'lua_pushstring(L,(const char*)v->STR);',
36 'gchar*': 'lua_pushstring(L,(const char*)v->STR);',
37 'guint': 'lua_pushinteger(L,(lua_Integer)v->STR);',
38 'guint8': 'lua_pushinteger(L,(lua_Integer)v->STR);',
39 'guint16': 'lua_pushinteger(L,(lua_Integer)v->STR);',
40 'guint32': 'lua_pushinteger(L,(lua_Integer)v->STR);',
41 'gint': 'lua_pushinteger(L,(lua_Integer)v->STR);',
42 'gint8': 'lua_pushinteger(L,(lua_Integer)v->STR);',
43 'gint16': 'lua_pushinteger(L,(lua_Integer)v->STR);',
44 'gint32': 'lua_pushinteger(L,(lua_Integer)v->STR);',
45 'gboolean': 'lua_pushboolean(L,(int)v->STR);',
46 'char[]': 'lua_pushstring(L,(const char*)v->STR);',
47 'char*': 'lua_pushstring(L,(const char*)v->STR);',
48 'unsigned': 'lua_pushinteger(L,(lua_Integer)v->STR);',
49 'uint8_t': 'lua_pushinteger(L,(lua_Integer)v->STR);',
50 'uint16_t': 'lua_pushinteger(L,(lua_Integer)v->STR);',
51 'uint32_t': 'lua_pushinteger(L,(lua_Integer)v->STR);',
52 'int': 'lua_pushinteger(L,(lua_Integer)v->STR);',
53 'int8_t': 'lua_pushinteger(L,(lua_Integer)v->STR);',
54 'int16_t': 'lua_pushinteger(L,(lua_Integer)v->STR);',
55 'int32': 'lua_pushinteger(L,(lua_Integer)v->STR);',
56 'bool': 'lua_pushboolean(L,(int)v->STR);',
57 'address': '{ Address a = (Address)g_malloc(sizeof(address)); copy_address(a, &(v->STR)); pushAddress(L,a); }',
58 'address*': '{ Address a = (Address)g_malloc(sizeof(address)); copy_address(a, v->STR); pushAddress(L,a); }',
59 'nstime_t': 'lua_pushnumber(L,(lua_Number)nstime_to_sec(&(v->STR)));',
60 'nstime_t*': 'lua_pushnumber(L,(lua_Number)nstime_to_sec(v->STR));',
74 'gboolean': 'boolean',
87 'address*': 'Address',
88 'nstime_t': 'number (seconds, since 1-1-1970 if absolute)',
89 'nstime_t*': 'number (seconds, since 1-1-1970 if absolute)',
92 with
open(os
.path
.join(this_dir
, header_file
), encoding
='utf-8') as header_f
:
95 line
= re
.sub(r
'\/\*.*?\*/', '', line
)
96 line
= re
.sub(r
'//.*', '', line
)
99 for enum
in enum_types
:
100 m
= re
.search(fr
'typedef\s+enum[^{{]*{{([^}}]*)}}[\s\n]*{enum}[\s\n]*;', buf
, flags
=re
.DOTALL
)
102 types
[enum
] = f
'lua_pushinteger(L,(lua_Integer)v->STR); /* {enum} */'
103 econsts
= m
.group(1).splitlines()
104 econsts
= [re
.sub(r
'\s+', '', item
) for item
in econsts
]
105 econsts
= [re
.sub(',', '', item
) for item
in econsts
]
106 econsts
= [item
for item
in econsts
if item
]
107 enums
[enum
] = econsts
108 ebody
= '|'.join(econsts
)
109 comments
[enum
] = f
'{enum}: {{ {ebody} }}'
111 m
= re
.search(fr
'typedef\s+struct.*?{{([^}}]*)}}[\s\n]*({struct_name})[\s\n]*;', buf
, flags
=re
.DOTALL
)
113 sys
.stderr
.write(f
'could not find typedef {struct_name} in {header_file}')
120 for line
in body
.splitlines():
124 m
= re
.search(r
'\s*(.*?)([\w\d_]+)\s*\[\s*\d+\s*\]\s*;', line
)
130 m
= re
.search(r
'\s*(.*?)([\w\d_]+)\s*;', line
)
136 v
= re
.sub(r
'const ', '', v
)
137 v
= re
.sub(r
'\s+', '', v
)
140 code
+= f
'static void wslua_{tap_name}_to_table(lua_State* L, const void* p) {{\n\tconst {struct_name}* v;\n\n\tv = (const {struct_name}*)p;\n\tlua_newtable(L);\n\n'
142 for el
in sorted(elems
):
144 fmt
= types
[elems
[el
]]
145 code
+= f
'\tlua_pushstring(L,\"{el}\");\n\t'
146 lua_type
= re
.sub(r
'\bSTR\b', el
, fmt
)
148 code
+= '\n\tlua_settable(L,-3);\n'
149 doc
+= f
'\t{el}: {comments[elems[el]]}\n'
156 return (code
, doc
, enums
)
160 parser
= argparse
.ArgumentParser(description
="Generate bindings required for Lua taps.")
161 parser
.add_argument("out_c", metavar
='C file', help="output C file")
162 parser
.add_argument("out_doc", metavar
='documentation file', help="output text file")
163 args
= parser
.parse_args()
165 tap_config
= configparser
.ConfigParser()
166 tap_config
.read(os
.path
.join(this_dir
, 'taps.ini'))
170 /* This file is autogenerated from ./taps by ./make-taps.py */
177 #include <wsutil/nstime.h>
182 for tap_name
in tap_config
.sections():
183 tap_d
= tap_config
[tap_name
]
185 if 'enum_types' in tap_d
.keys():
186 enum_types
= tap_d
['enum_types'].split(' ')
187 (code
, doc
, file_enums
) = get_tap_info(tap_name
, tap_d
['header_file'], tap_d
['struct_name'], enum_types
)
190 enums
.update(file_enums
)
192 c_body
+= 'static tappable_t tappables[] = {\n'
193 for tap_name
in sorted(tap_config
.sections()):
194 c_body
+= f
'\t{{"{tap_name}", wslua_{tap_name}_to_table }},\n'
201 c_body
+= '\nint wslua_set_tap_enums(lua_State* L) {\n'
202 for enum
in sorted(enums
):
203 c_body
+= f
'\n\t/*\n\t * {enum}\n\t */\n\tlua_newtable(L);\n'
204 for econst
in enums
[enum
]:
206 lua_pushinteger(L,(lua_Integer){econst});
207 lua_setglobal(L,"{econst}");
208 lua_pushinteger(L,(lua_Integer){econst});
209 lua_pushstring(L,"{econst}");
212 c_body
+= f
'\tlua_setglobal(L,\"{enum}\");\n'
213 c_body
+= '\treturn 0;\n}\n'
218 tap_extractor_t wslua_get_tap_extractor(const gchar* name) {
220 for(t = tappables; t->name; t++ ) {
221 if (g_str_equal(t->name,name)) return t->extractor;
228 with
open(args
.out_c
, mode
='w', encoding
='utf-8') as out_c_f
:
229 out_c_f
.write(c_body
)
231 with
open(args
.out_doc
, mode
='w', encoding
='utf-8') as out_doc_f
:
232 out_doc_f
.write(doc_body
)
234 if __name__
== '__main__':