3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer.sh
7 # Copyright (C) 2001,2002,2003,2004,2005 Free Software Foundation, Inc.
8 # Written by Bernd Warken
10 # This file is part of groff version @VERSION@.
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 files COPYING and LICENSE in the top
24 # directory of the groff source. If not, write to the Free Software
25 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
27 _PROGRAM_NAME
='groffer';
28 _PROGRAM_VERSION
='0.9.13';
29 _LAST_UPDATE
='17 May 2005';
32 ########################################################################
33 # Determine the shell under which to run this script from the command
34 # line arguments or $GROFF_OPT; if none is specified, just go on with
37 if test _
"${_groffer_run}"_
= __
; then
38 # only reached during the first run of the script
40 export _groffer_run
; # counter for the runs of groffer
44 export _PROGRAM_VERSION
;
47 export GROFFER_OPT
; # option environment for groffer
48 export _GROFFER_SH
; # file name of this shell script
49 export _OUTPUT_FILE_NAME
; # output generated, see main_set_res..()
51 export _CONFFILES
; # configuration files
52 _CONFFILES
="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
57 # was: _GROFFER_SH="@BINDIR@/${_PROGRAM_NAME}";
60 echo "The ${_PROGRAM_NAME} script should be started directly." >&2
65 ###########################
66 # _get_opt_shell ("$@")
68 # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
69 # if so echo its argument.
75 case " ${GROFFER_OPT} $*" in
76 *\
--shell\
*|
*\
--shell=*)
78 eval set -- "${GROFFER_OPT}" '"$@"';
83 if test "$#" -ge 2; then
89 # delete up to first `=' character
90 _sh
="$(echo -n "$1" | sed -e 's/^[^=]*=//')";
102 ###########################
103 # _test_on_shell (<name>)
105 # Test whether <name> is a shell program of Bourne type (POSIX sh).
109 if test "$#" -le 0 ||
test _
"$1"_
= __
; then
112 # do not quote $1 to allow arguments
113 test _
"$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)"_
= _ok_
;
116 # do the shell determination from command line and $GROFFER_OPT
117 _shell
="$(_get_opt_shell "$@
")";
119 if test _
"${_shell}"_
= __
; then
120 # none found, so look at the `--shell' lines in configuration files
122 for f
in ${_CONFFILES}; do
124 _all
="$(cat $f | sed -n -e '/^--shell[= ] *\([^ ]*\)$/s//\1/p')"
135 # restart the script with the last found $_shell, if it is a shell
136 if _test_on_shell
"${_shell}"; then
137 _groffer_run
='second';
138 # do not quote $_shell to allow arguments
139 exec ${_shell} "${_GROFFER_SH}" "$@";
143 _groffer_run
='second';
146 fi; # end of first run
148 if test _
"${_groffer_run}"_
!= _second_
;
150 echo "$_groffer_run should be 'second' here." >&2
157 ########################################################################
158 # diagnostic messages
161 _DEBUG
='no'; # disable debugging information
162 #_DEBUG='yes'; # enable debugging information
165 _DEBUG_LM
='no'; # disable landmark messages
166 #_DEBUG_LM='yes'; # enable landmark messages
169 ########################################################################
170 # Environment Variables
171 ########################################################################
173 # Environment variables that exist only for this file start with an
174 # underscore letter. Global variables to this file are written in
175 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
176 # start with an underline and use only lower case letters and
177 # underlines, e.g. $_local_variable .
179 # [A-Z]* system variables, e.g. $MANPATH
180 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
181 # _[a-z_]* temporary variables, e.g. $_manpath
183 # Due to incompatibilities of the `ash' shell, the name of loop
184 # variables in `for' must be single character
185 # [a-z] local loop variables, e.g. $i
188 ########################################################################
189 # read-only variables (global to this file)
190 ########################################################################
219 # function return values; `0' means ok
; other values are error codes
228 _GOOD
='0'; # return ok
229 _BAD
='1'; # return negatively, error code `1'
230 _ERROR
='7'; # for syntax errors; no `-1' in `ash'
232 _ALL_EXIT
="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
238 # quasi-functions, call with `eval'
245 return_ok
="func_pop; return ${_OK}";
246 return_good
="func_pop; return ${_GOOD}";
247 return_bad
="func_pop; return ${_BAD}";
248 return_yes
="func_pop; return ${_YES}";
249 return_no
="func_pop; return ${_NO}";
250 return_error
="func_pop; return ${_ERROR}";
253 export _DEFAULT_MODES
;
254 _DEFAULT_MODES
='x,ps,tty';
255 export _DEFAULT_RESOLUTION
;
256 _DEFAULT_RESOLUTION
='75';
258 export _DEFAULT_TTY_DEVICE
;
259 _DEFAULT_TTY_DEVICE
='latin1';
261 # _VIEWER_* viewer programs for different modes (only X is necessary)
262 # _VIEWER_* a comma-separated list of viewer programs (with options)
263 export _VIEWER_DVI
; # viewer program for dvi mode
264 export _VIEWER_PS
; # viewer program for ps mode
265 export _VIEWER_HTML_X
; # viewer program for html mode in X
266 export _VIEWER_HTML_TTY
; # viewer program for html mode in tty
267 _VIEWER_DVI
='kdvi,xdvi,dvilx';
268 _VIEWER_PDF
='kghostview,ggv,xpdf,acroread,kpdf';
269 _VIEWER_PS
='kghostview,ggv,gv,ghostview,gs_x11,gs';
270 _VIEWER_HTML
='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
271 _VIEWER_X
='gxditview,xditview';
273 # Search automatically in standard sections `1' to `8', and in the
274 # traditional sections `9', `n', and `o'. On many systems, there
275 # exist even more sections, mostly containing a set of man pages
276 # special to a specific program package. These aren't searched for
277 # automatically, but must be specified on the command line.
278 export _MAN_AUTO_SEC
;
279 _MAN_AUTO_SEC
="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
281 export _PROCESS_ID
; # for shutting down the program
285 ############ the command line options of the involved programs
287 # The naming scheme for the options environment names is
288 # $_OPTS_<prog>_<length>[_<argspec>]
290 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
291 # command line options)
292 # <length>: LONG (long options) or SHORT (single character options)
293 # <argspec>: ARG for options with argument, NA for no argument;
294 # without _<argspec> both the ones with and without arg.
296 # Each option that takes an argument must be specified with a
297 # trailing : (colon).
300 export _OPTS_GROFFER_SHORT_NA
;
301 export _OPTS_GROFFER_SHORT_ARG
;
302 export _OPTS_GROFFER_LONG_NA
;
303 export _OPTS_GROFFER_LONG_ARG
;
304 export _OPTS_GROFF_SHORT_NA
;
305 export _OPTS_GROFF_SHORT_ARG
;
306 export _OPTS_GROFF_LONG_NA
;
307 export _OPTS_GROFF_LONG_ARG
;
308 export _OPTS_X_SHORT_ARG
;
309 export _OPTS_X_SHORT_NA
;
310 export _OPTS_X_LONG_ARG
;
311 export _OPTS_X_LONG_NA
;
312 export _OPTS_MAN_SHORT_ARG
;
313 export _OPTS_MAN_SHORT_NA
;
314 export _OPTS_MAN_LONG_ARG
;
315 export _OPTS_MAN_LONG_NA
;
316 export _OPTS_MANOPT_SHORT_ARG
;
317 export _OPTS_MANOPT_SHORT_NA
;
318 export _OPTS_MANOPT_LONG_ARG
;
319 export _OPTS_MANOPT_LONG_NA
;
320 export _OPTS_CMDLINE_SHORT_NA
;
321 export _OPTS_CMDLINE_SHORT_ARG
;
322 export _OPTS_CMDLINE_LONG_NA
;
323 export _OPTS_CMDLINE_LONG_ARG
;
325 ###### groffer native options
327 _OPTS_GROFFER_SHORT_NA
="'h' 'Q' 'v' 'V' 'X' 'Z'";
328 _OPTS_GROFFER_SHORT_ARG
="'T'";
330 _OPTS_GROFFER_LONG_NA
="'auto' 'debug' 'default' 'dvi' \
331 'groff' 'help' 'intermediate-output' 'html' 'man' \
332 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
333 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
335 _OPTS_GROFFER_LONG_ARG
="\
336 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
337 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
338 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
339 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
341 ##### groffer options inhereted from groff
343 _OPTS_GROFF_SHORT_NA
="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
344 'R' 's' 'S' 't' 'U' 'z'";
345 _OPTS_GROFF_SHORT_ARG
="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
347 _OPTS_GROFF_LONG_NA
="";
348 _OPTS_GROFF_LONG_ARG
="";
350 ##### groffer options inhereted from the X Window toolkit
353 _OPTS_X_SHORT_ARG
="";
355 _OPTS_X_LONG_NA
="'iconic' 'rv'";
357 _OPTS_X_LONG_ARG
="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
358 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'
359 'resolution' 'title' 'xrm'";
361 ###### groffer options inherited from man
363 _OPTS_MAN_SHORT_NA
="";
364 _OPTS_MAN_SHORT_ARG
="";
366 _OPTS_MAN_LONG_NA
="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \
367 'local-file' 'location' 'pager' 'troff' 'update' 'version' \
370 _OPTS_MAN_LONG_ARG
="'extension' 'locale' 'manpath' \
371 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
373 ###### additional options for parsing $MANOPT only
375 _OPTS_MANOPT_SHORT_NA
="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
377 _OPTS_MANOPT_SHORT_ARG
="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
379 _OPTS_MANOPT_LONG_NA
="${_OPTS_MAN_LONG_NA} \
380 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
381 'match-case' 'troff' 'update' 'version' 'where-cat'";
383 _OPTS_MANOPT_LONG_ARG
="${_OPTS_MAN_LONG_NA} \
384 'config_file' 'encoding' 'locale'";
386 ###### collections of command line options
388 _OPTS_CMDLINE_SHORT_NA
="${_OPTS_GROFFER_SHORT_NA}\
389 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
390 _OPTS_CMDLINE_SHORT_ARG
="${_OPTS_GROFFER_SHORT_ARG} \
391 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
393 _OPTS_CMDLINE_LONG_NA
="${_OPTS_GROFFER_LONG_NA} \
394 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
395 _OPTS_CMDLINE_LONG_ARG
="${_OPTS_GROFFER_LONG_ARG} \
396 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
399 ########################################################################
400 # read-write variables (global to this file)
401 ########################################################################
403 export _ADDOPTS_GROFF
; # Transp. options for groff (`eval').
404 export _ADDOPTS_POST
; # Transp. options postproc (`eval').
405 export _ADDOPTS_X
; # Transp. options X postproc (`eval').
406 export _DEFAULT_MODES
; # Set default modes.
407 export _DISPLAY_MODE
; # Display mode.
408 export _DISPLAY_PROG
; # Viewer program to be used for display.
409 export _DISPLAY_ARGS
; # X resources for the viewer program.
410 export _FILEARGS
; # Stores filespec parameters.
411 export _FUNC_STACK
; # Store debugging information.
412 export _REGISTERED_TITLE
; # Processed file names.
413 # _HAS_* from availability tests
414 export _HAS_COMPRESSION
; # `yes' if compression is available
415 export _HAS_OPTS_GNU
; # `yes' if GNU `getopt' is available
416 export _HAS_OPTS_POSIX
; # `yes' if POSIX `getopts' is available
417 # _MAN_* finally used configuration of man searching
418 export _MAN_ALL
; # search all man pages per filespec
419 export _MAN_ENABLE
; # enable search for man pages
420 export _MAN_EXT
; # extension for man pages
421 export _MAN_FORCE
; # force file parameter to be man pages
422 export _MAN_IS_SETUP
; # setup man variables only once
423 export _MAN_LANG
; # language for man pages
424 export _MAN_LANG_DONE
; # language dirs added to man path
425 export _MAN_PATH
; # search path for man pages
426 export _MAN_SEC
; # sections for man pages; sep. `:'
427 export _MAN_SEC_DONE
; # sections added to man path
428 export _MAN_SYS
; # system names for man pages; sep. `,'
429 export _MAN_SYS
; # system names added to man path
430 # _MANOPT_* as parsed from $MANOPT
431 export _MANOPT_ALL
; # $MANOPT --all
432 export _MANOPT_EXTENSION
; # $MANOPT --extension
433 export _MANOPT_LANG
; # $MANOPT --locale
434 export _MANOPT_PATH
; # $MANOPT --manpath
435 export _MANOPT_PAGER
; # $MANOPT --pager
436 export _MANOPT_SEC
; # $MANOPT --sections
437 export _MANOPT_SYS
; # $MANOPT --systems
438 # _OPT_* as parsed from groffer command line
439 export _OPT_ALL
; # display all suitable man pages.
440 export _OPT_APROPOS
; # call `apropos' program.
441 export _OPT_APROPOS_DATA
; # `apropos' for man sections 4, 5, 7
442 export _OPT_APROPOS_DEVEL
; # `apropos' for man sections 2, 3, 9
443 export _OPT_APROPOS_PROGS
; # `apropos' for man sections 1, 6, 8
444 export _OPT_BD
; # set border color in some modes.
445 export _OPT_BG
; # set background color in some modes.
446 export _OPT_BW
; # set border width in some modes.
447 export _OPT_DEBUG
; # print debugging information on stderr.
448 export _OPT_DEFAULT_MODES
; # `,'-list of modes when no mode given.
449 export _OPT_DEVICE
; # device option.
450 export _OPT_DISPLAY
; # set X display.
451 export _OPT_FG
; # set foreground color in some modes.
452 export _OPT_FN
; # set font in some modes.
453 export _OPT_GEOMETRY
; # set size and position of viewer in X.
454 export _OPT_ICONIC
; # -iconic option for X viewers.
455 export _OPT_LANG
; # set language for man pages
456 export _OPT_LOCATION
; # print processed file names to stderr
457 export _OPT_MODE
; # values: X, tty, Q, Z, ""
458 export _OPT_MANPATH
; # manual setting of path for man-pages
459 export _OPT_PAGER
; # specify paging program for tty mode
460 export _OPT_RESOLUTION
; # set X resolution in dpi
461 export _OPT_RV
; # reverse fore- and background colors.
462 export _OPT_SECTIONS
; # sections for man page search
463 export _OPT_SYSTEMS
; # man pages of different OS's
464 export _OPT_TITLE
; # title for gxditview window
465 export _OPT_TEXT_DEVICE
; # set device for tty mode.
466 export _OPT_V
; # groff option -V.
467 export _OPT_VIEWER_DVI
; # viewer program for dvi mode
468 export _OPT_VIEWER_PDF
; # viewer program for pdf mode
469 export _OPT_VIEWER_PS
; # viewer program for ps mode
470 export _OPT_VIEWER_HTML
; # viewer program for html mode
471 export _OPT_VIEWER_X
; # viewer program for x mode
472 export _OPT_WHATIS
; # print the one-liner man info
473 export _OPT_XRM
; # specify X resource.
474 export _OPT_Z
; # groff option -Z.
475 # _TMP_* temporary files
476 export _TMP_DIR
; # groffer directory for temporary files
477 export _TMP_CAT
; # stores concatenation of everything
478 export _TMP_STDIN
; # stores stdin, if any
480 # these variables are preset in section `Preset' after the rudim. test
483 ########################################################################
484 # Test of rudimentary shell functionality
485 ########################################################################
488 ########################################################################
491 test "a" = "a" ||
exit 1;
494 ########################################################################
495 # Test of `echo' and the `$()' construct.
497 echo -n '' >/dev
/null ||
exit "${_ERROR}";
498 if test _
"$(echo -n 'te' && echo -n '' && echo -n 'st')"_
!= _test_
; then
503 ########################################################################
504 # Test of function definitions.
511 if _t_e_s_t_f_u_n_c_
2>/dev
/null
; then
514 echo 'shell does not support function definitions.' >&2;
519 ########################################################################
520 # Preset and reset of read-write global variables
521 ########################################################################
524 # For variables that can be reset by option `--default', see reset().
528 # _HAS_* from availability tests
533 # _TMP_* temporary files
539 ########################################################################
542 # Reset the variables that can be affected by options to their default.
546 if test "$#" -ne 0; then
547 error
"reset() does not have arguments.";
556 _REGISTERED_TITLE
='';
558 # _MAN_* finally used configuration of man searching
560 _MAN_ENABLE
='yes'; # do search for man-pages
562 _MAN_FORCE
='no'; # first local file, then search man page
572 # _MANOPT_* as parsed from $MANOPT
574 _MANOPT_EXTENSION
='';
581 # _OPT_* as parsed from groffer command line
584 _OPT_APROPOS_DATA
='';
585 _OPT_APROPOS_DEVEL
='';
586 _OPT_APROPOS_PROGS
='';
591 _OPT_DEFAULT_MODES
='';
624 ########################################################################
625 # Functions for error handling and debugging
626 ########################################################################
632 # Print <text> to standard error as a debugging aid.
634 # Globals: $_DEBUG_LM
638 if test _
"${_DEBUG_LM}"_
= _yes_
; then
643 landmark
"1: debugging functions";
653 if test -d "${_TMP_DIR}"; then
654 rm -f -r "${_TMP_DIR}";
664 # Arguments : arbitrary text.
677 # Arguments : arbitrary text.
688 # Output a diagnostic message to stderr
699 # Print an error message to standard error; exit with an error condition
708 1) echo2
'groffer error: '"$1"; ;;
710 echo2
'groffer error: '"$1";
713 *) echo2
'groffer error: wrong number of arguments in error().'; ;;
715 if test _
"${_DEBUG}"_
= _yes_
; then
719 kill "${_PROCESS_ID}" >/dev
/null
2>&1;
720 kill -9 "${_PROCESS_ID}" >/dev
/null
2>&1;
728 # Terminate program with error condition
732 error
"Program aborted.";
738 # func_check (<func_name> <rel_op> <nr_args> "$@")
740 # Check number of arguments and register to _FUNC_STACK.
743 # <func_name>: name of the calling function.
744 # <rel_op>: a relational operator: = != < > <= >=
745 # <nr_args>: number of arguments to be checked against <operator>
746 # "$@": the arguments of the calling function.
755 if test "$#" -lt 3; then
756 error
'func_check() needs at least 3 arguments.';
769 error
"func_check(): third argument must be a digit.";
799 'func_check(): second argument is not a relational operator.';
803 if test "$#" "${_op}" "${_nargs}"; then
807 "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
809 if test _
"${_DEBUG}"_
= _yes_
; then
810 func_push
"${_fname} $*";
818 # Retrieve the top element from the stack.
820 # The stack elements are separated by `!'; the popped element is
821 # identical to the original element, except that all `!' characters
828 if test _
"${_DEBUG}"_
= _yes_
; then
829 if test "$#" -ne 0; then
830 error
'func_pop() does not have arguments.';
832 case "${_FUNC_STACK}" in
834 error
'func_pop(): stack is empty.';
837 # split at first bang `!'.
838 _FUNC_STACK
="$(echo -n ${_FUNC_STACK} \
839 | sed -e 's/^[^!]*!//')";
850 # func_push (<element>)
852 # Store another element to stack.
854 # The stack elements are separated by `!'; if <element> contains a `!'
855 # it is removed first.
862 if test _
"${_DEBUG}"_
= _yes_
; then
863 if test "$#" -ne 1; then
864 error
'func_push() needs 1 argument.';
868 # remove all bangs `!'.
869 _element
="$(echo -n "$1" | sed -e 's/!//g')";
875 if test _
"${_FUNC_STACK}"_
= __
; then
876 _FUNC_STACK
="${_element}";
878 _FUNC_STACK
="${_element}!${_FUNC_STACK}";
887 # Print the content of the stack. Ignore the arguments.
892 case "${_FUNC_STACK}" in
894 _rest
="${_FUNC_STACK}";
895 while test _
"${_rest}"_
!= __
; do
896 # get part before the first bang `!'.
897 diag
"$(echo -n "${_rest}" | sed -e 's/!.*$//')";
898 # delete part before and including the first bang `!'.
899 _rest
="$(echo -n "${_rest}" | sed -e 's/^[^!]*!//')";
903 diag
"${_FUNC_STACK}";
909 ########################################################################
911 ########################################################################
913 landmark
"2: system test";
915 # Test the availability of the system utilities used in this script.
918 ########################################################################
921 if true
>/dev
/null
2>&1; then
936 ########################################################################
940 if unset _test
>/dev
/null
2>&1 && test _
"${_test}"_
= __
; then
952 ########################################################################
953 # Test of builtin `local'
958 local _test
>/dev
/null
2>&1 ||
return "${_BAD}";
961 if _t_e_s_t_f_u_n_c_
; then
966 if test _
"$1"_
!= __
; then
967 error
"overriding global variable \`$1' with local value.";
973 ########################################################################
974 # Test of global setting in functions
987 if test _
"${_global}"_
!= _inside_ ||
test _
"${_clobber}"_
!= _outside_
;
989 error
"Cannot assign to global variables from within functions.";
996 ########################################################################
997 # Test of function `sed'.
1000 if test _
"$(echo xTesTx \
1001 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1002 | sed -e '\|T|s|T|t|g')"_
!= _test_
;
1004 error
'Test of "sed" command failed.';
1008 ########################################################################
1009 # Test of function `cat'.
1011 if test _
"$(echo test | cat)"_
!= _test_
; then
1012 error
'Test of "cat" command failed.';
1016 ########################################################################
1017 # Test for compression.
1019 if test _
"$(echo 'test' | gzip -c -d -f - 2>/dev/null)"_
= _test_
; then
1020 _HAS_COMPRESSION
='yes';
1021 if echo 'test' |
bzip2 -c 2>/dev
/null |
bzip2 -t 2>/dev
/null \
1022 && test _
"$(echo 'test' | bzip2 -c 2>/dev/null \
1023 | bzip2 -d -c 2>/dev/null)"_ \
1030 _HAS_COMPRESSION
='no';
1035 ########################################################################
1042 ########################################################################
1043 # Definition of normal Functions in alphabetical order
1044 ########################################################################
1045 landmark
"3: functions";
1047 ########################################################################
1050 # Unconditionally terminate the program with error code;
1051 # useful for debugging.
1056 ########################################################################
1057 # apropos_run (<name>)
1061 func_check apropos_run
= 1 "$@";
1062 if apropos apropos
>/dev
/null
2>/dev
/null
; then
1064 elif man
--apropos man
>/dev
/null
2>/dev
/null
; then
1066 elif man
-k man
>/dev
/null
2>/dev
/null
; then
1072 ########################################################################
1073 # base_name (<path>)
1075 # Get the file name part of <path>, i.e. delete everything up to last
1076 # `/' from the beginning of <path>. Remove final slashes, too, to get a
1080 # Output : the file name part (without slashes)
1084 func_check base_name
= 1 "$@";
1089 # delete all final slashes
1090 f
="$(echo -n "$f" | sed -e '\|.*|s|//*$||')";
1095 eval "${return_bad}";
1098 # delete everything before and including the last slash `/'.
1099 echo -n "$f" |
sed -e '\|.*|s|^.*//*\([^/]*\)$|\1|';
1105 eval "${return_ok}";
1109 ########################################################################
1112 # Decompress if possible or just print <file> to standard output.
1114 # gzip, bzip2, and .Z decompression is supported.
1116 # Arguments: 1, a file name.
1117 # Output: the content of <file>, possibly decompressed.
1119 if test _
"${_HAS_COMPRESSION}"_
= _yes_
; then
1122 func_check catz
= 1 "$@";
1125 error
'catz(): empty file name';
1128 error
'catz(): for standard input use save_stdin()';
1131 if obj _HAS_BZIP is_yes
; then
1132 if bzip2 -t "$1" 2>/dev
/null
; then
1133 bzip2 -c -d "$1" 2>/dev
/null
;
1134 eval "${return_ok}";
1137 gzip -c -d -f "$1" 2>/dev
/null
;
1138 eval "${return_ok}";
1143 func_check catz
= 1 "$@";
1145 eval "${return_ok}";
1150 ########################################################################
1153 # Do the final cleaning up before exiting; used by the trap calls.
1158 ########################################################################
1161 # Print marked message to standard error; useful for debugging.
1166 ########################################################################
1167 landmark
'4: dirname()*';
1168 ########################################################################
1170 #######################################################################
1171 # dirname_append (<dir> <name>)
1173 # Append `name' to `dir' with clean handling of `/'.
1176 # Output : the generated new directory name <dir>/<name>
1180 func_check dirname_append
= 2 "$@";
1182 if is_empty
"$1"; then
1183 error
"dir_append(): first argument is empty.";
1185 if is_empty
"$2"; then
1188 dirname_chop
"$1"/"$2";
1190 eval "${return_ok}";
1194 ########################################################################
1195 # dirname_chop (<name>)
1197 # Remove unnecessary slashes from directory name.
1199 # Argument: 1, a directory name.
1200 # Output: path without double, or trailing slashes.
1204 func_check dirname_chop
= 1 "$@";
1208 # replace all multiple slashes by a single slash `/'.
1209 _res
="$(echo -n "$1" | sed -e '\|.*|s|///*|/|g')";
1212 # remove trailing slash '/';
1213 echo -n "${_res}" |
sed -e '\|.*|s|/$||';
1215 *) echo -n "${_res}"; ;;
1217 eval "${return_ok}";
1221 ########################################################################
1222 # do_filearg (<filearg>)
1224 # Append the file, man-page, or standard input corresponding to the
1225 # argument to the temporary file. If this is compressed in the gzip
1226 # or Z format it is decompressed. A title element is generated.
1229 # - name of an existing files.
1230 # - `-' to represent standard input (several times allowed).
1231 # - `man:name.(section)' the man-page for `name' in `section'.
1232 # - `man:name.section' the man-page for `name' in `section'.
1233 # - `man:name' the man-page for `name' in the lowest `section'.
1234 # - `name.section' the man-page for `name' in `section'.
1235 # - `name' the man-page for `name' in the lowest `section'.
1237 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1240 # Return : $_GOOD if found, ${_BAD} otherwise.
1244 func_check do_filearg
= 1 "$@";
1248 # store sequence into positional parameters
1249 case "${_filespec}" in
1251 eval "${return_good}";
1255 eval "${return_good}";
1257 */*) # with directory part; so no man search
1261 if obj _MAN_ENABLE is_yes
; then
1262 if obj _MAN_FORCE is_yes
; then
1263 set -- 'Manpage' 'File';
1265 set -- 'File' 'Manpage';
1275 if test -f "${_filespec}"; then
1276 if test -r "${_filespec}"; then
1277 register_file
"${_filespec}";
1278 eval "${return_good}";
1280 echo2
"could not read \`${_filespec}'";
1281 eval "${return_bad}";
1287 Manpage
) # parse filespec as man page
1288 if obj _MAN_IS_SETUP is_not_yes
; then
1291 if man_do_filespec
"${_filespec}"; then
1292 eval "${return_good}";
1299 eval "${return_bad}";
1303 ########################################################################
1314 ########################################################################
1317 # Print to standard error with final line break.
1322 ########################################################################
1325 # Print to standard error without final line break.
1330 ########################################################################
1333 # Print error message and exit with error code.
1338 ########################################################################
1339 # func_check (<func_name> <rel_op> <nr_args> "$@")
1341 # Check number of arguments and register to _FUNC_STACK.
1344 # <func_name>: name of the calling function.
1345 # <rel_op>: a relational operator: = != < > <= >=
1346 # <nr_args>: number of arguments to be checked against <operator>
1347 # "$@": the arguments of the calling function.
1351 #########################################################################
1354 # Delete the top element from the function call stack.
1359 ########################################################################
1360 # func_push (<element>)
1362 # Store another element to function call stack.
1367 ########################################################################
1368 # func_stack_dump ()
1370 # Print the content of the stack.
1375 ########################################################################
1376 # get_first_essential (<arg>*)
1378 # Retrieve first non-empty argument.
1380 # Return : `1' if all arguments are empty, `0' if found.
1381 # Output : the retrieved non-empty argument.
1383 get_first_essential
()
1385 func_check get_first_essential
'>=' 0 "$@";
1387 if is_equal
"$#" 0; then
1388 eval "${return_ok}";
1391 if obj i is_not_empty
; then
1393 eval "${return_ok}";
1396 eval "${return_bad}";
1400 ########################################################################
1401 landmark
'5: is_*()';
1402 ########################################################################
1404 ########################################################################
1407 # Test whether `name' is a directory.
1410 # Return : `0' if arg1 is a directory, `1' otherwise.
1414 func_check is_dir
= 1 "$@";
1415 if test -d "$1" && test -r "$1"; then
1416 eval "${return_yes}";
1418 eval "${return_no}";
1422 ########################################################################
1423 # is_empty (<string>)
1425 # Test whether `string' is empty.
1428 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1432 func_check is_empty
= 1 "$@";
1433 if test _
"$1"_
= __
; then
1434 eval "${return_yes}";
1436 eval "${return_no}";
1440 ########################################################################
1441 # is_equal (<string1> <string2>)
1443 # Test whether `string1' is equal to <string2>.
1446 # Return : `0' both arguments are equal strings, `1' otherwise.
1450 func_check is_equal
= 2 "$@";
1451 if test _
"$1"_
= _
"$2"_
; then
1452 eval "${return_yes}";
1454 eval "${return_no}";
1458 ########################################################################
1459 # is_existing (<name>)
1461 # Test whether `name' is an existing file or directory.
1464 # Return : `0' if arg1 exists, `1' otherwise.
1468 func_check is_existing
= 1 "$@";
1469 if test -e "$1"; then
1470 eval "${return_yes}";
1472 eval "${return_no}";
1476 ########################################################################
1479 # Test whether `name' is a readable file.
1482 # Return : `0' if arg1 is a readable file, `1' otherwise.
1486 func_check is_file
= 1 "$@";
1487 if test -f "$1" && test -r "$1"; then
1488 eval "${return_yes}";
1490 eval "${return_no}";
1494 ########################################################################
1495 # is_non_empty_file (<file_name>)
1497 # Test whether `file_name' is a non-empty existing file.
1501 # `0' if arg1 is a non-empty existing file
1506 func_check is_non_empty_file
= 1 "$@";
1507 if is_file
"$1" && test -s "$1"; then
1508 eval "${return_yes}";
1510 eval "${return_no}";
1514 ########################################################################
1515 # is_not_dir (<name>)
1517 # Test whether `name' is not a readable directory.
1520 # Return : `0' if arg1 is a directory, `1' otherwise.
1524 func_check is_not_dir
= 1 "$@";
1525 if is_dir
"$1"; then
1526 eval "${return_no}";
1528 eval "${return_yes}";
1532 ########################################################################
1533 # is_not_empty (<string>)
1535 # Test whether `string' is not empty.
1538 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1542 func_check is_not_empty
= 1 "$@";
1543 if is_empty
"$1"; then
1544 eval "${return_no}";
1546 eval "${return_yes}";
1550 ########################################################################
1551 # is_not_equal (<string1> <string2>)
1553 # Test whether `string1' differs from `string2'.
1559 func_check is_not_equal
= 2 "$@";
1560 if is_equal
"$1" "$2"; then
1561 eval "${return_no}";
1563 eval "${return_yes}";
1567 ########################################################################
1568 # is_not_file (<filename>)
1570 # Test whether `name' is a not readable file.
1572 # Arguments : >=1 (empty allowed), more args are ignored
1576 func_check is_not_file
'>=' 1 "$@";
1577 if is_file
"$1"; then
1578 eval "${return_no}";
1580 eval "${return_yes}";
1584 ########################################################################
1585 # is_not_prog (<name>)
1587 # Verify that arg is a not program in $PATH.
1589 # Arguments : >=1 (empty allowed)
1590 # more args are ignored, this allows to specify progs with arguments
1594 func_check is_not_prog
'>=' 1 "$@";
1595 if where
"$1" >/dev
/null
; then
1596 eval "${return_no}";
1598 eval "${return_yes}";
1602 ########################################################################
1603 # is_not_writable (<name>)
1605 # Test whether `name' is a not a writable file or directory.
1607 # Arguments : >=1 (empty allowed), more args are ignored
1611 func_check is_not_writable
'>=' 1 "$@";
1612 if is_writable
"$1"; then
1613 eval "${return_no}";
1615 eval "${return_yes}";
1619 ########################################################################
1620 # is_not_yes (<string>)
1622 # Test whether `string' is not "yes".
1628 func_check is_not_yes
= 1 "$@";
1629 if is_yes
"$1"; then
1630 eval "${return_no}";
1632 eval "${return_yes}";
1636 ########################################################################
1639 # Determine whether arg is a program in $PATH
1641 # Arguments : >=0 (empty allowed)
1642 # more args are ignored, this allows to specify progs with arguments
1646 func_check is_prog
'>=' 0 "$@";
1649 eval "${return_no}";
1652 if where
"$1" >/dev
/null
; then
1653 eval "${return_yes}";
1657 eval "${return_no}";
1661 ########################################################################
1662 # is_writable (<name>)
1664 # Test whether `name' is a writable file or directory.
1666 # Arguments : >=1 (empty allowed), more args are ignored
1670 func_check is_writable
'>=' 1 "$@";
1671 if test -r "$1"; then
1672 if test -w "$1"; then
1673 eval "${return_yes}";
1676 eval "${return_no}";
1680 ########################################################################
1683 # Test whether `string' has value "yes".
1686 # Return : `0' if arg1 is `yes', `1' otherwise.
1690 func_check is_yes
= 1 "$@";
1691 if is_equal
"$1" 'yes'; then
1692 eval "${return_yes}";
1694 eval "${return_no}";
1698 ########################################################################
1701 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1703 # Globals: $_DEBUG_LM
1705 # Defined in section `Debugging functions'.
1708 ########################################################################
1711 # Clean exit without an error.
1720 ########################################################################
1721 landmark
'6: list_*()';
1722 ########################################################################
1724 # `list' is an object class that represents an array or list. Its
1725 # data consists of space-separated single-quoted elements. So a list
1726 # has the form "'first' 'second' '...' 'last'". See list_append() for
1727 # more details on the list structure. The array elements of `list'
1728 # can be get by `set -- $list`.
1731 ########################################################################
1732 # list_append (<list> <element>...)
1735 # <list>: a variable name for a list of single-quoted elements
1736 # <element>: some sequence of characters.
1737 # Output: none, but $<list> is set to
1738 # if <list> is empty: "'<element>' '...'"
1739 # otherwise: "$list '<element>' ..."
1743 func_check list_append
'>=' 2 "$@";
1748 eval _list
='"${'$1'}"';
1753 # escape each single quote by replacing each
1754 # "'" (squote) by "'\''" (squote bslash squote squote);
1755 # note that the backslash must be doubled in the following `sed'
1756 _element
="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')";
1765 if obj _list is_empty
; then
1766 _list
="'${_element}'";
1768 _list
="${_list} '${_element}'";
1771 eval "${_name}"='"${_list}"';
1772 eval "${return_ok}";
1776 ########################################################################
1777 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1779 # Transform command line arguments into a normalized form.
1781 # Options, option arguments, and file parameters are identified and
1782 # output each as a single-quoted argument of its own. Options and
1783 # file parameters are separated by a '--' argument.
1786 # <pre_name>: common part of a set of 4 environment variable names:
1787 # $<pre_name>_SHORT_NA: list of short options without an arg.
1788 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1789 # $<pre_name>_LONG_NA: list of long options without an arg.
1790 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1791 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1792 # the content of a variable, or direct arguments.
1794 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1797 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1798 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1799 # none-empty option lists, this will result in printing:
1800 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1802 # Use this function in the following way:
1803 # eval set -- "$(args_norm PRE_NAME "$@")";
1804 # while test "$1" != '--'; do
1811 # # all positional parameters ("$@") left are file name parameters.
1815 func_check list_from_cmdline
'>=' 1 "$@";
1823 _short_n
="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1824 _short_a
="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1825 _long_n
="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1826 _long_a
="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1827 if obj _short_n is_empty
; then
1828 error
'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1830 if obj _short_a is_empty
; then
1831 error
'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1833 if obj _long_n is_empty
; then
1834 error
'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1836 if obj _long_a is_empty
; then
1837 error
'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1840 _fn
='list_from_cmdline():'; # for error messages
1841 if is_equal
"$#" 0; then
1843 eval "${return_ok}";
1847 while test "$#" -ge 1; do
1853 # delete leading '--';
1854 _opt
="$(echo -n "${_arg}" | sed -e 's/^..//')";
1855 if list_has _long_n
"${_opt}"; then
1856 # long option, no argument
1857 list_append _result
"--${_opt}";
1860 # test on `--opt=arg'
1861 if string_contains
"${_opt}" '='; then
1862 # extract option by deleting from the first '=' to the end
1863 _lopt
="$(echo -n "${_opt}" | sed -e 's/=.*$//')";
1864 if list_has _long_a
"${_lopt}"; then
1865 # get the option argument by deleting up to first `='
1866 _optarg
="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')";
1867 list_append _result
"--${_lopt}" "${_optarg}";
1871 if list_has _long_a
"${_opt}"; then
1872 # long option with argument
1873 if test "$#" -le 0; then
1874 error
"${_fn} no argument for option --${_opt}."
1876 list_append _result
"--${_opt}" "$1";
1880 error
"${_fn} --${_opt} is not an option."
1882 -?
*) # short option (cluster)
1883 # delete leading `-';
1884 _rest
="$(echo -n "${_arg}" | sed -e 's/^-//')";
1885 while obj _rest is_not_empty
; do
1886 # get next short option from cluster (first char of $_rest)
1887 _optchar
="$(echo -n "${_rest}" | sed -e 's/^\(.\).*$/\1/')";
1888 # remove first character from ${_rest};
1889 _rest
="$(echo -n "${_rest}" | sed -e 's/^.//')";
1890 if list_has _short_n
"${_optchar}"; then
1891 list_append _result
"-${_optchar}";
1893 elif list_has _short_a
"${_optchar}"; then
1894 if obj _rest is_empty
; then
1895 if test "$#" -ge 1; then
1896 list_append _result
"-${_optchar}" "$1";
1901 "${_fn}"' no argument for option -'"${_optchar}."
1903 else # rest is the argument
1904 list_append _result
"-${_optchar}" "${_rest}";
1909 error
"${_fn} unknown option -${_optchar}."
1914 # Here, $_arg is not an option, so a file parameter.
1915 list_append _fparams
"${_arg}";
1917 # Ignore the strange option handling of $POSIXLY_CORRECT to
1918 # end option parsing after the first file name argument. To
1919 # reuse it, do a `break' here if $POSIXLY_CORRECT is
1924 list_append _result
'--';
1925 if obj _fparams is_not_empty
; then
1926 _result
="${_result} ${_fparams}";
1928 if test "$#" -gt 0; then
1929 list_append _result
"$@";
1932 eval "${return_ok}";
1933 } # list_from_cmdline()
1936 ########################################################################
1937 # list_from_split (<string> <separator>)
1939 # In <string>, escape all white space characters and replace each
1940 # <separator> by space.
1942 # Arguments: 2: a <string> that is to be split into parts divided by
1944 # Output: the resulting list string
1948 func_check list_from_split
= 2 "$@";
1951 # precede each space or tab by a backslash `\' (doubled for `sed')
1952 _s
="$(echo -n "$1" | sed -e 's/\(['"${_SPACE}${_TAB}"']\)/\\\1/g')";
1954 # replace split character of string by the list separator ` ' (space).
1956 /) # cannot use normal `sed' separator
1957 echo -n "${_s}" |
sed -e '\|.*|s|'"$2"'| |g';
1959 ?
) # use normal `sed' separator
1960 echo -n "${_s}" |
sed -e 's/'"$2"'/ /g';
1963 error
'list_from_split(): separator must be a single character.';
1966 eval "${return_ok}";
1970 ########################################################################
1973 # Check whether <list> is a space-separated list of '-quoted elements.
1975 # If the test fails an error is raised.
1976 # If the test succeeds the argument is echoed.
1979 # A list has the form "'first' 'second' '...' 'last'". So it has a
1980 # leading and a final quote and the elements are separated by "' '"
1981 # constructs. If these are all removed there should not be any
1982 # unescaped single-quotes left. Watch out for escaped single
1983 # quotes; they have the form '\'' (sq bs sq sq).
1986 # Output: the argument <list> unchanged, if the check succeeded.
1990 func_check list_get
= 1 "$@";
1992 eval _list
='"${'$1'}"';
1993 # remove leading and final space characters
1994 _list
="$(echo -n "${_list}" | \
1995 sed -e 's/^['"${_SPACE}${_TAB}"']*//' | \
1996 sed -e 's/['"${_SPACE}${_TAB}"']*$//')";
1999 eval "${return_ok}";
2003 eval "${return_ok}";
2006 error
"list_get(): bad list: $1"
2009 eval "${return_ok}";
2013 ########################################################################
2014 # list_has (<var_name> <element>)
2017 # <var_name>: a variable name for a list of single-quoted elements
2018 # <element>: some sequence of characters.
2020 # if <list> is empty: "'<element>' '...'"
2021 # otherwise: "list '<element>' ..."
2025 func_check list_has
= 2 "$@";
2026 eval _list
='"${'$1'}"';
2027 if obj _list is_empty
; then
2028 eval "${return_no}";
2032 \'*\') _element
="$2"; ;;
2033 *) _element
="'$2'"; ;;
2035 if string_contains
"${_list}" "${_element}"; then
2036 eval "${return_yes}";
2038 eval "${return_no}";
2040 eval "${return_ok}";
2044 ########################################################################
2045 # list_has_not (<list> <element>)
2048 # <list>: a space-separated list of single-quoted elements.
2049 # <element>: some sequence of characters.
2051 # if <list> is empty: "'<element>' '...'"
2052 # otherwise: "<list> '<element>' ..."
2056 func_check list_has_not
= 2 "$@";
2057 eval _list
='"${'$1'}"';
2058 if obj _list is_empty
; then
2059 eval "${return_yes}";
2063 \'*\') _element
="$2"; ;;
2064 *) _element
="'$2'"; ;;
2066 if string_contains
"${_list}" "${_element}"; then
2067 eval "${return_no}";
2069 eval "${return_yes}";
2071 eval "${return_ok}";
2075 ########################################################################
2076 landmark
'7: man_*()';
2077 ########################################################################
2079 ########################################################################
2080 # man_do_filespec (<filespec>)
2082 # Print suitable man page(s) for filespec to $_TMP_CAT.
2085 # <filespec>: argument of the form `man:name.section', `man:name',
2086 # `man:name(section)', `name.section', `name'.
2088 # Globals : $_OPT_ALL
2091 # Return : `0' if man page was found, `1' else.
2093 # Only called from do_fileargs(), checks on $MANPATH and
2094 # $_MAN_ENABLE are assumed.
2098 func_check man_do_filespec
= 1 "$@";
2107 if obj _MAN_PATH is_empty
; then
2108 eval "${return_bad}";
2110 if is_empty
"$1"; then
2111 eval "${return_bad}";
2117 */*) # not a man spec when it contains '/'
2118 eval "${return_bad}";
2120 man
:?
*\
(?
*\
)) # man:name(section)
2121 _name
="$(echo -n "${_spec}" \
2122 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2123 _section
="$(echo -n "${_spec}" \
2124 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2126 man
:?
*.
[0-9on]) # man:name.section
2127 _name
="$(echo -n "${_spec}" \
2128 | sed -e 's/^man:\(..*\)\..$/\1/')";
2129 _section
="$(echo -n "${_spec}" \
2130 | sed -e 's/^.*\(.\)$/\1/')";
2133 _name
="$(echo -n "${_spec}" | sed -e 's/^man://')";
2135 ?
*\
(?
*\
)) # name(section)
2136 _name
="$(echo -n "${_spec}" \
2137 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2138 _section
="$(echo -n "${_spec}" \
2139 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2141 ?
*.
[0-9on]) # name.section
2142 _name
="$(echo -n "${_spec}" \
2143 | sed -e 's/^\(..*\)\..$/\1/')";
2144 _section
="$(echo -n "${_spec}" \
2145 | sed -e 's/^.*\(.\)$/\1/')";
2148 _name
="${_filespec}";
2151 if obj _name is_empty
; then
2152 eval "${return_bad}";
2155 if obj _section is_empty
; then
2156 eval set -- "${_MAN_AUTO_SEC}";
2158 if man_search_section
"${_name}" "$s"; then # found
2159 if obj _MAN_ALL is_yes
; then
2162 eval "${return_good}";
2167 if man_search_section
"${_name}" "${_section}"; then
2168 eval "${return_good}";
2170 eval "${return_bad}";
2173 if obj _MAN_ALL is_yes
&& is_yes
"${_got_one}"; then
2174 eval "${return_good}";
2176 eval "${return_bad}";
2177 } # man_do_filespec()
2180 ########################################################################
2181 # man_register_file (<file> <name> [<section>])
2183 # Write a found man page file and register the title element.
2185 # Arguments: 1, 2, or 3; maybe empty
2190 func_check man_register_file
'>=' 2 "$@";
2194 error
"man_register_file() expects 2 or 3 arguments.";
2197 if is_empty
"$1"; then
2198 error
'man_register_file(): file name is empty';
2203 register_title
"man:$2";
2204 eval "${return_ok}";
2207 register_title
"$2.$3";
2208 eval "${return_ok}";
2211 eval "${return_ok}";
2215 ########################################################################
2216 # man_search_section (<name> <section>)
2218 # Retrieve man pages.
2221 # Globals : $_MAN_PATH, $_MAN_EXT
2222 # Return : 0 if found, 1 otherwise
2224 man_search_section
()
2226 func_check man_search_section
= 2 "$@";
2235 if obj _MAN_PATH is_empty
; then
2236 eval "${return_bad}";
2238 if is_empty
"$1"; then
2239 eval "${return_bad}";
2241 if is_empty
"$2"; then
2242 eval "${return_bad}";
2246 eval set -- "$(path_split "${_MAN_PATH}")";
2248 if obj _MAN_EXT is_empty
; then
2250 _dir
="$(dirname_append "$d" "man
${_section}")";
2251 if obj _dir is_dir
; then
2252 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2253 for f
in $
(echo -n ${_prefix}*); do
2254 if obj f is_file
; then
2255 if is_yes
"${_got_one}"; then
2257 elif obj _MAN_ALL is_yes
; then
2258 man_register_file
"$f" "${_name}";
2260 man_register_file
"$f" "${_name}" "${_section}";
2261 eval "${return_good}";
2270 # check for directory name having trailing extension
2272 _dir
="$(dirname_append $d man${_section}${_ext})";
2273 if obj _dir is_dir
; then
2274 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2275 for f
in ${_prefix}*; do
2276 if obj f is_file
; then
2277 if is_yes
"${_got_one}"; then
2279 elif obj _MAN_ALL is_yes
; then
2280 man_register_file
"$f" "${_name}";
2282 man_register_file
"$f" "${_name}" "${_section}";
2283 eval "${return_good}";
2290 # check for files with extension in directories without extension
2292 _dir
="$(dirname_append "$d" "man
${_section}")";
2293 if obj _dir is_dir
; then
2294 _prefix
="$(dirname_append "${_dir}" \
2295 "${_name}.${_section}${_ext}")";
2296 for f
in ${_prefix}*; do
2297 if obj f is_file
; then
2298 if is_yes
"${_got_one}"; then
2300 elif obj _MAN_ALL is_yes
; then
2301 man_register_file
"$f" "${_name}";
2303 man_register_file
"$f" "${_name}" "${_section}";
2304 eval "${return_good}";
2312 if obj _MAN_ALL is_yes
&& is_yes
"${_got_one}"; then
2313 eval "${return_good}";
2315 eval "${return_bad}";
2316 } # man_search_section()
2319 ########################################################################
2322 # Setup the variables $_MAN_* needed for man page searching.
2325 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2326 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2327 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2328 # $_MAN_SEC, $_MAN_ALL
2329 # in/out: $_MAN_ENABLE
2331 # The precedence for the variables related to `man' is that of GNU
2334 # $LANG; overridden by
2335 # $LC_MESSAGES; overridden by
2336 # $LC_ALL; this has the same precedence as
2337 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2338 # $MANOPT; overridden by
2339 # the groffer command line options.
2343 func_check main_man_setup
= 0 "$@";
2346 if obj _MAN_IS_SETUP is_yes
; then
2347 eval "${return_ok}";
2349 _MAN_IS_SETUP
='yes';
2351 if obj _MAN_ENABLE is_not_yes
; then
2352 eval "${return_ok}";
2355 # determine basic path for man pages
2356 _MAN_PATH
="$(get_first_essential \
2357 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2358 if obj _MAN_PATH is_empty
; then
2359 manpath_set_from_path
;
2361 _MAN_PATH
="$(path_clean "${_MAN_PATH}")";
2363 if obj _MAN_PATH is_empty
; then
2364 if is_prog
'manpath'; then
2365 _MAN_PATH
="$(manpath 2>/dev/null)"; # not always available
2368 if obj _MAN_PATH is_empty
; then
2370 eval "${return_ok}";
2373 _MAN_ALL
="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2374 if obj _MAN_ALL is_empty
; then
2378 _MAN_SYS
="$(get_first_essential \
2379 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2380 _lang
="$(get_first_essential \
2381 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2388 _MAN_LANG
="${_lang}";
2392 _MAN_LANG
="${_lang}";
2393 # get first two characters of $_lang
2394 _MAN_LANG2
="$(echo -n "${_lang}" | sed -e 's/^\(..\).*$/\1/')";
2397 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2399 manpath_add_lang_sys
; # this is very slow
2401 _MAN_SEC
="$(get_first_essential \
2402 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2403 if obj _MAN_PATH is_empty
; then
2405 eval "${return_ok}";
2408 _MAN_EXT
="$(get_first_essential \
2409 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2410 eval "${return_ok}";
2414 ########################################################################
2415 landmark
'8: manpath_*()';
2416 ########################################################################
2418 ########################################################################
2419 # manpath_add_lang_sys ()
2421 # Add language and operating system specific directories to man path.
2426 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2427 # list of names of operating systems.
2428 # $_MAN_LANG and $_MAN_LANG2: each a single name
2429 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2430 # separated list of directories.
2432 manpath_add_lang_sys
()
2434 func_check manpath_add_lang_sys
= 0 "$@";
2437 if obj _MAN_PATH is_empty
; then
2438 eval "${return_ok}";
2440 # twice test both sys and lang
2441 eval set -- "$(path_split "${_MAN_PATH}")";
2443 for p
in "$@"; do # loop on man path directories
2444 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2446 eval set -- "$(path_split "${_mp}")";
2447 for p
in "$@"; do # loop on man path directories
2448 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2450 _MAN_PATH
="$(path_chop "${_mp}")";
2451 eval "${return_ok}";
2455 _manpath_add_lang_sys_single
()
2457 # To the directory in $1 append existing sys/lang subdirectories
2458 # Function is necessary to split the OS list.
2460 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2461 # argument: 2: `man_path' and `dir'
2462 # output: colon-separated path of the retrieved subdirectories
2464 func_check _manpath_add_lang_sys_single
= 2 "$@";
2468 eval set -- "$(list_from_split "${_MAN_SYS}" ',')";
2469 for d
in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"; do
2470 _dir
="$(dirname_append "${_parent}" "$d")";
2471 if obj _res path_not_contains
"${_dir}" && obj _dir is_dir
; then
2472 _res
="${_res}:${_dir}";
2475 if path_not_contains
"${_res}" "${_parent}"; then
2476 _res
="${_res}:${_parent}";
2478 path_chop
"${_res}";
2481 # end manpath_add_lang_sys ()
2484 ########################################################################
2485 # manpath_set_from_path ()
2487 # Determine basic search path for man pages from $PATH.
2489 # Return: `0' if a valid man path was retrieved.
2495 manpath_set_from_path
()
2497 func_check manpath_set_from_path
= 0 "$@";
2505 # get a basic man path from $PATH
2506 if obj PATH is_not_empty
; then
2507 eval set -- "$(path_split "${PATH}")";
2509 # delete the final `/bin' part
2510 _base
="$(echo -n "$d" | sed -e '\|.*|s|//*bin/*$||')";
2511 for e
in /share
/man
/man
; do
2512 _mandir
="${_base}$e";
2513 if test -d "${_mandir}" && test -r "${_mandir}"; then
2514 _manpath
="${_manpath}:${_mandir}";
2520 # append some default directories
2521 for d
in /usr
/local
/share
/man
/usr
/local
/man \
2522 /usr
/share
/man
/usr
/man \
2523 /usr
/X11R
6/man
/usr
/openwin
/man \
2524 /opt
/share
/man
/opt
/man \
2525 /opt
/gnome
/man
/opt
/kde
/man
; do
2526 if obj _manpath path_not_contains
"$d" && obj d is_dir
; then
2527 _manpath
="${_manpath}:$d";
2531 _MAN_PATH
="${_manpath}";
2532 eval "${return_ok}";
2533 } # manpath_set_from_path()
2536 ########################################################################
2537 landmark
'9: obj_*()';
2538 ########################################################################
2540 ########################################################################
2541 # obj (<object> <call_name> <arg>...)
2543 # This works like a method (object function) call for an object.
2544 # Run "<call_name> $<object> <arg> ...".
2546 # The first argument represents an object whose data is given as first
2547 # argument to <call_name>().
2550 # <object>: variable name
2551 # <call_name>: a program or function name
2555 func_check obj
'>=' 2 "$@";
2558 if is_empty
"$2"; then
2559 error
"obj(): function name is empty."
2563 eval arg1
='"${'$1'}"';
2566 eval "${func}"' "${arg1}" "$@"';
2570 ########################################################################
2571 # obj_data (<object>)
2573 # Print the data of <object>, i.e. the content of $<object>.
2574 # For possible later extensions.
2577 # <object>: a variable name
2578 # Output: the data of <object>
2582 func_check obj
'=' 1 "$@";
2583 if is_empty
"$1"; then
2584 error
"obj_data(): object name is empty."
2586 eval echo -n '"${'$1'}"';
2590 ########################################################################
2591 # obj_from_output (<object> <call_name> <arg>...)
2593 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2594 # function call to a global variable.
2597 # <object>: a variable name
2598 # <call_name>: the name of a function or program
2599 # <arg>: optional argument to <call_name>
2604 func_check obj_from_output
'>=' 2 "$@";
2606 if is_empty
"$1"; then
2607 error
"res(): variable name is empty.";
2608 elif is_empty
"$2"; then
2609 error
"res(): function name is empty."
2614 eval "${result_name}"'="$('"$@"')"';
2618 ########################################################################
2619 # obj_set (<object> <data>)
2621 # Set the data of <object>, i.e. call "$<object>=<data>".
2624 # <object>: a variable name
2630 func_check obj_set
'=' 2 "$@";
2631 if is_empty
"$1"; then
2632 error
"obj_set(): object name is empty."
2638 ########################################################################
2639 # path_chop (<path>)
2641 # Remove unnecessary colons from path.
2643 # Argument: 1, a colon separated path.
2644 # Output: path without leading, double, or trailing colons.
2648 func_check path_chop
= 1 "$@";
2651 # replace multiple colons by a single colon `:'
2652 # remove leading and trailing colons
2653 echo -n "$1" |
sed -e 's/:::*/:/g' |
2656 eval "${return_ok}";
2660 ########################################################################
2661 # path_clean (<path>)
2663 # Remove non-existing directories from a colon-separated list.
2665 # Argument: 1, a colon separated path.
2666 # Output: colon-separated list of existing directories.
2670 func_check path_clean
= 1 "$@";
2675 if is_not_equal
"$#" 1; then
2676 error
'path_clean() needs 1 argument.';
2679 eval set -- "$(path_split "${_arg}")";
2682 if obj i is_not_empty \
2683 && obj _res path_not_contains
"$i" \
2687 ?
*/) _res
="${_res}$(dirname_chop "$i")"; ;;
2688 *) _res
="${_res}:$i";
2692 if path_chop
"${_res}"; then
2693 eval "${return_ok}";
2695 eval "${return_badk}";
2700 ########################################################################
2701 # path_contains (<path> <dir>)
2703 # Test whether `dir' is contained in `path', a list separated by `:'.
2705 # Arguments : 2 arguments.
2706 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2710 func_check path_contains
= 2 "$@";
2713 eval "${return_yes}";
2716 eval "${return_no}";
2719 eval "${return_ok}";
2723 ########################################################################
2724 # path_not_contains (<path> <dir>)
2726 # Test whether `dir' is not contained in colon separated `path'.
2728 # Arguments : 2 arguments.
2732 func_check path_not_contains
= 2 "$@";
2733 if path_contains
"$1" "$2"; then
2734 eval "${return_no}";
2736 eval "${return_yes}";
2738 eval "${return_ok}";
2742 ########################################################################
2743 # path_split (<path>)
2745 # In `path' escape white space and replace each colon by a space.
2747 # Arguments: 1: a colon-separated path
2748 # Output: the resulting list, process with `eval set --'
2752 func_check path_split
= 1 "$@";
2753 list_from_split
"$1" ':';
2754 eval "${return_ok}";
2758 ########################################################################
2759 landmark
'10: register_*()';
2760 ########################################################################
2762 ########################################################################
2763 # register_file (<filename>)
2765 # Write a found file and register the title element.
2767 # Arguments: 1: a file name
2772 func_check register_file
= 1 "$@";
2773 if is_empty
"$1"; then
2774 error
'register_file(): file name is empty';
2776 if is_equal
"$1" '-'; then
2777 to_tmp
"${_TMP_STDIN}";
2781 register_title
"$(base_name "$1")";
2783 eval "${return_ok}";
2787 ########################################################################
2788 # register_title (<filespec>)
2790 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2792 # Globals: $_REGISTERED_TITLE (rw)
2796 func_check register_title
= 1 "$@";
2798 if is_empty
"$1"; then
2799 eval "${return_ok}";
2801 _title
="$(base_name "$1")"; # remove directory part
2803 # remove extension `.gz'
2804 _title
="$(echo -n "${_title}" | sed -e 's/\.gz$//')";
2805 # remove extension `.Z'
2806 _title
="$(echo -n "${_title}" | sed -e 's/\.Z$//')";
2808 if obj _title is_empty
; then
2809 eval "${return_ok}";
2811 _REGISTERED_TITLE
="${_REGISTERED_TITLE} ${_title}";
2812 eval "${return_ok}";
2816 ########################################################################
2819 # Reset the variables that can be affected by options to their default.
2822 # Defined in section `Preset' after the rudimentary shell tests.
2825 ########################################################################
2828 # Store standard input to temporary file (with decompression).
2830 if obj _HAS_COMPRESSION is_yes
; then
2834 func_check save_stdin
= 0 "$@";
2835 _f
="${_TMP_DIR}"/INPUT
;
2837 catz
"${_f}" >"${_TMP_STDIN}";
2839 eval "${return_ok}";
2844 func_check save_stdin
= 0 "$@";
2845 cat >"${_TMP_STDIN}";
2846 eval "${return_ok}";
2851 ########################################################################
2852 landmark
'11: stack_*()';
2853 ########################################################################
2855 ########################################################################
2856 # string_contains (<string> <part>)
2858 # Test whether `part' is contained in `string'.
2860 # Arguments : 2 text arguments.
2861 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2865 func_check string_contains
= 2 "$@";
2868 eval "${return_yes}";
2871 eval "${return_no}";
2874 eval "${return_ok}";
2878 ########################################################################
2879 # string_not_contains (<string> <part>)
2881 # Test whether `part' is not substring of `string'.
2883 # Arguments : 2 text arguments.
2884 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2886 string_not_contains
()
2888 func_check string_not_contains
= 2 "$@";
2889 if string_contains
"$1" "$2"; then
2890 eval "${return_no}";
2892 eval "${return_yes}";
2894 eval "${return_ok}";
2898 ########################################################################
2899 landmark
'12: tmp_*()';
2900 ########################################################################
2902 ########################################################################
2905 # output the temporary cat file (the concatenation of all input)
2913 ########################################################################
2914 # tmp_create (<suffix>?)
2916 # create temporary file
2918 # It's safe to use the shell process ID together with a suffix to
2919 # have multiple temporary files.
2921 # Output : name of created file
2925 func_check tmp_create
'<=' 1 "$@";
2927 # the output file does not have `,' as first character
2928 _tmp
="${_TMP_DIR}/,$1";
2930 echo -n "${_tmp}"; # output file name
2931 eval "${return_ok}";
2935 ########################################################################
2936 # to_tmp (<filename>)
2938 # print file (decompressed) to the temporary cat file
2942 func_check to_tmp
= 1 "$@";
2943 if is_file
"$1"; then
2944 if obj _OPT_LOCATION is_yes
; then
2947 if obj _OPT_WHATIS is_yes
; then
2948 what_is
"$1" >>"${_TMP_CAT}";
2950 catz
"$1" >>"${_TMP_CAT}";
2953 error
"to_tmp(): could not read file \`$1'.";
2955 eval "${return_ok}";
2959 ########################################################################
2962 # disable trap on all exit codes ($_ALL_EXIT)
2965 # Globals: $_ALL_EXIT
2969 func_check trap_clean
= 0 "$@";
2971 for i
in ${_ALL_EXIT}; do
2972 trap "" "$i" 2>/dev
/null || true
;
2974 eval "${return_ok}";
2978 ########################################################################
2979 # trap_set (<functionname>)
2981 # call function on all exit codes ($_ALL_EXIT)
2983 # Arguments: 1 (name of a shell function)
2984 # Globals: $_ALL_EXIT
2988 func_check trap_set
= 1 "$@";
2990 for i
in ${_ALL_EXIT}; do
2991 trap "$1" "$i" 2>/dev
/null || true
;
2993 eval "${return_ok}";
2997 ########################################################################
3000 # print usage information to stderr; for groffer option --help.
3004 func_check usage
= 0 "$@";
3007 echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';
3010 Display roff files, standard input, and/or Unix manual pages with a X
3011 Window viewer or in several text modes. All input is decompressed
3012 on-the-fly with all formats that gzip can handle.
3014 "filespec" is one of
3015 "filename" name of a readable file
3016 "-" for standard input
3017 "man:name.n" man page "name" in section "n"
3018 "man:name" man page "name" in first section found
3019 "name.n" man page "name" in section "n"
3020 "name" man page "name" in first section found
3021 and some more (see groffer(1) for details).
3023 -h --help print this usage message.
3024 -Q --source output as roff source.
3025 -T --device=name pass to groff using output device "name".
3026 -v --version print version information.
3027 -V display the groff execution pipe instead of formatting.
3028 -X --X --x display with "gxditview" using groff -X.
3029 -Z --ditroff --intermediate-output
3030 generate groff intermediate output without
3031 post-processing and viewing, like groff -Z.
3032 All other short options are interpreted as "groff" formatting options.
3034 The most important groffer long options are
3036 --apropos=name start man's "apropos" program for "name".
3038 "apropos" for "name" in man's data sections 4, 5, 7.
3039 --apropos-devel=name
3040 "apropos" for "name" in development sections 2, 3, 9.
3041 --apropos-progs=name
3042 "apropos" for "name" in man's program sections 1, 6, 8.
3043 --auto choose mode automatically from the default mode list.
3044 --default reset all options to the default value.
3045 --default-modes=mode1,mode2,...
3046 set sequence of automatically tried modes.
3047 --dvi display in a viewer for TeX device independent format.
3048 --dvi-viewer choose the viewer program for dvi mode.
3049 --groff process like groff, disable viewing features.
3050 --help display this helping output.
3051 --html --www display in a web browser.
3052 --html-viewer choose the web browser for www mode.
3053 --man check file parameters first whether they are man pages.
3054 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3055 choose display mode.
3056 --no-man disable man-page facility.
3057 --pager=program preset the paging program for tty mode.
3058 --pdf display in a PDF viewer.
3059 --pdf-viewer choose the viewer program for pdf mode.
3060 --ps display in a Postscript viewer.
3061 --ps-viewer choose the viewer program for ps mode.
3062 --shell specify shell under which to run this program.
3063 --text output in a text device without a pager.
3064 --tty display with a pager on text terminal even when in X.
3065 --www-viewer same as --html-viewer
3066 --x-viewer choose viewer program for x mode (X mode).
3067 --X-viewer same as "--xviewer".
3069 The usual X Windows toolkit options transformed into GNU long options
3070 --background=color, --bd=size, --bg=color, --bordercolor=color,
3071 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3072 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3073 --resolution=dpi, --rv, --title=text, --xrm=resource
3075 Long options of GNU "man"
3076 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3077 --local-file=name, --location, --manpath=dir1:dir2:...,
3078 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3081 eval "${return_ok}";
3085 ########################################################################
3088 # print version information to stderr
3092 func_check version
= 0 "$@";
3093 echo2
"${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3094 # also display groff's version, but not the called subprograms
3095 groff -v 2>&1 |
sed -e '/^ *$/q' |
sed -e '1s/^/is part of /' >&2;
3099 ########################################################################
3100 # warning (<string>)
3102 # Print warning to stderr
3106 echo2
"warning: $*";
3110 ########################################################################
3111 # what_is (<filename>)
3113 # Interpret <filename> as a man page and display its `whatis'
3114 # information as a fragment written in the groff language.
3118 func_check what_is
= 1 "$@";
3121 if is_not_file
"$1"; then
3122 error
"what_is(): argument is not a readable file."
3124 _dot
='^\.['"${_SPACE}${_TAB}"']*';
3129 # grep the line containing `.TH' macro, if any
3130 _res
="$(catz "$1" | sed -e '/'"${_dot}"'TH /p
3132 if obj _res is_not_empty
; then # traditional man style
3133 # get the text between the first and the second `.SH' macro, by
3134 # - delete up to first .SH;
3135 # - of this, print everything up to next .SH, and delete the rest;
3136 # - of this, delete the final .SH line;
3137 catz
"$1" |
sed -e '1,/'"${_dot}"'SH/d' \
3138 |
sed -e '1,/'"${_dot}"'SH/p
3140 |
sed -e '/'"${_dot}"'SH/d';
3141 eval "${return_ok}";
3143 # grep the line containing `.Dd' macro, if any
3144 _res
="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p
3146 if obj _res is_not_empty
; then # BSD doc style
3147 # get the text between the first and the second `.Nd' macro, by
3148 # - delete up to first .Nd;
3149 # - of this, print everything up to next .Nd, and delete the rest;
3150 # - of this, delete the final .Nd line;
3151 catz
"$1" |
sed -e '1,/'"${_dot}"'Nd/d' \
3152 |
sed -e '1,/'"${_dot}"'Nd/p
3154 |
sed -e '/'"${_dot}"'Nd/d';
3155 eval "${return_ok}";
3157 echo 'is not a man page.';
3158 eval "${return_bad}";
3162 ########################################################################
3165 # Output path of a program if in $PATH.
3167 # Arguments : >=1 (empty allowed)
3168 # more args are ignored, this allows to specify progs with arguments
3169 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3173 func_check where
'>=' 1 "$@";
3178 if obj _arg is_empty
; then
3179 eval "${return_bad}";
3183 if test -f "${_arg}" && test -x "${_arg}"; then
3184 eval "${return_ok}";
3186 eval "${return_bad}";
3190 eval set -- "$(path_split "${PATH}")";
3193 */) _file
=${p}${_arg}; ;;
3194 *) _file
=${p}/${_arg}; ;;
3196 if test -f "${_file}" && test -x "${_file}"; then
3198 eval "${return_ok}";
3201 eval "${return_bad}";
3205 ########################################################################
3207 ########################################################################
3209 # The main area contains the following parts:
3210 # - main_init(): initialize temporary files and set exit trap
3211 # - main_parse_MANOPT(): parse $MANOPT
3212 # - main_parse_args(): argument parsing
3213 # - main_set_mode (): determine the display mode
3214 # - main_do_fileargs(): process filespec arguments
3215 # - main_set_resources(): setup X resources
3216 # - main_display(): do the displaying
3217 # - main(): the main function that calls all main_*()
3219 # These parts are implemented as functions, being defined below in the
3220 # sequence they are called in the main() function.
3223 #######################################################################
3226 # set exit trap and create temporary files
3228 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3230 landmark
'13: main_init()';
3233 func_check main_init
= 0 "$@";
3234 # call clean_up() on any signal
3237 # create temporary directory
3240 for d
in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3241 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.';
3243 if obj d is_empty || obj d is_not_dir || obj d is_not_writable
; then
3254 _TMP_DIR
="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
3255 while obj _TMP_DIR is_existing
; do
3256 rm -f -r "${_TMP_DIR}" 2>/dev
/null
;
3257 if obj _TMP_DIR is_existing
; then
3258 # $_TMP_DIR could not be removed
3259 _TMP_DIR
="${_TMP_DIR}"'X';
3262 # $_TMP_DIR was removed
3266 mkdir
"${_TMP_DIR}";
3267 if is_not_equal
"$?" 0; then
3268 if obj _TMP_DIR is_existing
; then
3269 rm -f -r "${_TMP_DIR}" 2>/dev
/null
;
3274 if obj _TMP_DIR is_dir
&& obj _TMP_DIR is_writable
; then
3275 # $_TMP_DIR can now be used as temporary directory
3278 if obj _TMP_DIR is_existing
; then
3279 rm -f -r "${_TMP_DIR}" 2>/dev
/null
;
3285 if obj _TMP_DIR is_empty
; then
3286 error
"Couldn't create a directory for storing temporary files.";
3289 _TMP_CAT
="$(tmp_create groffer_cat)";
3290 _TMP_STDIN
="$(tmp_create groffer_input)";
3292 # groffer configuration files
3293 for f
in ${_CONFFILES}; do
3294 if obj f is_file
; then
3295 echo '_groffer_opt=""' >>${_TMP_CAT};
3296 # collect the lines starting with a minus
3298 's/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"'/ \
3300 # prepend the collected information to $GROFFER_OPT
3301 echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
3305 _TMP_CAT="$(tmp_create groffer_cat)";
3307 eval "${return_ok}";
3311 ########################################################################
3312 # main_parse_MANOPT ()
3314 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3315 # string; found man arguments can be overwritten by the command line.
3318 # in: $MANOPT, $_OPTS_MANOPT_*
3320 # in/out: $GROFFER_OPT
3322 landmark '14: main_parse_MANOPT
()';
3325 func_check main_parse_MANOPT = 0 "$@";
3329 if obj MANOPT is_not_empty; then
3330 MANOPT="$(echo -n "${MANOPT}" | \
3331 sed -e 's
/^
'"${_SPACE}${_SPACE}"'*//')";
3333 if obj MANOPT is_empty; then
3334 eval "${return_ok}";
3336 # add arguments in $MANOPT by mapping them to groffer options
3337 eval set -- "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3338 until test "$#" -le 0 || is_equal "$1" '--'; do
3343 list_append _list '--ascii';
3346 list_append _list '--all';
3353 list_append _list '--debug';
3356 # undo all man options so far
3360 list_append _list '--extension';
3364 list_append _list '--whatis';
3372 # groffer's
--apropos takes an argument
, but man
's does not, so
3377 list_append _list '--local-file';
3380 list_append _list '--locale' "$1";
3384 list_append _list '--systems' "$1";
3388 list_append _list '--manpath' "$1";
3395 -P|--pager|--tty-viewer)
3396 list_append _list '--pager' "$1";
3404 list_append _list '--sections' "$1";
3412 list_append _list '-T' "$1";
3422 -w|--where|--location)
3423 list_append _list '--location';
3426 list_append _list '-Z' "$1";
3429 # ignore all other options
3432 # append the 2 lists in $_list and $GROFFER_OPT to $GROFFER_OPT
3433 if obj GROFFER_OPT is_empty; then
3434 GROFFER_OPT="${_list}";
3435 elif obj _list is_not_empty; then
3436 GROFFER_OPT="${_list} ${GROFFER_OPT}";
3438 eval "${return_ok}";
3439 } # main_parse_MANOPT()
3442 ########################################################################
3443 # main_parse_args (<command_line_args>*)
3445 # Parse arguments; process options and filespec parameters
3447 # Arguments: pass the command line arguments unaltered.
3450 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3452 landmark '15: main_parse_args
()';
3455 func_check main_parse_args '>=' 0 "$@";
3467 eval set -- "${GROFFER_OPT}" '"$@"';
3469 eval set -- "$(list_from_cmdline _OPTS_CMDLINE "$@")";
3471 # By the call of `eval', unnecessary quoting was removed. So the
3472 # positional shell parameters ($1, $2, ...) are now guaranteed to
3473 # represent an option or an argument to the previous option, if any;
3474 # then a `--' argument for separating options and
3475 # parameters; followed by the filespec parameters if any.
3477 # Note, the existence of arguments to options has already been checked.
3478 # So a check for `$#' or `--' should not be done for arguments.
3480 until test "$#" -le 0 || is_equal
"$1" '--'; do
3481 _opt
="$1"; # $_opt is fed into the option handler
3488 -Q|
--source) # output source code (`Quellcode').
3491 -T|
--device|
--troff-device) # device; arg
3493 _check_device_with_mode
;
3503 -Z|
--ditroff|
--intermediate-output) # groff intermediate output
3510 # delete leading `-'
3511 _optchar
="$(echo -n "${_opt}" | sed -e 's/^.//')";
3512 if list_has _OPTS_GROFF_SHORT_NA
"${_optchar}";
3514 list_append _ADDOPTS_GROFF
"${_opt}";
3515 elif list_has _OPTS_GROFF_SHORT_ARG
"${_optchar}";
3517 list_append _ADDOPTS_GROFF
"${_opt}" "$1";
3520 error
"Unknown option : \`$1'";
3526 --apropos) # run `apropos'
3532 --apropos-data) # run `apropos' for data sections
3533 apropos_run
"$1" |
grep '^[^(]*([457][^)]*)';
3538 --apropos-devel) # run `apropos' for development sections
3539 apropos_run
"$1" |
grep '^[^(]*([239][^)]*)';
3544 --apropos-progs) # run `apropos' for program sections
3545 apropos_run
"$1" |
grep '^[^(]*([168][^)]*)';
3551 list_append _ADDOPTS_GROFF
'-mtty-char';
3552 if obj _mode is_empty
; then
3556 --auto) # the default automatic mode
3559 --bd) # border color for viewers, arg;
3563 --bg|
--backgroud) # background color for viewers, arg;
3567 --bw) # border width for viewers, arg;
3571 --default) # reset variables to default
3574 --default-modes) # sequence of modes in auto mode; arg
3575 _OPT_DEFAULT_MODES
="$1";
3578 --debug) # buggy, only for development
3581 --display) # set X display, arg
3588 --dvi-viewer) # viewer program for dvi mode; arg
3589 _OPT_VIEWER_DVI
="$1";
3592 --extension) # the extension for man pages, arg
3593 _OPT_EXTENSION
="$1";
3596 --fg|
--foreground) # foreground color for viewers, arg;
3600 --fn|
--font) # set font for viewers, arg;
3604 --geometry) # window geometry for viewers, arg;
3611 --html|
--www) # display with web browser
3614 --html-viewer|
--www-viewer) # viewer program for html mode; arg
3615 _OPT_VIEWER_HTML
="$1";
3618 --iconic) # start viewers as icons
3621 --locale) # set language for man pages, arg
3622 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3626 --local-file) # force local files; same as `--no-man'
3630 --location|
--where) # print file locations to stderr
3631 _OPT_LOCATION
='yes';
3633 --man) # force all file params to be man pages
3637 --manpath) # specify search path for man pages, arg
3638 # arg is colon-separated list of directories
3642 --mode) # display mode
3646 auto|
'') # search mode automatically among default
3649 groff) # pass input to plain groff
3652 html|www
) # display with a web browser
3655 dvi
) # display with xdvi viewer
3658 pdf
) # display with PDF viewer
3661 ps
) # display with Postscript viewer
3664 text
) # output on terminal
3667 tty
) # output on terminal
3670 X|x
) # output on X roff viewer
3673 Q|
source) # display source code
3677 error
"unknown mode ${_arg}";
3680 _OPT_MODE
="${_mode}";
3682 --no-location) # disable former call to `--location'
3683 _OPT_LOCATION
='yes';
3685 --no-man) # disable search for man pages
3686 # the same as --local-file
3690 --pager) # set paging program for tty mode, arg
3697 --pdf-viewer) # viewer program for ps mode; arg
3698 _OPT_VIEWER_PDF
="$1";
3704 --ps-viewer) # viewer program for ps mode; arg
3705 _OPT_VIEWER_PS
="$1";
3708 --resolution) # set resolution for X devices, arg
3719 error
"only resoutions of 75 or 100 dpi are supported";
3722 _OPT_RESOLUTION
="${_dpi}";
3727 --sections) # specify sections for man pages, arg
3728 # arg is colon-separated list of section names
3733 # already done during the first run; so ignore the argument
3736 --systems) # man pages for different OS's, arg
3737 # argument is a comma-separated list
3741 --text) # text mode without pager
3744 --title) # title for X viewers; arg
3748 --tty) # tty mode, text with pager
3751 --text-device|
--tty-device) # device for tty mode; arg
3752 _OPT_TEXT_DEVICE
="$1";
3758 --xrm) # pass X resource string, arg;
3759 list_append _OPT_XRM
"$1";
3762 --x-viewer|
--X-viewer) # viewer program for x mode; arg
3767 error
'error on argument parsing : '"\`$*'";
3771 shift; # remove `--' argument
3773 if obj _DEBUG is_not_yes
; then
3774 if obj _OPT_DEBUG is_yes
; then
3779 # Remaining arguments are file names (filespecs).
3780 # Save them to list $_FILEARGS
3781 if is_equal
"$#" 0; then # use "-" for standard input
3785 list_append _FILEARGS
"$@";
3786 if list_has _FILEARGS
'-'; then
3789 # $_FILEARGS must be retrieved with `eval set -- "$_FILEARGS"'
3790 eval "${return_ok}";
3791 } # main_parse_args()
3793 # Called from main_parse_args() because double `case' is not possible.
3794 # Globals: $_OPT_DEVICE, $_OPT_MODE
3795 _check_device_with_mode
()
3797 func_check _check_device_with_mode
= 0 "$@";
3798 case "${_OPT_DEVICE}" in
3801 eval "${return_ok}";
3805 eval "${return_ok}";
3809 eval "${return_ok}";
3813 eval "${return_ok}";
3815 ascii|cp1047|latin1|utf8
)
3816 if obj _OPT_MODE is_not_equal text
; then
3817 _OPT_MODE
=tty
; # default text mode
3819 eval "${return_ok}";
3823 eval "${return_ok}";
3825 *) # unknown device, go to groff mode
3827 eval "${return_ok}";
3830 eval "${return_error}";
3834 ########################################################################
3837 # Determine the display mode.
3840 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
3841 # out: $_DISPLAY_MODE
3844 # _get_first_prog (<proglist>)
3846 # Retrieve first argument that represents an existing program in $PATH.
3847 # Local function for main_set_mode().
3849 # Arguments: 1; a comma-separated list of commands (with options),
3852 # Return : `1' if none found, `0' if found.
3853 # Output : the argument that succeded.
3855 landmark
'16: main_set_mode()';
3858 func_check main_set_mode
= 0 "$@";
3865 if obj _OPT_APROPOS is_not_empty
; then
3866 apropos
"${_OPT_APROPOS}";
3871 if obj _OPT_APROPOS_DATA is_not_empty
; then
3872 apropos
"$@" |
grep '^[^(]*([457])';
3877 if obj _OPT_APROPOS_DEVEL is_not_empty
; then
3878 apropos
"$@" |
grep '^[^(]*([239])';
3883 if obj _OPT_APROPOS_PROGS is_not_empty
; then
3884 apropos
"$@" |
grep '^[^(]*([168])';
3891 if obj _OPT_DISPLAY is_not_empty
; then
3892 DISPLAY
="${_OPT_DISPLAY}";
3895 if obj _OPT_V is_yes
; then
3896 _DISPLAY_MODE
='groff';
3897 list_append _ADDOPTS_GROFF
'-V';
3899 if obj _OPT_Z is_yes
; then
3900 _DISPLAY_MODE
='groff';
3901 list_append _ADDOPTS_GROFF
'-Z';
3903 if obj _OPT_MODE is_equal
'groff'; then
3904 _DISPLAY_MODE
='groff';
3906 if obj _DISPLAY_MODE is_equal
'groff'; then
3907 eval "${return_ok}";
3910 if obj _OPT_MODE is_equal
'source'; then
3911 _DISPLAY_MODE
='source';
3912 eval "${return_ok}";
3915 case "${_OPT_MODE}" in
3916 '') # automatic mode
3917 case "${_OPT_DEVICE}" in
3919 if obj DISPLAY is_empty
; then
3920 error
"no X display found for device ${_OPT_DEVICE}";
3923 eval "${return_ok}";
3925 ascii|cp1047|latin1|utf8
)
3926 if obj _DISPLAY_MODE is_not_equal
'text'; then
3927 _DISPLAY_MODE
='tty';
3929 eval "${return_ok}";
3932 if obj DISPLAY is_empty
; then
3933 _DISPLAY_MODE
='tty';
3934 eval "${return_ok}";
3937 if obj _OPT_DEFAULT_MODES is_empty
; then
3938 _modes
="${_DEFAULT_MODES}";
3940 _modes
="${_OPT_DEFAULT_MODES}";
3944 _DISPLAY_MODE
='text';
3945 eval "${return_ok}";
3948 _DISPLAY_MODE
='tty';
3949 eval "${return_ok}";
3951 *) # display mode was given
3952 if obj DISPLAY is_empty
; then
3953 error
"you must be in X Window for ${_OPT_MODE} mode.";
3955 _modes
="${_OPT_MODE}";
3959 # only viewer modes are left
3960 eval set -- "$(list_from_split "${_modes}" ',')";
3961 while test "$#" -gt 0; do
3966 _DISPLAY_MODE
='text';
3967 eval "${return_ok}";
3970 _DISPLAY_MODE
='tty';
3971 eval "${return_ok}";
3974 if obj _OPT_VIEWER_X is_not_empty
; then
3975 _viewers
="${_OPT_VIEWER_X}";
3977 _viewers
="${_VIEWER_X}";
3979 _viewer
="$(_get_first_prog "${_viewers}")";
3980 if is_not_equal
"$?" 0; then
3983 _DISPLAY_PROG
="${_viewer}";
3985 eval "${return_ok}";
3988 if obj _OPT_VIEWER_DVI is_not_empty
; then
3989 _viewers
="${_OPT_VIEWER_DVI}";
3991 _viewers
="${_VIEWER_DVI}";
3993 _viewer
="$(_get_first_prog "${_viewers}")";
3994 if is_not_equal
"$?" 0; then
3997 _DISPLAY_PROG
="${_viewer}";
3998 _DISPLAY_MODE
="dvi";
3999 eval "${return_ok}";
4002 if obj _OPT_VIEWER_PDF is_not_empty
; then
4003 _viewers
="${_OPT_VIEWER_PDF}";
4005 _viewers
="${_VIEWER_PDF}";
4007 _viewer
="$(_get_first_prog "${_viewers}")";
4008 if is_not_equal
"$?" 0; then
4011 _DISPLAY_PROG
="${_viewer}";
4012 _DISPLAY_MODE
="pdf";
4013 eval "${return_ok}";
4016 if obj _OPT_VIEWER_PS is_not_empty
; then
4017 _viewers
="${_OPT_VIEWER_PS}";
4019 _viewers
="${_VIEWER_PS}";
4021 _viewer
="$(_get_first_prog "${_viewers}")";
4022 if is_not_equal
"$?" 0; then
4025 _DISPLAY_PROG
="${_viewer}";
4027 eval "${return_ok}";
4030 if obj _OPT_VIEWER_HTML is_not_empty
; then
4031 _viewers
="${_OPT_VIEWER_HTML}";
4033 _viewers
="${_VIEWER_HTML}";
4035 _viewer
="$(_get_first_prog "${_viewers}")";
4036 if is_not_equal
"$?" 0; then
4039 _DISPLAY_PROG
="${_viewer}";
4041 eval "${return_ok}";
4045 error
"no suitable display mode found.";
4051 if is_equal
"$#" 0; then
4052 error
"_get_first_prog() needs 1 argument.";
4054 if is_empty
"$1"; then
4057 eval set -- "$(list_from_split "$1" ',')";
4059 if obj i is_empty
; then
4062 if is_prog
"$(get_first_essential $i)"; then
4071 #######################################################################
4072 # main_do_fileargs ()
4074 # Process filespec arguments in $_FILEARGS.
4077 # in: $_FILEARGS (process with `eval set -- "$_FILEARGS"')
4079 landmark
'17: main_do_fileargs()';
4082 func_check main_do_fileargs
= 0 "$@";
4086 _exitcode
="${_BAD}";
4087 eval set -- "${_FILEARGS}";
4089 # temporary storage of all input to $_TMP_CAT
4090 while test "$#" -ge 2; do
4091 # test for `s name' arguments, with `s' a 1-char standard section
4094 case "${_filespec}" in
4099 if register_file
'-'; then
4100 _exitcode
="${_GOOD}";
4105 if list_has_not _MAN_AUTO_SEC
"${_filespec}"; then
4106 if do_filearg
"${_filespec}"; then
4107 _exitcode
="${_GOOD}";
4113 */*|man
:*|
*\
(*\
)|
*.
"${_filespec}")
4114 if do_filearg
"${_filespec}"; then
4115 _exitcode
="${_GOOD}";
4120 if do_filearg
"man:${_name}(${_filespec})"; then
4121 _exitcode
="${_GOOD}";
4125 if do_filearg
"${_filespec}"; then
4126 _exitcode
="${_GOOD}";
4132 if do_filearg
"${_filespec}"; then
4133 _exitcode
="${_GOOD}";
4138 done; # end of `s name' test
4139 while test "$#" -gt 0; do
4142 if do_filearg
"${_filespec}"; then
4143 _exitcode
="${_GOOD}";
4146 rm -f "${_TMP_STDIN}";
4147 if is_equal
"${_exitcode}" "${_BAD}"; then
4148 eval "${return_bad}";
4150 eval "${return_ok}";
4151 } # main_do_fileargs()
4154 ########################################################################
4155 # main_set_resources ()
4157 # Determine options for setting X resources with $_DISPLAY_PROG.
4159 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4161 landmark
'18: main_set_resources()';
4162 main_set_resources
()
4164 func_check main_set_resources
= 0 "$@";
4165 local _prog
; # viewer program
4166 local _rl
; # resource list
4168 _title
="$(get_first_essential \
4169 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4170 _OUTPUT_FILE_NAME
='';
4172 until is_equal
"$#" 0; do
4179 n
="$(echo -n "$1" | sed -e 's/^,,*//')";
4182 if obj n is_empty
; then
4185 if obj _OUTPUT_FILE_NAME is_not_empty
; then
4186 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME},";
4188 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}$n";
4191 case "${_OUTPUT_FILE_NAME}" in
4193 _OUTPUT_FILE_NAME
='-';
4196 error
"$_OUTPUT_FILE_NAME starts with a comma.";
4199 _OUTPUT_FILE_NAME
="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4201 if obj _DISPLAY_PROG is_empty
; then # for example, for groff mode
4203 eval "${return_ok}";
4206 set -- ${_DISPLAY_PROG};
4207 _prog
="$(base_name "$1")";
4209 if obj _OPT_BD is_not_empty
; then
4211 ghostview|gv|gxditview|xditview|xdvi
)
4212 list_append _rl
'-bd' "${_OPT_BD}";
4216 if obj _OPT_BG is_not_empty
; then
4218 ghostview|gv|gxditview|xditview|xdvi
)
4219 list_append _rl
'-bg' "${_OPT_BG}";
4222 list_append _rl
'-papercolor' "${_OPT_BG}";
4226 if obj _OPT_BW is_not_empty
; then
4228 ghostview|gv|gxditview|xditview|xdvi
)
4229 _list_append _rl
'-bw' "${_OPT_BW}";
4233 if obj _OPT_FG is_not_empty
; then
4235 ghostview|gv|gxditview|xditview|xdvi
)
4236 list_append _rl
'-fg' "${_OPT_FG}";
4240 if is_not_empty
"${_OPT_FN}"; then
4242 ghostview|gv|gxditview|xditview|xdvi
)
4243 list_append _rl
'-fn' "${_OPT_FN}";
4247 if is_not_empty
"${_OPT_GEOMETRY}"; then
4249 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4250 list_append _rl
'-geometry' "${_OPT_GEOMETRY}";
4254 if is_empty
"${_OPT_RESOLUTION}"; then
4255 _OPT_RESOLUTION
="${_DEFAULT_RESOLUTION}";
4258 list_append _rl
'-resolution' "${_DEFAULT_RESOLUTION}";
4261 case "${_DEFAULT_RESOLUTION}" in
4264 list_append _rl
'-z' '104';
4267 list_append _rl
'-z' '139';
4274 ghostview|gv|gxditview|xditview|xdvi
)
4275 list_append _rl
'-resolution' "${_OPT_RESOLUTION}";
4278 case "${_OPT_RESOLUTION}" in
4280 list_append _rl
'-z' '104';
4281 # '100' corresponds to 72dpi
4284 list_append _rl
'-z' '139';
4290 if is_yes
"${_OPT_ICONIC}"; then
4292 ghostview|gv|gxditview|xditview|xdvi
)
4293 list_append _rl
'-iconic';
4297 if is_yes
"${_OPT_RV}"; then
4299 ghostview|gv|gxditview|xditview|xdvi
)
4300 list_append _rl
'-rv';
4304 if is_not_empty
"${_OPT_XRM}"; then
4306 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4307 eval set -- "{$_OPT_XRM}";
4309 list_append _rl
'-xrm' "$i";
4314 if is_not_empty
"${_title}"; then
4317 list_append _rl
'-title' "${_title}";
4321 _DISPLAY_ARGS
="${_rl}";
4323 eval "${return_ok}";
4324 } # main_set_resources
4327 ########################################################################
4330 # Do the actual display of the whole thing.
4333 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4334 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4335 # $_REGISTERED_TITLE, $_TMP_CAT,
4336 # $_OPT_PAGER $PAGER $_MANOPT_PAGER
4338 landmark
'19: main_display()';
4341 func_check main_display
= 0 "$@";
4354 if obj _TMP_CAT is_non_empty_file
; then
4355 _modefile
="${_OUTPUT_FILE_NAME}";
4358 eval "${return_ok}";
4360 case "${_DISPLAY_MODE}" in
4362 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4363 if obj _OPT_DEVICE is_not_empty
; then
4364 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4366 _groggy
="$(tmp_cat | eval grog "${_options}")";
4368 # start a new shell program to get another process ID.
4371 test -f "${_modefile}" && rm -f "${_modefile}";
4372 mv "${_TMP_CAT}" "${_modefile}";
4373 cat "${_modefile}" | \
4377 if test -d "${_TMP_DIR}"; then
4378 rm -f "${_TMP_DIR}"/* || true;
4379 rmdir "${_TMP_DIR}";
4382 trap clean_up 0 2>/dev/null || true;
4383 eval "${_groggy}" "${_ADDOPTS_GROFF}";
4387 case "${_OPT_DEVICE}" in
4389 _device
="$(get_first_essential \
4390 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4392 ascii|cp1047|latin1|utf8
)
4393 _device
="${_OPT_DEVICE}";
4397 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4400 _addopts
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4401 _groggy
="$(tmp_cat | grog -T${_device})";
4402 if obj _DISPLAY_MODE is_equal
'text'; then
4403 tmp_cat |
eval "${_groggy}" "${_addopts}";
4406 for p
in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4407 'less -r -R' 'more' 'pager' 'cat'; do
4408 if is_prog
$p; then # no "" for is_prog() allows args for $p
4413 if obj _pager is_empty
; then
4414 error
'no pager program found for tty mode';
4416 tmp_cat |
eval "${_groggy}" "${_addopts}" | \
4425 case "${_OPT_DEVICE}" in
4426 ''|dvi
) do_nothing
; ;;
4429 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4432 _modefile
="${_modefile}".dvi
;
4433 _groggy
="$(tmp_cat | grog -Tdvi)";
4437 case "${_OPT_DEVICE}" in
4438 ''|html
) do_nothing
; ;;
4441 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4444 _modefile
="${_modefile}".html
;
4445 _groggy
="$(tmp_cat | grog -Thtml)";
4449 case "${_OPT_DEVICE}" in
4455 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4458 _groggy
="$(tmp_cat | grog -Tps)";
4460 # start a new shell program to get another process ID.
4463 _psfile="${_modefile}.ps";
4464 _modefile="${_modefile}.pdf";
4465 test -f "${_psfile}" && rm -f "${_psfile}";
4466 test -f "${_modefile}" && rm -f "${_modefile}";
4467 cat "${_TMP_CAT}" | \
4468 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4469 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4470 -sOutputFile="${_modefile}" -c save pop -f "${_psfile}";
4471 test -f "${_psfile}" && rm -f "${_psfile}";
4472 test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";
4475 rm -f "${_modefile}";
4476 if test -d "${_TMP_DIR}"; then
4477 rm -f "${_TMP_DIR}"/* || true;
4478 rmdir "${_TMP_DIR}";
4481 trap clean_up 0 2>/dev/null || true;
4482 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4486 case "${_OPT_DEVICE}" in
4492 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4495 _modefile
="${_modefile}".ps
;
4496 _groggy
="$(tmp_cat | grog -Tps)";
4504 case "${_OPT_DEVICE}" in
4506 _groggy
="$(tmp_cat | grog -Z)";
4509 _groggy
="$(tmp_cat | grog -T"${_OPT_DEVICE}" -Z)";
4513 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4514 _groggy
="$(tmp_cat | grog -Z)";
4520 error
"unknown mode \`${_DISPLAY_MODE}'";
4523 eval "${return_ok}";
4528 func_check _do_display
= 0 "$@";
4530 # start a new shell program for another process ID and better
4531 # cleaning-up of the temporary files.
4534 test -f "${_modefile}" && rm -f "${_modefile}";
4535 cat "${_TMP_CAT}" | \
4536 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}";
4537 rm -f "${_TMP_CAT}";
4540 if test -d "${_TMP_DIR}"; then
4541 rm -f "${_TMP_DIR}"/* || true;
4542 rmdir "${_TMP_DIR}";
4545 trap clean_up 0 2>/dev/null || true;
4546 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4551 ########################################################################
4552 # main (<command_line_args>*)
4554 # The main function for groffer.
4560 func_check main
'>=' 0 "$@";
4561 # Do not change the sequence of the following functions!
4564 main_parse_args
"$@";
4569 eval "${return_ok}";
4572 landmark
'20: end of function definitions';
4574 ########################################################################