forked from naf419/asterisk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget_documentation.py
172 lines (139 loc) · 5.74 KB
/
get_documentation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#! /usr/bin/env python
# vin: sw=3 et:
'''
Copyright (C) 2012, Digium, Inc.
Matt Jordan <[email protected]>
This program is free software, distributed under the terms of
the GNU General Public License Version 2.
'''
import sys
import xml.dom.minidom
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)