X-Git-Url: http://developer.intra2net.com/git/?a=blobdiff_plain;f=bindings%2Fdoxy2swig.py;fp=bindings%2Fdoxy2swig.py;h=0000000000000000000000000000000000000000;hb=c5285326555f088e7626dfa67ea7059e094d6e73;hp=cf4c52b5e9a0e75825e97d5da120ef853bdf2b83;hpb=602adb256f131ef673adb18f8581ff249b356077;p=libftdi diff --git a/bindings/doxy2swig.py b/bindings/doxy2swig.py deleted file mode 100644 index cf4c52b..0000000 --- a/bindings/doxy2swig.py +++ /dev/null @@ -1,451 +0,0 @@ -#!/usr/bin/env python -"""Doxygen XML to SWIG docstring converter. - -Usage: - - doxy2swig.py [options] input.xml output.i - -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. - -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 -# -# Thanks: -# Johan Hake: the include_function_definition feature -# Bill Spotz: bug reports and testing. -# Sebastian Henschel: Misc. enhancements. -# -###################################################################### - -from xml.dom import minidom -import re -import textwrap -import sys -import os.path -import optparse - - -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, include_function_definition=True, quiet=False): - """Initialize the instance given a source object. `src` can - be a file or filename. If you do not want to include function - definitions from doxygen then set - `include_function_definition` to `False`. This is handy since - this allows you to use the swig generated function definition - using %feature("autodoc", [0,1]). - - """ - 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 = [] - self.include_function_definition = include_function_definition - if not include_function_definition: - self.ignores.append('argsstring') - - self.quiet = quiet - - - 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, break_long_words=False)) - - 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 parse_Comment(self, node): - """Parse a `COMMENT_NODE`. This does nothing for now.""" - return - - def add_text(self, value): - """Adds text corresponding to `value` into `self.pieces`.""" - if isinstance(value, (list, tuple)): - 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): - text='unknown' - for key, val in node.attributes.items(): - if key == 'kind': - if val == 'param': text = 'Parameters' - elif val == 'exception': text = 'Exceptions' - elif val == 'retval': text = 'Returns' - else: text = val - break - self.add_text(['\n', '\n', text, ':', '\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') - try: - data=node.firstChild.data - except AttributeError: # perhaps a tag in it - data=node.firstChild.firstChild.data - if data.find('Exception') != -1: - self.add_text(data) - else: - self.add_text("%s: "%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 - - if not 'definition' in first or \ - kind in ['variable', 'typedef']: - return - - if self.include_function_definition: - defn = first['definition'].firstChild.data - else: - defn = "" - 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', 'user-defined', ''): - self.generic_parse(node) - - def do_header(self, node): - """For a user defined section def a header field is present - which should not be printed as such, so we comment it in the - output.""" - data = node.firstChild.data - self.add_text('\n/*\n %s \n*/\n'%data) - # If our immediate sibling is a 'description' node then we - # should comment that out also and remove it from the parent - # node's children. - parent = node.parentNode - idx = parent.childNodes.index(node) - if len(parent.childNodes) >= idx + 2: - nd = parent.childNodes[idx+2] - if nd.nodeName == 'description': - nd = parent.removeChild(nd) - self.add_text('\n/*') - self.generic_parse(nd) - self.add_text('\n*/\n') - - 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) - if not self.quiet: - print( "parsing file: %s"%fname ) - p = Doxy2SWIG(fname, self.include_function_definition, self.quiet) - 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:' or i == 'Exceptions:' or i == 'Returns:': - ret.extend([i, '\n'+'-'*len(i), '\n\n']) - elif i.find('// File:') > -1: # leave comments alone. - ret.extend([i, '\n']) - else: - _tmp = textwrap.fill(i.strip(), break_long_words=False) - _tmp = self.lead_spc.sub(r'\1"\2', _tmp) - ret.extend([_tmp, '\n\n']) - return ret - - -def convert(input, output, include_function_definition=True, quiet=False): - p = Doxy2SWIG(input, include_function_definition, quiet) - p.generate() - p.write(output) - -def main(): - usage = __doc__ - parser = optparse.OptionParser(usage) - parser.add_option("-n", '--no-function-definition', - action='store_true', - default=False, - dest='func_def', - help='do not include doxygen function definitions') - parser.add_option("-q", '--quiet', - action='store_true', - default=False, - dest='quiet', - help='be quiet and minimize output') - - options, args = parser.parse_args() - if len(args) != 2: - parser.error("error: no input and output specified") - - convert(args[0], args[1], not options.func_def, options.quiet) - - -if __name__ == '__main__': - main()