groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff-commit] groff/contrib/groffer/perl README_PERL func.pl ...


From: Werner LEMBERG
Subject: [Groff-commit] groff/contrib/groffer/perl README_PERL func.pl ...
Date: Sun, 11 Aug 2013 08:28:52 +0000

CVSROOT:        /sources/groff
Module name:    groff
Changes by:     Werner LEMBERG <wl>     13/08/11 08:28:52

Added files:
        contrib/groffer/perl: README_PERL func.pl groffer.man groffer.pl 
                              man.pl perl_test.pl roff2.pl split_env.sh 

Log message:
        Revert accidental removal of previous commit.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/README_PERL?cvsroot=groff&rev=1.6
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/func.pl?cvsroot=groff&rev=1.10
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/groffer.man?cvsroot=groff&rev=1.21
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/groffer.pl?cvsroot=groff&rev=1.17
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/man.pl?cvsroot=groff&rev=1.9
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/perl_test.pl?cvsroot=groff&rev=1.6
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/roff2.pl?cvsroot=groff&rev=1.8
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/groffer/perl/split_env.sh?cvsroot=groff&rev=1.6

Patches:
Index: README_PERL
===================================================================
RCS file: README_PERL
diff -N README_PERL
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ README_PERL 11 Aug 2013 08:28:51 -0000      1.6
@@ -0,0 +1,263 @@
+README_PERL
+
+Special description for the Perl version of `groffer'
+
+The files related to the Perl version are
+
+perl/groffer.pl          perl main source file for groffer
+perl/func.pl     selection of functions needed for groffer.pl
+perl/man.pl      selection of man functions needed for groffer.pl
+perl/split_env.sh shell script called from groffer.pl to split a variable
+perl/groffer.man  manual file rewritten for the perl version of groffer
+perl/README_PERL  this file
+perl_test.pl     test whether perl has a suitable version
+version.sh       information on version number and last update
+
+
+Compatibility
+
+This is the Perl version of groffer.  It was written under Perl v5.8.8
+and needs an installed Perl version of at least version 5.6.1.
+
+It was written in Linux, but it seems to be independent of the
+operating system.  At least no directory slashes are used.
+
+For testing, `groffer.pl' may be used directly without a Makefile.  By
+`make' this file will be transformed into the file `groffer' that will
+be installed.
+
+The following options were removed compared to the shell version of
+groffer:
+
+--shell --debug-func --debug-not_func --debug-lm --debug-shell
+--debug-stacks --debug-user
+
+They can be used, but they are just ignored.
+
+Otherwise, the Perl version has the same functionality as the shell
+version.
+
+
+Temporary files
+
+The Perl version keeps more files for debug mode than the shell
+version.  The `file' and `so' temporaries are numbered and the files
+with .so request are copied.  All .so requests are handled; this is an
+extension to `man' that deals only with the first .so request.
+
+
+Comparison of variable names in both groffer versions
+
+shell                          perl
+=======================================================================
+$GROFFER_OPT                   $Env{GROFFER}
+$PATH                          @Path
+$_ADDOPTS_GROFF                        @Addopts_Groff
+$_ALL_PARAMS                   @ARGV
+$_APROPOS_PROG                 $Apropos_Prog
+$_APROPOS_SECTIONS             $Opt{APROPOS_SECTIONS}
+$_AT                           $at
+$_AT_BINDIR_AT                 $at_at{BINDIR}
+$_AT_G_AT                      $at_at{G}
+$_AT_LIBDIR_AT                 $at_at{LIBDIR}
+$_BAD                          -
+$_BEFORE_MAKE                  $before_make
+$_CONF_FILES                   @Conf_Files
+$_CONF_FILE_ETC                        @Conf_Files
+$_CONF_FILE_HOME               @Conf_Files
+$_DEBUG_FUNC_CHECK             -
+$_DEBUG_KEEP_FILES             @Debug{KEEP}
+$_DEBUG_LM                     -
+$_DEBUG_PRINT_FILENAMES                @Debug{FILENAMES}
+$_DEBUG_PRINT_PARAMS           @Debug{PARAMS}
+$_DEBUG_PRINT_SHELL            -
+$_DEBUG_PRINT_TMPDIR           @Debug{TMPDIR}
+$_DEBUG_STACKS                 -
+$_DEBUG_USER_WITH_STACK                -
+$_DEFAULT_MODES                        $Default_Modes
+$_DEFAULT_RESOLUTION           $Default_Resolution
+$_DEFAULT_TTY_DEVICE           $Default_tty_Device
+$_DISPLAY_ARGS                 $Display{ARGS}
+$_DISPLAY_MODE                 $Display{MODE}
+$_DISPLAY_PROG                 $Display{PROG}
+$_ERROR                                -
+$_FILEARGS                     @Filespecs
+$_FILESPEC_ARG                 $Filespec_Arg
+$_FILESPEC_IS_MAN              $Filespec_Is_Man
+$_FUNC_STACK                   -
+$_GOOD                         -
+$_GROFFER2_SH                  -
+$_GROFFER_LIBDIR               $groffer_libdir
+$_GROFFER_SH                   _
+$_GROFF_VERSION                        $Groff_Version
+$_GROFF_VERSION_PRESET         $groff_version_preset
+$_HAS_BZIP                     $Has_bzip
+$_HAS_COMPRESSION              $Has_Compression
+$_LAST_UPDATE                  $last_update
+$_MACRO_PACKAGES               $Macro_Packages
+$_MACRO_PKG                    $Macro_Pkg
+$_MANOPT_ALL                   -
+$_MANOPT_EXTENSION             -
+$_MANOPT_LANG                  -
+$_MANOPT_PAGER                 -
+$_MANOPT_PATH                  -
+$_MANOPT_SEC                   -
+$_MANOPT_SYS                   -
+$_MAN_ALL                      $Man{ALL}
+$_MAN_AUTO_SEC_CHARS           $Man{AUTO_SEC_CHARS}
+$_MAN_AUTO_SEC_LIST            @{$Man{AUTO_SEC}}
+$_MAN_ENABLE                   $Man{ENABLE}
+$_MAN_EXT                      $Man{EXT}
+$_MAN_FORCE                    $Man{FORCE}
+$_MAN_IS_SETUP                 $Man{IS_SETUP}
+$_MAN_LANG                     $Man{LANG}
+$_MAN_LANG2                    $Man{LANG2}
+$_MAN_PATH                     @{$Man{PATH}}
+$_MAN_SEC                      @{$Man{SEC}}
+$_MAN_SEC_CHARS                        $Man{SEC_CHARS}
+$_MAN_SEC_LIST                 -
+$_MAN_SYS                      @{$Man{SYS}}
+$_NO                           -
+$_NO_FILESPECS                 $No_Filespecs
+$_NULL_DEV                     $Dev_Null
+$_OK                           -
+$_OPTS_CMDLINE_LONG_ARG                %Opts_Cmdline_Long with value 1
+$_OPTS_CMDLINE_LONG_NA         %Opts_Cmdline_Long with value 0
+$_OPTS_CMDLINE_SHORT_ARG       %Opts_Cmdline_Short with value 1
+$_OPTS_CMDLINE_SHORT_NA                %Opts_Cmdline_Short with value 0
+$_OPTS_GROFFER_LONG_ARG                -
+$_OPTS_GROFFER_LONG_NA         -
+$_OPTS_GROFFER_SHORT_ARG       -
+$_OPTS_GROFFER_SHORT_NA                -
+$_OPTS_GROFF_LONG_ARG          -
+$_OPTS_GROFF_LONG_NA           -
+$_OPTS_GROFF_SHORT_ARG         -
+$_OPTS_GROFF_SHORT_NA          -
+$_OPTS_MANOPT_LONG_ARG         -
+$_OPTS_MANOPT_LONG_NA          -
+$_OPTS_MANOPT_SHORT_ARG                -
+$_OPTS_MANOPT_SHORT_NA         -
+$_OPTS_MAN_LONG_ARG            -
+$_OPTS_MAN_LONG_NA             -
+$_OPTS_MAN_SHORT_ARG           -
+$_OPTS_MAN_SHORT_NA            -
+$_OPTS_X_LONG_ARG              -
+$_OPTS_X_LONG_NA               -
+$_OPTS_X_SHORT_ARG             -
+$_OPTS_X_SHORT_NA              -
+$_OPT_ALL                      $Opt{ALL}
+$_OPT_APROPOS                  $Opt{APROPOS}
+$_OPT_BD                       $Opt{BD}
+$_OPT_BG                       $Opt{BG}
+$_OPT_BW                       $Opt{BW}
+$_OPT_DEFAULT_MODES            $Opt{DEFAULT_MODES}
+$_OPT_DEVICE                   $Opt{DEVICE}
+$_OPT_DISPLAY                  $Opt{DISPLAY}
+$_OPT_DO_NOTHING               $Opt{DO_NOTHING}
+$_OPT_EXTENSION                        $Opt{EXTENSION}
+$_OPT_FG                       $Opt{FG}
+$_OPT_FN                       $Opt{FN}
+$_OPT_GEOMETRY                 $Opt{GEOMETRY}
+$_OPT_ICONIC                   $Opt{ICONIC}
+$_OPT_LANG                     $Opt{LANG}
+$_OPT_MANPATH                  $Opt{MANPATH}
+$_OPT_MODE                     $Opt{MODE}
+$_OPT_PAGER                    $Opt{PAGER}
+$_OPT_RESOLUTION               $Opt{RESOLUTION}
+$_OPT_RV                       $Opt{RV}
+$_OPT_SECTIONS                 $Opt{SECTIONS}
+$_OPT_SYSTEMS                  $Opt{SYSTEMS}
+$_OPT_TEXT_DEVICE              $Opt{TEXT_DEVICE}
+$_OPT_TITLE                    $Opt{TITLE}
+$_OPT_V                                $Opt{V}
+$_OPT_VIEWER_DVI               $Opt{VIEWER_DVI}
+$_OPT_VIEWER_HTML              $Opt{VIEWER_HTML}
+$_OPT_VIEWER_PDF               $Opt{VIEWER_PDF}
+$_OPT_VIEWER_PS                        $Opt{VIEWER_PS}
+$_OPT_VIEWER_X                 $Opt{VIEWER_X}
+$_OPT_WHATIS                   $Opt{WHATIS}
+$_OPT_XRM                      @{$Opt{XRM}}
+$_OPT_Z                                $Opt{Z}
+$_OUTPUT_FILE_NAME             $Output_File_Name
+$_PDF_DID_NOT_WORK             $PDF_Did_Not_Work
+$_PDF_HAS_GS                   $PDF_Has_gs
+$_PDF_HAS_PS2PDF               $PDF_Has_ps2pdf
+$_PROCESS_ID                   -
+$_PROGRAM_VERSION              $program_version
+$_REG_TITLE_LIST               @Reg_Title
+$_SHELL                                -
+$_SP                           -
+$_SPACE_CASE                   -
+$_SPACE_SED                    -
+$_SPECIAL_FILESPEC             $Special_Filespec
+$_SPECIAL_SETUP                        $Special_Setup
+$_SQ                           -
+$_START_DIR                    $Start_Dir
+$_TAB                          -
+$_TMP_CAT                      $fh_cat, $tmp_cat
+$_TMP_DIR                      $tmpdir
+$_TMP_MAN                      -
+$_TMP_MANSPEC                  $Manspec for @{Man{MANSPEC}{$Manspec}}
+$_TMP_STDIN                    $fh_stdin, $tmp_stdin
+$_UNSET                                -
+$_VIEWER_BACKGROUND            $Viewer_Background
+$_VIEWER_DVI_TTY               $Viewer_tty{'DVI'}
+$_VIEWER_DVI_X                 $Viewer_X{'DVI'}
+$_VIEWER_HTML_TTY              $Viewer_tty{'HTML'}
+$_VIEWER_HTML_X                        $Viewer_X{'HTML'}
+$_VIEWER_PDF_TTY               $Viewer_tty{'PDF'}
+$_VIEWER_PDF_X                 $Viewer_X{'PDF'}
+$_VIEWER_PS_TTY                        $Viewer_tty{'PS'}
+$_VIEWER_PS_X                  $Viewer_X{'PS'}
+$_VIEWER_TTY_TTY               -
+$_VIEWER_TTY_X                 -
+$_VIEWER_X_TTY                 $Viewer_tty{'X'}
+$_VIEWER_X_X                   $Viewer_X{'X'}
+$_YES                          -
+$return_bad                    -
+$return_error                  -
+$return_good                   -
+$return_no                     -
+$return_ok                     -
+$return_var                    -
+$return_yes                    -
+-                              @ARGV
+-                              @Manopt
+-                              $Opt{LOCATION}
+-                              $Opt{X}
+-                              $File_Split_Env
+-                              @Options
+-                              @StartingARGV
+-                              @StartingConf
+-                              $Umask
+
+
+####### License
+
+Copyright (C) 2003, 2004, 2005, 2006, 2009
+  Free Software Foundation, Inc.
+Written by Bernd Warken <address@hidden>.
+
+This file is part of `groffer', which is part of `groff'.
+
+`groff' is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+`groff' is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Last update: 5 Jan 2009
+
+
+####### Emacs settings
+
+Local Variables:
+mode: text
+End:

Index: func.pl
===================================================================
RCS file: func.pl
diff -N func.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ func.pl     11 Aug 2013 08:28:51 -0000      1.10
@@ -0,0 +1,789 @@
+#! /usr/bin/env perl
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/perl/func.pl
+# Installed position: <prefix>/lib/groff/groffer/func.pl
+
+# Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 5 Jan 2009
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+use strict;
+use warnings;
+
+########################################################################
+# some functions
+########################################################################
+
+##########
+# cat_z(<file>)
+#
+# Decompress or cat the <file>.
+#
+# Return: the decompressed file as array
+#
+sub cat_z {
+  my $n = @_;
+  die "cat_z(): one argument is needed; you used $n;"
+    unless $n == 1;
+
+  my $file = $_[0];
+  die "cat_z(): `$file' is not a readable file;" unless -f $file && -r $file;
+  return () if -z $file;
+
+  my @res;
+  if ($main::Has_Compression) {
+    if ($main::Has_bzip) {
+      # test whether bz2 compressed, shell return must be inverted
+      unless ( system("bzip2 -t $file 2>$main::Dev_Null") ) {
+       @res = `bzip2 -c -d $file 2>$main::Dev_Null`;
+       return @res;
+      }
+      # if not compressed with gz, gzip will act like `cat'
+      @res = `gzip -c -d -f $file 2>$main::Dev_Null`;
+      return @res;
+    }
+  } else {
+    my $fh;
+    open $fh, "<$file" or die "cat_z(): could not open $file";
+    @res = <$fh>;
+    close $fh;
+    return @res;
+  }
+  ();
+} # cat_z()
+
+
+##########
+# clean_up()
+#
+# Remove the temporary directory and restore the system.
+#
+sub clean_up {
+  umask $main::Umask;
+  chdir $main::Start_Dir;
+  if ($main::Debug{'KEEP'} && -d $main::tmpdir) {
+    my $glob = File::Spec->catfile($main::tmpdir, '*');
+    unlink glob($glob);                # rm $tmpdir/*
+    rmdir $main::tmpdir;
+  }
+} # clean_up()
+
+
+##########
+# get_dirname(<path>)
+#
+# Split the path and return the directory name part
+#
+# Return: string of directory name
+#
+sub get_dirname {
+  my $n = @_;
+  die "get_filename(): one argument is needed; you used $n;" unless $n == 1;
+  return '' unless $_[0];
+
+  my ($dirname, $filename) = &split_path($_[0]);
+  $dirname;
+}                              # get_dirname()
+
+
+##########
+# get_filename(<path>)
+#
+# Split the path and return the file name part
+#
+# Return: string of file name
+#
+sub get_filename {
+  my $n = @_;
+  die "get_dirname(): one argument is needed; you used $n;" unless $n == 1;
+  return '' unless $_[0];
+
+  my ($dirname, $filename) = &split_path($_[0]);
+  $filename;
+}                              # get_filename()
+
+
+##########
+# is_X()
+#
+# Test whether X Windows is running.
+#
+sub is_X {
+  return 1 if $ENV{'DISPLAY'};
+  return 0;
+}                              # is_X()
+
+
+##########
+# list_has(<list_ref>, <string>)
+#
+# Determine if <list_ref> has <string> as element.
+#
+sub list_has {
+  my $n = @_;
+  die "list_has(): 2 arguments are needed; you used $n;"
+    unless $n == 2;
+
+  my $list_ref = $_[0];
+  my $string = $_[1];
+  die "list_has(): first argument must be an array reference;"
+    unless ref($list_ref) eq 'ARRAY';
+
+  foreach ( @$list_ref ) {
+    return 1 if $_ eq $string;
+  }
+  0;
+}
+
+
+##########
+# path_uniq(<dir>...)
+#
+# make path having unique existing directories
+#
+sub path_uniq {
+  my @a;
+  my %h;
+  foreach (@_) {
+    next if exists $h{$_};
+    next unless -d $_;
+    push @a, $_;
+    $h{$_} = 1;
+  }
+  @a;
+}                              # path_uniq()
+
+
+##########
+# print_hash(<hash_or_ref>)
+#
+# print the elements of a hash or hash reference
+#
+sub print_hash {
+  my $hr;
+  my $n = scalar @_;
+  if ($n == 0) {
+    print "empty hash\n;";
+    return 1;
+  } elsif ($n == 1) {
+    if (ref($_[0]) eq 'HASH') {
+      $hr = $_[0];
+    } else {
+      warn 'print_hash(): the argument is not a hash or hash reference;';
+      return 0;
+    }
+  } else {
+    if ($n % 2) {
+      warn 'print_hash(): the arguments are not a hash;';
+      return 0;
+    } else {
+      my %h = @_;
+      $hr = \%h;
+    }
+  }
+
+### print_hash()
+  unless (%$hr) {
+    print "empty hash\n";
+    return 1;
+  }
+  print "hash (ignore the ^ characters):\n";
+  for my $k (sort keys %$hr) {
+    my $hk = $hr->{$k};
+    print "  $k => ";
+    if (defined $hk) {
+      print "^$hk^";
+    } else {
+      print "undef";
+    }
+    print "\n";
+  }
+
+  1;
+}                              # print_hash()
+
+
+##########
+# print_times(<string>)
+#
+# print the time, result: user, system, child process user, child system
+#
+sub print_times {
+  my @t = times;
+  my $s = '';
+  $s = $_[0] if $_[0];
+#  print STDERR "$s: @t\n";
+}                              # print_times()
+
+BEGIN { &print_times("start"); }
+END { &print_times("end"); }
+
+
+##########
+# split_path(<path>)
+#
+# Split the path into directory and file name parts
+#
+# Return: array with 2 elements consisting of directory and file name
+#
+sub split_path {
+  my $n = @_;
+  die "split_path(): one argument is needed; you used $n;" unless $n == 1;
+  my $arg = $_[0];
+  return () unless $arg;
+
+  my $basename = basename($arg);
+  if ( $basename ne $arg ) { # path with dir
+    # fileparse() is from File::Basename
+    my($filename, $dirname, $suffix) = fileparse($arg);
+    return ($dirname, $basename);
+  }
+  return ('', $arg);
+}
+
+
+{
+  my $nr_file = 0;
+  my $nr_so = 0;
+
+  my $tmp_file_base;
+  my $tmp_so_base;
+
+  my $soelim_r = '';
+  $soelim_r = '-r'
+    if ! system("echo -n '' | soelim -r 2>$main::Dev_Null >$main::Dev_Null");
+
+  ##########
+  # to_tmp (<filename>)
+  #
+  # Print file (decompressed) to the temporary cat file with handling .SO
+  # for man pages.
+  #
+  sub to_tmp {
+    my $n = @_;
+    die "to_tmp(): one argument is needed; you used $n;"
+      unless $n == 1;
+
+    my $arg = $_[0];
+    return 1 unless $arg;
+    die "to_tmp(): $arg is not an existing file;" unless -f $arg;
+    die "to_tmp(): could not read file $arg;" unless -r $arg;
+    return 1 if -z $arg;
+
+    $tmp_file_base = File::Spec->catfile($main::tmpdir, ',file')
+      unless $tmp_file_base;
+    $tmp_so_base = File::Spec->catfile($main::tmpdir, ',so')
+      unless $tmp_so_base;
+
+    open $main::fh_cat, ">>$main::tmp_cat" or
+      die "to_tmp(): could not open temporary cat file";
+
+    if ($main::Opt{'WHATIS'}) {
+      &whatis_filename($arg);
+      return 1;
+    }
+
+    ### to_tmp()
+    my $dir = &get_dirname($arg);
+
+    my ($fh_file, $tmp_file, $fh_tmp, $tmp_tmp);
+    ++$nr_file;
+    $tmp_file = $tmp_file_base . $nr_file;
+    $tmp_tmp = File::Spec->catfile($main::tmpdir, ',tmp');
+
+    print STDERR "file: $arg\n" if $main::Debug{'FILENAMES'};
+
+    if ($main::Filespec_Is_Man) {
+      my ($fh_so, $tmp_so);
+
+      open $fh_file, ">$tmp_file" or
+       die "to_tmp(): could not open $tmp_file;";
+      foreach ( &cat_z($arg) ) {
+       print $fh_file "$_";
+      }
+      close $fh_file;
+
+      open $fh_file, "<$tmp_file" or
+       die "to_tmp(): could not open $tmp_file;";
+      my @list;
+      foreach (<$fh_file>) {
+       if (/^[\.']\s*so\s/) {
+         chomp;
+         s/^[\.']\s*so\s*//;
+         push @list, $_;
+       }
+      }
+      close $fh_file;
+
+      if ( @list && $main::Debug{'KEEP'} ) {
+       my $f = $tmp_file . '+man';
+       copy($tmp_file, $f);
+      }
+
+      ### to_tmp()
+    DO_MAN_SO:  foreach (@list) {
+       # start of _do_man_so() in shell version
+       my $so = $_;
+       my $soname = $so;
+       $soname =~ s/\\\s/ /g;
+
+       my $sofound;
+       my $path = File::Spec->rootdir();
+       if ($soname =~ m#^$path#) {       # absolute path name
+         next DO_MAN_SO if -f $soname;
+         foreach ('.gz', '.Z', '.bz2') {
+           my $name = $soname . $_;
+           if (-f $name) {
+             $sofound = $name;
+             last;
+           }
+         }                     # foreach
+         next DO_MAN_SO unless $sofound;
+       } else {                # relative to man path
+       LOOP: foreach my $ext ('', '.gz', '.Z', '.bz2') {
+           foreach my $p ( @{$main::Man{'PATH'}} ) {
+             my $f = File::Spec->catfile($p, "$soname$ext");
+             if (-f $f) {
+               $sofound = $f if -f $f;
+               last LOOP;
+             }
+           }                   # foreach
+         }                     # LOOP:
+         next DO_MAN_SO unless $sofound;
+       }                       # if on path
+
+       print STDERR "file from .so: $so\n" if $main::Debug{'FILENAMES'};
+
+       ### to_tmp()
+       ++$nr_so;
+       $tmp_so = $tmp_so_base . $nr_so;
+       unlink $tmp_so if -e $tmp_so;
+       open $fh_so, ">$tmp_so" or
+         die "to_tmp(): could not open $tmp_so;";
+       foreach ( &cat_z($sofound) ) {
+         print $fh_so $_;
+       }
+       close $fh_so;
+
+       my $esc = $so;
+       $esc =~ s/\\/\\\\/g;
+       open $fh_file, "<$tmp_file" or
+         die "to_tmp(): could not open $tmp_file;";
+       open $fh_tmp, ">$tmp_tmp" or
+         die "to_tmp(): could not open $tmp_tmp;";
+       foreach (<$fh_file>) {
+         s#^([\.'])\s*so\s+($so|$esc|$soname)\s*\n$#${1}so $tmp_so\n#s;
+         print $fh_tmp $_;
+       }
+       ### to_tmp()
+       close $fh_tmp;
+       close $fh_file;
+       unlink $tmp_file if -e $tmp_file;
+       rename $tmp_tmp, $tmp_file;
+       # end of _do_man_so() in shell version
+      }                                # foreach (@list)
+
+      if ( @list && $main::Debug{'KEEP'} ) {
+       my $f = $tmp_file . '+tmp';
+       copy($tmp_file, $f);
+      }
+
+      unlink $tmp_tmp if -e $tmp_tmp;
+      rename $tmp_file, $tmp_tmp;
+      system("soelim -I$dir $soelim_r $tmp_tmp >$tmp_file");
+      unlink $tmp_tmp if -e $tmp_tmp;
+
+    } else {                   # $Filespec_Is_Man is empty
+      open $fh_tmp, ">$tmp_tmp" or
+       die "to_tmp(): could not open $tmp_tmp;";
+      foreach (cat_z $arg) {
+       print $fh_tmp $_;
+      }
+      close $fh_tmp;
+      if ($dir) {
+       system("soelim -I$dir $soelim_r $tmp_tmp >$tmp_file");
+      } else {
+       system("soelim $soelim_r $tmp_tmp >$tmp_file");
+      }
+      unlink $tmp_tmp;
+    }                          # if ($Filespec_Is_Man)
+
+    ### to_tmp()
+    my $grog = `grog $tmp_file`;
+    die "to_tmp(): grog error on $tmp_file;" if $?;
+    chomp $grog;
+    print STDERR "grog output: $grog\n" if $main::Debug{'GROG'};
+    if ($grog =~ /^.*\s-m.*$/) {
+      $grog =~ s/\s+/ /g;
+      $grog =~ s/ -m / -m/g;
+      $grog =~ s/ -mm([^ ]) / -m$1/g;
+      foreach my $g (split / /, $grog) {
+       if ($g =~ /^-m/) {
+         my $ref = address@hidden::Macro_Packages;
+         if ( &list_has($ref, $g) ) {
+           if (! $main::Macro_Pkg) {
+             $main::Macro_Pkg = $g;
+           } elsif ($main::Macro_Pkg eq $g) {
+             1;
+           } elsif ($main::Macro_Pkg =~ /^-m/) {
+             warn "to_tmp(): Ignore $arg because it needs $g " .
+               "instead of $main::Macro_Pkg";
+             unlink $tmp_file unless $main::Debug{'KEEP'};
+             return 0;
+           } elsif ($main::Macro_Pkg ne $g) {
+             die "to_tmp(): \$Macro_Pkg does not start with -m: " .
+               "$main::Macro_Pkg";
+           }                   # if (! $main::Macro_Pkg)
+         }                     # if (&list_has
+       }                       # if (/^-m/)
+      }                                # foreach my $g
+    }                          # if $grog
+
+    open $fh_file, "<$tmp_file" or
+      die "to_tmp(): could not open $tmp_file for reading;";
+    open $main::fh_cat, ">>$main::tmp_cat" or
+      die "to_tmp(): could not open $main::tmp_cat for appending;";
+    foreach (<$fh_file>) {
+      print $main::fh_cat $_;
+    }
+    close $main::fh_cat;
+    close $fh_file;
+
+    unless ( $main::Debug{'KEEP'} ) {
+      unlink $tmp_file;
+      foreach ( glob("$tmp_so_base*") ) {
+       unlink $_;
+      }
+    }
+    1;
+  }                            # to_tmp()
+}
+
+##########
+# to_tmp_line (<text>...)
+#
+# Print array of lines with <text> to the temporary cat file.  \n is added
+# if a line does not end with \n.
+#
+sub to_tmp_line {
+  my $n = @_;
+  return 1 if $n == 0;
+  open $main::fh_cat, ">>$main::tmp_cat" or
+    die "to_tmp_line(): could not open temporary cat file";
+  foreach (@_) {
+    my $line = $_;
+    chomp($line);
+    print $main::fh_cat "$line\n";
+  }
+  close $main::fh_cat;
+  1;
+} # to_tmp_line()
+
+
+##########
+# usage()
+#
+# Print usage information for --help.
+#
+sub usage {
+  print "\n";
+  &version();
+  print <<EOF;
+
+Usage: groffer [option]... [filespec]...
+
+Display roff files, standard input, and/or Unix manual pages with an X
+Window viewer or in several text modes.  All input is decompressed
+on-the-fly with all formats that gzip can handle.
+
+"filespec" is one of
+  "filename"       name of a readable file
+  "-"              for standard input
+  "man:name(n)"    man page "name" in section "n"
+  "man:name.n"     man page "name" in section "n"
+  "man:name"       man page "name" in first section found
+  "name(n)"        man page "name" in section "n"
+  "name.n"         man page "name" in section "n"
+  "n name"         man page "name" in section "n"
+  "name"           man page "name" in first section found
+where `section' is a single character out of [1-9on], optionally followed
+by some more letters that are called the `extension'.
+
+-h --help         print this usage message.
+-T --device=name  pass to groff using output device "name".
+-v --version      print version information.
+-V                display the groff execution pipe instead of formatting.
+-X                display with "gxditview" using groff -X.
+-Z --ditroff --intermediate-output
+                  generate groff intermediate output without
+                  post-processing and viewing, like groff -Z.
+All other short options are interpreted as "groff" formatting options.
+
+The most important groffer long options are
+
+--apropos=name    start man's "apropos" program for "name".
+--apropos-data=name
+                  "apropos" for "name" in man's data sections 4, 5, 7.
+--apropos-devel=name
+                  "apropos" for "name" in development sections 2, 3, 9.
+--apropos-progs=name
+                  "apropos" for "name" in man's program sections 1, 6, 8.
+--auto            choose mode automatically from the default mode list.
+--default         reset all options to the default value.
+--default-modes=mode1,mode2,...
+                  set sequence of automatically tried modes.
+--dvi             display in a viewer for TeX device independent format.
+--dvi-viewer=prog choose the viewer program for dvi mode.
+--groff           process like groff, disable viewing features.
+--help            display this helping output.
+--html            display in a web browser.
+--html-viewer=program
+                  choose the web browser for html mode.
+--man             check file parameters first whether they are man pages.
+--mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
+                  choose display mode.
+--no-man          disable man-page facility.
+--no-special      disable --all, --apropos*, and --whatis
+--pager=program   preset the paging program for tty mode.
+--pdf             display in a PDF viewer.
+--pdf-viewer=prog choose the viewer program for pdf mode.
+--ps              display in a Postscript viewer.
+--ps-viewer=prog  choose the viewer program for ps mode.
+--source          output as roff source.
+--text            output in a text device without a pager.
+--to-stdout       output the content of the mode file without display.
+--tty             display with a pager on text terminal even when in X.
+--tty-viewer=prog select a pager for tty mode; same as --pager.
+--whatis          display the file name and description of man pages
+--www             same as --html.
+--www-viewer=prog same as --html-viewer
+--x --X           display with "gxditview" using an X* device.
+--x-viewer=prog   choose viewer program for x mode (X mode).
+--X-viewer=prog   same as "--xviewer".
+
+The usual X Windows toolkit options transformed into GNU long options:
+--background=color, --bd=size, --bg=color, --bordercolor=color,
+--borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
+--fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
+--resolution=dpi, --rv, --title=text, --xrm=resource
+
+Long options of GNU "man":
+--all, --ascii, --ditroff, --extension=suffix, --locale=language,
+--local-file=name, --location, --manpath=dir1:dir2:...,
+--sections=s1:s2:..., --systems=s1,s2,..., --where, ...
+
+Development options that are not useful for normal usage:
+--debug, --debug-filenames, --debug-grog, --debug-keep, --debug-params,
+--debug-tmpdir, --do-nothing, --print=text
+
+EOF
+} # usage()
+
+
+##########
+# version()
+#
+# Get version information from version.sh and print a text with this.
+#
+sub version {
+  my $groff_version;
+  my $program_version = '';
+  my $last_update = '';
+  my $groff_version_preset = '';
+
+  die "$main::File_version_sh does not exist;"
+    unless -f "$main::File_version_sh";
+  my $fh;
+  open $fh, "<$main::File_version_sh";
+  foreach (<$fh>) {
+    chomp;
+    if (/^\s*_PROGRAM_VERSION\s*=\s*['"]*([^'"]*)['"]*\s*;?\s*$/) {
+      $program_version = $1;
+      next;
+    }
+    if (/^\s*_LAST_UPDATE\s*=\s*['"]*([^'"]*)['"]*\s*;?\s*$/) {
+      $last_update = $1;
+      next;
+    }
+    if (/^\s*_GROFF_VERSION_PRESET\s*=\s*['"]*([^'"]*)['"]*\s*;?\s*$/) {
+      # this setting of the groff version is only used before make is run,
+      # otherwise @VERSION@ will set it, see groffer.sh.
+      $groff_version_preset = $1;
+      next;
+    }
+  }
+  close $fh;
+
+  if ($main::Groff_Version) {
+    $groff_version = $main::Groff_Version;
+  } else {
+    $groff_version = $groff_version_preset;
+  }
+  my $year = $last_update;
+  $year =~ s/^.* //;
+  print <<EOF;
+groffer $program_version of $last_update (Perl version)
+is part of groff version $groff_version.
+Copyright (C) $year Free Software Foundation, Inc.
+GNU groff and groffer come with ABSOLUTELY NO WARRANTY.
+You may redistribute copies of groff and its subprograms
+under the terms of the GNU General Public License.
+EOF
+} # version()
+
+
+##########
+# where_is_prog(<program>)
+#
+# Test whether <program> without its arguments exists or is a program
+# in $PATH.
+#
+# Arguments : 1, <program> can have spaces and arguments.
+# Return    : a hash with `dir', `file', `fullname', `args' if
+#             argument exists or is a program in $PATH, empty hash else.
+#
+sub where_is_prog {
+  scalar @_ eq 1 or die "where_is_prog(): only one argument is allowed";
+  my $p1 = $_[0];
+  return () unless $p1;
+
+  $p1 =~ s/\s+/ /g;
+  $p1 =~ s/(\\)+ / /g;
+  $p1 =~ s/^ | $//g;
+  return () unless $p1;
+
+  my $noarg = $p1;
+  $noarg =~ s/ -.*$//;
+  return () unless $noarg;
+
+  my $args;
+  if ($p1 =~ /^.* -.*$/) {
+    $args = $p1;
+    $args =~ s#^$noarg ##;
+  }
+  $args = '' unless defined $args;
+
+  my %result;
+
+  # test whether $noarg has directory, so it is not tested with $PATH
+  my ($dir, $name) = &split_path($noarg);
+  $result{'dir'} = $dir;
+
+### where_is_prog()
+  if (-f $noarg && -x $noarg) {
+    $result{'args'} = $args;
+    $result{'file'} = $name;
+    $result{'fullname'} = File::Spec->catfile($dir, $name);
+    return %result;
+  }
+
+  if ($dir) {                  # $noarg has name with directory
+    # now $wip_noarg (with directory) is not an executable file
+
+    # test name with space
+    if ($name =~ / /) {
+      my @base = split(/ /, $name);
+      my $n = pop @base;
+      my @baseargs = ($n);
+      while (@base) {
+       my $base = join(' ', @base);
+       my $file = File::Spec->catpath($dir, $base);
+       if (-f $file && -x $file) {
+         my $baseargs = join(' ', @baseargs);
+         ### where_is_prog()
+         if ($args) {
+           $args = "$baseargs $args";
+         } else {
+           $args = $baseargs;
+         }
+         $result{'args'} = $args;
+         $result{'file'} = $base;
+         $result{'fullname'} = $file;
+         return %result;
+       }                       # file test $file
+       $n = pop @base;
+       unshift(@baseargs, $n);
+      }                                # while (@base)
+    }                          # end of test name with space
+    return ();
+  }                            # test on $dir
+
+  # now $noarg doesn't have a directory part
+
+  $name = $noarg;
+
+  # check with $PATH
+
+  # test path with $win_noarg as a whole, evt. with spaces
+  foreach my $d (@main::Path) {
+    my $file = File::Spec->catfile($d, $name);
+    if (-f $file && -x $file) {
+      $result{'args'} = $args;
+      $result{'fullname'} = $file;
+      ($result{'dir'}, $result{'file'}) = &split_path($file);
+      return %result;
+    }                          # file test $file
+  }                            # foreach (@main::Path)
+
+### where_is_prog()
+  if ($name =~ / /) {
+    my @base = split(/ /, $name);
+    my $n = pop @base;
+    my @baseargs = ($n);
+    while (@base) {
+      my $base = join(' ', @base);
+      foreach my $d (@maon::Path) {
+       my $file = File::Spec->catfile($d, $base);
+       if (-f $file && -x $file) {
+         my $baseargs = join(' ', @baseargs);
+         if ($args) {
+           $args = "$baseargs $args";
+         } else {
+           $args = $baseargs;
+         }
+         $result{'args'} = $args;
+         $result{'fullname'} = $file;
+         ($result{'dir'}, $result{'file'}) = &split_path($file);
+         return %result;
+       }                       # file test $file
+      }                                # foreach (@main::Path)
+      $n = pop @base;
+      unshift(@baseargs, $n);
+    }                          # while (@base)
+  }                            # test $name on space
+  return ();
+} # where_is_prog()
+
+
+##########
+# wait()
+#
+# stop for checking temp files, etc.
+#
+sub wait {
+  print "push Ctrl-D";
+  my @x = <STDIN>;
+  print "\n";
+}                              # wait()
+
+1;

Index: groffer.man
===================================================================
RCS file: groffer.man
diff -N groffer.man
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ groffer.man 11 Aug 2013 08:28:52 -0000      1.21
@@ -0,0 +1,3920 @@
+.TH GROFFER @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groffer \- display groff files and man\~pages on X and tty
+.
+.SH "SYNOPSIS"
+.\" The .SH was moved to this place in order to appease `apropos'.
+.
+.\" --------------------------------------------------------------------
+.\" Legalese
+.\" --------------------------------------------------------------------
+.
+.de author
+This file was written by Bernd Warken <address@hidden>.
+..
+.de copyleft
+Copyright (C) 2001, 2002, 2004-2006, 2009-2012
+  Free Software Foundation, Inc.
+.
+.P
+This file is part of
+.IR \%groffer ,
+which is part of
+.IR \%groff ,
+a free software project.
+.
+You can redistribute it and/or modify it under the terms of the
+.nh
+.B GNU General Public License
+.hy
+as published by the
+.nh
+.BR "Free Software Foundation" ,
+.hy
+either version 3 of the License, or (at your option) any later version.
+.
+.P
+You should have received a copy of the \f[CR]GNU General Public
+License\f[] along with
+.IR groff ,
+see the files \%\f[CB]COPYING\f[] and \%\f[CB]LICENSE\f[] in the top
+directory of the
+.I groff
+source package.
+.
+Or read the
+.I man\~page
+.BR gpl (1).
+You can also visit
+.nh
+.B <http://www.gnu.org/licenses/>.
+.hy
+..
+.
+.\" --------------------------------------------------------------------
+.\" Setup
+.\" --------------------------------------------------------------------
+.
+.ds Ellipsis "\&.\|.\|.\&\"
+.
+.\" --------------------------------------------------------------------
+.\" Macro definitions
+.
+.\" --------------------------------------------------------------------
+.\" .CB  (<text>...)
+.\"
+.\" Print in constant-width bold font.
+.\"
+.de CB
+.  ft CB
+.  Text \\$*
+.  ft
+..
+.\" --------------------------------------------------------------------
+.\" .CI  (<text>...)
+.\"
+.\" Print in constant-width italic font.
+.\"
+.de CI
+.  ft CI
+.  Text \\$*
+.  ft
+..
+.\" --------------------------------------------------------------------
+.\" .CR  (<text>...)
+.\"
+.\" Print in constant-width roman font.
+.\"
+.de CR
+.  ft CR
+.  Text \\$*
+.  ft
+..
+.\" --------------------------------------------------------------------
+.\" .Error  (<text>...)
+.\"
+.\" Print error message to terminal and abort.
+.\"
+.de Error
+.  tm \\$*
+.  ab
+..
+.\" --------------------------------------------------------------------
+.\" .Env_var  (<env_var_name> [<punct>])
+.\"
+.\" Display an environment variable, with optional punctuation.
+.\"
+.de Env_var
+.  nh
+.  SM
+.  Text \f[CB]\\$1\f[]\\$2
+.  hy
+..
+.\" --------------------------------------------------------------------
+.\" .File_name  (<path_name>)
+.\"
+.\" Display a file or directory name in CB font.
+.\"
+.de File_name
+.  Header_CB \\$@
+..
+.\" --------------------------------------------------------------------
+.\" .Header_CB  (<path_name>)
+.\"
+.\" Display a line in CB font, for example after .TP
+.\"
+.de Header_CB
+.  nh
+.  Text \f[CB]\\$1\f[]\\$2
+.  hy
+..
+.\"  --------------------------------------------------------------------
+.\" .Text  (<text>...)
+.\"
+.\" Treat the arguments as text, no matter how they look.
+.\"
+.de Text
+.  if \\n[.$]=0 \
+.    return
+.  nh
+.  nop \)\\$*\)
+.  hy
+..
+.\" --------------------------------------------------------------------
+.\" .Topic  ([<indent>])
+.\"
+.\" A bulleted paragraph
+.\"
+.de Topic
+.  ie \\n[.$]=0 \
+.    ds @indent 2m\"
+.  el \
+.    ds @indent \\$1\"
+.  IP \[bu] address@hidden
+.  rm @indent
+..
+
+.\" End of macro definitions
+.
+.
+.\" --------------------------------------------------------------------
+.\" SH "SYNOPSIS"
+.\" --------------------------------------------------------------------
+.
+.SY groffer
+.OP option \*[Ellipsis]
+.OP --
+.OP \%filespec \*[Ellipsis]
+.YS
+.
+.SY groffer
+.BR -h | --help
+.YS
+.
+.SY groffer
+.BR -v | --version
+.YS
+.
+.
+.\" --------------------------------------------------------------------
+.SH DESCRIPTION
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program is the easiest way to use
+.BR \%groff (@MAN1EXT@).
+It can display arbitrary documents written in the
+.I \%groff
+language, see
+.BR \%groff (@MAN7EXT@),
+or other
+.I \%roff
+languages, see
+.BR \%roff (@MAN7EXT@),
+that are compatible to the original
+.I \%troff
+language.
+.
+It finds and runs all necessary
+.I groff
+preprocessors, such as
+.BR @address@hidden .
+.
+.
+.P
+The
+.B \%groffer
+program also includes many of the features for finding and displaying
+the \%\f[CR]Unix\f[] manual pages
+.nh
+.RI ( man\~pages ),
+.hy
+such that it can be used as a replacement for a
+.BR \%man (1)
+program.
+.
+Moreover, compressed files that can be handled by
+.BR \%gzip (1)
+or
+.BR \%bzip2 (1)
+are decompressed on-the-fly.
+.
+.
+.P
+The normal usage is quite simple by supplying a file name or name of a
+.I \%man\~page
+without further options.
+.
+But the option handling has many possibilities for creating special
+behaviors.
+.
+This can be done either in configuration files, with the shell
+environment variable
+.Env_var \%$GROFFER_OPT ,
+or on the command line.
+.
+.
+.P
+The output can be generated and viewed in several different ways
+available for
+.IR \%groff .
+.
+This includes the
+.I \%groff
+native \%\f[CR]X\~Window\f[] viewer
+.BR \%gxditview (@MAN1EXT@),
+each
+.IR \%Postcript ,
+.IR \%pdf ,
+or
+.I \%dvi
+display program, a web browser by generating
+.I \%html
+in
+.IR \%www\~mode ,
+or several
+.I \%text\~modes
+in text terminals.
+.
+.
+.P
+Most of the options that must be named when running
+.B \%groff
+directly are determined automatically for
+.BR \%groffer ,
+due to the internal usage of the
+.BR \%grog (@MAN1EXT@)
+program.
+.
+But all parts can also be controlled manually by arguments.
+.
+.
+.P
+Several file names can be specified on the command line arguments.
+.
+They are transformed into a single document in the normal way of
+.BR \%groff .
+.
+.
+.P
+Option handling is done in \f[CR]GNU\f[] style.
+.
+Options and file names can be mixed freely.
+.
+The option
+.RB ` \-\- '
+closes the option handling, all following arguments are treated as
+file names.
+.
+Long options can be abbreviated in several ways.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OPTION OVERVIEW"
+.\" --------------------------------------------------------------------
+.
+.TP
+.I breaking options
+.RS
+.P
+.SY
+.OP -h\~\fR|\fB\~--help
+.OP -v\~\fR|\fB\~--version
+.YS
+.RE
+.
+.
+.TP
+.I \%groffer mode options
+.RS
+.P
+.SY
+.OP --auto
+.OP --default
+.OP --default\-modes mode1,mode2,\*[Ellipsis]
+.OP --dvi
+.OP --dvi\-viewer prog
+.OP --groff
+.OP --html
+.OP --html\-viewer prog
+.OP --mode display_mode
+.OP --pdf
+.OP --pdf\-viewer prog
+.OP --ps
+.OP --ps\-viewer prog
+.OP --source
+.OP --text
+.OP --to\-stdout
+.OP --tty
+.OP --tty\-viewer prog
+.OP --www
+.OP --www\-viewer prog
+.OP --x\~\fR|\fB\~--X
+.OP --x\-viewer\~\fR|\fB\~--X\-viewer prog
+.YS
+.RE
+.
+.
+.TP
+.I options related to \%groff
+.RS
+.P
+.SY
+.OP -T\~\fR|\fB\~--device device
+.OP -Z\~\fR|\fB\~--intermediate\-output\~\fR|\fB\~--ditroff
+.YS
+.P
+All further
+.B \%groff
+short options are accepted.
+.RE
+.
+.
+.TP
+.I options for man\~pages
+.RS
+.P
+.SY
+.OP --apropos
+.OP --apropos\-data
+.OP --apropos\-devel
+.OP --apropos\-progs
+.OP --man
+.OP --no\-man
+.OP --no\-special
+.OP --whatis
+.YS
+.RE
+.
+.
+.TP
+.I long options taken over from GNU man
+.RS
+.P
+.SY
+.OP --all
+.OP --ascii
+.OP --ditroff
+.OP --extension suffix
+.OP --locale language
+.OP --local\-file
+.OP --location\~\fR|\fB\~--where
+.OP --manpath dir1:dir2:\*[Ellipsis]
+.OP --no\-location
+.OP --pager program
+.OP --sections sec1:sec2:\*[Ellipsis]
+.OP --systems sys1,sys2,\*[Ellipsis]
+.OP --troff\-device device
+.YS
+.P
+Further long options of \f[CR]GNU\f[]
+.B man
+are accepted as well.
+.RE
+.
+.
+.TP
+.I X Window Toolkit options
+.RS
+.P
+.SY
+.OP --bd\~\fR|\fB\~--bordercolor pixels
+.OP --bg\~\fR|\fB\~--background color
+.OP --bw\~\fR|\fB\~--borderwidth pixels
+.OP --display X-display
+.OP --fg\~\fR|\fB\~--foreground color
+.OP --fn\~\fR|\fB\~--ft\~\fR|\fB\~--font font_name
+.OP --geometry size_pos
+.OP --resolution value
+.OP --rv
+.OP --title string
+.OP --xrm X\-resource
+.YS
+.RE
+.
+.
+.TP
+.I options for development
+.RS
+.P
+.SY
+.OP --debug
+.OP --debug\-filenames
+.OP --debug\-grog
+.OP --debug\-keep
+.OP --debug\-params
+.OP --debug\-tmpdir
+.OP --do\-nothing
+.OP --print text
+.OP -V
+.YS
+.RE
+.
+.
+.TP
+.I \%filespec arguments
+.RS
+.P
+The
+.I \%filespec
+parameters are all arguments that are neither an option nor an option
+argument.
+.
+They usually mean a file name or a
+.I man page
+searching scheme.
+.
+.
+.P
+In the following, the term
+.I section_extension
+is used.
+.
+It means a word that consists of a
+.I man section
+that is optionally followed by an
+.IR extension .
+.
+The name of a
+.I man section
+is a single character from
+.BR \%[1-9on] ,
+the
+.I extension
+is some word.
+.
+The
+.I extension
+is mostly lacking.
+.
+.
+.P
+No
+.I \%filespec
+parameters means standard input.
+.
+.
+.TP 10m
+.B -
+stands for standard input (can occur several times).
+.
+.
+.TP
+.I filename
+the path name of an existing file.
+.
+.
+.TP
+.BI man: name ( section_extension )
+.TQ
+.BI man: name . section_extension
+.TQ
+.IB name ( section_extension )
+.TQ
+.IB name . section_extension
+.TQ
+.I "section_extension name"
+search the \%man\~page
+.I \%name
+in the section with optional extension
+.IR section_extension .
+.
+.
+.TP
+.BI man: name
+\%man\~page in the lowest
+.I \%man\~section
+that has
+.IR \%name .
+.
+.
+.TP
+.I name
+if
+.I \%name
+is not an existing file search for the man\~page
+.I \%name
+in the lowest man\~section.
+.
+.RE
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OPTION DETAILS"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program can usually be run with very few options.
+.
+But for special purposes, it supports many options.
+.
+These can be classified in 5 option classes.
+.
+.
+.P
+All short options of
+.B \%groffer
+are compatible with the short options of
+.BR \%groff (@MAN1EXT@).
+.
+All long options of
+.B \%groffer
+are compatible with the long options of
+.BR \%man (1).
+.
+.
+.P
+Arguments for long option names can be abbreviated in several ways.
+.
+First, the argument is checked whether it can be prolonged as is.
+.
+Furthermore, each minus sign
+.B -
+is considered as a starting point for a new abbreviation.
+.
+This leads to a set of multiple abbreviations for a single argument.
+.
+For example,
+.B --de\-n\-f
+can be used as an abbreviation for
+.BR --debug\-not\-func ,
+but
+.B --de\-n
+works as well.
+.
+If the abbreviation of the argument leads to several resulting options
+an error is raised.
+.
+.
+.P
+These abbreviations are only allowed in the environment variable
+.Env_var \%$GROFFER_OPT ,
+but not in the configuration files.
+.
+In configuration, all long options must be exact.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "groffer breaking Options"
+.\" --------------------------------------------------------------------
+.
+As soon as one of these options is found on the command line it is
+executed, printed to standard output, and the running
+.B \%groffer
+is terminated thereafter.
+.
+All other arguments are ignored.
+.
+.
+.TP
+.B -h\~\fR|\fB\~--help
+Print help information with a short explanation of options to
+standard output.
+.
+.
+.TP
+.B -v\~\fR|\fB\~--version
+Print version information to standard output.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "groffer Mode Options"
+.\" --------------------------------------------------------------------
+.
+The display mode and the viewer programs are determined by these
+options.
+.
+If none of these mode and viewer options is specified
+.B \%groffer
+tries to find a suitable display mode automatically.
+.
+The default modes are
+.IR "mode pdf" ,
+.IR "mode ps" ,
+.IR "mode html" ,
+.IR "mode x" ,
+and
+.I "mode dvi"
+in \%\f[CR]X\~Window\f[] with different viewers and
+.I mode tty
+with device
+.I latin1
+under
+.B less
+on a terminal; other modes are tested if the programs for the main
+default mode do not exist.
+.
+.
+.P
+In \%\f[CR]X\~Window\f[],
+many programs create their own window when called.
+.B \%groffer
+can run these viewers as an independent program in the background.
+.
+As this does not work in text mode on a terminal (tty) there must be a
+way to know which viewers are \%\f[CR]X\~Window\f[] graphical
+programs.
+.
+The
+.B \%groffer
+script has a small set of information on some viewer names.
+.
+If a viewer argument of the command\-line chooses an element that is
+kept as \%\f[CR]X\~Window\f[] program in this list it is treated as a
+viewer that can run in the background.
+.
+All other, unknown viewer calls are not run in the background.
+.
+.
+.P
+For each mode, you are free to choose whatever viewer you want.
+.
+That need not be some graphical viewer suitable for this mode.
+.
+There is a chance to view the output source; for example, the
+combination of the options
+.B --mode=ps
+and
+.B --ps\-viewer=less
+shows the content of the
+.I Postscript
+output, the source code, with the pager
+.BR less .
+.
+.
+.TP
+.B --auto
+Equivalent to
+.BR --mode=auto .
+.
+.
+.TP
+.B --default
+Reset all configuration from previously processed command line options
+to the default values.
+.
+This is useful to wipe out all former options of the configuration, in
+.Env_var \%$GROFFER_OPT ,
+and restart option processing using only the rest of the command line.
+.
+.
+.TP
+.BI --default\-modes \ mode1,mode2,\*[Ellipsis]
+Set the sequence of modes for
+.I \%auto\~mode
+to the comma separated list given in the argument.
+.
+See
+.B --mode
+for details on modes.  Display in the default manner; actually, this
+means to try the modes
+.IR x ,
+.IR ps ,
+and
+.I \%tty
+in this sequence.
+.
+.
+.
+.TP
+.B --dvi
+Equivalent to
+.BR --mode=\%dvi .
+.
+.
+.TP
+.BI --dvi\-viewer \ prog
+Choose a viewer program for
+.IR \%dvi\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH .
+.
+Known \%\f[CR]X\~Window\f[]
+.I \%dvi
+viewers include
+.BR \%xdvi (1)
+and
+.BR \%dvilx (1).
+.
+In each case, arguments can be provided additionally.
+.
+.
+.TP
+.B --groff
+Equivalent to
+.BR --mode=groff .
+.
+.
+.TP
+.B --html
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.B --html\-viewer
+Choose a web browser program for viewing in
+.IR \%html\~mode .
+.
+It can be the path name of an executable file or a program in
+.Env_var $PATH .
+.
+In each case, arguments can be provided additionally.
+.
+.
+.TP
+.BI --mode \ value
+.
+Set the display mode.
+.
+The following mode values are recognized:
+.
+.RS
+.
+.TP
+.Header_CB auto
+Select the automatic determination of the display mode.
+.
+The sequence of modes that are tried can be set with the
+.B --default\-modes
+option.
+.
+Useful for restoring the
+.I \%default\~mode
+when a different mode was specified before.
+.
+.
+.TP
+.Header_CB dvi
+Display formatted input in a
+.I \%dvi
+viewer program.
+.
+By default, the formatted input is displayed with the
+.BR \%xdvi (1)
+program.
+.
+.
+.TP
+.Header_CB groff
+After the file determination, switch
+.B \%groffer
+to process the input like
+.BR \%groff (@MAN1EXT@)
+would do.
+.
+This disables the
+.I \%groffer
+viewing features.
+.
+.
+.TP
+.Header_CB html
+Translate the input into html format and display the result in a web
+browser program.
+.
+By default, the existence of a sequence of standard web browsers is
+tested, starting with
+.BR \%konqueror (1)
+and
+.BR \%mozilla (1).
+The text html viewer is
+.BR \%lynx (1).
+.
+.
+.TP
+.Header_CB pdf
+Display formatted input in a
+.I \%PDF
+(Portable Document Format) viewer
+program.
+.
+By default, the input is formatted by
+.B \%groff
+using the Postscript device, then it is transformed into the PDF file
+format using
+.BR \%gs (1),
+or
+.BR ps2pdf (1).
+If that's not possible, the
+.I Postscript mode (ps)
+is used instead.
+.
+Finally it is displayed using different viewer programs.
+.
+.I \%pdf
+has a big advantage because the text is displayed graphically and
+is searchable as well.
+.
+.
+.TP
+.Header_CB ps
+Display formatted input in a Postscript viewer program.
+.
+By default, the formatted input is displayed in one of many viewer
+programs.
+.
+.
+.TP
+.Header_CB text
+Format in a
+.I \%groff\~text\~mode
+and write the result to standard output without a pager or viewer
+program.
+.
+The text device,
+.I \%latin1
+by default, can be chosen with option
+.BR -T .
+.
+.
+.TP
+.Header_CB tty
+Format in a
+.I \%groff\~text\~mode
+and write the result to standard output using a text pager program,
+even when in \%\f[CR]X\~Window\f[].
+.
+.
+.TP
+.Header_CB www
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.Header_CB x
+Display the formatted input in a native
+.I roff
+viewer.
+.
+By default, the formatted input is displayed with the
+.BR \%gxditview (@MAN1EXT@)
+program being distributed together with
+.BR \%groff .
+But the standard \%\f[CR]X\~Window\f[] tool
+.BR \%xditview (1)
+can also be chosen with the option
+.BR --x\-viewer .
+The default resolution is
+.BR 75dpi ,
+but
+.B 100dpi
+are also possible.
+.
+The default
+.I groff
+device
+for the resolution of
+.B 75dpi
+is
+.BR X75\-12 ,
+for
+.B 100dpi
+it is
+.BR X100 .
+.
+The corresponding
+.I "groff intermediate output"
+for the actual device is generated and the result is displayed.
+.
+For a resolution of
+.BR 100dpi ,
+the default width of the geometry of the display program is chosen to
+.BR 850dpi .
+.
+.
+.TP
+.Header_CB X
+Equivalent to
+.BR --mode=x .
+.
+.
+.P
+The following modes do not use the
+.I \%groffer
+viewing features.
+.
+They are only interesting for advanced applications.
+.
+.
+.TP
+.Header_CB groff
+Generate device output with plain
+.I \%groff
+without using the special viewing features of
+.IR \%groffer .
+If no device was specified by option
+.B -T
+the
+.I \%groff
+default
+.B \%ps
+is assumed.
+.
+.
+.TP
+.Header_CB source
+Output the roff source code of the input files without further
+processing.
+.
+.
+.RE
+.
+.
+.TP
+.B --pdf
+Equivalent to
+.BR --mode=pdf .
+.
+.
+.TP
+.BI --pdf\-viewer \ prog
+Choose a viewer program for
+.IR \%pdf\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
+.TP
+.B --ps
+Equivalent to
+.BR --mode=ps .
+.
+.
+.TP
+.BI --ps\-viewer \ prog
+Choose a viewer program for
+.IR \%ps\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH .
+.
+Common Postscript viewers include
+.BR \%gv (1),
+.BR \%ghostview (1),
+and
+.BR \%gs (1),
+.
+In each case, arguments can be provided additionally.
+.
+.
+.TP
+.B --source
+Equivalent to
+.BR --mode=source .
+.
+.
+.TP
+.B --text
+Equivalent to
+.BR --mode=text .
+.
+.
+.TP
+.B --to\-stdout
+The file for the chosen mode is generated and its content is printed
+to standard output.
+.
+It will not be displayed in graphical mode.
+.
+.
+.TP
+.B --tty
+Equivalent to
+.BR --mode=tty .
+.
+.
+.TP
+.BI --tty\-viewer \ prog
+Choose a text pager for mode
+.IR tty .
+The standard pager is
+.BR less (1).
+This option is equivalent to
+.I man
+option
+.BR --pager=\fIprog\fP .
+The option argument can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
+.TP
+.B --www
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.BI --www\-viewer \ prog
+Equivalent to
+.BR --html\-viewer .
+.
+.
+.TP
+.B --X\~\fR|\fB\~--x
+Equivalent to
+.BR --mode=x .
+.
+.
+.TP
+.BI --X\-viewer\~\fR|\fB\~--x\-viewer \ prog
+Choose a viewer program for
+.IR \%x\~mode .
+Suitable viewer programs are
+.BR \%gxditview (@MAN1EXT@)
+which is the default and
+.BR \%xditview (1).
+The argument can be any executable file or a program in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
+.TP
+.B --
+Signals the end of option processing; all remaining arguments are
+interpreted as
+.I \%filespec
+parameters.
+.
+.
+.P
+Besides these,
+.B \%groffer
+accepts all short options that are valid for the
+.BR \%groff (@MAN1EXT@)
+program.
+.
+All
+.RB \%non- groffer
+options are sent unmodified via
+.B \%grog
+to
+.BR \%groff .
+.
+So postprocessors, macro packages, compatibility with
+.I classical
+.IR \%troff ,
+and much more can be manually specified.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options related to groff"
+.\" --------------------------------------------------------------------
+.
+All short options of
+.B \%groffer
+are compatible with the short options of
+.BR \%groff (@MAN1EXT@).
+.
+The following of
+.B \%groff
+options have either an additional special meaning within
+.B \%groffer
+or make sense for normal usage.
+.
+.
+.P
+Because of the special outputting behavior of the
+.B \%groff
+option
+.B -Z
+.B \%groffer
+was designed to be switched into
+.IR \%groff\~mode ;
+the
+.I \%groffer
+viewing features are disabled there.
+.
+The other
+.B \%groff
+options do not switch the mode, but allow to customize the formatting
+process.
+.
+.
+.TP
+.B --a
+This generates an ascii approximation of output in the
+.IR \%text\~modes .
+.
+That could be important when the text pager has problems with control
+sequences in
+.IR "tty mode" .
+.
+.
+.TP
+.BI --m \ file
+Add
+.I \%file
+as a
+.I \%groff
+macro file.
+.
+This is useful in case it cannot be recognized automatically.
+.
+.
+.TP
+.BI --P \ opt_or_arg
+Send the argument
+.I \%opt_or_arg
+as an option or option argument to the actual
+.B \%groff
+postprocessor.
+.
+.
+.TP
+.B --T \fIdevname\fR\~\fR|\fB\~--device \fIdevname\fR
+.
+This option determines
+.BR \%groff 's
+output device.
+.
+The most important devices are the text output devices for referring
+to the different character sets, such as
+.BR \%ascii ,
+.BR \%utf8 ,
+.BR \%latin1 ,
+and others.
+.
+Each of these arguments switches
+.B \%groffer
+into a
+.I \%text\~mode
+using this device, to
+.I \%mode\~tty
+if the actual mode is not a
+.IR \%text\~mode .
+.
+The following
+.I \%devname
+arguments are mapped to the corresponding
+.B \%groffer
+.B --mode=\fIdevname\fR
+option:
+.BR \%dvi ,
+.BR \%html ,
+and
+.BR \%ps .
+All
+.B \%X*
+arguments are mapped to
+.IR \%mode\~x .
+Each other
+.I \%devname
+argument switches to
+.I \%mode\~groff
+using this device.
+.
+.
+.TP
+.B --X
+is equivalent to
+.BR "groff \-X" .
+It displays the
+.I groff intermediate output
+with
+.BR gxditview .
+As the quality is relatively bad this option is deprecated; use
+.B --X
+instead because the
+.I \%x\~mode
+uses an
+.IR X *
+device for a better display.
+.
+.
+.TP
+.B -Z\~\fR|\fB\~--intermediate-output\~\fR|\fB\~--ditroff
+Switch into
+.I \%groff\~mode
+and format the input with the
+.I \%groff intermediate output
+without postprocessing; see
+.BR \%groff_out (@MAN5EXT@).
+This is equivalent to option
+.B --ditroff
+of
+.IR \%man ,
+which can be used as well.
+.
+.
+.P
+All other
+.B \%groff
+options are supported by
+.BR \%groffer ,
+but they are just transparently transferred to
+.B \%groff
+without any intervention.
+.
+The options that are not explicitly handled by
+.B \%groffer
+are transparently passed to
+.BR \%groff .
+.
+Therefore these transparent options are not documented here, but in
+.BR \%groff (@MAN1EXT@).
+Due to the automatism in
+.BR \%groffer ,
+none of these
+.B \%groff
+options should be needed, except for advanced usage.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options for man\~pages"
+.\" --------------------------------------------------------------------
+.
+.TP
+.B --apropos
+Start the
+.BR \%apropos (1)
+command or facility of
+.BR \%man (1)
+for searching the
+.I \%filespec
+arguments within all
+.I \%man\~page
+descriptions.
+.
+Each
+.I \%filespec
+argument is taken for search as it is;
+.I section
+specific parts are not handled, such that
+.B 7 groff
+searches for the two arguments
+.B 7
+and
+.BR groff ,
+with a large result; for the
+.I \%filespec
+.B groff.7
+nothing will be found.
+.
+The
+.I language
+locale is handled only when the called programs do support this; the
+GNU
+.B apropos
+and
+.B man \-k
+do not.
+.
+The display differs from the
+.B \%apropos
+program by the following concepts:
+.RS
+.Topic
+Construct a
+.I \%groff
+frame similar to a
+.I \%man\~page
+to the output of
+.BR \%apropos ,
+.Topic
+each
+.I \%filespec
+argument is searched on its own.
+.Topic
+The restriction by
+.B --sections
+is handled as well,
+.Topic
+wildcard characters are allowed and handled without a further option.
+.RE
+.
+.
+.TP
+.B --apropos\-data
+Show only the
+.B \%apropos
+descriptions for data documents, these are the
+.BR \%man (7)
+.IR sections\~4 ", " 5 ", and " 7 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --apropos\-devel
+Show only the
+.B \%apropos
+descriptions for development documents, these are the
+.BR man (7)
+.IR sections\~2 ", " 3 ", and " 9 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --apropos\-progs
+Show only the
+.B \%apropos
+descriptions for documents on programs, these are the
+.BR \%man (7)
+.IR sections\~1 ", " 6 ", and " 8 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --whatis
+For each
+.I \%filespec
+argument search all
+.I \%man\~pages
+and display their description \[em] or say that it is not a
+.IR \%man\~page .
+This is written from anew, so it differs from
+.IR man 's
+.B whatis
+output by the following concepts
+.RS
+.Topic
+each retrieved file name is added,
+.Topic
+local files are handled as well,
+.Topic
+the \fIlanguage\fP and \fIsystem\fP locale is supported,
+.Topic
+the display is framed by a
+.I groff
+output format similar to a
+.IR \%man\~page ,
+.Topic
+wildcard characters are allowed without a further option.
+.RE
+.
+.
+.P
+The following options were added to
+.B \%groffer
+for choosing whether the file name arguments are interpreted as names
+for local files or as a search pattern for
+.IR \%man\~pages .
+.
+The default is looking up for local files.
+.
+.
+.TP
+.B --man
+Check the non-option command line arguments
+.nh
+.RI ( filespecs )
+.hy
+first on being
+.IR \%man\~pages ,
+then whether they represent an existing file.
+.
+By default, a
+.I \%filespec
+is first tested whether it is an existing file.
+.
+.
+.TP
+.B --no-man\~\fR|\fB\~--local-file
+Do not check for
+.IR \%man\~pages .
+.
+.B --local-file
+is the corresponding
+.B man
+option.
+.
+.
+.TP
+.B --no-special
+Disable former calls of
+.BR --all ,
+.BR --apropos* ,
+and
+.BR --whatis .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Long options taken over from GNU man"
+.\" --------------------------------------------------------------------
+.
+The long options of
+.B \%groffer
+were synchronized with the long options of \f[CR]GNU\f[]
+.BR man .
+.
+All long options of \f[CR]GNU\f[]
+.B man
+are recognized, but not all of these options are important to
+.BR \%groffer ,
+so most of them are just ignored.
+.
+These ignored
+.B man
+options are
+.BR --catman ,
+.BR --troff ,
+and
+.BR --update .
+.
+.
+.P
+In the following, the
+.B man
+options that have a special meaning for
+.B \%groffer
+are documented.
+.
+.
+.P
+If your system has \f[CR]GNU\f[]
+.B man
+installed the full set of long and short options of the \f[CR]GNU\f[]
+.B man
+program can be passed via the environment variable
+.Env_var \%$MANOPT ;
+see
+.BR \%man (1).
+.
+.
+.TP
+.B --all
+In searching
+.IR \%man\~pages ,
+retrieve all suitable documents instead of only one.
+.
+.
+.TP
+.B -7\~\fR|\fB\~--ascii
+In
+.IR \%text\~modes ,
+display ASCII translation of special characters for critical environment.
+.
+This is equivalent to
+.BR "groff \%-mtty_char" ;
+see
+.BR groff_tmac (@MAN5EXT@).
+.
+.
+.TP
+.B --ditroff
+Produce
+.IR "groff intermediate output" .
+This is equivalent to
+.B \%groffer
+.BR -Z .
+.
+.
+.TP
+.BI --extension \ suffix
+Restrict
+.I \%man\~page
+search to file names that have
+.I \%suffix
+appended to their section element.
+.
+For example, in the file name
+.I \%/usr/share/man/man3/terminfo.3ncurses.gz
+the
+.I \%man\~page
+extension is
+.IR \%ncurses .
+.
+.
+.TP
+.BI --locale \ language
+.
+Set the language for
+.IR \%man\~pages .
+.
+This has the same effect, but overwrites
+.Env_var $LANG .
+.
+.
+.TP
+.B --location
+Print the location of the retrieved files to standard error.
+.
+.
+.TP
+.B --no-location
+Do not display the location of retrieved files; this resets a former
+call to
+.BR --location .
+.
+This was added by
+.BR \%groffer .
+.
+.
+.TP
+.BI --manpath \ 'dir1:dir2:\*[Ellipsis]'
+Use the specified search path for retrieving
+.I \%man\~pages
+instead of the program defaults.
+.
+If the argument is set to the empty string "" the search for
+.I \%man\~page
+is disabled.
+.
+.
+.TP
+.B --pager
+Set the pager program in
+.IR \%tty\~mode ;
+default is
+.BR \%less .
+This is equivalent to
+.BR --tty\-viewer .
+.
+.
+.TP
+.BI --sections \ sec1:sec2:\*[Ellipsis]
+Restrict searching for
+.I \%man\~pages
+to the given
+.IR sections ,
+a colon-separated list.
+.
+.
+.TP
+.BI --systems \ sys1,sys2,\*[Ellipsis]
+Search for
+.I \%man\~pages
+for the given operating systems; the argument
+.I \%systems
+is a comma-separated list.
+.
+.
+.TP
+.B --where
+Equivalent to
+.BR --location .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "X\~\%Window\~\%Toolkit Options"
+.\" --------------------------------------------------------------------
+.
+The following long options were adapted from the corresponding
+\%\f[CR]X\~Window\~Toolkit\f[] options.
+.
+.B \%groffer
+will pass them to the actual viewer program if it is an
+\%\f[CR]X\~Window\f[] program.
+.
+Otherwise these options are ignored.
+.
+.
+.P
+Unfortunately these options use the old style of a single minus for
+long options.
+.
+For
+.B \%groffer
+that was changed to the standard with using a double minus for long
+options, for example,
+.B \%groffer
+uses the option
+.B --font
+for the \%\f[CR]X\~Window\f[] option
+.BR -font .
+.
+.
+.P
+See
+.BR X (7)
+and the documentation on the \%\f[CR]X\~Window\~Toolkit\f[] options
+for more details on these options and their arguments.
+.
+.
+.TP
+.BI --background \ color
+Set the background color of the viewer window.
+.
+.
+.TP
+.BI --bd \ pixels
+This is equivalent to
+.BR --bordercolor .
+.
+.
+.TP
+.BI --bg \ color
+This is equivalent to
+.BR --background .
+.
+.
+.TP
+.BI --bw \ pixels
+This is equivalent to
+.BR --borderwidth .
+.
+.
+.TP
+.BI --bordercolor \ pixels
+Specifies the color of the border surrounding the viewer window.
+.
+.
+.TP
+.BI --borderwidth \ pixels
+Specifies the width in pixels of the border surrounding the viewer
+window.
+.
+.
+.TP
+.BI --display \ X-display
+Set the \%\f[CR]X\~Window\f[] display on which the viewer program
+shall be started, see the \%\f[CR]X\~Window\f[] documentation for the
+syntax of the argument.
+.
+.
+.TP
+.BI --foreground \ color
+Set the foreground color of the viewer window.
+.
+.
+.TP
+.BI --fg \ color
+This is equivalent to
+.BR -foreground .
+.
+.
+.TP
+.BI --fn \ font_name
+This is equivalent to
+.BR --font .
+.
+.
+.TP
+.BI --font \ font_name
+Set the font used by the viewer window.
+.
+The argument is an \%\f[CR]X\~Window\f[] font name.
+.
+.
+.TP
+.BI --ft \ font_name
+This is equivalent to
+.BR --font .
+.
+.
+.TP
+.BI --geometry \ size_pos
+Set the geometry of the display window, that means its size and its
+starting position.
+.
+See
+.BR \%X (7)
+for the syntax of the argument.
+.
+.
+.TP
+.BI --resolution \ value
+Set \%\f[CR]X\~Window\f[] resolution in dpi (dots per inch) in some
+viewer programs.
+.
+The only supported dpi values are
+.B 75
+and
+.BR 100 .
+.
+Actually, the default resolution for
+.B \%groffer
+is set to
+.BR 75dpi .
+The resolution also sets the default device in
+.IR "mode x" .
+.
+.
+.TP
+.B --rv
+Reverse foreground and background color of the viewer window.
+.
+.
+.TP
+.BI --title "\ 'some text'"
+Set the title for the viewer window.
+.
+.
+.TP
+.BI --xrm \ 'resource'
+Set \f[CR]\%X\~Window\f[] resource.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options for Development"
+.\" --------------------------------------------------------------------
+.
+.TP
+.B --debug
+Enable all debugging options
+.BR --debug\-\fItype\fP .
+.
+The temporary files are kept and not deleted, the
+.B grog
+output is printed, the name of the temporary directory is printed, the
+displayed file names are printed, and the parameters are printed.
+.
+.
+.TP
+.B --debug\-filenames
+Print the names of the files and
+.I \%man\~pages
+that are displayed by
+.BR \&groffer .
+.
+.
+.TP
+.B --debug\-grog
+Print the output of all
+.B grog
+commands.
+.
+.
+.TP
+.B --debug\-keep
+Enable two debugging informations.
+.
+Print the name of the temporary directory and keep the temporary
+files, do not delete them during the run of
+.BR \%groffer .
+.
+.
+.TP
+.B --debug\-params
+Print the parameters, as obtained from the configuration files, from
+.Env_var \%GROFFER_OPT ,
+and the command line arguments.
+.
+.
+.TP
+.B --debug\-tmpdir
+Print the name of the temporary directory.
+.
+.
+.TP
+.B --do-nothing
+This is like
+.BR --version ,
+but without the output; no viewer is started.
+.
+This makes only sense in development.
+.
+.
+.TP
+.B --print=\fItext\fR
+Just print the argument to standard error.
+.
+This is good for parameter check.
+.
+.
+.TP 
+.B -V
+This is an advanced option for debugging only.
+.
+Instead of displaying the formatted input, a lot of
+.I \%groffer
+specific information is printed to standard output:
+.
+.RS
+.Topic
+the output file name in the temporary directory,
+.
+.Topic
+the display mode of the actual
+.B \%groffer
+run,
+.
+.Topic
+the display program for viewing the output with its arguments,
+.
+.Topic
+the active parameters from the config files, the arguments in
+.Env_var \%$GROFFER_OPT ,
+and the arguments of the command line,
+.
+.Topic
+the pipeline that would be run by the
+.B \%groff
+program, but without executing it.
+.RE
+.
+.
+.P
+Other useful debugging options are the
+.B \%groff
+option
+.B -Z
+and
+.BR --mode=groff .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Filespec Arguments"
+.\" --------------------------------------------------------------------
+.
+A
+.I \%filespec
+parameter is an argument that is not an option or option argument.
+.
+In
+.BR \%groffer ,
+.I \%filespec
+parameters are a file name or a template for searching
+.IR \%man\~pages .
+.
+These input sources are collected and composed into a single output
+file such as
+.B \%groff
+does.
+.
+.
+.P
+The strange \%\f[CR]POSIX\f[] behavior to regard all arguments behind
+the first non-option argument as
+.I \%filespec
+arguments is ignored.
+.
+The \f[CR]GNU\f[] behavior to recognize options even when mixed with
+.I \%filespec
+arguments is used throughout.
+.
+But, as usual, the double minus argument
+.B --
+ends the option handling and interprets all following arguments as
+.I \%filespec
+arguments; so the \%\f[CR]POSIX\f[] behavior can be easily adopted.
+.
+.
+.P
+The options
+.B --apropos*
+have a special handling of
+.I filespec
+arguments.
+.
+Each argument is taken as a search scheme of its own.
+.
+Also a regexp (regular expression) can be used in the filespec.
+.
+For example,
+.B groffer --apropos '^gro.f$'
+searches
+.B groff
+in the
+.I man\~page
+name, while
+.B groffer --apropos groff
+searches
+.B groff
+somewhere in the name or description of the
+.IR man\~pages .
+.
+.
+.P
+All other parts of
+.IR groffer ,
+such as the normal display or the output with
+.B --whatis
+have a different scheme for
+.IR filespecs .
+No regular expressions are used for the arguments.
+.
+The
+.I filespec
+arguments are handled by the following scheme.
+.
+.
+.P
+It is necessary to know that on each system the
+.I \%man\~pages
+are sorted according to their content into several sections.
+.
+The
+.I classical man sections
+have a single-character name, either a digit from
+.B 1
+to
+.B 9
+or one of the characters
+.B n
+or
+.BR o .
+.
+.
+.P
+This can optionally be followed by a string, the so-called
+.IR extension .
+The
+.I extension
+allows to store several
+.I man\~pages
+with the same name in the same
+.IR section .
+But the
+.I extension
+is only rarely used, usually it is omitted.
+.
+Then the
+.I extensions
+are searched automatically by alphabet.
+.
+.
+.P
+In the following, we use the name
+.I section_extension
+for a word that consists of a single character
+.I section
+name or a
+.I section
+character that is followed by an
+.IR extension .
+.
+Each
+.I \%filespec
+parameter can have one of the following forms in decreasing sequence.
+.
+.
+.Topic
+No
+.I \%filespec
+parameters means that
+.B \%groffer
+waits for standard input.
+.
+The minus option
+.B -
+always stands for standard input; it can occur several times.
+.
+If you want to look up a
+.I \%man\~page
+called
+.B -
+use the argument
+.BR man:\- .
+.
+.
+.Topic
+Next a
+.I \%filespec
+is tested whether it is the path name of an existing file.
+.
+Otherwise it is assumed to be a searching pattern for a
+.IR \%man\~page .
+.
+.
+.Topic
+.BI \%man: name ( section_extension ) ,
+.BI \%man: name . section_extension,
+.IB \%name ( section_extension ) ,
+or
+.IB \%name . section_extension
+search the \%man\~page
+.I \%name
+in \%man\~section and possibly extension of
+.IR \%section_extension .
+.
+.
+.Topic
+Now
+.BI \%man: name
+searches for a
+.I \%man\~page
+in the lowest
+.I \%man\~section
+that has a document called
+.IR \%name .
+.
+.
+.Topic
+.I \%section_extension\~name
+is a pattern of 2 arguments that originates from a strange argument
+parsing of the
+.B man
+program.
+.
+Again, this searches the man page
+.I name
+with
+.IR \%section_extension ,
+a combination of a
+.I section
+character optionally followed by an
+.IR extension .
+.
+.
+.Topic
+We are left with the argument
+.I \%name
+which is not an existing file.
+.
+So this searches for the
+.I \%man\~page
+called
+.I \%name
+in the lowest
+.I \%man\~section
+that has a document for this name.
+.
+.
+.P
+Several file name arguments can be supplied.
+.
+They are mixed by
+.B \%groff
+into a single document.
+.
+Note that the set of option arguments must fit to all of these file
+arguments.
+.
+So they should have at least the same style of the
+.I \%groff
+language.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OUTPUT MODES"
+.\" --------------------------------------------------------------------
+.
+By default, the
+.B \%groffer
+program collects all input into a single file, formats it with the
+.B \%groff
+program for a certain device, and then chooses a suitable viewer
+program.
+.
+The device and viewer process in
+.B \%groffer
+is called a
+.IR \%mode .
+.
+The mode and viewer of a running
+.B \%groffer
+program is selected automatically, but the user can also choose it
+with options.
+.
+.
+The modes are selected by option the arguments of
+.BR --mode=\fIanymode .
+Additionally, each of this argument can be specified as an option of
+its own, such as
+.BR anymode .
+Most of these modes have a viewer program, which can be chosen by an
+option that is constructed like
+.BR --\fIanymode\fR\-viewer .
+.
+.
+.P
+Several different modes are offered, graphical modes for
+\f[CR]\%X\~Window\f[],
+.IR \%text\~modes ,
+and some direct
+.I \%groff\~modes
+for debugging and development.
+.
+.
+.P
+By default,
+.B \%groffer
+first tries whether
+.I \%x\~mode
+is possible, then
+.IR \%ps\~mode ,
+and finally
+.IR \%tty\~mode .
+.
+This mode testing sequence for
+.I \%auto\~mode
+can be changed by specifying a comma separated list of modes with the
+option
+.B --default\-modes.
+.
+.
+.P
+The searching for
+.I \%man\~pages
+and the decompression of the input are active in every mode.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Graphical Display Modes"
+.\" --------------------------------------------------------------------
+.
+The graphical display modes work mostly in the \%\f[CR]X\~Window\f[]
+environment (or similar implementations within other windowing
+environments).
+.
+The environment variable
+.Env_var \%$DISPLAY
+and the option
+.B --display
+are used for specifying the \%\f[CR]X\~Window\f[] display to be used.
+.
+If this environment variable is empty
+.B \%groffer
+assumes that no \%\f[CR]X\~Window\f[] is running and changes to a
+.IR \%text\~mode .
+.
+You can change this automatic behavior by the option
+.BR --default\-modes .
+.
+.
+.P
+Known viewers for the graphical display modes and their standard
+\%\f[CR]X\~Window\f[] viewer programs are
+.
+.Topic
+in a PDF viewer
+.nh
+.RI ( \%pdf\~mode )
+.hy
+.
+.Topic
+in a web browser
+.nh
+.RI ( html
+or
+.IR \%www\~mode )
+.hy
+.RE
+.
+.Topic
+in a Postscript viewer
+.nh
+.RI ( \%ps\~mode )
+.hy
+.
+.Topic
+\%\f[CR]X\~Window\f[]
+.I roff
+viewers such as
+.BR \%gxditview (@MAN1EXT@)
+or
+.BR \%xditview (1)
+(in
+.IR \%x\~mode )
+.
+.Topic
+in a dvi viewer program
+.nh
+.RI ( \%dvi\~mode )
+.hy
+.
+.
+.P
+The
+.I \%pdf\~mode
+has a major advantage \[em] it is the only graphical display mode that
+allows to search for text within the viewer; this can be a really
+important feature.
+.
+Unfortunately, it takes some time to transform the input into the PDF
+format, so it was not chosen as the major mode.
+.
+.
+.P
+These graphical viewers can be customized by options of the
+\%\f[CR]X\~Window\~Toolkit\f[].
+.
+But the
+.B \%groffer
+options use a leading double minus instead of the single minus used by
+the \%\f[CR]X\~Window\~Toolkit\f[].
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Text modes"
+.\" --------------------------------------------------------------------
+.
+There are two modes for text output,
+.I \%mode\~text
+for plain output without a pager and
+.I \%mode\~tty
+for a text output on a text terminal using some pager program.
+.
+.
+.P
+If the variable
+.Env_var \%$DISPLAY
+is not set or empty,
+.B \%groffer
+assumes that it should use
+.IR \%tty\~\%mode .
+.
+.
+.P
+In the actual implementation, the
+.I groff
+output device
+.I \%latin1
+is chosen for
+.IR \%text\~modes .
+.
+This can be changed by specifying option
+.B -T
+or
+.BR \%--device .
+.
+.
+.P
+The pager to be used can be specified by one of the options
+.B --pager
+and
+.BR --tty\-viewer ,
+or by the environment variable
+.Env_var \%$PAGER .
+If all of this is not used the
+.BR \%less (1)
+program with the option
+.B -r
+for correctly displaying control sequences is used as the default
+pager.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Special Modes for Debugging and Development"
+.\" --------------------------------------------------------------------
+.
+These modes use the
+.I \%groffer
+file determination and decompression.
+.
+This is combined into a single input file that is fed directly into
+.B \%groff
+with different strategy without the
+.I \%groffer
+viewing facilities.
+.
+These modes are regarded as advanced, they are useful for debugging
+and development purposes.
+.
+.
+.P
+The
+.I \%source\~mode
+with option
+.B --source
+just displays the decompressed input.
+.
+.
+.P
+Otion
+.B --to\-stdout
+does not display in a graphical mode.
+.
+It just generates the file for the chosen mode and then prints its
+content to standard output.
+.
+.
+.P
+The
+.I \%groff\~mode
+passes the input to
+.B \%groff
+using only some suitable options provided to
+.BR \%groffer .
+.
+This enables the user to save the generated output into a file or pipe
+it into another program.
+.
+.
+.P
+In
+.IR \%groff\~\%mode ,
+the option
+.B -Z
+disables post-processing, thus producing the
+.nh
+.I groff intermediate
+.IR output .
+.hy
+.
+In this mode, the input is formatted, but not postprocessed; see
+.BR \%groff_out (@MAN5EXT@)
+for details.
+.
+.
+.P
+All
+.B \%groff
+short options are supported by
+.BR \%groffer .
+.
+.
+.\" --------------------------------------------------------------------
+.SH "MAN PAGE SEARCHING"
+.\" --------------------------------------------------------------------
+.
+The default behavior of
+.B \%groffer
+is to first test whether a file parameter represents a local file; if
+it is not an existing file name, it is assumed to represent the name
+of a
+.IR \%man\~page .
+The following options can be used to determine whether the arguments
+should be handled as file name or
+.I \%man\~page
+arguments.
+.
+.TP
+.B --man
+forces to interpret all file parameters as
+.I \%filespecs
+for searching
+.IR \%man\~pages .
+.
+.TP
+.B --no\-man
+.TQ
+.B --local\-file
+disable the
+.I man
+searching; so only local files are displayed.
+.
+.
+.P
+If neither a local file nor a
+.I \%man\~page
+was retrieved for some file parameter a warning is issued on standard
+error, but processing is continued.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Search Algorithm"
+.\" --------------------------------------------------------------------
+.
+Let us now assume that a
+.I \%man\~page
+should be searched.
+.
+The
+.B \%groffer
+program provides a search facility for
+.IR \%man\~pages .
+.
+All long options, all environment variables, and most of the
+functionality of the \f[CR]GNU\fP
+.BR \%man (1)
+program were implemented.
+.
+The search algorithm shall determine which file is displayed for a given
+.IR \%man\~page .
+The process can be modified by options and environment variables.
+.
+.
+.P
+The only
+.I man
+action that is omitted in
+.B \%groffer
+are the preformatted
+.IR \%man\~pages ,
+also called
+.IR cat\~pages .
+.
+With the excellent performance of the actual computers, the
+preformatted
+.I \%man\~pages
+aren't necessary any longer.
+.
+Additionally,
+.B \%groffer
+is a
+.I roff
+program; it wants to read
+.I roff
+source files and format them itself.
+.
+.
+.P
+The algorithm for retrieving the file for a
+.I \%man\~page
+needs first a set of directories.
+.
+This set starts with the so-called
+.I man\~path
+that is modified later on by adding names of
+.I operating system
+and
+.IR language .
+.
+This arising set is used for adding the section directories which
+contain the
+.I \%man\~page
+files.
+.
+.
+.P
+The
+.I man\~path
+is a list of directories that are separated by colon.
+.
+It is generated by the following methods.
+.
+.Topic
+The environment variable
+.Env_var \%$MANPATH
+can be set.
+.
+.Topic
+It can be read from the arguments of the environment variable
+.Env_var \%$MANOPT .
+.
+.Topic
+The
+.I man\~path
+can be manually specified by using the option
+.BR --manpath .
+An empty argument disables the
+.I \%man\~page
+searching.
+.
+.Topic
+When no
+.I man\~path
+was set the
+.BR \%manpath (1)
+program is tried to determine one.
+.
+.Topic
+If this does not work a reasonable default path from
+.Env_var $PATH
+is determined.
+.
+.
+.P
+We now have a starting set of directories.
+.
+The first way to change this set is by adding names of
+.I operating
+.IR systems .
+.
+This assumes that
+.I \%man\~pages
+for several
+.I operating systems
+are installed.
+.
+This is not always true.
+.
+The names of such
+.I operating systems
+can be provided by 3 methods.
+.
+.Topic
+The environment variable
+.Env_var \%$SYSTEM
+has the lowest precedence.
+.
+.Topic
+This can be overridden by an option in
+.Env_var \%$MANOPT .
+.
+.Topic
+This again is overridden by the command line option
+.BR --systems .
+.
+.
+.P
+Several names of
+.I operating systems
+can be given by appending their names, separated by a comma.
+.
+.
+.P
+The
+.I man\~path
+is changed by appending each
+.I system
+name as subdirectory at the end of each directory of the set.
+.
+No directory of the
+.I man\~path
+set is kept.
+.
+But if no
+.I system
+name is specified the
+.I man\~path
+is left unchanged.
+.
+.
+.P
+After this, the actual set of directories can be changed by
+.I language
+information.
+.
+This assumes that there exist
+.I man\~pages
+in different languages.
+.
+The wanted
+.I language
+can be chosen by several methods.
+.
+.Topic
+Environment variable
+.Env_var $LANG .
+.
+.Topic
+This is overridden by
+.Env_var \%$LC_MESSAGES .
+.
+.Topic
+This is overridden by
+.Env_var $LC_ALL .
+.
+.Topic
+This can be overridden by providing an option in
+.Env_var \%$MANOPT .
+.
+.Topic
+All these environment variables are overridden by the command line
+option
+.BR --locale .
+.
+.
+.P
+The
+.I default language
+can be specified by specifying one of the pseudo-language parameters
+\f[CR]C\fP or \f[CR]\%POSIX\fP.
+.
+This is like deleting a formerly given
+.I language
+information.
+.
+The
+.I \%man\~pages
+in the
+.I default language
+are usually in English.
+.
+.
+.P
+Of course, the
+.I language
+name is determined by
+.BR man .
+In \f[CR]GNU\fP
+.BR man ,
+it is specified in the \%\f[CR]POSIX\~1003.1\fP based format:
+.P
+.nh
+\f[I]<language>\f[][\f[CB]_\f[]\f[I]<territory>\f[][\f[CB].\fP\
+\f[I]<character-set>\f[][\f[CB],\fP\f[I]<version>\fP]]],
+.hy
+.P
+but the two-letter code in
+.nh
+.I <language>
+.hy
+is sufficient for most purposes.
+.
+If for a complicated
+.I language
+formulation no
+.I \%man\~pages
+are found
+.B \%groffer
+searches the country part consisting of these first two characters as
+well.
+.
+.
+.P
+The actual directory set is copied thrice.
+.
+The
+.I language
+name is appended as subdirectory to each directory in the first copy
+of the actual directory set (this is only done when a language
+information is given).
+.
+Then the 2-letter abbreviation of the
+.I language
+name is appended as subdirectories to the second copy of the directory
+set (this is only done when the given language name has more than 2
+letters).
+.
+The third copy of the directory set is kept unchanged (if no
+.I language
+information is given this is the kept directory set).
+.
+These maximally 3 copies are appended to get the new directory set.
+.
+.
+.P
+We now have a complete set of directories to work with.
+.
+In each of these directories, the
+.I man
+files are separated in
+.IR sections .
+.
+The name of a
+.I section
+is represented by a single character, a digit between
+.I 1
+and
+.IR 9 ,
+or the character
+.I o
+or
+.IR n ,
+in this order.
+.
+.
+.P
+For each available
+.IR section ,
+a subdirectory
+.File_name man \fI<section>\fP
+exists containing all
+.I man
+files for this
+.IR section ,
+where
+.I <section>
+is a single character as described before.
+.
+Each
+.I man
+file in a
+.I section
+directory has the form
+.IR \%\f[CB]man\fP<section>\f[CB]/\fP<name>\f[CB].\fP<section>\
+[<extension>][\f[CB].\fP<compression>] ,
+where
+.I \%<extension>
+and
+.I \%<compression>
+are optional.
+.
+.I \%<name>
+is the name of the
+.I \%man\~page
+that is also specified as filespec argument on the command line.
+.
+.
+.P
+The
+.I extension
+is an addition to the section.
+.
+This postfix acts like a subsection.
+.
+An
+.I extension
+occurs only in the file name, not in name of the
+.I section
+subdirectory.
+.
+It can be specified on the command line.
+.
+.
+.P
+On the other hand, the
+.I compression
+is just an information on how the file is compressed.
+.
+This is not important for the user, such that it cannot be specified
+on the command line.
+.
+.
+.P
+There are 4 methods to specify a
+.I section
+on the command line:
+.
+.Topic
+Environment variable
+.Env_var \%$MANSECT
+.
+.Topic
+Command line option
+.B --sections
+.
+.Topic
+Appendix to the
+.I name
+argument in the form
+.I <name>.<section>
+.
+.Topic
+Preargument before the
+.I name
+argument in the form
+.I <section> <name>
+.
+.
+.P
+It is also possible to specify several
+.I sections
+by appending the single characters separated by colons.
+.
+One can imagine that this means to restrict the
+.I \%man\~page
+search to only some
+.IR sections .
+.
+The multiple
+.I sections
+are only possible for
+.Env_var \%$MANSECT
+and
+.BR --sections .
+.
+.
+.P
+If no
+.I section
+is specified all
+.I sections
+are searched one after the other in the given order, starting with
+.IR section\~1 ,
+until a suitable file is found.
+.
+.
+.P
+There are 4 methods to specify an
+.I extension
+on the command line.
+.
+But it is not necessary to provide the whole extension name, some
+abbreviation is good enough in most cases.
+.
+.Topic
+Environment variable
+.Env_var \%$EXTENSION
+.
+.Topic
+Command line option
+.B --extension
+.
+.Topic
+Appendix to the
+.I <name>.<section>
+argument in the form
+.I <name>.<section><extension>
+.
+.Topic
+Preargument before the
+.I name
+argument in the form
+.I <section><extension> <name>
+.
+.
+.P
+For further details on
+.I \%man\~page
+searching, see
+.BR \%man (1).
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Examples of man files"
+.\" --------------------------------------------------------------------
+.
+.TP
+.File_name /usr/share/man/man1/groff.1
+This is an uncompressed file for the
+.I \%man\~page
+\f[CR]groff\fP in
+.IR section\~1 .
+.
+It can be called by
+.EX
+\fIsh#\fR groffer\~groff
+.EE
+No
+.I section
+is specified here, so all
+.I sections
+should be searched, but as
+.I section\~1
+is searched first this file will be found first.
+.
+The file name is composed of the following components.
+.File_name /usr/share/man
+must be part of the
+.IR \%man\~path ;
+the subdirectory
+.File_name man1/
+and the part
+.File_name .1
+stand for the
+.IR section ;
+.File_name groff
+is the name of the
+.IR \%man\~page .
+.
+.
+.TP
+.File_name /usr/local/share/man/man7/groff.7.gz
+The file name is composed of the following components.
+.File_name /usr/local/share/man
+must be part of the
+.IR \%man\~path ;
+the subdirectory
+.File_name man7/
+and the part
+.File_name .7
+stand for the
+.IR section ;
+.File_name groff
+is the name of the
+.IR \%man\~page ;
+the final part
+.File_name .gz
+stands for a compression with
+.BR gzip (1).
+As the
+.I section
+is not the first one it must be specified as well.
+.
+This can be done by one of the following commands.
+.EX
+\fIsh#\fR\~groffer\~groff.7
+\fIsh#\fR\~groffer\~7\~groff
+\fIsh#\fR\~groffer\~\-\-sections=7\~groff
+.EE
+.
+.TP
+.File_name /usr/local/man/man1/ctags.1emacs21.bz2
+Here
+.File_name /usr/local/man
+must be in
+.IR \%man\~path ;
+the subdirectory
+.File_name man1/
+and the file name part
+.File_name .1
+stand for
+.IR section\~1 ;
+the name of the
+.I \%man\~page
+is
+.File_name ctags ;
+the section has an extension
+.File_name emacs21 ;
+and the file is compressed as
+.File_name .bz2
+with
+.BR bzip2 (1).
+The file can be viewed with one of the following commands
+.EX
+\fIsh#\fR\~groffer\~ctags.1e
+\fIsh#\fR\~groffer\~1e\~ctags
+\fIsh#\fR\~groffer\~\-\-extension=e\~\-\-sections=1\~ctags
+.EE
+where \f[CR]e\fP works as an abbreviation for the extension
+\f[CR]emacs21\fP.
+.
+.
+.TP
+.File_name /usr/man/linux/de/man7/man.7.Z
+The directory
+.File_name /usr/man
+is now part of the
+.IR \%man\~path ;
+then there is a subdirectory for an
+.I operating system
+name
+.File_name linux/ ;
+next comes  a subdirectory
+.File_name de/
+for the German
+.IR language ;
+the
+.I section
+names
+.File_name man7
+and
+.File_name .7
+are known so far;
+.File_name man
+is the name of the
+.IR \%man\~page ;
+and
+.File_name .Z
+signifies the compression that can be handled by
+.BR gzip (1).
+We want now show how to provide several values for some options.
+.
+That is possible for
+.I sections
+and
+.I operating system
+names.
+.
+So we use as
+.I sections\~5
+and
+.I 7
+and as
+.I system
+names
+.I linux
+and
+.IR aix .
+The command is then
+.sp
+.EX
+\fIsh#\fR groffer\~\-\-locale=de\~\-\-sections=5:7\~\-\-systems=linux,aix\~man
+\fIsh#\fR LANG=de\~MANSECT=5:7\~SYSTEM=linux,aix\~groffer\~man
+.EE
+.
+.
+.\" --------------------------------------------------------------------
+.SH DECOMPRESSION
+.\" --------------------------------------------------------------------
+.
+The program has a decompression facility.
+.
+If standard input or a file that was retrieved from the command line
+parameters is compressed with a format that is supported by either
+.BR \%gzip (1)
+or
+.BR \%bzip2 (1)
+it is decompressed on-the-fly.
+.
+This includes the \f[CR]GNU\fP
+.BR \%.gz ,
+.BR \%.bz2 ,
+and the traditional
+.B \%.Z
+compression.
+.
+The program displays the concatenation of all decompressed input in
+the sequence that was specified on the command line.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "ENVIRONMENT"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program supports many system variables, most of them by courtesy of
+other programs.
+.
+All environment variables of
+.BR \%groff (@MAN1EXT@)
+and \f[CR]GNU\fP
+.BR \%man (1)
+and some standard system variables are honored.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Native groffer Variables"
+.\" --------------------------------------------------------------------
+.
+.TP
+.Env_var \%$GROFFER_OPT
+Store options for a run of
+.BR \%groffer .
+.
+The options specified in this variable are overridden by the options
+given on the command line.
+.
+The content of this variable is run through the shell builtin `eval';
+so arguments containing white-space or special shell characters should
+be quoted.
+.
+Do not forget to export this variable, otherwise it does not exist
+during the run of
+.BR groffer .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "System Variables"
+.\" --------------------------------------------------------------------
+.
+The following variables have a special meaning for
+.BR \%groffer .
+.
+.
+.TP
+.Env_var \%$DISPLAY
+If this variable is set this indicates that the \%\f[CR]X\~Window\fP
+system is running.
+.
+Testing this variable decides on whether graphical or text output is
+generated.
+.
+This variable should not be changed by the user carelessly, but it can
+be used to start the graphical
+.B \%groffer
+on a remote \%\f[CR]X\~Window\fP terminal.
+.
+For example, depending on your system,
+.B \%groffer
+can be started on the second monitor by the command
+.sp
+.EX
+\fIsh#\fR DISPLAY=:0.1\~groffer\~what.ever &
+.EE
+.
+.
+.TP
+.Env_var \%$LC_ALL
+.TQ
+.Env_var \%$LC_MESSAGES
+.TQ
+.Env_var $LANG
+If one of these variables is set (in the above sequence), its content
+is interpreted as the locale, the language to be used, especially when
+retrieving
+.IR \%man\~pages .
+.
+A locale name is typically of the form
+.nh
+.IR language [\c
+.B _\c
+.IR territory [\c
+.B .\c
+.IR codeset [\c
+.B @\c
+.IR modifier ]]],
+.hy
+where
+.I \%language
+is an ISO 639 language code,
+.I \%territory
+is an ISO 3166 country code, and
+.I \%codeset
+is a character set or encoding identifier like ISO-8859-1 or UTF-8;
+see
+.BR \%setlocale (3).
+.
+The locale values \f[CR]C\fP and \%\f[CR]POSIX\fP
+stand for the default, i.e. the
+.I \%man\~page
+directories without a language prefix.
+.
+This is the same behavior as when all 3\~variables are unset.
+.
+.
+.TP
+.Env_var \%$PAGER
+This variable can be used to set the pager for the tty output.
+.
+For example, to disable the use of a pager completely set this
+variable to the
+.BR \%cat (1)
+program
+.sp
+.EX
+\fIsh#\fR PAGER=cat\~groffer\~anything
+.EE
+.sp
+.
+.TP
+.Env_var $PATH
+All programs within the
+.B \%groffer
+script are called without a fixed path.
+.
+Thus this environment variable determines the set of programs used
+within the run of
+.BR \%groffer .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Groff Variables"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program internally calls
+.BR \%groff ,
+so all environment variables documented in
+.BR \%groff (@MAN1EXT@)
+are internally used within
+.B \%groffer
+as well.
+.
+The following variable has a direct meaning for the
+.B \%groffer
+program.
+.
+.TP
+.Env_var \%$GROFF_TMPDIR
+If the value of this variable is an existing, writable directory,
+.B \%groffer
+uses it for storing its temporary files, just as
+.B groff
+does.
+.
+See the
+.BR \%groff (@MAN1EXT@)
+man page for more details on the location of temporary files.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Man Variables"
+.\" --------------------------------------------------------------------
+.
+Parts of the functionality of the
+.B man
+program were implemented in
+.BR \%groffer ;
+support for all environment variables documented in
+.BR \%man (1)
+was added to
+.BR \%groffer ,
+but the meaning was slightly modified due to the different approach in
+.BR \%groffer ;
+but the user interface is the same.
+.
+The
+.B man
+environment variables can be overwritten by options provided with
+.Env_var \%$MANOPT ,
+which in turn is overwritten by the command line.
+.
+.
+.TP
+.Env_var \%$EXTENSION
+Restrict the search for
+.I \%man\~pages
+to files having this extension.
+.
+This is overridden by option
+.BR --extension ;
+see there for details.
+.
+.
+.TP
+.Env_var \%$MANOPT
+This variable contains options as a preset for
+.BR \%man (1).
+As not all of these are relevant for
+.B \%groffer
+only the essential parts of its value are extracted.
+.
+The options specified in this variable overwrite the values of the
+other environment variables that are specific to
+.IR man .
+.
+All options specified in this variable are overridden by the options
+given on the command line.
+.
+.
+.TP
+.Env_var \%$MANPATH
+If set, this variable contains the directories in which the
+.I \%man\~page
+trees are stored.
+.
+This is overridden by option
+.BR \%--manpath .
+.
+.
+.TP
+.Env_var \%$MANSECT
+If this is a colon separated list of section names, the search for
+.I \%man\~pages
+is restricted to those manual sections in that order.
+.
+This is overridden by option
+.BR --sections .
+.
+.
+.TP
+.Env_var \%$SYSTEM
+If this is set to a comma separated list of names these are interpreted
+as
+.I \%man\~page
+trees for different operating systems.
+.
+This variable can be overwritten by option
+.BR --systems ;
+see there for details.
+.
+.
+.P
+The environment variable
+.Env_var \%$MANROFFSEQ
+is ignored by
+.B \%groffer
+because the necessary preprocessors are determined automatically.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "CONFIGURATION FILES"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program can be preconfigured by two configuration files.
+.
+.
+.TP
+.File_name \%/etc/groff/groffer.conf
+System-wide configuration file for
+.BR \%groffer .
+.
+.
+.TP
+.File_name \%$HOME/.groff/groffer.conf
+User-specific configuration file for
+.BR \%groffer ,
+where
+.Env_var \%$HOME
+denotes the user's home directory.
+.
+This file is called after the system-wide configuration file to enable
+overriding by the user.
+.
+.
+.P
+Both files are handled for the configuration, but the configuration
+file in
+.File_name /etc
+comes first; it is overwritten by the configuration file in the home
+directory; both configuration files are overwritten by the environment
+variable
+.Env_var \%$GROFFER_OPT ;
+everything is overwritten by the command line arguments.
+.
+.
+.P
+The configuration files contain options that should be called as
+default for every
+.B \%groffer
+run.
+.
+These options are written in lines such that each contains either a
+long option, a short option, or a short option cluster; each with or
+without an argument.
+.
+So each line with configuration information starts with a minus
+character
+.RB ` \- ';
+a line with a long option starts with two minus characters
+.RB ` \-\- ',
+a line with a short option or short option cluster starts with a
+single minus
+.RB ` \- '.
+.
+.
+.P
+The option names in the configuration files may not be abbreviated,
+they must be exact.
+.
+.
+.P
+The argument for a long option can be separated from the option name
+either by an equal sign
+.RB ` = '
+or by whitespace, i.e. one or several space or tab characters.
+.
+An argument for a short option or short option cluster can be directly
+appended to the option name or separated by whitespace.
+.
+The end of an argument is the end of the line.
+.
+It is not allowed to use a shell environment variable in an option
+name or argument.
+.
+.
+.P
+It is not necessary to use quotes in an option or argument, except for
+empty arguments.
+.
+An empty argument can be provided by appending a pair of quotes to the
+separating equal sign or whitespace; with a short option, the
+separator can be omitted as well.
+.
+For a long option with a separating equal sign
+.RB ` = ',
+the pair of quotes can be omitted, thus ending the line with the
+separating equal sign.
+.
+All other quote characters are cancelled internally.
+.
+.
+.P
+In the configuration files, arbitrary whitespace is allowed at the
+beginning of each line, it is just ignored.
+.
+Each whitespace within a line is replaced by a single space character
+` ' internally.
+.
+.
+.P
+All lines of the configuration lines that do not start
+with a minus character are ignored, such that comments starting with
+.RB ` # '
+are possible.
+.
+So there are no shell commands in the configuration files.
+.
+.
+.P
+As an example, consider the following configuration file that can be
+used either in
+.File_name \%/etc/groff/groffer.conf
+or
+.File_name \%~/.groff/groffer.conf .
+.
+.
+.P
+.ft CR
+.nh
+.nf
+# groffer configuration file
+#
+# groffer options that are used in each call of groffer
+\-\-foreground=DarkBlue
+\-\-resolution=100
+\-\-x\-viewer=gxditview \-geometry 900x1200
+\-\-pdf\-viewer xpdf \-Z 150
+.fi
+.hy
+.ft
+.
+.
+.P
+The lines starting with
+.B #
+are just ignored, so they act as command lines.
+.
+This configuration sets four
+.B \%groffer
+options (the lines starting with
+.RB ` \- ').
+This has the following effects:
+.
+.
+.Topic
+Use a text color of
+.B \%DarkBlue
+in all viewers that support this, such as
+.BR \%gxditview .
+.
+.
+.Topic
+Use a resolution of
+.B 100dpi
+in all viewers that support this, such as
+.BR \%gxditview .
+.
+By this, the default device in
+.I x mode
+is set to
+.BR X100 .
+.
+.
+.Topic
+Force
+.BR \%gxditview (@MAN1EXT@)
+as the
+.I \%x-mode
+viewer using the geometry option for setting the width to
+.B 900px
+and the height to
+.BR 1200px .
+This geometry is suitable for a resolution of
+.BR 100dpi .
+.
+.
+.Topic
+Use
+.BR \%xpdf (1)
+as the
+.I \%pdf-mode
+viewer with the argument
+.B \-Z
+.BR 150 .
+.
+.
+.\" --------------------------------------------------------------------
+.SH "EXAMPLES"
+.\" --------------------------------------------------------------------
+.
+The usage of
+.B \%groffer
+is very easy.
+.
+Usually, it is just called with a file name or
+.IR \%man\~page .
+.
+The following examples, however, show that
+.B \%groffer
+has much more fancy capabilities.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~/usr/local/share/doc/groff/meintro.ms.gz
+.EE
+.sp
+Decompress, format and display the compressed file
+.File_name meintro.ms.gz
+in the directory
+.File_name /usr/local/share/doc/groff ,
+using the standard viewer
+.B \%gxditview
+as graphical viewer when in \%\f[CR]X\~Window\fP, or the
+.BR \%less (1)
+pager program when not in \%\f[CR]X\~Window\fP.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff
+.EE
+.sp
+If the file
+.File_name \%./groff
+exists use it as input.
+.
+Otherwise interpret the argument as a search for the
+.I \%man\~page
+named
+.B \%groff
+in the smallest possible
+.IR \%man\~section ,
+being section 1 in this case.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~man:groff
+.EE
+.sp
+search for the
+.I \%man\~page
+of
+.B \%groff
+even when the file
+.File_name ./groff
+exists.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff.7
+\fIsh#\fR\~groffer\~7\~groff
+.EE
+.sp
+search the
+.I \%man\~page
+of
+.B \%groff
+in
+.I \%man\~section
+.BR 7 .
+This section search works only for a digit or a single character from
+a small set.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~fb.modes
+.EE
+.sp
+If the file
+.File_name ./fb.modes
+does not exist interpret this as a search for the
+.I \%man\~page
+of
+.BR fb.modes .
+As the extension
+.I \%modes
+is not a single character in classical section style the argument is
+not split to a search for
+.BR fb .
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff\~\[cq]troff(1)\[cq]\~man:roff
+.EE
+.sp
+The arguments that are not existing files are looked-up as the
+following
+.IR \%man\~pages :
+.B \%groff
+(automatic search, should be found in \fIman\fP\~section\~1),
+.B \%troff
+(in section\~1),
+and
+.B \%roff
+(in the section with the lowest number, being\~7 in this case).
+.
+The quotes around
+.nh
+.I \[cq]troff(1)\[cq]
+.hy
+are necessary because the parentheses are special shell characters;
+escaping them with a backslash character
+.I \[rs](
+and
+.I \[rs])
+would be possible, too.
+.
+The formatted files are concatenated and displayed in one piece.
+.
+.sp
+.EX
+\fIsh#\fR\~LANG=de\~groffer\~--man\~--www\~--www-viewer=galeon\~ls
+.EE
+.sp
+Retrieve the German
+.I \%man\~page
+(language
+.IR de )
+for the
+.B ls
+program, decompress it, format it to
+.I \%html
+format
+.nh
+.RI ( \%www\~mode )
+.hy
+and view the result in the web browser
+.BR \%galeon .
+The option
+.B --man
+guarantees that the
+.I \%man\~page
+is retrieved, even when a local file
+.File_name \%ls
+exists in the actual directory.
+.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~--source\~'man:roff(7)'
+.EE
+.sp
+Get the
+.I \%man\~page
+called
+.I \%roff
+in \fIman\fP\~section 7, decompress it, and print its unformatted
+content, its source code.
+.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~--de-p\~--in\~--ap
+.EE
+.sp
+This is a set of abbreviated arguments, it is determined as
+.br
+.sp
+.EX
+\fIsh#\fR\~groffer\~--debug-params\~--intermediate-output\~--apropos
+.EE
+.sp
+.
+.sp
+.EX
+\fIsh#\fR\~cat\~file.gz\~|\~groffer\~-Z\~-mfoo
+.EE
+.sp
+.
+The file
+.File_name file.gz
+is sent to standard input, this is decompressed, and then this is
+transported to the
+.I \%groff intermediate output mode
+without post-processing
+.RB ( groff
+option
+.BR -Z ),
+using macro package
+.I \%foo
+.RB ( groff
+option
+.BR -m ).
+.
+.
+.sp
+.EX
+\fIsh#\fR\~echo\~'\[rs]f[CB]WOW!'\~|
+> groffer --x --bg red --fg yellow --geometry 200x100 -
+.EX
+.sp
+.
+Display the word \f[CB]WOW!\fP in a small window in constant-width
+bold font, using color yellow on red background.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COMPATIBILITY"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program is written in Perl, the Perl version during writing was v5.8.8.
+.
+.
+.P
+.B \%groffer
+provides its own parser for command line arguments that is compatible
+to both \%\f[CR]POSIX\fP
+.BR \%getopts (1)
+and \%\f[CR]GNU\fP
+.BR \%getopt (1).
+It can handle option arguments and file names containing white space
+and a large set of special characters.
+.
+The following standard types of options are supported.
+.
+.
+.Topic
+The option consisting of a single minus
+.B -
+refers to standard input.
+.
+.
+.Topic
+A single minus followed by characters refers to a single character
+option or a combination thereof; for example, the
+.B \%groffer
+short option combination
+.B -Qmfoo
+is equivalent to
+.BR -Q\~\-m\~foo .
+.
+.
+.Topic
+Long options are options with names longer than one character; they
+are always preceded by a double minus.
+.
+An option argument can either go to the next command line argument or
+be appended with an equal sign to the argument; for example,
+.B --long=arg
+is equivalent to
+.BR --long\~arg .
+.
+.
+.Topic
+An argument of
+.B --
+ends option parsing; all further command line arguments are
+interpreted as
+.I \%filespec
+parameters, i.e. file names or constructs for searching
+.IR \%man\~pages ).
+.
+.
+.Topic
+All command line arguments that are neither options nor option
+arguments are interpreted as
+.I \%filespec
+parameters and stored until option parsing has finished.
+.
+For example, the command line
+.sp
+.EX
+\fIsh#\fR\~groffer file1 -a -o arg file2
+.EE
+.sp
+is equivalent to
+.sp
+.EX
+\fIsh#\fR\~groffer -a -o arg -- file1 file2
+.EE
+.sp
+.
+.P
+The free mixing of options and
+.I \%filespec
+parameters follows the GNU principle.
+.
+That does not fulfill the strange option behavior of \%\f[CR]POSIX\fP
+that ends option processing as soon as the first non-option argument
+has been reached.
+.
+The end of option processing can be forced by the option
+.RB ` \-\- '
+anyway.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "BUGS"
+.\" --------------------------------------------------------------------
+.
+Report bugs to the
+.MT address@hidden
+bug-groff mailing list 
+.ME .
+.
+Include a complete, self-contained example that will allow the bug to
+be reproduced, and say which version of
+.B \%groffer
+you are using.
+.
+.
+.P
+You can also use the
+.MT address@hidden
+groff mailing list
+.ME ,
+but you must first subscribe to this list.
+.
+You can do that by visiting the
+.UR http://\:lists.gnu.org/\:mailman/\:listinfo/\:groff
+groff mailing list web page
+.UE .
+.
+.
+.P
+See
+.BR \%groff (@MAN1EXT@)
+for information on availability.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "SEE ALSO"
+.\" --------------------------------------------------------------------
+.
+.P
+.BR \%groff (@MAN1EXT@),
+.BR address@hidden@troff (@MAN1EXT@)
+.RS
+Details on the options and environment variables available in
+.BR \%groff ;
+all of them can be used with
+.BR \%groffer .
+.RE
+.
+.
+.TP
+.BR \%groff (@MAN7EXT@)
+Documentation of the
+.I \%groff
+language.
+.
+.
+.TP
+.BR \%grog (@MAN1EXT@)
+Internally,
+.B \%groffer
+tries to guess the
+.B \%groff
+command line options from the input using this program.
+.
+.
+.TP
+.BR groff_out (@MAN5EXT@)
+Documentation on the
+.I \%groff intermediate output
+.nh
+.RI ( ditroff
+output).
+.hy
+.
+.
+.TP
+.BR groff_tmac (@MAN5EXT@)
+Documentation on the
+.I \%groff
+macro files.
+.
+.
+.TP
+.BR \%man (1)
+The standard program to display
+.IR \%man\~pages .
+.
+The information there is only useful if it is the
+.I \%man\~page
+for GNU
+.BR man .
+Then it documents the options and environment variables that are
+supported by
+.BR \%groffer .
+.
+.
+.P
+.BR \%gxditview (@MAN1EXT@),
+.BR \%xditview (1x)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%x\~mode .
+.RE
+.
+.
+.P
+.BR \%kpdf (1),
+.BR \%kghostview (1),
+.BR \%evince (1),
+.BR \%ggv (1),
+.BR \%gv (1),
+.BR \%ghostview (1),
+.BR \%gs (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%ps\~mode .
+.RE
+.
+.
+.P
+.BR \%kpdf (1),
+.BR \%acroread (1),
+.BR \%evince (1),
+.BR \%xpdf (1),
+.BR \%gpdf (1),
+.BR \%kghostview (1),
+.BR \%ggv (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%pdf\~mode .
+.RE
+.
+.
+.P
+.BR \%kdvi (1),
+.BR \%xdvi (1),
+.BR \%dvilx (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%dvi\~mode .
+.RE
+.
+.
+.P
+.BR \%konqueror (1),
+.BR \%epiphany (1),
+.BR \%firefox (1),
+.BR \%mozilla (1),
+.BR \%netscape (1),
+.BR \%lynx (1)
+.RS
+Web-browsers for
+.BR \%groffer 's
+.I \%html
+or
+.IR \%www\~mode .
+.RE
+.
+.
+.TP
+.BR \%less (1)
+Standard pager program for the
+.IR \%tty\~mode .
+.
+.
+.P
+.BR \%gzip (1),
+.BR \%bzip2 (1)
+.RS
+The decompression programs supported by
+.BR \%groffer .
+.RE
+.
+.
+.\" --------------------------------------------------------------------
+.SH "AUTHOR"
+.\" --------------------------------------------------------------------
+.author
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COPYING"
+.\" --------------------------------------------------------------------
+.copyleft
+.
+.
+.\" --------------------------------------------------------------------
+.\" Emacs settings
+.\" --------------------------------------------------------------------
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:

Index: groffer.pl
===================================================================
RCS file: groffer.pl
diff -N groffer.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ groffer.pl  11 Aug 2013 08:28:52 -0000      1.17
@@ -0,0 +1,2209 @@
+#! /usr/bin/env perl
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/perl/groffer.pl
+# Installed position: <prefix>/bin/groffer
+
+# Copyright (C) 2006, 2009, 2011, 2013
+#   Free Software Foundation, Inc.
+
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 29 Mar 2013
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+use strict;
+use warnings;
+#use diagnostics;
+
+# temporary dir and files
+use File::Temp qw/ tempfile tempdir /;
+
+# needed for temporary dir
+use File::Spec;
+
+# for `copy' and `move'
+use File::Copy;
+
+# for fileparse, dirname and basename
+use File::Basename;
+
+# current working directory
+use Cwd;
+
+# $Bin is the directory where this script is located
+use FindBin;
+
+
+########################################################################
+# system variables and exported variables
+########################################################################
+
+our $Dev_Null;
+our $Umask;
+our @Path;
+our $Start_Dir;
+
+our $tmpdir = '';
+our ($fh_cat, $tmp_cat);
+our ($fh_stdin, $tmp_stdin);
+
+our @Addopts_Groff;
+our %Debug;
+our %Opt;
+
+our $Has_Compression;
+our $Has_bzip;
+
+our $Output_File_Name;
+
+our $Apropos_Prog;
+our $Filespec_Arg;
+our $Filespec_Is_Man;
+our $Macro_Pkg;
+our $Manspec;
+our $No_Filespecs;
+our $Special_Filespec;
+our $Special_Setup;
+
+our %Man;
+
+BEGIN {
+  $Dev_Null = File::Spec->devnull();
+
+  $Umask = umask 077;
+
+  $Start_Dir = getcwd;
+
+  # flush after each print or write command
+  $| = 1;
+}
+
+
+########################################################################
+# read-only variables with double-@ construct
+########################################################################
+
+our $File_split_env_sh;
+our $File_version_sh;
+our $Groff_Version;
+
+BEGIN {
+  {
+    my $before_make;           # script before run of `make'
+    {
+      my $at = '@';
+      $before_make = 1 if '@VERSION@' eq "${at}VERSION${at}";
+    }
+
+    my %at_at;
+    my $file_perl_test_pl;
+    my $groffer_libdir;
+
+    if ($before_make) {
+      my $groffer_perl_dir = $FindBin::Bin;
+      my $groffer_top_dir = File::Spec->catdir($groffer_perl_dir, '..');
+      $groffer_top_dir = Cwd::realpath($groffer_top_dir);
+      $at_at{'BINDIR'} = $groffer_perl_dir;
+      $at_at{'G'} = '';
+      $at_at{'LIBDIR'} = '';
+      $groffer_libdir = $groffer_perl_dir;
+      $file_perl_test_pl = File::Spec->catfile($groffer_perl_dir,
+                                              'perl_test.pl');
+      $File_version_sh = File::Spec->catfile($groffer_top_dir, 'version.sh');
+      $Groff_Version = '';
+    } else {
+      $Groff_Version = '@VERSION@';
+      $at_at{'BINDIR'} = '@BINDIR@';
+      $at_at{'G'} = '@g@';
+      $at_at{'LIBDIR'} = '@libdir@';
+      $groffer_libdir = '@groffer_dir@';
+      $file_perl_test_pl = File::Spec->catfile($groffer_libdir,
+                                              'perl_test.pl');
+      $File_version_sh = File::Spec->catfile($groffer_libdir, 'version.sh');
+    }
+
+    die "$groffer_libdir is not an existing directory;"
+      unless -d $groffer_libdir;
+
+    unshift(@INC, $groffer_libdir);
+
+    $File_split_env_sh = File::Spec->catfile($groffer_libdir, 'split_env.sh');
+    die "$File_split_env_sh does not exist;" unless -f "$File_split_env_sh";
+
+    # test perl on suitable version
+    die "$file_perl_test_pl does not exist;" unless -f "$file_perl_test_pl";
+    do "$file_perl_test_pl" or die "Perl test: $@";
+
+    require 'func.pl';
+    require 'man.pl';
+
+    @Path = &path_uniq( File::Spec->path() );
+
+    if ( &where_is_prog('gzip') ) {
+      $Has_Compression = 1;
+      $Has_bzip = 1 if &where_is_prog('bzip2');
+    }
+  }
+}
+
+
+########################################################################
+# modes, viewers, man sections, and defaults
+########################################################################
+
+# configuration files
+my @Conf_Files = (File::Spec->catfile(File::Spec->rootdir(),
+                                     'etc', 'groff', 'groffer.conf'),
+                 File::Spec->catfile("$ENV{'HOME'}", '.groff',
+                                     'groffer.conf')
+                );
+
+my @Default_Modes = ('pdf', 'html', 'ps', 'x', 'dvi', 'tty');
+my $Default_Resolution = 75;
+my $Default_tty_Device = 'latin1';
+
+my @Macro_Packages = ('-man', '-mdoc', '-me', '-mm', '-mom', '-ms');
+
+my %Viewer_tty = ('DVI' => [],
+                 'HTML' => ['lynx', 'w3m'],
+                 'PDF' => [],
+                 'PS' => [],
+                 'TTY' => ['less -r -R', 'more', 'pager'],
+                 'X' => [],
+                );
+
+my %Viewer_X = ('DVI' => ['kdvi', 'xdvi', 'dvilx'],
+               'HTML' => ['konqueror', 'epiphany'. 'mozilla-firefox',
+                          'firefox', 'mozilla', 'netscape', 'galeon',
+                          'opera', 'amaya','arena', 'mosaic'],
+               'PDF' => ['okular', 'kpdf', 'acroread', 'evince',
+                         'xpdf -z 150', 'gpdf', 'xpdf', 'zathura'.
+                         'epdfview', 'qpdfview', 'apvlv', 'qpdfview',
+                         'kghostview --scale 1.45', 'gv', 'ggv'],
+               'PS' => ['gs', 'gs_x11', 'ghostscript', 'ghostview',
+                        'kghostview --scale 1.45',
+                        'gv', 'okular', 'kpdf', 'evince', 'ggv'],
+               'TTY' => ['xless'],
+               'X' => ['gxditview', 'xditview'],
+             );
+
+%Man = ('ALL' => 0,
+       'AUTO_SEC' => ['1', '2', '3', '4', '5', '6', '7', '8', '9',
+                         'n', 'o'],
+       'ENABLE' => 1,
+          'EXT' => '',
+          'FORCE' => 0,
+          'IS_SETUP' => 0,
+          'MANSPEC' => {},
+          'LANG' => '',
+          'LANG2' => '',
+          'PATH' => [],
+          'SEC' => [],
+          'SEC_CHARS' => '',
+          'SYS' => [],
+         );
+$Man{'AUTO_SEC_CHARS'} = join('', @{$Man{'AUTO_SEC'}});
+
+
+########################################################################
+# given options, main_set_options()
+########################################################################
+
+my %Opts_Cmdline_Short;
+my %Opts_Cmdline_Long;
+my $Opts_Cmdline_Long_Str;
+my %Opts_Cmdline_Double;
+my %Opts_Groff_Short;
+
+sub main_set_options {
+  # the following options are ignored in groffer.pl, but are kept from
+  # groffer.sh: --shell arg, --debug-shell
+
+  my @opts_ignored_short_na = ();
+  my @opts_ignored_short_arg = ();
+
+  my @opts_ignored_long_na = ('debug-shell');
+
+  my @opts_ignored_long_arg = ('shell');
+
+
+  ###### groffer native options
+
+  my @opts_groffer_short_na = ('h', 'Q', 'v', 'V', 'X', 'Z');
+  my @opts_groffer_short_arg = ('T');
+
+  my @opts_groffer_long_na = ('auto', 'apropos', 'apropos-data',
+  'apropos-devel', 'apropos-progs', 'debug', 'debug-all',
+  'debug-filenames', 'debug-func', 'debug-grog', 'debug-not-func',
+  'debug-keep', 'debug-lm', 'debug-params', 'debug-stacks',
+  'debug-tmpdir', 'debug-user', 'default', 'do-nothing', 'dvi',
+  'groff', 'help', 'intermediate-output', 'html', 'man',
+  'no-location', 'no-man', 'no-special', 'pdf', 'ps', 'rv', 'source',
+  'text', 'to-stdout', 'text-device', 'tty', 'tty-device', 'version',
+  'whatis', 'where', 'www', 'x', 'X');
+
+### main_set_options()
+  my @opts_groffer_long_arg = ('default-modes', 'device',
+  'dvi-viewer', 'dvi-viewer-tty', 'extension', 'fg', 'fn', 'font',
+  'foreground', 'html-viewer', 'html-viewer-tty', 'mode',
+  'pdf-viewer', 'pdf-viewer-tty', 'print', 'ps-viewer',
+  'ps-viewer-tty', 'title', 'tty-viewer', 'tty-viewer-tty',
+  'www-viewer', 'www-viewer-tty', 'x-viewer', 'x-viewer-tty',
+  'X-viewer', 'X-viewer-tty');
+
+  ##### groffer options inhereted from groff
+
+  my @opts_groff_short_na = ('a', 'b', 'c', 'C', 'e', 'E', 'g', 'G',
+  'i', 'k', 'l', 'N', 'p', 'R', 's', 'S', 't', 'U', 'z');
+
+  my @opts_groff_short_arg = ('d', 'f', 'F', 'I', 'K', 'L', 'm', 'M', 'n',
+  'o', 'P', 'r', 'w', 'W');
+
+  my @opts_groff_long_na = ();
+  my @opts_groff_long_arg = ();
+
+  ##### groffer options inhereted from the X Window toolkit
+
+  my @opts_x_short_na = ();
+  my @opts_x_short_arg = ();
+
+  my @opts_x_long_na = ('iconic', 'rv');
+
+  my @opts_x_long_arg = ('background', 'bd', 'bg', 'bordercolor',
+  'borderwidth', 'bw', 'display', 'fg', 'fn', 'font', 'foreground',
+  'ft', 'geometry', 'resolution', 'title', 'xrm');
+
+### main_set_options()
+  ###### groffer options inherited from man
+
+  my @opts_man_short_na = ();
+  my @opts_man_short_arg = ();
+
+  my @opts_man_long_na = ('all', 'ascii', 'catman', 'ditroff',
+  'local-file', 'location', 'troff', 'update');
+
+  my @opts_man_long_arg = ('locale', 'manpath', 'pager',
+  'preprocessor', 'prompt', 'sections', 'systems', 'troff-device');
+
+  ###### additional options for parsing evironment variable $MANOPT only
+
+  my @opts_manopt_short_na = ('7', 'a', 'c', 'd', 'D', 'f', 'h', 'k',
+  'l', 't', 'u', 'V', 'w', 'Z');
+
+  my @opts_manopt_short_arg = ('e', 'L', 'm', 'M', 'p', 'P', 'r', 'S',
+  'T');
+
+  my @opts_manopt_long_na = (@opts_man_long_na, 'apropos', 'debug',
+  'default', 'help', 'html', 'ignore-case', 'location-cat',
+  'match-case', 'troff', 'update', 'version', 'whatis', 'where',
+  'where-cat');
+
+  my @opts_manopt_long_arg = (@opts_man_long_na, 'config_file',
+  'encoding', 'extension', 'locale');
+
+### main_set_options()
+  ###### collections of command line options
+
+  # There are two hashes that control the whole of the command line
+  # options, one for short and one for long options.  Options without
+  # and with arguments are mixed by advicing a value of 0 for an option
+  # without argument and a value of 1 for an option with argument.
+  # The options are with leading minus.
+
+  foreach (@opts_groffer_short_na, @opts_groff_short_na,
+          @opts_x_short_na, @opts_man_short_na, @opts_ignored_short_na) {
+    $Opts_Cmdline_Short{"-$_"} = 0 if $_;
+  }
+  foreach (@opts_groffer_short_arg, @opts_groff_short_arg,
+          @opts_x_short_arg, @opts_man_short_arg, @opts_ignored_short_arg) {
+    $Opts_Cmdline_Short{"-$_"} = 1 if $_;
+  }
+
+  foreach (@opts_groffer_long_na, @opts_groff_long_na,
+          @opts_x_long_na, @opts_man_long_na, @opts_ignored_long_na) {
+    $Opts_Cmdline_Long{"--$_"} = 0 if $_;
+  }
+  foreach (@opts_groffer_long_arg, @opts_groff_long_arg,
+          @opts_x_long_arg, @opts_man_long_arg, @opts_ignored_long_arg) {
+    $Opts_Cmdline_Long{"--$_"} = 1 if $_;
+  }
+
+  # For determining abbreviations of an option take two spaces as join
+  # for better check.
+  # The options are without leading minus.
+  $Opts_Cmdline_Long_Str = join '  ', keys %Opts_Cmdline_Long;
+  if ($Opts_Cmdline_Long_Str) {
+    $Opts_Cmdline_Long_Str = " $Opts_Cmdline_Long_Str ";
+    $Opts_Cmdline_Long_Str =~ s/--//g;
+  }
+
+### main_set_options()
+  # options with equal meaning are mapped to a single option name
+  # all of these have leading minus characters
+  %Opts_Cmdline_Double = ('-h' => '--help',
+                         '-Q' => '--source',
+                         '-T' => '--device',
+                         '-v' => '--version',
+                         '-Z' => '--intermediate-output',
+                         '--bd' => '--bordercolor',
+                         '--bg' => '--background',
+                         '--bw' => '--borderwidth',
+                         '--debug-all' => '--debug',
+                         '--ditroff' => '--intermediate-output',
+                         '--dvi-viewer-tty' => '--dvi-viewer',
+                         '--fg' => '--foreground',
+                         '--fn' => '--font',
+                         '--ft' => '--font',
+                         '--html-viewer-tty' => '--html-viewer',
+                         '--pdf-viewer-tty' => '--pdf-viewer',
+                         '--ps-viewer-tty' => '--ps-viewer',
+                         '--troff-device' => '--device',
+                         '--tty-device' => '--text-device',
+                         '--tty-viewer' => '--pager',
+                         '--tty-viewer-tty' => '--pager',
+                         '--where' => '--location',
+                         '--www' => '--html',
+                         '--www-viewer' => '--html-viewer',
+                         '--www-viewer-tty' => '--html-viewer',
+                         '--x-viewer-tty' => '--x-viewer',
+                         '--X' => '--x',
+                         '--X-viewer' => '--x-viewer',
+                         '--X-viewer-tty' => '--x-viewer',
+                        );
+
+  # groff short options with leading minus
+  foreach (@opts_groff_short_na) {
+    $Opts_Groff_Short{"-$_"} = 0;
+  }
+  foreach (@opts_groff_short_arg) {
+    $Opts_Groff_Short{"-$_"} = 1;
+  }
+
+}                              # main_set_options()
+
+
+########################################################################
+# $MANOPT, main_parse_MANOPT()
+########################################################################
+
+# handle environment variable $MANOPT
+my @Manopt;
+
+sub main_parse_MANOPT {
+  if ($ENV{'MANOPT'}) {
+    @Manopt = `sh $File_split_env_sh MANOPT`;
+    chomp @Manopt;
+
+    my @manopt;
+    # %opts stores options that are used by groffer for $MANOPT
+    # All options not in %opts are ignored.
+    # Check options used with %Opts_Cmdline_Double.
+    # 0: option used ('' for ignore), 1: has argument or not
+### main_parse_MANOPT()
+    my %opts = ('-7' => ['--ascii', 0],
+               '--ascii' => ['--ascii', 0],
+               '-a' => ['--all', 0],
+               '--all' => ['--all', 0],
+               '-c' => ['', 1],
+               '--catman' => ['', 1],
+               '-e' => ['--extension', 1],
+               '--extension' => ['--extension', 1],
+               '-f' => ['--whatis', 1],
+               '--whatis' => ['--whatis', 1],
+               '-L' => ['--locale', 1],
+               '--locale' => ['--locale', 1],
+               '-m' => ['--systems', 1],
+               '--systems' => ['--systems', 1],
+               '-M' => ['--manpath', 1],
+               '-manpath' => ['--manpath', 1],
+               '--manpath' => ['--manpath', 1],
+               '-p' => ['', 1],
+               '--preprocessor' => ['', 1],
+               '-P' => ['--pager', 1],
+               '-pager' => ['--pager', 1],
+               '-r' => ['', 1],
+               '-prompt' => ['', 1],
+               '-S' => ['--sections', 1],
+               '-sections' => ['--sections', 1],
+               '-T' => ['-T', 1],
+               '--device' => ['-T', 1],
+               '-w' => ['--location', 0],
+               '--where' => ['--location', 0],
+               '--location' => ['--location', 0],
+              );
+
+### main_parse_MANOPT()
+    my ($opt, $has_arg);
+    my $i = 0;
+    my $n = $#Manopt;
+    while ($i <= $n) {
+      my $o = $Manopt[$i];
+      ++$i;
+      # ignore, when not in %opts
+      next unless (exists $opts{$o});
+      if (($o eq '-D') or ($o eq '--default')) {
+       @manopt = ();
+       next;
+      }
+      $opt = $opts{$o}[0];
+      $has_arg = $opts{$o}[1];
+      # ignore, when empty in %opts
+      unless ($opt) {
+       # ignore without argument
+       next unless ($has_arg);
+       # ignore the argument as well
+       ++$i;
+       next;
+      }
+      if ($has_arg) {
+       last if ($i > $n);
+       push @manopt, $opt, $Manopt[$i];
+       ++$i;
+       next;
+      } else {
+       push @manopt, $opt;
+       next;
+      }
+    }
+    @Manopt = @manopt;
+  }
+}                              # main_parse_MANOPT()
+
+
+########################################################################
+# configuration files, $GROFFER_OPT, and command line, main_config_params()
+########################################################################
+
+my @Options;
+my @Filespecs;
+my @Starting_Conf;
+my @Starting_ARGV = @ARGV;
+sub main_config_params {       # handle configuration files
+  # options may not be abbreviated, but must be exact
+  my @conf_args;
+  foreach my $f (@Conf_Files) {
+    if (-s $f) {
+      my $fh;
+      open $fh, "<$f" || next;
+      my $nr = 0;
+    LINE: foreach my $line (<$fh>) {
+       ++ $nr;
+       chomp $line;
+       # remove starting and ending whitespace
+       $line =~ s/^\s+|\s+$//g;
+       # replace whitespace by single space
+       $line =~ s/\s+/ /g;
+       # ignore all lines that do not start with minus
+       next unless $line =~ /^-/;
+       # three minus
+       if ($line =~ /^---/) {
+         warn "Wrong option $line in configuration file $f.\n";
+         next;
+       }
+       if ($line =~ /^--[ =]/) {
+         warn "No option name in `$line' in configuration " .
+           "file $f.\n";
+         next;
+       }
+       push @Starting_Conf, $line;
+       # -- or -
+       if ($line =~ /^--?$/) {
+         warn "`$line' is not allowed in configuration files.\n";
+         next;
+       }
+       ### main_config_params()
+       if ($line =~ /^--/) {   # line is long option
+         my ($name, $arg);
+         if ($line =~ /[ =]/) { # has arg on line
+           $line =~ /^(--[^ =]+)[ =] ?(.*)$/;
+           ($name, $arg) = ($1, $2);
+           $arg =~ s/[\'\"]//g;
+         } else {              # does not have an argument on line
+           $name = $line;
+         }
+         $name =~ s/[\'\"]//g;
+         unless (exists $Opts_Cmdline_Long{$name}) {
+           # option does not exist
+           warn "Option `$name' does not exist.\n";
+           next LINE;
+         }
+         # option exists
+         if ($Opts_Cmdline_Long{$name}) { # option has arg
+           if (defined $arg) {
+             push @conf_args, $name, $arg;
+             next LINE;
+           } else {
+             warn "Option `$name' needs an argument in " .
+               "configuration file $f\n";
+             next LINE;
+           }
+         } else {              # option has no arg
+           if (defined $arg) {
+             warn "Option `$name' may not have an argument " .
+               "in configuration file $f\n";
+             next LINE;
+           } else {
+             push @conf_args, $name;
+             next LINE;
+           }
+         }
+         ### main_config_params()
+       } else {                # line is short option or cluster
+         $line =~ s/^-//;
+         while ($line) {
+           $line =~ s/^(.)//;
+           my $opt = "-$1";
+           next if ($opt =~ /\'\"/);
+           if ($opt =~ /- /) {
+             warn "Option `$conf_args[$#conf_args]' does not " .
+               "have an argument.\n";
+             next LINE;
+           }
+           if (exists $Opts_Cmdline_Short{$opt}) {
+             # short opt exists
+             push @conf_args, $opt;
+             if ($Opts_Cmdline_Short{$opt}) { # with arg
+               my $arg = $line;
+               $arg =~ s/^ //;
+               $arg =~ s/\'\"//g;
+               push @conf_args, "$arg";
+               next LINE;
+             } else {          # no arg
+               next;
+             }
+           } else {            # short option does not exist
+             warn "Wrong short option `-$opt' from " .
+               "configuration.  Rest of line ignored.\n";
+             next LINE;
+           }
+         }
+       }
+      }
+      close $fh;
+    }
+  }
+
+### main_config_params()
+  # handle environment variable $GROFFER_OPT
+  my @GROFFER_OPT;
+  if ($ENV{'GROFFER_OPT'}) {
+    @GROFFER_OPT = `sh $File_split_env_sh GROFFER_OPT`;
+    chomp @GROFFER_OPT;
+  }
+
+  # Handle command line parameters together with $GROFFER_OPT.
+  # Options can be abbreviated, with each - as abbreviation place.
+  {
+    my @argv0 = (@GROFFER_OPT, @ARGV);
+    my @argv;
+    my $only_files = 0;
+    my $n = $#argv0;             # last element
+    my $n1 = scalar @GROFFER_OPT; # first element of @ARGV
+    my $i = 0;                 # number of the element
+    my @s = ('the environment variable $GROFFER_OPT', 'the command line');
+    my $j = 0;                 # index in @s, 0 before $n1, 1 then
+  ELT: while ($i <= $n) {
+      my $elt = $argv0[$i];
+      $j = 1 if $i >= $n1;
+      ++$i;
+      # remove starting and ending whitespace
+      $elt =~ s/^\s+|\s+$//g;
+      # replace whitespace by single space
+      $elt =~ s/\s+/ /g;
+
+      if ($only_files) {
+       push @Filespecs, $elt;
+       next ELT;
+      }
+
+### main_config_params()
+      if ($elt =~ /^-$/) {     # -
+       push @Filespecs, $elt;
+       next ELT;
+      }
+      if ($elt =~ /^--$/) {    # --
+       $only_files = 1;
+       next ELT;
+      }
+
+      if ($elt =~ /^--[ =]/) { # no option name
+       warn "No option name in `$elt' at $s[$j].\n";
+       next ELT;
+      }
+      if ($elt =~ /^---/) {    # wrong with three minus
+       warn "Wrong option `$elt' at $s[$j].\n";
+       next ELT;
+      }
+
+      if ($elt =~ /^--[^-]/) { # long option
+       my ($name, $opt, $abbrev, $arg);
+       if ($elt =~ /[ =]/) {   # has arg on elt
+         $elt =~ /^--([^ =]+)[ =] ?(.*)$/;
+         ($name, $arg) = ($1, $2);
+         $opt = "--$name";
+         $abbrev = $name;
+         $arg =~ s/[\'\"]//g;
+       } else {                # does not have an argument in the element
+         $opt = $name = $elt;
+         $name =~ s/^--//;
+         $abbrev = $name;
+       }
+### main_config_params()
+       # remove quotes in name
+       $name =~ s/[\'\"]//g;
+       my $match = $name;
+       $match =~ s/-/[^- ]*-/g;
+       ### main_config_params()
+       if (exists $Opts_Cmdline_Long{$opt}) {
+         # option exists exactly
+       } elsif ($Opts_Cmdline_Long_Str =~ / (${match}[^- ]*?) /) {
+         # option is an abbreviation without further -
+         my $n0 = $1;
+         if ($Opts_Cmdline_Long_Str =~
+             / (${match}[^- ]*) .* (${match}[^- ]*) /) {
+           warn "Option name `--$abbrev' is not unique: " .
+             "--$1 --$2 \n";
+           next ELT;
+         }
+         $name = $n0;
+         $opt = "--$n0";
+       } elsif ($Opts_Cmdline_Long_Str =~ / (${match}[^ ]*) /) {
+         # option is an abbreviation with further -
+         my $n0 = $1;
+         if ($Opts_Cmdline_Long_Str =~
+             / (${match}[^ ]*) .* (${match}[^ ]*) /) {
+           warn "Option name `--$abbrev' is not unique: " .
+             "--$1 --$2 \n";
+           next ELT;
+         }
+         $name = $n0;
+         $opt = "--$n0";
+       } else {
+         warn "Option `--$abbrev' does not exist.\n";
+         next ELT;
+       }
+### main_config_params()
+       if ($Opts_Cmdline_Long{$opt}) { # option has arg
+         if (defined $arg) {
+           push @argv, "--$name", $arg;
+           next ELT;
+         } else {              # $arg not defined, argument at next element
+           if (($i == $n1) || ($i > $n)) {
+             warn "No argument left for option " .
+               "`$elt' at $s[$j].\n";
+             next ELT;
+           }
+           ### main_config_params()
+           # add argument as next element
+           push @argv, "--$name", $argv0[$i];
+           ++$i;
+           next ELT;
+         }                     # if (defined $arg)
+       } else {                # option has no arg
+         if (defined $arg) {
+           warn "Option `$abbrev' may not have an argument " .
+             "at $s[$j].\n";
+           next ELT;
+         } else {
+           push @argv, "--$name";
+           next ELT;
+         }
+       }                       # if ($Opts_Cmdline_Long{$opt})
+### main_config_params()
+      } elsif ($elt =~ /^-[^-]/) { # short option or cluster
+       my $cluster = $elt;
+       $cluster =~ s/^-//;
+       while ($cluster) {
+         $cluster =~ s/^(.)//;
+         my $opt = "-$1";
+         if (exists $Opts_Cmdline_Short{$opt}) { # opt exists
+           if ($Opts_Cmdline_Short{$opt}) { # with arg
+             if ($cluster) {   # has argument in this element
+               $cluster =~ s/^ //;
+               $cluster =~ s/\'\"//g;
+                               # add argument as rest of this element
+               push @argv, $opt, $cluster;
+               next ELT;
+             } else {          # argument at next element
+               if (($i == $n1) || ($i > $n)) {
+                 warn "No argument left for option " .
+                   "`$opt' at $s[$j].\n";
+                 next ELT;
+               }
+               ### main_config_params()
+                               # add argument as next element
+               push @argv, $opt, $argv0[$i];
+               ++$i;
+               next ELT;
+             }
+           } else {            # no arg
+             push @argv, $opt;
+             next;
+           }
+         } else {              # short option does not exist
+           warn "Wrong short option `$opt' at $s[$j].\n";
+           next ELT;
+         }                     # if (exists $Opts_Cmdline_Short{$opt})
+       }                       # while ($cluster)
+      } else {                 # not an option, file name
+       push @Filespecs, $elt;
+       next;
+      }
+    }
+### main_config_params()
+    @Options = (@Manopt, @conf_args, @argv);
+    foreach my $i (0..$#Options) {
+      if ( exists $Opts_Cmdline_Double{ $Options[$i] } ) {
+       $Options[$i] = $Opts_Cmdline_Double{ $Options[$i] };
+      }
+    }
+    @Filespecs = ('-') unless (@Filespecs);
+    @ARGV = (@Options, '--', @Filespecs);
+  }
+} # main_config_params()
+
+if (0) {
+  print STDERR "<$_>\n" foreach @ARGV;
+}
+
+
+########################################################################
+# main_parse_params()
+########################################################################
+
+my $i;
+my $n;
+
+$Opt{'XRM'} = [];
+
+sub main_parse_params {
+  $i = 0;
+  $n = $#Options;
+
+  # options that are ignored in this part
+  # shell version of groffer: --debug*, --shell
+  # man options: --catman (only special in man),
+  #              --preprocessor (force groff preproc., handled by grog),
+  #              --prompt (prompt for less, ignored),
+  #              --troff (-mandoc, handled by grog),
+  #              --update (inode check, ignored)
+  my %ignored_opts = (
+                     '--catman' => 0,
+                     '--debug-func' => 0,
+                     '--debug-not-func' => 0,
+                     '--debug-lm' => 0,
+                     '--debug-shell' => 0,
+                     '--debug-stacks' => 0,
+                     '--debug-user' => 0,
+                     '--preprocessor' => 1,
+                     '--prompt' => 1,
+                     '--shell' => 1,
+                     '--troff' => 0,
+                     '--update' => 0,
+                    );
+
+### main_parse_params()
+  my %long_opts =
+    (
+     '--debug' =>
+     sub { $Debug{$_} = 1 foreach (qw/FILENAMES GROG KEEP PARAMS TMPDIR/); },
+     '--debug-filenames' => sub { $Debug{'FILENAMES'} = 1; },
+     '--debug-grog' => sub { $Debug{'GROG'} = 1; },
+     '--debug-keep' => sub { $Debug{'KEEP'} = 1; $Debug{'PARAMS'} = 1; },
+     '--debug-params' => sub { $Debug{'PARAMS'} = 1; },
+     '--debug-tmpdir' => sub { $Debug{'TMPDIR'} = 1; },
+     '--help' => sub { &usage(); $Opt{'DO_NOTHING'} = 1; },
+     '--source' => sub { $Opt{'MODE'} = 'source'; },
+     '--device' =>
+     sub {  $Opt{'DEVICE'} = &_get_arg();
+           my %modes = ( 'dvi'=> 'dvi',
+                         'html' => 'html',
+                         'lbp' => 'groff',
+                         'lj4' => 'groff',
+                         'ps' => 'ps',
+                         'ascii' => 'tty',
+                         'cp1047' => 'tty',
+                         'latin1' => 'tty',
+                         'utf8' => 'tty',
+                       );
+           if ($Opt{'DEVICE'} =~ /^X.*/) {
+             $Opt{'MODE'} = 'x';
+           } elsif ( exists $modes{ $Opt{'DEVICE'} } ) {
+             if ( $modes{ $Opt{'DEVICE'} } eq 'tty' ) {
+               $Opt{'MODE'} = 'tty'
+                 unless ($Opt{'MODE'} eq 'text');
+             } else {
+               $Opt{'MODE'} = $modes{ $Opt{'DEVICE'} };
+             }
+           } else {
+             # for all elements not in %modes
+             $Opt{'MODE'} = 'groff';
+           }
+         },
+### main_parse_params()
+     '--version' => sub { &version(); $Opt{'DO_NOTHING'} = 1; },
+     '--intermediate-output' => sub { $Opt{'Z'} = 1; },
+     '--all' => sub { $Opt{'ALL'} = 1; },
+     '--apropos' =>            # run apropos
+     sub { $Opt{'APROPOS'} = 1;
+          delete $Opt{'APROPOS_SECTIONS'};
+          delete $Opt{'WHATIS'}; },
+     '--apropos-data' =>       # run apropos for data sections
+     sub { $Opt{'APROPOS'} = 1;
+          $Opt{'APROPOS_SECTIONS'} = '457';
+          delete $Opt{'WHATIS'}; },
+     '--apropos-devel' =>      # run apropos for devel sections
+     sub { $Opt{'APROPOS'} = 1;
+          $Opt{'APROPOS_SECTIONS'} = '239';
+          delete $Opt{'WHATIS'}; },
+     '--apropos-progs' =>      # run apropos for prog sections
+     sub { $Opt{'APROPOS'} = 1;
+          $Opt{'APROPOS_SECTIONS'} = '168';
+          delete $Opt{'WHATIS'}; },
+     '--ascii' =>
+     sub { push @Addopts_Groff, '-mtty-char';
+          $Opt{'MODE'} = 'text' unless $Opt{'MODE'}; },
+     '--auto' =>               # the default automatic mode
+     sub { delete $Opt{'MODE'}; },
+     '--bordercolor' =>                # border color for viewers, arg
+     sub { $Opt{'BD'} = &_get_arg(); },
+     '--background' =>         # background color for viewers, arg
+     sub { $Opt{'BG'} = &_get_arg(); },
+### main_parse_params()
+     '--borderwidth' =>                # border width for viewers, arg
+     sub { $Opt{'BW'} = &_get_arg(); },
+     '--default' =>            # reset variables to default
+     sub { %Opt = (); },
+     '--default-modes' =>      # sequence of modes in auto mode; arg
+     sub { $Opt{'DEFAULT_MODES'} = &_get_arg(); },
+     '--display' =>            # set X display, arg
+     sub { $Opt{'DISPLAY'} = &_get_arg(); },
+     '--do-nothing' => sub { $Opt{'DO_NOTHING'} = 1; },
+     '--dvi' => sub { $Opt{'MODE'} = 'dvi'; },
+     '--dvi-viewer' =>         # viewer program for dvi mode; arg
+     sub { $Opt{'VIEWER_DVI'} = &_get_arg(); },
+     '--extension' =>          # the extension for man pages, arg
+     sub { $Opt{'EXTENSION'} = &_get_arg(); },
+     '--foreground' =>         # foreground color for viewers, arg
+     sub { $Opt{'FG'} = &_get_arg(); },
+     '--font' =>               # set font for viewers, arg
+     sub { $Opt{'FN'} = &_get_arg(); },
+     '--geometry' =>           # window geometry for viewers, arg
+     sub { $Opt{'GEOMETRY'} = &_get_arg(); },
+     '--groff' => sub { $Opt{'MODE'} = 'groff'; },
+     '--html' => sub { $Opt{'MODE'} = 'html'; },
+     '--html-viewer' =>                # viewer program for html mode; arg
+     sub { $Opt{'VIEWER_HTML'} = &_get_arg(); },
+     '--iconic' =>             # start viewers as icons
+     sub { $Opt{'ICONIC'} = 1; },
+     '--locale' =>             # set language for man pages, arg
+     # argument is address@hidden (ISO 639,...)
+     sub { $Opt{'LANG'} = &_get_arg(); },
+     '--local-file' =>         # force local files; same as `--no-man'
+     sub { delete $Man{'ENABLE'}; delete $Man{'FORCE'}; },
+     '--location' =>           # print file locations to stderr
+     sub { $Opt{'LOCATION'} = 1; },
+### main_parse_params()
+     '--man' =>                        # force all file params to be man pages
+     sub { $Man{'ENABLE'} = 1; $Man{'FORCE'} = 1; },
+     '--manpath' =>            # specify search path for man pages, arg
+     # arg is colon-separated list of directories
+     sub { $Opt{'MANPATH'} = &_get_arg(); },
+     '--mode' =>               # display mode
+     sub { my $arg = &_get_arg();
+          my %modes = ( '' => '',
+                        'auto' => '',
+                        'groff' => 'groff',
+                        'html' => 'html',
+                        'www' => 'html',
+                        'dvi' => 'dvi',
+                        'pdf' => 'pdf',
+                        'ps' => 'ps',
+                        'text' => 'text',
+                        'tty' => 'tty',
+                        'X' => 'x',
+                        'x' => 'x',
+                        'Q' => 'source',
+                        'source' => 'source',
+                      );
+          if ( exists $modes{$arg} ) {
+            if ( $modes{$arg} ) {
+              $Opt{'MODE'} = $modes{$arg};
+            } else {
+              delete $Opt{'MODE'};
+            }
+          } else {
+            warn "Unknown mode in `$arg' for --mode\n";
+          }
+        },
+### main_parse_params()
+     '--no-location' =>                # disable former call to `--location'
+     sub { delete $Opt{'LOCATION'}; },
+     '--no-man' =>             # disable search for man pages
+     sub { delete $Man{'ENABLE'}; delete $Man{'FORCE'}; },
+     '--no-special' =>         # disable some special former calls
+     sub { delete $Opt{'ALL'}; delete $Opt{'APROPOS'};
+          delete $Opt{'WHATIS'}; },
+     '--pager' =>              # set paging program for tty mode, arg
+     sub { $Opt{'PAGER'} = &_get_arg(); },
+     '--pdf' => sub { $Opt{'MODE'} = 'pdf'; },
+     '--pdf-viewer' =>         # viewer program for pdf mode; arg
+     sub { $Opt{'VIEWER_PDF'} = &_get_arg(); },
+     '--print' =>              # print argument, for argument test
+     sub { my $arg = &_get_arg; print STDERR "$arg\n"; },
+     '--ps' => sub { $Opt{'MODE'} = 'ps'; },
+     '--ps-viewer' =>          # viewer program for ps mode; arg
+     sub { $Opt{'VIEWER_PS'} = &_get_arg(); },
+     '--resolution' =>         # set resolution for X devices, arg
+     sub { my $arg = &_get_arg();
+          my %res = ( '75' => 75,
+                      '75dpi' => 75,
+                      '100' => 100,
+                      '100dpi' => 100,
+                    );
+          if (exists $res{$arg}) {
+            $Opt{'RESOLUTION'} = $res{$arg};
+          } else {
+            warn "--resolution allows only 75, 75dpi, " .
+              "100, 100dpi as argument.\n";
+          }
+        },
+### main_parse_params()
+     '--rv' => sub { $Opt{'RV'} = 1; },
+     '--sections' =>           # specify sections for man pages, arg
+     # arg is a `:'-separated (colon) list of section names
+     sub { my $arg = &_get_arg();
+          my @arg = split /:/, $arg;
+          my $s;
+          foreach (@arg) {
+            /^(.)/;
+            my $c = $1;
+            if ($Man{'AUTO_SEC_CHARS'} =~ /$c/) {
+              $s .= $c;
+            } else {
+              warn "main_parse_params(): not a man section `$c';";
+            }
+          }
+          $Opt{'SECTIONS'} = $s; },
+     '--systems' =>            # man pages for different OS's, arg
+     # argument is a comma-separated list
+     sub { $Opt{'SYSTEMS'} = &_get_arg(); },
+     '--text' =>               # text mode without pager
+     sub { $Opt{'MODE'} = 'text'; },
+     '--title' =>              # title for X viewers; arg
+     sub { my $arg = &_get_arg();
+          if ($arg) {
+            if ( $Opt{'TITLE'} ) {
+              $Opt{'TITLE'} = "$Opt{'TITLE'} $arg";
+            } else {
+              $Opt{'TITLE'} = $arg;
+            }
+          }
+        },
+     '--tty' =>                        # tty mode, text with pager
+     sub { $Opt{'MODE'} = 'tty'; },
+     '--to-stdout' =>          # print mode file without display
+     sub { $Opt{'STDOUT'} = 1; },
+     '--text-device' =>                # device for tty mode; arg
+     sub { $Opt{'TEXT_DEVICE'} = &_get_arg(); },
+     '--whatis' => sub { delete $Opt{'APROPOS'}; $Opt{'WHATIS'} = 1; },
+     '--x' => sub { $Opt{'MODE'} = 'x'; },
+### main_parse_params()
+     '--xrm' =>                        # pass X resource string, arg
+     sub { my $arg = &_get_arg(); push @{$Opt{'XRM'}}, $arg if $arg; },
+     '--x-viewer' =>           # viewer program for x mode; arg
+     sub { $Opt{'VIEWER_X'} = &_get_arg(); },
+    );
+
+  my %short_opts = (
+                   '-V' => sub { $Opt{'V'} = 1; },
+                   '-X' => sub { $Opt{'X'} = 1; },
+                  );
+
+  if (0) {
+    # check if all options are handled in parse parameters
+
+    #short options
+    my %these_opts = (%ignored_opts, %short_opts, %Opts_Groff_Short,
+                     %Opts_Cmdline_Double);
+    foreach my $key (keys %Opts_Cmdline_Short) {
+      warn "unused option: $key" unless exists $these_opts{$key};
+    }
+
+    # long options
+    %these_opts = (%ignored_opts, %long_opts, %Opts_Cmdline_Double);
+    foreach my $key (keys %Opts_Cmdline_Long) {
+      warn "unused option: $key" unless exists $these_opts{$key};
+    }
+  }                            # if (0)
+
+### main_parse_params()
+ OPTION: while ($i <= $n) {
+    my $opt = $Options[$i];
+    ++$i;
+    if ($opt =~ /^-([^-])$/) { # single minus for short option
+      if (exists $short_opts{$opt}) { # short option handled by hash
+       $short_opts{$opt}->();
+       next OPTION;
+      } else {                 # $short_opts{$opt} does not exist
+       my $c = $1;             # the option character
+       next OPTION unless $c;
+       if ( exists $Opts_Groff_Short{ $opt } ) { # groff short option
+         if ( $Opts_Groff_Short{ $opt } ) { # option has argument
+           my $arg = $Options[$i];
+           ++$i;
+           push @Addopts_Groff, $opt, $arg;
+           next OPTION;
+         } else {              # no argument for this option
+           push @Addopts_Groff, $opt;
+           next OPTION;
+         }
+       } elsif ( exists $Opts_Cmdline_Short{ $opt } ) {
+         # is a groffer short option
+         warn "Groffer option $opt not handled " .
+           "in parameter parsing";
+       } else {
+         warn "$opt is not a groffer option.\n";
+       }
+      }                                # if (exists $short_opts{$opt})
+    }                          # if ($opt =~ /^-([^-])$/)
+    # Now it is a long option
+
+    # handle ignored options
+    if ( exists $ignored_opts{ $opt } ) {
+      ++$i if ( $ignored_opts{ $opt } );
+      next OPTION;
+    }
+### main_parse_params()
+
+    # handle normal long options
+    if (exists $long_opts{$opt}) {
+      $long_opts{$opt}->();
+    } else {
+      warn "Unknown option $opt.\n";
+    }
+    next OPTION;
+  }                            # while ($i <= $n)
+
+  if ($Debug{'PARAMS'}) {
+    print STDERR '$MANOPT: ' . "$ENV{'MANOPT'}\n" if $ENV{'MANOPT'};
+    foreach (@Starting_Conf) {
+      print STDERR "configuration: $_\n";
+    }
+    print STDERR '$GROFFER_OPT: ' . "$ENV{'GROFFER_OPT'}\n"
+      if $ENV{'GROFFER_OPT'};
+    print STDERR "command line: @Starting_ARGV\n";
+    print STDERR "parameters: @ARGV\n";
+  }
+
+  if ( $Opt{'WHATIS'} ) {
+    die "main_parse_params(): cannot handle both `whatis' and `apropos';"
+      if $Opt{'APROPOS'};
+    $Man{'ALL'} = 1;
+    delete $Opt{'APROPOS_SECTIONS'};
+  }
+
+  if ( $Opt{'DO_NOTHING'} ) {
+    exit;
+  }
+
+  if ( $Opt{'DEFAULT_MODES'} ) {
+    @Default_Modes = split /,/, $Opt{'DEFAULT_MODES'};
+  }
+}                              # main_parse_params()
+
+
+sub _get_arg {
+  if ($i > $n) {
+    die '_get_arg(): No argument left for last option;';
+  }
+  my $arg = $Options[$i];
+  ++$i;
+  $arg;
+}                              # _get_arg() of main_parse_params()
+
+
+########################################################################
+# main_set_mode()
+########################################################################
+
+my $Viewer_Background;
+my $PDF_Did_Not_Work;
+my $PDF_Has_gs;
+my $PDF_Has_ps2pdf;
+my %Display = ('MODE' => '',
+              'PROG' => '',
+              'ARGS' => ''
+             );
+
+sub main_set_mode {
+  my @modes;
+
+  # set display
+  $ENV{'DISPLAY'} = $Opt{'DISPLAY'} if $Opt{'DISPLAY'};
+
+  push @Addopts_Groff, '-V' if $Opt{'V'};
+
+  if ( $Opt{'X'} ) {
+    $Display{'MODE'} = 'groff';
+    push @Addopts_Groff, '-X';
+  }
+
+  if ( $Opt{'Z'} ) {
+    $Display{'MODE'} = 'groff';
+    push @Addopts_Groff, '-Z';
+  }
+
+  $Display{'MODE'} = 'groff' if $Opt{'MODE'} and $Opt{'MODE'} eq 'groff';
+
+  return 1 if $Display{'MODE'} and $Display{'MODE'} eq 'groff';
+
+### main_set_mode()
+  if ($Opt{'MODE'}) {
+    if ($Opt{'MODE'} =~ /^(source|text|tty)$/) {
+      $Display{'MODE'} = $Opt{'MODE'};
+      return 1;
+    }
+    $Display{'MODE'} = $Opt{'MODE'} if $Opt{'MODE'} =~ /^html$/;
+    @modes = ($Opt{'MODE'});
+  } else {                     # empty mode
+    if ($Opt{'DEVICE'}) {
+      if ($Opt{'DEVICE'} =~ /^X/) {
+       &is_X() || die "no X display found for device $Opt{'DEVICE'}";
+       $Display{'MODE'} = 'x';
+       return 1;
+      }
+      ;
+      if ($Opt{'DEVICE'} =~ /^(ascii|cp1047|latin1|utf8)$/) {
+       $Display{'MODE'} ne 'text' and $Display{'MODE'} = 'tty';
+       return 1;
+      }
+      ;
+      unless (&is_X) {
+       $Display{'MODE'} = 'tty';
+       return 1;
+      }
+    }                          # check device
+    @modes = @Default_Modes;
+  }                            # check mode
+
+### main_set_mode()
+ LOOP: foreach my $m (@modes) {
+    $Viewer_Background = 0;
+    if ($m =~ /^(test|tty|X)$/) {
+      $Display{'MODE'} = $m;
+      return 1;
+    } elsif ($m eq 'pdf') {
+      next LOOP if $PDF_Did_Not_Work;
+      $PDF_Has_gs = &where_is_prog('gs') ? 1 : 0
+       unless (defined $PDF_Has_gs);
+      $PDF_Has_ps2pdf = &where_is_prog('ps2pdf') ? 1 : 0
+       unless (defined $PDF_Has_ps2pdf);
+      if ( (! $PDF_Has_gs) and (! $PDF_Has_ps2pdf) ) {
+       $PDF_Did_Not_Work = 1;
+       next LOOP;
+      }
+
+      if (&_get_prog_args($m)) {
+       return 1;
+      } else {
+       $PDF_Did_Not_Work = 1;
+       next LOOP;
+      }
+    } else {                   # other modes
+      &_get_prog_args($m) ? return 1 : next LOOP;
+    }                          # if $m
+  }                            # LOOP: foreach
+  die 'set mode: no suitable display mode found under ' .
+    join(', ', @modes) . ';' unless $Display{'MODE'};
+  die 'set mode: no viewer available for mode ' . $Display{'MODE'} . ';'
+    unless $Display{'PROG'};
+  0;
+} # main_set_mode()
+
+
+########################################################################
+# functions to main_set_mode()
+########################################################################
+
+##########
+# _get_prog_args(<MODE>)
+#
+# Simplification for loop in set mode.
+#
+# Globals in/out: $Viewer_Background
+# Globals in    : $Opt{VIEWER_<MODE>}, $Viewer_X{<MODE>},
+#                 $Viewer_tty{<MODE>}
+#
+sub _get_prog_args {
+  my $n = @_;
+  die "_get_prog_args(): one argument is needed; you used $n;"
+    unless $n == 1;
+
+  my $mode = lc($_[0]);
+  my $MODE = uc($mode);
+
+  my $xlist = $Viewer_X{$MODE};
+  my $ttylist = $Viewer_tty{$MODE};
+
+  my $vm = "VIEWER_${MODE}";
+  my $opt = $Opt{$vm};
+
+  if ($opt) {
+    my %prog = where_is_prog $opt;
+    my $prog_ref = \%prog;
+    unless (%prog) {
+      warn "_get_prog_args(): `$opt' is not an existing program;";
+      return 0;
+    }
+
+    # $prog from $opt is an existing program
+
+### _get_prog_args() of main_set_mode()
+    if (&is_X) {
+      if ( &_check_prog_on_list($prog_ref, $xlist) ) {
+       $Viewer_Background = 1;
+      } else {
+       $Viewer_Background = 0;
+       &_check_prog_on_list($prog_ref, $ttylist);
+      }
+    } else {                   # is not X
+      $Viewer_Background = 0;
+      &_check_prog_on_list($prog_ref, $ttylist);
+    }                          # if is X
+  } else {                     # $opt is empty
+    $Viewer_Background = 0;
+    my $x;
+    if (&is_X) {
+      $x = &_get_first_prog($xlist);
+      $Viewer_Background = 1 if $x;
+    } else {                   # is not X
+      $x = &_get_first_prog($ttylist);
+    }                          # test on X
+    $Display{'MODE'} = $mode if $x;
+    return $x;
+  }
+  $Display{'MODE'} = $mode;
+  return 1;
+} # _get_prog_args() of main_set_mode()
+
+
+##########
+# _get_first_prog(<prog_list_ref>)
+#
+# Retrieve from the elements of the list in the argument the first
+# existing program in $PATH.
+#
+# Local function of main_set_mode().
+#
+# Return  : `0' if not a part of the list, `1' if found in the list.
+#
+sub _get_first_prog {
+  my $n = @_;
+  die "_get_first_prog(): one argument is needed; you used $n;"
+    unless $n == 1;
+
+  foreach my $i (@{$_[0]}) {
+    next unless $i;
+    my %prog = &where_is_prog($i);
+    if (%prog) {
+      $Display{'PROG'} = $prog{'fullname'};
+      $Display{'ARGS'} = $prog{'args'};
+      return 1;
+    }
+  }
+  return 0;
+} # _get_first_prog() of main_set_mode()
+
+
+##########
+# _check_prog_on_list (<prog-hash-ref> <prog_list_ref>)
+#
+# Check whether the content of <prog-hash-ref> is in the list
+# <prog_list_ref>.
+# The globals are set correspondingly.
+#
+# Local function for main_set_mode().
+#
+# Arguments: 2
+#
+# Return  : `0' if not a part of the list, `1' if found in the list.
+# Output  : none
+#
+# Globals in    : $Viewer_X{<MODE>}, $Viewer_tty{<MODE>}
+# Globals in/out: $Display{'PROG'}, $Display{'ARGS'}
+#
+sub _check_prog_on_list {
+  my $n = @_;
+  die "_get_first_prog(): 2 arguments are needed; you used $n;"
+    unless $n == 2;
+
+  my %prog = %{$_[0]};
+
+  $Display{'PROG'} = $prog{'fullname'};
+  $Display{'ARGS'} = $prog{'args'};
+
+  foreach my $i (@{$_[1]}) {
+    my %p = &where_is_prog($i);
+    next unless %p;
+    next unless $Display{'PROG'} eq $p{'fullname'};
+    if ($p{'args'}) {
+      if ($Display{'ARGS'}) {
+       $Display{'ARGS'} = $p{'args'};
+      } else {
+       $Display{'ARGS'} = "$p{'args'} $Display{'ARGS'}";
+      }
+    }                          # if args
+    return 1;
+  }                            # foreach $i
+  # prog was not in the list
+  return 0;
+} # _check_prog_on_list() of main_set_mode()
+
+
+########################################################################
+# groffer temporary directory, main_temp()
+########################################################################
+
+sub main_temp {
+  my $template = 'groffer_' . "$$" . '_XXXX';
+  foreach ($ENV{'GROFF_TMPDIR'}, $ENV{'TMPDIR'}, $ENV{'TMP'}, $ENV{'TEMP'},
+          $ENV{'TEMPDIR'}, File::Spec->catfile($ENV{'HOME'}, 'tmp')) {
+    if ($_ && -d $_ && -w $_) {
+      if ($Debug{'KEEP'}) {
+       eval { $tmpdir = tempdir( $template, DIR => "$_" ); };
+      } else {
+       eval { $tmpdir = tempdir( $template,
+                                 CLEANUP => 1, DIR => "$_" ); };
+      }
+      last if $tmpdir;
+    }
+  }
+  $tmpdir = tempdir( $template, CLEANUP => 1, DIR => File::Spec->tmpdir )
+    unless ($tmpdir);
+
+  # see Lerning Perl, page 205, or Programming Perl, page 413
+  # $SIG{'INT'} is for Ctrl-C interruption
+  $SIG{'INT'} = sub { &clean_up(); die "interrupted..."; };
+  $SIG{'QUIT'} = sub { &clean_up(); die "quit..."; };
+
+  if ($Debug{'TMPDIR'}) {
+    if ( $Debug{'KEEP'}) {
+      print STDERR "temporary directory is kept: $tmpdir\n";
+    } else {
+      print STDERR "temporary directory will be cleaned: $tmpdir\n";
+    }
+  }
+
+  # further argument: SUFFIX => '.sh'
+  if ($Debug{'KEEP'}) {
+    ($fh_cat, $tmp_cat) = tempfile(',cat_XXXX', DIR => $tmpdir);
+    ($fh_stdin, $tmp_stdin) = tempfile(',stdin_XXXX', DIR => $tmpdir);
+  } else {
+    ($fh_cat, $tmp_cat) = tempfile(',cat_XXXX', UNLINK => 1,
+                                  DIR => $tmpdir);
+    ($fh_stdin, $tmp_stdin) = tempfile(',stdin_XXXX', UNLINK => 1,
+                                      DIR => $tmpdir);
+  }
+}                              # main_temp()
+
+
+########################################################################
+# tmp functions and compression
+########################################################################
+
+########################################################################
+# further functions needed for main_do_fileargs()
+########################################################################
+
+my @REG_TITLE = ();
+
+##########
+# register_file(<filename>)
+#
+# Write a found file and register the title element.
+#
+# Arguments: 1: a file name
+# Output: none
+#
+sub register_file {
+  my $n = @_;
+  die "register_file(): one argument is needed; you used $n;"
+    unless $n == 1;
+  die 'register_file(): file name is empty;' unless $_[0];
+
+  if ($_[0] eq '-') {
+    &to_tmp($tmp_stdin) && &register_title('stdin');
+  } else {
+    &to_tmp($_[0]) && &register_title($_[0]);
+  }
+  1;
+}                              # register_file()
+
+
+##########
+# register_title(<filespec>)
+#
+# Create title element from <filespec> and append to $_REG_TITLE_LIST.
+# Basename is created.
+#
+# Globals in/out: @REG_TITLE
+#
+# Variable prefix: rt
+#
+sub register_title {
+  my $n = @_;
+  die "register_title(): one argument is needed; you used $n;"
+    unless $n == 1;
+  return 1 unless $_[0];
+
+  return 1 if scalar @REG_TITLE > 3;
+
+  my $title = &get_filename($_[0]);
+  $title =~ s/\s/_/g;
+  $title =~ s/\.bz2$//g;
+  $title =~ s/\.gz$//g;
+  $title =~ s/\.Z$//g;
+
+  if ($Debug{'FILENAMES'}) {
+    if ($_[0] eq 'stdin') {
+      print STDERR "register_title(): file title is stdin\n";
+    } else {
+      print STDERR "register_title(): file title is $title\n";
+    }
+  }                            # if ($Debug{'FILENAMES'})
+
+  return 1 unless $title;
+  push @REG_TITLE, $title;
+  1;
+}                              # register_title()
+
+
+##########
+# save_stdin()
+#
+# Store standard input to temporary file (with decompression).
+#
+sub save_stdin {
+  my ($fh_input, $tmp_input);
+  $tmp_input = File::Spec->catfile($tmpdir, ',input');
+  open $fh_input, ">$tmp_input" or
+    die "save_stdin(): could not open $tmp_input";
+  foreach (<STDIN>) {
+    print $fh_input $_;
+  }
+  close $fh_input;
+  open $fh_stdin, ">$tmp_stdin" or
+    die "save_stdin(): could not open $tmp_stdin";
+  foreach ( &cat_z("$tmp_input") ) {
+    print $fh_stdin "$_";
+  }
+  close $fh_stdin;
+  unlink $tmp_input unless $Debug{'KEEP'};
+}                              # save_stdin()
+
+
+########################################################################
+# main_do_fileargs()
+########################################################################
+
+sub main_do_fileargs {
+  &special_setup();
+  if ($Opt{'APROPOS'}) {
+    if ($No_Filespecs) {
+      &apropos_filespec();
+      return 1;
+    }
+  } else {
+    foreach (@Filespecs) {
+      if (/^-$/) {
+       &save_stdin();
+       last;
+      }
+    }                          # foreach (@Filespecs)
+  }                            # if ($Opt{'APROPOS'})
+
+  my $section = '';
+  my $ext = '';
+  my $twoargs = 0;
+  my $filespec;
+  my $former_arg;
+
+ FILESPEC: foreach (@Filespecs) {
+    $filespec = $_;
+    $Filespec_Arg = $_;
+    $Filespec_Is_Man = 0;
+    $Manspec = '';
+    $Special_Filespec = 0;
+
+    next FILESPEC unless $filespec;
+
+### main_do_fileargs()
+    if ($twoargs) {            # second run
+      $twoargs = 0;
+      # $section and $ext are kept from earlier run
+      my $h = { 'name' => $filespec, 'sec' => $section, 'ext' => $ext };
+      &man_setup();
+      if ( &is_man($h) ) {
+       $Filespec_Arg = "$former_arg $Filespec_Arg";
+       &special_filespec();
+       $Filespec_Is_Man = 1;
+       &man_get($h);
+       next FILESPEC;
+      } else {
+       warn "main_do_fileargs(): $former_arg is neither a file nor a " .
+         "man page nor a section argument for $filespec;";
+      }
+    }
+    $twoargs = 0;
+
+    if ( $Opt{'APROPOS'} ) {
+      &apropos_filespec();
+      next FILESPEC;
+    }
+
+    if ($filespec eq '-') {
+      &register_file('-');
+      &special_filespec();
+      next FILESPEC;
+    } elsif ( &get_filename($filespec) ne $filespec ) { # path with dir
+      &special_filespec();
+      if (-f $filespec && -r $filespec) {
+       &register_file($filespec)
+      } else {
+       warn "main_do_fileargs: the argument $filespec is not a file;";
+      }
+      next FILESPEC;
+    } else {                   # neither `-' nor has dir
+      # check whether filespec is an existing file
+      unless ( $Man{'FORCE'} ) {
+       if (-f $filespec && -r $filespec) {
+         &special_filespec();
+         &register_file($filespec);
+         next FILESPEC;
+       }
+      }
+    }                          # if ($filespec eq '-')
+
+### main_do_fileargs()
+    # now it must be a man page pattern
+
+    if ($Macro_Pkg and $Macro_Pkg ne '-man') {
+      warn "main_do_fileargs(): $filespec is not a file, " .
+       "man pages are ignored due to $Macro_Pkg;";
+      next FILESPEC;
+    }
+
+    # check for man page
+    &man_setup();
+    unless ( $Man{'ENABLE'} ) {
+      warn "main_do_fileargs(): the argument $filespec is not a file;";
+      next FILESPEC;
+    }
+    my $errmsg;
+    if ( $Man{'FORCE'} ) {
+      $errmsg = 'is not a man page';
+    } else {
+      $errmsg = 'is neither a file nor a man page';
+    }
+
+    $Filespec_Is_Man = 1;
+
+### main_do_fileargs()
+    # test filespec with `man:...' or `...(...)' on man page
+
+    my @names = ($filespec);
+    if ($filespec =~ /^man:(.*)$/) {
+      push @names, $1;
+    }
+
+    foreach my $i (@names) {
+      next unless $i;
+      my $h = { 'name' => $i };
+      if ( &is_man($h) ) {
+       &special_filespec();
+       &man_get($h);
+       next FILESPEC;
+      }
+      if ( $i =~ /^(.*)\(([$Man{'AUTO_SEC_CHARS'}])(.*)\)$/ ) {
+       $h = { 'name' => $1, 'sec' => $2, 'ext' => $3 };
+       if ( &is_man($h) ) {
+         &special_filespec();
+         &man_get($h);
+         next FILESPEC;
+       }
+      }                                # if //
+      if ( $i =~ /^(.*)\.([$Man{'AUTO_SEC_CHARS'}])(.*)$/ ) {
+       $h = { 'name' => $1, 'sec' => $2, 'ext' => $3 };
+       if ( &is_man($h) ) {
+         &special_filespec();
+         &man_get($h);
+         next FILESPEC;
+       }
+      }                                # if //
+    }                          # foreach (@names)
+
+### main_do_fileargs()
+    # check on "s name", where "s" is a section with or without an extension
+    if ($filespec =~ /^([$Man{'AUTO_SEC_CHARS'}])(.*)$/) {
+      unless ( $Man{'ENABLE'} ) {
+       warn "main_do_fileargs(): $filespec $errmsg;";
+       next FILESPEC;
+      }
+      $twoargs = 1;
+      $section = $1;
+      $ext = $2;
+      $former_arg = $filespec;
+      next FILESPEC;
+    } else {
+      warn "main_do_fileargs(): $filespec $errmsg;";
+      next FILESPEC;
+    }
+  }                            # foreach (@Filespecs)
+
+  if ($twoargs) {
+    warn "main_do_fileargs(): no filespec arguments left for second run;";
+    return 0;
+  }
+  1;
+} # main_do_fileargs()
+
+
+########################################################################
+# main_set_resources()
+########################################################################
+
+##########
+# main_set_resources ()
+#
+# Determine options for setting X resources with $_DISPLAY_PROG.
+#
+# Globals: $Display{PROG}, $Output_File_Name
+#
+sub main_set_resources {
+  # $prog   viewer program
+  # $rl     resource list
+  unlink $tmp_stdin unless $Debug{'KEEP'};
+  $Output_File_Name = '';
+
+  my @title = @REG_TITLE;
+  @title = ($Opt{'TITLE'}) unless @title;
+  @title = () unless @title;
+
+  foreach my $n (@title) {
+    next unless $n;
+    $n =~ s/^,+// if $n =~ /^,/;
+    next unless $n;
+    $Output_File_Name = $Output_File_Name . ',' if $Output_File_Name;
+    $Output_File_Name = "$Output_File_Name$n";
+  }                            # foreach (@title)
+
+  $Output_File_Name =~ s/^,+//;
+  $Output_File_Name = '-' unless $Output_File_Name;
+  $Output_File_Name = File::Spec->catfile($tmpdir, $Output_File_Name);
+
+### main_set_resources()
+  unless ($Display{'PROG'}) {  # for example, for groff mode
+    $Display{'ARGS'} = '';
+    return 1;
+  }
+
+  my %h = &where_is_prog($Display{'PROG'});
+  my $prog = $h{'file'};
+  if ($Display{'ARGS'}) {
+    $Display{'ARGS'} = "$h{'args'} $Display{'ARGS'}";
+  } else {
+    $Display{'ARGS'} = $h{'args'};
+  }
+
+  my @rl = ();
+
+  if ($Opt{'BD'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-bd', $Opt{'BD'};
+    }
+  }
+
+  if ($Opt{'BG'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-bg', $Opt{'BG'};
+    } elsif ($prog eq 'kghostview') {
+      push @rl, '--bg', $Opt{'BG'};
+    } elsif ($prog eq 'xpdf') {
+      push @rl, '-papercolor', $Opt{'BG'};
+    }
+  }
+
+### main_set_resources()
+  if ($Opt{'BW'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-bw', $Opt{'BW'};
+    }
+  }
+
+  if ($Opt{'FG'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-fg', $Opt{'FG'};
+    } elsif ($prog eq 'kghostview') {
+      push @rl, '--fg', $Opt{'FG'};
+    }
+  }
+
+  if ($Opt{'FN'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-fn', $Opt{'FN'};
+    } elsif ($prog eq 'kghostview') {
+      push @rl, '--fn', $Opt{'FN'};
+    }
+  }
+
+  if ($Opt{'GEOMETRY'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-geometry', $Opt{'GEOMETRY'};
+    } elsif ($prog eq 'kghostview') {
+      push @rl, '--geometry', $Opt{'GEOMETRY'};
+    }
+  }
+
+### main_set_resources()
+  if ($Opt{'RESOLUTION'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-resolution', $Opt{'RESOLUTION'};
+    } elsif ($prog eq 'xpdf') {
+      if ($Display{'PROG'} !~ / -z/) { # if xpdf does not have option -z
+       if ($Default_Resolution == 75) {
+         push @rl, '-z', 104;
+       } elsif ($Default_Resolution == 100) { # 72dpi is '100'
+         push @rl, '-z', 139;
+       }
+      }
+    }                          # if $prog
+  } else {                     # empty $Opt{RESOLUTION}
+    $Opt{'RESOLUTION'} = $Default_Resolution;
+    if ($prog =~ /^(gxditview|xditview)$/) {
+      push @rl, '-resolution', $Default_Resolution;
+    } elsif ($prog eq 'xpdf') {
+      if ($Display{'PROG'} !~ / -z/) { # if xpdf does not have option -z
+       if ($Default_Resolution == 75) {
+         push @rl, '-z', 104;
+       } elsif ($Default_Resolution == 100) { # 72dpi is '100'
+         push @rl, '-z', 139;
+       }
+      }
+    }                          # if $prog
+  }                            # if $Opt{RESOLUTION}
+
+  if ($Opt{'ICONIC'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-iconic';
+    }
+  }
+
+### main_set_resources()
+  if ($Opt{'RV'}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
+      push @rl, '-rv';
+    }
+  }
+
+  if (@{$Opt{'XRM'}}) {
+    if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi|xpdf)$/) {
+      foreach (@{$Opt{'XRM'}}) {
+       push @rl, '-xrm', $_;
+      }
+    }
+  }
+
+  if (@title) {
+    if ($prog =~ /^(gxditview|xditview)$/) {
+      push @rl, '-title', $Output_File_Name;
+    }
+  }
+
+  my $args = join ' ', @rl;
+  if ($Display{'ARGS'}) {
+    $Display{'ARGS'} = "$args $Display{'ARGS'}";
+  } else {
+    $Display{'ARGS'} = $args;
+  }
+
+  1;
+}                              # main_set_resources()
+
+
+########################################################################
+# set resources
+########################################################################
+
+my $groggy;
+my $modefile;
+my $addopts;
+
+##########
+# main_display ()
+#
+# Do the actual display of the whole thing.
+#
+# Globals:
+#   in: $Display{MODE}, $Opt{DEVICE}, @Addopts_Groff,
+#       $fh_cat, $tmp_cat, $Opt{PAGER}, $Output_File_Name
+#
+sub main_display {
+  $addopts = join ' ', @Addopts_Groff;
+
+  if (-z $tmp_cat) {
+    warn "groffer: empty input\n";
+    &clean_up();
+    return 1;
+  }
+
+  $modefile = $Output_File_Name;
+
+  # go to the temporary directory to be able to access internal data files
+  chdir $tmpdir;
+
+### main_display()
+ SWITCH: foreach ($Display{'MODE'}) {
+    /^groff$/ and do {
+      push @Addopts_Groff, "-T$Opt{'DEVICE'}" if $Opt{'DEVICE'};
+      $addopts = join ' ', @Addopts_Groff;
+      $groggy = `cat $tmp_cat | grog`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_opt_V();
+      unlink $modefile;
+      rename $tmp_cat, $modefile;
+      system("cat $modefile | $groggy $addopts");
+      &clean_up();
+      next SWITCH;
+    };                         # /groff/
+
+    /^(text|tty)$/ and do {
+      my $device;
+      if (! $Opt{'DEVICE'}) {
+       $device = $Opt{'TEXT_DEVICE'};
+       $device = $Default_tty_Device unless $device;
+      } elsif ($Opt{'DEVICE'} =~ /^(ascii||cp1047|latin1|utf8)$/) {
+       $device = $Opt{'DEVICE'};
+      } else {
+       warn "main_display(): wrong device for $Display{'MODE'} mode: " .
+         "$Opt{'DEVICE'}";
+      }
+      $groggy = `cat $tmp_cat | grog -T$device`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      if ($Display{'MODE'} eq 'text') {
+       &_do_opt_V();
+       system("cat $tmp_cat | $groggy $addopts");
+       &clean_up();
+       next SWITCH;
+      }
+
+### main_display()
+      # mode is not 'text', but `tty'
+      my %pager;
+      my @p;
+      push @p, $Opt{'PAGER'} if $Opt{'PAGER'};
+      push @p, $ENV{'PAGER'} if $ENV{'PAGER'};
+      foreach (@p) {
+       %pager = &where_is_prog($_);
+       next unless %pager;
+       if ($pager{'file'} eq 'less') {
+         if ($pager{'args'}) {
+           $pager{'args'} = "-r -R $pager{'args'}";
+         } else {
+           $pager{'args'} = '-r -R';
+         }
+       }
+       last if $pager{'file'};
+      }                                # foreach @p
+      unless (%pager) {
+       foreach (@{$Viewer_tty{'TTY'}}, @{$Viewer_X{'TTY'}}, 'cat') {
+         next unless $_;
+         %pager = &where_is_prog($_);
+         last if %pager;
+       }
+      }
+      die "main_display(): no pager program found for tty mode;"
+       unless %pager;
+      &_do_opt_V();
+      system("cat $tmp_cat | $groggy $addopts | " .
+            "$pager{'fullname'} $pager{'args'}");
+      &clean_up();
+      next SWITCH;
+    };                         # /text|tty/
+
+    /^source$/ and do {
+      open $fh_cat, "<$tmp_cat";
+      foreach (<$fh_cat>) {
+       print "$_";
+      }
+      &clean_up();
+      next SWITCH;
+    };
+
+### main_display()
+    /^dvi$/ and do {
+      if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'dvi') {
+       warn "main_display(): " .
+         "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
+      }
+      $modefile .= '.dvi';
+      $groggy = `cat $tmp_cat | grog -Tdvi`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_display();
+      next SWITCH;
+    };
+
+    /^html$/ and do {
+      if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'html') {
+       warn "main_display(): " .
+         "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
+      }
+      $modefile .= '.html';
+      $groggy = `cat $tmp_cat | grog -Thtml`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_display();
+      next SWITCH;
+    };
+
+    /^pdf$/ and do {
+      if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'ps') {
+       warn "main_display(): " .
+         "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
+      }
+      $modefile .= '.ps';
+      $groggy = `cat $tmp_cat | grog -Tps`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_display(\&_make_pdf);
+      next SWITCH;
+    };
+
+### main_display()
+    /^ps$/ and do {
+      if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'ps') {
+       warn "main_display(): " .
+         "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
+      }
+      $modefile .= '.ps';
+      $groggy = `cat $tmp_cat | grog -Tps`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_display();
+      next SWITCH;
+    };
+
+    /^x$/ and do {
+      my $device;
+      if ($Opt{'DEVICE'} && $Opt{'DEVICE'} =~ /^X/) {
+       $device = $Opt{'DEVICE'};
+      } else {
+       if ($Opt{'RESOLUTION'} == 100) {
+         if ( $Display{'PROG'} =~ /^(g|)xditview$/ ) {
+           # add width of 800dpi for resolution of 100dpi to the args
+           $Display{'ARGS'} .= ' -geometry 800';
+           $Display{'ARGS'} =~ s/^ //;
+         }
+       } else {                # RESOLUTIOM != 100
+         $device = 'X75-12';
+       }                       # if RESOLUTIOM
+      }                                # if DEVICE
+      $groggy = `cat $tmp_cat | grog -T$device -Z`;
+      die "main_display(): grog error;" if $?;
+      chomp $groggy;
+      print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      &_do_display();
+      next SWITCH;
+    };
+
+### main_display()
+    /^X$/ and do {
+      if (! $Opt{'DEVICE'}) {
+       $groggy = `cat $tmp_cat | grog -X`;
+       die "main_display(): grog error;" if $?;
+       chomp $groggy;
+       print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      } elsif ($Opt{'DEVICE'} =~ /^(X.*|dvi|html|lbp|lj4|ps)$/) {
+       # these devices work with
+       $groggy = `cat $tmp_cat | grog -T$Opt{'DEVICE'} -X`;
+       die "main_display(): grog error;" if $?;
+       chomp $groggy;
+       print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      } else {
+       warn "main_display(): wrong device for " .
+         "$Display{'MODE'} mode: $Opt{'DEVICE'};";
+       $groggy = `cat $tmp_cat | grog -Z`;
+       die "main_display(): grog error;" if $?;
+       chomp $groggy;
+       print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
+      }                                # if DEVICE
+      &_do_display();
+      next SWITCH;
+    };
+
+    /^.*$/ and do {
+      die "main_display(): unknown mode `$Display{'MODE'}';";
+    };
+
+  }                            # SWITCH
+  1;
+} # main_display()
+
+
+########################
+# _do_display ([<prog>])
+#
+# Perform the generation of the output and view the result.  If an
+# argument is given interpret it as a function name that is called in
+# the midst (actually only for `pdf').
+#
+sub _do_display {
+  &_do_opt_V();
+  unless ($Display{'PROG'}) {
+    system("$groggy $addopts $tmp_cat");
+    &clean_up();
+    return 1;
+  }
+  unlink $modefile;
+  die "_do_display(): empty output;" if -z $tmp_cat;
+  system("cat $tmp_cat | $groggy $addopts >$modefile");
+  die "_do_display(): empty output;" if -z $modefile;
+  &print_times("before display");
+  if ($_[0] && ref($_[0]) eq 'CODE') {
+    $_[0]->();
+  }
+  unlink $tmp_cat unless $Debug{'KEEP'};
+
+  if ( $Opt{'STDOUT'} ) {
+    my $fh;
+    open $fh, "<$modefile";
+    foreach (<$fh>) {
+      print;
+    }
+    close $fh;
+    return 1;
+  }
+
+  if ($Viewer_Background) {
+    if ($Debug{'KEEP'}) {
+      exec "$Display{'PROG'} $Display{'ARGS'} $modefile &";
+    } else {
+      exec "{ $Display{'PROG'} $Display{'ARGS'} $modefile; " .
+       "rm -rf $tmpdir; } &";
+    }
+  } else {
+    system("$Display{'PROG'} $Display{'ARGS'} $modefile");
+    &clean_up();
+  }
+} # _do_display() of main_display()
+
+
+#############
+# _do_opt_V ()
+#
+# Check on option `-V'; if set print the corresponding output and leave.
+#
+# Globals: @ARGV, $Display{MODE}, $Display{PROG},
+#          $Display{ARGS}, $groggy,  $modefile, $addopts
+#
+sub _do_opt_V {
+  if ($Opt{'V'}) {
+    $Opt{'V'} = 0;
+    print "Parameters: @ARGV\n";
+    print "Display Mode: $Display{'MODE'}\n";
+    print "Output file: $modefile\n";
+    print "Display prog: $Display{'PROG'} $Display{'ARGS'}\n";
+    print "Output of grog: $groggy $addopts\n";
+    my $res = `$groggy $addopts\n`;
+    chomp $res;
+    print "groff -V: $res\n";
+    exit 0;
+  }
+  1;
+} # _do_opt_V() of main_display()
+
+##############
+# _make_pdf ()
+#
+# Transform to pdf format; for pdf mode in _do_display().
+#
+# Globals: $md_modefile (from main_display())
+#
+sub _make_pdf {
+  die "_make_pdf(): pdf mode did not work;" if $PDF_Did_Not_Work;
+  my $psfile = $modefile;
+  die "_make_pdf(): empty output;" if -z $modefile;
+  $modefile =~ s/\.ps$/.pdf/;
+  unlink $modefile;
+  my $done;
+  if ($PDF_Has_ps2pdf) {
+    system("ps2pdf $psfile $modefile 2>$Dev_Null");
+    $done = ! $?;
+  }
+  if (! $done && $PDF_Has_gs) {
+    system("gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite " .
+       "-sOutputFile=$modefile -c save pop -f $psfile 2>$Dev_Null");
+    $done = ! $?;
+  }
+  if (! $done) {
+    $PDF_Did_Not_Work = 1;
+    warn '_make_pdf(): Could not transform into pdf format, ' .
+      'the Postscript mode (ps) is used instead;';
+    $Opt{'MODE'} = 'ps';
+    &main_set_mode();
+    &main_set_resources();
+    &main_display();
+    exit 0;
+  }
+  unlink $psfile unless $Debug{'KEEP'};
+  1;
+} # _make_pdf() of main_display()
+
+
+########################################################################
+
+&main_set_options();
+&main_parse_MANOPT();
+&main_config_params();
+&main_parse_params();
+&main_set_mode();
+&main_temp();
+&main_do_fileargs();
+&main_set_resources();
+&main_display();
+
+&clean_up();
+
+1;
+########################################################################
+### Emacs settings
+# Local Variables:
+# mode: CPerl
+# End:

Index: man.pl
===================================================================
RCS file: man.pl
diff -N man.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ man.pl      11 Aug 2013 08:28:52 -0000      1.9
@@ -0,0 +1,731 @@
+#! /usr/bin/env perl
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/perl/man.pl
+# Installed position: <prefix>/lib/groff/groffer/man.pl
+
+# Copyright (C) 2006, 2009, 2011 Free Software Foundation, Inc.
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 27 Jan 2011
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+use strict;
+use warnings;
+
+########################################################################
+# functions for apropos, man, whatis
+########################################################################
+
+##########
+# apropos_filespec()
+#
+# Compose temporary file for filspec.
+#
+# Globals:  in: $main::Opt{'APROPOS'}, $main::Special_Setup, 
$main::Filespec_Arg,
+#               $main::Apropos_Prog, $main::Opt{'APROPOS_SECTIONS'}, 
$main::Opt{'SECTIONS'}
+#          out: $main::Special_Filespec
+#
+sub apropos_filespec {
+  return 0 unless $main::Opt{'APROPOS'};
+  die 'apropos_filespec(): apropos_setup() must be run first;'
+    unless $main::Special_Setup;
+  die 'apropos_filespec(): no $main::Filespec_Arg is set;'
+    unless defined $main::Filespec_Arg;
+  $main::Special_Filespec = 1;
+
+  my $s;
+  if ($main::No_Filespecs) {
+    &to_tmp_line('.SH no filespec');
+    $s = `$main::Apropos_Prog`;
+    $s =~ s/^/\\\&/;
+    &to_tmp_line($s);
+    return 1;
+  }
+
+  $s = $main::Filespec_Arg;
+  $s =~ s/[^\\]-/\\-/g;
+  &to_tmp_line(".SH $s");
+
+  if ( $main::Opt{'APROPOS_SECTIONS'} ) {
+    $s = qr/^[^\(]*\([$main::Opt{'APROPOS_SECTIONS'}]/;
+  } else {
+    if ( $main::Opt{'SECTIONS'} ) {
+      $s = $main::Opt{'SECTIONS'};
+      $s = qr/^[^\(]*\([$s]/;
+    } else {
+      $s = qr/^.*\(.+\).*$/;
+    }
+  }
+
+### apropos_filespec()
+  my $filespec = $main::Filespec_Arg;
+  $filespec =~ s#/#\\/#g;
+  $filespec =~ s#\.#\\./#g;
+  my @ap;
+  foreach ( `$main::Apropos_Prog $main::Filespec_Arg 2>$main::Dev_Null` ) {
+    chomp;
+    if (/^$filespec:\s/) {     # for error messages of this script
+      my $line = $_;
+      $line =~ s/^(.*)$/\\\&$1/s;
+      push @ap, $line;
+    }
+    if (/$s/) {
+      push @ap, $_;
+    }
+  }
+  my @res;
+  foreach (sort @ap) {
+    s/^
+      ([^\(]+\(+[$main::Man{'AUTO_SEC_CHARS'}][^\)]*\)+)
+      (\s*-*)*\s*
+      (.*)
+      $/.br\n.TP 15\n.BR "$1"\n\\\&$3\n/sx;
+    push @res, $_;
+  }
+  &to_tmp_line(@res);
+  1;
+}                              # apropos_filespec()
+
+
+##########
+# apropos_setup()
+#
+# Setup for the --apropos* options, just 2 global variables are set.
+#
+# Globals:  in: $main::Opt{'APROPOS'}
+#          out: $main::Special_Setup, $main::Apropos_Prog
+#
+sub apropos_setup {
+  return 0 unless $main::Opt{'APROPOS'};
+  if ( &where_is_prog('apropos') ) {
+    $main::Apropos_Prog = 'apropos';
+  } elsif ( &where_is_prog('man') ) {
+    if (! system("man --apropos man >$main::Dev_Null 2>$main::Dev_Null")) {
+      $main::Apropos_Prog = 'man --apropos';
+    } elsif (! system("man -k man >$main::Dev_Null 2>$main::Dev_Null")) {
+      $main::Apropos_Prog = 'man --k';
+    }
+  }                            # test man
+  die 'apropos_setup(): no apropos program available;'
+    unless $main::Apropos_Prog;
+  &to_tmp_line('.TH GROFFER APROPOS');
+  $main::Special_Setup = 1;
+  $main::Opt{'TITLE'} = 'apropos' unless $main::Opt{'TITLE'};
+  1;
+}                              # apropos_setup()
+
+
+##########
+# is_man(<man_sec_ext-hash-ref>)
+#
+# Test whether the argument hash exists as man page (from is_man()).
+#
+# Globals: in: $main::Man{AUTO_SEC_CHARS},$main::Man{SEC_CHARS},
+#              $main::Man{EXT}, $tmpdir
+#         out: $main::Manspec
+#
+# Arguments: 1, a hash reference with keys 'name', 'sec', 'ext', where
+#               'sec' is a string of one or several section characters
+#
+sub is_man {
+  my $n = @_;
+  die "is_man(): one argument is needed, you used $n;"
+    unless $n == 1;
+  die "is_man(): the argument is not a hash reference `$_[0]';"
+    if ref($_[0]) ne 'HASH';
+  die 'is_man(): temporary directory is not set;' unless $main::tmpdir;
+  die 'is_man(): man_setup() must be run first;' unless $main::Man{'IS_SETUP'};
+
+  my $name = $_[0]->{'name'};
+  unless ($name) {
+    $main::Manspec = '';
+    return 0;
+  }
+
+  my $sec;
+  $sec = $_[0]->{'sec'};
+  $sec = $main::Man{'SEC_CHARS'} unless $sec;
+  $sec = $main::Man{'AUTO_SEC_CHARS'} unless $sec;
+  $sec = '' unless defined $sec;
+  # take care, $sec may be several sections
+
+### is_man()
+  my $ext;
+  $ext = $_[0]->{'ext'};
+  $ext = $main::Man{'EXT'} unless $ext;
+  $ext = '' unless defined $ext;
+
+  $main::Manspec = "$name.$sec,$ext";
+  my @m;
+  if (exists $main::Man{'MANSPEC'}{$main::Manspec}) {
+    return 1;
+  } else {
+    foreach my $p ( @{$main::Man{'PATH'}} ) {
+      foreach my $s (split //, $sec) {
+       my $dir = File::Spec->catdir($p, "man$s");
+       next unless -d $dir;
+       my $file = File::Spec->catfile($dir, "$name.$s$ext");
+       push @m, glob("$file*");
+      }
+    }
+    $main::Man{'MANSPEC'}{$main::Manspec} = address@hidden;
+  }
+  return 0 unless (@m);
+  return 1;
+} # is_man()
+
+
+##########
+# man_get (<man_sec_ext-hash-ref>)
+#
+# Write a man page to the temporary file.
+#
+# Globals in: $main::Manspec, $main::Man{MANSPEC}, $main::Man{SEC_CHARS},
+#             $main::Man{EXT}, $main::Man{ALL}
+#
+# Arguments: 1, a hash reference with keys 'name', 'sec', 'ext', where
+#               'sec' is a string of one or several section characters
+#
+sub man_get {
+  my $n = @_;
+  die "man_get(): one argument is needed, you used $n;"
+    unless $n == 1;
+  die "man_get(): the argument is not a hash reference `$_[0]';"
+    if ref($_[0]) ne 'HASH';
+  die "man_get(): is_man() must be run first on the argument;"
+    unless $main::Manspec;
+  die "man_get(): wrong hash reference `$_[0]', no 'name' key;"
+    unless exists $_[0]->{'name'};
+
+  my ($name, $sec, $ext, $f, $path);
+  $name = $_[0]->{'name'};
+  die "man_get(): empty 'name' key in the argument;" unless $name;
+
+  $sec = $_[0]->{'sec'};
+  $sec = $main::Man{'SEC_CHARS'} if (! $sec) and $main::Man{'SEC_CHARS'};
+  $sec = '' unless defined $sec;
+  # take care $sec may be several sections
+
+### man_get()
+  $ext = $_[0]->{'ext'};
+  $ext = $main::Man{'EXT'} unless $ext;
+  $ext = '' unless defined $ext;
+
+  die 'man_get(): $main::Manspec does not suit the arguments;'
+    if ($main::Manspec ne "$name.$sec,$ext") and
+      (! exists $main::Man{'MANSPEC'}{$main::Manspec});
+
+  if ($main::Man{'ALL'}) {
+    my $ok;
+    my %list;
+    foreach ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+      next if exists $list{$_};
+      if (-f $_ and -r $_) {
+       $list{$_} = 1;
+       &to_tmp($_);
+       $ok = 1;
+      }
+    }
+    &register_title("man:$name") if $ok;
+    return 1;
+  }
+
+  # not $main::Man{'ALL'}
+
+  if ($_[0]->{'sec'}) {
+    my $path = File::Spec->catfile('', "man$sec", $name);
+    if ($ext) {
+      foreach $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+       if ($f =~ m#$path\.$sec$ext($|\..*$)#) {
+         if (-f $f && -r $f) {
+           &register_file($f);
+           return 1;
+         }
+       }                       # if $f =~
+      }                                # foreach $f
+### man_get()
+      foreach $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+       if ($f =~ m#$path\.$sec$ext.*$#) {
+         if (-f $f && -r $f) {
+           &register_file($f);
+           return 1;
+         }
+       }                       # if $f =~
+      }                                # foreach $f
+    } else {                   # $ext is empty
+      foreach $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+       if ($f =~ m#$path\.$sec($|\..*$)#) {
+         if (-f $f && -r $f) {
+           #       &to_tmp($f) && &register_file($f);
+           &register_file($f);
+           return 1;
+         }
+       }                       # if $f =~
+      }                                # foreach $f
+      foreach $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+       if ($f =~ m#$path\.$sec.*$#) {
+         if (-f $f && -r $f) {
+           #       &to_tmp($f) && &register_file($f);
+           &register_file($f);
+           return 1;
+         }
+       }                       # if $f =~
+      }                                # foreach $f
+    }                          # if $ext
+### man_get()
+  } else {                     # sec is empty
+    my $m = $main::Man{'SEC_CHARS'};
+    $m = $main::Man{'AUTO_SEC_CHARS'} unless $m;
+    foreach my $s (split //, $m) {
+      my $path = File::Spec->catfile('', "man$s", $name);
+      unless ($ext) {
+       foreach my $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+         if ( $f =~ m#$path\.$s($|\..*$)# ) {
+           if (-f $f && -r $f) {
+             #       &to_tmp($f) && &register_file($f);
+             &register_file($f);
+             return 1;
+           }
+         }                     # if $f =~
+       }                       # foreach $f
+      }                                # unless $ext
+      foreach $f ( @{$main::Man{'MANSPEC'}{$main::Manspec}} ) {
+       if ($f =~ m#$path\.$s$ext.*$#) {
+         if (-f $f && -r $f) {
+           #       &to_tmp($f) && &register_file($f);
+           &register_file($f);
+           return 1;
+         }
+       }                       # if $f =~
+      }                                # foreach $f
+    }                          # foreach $s
+  }                            # if sec
+
+  1;
+} # man_get()
+
+
+##########
+# man_setup ()
+#
+# Setup the variables in %MAN needed for man page searching.
+#
+# Globals:
+#   in:     %OPT, $LANG, $LC_MESSAGES, $LC_ALL,
+#           $MANPATH, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
+#   out:    $main::Man{PATH}, $main::Man{LANG}, $main::Man{LANG2}, 
$main::Man{SYS},
+#           $main::Man{SEC}, $main::Man{ALL}
+#   in/out: $main::Man{ENABLE}
+#
+# The precedence for the variables related to `man' is that of GNU
+# `man', i.e.
+#
+# $LANG; overridden by
+# $LC_MESSAGES; overridden by
+# $LC_ALL; this has the same precedence as
+# $MANPATH, $MANSEC, $PAGER, $SYSTEM; overridden by
+# $MANOPT; overridden by
+# the groffer command line options.
+#
+# $MANROFFSEQ is ignored because grog determines the preprocessors.
+#
+sub man_setup {
+  return 1 if $main::Man{'IS_SETUP'};
+  $main::Man{'IS_SETUP'} = 1;
+  return 1 unless $main::Man{'ENABLE'};
+
+  # determine basic path for man pages
+  my $path;
+  if (defined $main::Opt{'MANPATH'}) {
+    $path = $main::Opt{'MANPATH'};
+  } elsif ($ENV{'MANPATH'}) {
+    $path = $ENV{'MANPATH'};
+  } elsif ( &where_is_prog('manpath') ) {
+    $path = `manpath 2>$main::Dev_Null`;
+  }
+  if ($path) {
+    chomp $path;
+    $main::Man{'PATH'} = [split /:/, $path];
+  } else {
+    $main::Man{'PATH'} = [];
+    &manpath_set_from_path();
+  }
+  unless ( @{$main::Man{'PATH'}} ) {
+    $main::Man{'ENABLE'} = 0;
+    warn "man_setup(): man path is empty;";
+    return 1;
+  }
+
+### man_setup()
+  # make man path list consisting of unique existing directories
+  @{$main::Man{'PATH'}} = &path_uniq( @{$main::Man{'PATH'}} );
+
+  unless ($main::Man{'ALL'}) {
+    $main::Man{'ALL'} = $main::Opt{'ALL'} ? 1 : 0;
+  }
+
+  # handle man systems
+  my $sys = $ENV{'SYSTEM'};
+  $sys = $main::Opt{'SYSTEMS'} if $main::Opt{'SYSTEMS'};
+  if ($sys) {
+    chomp $sys;
+    $main::Man{'SYS'} = [split /,/, $sys];
+  } else {
+    $main::Man{'SYS'} = [];
+    $sys = '';
+  }
+
+### man_setup()
+  # handle language
+  my $lang = '';
+  $lang = $main::Opt{'LANG'} if $main::Opt{'LANG'};
+  unless ($lang) {
+    foreach ('LC_ALL', 'LC_MESSAGES', 'LANG') {
+      if ($ENV{$_}) {
+       $lang = $ENV{$_};
+       last;
+      }
+    }
+  }
+  if ($lang) {
+    if ($lang eq 'C' or $lang eq 'POSIX') {
+      $main::Man{'LANG'} = '';
+      $main::Man{'LANG2'} = '';
+    } elsif ($lang =~ /^.$/) {
+      $main::Man{'LANG'} = $lang;
+      $main::Man{'LANG2'} = '';
+    } elsif ($lang =~ /^..$/) {
+      $main::Man{'LANG'} = $lang;
+      $main::Man{'LANG2'} = $lang;
+    } else {
+      $main::Man{'LANG'} = $lang;
+      $main::Man{'LANG2'} = $lang;
+      $main::Man{'LANG2'} =~ s/^(..).*$/$1/;
+    }
+  }                            # if ($lang)
+  # from now on, use only $main::Man{LANG*}, forget about $main::Opt{LANG}, 
$ENV{LC_*}.
+
+  &manpath_add_lang_sys();
+
+### man_setup()
+  # section
+  my $sec;
+  $sec = $main::Opt{'SECTIONS'} if $main::Opt{'SECTIONS'};
+  unless ($sec) {
+    $sec = $ENV{'MANSEC'} if $ENV{'MANSEC'};
+  }
+  $main::Man{'SEC'} = [];
+  $main::Man{'SEC_CHARS'} = '';
+  if ($sec) {
+    foreach (split /:/, $sec) {
+      push @{$main::Man{'SEC'}}, $_ if /^[$main::Man{'AUTO_SEC_CHARS'}]$/;
+    }
+    $main::Man{'SEC_CHARS'} = join '', @{$main::Man{'SEC'}} if 
@{$main::Man{'SEC'}};
+  }                            # if ($sec)
+
+  # extension
+  my $ext = '';
+  $ext = $main::Opt{'EXTENSION'} if $main::Opt{'EXTENSION'};
+  unless ($ext) {
+    $ext = $ENV{'EXTENSION'} if $ENV{'EXTENSION'};
+  }
+  $main::Man{'EXT'} = $ext;
+
+  # creation of man temporary is omitted, because of globs in perl
+  1;
+} # man_setup()
+
+
+##########
+# manpath_add_lang_sys()
+#
+# Add language and operating system specific directories to man path.
+#
+# Globals:
+#   in:     $main::Man{SYS}: a list of names of operating systems.
+#           $main::Man{LANG} and $main::Man{LANG2}: each a single name
+#   in/out: @{$main::Man{PATH}}: list of directories which shall have the 
`man?'
+#           subdirectories.
+#
+sub manpath_add_lang_sys {
+  return 1 unless $main::Man{'PATH'};
+  return 1 unless @{$main::Man{'PATH'}};
+
+  my @mp;
+
+  if ( @{$main::Man{'SYS'}} ) {
+    foreach ( @{$main::Man{'SYS'}} ) {
+      if ($_ eq 'man') {
+       @mp = (@mp, @{$main::Man{'PATH'}});
+      } elsif ($_) {
+       my $sys = $_;
+       foreach my $p (@{$main::Man{'PATH'}}) {
+         my $dir = File::Spec->catdir($p, $sys);
+         push @mp, $dir;
+       }
+      }                                # if eq 'man'
+    }                          # foreach SYS
+  } else {                     # no SYS
+    @mp = @{$main::Man{'PATH'}};
+  }
+
+  if (@mp && $main::Man{'LANG'}) {
+    my @lang_path;
+    my $man_lang2 = '';
+    $man_lang2 = $main::Man{'LANG2'} if $main::Man{'LANG'} ne 
$main::Man{'LANG2'};
+    foreach my $i ($main::Man{'LANG'}, $man_lang2) {
+      next unless $i;
+      my $lang = $i;
+      foreach my $p (@mp) {
+       my $dir = File::Spec->catdir($p, $lang);
+       push @lang_path, $dir;
+      }                                # foreach $p
+    }                          # foreach $i
+    @mp = (@lang_path, @mp);
+  }                            # if $mp
+
+  $main::Man{PATH} = [&path_uniq(@mp)];
+  1;
+} # manpath_add_lang_sys()
+
+
+##########
+# manpath_set_from_path()
+#
+# Determine basic search path for man pages from $PATH.
+#
+# Return:    `1' if a valid man path was retrieved.
+# Output:    none
+# Globals:
+#   in:  $PATH
+#   out: $_MAN_PATH
+#
+sub manpath_set_from_path {
+  my @path =
+    qw( /usr/local /usr /usr/X11R6 /usr/openwin /opt /opt/gnome /opt/kde );
+  # get a basic man path from $ENV{PATH}
+  my @path2 = @main::Path;
+  foreach (@path2) {
+    s#bin/*$##;
+    push @path, $_;
+  }
+  @path = &path_uniq(@path);
+  foreach my $d (@path) {
+    foreach my $e ( File::Spec->catdir( qw(share man) ),
+                File::Spec->catdir( qw(share MAN) ),
+                'man',  'MAN' ) {
+      my $dir = File::Spec->catdir($d, $e);
+      push @{$main::Man{'PATH'}}, $dir if -d $dir;
+    }
+  }
+  1;
+} # manpath_set_from_path()
+
+
+##########
+# special_filespec()
+#
+# Handle special modes like whatis and apropos.  Run their filespec
+# functions if suitable.
+#
+# Globals:  in: $main::Opt{'APROPOS'}, $main::Opt{'WHATIS'}, 
$main::Special_Setup
+#          out: $main::Special_Filespec (internal)
+#
+sub special_filespec {
+  return 0 unless $main::Opt{'APROPOS'} || $main::Opt{'WHATIS'};
+  die 'special_filespec(): setup for apropos or whatis must be run first;'
+    unless $main::Special_Setup;
+  if ( $main::Opt{'APROPOS'} ) {
+    die "special_setup(): both apropos and whatis option variables are set;"
+      if $main::Opt{'WHATIS'};
+    return &apropos_filespec() ? 1 : 0;
+  }
+  if ( $main::Opt{'WHATIS'} ) {
+    return &whatis_filespec() ? 1 : 0;
+  }
+  0;
+} # special_filespec
+
+
+##########
+# special_setup()
+#
+# Handle special modes like whatis and apropos.  Run their setup
+# functions if suitable.
+#
+sub special_setup {
+  if ( $main::Opt{'APROPOS'} ) {
+    die "special_setup(): both --apropos and --whatis option variables " .
+      "are set;" if $main::Opt{'WHATIS'};
+    return &apropos_setup() ? 1 : 0;
+  }
+  if ( $main::Opt{'WHATIS'} ) {
+    return &whatis_setup() ? 1 : 0;
+  }
+  0;
+} # special_setup()
+
+
+##########
+# whatis_filename(<filename>)
+#
+# Interpret <filename> as a man page and display its `whatis'
+# information as a fragment written in the groff language.
+#
+# Globals:  in: $main::Opt{'WHATIS'}, $main::Special_Setup, 
$main::Special_Filespec,
+#               $main::Filespec_Arg
+#
+sub whatis_filename {
+  my $n = @_;
+  die "whatis_filename(): one argument is needed; you used $n;"
+    unless $n == 1;
+  die "whatis_filename(): whatis is not setup;" unless $main::Opt{'WHATIS'};
+  die "whatis_filename(): setup for whatis must be run first;"
+    unless $main::Special_Setup;
+  die "whatis_filename(): whatis_filespec() must be run first;"
+    unless $main::Special_Filespec;
+  die 'whatis_filename(): no $main::Filespec_Arg is set;'
+    unless defined $main::Filespec_Arg;
+
+  my $arg = $_[0];
+  die "whatis_file_name(): $arg is not an existing file" unless -f $arg;
+  die "whatis_file_name(): could not read file $arg" unless -r $arg;
+  return 1 if -z $arg;
+  $arg = 'stdin' if $main::Filespec_Arg eq '-';
+
+  &to_tmp_line('.br', '\\f[CR]' . $arg . '\\f[]:', '.br');
+
+### whatis_filename()
+  # get the parts of the file name according to the naming of man pages
+  my ($dir, $name) = &split_path( $_[0] );
+  my $section = $_[0];
+  my $path = File::Spec->catfile('', 'man');
+  $section =~ s#^.*$path([$main::Man{'AUTO_SEC_CHARS'}]).*$#$1#;
+  $section = '' if $section eq $_[0];
+  if ($section) {
+    if ($name =~ m#^.*\.$section.*$#) {
+      $name =~ s/^(.*)\.$section.*$/$1/;
+    } else {
+      $section = '';
+    }
+  }
+
+  # traditional man style; grep the line containing `.TH' macro, if any
+  my @catz = &cat_z($_[0]);
+  my $res;
+  my $test;
+  foreach (@catz) {
+    if (/^[\.']\s*TH\s/) {             # search .TH, traditional man style
+      $test = 1;
+      last;
+    }
+  }                            # foreach (@catz)
+### whatis_filename()
+  if ($test) {                 # traditional man style
+    # get the first line after the first `.SH' macro before the next `.SH'
+    my $test1;
+    foreach (@catz) {
+      if ($test1) {
+       chomp;
+       next unless $_;
+       next if /^[\.']?\s*$/;
+       last if /^[\.']/;               # especially for .SH
+       if ($res) {
+         $res = "$res $_";
+       } else {
+         $res = $_;
+       }
+      } else {                 # $test1 is empty
+       $test1 = 1 if (/^[\.']\s*SH\s/);
+      }                                # if ($test1)
+    }                          # foreach (@catz)
+
+    if ($section) {
+      if ($res =~ m|^
+                   $name
+                   \s
+                   [^-]*
+                   -
+                   \s*
+                   (.*)
+                   $|sx) {
+       $res = "$name ($section) \\[em] $1";
+      }
+    }                          # if ($section)
+### whatis_filename()
+    &to_tmp_line($res, '.br', '', '.br');
+    return 1;
+  }                            # if ($test)
+
+  # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
+  foreach (@catz) {
+    if (/^[\.']\s*Nd\s/) {             # BSD doc style
+      $res =~ s/^(.*)$/$name ($section) \\[em] $1/;
+      &to_tmp_line($res);
+      return 1;
+    }
+  }
+
+  &to_tmp_line('is not a man page', '.br', '', '.br');
+  1;
+} # whatis_filename()
+
+
+##########
+# whatis_filespec()
+#
+# Print the filespec name as .SH to the temporary cat file.
+#
+# Globals: in: $main::Opt{'WHATIS'}, $main::Filespec_Arg
+#      in/out: $main::Special_Filespec
+#
+sub whatis_filespec {
+  return 0 unless ($main::Opt{'WHATIS'});
+  die 'whatis_filespec(): whatis_setup() must be run first.'
+    unless $main::Special_Setup;
+  die 'whatis_filespec(): no $main::Filespec_Arg is set;'
+    unless defined $main::Filespec_Arg;
+  $main::Special_Filespec = 1;
+  my $arg = $main::Filespec_Arg;
+  $arg =~ s/[^\\]-/\\-/g;
+  to_tmp_line(".SH $arg");
+} # whatis_filespec()
+
+
+##########
+# whatis_setup ()
+#
+# Print the whatis header to the temporary cat file; this is the setup
+# for whatis.
+#
+# Globals:  in: $main::Opt{'WHATIS'}
+#          out: $main::Special_Setup
+sub whatis_setup {
+  if ( $main::Opt{'WHATIS'} ) {
+    &to_tmp_line('.TH GROFFER WHATIS');
+    $main::Special_Setup = 1;
+    $main::Opt{'TITLE'} = 'whatis' unless $main::Opt{'TITLE'};
+    return 1;
+  }
+  0;
+} # whatis_setup ()
+
+1;

Index: perl_test.pl
===================================================================
RCS file: perl_test.pl
diff -N perl_test.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ perl_test.pl        11 Aug 2013 08:28:52 -0000      1.6
@@ -0,0 +1,34 @@
+#! /usr/bin/env perl
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/perl/perl_test.sh
+# Installed position: <prefix>/lib/groff/groffer/perl_test.sh
+
+# Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 5 Jan 2009
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+# This file tests whether perl has a suitable version.  It is used by
+# groffer.pl and Makefile.sub.
+
+# require 5.004_05;
+require v5.6.1;

Index: roff2.pl
===================================================================
RCS file: roff2.pl
diff -N roff2.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ roff2.pl    11 Aug 2013 08:28:52 -0000      1.8
@@ -0,0 +1,223 @@
+#! /usr/bin/env perl
+
+# roff2* - transform roff files into other formats
+
+# Source file position: <groff-source>/contrib/groffer/perl/roff2.pl
+# Installed position: <prefix>/bin/roff2*
+
+# Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 5 Jan 2009
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+require v5.6;
+
+use strict;
+use warnings;
+use File::Spec;
+
+# temporary dir and files
+use File::Temp qw/ tempfile /;
+
+my $Dev_Null = File::Spec->devnull();
+my $Mode;
+my $Name;
+{
+  my ($v, $d);
+  ($v, $d, $Name) = File::Spec->splitpath($0);
+  die "wrong program name: $Name;"
+    if $Name !~ /^roff2[a-z]/;
+}
+$Mode = $Name;
+$Mode =~ s/^roff2//;
+
+my $Groff_Version = `groff --version 2>$Dev_Null`;
+die "$Name error: groff does not work;" if $?;
+my $Groffer_Version = `groffer --version 2>$Dev_Null`;
+my $Has_Groffer = ! $?;
+
+if ($Has_Groffer) {
+  foreach (@ARGV) {
+    last if $_ eq '--';
+    next if $_ eq '-';
+    if ($_ eq '-v' || '--version' =~ m|^$_|) {
+      print $Name, ' in ', $Groffer_Version;
+      exit 0;
+    }
+    if ($_ eq '-h' || '--help' =~ m|^$_|) {
+      &usage_with_groffer();
+      exit 0;
+    }
+  }
+  system('groffer', '--to-stdout', "--$Mode", @ARGV);
+  exit $?;
+} else {
+  my @filespec;
+  my $double_minus;
+  foreach (@ARGV) {
+    if ($double_minus) {
+      push @filespec, $_;
+      next;
+    }
+    if ($_ eq '--') {
+      $double_minus = 1;
+      next;
+    }
+    if ($_ eq '-') {
+      push @filespec, '-';
+      next;
+    }
+    if ($_ eq '-v' || '--version' =~ m|^$_|) {
+      print $Name, ' in ', $Groff_Version;
+      exit 0;
+    }
+    if ($_ eq '-h' || '--help' =~ m|^$_|) {
+      &usage_without_groffer();
+      exit 0;
+    }
+    if ($_ =~ /^-/) {
+      &error_no_groffer();
+      &error_no_options();
+      next;
+    }
+    if (-f && -r) {
+      push @filespec, $_;
+    } else {
+      &error_no_groffer();
+      print STDERR "$_ is not an existing, readable file.\n";
+    }
+  }
+
+  @filespec = ('-') unless @filespec;
+  my $has_stdin;
+  foreach (@filespec) {
+    if ($_ eq '-') {
+      $has_stdin =1;
+      last;
+    }
+  }
+
+  if ($has_stdin) {
+    my $tempdir;
+    foreach ($ENV{'GROFF_TMPDIR'}, $ENV{'TMPDIR'}, $ENV{'TMP'},
+            $ENV{'TEMP'}, $ENV{'TEMPDIR'},
+            File::Spec->catfile($ENV{'HOME'}, 'tmp')) {
+      if ($_ && -d $_ && -w $_) {
+       $tempdir = $_;
+       last;
+      }
+    }
+    my $template = $Name . '_XXXX';
+    my ($fh, $stdin);
+    if ($tempdir) {
+      ($fh, $stdin) = tempfile($template, UNLINK => 1, DIR => $tempdir) ||
+       die "$Name: could not create temporary file;";
+    } else {
+      ($fh, $stdin) = tempfile($template, UNLINK => 1) ||
+       die "$Name: could not create temporary file;";
+    }
+    open $fh, ">$stdin";
+    print $fh $_ foreach <STDIN>;
+
+    foreach (@filespec) {
+      $_ = $stdin if $_ eq '-';
+    }
+  }                            # if $has_stdin
+
+  my $grog;
+  my $groff_options = "-T$Mode";
+  $groff_options = '-TX75-12 -Z' if $Mode eq 'x';
+  $groff_options = '-Tlatin1' if $Mode eq 'text';
+  if ($Mode eq 'pdf') {
+    my $ps2pdf;
+    my @path = File::Spec->path();
+    foreach (@path) {
+      my $file = File::Spec->catfile($_, 'ps2pdf');
+      if (-f $file && -x $file) {
+       $ps2pdf = "$file -";
+       last;
+      }
+    }
+    unless ($ps2pdf) {
+      foreach (@path) {
+       my $file = File::Spec->catfile($_, 'gs');
+       if (-f $file && -x $file) {
+         $ps2pdf = $file . ' -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite ' .
+           '-sOutputFile=- -c save pop -f -';
+         last;
+       }
+      }
+    }
+    $grog = `grog -Tps @filespec`;
+    chomp $grog;
+    system("$grog | $ps2pdf");
+    exit $?;
+  } else {
+    $grog = `grog $groff_options @filespec`;
+    chomp $grog;
+    system($grog);
+    exit $?;
+  }
+}
+
+my $error_no_groffer;
+sub error_no_groffer {
+  return 1 if $error_no_groffer;
+  $error_no_groffer = 1;
+  print STDERR "$Name: groffer is not available.\n";
+}
+
+my $error_no_options;
+sub error_no_options {
+  return 1 if $error_no_options;
+  $error_no_groffer = 1;
+  print STDERR "$Name: groffer options are not allowed.\n";
+}
+
+sub usage_with_groffer {
+  print <<EOF;
+usage: $Name [option]... [--] [filespec]...
+
+-h | --help     print usage information
+-v | --version  print version information
+
+All other options are arbitrary options of `groffer'; the options
+override the behavior of this program.
+
+`filespec's are the same as in `groffer': either the names of
+existing, readable files or `-' for standard input or a search pattern
+for man pages.  No `filespec' assumes standard input automatically.
+EOF
+}
+
+sub usage_without_groffer {
+  print <<EOF;
+usage: $Name [option]... [--] [filespec]...
+
+-h | --help     print usage information
+-v | --version  print version information
+
+No other options are allowed because `groffer' is not available.
+
+The only `filespec's allowed are the names of existing, readable files
+or `-' for standard input.  No `filespec' assumes standard input
+automatically.
+EOF
+}

Index: split_env.sh
===================================================================
RCS file: split_env.sh
diff -N split_env.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ split_env.sh        11 Aug 2013 08:28:52 -0000      1.6
@@ -0,0 +1,48 @@
+#! /bin/sh
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/perl/split_env.sh
+# Installed position: <prefix>/lib/groff/groffer/split_env.sh
+
+# Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+# Written by Bernd Warken <address@hidden>.
+
+# Last update: 5 Jan 2009
+
+# This file is part of `groffer', which is part of `groff'.
+
+# `groff' is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# `groff' is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+# This file is called from groffer.pl.  The environment variable
+# of the name in $1 will be split at output.  The corresponding variable
+# must be exported before the call of groffer.pl.
+
+if test $# = 0
+then
+    echo 'split_env.sh was called without an argument.' >&2;
+else
+    eval v='"$'"$1"'"';
+    if test _"$v"_ != __
+    then
+       eval set x $v;
+       shift;
+       for i in "$@";
+         do
+         echo $i;
+       done;
+    fi;
+fi;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]