Blame tools/lttng-gen-tp

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())