On Thu, Jul 23, 2015 at 08:07:32AM -0400, Frediano Ziglio wrote: > Support ws_txt and ws_txt_n attributes. > These attributes are there to allow to set specific text to different > elements. 'on different elements' ? > The can be used to output in a single line the features of a structure. 'They can be used' > Or they can be used to format small array items. > They can applied to almost everything from primitives, arrays, > structure or even pointers. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > codegen/dissector_test.c | 28 ++++++ > codegen/out_array_raw.txt | 4 +- > codegen/out_array_struct.txt | 52 ++++++----- > codegen/out_struct1.txt | 13 +-- > python_modules/dissector.py | 205 +++++++++++++++++++++++++++++++++++++++---- > 5 files changed, 256 insertions(+), 46 deletions(-) > > Changed: > - compatibility with Python 3 > > diff --git a/codegen/dissector_test.c b/codegen/dissector_test.c > index 96b3107..84abacf 100644 > --- a/codegen/dissector_test.c > +++ b/codegen/dissector_test.c > @@ -276,6 +276,34 @@ WS_DLL_PUBLIC proto_tree* proto_item_add_subtree(proto_item *ti, const gint idx) > return res; > } > > +WS_DLL_PUBLIC void proto_item_set_end(proto_item *ti, tvbuff_t *tvb, gint end) > +{ > + assert(tvb); > + assert(end >= 0); > + if (!ti) > + return; > + check_item(ti); > + tvb_bytes(tvb, 0, end); > + assert(ti->finfo->start <= end); > + ti->finfo->length = end - ti->finfo->start; > + check_item(ti); > +} > + > +WS_DLL_PUBLIC void proto_item_set_text(proto_item *ti, const char *format, ...) > +{ > + va_list ap; > + assert(format); > + if (!ti) > + return; > + > + check_item(ti); > + va_start(ap, format); > + vsnprintf(ti->finfo->rep->representation, sizeof(ti->finfo->rep->representation), > + format, ap); > + va_end(ap); > + check_item(ti); > +} > + > struct all_ti > { > proto_item ti; > diff --git a/codegen/out_array_raw.txt b/codegen/out_array_raw.txt > index f276871..31b510c 100644 > --- a/codegen/out_array_raw.txt > +++ b/codegen/out_array_raw.txt > @@ -1,5 +1,3 @@ > --- tree > --- item > - Text: > - Name: array > - Abbrev: spice2.auto.ArrayRaw_array_array > + Text: array > diff --git a/codegen/out_array_struct.txt b/codegen/out_array_struct.txt > index eb03cd8..53d28ef 100644 > --- a/codegen/out_array_struct.txt > +++ b/codegen/out_array_struct.txt > @@ -1,25 +1,37 @@ > --- tree > --- item > - Text: 0 (0) > - Name: dummy > - Abbrev: spice2.auto.Dummy_dummy > - Type: FT_UINT16 > - Base: BASE_DEC > + Text: Dummy > + --- tree > + --- item > + Text: 0 (0) > + Name: dummy > + Abbrev: spice2.auto.Dummy_dummy > + Type: FT_UINT16 > + Base: BASE_DEC > --- item > - Text: 1 (0x1) > - Name: dummy > - Abbrev: spice2.auto.Dummy_dummy > - Type: FT_UINT16 > - Base: BASE_DEC > + Text: Dummy > + --- tree > + --- item > + Text: 1 (0x1) > + Name: dummy > + Abbrev: spice2.auto.Dummy_dummy > + Type: FT_UINT16 > + Base: BASE_DEC > --- item > - Text: 2 (0x2) > - Name: dummy > - Abbrev: spice2.auto.Dummy_dummy > - Type: FT_UINT16 > - Base: BASE_DEC > + Text: Dummy > + --- tree > + --- item > + Text: 2 (0x2) > + Name: dummy > + Abbrev: spice2.auto.Dummy_dummy > + Type: FT_UINT16 > + Base: BASE_DEC > --- item > - Text: 3 (0x3) > - Name: dummy > - Abbrev: spice2.auto.Dummy_dummy > - Type: FT_UINT16 > - Base: BASE_DEC > + Text: Dummy > + --- tree > + --- item > + Text: 3 (0x3) > + Name: dummy > + Abbrev: spice2.auto.Dummy_dummy > + Type: FT_UINT16 > + Base: BASE_DEC > diff --git a/codegen/out_struct1.txt b/codegen/out_struct1.txt > index a1d429c..993e77c 100644 > --- a/codegen/out_struct1.txt > +++ b/codegen/out_struct1.txt > @@ -1,7 +1,10 @@ > --- tree > --- item > - Text: 33154 (0x8182) > - Name: dummy > - Abbrev: spice2.auto.Dummy_dummy > - Type: FT_UINT16 > - Base: BASE_DEC > + Text: Dummy > + --- tree > + --- item > + Text: 33154 (0x8182) > + Name: dummy > + Abbrev: spice2.auto.Dummy_dummy > + Type: FT_UINT16 > + Base: BASE_DEC > diff --git a/python_modules/dissector.py b/python_modules/dissector.py > index f08cf0f..c4b0749 100644 > --- a/python_modules/dissector.py > +++ b/python_modules/dissector.py > @@ -3,6 +3,7 @@ from . import ptypes > from . import codegen > import re > > +from contextlib import contextmanager > import sys > import types > > @@ -196,6 +197,7 @@ class Destination: > self.reuse_scope = scope > self.parent_dest = None > self.level = Level() > + self.index = None > > def child_sub(self, member, scope): > return SubDestination(self, member, scope) > @@ -293,7 +295,6 @@ def get_primitive_ft_type(t): > # write a field > def write_wireshark_field(writer, container, member, t, ws, tree, dest, size, encoding='ENC_LITTLE_ENDIAN', prefix=''): > > - assert(member and container) > > size_name = '' > > @@ -344,7 +345,17 @@ def write_wireshark_field(writer, container, member, t, ws, tree, dest, size, en > > # read name > ws_name = ws.name > + > + # TODO change entirely to catch flags with same name in different places > + # read all forces, check not changed at end dump > + > if not ws_name: > + # write a text only item > + if (f_type, base, vals) == ('FT_NONE', 'BASE_NONE', 'NULL'): > + stmt = "%sproto_tree_add_text(%s, glb->tvb, offset, %s, \"%s\")" % (prefix, tree, size, desc) > + writer.statement(stmt) > + return > + > hf_name = member_hf_name(container, member) > ws_name = 'auto.' + hf_name[3:] > else: > @@ -447,24 +458,46 @@ def write_switch(writer, container, switch, dest, scope): > if switch.has_attr("fixedsize"): > writer.assign("output", "save_output + %s" % switch.get_fixed_nw_size()) > > + > +def write_array_core(writer, container, member, nelements, array, dest, scope): > + element_type = array.element_type > + > + with writer.index() as index, writer.for_loop(index, nelements) as array_scope: > + dest.index = index > + if element_type.is_primitive(): > + write_member_primitive(writer, container, member, element_type, WSAttributes(element_type, array.item_attrs), dest, scope) > + else: > + assert(element_type.is_struct()) > + write_struct(writer, member, element_type, index, dest, scope) > + dest.index = None > + > def write_array(writer, container, member, nelements, array, dest, scope): > assert(container and member) > > ws = WSAttributes(array, member.attributes) > > + tree = dest.level.tree > element_type = array.element_type > > + # easy case, binary data > if element_type == ptypes.uint8 or element_type == ptypes.int8: > - write_wireshark_field(writer, container, member, array, ws, dest.level.tree, dest, nelements, 'ENC_NA') > + if not ws.has_txts(): > + write_wireshark_field(writer, container, member, array, ws, tree, dest, nelements, 'ENC_NA') > + else: > + with dest.level: > + if not scope.variable_defined(dest.level.ti): > + scope.variable_def('proto_item *', dest.level.ti) > + write_wireshark_field(writer, container, member, array, ws, tree, dest, nelements, 'ENC_NA', prefix=dest.level.ti + ' = ') > + write_ws_formats(writer, ws, dest) > writer.increment("offset", nelements) > return > > - with writer.index() as index, writer.for_loop(index, nelements) as array_scope: > - if element_type.is_primitive(): > - write_member_primitive(writer, container, member, element_type, WSAttributes(element_type, array.item_attrs), dest, scope) > - else: > - assert(element_type.is_struct()) > - write_struct(writer, member, element_type, index, dest, scope) > + # just the core > + if not ws.desc and not ws.name and not ws.has_txts(): > + write_array_core(writer, container, member, nelements, array, dest, scope) > + else: > + with tree_item(writer, scope, ws, array, dest): > + write_array_core(writer, container, member, nelements, array, dest, scope) > > > def write_ptr_function(writer, target_type, container, member, dest, scope): > @@ -505,8 +538,15 @@ def write_pointer(writer, container, member, t, dest, scope): > assert(t.is_pointer()) > > if not scope.variable_defined('ptr'): > + # TODO correct pointer > scope.variable_def('guint32', 'ptr') > + > + ws = WSAttributes(ptypes.uint32, t.attributes) > + if ws.name: > + with tree_item(writer, scope, ws, ptypes.uint32, dest, has_subtree=False): > + pass > read_ptr(writer, t) > + > with writer.if_block('ptr'): > writer.variable_def('guint32', 'save_offset = offset') > writer.assign('offset', 'ptr + glb->message_offset') > @@ -519,6 +559,117 @@ def write_pointer(writer, container, member, t, dest, scope): > writer.assign('offset', 'save_offset') > > > +def get_ws_txt_formats(txt, dest): > + if txt is None: > + return None > + > + fmt = txt[0].replace('%%',chr(1)*2).split('%') > + if len(fmt) != len(txt): > + raise Exception('Wrong number of formatting argument in %s' % fmt) > + fmts = [fmt[0]] > + s = '' > + # parse all fields > + for f, fld in list(zip(fmt, txt))[1:]: > + s += ', ' > + if fld == 'INDEX': > + assert dest.index, 'INDEX variable not found' > + s += dest.index > + else: > + s += dest.read_ref(fld) > + size = dest.ref_size(fld) > + if size > 32: > + f = '" G_GINT%d_MODIFIER "' % size + f > + fmts.append(f) > + fmt = '%'.join(fmts).replace(chr(1), '%') > + s = '"%s"' % fmt + s > + return s > + > + > +# TODO ugly the fmt part > +def write_ws_formats(writer, ws, dest, fmt=None, formats=None): > + formats = get_ws_txt_formats(ws.txt, dest) if formats is None else formats > + formats_n = get_ws_txt_formats(ws.txt_n, dest) > + if not fmt: > + fmt = 'proto_item_set_text(%s, %%s)' % dest.level.ti > + if formats_n: > + assert dest.index, "ws_txt_n specified without an active index" > + with writer.if_block('%s != -1' % dest.index, newline=False): > + writer.statement(fmt % formats_n) > + if formats: > + with writer.block(' else ', newline=False): > + writer.statement(fmt % formats) > + writer.newline() > + elif formats: > + writer.statement(fmt % formats) > + > + > +# write a new tree > +@contextmanager > +def tree_item(writer, scope, ws, t, dest, has_subtree=True): > + # at enter generate the subtree > + size_written = t.is_fixed_nw_size() > + size = t.get_fixed_nw_size() if size_written else 1 > + need_treeitem = has_subtree or not size_written > + def declare_ti(): > + if need_treeitem and not scope.variable_defined(dest.level.ti): > + scope.variable_def('proto_item *', dest.level.ti) > + txt_done = False > + if not ws.name: > + can_format = False > + # TODO ugly > + fmt = "proto_tree_add_text(%s, glb->tvb, offset, %s, %%s)" % (dest.level.tree, size) > + try: > + txt = get_ws_txt_formats(ws.txt, dest) > + txt_n = get_ws_txt_formats(ws.txt_n, dest) > + can_format = True > + except: > + pass > + if can_format and ws.has_txts() and (txt is not None or ws.desc): > + if ws.txt is None and ws.desc: > + txt = '"%s"' % ws.desc.replace('%','%%') > + if need_treeitem: > + declare_ti() > + fmt = dest.level.ti + ' = ' + fmt > + write_ws_formats(writer, ws, dest, fmt=fmt, formats=txt) > + txt_done = True > + else: > + if not txt_done and ws.has_txts(): > + need_treeitem = True > + can_format = False > + desc = ws.desc > + if desc is None and t.is_struct(): > + desc = t.name > + txt = '"%s"' % desc.replace('%','%%') > + if need_treeitem: > + declare_ti() > + fmt = dest.level.ti + ' = ' + fmt > + writer.statement(fmt % txt) > + else: > + if not txt_done and ws.has_txts(): > + need_treeitem = True > + prefix = '' > + if need_treeitem: > + declare_ti() > + prefix = dest.level.ti + ' = ' > + write_wireshark_field(writer, None, None, t, ws, dest.level.tree, dest, size, 'ENC_LITTLE_ENDIAN', prefix=prefix) > + > + ti = dest.level.ti > + with dest.level: > + if has_subtree: > + if not scope.variable_defined(dest.level.tree): > + scope.variable_def('proto_tree *', dest.level.tree) > + ett_name = new_ett(writer) > + writer.assign(dest.level.tree, 'proto_item_add_subtree(%s, %s)' % (ti, ett_name)) > + > + yield scope > + > + # at exit fix length and write possible text > + if not size_written: > + writer.statement('proto_item_set_end(%s, glb->tvb, offset)' % dest.level.ti) > + if not txt_done and ws.has_txts(): > + write_ws_formats(writer, ws, dest) > + > + > def write_struct_func(writer, t, func_name, index): > func_name = 'dissect_spice_struct_' + t.name > > @@ -529,7 +680,11 @@ def write_struct_func(writer, t, func_name, index): > writer = writer.function_helper() > scope = writer.function(func_name, "guint32", "GlobalInfo *glb _U_, proto_tree *tree _U_, guint32 offset, gint32 index _U_", True) > dest = RootDestination(scope) > - write_container_parser(writer, t, dest) > + dest.index = 'index' > + if not t.is_fixed_nw_size() or t.get_fixed_nw_size() != 0: > + ws = WSAttributes(t) > + with tree_item(writer, scope, ws, t, dest): > + write_container_parser(writer, t, dest) > writer.statement('return offset') > writer.end_block() > > @@ -538,7 +693,9 @@ def write_struct(writer, member, t, index, dest, scope): > > if member.has_attr('ws_inline'): > dest = dest.child_sub(member.name, scope) > - with writer.block() as scope: > + dest.index = 'index' > + ws = WSAttributes(t, member.attributes) > + with writer.block() as scope, tree_item(writer, scope, ws, t, dest): > write_container_parser(writer, t, dest) > else: > func_name = 'dissect_spice_struct_' + t.name > @@ -603,19 +760,24 @@ def write_flags(writer, container, member, t, ws, tree, dest): > ws_func = WSAttributes(t) > > own_ti = ws.name != ws_func.name or ws.desc != ws_func.desc or ws.base != ws_func.base > - if not own_ti: > + if not own_ti and not ws.has_txts(): > stmt = write_flags_func(writer, t, ws_func, tree, 'NULL') > writer.statement(stmt) > return > > - tree = dest.level.tree > + # write reference to allows txt to read it > + dest.write_ref(writer, t.get_fixed_nw_size() * 8, member.name, '%s(glb->tvb, offset)' % primitive_read_func(t)) > + > + # write flags and override texts > with writer.block() as scope, dest.level: > scope.variable_def('proto_item *', dest.level.ti) > - size = t.get_fixed_nw_size() > - int_type = ptypes.IntegerType(size*8, False) > - write_wireshark_field(writer, container, member, int_type, ws, tree, dest, size, prefix=dest.level.ti + ' = ') > + if own_ti: > + size = t.get_fixed_nw_size() > + int_type = ptypes.IntegerType(size*8, False) > + write_wireshark_field(writer, container, member, int_type, ws, tree, dest, size, prefix=dest.level.ti + ' = ') > stmt = write_flags_func(writer, t, ws_func, tree, dest.level.ti) > - writer.statement(stmt) > + writer.assign(dest.level.ti, stmt) > + write_ws_formats(writer, ws, dest) > > > def write_member_primitive(writer, container, member, t, ws, dest, scope): > @@ -623,13 +785,20 @@ def write_member_primitive(writer, container, member, t, ws, dest, scope): > > if member.has_attr("bytes_count"): > raise NotImplementedError("bytes_count not implemented") > - > - write_wireshark_field(writer, container, member, t, ws, dest.level.tree, dest, t.get_fixed_nw_size()) > if member.has_attr("bytes_count"): > dest_var = member.attributes["bytes_count"][0] > else: > dest_var = member.name > dest.write_ref(writer, t.get_fixed_nw_size() * 8, dest_var, '%s(glb->tvb, offset)' % primitive_read_func(t)) > + > + if not ws.has_txts(): > + write_wireshark_field(writer, container, member, t, ws, dest.level.tree, dest, t.get_fixed_nw_size()) > + else: > + if not scope.variable_defined(dest.level.ti): > + scope.variable_def('proto_item *', dest.level.ti) > + write_wireshark_field(writer, container, member, t, ws, dest.level.tree, dest, t.get_fixed_nw_size(), prefix=dest.level.ti + ' = ') > + write_ws_formats(writer, ws, dest) > + > writer.increment("offset", t.get_fixed_nw_size()) > > def write_member(writer, container, member, dest, scope): > -- > 2.1.0 > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpeP4TtgXbgB.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel