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 \
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
@ $(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
- 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)
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
--- /dev/null
+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("&", "&").replace("<", "<").replace(">", ">")
+
+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)
+
+
--- /dev/null
+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("&","&")
+ .replace("<","<")
+ .replace(">",">"))
+ 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
--- /dev/null
+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)
--- /dev/null
+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
--- /dev/null
+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>'+
+ ' <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 <"+self.o.onlymainheader+">"
+ 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>"))
+
--- /dev/null
+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("->","->")
+ .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
--- /dev/null
+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>")
--- /dev/null
+#! /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()("&&") >> "\&\;\&\;",
+ m()("\$\<") >> "\$\<\;",
+ m()("&(\w+[\),])") >> "\&\;\\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:])
--- /dev/null
+#! /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
--- /dev/null
+#! /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
+ """
--- /dev/null
+
+def _src_to_xml(text):
+ return text.replace("&", "&").replace("<", "<").replace(">", ">")
+
+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
+
+
--- /dev/null
+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)