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