Make idl2wrs dissectors filterable - Part 1
[metze/wireshark/wip.git] / tools / checkhf.pl
1 #!/usr/bin/perl
2
3 my $debug = 0;
4 # 0: off
5 # 1: specific debug
6 # 2: full debug
7
8 #
9 # find unbalanced hf_ variables: Compare hf_ variable usage with the hf_ variables
10 #  declared in the hf_register_info array.
11 #
12 # Usage: checkhf.pl <file or files>
13
14 # $Id$
15
16 #
17 # Copyright 2005 Joerg Mayer (see AUTHORS file)
18 #
19 # Wireshark - Network traffic analyzer
20 # By Gerald Combs <gerald@wireshark.org>
21 # Copyright 1998 Gerald Combs
22 #
23 # This program is free software; you can redistribute it and/or
24 # modify it under the terms of the GNU General Public License
25 # as published by the Free Software Foundation; either version 2
26 # of the License, or (at your option) any later version.
27 #
28 # This program is distributed in the hope that it will be useful,
29 # but WITHOUT ANY WARRANTY; without even the implied warranty of
30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31 # GNU General Public License for more details.
32 #
33 # You should have received a copy of the GNU General Public License
34 # along with this program; if not, write to the Free Software
35 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36
37 #
38 # Example:
39 # ~/work/wireshark/trunk/epan/dissectors> ../../tools/checkhf.pl packet-afs.c
40 # Unused entry: packet-afs.c, hf_afs_ubik_voteend
41 # Unused entry: packet-afs.c, hf_afs_ubik_errcode
42 # Unused entry: packet-afs.c, hf_afs_ubik_votetype
43 # NO ARRAY: packet-afs.c, hf_afs_fs_ipaddr
44 #
45 # or checkhf.pl packet-*.c, which will check all the dissector files.
46 #
47 # NOTE: This tool currently generates false positives!
48 #
49 # The "NO ARRAY" messages - if accurate - points to an error that will
50 # cause (t|wire)shark to terminate with an assertion when a packet containing
51 # this particular element is being dissected.
52 #
53 # The "Unused entry" message indicates the opposite: We define an entry but
54 # never use it in a proto_...add... function.
55 #
56
57 use warnings;
58 use strict;
59
60 my $D;
61
62 my %elements;
63 my $element;
64 my %skip;
65
66 my $state;
67 my $newstate;
68 # "s_unknown",
69 # "s_declared",
70 # "s_used",
71 # "s_array",
72 # "s_usedarray",
73 # "s_error"
74
75 my $type;
76 # "t_declaration";
77 # "t_usage";
78 # "t_array";
79
80 my $restofline;
81 my $currfile = "";
82
83 my $comment = 0;
84 my $brace = 0;
85
86 my $error = 0;
87
88 sub printprevfile {
89         my $state;
90
91         foreach $element (keys %elements) {
92                 $state = $elements{$element};
93                 $debug>=2 && print "$currfile, $element: PRINT $state\n";
94                 if ($state eq "s_usedarray") {
95                         # Everything is fine
96                 } elsif ($state eq "s_used") {
97                         # A value is declared and used but the hf_ array
98                         # entry is missing
99                         print "ERROR: NO ARRAY: $currfile, $element\n";
100                         $error = 1;
101                 } elsif ($state eq "s_array") {
102                         # A value is declared, has an hf_ array entry
103                         # but it is never used
104                         print "Unused entry: $currfile, $element\n";
105                 } elsif ($state eq "s_declared") {
106                         # A value is declared but no error value exists.
107                         # This doesn't matter as it isn't used either.
108                         print "Declared only entry: $currfile, $element\n"
109                 } elsif ($state eq "s_unknown") {
110                         print "UNKNOWN: $currfile, $element\n";
111                 } else {
112                         die "Impossible: State $state for $currfile, $element\n";
113                 }
114         }
115 }
116
117 while (<>) {
118         if ($currfile !~ /$ARGV/) {
119                 &printprevfile();
120                 # New file - reset array and state
121                 $currfile = $ARGV;
122                 %elements = ( );
123                 %skip = ( "hf_register_info" => 1 );
124                 $state = "s_unknown";
125         }
126         # opening then closing comment
127         if (/(.*?)\/\*.*\*\/(.*)/) {
128                 $comment = 0;
129                 $_ = "$1$2";
130         # closing then opening comment
131         } elsif (/.*?\*\/(.*?)\/\*/) {
132                 $comment = 1;
133                 $_ = "$1";
134         # opening comment
135         } elsif (/(.*?)\/\*/) {
136                 $comment = 1;
137                 $_ = "$1";
138         # closing comment
139         } elsif (/\*\/(.*?)/) {
140                 $comment = 0;
141                 $_ = "$1";
142         } elsif ($comment == 1) {
143                 next;
144         }
145         # unhandled: more than one complete comment per line
146
147         chomp;
148         if ($debug) {
149                 $D = " ($_)";
150         } else {
151                 $D = "";
152         }
153
154         # Read input
155         if (/static\s+.*int\s+(hf_\w*)\s*=\s*-1\s*;/) {
156                 $element = $1;
157                 $debug && print "t_declaration for $element$D\n";
158                 $type = "t_declaration";
159                 # ignore: declarations without any use are detected by the compiler
160                 next;
161         # Skip function parameter declarations with hf_ names
162         } elsif (/(int\s+?|int\s*?\*\s*?|header_field_info\s+?|header_field_info\s*?\*\s*?|hf_register_info\s+?|hf_register_info\s*?\*\s*?|->\s*?)(hf_\w*)\W(.*)/) {
163                 $element = $2;
164                 $restofline = $3;
165                 $debug && print "Setting skip for $element$D\n";
166                 $skip{$element} = 1;
167                 # Handle functions with multiple hf_ parameters
168                 while ($restofline =~ /(int\s+?|int\s*?\*\s*?|header_field_info\s+?|header_field_info\s*?\*\s*?|hf_register_info\s+?|hf_register_info\s*?\*\s*?|->\s*?)(hf_\w*)\W(.*)/) {
169                         $element = $2;
170                         $restofline = $3;
171                         $debug && print "Setting skip for $element$D\n";
172                         $skip{$element} = 1;
173                 }
174                 next;
175         } elsif ($brace == 1 && /^\s*&\s*(hf_\w*)\W+/) {
176                 $element = $1;
177                 $debug && print "t_array1 for $element$D\n";
178                 $type = "t_array";
179         } elsif (/^\s*\{\s*?&\s*?(hf_\w*)\W+/) {
180                 $element = $1;
181                 $debug && print "t_array2 for $element$D\n";
182                 $type = "t_array";
183         # Order matters: catch all remaining hf_ lines
184         } elsif (/\w*\s*=\s*(hf_\w*)\s*;/) {
185                 # Catches: variable = hf_*
186                 # But we don't check if the variable actually gets used...
187                 $element = $1;
188                 $debug && print "in variable usage for $element$D\n";
189                 next if ($skip{$element});
190                 $debug && print "set t_usage for $element$D\n";
191                 $type = "t_usage";
192         } elsif (/\W(hf_\w*)\W*/) {
193                 $element = $1;
194                 $debug && print "in usage for $element$D\n";
195                 next if ($skip{$element});
196                 $debug && print "set t_usage for $element$D\n";
197                 $type = "t_usage";
198         } else {
199                 # Line with only a {
200                 if (/^\s+\{\s*$/) {
201                         $brace = 1;
202                 } else {
203                         $brace = 0;
204                         $debug && print "else: $D\n";
205                 }
206                 next;
207         }
208
209         # Get current state
210         if (!defined($elements{$element})) {
211                 $state = "s_unknown";
212         } else {
213                 $state = $elements{$element};
214         }
215
216         # current state + input ==> new state
217         # we currently ignore t_declaration
218         if ($state eq "s_error") {
219                 $newstate = $state;
220         } elsif ($state eq "s_unknown" && $type eq "t_usage") {
221                         $newstate = "s_used";
222         } elsif ($state eq "s_unknown" && $type eq "t_array") {
223                         $newstate = "s_array";
224         } elsif ($state eq "s_used" && $type eq "t_array") {
225                         $newstate = "s_usedarray";
226         } elsif ($state eq "s_array" && $type eq "t_usage") {
227                         $newstate = "s_usedarray";
228         } else {
229                 $newstate = $state;
230         }
231         $elements{$element} = $newstate;
232         $debug>=2 && print "$currfile, $element: SET $state + $type => $newstate$D\n";
233 }
234 &printprevfile();
235
236 exit $error;
237
238 __END__