nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #!/usr/bin/env python
2 #
3 # Looks for registration routines in the protocol dissectors,
4 # and assembles C code to call all the routines.
5 #
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.
11  
12 import os
13 import sys
14 import re
15 import pickle
16 import hashlib
17 from stat import *
18  
19 VERSION_KEY = '_VERSION'
20 CUR_VERSION = '$Id$'
21  
22 #
23 # The first argument is the directory in which the source files live.
24 #
25 srcdir = sys.argv[1]
26  
27 #
28 # The second argument is either "plugin" or "dissectors"; if it's
29 # "plugin", we build a plugin.c for a plugin, and if it's
30 # "dissectors", we build a register.c for libwireshark.
31 #
32 registertype = sys.argv[2]
33 if registertype in ("plugin", "plugin_wtap"):
34 final_filename = "plugin.c"
35 cache_filename = None
36 preamble = """\
37 /*
38 * Do not modify this file. Changes will be overwritten.
39 *
40 * Generated automatically from %s.
41 */
42 """ % (sys.argv[0])
43 elif registertype in ("dissectors", "dissectorsinfile"):
44 final_filename = "register.c"
45 cache_filename = "register-cache.pkl"
46 preamble = """\
47 /*
48 * Do not modify this file. Changes will be overwritten.
49 *
50 * Generated automatically by the "register.c" target in
51 * epan/dissectors/Makefile using %s
52 * and information in epan/dissectors/register-cache.pkl.
53 *
54 * You can force this file to be regenerated completely by deleting
55 * it along with epan/dissectors/register-cache.pkl.
56 */
57 """ % (sys.argv[0])
58 else:
59 print(("Unknown output type '%s'" % registertype))
60 sys.exit(1)
61  
62  
63 #
64 # All subsequent arguments are the files to scan
65 # or the name of a file containing the files to scan
66 #
67 if registertype == "dissectorsinfile":
68 try:
69 dissector_f = open(sys.argv[3])
70 except IOError:
71 print(("Unable to open input file '%s'" % sys.argv[3]))
72 sys.exit(1)
73  
74 files = [line.rstrip() for line in dissector_f]
75 else:
76 files = sys.argv[3:]
77  
78 # Create the proper list of filenames
79 filenames = []
80 for file in files:
81 if os.path.isfile(file):
82 filenames.append(file)
83 else:
84 filenames.append(os.path.join(srcdir, file))
85  
86 if len(filenames) < 1:
87 print("No files found")
88 sys.exit(1)
89  
90  
91 # Look through all files, applying the regex to each line.
92 # If the pattern matches, save the "symbol" section to the
93 # appropriate set.
94 regs = {
95 'proto_reg': set(),
96 'handoff_reg': set(),
97 'wtap_register': set(),
98 }
99  
100 # For those that don't know Python, r"" indicates a raw string,
101 # devoid of Python escapes.
102 proto_regex = r"(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
103  
104 handoff_regex = r"(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$"
105  
106 wtap_reg_regex = r"(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
107  
108 # This table drives the pattern-matching and symbol-harvesting
109 patterns = [
110 ( 'proto_reg', re.compile(proto_regex, re.MULTILINE) ),
111 ( 'handoff_reg', re.compile(handoff_regex, re.MULTILINE) ),
112 ( 'wtap_register', re.compile(wtap_reg_regex, re.MULTILINE) ),
113 ]
114  
115 # Open our registration symbol cache
116 cache = None
117 if cache_filename:
118 try:
119 cache_file = open(cache_filename, 'rb')
120 cache = pickle.load(cache_file)
121 cache_file.close()
122 if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
123 cache = {VERSION_KEY: CUR_VERSION}
124 except:
125 cache = {VERSION_KEY: CUR_VERSION}
126  
127 print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
128  
129 # Grep
130 cache_hits = 0
131 cache_misses = 0
132 for filename in filenames:
133 file = open(filename)
134 cur_mtime = os.fstat(file.fileno())[ST_MTIME]
135 if cache and filename in cache:
136 cdict = cache[filename]
137 if cur_mtime == cdict['mtime']:
138 cache_hits += 1
139 # print "Pulling %s from cache" % (filename)
140 regs['proto_reg'] |= set(cdict['proto_reg'])
141 regs['handoff_reg'] |= set(cdict['handoff_reg'])
142 regs['wtap_register'] |= set(cdict['wtap_register'])
143 file.close()
144 continue
145 # We don't have a cache entry
146 if cache is not None:
147 cache_misses += 1
148 cache[filename] = {
149 'mtime': cur_mtime,
150 'proto_reg': [],
151 'handoff_reg': [],
152 'wtap_register': [],
153 }
154 # print "Searching %s" % (filename)
155 # Read the whole file into memory
156 contents = file.read()
157 for action in patterns:
158 regex = action[1]
159 for match in regex.finditer(contents):
160 symbol = match.group("symbol")
161 sym_type = action[0]
162 regs[sym_type].add(symbol)
163 if cache is not None:
164 # print "Caching %s for %s: %s" % (sym_type, filename, symbol)
165 cache[filename][sym_type].append(symbol)
166 # We're done with the file contents
167 contets = ""
168 file.close()
169  
170  
171 if cache is not None and cache_filename is not None:
172 cache_file = open(cache_filename, 'wb')
173 pickle.dump(cache, cache_file)
174 cache_file.close()
175 print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
176  
177 # Make sure we actually processed something
178 if len(regs['proto_reg']) < 1:
179 print("No protocol registrations found")
180 sys.exit(1)
181  
182 # Convert the sets into sorted lists to make the output pretty
183 regs['proto_reg'] = sorted(regs['proto_reg'])
184 regs['handoff_reg'] = sorted(regs['handoff_reg'])
185 regs['wtap_register'] = sorted(regs['wtap_register'])
186  
187 reg_code = ""
188  
189 reg_code += preamble
190  
191 # Make the routine to register all protocols
192 if registertype == "plugin" or registertype == "plugin_wtap":
193 reg_code += """
194 #include "config.h"
195  
196 #include <gmodule.h>
197  
198 #include "moduleinfo.h"
199  
200 /* plugins are DLLs */
201 #define WS_BUILD_DLL
202 #include "ws_symbol_export.h"
203  
204 #ifndef ENABLE_STATIC
205 WS_DLL_PUBLIC_DEF void plugin_register (void);
206 WS_DLL_PUBLIC_DEF const gchar version[] = VERSION;
207  
208 """
209 else:
210 reg_code += """
211 #include "register.h"
212  
213 """
214  
215 for symbol in regs['proto_reg']:
216 reg_code += "extern void %s(void);\n" % (symbol)
217  
218 if registertype == "plugin" or registertype == "plugin_wtap":
219 reg_code += """
220 /* Start the functions we need for the plugin stuff */
221  
222 WS_DLL_PUBLIC_DEF void
223 plugin_register (void)
224 {
225 """
226 else:
227 reg_code += """
228 #define CALLBACK_REGISTER(proto, data) \\
229 if (cb) cb(RA_REGISTER, proto, data)
230  
231 void
232 register_all_protocols(register_cb cb, gpointer cb_data)
233 {
234 """
235  
236 for symbol in regs['proto_reg']:
237 if registertype != "plugin" and registertype != "plugin_wtap":
238 reg_code += " CALLBACK_REGISTER(\"%s\", cb_data);\n" % (symbol)
239 reg_code += " %s();\n" % (symbol)
240  
241 reg_code += "}\n\n"
242  
243  
244 # Make the routine to register all protocol handoffs
245  
246 for symbol in regs['handoff_reg']:
247 reg_code += "extern void %s(void);\n" % (symbol)
248  
249 if registertype == "plugin" or registertype == "plugin_wtap":
250 reg_code += """
251 WS_DLL_PUBLIC_DEF void plugin_reg_handoff(void);
252  
253 WS_DLL_PUBLIC_DEF void
254 plugin_reg_handoff(void)
255 {
256 """
257 else:
258 reg_code += """
259 #define CALLBACK_HANDOFF(proto, data) \\
260 if (cb) cb(RA_HANDOFF, proto, data)
261  
262 void
263 register_all_protocol_handoffs(register_cb cb, gpointer cb_data)
264 {
265 """
266  
267 for symbol in regs['handoff_reg']:
268 if registertype != "plugin" and registertype != "plugin_wtap":
269 reg_code += " CALLBACK_HANDOFF(\"%s\", cb_data);\n" % (symbol)
270 reg_code += " %s();\n" % (symbol)
271  
272 reg_code += "}\n"
273  
274 if registertype == "plugin":
275 reg_code += "#endif\n"
276 elif registertype == "plugin_wtap":
277 reg_code += """
278 WS_DLL_PUBLIC_DEF void
279 register_wtap_module(void)
280 {
281 """
282  
283 for symbol in regs['wtap_register']:
284 line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
285 reg_code += line
286  
287 reg_code += """
288 }
289 #endif
290 """
291  
292 else:
293 reg_code += """
294 static gulong proto_reg_count(void)
295 {
296 return %(proto_reg_len)d;
297 }
298  
299 static gulong handoff_reg_count(void)
300 {
301 return %(handoff_reg_len)d;
302 }
303  
304 gulong register_count(void)
305 {
306 return proto_reg_count() + handoff_reg_count();
307 }
308 """ % {
309 'proto_reg_len': len(regs['proto_reg']),
310 'handoff_reg_len': len(regs['handoff_reg'])
311 }
312  
313  
314 # Compare current and new content and update the file if anything has changed.
315  
316 try: # Python >= 2.6, >= 3.0
317 reg_code_bytes = bytes(reg_code.encode('utf-8'))
318 except:
319 reg_code_bytes = reg_code
320  
321 new_hash = hashlib.sha1(reg_code_bytes).hexdigest()
322  
323 try:
324 fh = open(final_filename, 'rb')
325 cur_hash = hashlib.sha1(fh.read()).hexdigest()
326 fh.close()
327 except:
328 cur_hash = ''
329  
330 try:
331 if new_hash != cur_hash:
332 print(('Updating ' + final_filename))
333 fh = open(final_filename, 'w')
334 fh.write(reg_code)
335 fh.close()
336 else:
337 print((final_filename + ' unchanged.'))
338 os.utime(final_filename, None)
339 except OSError:
340 sys.exit('Unable to write ' + final_filename + '.\n')
341  
342 #
343 # Editor modelines - http://www.wireshark.org/tools/modelines.html
344 #
345 # Local variables:
346 # c-basic-offset: 4
347 # indent-tabs-mode: nil
348 # End:
349 #
350 # vi: set shiftwidth=4 expandtab:
351 # :indentSize=4:noTabs=true:
352 #