]> Git Repo - qemu.git/blob - docs/sphinx/dbusparser.py
works with less than base ISA qemu-system-riscv32 -M virt -bios none -kernel output...
[qemu.git] / docs / sphinx / dbusparser.py
1 # Based from "GDBus - GLib D-Bus Library":
2 #
3 # Copyright (C) 2008-2011 Red Hat, Inc.
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General
16 # Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: David Zeuthen <[email protected]>
19
20 import xml.parsers.expat
21
22
23 class Annotation:
24     def __init__(self, key, value):
25         self.key = key
26         self.value = value
27         self.annotations = []
28         self.since = ""
29
30
31 class Arg:
32     def __init__(self, name, signature):
33         self.name = name
34         self.signature = signature
35         self.annotations = []
36         self.doc_string = ""
37         self.since = ""
38
39
40 class Method:
41     def __init__(self, name, h_type_implies_unix_fd=True):
42         self.name = name
43         self.h_type_implies_unix_fd = h_type_implies_unix_fd
44         self.in_args = []
45         self.out_args = []
46         self.annotations = []
47         self.doc_string = ""
48         self.since = ""
49         self.deprecated = False
50         self.unix_fd = False
51
52
53 class Signal:
54     def __init__(self, name):
55         self.name = name
56         self.args = []
57         self.annotations = []
58         self.doc_string = ""
59         self.since = ""
60         self.deprecated = False
61
62
63 class Property:
64     def __init__(self, name, signature, access):
65         self.name = name
66         self.signature = signature
67         self.access = access
68         self.annotations = []
69         self.arg = Arg("value", self.signature)
70         self.arg.annotations = self.annotations
71         self.readable = False
72         self.writable = False
73         if self.access == "readwrite":
74             self.readable = True
75             self.writable = True
76         elif self.access == "read":
77             self.readable = True
78         elif self.access == "write":
79             self.writable = True
80         else:
81             raise ValueError('Invalid access type "{}"'.format(self.access))
82         self.doc_string = ""
83         self.since = ""
84         self.deprecated = False
85         self.emits_changed_signal = True
86
87
88 class Interface:
89     def __init__(self, name):
90         self.name = name
91         self.methods = []
92         self.signals = []
93         self.properties = []
94         self.annotations = []
95         self.doc_string = ""
96         self.doc_string_brief = ""
97         self.since = ""
98         self.deprecated = False
99
100
101 class DBusXMLParser:
102     STATE_TOP = "top"
103     STATE_NODE = "node"
104     STATE_INTERFACE = "interface"
105     STATE_METHOD = "method"
106     STATE_SIGNAL = "signal"
107     STATE_PROPERTY = "property"
108     STATE_ARG = "arg"
109     STATE_ANNOTATION = "annotation"
110     STATE_IGNORED = "ignored"
111
112     def __init__(self, xml_data, h_type_implies_unix_fd=True):
113         self._parser = xml.parsers.expat.ParserCreate()
114         self._parser.CommentHandler = self.handle_comment
115         self._parser.CharacterDataHandler = self.handle_char_data
116         self._parser.StartElementHandler = self.handle_start_element
117         self._parser.EndElementHandler = self.handle_end_element
118
119         self.parsed_interfaces = []
120         self._cur_object = None
121
122         self.state = DBusXMLParser.STATE_TOP
123         self.state_stack = []
124         self._cur_object = None
125         self._cur_object_stack = []
126
127         self.doc_comment_last_symbol = ""
128
129         self._h_type_implies_unix_fd = h_type_implies_unix_fd
130
131         self._parser.Parse(xml_data)
132
133     COMMENT_STATE_BEGIN = "begin"
134     COMMENT_STATE_PARAMS = "params"
135     COMMENT_STATE_BODY = "body"
136     COMMENT_STATE_SKIP = "skip"
137
138     def handle_comment(self, data):
139         comment_state = DBusXMLParser.COMMENT_STATE_BEGIN
140         lines = data.split("\n")
141         symbol = ""
142         body = ""
143         in_para = False
144         params = {}
145         for line in lines:
146             orig_line = line
147             line = line.lstrip()
148             if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
149                 if len(line) > 0:
150                     colon_index = line.find(": ")
151                     if colon_index == -1:
152                         if line.endswith(":"):
153                             symbol = line[0 : len(line) - 1]
154                             comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
155                         else:
156                             comment_state = DBusXMLParser.COMMENT_STATE_SKIP
157                     else:
158                         symbol = line[0:colon_index]
159                         rest_of_line = line[colon_index + 2 :].strip()
160                         if len(rest_of_line) > 0:
161                             body += rest_of_line + "\n"
162                         comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
163             elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
164                 if line.startswith("@"):
165                     colon_index = line.find(": ")
166                     if colon_index == -1:
167                         comment_state = DBusXMLParser.COMMENT_STATE_BODY
168                         if not in_para:
169                             in_para = True
170                         body += orig_line + "\n"
171                     else:
172                         param = line[1:colon_index]
173                         docs = line[colon_index + 2 :]
174                         params[param] = docs
175                 else:
176                     comment_state = DBusXMLParser.COMMENT_STATE_BODY
177                     if len(line) > 0:
178                         if not in_para:
179                             in_para = True
180                         body += orig_line + "\n"
181             elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
182                 if len(line) > 0:
183                     if not in_para:
184                         in_para = True
185                     body += orig_line + "\n"
186                 else:
187                     if in_para:
188                         body += "\n"
189                         in_para = False
190         if in_para:
191             body += "\n"
192
193         if symbol != "":
194             self.doc_comment_last_symbol = symbol
195             self.doc_comment_params = params
196             self.doc_comment_body = body
197
198     def handle_char_data(self, data):
199         # print 'char_data=%s'%data
200         pass
201
202     def handle_start_element(self, name, attrs):
203         old_state = self.state
204         old_cur_object = self._cur_object
205         if self.state == DBusXMLParser.STATE_IGNORED:
206             self.state = DBusXMLParser.STATE_IGNORED
207         elif self.state == DBusXMLParser.STATE_TOP:
208             if name == DBusXMLParser.STATE_NODE:
209                 self.state = DBusXMLParser.STATE_NODE
210             else:
211                 self.state = DBusXMLParser.STATE_IGNORED
212         elif self.state == DBusXMLParser.STATE_NODE:
213             if name == DBusXMLParser.STATE_INTERFACE:
214                 self.state = DBusXMLParser.STATE_INTERFACE
215                 iface = Interface(attrs["name"])
216                 self._cur_object = iface
217                 self.parsed_interfaces.append(iface)
218             elif name == DBusXMLParser.STATE_ANNOTATION:
219                 self.state = DBusXMLParser.STATE_ANNOTATION
220                 anno = Annotation(attrs["name"], attrs["value"])
221                 self._cur_object.annotations.append(anno)
222                 self._cur_object = anno
223             else:
224                 self.state = DBusXMLParser.STATE_IGNORED
225
226             # assign docs, if any
227             if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
228                 self._cur_object.doc_string = self.doc_comment_body
229                 if "short_description" in self.doc_comment_params:
230                     short_description = self.doc_comment_params["short_description"]
231                     self._cur_object.doc_string_brief = short_description
232                 if "since" in self.doc_comment_params:
233                     self._cur_object.since = self.doc_comment_params["since"].strip()
234
235         elif self.state == DBusXMLParser.STATE_INTERFACE:
236             if name == DBusXMLParser.STATE_METHOD:
237                 self.state = DBusXMLParser.STATE_METHOD
238                 method = Method(
239                     attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd
240                 )
241                 self._cur_object.methods.append(method)
242                 self._cur_object = method
243             elif name == DBusXMLParser.STATE_SIGNAL:
244                 self.state = DBusXMLParser.STATE_SIGNAL
245                 signal = Signal(attrs["name"])
246                 self._cur_object.signals.append(signal)
247                 self._cur_object = signal
248             elif name == DBusXMLParser.STATE_PROPERTY:
249                 self.state = DBusXMLParser.STATE_PROPERTY
250                 prop = Property(attrs["name"], attrs["type"], attrs["access"])
251                 self._cur_object.properties.append(prop)
252                 self._cur_object = prop
253             elif name == DBusXMLParser.STATE_ANNOTATION:
254                 self.state = DBusXMLParser.STATE_ANNOTATION
255                 anno = Annotation(attrs["name"], attrs["value"])
256                 self._cur_object.annotations.append(anno)
257                 self._cur_object = anno
258             else:
259                 self.state = DBusXMLParser.STATE_IGNORED
260
261             # assign docs, if any
262             if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
263                 self._cur_object.doc_string = self.doc_comment_body
264                 if "since" in self.doc_comment_params:
265                     self._cur_object.since = self.doc_comment_params["since"].strip()
266
267         elif self.state == DBusXMLParser.STATE_METHOD:
268             if name == DBusXMLParser.STATE_ARG:
269                 self.state = DBusXMLParser.STATE_ARG
270                 arg_name = None
271                 if "name" in attrs:
272                     arg_name = attrs["name"]
273                 arg = Arg(arg_name, attrs["type"])
274                 direction = attrs.get("direction", "in")
275                 if direction == "in":
276                     self._cur_object.in_args.append(arg)
277                 elif direction == "out":
278                     self._cur_object.out_args.append(arg)
279                 else:
280                     raise ValueError('Invalid direction "{}"'.format(direction))
281                 self._cur_object = arg
282             elif name == DBusXMLParser.STATE_ANNOTATION:
283                 self.state = DBusXMLParser.STATE_ANNOTATION
284                 anno = Annotation(attrs["name"], attrs["value"])
285                 self._cur_object.annotations.append(anno)
286                 self._cur_object = anno
287             else:
288                 self.state = DBusXMLParser.STATE_IGNORED
289
290             # assign docs, if any
291             if self.doc_comment_last_symbol == old_cur_object.name:
292                 if "name" in attrs and attrs["name"] in self.doc_comment_params:
293                     doc_string = self.doc_comment_params[attrs["name"]]
294                     if doc_string is not None:
295                         self._cur_object.doc_string = doc_string
296                     if "since" in self.doc_comment_params:
297                         self._cur_object.since = self.doc_comment_params[
298                             "since"
299                         ].strip()
300
301         elif self.state == DBusXMLParser.STATE_SIGNAL:
302             if name == DBusXMLParser.STATE_ARG:
303                 self.state = DBusXMLParser.STATE_ARG
304                 arg_name = None
305                 if "name" in attrs:
306                     arg_name = attrs["name"]
307                 arg = Arg(arg_name, attrs["type"])
308                 self._cur_object.args.append(arg)
309                 self._cur_object = arg
310             elif name == DBusXMLParser.STATE_ANNOTATION:
311                 self.state = DBusXMLParser.STATE_ANNOTATION
312                 anno = Annotation(attrs["name"], attrs["value"])
313                 self._cur_object.annotations.append(anno)
314                 self._cur_object = anno
315             else:
316                 self.state = DBusXMLParser.STATE_IGNORED
317
318             # assign docs, if any
319             if self.doc_comment_last_symbol == old_cur_object.name:
320                 if "name" in attrs and attrs["name"] in self.doc_comment_params:
321                     doc_string = self.doc_comment_params[attrs["name"]]
322                     if doc_string is not None:
323                         self._cur_object.doc_string = doc_string
324                     if "since" in self.doc_comment_params:
325                         self._cur_object.since = self.doc_comment_params[
326                             "since"
327                         ].strip()
328
329         elif self.state == DBusXMLParser.STATE_PROPERTY:
330             if name == DBusXMLParser.STATE_ANNOTATION:
331                 self.state = DBusXMLParser.STATE_ANNOTATION
332                 anno = Annotation(attrs["name"], attrs["value"])
333                 self._cur_object.annotations.append(anno)
334                 self._cur_object = anno
335             else:
336                 self.state = DBusXMLParser.STATE_IGNORED
337
338         elif self.state == DBusXMLParser.STATE_ARG:
339             if name == DBusXMLParser.STATE_ANNOTATION:
340                 self.state = DBusXMLParser.STATE_ANNOTATION
341                 anno = Annotation(attrs["name"], attrs["value"])
342                 self._cur_object.annotations.append(anno)
343                 self._cur_object = anno
344             else:
345                 self.state = DBusXMLParser.STATE_IGNORED
346
347         elif self.state == DBusXMLParser.STATE_ANNOTATION:
348             if name == DBusXMLParser.STATE_ANNOTATION:
349                 self.state = DBusXMLParser.STATE_ANNOTATION
350                 anno = Annotation(attrs["name"], attrs["value"])
351                 self._cur_object.annotations.append(anno)
352                 self._cur_object = anno
353             else:
354                 self.state = DBusXMLParser.STATE_IGNORED
355
356         else:
357             raise ValueError(
358                 'Unhandled state "{}" while entering element with name "{}"'.format(
359                     self.state, name
360                 )
361             )
362
363         self.state_stack.append(old_state)
364         self._cur_object_stack.append(old_cur_object)
365
366     def handle_end_element(self, name):
367         self.state = self.state_stack.pop()
368         self._cur_object = self._cur_object_stack.pop()
369
370
371 def parse_dbus_xml(xml_data):
372     parser = DBusXMLParser(xml_data, True)
373     return parser.parsed_interfaces
This page took 0.061505 seconds and 4 git commands to generate.