Logoj0ke.net Open Build Service > Projects > GFS > kernel-source > guards
Sign Up | Log In

File guards of Package kernel-source (Revision ecdd4e62e8b5e5f38f0e0f18bd871734)

Currently displaying revision ecdd4e62e8b5e5f38f0e0f18bd871734, show latest

 
1
#!/usr/bin/perl -w
2
3
#
4
# Guards:
5
#
6
# +xxx   include if xxx is defined
7
# -xxx   exclude if xxx is defined
8
# +!xxx  include if xxx is not defined
9
# -!xxx  exclude if xxx is not defined
10
#
11
12
use FileHandle;
13
use Getopt::Long;
14
use strict;
15
16
# Prototypes
17
sub files_in($$);
18
sub parse($$);
19
sub help();
20
21
#sub strip_ext($) {
22
#    local ($_) = @_;
23
#    s/\.(diff?|patch)$//;
24
#}
25
26
#sub try_ext($) {
27
#    my ($path) = @_;
28
#    for my $p in (($path, "$path.diff", "$path.dif", "$path.patch")) {
29
#   return $p
30
#       if (-f $p);
31
#    }
32
#    return undef;
33
#}
34
35
sub slashme($) {
36
    my ($dir) = @_;
37
    $dir =~ s#([^/])$#$&/#; # append a slash if necessary
38
    if ($dir eq './') {
39
    return '';
40
    } else {
41
    return $dir;
42
    }
43
}
44
45
# Generate a list of files in a directory
46
#
47
sub files_in($$) {
48
    my ($dir, $path) = @_;
49
    my $dh = new FileHandle;
50
    my (@files, $file);
51
52
53
    opendir $dh, length("$dir$path") ? "$dir$path" : '.'
54
    or die "$dir$path: $!\n";
55
    while ($file = readdir($dh)) {
56
    next if $file =~ /^(\.|\.\.|\.#.*|CVS|.*~)$/;
57
    if (-d "$dir$path$file") {
58
        @files = (@files, files_in($dir, "$path$file/"));
59
    } else {
60
        #print "[$path$file]\n";
61
        push @files, "$path$file";
62
    }
63
    }
64
    closedir $dh;
65
    return @files;
66
}
67
68
# Parse a configuration file
69
# Callback called with ($patch, @guards) arguments
70
#
71
sub parse($$) {
72
    my ($fh, $callback) = @_;
73
74
    my $line = "";
75
76
    while (<$fh>) {
77
    chomp;
78
    s/(^|\s+)#.*//;
79
    if (s/\\$/ /) {
80
        $line .= $_;
81
        next;
82
    }
83
    $line .= $_;
84
        my @guards = ();
85
    foreach my $token (split /[\s\t\n]+/, $line) {
86
        next if $token eq "";
87
        if ($token =~ /^[-+]/) {
88
        push @guards, $token;
89
        } else {
90
        #print "[" . join(",", @guards) . "] $token\n";
91
        &$callback($token, @guards);
92
        }
93
    }
94
    $line = "";
95
    }
96
}
97
98
# Command line options
99
#
100
my ($dir, $config, $default, $check, $list, $invert_match, $with_guards) =
101
   (  '',     '-',        1,      0,     0,             0,            0);
102
my @path;
103
104
# Help text
105
#
106
sub help() {
107
    print "$0 - select from a list of files guarded by conditions\n";
108
    print "SYNOPSIS: $0 [--prefix=dir] [--path=dir1:dir2:...]\n" .
109
    "   [--default=0|1] [--check|--list] [--invert-match]\n" .
110
    "   [--with-guards] [--config=file] symbol ...\n\n" .
111
    "   (Default values: --path='" . join(':', @path) . "', " .
112
        "--default=$default)\n";
113
    exit 0;
114
}
115
116
# Parse command line options
117
#
118
Getopt::Long::Configure ("bundling");
119
eval {
120
    unless (GetOptions (
121
    'd|prefix=s' => \$dir,
122
    'c|config=s' => \$config,
123
    'C|check' => \$check,
124
    'l|list' => \$list,
125
    'w|with-guards' => \$with_guards,
126
    'p|path=s' => \@path,
127
    'D|default=i' => \$default,
128
    'v|invert-match' => \$invert_match,
129
    'h|help' => sub { help(); exit 0; })) {
130
    help();
131
    exit 1;
132
    }
133
};
134
if ($@) {
135
    print "$@";
136
    help();
137
    exit 1;
138
}
139
140
@path = ('.')
141
    unless (@path);
142
@path = split(/:/, join(':', @path));
143
144
my $fh = ($config eq '-') ? \*STDIN : new FileHandle($config)
145
    or die "$config: $!\n";
146
147
$dir = slashme($dir);
148
149
if ($check) {
150
    # Check for duplicate files, or for files that are not referenced by
151
    # the specification.
152
153
    my $problems = 0;
154
    my @files;
155
156
    foreach (@path) {
157
    @files = (@files, files_in($dir, slashme($_)));
158
    }
159
    my %files = map { $_ => 0 } @files;
160
161
    parse($fh, sub {
162
    my ($patch, @guards) = @_;
163
    if (exists $files{$patch}) {
164
        $files{$patch}++;
165
    } else {
166
        print "Not found: $dir$patch\n";
167
        $problems++;
168
    }});
169
170
    $fh->close();
171
172
    my ($file, $ref);
173
    while (($file, $ref) = each %files) {
174
    next if $ref == 1;
175
176
    if ($ref == 0) {
177
        print "Unused: $file\n" if $ref == 0;
178
        $problems++;
179
    }
180
    if ($ref > 1) {
181
        print "Warning: multiple uses: $file\n" if $ref > 1;
182
        # This is not an error if the entries are mutually exclusive...
183
    }
184
    }
185
    exit $problems ? 1 : 0;
186
187
} elsif ($list) {
188
    parse($fh, sub {
189
    my ($patch, @guards) = @_;
190
    print join(' ', @guards), ' '
191
        if (@guards && $with_guards);
192
    print "$dir$patch\n";
193
    });
194
} else {
195
    # Generate a list of patches to apply.
196
197
    my %symbols = map { $_ => 1 } @ARGV;
198
199
    parse($fh, sub {
200
    my ($patch, @guards) = @_;
201
202
    my $selected;
203
    if (@guards) {
204
        # If the first guard is -xxx, the patch is included by default;
205
        # if it is +xxx, the patch is excluded by default.
206
        $selected = ($guards[0] =~ /^-/);
207
208
        foreach (@guards) {
209
        /^([-+])(!?)(.*)?/
210
            or die "Bad guard '$_'\n";
211
212
        # Check if the guard matches
213
        if (($2 eq '!' && !exists $symbols{$3}) ||
214
            ($2 eq ''  && ( $3 eq '' || exists $symbols{$3}))) {
215
            # Include or exclude
216
            $selected = ($1 eq '+');
217
        }
218
        }
219
    } else {
220
        # If there are no guards, use the specified default result.
221
        $selected = $default;
222
    }
223
224
    print "$dir$patch\n"
225
        if $selected ^ $invert_match;
226
    });
227
228
    $fh->close();
229
230
    exit 0;
231
}
232
233
__END__
234
235
=head1 NAME
236
237
guards - select from a list of files guarded by conditions
238
239
=head1 SYNOPSIS
240
241
F<guards> [--prefix=F<dir>] [--path=F<dir1:dir2:...>] [--default=<0|1>]
242
      [--check|--list] [--invert-match] [--with-guards] [--config=<file>]
243
      I<symbol> ...
244
245
246
=head1 DESCRIPTION
247
248
The script reads a configuration file that may contain so-called guards, file
249
names, and comments, and writes those file names that satisfy all guards to
250
standard output. The script takes a list of symbols as its arguments. Each line
251
in the configuration file is processed separately. Lines may start with a
252
number of guards. The following guards are defined:
253
254
=over
255
256
+I<xxx> Include the file(s) on this line if the symbol I<xxx> is defined.
257
258
-I<xxx> Exclude the file(s) on this line if the symbol I<xxx> is defined.
259
260
+!I<xxx> Include the file(s) on this line if the symbol I<xxx> is not defined.
261
262
-!I<xxx> Exclude the file(s) on this line if the symbol I<xxx> is not defined.
263
264
- Exclude this file. Used to avoid spurious I<--check> messages.
265
266
=back
267
268
The guards are processed left to right. The last guard that matches determines
269
if the file is included. If no guard is specified, the I<--default>
270
setting determines if the file is included.
271
272
If no configuration file is specified, the script reads from standard input.
273
274
The I<--check> option is used to compare the specification file against the
275
file system. If files are referenced in the specification that do not exist, or
276
if files are not enlisted in the specification file warnings are printed. The
277
I<--path> option can be used to specify which directory or directories to scan.
278
Multiple directories are eparated by a colon (C<:>) character. The
279
I<--prefix> option specifies the location of the files.
280
281
Use I<--list> to list all files independend of any rules. Use I<--invert-match>
282
to list only the excluded patches. Use I<--with-guards> to also include all
283
inclusion and exclusion rules.
284
285
=head1 AUTHOR
286
287
Andreas Gruenbacher <agruen@suse.de>, SUSE Labs
288