#!/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 . # 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: