The Styleguide section has been moved to the Wireshark Developer's Guide.
[obnox/wireshark/wip.git] / tools / make-tap-reg.py
1 #!/usr/bin/env python
2 #
3 # Looks for registration routines in the taps,
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 # $Id$
13
14 import os
15 import sys
16 import re
17 import pickle
18 from stat import *
19
20 #
21 # The first argument is the directory in which the source files live.
22 #
23 srcdir = sys.argv[1]
24
25 #
26 # The second argument is  "taps".
27 #
28 registertype = sys.argv[2]
29 if registertype == "taps":
30         tmp_filename = "wireshark-tap-register.c-tmp"
31         final_filename = "wireshark-tap-register.c"
32         cache_filename = "wireshark-tap-register-cache.pkl"
33 else:
34         print "Unknown output type '%s'" % registertype
35         sys.exit(1)
36
37
38 #
39 # All subsequent arguments are the files to scan.
40 #
41 files = sys.argv[3:]
42
43 # Create the proper list of filenames
44 filenames = []
45 for file in files:
46         if os.path.isfile(file):
47                 filenames.append(file)
48         else:
49                 filenames.append("%s/%s" % (srcdir, file))
50
51 if len(filenames) < 1:
52         print "No files found"
53         sys.exit(1)
54
55
56 # Look through all files, applying the regex to each line.
57 # If the pattern matches, save the "symbol" section to the
58 # appropriate array.
59 regs = {
60         'tap_reg': [],
61         }
62
63 # For those that don't know Python, r"" indicates a raw string,
64 # devoid of Python escapes.
65 tap_regex0 = r"^(?P<symbol>register_tap_listener_[_A-Za-z0-9]+)\s*\([^;]+$"
66 tap_regex1 = r"void\s+(?P<symbol>register_tap_listener_[_A-Za-z0-9]+)\s*\([^;]+$"
67
68 # This table drives the pattern-matching and symbol-harvesting
69 patterns = [
70         ( 'tap_reg', re.compile(tap_regex0) ),
71         ( 'tap_reg', re.compile(tap_regex1) ),
72         ]
73
74 # Open our registration symbol cache
75 cache = None
76 if cache_filename:
77         try:
78                 cache_file = open(cache_filename, 'rb')
79                 cache = pickle.load(cache_file)
80                 cache_file.close()
81         except:
82                 cache = {}
83
84 # Grep
85 for filename in filenames:
86         file = open(filename)
87         cur_mtime = os.fstat(file.fileno())[ST_MTIME]
88         if cache and cache.has_key(filename):
89                 cdict = cache[filename]
90                 if cur_mtime == cdict['mtime']:
91 #                       print "Pulling %s from cache" % (filename)
92                         regs['tap_reg'].extend(cdict['tap_reg'])
93                         file.close()
94                         continue
95         # We don't have a cache entry
96         if cache is not None:
97                 cache[filename] = {
98                         'mtime': cur_mtime,
99                         'tap_reg': [],
100                         }
101 #       print "Searching %s" % (filename)
102         for line in file.readlines():
103                 for action in patterns:
104                         regex = action[1]
105                         match = regex.search(line)
106                         if match:
107                                 symbol = match.group("symbol")
108                                 sym_type = action[0]
109                                 regs[sym_type].append(symbol)
110                                 if cache is not None:
111 #                                       print "Caching %s for %s: %s" % (sym_type, filename, symbol)
112                                         cache[filename][sym_type].append(symbol)
113         file.close()
114
115 if cache is not None and cache_filename is not None:
116         cache_file = open(cache_filename, 'wb')
117         pickle.dump(cache, cache_file)
118         cache_file.close()
119
120 # Make sure we actually processed something
121 if len(regs['tap_reg']) < 1:
122         print "No protocol registrations found"
123         sys.exit(1)
124
125 # Sort the lists to make them pretty
126 regs['tap_reg'].sort()
127
128 reg_code = open(tmp_filename, "w")
129
130 reg_code.write("/* Do not modify this file.  */\n")
131 reg_code.write("/* It is created automatically by the Makefile.  */\n")
132
133 # Make the routine to register all taps
134 reg_code.write("""
135 #include "register.h"
136 void register_all_tap_listeners(void) {
137 """);
138
139 for symbol in regs['tap_reg']:
140         line = "  {extern void %s (void); %s ();}\n" % (symbol, symbol)
141         reg_code.write(line)
142
143 reg_code.write("}\n")
144
145
146 # Close the file
147 reg_code.close()
148
149 # Remove the old final_file if it exists.
150 try:
151         os.stat(final_filename)
152         os.remove(final_filename)
153 except OSError:
154         pass
155
156 # Move from tmp file to final file
157 os.rename(tmp_filename, final_filename)
158
159