2f468cbb79abde4fbf580208cc4728df91af548a
[lttng-ust.git] / tools / lttng-gen-tp
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
19 import sys
20 import getopt
21 import re
22 import os
23 import subprocess
24
25 class Usage(Exception):
26 def __init__(self, msg):
27 self.msg = msg
28
29 class HeaderFile:
30 HEADER_TPL="""
31 #undef TRACEPOINT_PROVIDER
32 #define TRACEPOINT_PROVIDER {providerName}
33
34 #undef TRACEPOINT_INCLUDE
35 #define TRACEPOINT_INCLUDE "./{headerFilename}"
36
37 #ifdef __cplusplus
38 extern "C"{{
39 #endif /* __cplusplus */
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 }}
55 #endif /* __cplusplus */
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
73 class 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
95 class 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
148 class 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
161 removeComments = re.compile("#.*$",flags=re.MULTILINE)
162 self.text = removeComments.sub("",self.text)
163 #Remove // comments
164 removeLineComment = re.compile("\/\/.*$",flags=re.MULTILINE)
165 nolinecomment = removeLineComment.sub("",self.text)
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
185 usage="""
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.
192 for example sample.tp will generate sample.h, sample.c and sample.o)
193
194 When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
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 """
201 def 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)
210
211 except Usage, err:
212 print >>sys.stderr, err.msg
213 print >>sys.stderr, "for help use --help"
214 return 2
215
216 outputNames = []
217 for o, a in opts:
218 if o in ("-h", "--help"):
219 print usage
220 return(0)
221 if o in ("-o",""):
222 outputNames.append(a)
223 if o in ("-a",""):
224 all = True
225 try:
226 if len(args) == 0:
227 raise Usage("No template file given")
228
229 except Usage, err:
230 print >>sys.stderr, err.msg
231 print >>sys.stderr, "for help use --help"
232 return 2
233
234 doCFile = None
235 doHeader = None
236 doObj = None
237 headerFilename = None
238 cFilename = None
239 objFilename = None
240
241 if len(outputNames) > 0:
242 if len(args) > 1:
243 print "Cannot process more than one input if you specify an output"
244 return(3)
245
246 for outputName in outputNames:
247 if outputName[-2:] == ".h":
248 doHeader = True
249 headerFilename = outputName
250 elif outputName[-2:] == ".c":
251 doCFile = True
252 cFilename = outputName
253 elif outputName[-2:] == ".o":
254 doObj = True
255 objFilename = outputName
256 else:
257 print "output file type unsupported"
258 return(4)
259 else:
260 doHeader = True
261 doCFile = True
262 doObj = True
263
264 # process arguments
265 for arg in args:
266 if arg[-3:] != ".tp":
267 print arg + " does not end in .tp. Skipping."
268 continue
269
270 tpl = None
271 try:
272 tpl = TemplateFile(arg)
273 except IOError as args:
274 print "Cannot read input file " + args.filename + " " + args.strerror
275 return -1
276 try:
277 if doHeader:
278 if headerFilename:
279 curFilename = headerFilename
280 else:
281 curFilename = re.sub("\.tp$",".h",arg)
282 doth = HeaderFile(curFilename, tpl)
283 doth.write()
284 if doCFile:
285 if cFilename:
286 curFilename = cFilename
287 else:
288 curFilename = re.sub("\.tp$",".c",arg)
289 dotc = CFile(curFilename, tpl)
290 dotc.write()
291 if doObj:
292 if objFilename:
293 curFilename = objFilename
294 else:
295 curFilename = re.sub("\.tp$",".o",arg)
296 dotobj = ObjFile(curFilename, tpl)
297 dotobj.write()
298 except IOError as args:
299 print "Cannot write output file " + args.filename + " " + args.strerror
300 return -1
301
302 if __name__ == "__main__":
303 sys.exit(main())
This page took 0.037043 seconds and 3 git commands to generate.