aboutsummaryrefslogtreecommitdiffstats
path: root/tools/make-plugin-reg.py
diff options
context:
space:
mode:
authorJoão Valverde <joao.valverde@tecnico.ulisboa.pt>2017-11-19 00:20:20 +0000
committerAnders Broman <a.broman58@gmail.com>2017-11-20 06:03:08 +0000
commitfe0c2b04853226b64a1aa17fbef6257c856e3fd9 (patch)
treed09f8b8c6fc44b402a17ab09d3d061311cccfb7f /tools/make-plugin-reg.py
parent129cb60f56f42e58b9e589d79ac3ee317066d43e (diff)
Rewrite make-dissector-reg.py in C
The output compares equal to make-dissector-reg.py and the regex should be more robust (multiline, complete start of function definition). The primary motivation is to clean up the python script. This small binary results in much cleaner code. The python script is used only to generate plugin code, therefore it is renamed. Also in my casual measurements the C code is much faster (without cache) than the python script with the cache. Change-Id: Id4e8cac3c836d56775aba4819357a95ef19bcb85 Reviewed-on: https://code.wireshark.org/review/24497 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'tools/make-plugin-reg.py')
-rwxr-xr-xtools/make-plugin-reg.py197
1 files changed, 197 insertions, 0 deletions
diff --git a/tools/make-plugin-reg.py b/tools/make-plugin-reg.py
new file mode 100755
index 0000000000..de95cb1082
--- /dev/null
+++ b/tools/make-plugin-reg.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+#
+# Looks for registration routines in the plugin dissectors,
+# and assembles C code to call all the routines.
+#
+
+import os
+import sys
+import re
+import hashlib
+from stat import *
+
+#
+# The first argument is the directory in which the source files live.
+#
+srcdir = sys.argv[1]
+#
+# The second argument is either "plugin" or "plugin_wtap".
+#
+registertype = sys.argv[2]
+#
+# All subsequent arguments are the files to scan.
+#
+files = sys.argv[3:]
+
+final_filename = "plugin.c"
+preamble = """\
+/*
+ * Do not modify this file. Changes will be overwritten.
+ *
+ * Generated automatically from %s.
+ */
+""" % (sys.argv[0])
+
+# Create the proper list of filenames
+filenames = []
+for file in files:
+ if os.path.isfile(file):
+ filenames.append(file)
+ else:
+ filenames.append(os.path.join(srcdir, file))
+
+if len(filenames) < 1:
+ print("No files found")
+ sys.exit(1)
+
+
+# Look through all files, applying the regex to each line.
+# If the pattern matches, save the "symbol" section to the
+# appropriate set.
+regs = {
+ 'proto_reg': set(),
+ 'handoff_reg': set(),
+ 'wtap_register': set(),
+ }
+
+# For those that don't know Python, r"" indicates a raw string,
+# devoid of Python escapes.
+proto_regex = r"(?P<symbol>\bproto_register_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
+
+handoff_regex = r"(?P<symbol>\bproto_reg_handoff_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
+
+wtap_reg_regex = r"(?P<symbol>\bwtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
+
+# This table drives the pattern-matching and symbol-harvesting
+patterns = [
+ ( 'proto_reg', re.compile(proto_regex, re.MULTILINE) ),
+ ( 'handoff_reg', re.compile(handoff_regex, re.MULTILINE) ),
+ ( 'wtap_register', re.compile(wtap_reg_regex, re.MULTILINE) ),
+ ]
+
+# Grep
+for filename in filenames:
+ file = open(filename)
+ cur_mtime = os.fstat(file.fileno())[ST_MTIME]
+ # Read the whole file into memory
+ contents = file.read()
+ for action in patterns:
+ regex = action[1]
+ for match in regex.finditer(contents):
+ symbol = match.group("symbol")
+ sym_type = action[0]
+ regs[sym_type].add(symbol)
+ # We're done with the file contents
+ del contents
+ file.close()
+
+# Make sure we actually processed something
+if len(regs['proto_reg']) < 1:
+ print("No protocol registrations found")
+ sys.exit(1)
+
+# Convert the sets into sorted lists to make the output pretty
+regs['proto_reg'] = sorted(regs['proto_reg'])
+regs['handoff_reg'] = sorted(regs['handoff_reg'])
+regs['wtap_register'] = sorted(regs['wtap_register'])
+
+reg_code = ""
+
+reg_code += preamble
+
+reg_code += """
+#include "config.h"
+
+#include <gmodule.h>
+
+#include "moduleinfo.h"
+
+/* plugins are DLLs */
+#define WS_BUILD_DLL
+#include "ws_symbol_export.h"
+
+WS_DLL_PUBLIC_DEF void plugin_register (void);
+
+WS_DLL_PUBLIC_DEF const gchar plugin_version[] = VERSION;
+WS_DLL_PUBLIC_DEF const gchar plugin_release[] = VERSION_RELEASE;
+
+"""
+
+for symbol in regs['proto_reg']:
+ reg_code += "extern void %s(void);\n" % (symbol)
+
+reg_code += """
+WS_DLL_PUBLIC_DEF void
+plugin_register (void)
+{
+"""
+
+for symbol in regs['proto_reg']:
+ reg_code += " %s();\n" % (symbol)
+
+reg_code += "}\n\n"
+
+for symbol in regs['handoff_reg']:
+ reg_code += "extern void %s(void);\n" % (symbol)
+
+reg_code += """
+WS_DLL_PUBLIC_DEF void plugin_reg_handoff(void);
+
+WS_DLL_PUBLIC_DEF void
+plugin_reg_handoff(void)
+{
+"""
+
+for symbol in regs['handoff_reg']:
+ reg_code += " %s();\n" % (symbol)
+reg_code += "}\n"
+
+if registertype == "plugin_wtap":
+ reg_code += """
+WS_DLL_PUBLIC_DEF void
+register_wtap_module(void)
+{
+"""
+
+ for symbol in regs['wtap_register']:
+ reg_code += " {extern void %s (void); %s ();}\n" % (symbol, symbol)
+ reg_code += "}"
+
+# Compare current and new content and update the file if anything has changed.
+
+try: # Python >= 2.6, >= 3.0
+ reg_code_bytes = bytes(reg_code.encode('utf-8'))
+except:
+ reg_code_bytes = reg_code
+
+new_hash = hashlib.sha1(reg_code_bytes).hexdigest()
+
+try:
+ fh = open(final_filename, 'rb')
+ cur_hash = hashlib.sha1(fh.read()).hexdigest()
+ fh.close()
+except:
+ cur_hash = ''
+
+try:
+ if new_hash != cur_hash:
+ print(('Updating ' + final_filename))
+ fh = open(final_filename, 'w')
+ fh.write(reg_code)
+ fh.close()
+ else:
+ print((final_filename + ' unchanged.'))
+except OSError:
+ sys.exit('Unable to write ' + final_filename + '.\n')
+
+#
+# Editor modelines - http://www.wireshark.org/tools/modelines.html
+#
+# Local variables:
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+#
+# vi: set shiftwidth=4 expandtab:
+# :indentSize=4:noTabs=true:
+#