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