I don't understand nroff well enough to review patch 6 and patch 7. If anyone else is up for it, please review.
On Thu, Feb 19, 2015 at 12:12 AM, Ben Pfaff <b...@nicira.com> wrote: > This will make it cleaner to add another build-time program that generates > nroff from XML. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > ovsdb/ovsdb-doc | 135 +------------------------------- > python/automake.mk | 6 ++ > python/build/__init__.py | 0 > python/build/nroff.py | 196 > +++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 206 insertions(+), 131 deletions(-) > create mode 100644 python/build/__init__.py > create mode 100644 python/build/nroff.py > > diff --git a/ovsdb/ovsdb-doc b/ovsdb/ovsdb-doc > index 15618ef..369efa9 100755 > --- a/ovsdb/ovsdb-doc > +++ b/ovsdb/ovsdb-doc > @@ -3,7 +3,6 @@ > from datetime import date > import getopt > import os > -import re > import sys > import xml.dom.minidom > > @@ -11,136 +10,9 @@ import ovs.json > from ovs.db import error > import ovs.db.schema > > -argv0 = sys.argv[0] > - > -def textToNroff(s, font=r'\fR'): > - def escape(match): > - c = match.group(0) > - if c.startswith('-'): > - if c != '-' or font == r'\fB': > - return '\\' + c > - else: > - return '-' > - if c == '\\': > - return r'\e' > - elif c == '"': > - return r'\(dq' > - elif c == "'": > - return r'\(cq' > - else: > - raise error.Error("bad escape") > +from build.nroff import * > > - # Escape - \ " ' as needed by nroff. > - s = re.sub('(-[0-9]|[-"\'\\\\])', escape, s) > - if s.startswith('.'): > - s = '\\' + s > - return s > - > -def escapeNroffLiteral(s): > - return r'\fB%s\fR' % textToNroff(s, r'\fB') > - > -def inlineXmlToNroff(node, font): > - if node.nodeType == node.TEXT_NODE: > - return textToNroff(node.data, font) > - elif node.nodeType == node.ELEMENT_NODE: > - if node.tagName in ['code', 'em', 'option']: > - s = r'\fB' > - for child in node.childNodes: > - s += inlineXmlToNroff(child, r'\fB') > - return s + font > - elif node.tagName == 'ref': > - s = r'\fB' > - if node.hasAttribute('column'): > - s += node.attributes['column'].nodeValue > - if node.hasAttribute('key'): > - s += ':' + node.attributes['key'].nodeValue > - elif node.hasAttribute('table'): > - s += node.attributes['table'].nodeValue > - elif node.hasAttribute('group'): > - s += node.attributes['group'].nodeValue > - else: > - raise error.Error("'ref' lacks required attributes: %s" % > node.attributes.keys()) > - return s + font > - elif node.tagName == 'var': > - s = r'\fI' > - for child in node.childNodes: > - s += inlineXmlToNroff(child, r'\fI') > - return s + font > - else: > - raise error.Error("element <%s> unknown or invalid here" % > node.tagName) > - else: > - raise error.Error("unknown node %s in inline xml" % node) > - > -def blockXmlToNroff(nodes, para='.PP'): > - s = '' > - for node in nodes: > - if node.nodeType == node.TEXT_NODE: > - s += textToNroff(node.data) > - s = s.lstrip() > - elif node.nodeType == node.ELEMENT_NODE: > - if node.tagName in ['ul', 'ol']: > - if s != "": > - s += "\n" > - s += ".RS\n" > - i = 0 > - for liNode in node.childNodes: > - if (liNode.nodeType == node.ELEMENT_NODE > - and liNode.tagName == 'li'): > - i += 1 > - if node.tagName == 'ul': > - s += ".IP \\(bu\n" > - else: > - s += ".IP %d. .25in\n" % i > - s += blockXmlToNroff(liNode.childNodes, ".IP") > - elif (liNode.nodeType != node.TEXT_NODE > - or not liNode.data.isspace()): > - raise error.Error("<%s> element may only have <li> > children" % node.tagName) > - s += ".RE\n" > - elif node.tagName == 'dl': > - if s != "": > - s += "\n" > - s += ".RS\n" > - prev = "dd" > - for liNode in node.childNodes: > - if (liNode.nodeType == node.ELEMENT_NODE > - and liNode.tagName == 'dt'): > - if prev == 'dd': > - s += '.TP\n' > - else: > - s += '.TQ\n' > - prev = 'dt' > - elif (liNode.nodeType == node.ELEMENT_NODE > - and liNode.tagName == 'dd'): > - if prev == 'dd': > - s += '.IP\n' > - prev = 'dd' > - elif (liNode.nodeType != node.TEXT_NODE > - or not liNode.data.isspace()): > - raise error.Error("<dl> element may only have <dt> > and <dd> children") > - s += blockXmlToNroff(liNode.childNodes, ".IP") > - s += ".RE\n" > - elif node.tagName == 'p': > - if s != "": > - if not s.endswith("\n"): > - s += "\n" > - s += para + "\n" > - s += blockXmlToNroff(node.childNodes, para) > - elif node.tagName in ('h1', 'h2', 'h3'): > - if s != "": > - if not s.endswith("\n"): > - s += "\n" > - nroffTag = {'h1': 'SH', 'h2': 'SS', 'h3': 'ST'}[node.tagName] > - s += ".%s " % nroffTag > - for child_node in node.childNodes: > - s += inlineXmlToNroff(child_node, r'\fR') > - s += "\n" > - else: > - s += inlineXmlToNroff(node, r'\fR') > - else: > - raise error.Error("unknown node %s in block xml" % node) > - if s != "" and not s.endswith('\n'): > - s += '\n' > - return s > +argv0 = sys.argv[0] > > def typeAndConstraintsToNroff(column): > type = column.type.toEnglish(escapeNroffLiteral) > @@ -283,8 +155,9 @@ def docsToNroff(schemaFile, xmlFile, erFile, > version=None): > # Putting '\" p as the first line tells "man" that the manpage > # needs to be preprocessed by "pic". > s = r''''\" p > -.TH "%s" 5 " DB Schema %s" "Open vSwitch %s" "Open vSwitch Manual" > .\" -*- nroff -*- > +.TH "%s" 5 " DB Schema %s" "Open vSwitch %s" "Open vSwitch Manual" > +.fp 5 L CR \\" Make fixed-width font available as \\fL. > .de TQ > . br > . ns > diff --git a/python/automake.mk b/python/automake.mk > index 08e1204..f6ab606 100644 > --- a/python/automake.mk > +++ b/python/automake.mk > @@ -35,6 +35,12 @@ ovs_pyfiles = \ > python/ovs/version.py \ > python/ovs/vlog.py > > +# These python files are used at build time but not runtime, > +# so they are not installed. > +EXTRA_DIST += \ > + python/build/__init__.py \ > + python/build/nroff.py > + > PYFILES = $(ovs_pyfiles) python/ovs/dirs.py $(ovstest_pyfiles) > EXTRA_DIST += $(PYFILES) > PYCOV_CLEAN_FILES += $(PYFILES:.py=.py,cover) > diff --git a/python/build/__init__.py b/python/build/__init__.py > new file mode 100644 > index 0000000..e69de29 > diff --git a/python/build/nroff.py b/python/build/nroff.py > new file mode 100644 > index 0000000..c277399 > --- /dev/null > +++ b/python/build/nroff.py > @@ -0,0 +1,196 @@ > +# Copyright (c) 2010, 2011, 2012, 2015 Nicira, Inc. > +# > +# Licensed under the Apache License, Version 2.0 (the "License"); > +# you may not use this file except in compliance with the License. > +# You may obtain a copy of the License at: > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, > +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > +# See the License for the specific language governing permissions and > +# limitations under the License. > + > +import re > + > +from ovs.db import error > + > +def textToNroff(s, font=r'\fR'): > + def escape(match): > + c = match.group(0) > + > + # In Roman type, let -- in XML be \- in nroff. That gives us a way > to > + # write minus signs, which is important in some places in manpages. > + # > + # Bold in nroff usually represents literal text, where there's no > + # distinction between hyphens and minus sign. The convention in > nroff > + # appears to be to use a minus sign in such cases, so we follow that > + # convention. > + # > + # Finally, we always output - as a minus sign when it is followed by > a > + # digit. > + if c.startswith('-'): > + if c == '--' and font == r'\fR': > + return r'\-' > + if c != '-' or font in (r'\fB', r'\fL'): > + return c.replace('-', r'\-') > + else: > + return '-' > + > + if c == '\\': > + return r'\e' > + elif c == '"': > + return r'\(dq' > + elif c == "'": > + return r'\(cq' > + elif c == ".": > + # groff(7) says that . can be escaped by \. but in practice groff > + # still gives an error with \. at the beginning of a line. > + return font + "." > + else: > + raise error.Error("bad escape") > + > + # Escape - \ " ' . as needed by nroff. > + s = re.sub('(-[0-9]|--|[-"\'\\\\.])', escape, s) > + return s > + > +def escapeNroffLiteral(s, font=r'\fB'): > + return font + r'%s\fR' % textToNroff(s, font) > + > +def pic_to_nroff(nodes, para): > + s = para + '\n.PS\n' > + for node in nodes: > + if node.nodeType != node.TEXT_NODE: > + fatal("<pic> element may only have text children") > + s += node.data + '\n' > + s += '.PE\n' > + return s > + > +def inlineXmlToNroff(node, font, to_upper=False): > + if node.nodeType == node.TEXT_NODE: > + if to_upper: > + return textToNroff(node.data.upper(), font) > + else: > + return textToNroff(node.data, font) > + elif node.nodeType == node.ELEMENT_NODE: > + if node.tagName in ['code', 'em', 'option']: > + s = r'\fB' > + for child in node.childNodes: > + s += inlineXmlToNroff(child, r'\fB') > + return s + font > + elif node.tagName == 'ref': > + s = r'\fB' > + if node.hasAttribute('column'): > + s += node.attributes['column'].nodeValue > + if node.hasAttribute('key'): > + s += ':' + node.attributes['key'].nodeValue > + elif node.hasAttribute('table'): > + s += node.attributes['table'].nodeValue > + elif node.hasAttribute('group'): > + s += node.attributes['group'].nodeValue > + elif node.hasAttribute('db'): > + s += node.attributes['db'].nodeValue > + else: > + raise error.Error("'ref' lacks required attributes: %s" % > node.attributes.keys()) > + return s + font > + elif node.tagName == 'var' or node.tagName == 'dfn': > + s = r'\fI' > + for child in node.childNodes: > + s += inlineXmlToNroff(child, r'\fI') > + return s + font > + else: > + raise error.Error("element <%s> unknown or invalid here" % > node.tagName) > + else: > + raise error.Error("unknown node %s in inline xml" % node) > + > +def pre_to_nroff(nodes, para, font): > + s = para + '\n.nf\n' > + for node in nodes: > + if node.nodeType != node.TEXT_NODE: > + fatal("<pre> element may only have text children") > + for line in node.data.split('\n'): > + s += escapeNroffLiteral(line, font) + '\n.br\n' > + s += '.fi\n' > + return s > + > +def blockXmlToNroff(nodes, para='.PP'): > + s = '' > + for node in nodes: > + if node.nodeType == node.TEXT_NODE: > + s += textToNroff(node.data) > + s = s.lstrip() > + elif node.nodeType == node.ELEMENT_NODE: > + if node.tagName in ['ul', 'ol']: > + if s != "": > + s += "\n" > + s += ".RS\n" > + i = 0 > + for liNode in node.childNodes: > + if (liNode.nodeType == node.ELEMENT_NODE > + and liNode.tagName == 'li'): > + i += 1 > + if node.tagName == 'ul': > + s += ".IP \\(bu\n" > + else: > + s += ".IP %d. .25in\n" % i > + s += blockXmlToNroff(liNode.childNodes, ".IP") > + elif (liNode.nodeType != node.TEXT_NODE > + or not liNode.data.isspace()): > + raise error.Error("<%s> element may only have <li> > children" % node.tagName) > + s += ".RE\n" > + elif node.tagName == 'dl': > + if s != "": > + s += "\n" > + s += ".RS\n" > + prev = "dd" > + for liNode in node.childNodes: > + if (liNode.nodeType == node.ELEMENT_NODE > + and liNode.tagName == 'dt'): > + if prev == 'dd': > + s += '.TP\n' > + else: > + s += '.TQ .5in\n' > + prev = 'dt' > + elif (liNode.nodeType == node.ELEMENT_NODE > + and liNode.tagName == 'dd'): > + if prev == 'dd': > + s += '.IP\n' > + prev = 'dd' > + elif (liNode.nodeType != node.TEXT_NODE > + or not liNode.data.isspace()): > + raise error.Error("<dl> element may only have <dt> > and <dd> children") > + s += blockXmlToNroff(liNode.childNodes, ".IP") > + s += ".RE\n" > + elif node.tagName == 'p': > + if s != "": > + if not s.endswith("\n"): > + s += "\n" > + s += para + "\n" > + s += blockXmlToNroff(node.childNodes, para) > + elif node.tagName in ('h1', 'h2', 'h3'): > + if s != "": > + if not s.endswith("\n"): > + s += "\n" > + nroffTag = {'h1': 'SH', 'h2': 'SS', 'h3': 'ST'}[node.tagName] > + s += '.%s "' % nroffTag > + for child_node in node.childNodes: > + s += inlineXmlToNroff(child_node, r'\fR', > + to_upper=(nroffTag == 'SH')) > + s += '"\n' > + elif node.tagName == 'pre': > + fixed = node.getAttribute('fixed') > + if fixed == 'yes': > + font = r'\fL' > + else: > + font = r'\fB' > + s += pre_to_nroff(node.childNodes, para, font) > + elif node.tagName == 'pic': > + s += pic_to_nroff(node.childNodes, para) > + else: > + s += inlineXmlToNroff(node, r'\fR') > + else: > + raise error.Error("unknown node %s in block xml" % node) > + if s != "" and not s.endswith('\n'): > + s += '\n' > + return s > -- > 2.1.3 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev