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