Add python3 support to lttng-gen-tp
[lttng-ust.git] / tools / lttng-gen-tp
CommitLineData
b25c5b37
YB
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
2d9c7df1 19from __future__ import print_function
b25c5b37
YB
20import sys
21import getopt
22import re
db06a0a2
YB
23import os
24import subprocess
b25c5b37
YB
25
26class Usage(Exception):
27 def __init__(self, msg):
28 self.msg = msg
29
30class HeaderFile:
31 HEADER_TPL="""
32#undef TRACEPOINT_PROVIDER
33#define TRACEPOINT_PROVIDER {providerName}
34
45f399e8
MD
35#undef TRACEPOINT_INCLUDE
36#define TRACEPOINT_INCLUDE "./{headerFilename}"
b25c5b37
YB
37
38#ifdef __cplusplus
9cc0a748
MD
39extern "C"{{
40#endif /* __cplusplus */
b25c5b37
YB
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}}
9cc0a748 56#endif /* __cplusplus */
b25c5b37
YB
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")
8ed68685
YB
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())
b25c5b37
YB
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
76class 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
db06a0a2
YB
98class ObjFile:
99 def __init__(self, filename, template):
100 self.outputFilename = filename
101 self.template = template
102 def _detectCC(self):
103 cc = ""
2d9c7df1 104 if 'CC' in os.environ:
db06a0a2
YB
105 cc = os.environ['CC']
106 try:
107 subprocess.call(cc,
108 stdout=subprocess.PIPE,
109 stderr=subprocess.PIPE)
2d9c7df1
ZT
110 except OSError as msg:
111 print("Invalid CC environment variable")
db06a0a2
YB
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)
2d9c7df1 121 except OSError as msg:
db06a0a2
YB
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)
2d9c7df1 132 except OSError as msg:
db06a0a2
YB
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")
2d9c7df1 143 if 'CFLAGS' in os.environ:
db06a0a2
YB
144 cflags = os.environ['CFLAGS']
145 else:
146 cflags = ""
147
148 command = cc + " -c " + cflags + " -I. -llttng-ust" + " -o " + self.outputFilename + " " + cFilename
0794b3f6
YB
149 if verbose:
150 print("Compile command: " + command)
db06a0a2
YB
151 subprocess.call(command.split())
152
b25c5b37
YB
153class 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
0794b3f6
YB
165 #Remove # comments (from input and output file) but keep
166 # #include in the output file
167 removeComments = re.compile("#[^include].*$",flags=re.MULTILINE)
c233fe11 168 self.text = removeComments.sub("",self.text)
0794b3f6
YB
169 # Remove #include directive from the parsed text
170 removePreprocess = re.compile("#.*$",flags=re.MULTILINE)
171 noPreprocess = removePreprocess.sub("", self.text)
b25c5b37 172 #Remove // comments
c233fe11 173 removeLineComment = re.compile("\/\/.*$",flags=re.MULTILINE)
0794b3f6 174 nolinecomment = removeLineComment.sub("", noPreprocess)
b25c5b37
YB
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:
2d9c7df1 192 print("Warning: different domain provided (%s,%s)" % (self.domain, domain))
b25c5b37 193
0794b3f6
YB
194verbose=False
195
b25c5b37
YB
196usage="""
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.
db06a0a2 203 for example sample.tp will generate sample.h, sample.c and sample.o)
b25c5b37 204
db06a0a2 205 When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
b25c5b37
YB
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"""
212def main(argv=None):
213 if argv is None:
214 argv = sys.argv
215
216 try:
217 try:
0794b3f6 218 opts, args = getopt.gnu_getopt(argv[1:], "ho:av", ["help","verbose"])
2d9c7df1 219 except getopt.error as msg:
b25c5b37
YB
220 raise Usage(msg)
221
2d9c7df1
ZT
222 except Usage as err:
223 print(err.msg, file=sys.stderr)
224 print("for help use --help", file=sys.stderr)
b25c5b37
YB
225 return 2
226
227 outputNames = []
228 for o, a in opts:
229 if o in ("-h", "--help"):
2d9c7df1 230 print(usage)
b25c5b37
YB
231 return(0)
232 if o in ("-o",""):
233 outputNames.append(a)
234 if o in ("-a",""):
235 all = True
0794b3f6
YB
236 if o in ("-v", "--verbose"):
237 global verbose
238 verbose = True
a719be64
CB
239 try:
240 if len(args) == 0:
241 raise Usage("No template file given")
242
2d9c7df1
ZT
243 except Usage as err:
244 print(err.msg, file=sys.stderr)
245 print("for help use --help", file=sys.stderr)
a719be64 246 return 2
b25c5b37
YB
247
248 doCFile = None
249 doHeader = None
db06a0a2 250 doObj = None
b25c5b37
YB
251 headerFilename = None
252 cFilename = None
db06a0a2 253 objFilename = None
b25c5b37
YB
254
255 if len(outputNames) > 0:
256 if len(args) > 1:
2d9c7df1 257 print("Cannot process more than one input if you specify an output")
b25c5b37
YB
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":
db06a0a2
YB
268 doObj = True
269 objFilename = outputName
b25c5b37 270 else:
2d9c7df1 271 print("output file type unsupported")
b25c5b37
YB
272 return(4)
273 else:
274 doHeader = True
275 doCFile = True
db06a0a2 276 doObj = True
b25c5b37
YB
277
278 # process arguments
279 for arg in args:
7cd5a840 280 if arg[-3:] != ".tp":
2d9c7df1 281 print(arg + " does not end in .tp. Skipping.")
7cd5a840 282 continue
b25c5b37 283
44745fc1
YB
284 tpl = None
285 try:
286 tpl = TemplateFile(arg)
287 except IOError as args:
2d9c7df1 288 print("Cannot read input file " + args.filename + " " + args.strerror)
44745fc1
YB
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:
2d9c7df1 313 print("Cannot write output file " + args.filename + " " + args.strerror)
44745fc1 314 return -1
2d9c7df1 315
b25c5b37
YB
316if __name__ == "__main__":
317 sys.exit(main())
This page took 0.0363329999999999 seconds and 4 git commands to generate.