Fri Aug 2 13:16:54 2013 UTC ()
Whitespace, from jmc@openbsd.


(wiz)
diff -r1.38 -r1.39 pkgsrc/textproc/mdoclint/files/mdoclint

cvs diff -r1.38 -r1.39 pkgsrc/textproc/mdoclint/files/Attic/mdoclint (switch to unified diff)

--- pkgsrc/textproc/mdoclint/files/Attic/mdoclint 2013/07/30 19:07:23 1.38
+++ pkgsrc/textproc/mdoclint/files/Attic/mdoclint 2013/08/02 13:16:54 1.39
@@ -1,702 +1,702 @@ @@ -1,702 +1,702 @@
1#!@PERL5@ 1#!@PERL5@
2# 2#
3# $OpenBSD: mdoclint,v 1.14 2009/04/13 12:40:05 espie Exp $ 3# $OpenBSD: mdoclint,v 1.14 2009/04/13 12:40:05 espie Exp $
4# $NetBSD: mdoclint,v 1.38 2013/07/30 19:07:23 wiz Exp $ 4# $NetBSD: mdoclint,v 1.39 2013/08/02 13:16:54 wiz Exp $
5# 5#
6# Copyright (c) 2001-2013 Thomas Klausner 6# Copyright (c) 2001-2013 Thomas Klausner
7# All rights reserved. 7# All rights reserved.
8# 8#
9# Redistribution and use in source and binary forms, with or without 9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions 10# modification, are permitted provided that the following conditions
11# are met: 11# are met:
12# 1. Redistributions of source code must retain the above copyright 12# 1. Redistributions of source code must retain the above copyright
13# notice, this list of conditions and the following disclaimer. 13# notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright 14# 2. Redistributions in binary form must reproduce the above copyright
15# notice, this list of conditions and the following disclaimer in the 15# notice, this list of conditions and the following disclaimer in the
16# documentation and/or other materials provided with the distribution. 16# documentation and/or other materials provided with the distribution.
17# 17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR, THOMAS KLAUSNER, 18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR, THOMAS KLAUSNER,
19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE. 28# POSSIBILITY OF SUCH DAMAGE.
29# 29#
30 30
31use strict; 31use strict;
32use warnings; 32use warnings;
33 33
34$| = 1; 34$| = 1;
35 35
36package Parser; 36package Parser;
37use Getopt::Std; 37use Getopt::Std;
38 38
39use constant { 39use constant {
40 OPENBSD => 0, 40 OPENBSD => 0,
41 NETBSD => 1, 41 NETBSD => 1,
42 SECTION_SEE_ALSO => 2, 42 SECTION_SEE_ALSO => 2,
43 SECTION_AUTHORS => 3 43 SECTION_AUTHORS => 3
44}; 44};
45 45
46use vars qw( 46use vars qw(
47 $opt_A $opt_a $opt_D $opt_d $opt_e $opt_F $opt_f $opt_H $opt_h $opt_l 47 $opt_A $opt_a $opt_D $opt_d $opt_e $opt_F $opt_f $opt_H $opt_h $opt_l
48 $opt_m 48 $opt_m
49 $opt_n $opt_o $opt_P $opt_p $opt_r $opt_S $opt_s $opt_v $opt_w 49 $opt_n $opt_o $opt_P $opt_p $opt_r $opt_S $opt_s $opt_v $opt_w
50 $opt_X $opt_x 50 $opt_X $opt_x
51); 51);
52 52
53 53
54my $arch=`uname -m`; 54my $arch=`uname -m`;
55chomp($arch); 55chomp($arch);
56my $options="AaDdeFfHhlmnoPprSsvwXx"; 56my $options="AaDdeFfHhlmnoPprSsvwXx";
57 57
58sub usage 58sub usage
59 { 59 {
60 my $default = OPENBSD ? "-AaDdfmnoPprSsXx" : "-AaDdeflmnoPprSsXx"; 60 my $default = OPENBSD ? "-AaDdfmnoPprSsXx" : "-AaDdeflmnoPprSsXx";
61  61
62 print STDERR <<"EOF"; 62 print STDERR <<"EOF";
63mdoclint: verify man page correctness 63mdoclint: verify man page correctness
64usage: mdoclint [-$options] file ... 64usage: mdoclint [-$options] file ...
65 -A warn about missing .An in AUTHORS section 65 -A warn about missing .An in AUTHORS section
66 -a warn about SEE ALSO section problems 66 -a warn about SEE ALSO section problems
67 -D warn about bad casing and archs in .Dt 67 -D warn about bad casing and archs in .Dt
68 -d warn about bad date strings (in .Dd only) 68 -d warn about bad date strings (in .Dd only)
69 -e warn about unsorted errors (for functions) 69 -e warn about unsorted errors (for functions)
70 -F fix whitespace problems (asks before overwriting) 70 -F fix whitespace problems (asks before overwriting)
71 -f warn about possible incorrect .Fn syntax 71 -f warn about possible incorrect .Fn syntax
72 -H warn about characters that produce problems in HTML output 72 -H warn about characters that produce problems in HTML output
73 -h display this help text 73 -h display this help text
74 -l warn about unknown libraries 74 -l warn about unknown libraries
75 -m warn about man pages that are not in mdoc(7) format 75 -m warn about man pages that are not in mdoc(7) format
76 -n warn about .Nd's ending in '.' 76 -n warn about .Nd's ending in '.'
77 -O warn about unsorted .It arguments 77 -O warn about unsorted .It arguments
78 -o warn about non-empty .Os strings 78 -o warn about non-empty .Os strings
79 -P warn about paragraph problems 79 -P warn about paragraph problems
80 -p warn about punctuation problems 80 -p warn about punctuation problems
81 -r warn about missing RCS Id 81 -r warn about missing RCS Id
82 -S warn about any .Sh weirdness 82 -S warn about any .Sh weirdness
83 -s warn about whitespace problems 83 -s warn about whitespace problems
84 -v verbose output 84 -v verbose output
85 -w show section header in warnings 85 -w show section header in warnings
86 -X warn about explicit mentions of FreeBSD, NetBSD, or OpenBSD 86 -X warn about explicit mentions of FreeBSD, NetBSD, or OpenBSD
87 -x warn about cross-references with missing targets 87 -x warn about cross-references with missing targets
88Default is $default if no flag is specified. 88Default is $default if no flag is specified.
89EOF 89EOF
90 exit(0); 90 exit(0);
91} 91}
92 92
93 93
94my %short = ( 94my %short = (
95 "Free" => ".Fx", 95 "Free" => ".Fx",
96 "Net" => ".Nx", 96 "Net" => ".Nx",
97 "Open" => ".Ox" 97 "Open" => ".Ox"
98); 98);
99 99
100my %libraries = ( 100my %libraries = (
101 "libarchive" => 1, 101 "libarchive" => 1,
102 "libarm" => 1, 102 "libarm" => 1,
103 "libarm32" => 1, 103 "libarm32" => 1,
104 "libbluetooth" => 1, 104 "libbluetooth" => 1,
105 "libc" => 1, 105 "libc" => 1,
106 "libcdk" => 1, 106 "libcdk" => 1,
107 "libcompat" => 1, 107 "libcompat" => 1,
108 "libcrypt" => 1, 108 "libcrypt" => 1,
109 "libcurses" => 1, 109 "libcurses" => 1,
110 "libdm" => 1, 110 "libdm" => 1,
111 "libedit" => 1, 111 "libedit" => 1,
112 "libelf" => 1, 112 "libelf" => 1,
113 "libevent" => 1, 113 "libevent" => 1,
114 "libexecinfo" => 1, 114 "libexecinfo" => 1,
115 "libfetch" => 1, 115 "libfetch" => 1,
116 "libform" => 1, 116 "libform" => 1,
117 "libi386" => 1, 117 "libi386" => 1,
118 "libintl" => 1, 118 "libintl" => 1,
119 "libipsec" => 1, 119 "libipsec" => 1,
120 "libiscsi" => 1, 120 "libiscsi" => 1,
121 "libisns" => 1, 121 "libisns" => 1,
122 "libkvm" => 1, 122 "libkvm" => 1,
123 "libm" => 1, 123 "libm" => 1,
124 "libm68k" => 1, 124 "libm68k" => 1,
125 "libmagic" => 1, 125 "libmagic" => 1,
126 "libmandoc" => 1, 126 "libmandoc" => 1,
127 "libmenu" => 1, 127 "libmenu" => 1,
128 "libmj" => 1, 128 "libmj" => 1,
129 "libnetpgp" => 1, 129 "libnetpgp" => 1,
130 "libnetpgpverify" => 1, 130 "libnetpgpverify" => 1,
131 "libnpf" => 1, 131 "libnpf" => 1,
132 "libossaudio" => 1, 132 "libossaudio" => 1,
133 "libpam" => 1, 133 "libpam" => 1,
134 "libpcap" => 1, 134 "libpcap" => 1,
135 "libpci" => 1, 135 "libpci" => 1,
136 "libperfuse" => 1, 136 "libperfuse" => 1,
137 "libpmc" => 1, 137 "libpmc" => 1,
138 "libposix" => 1, 138 "libposix" => 1,
139 "libppath" => 1, 139 "libppath" => 1,
140 "libprop" => 1, 140 "libprop" => 1,
141 "libpthread" => 1, 141 "libpthread" => 1,
142 "libpuffs" => 1, 142 "libpuffs" => 1,
143 "libquota" => 1, 143 "libquota" => 1,
144 "librefuse" => 1, 144 "librefuse" => 1,
145 "libresolv" => 1, 145 "libresolv" => 1,
146 "librt" => 1, 146 "librt" => 1,
147 "librumpclient" => 1, 147 "librumpclient" => 1,
148 "libsaslc" => 1, 148 "libsaslc" => 1,
149 "libssp" => 1, 149 "libssp" => 1,
150 "libtermcap" => 1, 150 "libtermcap" => 1,
151 "libterminfo" => 1, 151 "libterminfo" => 1,
152 "libusbhid" => 1, 152 "libusbhid" => 1,
153 "libutil" => 1, 153 "libutil" => 1,
154 "libx86_64" => 1, 154 "libx86_64" => 1,
155 "libz" => 1 155 "libz" => 1
156); 156);
157 157
158# constants to build 158# constants to build
159my %sections; 159my %sections;
160my $arches_re; 160my $arches_re;
161my $sections_re; 161my $sections_re;
162my $esections_re; 162my $esections_re;
163my $valid_date_re; 163my $valid_date_re;
164# and the code that builds them 164# and the code that builds them
165{ 165{
166 my @sections = ( 166 my @sections = (
167 "NAME", 167 "NAME",
168 NETBSD ? "LIBRARY" : undef, 168 NETBSD ? "LIBRARY" : undef,
169 "SYNOPSIS", 169 "SYNOPSIS",
170 "DESCRIPTION", 170 "DESCRIPTION",
171 NETBSD ? "IMPLEMENTATION NOTES" : undef, 171 NETBSD ? "IMPLEMENTATION NOTES" : undef,
172 "RETURN VALUES", 172 "RETURN VALUES",
173 "ENVIRONMENT", 173 "ENVIRONMENT",
174 "FILES", 174 "FILES",
175 "EXIT STATUS", 175 "EXIT STATUS",
176 "EXAMPLES", 176 "EXAMPLES",
177 "DIAGNOSTICS", 177 "DIAGNOSTICS",
178 NETBSD ? "COMPATIBILITY" : undef, 178 NETBSD ? "COMPATIBILITY" : undef,
179 "ERRORS", 179 "ERRORS",
180 "SEE ALSO", 180 "SEE ALSO",
181 "STANDARDS", 181 "STANDARDS",
182 "HISTORY", 182 "HISTORY",
183 "AUTHORS", 183 "AUTHORS",
184 "CAVEATS", 184 "CAVEATS",
185 "BUGS", 185 "BUGS",
186 NETBSD ? "SECURITY CONSIDERATIONS" : undef 186 NETBSD ? "SECURITY CONSIDERATIONS" : undef
187 ); 187 );
188 188
189 my $i = 1; 189 my $i = 1;
190 for my $sh (@sections) { 190 for my $sh (@sections) {
191 if (defined $sh) { 191 if (defined $sh) {
192 $sections{$sh} = $i++; 192 $sections{$sh} = $i++;
193 } 193 }
194 } 194 }
195 my @arches; 195 my @arches;
196 if (OPENBSD) { 196 if (OPENBSD) {
197 @arches = 197 @arches =
198 (qw(alpha amd64 arm armish aviion beagle cats hp300 hppa 198 (qw(alpha amd64 arm armish aviion beagle cats hp300 hppa
199 hppa64 i386 landisk loongson luna88k macppc mips64 199 hppa64 i386 landisk loongson luna88k macppc mips64
200 mvme68k mvme88k octeon sgi socppc sparc sparc64 vax 200 mvme68k mvme88k octeon sgi socppc sparc sparc64 vax
201 zaurus)); 201 zaurus));
202 } 202 }
203 if (NETBSD) { 203 if (NETBSD) {
204 @arches = 204 @arches =
205 (qw(acorn26 acorn32 algor alpha amiga arc atari 205 (qw(acorn26 acorn32 algor alpha amiga arc atari
206 bebox cats cesfic cobalt dreamcast evbarm evbmips evbppc 206 bebox cats cesfic cobalt dreamcast evbarm evbmips evbppc
207 evbsh3 evbsh5 hp300 hp700 hpcarm hpcmips hpcsh 207 evbsh3 evbsh5 hp300 hp700 hpcarm hpcmips hpcsh
208 i386 ibmnws luna68k mac68k macppc mipsco mmeye 208 i386 ibmnws luna68k mac68k macppc mipsco mmeye
209 mvme68k mvmeppc netwinder news68k newsmips next68k 209 mvme68k mvmeppc netwinder news68k newsmips next68k
210 pc532 playstation2 pmax pmppc prep sandpoint sbmips 210 pc532 playstation2 pmax pmppc prep sandpoint sbmips
211 sgimips shark sparc sparc64 sun2 sun3 vax walnut 211 sgimips shark sparc sparc64 sun2 sun3 vax walnut
212 x68k x86 x86_64 xen)); 212 x68k x86 x86_64 xen));
213 } 213 }
214 my $a = join('|', @arches); 214 my $a = join('|', @arches);
215 $arches_re = qr{(?:$a)}o; 215 $arches_re = qr{(?:$a)}o;
216 if (OPENBSD) { 216 if (OPENBSD) {
217 $sections_re = qr{(?:3p|[1-9])}o; 217 $sections_re = qr{(?:3p|[1-9])}o;
218 $esections_re = qr{(?:3p|[0-9])}o; 218 $esections_re = qr{(?:3p|[0-9])}o;
219 } 219 }
220 if (NETBSD) { 220 if (NETBSD) {
221 $sections_re = qr{[1-9]}o; 221 $sections_re = qr{[1-9]}o;
222 $esections_re = qr{[0-9]}o; 222 $esections_re = qr{[0-9]}o;
223 } 223 }
224 if (OPENBSD) { 224 if (OPENBSD) {
225 $valid_date_re = qr{\$Mdocdate\b}; 225 $valid_date_re = qr{\$Mdocdate\b};
226 } 226 }
227 if (NETBSD) { 227 if (NETBSD) {
228 $valid_date_re = qr{(?:January|February|March|April|May|June|July|August|September|October|November|December)\s*[1-9][0-9]*,\s*(?:198[0-9]|199[0-9]|200[0-9]|201[0-3])$}o; 228 $valid_date_re = qr{(?:January|February|March|April|May|June|July|August|September|October|November|December)\s*[1-9][0-9]*,\s*(?:198[0-9]|199[0-9]|200[0-9]|201[0-3])$}o;
229 } 229 }
230} 230}
231 231
232sub debug 232sub debug
233{ 233{
234 my $self = shift; 234 my $self = shift;
235 print STDOUT "debug: $self->{fn}:$self->{ln}: @_\n" if $opt_v; 235 print STDOUT "debug: $self->{fn}:$self->{ln}: @_\n" if $opt_v;
236} 236}
237 237
238sub warning 238sub warning
239{ 239{
240 my $self = shift; 240 my $self = shift;
241 my $extra = ""; 241 my $extra = "";
242 if ($opt_w) { 242 if ($opt_w) {
243 $extra = $self->{current_section_header}.":"; 243 $extra = $self->{current_section_header}.":";
244 } 244 }
245 print STDOUT "$self->{fn}:$extra$self->{ln}: ", join('', @_), "\n"; 245 print STDOUT "$self->{fn}:$extra$self->{ln}: ", join('', @_), "\n";
246} 246}
247 247
248my $order = " !\"#\$\%&'()*+,-./:;<=>?[\\]^_{|}~". 248my $order = " !\"#\$\%&'()*+,-./:;<=>?[\\]^_{|}~".
249 "0123456789". 249 "0123456789".
250 "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; 250 "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
251 251
252sub handle_options 252sub handle_options
253{ 253{
254 getopts($options); 254 getopts($options);
255 $opt_h and usage(); 255 $opt_h and usage();
256 256
257 # default to all warnings if no flag is set 257 # default to all warnings if no flag is set
258 unless ($opt_A or $opt_a or $opt_D or $opt_d or $opt_e 258 unless ($opt_A or $opt_a or $opt_D or $opt_d or $opt_e
259 or $opt_f or $opt_H or $opt_l 259 or $opt_f or $opt_H or $opt_l
260 or $opt_m or $opt_n 260 or $opt_m or $opt_n
261 or $opt_o or $opt_P or $opt_p or $opt_r 261 or $opt_o or $opt_P or $opt_p or $opt_r
262 or $opt_S or $opt_s or $opt_X or $opt_x) { 262 or $opt_S or $opt_s or $opt_X or $opt_x) {
263 $opt_A = $opt_a = $opt_D = $opt_d = $opt_f = $opt_m = 263 $opt_A = $opt_a = $opt_D = $opt_d = $opt_f = $opt_m =
264 $opt_n = $opt_o = $opt_P = $opt_p = $opt_r = $opt_S = 264 $opt_n = $opt_o = $opt_P = $opt_p = $opt_r = $opt_S =
265 $opt_s = $opt_X = $opt_x = 1; 265 $opt_s = $opt_X = $opt_x = 1;
266 $opt_e = $opt_l = 1 if NETBSD; 266 $opt_e = $opt_l = 1 if NETBSD;
267 } 267 }
268} 268}
269 269
270 270
271sub verify_xref 271sub verify_xref
272{ 272{
273 my ($self, $page, $section, $pre, $post) = @_; 273 my ($self, $page, $section, $pre, $post) = @_;
274 if ("$page.$section" eq $self->{fn}) { 274 if ("$page.$section" eq $self->{fn}) {
275 $self->warning("Xref to itself (use .Nm instead)") if $opt_x; 275 $self->warning("Xref to itself (use .Nm instead)") if $opt_x;
276 } 276 }
277 # try to find corresponding man page 277 # try to find corresponding man page
278 for my $dir ("/usr/share/man", 278 for my $dir ("/usr/share/man",
279 OPENBSD ? "/usr/X11R6/man" : "/usr/X11R7/man") { 279 OPENBSD ? "/usr/X11R6/man" : "/usr/X11R7/man") {
280 for my $a ("", $arch) { 280 for my $a ("", $arch) {
281 for my $page ("man$section/$a/$page.$section") { 281 for my $page ("man$section/$a/$page.$section") {
282 return 1 if -f "$dir/$page"; 282 return 1 if -f "$dir/$page";
283 } 283 }
284 } 284 }
285 } 285 }
286 return 1 if -f "./$page.$section"; 286 return 1 if -f "./$page.$section";
287 287
288 $self->warning($pre."trailing Xref to $page($section)$post") if $opt_x; 288 $self->warning($pre."trailing Xref to $page($section)$post") if $opt_x;
289 return 0; 289 return 0;
290} 290}
291 291
292sub new 292sub new
293{ 293{
294 my ($class, $fn) = @_; 294 my ($class, $fn) = @_;
295 295
296 my $o = { 296 my $o = {
297 mandoc_p => 1, 297 mandoc_p => 1,
298 all => [], 298 all => [],
299 lastline => '', 299 lastline => '',
300 changes => 0, 300 changes => 0,
301 oxrcsidseen => 0, 301 oxrcsidseen => 0,
302 nxrcsidseen => 0, 302 nxrcsidseen => 0,
303 lastsh => 0, 303 lastsh => 0,
304 sasection => 0, 304 sasection => 0,
305 saname => '', 305 saname => '',
306 sarest => ',', 306 sarest => ',',
307 inauthors => 0, 307 inauthors => 0,
308 in_section => 0, 308 in_section => 0,
309 inliteral => 0, 309 inliteral => 0,
310 shseen => {}, 310 shseen => {},
311 last_error_name => '', 311 last_error_name => '',
312 current_section_header => '', 312 current_section_header => '',
313 fn => $fn 313 fn => $fn
314 }; 314 };
315 open my $input, '<', $fn or die "can't open input file $fn"; 315 open my $input, '<', $fn or die "can't open input file $fn";
316 $o->{file} = $input; 316 $o->{file} = $input;
317 $o->{ln} = 0; 317 $o->{ln} = 0;
318 bless $o, $class; 318 bless $o, $class;
319} 319}
320 320
321sub next_line 321sub next_line
322{ 322{
323 my ($self) = @_; 323 my ($self) = @_;
324 324
325 my $l = readline($self->{file}); 325 my $l = readline($self->{file});
326 if (defined $l) { 326 if (defined $l) {
327 $self->{ln}++; 327 $self->{ln}++;
328 } 328 }
329 return $l; 329 return $l;
330} 330}
331 331
332sub close 332sub close
333{ 333{
334 my ($self) = @_; 334 my ($self) = @_;
335 335
336 close($self->{file}); 336 close($self->{file});
337} 337}
338 338
339sub parse_macro_args 339sub parse_macro_args
340{ 340{
341 my ($s, $string) = @_; 341 my ($s, $string) = @_;
342 $_ = $string; 342 $_ = $string;
343 my @params = (); 343 my @params = ();
344 while (!/^$/) { 344 while (!/^$/) {
345 if (s/^\"(.*?)\"\s*//) { 345 if (s/^\"(.*?)\"\s*//) {
346 push(@params, $1); 346 push(@params, $1);
347 } elsif (s/^(\S+)\s*//) { 347 } elsif (s/^(\S+)\s*//) {
348 push(@params, $1); 348 push(@params, $1);
349 } 349 }
350 } 350 }
351 if (@params > 9 and OPENBSD) { 351 if (@params > 9 and OPENBSD) {
352 $s->warning("$string holds >9 parameters"); 352 $s->warning("$string holds >9 parameters");
353 } 353 }
354 return @params; 354 return @params;
355} 355}
356 356
357sub end_of_section 357sub end_of_section
358{ 358{
359 my ($s) = @_; 359 my ($s) = @_;
360 360
361 if ($s->{in_section} == SECTION_SEE_ALSO and not $s->{sarest} eq "") { 361 if ($s->{in_section} == SECTION_SEE_ALSO and not $s->{sarest} eq "") {
362 $s->warning("unneeded characters at end of SEE ALSO: ", 362 $s->warning("unneeded characters at end of SEE ALSO: ",
363 "`$s->{sarest}'") if $opt_a; 363 "`$s->{sarest}'") if $opt_a;
364 # to avoid a second warning at EOF 364 # to avoid a second warning at EOF
365 $s->{sarest} = ""; 365 $s->{sarest} = "";
366 } 366 }
367 367
368 if ($s->{in_section} == SECTION_AUTHORS) { 368 if ($s->{in_section} == SECTION_AUTHORS) {
369 if (!$s->{an_found}) { 369 if (!$s->{an_found}) {
370 $s->warning("missing .An in AUTHORS section") if $opt_A; 370 $s->warning("missing .An in AUTHORS section") if $opt_A;
371 } 371 }
372 } 372 }
373} 373}
374 374
375sub set_section_header 375sub set_section_header
376{ 376{
377 my ($s, $section_header) = @_; 377 my ($s, $section_header) = @_;
378 $section_header = join(' ', $s->parse_macro_args($section_header)); 378 $section_header = join(' ', $s->parse_macro_args($section_header));
379 379
380 end_of_section($s); 380 end_of_section($s);
381  381
382 if ($section_header eq 'SEE ALSO') { 382 if ($section_header eq 'SEE ALSO') {
383 $s->{in_section} = SECTION_SEE_ALSO; 383 $s->{in_section} = SECTION_SEE_ALSO;
384 } elsif ($section_header eq 'AUTHORS') { 384 } elsif ($section_header eq 'AUTHORS') {
385 $s->{in_section} = SECTION_AUTHORS; 385 $s->{in_section} = SECTION_AUTHORS;
386 } else { 386 } else {
387 $s->{in_section} = 0; 387 $s->{in_section} = 0;
388 } 388 }
389 389
390 if (not $sections{$section_header}) { 390 if (not $sections{$section_header}) {
391 $s->warning("unknown section header: ", 391 $s->warning("unknown section header: ",
392 "`$section_header'") if $opt_S; 392 "`$section_header'") if $opt_S;
393 } else { 393 } else {
394 if ($s->{lastsh} >= $sections{$section_header}) { 394 if ($s->{lastsh} >= $sections{$section_header}) {
395 $s->warning("section header ", 395 $s->warning("section header ",
396 "`$section_header' in wrong order") if $opt_S; 396 "`$section_header' in wrong order") if $opt_S;
397 } 397 }
398 $s->{shseen}->{$section_header} = 1; 398 $s->{shseen}->{$section_header} = 1;
399 $s->{lastsh} = $sections{$section_header}; 399 $s->{lastsh} = $sections{$section_header};
400 } 400 }
401 401
402 if ($s->{lastline} =~ /^\.Pp/o) { 402 if ($s->{lastline} =~ /^\.Pp/o) {
403 $s->warning("Paragraph problem: section header after .Pp") 403 $s->warning("Paragraph problem: section header after .Pp")
404 if $opt_P; 404 if $opt_P;
405 } 405 }
406 406
407 $s->{current_section_header} = $section_header; 407 $s->{current_section_header} = $section_header;
408} 408}
409 409
410sub process_and_save_line 410sub process_and_save_line
411{ 411{
412 my $s; 412 my $s;
413 ($s, $_) = @_; 413 ($s, $_) = @_;
414 my $result = $s->process_line($_); 414 my $result = $s->process_line($_);
415 # note that process_line chomps \n, then re-adds it, 415 # note that process_line chomps \n, then re-adds it,
416 # so we detect a change on last lines without a \n. 416 # so we detect a change on last lines without a \n.
417 if ($result ne $_) { 417 if ($result ne $_) {
418 $s->{changes} = 1; 418 $s->{changes} = 1;
419 } 419 }
420 push(@{$s->{all}}, $result); 420 push(@{$s->{all}}, $result);
421} 421}
422 422
423sub process_line 423sub process_line
424{ 424{
425 my $s; 425 my $s;
426 ($s, $_) = @_; 426 ($s, $_) = @_;
427 chomp; 427 chomp;
428 # always cut trailing spaces 428 # always cut trailing spaces
429 if (/\s+$/o) { 429 if (/\s+$/o) {
430 $s->warning("trailing space: `$_'") if $opt_s; 430 $s->warning("trailing space: `$_'") if $opt_s;
431 s/\s+$//o; 431 s/\s+$//o;
432 } 432 }
433 if (/\$OpenBSD\b.*\$/o) { 433 if (/\$OpenBSD\b.*\$/o) {
434 $s->{oxrcsidseen}++; 434 $s->{oxrcsidseen}++;
435 if (OPENBSD and ($s->{oxrcsidseen} > 1)) { 435 if (OPENBSD and ($s->{oxrcsidseen} > 1)) {
436 $s->warning("RCS Id seen twice") if $opt_r; 436 $s->warning("RCS Id seen twice") if $opt_r;
437 } 437 }
438 return "$_\n"; 438 return "$_\n";
439 } 439 }
440 if (/[\$]NetBSD\b.*\$/o) { 440 if (/[\$]NetBSD\b.*\$/o) {
441 $s->{nxrcsidseen}++; 441 $s->{nxrcsidseen}++;
442 if (NETBSD and ($s->{nxrcsidseen} > 1)) { 442 if (NETBSD and ($s->{nxrcsidseen} > 1)) {
443 $s->warning("RCS Id seen twice") if $opt_r; 443 $s->warning("RCS Id seen twice") if $opt_r;
444 } 444 }
445 return "$_\n"; 445 return "$_\n";
446 } 446 }
447 # comments 447 # comments
448 if (/^\.\\\"/) { 448 if (/^\.\\\"/) {
449 return "$_\n"; 449 return "$_\n";
450 } 450 }
451 if (/^\.TH\s+/o) { 451 if (/^\.TH\s+/o) {
452 $s->warning("not mandoc") if $opt_m; 452 $s->warning("not mandoc") if $opt_m;
453 $s->{mandoc_p} = 0; 453 $s->{mandoc_p} = 0;
454# /^.TH\s*[\w-_".]+\s*([1-9])/; 454# /^.TH\s*[\w-_".]+\s*([1-9])/;
455# $section = $1; 455# $section = $1;
456 return "$_\n"; 456 return "$_\n";
457 } 457 }
458# if (/^.Dt\s*[\w-_".]+\s*([1-9])/) { 458# if (/^.Dt\s*[\w-_".]+\s*([1-9])/) {
459# $section = $1; 459# $section = $1;
460# } 460# }
461 if (/^\.Dt\s+/o) { 461 if (/^\.Dt\s+/o) {
462 if (! /^\.Dt\s+(?:[A-Z\d._-]+)\s+$sections_re(?:\s+$arches_re)?$/o) { 462 if (! /^\.Dt\s+(?:[A-Z\d._-]+)\s+$sections_re(?:\s+$arches_re)?$/o) {
463 $s->warning("bad .Dt: `$_'") if $opt_D; 463 $s->warning("bad .Dt: `$_'") if $opt_D;
464 } 464 }
465 } 465 }
466 466
467 if ($s->{mandoc_p}) { 467 if ($s->{mandoc_p}) {
468 if (/^\.Sh\s+(.*)$/o) { 468 if (/^\.Sh\s+(.*)$/o) {
469 my $line = $_; 469 my $line = $_;
470 $s->set_section_header($1); 470 $s->set_section_header($1);
471 return "$line\n"; 471 return "$line\n";
472 } 472 }
473 } else { 473 } else {
474 if (/^\.SH\s+(.*)$/o) { 474 if (/^\.SH\s+(.*)$/o) {
475 my $line = $_; 475 my $line = $_;
476 $s->set_section_header($1); 476 $s->set_section_header($1);
477 return "$line\n"; 477 return "$line\n";
478 } 478 }
479 } 479 }
480 480
481 if ($s->{in_section} == SECTION_SEE_ALSO) { 481 if ($s->{in_section} == SECTION_SEE_ALSO) {
482 if (/^\.Xr\s+(\S+)\s+($sections_re)\s?(.*)?$/o) { 482 if (/^\.Xr\s+(\S+)\s+($sections_re)\s?(.*)?$/o) {
483 my ($saname, $sasection, $sarest) = ($1, $2, $3); 483 my ($saname, $sasection, $sarest) = ($1, $2, $3);
484 $saname =~ s/^\\&//o; 484 $saname =~ s/^\\&//o;
485 if ($s->{sasection} gt $sasection 485 if ($s->{sasection} gt $sasection
486 or ($s->{sasection} eq $sasection and 486 or ($s->{sasection} eq $sasection and
487 (lc($s->{saname}) gt lc($saname)))) { 487 (lc($s->{saname}) gt lc($saname)))) {
488 $s->warning("SEE ALSO: `.Xr $s->{saname} ", 488 $s->warning("SEE ALSO: `.Xr $s->{saname} ",
489 "$s->{sasection}' should be after ", 489 "$s->{sasection}' should be after ",
490 "`.Xr $saname $sasection'") if $opt_a; 490 "`.Xr $saname $sasection'") if $opt_a;
491 } 491 }
492 if ($s->{sarest} ne ",") { 492 if ($s->{sarest} ne ",") {
493 $s->warning("SEE ALSO: .Xr not separated ", 493 $s->warning("SEE ALSO: .Xr not separated ",
494 "by comma, but `$s->{sarest}'") if $opt_a; 494 "by comma, but `$s->{sarest}'") if $opt_a;
495 } 495 }
496 $s->{saname} = $saname; 496 $s->{saname} = $saname;
497 $s->{sasection} = $sasection; 497 $s->{sasection} = $sasection;
498 $s->{sarest} = $sarest; 498 $s->{sarest} = $sarest;
499 } 499 }
500 if (/^\.Rs(?:\s+|$)/o) { 500 if (/^\.Rs(?:\s+|$)/o) {
501 if ($s->{sarest} ne "") { 501 if ($s->{sarest} ne "") {
502 $s->warning("SEE ALSO: Not necessary to ", 502 $s->warning("SEE ALSO: Not necessary to ",
503 "separate .Xr from .Rs by ", 503 "separate .Xr from .Rs by ",
504 "`$s->{sarest}'") if $opt_a; 504 "`$s->{sarest}'") if $opt_a;
505 } 505 }
506 $s->{sarest} = ""; 506 $s->{sarest} = "";
507 } 507 }
508 } 508 }
509 if ($s->{in_section} == SECTION_AUTHORS) { 509 if ($s->{in_section} == SECTION_AUTHORS) {
510 if (/^\.An / && not /^\.An -(no|)split/) { 510 if (/^\.An / && not /^\.An -(no|)split/) {
511 $s->{an_found} = 1; 511 $s->{an_found} = 1;
512 } 512 }
513 } 513 }
514 514
515 if (/^\.Fn.*,.+/o) { 515 if (/^\.Fn.*,.+/o) {
516 $s->warning("possible .Fn misuse: `$_'") if $opt_f; 516 $s->warning("possible .Fn misuse: `$_'") if $opt_f;
517 } 517 }
518 if (OPENBSD) { 518 if (OPENBSD) {
519 if (/^(?:[<>])/o or /[^\\][<>]/o) { 519 if (/^(?:[<>])/o or /[^\\][<>]/o) {
520 $s->warning("use \*(Lt \*(Gt (or .Aq) ", 520 $s->warning("use \*(Lt \*(Gt (or .Aq) ",
521 "instead of < >: `$_'") if $opt_H; 521 "instead of < >: `$_'") if $opt_H;
522 } 522 }
523 } 523 }
524 if (NETBSD) { 524 if (NETBSD) {
525 if (/^(?:[<>&])/o or /[^\\][<>&]/o) { 525 if (/^(?:[<>&])/o or /[^\\][<>&]/o) {
526 $s->warning("use \*[Lt] \*[Gt] (or .Aq) \*[Am] ", 526 $s->warning("use \*[Lt] \*[Gt] (or .Aq) \*[Am] ",
527 "instead of < > &: `$_'") if $opt_H; 527 "instead of < > &: `$_'") if $opt_H;
528 } 528 }
529 } 529 }
530 530
531 if (/\b(Free|Net|Open)BSD\b/o 531 if (/\b(Free|Net|Open)BSD\b/o
532 and not /\b(?:www|ftp)\.(?:Free|Net|Open)BSD\.org\b/o 532 and not /\b(?:www|ftp)\.(?:Free|Net|Open)BSD\.org\b/o
533 and not /\bOpenBSD\::.*3p\b/o 533 and not /\bOpenBSD\::.*3p\b/o
534 and not /\/pub\/OpenBSD\//o 534 and not /\/pub\/OpenBSD\//o
535 and not /\@(?:Free|Net|Open)BSD\.(?i:org)\b/o) { 535 and not /\@(?:Free|Net|Open)BSD\.(?i:org)\b/o) {
536 $s->warning("verbose mention of `$1BSD' instead of " 536 $s->warning("verbose mention of `$1BSD' instead of "
537 . "`$short{$1}': `$_'") if $opt_X; 537 . "`$short{$1}': `$_'") if $opt_X;
538 } 538 }
539 if (/^\./o and (/Bx (Open)/o or /Bx (Free)/o or /Bx (Net)/o)) { 539 if (/^\./o and (/Bx (Open)/o or /Bx (Free)/o or /Bx (Net)/o)) {
540 $s->warning("`.Bx $1' found -- use $short{$1} instead") 540 $s->warning("`.Bx $1' found -- use $short{$1} instead")
541 if $opt_X; 541 if $opt_X;
542 } 542 }
543 if (/^\.Lb\s+(\S+)/o) { 543 if (/^\.Lb\s+(\S+)/o) {
544 if (not $libraries{$1}) { 544 if (not $libraries{$1}) {
545 $s->warning("Unknown library `$1' used as Lb argument") if $opt_l; 545 $s->warning("Unknown library `$1' used as Lb argument") if $opt_l;
546 } 546 }
547 } 547 }
548 if (/^\.Os\s+(.+)/o) { 548 if (/^\.Os\s+(.+)/o) {
549 $s->warning(".Os used with argument `$1'") if $opt_o; 549 $s->warning(".Os used with argument `$1'") if $opt_o;
550 } 550 }
551 551
552 if (/^\.Nd.*\.$/o) { 552 if (/^\.Nd.*\.$/o) {
553 $s->warning(".Nd ends with a dot: `$_'") if $opt_n; 553 $s->warning(".Nd ends with a dot: `$_'") if $opt_n;
554 } 554 }
555 555
556 if (/(\w\w)\.\s+[A-Z]/o and not /^.%T/ and not $s->{inliteral}) { 556 if (/(\w\w)\.\s+[A-Z]/o and not /^.%T/ and not $s->{inliteral}) {
557 if ("$1" ne "St") { 557 if ("$1" ne "St") {
558 $s->warning("new sentence, new line: `$_'") if $opt_p; 558 $s->warning("new sentence, new line: `$_'") if $opt_p;
559 } 559 }
560 } 560 }
561 if (/^\... .*[^\s][\.();,\[\]\{\}:]$/o 561 if (/^\... .*[^\s][\.();,\[\]\{\}:]$/o
562 and not /\s\.\.\.$/o and not /\\&.$/o) { 562 and not /\s\.\.\.$/o and not /\\&.$/o) {
563 $s->warning("punctuation in format string ", 563 $s->warning("punctuation in format string ",
564 "without space: `$_'") if $opt_p; 564 "without space: `$_'") if $opt_p;
565 } 565 }
566 if (/^\./o and /Ns [\.();,\[\]\{\}:]/o) { 566 if (/^\./o and /Ns [\.();,\[\]\{\}:]/o) {
567 $s->warning("possible Ns abuse: `$_'") if $opt_p; 567 $s->warning("possible Ns abuse: `$_'") if $opt_p;
568 } 568 }
569 if ((/^([^\.]\w+)\(\)/o or /^[^\.].*\s(\w+)\(\)/o) and not $s->{inliteral}) { 569 if ((/^([^\.]\w+)\(\)/o or /^[^\.].*\s(\w+)\(\)/o) and not $s->{inliteral}) {
570 $s->warning("use .Fn or .Xr for functions: `$1()'") if $opt_p; 570 $s->warning("use .Fn or .Xr for functions: `$1()'") if $opt_p;
571 } 571 }
572 572
573 my $destruct = $_; 573 my $destruct = $_;
574 if ($s->{mandoc_p}) { 574 if ($s->{mandoc_p}) {
575 $destruct =~ s/\\\&([\w\.])/$1/o; 575 $destruct =~ s/\\\&([\w\.])/$1/o;
576 if ($destruct =~ /^\.Xr\s+([\w\:\.\-\+\/]+)\s+($esections_re)(.*)/o) { 576 if ($destruct =~ /^\.Xr\s+([\w\:\.\-\+\/]+)\s+($esections_re)(.*)/o) {
577 $s->debug("Xref to $1($2) found: `$_'"); 577 $s->debug("Xref to $1($2) found: `$_'");
578 $s->verify_xref($1, $2, "", ""); 578 $s->verify_xref($1, $2, "", "");
579 if ($3 =~ /^\S/o) { 579 if ($3 =~ /^\S/o) {
580 $s->warning("No space after section number in Xref: `$_'") if $opt_x; 580 $s->warning("No space after section number in Xref: `$_'") if $opt_x;
581 } 581 }
582 } elsif ($destruct =~ /^\.Xr/o) { 582 } elsif ($destruct =~ /^\.Xr/o) {
583 $s->warning("Weird Xref found: `$_'") if $opt_x; 583 $s->warning("Weird Xref found: `$_'") if $opt_x;
584 } 584 }
585 } else { 585 } else {
586 $destruct =~ s/\\f.//go; 586 $destruct =~ s/\\f.//go;
587 if ($destruct !~ /^\.\\\"/o) { 587 if ($destruct !~ /^\.\\\"/o) {
588 while ($destruct =~ s/([-\w.]+)\s*\(($esections_re)\)//o) { 588 while ($destruct =~ s/([-\w.]+)\s*\(($esections_re)\)//o) {
589 $s->debug("possible Xref to $1($2) found: `$_'"); 589 $s->debug("possible Xref to $1($2) found: `$_'");
590 $s->verify_xref($1, $2, "possible ", ": `$_'"); 590 $s->verify_xref($1, $2, "possible ", ": `$_'");
591 # so that we have a chance to find more than one 591 # so that we have a chance to find more than one
592 # per line 592 # per line
593 $destruct =~ s/(\w+)\s*\(($sections_re)\)//o; 593 $destruct =~ s/(\w+)\s*\(($sections_re)\)//o;
594 } 594 }
595 } 595 }
596 } 596 }
597 597
598 if (/^\.Dd/o and not /^\.Dd\s+$valid_date_re/o) { 598 if (/^\.Dd/o and not /^\.Dd\s+$valid_date_re/o) {
599 $s->warning("Invalid date found: `$_'") if $opt_d; 599 $s->warning("Invalid date found: `$_'") if $opt_d;
600 } 600 }
601 601
602 if (/^\.Bd\b.*-literal\b/o) { 602 if (/^\.Bd\b.*-literal\b/o) {
603 $s->{inliteral} = 1; 603 $s->{inliteral} = 1;
604 } 604 }
605 if ($s->{inliteral} == 1) { 605 if ($s->{inliteral} == 1) {
606 if (/^\.Ed\b/o) { 606 if (/^\.Ed\b/o) {
607 $s->{inliteral} = 0; 607 $s->{inliteral} = 0;
608 } 608 }
609 } elsif (/^$/o) { 609 } elsif (/^$/o) {
610 $s->warning("Paragraph problem: empty line -- ", 610 $s->warning("Paragraph problem: empty line -- ",
611 "use .Pp for paragraphs") if $opt_P; 611 "use .Pp for paragraphs") if $opt_P;
612 } 612 }
613 if ($s->{lastline} =~ /^\.Pp/o and /^(\.Ss|\.Pp)/o) { 613 if ($s->{lastline} =~ /^\.Pp/o and /^(\.Ss|\.Pp)/o) {
614 $s->warning("Paragraph problem: $1 after .Pp") if $opt_P; 614 $s->warning("Paragraph problem: $1 after .Pp") if $opt_P;
615 } 615 }
616 if (/^\.Pp/o and $s->{lastline} =~ /^(\.S[Ssh])/o) { 616 if (/^\.Pp/o and $s->{lastline} =~ /^(\.S[Ssh])/o) {
617 $s->warning("Paragraph problem: .Pp after $1") if $opt_P; 617 $s->warning("Paragraph problem: .Pp after $1") if $opt_P;
618 } 618 }
619 619
620 # Check whether the list of possible errors for a function is 620 # Check whether the list of possible errors for a function is
621 # sorted alphabetically. 621 # sorted alphabetically.
622 # 622 #
623 # Error names should not be sorted across different lists. 623 # Error names should not be sorted across different lists.
624 # (see bind(2) for an example.) 624 # (see bind(2) for an example.)
625 # 625 #
626 /^\.Bl\s+/o and $s->{last_error_name} = ""; 626 /^\.Bl\s+/o and $s->{last_error_name} = "";
627 627
628 if ($s->{current_section_header} eq "ERRORS" and 628 if ($s->{current_section_header} eq "ERRORS" and
629 /^\.It\s+(Bq\s+)?(Er\s+)?(E[\w_]+)$/o) { 629 /^\.It\s+(Bq\s+)?(Er\s+)?(E[\w_]+)$/o) {
630 my $current_error_name = $3; 630 my $current_error_name = $3;
631 631
632 if ($s->{last_error_name} eq $current_error_name) { 632 if ($s->{last_error_name} eq $current_error_name) {
633 $s->warning("Duplicate item for ", 633 $s->warning("Duplicate item for ",
634 $current_error_name, ".") if $opt_e; 634 $current_error_name, ".") if $opt_e;
635 } elsif ($current_error_name lt $s->{last_error_name}) { 635 } elsif ($current_error_name lt $s->{last_error_name}) {
636 $s->warning("$s->{last_error_name} and ", 636 $s->warning("$s->{last_error_name} and ",
637 "$current_error_name are not in ", 637 "$current_error_name are not in ",
638 "alphabetical order.") if $opt_e; 638 "alphabetical order.") if $opt_e;
639 } 639 }
640 $s->{last_error_name} = $current_error_name; 640 $s->{last_error_name} = $current_error_name;
641 } 641 }
642 642
643 $s->{lastline} = $_; 643 $s->{lastline} = $_;
644 return "$_\n"; 644 return "$_\n";
645} 645}
646 646
647sub finish 647sub finish
648{ 648{
649 my ($s) = @_; 649 my ($s) = @_;
650 650
651 if (NETBSD and not $s->{nxrcsidseen}) { 651 if (NETBSD and not $s->{nxrcsidseen}) {
652 $s->warning("Missing RCS Id") if $opt_r; 652 $s->warning("Missing RCS Id") if $opt_r;
653 } 653 }
654 if (OPENBSD and not $s->{oxrcsidseen}) { 654 if (OPENBSD and not $s->{oxrcsidseen}) {
655 $s->warning("Missing RCS Id") if $opt_r; 655 $s->warning("Missing RCS Id") if $opt_r;
656 } 656 }
657 657
658 if ($s->{lastline} =~ /^\.Pp/o) { 658 if ($s->{lastline} =~ /^\.Pp/o) {
659 $s->warning("Paragraph problem: .Pp at EOF") if $opt_P; 659 $s->warning("Paragraph problem: .Pp at EOF") if $opt_P;
660 } 660 }
661 661
662 end_of_section($s); 662 end_of_section($s);
663 663
664# if (not ($fn =~ /$section$/)) { 664# if (not ($fn =~ /$section$/)) {
665# $s->warning("section doesn't match (internal value: $section)"); 665# $s->warning("section doesn't match (internal value: $section)");
666# } 666# }
667 if ($s->{mandoc_p}) { 667 if ($s->{mandoc_p}) {
668 foreach my $i (qw(NAME SYNOPSIS DESCRIPTION)) { 668 foreach my $i (qw(NAME SYNOPSIS DESCRIPTION)) {
669 if (not ($s->{shseen}{$i})) { 669 if (not ($s->{shseen}{$i})) {
670 $s->warning("missing $i section") if $opt_S; 670 $s->warning("missing $i section") if $opt_S;
671 } 671 }
672 } 672 }
673 } 673 }
674} 674}
675 675
676package main; 676package main;
677 677
678sub handle_file 678sub handle_file
679{ 679{
680 my $parser = Parser->new($_[0]); 680 my $parser = Parser->new($_[0]);
681 681
682 while ($_ = $parser->next_line) { 682 while ($_ = $parser->next_line) {
683 $parser->process_and_save_line($_); 683 $parser->process_and_save_line($_);
684 } 684 }
685 685
686 $parser->finish; 686 $parser->finish;
687 $parser->close; 687 $parser->close;
688 if ($Parser::opt_F and $parser->{changes}) { 688 if ($Parser::opt_F and $parser->{changes}) {
689 open OUT, ">$_[0].new" or 689 open OUT, ">$_[0].new" or
690 die "can't open output file `$_[0].new'"; 690 die "can't open output file `$_[0].new'";
691 for my $l (@{$parser->{all}}) { 691 for my $l (@{$parser->{all}}) {
692 print OUT $l 692 print OUT $l
693 } 693 }
694 close OUT; 694 close OUT;
695 system("mv -i $_[0].new $_[0]"); 695 system("mv -i $_[0].new $_[0]");
696 } 696 }
697} 697}
698 698
699Parser->handle_options; 699Parser->handle_options;
700foreach my $file (@ARGV) { 700foreach my $file (@ARGV) {
701 handle_file($file); 701 handle_file($file);
702} 702}