1 ###################################################
2 # parse an Wireshark conformance file
3 # Copyright jelmer@samba.org 2005
4 # released under the GNU GPL
10 Parse::Pidl::Wireshark::Conformance - Conformance file parser for Wireshark
14 This module supports parsing Wireshark conformance files (*.cnf).
18 Pidl needs additional data for Wireshark output. This data is read from
19 so-called conformance files. This section describes the format of these
22 Conformance files are simple text files with a single command on each line.
23 Empty lines and lines starting with a '#' character are ignored.
24 Arguments to commands are seperated by spaces.
26 The following commands are currently supported:
30 =item I<TYPE> name dissector ft_type base_type mask valsstring alignment
32 Register new data type with specified name, what dissector function to call
33 and what properties to give header fields for elements of this type.
37 Suppress emitting a dissect_type function for the specified type
39 =item I<PARAM_VALUE> type param
41 Set parameter to specify to dissector function for given type.
43 =item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
45 Generate a custom header field with specified properties.
47 =item I<HF_RENAME> old_hf_name new_hf_name
49 Force the use of new_hf_name when the parser generator was going to
52 This can be used in conjunction with HF_FIELD in order to make more than
53 one element use the same filter name.
55 =item I<STRIP_PREFIX> prefix
57 Remove the specified prefix from all function names (if present).
59 =item I<PROTOCOL> longname shortname filtername
61 Change the short-, long- and filter-name for the current interface in
64 =item I<FIELD_DESCRIPTION> field desc
66 Change description for the specified header field. `field' is the hf name of the field.
68 =item I<IMPORT> dissector code...
70 Code to insert when generating the specified dissector. @HF@ and
71 @PARAM@ will be substituted.
73 =item I<TFS> hf_name "true string" "false string"
75 Override the text shown when a bitmap boolean value is enabled or disabled.
77 =item I<MANUAL> fn_name
79 Force pidl to not generate a particular function but allow the user
80 to write a function manually. This can be used to remove the function
81 for only one level for a particular element rather than all the functions and
82 ett/hf variables for a particular element as the NOEMIT command does.
92 package Parse
::Pidl
::Wireshark
::Conformance
;
95 use vars
qw($VERSION);
99 @EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type);
103 use Parse
::Pidl
qw(fatal warning error);
104 use Parse
::Pidl
::Util
qw(has_property);
106 sub handle_type
($$$$$$$$$$)
108 my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
110 unless(defined($alignment)) {
111 error
($pos, "incomplete TYPE command");
115 unless ($dissectorname =~ /.*dissect_.*/) {
116 warning
($pos, "dissector name does not contain `dissect'");
119 unless(valid_ft_type
($ft_type)) {
120 warning
($pos, "invalid FT_TYPE `$ft_type'");
123 unless (valid_base_type
($base_type)) {
124 warning
($pos, "invalid BASE_TYPE `$base_type'");
127 $dissectorname =~ s/^\"(.*)\"$/$1/g;
129 if (not ($dissectorname =~ /;$/)) {
130 warning
($pos, "missing semicolon");
133 $data->{types
}->{$name} = {
137 DISSECTOR_NAME
=> $dissectorname,
139 BASE_TYPE
=> $base_type,
141 VALSSTRING
=> $valsstring,
142 ALIGNMENT
=> $alignment
146 sub handle_tfs
($$$$$)
148 my ($pos,$data,$hf,$trues,$falses) = @_;
150 unless(defined($falses)) {
151 error
($pos, "incomplete TFS command");
155 $data->{tfs
}->{$hf} = {
156 TRUE_STRING
=> $trues,
157 FALSE_STRING
=> $falses
161 sub handle_hf_rename
($$$$)
163 my ($pos,$data,$old,$new) = @_;
165 unless(defined($new)) {
166 warning
($pos, "incomplete HF_RENAME command");
170 $data->{hf_renames
}->{$old} = {
178 sub handle_param_value
($$$$)
180 my ($pos,$data,$dissector_name,$value) = @_;
182 unless(defined($value)) {
183 error
($pos, "incomplete PARAM_VALUE command");
187 $data->{dissectorparams
}->{$dissector_name} = {
188 DISSECTOR
=> $dissector_name,
195 sub valid_base_type
($)
198 return 0 unless($t =~ /^BASE_.*/);
205 return 0 unless($t =~ /^FT_.*/);
209 sub handle_hf_field
($$$$$$$$$$)
211 my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
213 unless(defined($blurb)) {
214 error
($pos, "incomplete HF_FIELD command");
218 unless(valid_ft_type
($ft_type)) {
219 warning
($pos, "invalid FT_TYPE `$ft_type'");
222 unless(valid_base_type
($base_type)) {
223 warning
($pos, "invalid BASE_TYPE `$base_type'");
226 $data->{header_fields
}->{$index} = {
233 BASE_TYPE
=> $base_type,
234 VALSSTRING
=> $valsstring,
240 sub handle_strip_prefix
($$$)
242 my ($pos,$data,$x) = @_;
244 push (@
{$data->{strip_prefixes
}}, $x);
247 sub handle_noemit
($$$)
249 my ($pos,$data,$type) = @_;
251 if (defined($type)) {
252 $data->{noemit
}->{$type} = 1;
254 $data->{noemit_dissector
} = 1;
258 sub handle_manual
($$$)
260 my ($pos,$data,$fn) = @_;
262 unless(defined($fn)) {
263 warning
($pos, "incomplete MANUAL command");
267 $data->{manual
}->{$fn} = 1;
270 sub handle_protocol
($$$$$$)
272 my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
274 $data->{protocols
}->{$name} = {
275 LONGNAME
=> $longname,
276 SHORTNAME
=> $shortname,
277 FILTERNAME
=> $filtername
281 sub handle_fielddescription
($$$$)
283 my ($pos,$data,$field,$desc) = @_;
285 unless(defined($desc)) {
286 warning
($pos, "incomplete FIELD_DESCRIPTION command");
290 $data->{fielddescription
}->{$field} = {
291 DESCRIPTION
=> $desc,
301 my $dissectorname = shift @_;
303 unless(defined($dissectorname)) {
304 error
($pos, "no dissectorname specified");
308 $data->{imports
}->{$dissectorname} = {
309 NAME
=> $dissectorname,
310 DATA
=> join(' ', @_),
316 my %field_handlers = (
317 TYPE
=> \
&handle_type
,
318 NOEMIT
=> \
&handle_noemit
,
319 MANUAL
=> \
&handle_manual
,
320 PARAM_VALUE
=> \
&handle_param_value
,
321 HF_FIELD
=> \
&handle_hf_field
,
322 HF_RENAME
=> \
&handle_hf_rename
,
324 STRIP_PREFIX
=> \
&handle_strip_prefix
,
325 PROTOCOL
=> \
&handle_protocol
,
326 FIELD_DESCRIPTION
=> \
&handle_fielddescription
,
327 IMPORT
=> \
&handle_import
330 sub ReadConformance
($$)
335 open(IN
,"<$f") or return undef;
337 $ret = ReadConformanceFH
(*IN
, $data, $f);
344 sub ReadConformanceFH
($$$)
346 my ($fh,$data,$f) = @_;
359 if ($_ eq "CODE START") {
362 } elsif ($incodeblock and $_ eq "CODE END") {
365 } elsif ($incodeblock) {
366 if (exists $data->{override
}) {
367 $data->{override
}.="$_\n";
369 $data->{override
} = "$_\n";
374 my @fields = /([^ "]+|"[^"]+")/g;
376 my $cmd = $fields[0];
380 my $pos = { FILE
=> $f, LINE
=> $ln };
382 next unless(defined($cmd));
384 if (not defined($field_handlers{$cmd})) {
385 warning
($pos, "Unknown command `$cmd'");
389 $field_handlers{$cmd}($pos, $data, @fields);
393 warning
({ FILE
=> $f, LINE
=> $ln },
394 "Expecting CODE END");