blob: 5328a504e3aaa69b712705a1318dafd4ec145dca [file] [log] [blame]
Fred Drake03204731998-11-23 17:02:03 +00001#! /usr/bin/env python
2
Fred Drake7dab6af1999-01-28 23:59:58 +00003"""Perform massive transformations on a document tree created from the LaTeX
4of the Python documentation, and dump the ESIS data for the transformed tree.
Fred Drake03204731998-11-23 17:02:03 +00005"""
6__version__ = '$Revision$'
7
8
9import errno
Fred Drake4db5b461998-12-01 19:03:01 +000010import esistools
11import re
Fred Drake03204731998-11-23 17:02:03 +000012import string
13import sys
14import xml.dom.core
Fred Drakee779d4f1999-05-10 19:36:52 +000015
16from xml.dom.core import \
17 ELEMENT, \
18 TEXT
Fred Drake03204731998-11-23 17:02:03 +000019
20
Fred Drakef8ebb551999-01-14 19:45:38 +000021class ConversionError(Exception):
22 pass
23
24
Fred Drake865e9ff1999-07-29 22:23:19 +000025PARA_ELEMENT = "para"
26
Fred Drakefcc59101999-01-06 22:50:52 +000027DEBUG_PARA_FIXER = 0
28
Fred Drake7dab6af1999-01-28 23:59:58 +000029if DEBUG_PARA_FIXER:
30 def para_msg(s):
31 sys.stderr.write("*** %s\n" % s)
32else:
33 def para_msg(s):
34 pass
35
Fred Drakefcc59101999-01-06 22:50:52 +000036
Fred Drake03204731998-11-23 17:02:03 +000037# Workaround to deal with invalid documents (multiple root elements). This
38# does not indicate a bug in the DOM implementation.
39#
Fred Drakee779d4f1999-05-10 19:36:52 +000040def get_documentElement(doc):
Fred Drake03204731998-11-23 17:02:03 +000041 docelem = None
Fred Drakee779d4f1999-05-10 19:36:52 +000042 for n in doc.childNodes:
43 if n.nodeType == ELEMENT:
44 docelem = n
Fred Drake03204731998-11-23 17:02:03 +000045 return docelem
46
47xml.dom.core.Document.get_documentElement = get_documentElement
48
49
50# Replace get_childNodes for the Document class; without this, children
51# accessed from the Document object via .childNodes (no matter how many
52# levels of access are used) will be given an ownerDocument of None.
53#
Fred Drakee779d4f1999-05-10 19:36:52 +000054def get_childNodes(doc):
55 return xml.dom.core.NodeList(doc._node.children, doc._node)
Fred Drake03204731998-11-23 17:02:03 +000056
57xml.dom.core.Document.get_childNodes = get_childNodes
58
59
60def get_first_element(doc, gi):
61 for n in doc.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +000062 if n.nodeType == ELEMENT and n.tagName == gi:
Fred Drake03204731998-11-23 17:02:03 +000063 return n
64
65def extract_first_element(doc, gi):
66 node = get_first_element(doc, gi)
67 if node is not None:
68 doc.removeChild(node)
69 return node
70
71
Fred Drake7dab6af1999-01-28 23:59:58 +000072def find_all_elements(doc, gi):
73 nodes = []
Fred Drakee779d4f1999-05-10 19:36:52 +000074 if doc.nodeType == ELEMENT and doc.tagName == gi:
Fred Drake7dab6af1999-01-28 23:59:58 +000075 nodes.append(doc)
76 for child in doc.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +000077 if child.nodeType == ELEMENT:
Fred Drake7dab6af1999-01-28 23:59:58 +000078 if child.tagName == gi:
79 nodes.append(child)
80 for node in child.getElementsByTagName(gi):
81 nodes.append(node)
Fred Drake865e9ff1999-07-29 22:23:19 +000082 return nodes
83
84def find_all_elements_from_set(doc, gi_set, nodes=None):
85 if nodes is None:
86 nodes = []
87 if doc.nodeType == ELEMENT and doc.tagName in gi_set:
88 nodes.append(doc)
89 for child in doc.childNodes:
90 if child.nodeType == ELEMENT:
91 find_all_elements_from_set(child, gi_set, nodes)
92 return nodes
Fred Drake7dab6af1999-01-28 23:59:58 +000093
94
Fred Drakee779d4f1999-05-10 19:36:52 +000095def simplify(doc, fragment):
Fred Drake03204731998-11-23 17:02:03 +000096 # Try to rationalize the document a bit, since these things are simply
97 # not valid SGML/XML documents as they stand, and need a little work.
98 documentclass = "document"
99 inputs = []
Fred Drakee779d4f1999-05-10 19:36:52 +0000100 node = extract_first_element(fragment, "documentclass")
Fred Drake03204731998-11-23 17:02:03 +0000101 if node is not None:
102 documentclass = node.getAttribute("classname")
Fred Drakee779d4f1999-05-10 19:36:52 +0000103 node = extract_first_element(fragment, "title")
Fred Drake03204731998-11-23 17:02:03 +0000104 if node is not None:
105 inputs.append(node)
106 # update the name of the root element
Fred Drakee779d4f1999-05-10 19:36:52 +0000107 node = get_first_element(fragment, "document")
Fred Drake03204731998-11-23 17:02:03 +0000108 if node is not None:
109 node._node.name = documentclass
110 while 1:
Fred Drakee779d4f1999-05-10 19:36:52 +0000111 node = extract_first_element(fragment, "input")
Fred Drake03204731998-11-23 17:02:03 +0000112 if node is None:
113 break
114 inputs.append(node)
115 if inputs:
Fred Drakee779d4f1999-05-10 19:36:52 +0000116 docelem = get_documentElement(fragment)
Fred Drake03204731998-11-23 17:02:03 +0000117 inputs.reverse()
118 for node in inputs:
119 text = doc.createTextNode("\n")
120 docelem.insertBefore(text, docelem.firstChild)
121 docelem.insertBefore(node, text)
122 docelem.insertBefore(doc.createTextNode("\n"), docelem.firstChild)
Fred Drake865e9ff1999-07-29 22:23:19 +0000123 while fragment.firstChild and fragment.firstChild.nodeType == TEXT:
Fred Drakee779d4f1999-05-10 19:36:52 +0000124 fragment.removeChild(fragment.firstChild)
Fred Drake03204731998-11-23 17:02:03 +0000125
126
127def cleanup_root_text(doc):
128 discards = []
129 skip = 0
130 for n in doc.childNodes:
131 prevskip = skip
132 skip = 0
Fred Drakee779d4f1999-05-10 19:36:52 +0000133 if n.nodeType == TEXT and not prevskip:
Fred Drake03204731998-11-23 17:02:03 +0000134 discards.append(n)
Fred Drakee779d4f1999-05-10 19:36:52 +0000135 elif n.nodeType == ELEMENT and n.tagName == "COMMENT":
Fred Drake03204731998-11-23 17:02:03 +0000136 skip = 1
137 for node in discards:
138 doc.removeChild(node)
139
140
Fred Drakecb657811999-01-29 20:55:07 +0000141DESCRIPTOR_ELEMENTS = (
142 "cfuncdesc", "cvardesc", "ctypedesc",
143 "classdesc", "memberdesc", "memberdescni", "methoddesc", "methoddescni",
144 "excdesc", "funcdesc", "funcdescni", "opcodedesc",
145 "datadesc", "datadescni",
146 )
147
Fred Drakee779d4f1999-05-10 19:36:52 +0000148def fixup_descriptors(doc, fragment):
149 sections = find_all_elements(fragment, "section")
Fred Drake3a7ff991999-01-29 21:31:12 +0000150 for section in sections:
151 find_and_fix_descriptors(doc, section)
152
153
154def find_and_fix_descriptors(doc, container):
155 children = container.childNodes
156 for child in children:
Fred Drakee779d4f1999-05-10 19:36:52 +0000157 if child.nodeType == ELEMENT:
Fred Drake3a7ff991999-01-29 21:31:12 +0000158 tagName = child.tagName
159 if tagName in DESCRIPTOR_ELEMENTS:
160 rewrite_descriptor(doc, child)
161 elif tagName == "subsection":
162 find_and_fix_descriptors(doc, child)
163
Fred Drakecb657811999-01-29 20:55:07 +0000164
165def rewrite_descriptor(doc, descriptor):
166 #
167 # Do these things:
168 # 1. Add an "index=noindex" attribute to the element if the tagName
169 # ends in 'ni', removing the 'ni' from the name.
170 # 2. Create a <signature> from the name attribute and <args>.
171 # 3. Create additional <signature>s from <*line{,ni}> elements,
172 # if found.
Fred Drake1dd152d1999-01-29 22:12:29 +0000173 # 4. If a <versionadded> is found, move it to an attribute on the
174 # descriptor.
175 # 5. Move remaining child nodes to a <description> element.
176 # 6. Put it back together.
Fred Drakecb657811999-01-29 20:55:07 +0000177 #
178 descname = descriptor.tagName
179 index = 1
180 if descname[-2:] == "ni":
181 descname = descname[:-2]
182 descriptor.setAttribute("index", "noindex")
183 descriptor._node.name = descname
184 index = 0
185 desctype = descname[:-4] # remove 'desc'
186 linename = desctype + "line"
187 if not index:
188 linename = linename + "ni"
189 # 2.
190 signature = doc.createElement("signature")
191 name = doc.createElement("name")
192 signature.appendChild(doc.createTextNode("\n "))
193 signature.appendChild(name)
194 name.appendChild(doc.createTextNode(descriptor.getAttribute("name")))
195 descriptor.removeAttribute("name")
196 if descriptor.attributes.has_key("var"):
197 variable = descriptor.getAttribute("var")
198 if variable:
199 args = doc.createElement("args")
200 args.appendChild(doc.createTextNode(variable))
Fred Drake7dab6af1999-01-28 23:59:58 +0000201 signature.appendChild(doc.createTextNode("\n "))
Fred Drakecb657811999-01-29 20:55:07 +0000202 signature.appendChild(args)
203 descriptor.removeAttribute("var")
204 newchildren = [signature]
205 children = descriptor.childNodes
206 pos = skip_leading_nodes(children, 0)
207 if pos < len(children):
208 child = children[pos]
Fred Drakee779d4f1999-05-10 19:36:52 +0000209 if child.nodeType == ELEMENT and child.tagName == "args":
Fred Drakecb657811999-01-29 20:55:07 +0000210 # create an <args> in <signature>:
211 args = doc.createElement("args")
212 argchildren = []
213 map(argchildren.append, child.childNodes)
214 for n in argchildren:
215 child.removeChild(n)
216 args.appendChild(n)
217 signature.appendChild(doc.createTextNode("\n "))
218 signature.appendChild(args)
219 signature.appendChild(doc.createTextNode("\n "))
Fred Drake1dd152d1999-01-29 22:12:29 +0000220 # 3, 4.
Fred Drakecb657811999-01-29 20:55:07 +0000221 pos = skip_leading_nodes(children, pos + 1)
222 while pos < len(children) \
Fred Drakee779d4f1999-05-10 19:36:52 +0000223 and children[pos].nodeType == ELEMENT \
Fred Drake1dd152d1999-01-29 22:12:29 +0000224 and children[pos].tagName in (linename, "versionadded"):
225 if children[pos].tagName == linename:
226 # this is really a supplemental signature, create <signature>
227 sig = methodline_to_signature(doc, children[pos])
228 newchildren.append(sig)
229 else:
230 # <versionadded added=...>
231 descriptor.setAttribute(
232 "added", children[pos].getAttribute("version"))
Fred Drakecb657811999-01-29 20:55:07 +0000233 pos = skip_leading_nodes(children, pos + 1)
Fred Drake1dd152d1999-01-29 22:12:29 +0000234 # 5.
Fred Drakecb657811999-01-29 20:55:07 +0000235 description = doc.createElement("description")
236 description.appendChild(doc.createTextNode("\n"))
237 newchildren.append(description)
238 move_children(descriptor, description, pos)
239 last = description.childNodes[-1]
Fred Drakee779d4f1999-05-10 19:36:52 +0000240 if last.nodeType == TEXT:
Fred Drakecb657811999-01-29 20:55:07 +0000241 last.data = string.rstrip(last.data) + "\n "
Fred Drake1dd152d1999-01-29 22:12:29 +0000242 # 6.
Fred Drakecb657811999-01-29 20:55:07 +0000243 # should have nothing but whitespace and signature lines in <descriptor>;
244 # discard them
245 while descriptor.childNodes:
246 descriptor.removeChild(descriptor.childNodes[0])
247 for node in newchildren:
248 descriptor.appendChild(doc.createTextNode("\n "))
249 descriptor.appendChild(node)
250 descriptor.appendChild(doc.createTextNode("\n"))
Fred Drake03204731998-11-23 17:02:03 +0000251
Fred Drake7dab6af1999-01-28 23:59:58 +0000252
253def methodline_to_signature(doc, methodline):
254 signature = doc.createElement("signature")
255 signature.appendChild(doc.createTextNode("\n "))
256 name = doc.createElement("name")
257 name.appendChild(doc.createTextNode(methodline.getAttribute("name")))
Fred Drakecb657811999-01-29 20:55:07 +0000258 methodline.removeAttribute("name")
Fred Drake7dab6af1999-01-28 23:59:58 +0000259 signature.appendChild(name)
Fred Drake7dab6af1999-01-28 23:59:58 +0000260 if len(methodline.childNodes):
Fred Drakecb657811999-01-29 20:55:07 +0000261 args = doc.createElement("args")
Fred Drake7dab6af1999-01-28 23:59:58 +0000262 signature.appendChild(doc.createTextNode("\n "))
Fred Drakecb657811999-01-29 20:55:07 +0000263 signature.appendChild(args)
264 move_children(methodline, args)
Fred Drake7dab6af1999-01-28 23:59:58 +0000265 signature.appendChild(doc.createTextNode("\n "))
266 return signature
Fred Drake03204731998-11-23 17:02:03 +0000267
268
Fred Drakecb657811999-01-29 20:55:07 +0000269def move_children(origin, dest, start=0):
270 children = origin.childNodes
271 while start < len(children):
272 node = children[start]
273 origin.removeChild(node)
274 dest.appendChild(node)
275
276
Fred Drakee779d4f1999-05-10 19:36:52 +0000277def handle_appendix(doc, fragment):
Fred Drake4db5b461998-12-01 19:03:01 +0000278 # must be called after simplfy() if document is multi-rooted to begin with
Fred Drakee779d4f1999-05-10 19:36:52 +0000279 docelem = get_documentElement(fragment)
Fred Drake4db5b461998-12-01 19:03:01 +0000280 toplevel = docelem.tagName == "manual" and "chapter" or "section"
281 appendices = 0
282 nodes = []
283 for node in docelem.childNodes:
284 if appendices:
285 nodes.append(node)
Fred Drakee779d4f1999-05-10 19:36:52 +0000286 elif node.nodeType == ELEMENT:
Fred Drake4db5b461998-12-01 19:03:01 +0000287 appnodes = node.getElementsByTagName("appendix")
288 if appnodes:
289 appendices = 1
290 parent = appnodes[0].parentNode
291 parent.removeChild(appnodes[0])
292 parent.normalize()
293 if nodes:
294 map(docelem.removeChild, nodes)
295 docelem.appendChild(doc.createTextNode("\n\n\n"))
296 back = doc.createElement("back-matter")
297 docelem.appendChild(back)
298 back.appendChild(doc.createTextNode("\n"))
Fred Drakee779d4f1999-05-10 19:36:52 +0000299 while nodes and nodes[0].nodeType == TEXT \
Fred Drake4db5b461998-12-01 19:03:01 +0000300 and not string.strip(nodes[0].data):
301 del nodes[0]
302 map(back.appendChild, nodes)
303 docelem.appendChild(doc.createTextNode("\n"))
Fred Drake03204731998-11-23 17:02:03 +0000304
305
Fred Drake865e9ff1999-07-29 22:23:19 +0000306def handle_labels(doc, fragment):
307 for label in find_all_elements(fragment, "label"):
Fred Drake7dab6af1999-01-28 23:59:58 +0000308 id = label.getAttribute("id")
309 if not id:
310 continue
311 parent = label.parentNode
312 if parent.tagName == "title":
313 parent.parentNode.setAttribute("id", id)
314 else:
315 parent.setAttribute("id", id)
316 # now, remove <label id="..."/> from parent:
317 parent.removeChild(label)
Fred Drake865e9ff1999-07-29 22:23:19 +0000318 if parent.tagName == "title":
319 parent.normalize()
320 children = parent.childNodes
321 if children[-1].nodeType == TEXT:
322 children[-1].data = string.rstrip(children[-1].data)
Fred Drake03204731998-11-23 17:02:03 +0000323
324
Fred Drake1ff6db41998-11-23 23:10:35 +0000325def fixup_trailing_whitespace(doc, wsmap):
326 queue = [doc]
327 while queue:
328 node = queue[0]
329 del queue[0]
Fred Drakee779d4f1999-05-10 19:36:52 +0000330 if node.nodeType == ELEMENT \
Fred Drake1ff6db41998-11-23 23:10:35 +0000331 and wsmap.has_key(node.tagName):
332 ws = wsmap[node.tagName]
333 children = node.childNodes
334 children.reverse()
Fred Drakee779d4f1999-05-10 19:36:52 +0000335 if children[0].nodeType == TEXT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000336 data = string.rstrip(children[0].data) + ws
337 children[0].data = data
338 children.reverse()
339 # hack to get the title in place:
340 if node.tagName == "title" \
Fred Drakee779d4f1999-05-10 19:36:52 +0000341 and node.parentNode.firstChild.nodeType == ELEMENT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000342 node.parentNode.insertBefore(doc.createText("\n "),
343 node.parentNode.firstChild)
344 for child in node.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000345 if child.nodeType == ELEMENT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000346 queue.append(child)
347
348
349def normalize(doc):
350 for node in doc.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000351 if node.nodeType == ELEMENT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000352 node.normalize()
353
354
355def cleanup_trailing_parens(doc, element_names):
356 d = {}
357 for gi in element_names:
358 d[gi] = gi
359 rewrite_element = d.has_key
360 queue = []
361 for node in doc.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000362 if node.nodeType == ELEMENT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000363 queue.append(node)
364 while queue:
365 node = queue[0]
366 del queue[0]
367 if rewrite_element(node.tagName):
368 children = node.childNodes
369 if len(children) == 1 \
Fred Drakee779d4f1999-05-10 19:36:52 +0000370 and children[0].nodeType == TEXT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000371 data = children[0].data
372 if data[-2:] == "()":
373 children[0].data = data[:-2]
374 else:
375 for child in node.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000376 if child.nodeType == ELEMENT:
Fred Drake1ff6db41998-11-23 23:10:35 +0000377 queue.append(child)
378
379
Fred Drakeaaed9711998-12-10 20:25:30 +0000380def contents_match(left, right):
381 left_children = left.childNodes
382 right_children = right.childNodes
383 if len(left_children) != len(right_children):
384 return 0
385 for l, r in map(None, left_children, right_children):
386 nodeType = l.nodeType
387 if nodeType != r.nodeType:
388 return 0
Fred Drakee779d4f1999-05-10 19:36:52 +0000389 if nodeType == ELEMENT:
Fred Drakeaaed9711998-12-10 20:25:30 +0000390 if l.tagName != r.tagName:
391 return 0
392 # should check attributes, but that's not a problem here
393 if not contents_match(l, r):
394 return 0
Fred Drakee779d4f1999-05-10 19:36:52 +0000395 elif nodeType == TEXT:
Fred Drakeaaed9711998-12-10 20:25:30 +0000396 if l.data != r.data:
397 return 0
398 else:
399 # not quite right, but good enough
400 return 0
401 return 1
402
403
404def create_module_info(doc, section):
405 # Heavy.
406 node = extract_first_element(section, "modulesynopsis")
407 if node is None:
408 return
409 node._node.name = "synopsis"
410 lastchild = node.childNodes[-1]
Fred Drakee779d4f1999-05-10 19:36:52 +0000411 if lastchild.nodeType == TEXT \
Fred Drakeaaed9711998-12-10 20:25:30 +0000412 and lastchild.data[-1:] == ".":
413 lastchild.data = lastchild.data[:-1]
Fred Drake4259f0d1999-01-19 23:09:31 +0000414 modauthor = extract_first_element(section, "moduleauthor")
415 if modauthor:
416 modauthor._node.name = "author"
417 modauthor.appendChild(doc.createTextNode(
418 modauthor.getAttribute("name")))
419 modauthor.removeAttribute("name")
Fred Drake87a42cd1999-03-11 17:35:12 +0000420 platform = extract_first_element(section, "platform")
Fred Drakeaaed9711998-12-10 20:25:30 +0000421 if section.tagName == "section":
422 modinfo_pos = 2
423 modinfo = doc.createElement("moduleinfo")
424 moddecl = extract_first_element(section, "declaremodule")
425 name = None
426 if moddecl:
427 modinfo.appendChild(doc.createTextNode("\n "))
428 name = moddecl.attributes["name"].value
429 namenode = doc.createElement("name")
430 namenode.appendChild(doc.createTextNode(name))
431 modinfo.appendChild(namenode)
432 type = moddecl.attributes.get("type")
433 if type:
434 type = type.value
435 modinfo.appendChild(doc.createTextNode("\n "))
436 typenode = doc.createElement("type")
437 typenode.appendChild(doc.createTextNode(type))
438 modinfo.appendChild(typenode)
Fred Drake1dd152d1999-01-29 22:12:29 +0000439 versionadded = extract_first_element(section, "versionadded")
440 if versionadded:
441 modinfo.setAttribute("added", versionadded.getAttribute("version"))
Fred Drakeaaed9711998-12-10 20:25:30 +0000442 title = get_first_element(section, "title")
443 if title:
444 children = title.childNodes
445 if len(children) >= 2 \
Fred Drakee779d4f1999-05-10 19:36:52 +0000446 and children[0].nodeType == ELEMENT \
Fred Drakeaaed9711998-12-10 20:25:30 +0000447 and children[0].tagName == "module" \
448 and children[0].childNodes[0].data == name:
449 # this is it; morph the <title> into <short-synopsis>
450 first_data = children[1]
451 if first_data.data[:4] == " ---":
452 first_data.data = string.lstrip(first_data.data[4:])
453 title._node.name = "short-synopsis"
Fred Drakee779d4f1999-05-10 19:36:52 +0000454 if children[-1].nodeType == TEXT \
Fred Drake7dab6af1999-01-28 23:59:58 +0000455 and children[-1].data[-1:] == ".":
Fred Drakeaaed9711998-12-10 20:25:30 +0000456 children[-1].data = children[-1].data[:-1]
457 section.removeChild(title)
458 section.removeChild(section.childNodes[0])
459 title.removeChild(children[0])
460 modinfo_pos = 0
461 else:
462 sys.stderr.write(
463 "module name in title doesn't match"
464 " <declaremodule>; no <short-synopsis>\n")
465 else:
466 sys.stderr.write(
467 "Unexpected condition: <section> without <title>\n")
468 modinfo.appendChild(doc.createTextNode("\n "))
469 modinfo.appendChild(node)
470 if title and not contents_match(title, node):
471 # The short synopsis is actually different,
472 # and needs to be stored:
473 modinfo.appendChild(doc.createTextNode("\n "))
474 modinfo.appendChild(title)
Fred Drake4259f0d1999-01-19 23:09:31 +0000475 if modauthor:
476 modinfo.appendChild(doc.createTextNode("\n "))
477 modinfo.appendChild(modauthor)
Fred Drake87a42cd1999-03-11 17:35:12 +0000478 if platform:
479 modinfo.appendChild(doc.createTextNode("\n "))
480 modinfo.appendChild(platform)
Fred Drakeaaed9711998-12-10 20:25:30 +0000481 modinfo.appendChild(doc.createTextNode("\n "))
482 section.insertBefore(modinfo, section.childNodes[modinfo_pos])
483 section.insertBefore(doc.createTextNode("\n "), modinfo)
Fred Drake87a42cd1999-03-11 17:35:12 +0000484 #
485 # The rest of this removes extra newlines from where we cut out
486 # a lot of elements. A lot of code for minimal value, but keeps
487 # keeps the generated SGML from being too funny looking.
488 #
489 section.normalize()
490 children = section.childNodes
491 for i in range(len(children)):
492 node = children[i]
Fred Drakee779d4f1999-05-10 19:36:52 +0000493 if node.nodeType == ELEMENT \
Fred Drake87a42cd1999-03-11 17:35:12 +0000494 and node.tagName == "moduleinfo":
495 nextnode = children[i+1]
Fred Drakee779d4f1999-05-10 19:36:52 +0000496 if nextnode.nodeType == TEXT:
Fred Drake87a42cd1999-03-11 17:35:12 +0000497 data = nextnode.data
498 if len(string.lstrip(data)) < (len(data) - 4):
499 nextnode.data = "\n\n\n" + string.lstrip(data)
Fred Drakeaaed9711998-12-10 20:25:30 +0000500
501
Fred Drakefba0ba21998-12-10 05:07:09 +0000502def cleanup_synopses(doc):
Fred Drake7dab6af1999-01-28 23:59:58 +0000503 for node in find_all_elements(doc, "section"):
504 create_module_info(doc, node)
Fred Drakeaaed9711998-12-10 20:25:30 +0000505
506
Fred Drakef8ebb551999-01-14 19:45:38 +0000507def remap_element_names(root, name_map):
508 queue = []
509 for child in root.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000510 if child.nodeType == ELEMENT:
Fred Drakef8ebb551999-01-14 19:45:38 +0000511 queue.append(child)
512 while queue:
513 node = queue.pop()
514 tagName = node.tagName
515 if name_map.has_key(tagName):
516 name, attrs = name_map[tagName]
517 node._node.name = name
518 for attr, value in attrs.items():
519 node.setAttribute(attr, value)
520 for child in node.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000521 if child.nodeType == ELEMENT:
Fred Drakef8ebb551999-01-14 19:45:38 +0000522 queue.append(child)
523
524
Fred Drakee779d4f1999-05-10 19:36:52 +0000525def fixup_table_structures(doc, fragment):
Fred Drakef8ebb551999-01-14 19:45:38 +0000526 # must be done after remap_element_names(), or the tables won't be found
Fred Drakee779d4f1999-05-10 19:36:52 +0000527 for table in find_all_elements(fragment, "table"):
Fred Drake7dab6af1999-01-28 23:59:58 +0000528 fixup_table(doc, table)
529
Fred Drakef8ebb551999-01-14 19:45:38 +0000530
531def fixup_table(doc, table):
532 # create the table head
533 thead = doc.createElement("thead")
534 row = doc.createElement("row")
535 move_elements_by_name(doc, table, row, "entry")
536 thead.appendChild(doc.createTextNode("\n "))
537 thead.appendChild(row)
538 thead.appendChild(doc.createTextNode("\n "))
539 # create the table body
540 tbody = doc.createElement("tbody")
541 prev_row = None
542 last_was_hline = 0
543 children = table.childNodes
544 for child in children:
Fred Drakee779d4f1999-05-10 19:36:52 +0000545 if child.nodeType == ELEMENT:
Fred Drakef8ebb551999-01-14 19:45:38 +0000546 tagName = child.tagName
547 if tagName == "hline" and prev_row is not None:
548 prev_row.setAttribute("rowsep", "1")
549 elif tagName == "row":
550 prev_row = child
551 # save the rows:
552 tbody.appendChild(doc.createTextNode("\n "))
553 move_elements_by_name(doc, table, tbody, "row", sep="\n ")
554 # and toss the rest:
555 while children:
556 child = children[0]
557 nodeType = child.nodeType
Fred Drakee779d4f1999-05-10 19:36:52 +0000558 if nodeType == TEXT:
Fred Drakef8ebb551999-01-14 19:45:38 +0000559 if string.strip(child.data):
560 raise ConversionError("unexpected free data in table")
561 table.removeChild(child)
562 continue
Fred Drakee779d4f1999-05-10 19:36:52 +0000563 if nodeType == ELEMENT:
Fred Drakef8ebb551999-01-14 19:45:38 +0000564 if child.tagName != "hline":
565 raise ConversionError(
566 "unexpected <%s> in table" % child.tagName)
567 table.removeChild(child)
568 continue
569 raise ConversionError(
570 "unexpected %s node in table" % child.__class__.__name__)
571 # nothing left in the <table>; add the <thead> and <tbody>
572 tgroup = doc.createElement("tgroup")
573 tgroup.appendChild(doc.createTextNode("\n "))
574 tgroup.appendChild(thead)
575 tgroup.appendChild(doc.createTextNode("\n "))
576 tgroup.appendChild(tbody)
577 tgroup.appendChild(doc.createTextNode("\n "))
578 table.appendChild(tgroup)
579 # now make the <entry>s look nice:
580 for row in table.getElementsByTagName("row"):
581 fixup_row(doc, row)
582
583
584def fixup_row(doc, row):
585 entries = []
586 map(entries.append, row.childNodes[1:])
587 for entry in entries:
588 row.insertBefore(doc.createTextNode("\n "), entry)
589# row.appendChild(doc.createTextNode("\n "))
590
591
592def move_elements_by_name(doc, source, dest, name, sep=None):
593 nodes = []
594 for child in source.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000595 if child.nodeType == ELEMENT and child.tagName == name:
Fred Drakef8ebb551999-01-14 19:45:38 +0000596 nodes.append(child)
597 for node in nodes:
598 source.removeChild(node)
599 dest.appendChild(node)
600 if sep:
601 dest.appendChild(doc.createTextNode(sep))
602
603
Fred Drake7dab6af1999-01-28 23:59:58 +0000604RECURSE_INTO_PARA_CONTAINERS = (
Fred Drakecb657811999-01-29 20:55:07 +0000605 "chapter", "abstract", "enumerate",
Fred Drake7dab6af1999-01-28 23:59:58 +0000606 "section", "subsection", "subsubsection",
Fred Drake865e9ff1999-07-29 22:23:19 +0000607 "paragraph", "subparagraph", "back-matter",
Fred Drakecb657811999-01-29 20:55:07 +0000608 "howto", "manual",
Fred Drake4259f0d1999-01-19 23:09:31 +0000609 )
Fred Drakefcc59101999-01-06 22:50:52 +0000610
611PARA_LEVEL_ELEMENTS = (
Fred Drakecb657811999-01-29 20:55:07 +0000612 "moduleinfo", "title", "verbatim", "enumerate", "item",
Fred Drake865e9ff1999-07-29 22:23:19 +0000613 "interpreter-session", "back-matter", "interactive-session",
Fred Drakecb657811999-01-29 20:55:07 +0000614 "opcodedesc", "classdesc", "datadesc",
Fred Drake865e9ff1999-07-29 22:23:19 +0000615 "funcdesc", "methoddesc", "excdesc", "memberdesc", "membderdescni",
Fred Drake7dab6af1999-01-28 23:59:58 +0000616 "funcdescni", "methoddescni", "excdescni",
Fred Drakefcc59101999-01-06 22:50:52 +0000617 "tableii", "tableiii", "tableiv", "localmoduletable",
Fred Drake7dab6af1999-01-28 23:59:58 +0000618 "sectionauthor", "seealso",
Fred Drakefcc59101999-01-06 22:50:52 +0000619 # include <para>, so we can just do it again to get subsequent paras:
Fred Drake865e9ff1999-07-29 22:23:19 +0000620 PARA_ELEMENT,
Fred Drakefcc59101999-01-06 22:50:52 +0000621 )
622
623PARA_LEVEL_PRECEEDERS = (
Fred Drakecb657811999-01-29 20:55:07 +0000624 "index", "indexii", "indexiii", "indexiv", "setindexsubitem",
625 "stindex", "obindex", "COMMENT", "label", "input", "title",
Fred Drake865e9ff1999-07-29 22:23:19 +0000626 "versionadded", "versionchanged", "declaremodule", "modulesynopsis",
627 "moduleauthor",
Fred Drakefcc59101999-01-06 22:50:52 +0000628 )
629
Fred Drake7dab6af1999-01-28 23:59:58 +0000630
Fred Drakee779d4f1999-05-10 19:36:52 +0000631def fixup_paras(doc, fragment):
632 for child in fragment.childNodes:
633 if child.nodeType == ELEMENT \
Fred Drake7dab6af1999-01-28 23:59:58 +0000634 and child.tagName in RECURSE_INTO_PARA_CONTAINERS:
635 #
Fred Drakefcc59101999-01-06 22:50:52 +0000636 fixup_paras_helper(doc, child)
Fred Drakee779d4f1999-05-10 19:36:52 +0000637 descriptions = find_all_elements(fragment, "description")
Fred Drakecb657811999-01-29 20:55:07 +0000638 for description in descriptions:
639 fixup_paras_helper(doc, description)
Fred Drakefcc59101999-01-06 22:50:52 +0000640
641
Fred Drake7dab6af1999-01-28 23:59:58 +0000642def fixup_paras_helper(doc, container, depth=0):
Fred Drakefcc59101999-01-06 22:50:52 +0000643 # document is already normalized
644 children = container.childNodes
645 start = 0
Fred Drake7dab6af1999-01-28 23:59:58 +0000646 while len(children) > start:
647 start = skip_leading_nodes(children, start)
648 if start >= len(children):
649 break
650 #
651 # Either paragraph material or something to recurse into:
652 #
Fred Drakee779d4f1999-05-10 19:36:52 +0000653 if (children[start].nodeType == ELEMENT) \
Fred Drake7dab6af1999-01-28 23:59:58 +0000654 and (children[start].tagName in RECURSE_INTO_PARA_CONTAINERS):
655 fixup_paras_helper(doc, children[start])
656 start = skip_leading_nodes(children, start + 1)
657 continue
658 #
659 # paragraph material:
660 #
661 build_para(doc, container, start, len(children))
662 if DEBUG_PARA_FIXER and depth == 10:
663 sys.exit(1)
664 start = start + 1
Fred Drakefcc59101999-01-06 22:50:52 +0000665
666
667def build_para(doc, parent, start, i):
668 children = parent.childNodes
Fred Drakefcc59101999-01-06 22:50:52 +0000669 after = start + 1
670 have_last = 0
Fred Drakecb657811999-01-29 20:55:07 +0000671 BREAK_ELEMENTS = PARA_LEVEL_ELEMENTS + RECURSE_INTO_PARA_CONTAINERS
Fred Drake7dab6af1999-01-28 23:59:58 +0000672 # Collect all children until \n\n+ is found in a text node or a
673 # member of BREAK_ELEMENTS is found.
Fred Drakefcc59101999-01-06 22:50:52 +0000674 for j in range(start, i):
675 after = j + 1
676 child = children[j]
677 nodeType = child.nodeType
Fred Drakee779d4f1999-05-10 19:36:52 +0000678 if nodeType == ELEMENT:
Fred Drakefcc59101999-01-06 22:50:52 +0000679 if child.tagName in BREAK_ELEMENTS:
680 after = j
681 break
Fred Drakee779d4f1999-05-10 19:36:52 +0000682 elif nodeType == TEXT:
Fred Drakefcc59101999-01-06 22:50:52 +0000683 pos = string.find(child.data, "\n\n")
684 if pos == 0:
685 after = j
686 break
687 if pos >= 1:
688 child.splitText(pos)
689 break
690 else:
691 have_last = 1
Fred Drake7dab6af1999-01-28 23:59:58 +0000692 if (start + 1) > after:
693 raise ConversionError(
694 "build_para() could not identify content to turn into a paragraph")
Fred Drakee779d4f1999-05-10 19:36:52 +0000695 if children[after - 1].nodeType == TEXT:
Fred Drakefcc59101999-01-06 22:50:52 +0000696 # we may need to split off trailing white space:
697 child = children[after - 1]
698 data = child.data
699 if string.rstrip(data) != data:
700 have_last = 0
701 child.splitText(len(string.rstrip(data)))
Fred Drake865e9ff1999-07-29 22:23:19 +0000702 para = doc.createElement(PARA_ELEMENT)
Fred Drakefcc59101999-01-06 22:50:52 +0000703 prev = None
704 indexes = range(start, after)
705 indexes.reverse()
706 for j in indexes:
Fred Drake7dab6af1999-01-28 23:59:58 +0000707 node = parent.childNodes[j]
Fred Drakefcc59101999-01-06 22:50:52 +0000708 parent.removeChild(node)
709 para.insertBefore(node, prev)
710 prev = node
711 if have_last:
712 parent.appendChild(para)
Fred Drake7dab6af1999-01-28 23:59:58 +0000713 return len(parent.childNodes)
Fred Drakefcc59101999-01-06 22:50:52 +0000714 else:
715 parent.insertBefore(para, parent.childNodes[start])
Fred Drake7dab6af1999-01-28 23:59:58 +0000716 return start + 1
Fred Drakefcc59101999-01-06 22:50:52 +0000717
718
Fred Drake7dab6af1999-01-28 23:59:58 +0000719def skip_leading_nodes(children, start):
720 """Return index into children of a node at which paragraph building should
721 begin or a recursive call to fixup_paras_helper() should be made (for
722 subsections, etc.).
723
724 When the return value >= len(children), we've built all the paras we can
725 from this list of children.
726 """
727 i = len(children)
Fred Drakefcc59101999-01-06 22:50:52 +0000728 while i > start:
729 # skip over leading comments and whitespace:
Fred Drake7dab6af1999-01-28 23:59:58 +0000730 child = children[start]
Fred Drakefcc59101999-01-06 22:50:52 +0000731 nodeType = child.nodeType
Fred Drakee779d4f1999-05-10 19:36:52 +0000732 if nodeType == TEXT:
Fred Drakefcc59101999-01-06 22:50:52 +0000733 data = child.data
734 shortened = string.lstrip(data)
735 if shortened:
736 if data != shortened:
737 # break into two nodes: whitespace and non-whitespace
738 child.splitText(len(data) - len(shortened))
Fred Drake7dab6af1999-01-28 23:59:58 +0000739 return start + 1
740 return start
Fred Drakefcc59101999-01-06 22:50:52 +0000741 # all whitespace, just skip
Fred Drakee779d4f1999-05-10 19:36:52 +0000742 elif nodeType == ELEMENT:
Fred Drake7dab6af1999-01-28 23:59:58 +0000743 tagName = child.tagName
744 if tagName in RECURSE_INTO_PARA_CONTAINERS:
745 return start
746 if tagName not in PARA_LEVEL_ELEMENTS + PARA_LEVEL_PRECEEDERS:
747 return start
748 start = start + 1
749 return start
Fred Drakefba0ba21998-12-10 05:07:09 +0000750
751
Fred Drakee779d4f1999-05-10 19:36:52 +0000752def fixup_rfc_references(doc, fragment):
753 for rfcnode in find_all_elements(fragment, "rfc"):
Fred Drake7dab6af1999-01-28 23:59:58 +0000754 rfcnode.appendChild(doc.createTextNode(
755 "RFC " + rfcnode.getAttribute("num")))
Fred Draked24167b1999-01-14 21:18:03 +0000756
757
Fred Drakee779d4f1999-05-10 19:36:52 +0000758def fixup_signatures(doc, fragment):
759 for child in fragment.childNodes:
760 if child.nodeType == ELEMENT:
Fred Draked24167b1999-01-14 21:18:03 +0000761 args = child.getElementsByTagName("args")
762 for arg in args:
763 fixup_args(doc, arg)
Fred Drake7dab6af1999-01-28 23:59:58 +0000764 arg.normalize()
Fred Draked24167b1999-01-14 21:18:03 +0000765 args = child.getElementsByTagName("constructor-args")
766 for arg in args:
767 fixup_args(doc, arg)
768 arg.normalize()
769
770
771def fixup_args(doc, arglist):
772 for child in arglist.childNodes:
Fred Drakee779d4f1999-05-10 19:36:52 +0000773 if child.nodeType == ELEMENT \
Fred Draked24167b1999-01-14 21:18:03 +0000774 and child.tagName == "optional":
775 # found it; fix and return
776 arglist.insertBefore(doc.createTextNode("["), child)
777 optkids = child.childNodes
778 while optkids:
779 k = optkids[0]
780 child.removeChild(k)
781 arglist.insertBefore(k, child)
782 arglist.insertBefore(doc.createTextNode("]"), child)
783 arglist.removeChild(child)
784 return fixup_args(doc, arglist)
785
786
Fred Drakee779d4f1999-05-10 19:36:52 +0000787def fixup_sectionauthors(doc, fragment):
788 for sectauth in find_all_elements(fragment, "sectionauthor"):
Fred Drake7dab6af1999-01-28 23:59:58 +0000789 section = sectauth.parentNode
790 section.removeChild(sectauth)
791 sectauth._node.name = "author"
792 sectauth.appendChild(doc.createTextNode(
793 sectauth.getAttribute("name")))
794 sectauth.removeAttribute("name")
795 after = section.childNodes[2]
796 title = section.childNodes[1]
Fred Drakee779d4f1999-05-10 19:36:52 +0000797 if title.nodeType == ELEMENT and title.tagName != "title":
Fred Drake7dab6af1999-01-28 23:59:58 +0000798 after = section.childNodes[0]
799 section.insertBefore(doc.createTextNode("\n "), after)
800 section.insertBefore(sectauth, after)
801
802
Fred Drake93d762f1999-02-18 16:32:21 +0000803def fixup_verbatims(doc):
804 for verbatim in find_all_elements(doc, "verbatim"):
805 child = verbatim.childNodes[0]
Fred Drakee779d4f1999-05-10 19:36:52 +0000806 if child.nodeType == TEXT \
Fred Drake93d762f1999-02-18 16:32:21 +0000807 and string.lstrip(child.data)[:3] == ">>>":
Fred Drakee779d4f1999-05-10 19:36:52 +0000808 verbatim._node.name = "interactive-session"
Fred Drake93d762f1999-02-18 16:32:21 +0000809
810
Fred Drake865e9ff1999-07-29 22:23:19 +0000811def add_node_ids(fragment, counter=0):
812 fragment._node.node_id = counter
813 for node in fragment.childNodes:
814 counter = counter + 1
815 if node.nodeType == ELEMENT:
816 counter = add_node_ids(node, counter)
817 else:
818 node._node.node_id = counter
819 return counter + 1
820
821
822REFMODINDEX_ELEMENTS = ('refmodindex', 'refbimodindex',
823 'refexmodindex', 'refstmodindex')
824
825def fixup_refmodindexes(fragment):
826 # Locate <ref*modindex>...</> co-located with <module>...</>, and
827 # remove the <ref*modindex>, replacing it with index=index on the
828 # <module> element.
829 nodes = find_all_elements_from_set(fragment, REFMODINDEX_ELEMENTS)
830 d = {}
831 for node in nodes:
832 parent = node.parentNode
833 d[parent._node.node_id] = parent
834 del nodes
835 map(fixup_refmodindexes_chunk, d.values())
836
837
838def fixup_refmodindexes_chunk(container):
839 # node is probably a <para>; let's see how often it isn't:
840 if container.tagName != PARA_ELEMENT:
841 sys.stderr.write("--- fixup_refmodindexes_chunk(%s)\n" % container)
842 module_entries = find_all_elements(container, "module")
843 if not module_entries:
844 return
845 index_entries = find_all_elements_from_set(container, REFMODINDEX_ELEMENTS)
846 removes = []
847 for entry in index_entries:
848 children = entry.childNodes
849 if len(children) != 0:
850 sys.stderr.write(
851 "--- unexpected number of children for %s node:\n"
852 % entry.tagName)
853 sys.stderr.write(entry.toxml() + "\n")
854 continue
855 found = 0
856 module_name = entry.getAttribute("name")
857 for node in module_entries:
858 if len(node.childNodes) != 1:
859 continue
860 this_name = node.childNodes[0].data
861 if this_name == module_name:
862 found = 1
863 node.setAttribute("index", "index")
864 if found:
865 removes.append(entry)
866 for node in removes:
867 container.removeChild(node)
868
869
870def fixup_bifuncindexes(fragment):
871 nodes = find_all_elements(fragment, 'bifuncindex')
872 d = {}
873 for node in nodes:
874 parent = node.parentNode
875 d[parent._node.node_id] = parent
876 del nodes
877 map(fixup_bifuncindexes_chunk, d.values())
878
879
880def fixup_bifuncindexes_chunk(container):
881 removes = []
882 entries = find_all_elements(container, "bifuncindex")
883 function_entries = find_all_elements(container, "function")
884 for entry in entries:
885 function_name = entry.getAttribute("name")
886 found = 0
887 for func_entry in function_entries:
888 t2 = func_entry.childNodes[0].data
889 if t2[-2:] != "()":
890 continue
891 t2 = t2[:-2]
892 if t2 == function_name:
893
894 func_entry.setAttribute("index", "index")
895 func_entry.setAttribute("module", "__builtin__")
896 if not found:
897 removes.append(entry)
898 found = 1
899 for entry in removes:
900 container.removeChild(entry)
901
902
Fred Drake4db5b461998-12-01 19:03:01 +0000903_token_rx = re.compile(r"[a-zA-Z][a-zA-Z0-9.-]*$")
Fred Drakefcc59101999-01-06 22:50:52 +0000904
Fred Drake4db5b461998-12-01 19:03:01 +0000905def write_esis(doc, ofp, knownempty):
906 for node in doc.childNodes:
907 nodeType = node.nodeType
Fred Drakee779d4f1999-05-10 19:36:52 +0000908 if nodeType == ELEMENT:
Fred Drake4db5b461998-12-01 19:03:01 +0000909 gi = node.tagName
910 if knownempty(gi):
911 if node.hasChildNodes():
Fred Drake865e9ff1999-07-29 22:23:19 +0000912 raise ValueError, \
913 "declared-empty node <%s> has children" % gi
Fred Drake4db5b461998-12-01 19:03:01 +0000914 ofp.write("e\n")
915 for k, v in node.attributes.items():
916 value = v.value
917 if _token_rx.match(value):
918 dtype = "TOKEN"
919 else:
920 dtype = "CDATA"
921 ofp.write("A%s %s %s\n" % (k, dtype, esistools.encode(value)))
922 ofp.write("(%s\n" % gi)
923 write_esis(node, ofp, knownempty)
924 ofp.write(")%s\n" % gi)
Fred Drakee779d4f1999-05-10 19:36:52 +0000925 elif nodeType == TEXT:
Fred Drake4db5b461998-12-01 19:03:01 +0000926 ofp.write("-%s\n" % esistools.encode(node.data))
927 else:
928 raise RuntimeError, "unsupported node type: %s" % nodeType
929
930
Fred Drake03204731998-11-23 17:02:03 +0000931def convert(ifp, ofp):
Fred Drake4db5b461998-12-01 19:03:01 +0000932 p = esistools.ExtendedEsisBuilder()
Fred Drake03204731998-11-23 17:02:03 +0000933 p.feed(ifp.read())
934 doc = p.document
Fred Drakee779d4f1999-05-10 19:36:52 +0000935 fragment = p.fragment
936 normalize(fragment)
937 simplify(doc, fragment)
Fred Drake865e9ff1999-07-29 22:23:19 +0000938 handle_labels(doc, fragment)
Fred Drakee779d4f1999-05-10 19:36:52 +0000939 handle_appendix(doc, fragment)
Fred Drake1ff6db41998-11-23 23:10:35 +0000940 fixup_trailing_whitespace(doc, {
941 "abstract": "\n",
942 "title": "",
943 "chapter": "\n\n",
944 "section": "\n\n",
945 "subsection": "\n\n",
946 "subsubsection": "\n\n",
947 "paragraph": "\n\n",
948 "subparagraph": "\n\n",
949 })
Fred Drake03204731998-11-23 17:02:03 +0000950 cleanup_root_text(doc)
Fred Drake1ff6db41998-11-23 23:10:35 +0000951 cleanup_trailing_parens(doc, ["function", "method", "cfunction"])
Fred Drakefba0ba21998-12-10 05:07:09 +0000952 cleanup_synopses(doc)
Fred Drakee779d4f1999-05-10 19:36:52 +0000953 fixup_descriptors(doc, fragment)
954 fixup_verbatims(fragment)
955 normalize(fragment)
956 fixup_paras(doc, fragment)
957 fixup_sectionauthors(doc, fragment)
958 remap_element_names(fragment, {
Fred Drakef8ebb551999-01-14 19:45:38 +0000959 "tableii": ("table", {"cols": "2"}),
960 "tableiii": ("table", {"cols": "3"}),
961 "tableiv": ("table", {"cols": "4"}),
962 "lineii": ("row", {}),
963 "lineiii": ("row", {}),
964 "lineiv": ("row", {}),
Fred Draked6ced7d1999-01-19 17:11:23 +0000965 "refmodule": ("module", {"link": "link"}),
Fred Drakef8ebb551999-01-14 19:45:38 +0000966 })
Fred Drakee779d4f1999-05-10 19:36:52 +0000967 fixup_table_structures(doc, fragment)
968 fixup_rfc_references(doc, fragment)
969 fixup_signatures(doc, fragment)
Fred Drake865e9ff1999-07-29 22:23:19 +0000970 add_node_ids(fragment)
971 fixup_refmodindexes(fragment)
972 fixup_bifuncindexes(fragment)
Fred Drake4db5b461998-12-01 19:03:01 +0000973 #
974 d = {}
975 for gi in p.get_empties():
976 d[gi] = gi
Fred Draked24167b1999-01-14 21:18:03 +0000977 if d.has_key("rfc"):
978 del d["rfc"]
Fred Drake4db5b461998-12-01 19:03:01 +0000979 knownempty = d.has_key
980 #
Fred Drake03204731998-11-23 17:02:03 +0000981 try:
Fred Drakee779d4f1999-05-10 19:36:52 +0000982 write_esis(fragment, ofp, knownempty)
Fred Drake03204731998-11-23 17:02:03 +0000983 except IOError, (err, msg):
984 # Ignore EPIPE; it just means that whoever we're writing to stopped
985 # reading. The rest of the output would be ignored. All other errors
986 # should still be reported,
987 if err != errno.EPIPE:
988 raise
989
990
991def main():
992 if len(sys.argv) == 1:
993 ifp = sys.stdin
994 ofp = sys.stdout
995 elif len(sys.argv) == 2:
996 ifp = open(sys.argv[1])
997 ofp = sys.stdout
998 elif len(sys.argv) == 3:
999 ifp = open(sys.argv[1])
1000 ofp = open(sys.argv[2], "w")
1001 else:
1002 usage()
1003 sys.exit(2)
1004 convert(ifp, ofp)
1005
1006
1007if __name__ == "__main__":
1008 main()