Output numbers in 3-digit groups by default (e.g. 1,234,567).
[rsync/rsync.git] / packaging / var-checker
1 #!/usr/bin/perl -w
2 # This script checks the *.c files for extraneous "extern" variables,
3 # for vars that are defined but not used, and for inconsistent array
4 # sizes.  Run it from inside the main rsync directory.
5
6 use strict;
7
8 my %add_syscall_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c tls.c trimslash.c );
9 my %add_compat_c = map { $_ => 1 } qw( t_stub.c tls.c trimslash.c wildtest.c );
10 my %add_util_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c );
11 my %sizes;
12
13 open(IN, '<', 'syscall.c') or die $!;
14 undef $/; my $syscall_c = <IN>; $/ = "\n";
15 close IN;
16 $syscall_c =~ s/^extern\s.*//mg;
17
18 open(IN, '<', 'lib/compat.c') or die $!;
19 undef $/; my $compat_c = <IN>; $/ = "\n";
20 close IN;
21 $compat_c =~ s/^extern\s.*//mg;
22
23 open(IN, '<', 'util.c') or die $!;
24 undef $/; my $util_c = <IN>; $/ = "\n";
25 close IN;
26 $util_c =~ s/^extern\s.*//mg;
27
28 my @files = glob('*.c');
29
30 foreach my $fn (@files) {
31     open(IN, '<', $fn) or die $!;
32     undef $/; $_ = <IN>; $/ = "\n";
33     close IN;
34
35     my @vars = /^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);/mg;
36     my @externs = /^extern\s+(.*);/mg;
37
38     $_ .= $syscall_c if $add_syscall_c{$fn};
39     $_ .= $compat_c if $add_compat_c{$fn};
40     $_ .= $util_c if $add_util_c{$fn};
41     s/INFO_GTE/info_levels/g;
42     s/DEBUG_GTE/debug_levels/g;
43
44     check_vars($fn, 'var', @vars);
45     check_vars($fn, 'extern', @externs);
46 }
47
48 exit;
49
50 # The file's contents are in $_.
51 sub check_vars
52 {
53     my $fn = shift;
54     my $type = shift;
55
56     foreach my $line (@_) {
57         $line =~ s/\s*\{.*\}//;
58         $line =~ s/\s*\(.*\)//;
59         foreach my $item (split(/\s*,\s*/, $line)) {
60             $item =~ s/\s*=.*//;
61             my $sz = $item =~ s/(\[.*?\])// ? $1 : '';
62             my($var) = $item =~ /([^*\s]+)$/;
63             if (!defined $var) {
64                 print "Bogus match? ($item)\n";
65                 next;
66             }
67             if ($sz) {
68                 if (defined $sizes{$var}) {
69                     if ($sizes{$var} ne $sz) {
70                         print $fn, ' has inconsistent size for "', $var,
71                             "\": $sizes{$var} vs $sz\n";
72                     }
73                 } else {
74                     $sizes{$var} = $sz;
75                 }
76             }
77             my @matches = /(?<!\sstruct )\b(\Q$var\E)(?!\w)/g;
78             push(@matches, /(\QSIGACTION(\E)/g) if $var eq 'sigact';
79             print $fn, " has extraneous $type: \"", $var, "\"\n" if @matches == 1;
80         }
81     }
82 }