regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / tools / parse_xml2skinny_dissector.py
blobfc9933e6620a9d0aa0a9d2ff1cecb6c14f43457e
2 # Wireshark Dissector Generator for SkinnyProtocolOptimized.xml
4 # Author: Diederik de Groot <ddegroot@user.sf.net>
5 # Date: 2014-7-22
6 # Skinny Protocol Versions: 0 through 22
8 # Heritage:
9 # xml2obj based on https://code.activestate.com/recipes/149368-xml2obj/
11 # Dependencies:
12 # python / xml / sax
14 # Called By:
15 # cog.py + packet-skinny.c.in for inplace code generation
16 # See: https://nedbatchelder.com/code/cog/
19 # SPDX-License-Identifier: GPL-2.0-or-later
22 import re
23 import xml.sax.handler
25 indentation = 0
26 indent_str = ''
27 fieldsArray = {}
28 si_fields = {
29 "callReference" : "si->callId",
30 "lineInstance": "si->lineId",
31 "passThroughPartyId" : "si->passThroughPartyId",
32 "callState" : "si->callState",
33 "callingParty" : "si->callingParty",
34 "calledParty" : "si->calledParty",
35 "mediaReceptionStatus" : "si->mediaReceptionStatus",
36 "mediaTransmissionStatus" : "si->mediaTransmissionStatus",
37 "multimediaReceptionStatus" : "si->multimediaReceptionStatus",
38 "multimediaTransmissionStatus" : "si->multimediaTransmissionStatus",
39 "multicastReceptionStatus" : "si->multicastReceptionStatus",
42 debug = 0
44 def xml2obj(src):
45 """
46 A function to converts XML data into native Python objects.
48 """
49 non_id_char = re.compile('[^_0-9a-zA-Z]')
51 def _name_mangle(name):
52 return non_id_char.sub('_',
53 name)
55 class DataNode(object):
56 def __init__(self):
57 self._attrs = {} # XML attributes and child elements
58 self.data = None # child text data
59 self.parent = None
60 self.basemessage = None
61 self.intsize = 0
62 self._children = []
63 self.declared = []
65 def __len__(self):
66 # treat single element as a list of 1
67 return 1
68 def __getitem__(self, key):
69 if isinstance(key, str):
70 return self._attrs.get(key,None)
71 else:
72 return [self][key]
74 def __contains__(self, name):
75 return name in self._attrs
77 def __bool__(self):
78 return bool(self._attrs or self.data)
80 def __getattr__(self, name):
81 if name.startswith('__'):
82 # need to do this for Python special methods???
83 raise AttributeError(name)
84 return self._attrs.get(name,None)
86 def _add_xml_attr(self, name, value):
87 if name in self._attrs:
88 # multiple attribute of the same name are represented by a list
89 children = self._attrs[name]
90 if not isinstance(children, list):
91 children = [children]
92 self._attrs[name] = children
93 children.append(value)
94 else:
95 self._attrs[name] = value
97 def _add_child(self, name, value):
98 #print "adding : %s / %s to %s" %(name,value, self.__class__)
99 self._children.append(value)
101 def __str__(self):
102 return '%s:%s' %(self.__class__,self.name)
104 def keys(self):
105 return self._attrs.keys()
107 def __repr__(self):
108 items = {}
109 if self.data:
110 items.append(('data', self.data))
111 return '{%s}' % ', '.join(['%s:%s' % (k,repr(v)) for k,v in items])
113 def __setitem__(self, key, value):
114 self._attrs[key] = value
116 def getfieldnames(self):
117 return ''
119 def get_req_resp_keys(self, req_resp_keys):
120 return []
122 def get_req_resp_key(self):
123 if self.req_resp_key == "1":
124 return self.name
125 return None
127 def declaration(self):
128 global fieldsArray
129 if self.name not in fieldsArray:
130 fieldsArray[self.name] = '/* UNKNOWN { &hf_skinny_%s,\n {\n"%s", "skinny.%s", FT_UINT32, BASE_DEC, NULL, 0x0,\n "%s", HFILL }}, */\n' %(self.name, self.name, self.name, self.comment)
131 return ''
133 def dissect(self):
134 return self.name or ''
136 def incr_indent(self):
137 global indentation
138 global indent_str
139 indentation += 1
140 indent_str = ''
141 for x in range(0, indentation):
142 indent_str += ' '
144 def decr_indent(self):
145 global indentation
146 global indent_str
147 indentation -= 1
148 indent_str = ''
149 for x in range(0, indentation):
150 indent_str += ' '
152 def indent_out(self, string):
153 return indent_str + string
156 class Message(DataNode):
157 ''' Message '''
158 def __str__(self):
159 return self.name
161 def gen_handler(self):
162 if self.fields is None:
163 # skip whole message and return NULL as handler
164 return 'NULL'
165 return 'handle_%s' %self.name
167 def dissect(self):
168 ret = ''
169 declarations = 0
170 fixed = 0
172 if (self.fields is not None):
173 ret += self.indent_out("/*\n")
174 ret += self.indent_out(" * Message: %s\n" %self.name)
175 ret += self.indent_out(" * Opcode: %s\n" %self.opcode)
176 ret += self.indent_out(" * Type: %s\n" %self.type)
177 ret += self.indent_out(" * Direction: %s\n" %self.direction)
178 ret += self.indent_out(" * VarLength: %s\n" %self.dynamic)
179 ret += self.indent_out(" * MsgType: %s\n" %self.msgtype)
180 if self.comment:
181 ret += self.indent_out(" * Comment: %s\n" %self.comment)
182 ret += self.indent_out(" */\n")
183 ret += self.indent_out("static void\n")
184 ret += self.indent_out("handle_%s(ptvcursor_t *cursor, packet_info * pinfo _U_, skinny_conv_info_t * skinny_conv _U_)\n" %self.name)
185 ret += self.indent_out("{\n")
186 self.incr_indent()
188 for fields in self.fields:
189 if fields.size_lt or fields.size_gt:
190 if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
191 ret += self.indent_out("uint32_t hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
192 self.basemessage.declared.append("hdr_data_length")
193 declarations += 1
194 if fields.fixed == "yes":
195 fixed = 1
197 if not declarations or fixed == 1:
198 for fields in self.fields[1:]:
199 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
200 ret += self.indent_out("uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
201 self.basemessage.declared.append("hdr_version")
202 declarations += 1
204 req_resp_keys = []
205 for fields in self.fields:
206 fields.get_req_resp_keys(req_resp_keys)
207 ret += '%s' %fields.declaration()
208 declarations += 1
210 if declarations > 1:
211 ret += "\n"
213 if self.fields is not None:
214 for fields in self.fields:
215 ret += '%s' %fields.dissect()
217 # setup request/response
218 if self.msgtype == "request":
219 if req_resp_keys and req_resp_keys[0] != '':
220 ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.opcode, req_resp_keys[0]))
221 else:
222 ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s);\n' %(self.opcode))
224 if self.msgtype == "response":
225 if req_resp_keys and req_resp_keys[0] != '':
226 ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.request, req_resp_keys[0]))
227 else:
228 ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s);\n' %(self.request))
230 self.decr_indent()
232 ret += "}\n\n"
233 return ret
235 class Fields(DataNode):
236 ''' Fields '''
237 size_fieldnames= []
239 def get_req_resp_keys(self, req_resp):
240 for field in self._children:
241 key = field.get_req_resp_key()
242 if key is not None and key not in req_resp:
243 req_resp.append(key)
245 def declaration(self):
246 ret = ''
248 for field in self._children:
249 ret += '%s' %(field.declaration())
250 self.intsize += field.intsize
251 return ret
253 def dissect(self, lookupguide=""):
254 ret = ''
255 ifstarted = 0
256 #ret += "/* [PARENT: %s, BASEMESSAGE: %s] */\n" %(self.parent.name,self.basemessage.name)
258 if ((self.beginversion or self.endversion) and (self.beginversion != "0" or self.endversion != "22")):
260 ifstarted = 1
261 ret += self.indent_out('if (')
262 if (self.beginversion and self.beginversion != "0"):
263 if (not self.endversion or self.endversion == "22"):
264 ret += 'hdr_version >= V%s_MSG_TYPE) {\n' %self.beginversion
265 else:
266 ret += 'hdr_version >= V%s_MSG_TYPE && ' %self.beginversion
267 if (self.endversion and self.endversion != "22"):
268 ret += 'hdr_version <= V%s_MSG_TYPE) {\n' %self.endversion
269 self.incr_indent()
271 if self.size_lt:
272 ret += self.indent_out('if (hdr_data_length < %s) {\n' %self.size_lt)
273 self.incr_indent()
275 if self.size_gt:
276 ret += self.indent_out('if (hdr_data_length > %s) {\n' %self.size_gt)
277 self.incr_indent()
279 # generate dissection
280 for field in self._children:
281 ret += '%s' %(field.dissect())
283 if self.size_lt:
284 self.decr_indent()
285 ret += self.indent_out('}\n')
287 if self.size_gt:
288 self.decr_indent()
289 ret += self.indent_out('}\n')
291 if ifstarted:
292 self.decr_indent()
293 ret += self.indent_out('}\n')
295 return ret
297 class Integer(DataNode):
298 def __init__(self):
299 DataNode.__init__(self)
300 self.intsize = 0
301 self.endian = "ENC_LITTLE_ENDIAN"
303 def __str__(self):
304 return '%s:%s' %(self.__class__,self.name)
306 def declaration(self):
307 ret = ''
309 int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1,'ipport':4}
310 if self.endianness == "big":
311 self.endian = "ENC_BIG_ENDIAN"
312 if self.type in int_sizes:
313 self.intsize = int_sizes[self.type]
314 else:
315 print(("ERROR integer %s with type: %s, could not be found" %(self.name, self.type)))
317 if self.declare == "yes" or self.make_additional_info == "yes":
318 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
319 ret += self.indent_out(f'uint{self.intsize * 8}_t {self.name} = 0;\n')
320 self.basemessage.declared.append(self.name)
322 global fieldsArray
323 if self.name not in fieldsArray:
324 fieldsArray[self.name] ='{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_UINT%d, BASE_DEC, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
325 return ret
327 def dissect(self):
328 ret = ''
330 size = 0
331 if self.size_fieldname:
332 if self.basemessage.dynamic == "yes":
333 size = self.size_fieldname
334 else:
335 size = self.maxsize
336 elif self.size:
337 size = self.size
339 if size:
340 if self.size_fieldname:
341 ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb integer size guard */' if debug else ''))
342 else:
343 ret += self.indent_out('{\n')
344 self.incr_indent()
345 variable = 'counter_%d' %indentation
346 ret += self.indent_out('uint32_t %s = 0;\n' %(variable))
347 if self.size_fieldname:
348 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref:%s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
349 else:
350 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
351 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable))
352 if self.basemessage.dynamic == "no" and self.size_fieldname:
353 self.incr_indent()
354 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
355 self.incr_indent()
357 if self.declare == "yes" or self.make_additional_info == "yes":
358 if self.endianness == "big":
359 if (self.intsize == 4):
360 ret += self.indent_out('%s = tvb_get_ntohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
361 elif (self.intsize == 2):
362 ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
363 else:
364 ret += self.indent_out('%s = tvb_get_uint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
365 else:
366 if (self.intsize == 4):
367 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
368 elif (self.intsize == 2):
369 ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
370 else:
371 ret += self.indent_out('%s = tvb_get_uint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
373 if self.name in si_fields.keys():
374 if self.endianness == "big":
375 ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
376 else:
377 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
379 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, self.endian))
381 if size:
382 if self.basemessage.dynamic == "no" and self.size_fieldname:
383 self.decr_indent()
384 ret += self.indent_out('} else {\n')
385 ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %self.intsize)
386 ret += self.indent_out('}\n')
387 self.decr_indent()
388 ret += self.indent_out('}\n')
389 if debug:
390 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
391 else:
392 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
393 self.decr_indent()
394 if self.size_fieldname:
395 ret += self.indent_out('} else {\n')
396 self.incr_indent()
397 ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(size, self.intsize, ' /* guard kicked in -> skip the rest */;' if debug else ''))
398 self.decr_indent()
399 ret += self.indent_out('}\n')
401 if self.make_additional_info == "yes":
402 ret += self.indent_out('srtp_add_address(pinfo, PT_UDP, &%s, %s, 0, "SKINNY", pinfo->num, false, NULL, NULL, NULL);\n' %(self.use_param, self.name))
403 ret += self.indent_out('%s_str = address_to_display(NULL, &%s);\n' % (self.use_param, self.use_param))
404 ret += self.indent_out('si->additionalInfo = ws_strdup_printf("%%s:%%d", %s_str, %s);\n' % (self.use_param, self.name))
405 ret += self.indent_out('wmem_free(NULL, %s_str);\n' % (self.use_param))
407 return ret
409 class Enum(DataNode):
410 def __init__(self):
411 DataNode.__init__(self)
412 self.intsize = 0
413 self.sparse = 0
415 def __str__(self):
416 return '%s:%s' %(self.__class__,self.name)
418 def declaration(self):
419 ret = ''
420 enum_sizes = {'uint32':4,'uint16':2,'uint8':1}
421 if self.type in enum_sizes:
422 self.intsize = enum_sizes[self.type]
423 else:
424 print(("ERROR enum %s with type: %s, could not be found" %(self.name, self.type)))
426 if self.declare == "yes":
427 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
428 ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
429 self.basemessage.declared.append(self.name)
431 global fieldsArray
432 if self.name not in fieldsArray:
433 fieldsArray[self.name] ='{&hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_UINT%d, BASE_HEX | BASE_EXT_STRING, &%s_ext, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, self.subtype[0].upper() + self.subtype[1:], '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
434 return ret
436 def dissect(self):
437 ret = ''
438 endian = "ENC_LITTLE_ENDIAN"
439 size = 0
440 if self.size_fieldname:
441 if self.basemessage.dynamic == "yes":
442 size = self.size_fieldname
443 else:
444 size = self.maxsize
445 elif self.size:
446 size = self.size
448 if self.make_additional_info == "yes":
449 ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%s\\"",\n')
450 self.incr_indent()
451 ret += self.indent_out('try_val_to_str_ext(\n')
452 self.incr_indent()
453 ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
454 ret += self.indent_out('&%s_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
455 self.decr_indent()
456 ret += self.indent_out(')\n')
457 self.decr_indent()
458 ret += self.indent_out(');\n')
460 if self.make_additional_info_short == "yes":
461 ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%s\\"",\n')
462 self.incr_indent()
463 ret += self.indent_out('try_val_to_str_ext(\n')
464 self.incr_indent()
465 ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
466 ret += self.indent_out('&%s_short_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
467 self.decr_indent()
468 ret += self.indent_out(')\n')
469 self.decr_indent()
470 ret += self.indent_out(');\n')
472 if size:
473 if self.size_fieldname:
474 ret += self.indent_out('if (%s <= %s) { /* tvb enum size guard */\n' %(self.size_fieldname, self.maxsize))
475 else:
476 ret += self.indent_out('{\n')
477 self.incr_indent()
478 variable = 'counter_%d' %indentation
479 ret += self.indent_out('uint32_t %s = 0;\n' %(variable))
480 if self.size_fieldname:
481 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref: %s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
482 else:
483 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
484 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable))
485 if self.basemessage.dynamic == "no" and self.size_fieldname:
486 self.incr_indent()
487 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
488 self.incr_indent()
490 if self.name in si_fields.keys():
491 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
493 if self.declare == "yes":
494 if (self.intsize == 4):
495 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
496 elif (self.intsize == 2):
497 ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
498 else:
499 ret += self.indent_out('%s = tvb_get_uint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
501 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, endian))
503 if size:
504 if self.basemessage.dynamic == "no" and self.size_fieldname:
505 self.decr_indent()
506 ret += self.indent_out('} else {\n')
507 ret += self.indent_out(' ptvcursor_advance(cursor, 4);\n')
508 ret += self.indent_out('}\n')
509 self.decr_indent()
510 ret += self.indent_out('}\n')
511 if debug:
512 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
513 else:
514 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
515 self.decr_indent()
516 if self.size_fieldname:
517 ret += self.indent_out('} else {\n')
518 self.incr_indent()
519 ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s)); /* guard kicked in -> skip the rest */;\n' %(size, self.intsize))
520 self.decr_indent()
521 ret += self.indent_out('}\n')
523 return ret
525 class String(DataNode):
526 def __init__(self):
527 DataNode.__init__(self)
529 def __str__(self):
530 return '%s:%s' %(self.__class__,self.name)
532 def get_req_resp_key(self):
533 if self.req_resp_key == "1":
534 return 'wmem_str_hash(%s)' %self.name
535 return None
537 def declaration(self):
538 ret = ''
539 self.intsize = 0
540 if self.size:
541 if self.size=="VariableDirnumSize":
542 self.intsize = 24
543 else:
544 self.intsize = int(self.size)
545 elif self.maxsize and self.basemessage.dynamic == "no":
546 self.intsize = int(self.maxsize)
548 if self.declare == "yes":
549 if self.size=="VariableDirnumSize":
550 if self.basemessage.declared is None or "VariableDirnumSize" not in self.basemessage.declared:
551 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
552 #if (self.basemessage.fields is not None and len(self.basemessage.fields) == 1):
553 ret += self.indent_out('uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n')
554 self.basemessage.declared.append("hdr_version")
555 ret += self.indent_out('uint32_t VariableDirnumSize = (hdr_version >= V18_MSG_TYPE) ? 25 : 24;\n')
556 self.basemessage.declared.append("VariableDirnumSize")
557 #else:
558 # if self.basemessage.declared is None or self.name not in self.basemessage.declared:
559 # ret += self.indent_out('char *%s = NULL;\n' %self.name)
560 # self.basemessage.declared.append(self.name)
562 if self.basemessage.dynamic == "yes" and not self.subtype == "DisplayLabel":
563 if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
564 ret += self.indent_out('uint32_t %s_len = 0;\n' %self.name)
565 self.basemessage.declared.append(self.name + '_len')
567 global fieldsArray
568 if self.name not in fieldsArray:
569 fieldsArray[self.name] = '{&hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
570 return ret
572 def dissect(self):
573 ret = ''
575 if self.declare == "yes" and self.size != "VariableDirnumSize":
576 ret += self.indent_out('const char * %s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(self.name, self.size))
578 if self.subtype == "DisplayLabel":
579 if self.basemessage.dynamic == "yes":
580 ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, 0);\n' %(self.name))
581 elif self.size_fieldname:
582 ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size_fieldname))
583 else:
584 ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size))
586 elif self.basemessage.dynamic == "yes":
587 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
588 ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
589 if self.name in si_fields.keys():
590 ret += self.indent_out(' %s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(si_fields[self.name], self.name))
591 ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, %s_len, ENC_ASCII);\n' %(self.name, self.name))
592 ret += self.indent_out('} else {\n')
593 ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
594 ret += self.indent_out('}\n')
595 elif self.size_fieldname:
596 if self.name in si_fields.keys():
597 ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size_fieldname))
598 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII);\n' %(self.name, self.size_fieldname))
599 else:
600 if self.name in si_fields.keys():
601 ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size))
602 if self.make_additional_info == "yes":
603 ret += self.indent_out('uint32_t %s_len;\n' %(self.name))
604 if self.size=="VariableDirnumSize":
605 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), VariableDirnumSize)+1;\n' %(self.name))
606 else:
607 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 24)+1;\n' %(self.name))
608 ret += self.indent_out('if (%s_len > 1) {\n' %(self.name))
609 self.incr_indent()
610 ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%%s\\"", tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(self.name))
611 self.decr_indent()
612 ret += self.indent_out('}\n')
614 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII);\n' %(self.name, self.size))
616 return ret
618 class Ether(DataNode):
619 def __init__(self):
620 DataNode.__init__(self)
622 def __str__(self):
623 return '%s:%s' %(self.__class__,self.name)
625 def declaration(self):
626 ret = ''
627 self.intsize = 6
628 if self.size:
629 self.intsize = int(self.size)
630 elif self.maxsize and self.basemessage.dynamic == "no":
631 self.intsize = int(self.maxsize)
633 if self.declare == "yes":
634 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
635 ret += self.indent_out('uint32_t %s = 0;\n' %self.name)
636 self.basemessage.declared.append(self.name)
638 if self.basemessage.dynamic == "yes":
639 if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
640 ret += self.indent_out('uint32_t %s_len = 0;\n' %self.name)
641 self.basemessage.declared.append(self.name + '_len')
643 global fieldsArray
644 if self.name not in fieldsArray:
645 fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_ETHER, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
646 return ret
648 def dissect(self):
649 ret = ''
651 if self.basemessage.dynamic == "yes":
652 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
653 ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
654 ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
655 ret += self.indent_out(' ptvcursor_advance(cursor, %s_len - 6);\n' %(self.name))
656 ret += self.indent_out('} else {\n')
657 ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
658 ret += self.indent_out('}\n')
659 elif self.size_fieldname:
660 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
661 ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size_fieldname))
662 else:
663 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
664 ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size))
665 return ret
667 class BitField(DataNode):
668 def __init__(self):
669 DataNode.__init__(self)
671 def __str__(self):
672 return '%s:%s' %(self.__class__,self.name)
674 def declaration(self):
675 global fieldsArray
676 ret = ''
677 int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1}
678 self.intsize = 0
679 if self.size in int_sizes:
680 self.intsize = int_sizes[self.size]
682 for entries in self.entries:
683 for entry in entries.entry:
684 if entry.name not in fieldsArray:
685 fieldsArray[entry.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_BOOLEAN, %d, TFS(&tfs_yes_no), %s,\n %s, HFILL }},\n' %(entry.name, entry.text, entry.name.replace("_","."), self.intsize * 8, entry.value, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
687 return ret
689 def dissect(self):
690 ret = ''
691 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
692 for entries in self.entries:
693 for entry in entries.entry:
694 ret += self.indent_out('ptvcursor_add_no_advance(cursor, hf_skinny_%s, %d, ENC_LITTLE_ENDIAN);\n' %(entry.name, self.intsize))
695 ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.intsize))
696 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end bitfield: %s */\n' %(self.name))
699 return ret
701 class Ip(DataNode):
702 def __init__(self):
703 DataNode.__init__(self)
704 self.intsize = 4
705 if self.type == "ipv6":
706 self.intsize = 16
708 def __str__(self):
709 return '%s:%s' %(self.__class__,self.name)
711 def declaration(self):
712 global fieldsArray
713 if self.name not in fieldsArray:
714 if self.type == "ipv4":
715 fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
716 else:
717 fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
718 return ''
720 def dissect(self):
721 if self.type == "ipv4":
722 return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 4, ENC_BIG_ENDIAN);\n' %self.name)
723 else:
724 return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 16, ENC_NA);\n' %self.name)
726 class Ipv4or6(DataNode):
727 def __init__(self):
728 DataNode.__init__(self)
729 self.intsize = 4
730 if self.endianness is None:
731 self.intsize += 16
733 def __str__(self):
734 return '%s:%s' %(self.__class__,self.name)
736 def declaration(self):
737 global fieldsArray
739 ret = ''
740 name = self.name + '_ipv4'
741 if name not in fieldsArray:
742 fieldsArray[name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(name, self.name + ' IPv4 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
743 name = self.name + '_ipv6'
744 if name not in fieldsArray:
745 fieldsArray[name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(name, self.name + ' IPv6 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
746 if self.make_additional_info == "yes":
747 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
748 ret += self.indent_out('address %s;\n' %(self.name))
749 ret += self.indent_out('char *%s_str = NULL;\n' %(self.name))
750 self.basemessage.declared.append(self.name)
752 return ret
754 def dissect(self):
755 ret = ''
756 if self.make_additional_info == "yes":
757 ret += self.indent_out('read_skinny_ipv4or6(cursor, &%s);\n' %(self.name))
758 ret += self.indent_out('dissect_skinny_ipv4or6(cursor, hf_skinny_%s_ipv4, hf_skinny_%s_ipv6);\n' %(self.name, self.name))
759 return ret
761 class XML(DataNode):
762 def __init__(self):
763 DataNode.__init__(self)
764 self.intsize = 0
766 def __str__(self):
767 return '%s:%s' %(self.__class__,self.name)
769 def declaration(self):
770 global fieldsArray
772 if self.size:
773 self.intsize = int(self.size)
774 elif self.maxsize:
775 self.intsize = int(self.maxsize)
777 if self.name not in fieldsArray:
778 fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
779 return ''
781 def dissect(self):
782 ret = ''
783 if self.size_fieldname:
784 ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, %s, %d);\n' %(self.name, self.size_fieldname, self.intsize))
785 else:
786 ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, 0, %d);\n' %(self.name, self.intsize))
787 return ret
789 class Code(DataNode):
790 def __init__(self):
791 DataNode.__init__(self)
793 def __str__(self):
794 return '%s:%s' %(self.__class__,self.name)
796 def declaration(self):
797 return ''
799 def dissect(self):
800 ret = ''
801 if self.type == "calling_and_called_party":
802 params = self.use_param.split(',')
803 ret += self.indent_out('if (si->%s && si->%s) {\n' %(params[0], params[1]))
804 self.incr_indent()
805 ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%%s -> %%s\\"", si->%s, si->%s);\n' %(params[0], params[1]))
806 self.decr_indent()
807 ret += self.indent_out('}\n')
808 return ret
810 class Struct(DataNode):
811 def __str__(self):
812 return '// Struct : %s / %s / %s / %s\n' %(self.name, self.size, self.field_sizename, self.maxsize)
814 def declaration(self):
815 ret = ''
817 if (self.fields is not None and len(self.fields)):
818 if (len(self.fields) > 1):
819 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
820 ret += self.indent_out("uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
821 self.basemessage.declared.append("hdr_version")
822 for fields in self.fields:
823 ret += '%s' %fields.declaration()
824 #self.intsize += fields.intsize
825 self.intsize = fields.intsize
826 return ret
828 def dissect(self):
829 ret = ''
830 variable = 'counter_%d' %indentation
831 size = 0
833 if self.size_fieldname:
834 #if self.basemessage.dynamic == "yes":
835 # size = self.size_fieldname
836 #else:
837 # size = self.maxsize
838 size = self.maxsize
839 elif self.size:
840 size = self.size
842 if size:
843 if self.size_fieldname:
844 ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb struct size guard */' if debug else ''))
845 else:
846 ret += self.indent_out('{\n')
847 self.incr_indent()
848 if debug:
849 ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
850 ret += self.indent_out('uint32_t %s = 0;\n' %(variable))
851 if self.size_fieldname:
852 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref:%s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, self.maxsize, self.size_fieldname))
853 if self.maxsize:
854 ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s) && %s <= %s) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, self.size_fieldname, self.maxsize, '/* tvb counter size guard */' if debug else ''))
855 else:
856 ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s)) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, '/* tvb counter size guard */' if debug else ''))
857 self.incr_indent()
858 else:
859 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
861 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable))
862 if self.basemessage.dynamic == "no" and self.size_fieldname:
863 self.incr_indent()
864 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
865 self.incr_indent()
866 else:
867 if debug:
868 ret += self.indent_out('{ /* start struct : %s / size: %d */\n' %(self.name, self.intsize))
869 else:
870 ret += self.indent_out('{\n')
871 self.incr_indent()
872 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
874 if size:
875 if self.size_fieldname:
876 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, self.size_fieldname))
877 else:
878 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, size))
880 if (self.fields is not None and len(self.fields)):
881 for fields in self.fields:
882 ret += '%s' %fields.dissect()
884 if self.basemessage.dynamic == "no" and self.size_fieldname:
885 self.decr_indent()
886 ret += self.indent_out('} else {\n')
887 ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %(self.intsize))
888 ret += self.indent_out('}\n')
890 if size:
891 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
892 self.decr_indent()
893 if debug:
894 ret += self.indent_out('} /* end for loop tree: %s */\n' %self.name)
895 else:
896 ret += self.indent_out('}\n')
897 if self.size_fieldname:
898 self.decr_indent()
899 ret += self.indent_out('} /* end counter tvb size guard */\n' if debug else '}\n')
901 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
902 if debug:
903 ret += self.indent_out('/* end struct: %s */\n' %self.name)
904 self.decr_indent()
905 if self.size_fieldname:
906 ret += self.indent_out('} else {\n')
907 self.incr_indent()
908 ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(self.size_fieldname, self.intsize, ' /* guard kicked in -> skip the rest */' if debug else ''))
909 self.decr_indent()
910 ret += self.indent_out('} /* end struct size guard */\n' if debug else '}\n')
912 return ret
914 class Union(DataNode):
915 def __str__(self):
916 return '%s:%s' %(self.__class__,self.name)
918 def declaration(self):
919 ret = ''
920 self.maxsize = 0
921 if (self.fields is not None and len(self.fields)):
922 if (len(self.fields) > 1):
923 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
924 ret += self.indent_out("uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
925 self.basemessage.declared.append("hdr_version")
926 for fields in self.fields:
927 ret += '%s' %fields.declaration()
928 previous_lookup_eq = fields._children[0].lookup_eq
929 previous_lookup_le = fields._children[0].lookup_le
930 previous_lookup_ge = fields._children[0].lookup_ge
931 self.runningtotal = 0
932 for field in fields._children:
933 if previous_lookup_eq != field.lookup_eq or previous_lookup_le != field.lookup_le or previous_lookup_ge == field.lookup_ge:
934 previous_lookup_eq = field.lookup_eq
935 previous_lookup_le = field.lookup_le
936 previous_lookup_ge = field.lookup_ge
937 self.runningtotal = 0
939 self.runningtotal += field.intsize
940 if self.runningtotal > self.maxsize:
941 self.maxsize = self.runningtotal
943 self.intsize = self.maxsize
945 return ret
947 def dissect(self):
948 ret = ''
949 ifblock = self.indent_out('if')
950 #ret += self.indent_out('/* Union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
952 if (self.fields is not None and len(self.fields)):
953 for fields in self.fields:
954 for field in fields._children:
955 if self.lookup_guide and (field.lookup_ge or field.lookup_le or field.lookup_eq):
956 lookupguide = self.lookup_guide
957 # start block
958 subtree_text = ''
959 if field.lookup_ge and field.lookup_le:
960 ret += '%s (%s >= %s && %s <= %s)' %(ifblock, lookupguide, field.lookup_ge.upper(), lookupguide, field.lookup_le.upper())
961 subtree_text = "%s <= %s <= %s" %(field.lookup_ge, lookupguide, field.lookup_le)
962 elif field.lookup_ge:
963 ret += '%s (%s >= %s)' %(ifblock, lookupguide, field.lookup_ge.upper())
964 subtree_text = "%s >= %s" %(lookupguide, field.lookup_ge)
965 elif field.lookup_le:
966 ret += '%s (%s <= %s)' %(ifblock, lookupguide, field.lookup_le.upper())
967 subtree_text = "%s <= %s" %(lookupguide, field.lookup_le)
968 elif field.lookup_eq:
969 if field.lookup_eq == "*":
970 ret += ' else'
971 subtree_text = "any %s" %(lookupguide)
972 elif field.lookup_eq == "skip":
973 continue
974 else:
975 ret += '%s (%s == %s)' %(ifblock, lookupguide, field.lookup_eq.upper())
976 subtree_text = "%s is %s" %(lookupguide, field.lookup_eq)
978 ret += self.indent_out(' {\n')
979 self.incr_indent()
980 if debug:
981 ret += self.indent_out('/* start union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
982 currsize = 0
983 # dissect field
985 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %subtree_text)
986 ret += '%s' %field.dissect()
987 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
989 currsize += field.intsize
991 # compensate length
992 if (self.maxsize - currsize) > 0:
993 ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.maxsize - currsize))
995 self.decr_indent()
997 # close block
998 ret += self.indent_out('}')
999 ifblock = ' else if'
1000 else:
1001 ret += '/* ERROR %s, missing lookup_guide */' %field.dissect()
1002 ret += '\n'
1004 return ret
1006 class TreeBuilder(xml.sax.handler.ContentHandler):
1007 def __init__(self):
1008 self.stack = []
1009 self.root = DataNode()
1010 self.previous = self.root
1011 self.current = self.root
1012 self.basemessage = None
1013 self.text_parts = []
1014 def startElement(self, name, attrs):
1015 objecttype = {"message": Message(), "fields": Fields(), "enum" : Enum(), "bitfield" : BitField(), "struct": Struct(), "union": Union(), "integer": Integer(), "string": String(), "ether": Ether(), "ip": Ip(), "ipv4or6": Ipv4or6(), "xml": XML(), "code": Code()}
1016 self.previous = self.current
1017 self.stack.append((self.current, self.text_parts))
1018 if name in objecttype.keys():
1019 self.current = objecttype[name]
1020 else:
1021 self.current = DataNode()
1022 if name == "message":
1023 self.basemessage = self.current
1024 self.text_parts = []
1025 #self.children = []
1026 self.current.parent = self.previous
1027 self.current.basemessage = self.basemessage
1028 # xml attributes --> python attributes
1029 for k, v in list(attrs.items()):
1030 self.current._add_xml_attr(_name_mangle(k), v)
1032 def endElement(self, name):
1033 text = ''.join(self.text_parts).strip()
1034 if text:
1035 self.current.data = text
1036 if self.current._attrs:
1037 obj = self.current
1038 else:
1039 # a text only node is simply represented by the string
1040 obj = text or ''
1041 self.current, self.text_parts = self.stack.pop()
1042 self.current._add_xml_attr(_name_mangle(name), obj)
1043 self.current._add_child(_name_mangle(name), obj)
1044 def characters(self, content):
1045 self.text_parts.append(content)
1047 builder = TreeBuilder()
1048 xml.sax.parse(src, builder)
1049 return list(builder.root._attrs.values())[0]
1051 # skinny = xml2obj('SkinnyProtocolOptimized.xml')
1052 # for message in skinny.message:
1053 # print '%s' %message.dissect()
1055 #if __name__ == '__main__':
1056 # import timeit
1057 # print(timeit.timeit("generateMessageDissectors()", setup="from __main__ import generateMessageDissectors"))
1060 #skinny = xml2obj('SkinnyProtocolOptimized.xml')
1061 #for message in skinny.message:
1062 # print(message)
1063 # message.dissect()
1065 #for key,value in fieldsArray.items():
1066 # print "%s : %s" %(key,value)
1067 #print '%r\n' %fieldsArray
1069 #skinny = xml2obj('SkinnyProtocolOptimized.xml')
1070 #for message in skinny.message:
1071 # print message.declaration()