3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer.sh
7 # Copyright (C) 2001,2002,2003 Free Software Foundation, Inc.
8 # Written by Bernd Warken <bwarken@mayn.de>
10 # This file is part of groff.
12 # groff is free software; you can redistribute it and/or modify it
13 # under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2, or (at your option)
17 # groff is distributed in the hope that it will be useful, but WITHOUT
18 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 # License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with groff; see the file COPYING. If not, write to the
24 # Free Software Foundation, 59 Temple Place - Suite 330, Boston,
28 export _PROGRAM_VERSION
;
31 _PROGRAM_NAME
='groffer';
32 _PROGRAM_VERSION
='0.9.4';
33 _LAST_UPDATE
='22 Jan 2003';
35 # This program is installed with groff version @VERSION@.
37 ########################################################################
38 # Determine the shell under which to run this script;
39 # if `ash' is available restart the script using `ash';
40 # otherwise just go on.
42 if test "${_groffer_run}" != 'second'; then
43 # only reached during the first run of the script
49 _this
="@BINDIR@/${_PROGRAM_NAME}";
51 ###########################
52 # _get_opt_shell ("$@")
54 # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
55 # if so echo its argument.
61 case " ${GROFFER_OPT} $*" in
62 *\
--shell\
*|
*\
--shell=*)
64 eval set -- "${GROFFER_OPT}" '"$@"';
69 if test "$#" -ge 2; then
75 # delete up to first `=' character
76 _sh
="$(echo -n "$1" | sed -e 's/^[^=]*=//')";
88 ###########################
89 # _test_on_shell (<name>)
91 # Test whether <name> is a shell program of Bourne type (POSIX sh).
95 if test "$#" -le 0 ||
test "$1" = ''; then
98 # do not quote $1 to allow arguments
99 test "$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)" = 'ok';
102 # do the shell determination
103 _shell
="$(_get_opt_shell "$@
")";
104 if test "${_shell}" = ''; then
107 if _test_on_shell
"${_shell}"; then
108 _groffer_run
='second';
109 # do not quote $_shell to allow arguments
110 exec ${_shell} "${_this}" "$@";
114 # clean-up of shell determination
130 ########################################################################
131 # diagnostic messages
134 _DEBUG
='no'; # disable debugging information
135 #_DEBUG='yes'; # enable debugging information
138 _DEBUG_LM
='no'; # disable landmark messages
139 #_DEBUG_LM='yes'; # enable landmark messages
142 ########################################################################
144 ########################################################################
146 # Display groff files and man pages on X or tty, even when compressed.
151 # Input comes from either standard input or command line parameters
152 # that represent either names of exisiting roff files or standardized
153 # specifications for man pages. All of these can be compressed in a
154 # format that is decompressible by `gzip'.
156 # The following displaying modes are available:
157 # - Display formatted input with the X roff viewer `gxditview',
158 # - with a Prostcript viewer,
159 # - with a dvi viewer,
160 # - with a web browser.
161 # - Display formatted input in a text terminal using a text device.
162 # - Generate output for some groff device on stdout without a viewer.
163 # - Output only the source code without any groff processing.
164 # - Generate the troff intermediate output on standard output
165 # without groff postprocessing.
166 # By default, the program tries to display with `gxditview' (1); if
167 # this does not work, text display (2) is used.
172 # Error handling and exit behavior is complicated by the fact that
173 # `exit' can only escape from the current shell; trouble occurs in
174 # subshells. This was solved by sending kill signals, see
175 # $_PROCESS_ID and error().
180 # This shell script is compatible to the both the GNU and the POSIX
181 # shell and utilities. Care was taken to restrict the programming
182 # technics used here in order to achieve POSIX compatibility as far
183 # back as POSIX P1003.2 Draft 11.2 of September 1991.
185 # The only non-builtin used here is POSIX `sed'. This script was
186 # tested under `bash', `ash', and `ksh'. The speed under `ash' is
187 # more than double when compared to the larger shells.
189 # This script provides its own option parser. It is compatible to the
190 # usual GNU style command line (option clusters, long options, mixing
191 # of options and non-option file names), except that it is not
192 # possible to abbreviate long option names.
194 # The mixing of options and file names can be prohibited by setting
195 # the environment variable `$POSIXLY_CORRECT' to a non-empty value.
196 # This enables the rather wicked POSIX behavior to terminate option
197 # parsing when the first non-option command line argument is found.
200 ########################################################################
201 # Survey of functions defined in this document
202 ########################################################################
204 # The elements specified within paranthesis `(<>)' give hints to what
205 # the arguments are meant to be; the argument names are irrelevant.
207 # <>* arbitrarily many such arguments, incl. none
208 # <>+ one or more such arguments
211 # A function that starts with an underscore `_' is an internal
212 # function for some function. The internal functions are defined just
213 # after their corresponding function; they are not mentioned in the
221 # dirname_append (<path> [<dir...>])
222 # dirname_chop (<path>)
223 # do_filearg (<filearg>)
228 # get_first_essential (<arg>*)
230 # is_empty (<string>)
231 # is_equal (<string1> <string2>)
233 # is_not_empty (<string>)
234 # is_not_equal (<string1> <string2>)
235 # is_not_file (<name>)
236 # is_not_prog (<name>)
241 # list_append (<list> <element>...)
242 # list_check (<list>)
243 # list_from_args (<arg>...)
244 # list_from_cmdline (<s_n> <s_a> <l_n> <l_n> [<cmdline_arg>...])
245 # list_from_split (<string> <separator>)
246 # list_has (<list> <element>)
247 # list_has_not (<list> <element>)
248 # list_length (<list>)
249 # main_*(), see after the functions
250 # man_do_filespec (<filespec>)
252 # man_register_file (<file> [<name> [<section>]])
253 # man_search_section (<name> <section>)
255 # manpath_add_lang(<path> <language>)
256 # manpath_add_system()
257 # manpath_from_path ()
258 # normalize_args (<shortopts> <longopts> <arg>*)
260 # path_clean (<path>)
261 # path_contains (<path> <dir>)
262 # path_not_contains (<path> <dir>)
263 # path_split (<path>)
264 # register_file (<filename>)
265 # register_title (<filespec>)
268 # string_contains (<string> <part>)
269 # string_not_contains (<string> <part>)
271 # tmp_create (<suffix>?)
272 # to_tmp (<filename>)
274 # trap_set (<functionname>)
278 # whatis (<filename>)
282 ########################################################################
283 # Environment Variables
284 ########################################################################
286 # Environment variables that exist only for this file start with an
287 # underscore letter. Global variables to this file are written in
288 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
289 # start with an underline and use only lower case letters and
290 # underlines, e.g. $_local_variable .
292 # [A-Z]* system variables, e.g. $MANPATH
293 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
294 # _[a-z_]* temporary variables, e.g. $_manpath
296 # Due to incompatibilities of the `ash' shell, the name of loop
297 # variables in `for' must be single character
298 # [a-z] local loop variables, e.g. $i
301 ########################################################################
302 # External environment variables
304 # If these variables are exported here then the `ash' shell coughs
305 # when calling `groff' in `main_display()'.
307 if test "${GROFFER_EXPORT_EXTERNALS}" = 'yes'; then
309 # external system environment variables that are explicitly used
310 export DISPLAY
; # Presets the X display.
311 export LANG
; # For language specific man pages.
312 export LC_ALL
; # For language specific man pages.
313 export LC_MESSAGES
; # For language specific man pages.
314 export PAGER
; # Paging program for tty mode.
315 export PATH
; # Path for the programs called (: list).
317 # groffer native environment variables
318 export GROFFER_OPT
# preset options for groffer.
320 # all groff environment variables are used, see groff(1)
321 export GROFF_BIN_PATH
; # Path for all groff programs.
322 export GROFF_COMMAND_PREFIX
; # '' (normally) or 'g' (several troffs).
323 export GROFF_FONT_PATH
; # Path to non-default groff fonts.
324 export GROFF_TMAC_PATH
; # Path to non-default groff macro files.
325 export GROFF_TMPDIR
; # Directory for groff temporary files.
326 export GROFF_TYPESETTER
; # Preset default device.
328 # all GNU man environment variables are used, see man(1).
329 export MANOPT
; # Preset options for man pages.
330 export MANPATH
; # Search path for man pages (: list).
331 export MANROFFSEQ
; # Ignored because of grog guessing.
332 export MANSECT
; # Search man pages only in sections (:).
333 export SYSTEM
; # Man pages for different OS's (, list).
338 ########################################################################
339 # read-only variables (global to this file)
340 ########################################################################
369 # function return values; `0' means ok
; other values are error codes
378 _GOOD
='0'; # return ok
379 _BAD
='1'; # return negatively, error code `1'
380 _ERROR
='7'; # for syntax errors; no `-1' in `ash'
382 _ALL_EXIT
="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
388 # quasi-functions, call with `eval'
395 return_ok
="func_pop; return ${_OK}";
396 return_good
="func_pop; return ${_GOOD}";
397 return_bad
="func_pop; return ${_BAD}";
398 return_yes
="func_pop; return ${_YES}";
399 return_no
="func_pop; return ${_NO}";
400 return_error
="func_pop; return ${_ERROR}";
404 _CONFFILES
="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
406 export _DEFAULT_MODES
;
407 _DEFAULT_MODES
='ps,x,tty';
408 export _DEFAULT_RESOLUTION
;
409 _DEFAULT_RESOLUTION
='100';
411 export _DEFAULT_TTY_DEVICE
;
412 _DEFAULT_TTY_DEVICE
='latin1';
414 # _VIEWER_* viewer programs for different modes (only X is necessary)
415 # _VIEWER_* a comma-separated list of viewer programs (with options)
416 export _VIEWER_DVI
; # viewer program for dvi mode
417 export _VIEWER_PS
; # viewer program for ps mode
418 export _VIEWER_WWW_X
; # viewer program for www mode in X
419 export _VIEWER_WWW_TTY
; # viewer program for www mode in tty
420 _VIEWER_DVI
='xdvi,dvilx';
421 _VIEWER_PDF
='xpdf,acroread';
422 _VIEWER_PS
='gv,ghostview,gs_x11,gs';
423 _VIEWER_WWW
='mozilla,netscape,opera,amaya,arena';
424 _VIEWER_X
='gxditview,xditview';
426 # Search automatically in standard sections `1' to `8', and in the
427 # traditional sections `9', `n', and `o'. On many systems, there
428 # exist even more sections, mostly containing a set of man pages
429 # special to a specific program package. These aren't searched for
430 # automatically, but must be specified on the command line.
431 export _MAN_AUTO_SEC
;
432 _MAN_AUTO_SEC
="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
434 export _PROCESS_ID
; # for shutting down the program
438 ############ the command line options of the involved programs
440 # The naming scheme for the options environment names is
441 # $_OPTS_<prog>_<length>[_<argspec>]
443 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
444 # command line options)
445 # <length>: LONG (long options) or SHORT (single character options)
446 # <argspec>: ARG for options with argument, NA for no argument;
447 # without _<argspec> both the ones with and without arg.
449 # Each option that takes an argument must be specified with a
450 # trailing : (colon).
453 export _OPTS_GROFFER_SHORT_NA
;
454 export _OPTS_GROFFER_SHORT_ARG
;
455 export _OPTS_GROFFER_LONG_NA
;
456 export _OPTS_GROFFER_LONG_ARG
;
457 export _OPTS_GROFF_SHORT_NA
;
458 export _OPTS_GROFF_SHORT_ARG
;
459 export _OPTS_GROFF_LONG_NA
;
460 export _OPTS_GROFF_LONG_ARG
;
461 export _OPTS_MAN_SHORT_ARG
;
462 export _OPTS_MAN_SHORT_NA
;
463 export _OPTS_MAN_LONG_ARG
;
464 export _OPTS_MAN_LONG_NA
;
465 export _OPTS_GROFFER_LONG
;
466 export _OPTS_GROFFER_SHORT
;
467 export _OPTS_GROFF_LONG
;
468 export _OPTS_GROFF_SHORT
;
469 export _OPTS_CMDLINE_SHORT_NA
;
470 export _OPTS_CMDLINE_SHORT_ARG
;
471 export _OPTS_CMDLINE_SHORT
;
472 export _OPTS_CMDLINE_LONG_NA
;
473 export _OPTS_CMDLINE_LONG_ARG
;
474 export _OPTS_CMDLINE_LONG
;
477 ###### native groffer options
479 _OPTS_GROFFER_SHORT_NA
="'h' 'Q' 'v' 'V' 'X' 'Z'";
480 _OPTS_GROFFER_SHORT_ARG
="'T'";
482 _OPTS_GROFFER_LONG_NA
="'all' 'apropos' 'ascii' 'auto' 'default' 'dvi' \
483 'groff' 'help' 'intermediate-output' 'local-file' 'location' 'man' \
484 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'tty' 'tty-device' \
485 'version' 'whatis' 'where' 'www' 'x'";
487 _OPTS_GROFFER_LONG_ARG
="'background' 'bd' 'bg' 'bw' 'default-modes' \
488 'device' 'display' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
489 'foreground' 'geometry' 'locale' 'manpath' 'mode' 'pager' \
490 'pdf-viewer' 'ps-viewer' 'resolution' 'sections' 'shell' \
491 'systems' 'title' 'troff-device' 'www-viewer' 'xrm' 'x-viewer'";
493 ##### options inhereted from groff
495 _OPTS_GROFF_SHORT_NA
="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
496 'R' 's' 'S' 't' 'U' 'V' 'z'";
497 _OPTS_GROFF_SHORT_ARG
="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
499 _OPTS_GROFF_LONG_NA
="";
500 _OPTS_GROFF_LONG_ARG
="";
502 ###### man options (for parsing $MANOPT only)
504 _OPTS_MAN_SHORT_NA
="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
506 _OPTS_MAN_SHORT_ARG
="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
508 _OPTS_MAN_LONG_NA
="'all' 'ascii' 'apropos' 'catman' 'debug' 'default' \
509 'ditroff' 'help' 'local-file' 'location' 'troff' 'update' 'version' \
512 _OPTS_MAN_LONG_ARG
="'extension' 'locale' 'manpath' \
513 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
515 ###### collections of options
519 _OPTS_GROFFER_LONG
="${_OPTS_GROFFER_LONG_ARG} ${_OPTS_GROFFER_LONG_NA}";
520 _OPTS_GROFFER_SHORT
=\
521 "${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFFER_SHORT_NA}";
525 _OPTS_GROFF_LONG
="${_OPTS_GROFF_LONG_ARG} ${_OPTS_GROFF_LONG_NA}";
526 _OPTS_GROFF_SHORT
="${_OPTS_GROFF_SHORT_ARG} ${_OPTS_GROFF_SHORT_NA}";
528 # all command line options
530 _OPTS_CMDLINE_SHORT_NA
="\
531 ${_OPTS_GROFFER_SHORT_NA} ${_OPTS_GROFF_SHORT_NA}";
532 _OPTS_CMDLINE_SHORT_ARG
="\
533 ${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFF_SHORT_ARG}";
534 _OPTS_CMDLINE_SHORT
="${_OPTS_GROFFER_SHORT} ${_OPTS_GROFF_SHORT}";
536 _OPTS_CMDLINE_LONG_NA
="${_OPTS_GROFFER_LONG_NA} \
537 ${_OPTS_GROFF_LONG_NA} ${_OPTS_MAN_LONG_NA}";
538 _OPTS_CMDLINE_LONG_ARG
="${_OPTS_GROFFER_LONG_ARG} \
539 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG}";
540 _OPTS_CMDLINE_LONG
="${_OPTS_GROFFER_LONG} ${_OPTS_GROFF_LONG}";
543 ########################################################################
544 # read-write variables (global to this file)
545 ########################################################################
547 export _ADDOPTS_GROFF
; # Transp. options for groff (`eval').
548 export _ADDOPTS_POST
; # Transp. options postproc (`eval').
549 export _ADDOPTS_X
; # Transp. options X postproc (`eval').
550 export _DEFAULT_MODES
; # Set default modes.
551 export _DISPLAY_MODE
; # Display mode.
552 export _DISPLAY_PROG
; # Viewer program to be used for display.
553 export _DISPLAY_ARGS
; # X resources for the viewer program.
554 export _FILEARGS
; # Stores filespec parameters.
555 export _FUNC_STACK
; # Store debugging information.
556 export _REGISTERED_TITLE
; # Processed file names.
557 # _HAS_* from availability tests
558 export _HAS_COMPRESSION
; # `yes' if compression is available
559 export _HAS_OPTS_GNU
; # `yes' if GNU `getopt' is available
560 export _HAS_OPTS_POSIX
; # `yes' if POSIX `getopts' is available
561 # _MAN_* finally used configuration of man searching
562 export _MAN_ALL
; # search all man pages per filespec
563 export _MAN_ENABLE
; # enable search for man pages
564 export _MAN_EXT
; # extension for man pages
565 export _MAN_FORCE
; # force file parameter to be man pages
566 export _MAN_IS_SETUP
; # setup man variables only once
567 export _MAN_LANG
; # language for man pages
568 export _MAN_LANG_DONE
; # language dirs added to man path
569 export _MAN_PATH
; # search path for man pages
570 export _MAN_SEC
; # sections for man pages; sep. `:'
571 export _MAN_SEC_DONE
; # sections added to man path
572 export _MAN_SYS
; # system names for man pages; sep. `,'
573 export _MAN_SYS
; # system names added to man path
574 # _MANOPT_* as parsed from $MANOPT
575 export _MANOPT_ALL
; # $MANOPT --all
576 export _MANOPT_EXTENSION
; # $MANOPT --extension
577 export _MANOPT_LANG
; # $MANOPT --locale
578 export _MANOPT_PATH
; # $MANOPT --manpath
579 export _MANOPT_PAGER
; # $MANOPT --pager
580 export _MANOPT_SEC
; # $MANOPT --sections
581 export _MANOPT_SYS
; # $MANOPT --systems
582 # _OPT_* as parsed from groffer command line
583 export _OPT_ALL
; # display all suitable man pages.
584 export _OPT_APROPOS
; # branch to `apropos' program.
585 export _OPT_BD
; # set border color in some modes.
586 export _OPT_BG
; # set background color in some modes.
587 export _OPT_BW
; # set border width in some modes.
588 export _OPT_DEBUG
; # print debugging information on stderr.
589 export _OPT_DEFAULT_MODES
; # `,'-list of modes when no mode given.
590 export _OPT_DEVICE
; # device option.
591 export _OPT_DISPLAY
; # set X display.
592 export _OPT_FG
; # set foreground color in some modes.
593 export _OPT_FN
; # set font in some modes.
594 export _OPT_GEOMETRY
; # set size and position of viewer in X.
595 export _OPT_LANG
; # set language for man pages
596 export _OPT_LOCATION
; # print processed file names to stderr
597 export _OPT_MODE
; # values: X, tty, Q, Z, ""
598 export _OPT_MANPATH
; # manual setting of path for man-pages
599 export _OPT_PAGER
; # specify paging program for tty mode
600 export _OPT_RESOLUTION
; # set X resolution in dpi
601 export _OPT_RV
; # reverse fore- and background colors.
602 export _OPT_SECTIONS
; # sections for man page search
603 export _OPT_SYSTEMS
; # man pages of different OS's
604 export _OPT_TITLE
; # title for gxditview window
605 export _OPT_TTY_DEVICE
; # set device for tty mode.
606 export _OPT_V
; # groff option -V.
607 export _OPT_VIEWER_DVI
; # viewer program for dvi mode
608 export _OPT_VIEWER_PDF
; # viewer program for pdf mode
609 export _OPT_VIEWER_PS
; # viewer program for ps mode
610 export _OPT_VIEWER_WWW
; # viewer program for www mode
611 export _OPT_VIEWER_X
; # viewer program for x mode
612 export _OPT_WHATIS
; # print the one-liner man info
613 export _OPT_X
; # groff option -X.
614 export _OPT_XRM
; # specify X resource.
615 export _OPT_Z
; # groff option -Z.
616 # _TMP_* temporary files
617 export _TMP_DIR
; # groff directory for temporary files
618 export _TMP_DIR_SUB
; # groffer directory for temporary files
619 export _TMP_CAT
; # stores concatenation of everything
620 export _TMP_STDIN
; # stores stdin, if any
622 # these variables are preset in section `Preset' after the rudim. test
625 ########################################################################
626 # Test of rudimentary shell functionality
627 ########################################################################
630 ########################################################################
633 test "a" = "a" ||
exit 1;
636 ########################################################################
637 # Test of `echo' and the `$()' construct.
639 echo -n '' >/dev
/null ||
exit "${_ERROR}";
640 if test "$(echo -n 'te' && echo -n '' && echo -n 'st')" != "test"; then
645 ########################################################################
646 # Test of function definitions.
653 if _t_e_s_t_f_u_n_c_
2>/dev
/null
; then
656 echo 'shell does not support function definitions.' >&2;
661 ########################################################################
662 # Preset and reset of read-write global variables
663 ########################################################################
666 # For variables that can be reset by option `--default', see reset().
670 # _HAS_* from availability tests
675 # _TMP_* temporary files
682 ########################################################################
685 # Reset the variables that can be affected by options to their default.
689 if test "$#" -ne 0; then
690 error
"reset() does not have arguments.";
699 _REGISTERED_TITLE
='';
701 # _MAN_* finally used configuration of man searching
703 _MAN_ENABLE
='yes'; # do search for man-pages
705 _MAN_FORCE
='no'; # first local file, then search man page
715 # _MANOPT_* as parsed from $MANOPT
717 _MANOPT_EXTENSION
='';
724 # _OPT_* as parsed from groffer command line
731 _OPT_DEFAULT_MODES
='';
764 ########################################################################
765 # Functions for error handling and debugging
766 ########################################################################
772 # Print <text> to standard error as a debugging aid.
774 # Globals: $_DEBUG_LM
778 if test "${_DEBUG_LM}" = 'yes'; then
783 landmark
"1: debugging functions";
793 if test -d "${_TMP_DIR}"; then
794 rm -f "${_TMP_DIR}"/*;
805 # Arguments : arbitrary text.
818 # Arguments : arbitrary text.
829 # Output a diagnostic message to stderr
840 # Print an error message to standard error; exit with an error condition
849 1) echo2
'groffer error: '"$1"; ;;
851 echo2
'groffer error: '"$1";
854 *) echo2
'groffer error: wrong number of arguments in error().'; ;;
856 if test "${_DEBUG}" = 'yes'; then
860 kill "${_PROCESS_ID}" >/dev
/null
2>&1;
861 kill -9 "${_PROCESS_ID}" >/dev
/null
2>&1;
869 # Terminate program with error condition
873 error
"Program aborted.";
879 # func_check (<func_name> <rel_op> <nr_args> "$@")
881 # Check number of arguments and register to _FUNC_STACK.
884 # <func_name>: name of the calling function.
885 # <rel_op>: a relational operator: = != < > <= >=
886 # <nr_args>: number of arguments to be checked against <operator>
887 # "$@": the arguments of the calling function.
896 if test "$#" -lt 3; then
897 error
'func_check() needs at least 3 arguments.';
910 error
"func_check(): third argument must be a digit.";
940 'func_check(): second argument is not a relational operator.';
944 if test "$#" "${_op}" "${_nargs}"; then
948 "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
950 if test "${_DEBUG}" = 'yes'; then
951 func_push
"${_fname} $*";
959 # Retrieve the top element from the stack.
961 # The stack elements are separated by `!'; the popped element is
962 # identical to the original element, except that all `!' characters
969 if test "${_DEBUG}" = 'yes'; then
970 if test "$#" -ne 0; then
971 error
'func_pop() does not have arguments.';
973 case "${_FUNC_STACK}" in
975 error
'func_pop(): stack is empty.';
978 # split at first bang `!'.
979 _FUNC_STACK
="$(echo -n ${_FUNC_STACK} \
980 | sed -e 's/^[^!]*!//')";
991 # func_push (<element>)
993 # Store another element to stack.
995 # The stack elements are separated by `!'; if <element> contains a `!'
996 # it is removed first.
1003 if test "${_DEBUG}" = 'yes'; then
1004 if test "$#" -ne 1; then
1005 error
'func_push() needs 1 argument.';
1009 # remove all bangs `!'.
1010 _element
="$(echo -n "$1" | sed -e 's/!//g')";
1016 if test "${_FUNC_STACK}" = ''; then
1017 _FUNC_STACK
="${_element}";
1019 _FUNC_STACK
="${_element}!${_FUNC_STACK}";
1026 # func_stack_dump ()
1028 # Print the content of the stack. Ignore the arguments.
1033 case "${_FUNC_STACK}" in
1035 _rest
="${_FUNC_STACK}";
1036 while test "${_rest}" != ''; do
1037 # get part before the first bang `!'.
1038 diag
"$(echo -n "${_rest}" | sed -e 's/!.*$//')";
1039 # delete part before and including the first bang `!'.
1040 _rest
="$(echo -n "${_rest}" | sed -e 's/^[^!]*!//')";
1044 diag
"${_FUNC_STACK}";
1050 ########################################################################
1052 ########################################################################
1054 landmark
"2: system test";
1056 # Test the availability of the system utilities used in this script.
1059 ########################################################################
1062 if true
>/dev
/null
2>&1; then
1077 ########################################################################
1081 if unset _test
>/dev
/null
2>&1 && test "${_test}" = ''; then
1093 ########################################################################
1094 # Test of builtin `local'
1099 local _test
>/dev
/null
2>&1 ||
return "${_BAD}";
1102 if _t_e_s_t_f_u_n_c_
; then
1107 if test "$1" != ''; then
1108 error
"overriding global variable \`$1' with local value.";
1114 ########################################################################
1115 # Test of global setting in functions
1128 if test "${_global}" != 'inside' ||
test "${_clobber}" != 'outside';
1130 error
"Cannot assign to global variables from within functions.";
1137 ########################################################################
1138 # Test of function `sed'.
1140 if test "$(echo xTesTx \
1141 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1142 | sed -e '\|T|s||t|g')" != 'test';
1144 error
'Test of "sed" command failed.';
1148 ########################################################################
1149 # Test of function `cat'.
1151 if test "$(echo test | cat)" != "test"; then
1152 error
'Test of "cat" command failed.';
1156 ########################################################################
1157 # Test for compression.
1159 if test "$(echo 'test' | gzip -c -d -f - 2>/dev/null)" = 'test'; then
1160 _HAS_COMPRESSION
='yes';
1161 if echo 'test' |
bzip2 -c 2>/dev
/null |
bzip2 -t 2>/dev
/null \
1162 && test "$(echo 'test' | bzip2 -c 2>/dev/null \
1163 | bzip2 -d -c 2>/dev/null)" \
1170 _HAS_COMPRESSION
='no';
1175 ########################################################################
1182 ########################################################################
1183 # Definition of normal Functions
1184 ########################################################################
1185 landmark
"3: functions";
1187 ########################################################################
1190 # Unconditionally terminate the program with error code;
1191 # useful for debugging.
1196 ########################################################################
1197 # base_name (<path>)
1199 # Get the file name part of <path>, i.e. delete everything up to last
1200 # `/' from the beginning of <path>.
1203 # Output : the file name part (without slashes)
1207 func_check base_name
= 1 "$@";
1213 # delete everything before and including the last slash `/'.
1214 echo -n "$1" |
sed -e '\|^.*//*\([^/]*\)$|s||\1|';
1220 eval "${return_ok}";
1224 ########################################################################
1227 # Decompress if possible or just print <file> to standard output.
1229 # gzip, bzip2, and .Z decompression is supported.
1231 # Arguments: 1, a file name.
1232 # Output: the content of <file>, possibly decompressed.
1234 if test "${_HAS_COMPRESSION}" = 'yes'; then
1237 func_check catz
= 1 "$@";
1240 error
'catz(): empty file name';
1243 error
'catz(): for standard input use save_stdin()';
1246 if is_yes
"${_HAS_BZIP}"; then
1247 if bzip2 -t "$1" 2>/dev
/null
; then
1248 bzip2 -c -d "$1" 2>/dev
/null
;
1249 eval "${return_ok}";
1252 gzip -c -d -f "$1" 2>/dev
/null
;
1253 eval "${return_ok}";
1258 func_check catz
= 1 "$@";
1260 eval "${return_ok}";
1265 ########################################################################
1268 # Do the final cleaning up before exiting; used by the trap calls.
1273 ########################################################################
1276 # Print marked message to standard error; useful for debugging.
1281 ########################################################################
1282 landmark
'4: dirname()*';
1283 ########################################################################
1285 #######################################################################
1286 # dirname_append (<dir> <name>)
1288 # Append `name' to `dir' with clean handling of `/'.
1291 # Output : the generated new directory name <dir>/<name>
1295 func_check dirname_append
= 2 "$@";
1297 if is_empty
"$1"; then
1298 error
"dir_append(): first argument is empty.";
1300 if is_empty
"$2"; then
1303 dirname_chop
"$1"/"$2";
1305 eval "${return_ok}";
1309 ########################################################################
1310 # dirname_chop (<name>)
1312 # Remove unnecessary slashes from directory name.
1314 # Argument: 1, a directory name.
1315 # Output: path without double, or trailing slashes.
1319 func_check dirname_chop
= 1 "$@";
1323 # replace all multiple slashes by a single slash `/'.
1324 _res
="$(echo -n "$1" | sed -e '\|///*|s||/|g')";
1327 # remove trailing slash '/';
1328 echo -n "${_res}" |
sed -e '\|/$|s|||';
1330 *) echo -n "${_res}"; ;;
1332 eval "${return_ok}";
1336 ########################################################################
1337 # do_filearg (<filearg>)
1339 # Append the file, man-page, or standard input corresponding to the
1340 # argument to the temporary file. If this is compressed in the gzip
1341 # or Z format it is decompressed. A title element is generated.
1344 # - name of an existing files.
1345 # - `-' to represent standard input (several times allowed).
1346 # - `man:name.(section)' the man-page for `name' in `section'.
1347 # - `man:name.section' the man-page for `name' in `section'.
1348 # - `man:name' the man-page for `name' in the lowest `section'.
1349 # - `name.section' the man-page for `name' in `section'.
1350 # - `name' the man-page for `name' in the lowest `section'.
1352 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1355 # Return : $_GOOD if found, ${_BAD} otherwise.
1359 func_check do_filearg
= 1 "$@";
1363 # store sequence into positional parameters
1364 case "${_filespec}" in
1366 eval "${return_good}";
1370 eval "${return_good}";
1372 */*) # with directory part; so no man search
1376 if is_yes
"${_MAN_ENABLE}"; then
1377 if is_yes
"${_MAN_FORCE}"; then
1378 set -- 'Manpage' 'File';
1380 set -- 'File' 'Manpage';
1390 if test -f "${_filespec}"; then
1391 if test -r "${_filespec}"; then
1392 register_file
"${_filespec}";
1393 eval "${return_good}";
1395 echo2
"could not read \`${_filespec}'";
1396 eval "${return_bad}";
1402 Manpage
) # parse filespec as man page
1403 if is_not_yes
"${_MAN_IS_SETUP}"; then
1406 if man_do_filespec
"${_filespec}"; then
1407 eval "${return_good}";
1414 eval "${return_bad}";
1418 ########################################################################
1429 ########################################################################
1432 # Print to standard error with final line break.
1437 ########################################################################
1440 # Print to standard error without final line break.
1445 ########################################################################
1448 # Print error message and exit with error code.
1453 ########################################################################
1454 # func_check (<func_name> <rel_op> <nr_args> "$@")
1456 # Check number of arguments and register to _FUNC_STACK.
1459 # <func_name>: name of the calling function.
1460 # <rel_op>: a relational operator: = != < > <= >=
1461 # <nr_args>: number of arguments to be checked against <operator>
1462 # "$@": the arguments of the calling function.
1466 #########################################################################
1469 # Delete the top element from the function call stack.
1474 ########################################################################
1475 # func_push (<element>)
1477 # Store another element to function call stack.
1482 ########################################################################
1483 # func_stack_dump ()
1485 # Print the content of the stack.
1490 ########################################################################
1491 # get_first_essential (<arg>*)
1493 # Retrieve first non-empty argument.
1495 # Return : `1' if all arguments are empty, `0' if found.
1496 # Output : the retrieved non-empty argument.
1498 get_first_essential
()
1500 func_check get_first_essential
'>=' 0 "$@";
1502 if test "$#" -eq 0; then
1503 eval "${return_ok}";
1506 if is_not_empty
"$i"; then
1508 eval "${return_ok}";
1511 eval "${return_bad}";
1515 ########################################################################
1516 landmark
'5: is_*()';
1517 ########################################################################
1519 ########################################################################
1522 # Test whether `name' is a directory.
1525 # Return : `0' if arg1 is a directory, `1' otherwise.
1529 func_check is_dir
= 1 "$@";
1530 if is_not_empty
"$1" && test -d "$1" && test -r "$1"; then
1531 eval "${return_yes}";
1533 eval "${return_no}";
1535 eval "${return_ok}";
1539 ########################################################################
1540 # is_empty (<string>)
1542 # Test whether `string' is empty.
1545 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1549 func_check is_empty
= 1 "$@";
1550 if test -z "$1"; then
1551 eval "${return_yes}";
1553 eval "${return_no}";
1555 eval "${return_ok}";
1559 ########################################################################
1560 # is_equal (<string1> <string2>)
1562 # Test whether `string1' is equal to <string2>.
1565 # Return : `0' both arguments are equal strings, `1' otherwise.
1569 func_check is_equal
= 2 "$@";
1570 if test "$1" = "$2"; then
1571 eval "${return_yes}";
1573 eval "${return_no}";
1575 eval "${return_ok}";
1579 ########################################################################
1582 # Test whether `name' is a readable file.
1585 # Return : `0' if arg1 is a readable file, `1' otherwise.
1589 func_check is_file
= 1 "$@";
1590 if is_not_empty
"$1" && test -f "$1" && test -r "$1"; then
1591 eval "${return_yes}";
1593 eval "${return_no}";
1595 eval "${return_ok}";
1599 ########################################################################
1600 # is_not_dir (<name>)
1602 # Test whether `name' is not a readable directory.
1605 # Return : `0' if arg1 is a directory, `1' otherwise.
1609 func_check is_not_dir
= 1 "$@";
1610 if is_dir
"$1"; then
1611 eval "${return_no}";
1613 eval "${return_yes}";
1615 eval "${return_ok}";
1619 ########################################################################
1620 # is_not_empty (<string>)
1622 # Test whether `string' is not empty.
1625 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1629 func_check is_not_empty
= 1 "$@";
1630 if is_empty
"$1"; then
1631 eval "${return_no}";
1633 eval "${return_yes}";
1635 eval "${return_ok}";
1639 ########################################################################
1640 # is_not_equal (<string1> <string2>)
1642 # Test whether `string1' and <string2> differ.
1648 func_check is_not_equal
= 2 "$@";
1649 if is_equal
"$1" "$2"; then
1650 eval "${return_no}";
1652 eval "${return_yes}";
1654 eval "${return_ok}";
1658 ########################################################################
1659 # is_not_file (<filename>)
1661 # Test whether `name' is a not readable file.
1663 # Arguments : >=1 (empty allowed), more args are ignored
1667 func_check is_not_file
'>=' 1 "$@";
1668 if is_file
"$1"; then
1669 eval "${return_no}";
1671 eval "${return_yes}";
1673 eval "${return_ok}";
1677 ########################################################################
1678 # is_not_prog (<name>)
1680 # Verify that arg is a not program in $PATH.
1682 # Arguments : >=1 (empty allowed)
1683 # more args are ignored, this allows to specify progs with arguments
1687 func_check is_not_prog
'>=' 1 "$@";
1688 if where
"$1" >/dev
/null
; then
1689 eval "${return_no}";
1691 eval "${return_yes}";
1693 eval "${return_ok}";
1697 ########################################################################
1698 # is_not_yes (<string>)
1700 # Test whether `string' is not "yes".
1706 func_check is_not_yes
= 1 "$@";
1707 if test "$1" = 'yes'; then
1708 eval "${return_no}";
1710 eval "${return_yes}";
1712 eval "${return_ok}";
1716 ########################################################################
1719 # Determine whether arg is a program in $PATH
1721 # Arguments : >=1 (empty allowed)
1722 # more args are ignored, this allows to specify progs with arguments
1726 func_check is_prog
'>=' 1 "$@";
1727 if where
"$1" >/dev
/null
; then
1728 eval "${return_yes}";
1730 eval "${return_no}";
1732 eval "${return_ok}";
1736 ########################################################################
1739 # Test whether `string' has value "yes".
1742 # Return : `0' if arg1 is `yes', `1' otherwise.
1746 func_check is_yes
= 1 "$@";
1747 if test "$1" = 'yes'; then
1748 eval "${return_yes}";
1750 eval "${return_no}";
1752 eval "${return_ok}";
1756 ########################################################################
1759 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1761 # Globals: $_DEBUG_LM
1763 # Defined in section `Debugging functions'.
1766 ########################################################################
1769 # Clean exit without an error.
1778 ########################################################################
1779 landmark
'6: list_*()';
1780 ########################################################################
1782 ########################################################################
1783 # list_append (<list> <element>...)
1786 # <list>: a space-separated list of single-quoted elements.
1787 # <element>: some sequence of characters.
1789 # if <list> is empty: "'<element>' '...'"
1790 # otherwise: "<list> '<element>' ..."
1794 func_check list_append
'>=' 2 "$@";
1802 # escape each single quote by replacing each "'" (squote)
1803 # by "'\''" (squote bslash squote squote);
1804 # note that the backslash must be doubled for `sed'.
1805 _element
="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')";
1811 _res
="${_res} '${_element}'";
1814 eval "${return_ok}";
1818 ########################################################################
1819 # list_check (<list>)
1821 # Check whether <list> is a space-separated list of '-quoted elements.
1823 # If the test fails an error is raised.
1824 # If the test succeeds the argument is echoed.
1827 # A list has the form "'first' 'second' '...' 'last'".
1828 # So it has a leading and a final quote and the elements are separated
1829 # by "' '" constructs. If these are all removed there should not be
1830 # any single-quotes left. Watch out for escaped single quotes; they
1831 # have the form '\'' (sq bs sq sq).
1834 # Output: the argument <list> unchanged, it the check succeeded.
1838 func_check list_check
= 1 "$@";
1840 if is_empty
"$1"; then
1841 eval "${return_ok}";
1844 \'*\') _list
="$1"; ;;
1846 error
"list_check() bad list: $1"
1849 # Remove leading single quote,
1850 # remove final single quote,
1851 # remove escaped single quotes (squote bslash squote squote)
1852 # [note that `sed' doubles the backslash (bslash bslash)],
1853 # remove field separators (squote space squote).
1854 _list
="$(echo -n "${_list}" \
1855 | sed -e 's/^'"${_SQUOTE}"'//' \
1856 | sed -e 's/'"${_SQUOTE}"'$//' \
1858 's/'"${_SQUOTE}${_BSLASH}${_BSLASH}${_SQUOTE}${_SQUOTE}"'//g' \
1859 | sed -e 's/'"${_SQUOTE}${_SPACE}${_SPACE}"'*'"${_SQUOTE}"'//g')";
1861 *\'*) # criterium fails if squote is left
1862 error
'list_check() bad list: '"${_list}";
1866 eval "${return_ok}";
1870 ########################################################################
1871 # list_element_from_arg (<arg>)
1874 # <arg>: some sequence of characters (also single quotes allowed).
1875 # Output: the list element generated from <arg>.
1877 list_element_from_arg
()
1879 func_check list_element_from_arg
= 1 "$@";
1882 # replace each single quote "'" by "'\''".
1883 echo -n "$1" |
sed -e 's/'\''/&\\&&/g'; # ' for emacs
1885 eval "${return_ok}";
1889 ########################################################################
1890 # list_from_args (<arg>...)
1892 # Generate a space-separated list of single-quoted elements from args.
1895 # <arg>: some sequence of characters.
1896 # Output: "'<arg>' '...'"
1900 func_check list_from_args
'>=' 1 "$@";
1904 _list
="$(list_append "${_list}" "$s")";
1907 eval "${return_ok}";
1911 ########################################################################
1912 # list_from_cmdline (<s_n> <s_a> <l_n> <l_a> [<cmdline_arg>...])
1914 # Transform command line arguments into a normalized form.
1916 # Options, option arguments, and file parameters are identified and
1917 # output each as a single-quoted argument of its own. Options and
1918 # file parameters are separated by a '--' argument.
1921 # <s_n>: space-separated list of short options without an arg.
1922 # <s_a>: space-separated list of short options that have an arg.
1923 # <l_n>: space-separated list of long options without an arg.
1924 # <l_a>: space-separated list of long options that have an arg.
1925 # <cmdline_arg>...: the arguments from the command line (by "$@").
1927 # Globals: $POSIXLY_CORRECT (only kept for compatibility).
1929 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1932 # list_normalize 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1933 # will result in printing:
1934 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1935 # If $POSIXLY_CORRECT is not empty, the result will be:
1936 # '-a' '--' 'f1' '-bcarg' '--long=larg' 'f2'
1939 # In POSIX, the first non-option ends the option processing.
1940 # In GNU mode (default), non-options are sorted behind the options.
1942 # Use this function only in the following way:
1943 # eval set -- "$(args_norm '...' '...' '...' '...' "$@")";
1944 # while test "$1" != '--'; do
1951 # # all positional parameters ("$@") left are file name parameters.
1955 func_check list_from_cmdline
'>=' 4 "$@";
1963 _short_n
="$(list_check "$1")"; # short options, no argument
1964 _short_a
="$(list_check "$2")"; # short options with argument
1965 _long_n
="$(list_check "$3")"; # long options, no argument
1966 _long_a
="$(list_check "$4")"; # long options with argument
1968 _fn
='list_from_cmdline():'; # for error messages
1969 if test "$#" -eq 0; then
1971 eval "${return_ok}";
1975 while test "$#" -ge 1; do
1981 # delete leading '--';
1982 _opt
="$(echo -n "${_arg}" | sed -e 's/^..//')";
1983 if list_has
"${_long_n}" "${_opt}"; then
1984 # long option, no argument
1985 _result
="$(list_append "${_result}" "--${_opt}")";
1988 if list_has
"${_long_a}" "${_opt}"; then
1989 # long option with argument
1990 _result
="$(list_append "${_result}" "--${_opt}")";
1991 if test "$#" -le 0; then
1992 error
"${_fn} no argument for option --${_opt}."
1994 _result
="$(list_append "${_result}" "$1")";
1998 # test on `--opt=arg'
1999 if string_contains
"${_opt}" '='; then
2000 # extract option by deleting from the first '=' to the end
2001 _lopt
="$(echo -n "${_opt}" | sed -e 's/=.*$//')";
2002 if list_has
"${_long_a}" "${_lopt}"; then
2003 # get the option argument by deleting up to first `='
2004 _optarg
="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')";
2005 _result
="$(list_append "${_result}" \
2006 "--${_lopt}" "${_optarg}")";
2010 error
"${_fn} --${_opt} is not an option."
2012 -?
*) # short option (cluster)
2013 # delete leading `-';
2014 _rest
="$(echo -n "${_arg}" | sed -e 's/^.//')";
2015 while is_not_empty
"${_rest}"; do
2016 # get next short option from cluster (first char of $_rest)
2017 _optchar
="$(echo -n "${_rest}" | sed -e 's/^\(.\).*$/\1/')";
2018 # remove first character from ${_rest};
2019 _rest
="$(echo -n "${_rest}" | sed -e 's/^.//')";
2020 if list_has
"${_short_n}" "${_optchar}"; then
2021 _result
="$(list_append "${_result}" "-${_optchar}")";
2023 elif list_has
"${_short_a}" "${_optchar}"; then
2024 # remove leading character
2025 case "${_optchar}" in
2027 _rest
="$(echo -n "${_rest}" | sed -e '\|^.|s|||')";
2030 _rest
="$(echo -n "${_rest}" | sed -e 's/^.//')";
2033 error
"${_fn} several chars parsed for short option."
2036 if is_empty
"${_rest}"; then
2037 if test "$#" -ge 1; then
2038 _result
="$(list_append "${_result}" \
2039 "-${_optchar}" "$1")";
2044 "${_fn}"' no argument for option -'"${_optchar}."
2046 else # rest is the argument
2047 _result
="$(list_append "${_result}" \
2048 "-${_optchar}" "${_rest}")";
2053 error
"${_fn} unknown option -${_optchar}."
2058 # Here, $_arg is not an option, so a file parameter.
2059 # When $POSIXLY_CORRECT is set this ends option parsing;
2060 # otherwise, the argument is stored as a file parameter and
2061 # option processing is continued.
2062 _fparams
="$(list_append "${_fparams}" "${_arg}")";
2063 if is_not_empty
"$POSIXLY_CORRECT"; then
2069 _result
="$(list_append "${_result}" '--')";
2070 if is_not_empty
"${_fparams}"; then
2071 _result
="${_result} ${_fparams}";
2073 if test "$#" -gt 0; then
2074 _result
="$(list_append "${_result}" "$@
")";
2077 eval "${return_ok}";
2078 } # list_from_cmdline()
2081 ########################################################################
2082 # list_from_lists (<list1> <list2>...)
2084 # Generate a list from the concatenation of the lists in the arguments.
2087 # <list*>: string of space-separated single-quoted elements.
2088 # Output: "'<element1_of_list1>' ..."
2092 func_check list_from_lists
'>=' 2 "$@";
2095 eval "${return_ok}";
2098 ########################################################################
2099 # list_from_split (<string> <separator>)
2101 # In <string> escape white space and replace each <separator> by space.
2103 # Arguments: 2: a <string> that is to be split into parts divided by
2105 # Output: the resulting string
2109 func_check list_from_split
= 2 "$@";
2112 # precede each space or tab by a backslash `\' (doubled for `sed')
2113 _s
="$(echo -n "$1" | sed -e 's/\(['"${_SPACE}${_TAB}"']\)/\\\1/g')";
2115 # replace split character of string by the list separator ` ' (space).
2117 /) # cannot use normal `sed' separator
2118 echo -n "${_s}" |
sed -e '\|'"$2"'|s|| |g';
2120 ?
) # use normal `sed' separator
2121 echo -n "${_s}" |
sed -e 's/'"$2"'/ /g';
2124 error
'list_from_split(): separator must be a single character.';
2127 eval "${return_ok}";
2131 ########################################################################
2132 # list_has (<list> <element>)
2135 # <list>: a space-separated list of single-quoted elements.
2136 # <element>: some sequence of characters.
2138 # if <list> is empty: "'<element>' '...'"
2139 # otherwise: "<list> '<element>' ..."
2143 func_check list_has
= 2 "$@";
2144 if is_empty
"$1"; then
2145 eval "${return_no}";
2150 \'*\') _element
="$2"; ;;
2151 *) _element
="'$2'"; ;;
2153 if string_contains
"${_list}" "${_element}"; then
2154 eval "${return_yes}";
2156 eval "${return_no}";
2158 eval "${return_ok}";
2162 ########################################################################
2163 # list_has_not (<list> <element>)
2166 # <list>: a space-separated list of single-quoted elements.
2167 # <element>: some sequence of characters.
2169 # if <list> is empty: "'<element>' '...'"
2170 # otherwise: "<list> '<element>' ..."
2174 func_check list_has_not
= 2 "$@";
2175 if is_empty
"$1"; then
2176 eval "${return_yes}";
2181 \'*\') _element
="$2"; ;;
2182 *) _element
="'$2'"; ;;
2184 if string_contains
"${_list}" "${_element}"; then
2185 eval "${return_no}";
2187 eval "${return_yes}";
2189 eval "${return_ok}";
2193 ########################################################################
2194 # list_length (<list>)
2197 # <list>: a space-separated list of single-quoted elements.
2198 # Output: the number of elements in <list>
2202 func_check list_length
= 1 "$@";
2205 eval "${return_ok}";
2209 ########################################################################
2210 # list_prepend (<list> <element>...)
2212 # Insert new <element> at the beginning of <list>
2215 # <list>: a space-separated list of single-quoted elements.
2216 # <element>: some sequence of characters.
2218 # if <list> is empty: "'<element>' ..."
2219 # otherwise: "'<element>' ... <list>"
2223 func_check list_prepend
'>=' 2 "$@";
2228 # escape single quotes in list style (squote bslash squote squote).
2229 _element
="$(echo -n "$s" | sed -e 's/'\''/&\\&&/g')";
2230 _res
="'${_element}' ${_res}";
2233 eval "${return_ok}";
2237 ########################################################################
2238 landmark
'7: man_*()';
2239 ########################################################################
2241 ########################################################################
2242 # man_do_filespec (<filespec>)
2244 # Print suitable man page(s) for filespec to $_TMP_CAT.
2247 # <filespec>: argument of the form `man:name.section', `man:name',
2248 # `man:name(section)', `name.section', `name'.
2250 # Globals : $_OPT_ALL
2253 # Return : `0' if man page was found, `1' else.
2255 # Only called from do_fileargs(), checks on $MANPATH and
2256 # $_MAN_ENABLE are assumed.
2260 func_check man_do_filespec
= 1 "$@";
2269 if is_empty
"${_MAN_PATH}"; then
2270 eval "${return_bad}";
2272 if is_empty
"$1"; then
2273 eval "${return_bad}";
2279 */*) # not a man spec when it contains '/'
2280 eval "${return_bad}";
2282 man
:?
*\
(?
*\
)) # man:name(section)
2283 _name
="$(echo -n "${_spec}" \
2284 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2285 _section
="$(echo -n "${_spec}" \
2286 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2288 man
:?
*.?
*) # man:name.section
2289 _name
="$(echo -n "${_spec}" \
2290 | sed -e 's/^man:\(..*\)\.\(..*\)$/\1/')";
2291 _section
="$(echo -n "${_spec}" \
2292 | sed -e 's/^man:\(..*\)\.\(..*\)$/\2/')";
2295 _name
="$(echo -n "${_spec}" | sed -e 's/^man://')";
2297 ?
*\
(?
*\
)) # name(section)
2298 _name
="$(echo -n "${_spec}" \
2299 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2300 _section
="$(echo -n "${_spec}" \
2301 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2303 ?
*.?
*) # name.section
2304 _name
="$(echo -n "${_spec}" \
2305 | sed -e 's/^\(..*\)\.\(..*\)$/\1/')";
2306 _section
="$(echo -n "${_spec}" \
2307 | sed -e 's/^\(..*\)\.\(..*\)$/\2/')";
2310 _name
="${_filespec}";
2313 if is_empty
"${_name}"; then
2314 eval "${return_bad}";
2317 if is_empty
"${_section}"; then
2318 eval set -- "${_MAN_AUTO_SEC}";
2320 if man_search_section
"${_name}" "$s"; then # found
2321 if is_yes
"${_MAN_ALL}"; then
2324 eval "${return_good}";
2329 if man_search_section
"${_name}" "${_section}"; then
2330 eval "${return_good}";
2332 eval "${return_bad}";
2335 if is_yes
"${_MAN_ALL}" && is_yes
"${_got_one}"; then
2336 eval "${return_good}";
2338 eval "${return_bad}";
2339 } # man_do_filespec()
2342 ########################################################################
2343 # man_register_file (<file> <name> [<section>])
2345 # Write a found man page file and register the title element.
2347 # Arguments: 1, 2, or 3; maybe empty
2352 func_check man_register_file
'>=' 2 "$@";
2356 error
"man_register_file() expects 2 or 3 arguments.";
2359 if is_empty
"$1"; then
2360 error
'man_register_file(): file name is empty';
2365 register_title
"man:$2";
2366 eval "${return_ok}";
2369 register_title
"$2($3)";
2370 eval "${return_ok}";
2373 eval "${return_ok}";
2377 ########################################################################
2378 # man_search_section (<name> <section>)
2380 # Retrieve man pages.
2383 # Globals : $_MAN_PATH, $_MAN_EXT
2384 # Return : 0 if found, 1 otherwise
2386 man_search_section
()
2388 func_check man_search_section
= 2 "$@";
2397 if is_empty
"${_MAN_PATH}"; then
2398 eval "${return_bad}";
2400 if is_empty
"$1"; then
2401 eval "${return_bad}";
2403 if is_empty
"$2"; then
2404 eval "${return_bad}";
2408 eval set -- "$(path_split "${_MAN_PATH}")";
2410 if is_empty
"${_MAN_EXT}"; then
2412 _dir
="$(dirname_append "$d" "man
${_section}")";
2413 if is_dir
"${_dir}"; then
2414 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2415 for f
in $
(echo -n ${_prefix}*); do
2416 if is_file
"$f"; then
2417 if is_yes
"${_got_one}"; then
2419 elif is_yes
"${_MAN_ALL}"; then
2420 man_register_file
"$f" "${_name}";
2422 man_register_file
"$f" "${_name}" "${_section}";
2423 eval "${return_good}";
2432 # check for directory name having trailing extension
2434 _dir
="$(dirname_append $d man${_section}${_ext})";
2435 if is_dir
"${_dir}"; then
2436 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2437 for f
in ${_prefix}*; do
2438 if is_file
"$f"; then
2439 if is_yes
"${_got_one}"; then
2441 elif is_yes
"${_MAN_ALL}"; then
2442 man_register_file
"$f" "${_name}";
2444 man_register_file
"$f" "${_name}" "${_section}";
2445 eval "${return_good}";
2452 # check for files with extension in directories without extension
2454 _dir
="$(dirname_append "$d" "man
${_section}")";
2455 if is_dir
"${_dir}"; then
2456 _prefix
="$(dirname_append "${_dir}" \
2457 "${_name}.${_section}${_ext}")";
2458 for f
in ${_prefix}*; do
2459 if is_file
"$f"; then
2460 if is_yes
"${_got_one}"; then
2462 elif is_yes
"${_MAN_ALL}"; then
2463 man_register_file
"$f" "${_name}";
2465 man_register_file
"$f" "${_name}" "${_section}";
2466 eval "${return_good}";
2474 if is_yes
"${_MAN_ALL}" && is_yes
"${_got_one}"; then
2475 eval "${return_good}";
2477 eval "${return_bad}";
2478 } # man_search_section()
2481 ########################################################################
2484 # Setup the variables $_MAN_* needed for man page searching.
2487 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2488 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2489 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2490 # $_MAN_SEC, $_MAN_ALL
2491 # in/out: $_MAN_ENABLE
2493 # The precedence for the variables related to `man' is that of GNU
2496 # $LANG; overridden by
2497 # $LC_MESSAGES; overridden by
2498 # $LC_ALL; this has the same precedence as
2499 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2500 # $MANOPT; overridden by
2501 # the groffer command line options.
2505 func_check main_man_setup
= 0 "$@";
2508 if is_yes
"${_MAN_IS_SETUP}"; then
2509 eval "${return_ok}";
2511 _MAN_IS_SETUP
='yes';
2513 if is_not_yes
"${_MAN_ENABLE}"; then
2514 eval "${return_ok}";
2517 # determine basic path for man pages
2518 _MAN_PATH
="$(get_first_essential \
2519 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2520 if is_empty
"${_MAN_PATH}"; then
2521 if is_prog
'manpath'; then
2522 _MAN_PATH
="$(manpath 2>/dev/null)"; # not always available
2525 if is_empty
"${_MAN_PATH}"; then
2526 manpath_set_from_path
;
2528 _MAN_PATH
="$(path_clean "${_MAN_PATH}")";
2530 if is_empty
"${_MAN_PATH}"; then
2532 eval "${return_ok}";
2535 _MAN_ALL
="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2536 if is_empty
"${_MAN_ALL}"; then
2540 _MAN_SYS
="$(get_first_essential \
2541 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2542 _lang
="$(get_first_essential \
2543 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2550 _MAN_LANG
="${_lang}";
2554 _MAN_LANG
="${_lang}";
2555 # get first two characters of $_lang
2556 _MAN_LANG2
="$(echo -n "${_lang}" | sed -e 's/^\(..\).*$/\1/')";
2559 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2561 manpath_add_lang_sys
; # this is very slow
2563 _MAN_SEC
="$(get_first_essential \
2564 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2565 if is_empty
"${_MAN_PATH}"; then
2567 eval "${return_ok}";
2570 _MAN_EXT
="$(get_first_essential \
2571 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2572 eval "${return_ok}";
2576 ########################################################################
2577 landmark
'8: manpath_*()';
2578 ########################################################################
2580 ########################################################################
2581 # manpath_add_lang_sys ()
2583 # Add language and operating system specific directories to man path.
2588 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2589 # list of names of operating systems.
2590 # $_MAN_LANG and $_MAN_LANG2: each a single name
2591 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2592 # separated list of directories.
2594 manpath_add_lang_sys
()
2596 func_check manpath_add_lang_sys
= 0 "$@";
2599 if is_empty
"${_MAN_PATH}"; then
2600 eval "${return_ok}";
2602 # twice test both sys and lang
2603 eval set -- "$(path_split "${_MAN_PATH}")";
2605 for p
in "$@"; do # loop on man path directories
2606 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2608 eval set -- "$(path_split "${_mp}")";
2609 for p
in "$@"; do # loop on man path directories
2610 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2612 _MAN_PATH
="$(path_chop "${_mp}")";
2613 eval "${return_ok}";
2617 _manpath_add_lang_sys_single
()
2619 # To the directory in $1 append existing sys/lang subdirectories
2620 # Function is necessary to split the OS list.
2622 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2623 # argument: 2: `man_path' and `dir'
2624 # output: colon-separated path of the retrieved subdirectories
2627 # if test "$#" -ne 2; then
2628 # error "manpath_add_system_single() needs 2 arguments.";
2632 eval set -- "$(list_from_split "${_MAN_SYS}" ',')";
2633 for d
in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"; do
2634 _dir
="$(dirname_append "${_parent}" "$d")";
2635 if path_not_contains
"${_res}" "${_dir}" && is_dir "${_dir}"; then
2636 _res
="${_res}:${_dir}";
2639 if path_not_contains
"${_res}" "${_parent}"; then
2640 _res
="${_res}:${_parent}";
2642 path_chop
"${_res}";
2645 # end manpath_add_lang_sys ()
2648 ########################################################################
2649 # manpath_set_from_path ()
2651 # Determine basic search path for man pages from $PATH.
2653 # Return: `0' if a valid man path was retrieved.
2659 manpath_set_from_path
()
2661 func_check manpath_set_from_path
= 0 "$@";
2669 # get a basic man path from $PATH
2670 if is_not_empty
"${PATH}"; then
2671 eval set -- "$(path_split "${PATH}")";
2673 # delete the final `/bin' part
2674 _base
="$(echo -n "$d" | sed -e '\|//*bin/*$|s|||')";
2675 for e
in /share
/man
/man
; do
2676 _mandir
="${_base}$e";
2677 if test -d "${_mandir}" && test -r "${_mandir}"; then
2678 _manpath
="${_manpath}:${_mandir}";
2684 # append some default directories
2685 for d
in /usr
/local
/share
/man
/usr
/local
/man \
2686 /usr
/share
/man
/usr
/man \
2687 /usr
/X11R
6/man
/usr
/openwin
/man \
2688 /opt
/share
/man
/opt
/man \
2689 /opt
/gnome
/man
/opt
/kde
/man
; do
2690 if path_not_contains
"${_manpath}" "$d" && is_dir
"$d"; then
2691 _manpath
="${_manpath}:$d";
2695 _MAN_PATH
="${_manpath}";
2696 eval "${return_ok}";
2697 } # manpath_set_from_path()
2700 ########################################################################
2701 landmark
'9: path_*()';
2702 ########################################################################
2704 ########################################################################
2705 # path_chop (<path>)
2707 # Remove unnecessary colons from path.
2709 # Argument: 1, a colon separated path.
2710 # Output: path without leading, double, or trailing colons.
2714 func_check path_chop
= 1 "$@";
2717 # replace multiple colons by a single colon `:'
2718 # remove leading and trailing colons
2719 echo -n "$1" |
sed -e 's/:::*/:/g' |
2722 eval "${return_ok}";
2726 ########################################################################
2727 # path_clean (<path>)
2729 # Remove non-existing directories from a colon-separated list.
2731 # Argument: 1, a colon separated path.
2732 # Output: colon-separated list of existing directories.
2736 func_check path_clean
= 1 "$@";
2741 if test "$#" -ne 1; then
2742 error
'path_clean() needs 1 argument.';
2745 eval set -- "$(path_split "${_arg}")";
2748 if is_not_empty
"$i" \
2749 && path_not_contains
"${_res}" "$i" \
2753 ?
*/) _res
="${_res}$(dirname_chop "$i")"; ;;
2754 *) _res
="${_res}:$i";
2758 if path_chop
"${_res}"; then
2759 eval "${return_ok}";
2761 eval "${return_badk}";
2766 ########################################################################
2767 # path_contains (<path> <dir>)
2769 # Test whether `dir' is contained in `path', a list separated by `:'.
2771 # Arguments : 2 arguments.
2772 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2776 func_check path_contains
= 2 "$@";
2779 eval "${return_yes}";
2782 eval "${return_no}";
2785 eval "${return_ok}";
2789 ########################################################################
2790 # path_not_contains (<path> <dir>)
2792 # Test whether `dir' is not contained in colon separated `path'.
2794 # Arguments : 2 arguments.
2798 func_check path_not_contains
= 2 "$@";
2799 if path_contains
"$1" "$2"; then
2800 eval "${return_no}";
2802 eval "${return_yes}";
2804 eval "${return_ok}";
2808 ########################################################################
2809 # path_split (<path>)
2811 # In `path' escape white space and replace each colon by a space.
2813 # Arguments: 1: a colon-separated path
2814 # Output: the resulting list, process with `eval set --'
2818 func_check path_split
= 1 "$@";
2819 list_from_split
"$1" ':';
2820 eval "${return_ok}";
2824 ########################################################################
2827 # Reset the variables that can be affected by options to their default.
2830 # Defined in section `Preset' after the rudimentary shell tests.
2833 ########################################################################
2834 landmark
'10: register_*()';
2835 ########################################################################
2837 ########################################################################
2838 # register_file (<filename>)
2840 # Write a found file and register the title element.
2842 # Arguments: 1: a file name
2847 func_check register_file
= 1 "$@";
2848 if is_empty
"$1"; then
2849 error
'register_file(): file name is empty';
2851 if is_equal
"$1" '-'; then
2852 to_tmp
"${_TMP_STDIN}";
2856 register_title
"$(base_name "$1")";
2858 eval "${return_ok}";
2862 ########################################################################
2863 # register_title (<filespec>)
2865 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2867 # Globals: $_REGISTERED_TITLE (rw)
2871 func_check register_title
= 1 "$@";
2873 if is_empty
"$1"; then
2874 eval "${return_ok}";
2876 _title
="$(base_name "$1")"; # remove directory part
2878 # remove extension `.gz'
2879 _title
="$(echo -n "${_title}" | sed -e 's/\.gz$//')";
2880 # remove extension `.Z'
2881 _title
="$(echo -n "${_title}" | sed -e 's/\.Z$//')";
2883 if is_empty
"${_title}"; then
2884 eval "${return_ok}";
2886 _REGISTERED_TITLE
="${_REGISTERED_TITLE} ${_title}";
2887 eval "${return_ok}";
2891 ########################################################################
2894 # Store standard input to temporary file (with decompression).
2896 if test "${_HAS_COMPRESSION}" = 'yes'; then
2900 func_check save_stdin
= 0 "$@";
2901 _f
="${_TMP_DIR}"/INPUT
;
2903 catz
"${_f}" >"${_TMP_STDIN}";
2905 eval "${return_ok}";
2910 func_check save_stdin
= 0 "$@";
2911 cat >"${_TMP_STDIN}";
2912 eval "${return_ok}";
2917 ########################################################################
2918 landmark
'11: stack_*()';
2919 ########################################################################
2921 ########################################################################
2922 # string_contains (<string> <part>)
2924 # Test whether `part' is contained in `string'.
2926 # Arguments : 2 text arguments.
2927 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2931 func_check string_contains
= 2 "$@";
2934 eval "${return_yes}";
2937 eval "${return_no}";
2940 eval "${return_ok}";
2944 ########################################################################
2945 # string_not_contains (<string> <part>)
2947 # Test whether `part' is not substring of `string'.
2949 # Arguments : 2 text arguments.
2950 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2952 string_not_contains
()
2954 func_check string_not_contains
= 2 "$@";
2955 if string_contains
"$1" "$2"; then
2956 eval "${return_no}";
2958 eval "${return_yes}";
2960 eval "${return_ok}";
2964 ########################################################################
2965 landmark
'12: tmp_*()';
2966 ########################################################################
2968 ########################################################################
2971 # output the temporary cat file (the concatenation of all input)
2979 ########################################################################
2980 # tmp_create (<suffix>?)
2982 # create temporary file
2984 # It's safe to use the shell process ID together with a suffix to
2985 # have multiple temporary files.
2987 # Output : name of created file
2991 func_check tmp_create
'<=' 1 "$@";
2993 _tmp
="${_TMP_DIR}/$1";
2995 echo -n "${_tmp}"; # output file name
2996 eval "${return_ok}";
3000 ########################################################################
3001 # to_tmp (<filename>)
3003 # print file (decompressed) to the temporary cat file
3007 func_check to_tmp
= 1 "$@";
3008 if is_file
"$1"; then
3009 if is_yes
"${_OPT_LOCATION}"; then
3012 if is_yes
"${_OPT_WHATIS}"; then
3013 what_is
"$1" >>"${_TMP_CAT}";
3015 catz
"$1" >>"${_TMP_CAT}";
3018 error
"to_tmp(): could not read file \`$1'.";
3020 eval "${return_ok}";
3024 ########################################################################
3027 # disable trap on all exit codes ($_ALL_EXIT)
3030 # Globals: $_ALL_EXIT
3034 func_check trap_clean
= 0 "$@";
3036 for i
in ${_ALL_EXIT}; do
3037 trap "" "$i" 2>/dev
/null || true
;
3039 eval "${return_ok}";
3043 ########################################################################
3044 # trap_set (<functionname>)
3046 # call function on all exit codes ($_ALL_EXIT)
3048 # Arguments: 1 (name of a shell function)
3049 # Globals: $_ALL_EXIT
3053 func_check trap_set
= 1 "$@";
3055 for i
in ${_ALL_EXIT}; do
3056 trap "$1" "$i" 2>/dev
/null || true
;
3058 eval "${return_ok}";
3062 ########################################################################
3065 # print usage information to stderr
3069 func_check usage
= 0 "$@";
3073 Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3074 This is free software licensed under the GNU General Public License.
3078 echo2
"Usage: ${_PROGRAM_NAME} [option]... [filespec]...";
3082 where "filespec" is one of
3083 "filename" name of a readable file
3084 "-" for standard input
3085 "man:name.n" man page "name" in section "n"
3086 "man:name" man page "name" in first section found
3087 "name.n" man page "name" in section "n"
3088 "name" man page "name" in first section found
3089 and some more (see groffer(1) for details).
3091 Display roff files, standard input, and/or Unix manual pages with
3092 in a X window viewer or in a text pager.
3093 "-" stands for including standard input.
3094 "manpage" is the name of a man page, "x" its section.
3095 All input is decompressed on-the-fly (by gzip).
3097 -h --help print this usage message.
3098 -Q --source output as roff source.
3099 -T --device=name pass to groff using output device "name".
3100 -v --version print version information.
3102 All other short options are interpreted as "groff" formatting
3103 parameters and are transferred unmodified. The following groff
3104 options imply groff mode (groffer viewing disabled):
3106 -X display with "gxditview" using groff -X.
3107 -V display the groff execution pipe instead of formatting.
3108 -Z --ditroff --intermediate-output
3109 generate groff intermediate output without
3110 post-processing and viewing like groff -Z.
3112 The most important long options are
3114 --auto-modes=mode1,mode2,...
3115 set sequence of automatically tried modes.
3116 --bg set background color (not for all modes).
3117 --default reset effects of option processing so far.
3118 --display set the X device when displaying in X.
3119 --dpi=res set resolution to "res" ("75" (default) or "100").
3120 --dvi display in a viewer for TeX device independent format.
3121 --dvi-viewer choose the viewer program for dvi mode.
3122 --extension=ext restrict man pages to section suffix.
3123 --fg set foreground color (not for all modes).
3124 --geometry=geom set the window size and position when displaying in X.
3125 --groff process like groff, disable viewing features.
3126 --local-file same as --no-man.
3127 --locale=lang preset the language for man pages.
3128 --location print file locations additionally to standard error.
3129 --man check file parameters first whether they are man pages.
3130 --mode=auto|dvi|groff|pdf|ps|source|tty|www|x
3131 choose display mode.
3132 --no-location disable former call to "--location".
3133 --no-man disable man-page facility.
3134 --pager=program preset the paging program for tty mode.
3135 --pdf display in a PDF viewer.
3136 --pdf-viewer choose the viewer program for pdf mode.
3137 --ps display in a Postscript viewer.
3138 --ps-viewer choose the viewer program for ps mode.
3139 --shell specify shell under which to run this program.
3140 --systems=os1,os2,...
3141 search man pages for different operating systems.
3142 --title='text' set the title of the viewer window (not in all modes.
3143 --tty force paging on text terminal even when in X.
3144 --www display in a web browser.
3145 --www-viewer choose the web browser for www mode.
3146 --x display in an X roff viewer.
3147 --x-viewer choose viewer program for x mode.
3148 --xrm='resource' set X resouce.
3151 eval "${return_ok}";
3155 ########################################################################
3158 # print version information to stderr
3162 echo2
"${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3163 # also display groff's version, but not the called subprograms
3164 groff -v 2>&1 |
sed -e '/^ *$/q' |
sed -e '1s/^/is part of /' >&2;
3168 ########################################################################
3169 # warning (<string>)
3171 # Print warning to stderr
3175 echo2
"warning: $*";
3179 ########################################################################
3180 # what_is (<filename>)
3182 # Interpret <filename> as a man page and display its `whatis'
3183 # information as a fragment written in the groff language.
3187 func_check what_is
= 1 "$@";
3190 if is_not_file
"$1"; then
3191 error
"what_is(): argument is not a readable file."
3193 _dot
='^\.['"${_SPACE}${_TAB}"']*';
3198 # grep the line containing `.TH' macro, if any
3199 _res
="$(catz "$1" | sed -e '/'"${_dot}"'TH /p
3201 if is_not_empty
"${_res}"; then # traditional man style
3202 # get the text between the first and the second `.SH' macro, by
3203 # - delete up to first .SH;
3204 # - of this, print everything up to next .SH, and delete the rest;
3205 # - of this, delete the final .SH line;
3206 catz
"$1" |
sed -e '1,/'"${_dot}"'SH/d' \
3207 |
sed -e '1,/'"${_dot}"'SH/p
3209 |
sed -e '/'"${_dot}"'SH/d';
3210 eval "${return_ok}";
3212 # grep the line containing `.Dd' macro, if any
3213 _res
="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p
3215 if is_not_empty
"${_res}"; then # BSD doc style
3216 # get the text between the first and the second `.Nd' macro, by
3217 # - delete up to first .Nd;
3218 # - of this, print everything up to next .Nd, and delete the rest;
3219 # - of this, delete the final .Nd line;
3220 catz
"$1" |
sed -e '1,/'"${_dot}"'Nd/d' \
3221 |
sed -e '1,/'"${_dot}"'Nd/p
3223 |
sed -e '/'"${_dot}"'Nd/d';
3224 eval "${return_ok}";
3226 echo 'is not a man page.';
3227 eval "${return_bad}";
3231 ########################################################################
3234 # Output path of a program if in $PATH.
3236 # Arguments : >=1 (empty allowed)
3237 # more args are ignored, this allows to specify progs with arguments
3238 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3242 func_check where
'>=' 1 "$@";
3247 if is_empty
"${_arg}"; then
3248 eval "${return_bad}";
3252 if test -f "${_arg}" && test -x "${_arg}"; then
3253 eval "${return_ok}";
3255 eval "${return_bad}";
3259 eval set -- "$(path_split "${PATH}")";
3262 */) _file
=$p${_arg}; ;;
3263 *) _file
=$p/${_arg}; ;;
3265 if test -f "${_file}" && test -x "${_file}"; then
3267 eval "${return_ok}";
3270 eval "${return_bad}";
3274 ########################################################################
3276 ########################################################################
3278 # The main area contains the following parts:
3279 # - main_init(): initialize temporary files and set exit trap
3281 # - main_parse_args(): argument parsing
3282 # - determine display mode
3283 # - process filespec arguments
3284 # - setup X resources
3285 # - do the displaying
3287 # These parts are implemented as functions, being defined below in the
3288 # sequence they are called in the main() function.
3291 #######################################################################
3294 # set exit trap and create temporary files
3296 # Globals: $_TMP_CAT, $_TMP_STDIN
3298 landmark
'13: main_init()';
3301 func_check main_init
= 0 "$@";
3302 # call clean_up() on any signal
3305 for f
in ${_CONFFILES}; do
3306 if is_file
"$f"; then
3311 # determine temporary directory
3314 for d
in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3315 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.';
3317 if test "$d" != ""; then
3318 if test -d "$d" && test -r "$d" && test -w "$d"; then
3319 _TMP_DIR
="${d}/${_PROGRAM_NAME}${_PROCESS_ID}";
3320 if test -d "${_TMP_DIR}"; then
3321 rm -f "${_TMP_DIR}"/*;
3324 mkdir
"${_TMP_DIR}";
3325 if test ! -d "${_TMP_DIR}"; then
3332 if test ! -w "${_TMP_DIR}"; then
3339 if test "${_TMP_DIR}" = ''; then
3340 error
"Couldn't create a directory for storing temporary files.";
3343 _TMP_CAT
="$(tmp_create groffer_cat)";
3344 _TMP_STDIN
="$(tmp_create groffer_input)";
3345 eval "${return_ok}";
3349 ########################################################################
3350 # main_parse_MANOPT ()
3352 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3353 # string; found man arguments can be overwritten by the command line.
3356 # in: $MANOPT, $_OPTS_MAN_*
3358 # in/out: $GROFFER_OPT
3360 landmark
'14: main_parse_MANOPT()';
3363 func_check main_parse_MANOPT
= 0 "$@";
3367 if test "${MANOPT}" != ''; then
3368 MANOPT
="$(echo -n "${MANOPT}" | \
3369 sed -e 's/^'"${_SPACE}${_SPACE}"'*//')";
3371 if test "${MANOPT}" = ''; then
3372 eval "${return_ok}";
3374 # add arguments in $MANOPT by mapping them to groffer options
3375 eval set -- "$(list_from_cmdline \
3376 "${_OPTS_MAN_SHORT_NA}" "${_OPTS_MAN_SHORT_ARG}" \
3377 "${_OPTS_MAN_LONG_NA}" "${_OPTS_MAN_LONG_ARG}" \
3379 until test "$#" -le 0 || is_equal
"$1" '--'; do
3384 _list
="$(list_append "${_list}" '--ascii')";
3387 _list
="$(list_append "${_list}" '--all')";
3394 _list
="$(list_append "${_list}" '--debug')";
3397 # undo all man options so far
3401 _list
="$(list_append "${_list}" '--extension')";
3405 _list
="$(list_append "${_list}" '--whatis')";
3413 _list
="$(list_append "${_list}" '--apropos')";
3417 _list
="$(list_append "${_list}" '--local-file')";
3420 _list
="$(list_append "${_list}" '--locale' "$1")";
3424 _list
="$(list_append "${_list}" '--systems' "$1")";
3428 _list
="$(list_append "${_list}" '--manpath' "$1")";
3436 _list
="$(list_append "${_list}" '--pager' "$1")";
3444 _list
="$(list_append "${_list}" '--sections' "$1")";
3452 _list
="$(list_append "${_list}" '-T' "$1")";
3462 -w|
--where|
--location)
3463 _list
="$(list_append "${_list}" '--location')";
3466 _list
="$(list_append "${_list}" '-Z' "$1")";
3469 # ignore all other options
3472 GROFFER_OPT
="$(list_from_lists "${_list}" "${GROFFER_OPT}")";
3473 eval "${return_ok}";
3474 } # main_parse_MANOPT()
3477 ########################################################################
3478 # main_parse_args (<command_line_args>*)
3480 # Parse arguments; process options and filespec parameters
3482 # Arguments: pass the command line arguments unaltered.
3485 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3487 landmark
'15: main_parse_args()';
3490 func_check main_parse_args
'>=' 0 "$@";
3502 eval set -- "${GROFFER_OPT}" '"$@"';
3504 eval set -- "$(list_from_cmdline \
3505 "$_OPTS_CMDLINE_SHORT_NA" "$_OPTS_CMDLINE_SHORT_ARG" \
3506 "$_OPTS_CMDLINE_LONG_NA" "$_OPTS_CMDLINE_LONG_ARG" \
3509 # By the call of `eval', unnecessary quoting was removed. So the
3510 # positional shell parameters ($1, $2, ...) are now guaranteed to
3511 # represent an option or an argument to the previous option, if any;
3512 # then a `--' argument for separating options and
3513 # parameters; followed by the filespec parameters if any.
3515 # Note, the existence of arguments to options has already been checked.
3516 # So a check for `$#' or `--' should not be done for arguments.
3518 until test "$#" -le 0 || is_equal
"$1" '--'; do
3519 _opt
="$1"; # $_opt is fed into the option handler
3526 -Q|
--source) # output source code (`Quellcode').
3529 -T|
--device|
--troff-device)
3544 -Z|
--ditroff|
--intermediate-output)
3545 # groff intermediate output
3549 # delete leading `-'
3550 _optchar
="$(echo -n "${_opt}" | sed -e 's/^.//')";
3551 if list_has
"${_OPTS_GROFF_SHORT_NA}" "${_optchar}";
3553 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" \
3555 elif list_has
"${_OPTS_GROFF_SHORT_ARG}" "${_optchar}";
3557 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" \
3561 error
"Unknown option : \`$1'";
3568 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" \
3574 --auto) # the default automatic mode
3577 --bd) # border color for viewers, arg;
3581 --bg|
--backgroud) # background color for viewers, arg;
3585 --bw) # border width for viewers, arg;
3589 --default) # reset variables to default
3592 --default-modes) # sequence of modes in auto mode; arg
3593 _OPT_DEFAULT_MODES
="$1";
3596 --debug) # sequence of modes in auto mode; arg
3599 --display) # set X display, arg
3606 --dvi-viewer) # viewer program for dvi mode; arg
3607 _OPT_VIEWER_DVI
="$1";
3610 --extension) # the extension for man pages, arg
3611 _OPT_EXTENSION
="$1";
3614 --fg|
--foreground) # foreground color for viewers, arg;
3618 --fn|
--font) # set font for viewers, arg;
3622 --geometry) # window geometry for viewers, arg;
3629 --locale) # set language for man pages, arg
3630 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3634 --local-file) # force local files; same as `--no-man'
3638 --location|
--where) # print file locations to stderr
3639 _OPT_LOCATION
='yes';
3641 --man) # force all file params to be man pages
3645 --manpath) # specify search path for man pages, arg
3646 # arg is colon-separated list of directories
3650 --mode) # display mode
3654 auto|
'') # the default automatic mode
3657 groff) # pass input to plain groff
3660 dvi
) # display with xdvi viewer
3663 pdf
) # display with PDF viewer
3666 ps
) # display with Postscript viewer
3669 X|x
) # output on X roff viewer
3672 tty
) # output on terminal
3675 Q|
source) # display source code
3679 error
"unknown mode ${_arg}";
3682 _OPT_MODE
="${_mode}";
3684 --no-location) # disable former call to `--location'
3685 _OPT_LOCATION
='yes';
3687 --no-man) # disable search for man pages
3688 # the same as --local-file
3692 --pager) # set paging program for tty mode, arg
3699 --pdf-viewer) # viewer program for ps mode; arg
3700 _OPT_VIEWER_PDF
="$1";
3706 --ps-viewer) # viewer program for ps mode; arg
3707 _OPT_VIEWER_PS
="$1";
3710 --resolution) # set resolution for X devices, arg
3721 error
"only resoutions of 75 or 100 dpi are supported";
3724 _OPT_RESOLUTION
="${_dpi}";
3729 --sections) # specify sections for man pages, arg
3730 # arg is colon-separated list of section names
3737 --systems) # man pages for different OS's, arg
3738 # argument is a comma-separated list
3742 --title) # title for X viewers; arg
3749 --tty-device) # device for tty mode; arg
3750 _OPT_TTY_DEVICE
="$1";
3756 --www) # display with web browser
3759 --www-viewer) # viewer program for www mode; arg
3760 _OPT_VIEWER_WWW
="$1";
3766 --xrm) # pass X resource string, arg;
3767 _OPT_XRM
="$(list_append "${_OPT_XRM}" "$1")";
3770 --x-viewer) # viewer program for x mode; arg
3775 error
'error on argument parsing : '"\`$*'";
3779 shift; # remove `--' argument
3781 if test "${_DEBUG}" != 'yes'; then
3782 if test "${_OPT_DEBUG}" = 'yes'; then
3787 # Remaining arguments are file names (filespecs).
3788 # Save them to list $_FILEARGS
3789 if test "$#" -eq 0; then # use "-" for standard input
3792 _FILEARGS
="$(list_from_args "$@
")";
3793 if list_has
"$_FILEARGS" '-'; then
3796 # $_FILEARGS must be retrieved with `eval set -- "$_FILEARGS"'
3797 eval "${return_ok}";
3798 } # main_parse_args()
3801 ########################################################################
3804 # Determine the display mode.
3807 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
3808 # out: $_DISPLAY_MODE
3811 # _get_first_prog (<proglist>)
3813 # Retrieve first argument that represents an existing program in $PATH.
3814 # Local function for main_set_mode().
3816 # Arguments: 1; a comma-separated list of commands (with options),
3819 # Return : `1' if none found, `0' if found.
3820 # Output : the argument that succeded.
3822 landmark
'16: main_set_mode()';
3825 func_check main_set_mode
= 0 "$@";
3832 if is_yes
"${_OPT_APROPOS}"; then
3840 if is_not_empty
"${_OPT_DISPLAY}"; then
3841 DISPLAY
="${_OPT_DISPLAY}";
3844 if is_yes
"${_OPT_V}"; then
3845 _DISPLAY_MODE
='groff';
3846 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" '-V')";
3848 if is_yes
"${_OPT_X}"; then
3849 _DISPLAY_MODE
='groff';
3850 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" '-X')";
3852 if is_yes
"${_OPT_Z}"; then
3853 _DISPLAY_MODE
='groff';
3854 _ADDOPTS_GROFF
="$(list_append "${_ADDOPTS_GROFF}" '-Z')";
3856 if is_equal
"${_OPT_MODE}" 'groff'; then
3857 _DISPLAY_MODE
='groff';
3859 if is_equal
"${_DISPLAY_MODE}" 'groff'; then
3860 eval "${return_ok}";
3863 if is_equal
"${_OPT_MODE}" 'source'; then
3864 _DISPLAY_MODE
='source';
3865 eval "${return_ok}";
3868 case "${_OPT_MODE}" in
3869 '') # automatic mode
3870 case "${_OPT_DEVICE}" in
3872 if is_empty
"${DISPLAY}"; then
3873 error
"no X display found for device ${_OPT_DEVICE}";
3876 eval "${return_ok}";
3878 ascii|cp1047|latin1|utf8
)
3879 _DISPLAY_MODE
='tty';
3880 eval "${return_ok}";
3883 if is_empty
"${DISPLAY}"; then
3884 _DISPLAY_MODE
='tty';
3885 eval "${return_ok}";
3888 if is_empty
"${_OPT_DEFAULT_MODES}"; then
3889 _modes
="${_DEFAULT_MODES}";
3891 _modes
="${_OPT_DEFAULT_MODES}";
3895 _DISPLAY_MODE
='tty';
3896 eval "${return_ok}";
3898 *) # display mode was given
3899 if is_empty
"${DISPLAY}"; then
3900 error
"you must be in X Window for ${_OPT_MODE} mode.";
3902 _modes
="${_OPT_MODE}";
3906 # only viewer modes are left
3907 eval set -- "$(list_from_split "${_modes}" ',')";
3908 while test "$#" -gt 0; do
3913 _DISPLAY_MODE
='tty';
3914 eval "${return_ok}";
3917 if is_not_empty
"${_OPT_VIEWER_X}"; then
3918 _viewers
="${_OPT_VIEWER_X}";
3920 _viewers
="${_VIEWER_X}";
3922 _viewer
="$(_get_first_prog "${_viewers}")";
3923 if test "$?" -ne 0; then
3926 _DISPLAY_PROG
="${_viewer}";
3928 eval "${return_ok}";
3931 if is_not_empty
"${_OPT_VIEWER_DVI}"; then
3932 _viewers
="${_OPT_VIEWER_DVI}";
3934 _viewers
="${_VIEWER_DVI}";
3936 _viewer
="$(_get_first_prog "${_viewers}")";
3937 if test "$?" -ne 0; then
3940 _DISPLAY_PROG
="${_viewer}";
3941 _DISPLAY_MODE
="dvi";
3942 eval "${return_ok}";
3945 if is_not_empty
"${_OPT_VIEWER_PDF}"; then
3946 _viewers
="${_OPT_VIEWER_PDF}";
3948 _viewers
="${_VIEWER_PDF}";
3950 _viewer
="$(_get_first_prog "${_viewers}")";
3951 if test "$?" -ne 0; then
3954 _DISPLAY_PROG
="${_viewer}";
3955 _DISPLAY_MODE
="pdf";
3956 eval "${return_ok}";
3959 if is_not_empty
"${_OPT_VIEWER_PS}"; then
3960 _viewers
="${_OPT_VIEWER_PS}";
3962 _viewers
="${_VIEWER_PS}";
3964 _viewer
="$(_get_first_prog "${_viewers}")";
3965 if test "$?" -ne 0; then
3968 _DISPLAY_PROG
="${_viewer}";
3970 eval "${return_ok}";
3973 if is_not_empty
"${_OPT_VIEWER_WWW}"; then
3974 _viewers
="${_OPT_VIEWER_WWW}";
3976 _viewers
="${_VIEWER_WWW}";
3978 _viewer
="$(_get_first_prog "${_viewers}")";
3979 if test "$?" -ne 0; then
3982 _DISPLAY_PROG
="${_viewer}";
3983 _DISPLAY_MODE
="www";
3984 eval "${return_ok}";
3988 error
"no suitable display mode found.";
3994 if test "$#" -eq 0; then
3995 error
"_get_first_prog() needs 1 argument.";
3997 if is_empty
"$1"; then
4000 eval set -- "$(list_from_split "$1" ',')";
4002 if is_empty
"$i"; then
4005 if is_prog
"$(get_first_essential $i)"; then
4014 #######################################################################
4015 # main_do_fileargs ()
4017 # Process filespec arguments in $_FILEARGS.
4020 # in: $_FILEARGS (process with `eval set -- "$_FILEARGS"')
4022 landmark
'17: main_do_fileargs()';
4025 func_check main_do_fileargs
= 0 "$@";
4029 _exitcode
="${_BAD}";
4030 eval set -- "${_FILEARGS}";
4032 # temporary storage of all input to $_TMP_CAT
4033 while test "$#" -ge 2; do
4034 # test for `s name' arguments, with `s' a 1-char standard section
4037 case "${_filespec}" in
4042 if register_file
'-'; then
4043 _exitcode
="${_GOOD}";
4048 if list_has_not
"${_MAN_AUTO_SEC}" "${_filespec}"; then
4049 if do_filearg
"${_filespec}"; then
4050 _exitcode
="${_GOOD}";
4056 */*|man
:*|
*\
(*\
)|
*.
"${_filespec}")
4057 if do_filearg
"${_filespec}"; then
4058 _exitcode
="${_GOOD}";
4063 if do_filearg
"man:${_name}(${_filespec})"; then
4064 _exitcode
="${_GOOD}";
4068 if do_filearg
"${_filespec}"; then
4069 _exitcode
="${_GOOD}";
4075 if do_filearg
"${_filespec}"; then
4076 _exitcode
="${_GOOD}";
4081 done; # end of `s name' test
4082 while test "$#" -gt 0; do
4085 if do_filearg
"${_filespec}"; then
4086 _exitcode
="${_GOOD}";
4089 rm -f "${_TMP_STDIN}";
4090 if is_equal
"${_exitcode}" "${_BAD}"; then
4091 eval "${return_bad}";
4093 eval "${return_ok}";
4094 } # main_do_fileargs()
4097 ########################################################################
4098 # main_set_resources ()
4100 # Determine options for setting X resources with $_DISPLAY_PROG.
4102 landmark
'18: main_set_resources()';
4103 main_set_resources
()
4105 func_check main_set_resources
= 0 "$@";
4106 local _prog
; # viewer program
4107 local _rl
; # resource list
4109 if is_empty
"${_DISPLAY_PROG}"; then
4110 eval "${return_ok}";
4112 set -- ${_DISPLAY_PROG};
4113 _prog
="$(base_name "$1")";
4114 if is_not_empty
"${_OPT_BD}"; then
4116 ghostview|gv|gxditview|xditview|xdvi
)
4117 _rl
="$(list_append "$_rl" '-bd' "${_OPT_BD}")";
4121 if is_not_empty
"${_OPT_BG}"; then
4123 ghostview|gv|gxditview|xditview|xdvi
)
4124 _rl
="$(list_append "$_rl" '-bg' "${_OPT_BG}")";
4127 _rl
="$(list_append "$_rl" '-papercolor' "${_OPT_BG}")";
4131 if is_not_empty
"${_OPT_BW}"; then
4133 ghostview|gv|gxditview|xditview|xdvi
)
4134 _rl
="$(list_append "$_rl" '-bw' "${_OPT_BW}")";
4138 if is_not_empty
"${_OPT_FG}"; then
4140 ghostview|gv|gxditview|xditview|xdvi
)
4141 _rl
="$(list_append "$_rl" '-fg' "${_OPT_FG}")";
4145 if is_not_empty
"${_OPT_FN}"; then
4147 ghostview|gv|gxditview|xditview|xdvi
)
4148 _rl
="$(list_append "$_rl" '-fn' "${_OPT_FN}")";
4152 if is_not_empty
"${_OPT_GEOMETRY}"; then
4154 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4155 _rl
="$(list_append "$_rl" '-geometry' "${_OPT_GEOMETRY}")";
4159 if is_empty
"${_OPT_RESOLUTION}"; then
4162 _rl
="$(list_append "$_rl" \
4163 '-resolution' "${_DEFAULT_RESOLUTION}")";
4166 case "${_DEFAULT_RESOLUTION}" in
4168 _rl
="$(list_append "$_rl" '-z' '2')";
4171 _rl
="$(list_append "$_rl" '-z' '3')";
4178 ghostview|gv|gxditview|xditview|xdvi
)
4179 _rl
="$(list_append "$_rl" '-resolution' "${_OPT_RESOLUTION}")";
4182 case "${_OPT_RESOLUTION}" in
4184 _rl
="$(list_append "$_rl" '-z' '2')";
4187 _rl
="$(list_append "$_rl" '-z' '3')";
4193 if is_not_empty
"${_OPT_RV}"; then
4195 ghostview|gv|gxditview|xditview|xdvi
)
4196 _rl
="$(list_append "$_rl" '-rv')";
4200 if is_not_empty
"${_OPT_XRM}"; then
4202 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4203 eval set -- "{$_OPT_XRM}";
4205 _rl
="$(list_append "$_rl" '-xrm' "$i")";
4210 _title
="$(get_first_essential \
4211 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4212 if is_not_empty
"${_title}"; then
4215 _rl
="$(list_append "$_rl" '-title' "${_title}")";
4219 _DISPLAY_ARGS
="${_rl}";
4220 eval "${return_ok}";
4221 } # main_set_resources
4224 ########################################################################
4227 # Do the actual display of the whole thing.
4230 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4231 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4232 # $_REGISTERED_TITLE, $_TMP_CAT,
4233 # $_OPT_PAGER $PAGER $_MANOPT_PAGER
4235 landmark
'19: main_display()';
4238 func_check main_display
= 0 "$@";
4251 # Some display programs have trouble with empty input.
4252 # This is avoided by feeding a space character in this case.
4253 # Test on non-empty file by tracking a line with at least 1 character.
4254 if is_empty
"$(tmp_cat | sed -e '/./q')"; then
4255 echo ' ' > "${_TMP_CAT}";
4258 case "${_DISPLAY_MODE}" in
4260 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4261 if is_not_empty
"${_OPT_DEVICE}"; then
4262 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4264 _groggy
="$(tmp_cat | eval grog "${_options}")";
4266 # start a new shell program to get another process ID.
4270 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4271 rm -f "${_modefile}";
4272 mv "${_TMP_CAT}" "${_modefile}";
4273 rm -f "${_TMP_CAT}";
4274 cat "${_modefile}" | \
4278 rm -f "${_modefile}";
4280 trap clean_up 0 2>/dev/null || true;
4281 eval "${_groggy}" "${_ADDOPTS_GROFF}";
4285 case "${_OPT_DEVICE}" in
4287 _device
="$(get_first_essential \
4288 "${_OPT_TTY_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4290 ascii|cp1047|latin1|utf8
)
4291 _device
="${_OPT_DEVICE}";
4295 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4298 _addopts
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4299 _groggy
="$(tmp_cat | grog -T${_device})";
4301 for p
in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4302 'less' 'more' 'cat'; do
4303 if is_prog
"$p"; then
4308 if is_empty
"${_pager}"; then
4309 error
'no pager program found for tty mode';
4311 tmp_cat |
eval "${_groggy}" "${_addopts}" | \
4319 case "${_OPT_DEVICE}" in
4320 ''|dvi
) do_nothing
; ;;
4323 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4326 _groggy
="$(tmp_cat | grog -Tdvi)";
4330 case "${_OPT_DEVICE}" in
4336 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4339 _groggy
="$(tmp_cat | grog -Tps)";
4341 # start a new shell program to get another process ID.
4345 _psfile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4346 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}.pdf";
4348 rm -f "${_modefile}";
4349 cat "${_TMP_CAT}" | \
4350 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4351 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4352 -sOutputFile="${_modefile}" -c save pop -f "${_psfile}";
4354 rm -f "${_TMP_CAT}";
4358 rm -f "${_modefile}";
4360 trap clean_up 0 2>/dev/null || true;
4361 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4365 case "${_OPT_DEVICE}" in
4371 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4374 _groggy
="$(tmp_cat | grog -Tps)";
4382 case "${_OPT_DEVICE}" in
4383 ''|html
) do_nothing
; ;;
4386 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4389 _groggy
="$(tmp_cat | grog -Thtml)";
4393 case "${_OPT_DEVICE}" in
4395 _groggy
="$(tmp_cat | grog -Z)";
4398 _groggy
="$(tmp_cat | grog -T"${_OPT_DEVICE}" -Z)";
4402 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4403 _groggy
="$(tmp_cat | grog -Z)";
4409 error
"unknown mode \`${_DISPLAY_MODE}'";
4412 eval "${return_ok}";
4418 # start a new shell program for another process ID and better
4419 # cleaning-up of the temporary files.
4423 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4424 rm -f "${_modefile}";
4425 cat "${_TMP_CAT}" | \
4426 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}";
4427 rm -f "${_TMP_CAT}";
4431 if test -d "${_TMP_DIR}"; then
4432 rm -f "${_TMP_DIR}"/*;
4433 rmdir "${_TMP_DIR}";
4436 trap clean_up 0 2>/dev/null || true;
4437 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4442 ########################################################################
4443 # main (<command_line_args>*)
4445 # The main function for groffer.
4451 func_check main
'>=' 0 "$@";
4452 # Do not change the sequence of the following functions!
4455 main_parse_args
"$@";
4460 eval "${return_ok}";
4463 landmark
'20: end of function definitions';
4465 ########################################################################