|
Packit |
c04fcb |
#!/usr/bin/env python
|
|
Packit |
c04fcb |
#
|
|
Packit |
c04fcb |
# Copyright (c) 2012 Yannick Brosseau <yannick.brosseau@gmail.com>
|
|
Packit |
c04fcb |
#
|
|
Packit |
c04fcb |
# This program is free software; you can redistribute it and/or
|
|
Packit |
c04fcb |
# modify it under the terms of the GNU General Public License
|
|
Packit |
c04fcb |
# as published by the Free Software Foundation; only version 2
|
|
Packit |
c04fcb |
# of the License.
|
|
Packit |
c04fcb |
#
|
|
Packit |
c04fcb |
# This program is distributed in the hope that it will be useful,
|
|
Packit |
c04fcb |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
c04fcb |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
c04fcb |
# GNU General Public License for more details.
|
|
Packit |
c04fcb |
#
|
|
Packit |
c04fcb |
# You should have received a copy of the GNU General Public License along
|
|
Packit |
c04fcb |
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
c04fcb |
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
from __future__ import print_function
|
|
Packit |
c04fcb |
import sys
|
|
Packit |
c04fcb |
import getopt
|
|
Packit |
c04fcb |
import re
|
|
Packit |
c04fcb |
import os
|
|
Packit |
c04fcb |
import subprocess
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
class Usage(Exception):
|
|
Packit |
c04fcb |
def __init__(self, msg):
|
|
Packit |
c04fcb |
self.msg = msg
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
class HeaderFile:
|
|
Packit |
c04fcb |
HEADER_TPL="""
|
|
Packit |
c04fcb |
#undef TRACEPOINT_PROVIDER
|
|
Packit |
c04fcb |
#define TRACEPOINT_PROVIDER {providerName}
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
#undef TRACEPOINT_INCLUDE
|
|
Packit |
c04fcb |
#define TRACEPOINT_INCLUDE "./{headerFilename}"
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
#if !defined({includeGuard}) || defined(TRACEPOINT_HEADER_MULTI_READ)
|
|
Packit |
c04fcb |
#define {includeGuard}
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
#include <lttng/tracepoint.h>
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
"""
|
|
Packit |
c04fcb |
FOOTER_TPL="""
|
|
Packit |
c04fcb |
#endif /* {includeGuard} */
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
#include <lttng/tracepoint-event.h>
|
|
Packit |
c04fcb |
"""
|
|
Packit |
c04fcb |
def __init__(self, filename, template):
|
|
Packit |
c04fcb |
self.outputFilename = filename
|
|
Packit |
c04fcb |
self.template = template
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
def write(self):
|
|
Packit |
c04fcb |
outputFile = open(self.outputFilename,"w")
|
|
Packit |
c04fcb |
# Include guard macro will be created by uppercasing the filename and
|
|
Packit |
c04fcb |
# replacing all non alphanumeric characters with '_'
|
|
Packit |
c04fcb |
includeGuard = re.sub('[^0-9a-zA-Z]', '_', self.outputFilename.upper())
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
outputFile.write(HeaderFile.HEADER_TPL.format(providerName=self.template.domain,
|
|
Packit |
c04fcb |
includeGuard = includeGuard,
|
|
Packit |
c04fcb |
headerFilename = self.outputFilename))
|
|
Packit |
c04fcb |
outputFile.write(self.template.text)
|
|
Packit |
c04fcb |
outputFile.write(HeaderFile.FOOTER_TPL.format(includeGuard = includeGuard))
|
|
Packit |
c04fcb |
outputFile.close()
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
class CFile:
|
|
Packit |
c04fcb |
FILE_TPL="""
|
|
Packit |
c04fcb |
#define TRACEPOINT_CREATE_PROBES
|
|
Packit |
c04fcb |
/*
|
|
Packit |
c04fcb |
* The header containing our TRACEPOINT_EVENTs.
|
|
Packit |
c04fcb |
*/
|
|
Packit |
c04fcb |
#define TRACEPOINT_DEFINE
|
|
Packit |
c04fcb |
#include "{headerFilename}"
|
|
Packit |
c04fcb |
"""
|
|
Packit |
c04fcb |
def __init__(self, filename, template):
|
|
Packit |
c04fcb |
self.outputFilename = filename
|
|
Packit |
c04fcb |
self.template = template
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
def write(self):
|
|
Packit |
c04fcb |
outputFile = open(self.outputFilename,"w")
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
headerFilename = self.outputFilename.replace(".c",".h")
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
outputFile.write(CFile.FILE_TPL.format(
|
|
Packit |
c04fcb |
headerFilename = headerFilename))
|
|
Packit |
c04fcb |
outputFile.close()
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
class ObjFile:
|
|
Packit |
c04fcb |
def __init__(self, filename, template):
|
|
Packit |
c04fcb |
self.outputFilename = filename
|
|
Packit |
c04fcb |
self.template = template
|
|
Packit |
c04fcb |
def _detectCC(self):
|
|
Packit |
c04fcb |
cc = ""
|
|
Packit |
c04fcb |
if 'CC' in os.environ:
|
|
Packit |
c04fcb |
cc = os.environ['CC']
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
subprocess.call(cc.split(),
|
|
Packit |
c04fcb |
stdout=subprocess.PIPE,
|
|
Packit |
c04fcb |
stderr=subprocess.PIPE)
|
|
Packit |
c04fcb |
except OSError as msg:
|
|
Packit |
c04fcb |
print("Invalid CC environment variable")
|
|
Packit |
c04fcb |
cc = ""
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
# Try c first, if that fails try gcc
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
useCC = True
|
|
Packit |
c04fcb |
subprocess.call("cc",
|
|
Packit |
c04fcb |
stdout=subprocess.PIPE,
|
|
Packit |
c04fcb |
stderr=subprocess.PIPE)
|
|
Packit |
c04fcb |
except OSError as msg:
|
|
Packit |
c04fcb |
useCC = False
|
|
Packit |
c04fcb |
if useCC:
|
|
Packit |
c04fcb |
cc = "cc"
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
useGCC = True
|
|
Packit |
c04fcb |
subprocess.call("gcc",
|
|
Packit |
c04fcb |
stdout=subprocess.PIPE,
|
|
Packit |
c04fcb |
stderr=subprocess.PIPE)
|
|
Packit |
c04fcb |
except OSError as msg:
|
|
Packit |
c04fcb |
useGCC = False
|
|
Packit |
c04fcb |
if useGCC:
|
|
Packit |
c04fcb |
cc = "gcc"
|
|
Packit |
c04fcb |
return cc
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
def write(self):
|
|
Packit |
c04fcb |
cFilename = self.outputFilename.replace(".o",".c")
|
|
Packit |
c04fcb |
cc = self._detectCC()
|
|
Packit |
c04fcb |
if cc == "":
|
|
Packit |
c04fcb |
raise RuntimeError("No C Compiler detected")
|
|
Packit |
c04fcb |
if 'CPPFLAGS' in os.environ:
|
|
Packit |
c04fcb |
cppflags = " " + os.environ['CPPFLAGS']
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
cppflags = ""
|
|
Packit |
c04fcb |
if 'CFLAGS' in os.environ:
|
|
Packit |
c04fcb |
cflags = " " + os.environ['CFLAGS']
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
cflags = ""
|
|
Packit |
c04fcb |
if 'LDFLAGS' in os.environ:
|
|
Packit |
c04fcb |
ldflags = " " + os.environ['LDFLAGS']
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
ldflags = ""
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
command = cc + " -c" + cppflags + cflags + ldflags + " -I. -llttng-ust" + " -o " + self.outputFilename + " " + cFilename
|
|
Packit |
c04fcb |
if verbose:
|
|
Packit |
c04fcb |
print("Compile command: " + command)
|
|
Packit |
c04fcb |
subprocess.call(command.split())
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
class TemplateFile:
|
|
Packit |
c04fcb |
def __init__(self, filename):
|
|
Packit |
c04fcb |
self.domain = ""
|
|
Packit |
c04fcb |
self.inputFilename = filename
|
|
Packit |
c04fcb |
self.parseTemplate()
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
def parseTemplate(self):
|
|
Packit |
c04fcb |
f = open(self.inputFilename,"r")
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
self.text = f.read()
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
#Remove # comments (from input and output file) but keep
|
|
Packit |
c04fcb |
# #include in the output file
|
|
Packit |
c04fcb |
removeComments = re.compile("#[^include].*$",flags=re.MULTILINE)
|
|
Packit |
c04fcb |
self.text = removeComments.sub("",self.text)
|
|
Packit |
c04fcb |
# Remove #include directive from the parsed text
|
|
Packit |
c04fcb |
removePreprocess = re.compile("#.*$",flags=re.MULTILINE)
|
|
Packit |
c04fcb |
noPreprocess = removePreprocess.sub("", self.text)
|
|
Packit |
c04fcb |
#Remove // comments
|
|
Packit |
c04fcb |
removeLineComment = re.compile("\/\/.*$",flags=re.MULTILINE)
|
|
Packit |
c04fcb |
nolinecomment = removeLineComment.sub("", noPreprocess)
|
|
Packit |
c04fcb |
#Remove all spaces and lines
|
|
Packit |
c04fcb |
cleantext = re.sub("\s*","",nolinecomment)
|
|
Packit |
c04fcb |
#Remove multine C style comments
|
|
Packit |
c04fcb |
nocomment = re.sub("/\*.*?\*/","",cleantext)
|
|
Packit |
c04fcb |
entries = re.split("TRACEPOINT_.*?",nocomment)
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
for entry in entries:
|
|
Packit |
c04fcb |
if entry != '':
|
|
Packit |
c04fcb |
decomp = re.findall("(\w*?)\((\w*?),(\w*?),", entry)
|
|
Packit |
c04fcb |
typea = decomp[0][0]
|
|
Packit |
c04fcb |
domain = decomp[0][1]
|
|
Packit |
c04fcb |
name = decomp[0][2]
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
if self.domain == "":
|
|
Packit |
c04fcb |
self.domain = domain
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
if self.domain != domain:
|
|
Packit |
c04fcb |
print("Warning: different domain provided (%s,%s)" % (self.domain, domain))
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
verbose=False
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
usage="""
|
|
Packit |
c04fcb |
lttng-gen-tp - Generate the LTTng-UST header and source based on a simple template
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
usage: lttng-gen-tp TEMPLATE_FILE [-o OUTPUT_FILE][-o OUTPUT_FILE]
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
If no OUTPUT_FILE is given, the .h and .c file will be generated.
|
|
Packit |
c04fcb |
(The basename of the template file with be used for the generated file.
|
|
Packit |
c04fcb |
for example sample.tp will generate sample.h, sample.c and sample.o)
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
|
|
Packit |
c04fcb |
The -o option can be repeated multiple times.
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
The template file must contains TRACEPOINT_EVENT and TRACEPOINT_LOGLEVEL
|
|
Packit |
c04fcb |
as per defined in the lttng/tracepoint.h file.
|
|
Packit |
c04fcb |
See the lttng-ust(3) man page for more details on the format.
|
|
Packit |
c04fcb |
"""
|
|
Packit |
c04fcb |
def main(argv=None):
|
|
Packit |
c04fcb |
if argv is None:
|
|
Packit |
c04fcb |
argv = sys.argv
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
opts, args = getopt.gnu_getopt(argv[1:], "ho:av", ["help","verbose"])
|
|
Packit |
c04fcb |
except getopt.error as msg:
|
|
Packit |
c04fcb |
raise Usage(msg)
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
except Usage as err:
|
|
Packit |
c04fcb |
print(err.msg, file=sys.stderr)
|
|
Packit |
c04fcb |
print("for help use --help", file=sys.stderr)
|
|
Packit |
c04fcb |
return 2
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
outputNames = []
|
|
Packit |
c04fcb |
for o, a in opts:
|
|
Packit |
c04fcb |
if o in ("-h", "--help"):
|
|
Packit |
c04fcb |
print(usage)
|
|
Packit |
c04fcb |
return(0)
|
|
Packit |
c04fcb |
if o in ("-o",""):
|
|
Packit |
c04fcb |
outputNames.append(a)
|
|
Packit |
c04fcb |
if o in ("-a",""):
|
|
Packit |
c04fcb |
all = True
|
|
Packit |
c04fcb |
if o in ("-v", "--verbose"):
|
|
Packit |
c04fcb |
global verbose
|
|
Packit |
c04fcb |
verbose = True
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
if len(args) == 0:
|
|
Packit |
c04fcb |
raise Usage("No template file given")
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
except Usage as err:
|
|
Packit |
c04fcb |
print(err.msg, file=sys.stderr)
|
|
Packit |
c04fcb |
print("for help use --help", file=sys.stderr)
|
|
Packit |
c04fcb |
return 2
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
doCFile = None
|
|
Packit |
c04fcb |
doHeader = None
|
|
Packit |
c04fcb |
doObj = None
|
|
Packit |
c04fcb |
headerFilename = None
|
|
Packit |
c04fcb |
cFilename = None
|
|
Packit |
c04fcb |
objFilename = None
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
if len(outputNames) > 0:
|
|
Packit |
c04fcb |
if len(args) > 1:
|
|
Packit |
c04fcb |
print("Cannot process more than one input if you specify an output")
|
|
Packit |
c04fcb |
return(3)
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
for outputName in outputNames:
|
|
Packit |
c04fcb |
if outputName[-2:] == ".h":
|
|
Packit |
c04fcb |
doHeader = True
|
|
Packit |
c04fcb |
headerFilename = outputName
|
|
Packit |
c04fcb |
elif outputName[-2:] == ".c":
|
|
Packit |
c04fcb |
doCFile = True
|
|
Packit |
c04fcb |
cFilename = outputName
|
|
Packit |
c04fcb |
elif outputName[-2:] == ".o":
|
|
Packit |
c04fcb |
doObj = True
|
|
Packit |
c04fcb |
objFilename = outputName
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
print("output file type unsupported")
|
|
Packit |
c04fcb |
return(4)
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
doHeader = True
|
|
Packit |
c04fcb |
doCFile = True
|
|
Packit |
c04fcb |
doObj = True
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
# process arguments
|
|
Packit |
c04fcb |
for arg in args:
|
|
Packit |
c04fcb |
if arg[-3:] != ".tp":
|
|
Packit |
c04fcb |
print(arg + " does not end in .tp. Skipping.")
|
|
Packit |
c04fcb |
continue
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
tpl = None
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
tpl = TemplateFile(arg)
|
|
Packit |
c04fcb |
except IOError as args:
|
|
Packit |
c04fcb |
print("Cannot read input file " + args.filename + " " + args.strerror)
|
|
Packit |
c04fcb |
return -1
|
|
Packit |
c04fcb |
try:
|
|
Packit |
c04fcb |
if doHeader:
|
|
Packit |
c04fcb |
if headerFilename:
|
|
Packit |
c04fcb |
curFilename = headerFilename
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
curFilename = re.sub("\.tp$",".h",arg)
|
|
Packit |
c04fcb |
doth = HeaderFile(curFilename, tpl)
|
|
Packit |
c04fcb |
doth.write()
|
|
Packit |
c04fcb |
if doCFile:
|
|
Packit |
c04fcb |
if cFilename:
|
|
Packit |
c04fcb |
curFilename = cFilename
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
curFilename = re.sub("\.tp$",".c",arg)
|
|
Packit |
c04fcb |
dotc = CFile(curFilename, tpl)
|
|
Packit |
c04fcb |
dotc.write()
|
|
Packit |
c04fcb |
if doObj:
|
|
Packit |
c04fcb |
if objFilename:
|
|
Packit |
c04fcb |
curFilename = objFilename
|
|
Packit |
c04fcb |
else:
|
|
Packit |
c04fcb |
curFilename = re.sub("\.tp$",".o",arg)
|
|
Packit |
c04fcb |
dotobj = ObjFile(curFilename, tpl)
|
|
Packit |
c04fcb |
dotobj.write()
|
|
Packit |
c04fcb |
except IOError as args:
|
|
Packit |
c04fcb |
print("Cannot write output file " + args.filename + " " + args.strerror)
|
|
Packit |
c04fcb |
return -1
|
|
Packit |
c04fcb |
|
|
Packit |
c04fcb |
if __name__ == "__main__":
|
|
Packit |
c04fcb |
sys.exit(main())
|