summaryrefslogtreecommitdiff
path: root/build_tools/get_documentation.py
diff options
context:
space:
mode:
Diffstat (limited to 'build_tools/get_documentation.py')
-rw-r--r--build_tools/get_documentation.py175
1 files changed, 175 insertions, 0 deletions
diff --git a/build_tools/get_documentation.py b/build_tools/get_documentation.py
new file mode 100644
index 000000000..2ff4cb2b9
--- /dev/null
+++ b/build_tools/get_documentation.py
@@ -0,0 +1,175 @@
+#! /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)