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