Make lttng-gen-tp work on python 2.6
[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 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
226 doCFile = None
227 doHeader = None
228 doObj = None
229 headerFilename = None
230 cFilename = None
231 objFilename = None
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":
246 doObj = True
247 objFilename = outputName
248 else:
249 print "output file type unsupported"
250 return(4)
251 else:
252 doHeader = True
253 doCFile = True
254 doObj = True
255
256 # process arguments
257 for arg in args:
258
259 tpl = TemplateFile(arg)
260 if doHeader:
261 if headerFilename:
262 curFilename = headerFilename
263 else:
264 curFilename = re.sub("\.tp$",".h",arg)
265 doth = HeaderFile(curFilename, tpl)
266 doth.write()
267 if doCFile:
268 if cFilename:
269 curFilename = cFilename
270 else:
271 curFilename = re.sub("\.tp$",".c",arg)
272 dotc = CFile(curFilename, tpl)
273 dotc.write()
274 if doObj:
275 if objFilename:
276 curFilename = objFilename
277 else:
278 curFilename = re.sub("\.tp$",".o",arg)
279 dotobj = ObjFile(curFilename, tpl)
280 dotobj.write()
281
282 if __name__ == "__main__":
283 sys.exit(main())
This page took 0.036136 seconds and 5 git commands to generate.