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