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