Add python3 support to lttng-gen-tp
[lttng-ust.git] / tools / lttng-gen-tp
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2012 Yannick Brosseau <yannick.brosseau@gmail.com>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; only version 2
8 # of the License.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 from __future__ import print_function
20 import sys
21 import getopt
22 import re
23 import os
24 import subprocess
25
26 class Usage(Exception):
27 def __init__(self, msg):
28 self.msg = msg
29
30 class HeaderFile:
31 HEADER_TPL="""
32 #undef TRACEPOINT_PROVIDER
33 #define TRACEPOINT_PROVIDER {providerName}
34
35 #undef TRACEPOINT_INCLUDE
36 #define TRACEPOINT_INCLUDE "./{headerFilename}"
37
38 #ifdef __cplusplus
39 extern "C"{{
40 #endif /* __cplusplus */
41
42
43 #if !defined({includeGuard}) || defined(TRACEPOINT_HEADER_MULTI_READ)
44 #define {includeGuard}
45
46 #include <lttng/tracepoint.h>
47
48 """
49 FOOTER_TPL="""
50 #endif /* {includeGuard} */
51
52 #include <lttng/tracepoint-event.h>
53
54 #ifdef __cplusplus
55 }}
56 #endif /* __cplusplus */
57
58 """
59 def __init__(self, filename, template):
60 self.outputFilename = filename
61 self.template = template
62
63 def write(self):
64 outputFile = open(self.outputFilename,"w")
65 # Include guard macro will be created by uppercasing the filename and
66 # replacing all non alphanumeric characters with '_'
67 includeGuard = re.sub('[^0-9a-zA-Z]', '_', self.outputFilename.upper())
68
69 outputFile.write(HeaderFile.HEADER_TPL.format(providerName=self.template.domain,
70 includeGuard = includeGuard,
71 headerFilename = self.outputFilename))
72 outputFile.write(self.template.text)
73 outputFile.write(HeaderFile.FOOTER_TPL.format(includeGuard = includeGuard))
74 outputFile.close()
75
76 class CFile:
77 FILE_TPL="""
78 #define TRACEPOINT_CREATE_PROBES
79 /*
80 * The header containing our TRACEPOINT_EVENTs.
81 */
82 #define TRACEPOINT_DEFINE
83 #include "{headerFilename}"
84 """
85 def __init__(self, filename, template):
86 self.outputFilename = filename
87 self.template = template
88
89 def write(self):
90 outputFile = open(self.outputFilename,"w")
91
92 headerFilename = self.outputFilename.replace(".c",".h")
93
94 outputFile.write(CFile.FILE_TPL.format(
95 headerFilename = headerFilename))
96 outputFile.close()
97
98 class ObjFile:
99 def __init__(self, filename, template):
100 self.outputFilename = filename
101 self.template = template
102 def _detectCC(self):
103 cc = ""
104 if 'CC' in os.environ:
105 cc = os.environ['CC']
106 try:
107 subprocess.call(cc,
108 stdout=subprocess.PIPE,
109 stderr=subprocess.PIPE)
110 except OSError as msg:
111 print("Invalid CC environment variable")
112 cc = ""
113
114 else:
115 # Try c first, if that fails try gcc
116 try:
117 useCC = True
118 subprocess.call("cc",
119 stdout=subprocess.PIPE,
120 stderr=subprocess.PIPE)
121 except OSError as msg:
122 useCC = False
123 if useCC:
124 cc = "cc"
125
126 else:
127 try:
128 useGCC = True
129 subprocess.call("gcc",
130 stdout=subprocess.PIPE,
131 stderr=subprocess.PIPE)
132 except OSError as msg:
133 useGCC = False
134 if useGCC:
135 cc = "gcc"
136 return cc
137
138 def write(self):
139 cFilename = self.outputFilename.replace(".o",".c")
140 cc = self._detectCC()
141 if cc == "":
142 raise RuntimeError("No C Compiler detected")
143 if 'CFLAGS' in os.environ:
144 cflags = os.environ['CFLAGS']
145 else:
146 cflags = ""
147
148 command = cc + " -c " + cflags + " -I. -llttng-ust" + " -o " + self.outputFilename + " " + cFilename
149 if verbose:
150 print("Compile command: " + command)
151 subprocess.call(command.split())
152
153 class TemplateFile:
154 def __init__(self, filename):
155 self.domain = ""
156 self.inputFilename = filename
157 self.parseTemplate()
158
159
160 def parseTemplate(self):
161 f = open(self.inputFilename,"r")
162
163 self.text = f.read()
164
165 #Remove # comments (from input and output file) but keep
166 # #include in the output file
167 removeComments = re.compile("#[^include].*$",flags=re.MULTILINE)
168 self.text = removeComments.sub("",self.text)
169 # Remove #include directive from the parsed text
170 removePreprocess = re.compile("#.*$",flags=re.MULTILINE)
171 noPreprocess = removePreprocess.sub("", self.text)
172 #Remove // comments
173 removeLineComment = re.compile("\/\/.*$",flags=re.MULTILINE)
174 nolinecomment = removeLineComment.sub("", noPreprocess)
175 #Remove all spaces and lines
176 cleantext = re.sub("\s*","",nolinecomment)
177 #Remove multine C style comments
178 nocomment = re.sub("/\*.*?\*/","",cleantext)
179 entries = re.split("TRACEPOINT_.*?",nocomment)
180
181 for entry in entries:
182 if entry != '':
183 decomp = re.findall("(\w*?)\((\w*?),(\w*?),", entry)
184 typea = decomp[0][0]
185 domain = decomp[0][1]
186 name = decomp[0][2]
187
188 if self.domain == "":
189 self.domain = domain
190 else:
191 if self.domain != domain:
192 print("Warning: different domain provided (%s,%s)" % (self.domain, domain))
193
194 verbose=False
195
196 usage="""
197 lttng-gen-tp - Generate the LTTng-UST header and source based on a simple template
198
199 usage: lttng-gen-tp TEMPLATE_FILE [-o OUTPUT_FILE][-o OUTPUT_FILE]
200
201 If no OUTPUT_FILE is given, the .h and .c file will be generated.
202 (The basename of the template file with be used for the generated file.
203 for example sample.tp will generate sample.h, sample.c and sample.o)
204
205 When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
206 The -o option can be repeated multiple times.
207
208 The template file must contains TRACEPOINT_EVENT and TRACEPOINT_LOGLEVEL
209 as per defined in the lttng/tracepoint.h file.
210 See the lttng-ust(3) man page for more details on the format.
211 """
212 def main(argv=None):
213 if argv is None:
214 argv = sys.argv
215
216 try:
217 try:
218 opts, args = getopt.gnu_getopt(argv[1:], "ho:av", ["help","verbose"])
219 except getopt.error as msg:
220 raise Usage(msg)
221
222 except Usage as err:
223 print(err.msg, file=sys.stderr)
224 print("for help use --help", file=sys.stderr)
225 return 2
226
227 outputNames = []
228 for o, a in opts:
229 if o in ("-h", "--help"):
230 print(usage)
231 return(0)
232 if o in ("-o",""):
233 outputNames.append(a)
234 if o in ("-a",""):
235 all = True
236 if o in ("-v", "--verbose"):
237 global verbose
238 verbose = True
239 try:
240 if len(args) == 0:
241 raise Usage("No template file given")
242
243 except Usage as err:
244 print(err.msg, file=sys.stderr)
245 print("for help use --help", file=sys.stderr)
246 return 2
247
248 doCFile = None
249 doHeader = None
250 doObj = None
251 headerFilename = None
252 cFilename = None
253 objFilename = None
254
255 if len(outputNames) > 0:
256 if len(args) > 1:
257 print("Cannot process more than one input if you specify an output")
258 return(3)
259
260 for outputName in outputNames:
261 if outputName[-2:] == ".h":
262 doHeader = True
263 headerFilename = outputName
264 elif outputName[-2:] == ".c":
265 doCFile = True
266 cFilename = outputName
267 elif outputName[-2:] == ".o":
268 doObj = True
269 objFilename = outputName
270 else:
271 print("output file type unsupported")
272 return(4)
273 else:
274 doHeader = True
275 doCFile = True
276 doObj = True
277
278 # process arguments
279 for arg in args:
280 if arg[-3:] != ".tp":
281 print(arg + " does not end in .tp. Skipping.")
282 continue
283
284 tpl = None
285 try:
286 tpl = TemplateFile(arg)
287 except IOError as args:
288 print("Cannot read input file " + args.filename + " " + args.strerror)
289 return -1
290 try:
291 if doHeader:
292 if headerFilename:
293 curFilename = headerFilename
294 else:
295 curFilename = re.sub("\.tp$",".h",arg)
296 doth = HeaderFile(curFilename, tpl)
297 doth.write()
298 if doCFile:
299 if cFilename:
300 curFilename = cFilename
301 else:
302 curFilename = re.sub("\.tp$",".c",arg)
303 dotc = CFile(curFilename, tpl)
304 dotc.write()
305 if doObj:
306 if objFilename:
307 curFilename = objFilename
308 else:
309 curFilename = re.sub("\.tp$",".o",arg)
310 dotobj = ObjFile(curFilename, tpl)
311 dotobj.write()
312 except IOError as args:
313 print("Cannot write output file " + args.filename + " " + args.strerror)
314 return -1
315
316 if __name__ == "__main__":
317 sys.exit(main())
This page took 0.036392 seconds and 5 git commands to generate.