1*7f2fe78bSCy Schubert''' 2*7f2fe78bSCy Schubert Copyright 2011 by the Massachusetts 3*7f2fe78bSCy Schubert Institute of Technology. All Rights Reserved. 4*7f2fe78bSCy Schubert 5*7f2fe78bSCy Schubert Export of this software from the United States of America may 6*7f2fe78bSCy Schubert require a specific license from the United States Government. 7*7f2fe78bSCy Schubert It is the responsibility of any person or organization contemplating 8*7f2fe78bSCy Schubert export to obtain such a license before exporting. 9*7f2fe78bSCy Schubert 10*7f2fe78bSCy Schubert WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 11*7f2fe78bSCy Schubert distribute this software and its documentation for any purpose and 12*7f2fe78bSCy Schubert without fee is hereby granted, provided that the above copyright 13*7f2fe78bSCy Schubert notice appear in all copies and that both that copyright notice and 14*7f2fe78bSCy Schubert this permission notice appear in supporting documentation, and that 15*7f2fe78bSCy Schubert the name of M.I.T. not be used in advertising or publicity pertaining 16*7f2fe78bSCy Schubert to distribution of the software without specific, written prior 17*7f2fe78bSCy Schubert permission. Furthermore if you modify this software you must label 18*7f2fe78bSCy Schubert your software as modified software and not distribute it in such a 19*7f2fe78bSCy Schubert fashion that it might be confused with the original M.I.T. software. 20*7f2fe78bSCy Schubert M.I.T. makes no representations about the suitability of 21*7f2fe78bSCy Schubert this software for any purpose. It is provided "as is" without express 22*7f2fe78bSCy Schubert or implied warranty. 23*7f2fe78bSCy Schubert''' 24*7f2fe78bSCy Schubertimport sys 25*7f2fe78bSCy Schubertimport re 26*7f2fe78bSCy Schubert 27*7f2fe78bSCy Schubertfrom collections import defaultdict 28*7f2fe78bSCy Schubertfrom xml.sax import make_parser 29*7f2fe78bSCy Schubertfrom xml.sax.handler import ContentHandler 30*7f2fe78bSCy Schubertfrom docmodel import * 31*7f2fe78bSCy Schubert 32*7f2fe78bSCy Schubertexclude_funcs = ['krb5_free_octet_data'] 33*7f2fe78bSCy Schubert 34*7f2fe78bSCy Schubertclass DocNode(object): 35*7f2fe78bSCy Schubert """ 36*7f2fe78bSCy Schubert Represents the structure of xml node. 37*7f2fe78bSCy Schubert """ 38*7f2fe78bSCy Schubert def __init__(self, name): 39*7f2fe78bSCy Schubert """ 40*7f2fe78bSCy Schubert @param node: name - the name of a node. 41*7f2fe78bSCy Schubert @param attributes: a dictionary populated with attributes of a node 42*7f2fe78bSCy Schubert @param children: a dictionary with lists of children nodes. Nodes 43*7f2fe78bSCy Schubert in lists are ordered as they appear in a document. 44*7f2fe78bSCy Schubert @param content: a content of xml node represented as a list of 45*7f2fe78bSCy Schubert tuples [(type,value)] with type = ['char'|'element']. 46*7f2fe78bSCy Schubert If type is 'char' then the value is a character string otherwise 47*7f2fe78bSCy Schubert it is a reference to a child node. 48*7f2fe78bSCy Schubert """ 49*7f2fe78bSCy Schubert self.name = name 50*7f2fe78bSCy Schubert self.content = list() 51*7f2fe78bSCy Schubert self.attributes = dict() 52*7f2fe78bSCy Schubert self.children = defaultdict(list) 53*7f2fe78bSCy Schubert 54*7f2fe78bSCy Schubert def walk(self, decorators, sub_ws, stack=[]): 55*7f2fe78bSCy Schubert result = list() 56*7f2fe78bSCy Schubert decorator = decorators.get(self.name, decorators['default']) 57*7f2fe78bSCy Schubert stack.append(decorators['default']) 58*7f2fe78bSCy Schubert decorators['default'] = decorator 59*7f2fe78bSCy Schubert 60*7f2fe78bSCy Schubert for (obj_type,obj) in self.content: 61*7f2fe78bSCy Schubert if obj_type == 'char': 62*7f2fe78bSCy Schubert if obj != '': 63*7f2fe78bSCy Schubert result.append(obj) 64*7f2fe78bSCy Schubert else: 65*7f2fe78bSCy Schubert partial = obj.walk(decorators,1, stack) 66*7f2fe78bSCy Schubert if partial is not None: 67*7f2fe78bSCy Schubert result.append(' %s ' % partial) 68*7f2fe78bSCy Schubert decorators['default'] = stack.pop() 69*7f2fe78bSCy Schubert result = decorator(self, ''.join(result)) 70*7f2fe78bSCy Schubert if result is not None: 71*7f2fe78bSCy Schubert if sub_ws == 1: 72*7f2fe78bSCy Schubert result = re.sub(r'[ ]+', r' ', result) 73*7f2fe78bSCy Schubert else: 74*7f2fe78bSCy Schubert result = result.strip() 75*7f2fe78bSCy Schubert 76*7f2fe78bSCy Schubert return result 77*7f2fe78bSCy Schubert 78*7f2fe78bSCy Schubert def getContent(self): 79*7f2fe78bSCy Schubert decorators = {'default': lambda node,value: value} 80*7f2fe78bSCy Schubert result = self.walk(decorators, 1) 81*7f2fe78bSCy Schubert if len(result) == 0: 82*7f2fe78bSCy Schubert result = None 83*7f2fe78bSCy Schubert 84*7f2fe78bSCy Schubert return result 85*7f2fe78bSCy Schubert 86*7f2fe78bSCy Schubert def __repr__(self): 87*7f2fe78bSCy Schubert result = ['Content: %s' % self.content] 88*7f2fe78bSCy Schubert 89*7f2fe78bSCy Schubert for (key,value) in self.attributes.iteritems(): 90*7f2fe78bSCy Schubert result.append('Attr: %s = %s' % (key,value)) 91*7f2fe78bSCy Schubert for (key,value) in self.children.iteritems(): 92*7f2fe78bSCy Schubert result.append('Child: %s,%i' % (key,len(value))) 93*7f2fe78bSCy Schubert 94*7f2fe78bSCy Schubert return '\n'.join(result) 95*7f2fe78bSCy Schubert 96*7f2fe78bSCy Schubertclass DoxyContenHandler(ContentHandler): 97*7f2fe78bSCy Schubert def __init__(self, builder): 98*7f2fe78bSCy Schubert self.builder = builder 99*7f2fe78bSCy Schubert self.counters = defaultdict(int) 100*7f2fe78bSCy Schubert self._nodes = None 101*7f2fe78bSCy Schubert self._current = None 102*7f2fe78bSCy Schubert 103*7f2fe78bSCy Schubert def startDocument(self): 104*7f2fe78bSCy Schubert pass 105*7f2fe78bSCy Schubert 106*7f2fe78bSCy Schubert def endDocument(self): 107*7f2fe78bSCy Schubert import sys 108*7f2fe78bSCy Schubert 109*7f2fe78bSCy Schubert def startElement(self, name, attrs): 110*7f2fe78bSCy Schubert if name == self.builder.toplevel: 111*7f2fe78bSCy Schubert self._nodes = [] 112*7f2fe78bSCy Schubert 113*7f2fe78bSCy Schubert if name == 'memberdef': 114*7f2fe78bSCy Schubert kind = attrs.get('kind') 115*7f2fe78bSCy Schubert if kind is None: 116*7f2fe78bSCy Schubert raise ValueError('Kind is not defined') 117*7f2fe78bSCy Schubert self.counters[kind] += 1 118*7f2fe78bSCy Schubert 119*7f2fe78bSCy Schubert if self._nodes is None: 120*7f2fe78bSCy Schubert return 121*7f2fe78bSCy Schubert 122*7f2fe78bSCy Schubert node = DocNode(name) 123*7f2fe78bSCy Schubert for (key,value) in attrs.items(): 124*7f2fe78bSCy Schubert node.attributes[key] = value 125*7f2fe78bSCy Schubert if self._current is not None: 126*7f2fe78bSCy Schubert self._current.children[name].append(node) 127*7f2fe78bSCy Schubert self._nodes.append(self._current) 128*7f2fe78bSCy Schubert self._current = node 129*7f2fe78bSCy Schubert 130*7f2fe78bSCy Schubert def characters(self, content): 131*7f2fe78bSCy Schubert 132*7f2fe78bSCy Schubert if self._current is not None: 133*7f2fe78bSCy Schubert self._current.content.append(('char',content.strip())) 134*7f2fe78bSCy Schubert 135*7f2fe78bSCy Schubert def endElement(self, name): 136*7f2fe78bSCy Schubert if name == self.builder.toplevel: 137*7f2fe78bSCy Schubert assert(len(self._nodes) == 0) 138*7f2fe78bSCy Schubert self._nodes = None 139*7f2fe78bSCy Schubert self.builder.document.append(self._current) 140*7f2fe78bSCy Schubert self._current = None 141*7f2fe78bSCy Schubert else: 142*7f2fe78bSCy Schubert if self._nodes is not None: 143*7f2fe78bSCy Schubert node = self._current 144*7f2fe78bSCy Schubert self._current = self._nodes.pop() 145*7f2fe78bSCy Schubert self._current.content.append(('element',node)) 146*7f2fe78bSCy Schubert 147*7f2fe78bSCy Schubert 148*7f2fe78bSCy Schubertclass XML2AST(object): 149*7f2fe78bSCy Schubert """ 150*7f2fe78bSCy Schubert Translates XML document into Abstract Syntax Tree like representation 151*7f2fe78bSCy Schubert The content of document is stored in self.document 152*7f2fe78bSCy Schubert """ 153*7f2fe78bSCy Schubert def __init__(self, xmlpath, toplevel='doxygen'): 154*7f2fe78bSCy Schubert self.document = list() 155*7f2fe78bSCy Schubert self.toplevel = toplevel 156*7f2fe78bSCy Schubert self.parser = make_parser() 157*7f2fe78bSCy Schubert handler = DoxyContenHandler(self) 158*7f2fe78bSCy Schubert self.parser.setContentHandler(handler) 159*7f2fe78bSCy Schubert filename = 'krb5_8hin.xml' 160*7f2fe78bSCy Schubert filepath = '%s/%s' % (xmlpath,filename) 161*7f2fe78bSCy Schubert self.parser.parse(open(filepath,'r')) 162*7f2fe78bSCy Schubert 163*7f2fe78bSCy Schubert 164*7f2fe78bSCy Schubertclass DoxyFuncs(XML2AST): 165*7f2fe78bSCy Schubert def __init__(self, path): 166*7f2fe78bSCy Schubert super(DoxyFuncs, self).__init__(path,toplevel='memberdef') 167*7f2fe78bSCy Schubert self.objects = list() 168*7f2fe78bSCy Schubert 169*7f2fe78bSCy Schubert def run(self): 170*7f2fe78bSCy Schubert for node in self.document: 171*7f2fe78bSCy Schubert self.process(node) 172*7f2fe78bSCy Schubert 173*7f2fe78bSCy Schubert def process(self, node): 174*7f2fe78bSCy Schubert node_type = node.attributes['kind'] 175*7f2fe78bSCy Schubert if node_type == 'function': 176*7f2fe78bSCy Schubert data = self._process_function_node(node) 177*7f2fe78bSCy Schubert else: 178*7f2fe78bSCy Schubert return 179*7f2fe78bSCy Schubert 180*7f2fe78bSCy Schubert if 'name' in data and data['name'] in exclude_funcs: 181*7f2fe78bSCy Schubert return 182*7f2fe78bSCy Schubert self.objects.append(DocModel(**data)) 183*7f2fe78bSCy Schubert 184*7f2fe78bSCy Schubert def save(self, templates, target_dir): 185*7f2fe78bSCy Schubert for obj in self.objects: 186*7f2fe78bSCy Schubert template_path = templates[obj.category] 187*7f2fe78bSCy Schubert outpath = '%s/%s.rst' % (target_dir,obj.name) 188*7f2fe78bSCy Schubert obj.save(outpath, template_path) 189*7f2fe78bSCy Schubert 190*7f2fe78bSCy Schubert 191*7f2fe78bSCy Schubert def _process_function_node(self, node): 192*7f2fe78bSCy Schubert f_name = node.children['name'][0].getContent() 193*7f2fe78bSCy Schubert f_Id = node.attributes['id'] 194*7f2fe78bSCy Schubert f_ret_type = self._process_type_node(node.children['type'][0]) 195*7f2fe78bSCy Schubert f_brief = node.children['briefdescription'][0].getContent() 196*7f2fe78bSCy Schubert f_detailed = node.children['detaileddescription'][0] 197*7f2fe78bSCy Schubert detailed_description = self._process_description_node(f_detailed) 198*7f2fe78bSCy Schubert return_value_description = self._process_return_value_description(f_detailed) 199*7f2fe78bSCy Schubert retval_description = self._process_retval_description(f_detailed) 200*7f2fe78bSCy Schubert warning_description = self._process_warning_description(f_detailed) 201*7f2fe78bSCy Schubert seealso_description = self._process_seealso_description(f_detailed) 202*7f2fe78bSCy Schubert notes_description = self._process_notes_description(f_detailed) 203*7f2fe78bSCy Schubert f_version = self._process_version_description(f_detailed) 204*7f2fe78bSCy Schubert deprecated_description = self._process_deprecated_description(f_detailed) 205*7f2fe78bSCy Schubert param_description_map = self.process_parameter_description(f_detailed) 206*7f2fe78bSCy Schubert f_definition = node.children['definition'][0].getContent() 207*7f2fe78bSCy Schubert f_argsstring = node.children['argsstring'][0].getContent() 208*7f2fe78bSCy Schubert 209*7f2fe78bSCy Schubert function_descr = {'category': 'function', 210*7f2fe78bSCy Schubert 'name': f_name, 211*7f2fe78bSCy Schubert 'Id': f_Id, 212*7f2fe78bSCy Schubert 'return_type': f_ret_type[1], 213*7f2fe78bSCy Schubert 'return_description': return_value_description, 214*7f2fe78bSCy Schubert 'retval_description': retval_description, 215*7f2fe78bSCy Schubert 'sa_description': seealso_description, 216*7f2fe78bSCy Schubert 'warn_description': warning_description, 217*7f2fe78bSCy Schubert 'notes_description': notes_description, 218*7f2fe78bSCy Schubert 'short_description': f_brief, 219*7f2fe78bSCy Schubert 'version_num': f_version, 220*7f2fe78bSCy Schubert 'long_description': detailed_description, 221*7f2fe78bSCy Schubert 'deprecated_description': deprecated_description, 222*7f2fe78bSCy Schubert 'parameters': list()} 223*7f2fe78bSCy Schubert 224*7f2fe78bSCy Schubert parameters = function_descr['parameters'] 225*7f2fe78bSCy Schubert for (i,p) in enumerate(node.children['param']): 226*7f2fe78bSCy Schubert type_node = p.children['type'][0] 227*7f2fe78bSCy Schubert p_type = self._process_type_node(type_node) 228*7f2fe78bSCy Schubert if p_type[1].find('...') > -1 : 229*7f2fe78bSCy Schubert p_name = '' 230*7f2fe78bSCy Schubert else: 231*7f2fe78bSCy Schubert p_name = None 232*7f2fe78bSCy Schubert p_name_node = p.children.get('declname') 233*7f2fe78bSCy Schubert if p_name_node is not None: 234*7f2fe78bSCy Schubert p_name = p_name_node[0].getContent() 235*7f2fe78bSCy Schubert (p_direction,p_descr) = param_description_map.get(p_name,(None,None)) 236*7f2fe78bSCy Schubert 237*7f2fe78bSCy Schubert param_descr = {'seqno': i, 238*7f2fe78bSCy Schubert 'name': p_name, 239*7f2fe78bSCy Schubert 'direction': p_direction, 240*7f2fe78bSCy Schubert 'type': p_type[1], 241*7f2fe78bSCy Schubert 'typeId': p_type[0], 242*7f2fe78bSCy Schubert 'description': p_descr} 243*7f2fe78bSCy Schubert parameters.append(param_descr) 244*7f2fe78bSCy Schubert result = Function(**function_descr) 245*7f2fe78bSCy Schubert print(result, file=self.tmp) 246*7f2fe78bSCy Schubert 247*7f2fe78bSCy Schubert return function_descr 248*7f2fe78bSCy Schubert 249*7f2fe78bSCy Schubert def _process_type_node(self, type_node): 250*7f2fe78bSCy Schubert """ 251*7f2fe78bSCy Schubert Type node has form 252*7f2fe78bSCy Schubert <type>type_string</type> 253*7f2fe78bSCy Schubert for build in types and 254*7f2fe78bSCy Schubert <type> 255*7f2fe78bSCy Schubert <ref refid='reference',kindref='member|compound'> 256*7f2fe78bSCy Schubert 'type_name' 257*7f2fe78bSCy Schubert </ref></type> 258*7f2fe78bSCy Schubert postfix (ex. *, **m, etc.) 259*7f2fe78bSCy Schubert </type> 260*7f2fe78bSCy Schubert for user defined types. 261*7f2fe78bSCy Schubert """ 262*7f2fe78bSCy Schubert type_ref_node = type_node.children.get('ref') 263*7f2fe78bSCy Schubert if type_ref_node is not None: 264*7f2fe78bSCy Schubert p_type_id = type_ref_node[0].attributes['refid'] 265*7f2fe78bSCy Schubert else: 266*7f2fe78bSCy Schubert p_type_id = None 267*7f2fe78bSCy Schubert p_type = type_node.getContent() 268*7f2fe78bSCy Schubert # remove some macros 269*7f2fe78bSCy Schubert p_type = re.sub('KRB5_ATTR_DEPRECATED', '', p_type) 270*7f2fe78bSCy Schubert p_type = re.sub('KRB5_CALLCONV_C', '', p_type) 271*7f2fe78bSCy Schubert p_type = re.sub('KRB5_CALLCONV_WRONG', '', p_type) 272*7f2fe78bSCy Schubert p_type = re.sub('KRB5_CALLCONV', '', p_type) 273*7f2fe78bSCy Schubert p_type = p_type.strip() 274*7f2fe78bSCy Schubert 275*7f2fe78bSCy Schubert return (p_type_id, p_type) 276*7f2fe78bSCy Schubert 277*7f2fe78bSCy Schubert def _process_description_node(self, node): 278*7f2fe78bSCy Schubert """ 279*7f2fe78bSCy Schubert Description node is comprised of <para>...</para> sections 280*7f2fe78bSCy Schubert """ 281*7f2fe78bSCy Schubert para = node.children.get('para') 282*7f2fe78bSCy Schubert result = list() 283*7f2fe78bSCy Schubert if para is not None: 284*7f2fe78bSCy Schubert decorators = {'default': self.paragraph_content_decorator} 285*7f2fe78bSCy Schubert for e in para: 286*7f2fe78bSCy Schubert result.append(str(e.walk(decorators, 1))) 287*7f2fe78bSCy Schubert result.append('\n') 288*7f2fe78bSCy Schubert result = '\n'.join(result) 289*7f2fe78bSCy Schubert 290*7f2fe78bSCy Schubert return result 291*7f2fe78bSCy Schubert 292*7f2fe78bSCy Schubert def return_value_description_decorator(self, node, value): 293*7f2fe78bSCy Schubert if node.name == 'simplesect': 294*7f2fe78bSCy Schubert if node.attributes['kind'] == 'return': 295*7f2fe78bSCy Schubert cont = set() 296*7f2fe78bSCy Schubert cont = node.getContent() 297*7f2fe78bSCy Schubert return value 298*7f2fe78bSCy Schubert else: 299*7f2fe78bSCy Schubert return None 300*7f2fe78bSCy Schubert 301*7f2fe78bSCy Schubert def paragraph_content_decorator(self, node, value): 302*7f2fe78bSCy Schubert if node.name == 'para': 303*7f2fe78bSCy Schubert return value + '\n' 304*7f2fe78bSCy Schubert elif node.name == 'simplesect': 305*7f2fe78bSCy Schubert if node.attributes['kind'] == 'return': 306*7f2fe78bSCy Schubert return None 307*7f2fe78bSCy Schubert elif node.name == 'ref': 308*7f2fe78bSCy Schubert if value.find('()') >= 0: 309*7f2fe78bSCy Schubert # functions 310*7f2fe78bSCy Schubert return ':c:func:' + '`' + value + '`' 311*7f2fe78bSCy Schubert else: 312*7f2fe78bSCy Schubert # macro's 313*7f2fe78bSCy Schubert return ':data:' + '`' + value + '`' 314*7f2fe78bSCy Schubert elif node.name == 'emphasis': 315*7f2fe78bSCy Schubert return '*' + value + '*' 316*7f2fe78bSCy Schubert elif node.name == 'itemizedlist': 317*7f2fe78bSCy Schubert return '\n' + value 318*7f2fe78bSCy Schubert elif node.name == 'listitem': 319*7f2fe78bSCy Schubert return '\n\t - ' + value + '\n' 320*7f2fe78bSCy Schubert elif node.name == 'computeroutput': 321*7f2fe78bSCy Schubert return '**' + value + '**' 322*7f2fe78bSCy Schubert else: 323*7f2fe78bSCy Schubert return None 324*7f2fe78bSCy Schubert 325*7f2fe78bSCy Schubert def parameter_name_decorator(self, node, value): 326*7f2fe78bSCy Schubert if node.name == 'parametername': 327*7f2fe78bSCy Schubert direction = node.attributes.get('direction') 328*7f2fe78bSCy Schubert if direction is not None: 329*7f2fe78bSCy Schubert value = '%s:%s' % (value,direction) 330*7f2fe78bSCy Schubert return value 331*7f2fe78bSCy Schubert 332*7f2fe78bSCy Schubert elif node.name == 'parameterdescription': 333*7f2fe78bSCy Schubert return None 334*7f2fe78bSCy Schubert else: 335*7f2fe78bSCy Schubert return value 336*7f2fe78bSCy Schubert 337*7f2fe78bSCy Schubert def parameter_description_decorator(self, node, value): 338*7f2fe78bSCy Schubert if node.name == 'parameterdescription': 339*7f2fe78bSCy Schubert return value 340*7f2fe78bSCy Schubert elif node.name == 'parametername': 341*7f2fe78bSCy Schubert return None 342*7f2fe78bSCy Schubert else: 343*7f2fe78bSCy Schubert return value 344*7f2fe78bSCy Schubert 345*7f2fe78bSCy Schubert def process_parameter_description(self, node): 346*7f2fe78bSCy Schubert """ 347*7f2fe78bSCy Schubert Parameter descriptions reside inside detailed description section. 348*7f2fe78bSCy Schubert """ 349*7f2fe78bSCy Schubert para = node.children.get('para') 350*7f2fe78bSCy Schubert result = dict() 351*7f2fe78bSCy Schubert if para is not None: 352*7f2fe78bSCy Schubert for e in para: 353*7f2fe78bSCy Schubert 354*7f2fe78bSCy Schubert param_list = e.children.get('parameterlist') 355*7f2fe78bSCy Schubert if param_list is None: 356*7f2fe78bSCy Schubert continue 357*7f2fe78bSCy Schubert param_items = param_list[0].children.get('parameteritem') 358*7f2fe78bSCy Schubert if param_items is None: 359*7f2fe78bSCy Schubert continue 360*7f2fe78bSCy Schubert for it in param_items: 361*7f2fe78bSCy Schubert decorators = {'default': self.parameter_name_decorator} 362*7f2fe78bSCy Schubert direction = None 363*7f2fe78bSCy Schubert name = it.walk(decorators,0).split(':') 364*7f2fe78bSCy Schubert if len(name) == 2: 365*7f2fe78bSCy Schubert direction = name[1] 366*7f2fe78bSCy Schubert 367*7f2fe78bSCy Schubert decorators = {'default': self.parameter_description_decorator, 368*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 369*7f2fe78bSCy Schubert description = it.walk(decorators, 0) 370*7f2fe78bSCy Schubert result[name[0]] = (direction,description) 371*7f2fe78bSCy Schubert return result 372*7f2fe78bSCy Schubert 373*7f2fe78bSCy Schubert 374*7f2fe78bSCy Schubert def _process_return_value_description(self, node): 375*7f2fe78bSCy Schubert result = None 376*7f2fe78bSCy Schubert ret = list() 377*7f2fe78bSCy Schubert 378*7f2fe78bSCy Schubert para = node.children.get('para') 379*7f2fe78bSCy Schubert if para is not None: 380*7f2fe78bSCy Schubert for p in para: 381*7f2fe78bSCy Schubert simplesect_list = p.children.get('simplesect') 382*7f2fe78bSCy Schubert if simplesect_list is None: 383*7f2fe78bSCy Schubert continue 384*7f2fe78bSCy Schubert for it in simplesect_list: 385*7f2fe78bSCy Schubert decorators = {'default': self.return_value_description_decorator, 386*7f2fe78bSCy Schubert 'para': self.parameter_name_decorator} 387*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 388*7f2fe78bSCy Schubert if result is not None: 389*7f2fe78bSCy Schubert ret.append(result) 390*7f2fe78bSCy Schubert return ret 391*7f2fe78bSCy Schubert 392*7f2fe78bSCy Schubert 393*7f2fe78bSCy Schubert def _process_retval_description(self, node): 394*7f2fe78bSCy Schubert """ 395*7f2fe78bSCy Schubert retval descriptions reside inside detailed description section. 396*7f2fe78bSCy Schubert """ 397*7f2fe78bSCy Schubert para = node.children.get('para') 398*7f2fe78bSCy Schubert 399*7f2fe78bSCy Schubert result = None 400*7f2fe78bSCy Schubert ret = list() 401*7f2fe78bSCy Schubert if para is not None: 402*7f2fe78bSCy Schubert 403*7f2fe78bSCy Schubert for e in para: 404*7f2fe78bSCy Schubert param_list = e.children.get('parameterlist') 405*7f2fe78bSCy Schubert if param_list is None: 406*7f2fe78bSCy Schubert continue 407*7f2fe78bSCy Schubert for p in param_list: 408*7f2fe78bSCy Schubert kind = p.attributes['kind'] 409*7f2fe78bSCy Schubert if kind == 'retval': 410*7f2fe78bSCy Schubert 411*7f2fe78bSCy Schubert param_items = p.children.get('parameteritem') 412*7f2fe78bSCy Schubert if param_items is None: 413*7f2fe78bSCy Schubert continue 414*7f2fe78bSCy Schubert 415*7f2fe78bSCy Schubert 416*7f2fe78bSCy Schubert for it in param_items: 417*7f2fe78bSCy Schubert param_descr = it.children.get('parameterdescription') 418*7f2fe78bSCy Schubert if param_descr is not None: 419*7f2fe78bSCy Schubert val = param_descr[0].children.get('para') 420*7f2fe78bSCy Schubert 421*7f2fe78bSCy Schubert if val is not None: 422*7f2fe78bSCy Schubert val_descr = val[0].getContent() 423*7f2fe78bSCy Schubert 424*7f2fe78bSCy Schubert else: 425*7f2fe78bSCy Schubert val_descr ='' 426*7f2fe78bSCy Schubert 427*7f2fe78bSCy Schubert decorators = {'default': self.parameter_name_decorator} 428*7f2fe78bSCy Schubert 429*7f2fe78bSCy Schubert name = it.walk(decorators, 1).split(':') 430*7f2fe78bSCy Schubert 431*7f2fe78bSCy Schubert val = name[0] 432*7f2fe78bSCy Schubert result = " %s %s" % (val, val_descr) 433*7f2fe78bSCy Schubert ret.append (result) 434*7f2fe78bSCy Schubert return ret 435*7f2fe78bSCy Schubert 436*7f2fe78bSCy Schubert def return_warning_decorator(self, node, value): 437*7f2fe78bSCy Schubert if node.name == 'simplesect': 438*7f2fe78bSCy Schubert if node.attributes['kind'] == 'warning': 439*7f2fe78bSCy Schubert return value 440*7f2fe78bSCy Schubert else: 441*7f2fe78bSCy Schubert return None 442*7f2fe78bSCy Schubert 443*7f2fe78bSCy Schubert def _process_warning_description(self, node): 444*7f2fe78bSCy Schubert result = None 445*7f2fe78bSCy Schubert para = node.children.get('para') 446*7f2fe78bSCy Schubert if para is not None: 447*7f2fe78bSCy Schubert for p in para: 448*7f2fe78bSCy Schubert simplesect_list = p.children.get('simplesect') 449*7f2fe78bSCy Schubert if simplesect_list is None: 450*7f2fe78bSCy Schubert continue 451*7f2fe78bSCy Schubert for it in simplesect_list: 452*7f2fe78bSCy Schubert decorators = {'default': self.return_warning_decorator, 453*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 454*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 455*7f2fe78bSCy Schubert # Assuming that only one Warning per function 456*7f2fe78bSCy Schubert if result is not None: 457*7f2fe78bSCy Schubert return result 458*7f2fe78bSCy Schubert return result 459*7f2fe78bSCy Schubert 460*7f2fe78bSCy Schubert def return_seealso_decorator(self, node, value): 461*7f2fe78bSCy Schubert if node.name == 'simplesect': 462*7f2fe78bSCy Schubert if node.attributes['kind'] == 'see': 463*7f2fe78bSCy Schubert return value 464*7f2fe78bSCy Schubert else: 465*7f2fe78bSCy Schubert return None 466*7f2fe78bSCy Schubert 467*7f2fe78bSCy Schubert def _process_seealso_description(self, node): 468*7f2fe78bSCy Schubert result = None 469*7f2fe78bSCy Schubert para = node.children.get('para') 470*7f2fe78bSCy Schubert if para is not None: 471*7f2fe78bSCy Schubert for p in para: 472*7f2fe78bSCy Schubert simplesect_list = p.children.get('simplesect') 473*7f2fe78bSCy Schubert if simplesect_list is None: 474*7f2fe78bSCy Schubert continue 475*7f2fe78bSCy Schubert for it in simplesect_list: 476*7f2fe78bSCy Schubert decorators = {'default': self.return_seealso_decorator, 477*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 478*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 479*7f2fe78bSCy Schubert return result 480*7f2fe78bSCy Schubert 481*7f2fe78bSCy Schubert def return_version_decorator(self, node, value): 482*7f2fe78bSCy Schubert if node.name == 'simplesect': 483*7f2fe78bSCy Schubert if node.attributes['kind'] == 'version': 484*7f2fe78bSCy Schubert return value 485*7f2fe78bSCy Schubert else: 486*7f2fe78bSCy Schubert return None 487*7f2fe78bSCy Schubert 488*7f2fe78bSCy Schubert def _process_version_description(self, node): 489*7f2fe78bSCy Schubert result = None 490*7f2fe78bSCy Schubert para = node.children.get('para') 491*7f2fe78bSCy Schubert if para is not None: 492*7f2fe78bSCy Schubert for p in para: 493*7f2fe78bSCy Schubert simplesect_list = p.children.get('simplesect') 494*7f2fe78bSCy Schubert if simplesect_list is None: 495*7f2fe78bSCy Schubert continue 496*7f2fe78bSCy Schubert for it in simplesect_list: 497*7f2fe78bSCy Schubert decorators = {'default': self.return_version_decorator, 498*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 499*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 500*7f2fe78bSCy Schubert if result is not None: 501*7f2fe78bSCy Schubert return result 502*7f2fe78bSCy Schubert return result 503*7f2fe78bSCy Schubert 504*7f2fe78bSCy Schubert def return_notes_decorator(self, node, value): 505*7f2fe78bSCy Schubert if node.name == 'simplesect': 506*7f2fe78bSCy Schubert if node.attributes['kind'] == 'note': 507*7f2fe78bSCy Schubert # We indent notes with an extra tab. Do it for all paragraphs. 508*7f2fe78bSCy Schubert return value.replace("\n ", "\n\n\t "); 509*7f2fe78bSCy Schubert else: 510*7f2fe78bSCy Schubert return None 511*7f2fe78bSCy Schubert 512*7f2fe78bSCy Schubert def _process_notes_description(self, node): 513*7f2fe78bSCy Schubert result = None 514*7f2fe78bSCy Schubert para = node.children.get('para') 515*7f2fe78bSCy Schubert if para is not None: 516*7f2fe78bSCy Schubert for p in para: 517*7f2fe78bSCy Schubert simplesect_list = p.children.get('simplesect') 518*7f2fe78bSCy Schubert if simplesect_list is None: 519*7f2fe78bSCy Schubert continue 520*7f2fe78bSCy Schubert for it in simplesect_list: 521*7f2fe78bSCy Schubert decorators = {'default': self.return_notes_decorator, 522*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 523*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 524*7f2fe78bSCy Schubert if result is not None: 525*7f2fe78bSCy Schubert return result 526*7f2fe78bSCy Schubert return result 527*7f2fe78bSCy Schubert 528*7f2fe78bSCy Schubert def return_deprecated_decorator(self, node, value): 529*7f2fe78bSCy Schubert if node.name == 'xrefsect': 530*7f2fe78bSCy Schubert if node.attributes['id'].find('deprecated_') > -1: 531*7f2fe78bSCy Schubert xreftitle = node.children.get('xreftitle') 532*7f2fe78bSCy Schubert if xreftitle[0] is not None: 533*7f2fe78bSCy Schubert xrefdescr = node.children.get('xrefdescription') 534*7f2fe78bSCy Schubert deprecated_descr = "DEPRECATED %s" % xrefdescr[0].getContent() 535*7f2fe78bSCy Schubert return deprecated_descr 536*7f2fe78bSCy Schubert else: 537*7f2fe78bSCy Schubert return None 538*7f2fe78bSCy Schubert 539*7f2fe78bSCy Schubert def _process_deprecated_description(self, node): 540*7f2fe78bSCy Schubert result = None 541*7f2fe78bSCy Schubert para = node.children.get('para') 542*7f2fe78bSCy Schubert if para is not None: 543*7f2fe78bSCy Schubert for p in para: 544*7f2fe78bSCy Schubert xrefsect_list = p.children.get('xrefsect') 545*7f2fe78bSCy Schubert if xrefsect_list is None: 546*7f2fe78bSCy Schubert continue 547*7f2fe78bSCy Schubert for it in xrefsect_list: 548*7f2fe78bSCy Schubert decorators = {'default': self.return_deprecated_decorator, 549*7f2fe78bSCy Schubert 'para': self.paragraph_content_decorator} 550*7f2fe78bSCy Schubert result = it.walk(decorators, 1) 551*7f2fe78bSCy Schubert if result is not None: 552*7f2fe78bSCy Schubert return result 553*7f2fe78bSCy Schubert return result 554*7f2fe78bSCy Schubert 555*7f2fe78bSCy Schubert def break_into_lines(self, value, linelen=82): 556*7f2fe78bSCy Schubert breaks = range(0,len(value),linelen) + [len(value)] 557*7f2fe78bSCy Schubert result = list() 558*7f2fe78bSCy Schubert for (start,end) in zip(breaks[:-1],breaks[1:]): 559*7f2fe78bSCy Schubert result.append(value[start:end]) 560*7f2fe78bSCy Schubert result = '\n'.join(result) 561*7f2fe78bSCy Schubert 562*7f2fe78bSCy Schubert return result 563*7f2fe78bSCy Schubert 564*7f2fe78bSCy Schubert def _save(self, table, path = None): 565*7f2fe78bSCy Schubert if path is None: 566*7f2fe78bSCy Schubert f = sys.stdout 567*7f2fe78bSCy Schubert else: 568*7f2fe78bSCy Schubert f = open(path, 'w') 569*7f2fe78bSCy Schubert for l in table: 570*7f2fe78bSCy Schubert f.write('%s\n' % ','.join(l)) 571*7f2fe78bSCy Schubert if path is not None: 572*7f2fe78bSCy Schubert f.close() 573*7f2fe78bSCy Schubert 574*7f2fe78bSCy Schubert 575*7f2fe78bSCy Schubert 576*7f2fe78bSCy Schubertclass DoxyBuilderFuncs(DoxyFuncs): 577*7f2fe78bSCy Schubert def __init__(self, xmlpath, rstpath): 578*7f2fe78bSCy Schubert super(DoxyBuilderFuncs,self).__init__(xmlpath) 579*7f2fe78bSCy Schubert self.target_dir = rstpath 580*7f2fe78bSCy Schubert outfile = '%s/%s' % (self.target_dir, 'out.txt') 581*7f2fe78bSCy Schubert self.tmp = open(outfile, 'w') 582*7f2fe78bSCy Schubert 583*7f2fe78bSCy Schubert def run_all(self): 584*7f2fe78bSCy Schubert self.run() 585*7f2fe78bSCy Schubert templates = {'function': 'func_document.tmpl'} 586*7f2fe78bSCy Schubert self.save(templates, self.target_dir) 587*7f2fe78bSCy Schubert 588*7f2fe78bSCy Schubert def test_run(self): 589*7f2fe78bSCy Schubert self.run() 590*7f2fe78bSCy Schubert 591*7f2fe78bSCy Schubertif __name__ == '__main__': 592*7f2fe78bSCy Schubert builder = DoxyBuilderFuncs(xmlpath, rstpath) 593*7f2fe78bSCy Schubert builder.run_all() 594*7f2fe78bSCy Schubert 595