ust-fd: Add close_range declaration
[lttng-ust.git] / tools / lttng-gen-tp
old mode 100644 (file)
new mode 100755 (executable)
index 9b08275..e49083b
-#!/usr/bin/python
+#!/usr/bin/env python
 #
-# Copyright (c)  2012 Yannick Brosseau <yannick.brosseau@gmail.com>
+# 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 <yannick.brosseau@gmail.com>
 
+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="""
-#undef TRACEPOINT_PROVIDER
-#define TRACEPOINT_PROVIDER {providerName}
-
-#undef TRACEPOINT_INCLUDE_FILE
-#define TRACEPOINT_INCLUDE_FILE ./{headerFilename}
 
-#ifdef __cplusplus
-#extern "C"{{
-#endif /*__cplusplus */
+class HeaderFile:
+    HEADER_TPL = """
+#undef LTTNG_UST_TRACEPOINT_PROVIDER
+#define LTTNG_UST_TRACEPOINT_PROVIDER {providerName}
 
+#undef LTTNG_UST_TRACEPOINT_INCLUDE
+#define LTTNG_UST_TRACEPOINT_INCLUDE "./{headerFilename}"
 
-#if !defined({includeGuard}) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#if !defined({includeGuard}) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
 #define {includeGuard}
 
 #include <lttng/tracepoint.h>
 
 """
-    FOOTER_TPL="""
+    FOOTER_TPL = """
 #endif /* {includeGuard} */
 
 #include <lttng/tracepoint-event.h>
-
-#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="""
-#define TRACEPOINT_CREATE_PROBES
+    FILE_TPL = """
+#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
 /*
- * The header containing our TRACEPOINT_EVENTs.
+ * The header containing our LTTNG_UST_TRACEPOINT_EVENTs.
  */
-#define TRACEPOINT_DEFINE
+#define LTTNG_UST_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 = ""
+
+        command = cc + " -c" + cppflags + cflags + " -I. -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("^LTTNG_UST_TRACEPOINT_.*?", nocomment)
 
         for entry in entries:
             if entry != '':
@@ -123,57 +183,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
+ The template file must contains LTTNG_UST_TRACEPOINT_EVENT and LTTNG_UST_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 +262,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())
This page took 0.029765 seconds and 4 git commands to generate.