3 # Copyright (C) 2008, 2009 Free Software Foundation, Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 use constant true => 1;
21 use constant false => 0;
27 File::Spec->catfile($Bin, File::Spec->updir, 'src', 'main.c'),
28 qr/static \s+? struct \s+? cmdline_option \s+? option_data\[\] \s+? = \s+? \{ (.*?) \}\;/sx,
29 [ qw(long_name short_name type data argtype) ],
31 File::Spec->catfile($Bin, File::Spec->updir, 'src', 'init.c'),
32 qr/commands\[\] \s+? = \s+? \{ (.*?) \}\;/sx,
33 [ qw(name place action) ],
35 my $tex_file = File::Spec->catfile($Bin, File::Spec->updir, 'doc', 'wget.texi');
40 foreach my $arg (@args) {
41 my ($file, $regex, $names) = @$arg;
42 my $source = read_file($file);
43 my @chunks = extract_chunks($source, $regex);
44 push @data, extract_entries(\@chunks, $names);
47 output_results(@data);
54 open(my $fh, '<', $file) or die "Cannot open $file: $!";
56 return do { local $/; <$fh> };
61 my ($source, $regex) = @_;
63 my ($raw_data) = $source =~ $regex;
65 return map { /\S/ && !/^\#/ ? $_ : () } split /(?<=\})/, $raw_data;
70 my ($chunks, $names) = @_;
72 my (@entries, %index, $i);
74 foreach my $chunk (@$chunks) {
75 my ($args) = $chunk =~ /\{ \s+? (.*?) \s+? \}/sx;
76 next unless defined $args;
82 } split /\,\s+/, $args;
84 my $entry = { map { $_ => shift @args } @$names };
86 ($entry->{line}) = $chunk =~ /^ \s+? (\{.*)/mx;
87 if ($chunk =~ /deprecated/i) {
88 $entries[-1]->{deprecated} = true;
91 my $index_name = exists $entry->{data}
95 $index{$index_name} = $i++;
97 push @entries, $entry;
100 push @entries, \%index;
107 my ($opts, $cmds) = @_;
114 emit_no_corresponding_cmds($opts);
116 emit_no_matching_long_cmds($opts);
118 emit_no_corresponding_opts($opts, $cmds);
120 emit_deprecated_opts($opts);
122 emit_deprecated_cmds($cmds);
125 my $tex = read_file($tex_file);
127 emit_undocumented_opts($tex, $opts);
129 emit_undocumented_cmds($tex, $opts, $cmds, \%index);
133 sub emit_no_corresponding_cmds
138 foreach my $opt (@$opts) {
139 unless ($opt->{type} =~ /^(?:OPT_BOOLEAN|OPT_VALUE)$/
140 && $opt->{argtype} == -1)
142 push @options, $opt->{line};
148 No corresponding commands
149 =========================
154 sub emit_no_matching_long_cmds
159 foreach my $opt (@$opts) {
160 my $long_name = $opt->{long_name};
161 $long_name =~ tr/-//d;
162 unless ($long_name eq $opt->{data}) {
163 push @options, $opt->{line};
169 Non-matching commands
170 =====================
175 sub emit_no_corresponding_opts
177 my ($opts, $cmds) = @_;
180 foreach my $cmd (@$cmds) {
182 foreach my $opt (@$opts) {
183 my $long_name = $opt->{long_name};
184 $long_name =~ tr/-//d;
185 if ($cmd->{name} eq $opt->{data}
186 || $cmd->{name} eq $long_name) {
192 push @commands, $cmd->{line};
198 No corresponding options
199 ========================
204 sub emit_deprecated_opts
209 foreach my $opt (@$opts) {
210 if ($opt->{deprecated}) {
211 push @options, $opt->{line};
223 sub emit_deprecated_cmds
228 foreach my $cmd (@$cmds) {
229 if ($cmd->{deprecated}) {
230 push @commands, $cmd->{line};
242 sub emit_undocumented_opts
244 my ($tex, $opts) = @_;
247 while ($tex =~ /^\@item\w*? \s+? --([\w\-]+)/gmx) {
252 foreach my $opt (@$opts) {
253 my $opt_name = $opt->{long_name};
254 if (not $items{$opt_name}
255 || ($opt_name !~ /^no/
256 ? $items{"no-$opt_name"}
258 || $opt->{deprecated})
260 push @options, $opt_name;
272 sub emit_undocumented_cmds
274 my ($tex, $opts, $cmds, $index) = @_;
277 while ($tex =~ /^\@item\w*? \s+? ([\w\_]+) \s+? = \s+? \S+?/gmx) {
283 foreach my $cmd (@$cmds) {
285 local $_ = exists $index->{opts}->{$cmd->{name}}
286 ? $opts->[$index->{opts}->{$cmd->{name}}]->{long_name}
291 if (not $items{$cmd->{name}} || $cmd->{deprecated}) {
292 push @commands, $cmd_name;
298 Undocumented commands
299 =====================