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.16';
29 _LAST_UPDATE
='19 Jun 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}"_
= __
;
39 # only reached during the first run of the script
41 export _groffer_run
; # counter for the runs of groffer
45 export _PROGRAM_VERSION
;
48 export GROFFER_OPT
; # option environment for groffer
49 export _GROFFER_SH
; # file name of this shell script
50 export _OUTPUT_FILE_NAME
; # output generated, see main_set_res..()
52 export _CONFFILES
; # configuration files
53 _CONFFILES
="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
58 # was: _GROFFER_SH="@BINDIR@/${_PROGRAM_NAME}";
61 echo "The ${_PROGRAM_NAME} script should be started directly." >&2
69 _NULL_DEV
="/dev/null";
75 ###########################
76 # _get_opt_shell ("$@")
78 # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
79 # if so echo its argument.
85 case " ${GROFFER_OPT} $*" in
86 *\
--shell\
*|
*\
--shell=*)
88 eval set -- "${GROFFER_OPT}" '"$@"';
101 # delete up to first `=' character
102 _sh
="$(echo -n "$1" | sed -e 's/^[^=]*=//')";
114 ###########################
115 # _test_on_shell (<name>)
117 # Test whether <name> is a shell program of Bourne type (POSIX sh).
121 if test "$#" -le 0 ||
test _
"$1"_
= __
;
125 # do not quote $1 to allow arguments
126 test _
"$($1 -c 's=ok; echo -n "$s"' 2>${_NULL_DEV})"_
= _ok_
;
129 # do the shell determination from command line and $GROFFER_OPT
130 _shell
="$(_get_opt_shell "$@
")";
132 if test _
"${_shell}"_
= __
;
134 # none found, so look at the `--shell' lines in configuration files
136 for f
in ${_CONFFILES};
140 _all
="$(cat $f | sed -n -e '/^--shell[= ] *\([^ ]*\)$/s//\1/p')"
152 # restart the script with the last found $_shell, if it is a shell
153 if _test_on_shell
"${_shell}";
155 _groffer_run
='second';
156 # do not quote $_shell to allow arguments
157 exec ${_shell} "${_GROFFER_SH}" "$@";
161 _groffer_run
='second';
164 fi; # end of first run
166 if test _
"${_groffer_run}"_
!= _second_
;
168 echo "$_groffer_run should be 'second' here." >&2
175 ########################################################################
176 # diagnostic messages
179 _DEBUG
='no'; # disable debugging information
180 #_DEBUG='yes'; # enable debugging information
183 _DEBUG_LM
='no'; # disable landmark messages
184 #_DEBUG_LM='yes'; # enable landmark messages
187 ########################################################################
188 # Environment Variables
189 ########################################################################
191 # Environment variables that exist only for this file start with an
192 # underscore letter. Global variables to this file are written in
193 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
194 # start with an underline and use only lower case letters and
195 # underlines, e.g. $_local_variable .
197 # [A-Z]* system variables, e.g. $MANPATH
198 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
199 # _[a-z_]* temporary variables, e.g. $_manpath
201 # Due to incompatibilities of the `ash' shell, the name of loop
202 # variables in `for' must be single character
203 # [a-z] local loop variables, e.g. $i
206 ########################################################################
207 # read-only variables (global to this file)
208 ########################################################################
237 # function return values; `0' means ok
; other values are error codes
246 _GOOD
='0'; # return ok
247 _BAD
='1'; # return negatively, error code `1'
248 _ERROR
='7'; # for syntax errors; no `-1' in `ash'
250 _ALL_EXIT
="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
256 # quasi-functions, call with `eval'
263 return_ok
="func_pop; return ${_OK}";
264 return_good
="func_pop; return ${_GOOD}";
265 return_bad
="func_pop; return ${_BAD}";
266 return_yes
="func_pop; return ${_YES}";
267 return_no
="func_pop; return ${_NO}";
268 return_error
="func_pop; return ${_ERROR}";
271 export _DEFAULT_MODES
;
272 _DEFAULT_MODES
='x,ps,tty';
273 export _DEFAULT_RESOLUTION
;
274 _DEFAULT_RESOLUTION
='75';
276 export _DEFAULT_TTY_DEVICE
;
277 _DEFAULT_TTY_DEVICE
='latin1';
279 # _VIEWER_* viewer programs for different modes (only X is necessary)
280 # _VIEWER_* a comma-separated list of viewer programs (with options)
281 export _VIEWER_DVI
; # viewer program for dvi mode
282 export _VIEWER_PS
; # viewer program for ps mode
283 export _VIEWER_HTML_X
; # viewer program for html mode in X
284 export _VIEWER_HTML_TTY
; # viewer program for html mode in tty
285 _VIEWER_DVI
='kdvi,xdvi,dvilx';
286 _VIEWER_PDF
='kghostview,ggv,xpdf,acroread,kpdf';
287 _VIEWER_PS
='kghostview,ggv,gv,ghostview,gs_x11,gs';
288 _VIEWER_HTML
='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
289 _VIEWER_X
='gxditview,xditview';
291 # Search automatically in standard sections `1' to `8', and in the
292 # traditional sections `9', `n', and `o'. On many systems, there
293 # exist even more sections, mostly containing a set of man pages
294 # special to a specific program package. These aren't searched for
295 # automatically, but must be specified on the command line.
296 export _MAN_AUTO_SEC
;
297 _MAN_AUTO_SEC
="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
299 export _PROCESS_ID
; # for shutting down the program
303 ############ the command line options of the involved programs
305 # The naming scheme for the options environment names is
306 # $_OPTS_<prog>_<length>[_<argspec>]
308 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
309 # command line options)
310 # <length>: LONG (long options) or SHORT (single character options)
311 # <argspec>: ARG for options with argument, NA for no argument;
312 # without _<argspec> both the ones with and without arg.
314 # Each option that takes an argument must be specified with a
315 # trailing : (colon).
318 export _OPTS_GROFFER_SHORT_NA
;
319 export _OPTS_GROFFER_SHORT_ARG
;
320 export _OPTS_GROFFER_LONG_NA
;
321 export _OPTS_GROFFER_LONG_ARG
;
322 export _OPTS_GROFF_SHORT_NA
;
323 export _OPTS_GROFF_SHORT_ARG
;
324 export _OPTS_GROFF_LONG_NA
;
325 export _OPTS_GROFF_LONG_ARG
;
326 export _OPTS_X_SHORT_ARG
;
327 export _OPTS_X_SHORT_NA
;
328 export _OPTS_X_LONG_ARG
;
329 export _OPTS_X_LONG_NA
;
330 export _OPTS_MAN_SHORT_ARG
;
331 export _OPTS_MAN_SHORT_NA
;
332 export _OPTS_MAN_LONG_ARG
;
333 export _OPTS_MAN_LONG_NA
;
334 export _OPTS_MANOPT_SHORT_ARG
;
335 export _OPTS_MANOPT_SHORT_NA
;
336 export _OPTS_MANOPT_LONG_ARG
;
337 export _OPTS_MANOPT_LONG_NA
;
338 export _OPTS_CMDLINE_SHORT_NA
;
339 export _OPTS_CMDLINE_SHORT_ARG
;
340 export _OPTS_CMDLINE_LONG_NA
;
341 export _OPTS_CMDLINE_LONG_ARG
;
343 ###### groffer native options
345 _OPTS_GROFFER_SHORT_NA
="'h' 'Q' 'v' 'V' 'X' 'Z'";
346 _OPTS_GROFFER_SHORT_ARG
="'T'";
348 _OPTS_GROFFER_LONG_NA
="'auto' 'debug' 'default' 'dvi' \
349 'groff' 'help' 'intermediate-output' 'html' 'man' \
350 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
351 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
353 _OPTS_GROFFER_LONG_ARG
="\
354 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
355 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
356 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
357 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
359 ##### groffer options inhereted from groff
361 _OPTS_GROFF_SHORT_NA
="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
362 'R' 's' 'S' 't' 'U' 'z'";
363 _OPTS_GROFF_SHORT_ARG
="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
365 _OPTS_GROFF_LONG_NA
="";
366 _OPTS_GROFF_LONG_ARG
="";
368 ##### groffer options inhereted from the X Window toolkit
371 _OPTS_X_SHORT_ARG
="";
373 _OPTS_X_LONG_NA
="'iconic' 'rv'";
375 _OPTS_X_LONG_ARG
="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
376 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'
377 'resolution' 'title' 'xrm'";
379 ###### groffer options inherited from man
381 _OPTS_MAN_SHORT_NA
="";
382 _OPTS_MAN_SHORT_ARG
="";
384 _OPTS_MAN_LONG_NA
="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \
385 'local-file' 'location' 'pager' 'troff' 'update' 'version' \
388 _OPTS_MAN_LONG_ARG
="'extension' 'locale' 'manpath' \
389 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
391 ###### additional options for parsing $MANOPT only
393 _OPTS_MANOPT_SHORT_NA
="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
395 _OPTS_MANOPT_SHORT_ARG
="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
397 _OPTS_MANOPT_LONG_NA
="${_OPTS_MAN_LONG_NA} \
398 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
399 'match-case' 'troff' 'update' 'version' 'where-cat'";
401 _OPTS_MANOPT_LONG_ARG
="${_OPTS_MAN_LONG_NA} \
402 'config_file' 'encoding' 'locale'";
404 ###### collections of command line options
406 _OPTS_CMDLINE_SHORT_NA
="${_OPTS_GROFFER_SHORT_NA}\
407 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
408 _OPTS_CMDLINE_SHORT_ARG
="${_OPTS_GROFFER_SHORT_ARG} \
409 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
411 _OPTS_CMDLINE_LONG_NA
="${_OPTS_GROFFER_LONG_NA} \
412 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
413 _OPTS_CMDLINE_LONG_ARG
="${_OPTS_GROFFER_LONG_ARG} \
414 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
417 ########################################################################
418 # read-write variables (global to this file)
419 ########################################################################
421 export _ADDOPTS_GROFF
; # Transp. options for groff (`eval').
422 export _ADDOPTS_POST
; # Transp. options postproc (`eval').
423 export _ADDOPTS_X
; # Transp. options X postproc (`eval').
424 export _DEFAULT_MODES
; # Set default modes.
425 export _DISPLAY_MODE
; # Display mode.
426 export _DISPLAY_PROG
; # Viewer program to be used for display.
427 export _DISPLAY_ARGS
; # X resources for the viewer program.
428 export _FILEARGS
; # Stores filespec parameters.
429 export _FUNC_STACK
; # Store debugging information.
430 export _REGISTERED_TITLE
; # Processed file names.
431 # _HAS_* from availability tests
432 export _HAS_COMPRESSION
; # `yes' if compression is available
433 export _HAS_OPTS_GNU
; # `yes' if GNU `getopt' is available
434 export _HAS_OPTS_POSIX
; # `yes' if POSIX `getopts' is available
435 # _MAN_* finally used configuration of man searching
436 export _MAN_ALL
; # search all man pages per filespec
437 export _MAN_ENABLE
; # enable search for man pages
438 export _MAN_EXT
; # extension for man pages
439 export _MAN_FORCE
; # force file parameter to be man pages
440 export _MAN_IS_SETUP
; # setup man variables only once
441 export _MAN_LANG
; # language for man pages
442 export _MAN_LANG_DONE
; # language dirs added to man path
443 export _MAN_PATH
; # search path for man pages
444 export _MAN_SEC
; # sections for man pages; sep. `:'
445 export _MAN_SEC_DONE
; # sections added to man path
446 export _MAN_SYS
; # system names for man pages; sep. `,'
447 export _MAN_SYS
; # system names added to man path
448 # _MANOPT_* as parsed from $MANOPT
449 export _MANOPT_ALL
; # $MANOPT --all
450 export _MANOPT_EXTENSION
; # $MANOPT --extension
451 export _MANOPT_LANG
; # $MANOPT --locale
452 export _MANOPT_PATH
; # $MANOPT --manpath
453 export _MANOPT_PAGER
; # $MANOPT --pager
454 export _MANOPT_SEC
; # $MANOPT --sections
455 export _MANOPT_SYS
; # $MANOPT --systems
456 # _OPT_* as parsed from groffer command line
457 export _OPT_ALL
; # display all suitable man pages.
458 export _OPT_APROPOS
; # call `apropos' program.
459 export _OPT_APROPOS_DATA
; # `apropos' for man sections 4, 5, 7
460 export _OPT_APROPOS_DEVEL
; # `apropos' for man sections 2, 3, 9
461 export _OPT_APROPOS_PROGS
; # `apropos' for man sections 1, 6, 8
462 export _OPT_BD
; # set border color in some modes.
463 export _OPT_BG
; # set background color in some modes.
464 export _OPT_BW
; # set border width in some modes.
465 export _OPT_DEBUG
; # print debugging information on stderr.
466 export _OPT_DEFAULT_MODES
; # `,'-list of modes when no mode given.
467 export _OPT_DEVICE
; # device option.
468 export _OPT_DISPLAY
; # set X display.
469 export _OPT_FG
; # set foreground color in some modes.
470 export _OPT_FN
; # set font in some modes.
471 export _OPT_GEOMETRY
; # set size and position of viewer in X.
472 export _OPT_ICONIC
; # -iconic option for X viewers.
473 export _OPT_LANG
; # set language for man pages
474 export _OPT_LOCATION
; # print processed file names to stderr
475 export _OPT_MODE
; # values: X, tty, Q, Z, ""
476 export _OPT_MANPATH
; # manual setting of path for man-pages
477 export _OPT_PAGER
; # specify paging program for tty mode
478 export _OPT_RESOLUTION
; # set X resolution in dpi
479 export _OPT_RV
; # reverse fore- and background colors.
480 export _OPT_SECTIONS
; # sections for man page search
481 export _OPT_SYSTEMS
; # man pages of different OS's
482 export _OPT_TITLE
; # title for gxditview window
483 export _OPT_TEXT_DEVICE
; # set device for tty mode.
484 export _OPT_V
; # groff option -V.
485 export _OPT_VIEWER_DVI
; # viewer program for dvi mode
486 export _OPT_VIEWER_PDF
; # viewer program for pdf mode
487 export _OPT_VIEWER_PS
; # viewer program for ps mode
488 export _OPT_VIEWER_HTML
; # viewer program for html mode
489 export _OPT_VIEWER_X
; # viewer program for x mode
490 export _OPT_WHATIS
; # print the one-liner man info
491 export _OPT_XRM
; # specify X resource.
492 export _OPT_Z
; # groff option -Z.
493 # _TMP_* temporary files
494 export _TMP_DIR
; # groffer directory for temporary files
495 export _TMP_CAT
; # stores concatenation of everything
496 export _TMP_STDIN
; # stores stdin, if any
498 # these variables are preset in section `Preset' after the rudim. test
501 ########################################################################
502 # Test of rudimentary shell functionality
503 ########################################################################
506 ########################################################################
509 test "a" = "a" ||
exit 1;
512 ########################################################################
513 # Test of `echo' and the `$()' construct.
515 echo -n '' >${_NULL_DEV} ||
exit "${_ERROR}";
516 if test _
"$(echo -n 'te' && echo -n '' && echo -n 'st')"_
!= _test_
;
522 ########################################################################
523 # Test of function definitions.
530 if _t_e_s_t_f_u_n_c_
2>${_NULL_DEV};
534 echo 'shell does not support function definitions.' >&2;
539 ########################################################################
540 # Preset and reset of read-write global variables
541 ########################################################################
544 # For variables that can be reset by option `--default', see reset().
548 # _HAS_* from availability tests
553 # _TMP_* temporary files
559 ########################################################################
562 # Reset the variables that can be affected by options to their default.
568 error
"reset() does not have arguments.";
577 _REGISTERED_TITLE
='';
579 # _MAN_* finally used configuration of man searching
581 _MAN_ENABLE
='yes'; # do search for man-pages
583 _MAN_FORCE
='no'; # first local file, then search man page
593 # _MANOPT_* as parsed from $MANOPT
595 _MANOPT_EXTENSION
='';
602 # _OPT_* as parsed from groffer command line
605 _OPT_APROPOS_DATA
='';
606 _OPT_APROPOS_DEVEL
='';
607 _OPT_APROPOS_PROGS
='';
612 _OPT_DEFAULT_MODES
='';
645 ########################################################################
646 # Functions for error handling and debugging
647 ########################################################################
653 # Print <text> to standard error as a debugging aid.
655 # Globals: $_DEBUG_LM
659 if test _
"${_DEBUG_LM}"_
= _yes_
;
665 landmark
"1: debugging functions";
675 if test -d "${_TMP_DIR}";
677 rm -f -r "${_TMP_DIR}";
687 # Arguments : arbitrary text.
700 # Arguments : arbitrary text.
711 # Output a diagnostic message to stderr
722 # Print an error message to standard error; exit with an error condition
731 1) echo2
'groffer error: '"$1"; ;;
733 echo2
'groffer error: '"$1";
736 *) echo2
'groffer error: wrong number of arguments in error().'; ;;
738 if test _
"${_DEBUG}"_
= _yes_
;
743 kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
744 kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
752 # Terminate program with error condition
756 error
"Program aborted.";
762 # func_check (<func_name> <rel_op> <nr_args> "$@")
764 # Check number of arguments and register to _FUNC_STACK.
767 # <func_name>: name of the calling function.
768 # <rel_op>: a relational operator: = != < > <= >=
769 # <nr_args>: number of arguments to be checked against <operator>
770 # "$@": the arguments of the calling function.
781 error
'func_check() needs at least 3 arguments.';
794 error
"func_check(): third argument must be a digit.";
824 'func_check(): second argument is not a relational operator.';
828 if test "$#" "${_op}" "${_nargs}";
833 "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
835 if test _
"${_DEBUG}"_
= _yes_
;
837 func_push
"${_fname} $*";
845 # Retrieve the top element from the stack.
847 # The stack elements are separated by `!'; the popped element is
848 # identical to the original element, except that all `!' characters
855 if test _
"${_DEBUG}"_
= _yes_
;
859 error
'func_pop() does not have arguments.';
861 case "${_FUNC_STACK}" in
863 error
'func_pop(): stack is empty.';
866 # split at first bang `!'.
867 _FUNC_STACK
="$(echo -n ${_FUNC_STACK} \
868 | sed -e 's/^[^!]*!//')";
879 # func_push (<element>)
881 # Store another element to stack.
883 # The stack elements are separated by `!'; if <element> contains a `!'
884 # it is removed first.
891 if test _
"${_DEBUG}"_
= _yes_
;
895 error
'func_push() needs 1 argument.';
899 # remove all bangs `!'.
900 _element
="$(echo -n "$1" | sed -e 's/!//g')";
906 if test _
"${_FUNC_STACK}"_
= __
;
908 _FUNC_STACK
="${_element}";
910 _FUNC_STACK
="${_element}!${_FUNC_STACK}";
919 # Print the content of the stack. Ignore the arguments.
924 case "${_FUNC_STACK}" in
926 _rest
="${_FUNC_STACK}";
927 while test _
"${_rest}"_
!= __
;
929 # get part before the first bang `!'.
930 diag
"$(echo -n "${_rest}" | sed -e 's/!.*$//')";
931 # delete part before and including the first bang `!'.
932 _rest
="$(echo -n "${_rest}" | sed -e 's/^[^!]*!//')";
936 diag
"${_FUNC_STACK}";
942 ########################################################################
944 ########################################################################
946 landmark
"2: system test";
948 # Test the availability of the system utilities used in this script.
951 ########################################################################
954 if true
>${_NULL_DEV} 2>&1;
970 ########################################################################
974 if unset _test
>${_NULL_DEV} 2>&1 && test _
"${_test}"_
= __
;
988 ########################################################################
989 # Test of builtin `local'
994 local _test
>${_NULL_DEV} 2>&1 ||
return "${_BAD}";
997 if _t_e_s_t_f_u_n_c_
;
1003 if test _
"$1"_
!= __
;
1005 error
"overriding global variable \`$1' with local value.";
1011 ########################################################################
1012 # Test of global setting in functions
1025 if test _
"${_global}"_
!= _inside_ ||
test _
"${_clobber}"_
!= _outside_
;
1027 error
"Cannot assign to global variables from within functions.";
1034 ########################################################################
1035 # Test of function `sed'.
1038 if test _
"$(echo xTesTx \
1039 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1040 | sed -e '\|T|s|T|t|g')"_
!= _test_
;
1042 error
'Test of "sed" command failed.';
1046 ########################################################################
1047 # Test of function `cat'.
1049 if test _
"$(echo test | cat)"_
!= _test_
;
1051 error
'Test of "cat" command failed.';
1055 ########################################################################
1056 # Test for compression.
1058 if test _
"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_
= _test_
;
1060 _HAS_COMPRESSION
='yes';
1061 if echo 'test' |
bzip2 -c 2>${_NULL_DEV} |
bzip2 -t 2>${_NULL_DEV} \
1062 && test _
"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
1063 | bzip2 -d -c 2>${_NULL_DEV})"_ \
1071 _HAS_COMPRESSION
='no';
1076 ########################################################################
1083 ########################################################################
1084 # Definition of normal Functions in alphabetical order
1085 ########################################################################
1086 landmark
"3: functions";
1088 ########################################################################
1091 # Unconditionally terminate the program with error code;
1092 # useful for debugging.
1097 ########################################################################
1098 # apropos_run (<name>)
1102 func_check apropos_run
= 1 "$@";
1103 if apropos apropos
>${_NULL_DEV} 2>${_NULL_DEV};
1106 elif man
--apropos man
>${_NULL_DEV} 2>${_NULL_DEV};
1109 elif man
-k man
>${_NULL_DEV} 2>${_NULL_DEV};
1116 ########################################################################
1117 # base_name (<path>)
1119 # Get the file name part of <path>, i.e. delete everything up to last
1120 # `/' from the beginning of <path>. Remove final slashes, too, to get a
1124 # Output : the file name part (without slashes)
1128 func_check base_name
= 1 "$@";
1133 # delete all final slashes
1134 f
="$(echo -n "$f" | sed -e '\|.*|s|//*$||')";
1139 eval "${return_bad}";
1142 # delete everything before and including the last slash `/'.
1143 echo -n "$f" |
sed -e '\|.*|s|^.*//*\([^/]*\)$|\1|';
1149 eval "${return_ok}";
1153 ########################################################################
1156 # Decompress if possible or just print <file> to standard output.
1158 # gzip, bzip2, and .Z decompression is supported.
1160 # Arguments: 1, a file name.
1161 # Output: the content of <file>, possibly decompressed.
1163 if test _
"${_HAS_COMPRESSION}"_
= _yes_
;
1167 func_check catz
= 1 "$@";
1170 error
'catz(): empty file name';
1173 error
'catz(): for standard input use save_stdin()';
1176 if obj _HAS_BZIP is_yes
;
1178 if bzip2 -t "$1" 2>${_NULL_DEV};
1180 bzip2 -c -d "$1" 2>${_NULL_DEV};
1181 eval "${return_ok}";
1184 gzip -c -d -f "$1" 2>${_NULL_DEV};
1185 eval "${return_ok}";
1190 func_check catz
= 1 "$@";
1192 eval "${return_ok}";
1197 ########################################################################
1200 # Do the final cleaning up before exiting; used by the trap calls.
1205 ########################################################################
1208 # Print marked message to standard error; useful for debugging.
1213 ########################################################################
1214 landmark
'4: dirname()*';
1215 ########################################################################
1217 #######################################################################
1218 # dirname_append (<dir> <name>)
1220 # Append `name' to `dir' with clean handling of `/'.
1223 # Output : the generated new directory name <dir>/<name>
1227 func_check dirname_append
= 2 "$@";
1231 error
"dir_append(): first argument is empty.";
1237 dirname_chop
"$1"/"$2";
1239 eval "${return_ok}";
1243 ########################################################################
1244 # dirname_chop (<name>)
1246 # Remove unnecessary slashes from directory name.
1248 # Argument: 1, a directory name.
1249 # Output: path without double, or trailing slashes.
1253 func_check dirname_chop
= 1 "$@";
1257 # replace all multiple slashes by a single slash `/'.
1258 _res
="$(echo -n "$1" | sed -e '\|.*|s|///*|/|g')";
1261 # remove trailing slash '/';
1262 echo -n "${_res}" |
sed -e '\|.*|s|/$||';
1264 *) echo -n "${_res}"; ;;
1266 eval "${return_ok}";
1270 ########################################################################
1271 # do_filearg (<filearg>)
1273 # Append the file, man-page, or standard input corresponding to the
1274 # argument to the temporary file. If this is compressed in the gzip
1275 # or Z format it is decompressed. A title element is generated.
1278 # - name of an existing files.
1279 # - `-' to represent standard input (several times allowed).
1280 # - `man:name.(section)' the man-page for `name' in `section'.
1281 # - `man:name.section' the man-page for `name' in `section'.
1282 # - `man:name' the man-page for `name' in the lowest `section'.
1283 # - `name.section' the man-page for `name' in `section'.
1284 # - `name' the man-page for `name' in the lowest `section'.
1286 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1289 # Return : $_GOOD if found, ${_BAD} otherwise.
1293 func_check do_filearg
= 1 "$@";
1297 # store sequence into positional parameters
1298 case "${_filespec}" in
1300 eval "${return_good}";
1304 eval "${return_good}";
1306 */*) # with directory part; so no man search
1310 if obj _MAN_ENABLE is_yes
;
1312 if obj _MAN_FORCE is_yes
;
1314 set -- 'Manpage' 'File';
1316 set -- 'File' 'Manpage';
1327 if test -f "${_filespec}";
1329 if test -r "${_filespec}";
1331 register_file
"${_filespec}";
1332 eval "${return_good}";
1334 echo2
"could not read \`${_filespec}'";
1335 eval "${return_bad}";
1341 Manpage
) # parse filespec as man page
1342 if obj _MAN_IS_SETUP is_not_yes
;
1346 if man_do_filespec
"${_filespec}";
1348 eval "${return_good}";
1355 eval "${return_bad}";
1359 ########################################################################
1370 ########################################################################
1373 # Print to standard error with final line break.
1378 ########################################################################
1381 # Print to standard error without final line break.
1386 ########################################################################
1389 # Print error message and exit with error code.
1394 ########################################################################
1395 # func_check (<func_name> <rel_op> <nr_args> "$@")
1397 # Check number of arguments and register to _FUNC_STACK.
1400 # <func_name>: name of the calling function.
1401 # <rel_op>: a relational operator: = != < > <= >=
1402 # <nr_args>: number of arguments to be checked against <operator>
1403 # "$@": the arguments of the calling function.
1407 #########################################################################
1410 # Delete the top element from the function call stack.
1415 ########################################################################
1416 # func_push (<element>)
1418 # Store another element to function call stack.
1423 ########################################################################
1424 # func_stack_dump ()
1426 # Print the content of the stack.
1431 ########################################################################
1432 # get_first_essential (<arg>*)
1434 # Retrieve first non-empty argument.
1436 # Return : `1' if all arguments are empty, `0' if found.
1437 # Output : the retrieved non-empty argument.
1439 get_first_essential
()
1441 func_check get_first_essential
'>=' 0 "$@";
1445 eval "${return_ok}";
1449 if obj i is_not_empty
;
1452 eval "${return_ok}";
1455 eval "${return_bad}";
1459 ########################################################################
1460 landmark
'5: is_*()';
1461 ########################################################################
1463 ########################################################################
1466 # Test whether `name' is a directory.
1469 # Return : `0' if arg1 is a directory, `1' otherwise.
1473 func_check is_dir
= 1 "$@";
1474 if test -d "$1" && test -r "$1";
1476 eval "${return_yes}";
1478 eval "${return_no}";
1482 ########################################################################
1483 # is_empty (<string>)
1485 # Test whether `string' is empty.
1488 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1492 func_check is_empty
= 1 "$@";
1493 if test _
"$1"_
= __
;
1495 eval "${return_yes}";
1497 eval "${return_no}";
1501 ########################################################################
1502 # is_equal (<string1> <string2>)
1504 # Test whether `string1' is equal to <string2>.
1507 # Return : `0' both arguments are equal strings, `1' otherwise.
1511 func_check is_equal
= 2 "$@";
1512 if test _
"$1"_
= _
"$2"_
;
1514 eval "${return_yes}";
1516 eval "${return_no}";
1520 ########################################################################
1521 # is_existing (<name>)
1523 # Test whether `name' is an existing file or directory.
1526 # Return : `0' if arg1 exists, `1' otherwise.
1530 func_check is_existing
= 1 "$@";
1533 eval "${return_yes}";
1535 eval "${return_no}";
1539 ########################################################################
1542 # Test whether `name' is a readable file.
1545 # Return : `0' if arg1 is a readable file, `1' otherwise.
1549 func_check is_file
= 1 "$@";
1550 if test -f "$1" && test -r "$1";
1552 eval "${return_yes}";
1554 eval "${return_no}";
1558 ########################################################################
1559 # is_non_empty_file (<file_name>)
1561 # Test whether `file_name' is a non-empty existing file.
1565 # `0' if arg1 is a non-empty existing file
1570 func_check is_non_empty_file
= 1 "$@";
1571 if is_file
"$1" && test -s "$1";
1573 eval "${return_yes}";
1575 eval "${return_no}";
1579 ########################################################################
1580 # is_not_dir (<name>)
1582 # Test whether `name' is not a readable directory.
1585 # Return : `0' if arg1 is a directory, `1' otherwise.
1589 func_check is_not_dir
= 1 "$@";
1592 eval "${return_no}";
1594 eval "${return_yes}";
1598 ########################################################################
1599 # is_not_empty (<string>)
1601 # Test whether `string' is not empty.
1604 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1608 func_check is_not_empty
= 1 "$@";
1611 eval "${return_no}";
1613 eval "${return_yes}";
1617 ########################################################################
1618 # is_not_equal (<string1> <string2>)
1620 # Test whether `string1' differs from `string2'.
1626 func_check is_not_equal
= 2 "$@";
1627 if is_equal
"$1" "$2";
1629 eval "${return_no}";
1631 eval "${return_yes}";
1635 ########################################################################
1636 # is_not_file (<filename>)
1638 # Test whether `name' is a not readable file.
1640 # Arguments : >=1 (empty allowed), more args are ignored
1644 func_check is_not_file
'>=' 1 "$@";
1647 eval "${return_no}";
1649 eval "${return_yes}";
1653 ########################################################################
1654 # is_not_prog (<name>)
1656 # Verify that arg is a not program in $PATH.
1658 # Arguments : >=1 (empty allowed)
1659 # more args are ignored, this allows to specify progs with arguments
1663 func_check is_not_prog
'>=' 1 "$@";
1664 if where
"$1" >${_NULL_DEV};
1666 eval "${return_no}";
1668 eval "${return_yes}";
1672 ########################################################################
1673 # is_not_writable (<name>)
1675 # Test whether `name' is a not a writable file or directory.
1677 # Arguments : >=1 (empty allowed), more args are ignored
1681 func_check is_not_writable
'>=' 1 "$@";
1682 if is_writable
"$1";
1684 eval "${return_no}";
1686 eval "${return_yes}";
1690 ########################################################################
1691 # is_not_yes (<string>)
1693 # Test whether `string' is not "yes".
1699 func_check is_not_yes
= 1 "$@";
1702 eval "${return_no}";
1704 eval "${return_yes}";
1708 ########################################################################
1711 # Determine whether arg is a program in $PATH
1713 # Arguments : >=0 (empty allowed)
1714 # more args are ignored, this allows to specify progs with arguments
1718 func_check is_prog
'>=' 0 "$@";
1721 eval "${return_no}";
1724 if where
"$1" >${_NULL_DEV};
1726 eval "${return_yes}";
1730 eval "${return_no}";
1734 ########################################################################
1735 # is_writable (<name>)
1737 # Test whether `name' is a writable file or directory.
1739 # Arguments : >=1 (empty allowed), more args are ignored
1743 func_check is_writable
'>=' 1 "$@";
1748 eval "${return_yes}";
1751 eval "${return_no}";
1755 ########################################################################
1758 # Test whether `string' has value "yes".
1761 # Return : `0' if arg1 is `yes', `1' otherwise.
1765 func_check is_yes
= 1 "$@";
1766 if is_equal
"$1" 'yes';
1768 eval "${return_yes}";
1770 eval "${return_no}";
1774 ########################################################################
1777 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1779 # Globals: $_DEBUG_LM
1781 # Defined in section `Debugging functions'.
1784 ########################################################################
1787 # Clean exit without an error.
1796 ########################################################################
1797 landmark
'6: list_*()';
1798 ########################################################################
1800 # `list' is an object class that represents an array or list. Its
1801 # data consists of space-separated single-quoted elements. So a list
1802 # has the form "'first' 'second' '...' 'last'". See list_append() for
1803 # more details on the list structure. The array elements of `list'
1804 # can be get by `set -- $list`.
1807 ########################################################################
1808 # list_append (<list> <element>...)
1811 # <list>: a variable name for a list of single-quoted elements
1812 # <element>: some sequence of characters.
1813 # Output: none, but $<list> is set to
1814 # if <list> is empty: "'<element>' '...'"
1815 # otherwise: "$list '<element>' ..."
1819 func_check list_append
'>=' 2 "$@";
1824 eval _list
='"${'$1'}"';
1830 # escape each single quote by replacing each
1831 # "'" (squote) by "'\''" (squote bslash squote squote);
1832 # note that the backslash must be doubled in the following `sed'
1833 _element
="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')";
1842 if obj _list is_empty
;
1844 _list
="'${_element}'";
1846 _list
="${_list} '${_element}'";
1849 eval "${_name}"='"${_list}"';
1850 eval "${return_ok}";
1854 ########################################################################
1855 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1857 # Transform command line arguments into a normalized form.
1859 # Options, option arguments, and file parameters are identified and
1860 # output each as a single-quoted argument of its own. Options and
1861 # file parameters are separated by a '--' argument.
1864 # <pre_name>: common part of a set of 4 environment variable names:
1865 # $<pre_name>_SHORT_NA: list of short options without an arg.
1866 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1867 # $<pre_name>_LONG_NA: list of long options without an arg.
1868 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1869 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1870 # the content of a variable, or direct arguments.
1872 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1875 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1876 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1877 # none-empty option lists, this will result in printing:
1878 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1880 # Use this function in the following way:
1881 # eval set -- "$(args_norm PRE_NAME "$@")";
1882 # while test "$1" != '--'; do
1889 # # all positional parameters ("$@") left are file name parameters.
1893 func_check list_from_cmdline
'>=' 1 "$@";
1901 _short_n
="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1902 _short_a
="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1903 _long_n
="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1904 _long_a
="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1905 if obj _short_n is_empty
;
1907 error
'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1909 if obj _short_a is_empty
;
1911 error
'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1913 if obj _long_n is_empty
;
1915 error
'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1917 if obj _long_a is_empty
;
1919 error
'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1922 _fn
='list_from_cmdline():'; # for error messages
1926 eval "${return_ok}";
1930 while test "$#" -ge 1;
1937 # delete leading '--';
1938 _opt
="$(echo -n "${_arg}" | sed -e 's/^..//')";
1939 if list_has _long_n
"${_opt}";
1941 # long option, no argument
1942 list_append _result
"--${_opt}";
1945 # test on `--opt=arg'
1946 if string_contains
"${_opt}" '=';
1948 # extract option by deleting from the first '=' to the end
1949 _lopt
="$(echo -n "${_opt}" | sed -e 's/=.*$//')";
1950 if list_has _long_a
"${_lopt}";
1952 # get the option argument by deleting up to first `='
1953 _optarg
="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')";
1954 list_append _result
"--${_lopt}" "${_optarg}";
1958 if list_has _long_a
"${_opt}";
1960 # long option with argument
1963 error
"${_fn} no argument for option --${_opt}."
1965 list_append _result
"--${_opt}" "$1";
1969 error
"${_fn} --${_opt} is not an option."
1971 -?
*) # short option (cluster)
1972 # delete leading `-';
1973 _rest
="$(echo -n "${_arg}" | sed -e 's/^-//')";
1974 while obj _rest is_not_empty
;
1976 # get next short option from cluster (first char of $_rest)
1977 _optchar
="$(echo -n "${_rest}" | sed -e 's/^\(.\).*$/\1/')";
1978 # remove first character from ${_rest};
1979 _rest
="$(echo -n "${_rest}" | sed -e 's/^.//')";
1980 if list_has _short_n
"${_optchar}";
1982 list_append _result
"-${_optchar}";
1984 elif list_has _short_a
"${_optchar}";
1986 if obj _rest is_empty
;
1990 list_append _result
"-${_optchar}" "$1";
1995 "${_fn}"' no argument for option -'"${_optchar}."
1997 else # rest is the argument
1998 list_append _result
"-${_optchar}" "${_rest}";
2003 error
"${_fn} unknown option -${_optchar}."
2008 # Here, $_arg is not an option, so a file parameter.
2009 list_append _fparams
"${_arg}";
2011 # Ignore the strange option handling of $POSIXLY_CORRECT to
2012 # end option parsing after the first file name argument. To
2013 # reuse it, do a `break' here if $POSIXLY_CORRECT is
2018 list_append _result
'--';
2019 if obj _fparams is_not_empty
;
2021 _result
="${_result} ${_fparams}";
2025 list_append _result
"$@";
2028 eval "${return_ok}";
2029 } # list_from_cmdline()
2032 ########################################################################
2033 # list_from_split (<string> <separator>)
2035 # In <string>, escape all white space characters and replace each
2036 # <separator> by space.
2038 # Arguments: 2: a <string> that is to be split into parts divided by
2040 # Output: the resulting list string
2044 func_check list_from_split
= 2 "$@";
2047 # precede each space or tab by a backslash `\' (doubled for `sed')
2048 _s
="$(echo -n "$1" | sed -e 's/\(['"${_SPACE}${_TAB}"']\)/\\\1/g')";
2050 # replace split character of string by the list separator ` ' (space).
2052 /) # cannot use normal `sed' separator
2053 echo -n "${_s}" |
sed -e '\|.*|s|'"$2"'| |g';
2055 ?
) # use normal `sed' separator
2056 echo -n "${_s}" |
sed -e 's/'"$2"'/ /g';
2059 error
'list_from_split(): separator must be a single character.';
2062 eval "${return_ok}";
2066 ########################################################################
2069 # Check whether <list> is a space-separated list of '-quoted elements.
2071 # If the test fails an error is raised.
2072 # If the test succeeds the argument is echoed.
2075 # A list has the form "'first' 'second' '...' 'last'". So it has a
2076 # leading and a final quote and the elements are separated by "' '"
2077 # constructs. If these are all removed there should not be any
2078 # unescaped single-quotes left. Watch out for escaped single
2079 # quotes; they have the form '\'' (sq bs sq sq).
2082 # Output: the argument <list> unchanged, if the check succeeded.
2086 func_check list_get
= 1 "$@";
2088 eval _list
='"${'$1'}"';
2089 # remove leading and final space characters
2090 _list
="$(echo -n "${_list}" | \
2091 sed -e 's/^['"${_SPACE}${_TAB}"']*//' | \
2092 sed -e 's/['"${_SPACE}${_TAB}"']*$//')";
2095 eval "${return_ok}";
2099 eval "${return_ok}";
2102 error
"list_get(): bad list: $1"
2105 eval "${return_ok}";
2109 ########################################################################
2110 # list_has (<var_name> <element>)
2113 # <var_name>: a variable name for a list of single-quoted elements
2114 # <element>: some sequence of characters.
2116 # if <list> is empty: "'<element>' '...'"
2117 # otherwise: "list '<element>' ..."
2121 func_check list_has
= 2 "$@";
2122 eval _list
='"${'$1'}"';
2123 if obj _list is_empty
;
2125 eval "${return_no}";
2129 \'*\') _element
="$2"; ;;
2130 *) _element
="'$2'"; ;;
2132 if string_contains
"${_list}" "${_element}";
2134 eval "${return_yes}";
2136 eval "${return_no}";
2138 eval "${return_ok}";
2142 ########################################################################
2143 # list_has_not (<list> <element>)
2146 # <list>: a space-separated list of single-quoted elements.
2147 # <element>: some sequence of characters.
2149 # if <list> is empty: "'<element>' '...'"
2150 # otherwise: "<list> '<element>' ..."
2154 func_check list_has_not
= 2 "$@";
2155 eval _list
='"${'$1'}"';
2156 if obj _list is_empty
;
2158 eval "${return_yes}";
2162 \'*\') _element
="$2"; ;;
2163 *) _element
="'$2'"; ;;
2165 if string_contains
"${_list}" "${_element}";
2167 eval "${return_no}";
2169 eval "${return_yes}";
2171 eval "${return_ok}";
2175 ########################################################################
2176 landmark
'7: man_*()';
2177 ########################################################################
2179 ########################################################################
2180 # man_do_filespec (<filespec>)
2182 # Print suitable man page(s) for filespec to $_TMP_CAT.
2185 # <filespec>: argument of the form `man:name.section', `man:name',
2186 # `man:name(section)', `name.section', `name'.
2188 # Globals : $_OPT_ALL
2191 # Return : `0' if man page was found, `1' else.
2193 # Only called from do_fileargs(), checks on $MANPATH and
2194 # $_MAN_ENABLE are assumed.
2198 func_check man_do_filespec
= 1 "$@";
2207 if obj _MAN_PATH is_empty
;
2209 eval "${return_bad}";
2213 eval "${return_bad}";
2219 */*) # not a man spec when it contains '/'
2220 eval "${return_bad}";
2222 man
:?
*\
(?
*\
)) # man:name(section)
2223 _name
="$(echo -n "${_spec}" \
2224 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2225 _section
="$(echo -n "${_spec}" \
2226 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2228 man
:?
*.
[0-9on]) # man:name.section
2229 _name
="$(echo -n "${_spec}" \
2230 | sed -e 's/^man:\(..*\)\..$/\1/')";
2231 _section
="$(echo -n "${_spec}" \
2232 | sed -e 's/^.*\(.\)$/\1/')";
2235 _name
="$(echo -n "${_spec}" | sed -e 's/^man://')";
2237 ?
*\
(?
*\
)) # name(section)
2238 _name
="$(echo -n "${_spec}" \
2239 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2240 _section
="$(echo -n "${_spec}" \
2241 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2243 ?
*.
[0-9on]) # name.section
2244 _name
="$(echo -n "${_spec}" \
2245 | sed -e 's/^\(..*\)\..$/\1/')";
2246 _section
="$(echo -n "${_spec}" \
2247 | sed -e 's/^.*\(.\)$/\1/')";
2250 _name
="${_filespec}";
2253 if obj _name is_empty
;
2255 eval "${return_bad}";
2258 if obj _section is_empty
;
2260 eval set -- "${_MAN_AUTO_SEC}";
2263 if man_search_section
"${_name}" "$s";
2265 if obj _MAN_ALL is_yes
;
2269 eval "${return_good}";
2274 if man_search_section
"${_name}" "${_section}";
2276 eval "${return_good}";
2278 eval "${return_bad}";
2281 if obj _MAN_ALL is_yes
&& is_yes
"${_got_one}";
2283 eval "${return_good}";
2285 eval "${return_bad}";
2286 } # man_do_filespec()
2289 ########################################################################
2290 # man_register_file (<file> <name> [<section>])
2292 # Write a found man page file and register the title element.
2294 # Arguments: 1, 2, or 3; maybe empty
2299 func_check man_register_file
'>=' 2 "$@";
2303 error
"man_register_file() expects 2 or 3 arguments.";
2308 error
'man_register_file(): file name is empty';
2313 register_title
"man:$2";
2314 eval "${return_ok}";
2317 register_title
"$2.$3";
2318 eval "${return_ok}";
2321 eval "${return_ok}";
2325 ########################################################################
2326 # man_search_section (<name> <section>)
2328 # Retrieve man pages.
2331 # Globals : $_MAN_PATH, $_MAN_EXT
2332 # Return : 0 if found, 1 otherwise
2334 man_search_section
()
2336 func_check man_search_section
= 2 "$@";
2345 if obj _MAN_PATH is_empty
;
2347 eval "${return_bad}";
2351 eval "${return_bad}";
2355 eval "${return_bad}";
2359 eval set -- "$(path_split "${_MAN_PATH}")";
2361 if obj _MAN_EXT is_empty
;
2365 _dir
="$(dirname_append "$d" "man
${_section}")";
2368 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2369 for f
in $
(echo -n ${_prefix}*);
2373 if is_yes
"${_got_one}";
2376 elif obj _MAN_ALL is_yes
;
2378 man_register_file
"$f" "${_name}";
2380 man_register_file
"$f" "${_name}" "${_section}";
2381 eval "${return_good}";
2390 # check for directory name having trailing extension
2393 _dir
="$(dirname_append $d man${_section}${_ext})";
2396 _prefix
="$(dirname_append "${_dir}" "${_name}.${_section}")";
2397 for f
in ${_prefix}*;
2401 if is_yes
"${_got_one}";
2404 elif obj _MAN_ALL is_yes
;
2406 man_register_file
"$f" "${_name}";
2408 man_register_file
"$f" "${_name}" "${_section}";
2409 eval "${return_good}";
2416 # check for files with extension in directories without extension
2419 _dir
="$(dirname_append "$d" "man
${_section}")";
2422 _prefix
="$(dirname_append "${_dir}" \
2423 "${_name}.${_section}${_ext}")";
2424 for f
in ${_prefix}*;
2428 if is_yes
"${_got_one}";
2431 elif obj _MAN_ALL is_yes
;
2433 man_register_file
"$f" "${_name}";
2435 man_register_file
"$f" "${_name}" "${_section}";
2436 eval "${return_good}";
2444 if obj _MAN_ALL is_yes
&& is_yes
"${_got_one}";
2446 eval "${return_good}";
2448 eval "${return_bad}";
2449 } # man_search_section()
2452 ########################################################################
2455 # Setup the variables $_MAN_* needed for man page searching.
2458 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2459 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2460 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2461 # $_MAN_SEC, $_MAN_ALL
2462 # in/out: $_MAN_ENABLE
2464 # The precedence for the variables related to `man' is that of GNU
2467 # $LANG; overridden by
2468 # $LC_MESSAGES; overridden by
2469 # $LC_ALL; this has the same precedence as
2470 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2471 # $MANOPT; overridden by
2472 # the groffer command line options.
2476 func_check main_man_setup
= 0 "$@";
2479 if obj _MAN_IS_SETUP is_yes
;
2481 eval "${return_ok}";
2483 _MAN_IS_SETUP
='yes';
2485 if obj _MAN_ENABLE is_not_yes
;
2487 eval "${return_ok}";
2490 # determine basic path for man pages
2491 _MAN_PATH
="$(get_first_essential \
2492 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2493 if obj _MAN_PATH is_empty
;
2495 manpath_set_from_path
;
2497 _MAN_PATH
="$(path_clean "${_MAN_PATH}")";
2499 if obj _MAN_PATH is_empty
;
2501 if is_prog
'manpath';
2503 _MAN_PATH
="$(manpath 2>${_NULL_DEV})"; # not always available
2506 if obj _MAN_PATH is_empty
;
2509 eval "${return_ok}";
2512 _MAN_ALL
="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2513 if obj _MAN_ALL is_empty
;
2518 _MAN_SYS
="$(get_first_essential \
2519 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2520 _lang
="$(get_first_essential \
2521 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2528 _MAN_LANG
="${_lang}";
2532 _MAN_LANG
="${_lang}";
2533 # get first two characters of $_lang
2534 _MAN_LANG2
="$(echo -n "${_lang}" | sed -e 's/^\(..\).*$/\1/')";
2537 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2539 manpath_add_lang_sys
; # this is very slow
2541 _MAN_SEC
="$(get_first_essential \
2542 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2543 if obj _MAN_PATH is_empty
;
2546 eval "${return_ok}";
2549 _MAN_EXT
="$(get_first_essential \
2550 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2551 eval "${return_ok}";
2555 ########################################################################
2556 landmark
'8: manpath_*()';
2557 ########################################################################
2559 ########################################################################
2560 # manpath_add_lang_sys ()
2562 # Add language and operating system specific directories to man path.
2567 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2568 # list of names of operating systems.
2569 # $_MAN_LANG and $_MAN_LANG2: each a single name
2570 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2571 # separated list of directories.
2573 manpath_add_lang_sys
()
2575 func_check manpath_add_lang_sys
= 0 "$@";
2578 if obj _MAN_PATH is_empty
;
2580 eval "${return_ok}";
2582 # twice test both sys and lang
2583 eval set -- "$(path_split "${_MAN_PATH}")";
2586 do # loop on man path directories
2587 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2589 eval set -- "$(path_split "${_mp}")";
2591 do # loop on man path directories
2592 _mp
="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2594 _MAN_PATH
="$(path_chop "${_mp}")";
2595 eval "${return_ok}";
2599 _manpath_add_lang_sys_single
()
2601 # To the directory in $1 append existing sys/lang subdirectories
2602 # Function is necessary to split the OS list.
2604 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2605 # argument: 2: `man_path' and `dir'
2606 # output: colon-separated path of the retrieved subdirectories
2608 func_check _manpath_add_lang_sys_single
= 2 "$@";
2612 eval set -- "$(list_from_split "${_MAN_SYS}" ',')";
2613 for d
in "$@" "${_MAN_LANG}" "${_MAN_LANG2}";
2615 _dir
="$(dirname_append "${_parent}" "$d")";
2616 if obj _res path_not_contains
"${_dir}" && obj _dir is_dir
;
2618 _res
="${_res}:${_dir}";
2621 if path_not_contains
"${_res}" "${_parent}";
2623 _res
="${_res}:${_parent}";
2625 path_chop
"${_res}";
2628 # end manpath_add_lang_sys ()
2631 ########################################################################
2632 # manpath_set_from_path ()
2634 # Determine basic search path for man pages from $PATH.
2636 # Return: `0' if a valid man path was retrieved.
2642 manpath_set_from_path
()
2644 func_check manpath_set_from_path
= 0 "$@";
2652 # get a basic man path from $PATH
2653 if obj PATH is_not_empty
;
2655 eval set -- "$(path_split "${PATH}")";
2658 # delete the final `/bin' part
2659 _base
="$(echo -n "$d" | sed -e '\|.*|s|//*bin/*$||')";
2660 for e
in /share
/man
/man
;
2662 _mandir
="${_base}$e";
2663 if test -d "${_mandir}" && test -r "${_mandir}";
2665 _manpath
="${_manpath}:${_mandir}";
2671 # append some default directories
2672 for d
in /usr
/local
/share
/man
/usr
/local
/man \
2673 /usr
/share
/man
/usr
/man \
2674 /usr
/X11R
6/man
/usr
/openwin
/man \
2675 /opt
/share
/man
/opt
/man \
2676 /opt
/gnome
/man
/opt
/kde
/man
;
2678 if obj _manpath path_not_contains
"$d" && obj d is_dir
;
2680 _manpath
="${_manpath}:$d";
2684 _MAN_PATH
="${_manpath}";
2685 eval "${return_ok}";
2686 } # manpath_set_from_path()
2689 ########################################################################
2690 landmark
'9: obj_*()';
2691 ########################################################################
2693 ########################################################################
2694 # obj (<object> <call_name> <arg>...)
2696 # This works like a method (object function) call for an object.
2697 # Run "<call_name> $<object> <arg> ...".
2699 # The first argument represents an object whose data is given as first
2700 # argument to <call_name>().
2703 # <object>: variable name
2704 # <call_name>: a program or function name
2708 func_check obj
'>=' 2 "$@";
2713 error
"obj(): function name is empty."
2717 eval arg1
='"${'$1'}"';
2720 eval "${func}"' "${arg1}" "$@"';
2724 ########################################################################
2725 # obj_data (<object>)
2727 # Print the data of <object>, i.e. the content of $<object>.
2728 # For possible later extensions.
2731 # <object>: a variable name
2732 # Output: the data of <object>
2736 func_check obj
'=' 1 "$@";
2739 error
"obj_data(): object name is empty."
2741 eval echo -n '"${'$1'}"';
2745 ########################################################################
2746 # obj_from_output (<object> <call_name> <arg>...)
2748 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2749 # function call to a global variable.
2752 # <object>: a variable name
2753 # <call_name>: the name of a function or program
2754 # <arg>: optional argument to <call_name>
2759 func_check obj_from_output
'>=' 2 "$@";
2763 error
"res(): variable name is empty.";
2766 error
"res(): function name is empty."
2771 eval "${result_name}"'="$('"$@"')"';
2775 ########################################################################
2776 # obj_set (<object> <data>)
2778 # Set the data of <object>, i.e. call "$<object>=<data>".
2781 # <object>: a variable name
2787 func_check obj_set
'=' 2 "$@";
2790 error
"obj_set(): object name is empty."
2796 ########################################################################
2797 # path_chop (<path>)
2799 # Remove unnecessary colons from path.
2801 # Argument: 1, a colon separated path.
2802 # Output: path without leading, double, or trailing colons.
2806 func_check path_chop
= 1 "$@";
2809 # replace multiple colons by a single colon `:'
2810 # remove leading and trailing colons
2811 echo -n "$1" |
sed -e 's/:::*/:/g' |
2814 eval "${return_ok}";
2818 ########################################################################
2819 # path_clean (<path>)
2821 # Remove non-existing directories from a colon-separated list.
2823 # Argument: 1, a colon separated path.
2824 # Output: colon-separated list of existing directories.
2828 func_check path_clean
= 1 "$@";
2833 if is_not_equal
"$#" 1;
2835 error
'path_clean() needs 1 argument.';
2838 eval set -- "$(path_split "${_arg}")";
2842 if obj i is_not_empty \
2843 && obj _res path_not_contains
"$i" \
2847 ?
*/) _res
="${_res}$(dirname_chop "$i")"; ;;
2848 *) _res
="${_res}:$i";
2852 if path_chop
"${_res}";
2854 eval "${return_ok}";
2856 eval "${return_badk}";
2861 ########################################################################
2862 # path_contains (<path> <dir>)
2864 # Test whether `dir' is contained in `path', a list separated by `:'.
2866 # Arguments : 2 arguments.
2867 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2871 func_check path_contains
= 2 "$@";
2874 eval "${return_yes}";
2877 eval "${return_no}";
2880 eval "${return_ok}";
2884 ########################################################################
2885 # path_not_contains (<path> <dir>)
2887 # Test whether `dir' is not contained in colon separated `path'.
2889 # Arguments : 2 arguments.
2893 func_check path_not_contains
= 2 "$@";
2894 if path_contains
"$1" "$2";
2896 eval "${return_no}";
2898 eval "${return_yes}";
2900 eval "${return_ok}";
2904 ########################################################################
2905 # path_split (<path>)
2907 # In `path' escape white space and replace each colon by a space.
2909 # Arguments: 1: a colon-separated path
2910 # Output: the resulting list, process with `eval set --'
2914 func_check path_split
= 1 "$@";
2915 list_from_split
"$1" ':';
2916 eval "${return_ok}";
2920 ########################################################################
2921 landmark
'10: register_*()';
2922 ########################################################################
2924 ########################################################################
2925 # register_file (<filename>)
2927 # Write a found file and register the title element.
2929 # Arguments: 1: a file name
2934 func_check register_file
= 1 "$@";
2937 error
'register_file(): file name is empty';
2939 if is_equal
"$1" '-';
2941 to_tmp
"${_TMP_STDIN}";
2945 register_title
"$(base_name "$1")";
2947 eval "${return_ok}";
2951 ########################################################################
2952 # register_title (<filespec>)
2954 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2956 # Globals: $_REGISTERED_TITLE (rw)
2960 func_check register_title
= 1 "$@";
2964 eval "${return_ok}";
2966 _title
="$(base_name "$1")"; # remove directory part
2968 # remove extension `.gz'
2969 _title
="$(echo -n "${_title}" | sed -e 's/\.gz$//')";
2970 # remove extension `.Z'
2971 _title
="$(echo -n "${_title}" | sed -e 's/\.Z$//')";
2973 if obj _title is_empty
;
2975 eval "${return_ok}";
2977 _REGISTERED_TITLE
="${_REGISTERED_TITLE} ${_title}";
2978 eval "${return_ok}";
2982 ########################################################################
2985 # Reset the variables that can be affected by options to their default.
2988 # Defined in section `Preset' after the rudimentary shell tests.
2991 ########################################################################
2994 # Store standard input to temporary file (with decompression).
2996 if obj _HAS_COMPRESSION is_yes
;
3001 func_check save_stdin
= 0 "$@";
3002 _f
="${_TMP_DIR}"/INPUT
;
3004 catz
"${_f}" >"${_TMP_STDIN}";
3006 eval "${return_ok}";
3011 func_check save_stdin
= 0 "$@";
3012 cat >"${_TMP_STDIN}";
3013 eval "${return_ok}";
3018 ########################################################################
3019 landmark
'11: stack_*()';
3020 ########################################################################
3022 ########################################################################
3023 # string_contains (<string> <part>)
3025 # Test whether `part' is contained in `string'.
3027 # Arguments : 2 text arguments.
3028 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3032 func_check string_contains
= 2 "$@";
3035 eval "${return_yes}";
3038 eval "${return_no}";
3041 eval "${return_ok}";
3045 ########################################################################
3046 # string_not_contains (<string> <part>)
3048 # Test whether `part' is not substring of `string'.
3050 # Arguments : 2 text arguments.
3051 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3053 string_not_contains
()
3055 func_check string_not_contains
= 2 "$@";
3056 if string_contains
"$1" "$2";
3058 eval "${return_no}";
3060 eval "${return_yes}";
3062 eval "${return_ok}";
3066 ########################################################################
3067 landmark
'12: tmp_*()';
3068 ########################################################################
3070 ########################################################################
3073 # output the temporary cat file (the concatenation of all input)
3081 ########################################################################
3082 # tmp_create (<suffix>?)
3084 # create temporary file
3086 # It's safe to use the shell process ID together with a suffix to
3087 # have multiple temporary files.
3089 # Output : name of created file
3093 func_check tmp_create
'<=' 1 "$@";
3095 # the output file does not have `,' as first character
3096 _tmp
="${_TMP_DIR}/,$1";
3098 echo -n "${_tmp}"; # output file name
3099 eval "${return_ok}";
3103 ########################################################################
3104 # to_tmp (<filename>)
3106 # print file (decompressed) to the temporary cat file
3110 func_check to_tmp
= 1 "$@";
3113 if obj _OPT_LOCATION is_yes
;
3117 if obj _OPT_WHATIS is_yes
;
3119 what_is
"$1" >>"${_TMP_CAT}";
3121 catz
"$1" >>"${_TMP_CAT}";
3124 error
"to_tmp(): could not read file \`$1'.";
3126 eval "${return_ok}";
3130 ########################################################################
3133 # disable trap on all exit codes ($_ALL_EXIT)
3136 # Globals: $_ALL_EXIT
3140 func_check trap_clean
= 0 "$@";
3142 for i
in ${_ALL_EXIT};
3144 trap "" "$i" 2>${_NULL_DEV} || true
;
3146 eval "${return_ok}";
3150 ########################################################################
3151 # trap_set (<functionname>)
3153 # call function on all exit codes ($_ALL_EXIT)
3155 # Arguments: 1 (name of a shell function)
3156 # Globals: $_ALL_EXIT
3160 func_check trap_set
= 1 "$@";
3162 for i
in ${_ALL_EXIT};
3164 trap "$1" "$i" 2>${_NULL_DEV} || true
;
3166 eval "${return_ok}";
3170 ########################################################################
3173 # print usage information to stderr; for groffer option --help.
3177 func_check usage
= 0 "$@";
3180 echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';
3183 Display roff files, standard input, and/or Unix manual pages with a X
3184 Window viewer or in several text modes. All input is decompressed
3185 on-the-fly with all formats that gzip can handle.
3187 "filespec" is one of
3188 "filename" name of a readable file
3189 "-" for standard input
3190 "man:name.n" man page "name" in section "n"
3191 "man:name" man page "name" in first section found
3192 "name.n" man page "name" in section "n"
3193 "name" man page "name" in first section found
3194 and some more (see groffer(1) for details).
3196 -h --help print this usage message.
3197 -Q --source output as roff source.
3198 -T --device=name pass to groff using output device "name".
3199 -v --version print version information.
3200 -V display the groff execution pipe instead of formatting.
3201 -X --X --x display with "gxditview" using groff -X.
3202 -Z --ditroff --intermediate-output
3203 generate groff intermediate output without
3204 post-processing and viewing, like groff -Z.
3205 All other short options are interpreted as "groff" formatting options.
3207 The most important groffer long options are
3209 --apropos=name start man's "apropos" program for "name".
3211 "apropos" for "name" in man's data sections 4, 5, 7.
3212 --apropos-devel=name
3213 "apropos" for "name" in development sections 2, 3, 9.
3214 --apropos-progs=name
3215 "apropos" for "name" in man's program sections 1, 6, 8.
3216 --auto choose mode automatically from the default mode list.
3217 --default reset all options to the default value.
3218 --default-modes=mode1,mode2,...
3219 set sequence of automatically tried modes.
3220 --dvi display in a viewer for TeX device independent format.
3221 --dvi-viewer choose the viewer program for dvi mode.
3222 --groff process like groff, disable viewing features.
3223 --help display this helping output.
3224 --html --www display in a web browser.
3225 --html-viewer choose the web browser for www mode.
3226 --man check file parameters first whether they are man pages.
3227 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3228 choose display mode.
3229 --no-man disable man-page facility.
3230 --pager=program preset the paging program for tty mode.
3231 --pdf display in a PDF viewer.
3232 --pdf-viewer choose the viewer program for pdf mode.
3233 --ps display in a Postscript viewer.
3234 --ps-viewer choose the viewer program for ps mode.
3235 --shell specify shell under which to run this program.
3236 --text output in a text device without a pager.
3237 --tty display with a pager on text terminal even when in X.
3238 --www-viewer same as --html-viewer
3239 --x-viewer choose viewer program for x mode (X mode).
3240 --X-viewer same as "--xviewer".
3242 The usual X Windows toolkit options transformed into GNU long options
3243 --background=color, --bd=size, --bg=color, --bordercolor=color,
3244 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3245 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3246 --resolution=dpi, --rv, --title=text, --xrm=resource
3248 Long options of GNU "man"
3249 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3250 --local-file=name, --location, --manpath=dir1:dir2:...,
3251 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3254 eval "${return_ok}";
3258 ########################################################################
3261 # print version information to stderr
3265 func_check version
= 0 "$@";
3266 echo2
"${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3267 # also display groff's version, but not the called subprograms
3268 groff -v 2>&1 |
sed -e '/^ *$/q' |
sed -e '1s/^/is part of /' >&2;
3272 ########################################################################
3273 # warning (<string>)
3275 # Print warning to stderr
3279 echo2
"warning: $*";
3283 ########################################################################
3284 # what_is (<filename>)
3286 # Interpret <filename> as a man page and display its `whatis'
3287 # information as a fragment written in the groff language.
3291 func_check what_is
= 1 "$@";
3294 if is_not_file
"$1";
3296 error
"what_is(): argument is not a readable file."
3298 _dot
='^\.['"${_SPACE}${_TAB}"']*';
3303 # grep the line containing `.TH' macro, if any
3304 _res
="$(catz "$1" | sed -e '/'"${_dot}"'TH /p
3306 if obj _res is_not_empty
;
3307 then # traditional man style
3308 # get the text between the first and the second `.SH' macro, by
3309 # - delete up to first .SH;
3310 # - of this, print everything up to next .SH, and delete the rest;
3311 # - of this, delete the final .SH line;
3312 catz
"$1" |
sed -e '1,/'"${_dot}"'SH/d' \
3313 |
sed -e '1,/'"${_dot}"'SH/p
3315 |
sed -e '/'"${_dot}"'SH/d';
3316 eval "${return_ok}";
3318 # grep the line containing `.Dd' macro, if any
3319 _res
="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p
3321 if obj _res is_not_empty
;
3322 then # BSD doc style
3323 # get the text between the first and the second `.Nd' macro, by
3324 # - delete up to first .Nd;
3325 # - of this, print everything up to next .Nd, and delete the rest;
3326 # - of this, delete the final .Nd line;
3327 catz
"$1" |
sed -e '1,/'"${_dot}"'Nd/d' \
3328 |
sed -e '1,/'"${_dot}"'Nd/p
3330 |
sed -e '/'"${_dot}"'Nd/d';
3331 eval "${return_ok}";
3333 echo 'is not a man page.';
3334 eval "${return_bad}";
3338 ########################################################################
3341 # Output path of a program if in $PATH.
3343 # Arguments : >=1 (empty allowed)
3344 # more args are ignored, this allows to specify progs with arguments
3345 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3349 func_check where
'>=' 1 "$@";
3354 if obj _arg is_empty
;
3356 eval "${return_bad}";
3360 if test -f "${_arg}" && test -x "${_arg}";
3362 eval "${return_ok}";
3364 eval "${return_bad}";
3368 eval set -- "$(path_split "${PATH}")";
3372 */) _file
=${p}${_arg}; ;;
3373 *) _file
=${p}/${_arg}; ;;
3375 if test -f "${_file}" && test -x "${_file}";
3378 eval "${return_ok}";
3381 eval "${return_bad}";
3385 ########################################################################
3387 ########################################################################
3389 # The main area contains the following parts:
3390 # - main_init(): initialize temporary files and set exit trap
3391 # - main_parse_MANOPT(): parse $MANOPT
3392 # - main_parse_args(): argument parsing
3393 # - main_set_mode (): determine the display mode
3394 # - main_do_fileargs(): process filespec arguments
3395 # - main_set_resources(): setup X resources
3396 # - main_display(): do the displaying
3397 # - main(): the main function that calls all main_*()
3399 # These parts are implemented as functions, being defined below in the
3400 # sequence they are called in the main() function.
3403 #######################################################################
3406 # set exit trap and create temporary files
3408 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3410 landmark
'13: main_init()';
3413 func_check main_init
= 0 "$@";
3414 # call clean_up() on any signal
3417 # create temporary directory
3420 for d
in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3421 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.';
3423 if obj d is_empty || obj d is_not_dir || obj d is_not_writable
;
3435 _TMP_DIR
="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
3436 while obj _TMP_DIR is_existing
;
3438 rm -f -r "${_TMP_DIR}" 2>${_NULL_DEV};
3439 if obj _TMP_DIR is_existing
;
3441 # $_TMP_DIR could not be removed
3442 _TMP_DIR
="${_TMP_DIR}"'X';
3445 # $_TMP_DIR was removed
3449 mkdir
"${_TMP_DIR}";
3450 if is_not_equal
"$?" 0;
3452 if obj _TMP_DIR is_existing
;
3454 rm -f -r "${_TMP_DIR}" 2>${_NULL_DEV};
3459 if obj _TMP_DIR is_dir
&& obj _TMP_DIR is_writable
;
3461 # $_TMP_DIR can now be used as temporary directory
3464 if obj _TMP_DIR is_existing
;
3466 rm -f -r "${_TMP_DIR}" 2>${_NULL_DEV};
3472 if obj _TMP_DIR is_empty
;
3474 error
"Couldn't create a directory for storing temporary files.";
3477 _TMP_CAT
="$(tmp_create groffer_cat)";
3478 _TMP_STDIN
="$(tmp_create groffer_input)";
3480 # groffer configuration files
3481 for f
in ${_CONFFILES};
3485 echo '_groffer_opt=""' >>${_TMP_CAT};
3486 # collect the lines starting with a minus
3488 's/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"'/ \
3490 # prepend the collected information to $GROFFER_OPT
3491 echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
3495 _TMP_CAT="$(tmp_create groffer_cat)";
3497 eval "${return_ok}";
3501 ########################################################################
3502 # main_parse_MANOPT ()
3504 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3505 # string; found man arguments can be overwritten by the command line.
3508 # in: $MANOPT, $_OPTS_MANOPT_*
3510 # in/out: $GROFFER_OPT
3512 landmark '14: main_parse_MANOPT
()';
3515 func_check main_parse_MANOPT = 0 "$@";
3519 if obj MANOPT is_not_empty;
3521 MANOPT="$(echo -n "${MANOPT}" | \
3522 sed -e 's
/^
'"${_SPACE}${_SPACE}"'*//')";
3524 if obj MANOPT is_empty;
3526 eval "${return_ok}";
3528 # add arguments in $MANOPT by mapping them to groffer options
3529 eval set -- "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3530 until test "$#" -le 0 || is_equal "$1" '--';
3536 list_append _list '--ascii';
3539 list_append _list '--all';
3546 list_append _list '--debug';
3549 # undo all man options so far
3553 list_append _list '--extension';
3557 list_append _list '--whatis';
3565 # groffer's
--apropos takes an argument
, but man
's does not, so
3570 list_append _list '--local-file';
3573 list_append _list '--locale' "$1";
3577 list_append _list '--systems' "$1";
3581 list_append _list '--manpath' "$1";
3588 -P|--pager|--tty-viewer)
3589 list_append _list '--pager' "$1";
3597 list_append _list '--sections' "$1";
3605 list_append _list '-T' "$1";
3615 -w|--where|--location)
3616 list_append _list '--location';
3619 list_append _list '-Z' "$1";
3622 # ignore all other options
3625 # append the 2 lists in $_list and $GROFFER_OPT to $GROFFER_OPT
3626 if obj GROFFER_OPT is_empty;
3628 GROFFER_OPT="${_list}";
3629 elif obj _list is_not_empty;
3631 GROFFER_OPT="${_list} ${GROFFER_OPT}";
3633 eval "${return_ok}";
3634 } # main_parse_MANOPT()
3637 ########################################################################
3638 # main_parse_args (<command_line_args>*)
3640 # Parse arguments; process options and filespec parameters
3642 # Arguments: pass the command line arguments unaltered.
3645 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3647 landmark '15: main_parse_args
()';
3650 func_check main_parse_args '>=' 0 "$@";
3662 eval set -- "${GROFFER_OPT}" '"$@"';
3664 eval set -- "$(list_from_cmdline _OPTS_CMDLINE "$@")";
3666 # By the call of `eval', unnecessary quoting was removed. So the
3667 # positional shell parameters ($1, $2, ...) are now guaranteed to
3668 # represent an option or an argument to the previous option, if any;
3669 # then a `--' argument for separating options and
3670 # parameters; followed by the filespec parameters if any.
3672 # Note, the existence of arguments to options has already been checked.
3673 # So a check for `$#' or `--' should not be done for arguments.
3675 until test "$#" -le 0 || is_equal
"$1" '--';
3677 _opt
="$1"; # $_opt is fed into the option handler
3684 -Q|
--source) # output source code (`Quellcode').
3687 -T|
--device|
--troff-device) # device; arg
3689 _check_device_with_mode
;
3699 -Z|
--ditroff|
--intermediate-output) # groff intermediate output
3706 # delete leading `-'
3707 _optchar
="$(echo -n "${_opt}" | sed -e 's/^.//')";
3708 if list_has _OPTS_GROFF_SHORT_NA
"${_optchar}";
3710 list_append _ADDOPTS_GROFF
"${_opt}";
3711 elif list_has _OPTS_GROFF_SHORT_ARG
"${_optchar}";
3713 list_append _ADDOPTS_GROFF
"${_opt}" "$1";
3716 error
"Unknown option : \`$1'";
3722 --apropos) # run `apropos'
3728 --apropos-data) # run `apropos' for data sections
3729 apropos_run
"$1" |
grep '^[^(]*([457][^)]*)';
3734 --apropos-devel) # run `apropos' for development sections
3735 apropos_run
"$1" |
grep '^[^(]*([239][^)]*)';
3740 --apropos-progs) # run `apropos' for program sections
3741 apropos_run
"$1" |
grep '^[^(]*([168][^)]*)';
3747 list_append _ADDOPTS_GROFF
'-mtty-char';
3748 if obj _mode is_empty
;
3753 --auto) # the default automatic mode
3756 --bd) # border color for viewers, arg;
3760 --bg|
--backgroud) # background color for viewers, arg;
3764 --bw) # border width for viewers, arg;
3768 --default) # reset variables to default
3771 --default-modes) # sequence of modes in auto mode; arg
3772 _OPT_DEFAULT_MODES
="$1";
3775 --debug) # buggy, only for development
3778 --display) # set X display, arg
3785 --dvi-viewer) # viewer program for dvi mode; arg
3786 _OPT_VIEWER_DVI
="$1";
3789 --extension) # the extension for man pages, arg
3790 _OPT_EXTENSION
="$1";
3793 --fg|
--foreground) # foreground color for viewers, arg;
3797 --fn|
--font) # set font for viewers, arg;
3801 --geometry) # window geometry for viewers, arg;
3808 --html|
--www) # display with web browser
3811 --html-viewer|
--www-viewer) # viewer program for html mode; arg
3812 _OPT_VIEWER_HTML
="$1";
3815 --iconic) # start viewers as icons
3818 --locale) # set language for man pages, arg
3819 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3823 --local-file) # force local files; same as `--no-man'
3827 --location|
--where) # print file locations to stderr
3828 _OPT_LOCATION
='yes';
3830 --man) # force all file params to be man pages
3834 --manpath) # specify search path for man pages, arg
3835 # arg is colon-separated list of directories
3839 --mode) # display mode
3843 auto|
'') # search mode automatically among default
3846 groff) # pass input to plain groff
3849 html|www
) # display with a web browser
3852 dvi
) # display with xdvi viewer
3855 pdf
) # display with PDF viewer
3858 ps
) # display with Postscript viewer
3861 text
) # output on terminal
3864 tty
) # output on terminal
3867 X|x
) # output on X roff viewer
3870 Q|
source) # display source code
3874 error
"unknown mode ${_arg}";
3877 _OPT_MODE
="${_mode}";
3879 --no-location) # disable former call to `--location'
3880 _OPT_LOCATION
='yes';
3882 --no-man) # disable search for man pages
3883 # the same as --local-file
3887 --pager) # set paging program for tty mode, arg
3894 --pdf-viewer) # viewer program for ps mode; arg
3895 _OPT_VIEWER_PDF
="$1";
3901 --ps-viewer) # viewer program for ps mode; arg
3902 _OPT_VIEWER_PS
="$1";
3905 --resolution) # set resolution for X devices, arg
3916 error
"only resoutions of 75 or 100 dpi are supported";
3919 _OPT_RESOLUTION
="${_dpi}";
3924 --sections) # specify sections for man pages, arg
3925 # arg is colon-separated list of section names
3930 # already done during the first run; so ignore the argument
3933 --systems) # man pages for different OS's, arg
3934 # argument is a comma-separated list
3938 --text) # text mode without pager
3941 --title) # title for X viewers; arg
3945 --tty) # tty mode, text with pager
3948 --text-device|
--tty-device) # device for tty mode; arg
3949 _OPT_TEXT_DEVICE
="$1";
3955 --xrm) # pass X resource string, arg;
3956 list_append _OPT_XRM
"$1";
3959 --x-viewer|
--X-viewer) # viewer program for x mode; arg
3964 error
'error on argument parsing : '"\`$*'";
3968 shift; # remove `--' argument
3970 if obj _DEBUG is_not_yes
;
3972 if obj _OPT_DEBUG is_yes
;
3978 # Remaining arguments are file names (filespecs).
3979 # Save them to list $_FILEARGS
3981 then # use "-" for standard input
3985 list_append _FILEARGS
"$@";
3986 if list_has _FILEARGS
'-';
3990 # $_FILEARGS must be retrieved with `eval set -- "$_FILEARGS"'
3991 eval "${return_ok}";
3992 } # main_parse_args()
3994 # Called from main_parse_args() because double `case' is not possible.
3995 # Globals: $_OPT_DEVICE, $_OPT_MODE
3996 _check_device_with_mode
()
3998 func_check _check_device_with_mode
= 0 "$@";
3999 case "${_OPT_DEVICE}" in
4002 eval "${return_ok}";
4006 eval "${return_ok}";
4010 eval "${return_ok}";
4014 eval "${return_ok}";
4016 ascii|cp1047|latin1|utf8
)
4017 if obj _OPT_MODE is_not_equal text
;
4019 _OPT_MODE
=tty
; # default text mode
4021 eval "${return_ok}";
4025 eval "${return_ok}";
4027 *) # unknown device, go to groff mode
4029 eval "${return_ok}";
4032 eval "${return_error}";
4036 ########################################################################
4039 # Determine the display mode.
4042 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4043 # out: $_DISPLAY_MODE
4046 # _get_first_prog (<proglist>)
4048 # Retrieve first argument that represents an existing program in $PATH.
4049 # Local function for main_set_mode().
4051 # Arguments: 1; a comma-separated list of commands (with options),
4054 # Return : `1' if none found, `0' if found.
4055 # Output : the argument that succeded.
4057 landmark
'16: main_set_mode()';
4060 func_check main_set_mode
= 0 "$@";
4067 if obj _OPT_APROPOS is_not_empty
;
4069 apropos
"${_OPT_APROPOS}";
4074 if obj _OPT_APROPOS_DATA is_not_empty
;
4076 apropos
"$@" |
grep '^[^(]*([457])';
4081 if obj _OPT_APROPOS_DEVEL is_not_empty
;
4083 apropos
"$@" |
grep '^[^(]*([239])';
4088 if obj _OPT_APROPOS_PROGS is_not_empty
;
4090 apropos
"$@" |
grep '^[^(]*([168])';
4097 if obj _OPT_DISPLAY is_not_empty
;
4099 DISPLAY
="${_OPT_DISPLAY}";
4102 if obj _OPT_V is_yes
;
4104 _DISPLAY_MODE
='groff';
4105 list_append _ADDOPTS_GROFF
'-V';
4107 if obj _OPT_Z is_yes
;
4109 _DISPLAY_MODE
='groff';
4110 list_append _ADDOPTS_GROFF
'-Z';
4112 if obj _OPT_MODE is_equal
'groff';
4114 _DISPLAY_MODE
='groff';
4116 if obj _DISPLAY_MODE is_equal
'groff';
4118 eval "${return_ok}";
4121 if obj _OPT_MODE is_equal
'source';
4123 _DISPLAY_MODE
='source';
4124 eval "${return_ok}";
4127 case "${_OPT_MODE}" in
4128 '') # automatic mode
4129 case "${_OPT_DEVICE}" in
4131 if obj DISPLAY is_empty
;
4133 error
"no X display found for device ${_OPT_DEVICE}";
4136 eval "${return_ok}";
4138 ascii|cp1047|latin1|utf8
)
4139 if obj _DISPLAY_MODE is_not_equal
'text';
4141 _DISPLAY_MODE
='tty';
4143 eval "${return_ok}";
4146 if obj DISPLAY is_empty
;
4148 _DISPLAY_MODE
='tty';
4149 eval "${return_ok}";
4152 if obj _OPT_DEFAULT_MODES is_empty
;
4154 _modes
="${_DEFAULT_MODES}";
4156 _modes
="${_OPT_DEFAULT_MODES}";
4160 _DISPLAY_MODE
='text';
4161 eval "${return_ok}";
4164 _DISPLAY_MODE
='tty';
4165 eval "${return_ok}";
4167 *) # display mode was given
4168 if obj DISPLAY is_empty
;
4170 error
"you must be in X Window for ${_OPT_MODE} mode.";
4172 _modes
="${_OPT_MODE}";
4176 # only viewer modes are left
4177 eval set -- "$(list_from_split "${_modes}" ',')";
4178 while test "$#" -gt 0;
4184 _DISPLAY_MODE
='text';
4185 eval "${return_ok}";
4188 _DISPLAY_MODE
='tty';
4189 eval "${return_ok}";
4192 if obj _OPT_VIEWER_X is_not_empty
;
4194 _viewers
="${_OPT_VIEWER_X}";
4196 _viewers
="${_VIEWER_X}";
4198 _viewer
="$(_get_first_prog "${_viewers}")";
4199 if is_not_equal
"$?" 0;
4203 _DISPLAY_PROG
="${_viewer}";
4205 eval "${return_ok}";
4208 if obj _OPT_VIEWER_DVI is_not_empty
;
4210 _viewers
="${_OPT_VIEWER_DVI}";
4212 _viewers
="${_VIEWER_DVI}";
4214 _viewer
="$(_get_first_prog "${_viewers}")";
4215 if is_not_equal
"$?" 0;
4219 _DISPLAY_PROG
="${_viewer}";
4220 _DISPLAY_MODE
="dvi";
4221 eval "${return_ok}";
4224 if obj _OPT_VIEWER_PDF is_not_empty
;
4226 _viewers
="${_OPT_VIEWER_PDF}";
4228 _viewers
="${_VIEWER_PDF}";
4230 _viewer
="$(_get_first_prog "${_viewers}")";
4231 if is_not_equal
"$?" 0;
4235 _DISPLAY_PROG
="${_viewer}";
4236 _DISPLAY_MODE
="pdf";
4237 eval "${return_ok}";
4240 if obj _OPT_VIEWER_PS is_not_empty
;
4242 _viewers
="${_OPT_VIEWER_PS}";
4244 _viewers
="${_VIEWER_PS}";
4246 _viewer
="$(_get_first_prog "${_viewers}")";
4247 if is_not_equal
"$?" 0;
4251 _DISPLAY_PROG
="${_viewer}";
4253 eval "${return_ok}";
4256 if obj _OPT_VIEWER_HTML is_not_empty
;
4258 _viewers
="${_OPT_VIEWER_HTML}";
4260 _viewers
="${_VIEWER_HTML}";
4262 _viewer
="$(_get_first_prog "${_viewers}")";
4263 if is_not_equal
"$?" 0;
4267 _DISPLAY_PROG
="${_viewer}";
4269 eval "${return_ok}";
4273 error
"no suitable display mode found.";
4281 error
"_get_first_prog() needs 1 argument.";
4287 eval set -- "$(list_from_split "$1" ',')";
4294 if is_prog
"$(get_first_essential $i)";
4304 #######################################################################
4305 # main_do_fileargs ()
4307 # Process filespec arguments in $_FILEARGS.
4310 # in: $_FILEARGS (process with `eval set -- "$_FILEARGS"')
4312 landmark
'17: main_do_fileargs()';
4315 func_check main_do_fileargs
= 0 "$@";
4319 _exitcode
="${_BAD}";
4320 eval set -- "${_FILEARGS}";
4322 # temporary storage of all input to $_TMP_CAT
4323 while test "$#" -ge 2;
4325 # test for `s name' arguments, with `s' a 1-char standard section
4328 case "${_filespec}" in
4333 if register_file
'-';
4335 _exitcode
="${_GOOD}";
4340 if list_has_not _MAN_AUTO_SEC
"${_filespec}";
4342 if do_filearg
"${_filespec}";
4344 _exitcode
="${_GOOD}";
4350 */*|man
:*|
*\
(*\
)|
*.
"${_filespec}")
4351 if do_filearg
"${_filespec}";
4353 _exitcode
="${_GOOD}";
4358 if do_filearg
"man:${_name}(${_filespec})";
4360 _exitcode
="${_GOOD}";
4364 if do_filearg
"${_filespec}";
4366 _exitcode
="${_GOOD}";
4372 if do_filearg
"${_filespec}";
4374 _exitcode
="${_GOOD}";
4379 done; # end of `s name' test
4380 while test "$#" -gt 0;
4384 if do_filearg
"${_filespec}";
4386 _exitcode
="${_GOOD}";
4389 rm -f "${_TMP_STDIN}";
4390 if is_equal
"${_exitcode}" "${_BAD}";
4392 eval "${return_bad}";
4394 eval "${return_ok}";
4395 } # main_do_fileargs()
4398 ########################################################################
4399 # main_set_resources ()
4401 # Determine options for setting X resources with $_DISPLAY_PROG.
4403 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4405 landmark
'18: main_set_resources()';
4406 main_set_resources
()
4408 func_check main_set_resources
= 0 "$@";
4409 local _prog
; # viewer program
4410 local _rl
; # resource list
4412 _title
="$(get_first_essential \
4413 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4414 _OUTPUT_FILE_NAME
='';
4416 until is_equal
"$#" 0;
4424 n
="$(echo -n "$1" | sed -e 's/^,,*//')";
4431 if obj _OUTPUT_FILE_NAME is_not_empty
;
4433 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME},";
4435 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}$n";
4438 case "${_OUTPUT_FILE_NAME}" in
4440 _OUTPUT_FILE_NAME
='-';
4443 error
"$_OUTPUT_FILE_NAME starts with a comma.";
4446 _OUTPUT_FILE_NAME
="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4448 if obj _DISPLAY_PROG is_empty
;
4449 then # for example, for groff mode
4451 eval "${return_ok}";
4454 set -- ${_DISPLAY_PROG};
4455 _prog
="$(base_name "$1")";
4457 if obj _OPT_BD is_not_empty
;
4460 ghostview|gv|gxditview|xditview|xdvi
)
4461 list_append _rl
'-bd' "${_OPT_BD}";
4465 if obj _OPT_BG is_not_empty
;
4468 ghostview|gv|gxditview|xditview|xdvi
)
4469 list_append _rl
'-bg' "${_OPT_BG}";
4472 list_append _rl
'-papercolor' "${_OPT_BG}";
4476 if obj _OPT_BW is_not_empty
;
4479 ghostview|gv|gxditview|xditview|xdvi
)
4480 _list_append _rl
'-bw' "${_OPT_BW}";
4484 if obj _OPT_FG is_not_empty
;
4487 ghostview|gv|gxditview|xditview|xdvi
)
4488 list_append _rl
'-fg' "${_OPT_FG}";
4492 if is_not_empty
"${_OPT_FN}";
4495 ghostview|gv|gxditview|xditview|xdvi
)
4496 list_append _rl
'-fn' "${_OPT_FN}";
4500 if is_not_empty
"${_OPT_GEOMETRY}";
4503 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4504 list_append _rl
'-geometry' "${_OPT_GEOMETRY}";
4508 if is_empty
"${_OPT_RESOLUTION}";
4510 _OPT_RESOLUTION
="${_DEFAULT_RESOLUTION}";
4513 list_append _rl
'-resolution' "${_DEFAULT_RESOLUTION}";
4516 case "${_DEFAULT_RESOLUTION}" in
4519 list_append _rl
'-z' '104';
4522 list_append _rl
'-z' '139';
4529 ghostview|gv|gxditview|xditview|xdvi
)
4530 list_append _rl
'-resolution' "${_OPT_RESOLUTION}";
4533 case "${_OPT_RESOLUTION}" in
4535 list_append _rl
'-z' '104';
4536 # '100' corresponds to 72dpi
4539 list_append _rl
'-z' '139';
4545 if is_yes
"${_OPT_ICONIC}";
4548 ghostview|gv|gxditview|xditview|xdvi
)
4549 list_append _rl
'-iconic';
4553 if is_yes
"${_OPT_RV}";
4556 ghostview|gv|gxditview|xditview|xdvi
)
4557 list_append _rl
'-rv';
4561 if is_not_empty
"${_OPT_XRM}";
4564 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4565 eval set -- "{$_OPT_XRM}";
4568 list_append _rl
'-xrm' "$i";
4573 if is_not_empty
"${_title}";
4577 list_append _rl
'-title' "${_title}";
4581 _DISPLAY_ARGS
="${_rl}";
4583 eval "${return_ok}";
4584 } # main_set_resources
4587 ########################################################################
4590 # Do the actual display of the whole thing.
4593 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4594 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4595 # $_REGISTERED_TITLE, $_TMP_CAT,
4596 # $_OPT_PAGER $PAGER $_MANOPT_PAGER
4598 landmark
'19: main_display()';
4601 func_check main_display
= 0 "$@";
4614 if obj _TMP_CAT is_non_empty_file
;
4616 _modefile
="${_OUTPUT_FILE_NAME}";
4619 eval "${return_ok}";
4621 case "${_DISPLAY_MODE}" in
4623 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4624 if obj _OPT_DEVICE is_not_empty
;
4626 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4628 _groggy
="$(tmp_cat | eval grog "${_options}")";
4630 # start a new shell program to get another process ID.
4633 test -f "${_modefile}" && rm -f "${_modefile}";
4634 mv "${_TMP_CAT}" "${_modefile}";
4635 cat "${_modefile}" | \
4639 if test -d "${_TMP_DIR}";
4641 rm -f "${_TMP_DIR}"/* || true;
4642 rmdir "${_TMP_DIR}";
4645 trap clean_up 0 2>${_NULL_DEV} || true;
4646 eval "${_groggy}" "${_ADDOPTS_GROFF}";
4650 case "${_OPT_DEVICE}" in
4652 _device
="$(get_first_essential \
4653 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4655 ascii|cp1047|latin1|utf8
)
4656 _device
="${_OPT_DEVICE}";
4660 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4663 _addopts
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4664 _groggy
="$(tmp_cat | grog -T${_device})";
4665 if obj _DISPLAY_MODE is_equal
'text';
4667 tmp_cat |
eval "${_groggy}" "${_addopts}";
4670 for p
in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4671 'less -r -R' 'more' 'pager' 'cat';
4674 then # no "" for is_prog() allows args for $p
4679 if obj _pager is_empty
;
4681 error
'no pager program found for tty mode';
4683 tmp_cat |
eval "${_groggy}" "${_addopts}" | \
4692 case "${_OPT_DEVICE}" in
4693 ''|dvi
) do_nothing
; ;;
4696 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4699 _modefile
="${_modefile}".dvi
;
4700 _groggy
="$(tmp_cat | grog -Tdvi)";
4704 case "${_OPT_DEVICE}" in
4705 ''|html
) do_nothing
; ;;
4708 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4711 _modefile
="${_modefile}".html
;
4712 _groggy
="$(tmp_cat | grog -Thtml)";
4716 case "${_OPT_DEVICE}" in
4722 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4725 _groggy
="$(tmp_cat | grog -Tps)";
4727 # start a new shell program to get another process ID.
4730 _psfile="${_modefile}.ps";
4731 _modefile="${_modefile}.pdf";
4732 test -f "${_psfile}" && rm -f "${_psfile}";
4733 test -f "${_modefile}" && rm -f "${_modefile}";
4734 cat "${_TMP_CAT}" | \
4735 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4736 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4737 -sOutputFile="${_modefile}" -c save pop -f "${_psfile}";
4738 test -f "${_psfile}" && rm -f "${_psfile}";
4739 test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";
4742 rm -f "${_modefile}";
4743 if test -d "${_TMP_DIR}";
4745 rm -f "${_TMP_DIR}"/* || true;
4746 rmdir "${_TMP_DIR}";
4749 trap clean_up 0 2>${_NULL_DEV} || true;
4750 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4754 case "${_OPT_DEVICE}" in
4760 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4763 _modefile
="${_modefile}".ps
;
4764 _groggy
="$(tmp_cat | grog -Tps)";
4772 case "${_OPT_DEVICE}" in
4774 _groggy
="$(tmp_cat | grog -Z)";
4777 _groggy
="$(tmp_cat | grog -T"${_OPT_DEVICE}" -Z)";
4781 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4782 _groggy
="$(tmp_cat | grog -Z)";
4788 error
"unknown mode \`${_DISPLAY_MODE}'";
4791 eval "${return_ok}";
4796 func_check _do_display
= 0 "$@";
4798 # start a new shell program for another process ID and better
4799 # cleaning-up of the temporary files.
4802 test -f "${_modefile}" && rm -f "${_modefile}";
4803 cat "${_TMP_CAT}" | \
4804 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}";
4805 rm -f "${_TMP_CAT}";
4808 if test -d "${_TMP_DIR}";
4810 rm -f "${_TMP_DIR}"/* || true;
4811 rmdir "${_TMP_DIR}";
4814 trap clean_up 0 2>${_NULL_DEV} || true;
4815 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4820 ########################################################################
4821 # main (<command_line_args>*)
4823 # The main function for groffer.
4829 func_check main
'>=' 0 "$@";
4830 # Do not change the sequence of the following functions!
4833 main_parse_args
"$@";
4838 eval "${return_ok}";
4841 landmark
'20: end of function definitions';
4843 ########################################################################