summaryrefslogtreecommitdiff
path: root/tools/build/src/tools/doxproc.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/build/src/tools/doxproc.py')
-rw-r--r--tools/build/src/tools/doxproc.py859
1 files changed, 859 insertions, 0 deletions
diff --git a/tools/build/src/tools/doxproc.py b/tools/build/src/tools/doxproc.py
new file mode 100644
index 000000000..4cbd5edd2
--- /dev/null
+++ b/tools/build/src/tools/doxproc.py
@@ -0,0 +1,859 @@
+#!/usr/bin/python
+# Copyright 2006 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+'''
+Processing of Doxygen generated XML.
+'''
+
+import os
+import os.path
+import sys
+import time
+import string
+import getopt
+import glob
+import re
+import xml.dom.minidom
+
+
+def usage():
+ print '''
+Usage:
+ %s options
+
+Options:
+ --xmldir Directory with the Doxygen xml result files.
+ --output Write the output BoostBook to the given location.
+ --id The ID of the top level BoostBook section.
+ --title The title of the top level BoostBook section.
+ --enable-index Generate additional index sections for classes and
+ types.
+''' % ( sys.argv[0] )
+
+
+def get_args( argv = sys.argv[1:] ):
+ spec = [
+ 'xmldir=',
+ 'output=',
+ 'id=',
+ 'title=',
+ 'enable-index',
+ 'help' ]
+ options = {
+ '--xmldir' : 'xml',
+ '--output' : None,
+ '--id' : 'dox',
+ '--title' : 'Doxygen'
+ }
+ ( option_pairs, other ) = getopt.getopt( argv, '', spec )
+ map( lambda x: options.__setitem__( x[0], x[1] ), option_pairs )
+
+ if options.has_key( '--help' ):
+ usage()
+ sys.exit(1)
+
+ return {
+ 'xmldir' : options['--xmldir'],
+ 'output' : options['--output'],
+ 'id' : options['--id'],
+ 'title' : options['--title'],
+ 'index' : options.has_key('--enable-index')
+ }
+
+def if_attribute(node, attribute, true_value, false_value=None):
+ if node.getAttribute(attribute) == 'yes':
+ return true_value
+ else:
+ return false_value
+
+class Doxygen2BoostBook:
+
+ def __init__( self, **kwargs ):
+ ##
+ self.args = kwargs
+ self.args.setdefault('id','')
+ self.args.setdefault('title','')
+ self.args.setdefault('last_revision', time.asctime())
+ self.args.setdefault('index', False)
+ self.id = '%(id)s.reference' % self.args
+ self.args['id'] = self.id
+ #~ This is our template BoostBook document we insert the generated content into.
+ self.boostbook = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
+<section id="%(id)s" name="%(title)s" last-revision="%(last_revision)s">
+ <title>%(title)s</title>
+ <library-reference id="%(id)s.headers">
+ <title>Headers</title>
+ </library-reference>
+ <index id="%(id)s.classes">
+ <title>Classes</title>
+ </index>
+ <index id="%(id)s.index">
+ <title>Index</title>
+ </index>
+</section>
+''' % self.args )
+ self.section = {
+ 'headers' : self._getChild('library-reference',id='%(id)s.headers' % self.args),
+ 'classes' : self._getChild('index',id='%(id)s.classes' % self.args),
+ 'index' : self._getChild('index',id='%(id)s.index' % self.args)
+ }
+ #~ Remove the index sections if we aren't generating it.
+ if not self.args['index']:
+ self.section['classes'].parentNode.removeChild(self.section['classes'])
+ self.section['classes'].unlink()
+ del self.section['classes']
+ self.section['index'].parentNode.removeChild(self.section['index'])
+ self.section['index'].unlink()
+ del self.section['index']
+ #~ The symbols, per Doxygen notion, that we translated.
+ self.symbols = {}
+ #~ Map of Doxygen IDs and BoostBook IDs, so we can translate as needed.
+ self.idmap = {}
+ #~ Marks generation, to prevent redoing it.
+ self.generated = False
+
+ #~ Add an Doxygen generated XML document to the content we are translating.
+ def addDox( self, document ):
+ self._translateNode(document.documentElement)
+
+ #~ Turns the internal XML tree into an output UTF-8 string.
+ def tostring( self ):
+ self._generate()
+ #~ return self.boostbook.toprettyxml(' ')
+ return self.boostbook.toxml('utf-8')
+
+ #~ Does post-processing on the partial generated content to generate additional info
+ #~ now that we have the complete source documents.
+ def _generate( self ):
+ if not self.generated:
+ self.generated = True
+ symbols = self.symbols.keys()
+ symbols.sort()
+ #~ Populate the header section.
+ for symbol in symbols:
+ if self.symbols[symbol]['kind'] in ('header'):
+ self.section['headers'].appendChild(self.symbols[symbol]['dom'])
+ for symbol in symbols:
+ if self.symbols[symbol]['kind'] not in ('namespace', 'header'):
+ container = self._resolveContainer(self.symbols[symbol],
+ self.symbols[self.symbols[symbol]['header']]['dom'])
+ if container.nodeName != 'namespace':
+ ## The current BoostBook to Docbook translation doesn't
+ ## respect, nor assign, IDs to inner types of any kind.
+ ## So nuke the ID entry so as not create bogus links.
+ del self.idmap[self.symbols[symbol]['id']]
+ container.appendChild(self.symbols[symbol]['dom'])
+ self._rewriteIDs(self.boostbook.documentElement)
+
+ #~ Rewrite the various IDs from Doxygen references to the newly created
+ #~ BoostBook references.
+ def _rewriteIDs( self, node ):
+ if node.nodeName in ('link'):
+ if (self.idmap.has_key(node.getAttribute('linkend'))):
+ #~ A link, and we have someplace to repoint it at.
+ node.setAttribute('linkend',self.idmap[node.getAttribute('linkend')])
+ else:
+ #~ A link, but we don't have a generated target for it.
+ node.removeAttribute('linkend')
+ elif hasattr(node,'hasAttribute') and node.hasAttribute('id') and self.idmap.has_key(node.getAttribute('id')):
+ #~ Simple ID, and we have a translation.
+ node.setAttribute('id',self.idmap[node.getAttribute('id')])
+ #~ Recurse, and iterate, depth-first traversal which turns out to be
+ #~ left-to-right and top-to-bottom for the document.
+ if node.firstChild:
+ self._rewriteIDs(node.firstChild)
+ if node.nextSibling:
+ self._rewriteIDs(node.nextSibling)
+
+ def _resolveContainer( self, cpp, root ):
+ container = root
+ for ns in cpp['namespace']:
+ node = self._getChild('namespace',name=ns,root=container)
+ if not node:
+ node = container.appendChild(
+ self._createNode('namespace',name=ns))
+ container = node
+ for inner in cpp['name'].split('::'):
+ node = self._getChild(name=inner,root=container)
+ if not node:
+ break
+ container = node
+ return container
+
+ def _setID( self, id, name ):
+ self.idmap[id] = name.replace('::','.').replace('/','.')
+ #~ print '--| setID:',id,'::',self.idmap[id]
+
+ #~ Translate a given node within a given context.
+ #~ The translation dispatches to a local method of the form
+ #~ "_translate[_context0,...,_contextN]", and the keyword args are
+ #~ passed along. If there is no translation handling method we
+ #~ return None.
+ def _translateNode( self, *context, **kwargs ):
+ node = None
+ names = [ ]
+ for c in context:
+ if c:
+ if not isinstance(c,xml.dom.Node):
+ suffix = '_'+c.replace('-','_')
+ else:
+ suffix = '_'+c.nodeName.replace('-','_')
+ node = c
+ names.append('_translate')
+ names = map(lambda x: x+suffix,names)
+ if node:
+ for name in names:
+ if hasattr(self,name):
+ return getattr(self,name)(node,**kwargs)
+ return None
+
+ #~ Translates the children of the given parent node, appending the results
+ #~ to the indicated target. For nodes not translated by the translation method
+ #~ it copies the child over and recurses on that child to translate any
+ #~ possible interior nodes. Hence this will translate the entire subtree.
+ def _translateChildren( self, parent, **kwargs ):
+ target = kwargs['target']
+ for n in parent.childNodes:
+ child = self._translateNode(n,target=target)
+ if child:
+ target.appendChild(child)
+ else:
+ child = n.cloneNode(False)
+ if hasattr(child,'data'):
+ child.data = re.sub(r'\s+',' ',child.data)
+ target.appendChild(child)
+ self._translateChildren(n,target=child)
+
+ #~ Translate the given node as a description, into the description subnode
+ #~ of the target. If no description subnode is present in the target it
+ #~ is created.
+ def _translateDescription( self, node, target=None, tag='description', **kwargs ):
+ description = self._getChild(tag,root=target)
+ if not description:
+ description = target.appendChild(self._createNode(tag))
+ self._translateChildren(node,target=description)
+ return description
+
+ #~ Top level translation of: <doxygen ...>...</doxygen>,
+ #~ translates the children.
+ def _translate_doxygen( self, node ):
+ #~ print '_translate_doxygen:', node.nodeName
+ result = []
+ for n in node.childNodes:
+ newNode = self._translateNode(n)
+ if newNode:
+ result.append(newNode)
+ return result
+
+ #~ Top level translation of:
+ #~ <doxygenindex ...>
+ #~ <compound ...>
+ #~ <member ...>
+ #~ <name>...</name>
+ #~ </member>
+ #~ ...
+ #~ </compound>
+ #~ ...
+ #~ </doxygenindex>
+ #~ builds the class and symbol sections, if requested.
+ def _translate_doxygenindex( self, node ):
+ #~ print '_translate_doxygenindex:', node.nodeName
+ if self.args['index']:
+ entries = []
+ classes = []
+ #~ Accumulate all the index entries we care about.
+ for n in node.childNodes:
+ if n.nodeName == 'compound':
+ if n.getAttribute('kind') not in ('file','dir','define'):
+ cpp = self._cppName(self._getChildData('name',root=n))
+ entry = {
+ 'name' : cpp['name'],
+ 'compoundname' : cpp['compoundname'],
+ 'id' : n.getAttribute('refid')
+ }
+ if n.getAttribute('kind') in ('class','struct'):
+ classes.append(entry)
+ entries.append(entry)
+ for m in n.childNodes:
+ if m.nodeName == 'member':
+ cpp = self._cppName(self._getChildData('name',root=m))
+ entry = {
+ 'name' : cpp['name'],
+ 'compoundname' : cpp['compoundname'],
+ 'id' : n.getAttribute('refid')
+ }
+ if hasattr(m,'getAttribute') and m.getAttribute('kind') in ('class','struct'):
+ classes.append(entry)
+ entries.append(entry)
+ #~ Put them in a sensible order.
+ entries.sort(lambda x,y: cmp(x['name'].lower(),y['name'].lower()))
+ classes.sort(lambda x,y: cmp(x['name'].lower(),y['name'].lower()))
+ #~ And generate the BoostBook for them.
+ self._translate_index_(entries,target=self.section['index'])
+ self._translate_index_(classes,target=self.section['classes'])
+ return None
+
+ #~ Translate a set of index entries in the BoostBook output. The output
+ #~ is grouped into groups of the first letter of the entry names.
+ def _translate_index_(self, entries, target=None, **kwargs ):
+ i = 0
+ targetID = target.getAttribute('id')
+ while i < len(entries):
+ dividerKey = entries[i]['name'][0].upper()
+ divider = target.appendChild(self._createNode('indexdiv',id=targetID+'.'+dividerKey))
+ divider.appendChild(self._createText('title',dividerKey))
+ while i < len(entries) and dividerKey == entries[i]['name'][0].upper():
+ iename = entries[i]['name']
+ ie = divider.appendChild(self._createNode('indexentry'))
+ ie = ie.appendChild(self._createText('primaryie',iename))
+ while i < len(entries) and entries[i]['name'] == iename:
+ ie.appendChild(self.boostbook.createTextNode(' ('))
+ ie.appendChild(self._createText(
+ 'link',entries[i]['compoundname'],linkend=entries[i]['id']))
+ ie.appendChild(self.boostbook.createTextNode(')'))
+ i += 1
+
+ #~ Translate a <compounddef ...>...</compounddef>,
+ #~ by retranslating with the "kind" of compounddef.
+ def _translate_compounddef( self, node, target=None, **kwargs ):
+ return self._translateNode(node,node.getAttribute('kind'))
+
+ #~ Translate a <compounddef kind="namespace"...>...</compounddef>. For
+ #~ namespaces we just collect the information for later use as there is no
+ #~ currently namespaces are not included in the BoostBook format. In the future
+ #~ it might be good to generate a namespace index.
+ def _translate_compounddef_namespace( self, node, target=None, **kwargs ):
+ namespace = {
+ 'id' : node.getAttribute('id'),
+ 'kind' : 'namespace',
+ 'name' : self._getChildData('compoundname',root=node),
+ 'brief' : self._getChildData('briefdescription',root=node),
+ 'detailed' : self._getChildData('detaileddescription',root=node),
+ 'parsed' : False
+ }
+ if self.symbols.has_key(namespace['name']):
+ if not self.symbols[namespace['name']]['parsed']:
+ self.symbols[namespace['name']]['parsed'] = True
+ #~ for n in node.childNodes:
+ #~ if hasattr(n,'getAttribute'):
+ #~ self._translateNode(n,n.getAttribute('kind'),target=target,**kwargs)
+ else:
+ self.symbols[namespace['name']] = namespace
+ #~ self._setID(namespace['id'],namespace['name'])
+ return None
+
+ #~ Translate a <compounddef kind="class"...>...</compounddef>, which
+ #~ forwards to the kind=struct as they are the same.
+ def _translate_compounddef_class( self, node, target=None, **kwargs ):
+ return self._translate_compounddef_struct(node,tag='class',target=target,**kwargs)
+
+ #~ Translate a <compounddef kind="struct"...>...</compounddef> into:
+ #~ <header id="?" name="?">
+ #~ <struct name="?">
+ #~ ...
+ #~ </struct>
+ #~ </header>
+ def _translate_compounddef_struct( self, node, tag='struct', target=None, **kwargs ):
+ result = None
+ includes = self._getChild('includes',root=node)
+ if includes:
+ ## Add the header into the output table.
+ self._translate_compounddef_includes_(includes,includes,**kwargs)
+ ## Compounds are the declared symbols, classes, types, etc.
+ ## We add them to the symbol table, along with the partial DOM for them
+ ## so that they can be organized into the output later.
+ compoundname = self._getChildData('compoundname',root=node)
+ compoundname = self._cppName(compoundname)
+ self._setID(node.getAttribute('id'),compoundname['compoundname'])
+ struct = self._createNode(tag,name=compoundname['name'].split('::')[-1])
+ self.symbols[compoundname['compoundname']] = {
+ 'header' : includes.firstChild.data,
+ 'namespace' : compoundname['namespace'],
+ 'id' : node.getAttribute('id'),
+ 'kind' : tag,
+ 'name' : compoundname['name'],
+ 'dom' : struct
+ }
+ ## Add the children which will be the members of the struct.
+ for n in node.childNodes:
+ self._translateNode(n,target=struct,scope=compoundname['compoundname'])
+ result = struct
+ return result
+
+ #~ Translate a <compounddef ...><includes ...>...</includes></compounddef>,
+ def _translate_compounddef_includes_( self, node, target=None, **kwargs ):
+ name = node.firstChild.data
+ if not self.symbols.has_key(name):
+ self._setID(node.getAttribute('refid'),name)
+ self.symbols[name] = {
+ 'kind' : 'header',
+ 'id' : node.getAttribute('refid'),
+ 'dom' : self._createNode('header',
+ id=node.getAttribute('refid'),
+ name=name)
+ }
+ return None
+
+ #~ Translate a <basecompoundref...>...</basecompoundref> into:
+ #~ <inherit access="?">
+ #~ ...
+ #~ </inherit>
+ def _translate_basecompoundref( self, ref, target=None, **kwargs ):
+ inherit = target.appendChild(self._createNode('inherit',
+ access=ref.getAttribute('prot')))
+ self._translateChildren(ref,target=inherit)
+ return
+
+ #~ Translate:
+ #~ <templateparamlist>
+ #~ <param>
+ #~ <type>...</type>
+ #~ <declname>...</declname>
+ #~ <defname>...</defname>
+ #~ <defval>...</defval>
+ #~ </param>
+ #~ ...
+ #~ </templateparamlist>
+ #~ Into:
+ #~ <template>
+ #~ <template-type-parameter name="?" />
+ #~ <template-nontype-parameter name="?">
+ #~ <type>?</type>
+ #~ <default>?</default>
+ #~ </template-nontype-parameter>
+ #~ </template>
+ def _translate_templateparamlist( self, templateparamlist, target=None, **kwargs ):
+ template = target.appendChild(self._createNode('template'))
+ for param in templateparamlist.childNodes:
+ if param.nodeName == 'param':
+ type = self._getChildData('type',root=param)
+ defval = self._getChild('defval',root=param)
+ paramKind = None
+ if type in ('class','typename'):
+ paramKind = 'template-type-parameter'
+ else:
+ paramKind = 'template-nontype-parameter'
+ templateParam = template.appendChild(
+ self._createNode(paramKind,
+ name=self._getChildData('declname',root=param)))
+ if paramKind == 'template-nontype-parameter':
+ template_type = templateParam.appendChild(self._createNode('type'))
+ self._translate_type(
+ self._getChild('type',root=param),target=template_type)
+ if defval:
+ value = self._getChildData('ref',root=defval.firstChild)
+ if not value:
+ value = self._getData(defval)
+ templateParam.appendChild(self._createText('default',value))
+ return template
+
+ #~ Translate:
+ #~ <briefdescription>...</briefdescription>
+ #~ Into:
+ #~ <purpose>...</purpose>
+ def _translate_briefdescription( self, brief, target=None, **kwargs ):
+ self._translateDescription(brief,target=target,**kwargs)
+ return self._translateDescription(brief,target=target,tag='purpose',**kwargs)
+
+ #~ Translate:
+ #~ <detaileddescription>...</detaileddescription>
+ #~ Into:
+ #~ <description>...</description>
+ def _translate_detaileddescription( self, detailed, target=None, **kwargs ):
+ return self._translateDescription(detailed,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="?">...</sectiondef>
+ #~ With kind specific translation.
+ def _translate_sectiondef( self, sectiondef, target=None, **kwargs ):
+ self._translateNode(sectiondef,sectiondef.getAttribute('kind'),target=target,**kwargs)
+
+ #~ Translate non-function sections.
+ def _translate_sectiondef_x_( self, sectiondef, target=None, **kwargs ):
+ for n in sectiondef.childNodes:
+ if hasattr(n,'getAttribute'):
+ self._translateNode(n,n.getAttribute('kind'),target=target,**kwargs)
+ return None
+
+ #~ Translate:
+ #~ <sectiondef kind="public-type">...</sectiondef>
+ def _translate_sectiondef_public_type( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_x_(sectiondef,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-sttrib">...</sectiondef>
+ def _translate_sectiondef_public_attrib( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_x_(sectiondef,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="?-func">...</sectiondef>
+ #~ All the various function group translations end up here for which
+ #~ they are translated into:
+ #~ <method-group name="?">
+ #~ ...
+ #~ </method-group>
+ def _translate_sectiondef_func_( self, sectiondef, name='functions', target=None, **kwargs ):
+ members = target.appendChild(self._createNode('method-group',name=name))
+ for n in sectiondef.childNodes:
+ if hasattr(n,'getAttribute'):
+ self._translateNode(n,n.getAttribute('kind'),target=members,**kwargs)
+ return members
+
+ #~ Translate:
+ #~ <sectiondef kind="public-func">...</sectiondef>
+ def _translate_sectiondef_public_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='public member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-static-func">...</sectiondef>
+ def _translate_sectiondef_public_static_func( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='public static functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="protected-func">...</sectiondef>
+ def _translate_sectiondef_protected_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='protected member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="private-static-func">...</sectiondef>
+ def _translate_sectiondef_private_static_func( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='private static functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-func">...</sectiondef>
+ def _translate_sectiondef_private_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='private member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="user-defined"><header>...</header>...</sectiondef>
+ def _translate_sectiondef_user_defined( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name=self._getChildData('header', root=sectiondef),target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="typedef" id="?">
+ #~ <name>...</name>
+ #~ </memberdef>
+ #~ To:
+ #~ <typedef id="?" name="?">
+ #~ <type>...</type>
+ #~ </typedef>
+ def _translate_memberdef_typedef( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ typedef = target.appendChild(self._createNode('typedef',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ typedef_type = typedef.appendChild(self._createNode('type'))
+ self._translate_type(self._getChild('type',root=memberdef),target=typedef_type)
+ return typedef
+
+ #~ Translate:
+ #~ <memberdef kind="function" id="?" const="?" static="?" explicit="?" inline="?">
+ #~ <name>...</name>
+ #~ </memberdef>
+ #~ To:
+ #~ <method name="?" cv="?" specifiers="?">
+ #~ ...
+ #~ </method>
+ def _translate_memberdef_function( self, memberdef, target=None, scope=None, **kwargs ):
+ name = self._getChildData('name',root=memberdef)
+ self._setID(memberdef.getAttribute('id'),scope+'::'+name)
+ ## Check if we have some specific kind of method.
+ if name == scope.split('::')[-1]:
+ kind = 'constructor'
+ target = target.parentNode
+ elif name == '~'+scope.split('::')[-1]:
+ kind = 'destructor'
+ target = target.parentNode
+ elif name == 'operator=':
+ kind = 'copy-assignment'
+ target = target.parentNode
+ else:
+ kind = 'method'
+ method = target.appendChild(self._createNode(kind,
+ # id=memberdef.getAttribute('id'),
+ name=name,
+ cv=' '.join([
+ if_attribute(memberdef,'const','const','').strip()
+ ]),
+ specifiers=' '.join([
+ if_attribute(memberdef,'static','static',''),
+ if_attribute(memberdef,'explicit','explicit',''),
+ if_attribute(memberdef,'inline','inline','')
+ ]).strip()
+ ))
+ ## We iterate the children to translate each part of the function.
+ for n in memberdef.childNodes:
+ self._translateNode(memberdef,'function',n,target=method)
+ return method
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><templateparamlist>...</templateparamlist></memberdef>
+ def _translate_memberdef_function_templateparamlist(
+ self, templateparamlist, target=None, **kwargs ):
+ return self._translate_templateparamlist(templateparamlist,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><type>...</type></memberdef>
+ #~ To:
+ #~ ...<type>?</type>
+ def _translate_memberdef_function_type( self, resultType, target=None, **kwargs ):
+ methodType = self._createNode('type')
+ self._translate_type(resultType,target=methodType)
+ if methodType.hasChildNodes():
+ target.appendChild(methodType)
+ return methodType
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><briefdescription>...</briefdescription></memberdef>
+ def _translate_memberdef_function_briefdescription( self, description, target=None, **kwargs ):
+ result = self._translateDescription(description,target=target,**kwargs)
+ ## For functions if we translate the brief docs to the purpose they end up
+ ## right above the regular description. And since we just added the brief to that
+ ## on the previous line, don't bother with the repetition.
+ # result = self._translateDescription(description,target=target,tag='purpose',**kwargs)
+ return result
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><detaileddescription>...</detaileddescription></memberdef>
+ def _translate_memberdef_function_detaileddescription( self, description, target=None, **kwargs ):
+ return self._translateDescription(description,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><inbodydescription>...</inbodydescription></memberdef>
+ def _translate_memberdef_function_inbodydescription( self, description, target=None, **kwargs ):
+ return self._translateDescription(description,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><param>...</param></memberdef>
+ def _translate_memberdef_function_param( self, param, target=None, **kwargs ):
+ return self._translate_param(param,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="variable" id="?">
+ #~ <name>...</name>
+ #~ <type>...</type>
+ #~ </memberdef>
+ #~ To:
+ #~ <data-member id="?" name="?">
+ #~ <type>...</type>
+ #~ </data-member>
+ def _translate_memberdef_variable( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ data_member = target.appendChild(self._createNode('data-member',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ data_member_type = data_member.appendChild(self._createNode('type'))
+ self._translate_type(self._getChild('type',root=memberdef),target=data_member_type)
+
+ #~ Translate:
+ #~ <memberdef kind="enum" id="?">
+ #~ <name>...</name>
+ #~ ...
+ #~ </memberdef>
+ #~ To:
+ #~ <enum id="?" name="?">
+ #~ ...
+ #~ </enum>
+ def _translate_memberdef_enum( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ enum = target.appendChild(self._createNode('enum',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ for n in memberdef.childNodes:
+ self._translateNode(memberdef,'enum',n,target=enum,scope=scope,**kwargs)
+ return enum
+
+ #~ Translate:
+ #~ <memberdef kind="enum"...>
+ #~ <enumvalue id="?">
+ #~ <name>...</name>
+ #~ <initializer>...</initializer>
+ #~ </enumvalue>
+ #~ </memberdef>
+ #~ To:
+ #~ <enumvalue id="?" name="?">
+ #~ <default>...</default>
+ #~ </enumvalue>
+ def _translate_memberdef_enum_enumvalue( self, enumvalue, target=None, scope=None, **kwargs ):
+ self._setID(enumvalue.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=enumvalue))
+ value = target.appendChild(self._createNode('enumvalue',
+ id=enumvalue.getAttribute('id'),
+ name=self._getChildData('name',root=enumvalue)))
+ initializer = self._getChild('initializer',root=enumvalue)
+ if initializer:
+ self._translateChildren(initializer,
+ target=target.appendChild(self._createNode('default')))
+ return value
+
+ #~ Translate:
+ #~ <param>
+ #~ <type>...</type>
+ #~ <declname>...</declname>
+ #~ <defval>...</defval>
+ #~ </param>
+ #~ To:
+ #~ <parameter name="?">
+ #~ <paramtype>...</paramtype>
+ #~ ...
+ #~ </parameter>
+ def _translate_param( self, param, target=None, **kwargs):
+ parameter = target.appendChild(self._createNode('parameter',
+ name=self._getChildData('declname',root=param)))
+ paramtype = parameter.appendChild(self._createNode('paramtype'))
+ self._translate_type(self._getChild('type',root=param),target=paramtype)
+ defval = self._getChild('defval',root=param)
+ if defval:
+ self._translateChildren(self._getChild('defval',root=param),target=parameter)
+ return parameter
+
+ #~ Translate:
+ #~ <ref kindref="?" ...>...</ref>
+ def _translate_ref( self, ref, **kwargs ):
+ return self._translateNode(ref,ref.getAttribute('kindref'))
+
+ #~ Translate:
+ #~ <ref refid="?" kindref="compound">...</ref>
+ #~ To:
+ #~ <link linkend="?"><classname>...</classname></link>
+ def _translate_ref_compound( self, ref, **kwargs ):
+ result = self._createNode('link',linkend=ref.getAttribute('refid'))
+ classname = result.appendChild(self._createNode('classname'))
+ self._translateChildren(ref,target=classname)
+ return result
+
+ #~ Translate:
+ #~ <ref refid="?" kindref="member">...</ref>
+ #~ To:
+ #~ <link linkend="?">...</link>
+ def _translate_ref_member( self, ref, **kwargs ):
+ result = self._createNode('link',linkend=ref.getAttribute('refid'))
+ self._translateChildren(ref,target=result)
+ return result
+
+ #~ Translate:
+ #~ <type>...</type>
+ def _translate_type( self, type, target=None, **kwargs ):
+ result = self._translateChildren(type,target=target,**kwargs)
+ #~ Filter types to clean up various readability problems, most notably
+ #~ with really long types.
+ xml = target.toxml('utf-8');
+ if (
+ xml.startswith('<type>boost::mpl::') or
+ xml.startswith('<type>BOOST_PP_') or
+ re.match('<type>boost::(lazy_)?(enable|disable)_if',xml)
+ ):
+ while target.firstChild:
+ target.removeChild(target.firstChild)
+ target.appendChild(self._createText('emphasis','unspecified'))
+ return result
+
+ def _getChild( self, tag = None, id = None, name = None, root = None ):
+ if not root:
+ root = self.boostbook.documentElement
+ for n in root.childNodes:
+ found = True
+ if tag and found:
+ found = found and tag == n.nodeName
+ if id and found:
+ if n.hasAttribute('id'):
+ found = found and n.getAttribute('id') == id
+ else:
+ found = found and n.hasAttribute('id') and n.getAttribute('id') == id
+ if name and found:
+ found = found and n.hasAttribute('name') and n.getAttribute('name') == name
+ if found:
+ #~ print '--|', n
+ return n
+ return None
+
+ def _getChildData( self, tag, **kwargs ):
+ return self._getData(self._getChild(tag,**kwargs),**kwargs)
+
+ def _getData( self, node, **kwargs ):
+ if node:
+ text = self._getChild('#text',root=node)
+ if text:
+ return text.data.strip()
+ return ''
+
+ def _cppName( self, type ):
+ parts = re.search('^([^<]+)[<]?(.*)[>]?$',type.strip().strip(':'))
+ result = {
+ 'compoundname' : parts.group(1),
+ 'namespace' : parts.group(1).split('::')[0:-1],
+ 'name' : parts.group(1).split('::')[-1],
+ 'specialization' : parts.group(2)
+ }
+ if result['namespace'] and len(result['namespace']) > 0:
+ namespace = '::'.join(result['namespace'])
+ while (
+ len(result['namespace']) > 0 and (
+ not self.symbols.has_key(namespace) or
+ self.symbols[namespace]['kind'] != 'namespace')
+ ):
+ result['name'] = result['namespace'].pop()+'::'+result['name']
+ namespace = '::'.join(result['namespace'])
+ return result
+
+ def _createNode( self, tag, **kwargs ):
+ result = self.boostbook.createElement(tag)
+ for k in kwargs.keys():
+ if kwargs[k] != '':
+ if k == 'id':
+ result.setAttribute('id',kwargs[k])
+ else:
+ result.setAttribute(k,kwargs[k])
+ return result
+
+ def _createText( self, tag, data, **kwargs ):
+ result = self._createNode(tag,**kwargs)
+ data = data.strip()
+ if len(data) > 0:
+ result.appendChild(self.boostbook.createTextNode(data))
+ return result
+
+
+def main( xmldir=None, output=None, id=None, title=None, index=False ):
+ #~ print '--- main: xmldir = %s, output = %s' % (xmldir,output)
+
+ input = glob.glob( os.path.abspath( os.path.join( xmldir, "*.xml" ) ) )
+ input.sort
+ translator = Doxygen2BoostBook(id=id, title=title, index=index)
+ #~ Feed in the namespaces first to build up the set of namespaces
+ #~ and definitions so that lookup is unambiguous when reading in the definitions.
+ namespace_files = filter(
+ lambda x:
+ os.path.basename(x).startswith('namespace'),
+ input)
+ decl_files = filter(
+ lambda x:
+ not os.path.basename(x).startswith('namespace') and not os.path.basename(x).startswith('_'),
+ input)
+ for dox in namespace_files:
+ #~ print '--|',os.path.basename(dox)
+ translator.addDox(xml.dom.minidom.parse(dox))
+ for dox in decl_files:
+ #~ print '--|',os.path.basename(dox)
+ translator.addDox(xml.dom.minidom.parse(dox))
+
+ if output:
+ output = open(output,'w')
+ else:
+ output = sys.stdout
+ if output:
+ output.write(translator.tostring())
+
+
+main( **get_args() )