X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ovsdb%2Fovsdb-doc.in;h=aa4fae2e6c26ac1d25246ddb407c5f05711b2fe4;hb=cb22974d773942d66da42b700b8bca0db27a0920;hp=9e0a318d2b9fb41366cae87e4d77d0589029fa7d;hpb=c94238565522c51a117a7f89fecaabd2605b7c66;p=sliver-openvswitch.git diff --git a/ovsdb/ovsdb-doc.in b/ovsdb/ovsdb-doc.in index 9e0a318d2..aa4fae2e6 100755 --- a/ovsdb/ovsdb-doc.in +++ b/ovsdb/ovsdb-doc.in @@ -16,9 +16,9 @@ argv0 = sys.argv[0] def textToNroff(s, font=r'\fR'): def escape(match): c = match.group(0) - if c == '-': - if font == r'\fB': - return r'\-' + if c.startswith('-'): + if c != '-' or font == r'\fB': + return '\\' + c else: return '-' if c == '\\': @@ -31,7 +31,7 @@ def textToNroff(s, font=r'\fR'): raise error.Error("bad escape") # Escape - \ " ' as needed by nroff. - s = re.sub('([-"\'\\\\])', escape, s) + s = re.sub('(-[0-9]|[-"\'\\\\])', escape, s) if s.startswith('.'): s = '\\' + s return s @@ -52,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.Error("'ref' lacks column and table attributes") + raise error.Error("'ref' lacks required attributes: %s" % node.attributes.keys()) return s + font elif node.tagName == 'var': s = r'\fI' @@ -86,7 +88,7 @@ def blockXmlToNroff(nodes, para='.PP'): and liNode.tagName == 'li'): i += 1 if node.tagName == 'ul': - s += ".IP \\bu\n" + s += ".IP \\(bu\n" else: s += ".IP %d. .25in\n" % i s += blockXmlToNroff(liNode.childNodes, ".IP") @@ -123,6 +125,15 @@ def blockXmlToNroff(nodes, para='.PP'): 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: @@ -133,17 +144,14 @@ def blockXmlToNroff(nodes, para='.PP'): def typeAndConstraintsToNroff(column): type = column.type.toEnglish(escapeNroffLiteral) - constraints = column.type.constraintsToEnglish(escapeNroffLiteral) + constraints = column.type.constraintsToEnglish(escapeNroffLiteral, + textToNroff) if constraints: type += ", " + constraints + if column.unique: + type += " (must be unique within table)" return type -def columnToNroff(columnName, column, node): - type = typeAndConstraintsToNroff(column) - s = '.IP "\\fB%s\\fR: %s"\n' % (columnName, type) - s += blockXmlToNroff(node.childNodes, '.IP') + "\n" - return s - def columnGroupToNroff(table, groupXml): introNodes = [] columnNodes = [] @@ -152,6 +160,10 @@ def columnGroupToNroff(table, groupXml): and node.tagName in ('column', 'group')): columnNodes += [node] else: + if (columnNodes + and not (node.nodeType == node.TEXT_NODE + and node.data.isspace())): + raise error.Error("text follows or inside : %s" % node) introNodes += [node] summary = [] @@ -159,10 +171,50 @@ def columnGroupToNroff(table, groupXml): body = '' for node in columnNodes: if node.tagName == 'column': - columnName = node.attributes['name'].nodeValue - column = table.columns[columnName] - body += columnToNroff(columnName, column, node) - summary += [('column', columnName, column)] + name = node.attributes['name'].nodeValue + column = table.columns[name] + if node.hasAttribute('key'): + key = node.attributes['key'].nodeValue + if node.hasAttribute('type'): + type_string = node.attributes['type'].nodeValue + type_json = ovs.json.from_string(str(type_string)) + if type(type_json) in (str, unicode): + raise error.Error("%s %s:%s has invalid 'type': %s" + % (table.name, name, key, type_json)) + type_ = ovs.db.types.BaseType.from_json(type_json) + else: + type_ = column.type.value + + nameNroff = "%s : %s" % (name, key) + + if column.type.value: + typeNroff = "optional %s" % column.type.value.toEnglish( + escapeNroffLiteral) + if (column.type.value.type == ovs.db.types.StringType and + type_.type == ovs.db.types.BooleanType): + # This is a little more explicit and helpful than + # "containing a boolean" + typeNroff += r", either \fBtrue\fR or \fBfalse\fR" + else: + if type_.type != column.type.value.type: + type_english = type_.toEnglish() + if type_english[0] in 'aeiou': + typeNroff += ", containing an %s" % type_english + else: + typeNroff += ", containing a %s" % type_english + constraints = ( + type_.constraintsToEnglish(escapeNroffLiteral, + textToNroff)) + if constraints: + typeNroff += ", %s" % constraints + else: + typeNroff = "none" + else: + nameNroff = name + typeNroff = typeAndConstraintsToNroff(column) + body += '.IP "\\fB%s\\fR: %s"\n' % (nameNroff, typeNroff) + body += blockXmlToNroff(node.childNodes, '.IP') + "\n" + summary += [('column', nameNroff, typeNroff)] elif node.tagName == 'group': title = node.attributes["title"].nodeValue subSummary, subIntro, subBody = columnGroupToNroff(table, node) @@ -177,19 +229,11 @@ 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)) + s += ".TQ %.2fin\n\\fB%s\\fR\n%s\n" % (3 - level * .25, name, arg) else: - if s != "": - s += "_\n" - s += """.T& -li | s -l | l. -%s%s -_ -""" % (r'\ \ ' * level, name) + s += ".TQ .25in\n\\fI%s:\\fR\n.RS .25in\n" % name s += tableSummaryToNroff(arg, level + 1) + s += ".RE\n" return s def tableToNroff(schema, tableXml): @@ -197,42 +241,31 @@ def tableToNroff(schema, tableXml): table = schema.tables[tableName] s = """.bp -.SS "%s Table" +.SH "%s TABLE" """ % tableName summary, intro, body = columnGroupToNroff(table, tableXml) s += intro - - s += r""" -.sp -.ce 1 -\fB%s\fR Table Columns: -.TS -center box; -l | l. -Column Type -= -""" % tableName + s += '.SS "Summary:\n' s += tableSummaryToNroff(summary) - s += ".TE\n" - + s += '.SS "Details:\n' s += body return s 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 - # 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" + # Putting '\" p as the first line tells "man" that the manpage + # needs to be preprocessed by "pic". + s = r''''\" p +.TH @VERSION@ 5 "%s" "Open vSwitch" "Open vSwitch Manual" .\" -*- nroff -*- .de TQ . br @@ -245,9 +278,10 @@ def docsToNroff(schemaFile, xmlFile, erFile, title=None): . I "\\$1" . RE .. -''' % (title, d.strftime("%B %Y")) - - s += '.SH "%s DATABASE"\n' % schema.name +.SH NAME +%s \- %s database schema +.PP +''' % (title, textToNroff(title), schema.name) tables = "" introNodes = [] @@ -268,38 +302,45 @@ def docsToNroff(schemaFile, xmlFile, erFile, title=None): introNodes += [dbNode] s += blockXmlToNroff(introNodes) + "\n" - tableSummary = r""" -.sp -.ce 1 -\fB%s\fR Database Tables: -.TS -center box; -l | l -lb | l. -Table Purpose -= + + s += r""" +.SH "TABLE SUMMARY" +.PP +The following list summarizes the purpose of each of the tables in the +\fB%s\fR database. Each table is described in more detail on a later +page. +.IP "Table" 1in +Purpose """ % schema.name for name, title in summary: - tableSummary += "%s\t%s\n" % (name, textToNroff(title)) - tableSummary += '.TE\n' - s += tableSummary + s += r""" +.TQ 1in +\fB%s\fR +%s +""" % (name, textToNroff(title)) if erFile: s += """ -.sp 1 +.\\" check if in troff mode (TTY) +.if t \{ +.bp .SH "TABLE RELATIONSHIPS" .PP The following diagram shows the relationship among tables in the -database. Each node represents a table. Each edge leads from 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. +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" + s += ".RE\\}\n" for node in tableNodes: s += tableToNroff(schema, node) + "\n" @@ -344,19 +385,19 @@ 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], er_diagram) for line in s.split("\n"): line = line.strip() if len(line): print line - + except error.Error, e: sys.stderr.write("%s: %s\n" % (argv0, e.msg)) sys.exit(1)