Make lttng-gen-tp executable
[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_FILE
35 #define TRACEPOINT_INCLUDE_FILE ./{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 self.text = re.sub("#.*$","",self.text,flags=re.MULTILINE)
162 #Remove // comments
163 nolinecomment = re.sub("\/\/.*$","",self.text,flags=re.MULTILINE)
164 #Remove all spaces and lines
165 cleantext = re.sub("\s*","",nolinecomment)
166 #Remove multine C style comments
167 nocomment = re.sub("/\*.*?\*/","",cleantext)
168 entries = re.split("TRACEPOINT_.*?",nocomment)
169
170 for entry in entries:
171 if entry != '':
172 decomp = re.findall("(\w*?)\((\w*?),(\w*?),", entry)
173 typea = decomp[0][0]
174 domain = decomp[0][1]
175 name = decomp[0][2]
176
177 if self.domain == "":
178 self.domain = domain
179 else:
180 if self.domain != domain:
181 print "Warning: different domain provided (%s,%s)" % (self.domain, domain)
182
183 usage="""
184 lttng-gen-tp - Generate the LTTng-UST header and source based on a simple template
185
186 usage: lttng-gen-tp TEMPLATE_FILE [-o OUTPUT_FILE][-o OUTPUT_FILE]
187
188 If no OUTPUT_FILE is given, the .h and .c file will be generated.
189 (The basename of the template file with be used for the generated file.
190 for example sample.tp will generate sample.h, sample.c and sample.o)
191
192 When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
193 The -o option can be repeated multiple times.
194
195 The template file must contains TRACEPOINT_EVENT and TRACEPOINT_LOGLEVEL
196 as per defined in the lttng/tracepoint.h file.
197 See the lttng-ust(3) man page for more details on the format.
198 """
199 def main(argv=None):
200 if argv is None:
201 argv = sys.argv
202
203 try:
204 try:
205 opts, args = getopt.gnu_getopt(argv[1:], "ho:a", ["help"])
206 except getopt.error, msg:
207 raise Usage(msg)
208
209 except Usage, err:
210 print >>sys.stderr, err.msg
211 print >>sys.stderr, "for help use --help"
212 return 2
213
214 outputNames = []
215 for o, a in opts:
216 if o in ("-h", "--help"):
217 print usage
218 return(0)
219 if o in ("-o",""):
220 outputNames.append(a)
221 if o in ("-a",""):
222 all = True
223
224 doCFile = None
225 doHeader = None
226 doObj = None
227 headerFilename = None
228 cFilename = None
229 objFilename = None
230
231 if len(outputNames) > 0:
232 if len(args) > 1:
233 print "Cannot process more than one input if you specify an output"
234 return(3)
235
236 for outputName in outputNames:
237 if outputName[-2:] == ".h":
238 doHeader = True
239 headerFilename = outputName
240 elif outputName[-2:] == ".c":
241 doCFile = True
242 cFilename = outputName
243 elif outputName[-2:] == ".o":
244 doObj = True
245 objFilename = outputName
246 else:
247 print "output file type unsupported"
248 return(4)
249 else:
250 doHeader = True
251 doCFile = True
252 doObj = True
253
254 # process arguments
255 for arg in args:
256
257 tpl = TemplateFile(arg)
258 if doHeader:
259 if headerFilename:
260 curFilename = headerFilename
261 else:
262 curFilename = re.sub("\.tp$",".h",arg)
263 doth = HeaderFile(curFilename, tpl)
264 doth.write()
265 if doCFile:
266 if cFilename:
267 curFilename = cFilename
268 else:
269 curFilename = re.sub("\.tp$",".c",arg)
270 dotc = CFile(curFilename, tpl)
271 dotc.write()
272 if doObj:
273 if objFilename:
274 curFilename = objFilename
275 else:
276 curFilename = re.sub("\.tp$",".o",arg)
277 dotobj = ObjFile(curFilename, tpl)
278 dotobj.write()
279
280 if __name__ == "__main__":
281 sys.exit(main())
This page took 0.035387 seconds and 5 git commands to generate.