265 lines
7.1 KiB
Bash
265 lines
7.1 KiB
Bash
#!/bin/sh
|
|
#
|
|
# Emulate nroff with groff.
|
|
#
|
|
# Copyright 1992-2021 Free Software Foundation, Inc.
|
|
# 2019-2024 G. Branden Robinson
|
|
#
|
|
# Written by James Clark, Werner Lemberg, and G. Branden Robinson.
|
|
#
|
|
# This file is part of groff, the GNU roff typesetting system.
|
|
#
|
|
# groff is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License (GPL) 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/>.
|
|
|
|
# Screen out shells non-conforming with POSIX Issue 4 (1994).
|
|
badshell=yes
|
|
# Solaris 10 /bin/sh is so wretched that it not only doesn't support
|
|
# standard parameter expansion, but it also writes diagnostic messages
|
|
# to the standard output instead of standard error.
|
|
if [ -n "$SHELL" ]
|
|
then
|
|
"$SHELL" -c 'prog=${0##*/}' >/dev/null 2>&1 && badshell=
|
|
fi
|
|
|
|
if [ -n "$badshell" ]
|
|
then
|
|
prog=`basename $0`
|
|
else
|
|
prog=${0##*/}
|
|
fi
|
|
|
|
T=
|
|
Topt=
|
|
opts=
|
|
dry_run=
|
|
is_option_argument_pending=
|
|
|
|
usage="usage: $prog [-abcCDEhiIkpRStUVzZ] [-d ctext] [-d string=text] \
|
|
[-K fallback-encoding] [-m macro-package] [-M macro-directory] \
|
|
[-n page-number] [-o page-list] [-P postprocessor-argument] \
|
|
[-r cnumeric-expression] [-r register=numeric-expression] \
|
|
[-T output-device] [-w warning-category] [-W warning-category] \
|
|
[file ...]
|
|
usage: $prog {-v | --version}
|
|
usage: $prog --help"
|
|
|
|
summary="
|
|
Format documents for terminal devices with groff(1). See the nroff(1)
|
|
manual page."
|
|
|
|
# Break up option clusters into separate arguments.
|
|
newargs=
|
|
for arg
|
|
do
|
|
thisarg=$arg
|
|
while :
|
|
do
|
|
case $thisarg in
|
|
-[abCEikpRStUvzZ])
|
|
newargs="$newargs $thisarg"
|
|
break
|
|
;;
|
|
-[abCEikpRStUvzZ]*)
|
|
if test -n "$badshell"
|
|
then
|
|
# POSIX doesn't actually require $SHELL, but fortunately at
|
|
# least one craptastic non-conforming shell offers it.
|
|
echo "$prog: option cluster '$thisarg' not supported with" \
|
|
"POSIX-non-conforming shell '$SHELL'" >&2
|
|
exit 2
|
|
fi
|
|
remainder=${thisarg#-?}
|
|
thisarg=${thisarg%%$remainder}
|
|
newargs="$newargs $thisarg"
|
|
thisarg=-$remainder
|
|
;;
|
|
*)
|
|
newargs="$newargs $thisarg"
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
|
|
set -- $newargs
|
|
|
|
for arg
|
|
do
|
|
if [ -n "$is_option_argument_pending" ]
|
|
then
|
|
is_option_argument_pending=
|
|
opts="$opts $arg"
|
|
shift
|
|
continue
|
|
fi
|
|
|
|
# groff(1) options we don't support:
|
|
#
|
|
# -e because of historical clash in meaning.
|
|
# -s "
|
|
# -f because terminal devices don't support font families.
|
|
# -g because terminals don't do graphics. (Some do, but grotty(1)
|
|
# does not produce ReGIS or Sixel output. Yet we support `-p`.)
|
|
# -G "
|
|
# -j "
|
|
# -l because terminal output is not suitable for a print spooler.
|
|
# -L "
|
|
# -N because we don't support -e.
|
|
# -X because gxditview(1) doesn't support terminal documents (why?).
|
|
case $arg in
|
|
-c)
|
|
opts="$opts $arg -P-c" ;;
|
|
-h)
|
|
opts="$opts -P-h" ;;
|
|
-[eq] | -s*)
|
|
# ignore these options
|
|
;;
|
|
-[dDIKmMnoPrTwW])
|
|
is_option_argument_pending=yes
|
|
opts="$opts $arg" ;;
|
|
-[abCEikpRStUzZ] | -[dDIKMmrnoPwW]*)
|
|
opts="$opts $arg" ;;
|
|
-T*)
|
|
Topt=$arg ;;
|
|
-u*)
|
|
# -u is for Solaris compatibility and not otherwise documented.
|
|
#
|
|
# Solaris 2.2 through at least Solaris 9 'man' invokes
|
|
# 'nroff -u0 ... | col -x'. Ignore the -u0, since 'less' and
|
|
# 'more' interpret overstriking sequences. But disable SGR, since
|
|
# Solaris 'col' mishandles it.
|
|
opts="$opts -P-c" ;;
|
|
-V)
|
|
dry_run=yes ;;
|
|
-v | --version)
|
|
echo "GNU nroff (groff) version 1.24.1"
|
|
opts="$opts $arg" ;;
|
|
--help)
|
|
echo "$usage"
|
|
echo "$summary"
|
|
exit 0 ;;
|
|
--)
|
|
shift
|
|
break ;;
|
|
-)
|
|
break ;;
|
|
-*)
|
|
echo "$prog: usage error: invalid option '$arg'" >&2
|
|
echo "$usage" >&2
|
|
exit 2 ;;
|
|
*)
|
|
break ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -n "$is_option_argument_pending" ]
|
|
then
|
|
echo "$prog: usage error: option '$arg' requires an argument" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# Determine the -T option. Was a valid one specified?
|
|
case "$Topt" in
|
|
-Tascii | -Tlatin1 | -Tutf8)
|
|
T=$Topt ;;
|
|
esac
|
|
|
|
# -T option absent or invalid; try environment.
|
|
if [ -z "$T" ]
|
|
then
|
|
Tenv=-T$GROFF_TYPESETTER
|
|
case "$Tenv" in
|
|
-Tascii | -Tlatin1 | -Tutf8)
|
|
T=$Tenv ;;
|
|
esac
|
|
fi
|
|
|
|
# Finally, infer a -T option from the locale. Try 'locale charmap'
|
|
# first because it is the most reliable, then look at environment
|
|
# variables.
|
|
if [ -z "$T" ]
|
|
then
|
|
# The separate `exec` is to work around a ~2004 bug in Cygwin sh.exe.
|
|
case "`exec 2>/dev/null ; locale charmap`" in
|
|
UTF-8)
|
|
Tloc=utf8 ;;
|
|
ISO-8859-1 | ISO-8859-15)
|
|
Tloc=latin1 ;;
|
|
*)
|
|
# Some old shells don't support ${FOO:-bar} expansion syntax. We
|
|
# should switch to it when it is safe to abandon support for them.
|
|
case "${LC_ALL-${LC_CTYPE-${LANG}}}" in
|
|
*.UTF-8)
|
|
Tloc=utf8 ;;
|
|
iso_8859_1 | *.ISO-8859-1 | *.ISO8859-1 | \
|
|
iso_8859_15 | *.ISO-8859-15 | *.ISO8859-15)
|
|
Tloc=latin1 ;;
|
|
*)
|
|
case "$LESSCHARSET" in
|
|
utf-8)
|
|
Tloc=utf8 ;;
|
|
latin1)
|
|
Tloc=latin1 ;;
|
|
*)
|
|
Tloc=ascii ;;
|
|
esac ;;
|
|
esac ;;
|
|
esac
|
|
T=-T$Tloc
|
|
fi
|
|
|
|
# Load nroff-style character definitions too.
|
|
opts="-mtty-char$opts"
|
|
|
|
# Set up the 'GROFF_BIN_PATH' variable to be exported in the current
|
|
# 'GROFF_RUNTIME' environment.
|
|
|
|
GROFF_RUNTIME="${GROFF_BIN_PATH=/usr/bin}:"
|
|
export GROFF_BIN_PATH
|
|
|
|
# Let our test harness redirect us. See LC_ALL comment above.
|
|
groff=${GROFF_TEST_GROFF-groff}
|
|
|
|
# Note 1: It would be nice to apply the DRY ("Don't Repeat Yourself")
|
|
# principle here and store the entire command string to be executed into
|
|
# a variable, and then either display it or execute it. For example:
|
|
#
|
|
# cmd="PATH=... groff ... $@"
|
|
# ...
|
|
# printf "%s\n" "$cmd"
|
|
# ...
|
|
# eval $cmd
|
|
#
|
|
# Unfortunately, the shell is a nightmarish hellscape of quoting issues.
|
|
# Naïve attempts to solve the problem fail when arguments to nroff
|
|
# contain embedded whitespace or shell metacharacters. The solution
|
|
# below works with those, but there is insufficient quoting in -V (dry
|
|
# run) mode, such that you can't copy-and-paste the output of 'nroff -V'
|
|
# if you pass it a filename like foo"bar (with the embedded quotation
|
|
# mark) and expect it to run without further quoting.
|
|
#
|
|
# If POSIX adopts Bash's ${var@Q} or an equivalent, this issue can be
|
|
# revisited.
|
|
if [ -n "$dry_run" ]
|
|
then
|
|
echo PATH="$GROFF_RUNTIME$PATH" $groff $T $opts "$@"
|
|
else
|
|
PATH="$GROFF_RUNTIME$PATH" $groff $T $opts "$@"
|
|
fi
|
|
|
|
# Local Variables:
|
|
# fill-column: 72
|
|
# End:
|
|
# vim: set autoindent expandtab shiftwidth=2 softtabstop=2 textwidth=72:
|