3 # Script to convert xcbproto and mesa protocol files for
4 # X11 dissector. Creates header files containing code to
5 # dissect X11 extensions.
7 # Copyright 2008, 2009 Open Text Corporation <pharris[AT]opentext.com>
11 # Wireshark - Network traffic analyzer
12 # By Gerald Combs <gerald@wireshark.org>
13 # Copyright 1998 Gerald Combs
15 # This program is free software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public License
17 # as published by the Free Software Foundation; either version 2
18 # of the License, or (at your option) any later version.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 # - look ahead to see if values are ever used again before creating an "int" in the output
32 # - support constructs that are legal in XCB, but don't appear to be used
44 my @reslist = grep {!/xproto\.xml$/} glob File
::Spec
->catfile('xcbproto', 'src', '*.xml');
48 char
=> { size
=> 1, encoding
=> 'ENC_ASCII|ENC_NA', type
=> 'FT_STRING', base
=> 'BASE_NONE', get
=> 'VALUE8', list
=> 'listOfByte', },
49 void
=> { size
=> 1, encoding
=> 'ENC_NA', type
=> 'FT_BYTES', base
=> 'BASE_NONE', get
=> 'VALUE8', list
=> 'listOfByte', },
50 BYTE
=> { size
=> 1, encoding
=> 'ENC_NA', type
=> 'FT_BYTES', base
=> 'BASE_NONE', get
=> 'VALUE8', list
=> 'listOfByte', },
51 CARD8
=> { size
=> 1, encoding
=> 'byte_order', type
=> 'FT_UINT8', base
=> 'BASE_HEX_DEC', get
=> 'VALUE8', list
=> 'listOfByte', },
52 CARD16
=> { size
=> 2, encoding
=> 'byte_order', type
=> 'FT_UINT16', base
=> 'BASE_HEX_DEC', get
=> 'VALUE16', list
=> 'listOfCard16', },
53 CARD32
=> { size
=> 4, encoding
=> 'byte_order', type
=> 'FT_UINT32', base
=> 'BASE_HEX_DEC', get
=> 'VALUE32', list
=> 'listOfCard32', },
54 INT8
=> { size
=> 1, encoding
=> 'byte_order', type
=> 'FT_INT8', base
=> 'BASE_DEC', get
=> 'VALUE8', list
=> 'listOfByte', },
55 INT16
=> { size
=> 2, encoding
=> 'byte_order', type
=> 'FT_INT16', base
=> 'BASE_DEC', get
=> 'VALUE16', list
=> 'listOfInt16', },
56 INT32
=> { size
=> 4, encoding
=> 'byte_order', type
=> 'FT_INT32', base
=> 'BASE_DEC', get
=> 'VALUE32', list
=> 'listOfInt32', },
57 float
=> { size
=> 4, encoding
=> 'byte_order', type
=> 'FT_FLOAT', base
=> 'BASE_NONE', get
=> 'FLOAT', list
=> 'listOfFloat', },
58 double
=> { size
=> 8, encoding
=> 'byte_order', type
=> 'FT_DOUBLE', base
=> 'BASE_NONE', get
=> 'DOUBLE', list
=> 'listOfDouble', },
59 BOOL
=> { size
=> 1, encoding
=> 'byte_order', type
=> 'FT_BOOLEAN',base
=> 'BASE_NONE', get
=> 'VALUE8', list
=> 'listOfByte', },
62 my %simpletype; # Reset at the beginning of each extension
63 my %gltype; # No need to reset, since it's only used once
65 my %struct = # Not reset; contains structures already defined.
66 # Also contains this black-list of structures never used by any
67 # extension (to avoid generating useless code).
69 # structures defined by xproto, but not used by any extension
78 SetupAuthenticate
=> 1,
88 # structures defined by xinput, but never used (except by each other)(bug in xcb?)
96 KbdFeedbackState
=> 1,
97 PtrFeedbackState
=> 1,
98 IntegerFeedbackState
=> 1,
99 StringFeedbackState
=> 1,
100 BellFeedbackState
=> 1,
101 LedFeedbackState
=> 1,
105 IntegerFeedbackCtl
=> 1,
106 StringFeedbackCtl
=> 1,
107 BellFeedbackCtl
=> 1,
114 DeviceResolutionState
=> 1,
115 DeviceAbsCalibState
=> 1,
116 DeviceAbsAreaState
=> 1,
117 DeviceCoreState
=> 1,
118 DeviceEnableState
=> 1,
120 DeviceResolutionCtl
=> 1,
121 DeviceAbsCalibCtl
=> 1,
122 DeviceAbsAreaCtrl
=> 1,
124 DeviceEnableCtrl
=> 1,
126 # structures defined by xv, but never used (bug in xcb?)
129 # structures defined by xkb, but never used (bug in xcb?)
132 my %enum; # Not reset; contains enums already defined.
147 # glRender sub-op output files
150 # Mesa API definitions keep moving
151 my @mesas = ('mesa/src/mapi/glapi/gen', # 2010-04-26
152 'mesa/src/mesa/glapi/gen', # 2010-02-22
153 'mesa/src/mesa/glapi'); # 2004-05-18
154 my $mesadir = (grep { -d
} @mesas)[0];
156 sub mesa_category_start
{
158 my $name = $elt->att('name');
160 if ($name =~ /^\d\.\d$/) {
161 $comment = "version $name";
163 $comment = "extension $name";
166 print $enum "/* OpenGL $comment */\n";
167 print(" - $comment\n");
177 my $name = $elt->att('name');
178 my $value = $elt->att('value');
180 print $enum " { $value, \"$name\" },\n" if (length($value) > 3 && length($value) < 10);
187 my $name = $elt->att('name');
188 my $size = $elt->att('size');
189 my $float = $elt->att('float');
190 my $unsigned = $elt->att('unsigned');
195 if($name eq 'enum') {
196 # enum does not have a direct X equivalent
197 $gltype{'GLenum'} = { size
=> 4, encoding
=> 'byte_order', type
=> 'FT_UINT32', base
=> 'BASE_HEX',
198 get
=> 'VALUE32', list
=> 'listOfCard32',
199 val
=> 'VALS(mesa_enum)', };
204 if (defined($float) && $float eq 'true') {
206 $base = 'double' if ($size == 8);
209 if (defined($unsigned) && $unsigned eq 'true') {
212 $base .= ($size * 8);
214 $base = 'BOOL' if ($name eq 'bool');
215 $base = 'BYTE' if ($name eq 'void');
218 $gltype{$name} = $basictype{$base};
221 sub registered_name
($$)
226 return "hf_x11_$header"."_$name"."_$field";
231 # rop == glRender sub-op
232 # sop == GLX minor opcode
233 my $glx = $elt->first_child('glx');
234 unless(defined $glx) { $t->purge; return; }
236 my $rop = $glx->att('rop');
237 unless (defined $rop) { $t->purge; return; }
239 # Ideally, we want the main name, not the alias name.
240 # Practically, we'd have to scan the file twice to find
241 # the functions that we want to skip.
242 my $alias = $elt->att('alias');
243 if (defined $alias) { $t->purge; return; }
245 my $name = $elt->att('name');
246 $request{$rop} = $name;
251 my @elements = $elt->children('param');
253 # Wireshark defines _U_ to mean "Unused" (compiler specific define)
256 static void mesa_$name(tvbuff_t *tvb _U_, int *offsetp _U_, proto_tree *t _U_, guint byte_order _U_, int length _U_)
262 static void mesa_$name(tvbuff_t *tvb, int *offsetp, proto_tree *t, guint byte_order, int length _U_)
268 foreach my $e (@elements) {
269 # Register field with wireshark
271 my $type = $e->att('type');
272 $type =~ s/^const //;
274 $list = 1 if ($type =~ /\*$/);
277 my $fieldname = $e->att('name');
278 my $regname = registered_name
($name, $fieldname);
280 my $info = $gltype{$type};
281 my $ft = $info->{'type'};
282 my $base = $info->{'base'};
283 my $val = $info->{'val'} // 'NULL';
285 print $decl "static int $regname = -1;\n";
286 if ($list and $info->{'size'} > 1) {
287 print $reg "{ &$regname, { \"$fieldname\", \"x11.glx.render.$name.$fieldname\", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},\n";
289 print $decl "static int $regname = -1;\n";
291 print $reg "{ &$regname, { \"$fieldname\", \"x11.glx.render.$name.$fieldname\", $ft, $base, $val, 0, NULL, HFILL }},\n";
293 if ($e->att('counter')) {
294 print $impl " int $fieldname;\n";
298 if ($e->att('img_format')) {
300 foreach my $wholename (('swap bytes', 'lsb first')) {
302 my $varname = $wholename;
304 my $regname = registered_name
($name, $varname);
305 print $decl "static int $regname = -1;\n";
306 print $reg "{ &$regname, { \"$wholename\", \"x11.glx.render.$name.$varname\", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},\n";
308 foreach my $wholename (('row length', 'skip rows', 'skip pixels', 'alignment')) {
310 my $varname = $wholename;
312 my $regname = registered_name
($name, $varname);
313 print $decl "static int $regname = -1;\n";
314 print $reg "{ &$regname, { \"$wholename\", \"x11.glx.render.$name.$varname\", FT_UINT32, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},\n";
320 # The image requests have a few implicit elements first:
322 foreach my $wholename (('swap bytes', 'lsb first')) {
324 my $varname = $wholename;
326 my $regname = registered_name
($name, $varname);
327 print $impl " proto_tree_add_item(t, $regname, tvb, *offsetp, 1, byte_order);\n";
328 print $impl " *offsetp += 1;\n";
331 print $impl " UNUSED(2);\n";
333 foreach my $wholename (('row length', 'skip rows', 'skip pixels', 'alignment')) {
335 my $varname = $wholename;
337 my $regname = registered_name
($name, $varname);
338 print $impl " proto_tree_add_item(t, $regname, tvb, *offsetp, 4, byte_order);\n";
339 print $impl " *offsetp += 4;\n";
344 foreach my $e (@elements) {
345 my $type = $e->att('type');
346 $type =~ s/^const //;
348 $list = 1 if ($type =~ /\*$/);
351 my $fieldname = $e->att('name');
352 my $regname = registered_name
($name, $fieldname);
354 my $info = $gltype{$type};
355 my $ft = $info->{'type'};
356 my $base = $info->{'base'};
359 my $size = $info->{'size'};
360 my $encoding = $info->{'encoding'};
361 my $get = $info->{'get'};
363 if ($e->att('counter')) {
364 print $impl " $fieldname = $get(tvb, *offsetp);\n";
366 print $impl " proto_tree_add_item(t, $regname, tvb, *offsetp, $size, $encoding);\n";
367 print $impl " *offsetp += $size;\n";
370 # TODO: variable_param
371 my $list = $info->{'list'};
372 my $count = $e->att('count');
373 my $variable_param = $e->att('variable_param');
375 $regname .= ", $regname".'_item' if ($info->{'size'} > 1);
376 if (defined($count) && !defined($variable_param)) {
377 print $impl " $list(tvb, offsetp, t, $regname, $count, byte_order);\n";
379 print $impl " $list(tvb, offsetp, t, $regname, (length - $length) / $gltype{$type}{'size'}, byte_order);\n";
397 given($elt->name()) {
403 when ('value') { $rv = $elt->text(); }
404 when ('op') { $rv = get_op
($elt, $refref); }
405 when (['unop','popcount']) { $rv = get_unop
($elt, $refref); }
406 default { die "Invalid op fragment: $_" }
413 my $refref = shift // {};
415 my @elements = $op->children(qr/fieldref|value|op|unop|popcount/);
416 (@elements == 2) or die ("Wrong number of children for 'op'\n");
420 $left = get_ref
($elements[0], $refref);
421 $right = get_ref
($elements[1], $refref);
423 return "($left " . $op->att('op') . " $right)";
428 my $refref = shift // {};
430 my @elements = $op->children(qr/fieldref|value|op|unop|popcount/);
431 (@elements == 1) or die ("Wrong number of children for 'unop'\n");
434 $left = get_ref
($elements[0], $refref);
436 given ($op->name()) {
438 return '(' . $op->att('op') . "$left)";
441 return "popcount($left)";
443 default { die "Invalid unop element $op->name()\n"; }
447 sub dump_enum_values
($)
451 defined($enum{$e}) or die("Enum $e not found");
453 my $enumname = "x11_enum_$e";
454 return $enumname if (defined $enum{$e}{done
});
456 say $enum 'static const value_string '.$enumname.'[] = {';
458 my $value = $enum{$e}{value
};
459 for my $val (sort { $a <=> $b } keys %$value) {
460 say $enum sprintf("\t{ %3d, \"%s\" },", $val, $$value{$val});
462 say $enum sprintf("\t{ %3d, NULL },", 0);
470 sub register_element
($$$;$);
472 sub register_element
($$$;$)
476 my $humanpat = shift;
477 my $indent = shift // ' ' x
4;
480 when ('pad') { return; } # Pad has no variables
481 when ('switch') { return; } # Switch defines varaibles in a tighter scope to avoid collisions
484 # Register field with wireshark
486 my $fieldname = $e->att('name');
487 my $type = $e->att('type') or die ("Field $fieldname does not have a valid type\n");
490 my $regname = 'hf_x11_'.sprintf ($varpat, $fieldname);
491 my $humanname = 'x11.'.sprintf ($humanpat, $fieldname);
493 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
494 my $ft = $info->{'type'} // 'FT_NONE';
495 my $base = $info->{'base'} // 'BASE_NONE';
498 my $enum = $e->att('enum') // $e->att('altenum');
500 my $enumname = dump_enum_values
($enum_name{$enum});
501 $vals = "VALS($enumname)";
503 # Wireshark does not allow FT_BYTES or BASE_NONE to have an enum
504 $ft =~ s/FT_BYTES/FT_UINT8/;
505 $base =~ s/BASE_NONE/BASE_DEC/;
508 $enum = $e->att('mask');
510 # Create subtree items:
511 defined($enum{$enum_name{$enum}}) or die("Enum $enum not found");
513 # Wireshark does not allow FT_BYTES or BASE_NONE to have an enum
514 $ft =~ s/FT_BYTES/FT_UINT8/;
515 $base =~ s/BASE_NONE/BASE_DEC/;
517 my $bitsize = $info->{'size'} * 8;
519 my $bit = $enum{$enum_name{$enum}}{bit
};
520 for my $val (sort { $a <=> $b } keys %$bit) {
521 my $itemname = $$bit{$val};
522 my $item = $regname . '_mask_' . $itemname;
523 my $itemhuman = $humanname . '.' . $itemname;
524 my $bitshift = "1 << $val";
526 say $decl "static int $item = -1;";
527 say $reg "{ &$item, { \"$itemname\", \"$itemhuman\", FT_BOOLEAN, $bitsize, NULL, $bitshift, NULL, HFILL }},";
531 print $decl "static int $regname = -1;\n";
532 if ($e->name() eq 'list' and $info->{'size'} > 1) {
533 print $reg "{ &$regname, { \"$fieldname\", \"$humanname\", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},\n";
535 print $decl "static int $regname = -1;\n";
537 print $reg "{ &$regname, { \"$fieldname\", \"$humanname\", $ft, $base, $vals, 0, NULL, HFILL }},\n";
539 if ($e->name() eq 'field') {
540 if ($basictype{$type} or $simpletype{$type}) {
541 # Pre-declare variable
542 if ($ft eq 'FT_FLOAT') {
543 print $impl $indent."gfloat f_$fieldname;\n";
544 } elsif ($ft eq 'FT_DOUBLE') {
545 print $impl $indent."gdouble f_$fieldname;\n";
547 print $impl $indent."int f_$fieldname;\n";
553 sub dissect_element
($$$$;$$);
555 sub dissect_element
($$$$;$$)
559 my $humanpat = shift;
561 my $adjustlength = shift;
562 my $indent = shift // ' ' x
4;
566 my $bytes = $e->att('bytes');
567 print $impl $indent."UNUSED($bytes);\n";
571 my $fieldname = $e->att('name');
572 my $regname = 'hf_x11_'.sprintf ($varpat, $fieldname);
573 my $type = $e->att('type');
576 if ($basictype{$type} or $simpletype{$type}) {
577 my $info = $basictype{$type} // $simpletype{$type};
578 my $size = $info->{'size'};
579 my $encoding = $info->{'encoding'};
580 my $get = $info->{'get'};
582 if ($e->att('enum') // $e->att('altenum')) {
583 my $fieldsize = $size * 8;
584 say $impl $indent."f_$fieldname = field$fieldsize(tvb, offsetp, t, $regname, byte_order);";
585 } elsif ($e->att('mask')) {
586 say $impl $indent."f_$fieldname = $get(tvb, *offsetp);";
587 say $impl $indent."{";
588 say $impl $indent." proto_item *ti = proto_tree_add_item(t, $regname, tvb, *offsetp, $size, $encoding);";
589 say $impl $indent." proto_tree *bitmask_tree = proto_item_add_subtree(ti, ett_x11_rectangle);";
591 my $bytesize = $info->{'size'};
592 my $byteencoding = $info->{'encoding'};
593 my $bit = $enum{$enum_name{$e->att('mask')}}{bit
};
594 for my $val (sort { $a <=> $b } keys %$bit) {
595 my $item = $regname . '_mask_' . $$bit{$val};
597 say $impl "$indent proto_tree_add_item(bitmask_tree, $item, tvb, *offsetp, $bytesize, $byteencoding);";
600 say $impl $indent."}";
601 say $impl $indent."*offsetp += $size;";
603 print $impl $indent."f_$fieldname = $get(tvb, *offsetp);\n";
604 print $impl $indent."proto_tree_add_item(t, $regname, tvb, *offsetp, $size, $encoding);\n";
605 print $impl $indent."*offsetp += $size;\n";
608 } elsif ($struct{$type}) {
609 # TODO: variable-lengths (when $info->{'size'} == 0 )
610 my $info = $struct{$type};
611 $length += $info->{'size'};
612 print $impl $indent."struct_$info->{'name'}(tvb, offsetp, t, byte_order, 1);\n";
614 die ("Unrecognized type: $type\n");
618 my $fieldname = $e->att('name');
619 my $regname = 'hf_x11_'.sprintf ($varpat, $fieldname);
620 my $type = $e->att('type');
623 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
624 my $lencalc = "(length - $length) / $info->{'size'}";
625 my $lentype = $e->first_child();
626 if (defined $lentype) {
627 given ($lentype->name()) {
628 when ('value') { $lencalc = $lentype->text(); }
629 when ('fieldref') { $lencalc = 'f_'.$lentype->text(); }
630 when ('op') { $lencalc = get_op
($lentype); }
631 when (['unop','popcount']) { $lencalc = get_unop
($lentype); }
635 if ($basictype{$type} or $simpletype{$type}) {
636 my $list = $info->{'list'};
637 $regname .= ", $regname".'_item' if ($info->{'size'} > 1);
638 print $impl $indent."$list(tvb, offsetp, t, $regname, $lencalc, byte_order);\n";
639 } elsif ($struct{$type}) {
640 print $impl $indent."struct_$info->{'name'}(tvb, offsetp, t, byte_order, $lencalc);\n";
642 die ("Unrecognized type: $type\n");
645 if ($adjustlength && defined($lentype)) {
646 # Some requests end with a list of unspecified length
647 # Adjust the length field here so that the next $lencalc will be accurate
648 say $impl $indent."length -= $lencalc * $info->{'size'};";
652 my $switchtype = $e->first_child() or die("Switch element not defined");
654 my $switchon = get_ref
($switchtype, {});
655 my @elements = $e->children('bitcase');
656 for my $case (@elements) {
657 my $ref = $case->first_child('enumref');
658 my $enum_ref = $ref->att('ref');
659 my $field = $ref->text();
660 my $bit = $enum{$enum_name{$enum_ref}}{rbit
}{$field};
661 if (! defined($bit)) {
662 for my $foo (keys %{$enum{$enum_name{$enum_ref}}{rbit
}}) { say "'$foo'"; }
663 die ("Field '$field' not found in '$enum_ref'");
665 $bit = "(1 << $bit)";
666 say $impl $indent."if (($switchon & $bit) != 0) {";
671 $vp =~ s/%s/${field}_%s/;
672 $hp =~ s/%s/${field}.%s/;
674 my @sub_elements = $case->children(qr/pad|field|list|switch/);
675 foreach my $sub_e (@sub_elements) {
676 register_element
($sub_e, $vp, $hp, $indent . ' ');
678 foreach my $sub_e (@sub_elements) {
679 $length = dissect_element
($sub_e, $vp, $hp, $length, $adjustlength, $indent . ' ');
682 say $impl $indent."}";
685 default { die "Unknown field type: $_\n"; }
692 my $name = $elt->att('name');
694 if (defined $struct{$name}) {
699 my @elements = $elt->children(qr/pad|field|list|switch/);
701 print(" - Struct $name\n");
708 foreach my $e (@elements) {
713 my $bytes = $e->att('bytes');
718 my $type = $e->att('type');
719 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
722 $needi = 1 if ($info->{'size'} == 0);
724 my $value = $e->first_child();
725 given($value->name()) {
727 $refs{$value->text()} = 1;
732 get_op
($value, \
%refs);
736 when (['unop','popcount']) {
737 get_unop
($value, \
%refs);
742 $count = $value->text();
744 default { die("Invalid list size $_\n"); }
748 default { die("unrecognized field $_\n"); }
751 my $type = $e->att('type');
752 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
754 $size += $info->{'size'} * $count;
761 static int struct_size_$name(tvbuff_t *tvb, int *offsetp, guint byte_order _U_)
766 say $impl ' int i, off;' if ($needi);
768 foreach my $ref (keys %refs) {
769 say $impl " int f_$ref;";
772 foreach my $e (@elements) {
776 my $type = $e->att('type') // '';
777 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
781 my $bytes = $e->att('bytes');
785 my $len = $e->first_child();
786 my $infosize = $info->{'size'};
789 given ($len->name()) {
790 when ('op') { $sizemul = get_op
($len, \
%refs); }
791 when (['unop','popcount']) { $sizemul = get_unop
($len, \
%refs); }
792 when ('fieldref') { $sizemul = 'f_'.$len->text(); }
795 $size += $infosize * $len->text();
797 $sizemul = $len->text();
800 default { die "Invalid list size: $_\n"; }
802 if (defined $sizemul) {
804 say $impl " size += $sizemul * $infosize;";
806 say $impl " for (i = 0; i < $sizemul; i++) {";
807 say $impl " off = (*offsetp) + size + $size;";
808 say $impl " size += struct_size_$type(tvb, &off, byte_order);";
814 my $fname = $e->att('name');
815 if (defined($refs{$fname})) {
816 say $impl " f_$fname = $info->{'get'}(tvb, *offsetp + size + $size);";
818 $size += $info->{'size'};
822 say $impl " return size + $size;";
824 $size = 0; # 0 means "dynamic calcuation required"
827 print $decl "static int hf_x11_struct_$name = -1;\n";
828 print $reg "{ &hf_x11_struct_$name, { \"$name\", \"x11.struct.$name\", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},\n";
832 static void struct_$name(tvbuff_t *tvb, int *offsetp, proto_tree *root, guint byte_order _U_, int count)
835 for (i = 0; i < count; i++) {
841 my $varpat = 'struct_'.$name.'_%s';
842 my $humanpat = "struct.$name.%s";
844 foreach my $e (@elements) {
845 register_element
($e, $varpat, $humanpat, "\t");
848 my $sizecalc = $size;
849 $size or $sizecalc = "struct_size_$name(tvb, offsetp, byte_order)";
853 item = proto_tree_add_item(root, hf_x11_struct_$name, tvb, *offsetp, $sizecalc, ENC_NA);
854 t = proto_item_add_subtree(item, ett_x11_rectangle);
858 foreach my $e (@elements) {
859 $length = dissect_element
($e, $varpat, $humanpat, $length, 0, "\t");
862 print $impl " }\n}\n";
863 $struct{$name} = { size
=> $size, name
=> $name };
868 # TODO proper dissection
870 # Right now, the only extension to use a union is randr.
873 my $name = $elt->att('name');
875 if (defined $struct{$name}) {
880 my @elements = $elt->children(qr/field/);
883 print(" - Union $name\n");
886 foreach my $e (@elements) {
887 my $type = $e->att('type');
888 my $info = $basictype{$type} // $simpletype{$type} // $struct{$type};
890 $info->{'size'} > 0 or die ("Error: Union containing variable sized struct $type\n");
891 push @sizes, $info->{'size'};
893 @sizes = sort {$b <=> $a} @sizes;
894 my $size = $sizes[0];
896 print $decl "static int hf_x11_union_$name = -1;\n";
897 print $reg "{ &hf_x11_union_$name, { \"$name\", \"x11.union.$name\", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},\n";
901 static void struct_$name(tvbuff_t *tvb, int *offsetp, proto_tree *root, guint byte_order, int count)
905 for (i = 0; i < count; i++) {
911 my $varpat = 'union_'.$name.'_%s';
912 my $humanpat = "union.$name.%s";
914 foreach my $e (@elements) {
915 register_element
($e, $varpat, $humanpat, "\t");
919 item = proto_tree_add_item(root, hf_x11_union_$name, tvb, base, $size, ENC_NA);
920 t = proto_item_add_subtree(item, ett_x11_rectangle);
925 foreach my $e (@elements) {
926 say $impl ' *offsetp = base;';
927 dissect_element
($e, $varpat, $humanpat, 0, 0, "\t");
929 say $impl " base += $size;";
931 say $impl ' *offsetp = base;';
934 $struct{$name} = { size
=> $size, name
=> $name };
940 my $name = $elt->att('name');
941 my $fullname = $incname[0].'_'.$name;
943 $enum_name{$name} = $fullname;
944 $enum_name{$incname[0].':'.$name} = $fullname;
946 if (defined $enum{$fullname}) {
951 my @elements = $elt->children('item');
953 print(" - Enum $name\n");
958 $enum{$fullname} = { value
=> $value, bit
=> $bit, rbit
=> $rbit };
962 foreach my $e (@elements) {
963 my $n = $e->att('name');
964 my $valtype = $e->first_child(qr/value|bit/);
965 if (defined $valtype) {
966 my $val = int($valtype->text());
967 given ($valtype->name()) {
970 $nextvalue = $val + 1;
978 $$value{$nextvalue} = $n;
988 my $name = $elt->att('name');
990 print(" - Request $name\n");
991 $request{$elt->att('opcode')} = $name;
994 my @elements = $elt->children(qr/pad|field|list|switch/);
996 # Wireshark defines _U_ to mean "Unused" (compiler specific define)
1000 static void $header$name(tvbuff_t *tvb _U_, packet_info *pinfo _U_, int *offsetp _U_, proto_tree *t _U_, guint byte_order _U_, int length _U_)
1007 static void $header$name(tvbuff_t *tvb, packet_info *pinfo _U_, int *offsetp, proto_tree *t, guint byte_order, int length _U_)
1012 my $varpat = $header.'_'.$name.'_%s';
1013 my $humanpat = "$header.$name.%s";
1015 foreach my $e (@elements) {
1016 register_element
($e, $varpat, $humanpat);
1019 foreach my $e (@elements) {
1020 if ($e->name() eq 'list' && $name eq 'Render' && $e->att('name') eq 'data' && -e
"$mesadir/gl_API.xml") {
1021 # Special case: Use mesa-generated dissector for 'data'
1022 print $impl " dispatch_glx_render(tvb, pinfo, offsetp, t, byte_order, (length - $length));\n";
1024 $length = dissect_element
($e, $varpat, $humanpat, $length, 1);
1030 my $reply = $elt->first_child('reply');
1032 $reply{$elt->att('opcode')} = $name;
1034 $varpat = $header.'_'.$name.'_reply_%s';
1035 $humanpat = "$header.$name.reply.%s";
1037 @elements = $reply->children(qr/pad|field|list|switch/);
1039 # Wireshark defines _U_ to mean "Unused" (compiler specific define)
1041 say $impl "static void $header$name"."_Reply(tvbuff_t *tvb _U_, packet_info *pinfo, int *offsetp _U_, proto_tree *t _U_, guint byte_order _U_)\n{";
1043 say $impl "static void $header$name"."_Reply(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, guint byte_order)\n{";
1045 say $impl ' int f_length, length, sequence_number;' if (@elements);
1047 foreach my $e (@elements) {
1048 register_element
($e, $varpat, $humanpat);
1052 say $impl ' col_append_fstr(pinfo->cinfo, COL_INFO, "-'.$name.'");';
1054 say $impl ' REPLY(reply);';
1058 foreach my $e (@elements) {
1059 $length = dissect_element
($e, $varpat, $humanpat, $length);
1062 say $impl ' sequence_number = VALUE16(tvb, *offsetp);';
1063 say $impl ' proto_tree_add_uint_format(t, hf_x11_reply_sequencenumber, tvb, *offsetp, 2, sequence_number,';
1064 say $impl ' "sequencenumber: %d ('.$header.'-'.$name.')", sequence_number);';
1065 say $impl ' *offsetp += 2;';
1067 say $impl ' f_length = VALUE32(tvb, *offsetp);';
1068 say $impl ' length = f_length * 4 + 32;';
1069 say $impl ' proto_tree_add_item(t, hf_x11_replylength, tvb, *offsetp, 4, byte_order);';
1070 say $impl ' *offsetp += 4;';
1083 while ($name = shift) {
1084 $simpletype{$name} = { size
=> 4, encoding
=> 'byte_order', type
=> 'FT_UINT32', base
=> 'BASE_HEX', get
=> 'VALUE32', list
=> 'listOfCard32', };
1090 my $name = $elt->att('name');
1099 my $oldname = $elt->att('oldname');
1100 my $newname = $elt->att('newname');
1102 # Duplicate the type
1103 my $info = $basictype{$oldname} // $simpletype{$oldname};
1105 $simpletype{$newname} = $info;
1106 } elsif ($struct{$oldname}) {
1107 $struct{$newname} = $struct{$oldname};
1109 die ("$oldname not found while attempting to typedef $newname\n");
1118 my $number = $elt->att('number');
1120 my $name = $elt->att('name');
1121 print $error " \"$header-$name\",\n";
1130 my $number = $elt->att('number');
1131 my $name = $elt->att('name');
1133 $event{$elt->att('number')} = $name;
1136 my @elements = $elt->children(qr/pad|field|list|switch/);
1138 # Wireshark defines _U_ to mean "Unused" (compiler specific define)
1142 static void $header$name(tvbuff_t *tvb _U_, int *offsetp _U_, proto_tree *t _U_, guint byte_order _U_)
1149 static void $header$name(tvbuff_t *tvb, int *offsetp, proto_tree *t, guint byte_order)
1155 my $varpat = $header.'_'.$name.'_%s';
1156 my $humanpat = "$header.$name.%s";
1158 foreach my $e (@elements) {
1159 register_element
($e, $varpat, $humanpat);
1163 foreach my $e (@elements) {
1164 $length = dissect_element
($e, $varpat, $humanpat, $length);
1167 say $impl " CARD16(event_sequencenumber);";
1178 my $header = $elt->att('header');
1179 unshift @incname, $header;
1189 my $include = $elt->text();
1191 print " - Import $include\n";
1192 my $xml = XML
::Twig
->new(
1193 start_tag_handlers
=> {
1194 'xcb' => \
&include_start
,
1197 'import' => \
&include
,
1198 'struct' => \
&struct
,
1199 'xidtype' => \
&xidtype
,
1200 'xidunion' => \
&xidtype
,
1201 'typedef' => \
&typedef
,
1204 end_tag_handlers
=> {
1205 'xcb' => \
&include_end
,
1207 $xml->parsefile("xcbproto/src/$include.xml") or die ("Cannot open $include.xml\n");
1215 $header = $elt->att('header');
1216 $extname = ($elt->att('extension-name') or $header);
1217 unshift @incname, $header;
1219 print("Extension $extname\n");
1228 print $error "const char *$header"."_errors[] = {\n";
1234 my $xextname = $elt->att('extension-xname');
1235 my $lookup_name = $header . "_extension_minor";
1236 my $error_name = $header . "_errors";
1237 my $event_name = $header . "_events";
1238 my $reply_name = $header . "_replies";
1240 print $decl "static int hf_x11_$lookup_name = -1;\n\n";
1242 print $impl "static const value_string $lookup_name"."[] = {\n";
1243 foreach my $req (sort {$a <=> $b} keys %request) {
1244 print $impl " { $req, \"$request{$req}\" },\n";
1246 print $impl " { 0, NULL }\n";
1249 say $impl "const x11_event_info $event_name".'[] = {';
1250 foreach my $e (sort {$a <=> $b} keys %event) {
1251 say $impl " { \"$header-$event{$e}\", $header$event{$e} },";
1253 say $impl ' { NULL, NULL }';
1256 print $impl "static x11_reply_info $reply_name"."[] = {\n";
1257 foreach my $e (sort {$a <=> $b} keys %reply) {
1258 print $impl " { $e, $header$reply{$e}_Reply },\n";
1260 print $impl " { 0, NULL }\n";
1263 print $reg "{ &hf_x11_$lookup_name, { \"extension-minor\", \"x11.extension-minor\", FT_UINT8, BASE_DEC, VALS($lookup_name), 0, \"minor opcode\", HFILL }},\n\n";
1267 static void dispatch_$header(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, guint byte_order)
1270 minor = CARD8($lookup_name);
1271 length = REQUEST_LENGTH();
1273 col_append_fstr(pinfo->cinfo, COL_INFO, "-%s",
1274 val_to_str(minor, $lookup_name,
1275 "<Unknown opcode %d>"));
1280 foreach my $req (sort {$a <=> $b} keys %request) {
1281 print $impl " case $req:\n";
1282 print $impl "\t$header$request{$req}(tvb, pinfo, offsetp, t, byte_order, length);\n";
1283 print $impl "\tbreak;\n";
1285 say $impl " /* No need for a default case here, since Unknown is printed above,";
1286 say $impl " and UNDECODED() is taken care of by dissect_x11_request */";
1287 print $impl " }\n}\n";
1290 static void register_$header(void)
1292 set_handler("$xextname", dispatch_$header, $error_name, $event_name, $reply_name);
1297 print $error " NULL\n};\n\n";
1299 push @register, $header;
1303 #my $git = `which git`;
1305 #-x $git or return 'unknown';
1308 # this will generate an error on stderr if git isn't in our $PATH
1309 # but that's OK. The version is still set to 'unknown' in that case
1310 # and at least the operator could see it.
1311 my $ver = `git --git-dir=$lib/.git describe --tags`;
1317 sub add_generated_header
{
1318 my ($out, $using) = @_;
1319 my $ver = find_version
($using);
1322 /* Do not modify this file. */
1323 /* It was automatically generated by $0
1324 using $using version $ver */
1327 # Since this file is checked in, add its SVN revision
1328 print $out "/* \$"."Id"."\$ */\n\n";
1333 * Copyright 2008, 2009 Open Text Corporation <pharris[AT]opentext.com>
1335 * Wireshark - Network traffic analyzer
1336 * By Gerald Combs <gerald[AT]wireshark.org>
1337 * Copyright 1998 Gerald Combs
1339 * This program is free software; you can redistribute it and/or modify
1340 * it under the terms of the GNU General Public License as published by
1341 * the Free Software Foundation; either version 2 of the License, or
1342 * (at your option) any later version.
1344 * This program is distributed in the hope that it will be useful,
1345 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1346 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1347 * GNU General Public License for more details.
1349 * You should have received a copy of the GNU General Public License along
1350 * with this program; if not, write to the Free Software Foundation, Inc.,
1351 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1358 # initialize core X11 protocol
1359 # Do this in the Makefile now
1360 #system('./process-x11-fields.pl < x11-fields');
1362 # Extension implementation
1363 $impl = new IO
::File
'> x11-extension-implementation.h'
1364 or die ("Cannot open x11-extension-implementation.h for writing\n");
1365 $error = new IO
::File
'> x11-extension-errors.h'
1366 or die ("Cannot open x11-extension-errors.h for writing\n");
1368 add_generated_header
($impl, 'xcbproto');
1369 add_generated_header
($error, 'xcbproto');
1371 # Open the files generated by process-x11-fields.pl for appending
1372 $reg = new IO
::File
'>> x11-register-info.h'
1373 or die ("Cannot open x11-register-info.h for appending\n");
1374 $decl = new IO
::File
'>> x11-declarations.h'
1375 or die ("Cannot open x11-declarations.h for appending\n");
1377 print $reg "\n/* Generated by $0 below this line */\n";
1378 print $decl "\n/* Generated by $0 below this line */\n";
1381 if (-e
"$mesadir/gl_API.xml") {
1382 $enum = new IO
::File
'> x11-glx-render-enum.h'
1383 or die ("Cannot open x11-glx-render-enum.h for writing\n");
1384 add_generated_header
($enum, 'mesa');
1385 print $enum "static const value_string mesa_enum[] = {\n";
1386 print $impl "#if defined(__GNUC__)\n";
1387 print $impl '#pragma GCC diagnostic ignored "-Wunused-but-set-variable"'."\n";
1388 print $impl "#endif\n\n";
1389 print $impl '#include "x11-glx-render-enum.h"'."\n\n";
1391 print("Mesa glRender:\n");
1392 $header = "glx_render";
1394 my $xml = XML
::Twig
->new(
1395 start_tag_handlers
=> {
1396 'category' => \
&mesa_category_start
,
1399 'category' => \
&mesa_category
,
1400 'enum' => \
&mesa_enum
,
1401 'type' => \
&mesa_type
,
1402 'function' => \
&mesa_function
,
1404 $xml->parsefile("$mesadir/gl_API.xml") or die ("Cannot open gl_API\n");
1406 print $enum " { 0, NULL }\n";
1410 print $decl "static int hf_x11_glx_render_op_name = -1;\n\n";
1412 print $impl "static const value_string glx_render_op_name"."[] = {\n";
1413 foreach my $req (sort {$a <=> $b} keys %request) {
1414 print $impl " { $req, \"gl$request{$req}\" },\n";
1416 print $impl " { 0, NULL }\n";
1419 print $reg "{ &hf_x11_glx_render_op_name, { \"render op\", \"x11.glx.render.op\", FT_UINT16, BASE_DEC, VALS(glx_render_op_name), 0, NULL, HFILL }},\n\n";
1421 # Uses ett_x11_list_of_rectangle, since I am unable to see how the subtree type matters.
1424 static void dispatch_glx_render(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, guint byte_order, int length)
1426 while (length >= 4) {
1432 len = VALUE16(tvb, *offsetp);
1434 op = VALUE16(tvb, *offsetp + 2);
1435 ti = proto_tree_add_uint(t, hf_x11_glx_render_op_name, tvb, *offsetp, len, op);
1437 tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1439 ti = proto_tree_add_item(tt, hf_x11_request_length, tvb, *offsetp, 2, byte_order);
1441 proto_tree_add_item(tt, hf_x11_glx_render_op_name, tvb, *offsetp, 2, byte_order);
1445 expert_add_info(pinfo, ti, &ei_x11_request_length);
1446 /* Eat the rest of the packet, mark it undecoded */
1452 next = *offsetp + len;
1457 foreach my $req (sort {$a <=> $b} keys %request) {
1458 print $impl "\tcase $req:\n";
1459 print $impl "\t mesa_$request{$req}(tvb, offsetp, tt, byte_order, len);\n";
1460 print $impl "\t break;\n";
1462 print $impl "\tdefault:\n";
1463 print $impl "\t proto_tree_add_item(tt, hf_x11_undecoded, tvb, *offsetp, len, ENC_NA);\n";
1464 print $impl "\t *offsetp += len;\n";
1466 print $impl "\t}\n";
1467 print $impl "\tif (*offsetp < next) {\n";
1468 print $impl "\t proto_tree_add_item(tt, hf_x11_unused, tvb, *offsetp, next - *offsetp, ENC_NA);\n";
1469 print $impl "\t *offsetp = next;\n";
1470 print $impl "\t}\n";
1471 print $impl "\tlength -= (len + 4);\n";
1472 print $impl " }\n}\n";
1475 $enum = new IO
::File
'> x11-enum.h'
1476 or die ("Cannot open x11-enum.h for writing\n");
1477 add_generated_header
($enum, 'xcbproto');
1478 print $impl '#include "x11-enum.h"'."\n\n";
1481 foreach my $ext (@reslist) {
1482 my $xml = XML
::Twig
->new(
1483 start_tag_handlers
=> {
1484 'xcb' => \
&xcb_start
,
1488 'import' => \
&include
,
1489 'request' => \
&request
,
1490 'struct' => \
&struct
,
1492 'xidtype' => \
&xidtype
,
1493 'xidunion' => \
&xidtype
,
1494 'typedef' => \
&typedef
,
1496 'errorcopy' => \
&error
,
1500 $xml->parsefile($ext) or die ("Cannot open $ext\n");
1503 print $impl "static void register_x11_extensions(void)\n{\n";
1504 foreach my $reg (@register) {
1505 print $impl " register_$reg();\n";