1#!/usr/bin/env python3 2# 3# Looks for registration routines in the plugins 4# and assembles C code to call all the routines. 5# A new "plugin.c" file will be written in the current directory. 6# 7 8import os 9import sys 10import re 11 12# 13# The first argument is the directory in which the source files live. 14# 15srcdir = sys.argv[1] 16# 17# The second argument is either "plugin", "plugin_wtap", "plugin_codec", 18# or "plugin_tap". 19# 20registertype = sys.argv[2] 21# 22# All subsequent arguments are the files to scan. 23# 24files = sys.argv[3:] 25 26final_filename = "plugin.c" 27preamble = """\ 28/* 29 * Do not modify this file. Changes will be overwritten. 30 * 31 * Generated automatically from %s. 32 */ 33""" % (os.path.basename(sys.argv[0])) 34 35# Create the proper list of filenames 36filenames = [] 37for file in files: 38 if os.path.isfile(file): 39 filenames.append(file) 40 else: 41 filenames.append(os.path.join(srcdir, file)) 42 43if len(filenames) < 1: 44 print("No files found") 45 sys.exit(1) 46 47 48# Look through all files, applying the regex to each line. 49# If the pattern matches, save the "symbol" section to the 50# appropriate set. 51regs = { 52 'proto_reg': set(), 53 'handoff_reg': set(), 54 'wtap_register': set(), 55 'codec_register': set(), 56 'register_tap_listener': set(), 57 } 58 59# For those that don't know Python, r"" indicates a raw string, 60# devoid of Python escapes. 61proto_regex = r"\bproto_register_(?P<symbol>[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$" 62 63handoff_regex = r"\bproto_reg_handoff_(?P<symbol>[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$" 64 65wtap_reg_regex = r"\bwtap_register_(?P<symbol>[_A-Za-z0-9]+)\s*\([^;]+$" 66 67codec_reg_regex = r"\bcodec_register_(?P<symbol>[_A-Za-z0-9]+)\s*\([^;]+$" 68 69tap_reg_regex = r"\bregister_tap_listener_(?P<symbol>[_A-Za-z0-9]+)\s*\([^;]+$" 70 71# This table drives the pattern-matching and symbol-harvesting 72patterns = [ 73 ( 'proto_reg', re.compile(proto_regex, re.MULTILINE) ), 74 ( 'handoff_reg', re.compile(handoff_regex, re.MULTILINE) ), 75 ( 'wtap_register', re.compile(wtap_reg_regex, re.MULTILINE) ), 76 ( 'codec_register', re.compile(codec_reg_regex, re.MULTILINE) ), 77 ( 'register_tap_listener', re.compile(tap_reg_regex, re.MULTILINE) ), 78 ] 79 80# Grep 81for filename in filenames: 82 file = open(filename) 83 # Read the whole file into memory 84 contents = file.read() 85 for action in patterns: 86 regex = action[1] 87 for match in regex.finditer(contents): 88 symbol = match.group("symbol") 89 sym_type = action[0] 90 regs[sym_type].add(symbol) 91 # We're done with the file contents 92 del contents 93 file.close() 94 95# Make sure we actually processed something 96if (len(regs['proto_reg']) < 1 and len(regs['wtap_register']) < 1 and len(regs['codec_register']) < 1 and len(regs['register_tap_listener']) < 1): 97 print("No plugin registrations found") 98 sys.exit(1) 99 100# Convert the sets into sorted lists to make the output pretty 101regs['proto_reg'] = sorted(regs['proto_reg']) 102regs['handoff_reg'] = sorted(regs['handoff_reg']) 103regs['wtap_register'] = sorted(regs['wtap_register']) 104regs['codec_register'] = sorted(regs['codec_register']) 105regs['register_tap_listener'] = sorted(regs['register_tap_listener']) 106 107reg_code = "" 108 109reg_code += preamble 110 111reg_code += """ 112#include "config.h" 113 114#include <gmodule.h> 115 116/* plugins are DLLs on Windows */ 117#define WS_BUILD_DLL 118#include "ws_symbol_export.h" 119 120""" 121 122if registertype == "plugin": 123 reg_code += "#include \"epan/proto.h\"\n\n" 124if registertype == "plugin_wtap": 125 reg_code += "#include \"wiretap/wtap.h\"\n\n" 126if registertype == "plugin_codec": 127 reg_code += "#include \"wsutil/codecs.h\"\n\n" 128if registertype == "plugin_tap": 129 reg_code += "#include \"epan/tap.h\"\n\n" 130 131for symbol in regs['proto_reg']: 132 reg_code += "void proto_register_%s(void);\n" % (symbol) 133for symbol in regs['handoff_reg']: 134 reg_code += "void proto_reg_handoff_%s(void);\n" % (symbol) 135for symbol in regs['wtap_register']: 136 reg_code += "void wtap_register_%s(void);\n" % (symbol) 137for symbol in regs['codec_register']: 138 reg_code += "void codec_register_%s(void);\n" % (symbol) 139for symbol in regs['register_tap_listener']: 140 reg_code += "void register_tap_listener_%s(void);\n" % (symbol) 141 142reg_code += """ 143WS_DLL_PUBLIC_DEF const gchar plugin_version[] = PLUGIN_VERSION; 144WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR; 145WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR; 146 147WS_DLL_PUBLIC void plugin_register(void); 148 149void plugin_register(void) 150{ 151""" 152 153if registertype == "plugin": 154 for symbol in regs['proto_reg']: 155 reg_code +=" static proto_plugin plug_%s;\n\n" % (symbol) 156 reg_code +=" plug_%s.register_protoinfo = proto_register_%s;\n" % (symbol, symbol) 157 if symbol in regs['handoff_reg']: 158 reg_code +=" plug_%s.register_handoff = proto_reg_handoff_%s;\n" % (symbol, symbol) 159 else: 160 reg_code +=" plug_%s.register_handoff = NULL;\n" % (symbol) 161 reg_code += " proto_register_plugin(&plug_%s);\n" % (symbol) 162if registertype == "plugin_wtap": 163 for symbol in regs['wtap_register']: 164 reg_code += " static wtap_plugin plug_%s;\n\n" % (symbol) 165 reg_code += " plug_%s.register_wtap_module = wtap_register_%s;\n" % (symbol, symbol) 166 reg_code += " wtap_register_plugin(&plug_%s);\n" % (symbol) 167if registertype == "plugin_codec": 168 for symbol in regs['codec_register']: 169 reg_code += " static codecs_plugin plug_%s;\n\n" % (symbol) 170 reg_code += " plug_%s.register_codec_module = codec_register_%s;\n" % (symbol, symbol) 171 reg_code += " codecs_register_plugin(&plug_%s);\n" % (symbol) 172if registertype == "plugin_tap": 173 for symbol in regs['register_tap_listener']: 174 reg_code += " static tap_plugin plug_%s;\n\n" % (symbol) 175 reg_code += " plug_%s.register_tap_listener = register_tap_listener_%s;\n" % (symbol, symbol) 176 reg_code += " tap_register_plugin(&plug_%s);\n" % (symbol) 177 178reg_code += "}\n" 179 180try: 181 fh = open(final_filename, 'w') 182 fh.write(reg_code) 183 fh.close() 184except OSError: 185 sys.exit('Unable to write ' + final_filename + '.\n') 186 187# 188# Editor modelines - https://www.wireshark.org/tools/modelines.html 189# 190# Local variables: 191# c-basic-offset: 4 192# indent-tabs-mode: nil 193# End: 194# 195# vi: set shiftwidth=4 expandtab: 196# :indentSize=4:noTabs=true: 197# 198