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