summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
Diffstat (limited to 'libexec')
-rw-r--r--libexec/makewhatis/Makefile43
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis.pm193
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis/Check.pm84
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis/Find.pm45
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis/Formated.pm139
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis/Unformated.pm231
-rw-r--r--libexec/makewhatis/OpenBSD/Makewhatis/Whatis.pm64
-rw-r--r--libexec/makewhatis/makewhatis37
-rw-r--r--libexec/makewhatis/makewhatis.pl632
9 files changed, 831 insertions, 637 deletions
diff --git a/libexec/makewhatis/Makefile b/libexec/makewhatis/Makefile
index a4c7002fb13..743ceaccb54 100644
--- a/libexec/makewhatis/Makefile
+++ b/libexec/makewhatis/Makefile
@@ -1,10 +1,43 @@
-# $OpenBSD: Makefile,v 1.6 2000/02/03 18:10:48 espie Exp $
+# $OpenBSD: Makefile,v 1.7 2004/08/06 12:05:08 espie Exp $
MAN=makewhatis.8
-NOPROG=
+PACKAGES= \
+ OpenBSD/Makewhatis.pm \
+ OpenBSD/Makewhatis/Check.pm \
+ OpenBSD/Makewhatis/Find.pm \
+ OpenBSD/Makewhatis/Formated.pm \
+ OpenBSD/Makewhatis/Unformated.pm \
+ OpenBSD/Makewhatis/Whatis.pm
-afterinstall:
+SCRIPTS= \
+ makewhatis
+
+LIBBASE=/usr/libdata/perl5
+
+# Nothing to build
+depend:
+all:
+
+install:
+.for i in ${PACKAGES}
+ ${INSTALL} -d -o ${LIBOWN} -g ${LIBGRP} -m ${DIRMODE} \
+ ${DESTDIR}${LIBBASE}/${i:H}
+ ${INSTALL} ${INSTALL_COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${.CURDIR}/$i ${DESTDIR}${LIBBASE}/$i
+.endfor
+.for i in ${SCRIPTS}
${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
- ${.CURDIR}/makewhatis.pl ${DESTDIR}${BINDIR}/makewhatis
+ ${.CURDIR}/$i ${DESTDIR}${BINDIR}/$i
+.endfor
+
+clean:
+
+.include <bsd.own.mk>
+
+.if !defined(NOMAN)
+install: maninstall
+.include <bsd.man.mk>
+.endif
-.include <bsd.prog.mk>
+.include <bsd.obj.mk>
+.include <bsd.subdir.mk>
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis.pm b/libexec/makewhatis/OpenBSD/Makewhatis.pm
new file mode 100644
index 00000000000..efe47e7c020
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis.pm
@@ -0,0 +1,193 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Makewhatis.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+
+package OpenBSD::Makewhatis;
+
+my ($picky, $testmode);
+
+
+# $subjects = scan_manpages($list)
+#
+# scan a set of manpages, return list of subjects
+#
+sub scan_manpages
+{
+ my $list = shift;
+ local $_;
+ my $done=[];
+
+ for (@$list) {
+ my ($file, $subjects);
+ if (m/\.(?:Z|gz)$/) {
+ unless (open $file, '-|', "gzip -fdc $_") {
+ warn "$0: Can't decompress $_\n";
+ next;
+ }
+ $_ = $`;
+ } else {
+ unless (open $file, '<', $_) {
+ warn "$0: Can't read $_\n";
+ next;
+ }
+ }
+ if (m/\.[1-9ln][^.]*$/) {
+ require OpenBSD::Makewhatis::Unformated;
+
+ $subjects = OpenBSD::Makewhatis::Unformated::handle($file, $_);
+ } elsif (m/\.0$/) {
+ require OpenBSD::Makewhatis::Formated;
+
+ $subjects = OpenBSD::Makewhatis::Formated::handle($file, $_);
+ # in test mode, we try harder
+ } elsif ($testmode) {
+ require OpenBSD::Makewhatis::Unformated;
+
+ $subjects = OpenBSD::Makewhatis::Unformated::handle($file, $_);
+ if (@$subjects == 0) {
+ require OpenBSD::Makewhatis::Formated;
+
+ $subjects = OpenBSD::Makewhatis::Formated::handle($file, $_);
+ }
+ } else {
+ print STDERR "Can't find type of $_";
+ next;
+ }
+ if ($picky) {
+ require OpenBSD::Makewhatis::Check;
+
+ for my $s (@$subjects) {
+ OpenBSD::Makewhatis::Check::verify_subject($s, $_);
+ }
+ }
+ push @$done, @$subjects;
+ }
+ return $done;
+}
+
+# build_index($dir)
+#
+# build index for $dir
+#
+sub build_index
+{
+ require OpenBSD::Makewhatis::Find;
+ require OpenBSD::Makewhatis::Whatis;
+
+ my $dir = shift;
+ my $list = OpenBSD::Makewhatis::Find::find_manpages($dir);
+ my $subjects = scan_manpages($list);
+ OpenBSD::Makewhatis::Whatis::write($subjects, $dir);
+}
+
+sub merge
+{
+ require OpenBSD::Makewhatis::Whatis;
+
+ my ($mandir, $args) = @_;
+
+ unless (-d $mandir) {
+ die "$0: $mandir: not a directory"
+ }
+ chdir $mandir;
+
+ my $whatis = "$mandir/whatis.db";
+ open(my $old, '<', $whatis) or
+ die "$0 $whatis to merge with";
+ my $subjects = scan_manpages($args);
+ while (<$old>) {
+ chomp;
+ push(@$subjects, $_);
+ }
+ close($old);
+ OpenBSD::Makewhatis::Whatis::write($subjects, $mandir);
+}
+
+sub remove
+{
+ require OpenBSD::Makewhatis::Whatis;
+
+ my ($mandir, $args) = @_;
+ unless (-d $mandir) {
+ die "$0: $mandir: not a directory"
+ }
+ chdir $mandir;
+
+ my $whatis = "$mandir/whatis.db";
+ open(my $old, '<', $whatis) or
+ die "$0 $whatis to merge with";
+ my $subjects = scan_manpages($args);
+ my %remove = map {$_ => 1 } @$subjects;
+ $subjects = [];
+ while (<$old>) {
+ chomp;
+ push(@$subjects, $_) unless defined $remove{$_};
+ }
+ close($old);
+ OpenBSD::Makewhatis::Whatis::write($subjects, $mandir);
+}
+
+sub default_dirs
+{
+ local $_;
+ my $args=[];
+ open(my $conf, '<', '/etc/man.conf') or
+ die "$0: Can't open /etc/man.conf";
+ while (<$conf>) {
+ chomp;
+ push(@$args, $1) if /^_whatdb\s+(.*)\/whatis\.db\s*$/;
+ }
+ close $conf;
+ return $args;
+}
+
+sub makewhatis
+{
+ my ($args, $opts) = @_;
+ if (defined $opts->{'p'}) {
+ $picky = 1;
+ }
+ if (defined $opts->{'t'}) {
+ $testmode = 1;
+ my $subjects = scan_manpages($args);
+ print join("\n", @$subjects), "\n";
+ return;
+ }
+
+ if (defined $opts->{'d'}) {
+ merge($opts->{'d'}, $args);
+ return;
+ }
+ if (defined $opts->{'u'}) {
+ remove($opts->{'u'}, $args);
+ return;
+ }
+ if (@$args == 0) {
+ $args = default_dirs();
+ }
+
+ for my $mandir (@$args) {
+ if (-d $mandir) {
+ build_index($mandir);
+ } elsif (-e $mandir || $picky) {
+ print STDERR "$0: $mandir is not a directory\n";
+ }
+ }
+}
+
+1;
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis/Check.pm b/libexec/makewhatis/OpenBSD/Makewhatis/Check.pm
new file mode 100644
index 00000000000..66ee4ba12e9
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis/Check.pm
@@ -0,0 +1,84 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Check.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+package OpenBSD::Makewhatis::Check;
+
+sub found($$)
+{
+ my ($pattern, $filename) = @_;
+ my @candidates = glob $pattern;
+ if (@candidates > 0) {
+ # quick check of inode, dev number
+ my ($dev_cmp, $inode_cmp) = (stat $filename)[0,1];
+ for my $f (@candidates) {
+ my ($dev, $inode) = (stat $f)[0, 1];
+ if ($dev == $dev_cmp && $inode == $inode_cmp) {
+ return 1;
+ }
+ }
+ # slow check with File::Compare
+ require File::Compare;
+
+ for my $f (@candidates) {
+ if (File::Compare::compare($f, $filename) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+# verify_subject($subject, $filename):
+#
+# reparse the subject we're about to add, and check whether it makes
+# sense, e.g., is there a man page around.
+sub verify_subject
+{
+ local $_ = shift;
+ my $filename = shift;
+ if (m/\s*(.*?)\s*\((.*?)\)\s-\s/) {
+ my $man = $1;
+ my $section = $2;
+ my @mans = split(/\s*,\s*|\s+/, $man);
+ my $base = $filename;
+ if ($base =~ m|/|) {
+ $base =~ s,/[^/]*$,,;
+ } else {
+ $base = '.';
+ }
+ my @notfound = ();
+ for my $func (@mans) {
+ my $i = $func;
+ next if found("$base/$i.*", $filename);
+ # try harder
+ $i =~ s/\(\)//;
+ $i =~ s/\-//g;
+ $i =~ s,^etc/,,;
+ next if found("$base/$i.*", $filename);
+ # and harder...
+ $i =~ tr/[A-Z]/[a-z]/;
+ next if found("$base/$i.*", $filename);
+ push(@notfound, $func);
+ }
+ if (@notfound > 0) {
+ print STDERR "Couldn't find ", join(', ', @notfound),
+ " in $filename:\n$_\n"
+ }
+ }
+}
+
+1;
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis/Find.pm b/libexec/makewhatis/OpenBSD/Makewhatis/Find.pm
new file mode 100644
index 00000000000..2673b86e9c2
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis/Find.pm
@@ -0,0 +1,45 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Find.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+package OpenBSD::Makewhatis::Find;
+
+use File::Find;
+
+
+# $list = find_manpages($dir)
+#
+# find all manpages under $dir, trim some duplicates.
+#
+sub find_manpages
+{
+ my $dir = shift;
+ my ($list, %nodes);
+ $list=[];
+ find(
+ sub {
+ return unless /\.[\dln]\w*(?:\.Z|\.gz)?$/;
+ return unless -f $_;
+ my $unique = (stat _)[0]."/".(stat _)[1];
+ return if defined $nodes{$unique};
+ $nodes{$unique} = 1;
+ push(@$list, $File::Find::name);
+ }, $dir);
+ return $list;
+}
+
+1;
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis/Formated.pm b/libexec/makewhatis/OpenBSD/Makewhatis/Formated.pm
new file mode 100644
index 00000000000..33343e8c587
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis/Formated.pm
@@ -0,0 +1,139 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Formated.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+package OpenBSD::Makewhatis::Formated;
+
+# add_formated_subject($subjects, $_, $section):
+# add subject $_ to the list of current $subjects, in section $section.
+#
+sub add_formated_subject
+{
+ my ($subjects, $line, $section, $filename, $picky) = @_;
+ local $_ = $line;
+
+ # some twits underline the command name
+ while (s/_\cH//g || s/(.)\cH\1/$1/g)
+ {}
+ if (m/-/) {
+ s/([-+.\w\d,])\s+/$1 /g;
+ s/([a-z][A-z])-\s+/$1/g;
+ # some twits use: func -- description
+ if (m/^[^-+.\w\d]*(.*?) -(?:-?)\s+(.*)/) {
+ my ($func, $descr) = ($1, $2);
+ $func =~ s/,\s*$//;
+ # nroff will tend to cut function names at the weirdest places
+ if (length($func) > 40 && $func =~ m/,/ && $section =~ /^3/) {
+ $func =~ s/\b \b//g;
+ }
+ $_ = "$func ($section) - $descr";
+ push(@$subjects, $_);
+ return;
+ }
+ }
+
+ print STDERR "Weird subject line in $filename:\n$_\n" if $picky;
+
+ # try to find subject in line anyway
+ if (m/^\s*(.*\S)(?:\s{3,}|\(\)\s+)(.*?)\s*$/) {
+ my ($func, $descr) = ($1, $2);
+ $func =~ s/\s+/ /g;
+ $descr =~ s/\s+/ /g;
+ $_ = "$func ($section) - $descr";
+ push(@$subjects, $_);
+ return;
+ }
+
+ print STDERR "Weird subject line in $filename:\n$_\n" unless $picky;
+}
+
+# $lines = handle($file, $filename, $picky)
+#
+# handle a formatted manpage in $file
+#
+# may return several subjects, perl(3p) do !
+#
+sub handle
+{
+ my ($file, $filename, $picky) = @_;
+ local $_;
+ my ($section, $subject);
+ my @lines=();
+ while (<$file>) {
+ next if /^$/;
+ chomp;
+ # Remove boldface from wide characters
+ while (s/(..)\cH\cH\1/$1/g)
+ {}
+ # Remove boldface and underlining
+ while (s/_\cH//g || s/(.)\cH\1/$1/g)
+ {}
+ if (m/\w[-+.\w\d]*\(([-+.\w\d\/]+)\)/) {
+ $section = $1;
+ # Find architecture
+ if (m/Manual\s+\((.*?)\)/) {
+ $section = "$section/$1";
+ }
+ }
+ # Not all man pages are in english
+ # weird hex is `Namae' in japanese
+ if (m/^(?:NAME|NAMES|NAMN|Name|\xbe|\xcc\xbe\xbe\xce|\xcc\xbe\xc1\xb0)\s*$/) {
+ unless (defined $section) {
+ # try to retrieve section from filename
+ if ($filename =~ m/(?:cat|man)([\dln])\//) {
+ $section = $1;
+ print STDERR "Can't find section in $filename, deducting $section from context\n" if $picky;
+ } else {
+ $section='??';
+ print STDERR "Can't find section in $filename\n";
+ }
+ }
+ while (<$file>) {
+ chomp;
+ # perl aggregates several subjects in one manpage
+ if (m/^$/) {
+ add_formated_subject(\@lines, $subject, $section, $filename, $picky)
+ if defined $subject;
+ $subject = undef;
+ } elsif (m/^\S/ || m/^\s+\*{3,}\s*$/) {
+ add_formated_subject(\@lines, $subject, $section, $filename, $picky)
+ if defined $subject;
+ last;
+ } else {
+ # deal with troff hyphenations
+ if (defined $subject and $subject =~ m/\xad\s*$/) {
+ $subject =~ s/(?:\xad\cH)*\xad\s*$//;
+ s/^\s*//;
+ }
+ # more troff hyphenation
+ if (defined $subject and $subject =~ m/\S(?:\-\cH)*\-$/) {
+ $subject =~ s/(?:\-\cH)*\-$//;
+ s/^\s*//;
+ }
+ s/^\s+/ /;
+ $subject.=$_;
+ }
+ }
+ last;
+ }
+ }
+
+ print STDERR "Can't parse $filename (not a manpage ?)\n" if @lines == 0;
+ return \@lines;
+}
+
+1;
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis/Unformated.pm b/libexec/makewhatis/OpenBSD/Makewhatis/Unformated.pm
new file mode 100644
index 00000000000..6cc133dd645
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis/Unformated.pm
@@ -0,0 +1,231 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Unformated.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+package OpenBSD::Makewhatis::Unformated;
+
+# add_unformated_subject($lines, $toadd, $section, $filename, $toexpand):
+#
+# build subject from list of $toadd lines, and add it to the list
+# of current subjects as section $section
+#
+sub add_unformated_subject
+{
+ my ($subjects, $toadd, $section, $filename, $toexpand, $picky) = @_;
+
+ my $exp = sub {
+ if (defined $toexpand->{$_[0]}) {
+ return $toexpand->{$_[0]};
+ } else {
+ print STDERR "$filename: can't expand $_[0]\n";
+ return "";
+ }
+ };
+
+ local $_ = join(' ', @$toadd);
+ # do interpolations
+ s/\\\*\((..)/&$exp($1)/ge;
+ s/\\\*\[(.*?)\]/&$exp($1)/ge;
+
+ # horizontal space adjustments
+ while (s/\\s[-+]?\d+//g)
+ {}
+ # unbreakable spaces
+ s/\\\s+/ /g;
+ # unbreakable em dashes
+ s/\\\|\\\(em\\\|/-/g;
+ # em dashes
+ s/\\\(em\s+/- /g;
+ # em dashes in the middle of lines
+ s/\\\(em/-/g;
+ s/\\\*[LO]//g;
+ s/\\\(tm/(tm)/g;
+ # font changes
+ s/\\f[BIRP]//g;
+ s/\\f\(..//g;
+ # fine space adjustments
+ while (s/\\[vh]\'.*?\'//g)
+ {}
+ unless (s/\s+\\-\s+/ ($section) - / || s/\s*\\\-/ ($section) -/ ||
+ s/\s-\s/ ($section) - /) {
+ print STDERR "Weird subject line in $filename:\n$_\n" if $picky;
+ # Try guessing where the separation falls...
+ s/\s+\:\s+/ ($section) - / || s/\S+\s+/$& ($section) - / || s/\s*$/ ($section) - (empty subject)/;
+ }
+ # other dashes
+ s/\\-/-/g;
+ # escaped characters
+ s/\\\&(.)/$1/g;
+ s/\\\|/|/g;
+ # gremlins...
+ s/\\c//g;
+ # sequence of spaces
+ s/\s+$//;
+ s/^\s+//;
+ s/\s+/ /g;
+ # some damage control
+ if (m/^\Q($section) - \E/) {
+ print STDERR "Rejecting non-subject line from $filename:\n$_\n"
+ if $picky;
+ return;
+ }
+ push(@$subjects, $_);
+}
+
+# $lines = handle($file, $filename, $picky)
+#
+# handle an unformated manpage in $file
+#
+# may return several subjects, perl(3p) do !
+#
+sub handle
+{
+ my ($f, $filename, $picky) = @_;
+ my @lines = ();
+ my %toexpand = ();
+ my $so_found = 0;
+ local $_;
+ # retrieve basename of file
+ my ($name, $section) = $filename =~ m|(?:.*/)?(.*)\.([\w\d]+)|;
+ # scan until macro
+ while (<$f>) {
+ next unless m/^\./;
+ if (m/^\.\s*de/) {
+ while (<$f>) {
+ last if m/^\.\s*\./;
+ }
+ next;
+ }
+ if (m/^\.\s*ds\s+(\S+)\s+/) {
+ chomp($toexpand{$1} = $');
+ next;
+ }
+ # Some cross-refs just link to another manpage
+ $so_found = 1 if m/^\.\s*so/;
+ if (m/^\.\s*TH/ || m/^\.\s*th/) {
+ # in pricky mode, we should try to match these
+ # ($name2, $section2) = m/^\.(?:TH|th)\s+(\S+)\s+(\S+)/;
+ # scan until first section
+ while (<$f>) {
+ if (m/^\.\s*de/) {
+ while (<$f>) {
+ last if m/^\.\s*\./;
+ }
+ next;
+ }
+ if (m/^\.\s*ds\s+(\S+)\s+/) {
+ chomp($toexpand{$1} = $');
+ next;
+ }
+ next unless m/^\./;
+ if (m/^\.\s*SH/ || m/^\.\s*sh/) {
+ my @subject = ();
+ while (<$f>) {
+ last if m/^\.\s*(?:SH|sh|SS|ss|nf|LI)/;
+ # several subjects in one manpage
+ if (m/^\.\s*(?:PP|Pp|br|PD|LP|sp)/) {
+ add_unformated_subject(\@lines, \@subject,
+ $section, $filename, \%toexpand, $picky)
+ if @subject != 0;
+ @subject = ();
+ next;
+ }
+ next if m/^\'/ || m/^\.\s*tr\s+/ || m/^\.\s*\\\"/ ||
+ m/^\.\s*sv/ || m/^\.\s*Vb\s+/ || m/\.\s*HP\s+/;
+ if (m/^\.\s*de/) {
+ while (<$f>) {
+ last if m/^\.\s*\./;
+ }
+ next;
+ }
+ if (m/^\.\s*ds\s+(\S+)\s+/) {
+ chomp($toexpand{$1} = $');
+ next;
+ }
+ # Motif index entries, don't do anything for now.
+ next if m/^\.\s*iX/;
+ # Some other index (cook)
+ next if m/^\.\s*XX/;
+ chomp;
+ s/\.\s*(?:B|I|IR|SM|BR)\s+//;
+ if (m/^\.\s*(\S\S)/) {
+ print STDERR "$filename: not grokking $_\n"
+ if $picky;
+ next;
+ }
+ push(@subject, $_) unless m/^\s*$/;
+ }
+ add_unformated_subject(\@lines, \@subject, $section,
+ $filename, \%toexpand, $picky) if @subject != 0;
+ return \@lines;
+ }
+ }
+ print STDERR "Couldn't find subject in old manpage $filename\n";
+ } elsif (m/^\.\s*Dt/) {
+ $section .= "/$1" if (m/^\.\s*Dt\s+\S+\s+\d\S*\s+(\S+)/);
+ while (<$f>) {
+ next unless m/^\./;
+ if (m/^\.\s*Sh/) {
+ # subject/keep is the only way to deal with Nm/Nd pairs
+ my @subject = ();
+ my @keep = ();
+ my $nd_seen = 0;
+ while (<$f>) {
+ next if m/^\.\\\"/;
+ last if m/^\.\s*Sh/;
+ s/\s,/,/g;
+ if (s/^\.\s*(\S\S)\s+//) {
+ my $macro = $1;
+ next if $macro eq "\\\"";
+ s/\"(.*?)\"/$1/g;
+ s/\\-/-/g;
+ $macro eq 'Xr' and s/^(\S+)\s+(\d\S*)/$1 ($2)/;
+ $macro eq 'Ox' and s/^/OpenBSD /;
+ $macro eq 'Nx' and s/^/NetBSD /;
+ if ($macro eq 'Nd') {
+ if (@keep != 0) {
+ add_unformated_subject(\@lines, \@keep,
+ $section, $filename, \%toexpand, $picky);
+ @keep = ();
+ }
+ push(@subject, "\\-");
+ $nd_seen = 1;
+ }
+ if ($nd_seen && $macro eq 'Nm') {
+ @keep = @subject;
+ @subject = ();
+ $nd_seen = 0;
+ }
+ }
+ push(@subject, $_) unless m/^\s*$/;
+ }
+ unshift(@subject, @keep) if @keep != 0;
+ add_unformated_subject(\@lines, \@subject, $section,
+ $filename, \%toexpand, $picky)
+ if @subject != 0;
+ return \@lines;
+ }
+ }
+ }
+ }
+ if ($so_found == 0) {
+ print STDERR "Unknown manpage type $filename\n";
+ }
+ return \@lines;
+}
+
+1;
diff --git a/libexec/makewhatis/OpenBSD/Makewhatis/Whatis.pm b/libexec/makewhatis/OpenBSD/Makewhatis/Whatis.pm
new file mode 100644
index 00000000000..5b941dd21de
--- /dev/null
+++ b/libexec/makewhatis/OpenBSD/Makewhatis/Whatis.pm
@@ -0,0 +1,64 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: Whatis.pm,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use strict;
+use warnings;
+package OpenBSD::Makewhatis::Whatis;
+
+use File::Temp qw/tempfile/;
+use File::Compare;
+
+# write($list, $dir):
+#
+# write $list to file named $file, removing duplicate entries.
+# Change $file mode/owners to expected values
+# Write to temporary file first, and do the copy only if changes happened.
+#
+sub write
+{
+ my ($list, $dir) = @_;
+ my $f = "$dir/whatis.db";
+ local $_;
+
+ my ($out, $tempname);
+ ($out, $tempname) = tempfile('/tmp/makewhatis.XXXXXXXXXX') or die "$0: Can't open temporary file";
+
+ my @sorted = sort @$list;
+ my $last;
+
+ while ($_ = shift @sorted) {
+ print $out $_, "\n" unless defined $last and $_ eq $last;
+ $last = $_;
+ }
+ close $out;
+ if (compare($tempname, $f) == 0) {
+ unlink($tempname);
+ } else {
+ require File::Copy;
+
+ unlink($f);
+ if (File::Copy::move($tempname, $f)) {
+ chmod 0444, $f;
+ chown 0, (getgrnam 'bin')[2], $f;
+ } else {
+ print STDERR "$0: Can't create $f ($!)\n";
+ unlink($tempname);
+ exit 1;
+ }
+ }
+}
+
+1;
diff --git a/libexec/makewhatis/makewhatis b/libexec/makewhatis/makewhatis
new file mode 100644
index 00000000000..dfea4c81777
--- /dev/null
+++ b/libexec/makewhatis/makewhatis
@@ -0,0 +1,37 @@
+#!/usr/bin/perl -w
+# ex:ts=8 sw=4:
+
+# $OpenBSD: makewhatis,v 1.1 2004/08/06 12:05:08 espie Exp $
+# Copyright (c) 2000-2004 Marc Espie <espie@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+require 5.006_000;
+
+use strict;
+use warnings;
+
+use Getopt::Std;
+use OpenBSD::Makewhatis;
+
+
+# main code
+
+my %opts;
+getopts('tpd:u:', \%opts);
+
+OpenBSD::Makewhatis::makewhatis(\@ARGV, \%opts);
+
+#while (my ($key, $value) = each %INC) {
+# print "$key => $value\n";
+#}
diff --git a/libexec/makewhatis/makewhatis.pl b/libexec/makewhatis/makewhatis.pl
deleted file mode 100644
index 009ef298912..00000000000
--- a/libexec/makewhatis/makewhatis.pl
+++ /dev/null
@@ -1,632 +0,0 @@
-#!/usr/bin/perl -w
-# ex:ts=8 sw=4:
-
-# $OpenBSD: makewhatis.pl,v 1.29 2004/03/01 20:13:24 espie Exp $
-#
-# Copyright (c) 2000 Marc Espie.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
-# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-require 5.006_000;
-
-use strict;
-use File::Find;
-use File::Temp qw/tempfile/;
-use File::Compare;
-
-use Getopt::Std;
-
-my ($picky, $testmode);
-
-# write_uniques($list, $file):
-#
-# write $list to file named $file, removing duplicate entries.
-# Change $file mode/owners to expected values
-# Write to temporary file first, and do the copy only if changes happened.
-#
-sub write_uniques
-{
- my $list = shift;
- my $f = shift;
- local $_;
-
- my ($out, $tempname);
- ($out, $tempname) = tempfile('/tmp/makewhatis.XXXXXXXXXX') or die "$0: Can't open temporary file";
-
- my @sorted = sort @$list;
- my $last;
-
- while ($_ = shift @sorted) {
- print $out $_, "\n" unless defined $last and $_ eq $last;
- $last = $_;
- }
- close $out;
- if (compare($tempname, $f) == 0) {
- unlink($tempname);
- } else {
- use File::Copy;
-
- unlink($f);
- if (move($tempname, $f)) {
- chmod 0444, $f;
- chown 0, (getgrnam 'bin')[2], $f;
- } else {
- print STDERR "$0: Can't create $f ($!)\n";
- unlink($tempname);
- exit 1;
- }
- }
-}
-
-sub found($$)
-{
- my ($pattern, $filename) = @_;
- my @candidates = glob $pattern;
- if (@candidates > 0) {
- # quick check of inode, dev number
- my ($dev_cmp, $inode_cmp) = (stat $filename)[0,1];
- for my $f (@candidates) {
- my ($dev, $inode) = (stat $f)[0, 1];
- if ($dev == $dev_cmp && $inode == $inode_cmp) {
- return 1;
- }
- }
- # slow check with File::Compare
- for my $f (@candidates) {
- if (compare($f, $filename) == 0) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-# verify_subject($subject, $filename):
-#
-# reparse the subject we're about to add, and check whether it makes
-# sense, e.g., is there a man page around.
-sub verify_subject
-{
- local $_ = shift;
- my $filename = shift;
- if (m/\s*(.*?)\s*\((.*?)\)\s-\s/) {
- my $man = $1;
- my $section = $2;
- my @mans = split(/\s*,\s*|\s+/, $man);
- my $base = $filename;
- if ($base =~ m|/|) {
- $base =~ s,/[^/]*$,,;
- } else {
- $base = '.';
- }
- my @notfound = ();
- for my $func (@mans) {
- my $i = $func;
- next if found("$base/$i.*", $filename);
- # try harder
- $i =~ s/\(\)//;
- $i =~ s/\-//g;
- $i =~ s,^etc/,,;
- next if found("$base/$i.*", $filename);
- # and harder...
- $i =~ tr/[A-Z]/[a-z]/;
- next if found("$base/$i.*", $filename);
- push(@notfound, $func);
- }
- if (@notfound > 0) {
- print STDERR "Couldn't find ", join(', ', @notfound),
- " in $filename:\n$_\n"
- }
- }
-}
-
-
-# add_unformated_subject($lines, $toadd, $section, $filename, $toexpand):
-#
-# build subject from list of $toadd lines, and add it to the list
-# of current subjects as section $section
-#
-sub add_unformated_subject
-{
- my $subjects = shift;
- my $toadd = shift;
- my $section = shift;
- my $filename = shift;
- my $toexpand = shift;
-
- my $exp = sub {
- if (defined $toexpand->{$_[0]}) {
- return $toexpand->{$_[0]};
- } else {
- print STDERR "$filename: can't expand $_[0]\n";
- return "";
- }
- };
-
- local $_ = join(' ', @$toadd);
- # do interpolations
- s/\\\*\((..)/&$exp($1)/ge;
- s/\\\*\[(.*?)\]/&$exp($1)/ge;
-
- # horizontal space adjustments
- while (s/\\s[-+]?\d+//g)
- {}
- # unbreakable spaces
- s/\\\s+/ /g;
- # unbreakable em dashes
- s/\\\|\\\(em\\\|/-/g;
- # em dashes
- s/\\\(em\s+/- /g;
- # em dashes in the middle of lines
- s/\\\(em/-/g;
- s/\\\*[LO]//g;
- s/\\\(tm/(tm)/g;
- # font changes
- s/\\f[BIRP]//g;
- s/\\f\(..//g;
- # fine space adjustments
- while (s/\\[vh]\'.*?\'//g)
- {}
- unless (s/\s+\\-\s+/ ($section) - / || s/\s*\\\-/ ($section) -/ ||
- s/\s-\s/ ($section) - /) {
- print STDERR "Weird subject line in $filename:\n$_\n" if $picky;
- # Try guessing where the separation falls...
- s/\s+\:\s+/ ($section) - / || s/\S+\s+/$& ($section) - / || s/\s*$/ ($section) - (empty subject)/;
- }
- # other dashes
- s/\\-/-/g;
- # escaped characters
- s/\\\&(.)/$1/g;
- s/\\\|/|/g;
- # gremlins...
- s/\\c//g;
- # sequence of spaces
- s/\s+$//;
- s/^\s+//;
- s/\s+/ /g;
- # some damage control
- if (m/^\Q($section) - \E/) {
- print STDERR "Rejecting non-subject line from $filename:\n$_\n"
- if $picky;
- return;
- }
- push(@$subjects, $_);
- verify_subject($_, $filename) if $picky;
-}
-
-# $lines = handle_unformated($file)
-#
-# handle an unformated manpage in $file
-#
-# may return several subjects, perl(3p) do !
-#
-sub handle_unformated
-{
- my $f = shift;
- my $filename = shift;
- my @lines = ();
- my %toexpand = ();
- my $so_found = 0;
- local $_;
- # retrieve basename of file
- my ($name, $section) = $filename =~ m|(?:.*/)?(.*)\.([\w\d]+)|;
- # scan until macro
- while (<$f>) {
- next unless m/^\./;
- if (m/^\.\s*de/) {
- while (<$f>) {
- last if m/^\.\s*\./;
- }
- next;
- }
- if (m/^\.\s*ds\s+(\S+)\s+/) {
- chomp($toexpand{$1} = $');
- next;
- }
- # Some cross-refs just link to another manpage
- $so_found = 1 if m/^\.\s*so/;
- if (m/^\.\s*TH/ || m/^\.\s*th/) {
- # in pricky mode, we should try to match these
- # ($name2, $section2) = m/^\.(?:TH|th)\s+(\S+)\s+(\S+)/;
- # scan until first section
- while (<$f>) {
- if (m/^\.\s*de/) {
- while (<$f>) {
- last if m/^\.\s*\./;
- }
- next;
- }
- if (m/^\.\s*ds\s+(\S+)\s+/) {
- chomp($toexpand{$1} = $');
- next;
- }
- next unless m/^\./;
- if (m/^\.\s*SH/ || m/^\.\s*sh/) {
- my @subject = ();
- while (<$f>) {
- last if m/^\.\s*(?:SH|sh|SS|ss|nf|LI)/;
- # several subjects in one manpage
- if (m/^\.\s*(?:PP|Pp|br|PD|LP|sp)/) {
- add_unformated_subject(\@lines, \@subject,
- $section, $filename, \%toexpand)
- if @subject != 0;
- @subject = ();
- next;
- }
- next if m/^\'/ || m/^\.\s*tr\s+/ || m/^\.\s*\\\"/ ||
- m/^\.\s*sv/ || m/^\.\s*Vb\s+/ || m/\.\s*HP\s+/;
- if (m/^\.\s*de/) {
- while (<$f>) {
- last if m/^\.\s*\./;
- }
- next;
- }
- if (m/^\.\s*ds\s+(\S+)\s+/) {
- chomp($toexpand{$1} = $');
- next;
- }
- # Motif index entries, don't do anything for now.
- next if m/^\.\s*iX/;
- # Some other index (cook)
- next if m/^\.\s*XX/;
- chomp;
- s/\.\s*(?:B|I|IR|SM|BR)\s+//;
- if (m/^\.\s*(\S\S)/) {
- print STDERR "$filename: not grokking $_\n"
- if $picky;
- next;
- }
- push(@subject, $_) unless m/^\s*$/;
- }
- add_unformated_subject(\@lines, \@subject, $section,
- $filename, \%toexpand) if @subject != 0;
- return \@lines;
- }
- }
- print STDERR "Couldn't find subject in old manpage $filename\n";
- } elsif (m/^\.\s*Dt/) {
- $section .= "/$1" if (m/^\.\s*Dt\s+\S+\s+\d\S*\s+(\S+)/);
- while (<$f>) {
- next unless m/^\./;
- if (m/^\.\s*Sh/) {
- # subject/keep is the only way to deal with Nm/Nd pairs
- my @subject = ();
- my @keep = ();
- my $nd_seen = 0;
- while (<$f>) {
- next if m/^\.\\\"/;
- last if m/^\.\s*Sh/;
- s/\s,/,/g;
- if (s/^\.\s*(\S\S)\s+//) {
- my $macro = $1;
- next if $macro eq "\\\"";
- s/\"(.*?)\"/$1/g;
- s/\\-/-/g;
- $macro eq 'Xr' and s/^(\S+)\s+(\d\S*)/$1 ($2)/;
- $macro eq 'Ox' and s/^/OpenBSD /;
- $macro eq 'Nx' and s/^/NetBSD /;
- if ($macro eq 'Nd') {
- if (@keep != 0) {
- add_unformated_subject(\@lines, \@keep,
- $section, $filename, \%toexpand);
- @keep = ();
- }
- push(@subject, "\\-");
- $nd_seen = 1;
- }
- if ($nd_seen && $macro eq 'Nm') {
- @keep = @subject;
- @subject = ();
- $nd_seen = 0;
- }
- }
- push(@subject, $_) unless m/^\s*$/;
- }
- unshift(@subject, @keep) if @keep != 0;
- add_unformated_subject(\@lines, \@subject, $section,
- $filename, \%toexpand)
- if @subject != 0;
- return \@lines;
- }
- }
- }
- }
- if ($so_found == 0) {
- print STDERR "Unknown manpage type $filename\n";
- }
- return \@lines;
-}
-
-# add_formated_subject($subjects, $_, $section):
-# add subject $_ to the list of current $subjects, in section $section.
-#
-sub add_formated_subject
-{
- my $subjects = shift;
- local $_ = shift;
- my $section = shift;
- my $filename = shift;
-
- # some twits underline the command name
- while (s/_\cH//g || s/(.)\cH\1/$1/g)
- {}
- if (m/-/) {
- s/([-+.\w\d,])\s+/$1 /g;
- s/([a-z][A-z])-\s+/$1/g;
- # some twits use: func -- description
- if (m/^[^-+.\w\d]*(.*?) -(?:-?)\s+(.*)/) {
- my ($func, $descr) = ($1, $2);
- $func =~ s/,\s*$//;
- # nroff will tend to cut function names at the weirdest places
- if (length($func) > 40 && $func =~ m/,/ && $section =~ /^3/) {
- $func =~ s/\b \b//g;
- }
- $_ = "$func ($section) - $descr";
- verify_subject($_, $filename) if $picky;
- push(@$subjects, $_);
- return;
- }
- }
-
- print STDERR "Weird subject line in $filename:\n$_\n" if $picky;
-
- # try to find subject in line anyway
- if (m/^\s*(.*\S)(?:\s{3,}|\(\)\s+)(.*?)\s*$/) {
- my ($func, $descr) = ($1, $2);
- $func =~ s/\s+/ /g;
- $descr =~ s/\s+/ /g;
- $_ = "$func ($section) - $descr";
- verify_subject($_, $filename) if $picky;
- push(@$subjects, $_);
- return;
- }
-
- print STDERR "Weird subject line in $filename:\n$_\n" unless $picky;
-}
-
-# $lines = handle_formated($file)
-#
-# handle a formatted manpage in $file
-#
-# may return several subjects, perl(3p) do !
-#
-sub handle_formated
-{
- my $file = shift;
- my $filename = shift;
- local $_;
- my ($section, $subject);
- my @lines=();
- while (<$file>) {
- next if /^$/;
- chomp;
- # Remove boldface from wide characters
- while (s/(..)\cH\cH\1/$1/g)
- {}
- # Remove boldface and underlining
- while (s/_\cH//g || s/(.)\cH\1/$1/g)
- {}
- if (m/\w[-+.\w\d]*\(([-+.\w\d\/]+)\)/) {
- $section = $1;
- # Find architecture
- if (m/Manual\s+\((.*?)\)/) {
- $section = "$section/$1";
- }
- }
- # Not all man pages are in english
- # weird hex is `Namae' in japanese
- if (m/^(?:NAME|NAMES|NAMN|Name|\xbe|\xcc\xbe\xbe\xce|\xcc\xbe\xc1\xb0)\s*$/) {
- unless (defined $section) {
- # try to retrieve section from filename
- if ($filename =~ m/(?:cat|man)([\dln])\//) {
- $section = $1;
- print STDERR "Can't find section in $filename, deducting $section from context\n" if $picky;
- } else {
- $section='??';
- print STDERR "Can't find section in $filename\n";
- }
- }
- while (<$file>) {
- chomp;
- # perl aggregates several subjects in one manpage
- if (m/^$/) {
- add_formated_subject(\@lines, $subject, $section, $filename)
- if defined $subject;
- $subject = undef;
- } elsif (m/^\S/ || m/^\s+\*{3,}\s*$/) {
- add_formated_subject(\@lines, $subject, $section, $filename)
- if defined $subject;
- last;
- } else {
- # deal with troff hyphenations
- if (defined $subject and $subject =~ m/\xad\s*$/) {
- $subject =~ s/(?:\xad\cH)*\xad\s*$//;
- s/^\s*//;
- }
- # more troff hyphenation
- if (defined $subject and $subject =~ m/\S(?:\-\cH)*\-$/) {
- $subject =~ s/(?:\-\cH)*\-$//;
- s/^\s*//;
- }
- s/^\s+/ /;
- $subject.=$_;
- }
- }
- last;
- }
- }
-
- print STDERR "Can't parse $filename (not a manpage ?)\n" if @lines == 0;
- return \@lines;
-}
-
-# $list = find_manpages($dir)
-#
-# find all manpages under $dir, trim some duplicates.
-#
-sub find_manpages
-{
- my $dir = shift;
- my ($list, %nodes);
- $list=[];
- find(
- sub {
- return unless /\.[\dln]\w*(?:\.Z|\.gz)?$/;
- return unless -f $_;
- my $unique = (stat _)[0]."/".(stat _)[1];
- return if defined $nodes{$unique};
- $nodes{$unique} = 1;
- push(@$list, $File::Find::name);
- }, $dir);
- return $list;
-}
-
-# $subjects = scan_manpages($list)
-#
-# scan a set of manpages, return list of subjects
-#
-sub scan_manpages
-{
- my $list = shift;
- local $_;
- my ($done);
- $done=[];
-
- for (@$list) {
- my ($file, $subjects);
- if (m/\.(?:Z|gz)$/) {
- unless (open $file, '-|', "gzip -fdc $_") {
- warn "$0: Can't decompress $_\n";
- next;
- }
- $_ = $`;
- } else {
- unless (open $file, '<', $_) {
- warn "$0: Can't read $_\n";
- next;
- }
- }
- if (m/\.[1-9ln][^.]*$/) {
- $subjects = handle_unformated($file, $_);
- } elsif (m/\.0$/) {
- $subjects = handle_formated($file, $_);
- # in test mode, we try harder
- } elsif ($testmode) {
- $subjects = handle_unformated($file, $_);
- if (@$subjects == 0) {
- $subjects = handle_formated($file, $_);
- }
- } else {
- print STDERR "Can't find type of $_";
- next;
- }
- push @$done, @$subjects;
- }
- return $done;
-}
-
-# build_index($dir)
-#
-# build index for $dir
-#
-sub build_index
-{
- my $dir = shift;
- my $list = find_manpages($dir);
- my $subjects = scan_manpages($list);
- write_uniques($subjects, "$dir/whatis.db");
-}
-
-# main code
-
-my %opts;
-getopts('tpd:u:', \%opts);
-
-if (defined $opts{'p'}) {
- $picky = 1;
-}
-if (defined $opts{'t'}) {
- $testmode = 1;
- my $subjects = scan_manpages(\@ARGV);
- print join("\n", @$subjects), "\n";
- exit 0;
-}
-
-if (defined $opts{'d'}) {
- my $mandir = $opts{'d'};
- unless (-d $mandir) {
- die "$0: $mandir: not a directory"
- }
- chdir $mandir;
-
- my $whatis = "$mandir/whatis.db";
- open(my $old, '<', $whatis) or
- die "$0 $whatis to merge with";
- my $subjects = scan_manpages(\@ARGV);
- while (<$old>) {
- chomp;
- push(@$subjects, $_);
- }
- close($old);
- write_uniques($subjects, $whatis);
- exit 0;
-}
-if (defined $opts{'u'}) {
- my $mandir = $opts{'u'};
- unless (-d $mandir) {
- die "$0: $mandir: not a directory"
- }
- chdir $mandir;
-
- my $whatis = "$mandir/whatis.db";
- open(my $old, '<', $whatis) or
- die "$0 $whatis to merge with";
- my $subjects = scan_manpages(\@ARGV);
- my %remove = map {$_ => 1 } @$subjects;
- $subjects = [];
- while (<$old>) {
- chomp;
- push(@$subjects, $_) unless defined $remove{$_};
- }
- close($old);
- write_uniques($subjects, $whatis);
- exit 0;
-}
-if ($#ARGV == -1) {
- local $_;
- @ARGV=();
- open(my $conf, '<', '/etc/man.conf') or
- die "$0: Can't open /etc/man.conf";
- while (<$conf>) {
- chomp;
- push(@ARGV, $1) if /^_whatdb\s+(.*)\/whatis\.db\s*$/;
- }
- close $conf;
-}
-
-for my $mandir (@ARGV) {
- if (-d $mandir) {
- build_index($mandir);
- } elsif (-e $mandir || $picky) {
- print STDERR "$0: $mandir is not a directory\n";
- }
-}