3 # Looks for registration routines in the protocol dissectors,
4 # and assembles C code to call all the routines.
6 # This is a Python version of the make-reg-dotc shell script.
7 # Running the shell script on Win32 is very very slow because of
8 # all the process-launching that goes on --- multiple greps and
9 # seds for each input file. I wrote this python version so that
10 # less processes would have to be started.
21 VERSION_KEY = '_VERSION'
25 # The first argument is the directory in which the source files live.
30 # The second argument is either "plugin" or "dissectors"; if it's
31 # "plugin", we build a plugin.c for a plugin, and if it's
32 # "dissectors", we build a register.c for libwireshark.
34 registertype = sys.argv[2]
35 if registertype in ("plugin", "plugin_wtap"):
36 final_filename = "plugin.c"
40 * Do not modify this file. Changes will be overwritten.
42 * Generated automatically from %s.
45 elif registertype in ("dissectors", "dissectorsinfile"):
46 final_filename = "register.c"
47 cache_filename = "register-cache.pkl"
50 * Do not modify this file. Changes will be overwritten.
52 * Generated automatically by the "register.c" target in
53 * epan/dissectors/Makefile or Makefile.nmake using
55 * and information in epan/dissectors/register-cache.pkl.
57 * You can force this file to be regenerated completely by deleting
58 * it along with epan/dissectors/register-cache.pkl.
62 print(("Unknown output type '%s'" % registertype))
67 # All subsequent arguments are the files to scan
68 # or the name of a file containing the files to scan
70 if registertype == "dissectorsinfile":
72 dissector_f = open(sys.argv[3])
74 print(("Unable to open input file '%s'" % sys.argv[3]))
77 files = [line.rstrip() for line in dissector_f]
81 # Create the proper list of filenames
84 if os.path.isfile(file):
85 filenames.append(file)
87 filenames.append(os.path.join(srcdir, file))
89 if len(filenames) < 1:
90 print("No files found")
94 # Look through all files, applying the regex to each line.
95 # If the pattern matches, save the "symbol" section to the
100 'wtap_register': set(),
103 # For those that don't know Python, r"" indicates a raw string,
104 # devoid of Python escapes.
105 proto_regex = r"(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
107 handoff_regex = r"(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
109 wtap_reg_regex = r"(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
111 # This table drives the pattern-matching and symbol-harvesting
113 ( 'proto_reg', re.compile(proto_regex, re.MULTILINE) ),
114 ( 'handoff_reg', re.compile(handoff_regex, re.MULTILINE) ),
115 ( 'wtap_register', re.compile(wtap_reg_regex, re.MULTILINE) ),
118 # Open our registration symbol cache
122 cache_file = open(cache_filename, 'rb')
123 cache = pickle.load(cache_file)
125 if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
126 cache = {VERSION_KEY: CUR_VERSION}
128 cache = {VERSION_KEY: CUR_VERSION}
130 print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
135 for filename in filenames:
136 file = open(filename)
137 cur_mtime = os.fstat(file.fileno())[ST_MTIME]
138 if cache and filename in cache:
139 cdict = cache[filename]
140 if cur_mtime == cdict['mtime']:
142 # print "Pulling %s from cache" % (filename)
143 regs['proto_reg'] |= set(cdict['proto_reg'])
144 regs['handoff_reg'] |= set(cdict['handoff_reg'])
145 regs['wtap_register'] |= set(cdict['wtap_register'])
148 # We don't have a cache entry
149 if cache is not None:
157 # print "Searching %s" % (filename)
158 # Read the whole file into memory
159 contents = file.read()
160 for action in patterns:
162 for match in regex.finditer(contents):
163 symbol = match.group("symbol")
165 regs[sym_type].add(symbol)
166 if cache is not None:
167 # print "Caching %s for %s: %s" % (sym_type, filename, symbol)
168 cache[filename][sym_type].append(symbol)
169 # We're done with the file contents
174 if cache is not None and cache_filename is not None:
175 cache_file = open(cache_filename, 'wb')
176 pickle.dump(cache, cache_file)
178 print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
180 # Make sure we actually processed something
181 if len(regs['proto_reg']) < 1:
182 print("No protocol registrations found")
185 # Convert the sets into sorted lists to make the output pretty
186 regs['proto_reg'] = sorted(regs['proto_reg'])
187 regs['handoff_reg'] = sorted(regs['handoff_reg'])
188 regs['wtap_register'] = sorted(regs['wtap_register'])
194 # Make the routine to register all protocols
195 if registertype == "plugin" or registertype == "plugin_wtap":
201 #include "moduleinfo.h"
203 /* plugins are DLLs */
205 #include "ws_symbol_export.h"
207 #ifndef ENABLE_STATIC
208 WS_DLL_PUBLIC_DEF void plugin_register (void);
209 WS_DLL_PUBLIC_DEF const gchar version[] = VERSION;
211 /* Start the functions we need for the plugin stuff */
213 WS_DLL_PUBLIC_DEF void
214 plugin_register (void)
219 #include "register.h"
221 register_all_protocols(register_cb cb, gpointer client_data)
225 for symbol in regs['proto_reg']:
226 if registertype == "plugin" or registertype == "plugin_wtap":
227 reg_code += " {extern void %s (void); %s ();}\n" % (symbol, symbol)
229 reg_code += " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
234 # Make the routine to register all protocol handoffs
235 if registertype == "plugin" or registertype == "plugin_wtap":
237 WS_DLL_PUBLIC_DEF void plugin_reg_handoff(void);
239 WS_DLL_PUBLIC_DEF void
240 plugin_reg_handoff(void)
246 register_all_protocol_handoffs(register_cb cb, gpointer client_data)
250 for symbol in regs['handoff_reg']:
251 if registertype == "plugin" or registertype == "plugin_wtap":
252 reg_code += " {extern void %s (void); %s ();}\n" % (symbol, symbol)
254 reg_code += " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
258 if registertype == "plugin":
259 reg_code += "#endif\n"
260 elif registertype == "plugin_wtap":
262 WS_DLL_PUBLIC_DEF void
263 register_wtap_module(void)
267 for symbol in regs['wtap_register']:
268 line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
278 static gulong proto_reg_count(void)
280 return %(proto_reg_len)d;
283 static gulong handoff_reg_count(void)
285 return %(handoff_reg_len)d;
288 gulong register_count(void)
290 return proto_reg_count() + handoff_reg_count();
294 'proto_reg_len': len(regs['proto_reg']),
295 'handoff_reg_len': len(regs['handoff_reg'])
299 # Compare current and new content and update the file if anything has changed.
301 try: # Python >= 2.6, >= 3.0
302 reg_code_bytes = bytes(reg_code.encode('utf-8'))
304 reg_code_bytes = reg_code
306 new_hash = hashlib.sha1(reg_code_bytes).hexdigest()
309 fh = open(final_filename, 'rb')
310 cur_hash = hashlib.sha1(fh.read()).hexdigest()
316 if new_hash != cur_hash:
317 print(('Updating ' + final_filename))
318 fh = open(final_filename, 'w')
322 print((final_filename + ' unchanged.'))
323 os.utime(final_filename, None)
325 sys.exit('Unable to write ' + final_filename + '.\n')
328 # Editor modelines - http://www.wireshark.org/tools/modelines.html
332 # indent-tabs-mode: nil
335 # vi: set shiftwidth=4 expandtab:
336 # :indentSize=4:noTabs=true: