]>
Commit | Line | Data |
---|---|---|
1ca0323e | 1 | #! /usr/bin/python3 |
a4e3c495 | 2 | |
8a988976 | 3 | # Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. |
a4e3c495 BP |
4 | # |
5 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | # you may not use this file except in compliance with the License. | |
7 | # You may obtain a copy of the License at: | |
8 | # | |
9 | # http://www.apache.org/licenses/LICENSE-2.0 | |
10 | # | |
11 | # Unless required by applicable law or agreed to in writing, software | |
12 | # distributed under the License is distributed on an "AS IS" BASIS, | |
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | # See the License for the specific language governing permissions and | |
15 | # limitations under the License. | |
16 | ||
a4e3c495 | 17 | import getopt |
a4e3c495 BP |
18 | import sys |
19 | import xml.dom.minidom | |
20 | ||
d43bf6a6 | 21 | import build.nroff |
a4e3c495 BP |
22 | |
23 | argv0 = sys.argv[0] | |
24 | ||
e78cd628 | 25 | |
a4e3c495 | 26 | def usage(): |
e522804f | 27 | print("""\ |
a4e3c495 BP |
28 | %(argv0)s: XML to nroff converter |
29 | Converts the XML format supplied as input into an nroff-formatted manpage. | |
b59de254 | 30 | usage: %(argv0)s [OPTIONS] INPUT.XML [VAR=VALUE]... |
a4e3c495 BP |
31 | where INPUT.XML is a manpage in an OVS-specific XML format. |
32 | ||
b59de254 BP |
33 | Each VAR, when enclosed by "@"s in the input, is replaced by its |
34 | corresponding VALUE, with characters &<>"' in VALUE escaped. | |
35 | ||
a4e3c495 | 36 | The following options are also available: |
8a988976 | 37 | -I, --include=DIR search DIR for include files (default: .) |
a4e3c495 BP |
38 | --version=VERSION use VERSION to display on document footer |
39 | -h, --help display this help message\ | |
e522804f | 40 | """ % {'argv0': argv0}) |
a4e3c495 BP |
41 | sys.exit(0) |
42 | ||
e78cd628 | 43 | |
8a988976 | 44 | def manpage_to_nroff(xml_file, subst, include_path, version=None): |
069390bb RB |
45 | with open(xml_file) as f: |
46 | content = f.read() | |
e522804f | 47 | for k, v in subst.items(): |
069390bb RB |
48 | content = content.replace(k, v) |
49 | doc = xml.dom.minidom.parseString(content).documentElement | |
a4e3c495 | 50 | |
7ba0c32f WL |
51 | xi_nodes = doc.getElementsByTagName("xi:include") |
52 | for node in xi_nodes: | |
8a988976 BP |
53 | fn = node.getAttribute("href") |
54 | content = None | |
55 | for dir in include_path: | |
56 | try: | |
57 | with open("%s/%s" % (dir, fn)) as xi_f: | |
58 | content = xi_f.read() | |
59 | except IOError: | |
60 | pass | |
61 | if not content: | |
62 | sys.stderr.write("%s: could not open include file %s\n" | |
63 | % (argv0, fn)) | |
64 | sys.exit(1) | |
e522804f | 65 | for k, v in subst.items(): |
7ba0c32f WL |
66 | content = content.replace(k, v) |
67 | xi_doc = xml.dom.minidom.parseString(content).documentElement | |
68 | doc.replaceChild(xi_doc, node) | |
69 | ||
e78cd628 | 70 | if version is None: |
a4e3c495 BP |
71 | version = "UNKNOWN" |
72 | program = doc.attributes['program'].nodeValue | |
73 | title = doc.attributes['title'].nodeValue | |
74 | section = doc.attributes['section'].nodeValue | |
75 | ||
76 | # Putting '\" p as the first line tells "man" that the manpage | |
77 | # needs to be preprocessed by "pic". | |
78 | s = r''''\" p | |
79 | .\" -*- nroff -*- | |
80 | .TH "%s" %s "%s" "Open vSwitch %s" "Open vSwitch Manual" | |
81 | .fp 5 L CR \\" Make fixed-width font available as \\fL. | |
82 | .de TQ | |
83 | . br | |
84 | . ns | |
85 | . TP "\\$1" | |
86 | .. | |
87 | .de ST | |
88 | . PP | |
89 | . RS -0.15in | |
90 | . I "\\$1" | |
91 | . RE | |
92 | .. | |
d43bf6a6 RB |
93 | ''' % (build.nroff.text_to_nroff(program), build.nroff.text_to_nroff(section), |
94 | build.nroff.text_to_nroff(title), build.nroff.text_to_nroff(version)) | |
a4e3c495 | 95 | |
d43bf6a6 | 96 | s += build.nroff.block_xml_to_nroff(doc.childNodes) + "\n" |
a4e3c495 BP |
97 | |
98 | return s | |
99 | ||
a4e3c495 BP |
100 | |
101 | if __name__ == "__main__": | |
102 | try: | |
8a988976 BP |
103 | options, args = getopt.gnu_getopt(sys.argv[1:], 'hVI:', |
104 | ['version=', 'help', 'include=']) | |
e522804f | 105 | except getopt.GetoptError as geo: |
a4e3c495 BP |
106 | sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) |
107 | sys.exit(1) | |
108 | ||
109 | er_diagram = None | |
110 | title = None | |
111 | version = None | |
8a988976 | 112 | include_path = [] |
a4e3c495 BP |
113 | for key, value in options: |
114 | if key == '--version': | |
115 | version = value | |
116 | elif key in ['-h', '--help']: | |
117 | usage() | |
8a988976 BP |
118 | elif key in ['-I', '--include']: |
119 | include_path.append(value) | |
a4e3c495 BP |
120 | else: |
121 | sys.exit(0) | |
8a988976 BP |
122 | if not include_path: |
123 | include_path = ['.'] | |
a4e3c495 | 124 | |
b59de254 | 125 | if len(args) < 1: |
a4e3c495 BP |
126 | sys.stderr.write("%s: exactly 1 non-option arguments required " |
127 | "(use --help for help)\n" % argv0) | |
128 | sys.exit(1) | |
129 | ||
b59de254 BP |
130 | subst = {} |
131 | for s in args[1:]: | |
132 | var, value = s.split('=', 1) | |
133 | value = value.replace('&', '&') | |
134 | value = value.replace('<', '<') | |
135 | value = value.replace('>', '>') | |
136 | value = value.replace('"', '"') | |
137 | value = value.replace("'", ''') | |
138 | subst['@%s@' % var] = value | |
139 | ||
a4e3c495 | 140 | try: |
8a988976 | 141 | s = manpage_to_nroff(args[0], subst, include_path, version) |
e522804f | 142 | except build.nroff.error.Error as e: |
a4e3c495 BP |
143 | sys.stderr.write("%s: %s\n" % (argv0, e.msg)) |
144 | sys.exit(1) | |
145 | for line in s.splitlines(): | |
146 | line = line.strip() | |
147 | if line: | |
e522804f | 148 | print(line) |
a4e3c495 BP |
149 | |
150 | ||
151 | # Local variables: | |
152 | # mode: python | |
153 | # End: |