123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- #! /usr/bin/env python
- # vin: sw=3 et:
- '''
- Copyright (C) 2012, Digium, Inc.
- Matt Jordan <mjordan@digium.com>
- This program is free software, distributed under the terms of
- the GNU General Public License Version 2.
- '''
- import sys
- import os
- import xml.dom.minidom
- from xml.dom.minidom import Element
- def get_manager_event_method_type(candidate_string):
- if "ast_manager_event_multichan" in candidate_string:
- return "multichan"
- elif "ast_manager_event" in candidate_string:
- return "ast_manager_event"
- elif "manager_event" in candidate_string:
- return "manager_event"
- return ""
- def parse_manager_event_instance(xml_fragment):
- ''' Parse the information for a manager event
- Keyword Arguments:
- xml_fragment The XML fragment comment
- Returns:
- A well-formed XML fragment containing the comments passed in, as well as
- information obtained from the manager_event macro calls
- '''
- def __node_contains_parameter(node, parameter):
- ''' Return whether or not a node contains a given parameter name '''
- return any([n for n in node.getElementsByTagName("parameter")
- if __node_contains_attribute(n, parameter)])
- def __node_contains_attribute(node, attribute_name):
- ''' Return whether or not a node contains a given attribute name '''
- return any([attr for attr in node.attributes.items()
- if attr[1] == attribute_name])
- candidate_lines = []
- type = ""
- # Read the manager_event method call, which should occur after
- # the documentation block
- for line in sys.stdin:
- if len(line):
- candidate_lines.append(line)
- if ");" in line:
- break
- candidate_string = ''.join(candidate_lines)
- type = get_manager_event_method_type(candidate_string)
- if not type:
- # Unknown, return what we have
- return ''.join(xml_fragment)
- # strip off the macro name
- first_paren = candidate_string.index("(", 0)
- last_paren = candidate_string.rindex(");")
- candidate_string = candidate_string[first_paren + 1:last_paren]
- # split into parameter tokens
- func_parameter_tokens = candidate_string.split(',')
- if type == "manager_event" or type == "multichan":
- class_level = func_parameter_tokens[0].strip()
- event_type = func_parameter_tokens[1].strip()
- else:
- class_level = func_parameter_tokens[1].strip()
- event_type = func_parameter_tokens[2].strip()
- if type == "manager_event":
- event_parameters = func_parameter_tokens[2].strip()
- elif type == "ast_manager_event":
- event_parameters = func_parameter_tokens[3].strip()
- else:
- event_parameters = func_parameter_tokens[4].strip()
- parameter_tokens = event_parameters.replace("\"", "").split('\\r\\n')
- # Build the top level XML element information. Note that we temporarily
- # add the xi namespace in case any includes are used
- node_text = '<managerEvent language=\"%s\" name=\"%s\" xmlns:xi=\"%s\">'
- xml_fragment.insert(0, node_text % ('en_US',
- event_type.strip().replace("\"", ""),
- 'http://www.w3.org/2001/XInclude'))
- xml_fragment[1] = "<managerEventInstance class=\"%s\">" % (class_level)
- xml_fragment.insert(len(xml_fragment), "</managerEvent>")
- # Turn the XML into a DOM to manage the rest of the node manipulations
- dom = xml.dom.minidom.parseString(''.join(xml_fragment))
- # Get the syntax node if we have one; otherwise make one
- instance = dom.getElementsByTagName("managerEventInstance")[0]
- syntax = instance.getElementsByTagName("syntax")
- if not syntax:
- syntax = dom.createElement("syntax")
- instance.appendChild(syntax)
- # Move any existing parameter nodes over
- for node in instance.getElementsByTagName("parameter"):
- syntax.appendChild(node.cloneNode(True))
- instance.removeChild(node)
- else:
- syntax = syntax[0]
- # Add parameters found in the method invocation that were not previously
- # documented
- for parameter in parameter_tokens:
- if not len(parameter):
- continue
- index = parameter.find(':')
- if index < 0:
- index = len(parameter)
- parameter = (parameter[:index].strip().replace("\"", ""))
- if ('%s' not in parameter and
- not __node_contains_parameter(syntax, parameter)):
- e = dom.createElement("parameter")
- e.setAttribute('name', parameter)
- syntax.appendChild(e)
- return dom.toxml().replace("<?xml version=\"1.0\" ?>", "").replace(
- 'xmlns:xi="http://www.w3.org/2001/XInclude"', '')
- def main(argv=None):
- if argv is None:
- argv = sys.argv
- in_doc = False
- xml_fragment = []
- xml = []
- line_number = 0
- for line in sys.stdin:
- # Note: multiple places may have to read a line, so iterating over
- # readlines isn't possible. Break when a null line is returned
- line_number += 1
- if not line:
- break
- line = line.strip()
- if ("/*** DOCUMENTATION" in line):
- in_doc = True
- elif ("***/" in line and in_doc):
- # Depending on what we're processing, determine if we need to do
- # any additional work
- in_doc = False
- if not xml_fragment:
- # Nothing read, move along
- continue
- if "<managerEventInstance>" in xml_fragment[0]:
- xml.append(parse_manager_event_instance(xml_fragment))
- else:
- xml.append(''.join(xml_fragment))
- xml_fragment = []
- elif (in_doc):
- xml_fragment.append("%s\n" % line)
- sys.stdout.write(''.join(xml))
- return 0
- if __name__ == "__main__":
- sys.exit(main() or 0)
|