X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ovsdb%2Fovsdb-doc.in;h=17eca52e76b07a3084d31c1c9d169f6c6bd9d737;hb=0ff2282245a87f253843bf357988d7230139888f;hp=cb21c1f40d34b1c3433db22a251c4f9b951fff51;hpb=5f55c39b21e69025045437ffbd3bb98fe6ce2e89;p=openvswitch
diff --git a/ovsdb/ovsdb-doc.in b/ovsdb/ovsdb-doc.in
index cb21c1f4..17eca52e 100755
--- a/ovsdb/ovsdb-doc.in
+++ b/ovsdb/ovsdb-doc.in
@@ -7,16 +7,20 @@ import re
import sys
import xml.dom.minidom
-sys.path.insert(0, "@abs_top_srcdir@/ovsdb")
-import simplejson as json
-
-from OVSDB import *
+import ovs.json
+from ovs.db import error
+import ovs.db.schema
argv0 = sys.argv[0]
-def textToNroff(s):
+def textToNroff(s, font=r'\fR'):
def escape(match):
c = match.group(0)
+ if c == '-':
+ if font == r'\fB':
+ return r'\-'
+ else:
+ return '-'
if c == '\\':
return r'\e'
elif c == '"':
@@ -24,21 +28,22 @@ def textToNroff(s):
elif c == "'":
return r'\(cq'
else:
- raise Error("bad escape")
+ raise error.Error("bad escape")
- s = re.sub('([\\\\"\'])', escape, s)
+ # Escape - \ " ' as needed by nroff.
+ s = re.sub('([-"\'\\\\])', escape, s)
if s.startswith('.'):
s = '\\' + s
return s
def escapeNroffLiteral(s):
- return r'\fB%s\fR' % textToNroff(s)
+ return r'\fB%s\fR' % textToNroff(s, r'\fB')
def inlineXmlToNroff(node, font):
if node.nodeType == node.TEXT_NODE:
- return textToNroff(node.data)
+ return textToNroff(node.data, font)
elif node.nodeType == node.ELEMENT_NODE:
- if node.tagName == 'code' or node.tagName == 'em':
+ if node.tagName in ['code', 'em', 'option']:
s = r'\fB'
for child in node.childNodes:
s += inlineXmlToNroff(child, r'\fB')
@@ -47,12 +52,14 @@ def inlineXmlToNroff(node, font):
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("'ref' lacks column and table attributes")
+ raise error.Error("'ref' lacks column and table attributes")
return s + font
elif node.tagName == 'var':
s = r'\fI'
@@ -60,9 +67,9 @@ def inlineXmlToNroff(node, font):
s += inlineXmlToNroff(child, r'\fI')
return s + font
else:
- raise Error("element <%s> unknown or invalid here" % node.tagName)
+ raise error.Error("element <%s> unknown or invalid here" % node.tagName)
else:
- raise Error("unknown node %s in inline xml" % node)
+ raise error.Error("unknown node %s in inline xml" % node)
def blockXmlToNroff(nodes, para='.PP'):
s = ''
@@ -71,17 +78,23 @@ def blockXmlToNroff(nodes, para='.PP'):
s += textToNroff(node.data)
s = s.lstrip()
elif node.nodeType == node.ELEMENT_NODE:
- if node.tagName == 'ul':
+ 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'):
- s += ".IP \\(bu\n" + blockXmlToNroff(liNode.childNodes, ".IP")
+ 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("
element may only have - children")
+ raise error.Error("<%s> element may only have
- children" % node.tagName)
s += ".RE\n"
elif node.tagName == 'dl':
if s != "":
@@ -103,7 +116,7 @@ def blockXmlToNroff(nodes, para='.PP'):
prev = 'dd'
elif (liNode.nodeType != node.TEXT_NODE
or not liNode.data.isspace()):
- raise Error("
element may only have - and
- children")
+ raise error.Error("
element may only have - and
- children")
s += blockXmlToNroff(liNode.childNodes, ".IP")
s += ".RE\n"
elif node.tagName == 'p':
@@ -115,7 +128,7 @@ def blockXmlToNroff(nodes, para='.PP'):
else:
s += inlineXmlToNroff(node, r'\fR')
else:
- raise Error("unknown node %s in block xml" % node)
+ raise error.Error("unknown node %s in block xml" % node)
if s != "" and not s.endswith('\n'):
s += '\n'
return s
@@ -125,6 +138,8 @@ def typeAndConstraintsToNroff(column):
constraints = column.type.constraintsToEnglish(escapeNroffLiteral)
if constraints:
type += ", " + constraints
+ if column.unique:
+ type += " (must be unique within table)"
return type
def columnToNroff(columnName, column, node):
@@ -159,14 +174,14 @@ def columnGroupToNroff(table, groupXml):
body += '.ST "%s:"\n' % textToNroff(title)
body += subIntro + subBody
else:
- raise Error("unknown element %s in
" % node.tagName)
+ raise error.Error("unknown element %s in " % node.tagName)
return summary, intro, body
def tableSummaryToNroff(summary, level=0):
s = ""
for type, name, arg in summary:
if type == 'column':
-
+
s += "%s\\fB%s\\fR\tT{\n%s\nT}\n" % (
r'\ \ ' * level, name, typeAndConstraintsToNroff(arg))
else:
@@ -207,23 +222,27 @@ Column Type
s += body
return s
-def docsToNroff(schemaFile, xmlFile, title=None):
- schema = DbSchema.fromJson(json.load(open(schemaFile, "r")))
+def docsToNroff(schemaFile, xmlFile, erFile, title=None):
+ schema = ovs.db.schema.DbSchema.from_json(ovs.json.from_file(schemaFile))
doc = xml.dom.minidom.parse(xmlFile).documentElement
schemaDate = os.stat(schemaFile).st_mtime
xmlDate = os.stat(xmlFile).st_mtime
d = date.fromtimestamp(max(schemaDate, xmlDate))
-
+
if title == None:
title = schema.name
- s = r'''.TH %s 5 "%s" "Open vSwitch" "Open vSwitch Manual"
+ # Putting '\" pt as the first line tells "man" that the manpage
+ # needs to be preprocessed by "pic" and "tbl".
+ s = r''''\" pt
+.TH %s 5 "%s" "Open vSwitch" "Open vSwitch Manual"
.\" -*- nroff -*-
.de TQ
. br
. ns
-. TP "\\$1"
+. TP
+\\$1
..
.de ST
. PP
@@ -269,6 +288,29 @@ Table Purpose
tableSummary += "%s\t%s\n" % (name, textToNroff(title))
tableSummary += '.TE\n'
s += tableSummary
+
+ if erFile:
+ s += """
+.if !'\*[.T]'ascii' \{
+.sp 1
+.SH "TABLE RELATIONSHIPS"
+.PP
+The following diagram shows the relationship among tables in the
+database. Each node represents a table. Tables that are part of the
+``root set'' are shown with double borders. Each edge leads from the
+table that contains it and points to the table that its value
+represents. Edges are labeled with their column names, followed by a
+constraint on the number of allowed values: \\fB?\\fR for zero or one,
+\\fB*\\fR for zero or more, \\fB+\\fR for one or more. Thick lines
+represent strong references; thin lines represent weak references.
+.RS -1in
+"""
+ erStream = open(erFile, "r")
+ for line in erStream:
+ s += line + '\n'
+ erStream.close()
+ s += ".RE\\}\n"
+
for node in tableNodes:
s += tableToNroff(schema, node) + "\n"
return s
@@ -282,6 +324,7 @@ where SCHEMA is an OVSDB schema in JSON format
and XML is OVSDB documentation in XML format.
The following options are also available:
+ --er-diagram=DIAGRAM.PIC include E-R diagram from DIAGRAM.PIC
--title=TITLE use TITLE as title instead of schema name
-h, --help display this help message
-V, --version display version information\
@@ -292,14 +335,18 @@ if __name__ == "__main__":
try:
try:
options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
- ['title=', 'help', 'version'])
+ ['er-diagram=', 'title=',
+ 'help', 'version'])
except getopt.GetoptError, geo:
sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
sys.exit(1)
+ er_diagram = None
title = None
for key, value in options:
- if key == '--title':
+ if key == '--er-diagram':
+ er_diagram = value
+ elif key == '--title':
title = value
elif key in ['-h', '--help']:
usage()
@@ -307,20 +354,20 @@ if __name__ == "__main__":
print "ovsdb-doc (Open vSwitch) @VERSION@"
else:
sys.exit(0)
-
+
if len(args) != 2:
sys.stderr.write("%s: exactly 2 non-option arguments required "
"(use --help for help)\n" % argv0)
sys.exit(1)
-
+
# XXX we should warn about undocumented tables or columns
- s = docsToNroff(args[0], args[1])
+ s = docsToNroff(args[0], args[1], er_diagram)
for line in s.split("\n"):
line = line.strip()
if len(line):
print line
-
- except Error, e:
+
+ except error.Error, e:
sys.stderr.write("%s: %s\n" % (argv0, e.msg))
sys.exit(1)