From f9a48cfc808590b5e42a55b289e43f0facae401a Mon Sep 17 00:00:00 2001 From: Guido Draheim Date: Mon, 18 Sep 2006 01:53:25 +0000 Subject: [PATCH] makedocs.py initial (Makefile.am makedocs.py zzipdoc/) --- docs/Makefile.am | 117 ++++++----- docs/makedocs.py | 292 ++++++++++++++++++++++++++ docs/zzipdoc/__init__.py | 0 docs/zzipdoc/commentmarkup.py | 86 ++++++++ docs/zzipdoc/dbk2htm.py | 26 +++ docs/zzipdoc/functionheader.py | 97 +++++++++ docs/zzipdoc/functionlisthtmlpage.py | 119 +++++++++++ docs/zzipdoc/functionlistreference.py | 267 +++++++++++++++++++++++ docs/zzipdoc/functionprototype.py | 59 ++++++ docs/zzipdoc/htm2dbk.py | 158 ++++++++++++++ docs/zzipdoc/match.py | 103 +++++++++ docs/zzipdoc/options.py | 31 +++ docs/zzipdoc/textfile.py | 49 +++++ docs/zzipdoc/textfileheader.py | 47 +++++ 14 files changed, 1403 insertions(+), 48 deletions(-) create mode 100644 docs/makedocs.py create mode 100644 docs/zzipdoc/__init__.py create mode 100644 docs/zzipdoc/commentmarkup.py create mode 100644 docs/zzipdoc/dbk2htm.py create mode 100644 docs/zzipdoc/functionheader.py create mode 100644 docs/zzipdoc/functionlisthtmlpage.py create mode 100644 docs/zzipdoc/functionlistreference.py create mode 100644 docs/zzipdoc/functionprototype.py create mode 100644 docs/zzipdoc/htm2dbk.py create mode 100644 docs/zzipdoc/match.py create mode 100644 docs/zzipdoc/options.py create mode 100644 docs/zzipdoc/textfile.py create mode 100644 docs/zzipdoc/textfileheader.py diff --git a/docs/Makefile.am b/docs/Makefile.am index 559758b..1962c95 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -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= // or " \ - "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= // or " \ + "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 =
\ - guidod@gmx.de \ - -datetail =
-borderhead =
-bordertail =
- 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 '

' $< | sed -e 's:

.*::' -e 's:<[^<>]*>::g'` \ - ; D=$(DATESPEC) ; cat $(srcdir)/body.htm \ - | sed -e "s//$(VERSION)/" \ - | sed -e "s//$$D/" \ - | sed -e "s:: - $$title:" \ - | sed -e "/$@.>/s:\\([^<>]*\\):\\1:" \ - > $@ - @ echo $< '>>' $@; cat $< | sed -e "s//$(VERSION)/" \ - -e "s:\\(.*\\):\\1:" \ - -e 's:

:

:' \ - -e 's:

:
:' \ - -e 's:

:

:g' \ - -e 's:

:

:g' \ - -e 's,,,' \ - -e 's,,$(borderhead),' >>$@ - @ if grep '' $@ >/dev/null ; then : \ - ; echo "$(bordertail)" >>$@ ; fi - @ D=`grep ',,'` \ - ; if test ".$$D" != "." ; then echo '$(datehead)' >>$@ \ - ; echo "$$D" >> $@ ; echo "$(datetail)" >> $@ ; fi - @ echo "
" >>$@ - # ----------------------------------------------- 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 index 0000000..c7b879c --- /dev/null +++ b/docs/makedocs.py @@ -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("&", "&").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) + + diff --git a/docs/zzipdoc/__init__.py b/docs/zzipdoc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/zzipdoc/commentmarkup.py b/docs/zzipdoc/commentmarkup.py new file mode 100644 index 0000000..d9444c2 --- /dev/null +++ b/docs/zzipdoc/commentmarkup.py @@ -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\2" + & Match(r"(?m)(^|\s)\=\>\'([^\']*)\'") + >> r"\1\2" + & Match(r"(?m)(^|\s)\=\>\s(\w[\w.]*\w\([^\(\)]*\))") + >> r"\1\2" + & Match(r"(?m)(^|\s)\=\>\s(\w[\w.]*\w)\b") + >> r"\1\2" + & Match(r"(?m)(^|\s)\=\>\s([^\s\,\.\!\?\:\;\<\>\&\'\=\-]+)") + >> r"\1\2") + +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 = "ul" ; text += "<"+mode+">" + line = check.group(1) + text += "
  • "+self.markup_para_line(line)+"
  • \n" + elif line & check(r"^\s?\s?\s?[*](.*)"): + if mode != "para": + if mode: text += "" + mode = "para" ; text += "<"+mode+">" + line = check.group(1) + if line.strip() == "": + text += ""+"\n" + else: + text += " "+self.markup_para_line(line)+"\n" + else: + if mode != "screen": + if mode: text += "" + mode = "screen" ; text += "<"+mode+">" + text += " "+self.markup_screen_line(line)+"\n" + if mode: text += ""+"\n" + self.text = (text + & Match(r"()(\s*[R]eturns)") >>r"\1This function\2" + & Match(r"(?s)\s*") >> "" + & Match(r"(?s)\s*") >> "") + 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("","") + .replace("","")) + 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 ""+text+" 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 index 0000000..f8593e6 --- /dev/null +++ b/docs/zzipdoc/dbk2htm.py @@ -0,0 +1,26 @@ +from match import Match +import string + +class dbk2htm_conversion: + mapping = { "" : "
    ", "" : "
    ", + "" : "

    ", "" : "

    " , + "" : "", "" : "" } + 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+") >> r"\n" + txt &= s(r"") >> r"" + txt &= s(r"") >> r"" + txt &= s(r"") >> r"\n " + txt &= s(r"") >> r"\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 index 0000000..8e6bf2f --- /dev/null +++ b/docs/zzipdoc/functionheader.py @@ -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*"): 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 index 0000000..e4dd4ec --- /dev/null +++ b/docs/zzipdoc/functionlisthtmlpage.py @@ -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 = '' + _ul_start = '
    ' + _ul_end = '
    ' + _li_start = '' + _li_end = '' + 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 += ("
    "+self._ul_start+self.head+self._ul_end+"
    "+ + "
    "+self._ul_start+self.body+self._ul_end+"
    ") + 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 = (""+namespec+"" + +callspec+" : "+prespec+"") + except Exception, e: + pass + try: + extraline = "" + title = entry.get_title() + filename = entry.get_filename().replace("../","") + if title: + extraline = (self._null_table100+''+ + ' '+title+''+ + ' '+ + ''+filename+''+ + '') + body_text = extraline + body_text + except Exception, e: + pass + def link(text): + return (text & Match("(\w*)") + >> "\\1") + def here(text): + has_function = Match("(\w*)") + if text & has_function: + func = has_function[1] + self.anchors += [ func ] + return (text & has_function + >> ''+"\\1"+'') + 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 (""+title+"" + "

    "+title+"

    "+ + self.version_line()+ + self.mainheader_line()+ + self._ul_start+ + self.resolve_links(self.toc)+ + self._ul_end+ + "

    Documentation

    "+self.resolve_links(self.text)+ + "
    ") + def version_line(self): + if self.o.version: + return "

    Version "+self.o.version+"

    " + return "" + def mainheader_line(self): + if self.o.onlymainheader: + include = "#include <"+self.o.onlymainheader+">" + return "

    "+include+"

    " + return "" + def resolve_links(self, text): + text &= (Match("(?s)([^<>]*)(\(\d\))") + >> (lambda x: self.resolve_external(x.group(1), x.group(2)))) + text &= (Match("(?s)(\w+)") + >> (lambda x: self.resolve_internal(x.group(1)))) + return (text & Match("(?s)([^<>]*)") + >> "\\1") + def resolve_external(self, func, sect): + x = Match() + if func & x("^zlib(.*)"): + return (''+ + ""+func+sect+""+'') + if sect & x("[23]"): + return (''+ + ""+func+sect+""+'') + return ""+func+""+sect+"" + def resolve_internal(self, func): + if func in self.anchors: + return ''+func+"" + print "not in anchors '"+func+"'" + return ""+func+"" + def sane(self, text): + return (text + .replace("", "") + .replace("", "")) + diff --git a/docs/zzipdoc/functionlistreference.py b/docs/zzipdoc/functionlistreference.py new file mode 100644 index 0000000..9617f6f --- /dev/null +++ b/docs/zzipdoc/functionlistreference.py @@ -0,0 +1,267 @@ +from match import Match +from htm2dbk import * + +class FunctionListReference: + """ Creating a docbook-style list of parts + that will each be translated into a unix manual page in a second step """ + doctype = ( + ''+ + "\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 += ""+self.o.package+" Function List\n" + for item in self.pages: + T += self.sane(item.refentry_text()) + T += "\n" + return T + def sane(self, text): + return (html2docbook(text).replace("->","->") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","") + .replace("","")) & ( + Match("((?:.(?!(") + >> "\\1") + + +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 + hello. Names with underscores are only used as + temporaries but they are memorized, perhaps for later usage. """ + self.name = func.get_name() + self.refhint = "\n\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 """ + if self.refentryinfo: + return self.refentryinfo + if self.refentry_date and \ + self.refentry_productname and \ + self.refentry_title: return ( + "\n "+self.refentry_date+""+ + "\n "+self.refentry_productname+""+ + "\n "+self.refentry_title+"") + if self.refentry_date and \ + self.refentry_productname: return ( + "\n "+self.refentry_date+""+ + "\n "+self.refentry_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 actually """ + if self.refmeta: + return self.refmeta + if self.manvolnum and self.refentrytitle: + return ( + "\n "+self.refentrytitle+""+ + "\n "+self.manvolnum+"") + if self.manvolnum and self.name: + return ( + "\n "+self.name+""+ + "\n "+self.manvolnum+"") + return "" + def refnamediv_text(self): + """ the manvol formatter prints a header line with a line + and 'd functions that are described later. For each of + the s listed here, a mangpage is generated, and for each + of the != then a symlink is created """ + if self.refnamediv: + return self.refnamediv + if self.refpurpose and self.refname: + return ("\n "+self.refname+''+ + "\n "+self.refpurpose+" ") + if self.refpurpose and self.refname_list: + T = "" + for refname in self.refname_list: + T += "\n "+refname+'' + T += "\n "+self.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" + if self.funcsynopsisinfo: + T += "\n"+ self.funcsynopsisinfo + \ + "\n\n" + T += self.funcsynopsis + \ + "\n\n" + if self.funcsynopsis_list: + T += "\n" + if self.funcsynopsisinfo: + T += "\n"+ self.funcsynopsisinfo + \ + "\n\n" + for funcsynopsis in self.funcsynopsis_list: + T += funcsynopsis + T += "\n\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 "(missing description)" + 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 = "" + previous="" + for authors in self.authors_list: + if not authors: continue + if previous == authors: continue + T += "\n "+authors+"" + previous = authors + T += "" + 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 = '' + else: + T = '' # this is an error + + if self.refentryinfo_text(): + T += "\n"+ self.refentryinfo_text()+ \ + "\n\n" + if self.refmeta_text(): + T += "\n"+ self.refmeta_text() + \ + "\n\n" + if self.refnamediv_text(): + T += "\n"+ self.refnamediv_text() + \ + "\n\n" + if self.funcsynopsisdiv_text(): + T += "\n\n"+ self.funcsynopsisdiv_text()+ \ + "\n\n" + if self.description_text(): + T += "\nDescription " + \ + self.description_text() + "\n" + if self.authors_text(): + T += "\nAuthor " + \ + self.authors_text() + "\n" + if self.copyright_text(): + T += "\nCopyright " + \ + self.copyright_text() + "\n\n" + if self.seealso_text(): + T += "\nSee Also " + \ + self.seealso_text() + "\n\n" + + T += "\n\n" + return T + #fu +#end diff --git a/docs/zzipdoc/functionprototype.py b/docs/zzipdoc/functionprototype.py new file mode 100644 index 0000000..5924ce8 --- /dev/null +++ b/docs/zzipdoc/functionprototype.py @@ -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 (""+self.prespec+""+ + ""+self.namespec+""+ + ""+self.callspec+"") diff --git a/docs/zzipdoc/htm2dbk.py b/docs/zzipdoc/htm2dbk.py new file mode 100644 index 0000000..b4a4e2e --- /dev/null +++ b/docs/zzipdoc/htm2dbk.py @@ -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()("(.*)", "m") >> "\n\\1", + m()("<[hH]2>") >> "", + 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") >> "\\1", + m()("]*>","s") >> "", + m()("]*>","s") >> "", + m()("(<\w+\b[^<>]*\swidth=)(\d+\%)","s") >> "\\1\"\\2\"", + m()("(<\w+\b[^<>]*\s\w+=)(\d+)","s") >> "\\1\"\\2\"", + m()("&&") >> "\&\;\&\;", + m()("\$\<") >> "\$\<\;", + m()("&(\w+[\),])") >> "\&\;\\1", + m()("(]*)?>","s") >> "\\1phrase\\2>", + m()("(]*)?>","s") >> "\\1note\\2>", + m()("(")>> "\\1emphasis>", + m()("(") >> "\\1listitem>", + m()("(") >> "\\1itemizedlist>", + m()("(") >> "\\1orderedlist>", + m()("(") >> "\\1variablelist>", + m()("]*)>","s") >> "", + m()("]*)>","s") >> "", + m()("]*)>","s") >> "", + m()("]*)>","s") >> "", + m()("]*)>","s") + >> "", + m()("]*)>","s") >> "", + m()("(]*)?>","s") >> "\\1row\\2>", + m()("(]*)?>","s") >> "\\1entry\\2>", + m()("]*>\s*]*>\s*"+ + "\s*]*>\s*]*>\s*> "\s*\s*"+ + "\s*\s*\s*", "s") + >> "", + m()("(]*\swidth=\"100\%\")","s") >> "\\1 pgwide=\"1\"", + m()("(\s*]*>\s*]*\s)(width=\"50\%\")","s") + >> "\n\\1\\2", + m()("([\'\`]*)") >> "\\1", + m()("([\'\`]*)") >> "\\1", + m()("<(?:tt|code)>([\`\"\'])") >> "\\1", + m()("<(?:tt|code)>([\`\"\'])") >> "\\1", + m()("([\`\"\'])") >> "\\1", + m()("([\`\"\'])") >> "\\1", + m()("(") >> "\\1constant>", + m()("(") >> "\\1literal>", + m()(">([^<>]+)
    ","s") >> ">\\1", + m()("
    ") >> "
    ", + # m()("") >> "", + # m()("") >> "", + m()("") >> "" >> 1, + m()("]+)\"\s*>((?:.(?!))*.)" + ,"s") >> "\\2", + m()("((?:.(?!))*.)","s") + >> "$2", + m()("((?:.(?!))*.)","s") + >> "$2", + m()("((?:.(?!))*.)","s") + >> "\\2", + m()("((?:.(?!))*.)" + ,"s") >> "\\2", + m()("((?:.(?!))*.)","s") + >> "\\2" + # m()("(") >> "\\1para>" + # $_ .= "" if / ]/ + ] + regexlist2 = [ + m()(r"") >> "", + m()(r"(") >> r"\1emphasis>", + m()(r"") >> "", + m()(r"") >> "", + m()(r"") >> "", + m()(r"") >> "", + m()(r"(?s)\s*
    ") >> "", + # m()(r"
      ") >> "", + # m()(r"
    ") >> "", + # m()(r"
  • ") >> "", + # m()(r"
  • ") >> "
    \n", + m()(r"
      ") >> "\n", + m()(r"
    ") >> "", + m()(r"
  • ") >> "", + m()(r"
  • ") >> "" + ] +class htm2dbk_conversion(htm2dbk_conversion_base): + def __init__(self): + self.version = "" # str(date.today) + self.filename = "." + def convert(self,text): # $text + txt = text.replace("", self.version) + for conv in self.regexlist: + txt &= conv + return txt.replace("--filename--", self.filename) + def convert2(self,text): # $text + txt = text.replace("", 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 = ( + ''+ + "\n") + book_start = 'Documentation'+"\n" + book_end_chapters = ''+"\n" + book_end = ''+"\n" + def __init__(self): + htm2dbk_conversion.__init__(self) + self.text = self.doctype + self.book_start + def add(self,text): + if self.text & m()("","") & ( + m()("([^<>]*)") >> "\\1") & ( + m()("(?s)(\s*)" + + "([^<>]*)") >> "\\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 index 0000000..a089ec3 --- /dev/null +++ b/docs/zzipdoc/match.py @@ -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 index 0000000..c6758d5 --- /dev/null +++ b/docs/zzipdoc/options.py @@ -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 index 0000000..bfaff8d --- /dev/null +++ b/docs/zzipdoc/textfile.py @@ -0,0 +1,49 @@ + +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 + + diff --git a/docs/zzipdoc/textfileheader.py b/docs/zzipdoc/textfileheader.py new file mode 100644 index 0000000..2ac0896 --- /dev/null +++ b/docs/zzipdoc/textfileheader.py @@ -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) -- 2.40.0