From: jcorgan Date: Sun, 24 Aug 2008 19:57:24 +0000 (+0000) Subject: Fixup XML generation to avoid erroneous copying. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=6f1b6b2982ea0ed7bdba025b3ed911111d6e8e7d;p=debian%2Fgnuradio Fixup XML generation to avoid erroneous copying. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9399 221aa14e-8319-0410-a670-987f0aec2ac5 --- diff --git a/config/grc_gnuradio_core.m4 b/config/grc_gnuradio_core.m4 index 562641eb..df2ec305 100644 --- a/config/grc_gnuradio_core.m4 +++ b/config/grc_gnuradio_core.m4 @@ -80,7 +80,7 @@ AC_DEFUN([GRC_GNURADIO_CORE],[ gnuradio-core/doc/Doxyfile \ gnuradio-core/doc/Makefile \ gnuradio-core/doc/other/Makefile \ - gnuradio-core/doc/xml/Makefile \ + gnuradio-core/doc/xml-swig/Makefile \ gnuradio-core/src/Makefile \ gnuradio-core/src/gen_interpolator_taps/Makefile \ gnuradio-core/src/lib/Makefile \ diff --git a/gnuradio-core/doc/Makefile.am b/gnuradio-core/doc/Makefile.am index a499946a..1fd11a92 100644 --- a/gnuradio-core/doc/Makefile.am +++ b/gnuradio-core/doc/Makefile.am @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = other xml +SUBDIRS = other xml-swig docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ @@ -36,6 +36,7 @@ html/index.html: prep: mkdir -p html + mkdir -p xml install-data-local: $(mkinstalldirs) $(DESTDIR)$(docdir) diff --git a/gnuradio-core/doc/xml-swig/Makefile.am b/gnuradio-core/doc/xml-swig/Makefile.am new file mode 100644 index 00000000..f508deb2 --- /dev/null +++ b/gnuradio-core/doc/xml-swig/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +EXTRA_DIST = README doxy2swig.py swig.xsl + +CLEANFILES = *.xml combine.xslt compound.xsd index.xsd + diff --git a/gnuradio-core/doc/xml-swig/README b/gnuradio-core/doc/xml-swig/README new file mode 100644 index 00000000..e5187df2 --- /dev/null +++ b/gnuradio-core/doc/xml-swig/README @@ -0,0 +1,129 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +# +# Generating Python docstrings from C++ code using doxygen +# + +There are at least two strategies for this: + - use xsltproc as described below + - use doxy2swig.py (included in this directory) + +FIXME: get one of these working (probably doxy2swig since it doesn't +add any additional dependencies). + +---------------------------------------------------------------- + +Note: Robin's patch is in SWIG >= 1.3.23 + +-------------------------------------------------------------------------------- +From: http://mailman.cs.uchicago.edu/pipermail/swig/2004-October/010604.html + +> I applied the docstring patch. '%feature("autodoc",1");' is working as +> expected ... + +[problem solved. ...] + +> I can not agree more with the doxygen idea. I am using doxygen for +> documentation and I have been trying to put doxygen output to the +> python interface. Automatic generation of %feature("docstring") lines +> from doxygen output is the closest solution I can think of but the +> workload is still pretty big. How I wish this feature can be +> implemented in the near future. + +I have successfully extracted function/class description from doxygen +generated xml files, using an xslt script. To add doxygen generated +description to each class/function, you will need to (tested under +linux, note that this works only for Python, using Robin's docstring +patch) + +1. download swig source, apply Robin's docstring patch from + https://sourceforge.net/tracker/index.php?func=detail&aid=1023309&group_id=1645&atid=301645 + compile and install + +2. generate doxygen document with option "GENERATE_XML = YES" + +3. copy the attached script (save as swig.xsl) to the doc/xml directory + and run + + > xsltproc swig.xsl index.xml > temp_doc.i + > cat temp_doc.i | sed 's/"/\\"/g' | sed 's/__QuOtE__/"/g' > swig_doc.i + + you will get an interface file with lines like + %feature("docstring") class "class description"; + %feature("docstring") class::function "member function + description"; + + the second step is necessary since there might be " in descriptions + and I need to backquote them before I replace __QuOtE__ by real + quotes. (xslt experts may know how to post-process and + make the script easier to use.) + +4. in your interface file, add + %include "siwg_doc.i" + %feature("autodoc","1") ; + +Hope this helps. + +swig.xsl: +========================================================= + + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + + +-- +Bo Peng \ No newline at end of file diff --git a/gnuradio-core/doc/xml-swig/doxy2swig.py b/gnuradio-core/doc/xml-swig/doxy2swig.py new file mode 100644 index 00000000..1e379d94 --- /dev/null +++ b/gnuradio-core/doc/xml-swig/doxy2swig.py @@ -0,0 +1,371 @@ +#!/usr/bin/env python +"""Doxygen XML to SWIG docstring converter. + +Converts Doxygen generated XML files into a file containing docstrings +that can be used by SWIG-1.3.x. Note that you need to get SWIG +version > 1.3.23 or use Robin Dunn's docstring patch to be able to use +the resulting output. + +Usage: + + doxy2swig.py input.xml output.i + +input.xml is your doxygen generated XML file and output.i is where the +output will be written (the file will be clobbered). + +""" + +# This code is implemented using Mark Pilgrim's code as a guideline: +# http://www.faqs.org/docs/diveintopython/kgp_divein.html +# +# Author: Prabhu Ramachandran +# License: BSD style + + +from xml.dom import minidom +import re +import textwrap +import sys +import types +import os.path + + +def my_open_read(source): + if hasattr(source, "read"): + return source + else: + return open(source) + +def my_open_write(dest): + if hasattr(dest, "write"): + return dest + else: + return open(dest, 'w') + + +class Doxy2SWIG: + """Converts Doxygen generated XML files into a file containing + docstrings that can be used by SWIG-1.3.x that have support for + feature("docstring"). Once the data is parsed it is stored in + self.pieces. + + """ + + def __init__(self, src): + """Initialize the instance given a source object (file or + filename). + + """ + f = my_open_read(src) + self.my_dir = os.path.dirname(f.name) + self.xmldoc = minidom.parse(f).documentElement + f.close() + + self.pieces = [] + self.pieces.append('\n// File: %s\n'%\ + os.path.basename(f.name)) + + self.space_re = re.compile(r'\s+') + self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') + self.multi = 0 + self.ignores = ('inheritancegraph', 'param', 'listofallmembers', + 'innerclass', 'name', 'declname', 'incdepgraph', + 'invincdepgraph', 'programlisting', 'type', + 'references', 'referencedby', 'location', + 'collaborationgraph', 'reimplements', + 'reimplementedby', 'derivedcompoundref', + 'basecompoundref') + #self.generics = [] + + def generate(self): + """Parses the file set in the initialization. The resulting + data is stored in `self.pieces`. + + """ + self.parse(self.xmldoc) + + def parse(self, node): + """Parse a given node. This function in turn calls the + `parse_` functions which handle the respective + nodes. + + """ + pm = getattr(self, "parse_%s"%node.__class__.__name__) + pm(node) + + def parse_Document(self, node): + self.parse(node.documentElement) + + def parse_Text(self, node): + txt = node.data + txt = txt.replace('\\', r'\\\\') + txt = txt.replace('"', r'\"') + # ignore pure whitespace + m = self.space_re.match(txt) + if m and len(m.group()) == len(txt): + pass + else: + self.add_text(textwrap.fill(txt)) + + def parse_Element(self, node): + """Parse an `ELEMENT_NODE`. This calls specific + `do_` handers for different elements. If no handler + is available the `generic_parse` method is called. All + tagNames specified in `self.ignores` are simply ignored. + + """ + name = node.tagName + ignores = self.ignores + if name in ignores: + return + attr = "do_%s" % name + if hasattr(self, attr): + handlerMethod = getattr(self, attr) + handlerMethod(node) + else: + self.generic_parse(node) + #if name not in self.generics: self.generics.append(name) + + def add_text(self, value): + """Adds text corresponding to `value` into `self.pieces`.""" + if type(value) in (types.ListType, types.TupleType): + self.pieces.extend(value) + else: + self.pieces.append(value) + + def get_specific_nodes(self, node, names): + """Given a node and a sequence of strings in `names`, return a + dictionary containing the names as keys and child + `ELEMENT_NODEs`, that have a `tagName` equal to the name. + + """ + nodes = [(x.tagName, x) for x in node.childNodes \ + if x.nodeType == x.ELEMENT_NODE and \ + x.tagName in names] + return dict(nodes) + + def generic_parse(self, node, pad=0): + """A Generic parser for arbitrary tags in a node. + + Parameters: + + - node: A node in the DOM. + - pad: `int` (default: 0) + + If 0 the node data is not padded with newlines. If 1 it + appends a newline after parsing the childNodes. If 2 it + pads before and after the nodes are processed. Defaults to + 0. + + """ + npiece = 0 + if pad: + npiece = len(self.pieces) + if pad == 2: + self.add_text('\n') + for n in node.childNodes: + self.parse(n) + if pad: + if len(self.pieces) > npiece: + self.add_text('\n') + + def space_parse(self, node): + self.add_text(' ') + self.generic_parse(node) + + do_ref = space_parse + do_emphasis = space_parse + do_bold = space_parse + do_computeroutput = space_parse + do_formula = space_parse + + def do_compoundname(self, node): + self.add_text('\n\n') + data = node.firstChild.data + self.add_text('%%feature("docstring") %s "\n'%data) + + def do_compounddef(self, node): + kind = node.attributes['kind'].value + if kind in ('class', 'struct'): + prot = node.attributes['prot'].value + if prot <> 'public': + return + names = ('compoundname', 'briefdescription', + 'detaileddescription', 'includes') + first = self.get_specific_nodes(node, names) + for n in names: + if first.has_key(n): + self.parse(first[n]) + self.add_text(['";','\n']) + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + elif kind in ('file', 'namespace'): + nodes = node.getElementsByTagName('sectiondef') + for n in nodes: + self.parse(n) + + def do_includes(self, node): + self.add_text('C++ includes: ') + self.generic_parse(node, pad=1) + + def do_parameterlist(self, node): + self.add_text(['\n', '\n', 'Parameters:', '\n']) + self.generic_parse(node, pad=1) + + def do_para(self, node): + self.add_text('\n') + self.generic_parse(node, pad=1) + + def do_parametername(self, node): + self.add_text('\n') + self.add_text("%s: "%node.firstChild.data) + + def do_parameterdefinition(self, node): + self.generic_parse(node, pad=1) + + def do_detaileddescription(self, node): + self.generic_parse(node, pad=1) + + def do_briefdescription(self, node): + self.generic_parse(node, pad=1) + + def do_memberdef(self, node): + prot = node.attributes['prot'].value + id = node.attributes['id'].value + kind = node.attributes['kind'].value + tmp = node.parentNode.parentNode.parentNode + compdef = tmp.getElementsByTagName('compounddef')[0] + cdef_kind = compdef.attributes['kind'].value + + if prot == 'public': + first = self.get_specific_nodes(node, ('definition', 'name')) + name = first['name'].firstChild.data + if name[:8] == 'operator': # Don't handle operators yet. + return + + defn = first['definition'].firstChild.data + self.add_text('\n') + self.add_text('%feature("docstring") ') + + anc = node.parentNode.parentNode + if cdef_kind in ('file', 'namespace'): + ns_node = anc.getElementsByTagName('innernamespace') + if not ns_node and cdef_kind == 'namespace': + ns_node = anc.getElementsByTagName('compoundname') + if ns_node: + ns = ns_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(ns, name, defn)) + else: + self.add_text(' %s "\n%s'%(name, defn)) + elif cdef_kind in ('class', 'struct'): + # Get the full function name. + anc_node = anc.getElementsByTagName('compoundname') + cname = anc_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(cname, name, defn)) + + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + self.add_text(['";', '\n']) + + def do_definition(self, node): + data = node.firstChild.data + self.add_text('%s "\n%s'%(data, data)) + + def do_sectiondef(self, node): + kind = node.attributes['kind'].value + if kind in ('public-func', 'func'): + self.generic_parse(node) + + def do_simplesect(self, node): + kind = node.attributes['kind'].value + if kind in ('date', 'rcs', 'version'): + pass + elif kind == 'warning': + self.add_text(['\n', 'WARNING: ']) + self.generic_parse(node) + elif kind == 'see': + self.add_text('\n') + self.add_text('See: ') + self.generic_parse(node) + else: + self.generic_parse(node) + + def do_argsstring(self, node): + self.generic_parse(node, pad=1) + + def do_member(self, node): + kind = node.attributes['kind'].value + refid = node.attributes['refid'].value + if kind == 'function' and refid[:9] == 'namespace': + self.generic_parse(node) + + def do_doxygenindex(self, node): + self.multi = 1 + comps = node.getElementsByTagName('compound') + for c in comps: + refid = c.attributes['refid'].value + fname = refid + '.xml' + if not os.path.exists(fname): + fname = os.path.join(self.my_dir, fname) + print "parsing file: %s"%fname + p = Doxy2SWIG(fname) + p.generate() + self.pieces.extend(self.clean_pieces(p.pieces)) + + def write(self, fname): + o = my_open_write(fname) + if self.multi: + o.write("".join(self.pieces)) + else: + o.write("".join(self.clean_pieces(self.pieces))) + o.close() + + def clean_pieces(self, pieces): + """Cleans the list of strings given as `pieces`. It replaces + multiple newlines by a maximum of 2 and returns a new list. + It also wraps the paragraphs nicely. + + """ + ret = [] + count = 0 + for i in pieces: + if i == '\n': + count = count + 1 + else: + if i == '";': + if count: + ret.append('\n') + elif count > 2: + ret.append('\n\n') + elif count: + ret.append('\n'*count) + count = 0 + ret.append(i) + + _data = "".join(ret) + ret = [] + for i in _data.split('\n\n'): + if i == 'Parameters:': + ret.extend(['Parameters:\n-----------', '\n\n']) + elif i.find('// File:') > -1: # leave comments alone. + ret.extend([i, '\n']) + else: + _tmp = textwrap.fill(i.strip()) + _tmp = self.lead_spc.sub(r'\1"\2', _tmp) + ret.extend([_tmp, '\n\n']) + return ret + + +def main(input, output): + p = Doxy2SWIG(input) + p.generate() + p.write(output) + + +if __name__ == '__main__': + if len(sys.argv) != 3: + print __doc__ + sys.exit(1) + main(sys.argv[1], sys.argv[2]) diff --git a/gnuradio-core/doc/xml-swig/swig.xsl b/gnuradio-core/doc/xml-swig/swig.xsl new file mode 100644 index 00000000..6163c2d9 --- /dev/null +++ b/gnuradio-core/doc/xml-swig/swig.xsl @@ -0,0 +1,38 @@ + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + diff --git a/gnuradio-core/doc/xml/Makefile.am b/gnuradio-core/doc/xml/Makefile.am deleted file mode 100644 index f508deb2..00000000 --- a/gnuradio-core/doc/xml/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -EXTRA_DIST = README doxy2swig.py swig.xsl - -CLEANFILES = *.xml combine.xslt compound.xsd index.xsd - diff --git a/gnuradio-core/doc/xml/README b/gnuradio-core/doc/xml/README deleted file mode 100644 index e5187df2..00000000 --- a/gnuradio-core/doc/xml/README +++ /dev/null @@ -1,129 +0,0 @@ -# -# Copyright 2005 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# -# Generating Python docstrings from C++ code using doxygen -# - -There are at least two strategies for this: - - use xsltproc as described below - - use doxy2swig.py (included in this directory) - -FIXME: get one of these working (probably doxy2swig since it doesn't -add any additional dependencies). - ----------------------------------------------------------------- - -Note: Robin's patch is in SWIG >= 1.3.23 - --------------------------------------------------------------------------------- -From: http://mailman.cs.uchicago.edu/pipermail/swig/2004-October/010604.html - -> I applied the docstring patch. '%feature("autodoc",1");' is working as -> expected ... - -[problem solved. ...] - -> I can not agree more with the doxygen idea. I am using doxygen for -> documentation and I have been trying to put doxygen output to the -> python interface. Automatic generation of %feature("docstring") lines -> from doxygen output is the closest solution I can think of but the -> workload is still pretty big. How I wish this feature can be -> implemented in the near future. - -I have successfully extracted function/class description from doxygen -generated xml files, using an xslt script. To add doxygen generated -description to each class/function, you will need to (tested under -linux, note that this works only for Python, using Robin's docstring -patch) - -1. download swig source, apply Robin's docstring patch from - https://sourceforge.net/tracker/index.php?func=detail&aid=1023309&group_id=1645&atid=301645 - compile and install - -2. generate doxygen document with option "GENERATE_XML = YES" - -3. copy the attached script (save as swig.xsl) to the doc/xml directory - and run - - > xsltproc swig.xsl index.xml > temp_doc.i - > cat temp_doc.i | sed 's/"/\\"/g' | sed 's/__QuOtE__/"/g' > swig_doc.i - - you will get an interface file with lines like - %feature("docstring") class "class description"; - %feature("docstring") class::function "member function - description"; - - the second step is necessary since there might be " in descriptions - and I need to backquote them before I replace __QuOtE__ by real - quotes. (xslt experts may know how to post-process and - make the script easier to use.) - -4. in your interface file, add - %include "siwg_doc.i" - %feature("autodoc","1") ; - -Hope this helps. - -swig.xsl: -========================================================= - - - - - - - - - - - - - - %feature(__QuOtE__docstring__QuOtE__) - - __QuOtE__ - - - - see also: - - __QuOtE__; - - - - %feature(__QuOtE__docstring__QuOtE__) :: - __QuOtE__ - - - - - __QuOtE__; - - - - - --- -Bo Peng \ No newline at end of file diff --git a/gnuradio-core/doc/xml/doxy2swig.py b/gnuradio-core/doc/xml/doxy2swig.py deleted file mode 100644 index 1e379d94..00000000 --- a/gnuradio-core/doc/xml/doxy2swig.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/env python -"""Doxygen XML to SWIG docstring converter. - -Converts Doxygen generated XML files into a file containing docstrings -that can be used by SWIG-1.3.x. Note that you need to get SWIG -version > 1.3.23 or use Robin Dunn's docstring patch to be able to use -the resulting output. - -Usage: - - doxy2swig.py input.xml output.i - -input.xml is your doxygen generated XML file and output.i is where the -output will be written (the file will be clobbered). - -""" - -# This code is implemented using Mark Pilgrim's code as a guideline: -# http://www.faqs.org/docs/diveintopython/kgp_divein.html -# -# Author: Prabhu Ramachandran -# License: BSD style - - -from xml.dom import minidom -import re -import textwrap -import sys -import types -import os.path - - -def my_open_read(source): - if hasattr(source, "read"): - return source - else: - return open(source) - -def my_open_write(dest): - if hasattr(dest, "write"): - return dest - else: - return open(dest, 'w') - - -class Doxy2SWIG: - """Converts Doxygen generated XML files into a file containing - docstrings that can be used by SWIG-1.3.x that have support for - feature("docstring"). Once the data is parsed it is stored in - self.pieces. - - """ - - def __init__(self, src): - """Initialize the instance given a source object (file or - filename). - - """ - f = my_open_read(src) - self.my_dir = os.path.dirname(f.name) - self.xmldoc = minidom.parse(f).documentElement - f.close() - - self.pieces = [] - self.pieces.append('\n// File: %s\n'%\ - os.path.basename(f.name)) - - self.space_re = re.compile(r'\s+') - self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') - self.multi = 0 - self.ignores = ('inheritancegraph', 'param', 'listofallmembers', - 'innerclass', 'name', 'declname', 'incdepgraph', - 'invincdepgraph', 'programlisting', 'type', - 'references', 'referencedby', 'location', - 'collaborationgraph', 'reimplements', - 'reimplementedby', 'derivedcompoundref', - 'basecompoundref') - #self.generics = [] - - def generate(self): - """Parses the file set in the initialization. The resulting - data is stored in `self.pieces`. - - """ - self.parse(self.xmldoc) - - def parse(self, node): - """Parse a given node. This function in turn calls the - `parse_` functions which handle the respective - nodes. - - """ - pm = getattr(self, "parse_%s"%node.__class__.__name__) - pm(node) - - def parse_Document(self, node): - self.parse(node.documentElement) - - def parse_Text(self, node): - txt = node.data - txt = txt.replace('\\', r'\\\\') - txt = txt.replace('"', r'\"') - # ignore pure whitespace - m = self.space_re.match(txt) - if m and len(m.group()) == len(txt): - pass - else: - self.add_text(textwrap.fill(txt)) - - def parse_Element(self, node): - """Parse an `ELEMENT_NODE`. This calls specific - `do_` handers for different elements. If no handler - is available the `generic_parse` method is called. All - tagNames specified in `self.ignores` are simply ignored. - - """ - name = node.tagName - ignores = self.ignores - if name in ignores: - return - attr = "do_%s" % name - if hasattr(self, attr): - handlerMethod = getattr(self, attr) - handlerMethod(node) - else: - self.generic_parse(node) - #if name not in self.generics: self.generics.append(name) - - def add_text(self, value): - """Adds text corresponding to `value` into `self.pieces`.""" - if type(value) in (types.ListType, types.TupleType): - self.pieces.extend(value) - else: - self.pieces.append(value) - - def get_specific_nodes(self, node, names): - """Given a node and a sequence of strings in `names`, return a - dictionary containing the names as keys and child - `ELEMENT_NODEs`, that have a `tagName` equal to the name. - - """ - nodes = [(x.tagName, x) for x in node.childNodes \ - if x.nodeType == x.ELEMENT_NODE and \ - x.tagName in names] - return dict(nodes) - - def generic_parse(self, node, pad=0): - """A Generic parser for arbitrary tags in a node. - - Parameters: - - - node: A node in the DOM. - - pad: `int` (default: 0) - - If 0 the node data is not padded with newlines. If 1 it - appends a newline after parsing the childNodes. If 2 it - pads before and after the nodes are processed. Defaults to - 0. - - """ - npiece = 0 - if pad: - npiece = len(self.pieces) - if pad == 2: - self.add_text('\n') - for n in node.childNodes: - self.parse(n) - if pad: - if len(self.pieces) > npiece: - self.add_text('\n') - - def space_parse(self, node): - self.add_text(' ') - self.generic_parse(node) - - do_ref = space_parse - do_emphasis = space_parse - do_bold = space_parse - do_computeroutput = space_parse - do_formula = space_parse - - def do_compoundname(self, node): - self.add_text('\n\n') - data = node.firstChild.data - self.add_text('%%feature("docstring") %s "\n'%data) - - def do_compounddef(self, node): - kind = node.attributes['kind'].value - if kind in ('class', 'struct'): - prot = node.attributes['prot'].value - if prot <> 'public': - return - names = ('compoundname', 'briefdescription', - 'detaileddescription', 'includes') - first = self.get_specific_nodes(node, names) - for n in names: - if first.has_key(n): - self.parse(first[n]) - self.add_text(['";','\n']) - for n in node.childNodes: - if n not in first.values(): - self.parse(n) - elif kind in ('file', 'namespace'): - nodes = node.getElementsByTagName('sectiondef') - for n in nodes: - self.parse(n) - - def do_includes(self, node): - self.add_text('C++ includes: ') - self.generic_parse(node, pad=1) - - def do_parameterlist(self, node): - self.add_text(['\n', '\n', 'Parameters:', '\n']) - self.generic_parse(node, pad=1) - - def do_para(self, node): - self.add_text('\n') - self.generic_parse(node, pad=1) - - def do_parametername(self, node): - self.add_text('\n') - self.add_text("%s: "%node.firstChild.data) - - def do_parameterdefinition(self, node): - self.generic_parse(node, pad=1) - - def do_detaileddescription(self, node): - self.generic_parse(node, pad=1) - - def do_briefdescription(self, node): - self.generic_parse(node, pad=1) - - def do_memberdef(self, node): - prot = node.attributes['prot'].value - id = node.attributes['id'].value - kind = node.attributes['kind'].value - tmp = node.parentNode.parentNode.parentNode - compdef = tmp.getElementsByTagName('compounddef')[0] - cdef_kind = compdef.attributes['kind'].value - - if prot == 'public': - first = self.get_specific_nodes(node, ('definition', 'name')) - name = first['name'].firstChild.data - if name[:8] == 'operator': # Don't handle operators yet. - return - - defn = first['definition'].firstChild.data - self.add_text('\n') - self.add_text('%feature("docstring") ') - - anc = node.parentNode.parentNode - if cdef_kind in ('file', 'namespace'): - ns_node = anc.getElementsByTagName('innernamespace') - if not ns_node and cdef_kind == 'namespace': - ns_node = anc.getElementsByTagName('compoundname') - if ns_node: - ns = ns_node[0].firstChild.data - self.add_text(' %s::%s "\n%s'%(ns, name, defn)) - else: - self.add_text(' %s "\n%s'%(name, defn)) - elif cdef_kind in ('class', 'struct'): - # Get the full function name. - anc_node = anc.getElementsByTagName('compoundname') - cname = anc_node[0].firstChild.data - self.add_text(' %s::%s "\n%s'%(cname, name, defn)) - - for n in node.childNodes: - if n not in first.values(): - self.parse(n) - self.add_text(['";', '\n']) - - def do_definition(self, node): - data = node.firstChild.data - self.add_text('%s "\n%s'%(data, data)) - - def do_sectiondef(self, node): - kind = node.attributes['kind'].value - if kind in ('public-func', 'func'): - self.generic_parse(node) - - def do_simplesect(self, node): - kind = node.attributes['kind'].value - if kind in ('date', 'rcs', 'version'): - pass - elif kind == 'warning': - self.add_text(['\n', 'WARNING: ']) - self.generic_parse(node) - elif kind == 'see': - self.add_text('\n') - self.add_text('See: ') - self.generic_parse(node) - else: - self.generic_parse(node) - - def do_argsstring(self, node): - self.generic_parse(node, pad=1) - - def do_member(self, node): - kind = node.attributes['kind'].value - refid = node.attributes['refid'].value - if kind == 'function' and refid[:9] == 'namespace': - self.generic_parse(node) - - def do_doxygenindex(self, node): - self.multi = 1 - comps = node.getElementsByTagName('compound') - for c in comps: - refid = c.attributes['refid'].value - fname = refid + '.xml' - if not os.path.exists(fname): - fname = os.path.join(self.my_dir, fname) - print "parsing file: %s"%fname - p = Doxy2SWIG(fname) - p.generate() - self.pieces.extend(self.clean_pieces(p.pieces)) - - def write(self, fname): - o = my_open_write(fname) - if self.multi: - o.write("".join(self.pieces)) - else: - o.write("".join(self.clean_pieces(self.pieces))) - o.close() - - def clean_pieces(self, pieces): - """Cleans the list of strings given as `pieces`. It replaces - multiple newlines by a maximum of 2 and returns a new list. - It also wraps the paragraphs nicely. - - """ - ret = [] - count = 0 - for i in pieces: - if i == '\n': - count = count + 1 - else: - if i == '";': - if count: - ret.append('\n') - elif count > 2: - ret.append('\n\n') - elif count: - ret.append('\n'*count) - count = 0 - ret.append(i) - - _data = "".join(ret) - ret = [] - for i in _data.split('\n\n'): - if i == 'Parameters:': - ret.extend(['Parameters:\n-----------', '\n\n']) - elif i.find('// File:') > -1: # leave comments alone. - ret.extend([i, '\n']) - else: - _tmp = textwrap.fill(i.strip()) - _tmp = self.lead_spc.sub(r'\1"\2', _tmp) - ret.extend([_tmp, '\n\n']) - return ret - - -def main(input, output): - p = Doxy2SWIG(input) - p.generate() - p.write(output) - - -if __name__ == '__main__': - if len(sys.argv) != 3: - print __doc__ - sys.exit(1) - main(sys.argv[1], sys.argv[2]) diff --git a/gnuradio-core/doc/xml/swig.xsl b/gnuradio-core/doc/xml/swig.xsl deleted file mode 100644 index 6163c2d9..00000000 --- a/gnuradio-core/doc/xml/swig.xsl +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - %feature(__QuOtE__docstring__QuOtE__) - - __QuOtE__ - - - - see also: - - __QuOtE__; - - - - %feature(__QuOtE__docstring__QuOtE__) :: - __QuOtE__ - - - - - __QuOtE__; - - - -