]> granicus.if.org Git - zziplib/commitdiff
makedocs.py initial
authorGuido Draheim <guidod@gmx.de>
Mon, 18 Sep 2006 01:53:25 +0000 (01:53 +0000)
committerGuido Draheim <guidod@gmx.de>
Mon, 18 Sep 2006 01:53:25 +0000 (01:53 +0000)
 (Makefile.am makedocs.py zzipdoc/)

14 files changed:
docs/Makefile.am
docs/makedocs.py [new file with mode: 0644]
docs/zzipdoc/__init__.py [new file with mode: 0644]
docs/zzipdoc/commentmarkup.py [new file with mode: 0644]
docs/zzipdoc/dbk2htm.py [new file with mode: 0644]
docs/zzipdoc/functionheader.py [new file with mode: 0644]
docs/zzipdoc/functionlisthtmlpage.py [new file with mode: 0644]
docs/zzipdoc/functionlistreference.py [new file with mode: 0644]
docs/zzipdoc/functionprototype.py [new file with mode: 0644]
docs/zzipdoc/htm2dbk.py [new file with mode: 0644]
docs/zzipdoc/match.py [new file with mode: 0644]
docs/zzipdoc/options.py [new file with mode: 0644]
docs/zzipdoc/textfile.py [new file with mode: 0644]
docs/zzipdoc/textfileheader.py [new file with mode: 0644]

index 559758b81d285bdd2fb692a55283f589d6e9962b..1962c95f83b41683ea508295dc98fc7963c57079 100644 (file)
@@ -1,6 +1,9 @@
 AUTOMAKE_OPTIONS = 1.4 foreign
 AUTOTOOL_VERSION=autoconf-2.52 automake-1.5 libtool-1.4.2
 
+PYRUN = $(PYDEFS) @PYTHON@ $(PYFLAGS)
+PLRUN = $(PLDEFS) @PERL@   $(PLFLAGS)
+
 doc_FILES = README.MSVC6 README.SDL COPYING.MPL COPYING.LIB COPYING.ZLIB \
             zziplib.html
 htm_FILES = zzip-index.htm zzip-zip.htm zzip-file.htm zzip-sdl-rwops.htm \
@@ -16,10 +19,18 @@ changelog = @top_srcdir@/ChangeLog
 
 EXTRA_DIST = make-doc.py $(doc_FILES) $(htm_FILES) $(SDL_RWOPS) \
              make-doc.pl make-dbk.pl   mksite.sh mksite.pl body.htm \
-             manpages.ar zziplib-master.dbk
+             manpages.ar zziplib-master.dbk $(zzipdoc_FILES)
 CLEANFILES = *.pc *.omf
 DISTCLEANFILES = zziplib.spec manpages.ar htmpages.ar *.html *.xml
 
+zzipdoc_FILES = makedocs.py               zzipdoc/__init__.py \
+       zzipdoc/commentmarkup.py          zzipdoc/match.py    \
+       zzipdoc/dbk2htm.py                zzipdoc/htm2dbk.py  \
+       zzipdoc/functionheader.py         zzipdoc/options.py  \
+       zzipdoc/functionlisthtmlpage.py   zzipdoc/textfileheader.py \
+       zzipdoc/functionlistreference.py  zzipdoc/textfile.py
+       zzipdoc/functionprototype.py
+
 html_FILES = $(htm_FILES:.htm=.html) \
              $(htm_FILES:.htm=.print.html) \
              site.html site.print.html
@@ -34,29 +45,70 @@ zziplib.spec : @top_srcdir@/$(PACKAGE).spec
        @ $(LN_S) $? $@ # the two zzip-doc.* will grep thru zziplib.spec
 doc  : $(doc_FILES) site.html
 docs : doc manpages.ar htmpages.ar
-docu : docs
-zziplib0.html : zziplib0.xml
-zziplib0.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.pl \
-                 $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c
-       - @PERL@ $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c \
-          "suffix=0" "package=$(PACKAGE)" "version=$(VERSION)" \
-          "mainheader=zzip/zzip.h" "exported=<zzip/zzip.h> // or <zziplib.h>" \
-         "docbookfile=$@" 
-       - test -s $@
-zziplib1.html : zziplib1.xml
-zziplib1.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.py \
-                   $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c
-       - @PYTHON@ $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c suffix=1
-       - test -f zziplib1.docbook && mv zziplib1.docbook $@ ; test -s $@
+# docu : docs
+docu : 
+       - rm zziplib2.html zzipmmapped.html zzipfseeko.html
+       $(MAKE) zziplib2.html
+       $(MAKE) zzipmmapped.html
+       $(MAKE) zzipfseeko.html
+       $(MAKE) zziplib-man3.tar.gz
+
 zziplib.html :    zziplib1.html zziplib0.html
        - test -s zziplib0.html && cp zziplib0.html zziplib.html
        - test -s zziplib1.html && cp zziplib1.html zziplib.html
+       - test -s zziplib2.html && cp zziplib2.html zziplib.html
        test -s $@
 zziplib.xml :     zziplib1.xml zziplib0.xml
        - test -s zziplib0.xml && cp zziplib0.xml zziplib.xml
        - test -s zziplib1.xml && cp zziplib1.xml zziplib.xml
+       - test -s zziplib2.xml && cp zziplib2.xml zziplib.xml
        test -s $@ || rm $@
 
+_zziplib0 = $(zziplib0) \
+          "suffix=0" "package=$(PACKAGE)" "version=$(VERSION)" \
+          "mainheader=zzip/zzip.h" "exported=<zzip/zzip.h> // or <zziplib.h>" \
+         "docbookfile=$@" 
+zziplib0.html : zziplib0.xml
+zziplib0.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.pl \
+                 $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c
+       - $(PLRUN) $(srcdir)/make-doc.pl @top_srcdir@/zzip/*.c $(_zziplib0)
+       - test -s $@
+_zziplib1 = $(zziplib1) \
+          "--suffix=1"
+zziplib1.html : zziplib1.xml
+zziplib1.xml : zziplib.spec @srcdir@/Makefile.am @srcdir@/make-doc.py \
+                   $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c
+       - $(PYRUN) $(srcdir)/make-doc.py @top_srcdir@/zzip/*.c $(_zziplib1)
+       - test -f zziplib1.docbook && mv zziplib1.docbook $@ ; test -s $@
+_zziplib2 = $(zziplib2) "--package=$(PACKAGE)" "--version=$(VERSION)" \
+               "--onlymainheader=zzip/lib.h" "--suffix=2"
+zziplib2.html : zziplib2.xml
+zziplib2.xml : zziplib.spec $(srcdir)/Makefile.am $(srcdir)/zzipdoc/*.py \
+                   $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c
+       - $(PYRUN) $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c $(_zziplib2)
+       - test -f zziplib2.docbook && mv zziplib2.docbook $@ ; test -s $@
+_zzipmmapped = $(zziplib2) "--package=$(PACKAGE)" "--version=$(VERSION)" \
+               "--onlymainheader=zzip/mmapped.h" "--suffix=3"
+zzipmmapped.html : zzipmmapped.xml
+zzipmmapped.xml : zziplib.spec $(srcdir)/Makefile.am $(srcdir)/zzipdoc/*.py \
+                   $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c
+       - $(PYRUN) $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c $(_zzipmmapped)
+       - test -f zziplib3.docbook && mv zziplib3.docbook $@ ; test -s $@
+_zzipfseeko = $(zziplib2) "--package=$(PACKAGE)" "--version=$(VERSION)" \
+               "--onlymainheader=zzip/fseeko.h" "--suffix=4"
+zzipfseeko.html : zzipfseeko.xml
+zzipfseeko.xml : zziplib.spec $(srcdir)/Makefile.am $(srcdir)/zzipdoc/*.py \
+                   $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c
+       - $(PYRUN) $(srcdir)/makedocs.py @top_srcdir@/zzip/*.c $(_zzipfseeko)
+       - test -f zziplib4.docbook && mv zziplib4.docbook $@ ; test -s $@
+
+zziplib-man3.tar.gz : zziplib2.xml
+       - mkdir zziplib-man3 || rm zziplib-man3/* 
+       (cd zziplib-man3 && xmlto man ../zziplib2.xml) 
+       (cd zziplib-man3 && xmlto man ../zzipmmapped.xml) 
+       (cd zziplib-man3 && xmlto man ../zzipfseeko.xml) 
+       tar czf $@ zziplib-man3/
+
 omfdir=${datadir}/omf
 pkgomfdir=${omfdir}/${PACKAGE}
 SFNETDIR=/groups/z/zz/zziplib/htdocs
@@ -192,13 +244,6 @@ install-omf : $(PACKAGE)-doc.omf $(PACKAGE)-man.omf $(PACKAGE).xml
        - test ".$(DESTDIR)" != "." || scrollkeeper-update -v
 
 # -------------------------------------------------------------------
-datehead = <hr><table border="0" width="100%"><tr><td> \
-    <a href="mailto:guidod@gmx.de?subject=$(PACKAGE):">guidod@gmx.de</a> \
-    </td><td align="right">
-datetail = </td></tr></table>
-borderhead = <table cellpadding="10"><tr><td>
-bordertail = </td></tr></table>
-
 site.htm : body.htm
        cp $(srcdir)/body.htm site.htm
 mksite_sh_args = --VERSION=$(VERSION) --xml --src-dir=$(srcdir)
@@ -206,34 +251,10 @@ site.html : site.htm mksite.sh $(htm_FILES)
        perl $(srcdir)/mksite.pl $(mksite_sh_args) site.htm || \
        $(SHELL) $(srcdir)/mksite.sh $(mksite_sh_args) site.htm
 
-x : $(htm_FILES:.htm=.htmls)
-$(htm_FILES:.htm=.htmls) : body.htm
-%.htmls : %.htm
-       @ title=`grep '<h2>' $< | sed -e 's:</h2>.*::' -e 's:<[^<>]*>::g'` \
-       ; D=$(DATESPEC) ; cat $(srcdir)/body.htm \
-       | sed -e "s/<!--VERSION-->/$(VERSION)/" \
-       | sed -e "s/<!--DATE-->/$$D/" \
-       | sed -e "s:</title>: - $$title</title>:" \
-       | sed -e "/$@.>/s:\\([^<>]*\\)</a>:<b>\\1</b></a>:" \
-       > $@
-       @ echo $< '>>' $@; cat $< | sed -e "s/<!--VERSION-->/$(VERSION)/" \
-       -e "s:</h2>\\(.*\\):</h2></td><td><i>\\1</i></td></tr></table>:" \
-       -e 's:<h2>:<table width="100%"><tr valign="bottom"><td><h2>:' \
-       -e 's:<td><i>:<td align="right"><br> <i>:' \
-       -e 's:<P>:<p class="justify"><span class="justify">:g' \
-       -e 's:</P>:</span></p>:g' \
-       -e 's,<date>,<!--DATE: ,' -e 's,</date>, -->,' \
-       -e 's,<!--border-->,$(borderhead)<!--BORDER-->,' >>$@
-       @ if grep '<!--BORDER-->' $@ >/dev/null ; then : \
-       ; echo "$(bordertail)<!--/BORDER-->" >>$@ ; fi
-       @ D=`grep '<!--DATE:' $@ | sed -e 's,.*<!--DATE: *,,' -e 's, *-->,,'` \
-       ; if test ".$$D" != "." ; then echo '$(datehead)' >>$@ \
-       ; echo "$$D" >> $@ ; echo "$(datetail)" >> $@ ; fi
-       @ echo "</td></tr></table></body></html>" >>$@
-
 # ----------------------------------------------- create pdf via docbook xml
 zzip.xml : $(htm_FILES) zziplib.xml make-dbk.pl
-       @PERL@ make-dbk.pl $(htm_FILES) zziplib.xml >$@
+       : '@PERL@ make-dbk.pl $(htm_FILES) zziplib.xml >$@'
+       @PYTHON@ $(srcdir)/zzipdoc/htm2dbk.py $(htm_FILES) zziplib.xml >$@
        test -s "$@" || rm "$@"
 
 zzip.html : zzip.xml
diff --git a/docs/makedocs.py b/docs/makedocs.py
new file mode 100644 (file)
index 0000000..c7b879c
--- /dev/null
@@ -0,0 +1,292 @@
+import sys
+from zzipdoc.match import *
+from zzipdoc.options import *
+from zzipdoc.textfile import *
+from zzipdoc.textfileheader import *
+from zzipdoc.functionheader import *
+from zzipdoc.functionprototype import *
+from zzipdoc.commentmarkup import *
+from zzipdoc.functionlisthtmlpage import *
+from zzipdoc.functionlistreference import *
+from zzipdoc.dbk2htm import *
+
+def _src_to_xml(text):
+    return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
+
+class PerFileEntry:
+    def __init__(self, header, comment):
+        self.textfileheader = header
+        self.filecomment = comment
+class PerFile:
+    def __init__(self):
+        self.textfileheaders = []
+        self.filecomments = []
+        self.entries = []
+    def add(self, textfileheader, filecomment):
+        self.textfileheaders += [ textfileheader ]
+        self.filecomments += [ filecomment ]
+        self.entries += [ PerFileEntry(textfileheader, filecomment) ]
+    def print_list_mainheader(self):
+        for t_fileheader in self.headers:
+            print t_fileheader.get_filename(), t_fileheader.src_mainheader()
+        
+class PerFunctionEntry:
+    def __init__(self, header, comment, prototype):
+        self.header = header
+        self.comment = comment
+        self.prototype = prototype
+    def get_name(self):
+        return self.prototype.get_name()
+    def get_titleline(self):
+        return self.header.get_titleline()
+    def get_head(self):
+        return self.prototype
+    def get_body(self):
+        return self.comment
+class PerFunction:
+    def __init__(self):
+        self.headers = []
+        self.comments = []
+        self.prototypes = []
+        self.entries = []
+    def add(self, functionheader, functioncomment, functionprototype):
+        self.headers += [ functionheader ]
+        self.comments += [ functionprototype ]
+        self.prototypes += [ functionprototype ]
+        self.entries += [ PerFunctionEntry(functionheader, functioncomment,
+                                           functionprototype) ]
+    def print_list_titleline(self):
+        for funcheader in self.headers:
+            print funcheader.get_filename(), "[=>]", funcheader.get_titleline()
+    def print_list_name(self):
+        for funcheader in self.prototypes:
+            print funcheader.get_filename(), "[>>]", funcheader.get_name()
+
+class PerFunctionFamilyEntry:
+    def __init__(self, leader):
+        self.leader = leader
+        self.functions = []
+    def contains(self, func):
+        for item in self.functions:
+            if item == func: return True
+        return False
+    def add(self, func):
+        if not self.contains(func):
+            self.functions += [ func ]
+    def get_name(self):
+        if self.leader is None: return None
+        return self.leader.get_name()
+class PerFunctionFamily:
+    def __init__(self):
+        self.functions = []
+        self.families = []
+        self.retarget = {}
+        self.entries = []
+    def add_PerFunction(self, per_list):
+        for item in per_list.entries:
+            add_PerFunctionEntry(item)
+    def add_PerFunctionEntry(self, item):
+        self.functions += [ item ]
+    def get_function(self, name):
+        for item in self.functions:
+            if item.get_name() == name:
+                return item
+        return None
+    def get_entry(self, name):
+        for item in self.entries:
+            if item.get_name() == name:
+                return item
+        return None
+    def fill_families(self):
+        name_list = {}
+        for func in self.functions:
+            name = func.get_name()
+            name_list[name] = func
+        for func in self.functions:
+            name = func.get_name()
+            line = func.get_titleline()
+            is_retarget = Match("=>\s*(\w+)")
+            if line & is_retarget:
+                into = is_retarget[1]
+                self.retarget[name] = is_retarget[1]
+        lead_list = []
+        for name in self.retarget:
+            into = self.retarget[name]
+            if into not in name_list:
+                print ("function '"+name+"' retarget into '"+into+
+                       "' does not exist - keep alone")
+            if into in self.retarget:
+                other = self.retarget[into]
+                print ("function '"+name+"' retarget into '"+into+
+                       "' which is itself a retarget into '"+other+"'")
+            if into not in lead_list:
+                lead_list += [ into ]
+        for func in self.functions:
+            name = func.get_name()
+            if name not in lead_list and name not in self.retarget:
+                lead_list += [ name ]
+        for name in lead_list:
+            func = self.get_function(name)
+            if func is not None:
+                entry = PerFunctionFamilyEntry(func)
+                entry.add(func) # the first
+                self.entries += [ entry ]
+            else:
+                print "head function '"+name+" has no entry"
+        for func in self.functions:
+            name = func.get_name()
+            if name in self.retarget:
+                into = self.retarget[name]
+                entry = self.get_entry(into)
+                if entry is not None:
+                    entry.add(func) # will not add duplicates
+                else:
+                    print "into function '"+name+" has no entry"
+    def print_list_name(self):
+        for family in self.entries:
+            name = family.get_name()
+            print name, ":",
+            for item in family.functions:
+                print item.get_name(), ",",
+            print ""
+class HtmlManualPageAdapter:
+    def __init__(self, entry):
+        """ usually takes a PerFunctionEntry """
+        self.entry = entry
+    def get_name(self):
+        return self.entry.get_name()
+    def _head(self):
+        return self.entry.get_head()
+    def _body(self):
+        return self.entry.get_body()
+    def head_xml_text(self):
+        return self._head().xml_text()
+    def body_xml_text(self, name):
+        return self._body().xml_text(name)
+    def head_get_prespec(self):
+        return self._head().get_prespec()
+    def head_get_namespec(self):
+        return self._head().get_namespec()
+    def head_get_callspec(self):
+        return self._head().get_callspec()
+    def get_title(self):
+        return self._body().header.get_title()
+    def get_filename(self):
+        return self._body().header.get_filename()
+    def src_mainheader(self):
+        return self._body().header.parent.textfile.src_mainheader()
+    def get_mainheader(self):
+        return _src_to_xml(self.src_mainheader())
+class RefEntryManualPageAdapter:
+    def __init__(self, entry):
+        """ usually takes a PerFunctionEntry """
+        self.entry = entry
+    def get_name(self):
+        return self.entry.get_name()
+    def _head(self):
+        return self.entry.get_head()
+    def _body(self):
+        return self.entry.get_body()
+    def head_xml_text(self):
+        return self._head().xml_text()
+    def body_xml_text(self, name):
+        return self._body().xml_text(name)
+    def get_title(self):
+        return self._body().header.get_title()
+    def src_mainheader(self):
+        return self._body().header.parent.textfile.src_mainheader()
+    def get_mainheader(self):
+        return _src_to_xml(self.src_mainheader())
+    def get_includes(self):
+        return ""
+    def list_seealso(self):
+        return self._body().header.get_alsolist()
+    def get_authors(self):
+        return None
+    def get_copyright(self):
+        return None
+
+def makedocs(filenames, o):
+    textfiles = []
+    for filename in filenames:
+        textfile = TextFile(filename)
+        textfile.parse()
+        textfiles += [ textfile ]
+    per_file = PerFile()
+    for textfile in textfiles:
+        textfileheader = TextFileHeader(textfile)
+        textfileheader.parse()
+        filecomment = CommentMarkup(textfileheader)
+        filecomment.parse()
+        per_file.add(textfileheader, filecomment)
+    funcheaders = []
+    for textfile in per_file.textfileheaders:
+        funcheader = FunctionHeaderList(textfile)
+        funcheader.parse()
+        funcheaders += [ funcheader ]
+    per_function = PerFunction()
+    for funcheader in funcheaders:
+        for child in funcheader.get_children():
+            funcprototype = FunctionPrototype(child)
+            funcprototype.parse()
+            funccomment = CommentMarkup(child)
+            funccomment.parse()
+            per_function.add(child, funccomment, funcprototype)
+    per_family = PerFunctionFamily()
+    for item in per_function.entries:
+        per_family.add_PerFunctionEntry(item)
+    per_family.fill_families()
+    # debug output....
+    # per_file.print_list_mainheader()
+    # per_function.print_list_titleline()
+    # per_function.print_list_name()
+    per_family.print_list_name()
+    html = FunctionListHtmlPage(o)
+    for item in per_family.entries:
+        for func in item.functions:
+            func_adapter = HtmlManualPageAdapter(func)
+            if o.onlymainheader and not (Match("<"+o.onlymainheader+">")
+                                         & func_adapter.src_mainheader()):
+                    continue
+            html.add(func_adapter)
+        html.cut()
+    html.cut()
+    html_filename = "zziplib"+o.suffix+".html"
+    try:
+        print "writing "+html_filename
+        fd = open(html_filename, "w")
+        print >>fd, section2html(paramdef2html(html.xml_text()))
+        fd.close()
+    except IOError, e:
+        print "could not open '"+html_filename+"'file", e
+    man3 = FunctionListReference(o)
+    for item in per_family.entries:
+        for func in item.functions:
+            func_adapter = RefEntryManualPageAdapter(func)
+            if o.onlymainheader and not (Match("<"+o.onlymainheader+">")
+                                         & func_adapter.src_mainheader()):
+                    continue
+            man3.add(func_adapter)
+        man3.cut()
+    man3.cut()
+    man3_filename = "zziplib"+o.suffix+".docbook"
+    try:
+        print "writing "+man3_filename
+        fd = open(man3_filename, "w")
+        print >>fd, man3.xml_text()
+        fd.close()
+    except IOError, e:
+        print "could not open '"+man3_filename+"'file", e
+    
+        
+if __name__ == "__main__":
+    filenames = []
+    o = Options()
+    o.package = "ZZipLib"
+    o.program = sys.argv[0]
+    for item in sys.argv[1:]:
+        if o.scan(item): continue
+        filenames += [ item ]
+    makedocs(filenames, o)
+    
+        
diff --git a/docs/zzipdoc/__init__.py b/docs/zzipdoc/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/zzipdoc/commentmarkup.py b/docs/zzipdoc/commentmarkup.py
new file mode 100644 (file)
index 0000000..d9444c2
--- /dev/null
@@ -0,0 +1,86 @@
+from match import Match
+
+def markup_link_syntax(text):
+    """ markup the link-syntax ` => somewhere ` in the text block """
+    return (text
+            & Match(r"(?m)(^|\s)\=\>\"([^\"]*)\"")
+            >> r"\1<link>\2</link>"
+            & Match(r"(?m)(^|\s)\=\>\'([^\']*)\'")
+            >> r"\1<link>\2</link>"
+            & Match(r"(?m)(^|\s)\=\>\s(\w[\w.]*\w\([^\(\)]*\))")
+            >> r"\1<link>\2</link>"
+            & Match(r"(?m)(^|\s)\=\>\s(\w[\w.]*\w)\b")
+            >> r"\1<link>\2</link>"
+            & Match(r"(?m)(^|\s)\=\>\s([^\s\,\.\!\?\:\;\<\>\&\'\=\-]+)")
+            >> r"\1<link>\2</link>")
+
+class CommentMarkup:
+    """ using a structure having a '.comment' item - it does pick it up
+    and enhances its text with new markups so that they can be represented
+    in xml. Use self.xml_text() to get markup text (knows 'this function') """
+    def __init__(self, header = None):
+        self.header = header
+        self.text = None     # xml'text
+    def get_filename(self):
+        if self.header is None:
+            return None
+        return self.header.get_filename()
+    def parse(self, header = None):
+        if header is not None:
+            self.header = header
+        if self.header is None:
+            return False
+        comment = self.header.comment
+        try:
+            comment = self.header.get_otherlines()
+        except Exception, e:
+            pass
+        mode = ""
+        text = ""
+        for line in comment.split("\n"):
+            check = Match()
+            if line & check(r"^\s?\s?\s?[*]\s+[*]\s(.*)"):
+                if mode != "ul":
+                    if mode: text += "</"+mode+">"
+                    mode = "ul" ; text += "<"+mode+">"
+                line = check.group(1)
+                text += "<li> "+self.markup_para_line(line)+" </li>\n"
+            elif line & check(r"^\s?\s?\s?[*](.*)"):
+                if mode != "para":
+                    if mode: text += "</"+mode+">"
+                    mode = "para" ; text += "<"+mode+">"
+                line = check.group(1)
+                if line.strip() == "":
+                    text += "</para><para>"+"\n"
+                else:
+                    text += " "+self.markup_para_line(line)+"\n"
+            else:
+                if mode != "screen":
+                    if mode: text += "</"+mode+">"
+                    mode = "screen" ; text += "<"+mode+">"
+                text += " "+self.markup_screen_line(line)+"\n"
+        if mode: text += "</"+mode+">"+"\n"
+        self.text = (text
+                     & Match(r"(<para>)(\s*[R]eturns)") >>r"\1This function\2"
+                     & Match(r"(?s)<para>\s*</para><para>") >> "<para>"
+                     & Match(r"(?s)<screen>\s*</screen>") >> "")
+    def markup_screen_line(self, line):
+        return self.markup_line(line.replace("&","&amp;")
+                                .replace("<","&lt;")
+                                .replace(">","&gt;"))
+    def markup_para_line(self, line):
+        return markup_link_syntax(self.markup_line(line))
+    def markup_line(self, line):
+        return (line
+                .replace("<c>","<code>")
+                .replace("</c>","</code>"))
+    def xml_text(self, functionname = None):
+        if self.text is None:
+            if not self.parse(): return None
+        text = self.text
+        if functionname is not None:
+            def function(text): return "<function>"+text+"</function> function"
+            text = (text
+                    .replace("this function", "the "+function(functionname))
+                    .replace("This function", "The "+function(functionname)))
+        return text
diff --git a/docs/zzipdoc/dbk2htm.py b/docs/zzipdoc/dbk2htm.py
new file mode 100644 (file)
index 0000000..f8593e6
--- /dev/null
@@ -0,0 +1,26 @@
+from match import Match
+import string
+
+class dbk2htm_conversion:
+    mapping = { "<screen>" : "<pre>", "</screen>" : "</pre>",
+                "<para>" : "<p>", "</para>" : "</p>" ,
+                "<function>" : "<link>", "</function>" : "</link>" }
+    def __init__(self):
+        pass
+    def section2html(self, text):
+        for str in self.mapping:
+            text = string.replace(text, str, self.mapping[str])
+        return text
+    def paramdef2html(self, text):
+        s = Match()
+        txt = text & s(r"\s+<paramdef>") >> r"\n<nobr>"
+        txt &= s(r"<paramdef>") >> r"<nobr>"
+        txt &= s(r"</paramdef>") >> r"</nobr>"
+        txt &= s(r"<parameters>") >> r"\n <code>"
+        txt &= s(r"</parameters>") >> r"</code>\n"
+        return txt
+
+def section2html(text):
+    return dbk2htm_conversion().section2html(text)
+def paramdef2html(text):
+    return dbk2htm_conversion().paramdef2html(text)
diff --git a/docs/zzipdoc/functionheader.py b/docs/zzipdoc/functionheader.py
new file mode 100644 (file)
index 0000000..8e6bf2f
--- /dev/null
@@ -0,0 +1,97 @@
+from match import Match
+
+class FunctionHeader:
+    """ parsing the comment block that is usually presented before
+    a function prototype - the prototype part is passed along
+    for further parsing through => FunctionPrototype """
+    def __init__(self, functionheaderlist, comment, prototype):
+        self.parent = functionheaderlist
+        self.comment = comment
+        self.prototype = prototype
+        self.firstline = None
+        self.otherlines = None
+        self.titleline = None
+        self.alsolist = []
+    def get_filename(self):
+        return self.parent.get_filename()
+    def parse_firstline(self):
+        if not self.comment: return False
+        x = self.comment.find("\n")
+        if x > 0:
+            self.firstline = self.comment[:x]
+            self.otherlines = self.comment[x:]
+        elif x == 0:
+            self.firstline = "..."
+            self.otherlines = self.comment[1:x]
+        else:
+            self.firstline = self.comment
+            self.otherlines = ""
+        return True
+    def get_firstline(self):
+        if self.firstline is None:
+            if not self.parse_firstline(): return ""
+        return self.firstline
+    def get_otherlines(self):
+        if self.firstline is None:
+            if not self.parse_firstline(): return ""
+        return self.otherlines
+    def parse_titleline(self):
+        """ split extra-notes from the firstline - keep only titleline """
+        line = self.get_firstline()
+        if line is None: return False
+        self.titleline = line
+        self.alsolist = []
+        x = line.find("also:")
+        if x > 0:
+            self.titleline = line[:x]
+            for also in line[x+5:].split(","):
+                self.alsolist += [ also.strip() ]
+            print "[[[", self.alsolist, "}}}", self.titleline
+        self._alsolist = self.alsolist
+        return True
+    def get_alsolist(self):
+        """ gets the see-also notes from the firstline """
+        if self.titleline is None:
+            if not self.parse_titleline(): return None
+        return self.alsolist
+    def get_titleline(self):
+        """ gets firstline with see-also notes removed """
+        if self.titleline is None:
+            if not self.parse_titleline(): return False
+        return self.titleline
+    def get_title(self):
+        """ gets titleline unless that is a redirect """
+        titleline = self.get_titleline()
+        if titleline & Match(r"^\s*=>"): return ""
+        if titleline & Match(r"^\s*<link>"): return ""
+        return titleline
+    def get_prototype(self):
+        return self.prototype
+    
+class FunctionHeaderList:
+    """ scan for comment blocks in the source file that are followed by
+    something quite like a C definition (probably a function definition).
+    Unpack the occurrences and fill self.comment and self.prototype. """
+    def __init__(self, textfile = None):
+        self.textfile = textfile # TextFile
+        self.children = None     # src'style
+    def parse(self, textfile = None):
+        if textfile is not None:
+            self.textfile = textfile
+        if self.textfile is None:
+            return False
+        text = self.textfile.get_src_text()
+        m = Match(r"(?s)\/\*[*]+(?=\s)"
+                  r"((?:.(?!\*\/))*.)\*\/"
+                  r"([^/\{\}\;\#]+)[\{\;]")
+        self.children = []
+        for found in m.finditer(text):
+            child = FunctionHeader(self, found.group(1), found.group(2))
+            self.children += [ child ]
+        return len(self.children) > 0
+    def get_filename(self):
+        return self.textfile.get_filename()
+    def get_children(self):
+        if self.children is None:
+            if not self.parse(): return []
+        return self.children
diff --git a/docs/zzipdoc/functionlisthtmlpage.py b/docs/zzipdoc/functionlisthtmlpage.py
new file mode 100644 (file)
index 0000000..e4dd4ec
--- /dev/null
@@ -0,0 +1,119 @@
+from options import *
+from match import Match
+
+class FunctionListHtmlPage:
+    """ The main part here is to create a TOC (table of contents) at the
+    start of the page - linking down to the descriptions of the functions.
+    Sure we need to generate anchors on the fly. Additionally, all the
+    non-html (docbook-like) markup needs to be converted for ouput. -
+    each element to be added should implement get_name(), get_head() and
+    get_body() with the latter two having a xml_text() method."""
+    _null_table100 =  '<table border="0" width="100%"' \
+                     ' cellpadding="0" cellspacing="0">'
+    _ul_start = '<table width="100%">'
+    _ul_end = '</table>'
+    _li_start = '<tr><td valign="top">'
+    _li_end = '</td></tr>'
+    http_opengroup = "http://www.opengroup.org/onlinepubs/000095399/functions/"
+    http_zlib = "http://www.zlib.net/manual.html"
+    def __init__(self, o = None):
+        self.toc = ""
+        self.text = ""
+        self.head = ""
+        self.body = ""
+        self.anchors = []
+        self.o = o
+        if self.o is None: self.o = Options()
+    def cut(self):
+        self.text += ("<dt>"+self._ul_start+self.head+self._ul_end+"</dt>"+
+                      "<dd>"+self._ul_start+self.body+self._ul_end+"</dd>")
+        self.head = ""
+        self.body = ""
+    def add(self, entry):
+        name = entry.get_name()
+        head_text = entry.head_xml_text()
+        body_text = entry.body_xml_text(name)
+        assert head_text
+        try:
+            prespec = entry.head_get_prespec()
+            namespec = entry.head_get_namespec()
+            callspec = entry.head_get_callspec()
+            head_text = ("<code><b><function>"+namespec+"</function></b>"
+                         +callspec+" : "+prespec+"</code>")
+        except Exception, e:
+            pass
+        try:
+            extraline = ""
+            title = entry.get_title()
+            filename = entry.get_filename().replace("../","")
+            if title:
+                extraline = (self._null_table100+'<td>'+
+                             '&nbsp;<em>'+title+'</em>'+
+                             ' </td><td align="right"> '+
+                             '<em><small>'+filename+'</small></em>'+
+                             '</td></table>')
+            body_text = extraline + body_text
+        except Exception, e:
+            pass
+        def link(text):
+            return (text & Match("<function>(\w*)</function>")
+                    >> "<link>\\1</link>")
+        def here(text):
+            has_function = Match("<function>(\w*)</function>")
+            if text & has_function:
+                func = has_function[1]
+                self.anchors += [ func ]
+                return (text & has_function
+                        >> '<a name="'+"\\1"+'">'+"\\1"+'</a>')
+            else:
+                return text
+        self.toc += self._li_start+self.sane(link(head_text))+self._li_end
+        self.head += self._li_start+self.sane(here(head_text))+self._li_end
+        self.body += self._li_start+self.sane(body_text)+self._li_end
+    def xml_text(self):
+        self.cut()
+        title=self.o.package+" Library Functions"
+        return ("<html><title>"+title+"</title><body>"
+                "<h2>"+title+"</h2>"+
+                self.version_line()+
+                self.mainheader_line()+
+                self._ul_start+
+                self.resolve_links(self.toc)+
+                self._ul_end+
+                "<h3>Documentation</h3><dl>"+self.resolve_links(self.text)+
+                "</dl></html>")
+    def version_line(self):
+        if self.o.version:
+            return "<p>Version "+self.o.version+"</p>"
+        return ""
+    def mainheader_line(self):
+        if self.o.onlymainheader:
+            include = "#include &lt;"+self.o.onlymainheader+"&gt;"
+            return "<p><big><b><code>"+include+"</code></b></big></p>"
+        return ""
+    def resolve_links(self, text):
+        text &= (Match("(?s)<link>([^<>]*)(\(\d\))</link>")
+                 >> (lambda x: self.resolve_external(x.group(1), x.group(2))))
+        text &= (Match("(?s)<link>(\w+)</link>")
+                 >> (lambda x: self.resolve_internal(x.group(1))))
+        return (text & Match("(?s)<link>([^<>]*)</link>")
+                >> "<code>\\1</code>")
+    def resolve_external(self, func, sect):
+        x = Match()
+        if func & x("^zlib(.*)"):
+            return ('<a href="'+self.http_zlib+x[1]+'">'+
+                    "<code>"+func+sect+"</code>"+'</a>')
+        if sect & x("[23]"):
+            return ('<a href="'+self.http_opengroup+func+'.html">'+
+                     "<code>"+func+sect+"</code>"+'</a>')
+        return "<code>"+func+"<em>"+sect+"</em></sect>"
+    def resolve_internal(self, func):
+        if func in self.anchors:
+            return '<code><a href="#'+func+'">'+func+"</a></code>"
+        print "not in anchors '"+func+"'"
+        return "<code><u>"+func+"</u></code>"
+    def sane(self, text):
+        return (text 
+                .replace("<function>", "<code>")
+                .replace("</function>", "</code>"))
+                
diff --git a/docs/zzipdoc/functionlistreference.py b/docs/zzipdoc/functionlistreference.py
new file mode 100644 (file)
index 0000000..9617f6f
--- /dev/null
@@ -0,0 +1,267 @@
+from match import Match
+from htm2dbk import *
+
+class FunctionListReference:
+    """ Creating a docbook-style <reference> list of <refentry> parts
+    that will each be translated into a unix manual page in a second step """
+    doctype = (
+        '<!DOCTYPE reference PUBLIC "-//OASIS//DTD'+
+        ' DocBook XML V4.1.2//EN"'+"\n"+
+        '       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">'+
+        "\n")
+    def __init__(self, o = None):
+        self.o = o
+        self.pages = []
+        self.entry = None
+    def cut(self):
+        if not self.entry: return
+        self.pages += [ self.entry ]
+        self.entry = None
+    def add(self, entry):
+        if self.entry is None:
+            self.entry = FunctionListRefEntry(entry, self.o)
+            self.entry.funcsynopsisinfo = entry.get_mainheader()
+            self.entry.refpurpose = entry.get_title()
+            self.entry.refentrytitle = entry.get_name()
+            # self.entry.refname = entry.get_name()
+        name = entry.get_name()
+        description = entry.body_xml_text(name)
+        funcsynopsis = entry.head_xml_text()
+        self.entry.funcsynopsis_list += [ funcsynopsis ]
+        self.entry.description_list += [ description ]
+        self.entry.refname_list += [ name ]
+        if entry.list_seealso():
+            for item in entry.list_seealso():
+                if item not in self.entry.seealso_list:
+                    self.entry.seealso_list += [ item ]
+    def xml_text(self):
+        T = self.doctype
+        T += "<reference><title>"+self.o.package+" Function List</title>\n"
+        for item in self.pages:
+            T += self.sane(item.refentry_text())
+        T += "</reference>\n"
+        return T
+    def sane(self, text):
+        return (html2docbook(text).replace("->","-&gt;")
+                .replace("<link>","<function>")
+                .replace("</link>","</function>")
+                .replace("<fu:protospec>","<funcprototype>")
+                .replace("</fu:protospec>","</funcprototype>")
+                .replace("<fu:prespec>","<funcdef>")
+                .replace("</fu:prespec>","")
+                .replace("<fu:namespec>","")
+                .replace("</fu:namespec>","</funcdef>")
+                .replace("</fu:callspec>","</paramdef>")
+                .replace("<fu:callspec>","<paramdef>")) & (
+            Match("<listitem>((?:.(?!(<para|</listitem)))*).</listitem>")
+            >> "<listitem><para>\\1</para></listitem>")
+
+    
+class FunctionListRefEntry:
+    def __init__(self, func, o):
+        """ initialize the fields needed for a man page entry - the fields are
+           named after the docbook-markup that encloses (!!) the text we store
+           the entries like X.refhint = "hello" will be printed therefore as
+           <refhint>hello</refhint>. Names with underscores are only used as
+           temporaries but they are memorized, perhaps for later usage. """
+        self.name = func.get_name()
+        self.refhint = "\n<!--========= "+self.name+" (3) ============-->\n"
+        self.refentry = None
+        self.refentry_date = o.version.strip()        # //refentryinfo/date
+        self.refentry_productname = o.package.strip() # //refentryinfo/prod*
+        self.refentry_title = None                    # //refentryinfo/title
+        self.refentryinfo = None                      # override
+        self.manvolnum = "3"                         # //refmeta/manvolnum
+        self.refentrytitle = None                    # //refmeta/refentrytitle
+        self.refmeta = None                          # override
+        self.refpurpose = None                       # //refnamediv/refpurpose
+        self.refname = None                          # //refnamediv/refname
+        self.refname_list = []
+        self.refnamediv = None                       # override
+        self.mainheader = func.get_mainheader()
+        self.includes = func.get_includes()
+        self.funcsynopsisinfo = ""       # //funcsynopsisdiv/funcsynopsisinfo
+        self.funcsynopsis = None         # //funcsynopsisdiv/funcsynopsis
+        self.funcsynopsis_list = []
+        self.description = None
+        self.description_list = []
+        # optional sections
+        self.authors_list = []           # //sect1[authors]/listitem
+        self.authors = None              # override
+        self.copyright = None
+        self.copyright_list = []
+        self.seealso = None
+        self.seealso_list = []
+        if  func.list_seealso():
+            for item in func.list_seealso():
+                self.seealso_list += [ item ]
+        self.file_authors = None
+        if  func.get_authors():
+            self.file_authors = func.get_authors()
+        self.file_copyright = None
+        if  func.get_copyright():
+            self.file_copyright = func.get_copyright()
+    #fu
+    def refentryinfo_text(self):
+        """ the manvol formatter wants to render a footer line and header line
+            on each manpage and such info is set in <refentryinfo> """
+        if self.refentryinfo:
+            return self.refentryinfo
+        if self.refentry_date and \
+           self.refentry_productname and \
+           self.refentry_title: return (
+            "\n <date>"+self.refentry_date+"</date>"+ 
+            "\n <productname>"+self.refentry_productname+"</productname>"+
+            "\n <title>"+self.refentry_title+"</title>")
+        if self.refentry_date and \
+           self.refentry_productname: return (
+            "\n <date>"+self.refentry_date+"</date>"+ 
+            "\n <productname>"+self.refentry_productname+"</productname>")
+        return ""
+    def refmeta_text(self):
+        """ the manvol formatter needs to know the filename of the manpage to
+            be made up and these parts are set in <refmeta> actually """
+        if self.refmeta:
+            return self.refmeta
+        if self.manvolnum and self.refentrytitle:
+            return (
+                "\n <refentrytitle>"+self.refentrytitle+"</refentrytitle>"+
+                "\n <manvolnum>"+self.manvolnum+"</manvolnum>")
+        if self.manvolnum and self.name:
+            return (
+                "\n <refentrytitle>"+self.name+"</refentrytitle>"+
+                "\n <manvolnum>"+self.manvolnum+"</manvolnum>")
+        return ""
+    def refnamediv_text(self):
+        """ the manvol formatter prints a header line with a <refpurpose> line
+            and <refname>'d functions that are described later. For each of
+            the <refname>s listed here, a mangpage is generated, and for each
+            of the <refname>!=<refentrytitle> then a symlink is created """
+        if self.refnamediv:
+            return self.refnamediv
+        if self.refpurpose and self.refname:
+            return ("\n <refname>"+self.refname+'</refname>'+
+                    "\n <refpurpose>"+self.refpurpose+" </refpurpose>")
+        if self.refpurpose and self.refname_list:
+            T = ""
+            for refname in self.refname_list:
+                T += "\n <refname>"+refname+'</refname>'
+            T += "\n <refpurpose>"+self.refpurpose+" </refpurpose>"
+            return T
+        return ""
+    def funcsynopsisdiv_text(self):
+        """ refsynopsisdiv shall be between the manvol mangemaent information
+            and the reference page description blocks """
+        T=""
+        if self.funcsynopsis:
+            T += "\n<funcsynopsis>"
+            if self.funcsynopsisinfo:
+                T += "\n<funcsynopsisinfo>"+    self.funcsynopsisinfo + \
+                     "\n</funcsynopsisinfo>\n"
+            T += self.funcsynopsis + \
+                 "\n</funcsynopsis>\n"
+        if self.funcsynopsis_list:
+            T += "\n<funcsynopsis>"
+            if self.funcsynopsisinfo:
+                T += "\n<funcsynopsisinfo>"+    self.funcsynopsisinfo + \
+                     "\n</funcsynopsisinfo>\n"
+            for funcsynopsis in self.funcsynopsis_list:
+                T += funcsynopsis
+            T += "\n</funcsynopsis>\n"
+        #fi
+        return T
+    def description_text(self):
+        """ the description section on a manpage is the main part. Here
+            it is generated from the per-function comment area. """
+        if self.description:
+            return self.description
+        if self.description_list:
+            T = ""
+            for description in self.description_list:
+                if not description: continue
+                T += description
+            if T.strip() != "": return T
+        return "<para>(missing description)</para>"
+    def authors_text(self):
+        """ part of the footer sections on a manpage and a description of
+            original authors. We prever an itimizedlist to let the manvol
+            show a nice vertical aligment of authors of this ref item """
+        if self.authors:
+            return self.authors
+        if self.authors_list:
+            T = "<itemizedlist>"
+            previous=""
+            for authors in self.authors_list:
+                if not authors: continue
+                if previous == authors: continue
+                T += "\n <listitem><para>"+authors+"</para></listitem>"
+                previous = authors
+            T += "</itemizedlist>"
+            return T
+        if self.authors:
+            return self.authors
+        return ""
+    def copyright_text(self):
+        """ the copyright section is almost last on a manpage and purely
+            optional. We list the part of the per-file copyright info """
+        if self.copyright:
+            return self.copyright
+        """ we only return the first valid instead of merging them """
+        if self.copyright_list:
+            T = ""
+            for copyright in self.copyright_list:
+                if not copyright: continue
+                return copyright # !!!
+        return ""
+    def seealso_text(self):
+        """ the last section on a manpage is called 'SEE ALSO' usally and
+            contains a comma-separated list of references. Some manpage
+            viewers can parse these and convert them into hyperlinks """
+        if self.seealso:
+            return self.seealso
+        if self.seealso_list:
+            T = ""
+            for seealso in self.seealso_list:
+                if not seealso: continue
+                if T: T += ", "
+                T += seealso
+            if T: return T
+        return ""
+    def refentry_text(self, id=None):
+        """ combine fields into a proper docbook refentry """
+        if id is None:
+            id = self.refentry
+        if id:
+            T = '<refentry id="'+id+'">'
+        else:
+            T = '<refentry>' # this is an error
+           
+        if self.refentryinfo_text():
+            T += "\n<refentryinfo>"+       self.refentryinfo_text()+ \
+                 "\n</refentryinfo>\n"
+        if self.refmeta_text():
+            T += "\n<refmeta>"+            self.refmeta_text() + \
+                 "\n</refmeta>\n" 
+        if self.refnamediv_text():
+            T += "\n<refnamediv>"+         self.refnamediv_text() + \
+                 "\n</refnamediv>\n"
+        if self.funcsynopsisdiv_text():     
+            T += "\n<refsynopsisdiv>\n"+   self.funcsynopsisdiv_text()+ \
+                 "\n</refsynopsisdiv>\n"
+        if self.description_text():
+            T += "\n<refsect1><title>Description</title> " + \
+                 self.description_text() + "\n</refsect1>"
+        if self.authors_text():
+            T += "\n<refsect1><title>Author</title> " + \
+                 self.authors_text() + "\n</refsect1>"
+        if self.copyright_text():
+            T += "\n<refsect1><title>Copyright</title> " + \
+                 self.copyright_text() + "\n</refsect1>\n"
+        if self.seealso_text():
+            T += "\n<refsect1><title>See Also</title><para> " + \
+                 self.seealso_text() + "\n</para></refsect1>\n"
+
+        T +=  "\n</refentry>\n"
+        return T
+    #fu
+#end
diff --git a/docs/zzipdoc/functionprototype.py b/docs/zzipdoc/functionprototype.py
new file mode 100644 (file)
index 0000000..5924ce8
--- /dev/null
@@ -0,0 +1,59 @@
+from match import Match
+
+class FunctionPrototype:
+    """ takes a single function prototype line (cut from some source file)
+    and parses it into the relevant portions 'prespec', 'namespec' and
+    'callspec'. Additionally we present 'name' from the namespec that is
+    usually used as the filename stem for a manual page """
+    def __init__(self, functionheader = None):
+        self.functionheader = functionheader
+        self.prespec = None
+        self.namespec = None
+        self.callspec = None
+        self.name = None
+    def get_functionheader(self):
+        return self.functionheader
+    def get_prototype(self):
+        if self.functionheader is None:
+            return None
+        return self.functionheader.get_prototype()
+    def get_filename(self):
+        if self.functionheader is None:
+            return None
+        return self.functionheader.get_filename()
+    def parse(self, functionheader = None):
+        if functionheader is not None:
+            self.functionheader = functionheader
+        if self.functionheader is None:
+            return False
+        found = Match()
+        prototype = self.get_prototype()
+        if prototype & found(r"(?s)^(.*[^.])"
+                             r"\b(\w[\w.]*\w)\b"
+                             r"(\s*\(.*)$"):
+            self.prespec = found.group(1).lstrip()
+            self.namespec = found.group(2)
+            self.callspec = found.group(3).lstrip()
+            self.name = self.namespec.strip()
+            return True
+        return False
+    def _assert_parsed(self):
+        if self.name is None:
+            return self.parse()
+        return True
+    def get_prespec(self):
+        if not self._assert_parsed(): return None
+        return self.prespec
+    def get_namespec(self):
+        if not self._assert_parsed(): return None
+        return self.namespec
+    def get_callspec(self):
+        if not self._assert_parsed(): return None
+        return self.callspec
+    def get_name(self):
+        if not self._assert_parsed(): return None
+        return self.name
+    def xml_text(self):
+        return ("<fu:protospec><fu:prespec>"+self.prespec+"</fu:prespec>"+
+                "<fu:namespec>"+self.namespec+"</fu:namespec>"+
+                "<fu:callspec>"+self.callspec+"</fu:callspec></fu:protospec>")
diff --git a/docs/zzipdoc/htm2dbk.py b/docs/zzipdoc/htm2dbk.py
new file mode 100644 (file)
index 0000000..b4a4e2e
--- /dev/null
@@ -0,0 +1,158 @@
+#! /usr/bin/env python
+
+"""
+this file converts simple html text into a docbook xml variant. 
+The mapping of markups and links is far from perfect. But all we
+want is the docbook-to-pdf converter and similar technology being
+present in the world of docbook-to-anything converters. """
+
+from datetime import date
+import match
+import sys
+
+m = match.Match
+
+class htm2dbk_conversion_base:
+    regexlist = [
+        m()("</[hH]2>(.*)", "m") >> "</title>\n<subtitle>\\1</subtitle>",
+        m()("<[hH]2>") >> "<sect1 id=\"--filename--\"><title>",
+        m()("<[Pp]([> ])","m") >> "<para\\1",
+        m()("</[Pp]>") >> "</para>",
+        m()("<(pre|PRE)>") >> "<screen>",
+        m()("</(pre|PRE)>") >> "</screen>",
+        m()("<[hH]3>") >> "<sect2><title>",
+        m()("</[hH]3>((?:.(?!<sect2>))*.?)", "s") >> "</title>\\1</sect2>",
+        m()("<!doctype [^<>]*>","s") >> "",
+        m()("<!DOCTYPE [^<>]*>","s") >> "",
+        m()("(<\w+\b[^<>]*\swidth=)(\d+\%)","s") >> "\\1\"\\2\"",
+        m()("(<\w+\b[^<>]*\s\w+=)(\d+)","s") >> "\\1\"\\2\"",
+        m()("&&") >> "\&amp\;\&amp\;",
+        m()("\$\<") >> "\$\&lt\;",
+        m()("&(\w+[\),])") >> "\&amp\;\\1",
+        m()("(</?)span(\s[^<>]*)?>","s") >> "\\1phrase\\2>",
+        m()("(</?)small(\s[^<>]*)?>","s") >> "\\1note\\2>",
+        m()("(</?)(b|em|i)>")>> "\\1emphasis>",
+        m()("(</?)(li)>") >> "\\1listitem>",
+        m()("(</?)(ul)>") >> "\\1itemizedlist>",
+        m()("(</?)(ol)>") >> "\\1orderedlist>",
+        m()("(</?)(dl)>") >> "\\1variablelist>",
+        m()("<dt\b([^<>]*)>","s") >> "<varlistentry\\1><term>",
+        m()("</dt\b([^<>]*)>","s") >> "</term>",
+        m()("<dd\b([^<>]*)>","s") >> "<listitem\\1>",
+        m()("</dd\b([^<>]*)>","s") >> "</listitem></varlistentry>",
+        m()("<table\b([^<>]*)>","s")
+        >> "<informaltable\\1><tgroup cols=\"2\"><tbody>",
+        m()("</table\b([^<>]*)>","s") >> "</tbody></tgroup></informaltable>",
+        m()("(</?)tr(\s[^<>]*)?>","s") >> "\\1row\\2>",
+        m()("(</?)td(\s[^<>]*)?>","s") >> "\\1entry\\2>",
+        m()("<informaltable\b[^<>]*>\s*<tgroup\b[^<>]*>\s*<tbody>"+
+          "\s*<row\b[^<>]*>\s*<entry\b[^<>]*>\s*<informaltable\b","s")
+        >> "<informaltable",
+        m()("</informaltable>\s*</entry>\s*</row>"+
+          "\s*</tbody>\s*</tgroup>\s*</informaltable>", "s")
+        >> "</informaltable>",
+        m()("(<informaltable[^<>]*\swidth=\"100\%\")","s") >> "\\1 pgwide=\"1\"",
+        m()("(<tbody>\s*<row[^<>]*>\s*<entry[^<>]*\s)(width=\"50\%\")","s")
+        >> "<colspec colwidth=\"1*\" /><colspec colwidth=\"1*\" />\n\\1\\2",
+        m()("<nobr>([\'\`]*)<tt>") >> "<cmdsynopsis>\\1",
+        m()("</tt>([\'\`]*)</nobr>") >> "\\1</cmdsynopsis>",
+        m()("<nobr><(?:tt|code)>([\`\"\'])") >> "<cmdsynopsis>\\1",
+        m()("<(?:tt|code)><nobr>([\`\"\'])") >> "<cmdsynopsis>\\1",
+        m()("([\`\"\'])</(?:tt|code)></nobr>") >> "\\1</cmdsynopsis>",
+        m()("([\`\"\'])</nobr></(?:tt|code)>") >> "\\1</cmdsynopsis>",
+        m()("(</?)tt>") >> "\\1constant>",
+        m()("(</?)code>") >> "\\1literal>",
+        m()(">([^<>]+)<br>","s") >> "><highlights>\\1</highlights>",
+        m()("<br>") >> "<br />",
+        #        m()("<date>") >> "<sect1info><date>",
+        #        m()("</date>") >> "</date></sect1info>",
+        m()("<reference>") >> "<reference id=\"reference\">" >> 1,
+        m()("<a\s+href=\"((?:http|ftp|mailto):[^<>]+)\"\s*>((?:.(?!</a>))*.)</a>"
+          ,"s") >> "<ulink url=\"\\1\">\\2</ulink>",
+        m()("<a\s+href=\"zziplib.html\#([\w_]+)\"\s*>((?:.(?!</a>))*.)</a>","s")
+        >> "<link linkend=\"$1\">$2</link>",
+        m()("<a\s+href=\"(zziplib.html)\"\s*>((?:.(?!</a>))*.)</a>","s")
+        >> "<link linkend=\"reference\">$2</link>",
+        m()("<a\s+href=\"([\w-]+[.]html)\"\s*>((?:.(?!</a>))*.)</a>","s")
+        >> "<link linkend=\"\\1\">\\2</link>",
+        m()("<a\s+href=\"([\w-]+[.](?:h|c|am|txt))\"\s*>((?:.(?!</a>))*.)</a>"
+          ,"s") >> "<ulink url=\"file:\\1\">\\2</ulink>",
+        m()("<a\s+href=\"([A-Z0-9]+[.][A-Z0-9]+)\"\s*>((?:.(?!</a>))*.)</a>","s")
+        >> "<ulink url=\"file:\\1\">\\2</ulink>"
+        # m()("(</?)subtitle>") >> "\\1para>"
+        # $_ .= "</sect1>" if /<sect1[> ]/
+        ]
+    regexlist2 = [
+        m()(r"<br\s*/?>") >> "",
+        m()(r"(</?)em>") >> r"\1emphasis>",
+        m()(r"<code>") >> "<userinput>",
+        m()(r"</code>") >> "</userinput>",
+        m()(r"<link>") >> "<function>",
+        m()(r"</link>") >> "</function>",
+        m()(r"(?s)\s*</screen>") >> "</screen>",
+        # m()(r"<ul>") >> "</para><itemizedlist>",
+        # m()(r"</ul>") >> "</itemizedlist><para>",
+        # m()(r"<li>") >> "<listitem><para>",
+        # m()(r"</li>") >> "</para></listitem>\n",
+        m()(r"<ul>") >> "</para><programlisting>\n",
+        m()(r"</ul>") >> "</programlisting><para>",
+        m()(r"<li>") >> "",
+        m()(r"</li>") >> ""
+        ]
+class htm2dbk_conversion(htm2dbk_conversion_base):
+    def __init__(self):
+        self.version = "" # str(date.today)
+        self.filename = "."
+    def convert(self,text): # $text
+        txt = text.replace("<!--VERSION-->", self.version)
+        for conv in self.regexlist:
+            txt &= conv
+        return txt.replace("--filename--", self.filename)
+    def convert2(self,text): # $text
+        txt = text.replace("<!--VERSION-->", self.version)
+        for conv in self.regexlist:
+            txt &= conv
+        return txt
+
+class htm2dbk_document(htm2dbk_conversion):
+    """ create document, add(text) and get the value() """
+    doctype = (
+        '<!DOCTYPE book PUBLIC "-//OASIS//DTD'+
+        ' DocBook XML V4.1.2//EN"'+"\n"+
+        '       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">'+
+        "\n")
+    book_start = '<book><chapter><title>Documentation</title>'+"\n"
+    book_end_chapters = '</chapter>'+"\n"
+    book_end = '</book>'+"\n"
+    def __init__(self):
+        htm2dbk_conversion.__init__(self)
+        self.text = self.doctype + self.book_start
+    def add(self,text):
+        if self.text & m()("<reference"):
+            self.text += self.book_end_chapters ; self.book_end_chapters = ""
+        self.text += self.convert(text).replace(
+            "<br />","") & (
+            m()("<link>([^<>]*)</link>") >> "<function>\\1</function>") & (
+            m()("(?s)(<refentryinfo>\s*)<sect1info>" +
+                "(<date>[^<>]*</date>)</sect1info>") >> "\\1\\2")
+    def value(self):
+        return self.text + self.book_end_chapters + self.book_end
+
+def htm2dbk_files(args):
+    doc = htm2dbk_document()
+    for filename in args:
+        try:
+            f = open(filename, "r")
+            doc.filename = filename
+            doc.add(f.read())
+            f.close()
+        except IOError, e:
+            print >> sys.stderr, "can not open "+filename
+    return doc.value()
+
+def html2docbook(text):
+    """ the C comment may contain html markup - simulate with docbook tags """
+    return htm2dbk_conversion().convert2(text)
+
+if __name__ == "__main__":
+    print htm2dbk_files(sys.argv[1:])
diff --git a/docs/zzipdoc/match.py b/docs/zzipdoc/match.py
new file mode 100644 (file)
index 0000000..a089ec3
--- /dev/null
@@ -0,0 +1,103 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+# @creator (C) 2003 Guido U. Draheim
+# @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
+
+import re
+
+# ---------------------------------------------------------- Regex Match()
+# beware, stupid python interprets backslashes in replace-parts only partially!
+class MatchReplace:
+    """ A MatchReplace is a mix of a Python Pattern and a Replace-Template """
+    def __init__(self, matching, template, count = 0, flags = None):
+        """ setup a substition from regex 'matching' into 'template',
+            the replacement count default of 0 will replace all occurrences.
+            The first argument may be a Match object or it is a string that
+            will be turned into one by using Match(matching, flags). """
+        self.template = template
+        MatchReplace.__call__(self, matching, template, count, flags)
+    def __call__(self, matching, template = None, count = 0, flags = None):
+        """ other than __init__ the template may be left off to be unchanged"""
+        if isinstance(count, basestring): # count/flags swapped over?
+            flags = count; count = 0
+        if isinstance(matching, Match):
+            self.matching = matching
+        else:
+            self.matching = Match()(matching, flags) ## python 2.4.2 bug
+        if template is not None:
+            self.template = template
+        self.count = count
+    def __and__(self, string):
+        """ z = MatchReplace('foo', 'bar') & 'foo'; assert z = 'bar' """
+        text, self.matching.replaced = \
+              self.matching.regex.subn(self.template, string, self.count)
+        return text
+    def __rand__(self, string):
+        """ z = 'foo' & Match('foo') >> 'bar'; assert z = 'bar' """
+        text, self.matching.replaced = \
+              self.matching.regex.subn(self.template, string, self.count)
+        return text
+    def __iand__(self, string):
+        """ x = 'foo' ; x &= Match('foo') >> 'bar'; assert x == 'bar' """
+        string, self.matching.replaced = \
+                self.matching.regex.subn(self.template, string, self.count)
+        return string
+    def __rshift__(self, count):
+        " shorthand to set the replacement count: Match('foo') >> 'bar' >> 1 "
+        self.count = count ; return self
+    def __rlshift__(self, count):
+        self.count = count ; return self
+
+class Match(str):
+    """ A Match is actually a mix of a Python Pattern and MatchObject """
+    def __init__(self, pattern = None, flags = None):
+        """ flags is a string: 'i' for case-insensitive etc.; it is just
+        short for a regex prefix: Match('foo','i') == Match('(?i)foo') """
+        Match.__call__(self, pattern, flags)
+    def __call__(self, pattern, flags = None):
+        assert isinstance(pattern, str) or pattern is None
+        assert isinstance(flags, str) or flags is None
+        str.__init__(self, pattern)
+        self.replaced = 0 # set by subn() inside MatchReplace
+        self.found = None # set by search() to a MatchObject
+        self.pattern = pattern
+        if pattern is not None:
+            if flags:
+                self.regex = re.compile("(?"+flags+")"+self.pattern)
+            else:
+                self.regex = re.compile(self.pattern)
+        return self
+    def __truth__(self):
+        return self.found is not None
+    def __and__(self, string):
+        self.found = self.regex.search(string)
+        return self.__truth__()
+    def __rand__(self, string):
+        self.found = self.regex.search(string)
+        return self.__truth__()
+    def __rshift__(self, template):
+        return MatchReplace(self, template)
+    def __rlshift__(self, template):
+        return MatchReplace(self, template)
+    def __getitem__(self, index):
+        return self.group(index)
+    def group(self, index):
+        assert self.found is not None
+        return self.found.group(index)
+    def finditer(self, string):
+        return self.regex.finditer(string)
+
+if __name__ == "__main__":
+    # matching:
+    if "foo" & Match("oo"):
+        print "oo"
+    x = Match()
+    if "foo" & x("(o+)"):
+        print x[1]
+    # replacing:
+    y = "fooboo" & Match("oo") >> "ee"
+    print y
+    r = Match("oo") >> "ee"
+    print "fooboo" & r
+    s = MatchReplace("oo", "ee")
+    print "fooboo" & s
diff --git a/docs/zzipdoc/options.py b/docs/zzipdoc/options.py
new file mode 100644 (file)
index 0000000..c6758d5
--- /dev/null
@@ -0,0 +1,31 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+# @creator (C) 2003 Guido U. Draheim
+# @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
+
+from match import Match
+
+# use as o.optionname to check for commandline options.
+class Options:
+    var = {}
+    def __getattr__(self, name):
+        if not self.var.has_key(name): return None
+        return self.var[name]
+    def __setattr__(self, name, value):
+        self.var[name] = value
+    def scan(self, optionstring): # option-name or None
+        x = Match()
+        if optionstring & x(r"^--?(\w+)=(.*)"):
+            self.var[x[1]] = x[2] ;  return x[1]
+        if optionstring & x(r"^--?no-(\w+)$"):
+            self.var[x[1]] = "" ; return x[1]
+        if optionstring & x(r"^--?(\w+)$"):
+            self.var[x[1]] = "*"; return x[1]
+        return None
+#end Options
+
+if False:
+    o = Options()
+    o.help = """
+    scans for options
+    """
diff --git a/docs/zzipdoc/textfile.py b/docs/zzipdoc/textfile.py
new file mode 100644 (file)
index 0000000..bfaff8d
--- /dev/null
@@ -0,0 +1,49 @@
+
+def _src_to_xml(text):
+    return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt")
+
+class TextFile:
+    def __init__(self, filename = None):
+        self.filename = filename
+        self.src_text = None
+        self.xml_text = None
+    def parse(self, filename = None):
+        if filename is not None:
+            self.filename = filename
+        if self.filename is None:
+            return False
+        try:
+            fd = open(self.filename, "r")
+            self.src_text = fd.read()
+            fd.close()
+            return True
+        except IOError, e:
+            pass
+        return False
+    def assert_src_text(self):
+        if self.src_text: return True
+        return self.parse()
+    def assert_xml_text(self):
+        if self.xml_text: return True
+        if not self.assert_src_text(): return False
+        self.xml_text = _src_to_xml(self.src_text)
+    def get_src_text(self):
+        self.assert_src_text()
+        return self.src_text
+    def get_xml_text(self):
+        self.assert_xml_text()
+        return self.xml_text
+    def get_filename(self):
+        return self.filename
+    def line_xml_text(self, offset):
+        self._line(self.xml_text, offset)
+    def line_src_text(self, offset):
+        self._line(self.src_text, offset)
+    def _line(self, text, offset):
+        line = 1
+        for x in xrange(0,offset):
+            if x == "\n":
+                line += 1
+        return line
+            
+
diff --git a/docs/zzipdoc/textfileheader.py b/docs/zzipdoc/textfileheader.py
new file mode 100644 (file)
index 0000000..2ac0896
--- /dev/null
@@ -0,0 +1,47 @@
+from match import Match
+
+class TextFileHeader:
+    """ scan for a comment block at the source file start and fill the
+    inner text into self.comment - additionally scan for the first
+    #include statement and put the includename into self.mainheader
+    (TextFileHeader re-exports all => TextFile methods for processing)"""
+    def __init__(self, textfile = None):
+        self.textfile = textfile # TextFile
+        self.comment = ""    # src'style
+        self.mainheader = ""     # src'style
+    def parse(self, textfile = None):
+        if textfile is not None:
+            self.textfile = textfile
+        if self.textfile is None:
+            return False
+        x = Match()
+        text = self.textfile.get_src_text()
+        if not text:
+            print "nonexistant file:", self.textfile.get_filename()
+            return False
+        if text & x(r"(?s)[/][*]+(\s(?:.(?!\*\/))*.)\*\/"
+                    r"(?:\s*\#(?:define|ifdef|endif)[ ]*\S*[ ]*\S*)*"
+                    r"(\s*\#include\s*<[^<>]*>(?:\s*//[^\n]*)?)"):
+            self.comment = x[1]
+            self.mainheader = x[2].strip()
+        elif text & x(r"(?s)[/][*]+(\s(?:.(?!\*\/))*.)\*\/"):
+            self.comment = x[1]
+        elif text & x(r"(?s)(?:\s*\#(?:define|ifdef|endif)[ ]*\S*[ ]*\S*)*"
+                      r"(\s*\#include\s*<[^<>]*>(?:\s*//[^\n]*)?)"):
+            self.mainheader = x[1].strip()
+        return True
+    def src_mainheader(self):
+        return self.mainheader
+    def src_filecomment(self):
+        return self.comment
+    # re-export textfile functions - allows textfileheader to be used instead
+    def get_filename(self):
+        return self.textfile.get_filename()
+    def get_src_text(self):
+        return self.textfile.get_src_text()
+    def get_xml_text(self):
+        return self.textfile.get_src_text()
+    def line_src__text(self, offset):
+        return self.textfile.line_src_text(offset)
+    def line_xml__text(self, offset):
+        return self.textfile.line_xml_text(offset)