312 lines
7.7 KiB
Python
312 lines
7.7 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Looks for registration routines in the protocol dissectors,
|
||
|
# and assembles C code to call all the routines.
|
||
|
#
|
||
|
# This is a Python version of the make-reg-dotc shell script.
|
||
|
# Running the shell script on Win32 is very very slow because of
|
||
|
# all the process-launching that goes on --- multiple greps and
|
||
|
# seds for each input file. I wrote this python version so that
|
||
|
# less processes would have to be started.
|
||
|
#
|
||
|
# $Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import re
|
||
|
import pickle
|
||
|
from stat import *
|
||
|
|
||
|
VERSION_KEY = '_VERSION'
|
||
|
CUR_VERSION = '$Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $'
|
||
|
|
||
|
#
|
||
|
# The first argument is the directory in which the source files live.
|
||
|
#
|
||
|
srcdir = sys.argv[1]
|
||
|
|
||
|
#
|
||
|
# The second argument is either "plugin" or "dissectors"; if it's
|
||
|
# "plugin", we build a plugin.c for a plugin, and if it's
|
||
|
# "dissectors", we build a register.c for libwireshark.
|
||
|
#
|
||
|
registertype = sys.argv[2]
|
||
|
if registertype == "plugin" or registertype == "plugin_wtap":
|
||
|
tmp_filename = "plugin.c-tmp"
|
||
|
final_filename = "plugin.c"
|
||
|
cache_filename = None
|
||
|
preamble = """\
|
||
|
/*
|
||
|
* Do not modify this file.
|
||
|
*
|
||
|
* It is created automatically by Makefile or Makefile.nmake.
|
||
|
*/
|
||
|
"""
|
||
|
elif registertype == "dissectors":
|
||
|
tmp_filename = "register.c-tmp"
|
||
|
final_filename = "register.c"
|
||
|
cache_filename = "register-cache.pkl"
|
||
|
preamble = """\
|
||
|
/*
|
||
|
* Do not modify this file.
|
||
|
*
|
||
|
* It is created automatically by the "register.c" target in
|
||
|
* epan/dissectors/Makefile or Makefile.nmake using information in
|
||
|
* epan/dissectors/register-cache.pkl.
|
||
|
*
|
||
|
* You can force this file to be regenerated completely by deleting
|
||
|
* it along with epan/dissectors/register-cache.pkl.
|
||
|
*/
|
||
|
"""
|
||
|
else:
|
||
|
print(("Unknown output type '%s'" % registertype))
|
||
|
sys.exit(1)
|
||
|
|
||
|
|
||
|
#
|
||
|
# All subsequent arguments are the files to scan.
|
||
|
#
|
||
|
files = sys.argv[3:]
|
||
|
|
||
|
# 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 array.
|
||
|
regs = {
|
||
|
'proto_reg': [],
|
||
|
'handoff_reg': [],
|
||
|
'wtap_register': [],
|
||
|
}
|
||
|
|
||
|
# For those that don't know Python, r"" indicates a raw string,
|
||
|
# devoid of Python escapes.
|
||
|
proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
|
||
|
handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
|
||
|
wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
|
||
|
|
||
|
# This table drives the pattern-matching and symbol-harvesting
|
||
|
patterns = [
|
||
|
( 'proto_reg', re.compile(proto_regex0) ),
|
||
|
( 'proto_reg', re.compile(proto_regex1) ),
|
||
|
( 'handoff_reg', re.compile(handoff_regex0) ),
|
||
|
( 'handoff_reg', re.compile(handoff_regex1) ),
|
||
|
( 'wtap_register', re.compile(wtap_reg_regex0) ),
|
||
|
( 'wtap_register', re.compile(wtap_reg_regex1) ),
|
||
|
]
|
||
|
|
||
|
# Open our registration symbol cache
|
||
|
cache = None
|
||
|
if cache_filename:
|
||
|
try:
|
||
|
cache_file = open(cache_filename, 'rb')
|
||
|
cache = pickle.load(cache_file)
|
||
|
cache_file.close()
|
||
|
if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
|
||
|
cache = {VERSION_KEY: CUR_VERSION}
|
||
|
except:
|
||
|
cache = {VERSION_KEY: CUR_VERSION}
|
||
|
|
||
|
print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
|
||
|
|
||
|
# Grep
|
||
|
cache_hits = 0
|
||
|
cache_misses = 0
|
||
|
for filename in filenames:
|
||
|
file = open(filename)
|
||
|
cur_mtime = os.fstat(file.fileno())[ST_MTIME]
|
||
|
if cache and filename in cache:
|
||
|
cdict = cache[filename]
|
||
|
if cur_mtime == cdict['mtime']:
|
||
|
cache_hits += 1
|
||
|
# print "Pulling %s from cache" % (filename)
|
||
|
regs['proto_reg'].extend(cdict['proto_reg'])
|
||
|
regs['handoff_reg'].extend(cdict['handoff_reg'])
|
||
|
regs['wtap_register'].extend(cdict['wtap_register'])
|
||
|
file.close()
|
||
|
continue
|
||
|
# We don't have a cache entry
|
||
|
if cache is not None:
|
||
|
cache_misses += 1
|
||
|
cache[filename] = {
|
||
|
'mtime': cur_mtime,
|
||
|
'proto_reg': [],
|
||
|
'handoff_reg': [],
|
||
|
'wtap_register': [],
|
||
|
}
|
||
|
# print "Searching %s" % (filename)
|
||
|
for line in file.readlines():
|
||
|
for action in patterns:
|
||
|
regex = action[1]
|
||
|
match = regex.search(line)
|
||
|
if match:
|
||
|
symbol = match.group("symbol")
|
||
|
sym_type = action[0]
|
||
|
regs[sym_type].append(symbol)
|
||
|
if cache is not None:
|
||
|
# print "Caching %s for %s: %s" % (sym_type, filename, symbol)
|
||
|
cache[filename][sym_type].append(symbol)
|
||
|
file.close()
|
||
|
|
||
|
|
||
|
if cache is not None and cache_filename is not None:
|
||
|
cache_file = open(cache_filename, 'wb')
|
||
|
pickle.dump(cache, cache_file)
|
||
|
cache_file.close()
|
||
|
print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
|
||
|
|
||
|
# Make sure we actually processed something
|
||
|
if len(regs['proto_reg']) < 1:
|
||
|
print("No protocol registrations found")
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Sort the lists to make them pretty
|
||
|
regs['proto_reg'].sort()
|
||
|
regs['handoff_reg'].sort()
|
||
|
regs['wtap_register'].sort()
|
||
|
|
||
|
reg_code = open(tmp_filename, "w")
|
||
|
|
||
|
reg_code.write(preamble)
|
||
|
|
||
|
# Make the routine to register all protocols
|
||
|
if registertype == "plugin" or registertype == "plugin_wtap":
|
||
|
reg_code.write("""
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include <gmodule.h>
|
||
|
|
||
|
#include "moduleinfo.h"
|
||
|
|
||
|
#ifndef ENABLE_STATIC
|
||
|
G_MODULE_EXPORT const gchar version[] = VERSION;
|
||
|
|
||
|
/* Start the functions we need for the plugin stuff */
|
||
|
|
||
|
G_MODULE_EXPORT void
|
||
|
plugin_register (void)
|
||
|
{
|
||
|
""");
|
||
|
else:
|
||
|
reg_code.write("""
|
||
|
#include "register.h"
|
||
|
void
|
||
|
register_all_protocols(register_cb cb, gpointer client_data)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
for symbol in regs['proto_reg']:
|
||
|
if registertype == "plugin" or registertype == "plugin_wtap":
|
||
|
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||
|
else:
|
||
|
line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("}\n")
|
||
|
|
||
|
|
||
|
# Make the routine to register all protocol handoffs
|
||
|
if registertype == "plugin" or registertype == "plugin_wtap":
|
||
|
reg_code.write("""
|
||
|
G_MODULE_EXPORT void
|
||
|
plugin_reg_handoff(void)
|
||
|
{
|
||
|
""");
|
||
|
else:
|
||
|
reg_code.write("""
|
||
|
void
|
||
|
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
for symbol in regs['handoff_reg']:
|
||
|
if registertype == "plugin" or registertype == "plugin_wtap":
|
||
|
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||
|
else:
|
||
|
line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("}\n")
|
||
|
|
||
|
if registertype == "plugin":
|
||
|
reg_code.write("#endif\n");
|
||
|
elif registertype == "plugin_wtap":
|
||
|
reg_code.write("""
|
||
|
G_MODULE_EXPORT void
|
||
|
register_wtap_module(void)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
for symbol in regs['wtap_register']:
|
||
|
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("}\n");
|
||
|
reg_code.write("#endif\n");
|
||
|
else:
|
||
|
reg_code.write("""
|
||
|
static gulong proto_reg_count(void)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
line = " return %d;\n" % len(regs['proto_reg'])
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("""
|
||
|
}
|
||
|
""");
|
||
|
reg_code.write("""
|
||
|
static gulong handoff_reg_count(void)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
line = " return %d;\n" % len(regs['handoff_reg'])
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("""
|
||
|
}
|
||
|
""");
|
||
|
reg_code.write("""
|
||
|
gulong register_count(void)
|
||
|
{
|
||
|
""");
|
||
|
|
||
|
line = " return proto_reg_count() + handoff_reg_count();"
|
||
|
reg_code.write(line)
|
||
|
|
||
|
reg_code.write("""
|
||
|
}\n
|
||
|
""");
|
||
|
|
||
|
|
||
|
# Close the file
|
||
|
reg_code.close()
|
||
|
|
||
|
# Remove the old final_file if it exists.
|
||
|
try:
|
||
|
os.stat(final_filename)
|
||
|
os.remove(final_filename)
|
||
|
except OSError:
|
||
|
pass
|
||
|
|
||
|
# Move from tmp file to final file
|
||
|
os.rename(tmp_filename, final_filename)
|