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