initial source import
diff --git a/doc/tools/mkmodindex b/doc/tools/mkmodindex
new file mode 100755
index 0000000..5f2da0e
--- /dev/null
+++ b/doc/tools/mkmodindex
@@ -0,0 +1,136 @@
+#! /usr/bin/env python
+#  -*- Python -*-
+
+"""usage: %(program)s [options] file...
+
+Supported options:
+
+    --address addr
+    -a addr         Set the address text to include at the end of the generated
+                    HTML; this should be used for contact information.
+    --columns cols
+    -c cols         Set the number of columns each index section should be
+                    displayed in.  The default is 1.
+    --help
+    -h              Display this help message.
+    --letters
+    -l              Split the output into sections by letter.
+    --output file
+    -o file         Write output to 'file' instead of standard out.
+    --iconserver is Use 'is' as the directory containing icons for the
+                    navigation bar.  The default is 'icons'.
+    --title str     Set the page title to 'str'.  The default is 'Global
+                    Module Index'.
+    --uplink url    Set the upward link URL.  The default is './'.
+    --uptitle str   Set the upward link title.  The default is 'Python
+                    Documentation Index'.
+"""
+import buildindex
+import os
+import re
+import string
+import support
+import sys
+
+
+class IndexOptions(support.Options):
+    def __init__(self):
+        support.Options.__init__(self)
+        self.add_args("l", ["letters"])
+        self.letters = 0
+
+    def handle_option(self, opt, val):
+        if opt in ("-l", "--letters"):
+            self.letters = 1
+
+    def usage(self):
+        program = os.path.basename(sys.argv[0])
+        print __doc__ % {"program": program}
+
+
+class Node(buildindex.Node):
+    annotation = ""
+
+    def __init__(self, link, str, seqno):
+        parts = string.split(str, None, 1)
+        if parts[0][-5:] == "</tt>":
+            self.modname = parts[0][:-5]
+        else:
+            self.modname = parts[0]
+        if len(parts) == 2:
+            self.annotation = parts[1]
+        buildindex.Node.__init__(self, link, self.modname, seqno)
+
+    def __str__(self):
+        return '<tt class="module">%s</tt> %s' \
+               % (self.modname, self.annotation)
+
+_rx = re.compile(
+    "<dt><a href='(module-.*\.html)#l2h-\d+'><tt class='module'>"
+    "([a-zA-Z_][a-zA-Z0-9_.]*</tt>(\s*<em>"
+    "\(<span class='platform'>.*</span>\)</em>)?)</a>")
+
+def main():
+    options = IndexOptions()
+    options.variables["title"] = "Global Module Index"
+    options.parse(sys.argv[1:])
+    args = options.args
+    if not args:
+        args = ["-"]
+    #
+    # Collect the input data:
+    #
+    nodes = []
+    seqno = 0
+    has_plat_flag = 0
+    for ifn in args:
+        if ifn == "-":
+            ifp = sys.stdin
+            dirname = ''
+        else:
+            ifp = open(ifn)
+            dirname = os.path.dirname(ifn)
+        while 1:
+            line = ifp.readline()
+            if not line:
+                break
+            m = _rx.match(line)
+            if m:
+                # This line specifies a module!
+                basename, modname = m.group(1, 2)
+                has_plat_flag = has_plat_flag or m.group(3)
+                linkfile = os.path.join(dirname, basename)
+                nodes.append(Node('<a href="%s">' % linkfile, modname, seqno))
+                seqno = seqno + 1
+        ifp.close()
+    #
+    # Generate all output:
+    #
+    num_nodes = len(nodes)
+    # Here's the HTML generation:
+    parts = [options.get_header(),
+             buildindex.process_nodes(nodes, options.columns, options.letters),
+             options.get_footer(),
+             ]
+    if has_plat_flag:
+        parts.insert(1, PLAT_DISCUSS)
+    html = string.join(parts, '')
+    program = os.path.basename(sys.argv[0])
+    fp = options.get_output_file()
+    fp.write(string.rstrip(html) + "\n")
+    if options.outputfile == "-":
+        sys.stderr.write("%s: %d index nodes\n" % (program, num_nodes))
+    else:
+        print
+        print "%s: %d index nodes" % (program, num_nodes)
+
+
+PLAT_DISCUSS = """
+<p> Some module names are followed by an annotation indicating what
+platform they are available on.</p>
+
+"""
+
+
+if __name__ == "__main__":
+    main()