ovsdb-server: Fix a reference count leak bug
[cascardo/ovs.git] / build-aux / xml2nroff
index 8dc9d4f..df1df28 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/python
 
-# Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+# Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from datetime import date
 import getopt
-import os
 import sys
 import xml.dom.minidom
 
-from build.nroff import *
+import build.nroff
 
 argv0 = sys.argv[0]
 
+
 def usage():
     print """\
 %(argv0)s: XML to nroff converter
 Converts the XML format supplied as input into an nroff-formatted manpage.
-usage: %(argv0)s [OPTIONS] INPUT.XML
+usage: %(argv0)s [OPTIONS] INPUT.XML [VAR=VALUE]...
 where INPUT.XML is a manpage in an OVS-specific XML format.
 
+Each VAR, when enclosed by "@"s in the input, is replaced by its
+corresponding VALUE, with characters &<>"' in VALUE escaped.
+
 The following options are also available:
+  -I, --include=DIR           search DIR for include files (default: .)
   --version=VERSION           use VERSION to display on document footer
   -h, --help                  display this help message\
 """ % {'argv0': argv0}
     sys.exit(0)
 
-def manpage_to_nroff(xml_file, version=None):
-    doc = xml.dom.minidom.parse(xml_file).documentElement
-    d = date.fromtimestamp(os.stat(xml_file).st_mtime)
 
-    if version == None:
+def manpage_to_nroff(xml_file, subst, include_path, version=None):
+    with open(xml_file) as f:
+        content = f.read()
+    for k, v in subst.iteritems():
+        content = content.replace(k, v)
+    doc = xml.dom.minidom.parseString(content).documentElement
+
+    xi_nodes = doc.getElementsByTagName("xi:include")
+    for node in xi_nodes:
+        fn = node.getAttribute("href")
+        content = None
+        for dir in include_path:
+            try:
+                with open("%s/%s" % (dir, fn)) as xi_f:
+                    content = xi_f.read()
+            except IOError:
+                pass
+        if not content:
+            sys.stderr.write("%s: could not open include file %s\n"
+                             % (argv0, fn))
+            sys.exit(1)
+        for k, v in subst.iteritems():
+            content = content.replace(k, v)
+        xi_doc = xml.dom.minidom.parseString(content).documentElement
+        doc.replaceChild(xi_doc, node)
+
+    if version is None:
         version = "UNKNOWN"
     program = doc.attributes['program'].nodeValue
     title = doc.attributes['title'].nodeValue
@@ -64,29 +90,18 @@ def manpage_to_nroff(xml_file, version=None):
 .  I "\\$1"
 .  RE
 ..
-''' % (textToNroff(program), textToNroff(section), textToNroff(title), textToNroff(version))
+''' % (build.nroff.text_to_nroff(program), build.nroff.text_to_nroff(section),
+       build.nroff.text_to_nroff(title), build.nroff.text_to_nroff(version))
 
-    s += blockXmlToNroff(doc.childNodes) + "\n"
+    s += build.nroff.block_xml_to_nroff(doc.childNodes) + "\n"
 
     return s
 
-def usage():
-    print """\
-%(argv0)s: converts XML in a somewhat HTML-like format to nroff
-usage: %(argv0)s [OPTIONS] XML
-where XML is documentation in a somewhat HTML-like XML format.
-The manpage, in nroff "man" format, is output on stdout.
-
-The following options are also available:
-  --version=VERSION           use VERSION to display on document footer
-  -h, --help                  display this help message\
-""" % {'argv0': argv0}
-    sys.exit(0)
 
 if __name__ == "__main__":
     try:
-        options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
-                                          ['version=', 'help'])
+        options, args = getopt.gnu_getopt(sys.argv[1:], 'hVI:',
+                                          ['version=', 'help', 'include='])
     except getopt.GetoptError, geo:
         sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
         sys.exit(1)
@@ -94,22 +109,37 @@ if __name__ == "__main__":
     er_diagram = None
     title = None
     version = None
+    include_path = []
     for key, value in options:
         if key == '--version':
             version = value
         elif key in ['-h', '--help']:
             usage()
+        elif key in ['-I', '--include']:
+            include_path.append(value)
         else:
             sys.exit(0)
+    if not include_path:
+        include_path = ['.']
 
-    if len(args) != 1:
+    if len(args) < 1:
         sys.stderr.write("%s: exactly 1 non-option arguments required "
                          "(use --help for help)\n" % argv0)
         sys.exit(1)
 
+    subst = {}
+    for s in args[1:]:
+        var, value = s.split('=', 1)
+        value = value.replace('&', '&amp;')
+        value = value.replace('<', '&lt;')
+        value = value.replace('>', '&gt;')
+        value = value.replace('"', '&quot;')
+        value = value.replace("'", '&apos;')
+        subst['@%s@' % var] = value
+
     try:
-        s = manpage_to_nroff(args[0], version)
-    except error.Error, e:
+        s = manpage_to_nroff(args[0], subst, include_path, version)
+    except build.nroff.error.Error, e:
         sys.stderr.write("%s: %s\n" % (argv0, e.msg))
         sys.exit(1)
     for line in s.splitlines():