3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer2.sh
6 # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
8 # This file should not be run independently. It is called by
9 # `groffer.sh' in the source or by the installed `groffer' program.
11 # Copyright (C) 2001,2002,2003,2004,2005
12 # Free Software Foundation, Inc.
13 # Written by Bernd Warken
15 # Last update: 22 August 2005
17 # This file is part of `groffer', which is part of `groff'.
19 # `groff' is free software; you can redistribute it and/or modify it
20 # under the terms of the GNU General Public License as published by
21 # the Free Software Foundation; either version 2, or (at your option)
24 # `groff' is distributed in the hope that it will be useful, but
25 # WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 # General Public License for more details.
29 # You should have received a copy of the GNU General Public License
30 # along with `groff'; see the files COPYING and LICENSE in the top
31 # directory of the `groff' source. If not, write to the Free Software
32 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
36 ########################################################################
37 # Test of rudimentary shell functionality
38 ########################################################################
41 ########################################################################
47 _res
="$(unset _foo 2>&1)";
48 if unset _foo
>${_NULL_DEV} 2>&1 && \
49 test _
"${_res}"_
= __
&& test _
"${_foo}"_
= __
52 eval "${_UNSET}" _foo
;
53 eval "${_UNSET}" _res
;
59 ########################################################################
62 if test a
= a
&& test a
!= b
&& test -f "${_GROFFER_SH}"
66 echo '"test" did not work.' >&2;
71 ########################################################################
72 # Test of `echo' and the `$()' construct.
74 if echo '' >${_NULL_DEV}
78 echo '"echo" did not work.' >&2;
81 if test _
"$(t1="$
(echo te
)" &&
84 echo "${t1}${t2}${t3}")"_ \
87 echo 'The "$()" construct did not work' >&2;
92 ########################################################################
93 # Test of sed program; test in groffer.sh is not valid here.
95 if test _
"$(echo red | sed -e 's/r/s/')"_
!= _sed_
97 echo 'The sed program did not work.' >&2;
102 ########################################################################
103 # Test of function definitions.
110 if _t_e_s_t_f_u_n_c_
2>${_NULL_DEV}
114 echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
119 ########################################################################
120 # debug - diagnostic messages
121 ########################################################################
123 export _DEBUG_STACKS
;
124 _DEBUG_STACKS
='no'; # disable stack output in each function
125 #_DEBUG_STACKS='yes'; # enable stack output in each function
128 _DEBUG_LM
='no'; # disable landmark messages
129 #_DEBUG_LM='yes'; # enable landmark messages
131 export _DEBUG_KEEP_FILES
;
132 _DEBUG_KEEP_FILES
='no' # disable file keeping in temporary dir
133 #_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
135 export _DEBUG_PRINT_PARAMS
;
136 _DEBUG_PRINT_PARAMS
='no'; # disable printing of all parameters
137 #_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters
139 export _DEBUG_PRINT_SHELL
;
140 _DEBUG_PRINT_SHELL
='no'; # disable printing of the shell name
141 #_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name
143 export _DEBUG_PRINT_TMPDIR
;
144 _DEBUG_PRINT_TMPDIR
='no'; # disable printing of the temporary dir
145 #_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir
147 export _DEBUG_USER_WITH_STACK
;
148 _DEBUG_USER_WITH_STACK
='no'; # disable stack dump in error_user()
149 #_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user()
151 # determine all --debug* options
156 # _DEBUG_STACKS='yes';
158 _DEBUG_KEEP_FILES
='yes';
159 _DEBUG_PRINT_PARAMS
='yes';
160 _DEBUG_PRINT_SHELL
='yes';
161 _DEBUG_PRINT_TMPDIR
='yes';
162 _DEBUG_USER_WITH_STACK
='yes';
165 d
=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\
166 '--debug-stacks --debug-tmpdir --debug-user ';
171 echo 'The abbreviation --debug-s has multiple options: '\
172 '--debug-shell and --debug-stacks.' >&2
178 # extract whole word of abbreviation $i
179 s
="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p'
188 _DEBUG_KEEP_FILES
='yes';
189 _DEBUG_PRINT_PARAMS
='yes';
190 _DEBUG_PRINT_SHELL
='yes';
191 _DEBUG_PRINT_TMPDIR
='yes';
192 _DEBUG_USER_WITH_STACK
='yes';
195 _DEBUG_PRINT_TMPDIR
='yes';
196 _DEBUG_KEEP_FILES
='yes';
202 _DEBUG_PRINT_PARAMS
='yes';
205 _DEBUG_PRINT_SHELL
='yes';
211 _DEBUG_PRINT_TMPDIR
='yes';
214 _DEBUG_USER_WITH_STACK
='yes';
223 if test _
"${_DEBUG_PRINT_PARAMS}"_
= _yes_
225 echo "parameters: $@" >&2;
228 if test _
"${_DEBUG_PRINT_SHELL}"_
= _yes_
230 if test _
"${_SHELL}"_
= __
232 if test _
"${POSIXLY_CORRECT}"_
= _y_
234 echo 'shell: bash as /bin/sh (none specified)' >&2;
236 echo 'shell: /bin/sh (none specified)' >&2;
239 echo "shell: ${_SHELL}" >&2;
244 ########################################################################
245 # Environment Variables
246 ########################################################################
248 # Environment variables that exist only for this file start with an
249 # underscore letter. Global variables to this file are written in
250 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
251 # start with an underline and use only lower case letters and
252 # underlines, e.g. $_local_variable .
254 # [A-Z]* system variables, e.g. $MANPATH
255 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
256 # _[a-z_]* temporary variables, e.g. $_manpath
258 # Due to incompatibilities of the `ash' shell, the name of loop
259 # variables in `for' must be single character
260 # [a-z] local loop variables, e.g. $i
263 ########################################################################
264 # read-only variables (global to this file)
265 ########################################################################
267 # function return values; `0' means ok; other values are error codes
275 _GOOD
='0'; # return ok
276 _BAD
='1'; # return negatively, error code `1'
277 # $_ERROR was already defined as `7' in groffer.sh.
283 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
291 return_ok
="func_pop; return ${_OK}";
292 return_good
="func_pop; return ${_GOOD}";
293 return_bad
="func_pop; return ${_BAD}";
294 return_yes
="func_pop; return ${_YES}";
295 return_no
="func_pop; return ${_NO}";
296 return_error
="func_pop; return ${_ERROR}";
297 return_var
="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
300 export _DEFAULT_MODES
;
301 _DEFAULT_MODES
='x,ps,tty';
302 export _DEFAULT_RESOLUTION
;
303 _DEFAULT_RESOLUTION
='75';
305 export _DEFAULT_TTY_DEVICE
;
306 _DEFAULT_TTY_DEVICE
='latin1';
308 # _VIEWER_* viewer programs for different modes (only X is necessary)
309 # _VIEWER_* a comma-separated list of viewer programs (with options)
310 export _VIEWER_DVI
; # viewer program for dvi mode
311 export _VIEWER_HTML_TTY
; # viewer program for html mode in tty
312 export _VIEWER_HTML_X
; # viewer program for html mode in X
313 export _VIEWER_PDF
; # viewer program for pdf mode
314 export _VIEWER_PS
; # viewer program for ps mode
315 export _VIEWER_X
; # viewer program for X mode
316 _VIEWER_DVI
='kdvi,xdvi,dvilx';
317 _VIEWER_HTML_TTY
='lynx';
318 _VIEWER_HTML_X
='konqueror,mozilla,netscape,galeon,opera,amaya,arena';
319 _VIEWER_PDF
='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
320 _VIEWER_PS
='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
321 _VIEWER_X
='gxditview,xditview';
323 # Search automatically in standard sections `1' to `8', and in the
324 # traditional sections `9', `n', and `o'. On many systems, there
325 # exist even more sections, mostly containing a set of man pages
326 # special to a specific program package. These aren't searched for
327 # automatically, but must be specified on the command line.
328 export _MAN_AUTO_SEC_LIST
;
329 _MAN_AUTO_SEC_LIST
="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
330 export _MAN_AUTO_SEC_CHARS
;
331 _MAN_AUTO_SEC_CHARS
='[123456789no]';
334 _SPACE_SED
='['"${_SP}${_TAB}"']';
337 _SPACE_CASE
='[\'"${_SP}"'\'"${_TAB}"']';
339 export _PROCESS_ID
; # for shutting down the program
343 ############ the command line options of the involved programs
345 # The naming scheme for the options environment names is
346 # $_OPTS_<prog>_<length>[_<argspec>]
348 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
349 # command line options)
350 # <length>: LONG (long options) or SHORT (single character options)
351 # <argspec>: ARG for options with argument, NA for no argument;
352 # without _<argspec> both the ones with and without arg.
354 # Each option that takes an argument must be specified with a
355 # trailing : (colon).
358 export _OPTS_GROFFER_SHORT_NA
;
359 export _OPTS_GROFFER_SHORT_ARG
;
360 export _OPTS_GROFFER_LONG_NA
;
361 export _OPTS_GROFFER_LONG_ARG
;
362 export _OPTS_GROFF_SHORT_NA
;
363 export _OPTS_GROFF_SHORT_ARG
;
364 export _OPTS_GROFF_LONG_NA
;
365 export _OPTS_GROFF_LONG_ARG
;
366 export _OPTS_X_SHORT_ARG
;
367 export _OPTS_X_SHORT_NA
;
368 export _OPTS_X_LONG_ARG
;
369 export _OPTS_X_LONG_NA
;
370 export _OPTS_MAN_SHORT_ARG
;
371 export _OPTS_MAN_SHORT_NA
;
372 export _OPTS_MAN_LONG_ARG
;
373 export _OPTS_MAN_LONG_NA
;
374 export _OPTS_MANOPT_SHORT_ARG
;
375 export _OPTS_MANOPT_SHORT_NA
;
376 export _OPTS_MANOPT_LONG_ARG
;
377 export _OPTS_MANOPT_LONG_NA
;
378 export _OPTS_CMDLINE_SHORT_NA
;
379 export _OPTS_CMDLINE_SHORT_ARG
;
380 export _OPTS_CMDLINE_LONG_NA
;
381 export _OPTS_CMDLINE_LONG_ARG
;
383 ###### groffer native options
385 _OPTS_GROFFER_SHORT_NA
="'h' 'Q' 'v' 'V' 'X' 'Z'";
386 _OPTS_GROFFER_SHORT_ARG
="'T'";
388 _OPTS_GROFFER_LONG_NA
="'auto' \
389 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
390 'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \
391 'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \
392 'groff' 'help' 'intermediate-output' 'html' 'man' \
393 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
394 'text' 'text-device' \
395 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
397 _OPTS_GROFFER_LONG_ARG
="\
398 'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
399 'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
400 'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
401 'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
402 'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
404 ##### groffer options inhereted from groff
406 _OPTS_GROFF_SHORT_NA
="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
407 'R' 's' 'S' 't' 'U' 'z'";
408 _OPTS_GROFF_SHORT_ARG
="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
410 _OPTS_GROFF_LONG_NA
="";
411 _OPTS_GROFF_LONG_ARG
="";
413 ##### groffer options inhereted from the X Window toolkit
416 _OPTS_X_SHORT_ARG
="";
418 _OPTS_X_LONG_NA
="'iconic' 'rv'";
420 _OPTS_X_LONG_ARG
="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
421 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
422 'resolution' 'title' 'xrm'";
424 ###### groffer options inherited from man
426 _OPTS_MAN_SHORT_NA
="";
427 _OPTS_MAN_SHORT_ARG
="";
429 _OPTS_MAN_LONG_NA
="'all' 'ascii' 'catman' 'ditroff' \
430 'local-file' 'location' 'troff' 'update'";
432 _OPTS_MAN_LONG_ARG
="'locale' 'manpath' \
433 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
435 ###### additional options for parsing $MANOPT only
437 _OPTS_MANOPT_SHORT_NA
="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
439 _OPTS_MANOPT_SHORT_ARG
="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
441 _OPTS_MANOPT_LONG_NA
="${_OPTS_MAN_LONG_NA} \
442 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
443 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
445 _OPTS_MANOPT_LONG_ARG
="${_OPTS_MAN_LONG_NA} \
446 'config_file' 'encoding' 'extension' 'locale'";
448 ###### collections of command line options
450 _OPTS_CMDLINE_SHORT_NA
="${_OPTS_GROFFER_SHORT_NA} \
451 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
452 _OPTS_CMDLINE_SHORT_ARG
="${_OPTS_GROFFER_SHORT_ARG} \
453 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
455 _OPTS_CMDLINE_LONG_NA
="${_OPTS_GROFFER_LONG_NA} \
456 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
457 _OPTS_CMDLINE_LONG_ARG
="${_OPTS_GROFFER_LONG_ARG} \
458 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
461 ########################################################################
462 # read-write variables (global to this file)
463 ########################################################################
465 export _ALL_PARAMS
; # All options and file name parameters
466 export _ADDOPTS_GROFF
; # Transp. options for groff (`eval').
467 export _ADDOPTS_POST
; # Transp. options postproc (`eval').
468 export _ADDOPTS_X
; # Transp. options X postproc (`eval').
469 export _APROPOS_PROG
; # Program to run apropos.
470 export _APROPOS_SECTIONS
; # Sections for different --apropos-*.
471 export _DEFAULT_MODES
; # Set default modes.
472 export _DISPLAY_MODE
; # Display mode.
473 export _DISPLAY_PROG
; # Viewer program to be used for display.
474 export _DISPLAY_ARGS
; # X resources for the viewer program.
475 export _FILEARGS
; # Stores filespec parameters.
476 export _FILESPEC_ARG
; # Stores the actual filespec parameter.
477 export _FUNC_STACK
; # Store debugging information.
478 export _REGISTERED_TITLE
; # Processed file names.
479 # _HAS_* from availability tests
480 export _HAS_COMPRESSION
; # `yes' if gzip compression is available
481 export _HAS_BZIP
; # `yes' if bzip2 compression is available
482 # _MAN_* finally used configuration of man searching
483 export _MAN_ALL
; # search all man pages per filespec
484 export _MAN_ENABLE
; # enable search for man pages
485 export _MAN_EXT
; # extension for man pages
486 export _MAN_FORCE
; # force file parameter to be man pages
487 export _MAN_IS_SETUP
; # setup man variables only once
488 export _MAN_LANG
; # language for man pages
489 export _MAN_LANG2
; # language for man pages
490 export _MAN_LANG_DONE
; # language dirs added to man path
491 export _MAN_PATH
; # search path for man pages
492 export _MAN_SEC
; # sections for man pages; sep. `:'
493 export _MAN_SEC_DONE
; # sections added to man path
494 export _MAN_SYS
; # system names for man pages; sep. `,'
495 export _MAN_SYS
; # system names added to man path
496 # _MANOPT_* as parsed from $MANOPT
497 export _MANOPT_ALL
; # $MANOPT --all
498 export _MANOPT_EXTENSION
; # $MANOPT --extension
499 export _MANOPT_LANG
; # $MANOPT --locale
500 export _MANOPT_PATH
; # $MANOPT --manpath
501 export _MANOPT_PAGER
; # $MANOPT --pager
502 export _MANOPT_SEC
; # $MANOPT --sections
503 export _MANOPT_SYS
; # $MANOPT --systems
504 # _OPT_* as parsed from groffer command line
505 export _OPT_ALL
; # display all suitable man pages.
506 export _OPT_APROPOS
; # call `apropos' program.
507 export _OPT_BD
; # set border color in some modes.
508 export _OPT_BG
; # set background color in some modes.
509 export _OPT_BW
; # set border width in some modes.
510 export _OPT_DEFAULT_MODES
; # `,'-list of modes when no mode given.
511 export _OPT_DEVICE
; # device option.
512 export _OPT_DO_NOTHING
; # do nothing in main_display().
513 export _OPT_DISPLAY
; # set X display.
514 export _OPT_FG
; # set foreground color in some modes.
515 export _OPT_FN
; # set font in some modes.
516 export _OPT_GEOMETRY
; # set size and position of viewer in X.
517 export _OPT_ICONIC
; # -iconic option for X viewers.
518 export _OPT_LANG
; # set language for man pages
519 export _OPT_LOCATION
; # print processed file names to stderr
520 export _OPT_MODE
; # values: X, tty, Q, Z, ""
521 export _OPT_MANPATH
; # manual setting of path for man-pages
522 export _OPT_PAGER
; # specify paging program for tty mode
523 export _OPT_RESOLUTION
; # set X resolution in dpi
524 export _OPT_RV
; # reverse fore- and background colors.
525 export _OPT_SECTIONS
; # sections for man page search
526 export _OPT_SYSTEMS
; # man pages of different OS's
527 export _OPT_TITLE
; # title for gxditview window
528 export _OPT_TEXT_DEVICE
; # set device for tty mode.
529 export _OPT_V
; # groff option -V.
530 export _OPT_VIEWER_DVI
; # viewer program for dvi mode
531 export _OPT_VIEWER_PDF
; # viewer program for pdf mode
532 export _OPT_VIEWER_PS
; # viewer program for ps mode
533 export _OPT_VIEWER_HTML
; # viewer program for html mode
534 export _OPT_VIEWER_X
; # viewer program for x mode
535 export _OPT_WHATIS
; # print the man description
536 export _OPT_XRM
; # specify X resource.
537 export _OPT_Z
; # groff option -Z.
538 export _OUTPUT_FILE_NAME
; # output generated, see main_set_res..()
539 export _VIEWER_TERMINAL
; # viewer options for terminal (--*-viewer-tty)
540 # _TMP_* temporary directory and files
541 export _TMP_DIR
; # groffer directory for temporary files
542 export _TMP_CAT
; # stores concatenation of everything
543 export _TMP_STDIN
; # stores stdin, if any
545 # these variables are preset in section `Preset' after the rudim. test
548 ########################################################################
549 # Preset and reset of read-write global variables
550 ########################################################################
553 export _START_DIR
; # directory at start time of the script
556 # For variables that can be reset by option `--default', see reset().
560 # _HAS_* from availability tests
564 # _TMP_* temporary files
571 ########################################################################
574 # Reset the variables that can be affected by options to their default.
580 error
"reset() does not have arguments.";
587 _APROPOS_SECTIONS
='';
591 _REGISTERED_TITLE
='';
593 # _MAN_* finally used configuration of man searching
595 _MAN_ENABLE
='yes'; # do search for man-pages
597 _MAN_FORCE
='no'; # first local file, then search man page
607 # _MANOPT_* as parsed from $MANOPT
609 _MANOPT_EXTENSION
='';
616 # _OPT_* as parsed from groffer command line
622 _OPT_DEFAULT_MODES
='';
625 _OPT_DO_NOTHING
='no';
650 _VIEWER_TERMINAL
='no';
656 ########################################################################
657 # Functions for error handling and debugging
658 ########################################################################
666 # Arguments : arbitrary text including `-'.
681 # Arguments : arbitrary text.
694 # Print <text> to standard error as a debugging aid.
696 # Globals: $_DEBUG_LM
700 if test _
"${_DEBUG_LM}"_
= _yes_
706 landmark
"1: debugging functions";
716 cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
717 if test _
${_DEBUG_KEEP_FILES}_
= _yes_
719 echo2
"Kept temporary directory ${_TMP_DIR}."
721 if test _
"${_TMP_DIR}"_
!= __
723 if test -d "${_TMP_DIR}" ||
test -f "${_TMP_DIR}"
725 rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
735 # Output a diagnostic message to stderr
746 # Print an error message to standard error, print the function stack,
747 # exit with an error condition. The argument should contain the name
748 # of the function from which it was called. This is for system errors.
753 1) echo2
'groffer error: '"$1"; ;;
754 *) echo2
'groffer error: wrong number of arguments in error().'; ;;
757 if test _
"${_TMP_DIR}"_
!= __
&& test -d "${_TMP_DIR}"
759 : >"${_TMP_DIR}"/,error
;
766 # error_user (<text>*)
768 # Print an error message to standard error; exit with an error condition.
769 # The error is supposed to be produce by the user. So the funtion stack
776 echo2
'groffer error: '"$1";
779 echo2
'groffer error: wrong number of arguments in error_user().';
782 if test _
"${_DEBUG_USER_WITH_STACK}"_
= _yes_
786 if test _
"${_TMP_DIR}"_
!= __
&& test -d "${_TMP_DIR}"
788 : >"${_TMP_DIR}"/,error
;
797 # Test whether the former command ended with error(). Exit again.
803 if test "$?" = "${_ERROR}"
807 if test _
"${_TMP_DIR}"_
!= __
&& test -f "${_TMP_DIR}"/,error
815 # func_check (<func_name> <rel_op> <nr_args> "$@")
817 # Check number of arguments and register to _FUNC_STACK.
820 # <func_name>: name of the calling function.
821 # <rel_op>: a relational operator: = != < > <= >=
822 # <nr_args>: number of arguments to be checked against <operator>
823 # "$@": the arguments of the calling function.
825 # Variable prefix: fc
831 error
'func_check() needs at least 3 arguments.';
844 error
"func_check(): third argument must be a digit.";
874 'func_check(): second argument is not a relational operator.';
880 if test "$#" "${fc_op}" "${fc_nargs}"
884 error
"func_check(): \
885 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
887 func_push
"${fc_fname}";
888 if test _
"${_DEBUG_STACKS}"_
= _yes_
890 echo2
'+++ '"${fc_fname} $@";
891 echo2
'>>> '"${_FUNC_STACK}";
893 eval ${_UNSET} fc_comp
;
894 eval ${_UNSET} fc_fname
;
895 eval ${_UNSET} fc_nargs
;
896 eval ${_UNSET} fc_op
;
904 # Retrieve the top element from the stack.
906 # The stack elements are separated by `!'; the popped element is
907 # identical to the original element, except that all `!' characters
916 error
'func_pop() does not have arguments.';
918 case "${_FUNC_STACK}" in
920 if test _
"${_DEBUG_STACKS}"_
= _yes_
922 error
'func_pop(): stack is empty.';
926 # split at first bang `!'.
927 _FUNC_STACK
="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
934 if test _
"${_DEBUG_STACKS}"_
= _yes_
936 echo2
'<<< '"${_FUNC_STACK}";
942 # func_push (<element>)
944 # Store another element to stack.
946 # The stack elements are separated by `!'; if <element> contains a `!'
947 # it is removed first.
951 # Variable prefix: fp
957 error
'func_push() needs 1 argument.';
961 # remove all bangs `!'.
962 fp_element
="$(echo1 "$1" | sed -e 's/!//g')";
969 if test _
"${_FUNC_STACK}"_
= __
971 _FUNC_STACK
="${fp_element}";
973 _FUNC_STACK
="${fp_element}!${_FUNC_STACK}";
975 eval ${_UNSET} fp_element
;
982 # Print the content of the stack. Ignore the arguments.
986 diag
'call stack: '"${_FUNC_STACK}";
990 ########################################################################
992 ########################################################################
994 landmark
"2: system test";
996 # Test the availability of the system utilities used in this script.
999 ########################################################################
1000 # Test of function `sed'.
1003 if test _
"$(echo xTesTx \
1004 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1005 | sed -e 's|T|t|g')"_
!= _test_
1007 error
'Test of "sed" command failed.';
1011 ########################################################################
1012 # Test of function `cat'.
1014 if test _
"$(echo test | cat)"_
!= _test_
1016 error
'Test of "cat" command failed.';
1020 ########################################################################
1021 # Test for compression.
1023 if test _
"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_
= _test_
1025 _HAS_COMPRESSION
='yes';
1026 if echo1
'test' |
bzip2 -c 2>${_NULL_DEV} |
bzip2 -t 2>${_NULL_DEV} \
1027 && test _
"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
1028 | bzip2 -d -c 2>${_NULL_DEV})"_ \
1036 _HAS_COMPRESSION
='no';
1041 ########################################################################
1042 # Definition of normal Functions in alphabetical order
1043 ########################################################################
1044 landmark
"3: functions";
1046 ########################################################################
1047 # apropos_filespec ()
1049 # Setup for the --apropos* options
1054 func_check apropos_filespec
'=' 0 "$@";
1055 if obj _OPT_APROPOS is_yes
1058 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
1060 if obj _APROPOS_PROG is_empty
1062 error
'apropos_filespec: apropos_setup() must be run first.';
1064 if obj _APROPOS_SECTIONS is_empty
1066 if obj _OPT_SECTIONS is_empty
1070 s
='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
1073 s
='^.*(['"${_APROPOS_SECTIONS}"']';
1075 eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
1077 /^'"${_FILESPEC_ARG}"': /p
1082 s/^\(.* (..*)\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/
1085 eval "${return_ok}";
1089 ########################################################################
1092 # Setup for the --apropos* options
1096 func_check apropos_setup
'=' 0 "$@";
1097 if obj _OPT_APROPOS is_yes
1101 _APROPOS_PROG
='apropos';
1104 if man
--apropos man
>${_NULL_DEV} 2>${_NULL_DEV}
1106 _APROPOS_PROG
='man --apropos';
1107 elif man
-k man
>${_NULL_DEV} 2>${_NULL_DEV}
1109 _APROPOS_PROG
='man -k';
1112 if obj _APROPOS_PROG is_empty
1114 error
'apropos_setup: no apropos program available.';
1116 to_tmp_line
'.TH GROFFER APROPOS';
1118 eval "${return_ok}";
1122 ########################################################################
1123 # base_name (<path>)
1125 # Get the file name part of <path>, i.e. delete everything up to last
1126 # `/' from the beginning of <path>. Remove final slashes, too, to get a
1130 # Output : the file name part (without slashes)
1132 # Variable prefix: bn
1136 func_check base_name
= 1 "$@";
1138 case "${bn_name}" in
1140 # delete all final slashes
1141 bn_name
="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
1145 case "${bn_name}" in
1147 eval ${_UNSET} bn_name
;
1148 eval "${return_bad}";
1151 # delete everything before and including the last slash `/'.
1152 echo1
"${bn_name}" |
sed -e 's|^.*//*\([^/]*\)$|\1|';
1158 eval ${_UNSET} bn_name
;
1159 eval "${return_ok}";
1163 ########################################################################
1166 # Decompress if possible or just print <file> to standard output.
1168 # gzip, bzip2, and .Z decompression is supported.
1170 # Arguments: 1, a file name.
1171 # Output: the content of <file>, possibly decompressed.
1173 if test _
"${_HAS_COMPRESSION}"_
= _yes_
1177 func_check cat_z
= 1 "$@";
1180 error
'cat_z(): empty file name';
1183 error
'cat_z(): for standard input use save_stdin()';
1186 if obj _HAS_BZIP is_yes
1188 if bzip2 -t "$1" 2>${_NULL_DEV}
1190 bzip2 -c -d "$1" 2>${_NULL_DEV};
1191 eval "${return_ok}";
1194 gzip -c -d -f "$1" 2>${_NULL_DEV};
1195 eval "${return_ok}";
1200 func_check cat_z
= 1 "$@";
1202 eval "${return_ok}";
1207 ########################################################################
1210 # Do the final cleaning up before exiting; used by the trap calls.
1215 ########################################################################
1218 # Print marked message to standard error; useful for debugging.
1223 ########################################################################
1224 landmark
'4: dirname()*';
1225 ########################################################################
1227 #######################################################################
1228 # dirname_append (<dir> <name>)
1230 # Append `name' to `dir' with clean handling of `/'.
1233 # Output : the generated new directory name <dir>/<name>
1237 func_check dirname_append
= 2 "$@";
1240 error
"dir_append(): first argument is empty.";
1246 dirname_chop
"$1"/"$2";
1248 eval "${return_ok}";
1252 ########################################################################
1253 # dirname_chop (<name>)
1255 # Remove unnecessary slashes from directory name.
1257 # Argument: 1, a directory name.
1258 # Output: path without double, or trailing slashes.
1260 # Variable prefix: dc
1264 func_check dirname_chop
= 1 "$@";
1265 # replace all multiple slashes by a single slash `/'.
1266 dc_res
="$(echo1 "$1" | sed -e 's|///*|/|g')";
1270 # remove trailing slash '/';
1271 echo1
"${dc_res}" |
sed -e 's|/$||';
1277 eval ${_UNSET} dc_res
;
1278 eval "${return_ok}";
1282 ########################################################################
1283 # do_filearg (<filearg>)
1285 # Append the file, man-page, or standard input corresponding to the
1286 # argument to the temporary file. If this is compressed in the gzip
1287 # or Z format it is decompressed. A title element is generated.
1290 # - name of an existing file.
1291 # - `-' to represent standard input (several times allowed).
1292 # - `man:name.(section)' the man-page for `name' in `section'.
1293 # - `man:name.section' the man-page for `name' in `section'.
1294 # - `man:name' the man-page for `name' in the lowest `section'.
1295 # - `name.section' the man-page for `name' in `section'.
1296 # - `name' the man-page for `name' in the lowest `section'.
1298 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1301 # Return : $_GOOD if found, ${_BAD} otherwise.
1303 # Variable prefix: df
1307 func_check do_filearg
= 1 "$@";
1309 # store sequence into positional parameters
1310 case "${df_filespec}" in
1312 eval ${_UNSET} df_filespec
;
1313 eval "${return_good}";
1317 eval ${_UNSET} df_filespec
;
1318 eval "${return_good}";
1320 */*) # with directory part; so no man search
1324 if obj _MAN_ENABLE is_yes
1326 if obj _MAN_FORCE is_yes
1328 set 'Manpage' 'File';
1330 set 'File' 'Manpage';
1341 if test -f "${df_filespec}"
1343 if test -r "${df_filespec}"
1345 register_file
"${df_filespec}";
1346 eval ${_UNSET} df_filespec
;
1347 eval ${_UNSET} df_no_man
;
1348 eval "${return_good}";
1350 echo2
"could not read \`${df_filespec}'";
1351 eval ${_UNSET} df_filespec
;
1352 eval ${_UNSET} df_no_man
;
1353 eval "${return_bad}";
1356 if obj df_no_man is_not_empty
1358 if obj _OPT_WHATIS is_yes
1360 to_tmp_line
"This is neither a file nor a man page."
1362 echo2
"\`${df_filespec}' is neither a file nor a man page."
1369 Manpage
) # parse filespec as man page
1370 if obj _MAN_IS_SETUP is_not_yes
1374 if man_do_filespec
"${df_filespec}"
1376 eval ${_UNSET} df_filespec
;
1377 eval ${_UNSET} df_no_file
;
1378 eval "${return_good}";
1380 if obj df_no_file is_not_empty
1382 if obj _OPT_WHATIS is_yes
1384 to_tmp_line
"This is neither a file nor a man page."
1386 echo2
"\`${df_filespec}' is neither a file nor a man page."
1395 eval ${_UNSET} df_filespec
;
1396 eval ${_UNSET} df_no_file
;
1397 eval ${_UNSET} df_no_man
;
1398 eval "${return_bad}";
1402 ########################################################################
1409 eval return "${_OK}";
1413 ########################################################################
1416 # Print to standard error with final line break.
1421 ########################################################################
1424 # Print error message and exit with error code.
1429 ########################################################################
1432 # Test whether the former command ended with error(). Exit again.
1437 ########################################################################
1438 # func_check (<func_name> <rel_op> <nr_args> "$@")
1440 # Check number of arguments and register to _FUNC_STACK.
1443 # <func_name>: name of the calling function.
1444 # <rel_op>: a relational operator: = != < > <= >=
1445 # <nr_args>: number of arguments to be checked against <operator>
1446 # "$@": the arguments of the calling function.
1450 #########################################################################
1453 # Delete the top element from the function call stack.
1458 ########################################################################
1459 # func_push (<element>)
1461 # Store another element to function call stack.
1466 ########################################################################
1467 # func_stack_dump ()
1469 # Print the content of the stack.
1474 ########################################################################
1475 # get_first_essential (<arg>*)
1477 # Retrieve first non-empty argument.
1479 # Return : `1' if all arguments are empty, `0' if found.
1480 # Output : the retrieved non-empty argument.
1482 # Variable prefix: gfe
1484 get_first_essential
()
1486 func_check get_first_essential
'>=' 0 "$@";
1489 eval "${return_ok}";
1494 if obj gfe_var is_not_empty
1497 eval ${_UNSET} gfe_var
;
1498 eval "${return_ok}";
1501 eval ${_UNSET} gfe_var
;
1502 eval "${return_bad}";
1506 ########################################################################
1507 landmark
'5: is_*()';
1508 ########################################################################
1510 ########################################################################
1513 # Test whether `name' is a directory.
1516 # Return : `0' if arg1 is a directory, `1' otherwise.
1520 func_check is_dir
'=' 1 "$@";
1521 if test _
"$1"_
!= __
&& test -d "$1" && test -r "$1"
1523 eval "${return_yes}";
1525 eval "${return_no}";
1529 ########################################################################
1530 # is_empty (<string>)
1532 # Test whether `string' is empty.
1535 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1539 func_check is_empty
'=' 1 "$@";
1542 eval "${return_yes}";
1544 eval "${return_no}";
1548 ########################################################################
1549 # is_equal (<string1> <string2>)
1551 # Test whether `string1' is equal to <string2>.
1554 # Return : `0' both arguments are equal strings, `1' otherwise.
1558 func_check is_equal
'=' 2 "$@";
1559 if test _
"$1"_
= _
"$2"_
1561 eval "${return_yes}";
1563 eval "${return_no}";
1567 ########################################################################
1568 # is_existing (<name>)
1570 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1571 # not have `test -e'.
1574 # Return : `0' if arg1 exists, `1' otherwise.
1578 func_check is_existing
'=' 1 "$@";
1581 eval "${return_no}";
1583 if test -f "$1" ||
test -d "$1" ||
test -c "$1"
1585 eval "${return_yes}";
1587 eval "${return_no}";
1591 ########################################################################
1594 # Test whether `name' is a readable file.
1597 # Return : `0' if arg1 is a readable file, `1' otherwise.
1601 func_check is_file
'=' 1 "$@";
1602 if is_not_empty
"$1" && test -f "$1" && test -r "$1"
1604 eval "${return_yes}";
1606 eval "${return_no}";
1610 ########################################################################
1611 # is_non_empty_file (<file_name>)
1613 # Test whether `file_name' is a non-empty existing file.
1617 # `0' if arg1 is a non-empty existing file
1622 func_check is_non_empty_file
'=' 1 "$@";
1623 if is_file
"$1" && test -s "$1"
1625 eval "${return_yes}";
1627 eval "${return_no}";
1631 ########################################################################
1632 # is_not_dir (<name>)
1634 # Test whether `name' is not a readable directory.
1637 # Return : `0' if arg1 is a directory, `1' otherwise.
1641 func_check is_not_dir
'=' 1 "$@";
1644 eval "${return_no}";
1646 eval "${return_yes}";
1650 ########################################################################
1651 # is_not_empty (<string>)
1653 # Test whether `string' is not empty.
1656 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1660 func_check is_not_empty
'=' 1 "$@";
1663 eval "${return_no}";
1665 eval "${return_yes}";
1669 ########################################################################
1670 # is_not_equal (<string1> <string2>)
1672 # Test whether `string1' differs from `string2'.
1678 func_check is_not_equal
'=' 2 "$@";
1679 if is_equal
"$1" "$2"
1681 eval "${return_no}";
1683 eval "${return_yes}";
1687 ########################################################################
1688 # is_not_file (<filename>)
1690 # Test whether `name' is a not readable file.
1692 # Arguments : 1 (empty allowed)
1696 func_check is_not_file
'=' 1 "$@";
1699 eval "${return_no}";
1701 eval "${return_yes}";
1705 ########################################################################
1706 # is_not_prog ([<name> [<arg>*]])
1708 # Verify that arg is a not program in $PATH.
1710 # Arguments : >=0 (empty allowed)
1711 # more args are ignored, this allows to specify progs with arguments
1715 func_check is_not_prog
'>=' 0 "$@";
1718 eval "${return_yes}";
1721 if where_is
"$1" >${_NULL_DEV}
1723 eval "${return_no}";
1727 eval "${return_yes}";
1731 ########################################################################
1732 # is_not_writable (<name>)
1734 # Test whether `name' is a not a writable file or directory.
1736 # Arguments : >=1 (empty allowed), more args are ignored
1740 func_check is_not_writable
'>=' 1 "$@";
1743 eval "${return_no}";
1745 eval "${return_yes}";
1749 ########################################################################
1752 # Test whether not running in X Window by checking $DISPLAY
1756 func_check is_X
'=' 0 "$@";
1757 if obj DISPLAY is_empty
1759 eval "${return_yes}";
1761 eval "${return_no}";
1765 ########################################################################
1766 # is_not_yes (<string>)
1768 # Test whether `string' is not "yes".
1774 func_check is_not_yes
= 1 "$@";
1777 eval "${return_no}";
1779 eval "${return_yes}";
1783 ########################################################################
1784 # is_prog ([<name> [<arg>*]])
1786 # Determine whether <name> is a program in $PATH
1788 # Arguments : >=0 (empty allowed)
1789 # <arg>* are ignored, this allows to specify progs with arguments.
1793 func_check is_prog
'>=' 0 "$@";
1796 eval "${return_no}";
1799 if where_is
"$1" >${_NULL_DEV}
1801 eval "${return_yes}";
1805 eval "${return_no}";
1809 ########################################################################
1810 # is_writable (<name>)
1812 # Test whether `name' is a writable file or directory.
1814 # Arguments : >=1 (empty allowed), more args are ignored
1818 func_check is_writable
'>=' 1 "$@";
1821 eval "${return_no}";
1827 eval "${return_yes}";
1830 eval "${return_no}";
1834 ########################################################################
1837 # Test whether running in X Window by checking $DISPLAY
1841 func_check is_X
'=' 0 "$@";
1842 if obj DISPLAY is_not_empty
1844 eval "${return_yes}";
1846 eval "${return_no}";
1850 ########################################################################
1853 # Test whether `string' has value "yes".
1855 # Return : `0' if arg1 is `yes', `1' otherwise.
1859 func_check is_yes
'=' 1 "$@";
1860 if is_equal
"$1" 'yes'
1862 eval "${return_yes}";
1864 eval "${return_no}";
1868 ########################################################################
1871 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1873 # Globals: $_DEBUG_LM
1875 # Defined in section `Debugging functions'.
1878 ########################################################################
1881 # Clean exit without an error or with <code>.
1895 ########################################################################
1896 landmark
'6: list_*()';
1897 ########################################################################
1899 # `list' is an object class that represents an array or list. Its
1900 # data consists of space-separated single-quoted elements. So a list
1901 # has the form "'first' 'second' '...' 'last'". See list_append() for
1902 # more details on the list structure. The array elements of `list'
1903 # can be get by `eval set x "$list"; shift`.
1906 ########################################################################
1907 # list_append (<list> <element>...)
1910 # <list>: a variable name for a list of single-quoted elements
1911 # <element>: some sequence of characters.
1912 # Output: none, but $<list> is set to
1913 # if <list> is empty: "'<element>' '...'"
1914 # otherwise: "$list '<element>' ..."
1916 # Variable prefix: la
1920 func_check list_append
'>=' 2 "$@";
1922 eval la_list
='"${'$1'}"';
1929 # escape each single quote by replacing each
1930 # "'" (squote) by "'\''" (squote bslash squote squote);
1931 # note that the backslash must be doubled in the following `sed'
1932 la_element
="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
1939 la_element
="${la_s}";
1942 if obj la_list is_empty
1944 la_list
="'${la_element}'";
1946 la_list
="${la_list} '${la_element}'";
1949 eval "${la_name}"='"${la_list}"';
1950 eval ${_UNSET} la_element
;
1951 eval ${_UNSET} la_list
;
1952 eval ${_UNSET} la_name
;
1953 eval ${_UNSET} la_s
;
1954 eval "${return_ok}";
1958 ########################################################################
1959 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1961 # Transform command line arguments into a normalized form.
1963 # Options, option arguments, and file parameters are identified and
1964 # output each as a single-quoted argument of its own. Options and
1965 # file parameters are separated by a '--' argument.
1968 # <pre_name>: common part of a set of 4 environment variable names:
1969 # $<pre_name>_SHORT_NA: list of short options without an arg.
1970 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1971 # $<pre_name>_LONG_NA: list of long options without an arg.
1972 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1973 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1974 # the content of a variable, or direct arguments.
1976 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1979 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1980 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1981 # none-empty option lists, this will result in printing:
1982 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1984 # Use this function in the following way:
1985 # eval set x "$(args_norm PRE_NAME "$@")";
1987 # while test "$1" != '--'; do
1994 # # all positional parameters ("$@") left are file name parameters.
1996 # Variable prefix: lfc
2000 func_check list_from_cmdline
'>=' 1 "$@";
2001 lfc_short_n
="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
2002 lfc_short_a
="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
2003 lfc_long_n
="$(obj_data "$1"_LONG_NA)"; # long options, no argument
2004 lfc_long_a
="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
2006 if obj lfc_short_n is_empty
2008 error
'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
2010 if obj lfc_short_a is_empty
2012 error
'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
2014 if obj lfc_long_n is_empty
2016 error
'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
2018 if obj lfc_long_a is_empty
2020 error
'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
2027 eval ${_UNSET} lfc_fparams
;
2028 eval ${_UNSET} lfc_short_a
;
2029 eval ${_UNSET} lfc_short_n
;
2030 eval ${_UNSET} lfc_long_a
;
2031 eval ${_UNSET} lfc_long_n
;
2032 eval ${_UNSET} lfc_result
;
2033 eval "${return_ok}";
2038 while test "$#" -ge 1
2042 case "${lfc_arg}" in
2045 # delete leading '--';
2046 lfc_abbrev
="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
2047 lfc_with_equal
="${lfc_abbrev}";
2048 # extract option by deleting from the first '=' to the end
2049 lfc_abbrev
="$(echo1 "${lfc_with_equal}" | \
2050 sed -e 's/^\([^=]*\)=.*$/\1/')";
2051 lfc_opt
="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2053 if obj lfc_opt is_empty
2055 error_user
"--${lfc_abbrev} is not an option.";
2057 # get the option argument by deleting up to first `='
2058 lfc_optarg
="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')";
2060 list_append lfc_result
"--${lfc_opt}" "${lfc_optarg}";
2065 # delete leading '--';
2066 lfc_abbrev
="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
2067 if list_has lfc_long_n
"${lfc_abbrev}"
2069 lfc_opt
="${lfc_abbrev}";
2072 lfc_opt
="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")";
2074 if obj lfc_opt is_not_empty
&& is_not_equal
"$#" 0
2076 a
="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2078 if obj a is_not_empty
2080 error_user
"The abbreviation ${lfc_arg} \
2081 has multiple options: --${lfc_opt} and --${a}.";
2085 if obj lfc_opt is_not_empty
2087 # long option, no argument
2088 list_append lfc_result
"--${lfc_opt}";
2091 lfc_opt
="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2093 if obj lfc_opt is_not_empty
2095 # long option with argument
2098 error_user
"no argument for option --${lfc_opt}."
2100 list_append lfc_result
"--${lfc_opt}" "$1";
2104 error_user
"${lfc_arg} is not an option.";
2106 -?
*) # short option (cluster)
2107 # delete leading `-';
2108 lfc_rest
="$(echo1 "${lfc_arg}" | sed -e 's/^-//')";
2110 while obj lfc_rest is_not_empty
2112 # get next short option from cluster (first char of $lfc_rest)
2113 lfc_optchar
="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')";
2114 # remove first character from ${lfc_rest};
2115 lfc_rest
="$(echo1 "${lfc_rest}" | sed -e 's/^.//')";
2117 if list_has lfc_short_n
"${lfc_optchar}"
2119 list_append lfc_result
"-${lfc_optchar}";
2121 elif list_has lfc_short_a
"${lfc_optchar}"
2123 if obj lfc_rest is_empty
2127 list_append lfc_result
"-${lfc_optchar}" "$1";
2131 error_user
"no argument for option -${lfc_optchar}.";
2133 else # rest is the argument
2134 list_append lfc_result
"-${lfc_optchar}" "${lfc_rest}";
2139 error_user
"unknown option -${lfc_optchar}.";
2144 # Here, $lfc_arg is not an option, so a file parameter.
2145 list_append lfc_fparams
"${lfc_arg}";
2147 # Ignore the strange POSIX option handling to end option
2148 # parsing after the first file name argument. To reuse it, do
2149 # a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
2150 # When `bash' is called as `sh' $POSIXLY_CORRECT is set
2151 # automatically to `y'.
2155 list_append lfc_result
'--';
2156 if obj lfc_fparams is_not_empty
2158 lfc_result
="${lfc_result} ${lfc_fparams}";
2162 list_append lfc_result
"$@";
2164 obj lfc_result echo1
;
2165 eval ${_UNSET} lfc_abbrev
;
2166 eval ${_UNSET} lfc_fparams
;
2167 eval ${_UNSET} lfc_short_a
;
2168 eval ${_UNSET} lfc_short_n
;
2169 eval ${_UNSET} lfc_long_a
;
2170 eval ${_UNSET} lfc_long_n
;
2171 eval ${_UNSET} lfc_result
;
2172 eval ${_UNSET} lfc_arg
;
2173 eval ${_UNSET} lfc_opt
;
2174 eval ${_UNSET} lfc_opt_arg
;
2175 eval ${_UNSET} lfc_opt_char
;
2176 eval ${_UNSET} lfc_with_equal
;
2177 eval ${_UNSET} lfc_rest
;
2178 eval "${return_ok}";
2179 } # list_from_cmdline()
2182 ########################################################################
2183 # list_from_split (<string> <separator>)
2185 # In <string>, escape all white space characters and replace each
2186 # <separator> by space.
2188 # Arguments: 2: a <string> that is to be split into parts divided by
2190 # Output: the resulting list string
2192 # Variable prefix: lfs
2196 func_check list_from_split
= 2 "$@";
2198 # precede each space or tab by a backslash `\' (doubled for `sed')
2199 lfs_s
="$(echo1 "$1" | sed -e 's/\('"${_SPACE_SED}"'\)/\\\1/g')";
2202 # replace split character of string by the list separator ` ' (space).
2204 /) # cannot use normal `sed' separator
2205 echo1
"${lfs_s}" |
sed -e 's|'"$2"'| |g';
2207 ?
) # use normal `sed' separator
2208 echo1
"${lfs_s}" |
sed -e 's/'"$2"'/ /g';
2211 error
'list_from_split(): separator must be a single character.';
2214 eval ${_UNSET} lfs_s
;
2215 eval "${return_ok}";
2219 ########################################################################
2222 # Check whether <list> is a space-separated list of '-quoted elements.
2224 # If the test fails an error is raised.
2225 # If the test succeeds the argument is echoed.
2228 # A list has the form "'first' 'second' '...' 'last'". So it has a
2229 # leading and a final quote and the elements are separated by "' '"
2230 # constructs. If these are all removed there should not be any
2231 # unescaped single-quotes left. Watch out for escaped single
2232 # quotes; they have the form '\'' (sq bs sq sq).
2235 # Output: the argument <list> unchanged, if the check succeeded.
2237 # Variable prefix: lg
2241 func_check list_get
= 1 "$@";
2242 eval lg_list
='"${'$1'}"';
2243 # remove leading and final space characters
2244 lg_list
="$(echo1 "${lg_list}" | sed -e '
2245 s/^'"${_SPACE_SED}"'*//
2246 s/'"${_SPACE_SED}"'*$//
2249 case "${lg_list}" in
2251 eval ${_UNSET} lg_list
;
2252 eval "${return_ok}";
2256 eval ${_UNSET} lg_list
;
2257 eval "${return_ok}";
2260 error
"list_get(): bad list: $1"
2263 eval ${_UNSET} lg_list
;
2264 eval "${return_ok}";
2268 ########################################################################
2269 # list_has (<var_name> <element>)
2271 # Test whether the list <var_name> has the element <element>.
2274 # <var_name>: a variable name for a list of single-quoted elements
2275 # <element>: some sequence of characters.
2277 # Variable prefix: lh
2281 func_check list_has
= 2 "$@";
2282 eval lh_list
='"${'$1'}"';
2283 if obj lh_list is_empty
2285 eval "${_UNSET}" lh_list
;
2286 eval "${return_no}";
2289 \'*\') lh_element
=" $2 "; ;;
2290 *) lh_element
=" '$2' "; ;;
2292 if string_contains
" ${lh_list} " "${lh_element}"
2294 eval "${_UNSET}" lh_list
;
2295 eval "${_UNSET}" lh_element
;
2296 eval "${return_yes}";
2298 eval "${_UNSET}" lh_list
;
2299 eval "${_UNSET}" lh_element
;
2300 eval "${return_no}";
2305 ########################################################################
2306 # list_has_abbrev (<var_name> <abbrev>)
2308 # Test whether the list <var_name> has an element starting with <abbrev>.
2311 # <var_name>: a variable name for a list of single-quoted elements
2312 # <abbrev>: some sequence of characters.
2314 # Variable prefix: lha
2318 func_check list_has_abbrev
= 2 "$@";
2319 eval lha_list
='"${'$1'}"';
2320 if obj lha_list is_empty
2322 eval "${_UNSET}" lha_list
;
2323 eval "${return_no}";
2327 lha_element
="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')";
2330 *) lha_element
="'$2"; ;;
2332 if string_contains
" ${lha_list}" " ${lha_element}"
2334 eval "${_UNSET}" lha_list
;
2335 eval "${_UNSET}" lha_element
;
2336 eval "${return_yes}";
2338 eval "${_UNSET}" lha_list
;
2339 eval "${_UNSET}" lha_element
;
2340 eval "${return_no}";
2342 eval "${return_ok}";
2346 ########################################################################
2347 # list_has_not (<list> <element>)
2349 # Test whether <list> has no <element>.
2352 # <list>: a space-separated list of single-quoted elements.
2353 # <element>: some sequence of characters.
2355 # Variable prefix: lhn
2359 func_check list_has_not
= 2 "$@";
2360 eval lhn_list
='"${'$1'}"';
2361 if obj lhn_list is_empty
2363 eval "${_UNSET}" lhn_list
;
2364 eval "${return_yes}";
2367 \'*\') lhn_element
=" $2 "; ;;
2368 *) lhn_element
=" '$2' "; ;;
2370 if string_contains
" ${lhn_list} " "${lhn_element}"
2372 eval "${_UNSET}" lhn_list
;
2373 eval "${_UNSET}" lhn_element
;
2374 eval "${return_no}";
2376 eval "${_UNSET}" lhn_list
;
2377 eval "${_UNSET}" lhn_element
;
2378 eval "${return_yes}";
2383 ########################################################################
2384 # list_single_from_abbrev (<list> <abbrev>)
2386 # Check whether the list has an element starting with <abbrev>. If
2387 # there are more than a single element an error is created.
2390 # <list>: a variable name for a list of single-quoted elements
2391 # <abbrev>: some sequence of characters.
2393 # Output: the found element.
2395 # Variable prefix: lsfa
2397 list_single_from_abbrev
()
2399 func_check list_single_from_abbrev
= 2 "$@";
2400 eval lsfa_list
='"${'$1'}"';
2401 if obj lsfa_list is_empty
2403 eval "${_UNSET}" lsfa_list
;
2404 eval "${return_no}";
2407 if list_has lsfa_list
"${lsfa_abbrev}"
2409 obj lsfa_abbrev echo1
;
2410 eval "${_UNSET}" lsfa_abbrev
;
2411 eval "${_UNSET}" lsfa_list
;
2412 eval "${return_yes}";
2414 if list_has_abbrev lsfa_list
"${lsfa_abbrev}"
2417 eval set x
"${lsfa_list}";
2423 if obj lsfa_element is_not_empty
2425 error_user
"The abbreviation --${lsfa_abbrev} \
2426 has multiple options: --${lsfa_element} and --${i}.";
2432 obj lsfa_element echo1
;
2433 eval "${_UNSET}" lsfa_abbrev
;
2434 eval "${_UNSET}" lsfa_element
;
2435 eval "${_UNSET}" lsfa_list
;
2436 eval "${return_yes}";
2438 eval "${_UNSET}" lsfa_abbrev
;
2439 eval "${_UNSET}" lsfa_element
;
2440 eval "${_UNSET}" lsfa_list
;
2441 eval "${return_no}";
2446 ########################################################################
2447 landmark
'7: man_*()';
2448 ########################################################################
2450 ########################################################################
2451 # man_do_filespec (<filespec>)
2453 # Print suitable man page(s) for filespec to $_TMP_CAT.
2456 # <filespec>: argument of the form `man:name.section', `man:name',
2457 # `man:name(section)', `name.section', `name'.
2459 # Globals : $_OPT_ALL
2462 # Return : `0' if man page was found, `1' else.
2464 # Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE
2465 # are assumed (see man_setup()).
2467 # Variable prefix: mdf
2471 func_check man_do_filespec
= 1 "$@";
2472 if obj _MAN_PATH is_empty
2474 eval "${return_bad}";
2478 eval "${return_bad}";
2483 case "${mdf_spec}" in
2484 */*) # not a man spec with containing '/'
2485 eval ${_UNSET} mdf_got_one
;
2486 eval ${_UNSET} mdf_name
;
2487 eval ${_UNSET} mdf_section
;
2488 eval ${_UNSET} mdf_spec
;
2489 eval "${return_bad}";
2491 man
:?
*\
(?
*\
)) # man:name(section)
2492 mdf_name
="$(echo1 "${mdf_spec}" \
2493 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2494 mdf_section
="$(echo1 "${mdf_spec}" \
2495 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2498 man
:?
*.
${_MAN_AUTO_SEC_CHARS}) # man:name.section
2499 mdf_name
="$(echo1 "${mdf_spec}" \
2500 | sed -e 's/^man:\(..*\)\..$/\1/')";
2501 mdf_section
="$(echo1 "${mdf_spec}" \
2502 | sed -e 's/^.*\(.\)$/\1/')";
2506 mdf_name
="$(echo1 "${mdf_spec}" | sed -e 's/^man://')";
2509 ?
*\
(?
*\
)) # name(section)
2510 mdf_name
="$(echo1 "${mdf_spec}" \
2511 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2512 mdf_section
="$(echo1 "${mdf_spec}" \
2513 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2516 ?
*.
${_MAN_AUTO_SEC_CHARS}) # name.section
2517 mdf_name
="$(echo1 "${mdf_spec}" \
2518 | sed -e 's/^\(..*\)\..$/\1/')";
2519 mdf_section
="$(echo1 "${mdf_spec}" \
2520 | sed -e 's/^.*\(.\)$/\1/')";
2524 mdf_name
="${mdf_spec}";
2527 if obj mdf_name is_empty
2529 eval ${_UNSET} mdf_got_one
;
2530 eval ${_UNSET} mdf_name
;
2531 eval ${_UNSET} mdf_section
;
2532 eval ${_UNSET} mdf_spec
;
2533 eval "${return_bad}";
2536 if obj mdf_section is_empty
2538 if obj _OPT_SECTIONS is_empty
2540 eval set x
"${_MAN_AUTO_SEC_LIST}";
2542 # use --sections when no section is given to filespec
2543 eval set x
"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/:/ /g')";
2549 if man_search_section
"${mdf_name}" "${mdf_s}"
2551 if obj _MAN_ALL is_yes
2555 eval ${_UNSET} mdf_got_one
;
2556 eval ${_UNSET} mdf_name
;
2557 eval ${_UNSET} mdf_s
;
2558 eval ${_UNSET} mdf_section
;
2559 eval ${_UNSET} mdf_spec
;
2560 eval "${return_good}";
2565 if man_search_section
"${mdf_name}" "${mdf_section}"
2567 eval ${_UNSET} mdf_got_one
;
2568 eval ${_UNSET} mdf_name
;
2569 eval ${_UNSET} mdf_s
;
2570 eval ${_UNSET} mdf_section
;
2571 eval ${_UNSET} mdf_spec
;
2572 eval "${return_good}";
2574 eval ${_UNSET} mdf_got_one
;
2575 eval ${_UNSET} mdf_name
;
2576 eval ${_UNSET} mdf_section
;
2577 eval ${_UNSET} mdf_spec
;
2578 eval "${return_bad}";
2581 if obj _MAN_ALL is_yes
&& obj mdf_got_one is_yes
2583 eval ${_UNSET} mdf_got_one
;
2584 eval ${_UNSET} mdf_name
;
2585 eval ${_UNSET} mdf_s
;
2586 eval ${_UNSET} mdf_section
;
2587 eval ${_UNSET} mdf_spec
;
2588 eval "${return_good}";
2590 eval ${_UNSET} mdf_got_one
;
2591 eval ${_UNSET} mdf_name
;
2592 eval ${_UNSET} mdf_s
;
2593 eval ${_UNSET} mdf_section
;
2594 eval ${_UNSET} mdf_spec
;
2595 eval "${return_bad}";
2596 } # man_do_filespec()
2599 ########################################################################
2600 # man_register_file (<file> <name> [<section>])
2602 # Write a found man page file and register the title element.
2604 # Arguments: 1, 2, or 3; maybe empty
2609 func_check man_register_file
'>=' 2 "$@";
2613 error
"man_register_file() expects 2 or 3 arguments.";
2618 error
'man_register_file(): file name is empty';
2623 register_title
"man:$2";
2624 eval "${return_ok}";
2627 register_title
"$2.$3";
2628 eval "${return_ok}";
2631 eval "${return_ok}";
2635 ########################################################################
2636 # man_search_section (<name> <section>)
2638 # Retrieve man pages.
2641 # Globals : $_MAN_PATH, $_MAN_EXT
2642 # Return : 0 if found, 1 otherwise
2644 # Variable prefix: mss
2646 man_search_section
()
2648 func_check man_search_section
= 2 "$@";
2649 if obj _MAN_PATH is_empty
2651 eval "${return_bad}";
2655 eval "${return_bad}";
2659 eval "${return_bad}";
2663 eval set x
"$(path_split "${_MAN_PATH}")";
2667 if obj _MAN_EXT is_empty
2671 mss_dir
="$(dirname_append "$d" "man
${mss_section}")";
2673 if obj mss_dir is_dir
2676 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2677 if obj _OPT_WHATIS is_yes
2679 mss_files
="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2680 sed -e '\| found|s|.*||'
2683 mss_files
="$(eval ls "'${mss_prefix}'"'*' 2>${_NULL_DEV} |
2684 sed -e '\| found|s|.*||'
2688 if obj mss_files is_not_empty
2690 # for f in $mss_files
2691 for f
in $
(eval set x
${mss_files}; shift; echo1
"$@")
2695 if obj mss_f is_file
2697 if is_yes
"${mss_got_one}"
2699 register_file
"${mss_f}";
2700 elif obj _MAN_ALL is_yes
2702 man_register_file
"${mss_f}" "${mss_name}";
2704 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2705 eval ${_UNSET} mss_dir
;
2706 eval ${_UNSET} mss_ext
;
2707 eval ${_UNSET} mss_f
;
2708 eval ${_UNSET} mss_files
;
2709 eval ${_UNSET} mss_got_one
;
2710 eval ${_UNSET} mss_name
;
2711 eval ${_UNSET} mss_prefix
;
2712 eval ${_UNSET} mss_section
;
2713 eval "${return_good}";
2722 mss_ext
="${_MAN_EXT}";
2723 # check for directory name having trailing extension
2726 mss_dir
="$(dirname_append $d man${mss_section}${mss_ext})";
2728 if obj mss_dir is_dir
2731 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2732 mss_files
="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2733 sed -e '\|not found|s|.*||'
2736 if obj mss_files is_not_empty
2738 # for f in $mss_files
2739 for f
in $
(eval set x
${mss_files}; shift; echo1
"$@")
2742 if obj mss_f is_file
2744 if is_yes
"${mss_got_one}"
2746 register_file
"${mss_f}";
2747 elif obj _MAN_ALL is_yes
2749 man_register_file
"${mss_f}" "${mss_name}";
2751 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2752 eval ${_UNSET} mss_dir
;
2753 eval ${_UNSET} mss_ext
;
2754 eval ${_UNSET} mss_f
;
2755 eval ${_UNSET} mss_files
;
2756 eval ${_UNSET} mss_got_one
;
2757 eval ${_UNSET} mss_name
;
2758 eval ${_UNSET} mss_prefix
;
2759 eval ${_UNSET} mss_section
;
2760 eval "${return_good}";
2768 # check for files with extension in directories without extension
2771 mss_dir
="$(dirname_append "$d" "man
${mss_section}")";
2773 if obj mss_dir is_dir
2775 mss_prefix
="$(dirname_append "${mss_dir}" \
2776 "${mss_name}.${mss_section}${mss_ext}")";
2777 mss_files
="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2778 sed -e '\|not found|s|.*||'
2781 if obj mss_files is_not_empty
2783 # for f in $mss_files
2784 for f
in $
(eval set x
${mss_files}; shift; echo1
"$@")
2787 if obj mss_f is_file
2789 if is_yes
"${mss_got_one}"
2791 register_file
"${mss_f}";
2792 elif obj _MAN_ALL is_yes
2794 man_register_file
"${mss_f}" "${mss_name}";
2796 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2797 eval ${_UNSET} mss_dir
;
2798 eval ${_UNSET} mss_ext
;
2799 eval ${_UNSET} mss_f
;
2800 eval ${_UNSET} mss_files
;
2801 eval ${_UNSET} mss_got_one
;
2802 eval ${_UNSET} mss_name
;
2803 eval ${_UNSET} mss_prefix
;
2804 eval ${_UNSET} mss_section
;
2805 eval "${return_good}";
2814 if obj _MAN_ALL is_yes
&& is_yes
"${mss_got_one}"
2816 eval ${_UNSET} mss_dir
;
2817 eval ${_UNSET} mss_ext
;
2818 eval ${_UNSET} mss_f
;
2819 eval ${_UNSET} mss_files
;
2820 eval ${_UNSET} mss_got_one
;
2821 eval ${_UNSET} mss_name
;
2822 eval ${_UNSET} mss_prefix
;
2823 eval ${_UNSET} mss_section
;
2824 eval "${return_good}";
2826 eval ${_UNSET} mss_dir
;
2827 eval ${_UNSET} mss_ext
;
2828 eval ${_UNSET} mss_f
;
2829 eval ${_UNSET} mss_files
;
2830 eval ${_UNSET} mss_got_one
;
2831 eval ${_UNSET} mss_name
;
2832 eval ${_UNSET} mss_prefix
;
2833 eval ${_UNSET} mss_section
;
2834 eval "${return_bad}";
2835 } # man_search_section()
2838 ########################################################################
2841 # Setup the variables $_MAN_* needed for man page searching.
2844 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2845 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2846 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2847 # $_MAN_SEC, $_MAN_ALL
2848 # in/out: $_MAN_ENABLE
2850 # The precedence for the variables related to `man' is that of GNU
2853 # $LANG; overridden by
2854 # $LC_MESSAGES; overridden by
2855 # $LC_ALL; this has the same precedence as
2856 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2857 # $MANOPT; overridden by
2858 # the groffer command line options.
2860 # Variable prefix: ms
2864 func_check main_man_setup
= 0 "$@";
2866 if obj _MAN_IS_SETUP is_yes
2868 eval "${return_ok}";
2870 _MAN_IS_SETUP
='yes';
2872 if obj _MAN_ENABLE is_not_yes
2874 eval "${return_ok}";
2877 # determine basic path for man pages
2878 _MAN_PATH
="$(get_first_essential \
2879 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2881 if obj _MAN_PATH is_empty
2883 manpath_set_from_path
;
2885 _MAN_PATH
="$(path_clean "${_MAN_PATH}")";
2888 if obj _MAN_PATH is_empty
2890 if is_prog
'manpath'
2892 _MAN_PATH
="$(manpath 2>${_NULL_DEV})"; # not always available
2896 if obj _MAN_PATH is_empty
2899 eval "${return_ok}";
2902 _MAN_ALL
="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2904 if obj _MAN_ALL is_empty
2909 _MAN_SYS
="$(get_first_essential \
2910 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2911 ms_lang
="$(get_first_essential \
2912 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2914 case "${ms_lang}" in
2920 _MAN_LANG
="${ms_lang}";
2924 _MAN_LANG
="${ms_lang}";
2925 # get first two characters of $ms_lang
2926 _MAN_LANG2
="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')";
2930 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2932 manpath_add_lang_sys
; # this is very slow
2934 _MAN_SEC
="$(get_first_essential \
2935 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2937 if obj _MAN_PATH is_empty
2940 eval ${_UNSET} ms_lang
;
2941 eval "${return_ok}";
2944 _MAN_EXT
="$(get_first_essential \
2945 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2947 eval ${_UNSET} ms_lang
;
2948 eval "${return_ok}";
2952 ########################################################################
2953 landmark
'8: manpath_*()';
2954 ########################################################################
2956 ########################################################################
2957 # manpath_add_lang_sys ()
2959 # Add language and operating system specific directories to man path.
2964 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2965 # list of names of operating systems.
2966 # $_MAN_LANG and $_MAN_LANG2: each a single name
2967 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2968 # separated list of directories.
2970 # Variable prefix: mals
2972 manpath_add_lang_sys
()
2974 func_check manpath_add_lang_sys
= 0 "$@";
2975 if obj _MAN_PATH is_empty
2977 eval "${return_ok}";
2979 # twice test both sys and lang
2980 eval set x
"$(path_split "${_MAN_PATH}")";
2985 do # loop on man path directories
2986 mals_mp
="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2989 eval set x
"$(path_split "${mals_mp}")";
2993 do # loop on man path directories
2994 mals_mp
="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2997 _MAN_PATH
="$(path_chop "${mals_mp}")";
2999 eval ${_UNSET} mals_mp
;
3000 eval "${return_ok}";
3004 # To the directory in $1 append existing sys/lang subdirectories
3005 # Function is necessary to split the OS list.
3007 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
3008 # argument: 2: `man_path' and `dir'
3009 # output: colon-separated path of the retrieved subdirectories
3011 # Variable prefix: _mals
3013 _manpath_add_lang_sys_single
()
3015 func_check _manpath_add_lang_sys_single
= 2 "$@";
3018 eval set x
"$(list_from_split "${_MAN_SYS}" ',')";
3021 for d
in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
3023 _mals_dir
="$(dirname_append "${_mals_parent}" "$d")";
3025 if obj _mals_res path_not_contains
"${_mals_dir}" && \
3026 obj _mals_dir is_dir
3028 _mals_res
="${_mals_res}:${_mals_dir}";
3031 if path_not_contains
"${_mals_res}" "${_mals_parent}"
3033 _mals_res
="${_mals_res}:${_mals_parent}";
3035 path_chop
"${_mals_res}";
3036 eval ${_UNSET} _mals_dir
;
3037 eval ${_UNSET} _mals_parent
;
3038 eval ${_UNSET} _mals_res
;
3039 eval "${return_ok}";
3042 # end manpath_add_lang_sys ()
3045 ########################################################################
3046 # manpath_set_from_path ()
3048 # Determine basic search path for man pages from $PATH.
3050 # Return: `0' if a valid man path was retrieved.
3056 # Variable prefix: msfp
3058 manpath_set_from_path
()
3060 func_check manpath_set_from_path
= 0 "$@";
3064 # get a basic man path from $PATH
3065 if obj PATH is_not_empty
3067 eval set x
"$(path_split "${PATH}")";
3072 # delete the final `/bin' part
3073 msfp_base
="$(echo1 "$d" | sed -e 's|//*bin/*$||')";
3075 for e
in /share
/man
/man
3077 msfp_mandir
="${msfp_base}$e";
3078 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}"
3080 msfp_manpath
="${msfp_manpath}:${msfp_mandir}";
3086 # append some default directories
3087 for d
in /usr
/local
/share
/man
/usr
/local
/man \
3088 /usr
/share
/man
/usr
/man \
3089 /usr
/X11R
6/man
/usr
/openwin
/man \
3090 /opt
/share
/man
/opt
/man \
3091 /opt
/gnome
/man
/opt
/kde
/man
3094 if obj msfp_manpath path_not_contains
"${msfp_d}" && obj mfsp_d is_dir
3096 msfp_manpath
="${msfp_manpath}:${mfsp_d}";
3100 _MAN_PATH
="${msfp_manpath}";
3101 eval ${_UNSET} msfp_base
;
3102 eval ${_UNSET} msfp_d
;
3103 eval ${_UNSET} msfp_mandir
;
3104 eval ${_UNSET} msfp_manpath
;
3105 eval "${return_ok}";
3106 } # manpath_set_from_path()
3109 ########################################################################
3110 landmark
'9: obj_*()';
3111 ########################################################################
3113 ########################################################################
3114 # obj (<object> <call_name> <arg>...)
3116 # This works like a method (object function) call for an object.
3117 # Run "<call_name> $<object> <arg> ...".
3119 # The first argument represents an object whose data is given as first
3120 # argument to <call_name>().
3123 # <object>: variable name
3124 # <call_name>: a program or function name
3126 # Variable prefix: o
3130 func_check obj
'>=' 2 "$@";
3131 eval o_arg1
='"${'$1'}"';
3134 error
"obj(): function name is empty."
3140 eval "${o_func}"' "${o_arg1}" "$@"';
3142 eval ${_UNSET} o_arg1
;
3143 eval ${_UNSET} o_func
;
3144 eval "${return_var} $n";
3148 ########################################################################
3149 # obj_data (<object>)
3151 # Print the data of <object>, i.e. the content of $<object>.
3152 # For possible later extensions.
3155 # <object>: a variable name
3156 # Output: the data of <object>
3158 # Variable prefix: od
3162 func_check obj
'=' 1 "$@";
3165 error
"obj_data(): object name is empty."
3167 eval od_res
='"${'$1'}"';
3169 eval ${_UNSET} od_res
;
3170 eval "${return_ok}";
3174 ########################################################################
3175 # obj_from_output (<object> <call_name> <arg>...)
3177 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
3178 # function call to a global variable.
3181 # <object>: a variable name
3182 # <call_name>: the name of a function or program
3183 # <arg>: optional argument to <call_name>
3186 # Variable prefix: ofo
3190 func_check obj_from_output
'>=' 2 "$@";
3193 error
"res(): variable name is empty.";
3196 error
"res(): function name is empty."
3198 ofo_result_name
="$1";
3201 eval "${ofo_result_name}"'="$('"$@"')"';
3203 eval "${return_ok}";
3207 ########################################################################
3208 # obj_set (<object> <data>)
3210 # Set the data of <object>, i.e. call "$<object>=<data>".
3213 # <object>: a variable name
3219 func_check obj_set
'=' 2 "$@";
3222 error
"obj_set(): object name is empty."
3225 eval "${return_ok}";
3229 ########################################################################
3230 # path_chop (<path>)
3232 # Remove unnecessary colons from path.
3234 # Argument: 1, a colon separated path.
3235 # Output: path without leading, double, or trailing colons.
3239 func_check path_chop
= 1 "$@";
3241 # replace multiple colons by a single colon `:'
3242 # remove leading and trailing colons
3243 echo1
"$1" |
sed -e '
3248 eval "${return_ok}";
3252 ########################################################################
3253 # path_clean (<path>)
3255 # Remove non-existing directories from a colon-separated list.
3257 # Argument: 1, a colon separated path.
3258 # Output: colon-separated list of existing directories.
3260 # Variable prefix: pc
3264 func_check path_clean
= 1 "$@";
3265 if is_not_equal
"$#" 1
3267 error
'path_clean() needs 1 argument.';
3270 eval set x
"$(path_split "${pc_arg}")";
3277 if obj pc_i is_not_empty \
3278 && obj pc_res path_not_contains
"${pc_i}" \
3283 pc_res
="${pc_res}$(dirname_chop "${pc_i}")";
3287 pc_res
="${pc_res}:${pc_i}";
3293 eval ${_UNSET} pc_arg
;
3294 eval ${_UNSET} pc_i
;
3295 eval ${_UNSET} pc_res
;
3296 if path_chop
"${pc_res}"
3298 eval "${return_ok}";
3300 eval "${return_bad}";
3305 ########################################################################
3306 # path_contains (<path> <dir>)
3308 # Test whether `dir' is contained in `path', a list separated by `:'.
3310 # Arguments : 2 arguments.
3311 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3315 func_check path_contains
= 2 "$@";
3318 eval "${return_yes}";
3321 eval "${return_no}";
3324 eval "${return_ok}";
3328 ########################################################################
3329 # path_not_contains (<path> <dir>)
3331 # Test whether `dir' is not contained in colon separated `path'.
3333 # Arguments : 2 arguments.
3337 func_check path_not_contains
= 2 "$@";
3338 if path_contains
"$1" "$2"
3340 eval "${return_no}";
3342 eval "${return_yes}";
3344 eval "${return_ok}";
3348 ########################################################################
3349 # path_split (<path>)
3351 # In `path' escape white space and replace each colon by a space.
3353 # Arguments: 1: a colon-separated path
3354 # Output: the resulting list, process with `eval set'
3358 func_check path_split
= 1 "$@";
3359 list_from_split
"$1" ':';
3360 eval "${return_ok}";
3364 ########################################################################
3365 landmark
'10: register_*()';
3366 ########################################################################
3368 ########################################################################
3369 # register_file (<filename>)
3371 # Write a found file and register the title element.
3373 # Arguments: 1: a file name
3378 func_check register_file
= 1 "$@";
3381 error
'register_file(): file name is empty';
3383 if is_equal
"$1" '-'
3385 to_tmp
"${_TMP_STDIN}";
3386 register_title
'stdin';
3389 register_title
"$(base_name "$1")";
3392 eval "${return_ok}";
3396 ########################################################################
3397 # register_title (<filespec>)
3399 # Create title element from <filespec> and append to $_REGISTERED_TITLE
3401 # Globals: $_REGISTERED_TITLE (rw)
3403 # Variable prefix: rt
3407 func_check register_title
'=' 1 "$@";
3410 eval "${return_ok}";
3413 case "${_REGISTERED_TITLE}" in
3415 eval "${return_ok}";
3419 # remove directory part
3420 rt_title
="$(base_name "$1")";
3421 # replace space characters by `_'
3422 rt_title
="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')";
3423 # remove extension `.bz2'
3424 rt_title
="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')";
3425 # remove extension `.gz'
3426 rt_title
="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')";
3427 # remove extension `.Z'
3428 rt_title
="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')";
3431 if obj rt_title is_empty
3433 eval ${_UNSET} rt_title
;
3434 eval "${return_ok}";
3436 if obj _REGISTERED_TITLE is_empty
3438 _REGISTERED_TITLE
="${rt_title}";
3440 _REGISTERED_TITLE
="${_REGISTERED_TITLE} ${rt_title}";
3442 eval ${_UNSET} rt_title
;
3443 eval "${return_ok}";
3444 } # register_title()
3447 ########################################################################
3450 # Reset the variables that can be affected by options to their default.
3453 # Defined in section `Preset' after the rudimentary shell tests.
3456 ########################################################################
3457 # rm_file (<file_name>)
3459 # Remove file if $_DEBUG_KEEP_FILES allows it.
3461 # Globals: $_DEBUG_KEEP_FILES
3465 func_check rm_file
'=' 1 "$@";
3468 rm -f "$1" >${_NULL_DEV} 2>&1;
3472 eval "${return_bad}";
3474 eval "${return_good}";
3479 ########################################################################
3480 # rm_file_with_debug (<file_name>)
3482 # Remove file if $_DEBUG_KEEP_FILES allows it.
3484 # Globals: $_DEBUG_KEEP_FILES
3486 rm_file_with_debug
()
3488 func_check rm_file_with_debug
'=' 1 "$@";
3489 if obj _DEBUG_KEEP_FILES is_not_yes
3493 rm -f "$1" >${_NULL_DEV} 2>&1;
3498 eval "${return_bad}";
3500 eval "${return_good}";
3505 ########################################################################
3506 # rm_tree (<dir_name>)
3508 # Remove file if $_DEBUG_KEEP_FILES allows it.
3510 # Globals: $_DEBUG_KEEP_FILES
3514 func_check rm_tree
'=' 1 "$@";
3517 rm -f -r "$1" >${_NULL_DEV} 2>&1;
3521 eval "${return_bad}";
3523 eval "${return_good}";
3528 ########################################################################
3531 # Store standard input to temporary file (with decompression).
3533 # Variable prefix: ss
3535 if obj _HAS_COMPRESSION is_yes
3539 func_check save_stdin
'=' 0 "$@";
3540 ss_f
="${_TMP_DIR}"/INPUT
;
3542 cat_z
"${ss_f}" >"${_TMP_STDIN}";
3544 eval ${_UNSET} ss_f
;
3545 eval "${return_ok}";
3550 func_check save_stdin
= 0 "$@";
3551 cat >"${_TMP_STDIN}";
3552 eval "${return_ok}";
3557 ########################################################################
3558 # special_filespec ()
3560 # Handle special modes like whatis and apropos.
3564 func_check special_setup
'=' 0 "$@";
3565 if obj _OPT_APROPOS is_yes
3567 if obj _OPT_WHATIS is_yes
3570 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
3573 eval "${return_ok}";
3575 if obj _OPT_WHATIS is_yes
3579 eval "${return_ok}";
3583 ########################################################################
3586 # Handle special modes like whatis and apropos.
3590 func_check special_setup
'=' 0 "$@";
3591 if obj _OPT_APROPOS is_yes
3593 if obj _OPT_WHATIS is_yes
3596 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
3599 eval "${return_ok}";
3601 if obj _OPT_WHATIS is_yes
3605 eval "${return_ok}";
3609 ########################################################################
3610 landmark
'11: stack_*()';
3611 ########################################################################
3613 ########################################################################
3614 # string_contains (<string> <part>)
3616 # Test whether `part' is contained in `string'.
3618 # Arguments : 2 text arguments.
3619 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3623 func_check string_contains
'=' 2 "$@";
3626 eval "${return_yes}";
3629 eval "${return_no}";
3632 eval "${return_ok}";
3636 ########################################################################
3637 # string_not_contains (<string> <part>)
3639 # Test whether `part' is not substring of `string'.
3641 # Arguments : 2 text arguments.
3642 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3644 string_not_contains
()
3646 func_check string_not_contains
'=' 2 "$@";
3647 if string_contains
"$1" "$2"
3649 eval "${return_no}";
3651 eval "${return_yes}";
3653 eval "${return_ok}";
3657 ########################################################################
3658 landmark
'12: tmp_*()';
3659 ########################################################################
3661 ########################################################################
3664 # output the temporary cat file (the concatenation of all input)
3668 func_check tmp_cat
'=' 0 "$@";
3670 eval "${return_var}" "$?";
3674 ########################################################################
3675 # tmp_create (<suffix>?)
3677 # Create temporary file.
3679 # It's safe to use the shell process ID together with a suffix to
3680 # have multiple temporary files.
3682 # Globals: $_TMP_DIR
3684 # Output : name of created file
3686 # Variable prefix: tc
3690 func_check tmp_create
'<=' 1 "$@";
3691 # the output file does not have `,' as first character, so these are
3692 # different names from the output file.
3693 tc_tmp
="${_TMP_DIR}/,$1";
3696 eval ${_UNSET} tc_tmp
;
3697 eval "${return_ok}";
3701 ########################################################################
3702 # to_tmp (<filename>)
3704 # print file (decompressed) to the temporary cat file
3708 func_check to_tmp
'=' 1 "$@";
3709 if obj _TMP_CAT is_empty
3711 error
'to_tmp_line: $_TMP_CAT is not yet set';
3715 if obj _OPT_LOCATION is_yes
3719 if obj _OPT_WHATIS is_yes
3721 whatis_filename
"$1" >>"${_TMP_CAT}";
3723 cat_z
"$1" >>"${_TMP_CAT}";
3726 error
"to_tmp(): could not read file \`$1'.";
3728 eval "${return_ok}";
3732 ########################################################################
3733 # to_tmp_line ([<text>])
3735 # print line to the temporary cat file
3739 func_check to_tmp
'>=' 0 "$@";
3740 if obj _TMP_CAT is_empty
3742 error
'to_tmp_line: $_TMP_CAT is not yet set';
3744 echo1
"$*" >>"${_TMP_CAT}";
3745 eval "${return_ok}";
3749 ########################################################################
3752 # call function on signal 0
3756 func_check trap_set
'=' 0 "$@";
3757 trap 'clean_up' 0 2>${_NULL_DEV} ||
:;
3758 eval "${return_ok}";
3762 ########################################################################
3765 # disable trap on signal 0.
3769 func_check trap_unset
'=' 0 "$@";
3770 trap '' 0 2>${_NULL_DEV} ||
:;
3771 eval "${return_ok}";
3775 ########################################################################
3778 # print usage information to stderr; for groffer option --help.
3782 func_check usage
= 0 "$@";
3785 echo1
'Usage: groffer [option]... [filespec]...';
3788 Display roff files, standard input, and/or Unix manual pages with a X
3789 Window viewer or in several text modes. All input is decompressed
3790 on-the-fly with all formats that gzip can handle.
3792 "filespec" is one of
3793 "filename" name of a readable file
3794 "-" for standard input
3795 "man:name.n" man page "name" in section "n"
3796 "man:name" man page "name" in first section found
3797 "name.n" man page "name" in section "n"
3798 "name" man page "name" in first section found
3799 and some more (see groffer(1) for details).
3801 -h --help print this usage message.
3802 -Q --source output as roff source.
3803 -T --device=name pass to groff using output device "name".
3804 -v --version print version information.
3805 -V display the groff execution pipe instead of formatting.
3806 -X display with "gxditview" using groff -X.
3807 -Z --ditroff --intermediate-output
3808 generate groff intermediate output without
3809 post-processing and viewing, like groff -Z.
3810 All other short options are interpreted as "groff" formatting options.
3812 The most important groffer long options are
3814 --apropos=name start man's "apropos" program for "name".
3816 "apropos" for "name" in man's data sections 4, 5, 7.
3817 --apropos-devel=name
3818 "apropos" for "name" in development sections 2, 3, 9.
3819 --apropos-progs=name
3820 "apropos" for "name" in man's program sections 1, 6, 8.
3821 --auto choose mode automatically from the default mode list.
3822 --default reset all options to the default value.
3823 --default-modes=mode1,mode2,...
3824 set sequence of automatically tried modes.
3825 --dvi display in a viewer for TeX device independent format.
3826 --dvi-viewer=prog choose the viewer program for dvi mode.
3827 --groff process like groff, disable viewing features.
3828 --help display this helping output.
3829 --html display in a web browser.
3830 --html-viewer=program
3831 choose the web browser for html mode.
3832 --man check file parameters first whether they are man pages.
3833 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3834 choose display mode.
3835 --no-man disable man-page facility.
3836 --no-special disable --all, --apropos*, and --whatis
3837 --pager=program preset the paging program for tty mode.
3838 --pdf display in a PDF viewer.
3839 --pdf-viewer=prog choose the viewer program for pdf mode.
3840 --ps display in a Postscript viewer.
3841 --ps-viewer=prog choose the viewer program for ps mode.
3842 --shell=program specify a shell under which to run groffer2.sh.
3843 --text output in a text device without a pager.
3844 --tty display with a pager on text terminal even when in X.
3845 --tty-viewer=prog select a pager for tty mode; same as --pager.
3846 --whatis display the file name and description of man pages
3847 --www same as --html.
3848 --www-viewer=prog same as --html-viewer
3849 --x --X display with "gxditview" using an X* device.
3850 --x-viewer=prog choose viewer program for x mode (X mode).
3851 --X-viewer=prog same as "--xviewer".
3853 Development options that are not useful for normal usage:
3854 --debug, --debug-all, --debug-keep, --debug-lm, --debug-params,
3855 --debug-shell, --debug-stacks, --debug-tmpdir, --debug-user,
3856 --do-nothing, --print=text
3858 Viewer programs for the different modes that run on the terminal:
3859 --dvi-viewer-tty=prog, --html-viewer-tty=prog, --pdf-viewer-tty=prog,
3860 --ps-viewer-tty=prog, --tty-viewer-tty, --X-viewer-tty=prog,
3861 --x-viewer-tty=prog, --www-viewer-tty=prog
3863 The usual X Windows toolkit options transformed into GNU long options:
3864 --background=color, --bd=size, --bg=color, --bordercolor=color,
3865 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3866 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3867 --resolution=dpi, --rv, --title=text, --xrm=resource
3869 Long options of GNU "man":
3870 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3871 --local-file=name, --location, --manpath=dir1:dir2:...,
3872 --sections=s1:s2:..., --systems=s1,s2,..., --where, ...
3875 eval "${return_ok}";
3879 ########################################################################
3882 # print version information to stderr
3886 func_check version
= 0 "$@";
3887 echo1
"groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3888 # also display groff's version, but not the called subprograms
3889 groff -v 2>&1 |
sed -e '/^ *$/q' |
sed -e '1s/^/is part of /';
3890 eval "${return_ok}";
3894 ########################################################################
3895 # warning (<string>)
3897 # Print warning to stderr
3901 echo2
"warning: $*";
3905 ########################################################################
3906 # whatis_filename (<filename>)
3908 # Interpret <filename> as a man page and display its `whatis'
3909 # information as a fragment written in the groff language.
3911 # Variable prefix: wf
3915 func_check whatis_filename
= 1 "$@";
3917 if obj wf_arg is_not_file
3919 error
"whatis_filename(): argument is not a readable file."
3921 wf_dot
='^\.'"${_SPACE_SED}"'*';
3922 if obj _FILESPEC_ARG is_equal
'-'
3927 \f[CR]${wf_arg}\f[]:
3931 # get the parts of the file name
3932 wf_name
="$(base_name $1)";
3933 wf_section
="$(echo1 $1 | sed -n -e '
3934 s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p
3936 if obj wf_section is_not_empty
3938 case "${wf_name}" in
3949 wf_name
="$(echo1 ${wf_name} | sed -e '
3950 s/^\(.*\)\.'${wf_section}'.*$/\1/
3955 # traditional man style; grep the line containing `.TH' macro, if any
3956 wf_res
="$(cat_z "$1" | sed -e '
3961 if obj wf_res is_not_empty
3962 then # traditional man style
3963 # get the first line after the first `.SH' macro, by
3964 # - delete up to first .SH;
3965 # - print all lines before the next .SH;
3967 wf_res
="$(cat_z "$1" | sed -n -e '
3968 1,/'"${wf_dot}"'SH/d
3973 if obj wf_section is_not_empty
3976 ${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*)
3985 wf_res
="$(obj wf_res echo1 | sed -e '
3986 s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/
3992 eval ${_UNSET} wf_arg
;
3993 eval ${_UNSET} wf_dot
;
3994 eval ${_UNSET} wf_name
;
3995 eval ${_UNSET} wf_res
;
3996 eval ${_UNSET} wf_section
;
3997 eval "${return_ok}";
4000 # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
4001 wf_res
="$(cat_z "$1" | sed -n -e '/'"${wf_dot}"'Nd /s///p')";
4003 if obj wf_res is_not_empty
4004 then # BSD doc style
4005 if obj wf_section is_not_empty
4007 wf_res
="$(obj wf_res echo1 | sed -n -e '
4008 s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p
4013 eval ${_UNSET} wf_arg
;
4014 eval ${_UNSET} wf_dot
;
4015 eval ${_UNSET} wf_name
;
4016 eval ${_UNSET} wf_res
;
4017 eval ${_UNSET} wf_section
;
4018 eval "${return_ok}";
4020 echo1
'is not a man page';
4022 eval ${_UNSET} wf_arg
;
4023 eval ${_UNSET} wf_dot
;
4024 eval ${_UNSET} wf_name
;
4025 eval ${_UNSET} wf_res
;
4026 eval ${_UNSET} wf_section
;
4027 eval "${return_bad}";
4031 ########################################################################
4032 # whatis_filespec ()
4034 # Print the filespec name as .SH to the temporary cat file.
4038 func_check whatis_filespec
'=' 0 "$@";
4039 if obj _OPT_WHATIS is_yes
4042 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
4045 eval "${return_ok}";
4049 ########################################################################
4052 # Print the whatis header to the temporary cat file.
4056 func_check whatis_header
'=' 0 "$@";
4057 if obj _OPT_WHATIS is_yes
4059 to_tmp_line
'.TH GROFFER WHATIS';
4061 eval "${return_ok}";
4065 ########################################################################
4066 # where_is (<program>)
4068 # Output path of a program if in $PATH.
4070 # Arguments : >=1 (empty allowed)
4071 # more args are ignored, this allows to specify progs with arguments
4072 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
4074 # Variable prefix: w
4078 func_check where_is
'>=' 1 "$@";
4080 if obj w_arg is_empty
4082 eval ${_UNSET} w_arg
;
4083 eval "${return_bad}";
4087 eval ${_UNSET} w_arg
;
4088 eval ${_UNSET} w_file
;
4089 if test -f "${w_arg}" && test -x "${w_arg}"
4091 eval "${return_ok}";
4093 eval "${return_bad}";
4097 eval set x
"$(path_split "${PATH}")";
4103 */) w_file
=${p}${w_arg}; ;;
4104 *) w_file
=${p}/${w_arg}; ;;
4106 if test -f "${w_file}" && test -x "${w_file}"
4109 eval ${_UNSET} w_arg
;
4110 eval ${_UNSET} w_file
;
4111 eval "${return_ok}";
4114 eval ${_UNSET} w_arg
;
4115 eval ${_UNSET} w_file
;
4116 eval "${return_bad}";
4120 ########################################################################
4122 ########################################################################
4124 # The main area contains the following parts:
4125 # - main_init(): initialize temporary files and set exit trap
4126 # - main_parse_MANOPT(): parse $MANOPT
4127 # - main_parse_args(): argument parsing
4128 # - main_set_mode (): determine the display mode
4129 # - main_do_fileargs(): process filespec arguments
4130 # - main_set_resources(): setup X resources
4131 # - main_display(): do the displaying
4132 # - main(): the main function that calls all main_*()
4135 #######################################################################
4138 # set exit trap and create temporary files
4140 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
4142 # Variable prefix: mi
4146 func_check main_init
= 0 "$@";
4147 # call clean_up() on shell termination.
4150 # create temporary directory
4153 for d
in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
4154 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
4157 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
4158 obj mi_dir is_not_writable
4165 _TMP_DIR
="${mi_dir}";
4168 _TMP_DIR
="${mi_dir}"'/';
4171 _TMP_DIR
="${_TMP_DIR}groffer${_PROCESS_ID}";
4172 if obj _TMP_DIR rm_tree
4176 mi_tdir_
="${_TMP_DIR}"_
;
4178 mi_tdir_n
="${mi_tdir_}${mi_n}";
4179 while obj mi_tdir_n is_existing
4181 if obj mi_tdir_n rm_tree
4183 # directory could not be removed
4184 mi_n
="$(expr "${mi_n}" + 1)";
4185 mi_tdir_n
="${mi_tdir_}${mi_n}";
4189 _TMP_DIR
="${mi_tdir_n}";
4191 eval mkdir
"${_TMP_DIR}";
4192 if is_not_equal
"$?" 0
4194 obj _TMP_DIR rm_tree
;
4198 if obj _TMP_DIR is_dir
&& obj _TMP_DIR is_writable
4200 # $_TMP_DIR can now be used as temporary directory
4203 obj _TMP_DIR rm_tree
;
4207 if obj _TMP_DIR is_empty
4210 Couldn't create a directory for storing temporary files.";
4212 if obj _DEBUG_PRINT_TMPDIR is_yes
4214 echo2
"temporary directory: ${_TMP_DIR}";
4217 _TMP_CAT
="$(tmp_create groffer_cat)";
4218 _TMP_STDIN
="$(tmp_create groffer_input)";
4221 eval ${_UNSET} mi_dir
;
4222 eval ${_UNSET} mi_n
;
4223 eval ${_UNSET} mi_tdir_
;
4224 eval ${_UNSET} mi_tdir_n
;
4225 eval "${return_ok}";
4229 ########################################################################
4230 # main_parse_MANOPT ()
4232 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
4233 # string; found man arguments can be overwritten by the command line.
4236 # in: $MANOPT, $_OPTS_MANOPT_*
4239 # Variable prefix: mpm
4243 func_check main_parse_MANOPT
= 0 "$@";
4245 if obj MANOPT is_not_empty
4247 # Delete leading and final spaces
4248 MANOPT
="$(echo1 "${MANOPT}" | sed -e '
4249 s/^'"${_SPACE_SED}"'*//
4250 s/'"${_SPACE_SED}"'*$//
4254 if obj MANOPT is_empty
4256 eval "${return_ok}";
4260 # add arguments in $MANOPT by mapping them to groffer options
4261 eval set x
"$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
4264 until test "$#" -le 0 || is_equal
"$1" '--'
4268 case "${mpm_opt}" in
4270 list_append mpm_list
'--ascii';
4273 list_append mpm_list
'--all';
4283 # undo all man options so far
4287 list_append mpm_list
'--extension';
4291 list_append mpm_list
'--whatis';
4299 # groffer's --apropos takes an argument, but man's does not, so
4306 list_append mpm_list
'--locale' "$1";
4310 list_append mpm_list
'--systems' "$1";
4314 list_append mpm_list
'--manpath' "$1";
4322 list_append mpm_list
'--pager' "$1";
4330 list_append mpm_list
'--sections' "$1";
4338 list_append mpm_list
'-T' "$1";
4348 -w|
--where|
--location)
4349 list_append mpm_list
'--location';
4354 # ignore all other options
4358 # prepend $mpm_list to the command line
4359 if obj mpm_list is_not_empty
4361 eval set x
"${mpm_list}" '"$@"';
4365 eval ${_UNSET} mpm_list
;
4366 eval ${_UNSET} mpm_opt
;
4367 eval "${return_ok}";
4368 } # main_parse_MANOPT()
4371 ########################################################################
4372 # main_parse_args (<command_line_args>*)
4374 # Parse arguments; process options and filespec parameters
4376 # Arguments: pass the command line arguments unaltered.
4379 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
4381 # Variable prefix: mpa
4385 func_check main_parse_args
'>=' 0 "$@";
4386 _ALL_PARAMS
="$(list_from_cmdline _OPTS_CMDLINE "$@
")";
4388 if obj _DEBUG_PRINT_PARAMS is_yes
4390 echo2
"parameters: ${_ALL_PARAMS}";
4392 eval set x
"${_ALL_PARAMS}";
4395 # By the call of `eval', unnecessary quoting was removed. So the
4396 # positional shell parameters ($1, $2, ...) are now guaranteed to
4397 # represent an option or an argument to the previous option, if any;
4398 # then a `--' argument for separating options and
4399 # parameters; followed by the filespec parameters if any.
4401 # Note, the existence of arguments to options has already been checked.
4402 # So a check for `$#' or `--' should not be done for arguments.
4404 until test "$#" -le 0 || is_equal
"$1" '--'
4406 mpa_opt
="$1"; # $mpa_opt is fed into the option handler
4408 case "${mpa_opt}" in
4413 -Q|
--source) # output source code (`Quellcode').
4416 -T|
--device|
--troff-device) # device; arg
4418 _check_device_with_mode
;
4428 -Z|
--ditroff|
--intermediate-output) # groff intermediate output
4438 # delete leading `-'
4439 mpa_optchar
="$(echo1 "${mpa_opt}" | sed -e 's/^-//')";
4441 if list_has _OPTS_GROFF_SHORT_NA
"${mpa_optchar}"
4443 list_append _ADDOPTS_GROFF
"${mpa_opt}";
4444 elif list_has _OPTS_GROFF_SHORT_ARG
"${mpa_optchar}"
4446 list_append _ADDOPTS_GROFF
"${mpa_opt}" "$1";
4449 error
"main_parse_args(): Unknown option : \`$1'";
4455 --apropos) # run `apropos'
4457 _APROPOS_SECTIONS
='';
4460 --apropos-data) # run `apropos' for data sections
4462 _APROPOS_SECTIONS
='457';
4465 --apropos-devel) # run `apropos' for development sections
4467 _APROPOS_SECTIONS
='239';
4470 --apropos-progs) # run `apropos' for program sections
4472 _APROPOS_SECTIONS
='168';
4476 list_append _ADDOPTS_GROFF
'-mtty-char';
4477 if obj _OPT_MODE is_empty
4482 --auto) # the default automatic mode
4485 --bd) # border color for viewers, arg;
4489 --bg|
--backgroud) # background color for viewers, arg;
4493 --bw) # border width for viewers, arg;
4497 --debug|
--debug-all|
--debug-keep|
--debug-lm|
--debug-params|\
4498 --debug-shell|
--debug-stacks|
--debug-tmpdir|
--debug-user)
4499 # debug is handled at the beginning
4502 --default) # reset variables to default
4505 --default-modes) # sequence of modes in auto mode; arg
4506 _OPT_DEFAULT_MODES
="$1";
4509 --display) # set X display, arg
4514 _OPT_DO_NOTHING
='yes';
4522 --dvi-viewer) # viewer program for dvi mode; arg
4523 _VIEWER_TERMINAL
='no';
4524 _OPT_VIEWER_DVI
="$1";
4527 --dvi-viewer-tty) # viewer program for dvi mode in tty; arg
4528 _VIEWER_TERMINAL
='yes';
4529 _OPT_VIEWER_DVI
="$1";
4532 --extension) # the extension for man pages, arg
4533 _OPT_EXTENSION
="$1";
4536 --fg|
--foreground) # foreground color for viewers, arg;
4540 --fn|
--font) # set font for viewers, arg;
4544 --geometry) # window geometry for viewers, arg;
4551 --html|
--www) # display with web browser
4554 --html-viewer|
--www-viewer) # viewer program for html mode; arg
4555 _VIEWER_TERMINAL
='no';
4556 _OPT_VIEWER_HTML
="$1";
4559 --html-viewer-tty|
--www-viewer-tty) # viewer for html mode in tty; arg
4560 _VIEWER_TERMINAL
='yes';
4561 _OPT_VIEWER_HTML
="$1";
4564 --iconic) # start viewers as icons
4567 --locale) # set language for man pages, arg
4568 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
4572 --local-file) # force local files; same as `--no-man'
4576 --location|
--where) # print file locations to stderr
4577 _OPT_LOCATION
='yes';
4579 --man) # force all file params to be man pages
4583 --manpath) # specify search path for man pages, arg
4584 # arg is colon-separated list of directories
4588 --mode) # display mode
4591 case "${mpa_arg}" in
4592 auto|
'') # search mode automatically among default
4595 groff) # pass input to plain groff
4598 html|www
) # display with a web browser
4601 dvi
) # display with xdvi viewer
4607 pdf
) # display with PDF viewer
4613 ps
) # display with Postscript viewer
4619 text
) # output on terminal
4622 tty
) # output on terminal
4625 X|x
) # output on X roff viewer
4631 Q|
source) # display source code
4635 error
"main_parse_args(): unknown mode ${mpa_arg}";
4639 --no-location) # disable former call to `--location'
4640 _OPT_LOCATION
='yes';
4642 --no-man) # disable search for man pages
4643 # the same as --local-file
4647 --no-special) # disable some special former calls
4652 --pager|
--tty-viewer|
--tty-viewer-tty)
4653 # set paging program for tty mode, arg
4654 _VIEWER_TERMINAL
='yes';
4664 --pdf-viewer) # viewer program for ps mode; arg
4665 _VIEWER_TERMINAL
='no';
4666 _OPT_VIEWER_PDF
="$1";
4669 --pdf-viewer-tty) # viewer program for ps mode in tty; arg
4670 _VIEWER_TERMINAL
='yes';
4671 _OPT_VIEWER_PDF
="$1";
4674 --print) # for argument test
4684 --ps-viewer) # viewer program for ps mode; arg
4685 _VIEWER_TERMINAL
='no';
4686 _OPT_VIEWER_PS
="$1";
4689 --ps-viewer-tty) # viewer program for ps mode in tty; arg
4690 _VIEWER_TERMINAL
='yes';
4691 _OPT_VIEWER_PS
="$1";
4694 --resolution) # set resolution for X devices, arg
4697 case "${mpa_arg}" in
4705 error
"main_parse_args(): \
4706 only resoutions of 75 or 100 dpi are supported";
4709 _OPT_RESOLUTION
="${mpa_dpi}";
4714 --sections) # specify sections for man pages, arg
4715 # arg is colon-separated list of section names
4720 # already done during the first run; so ignore the argument
4723 --systems) # man pages for different OS's, arg
4724 # argument is a comma-separated list
4728 --text) # text mode without pager
4731 --title) # title for X viewers; arg
4735 --tty) # tty mode, text with pager
4738 --text-device|
--tty-device) # device for tty mode; arg
4739 _OPT_TEXT_DEVICE
="$1";
4753 --xrm) # pass X resource string, arg;
4754 list_append _OPT_XRM
"$1";
4757 --x-viewer|
--X-viewer) # viewer program for x mode; arg
4758 _VIEWER_TERMINAL
='no';
4762 --x-viewer-tty|
--X-viewer-tty) # viewer program for x mode in tty; arg
4763 _VIEWER_TERMINAL
='yes';
4768 error
'main_parse_args(): error on argument parsing : '"\`$*'";
4772 shift; # remove `--' argument
4774 if obj _OPT_DO_NOTHING is_yes
4779 # Remaining arguments are file names (filespecs).
4780 # Save them to list $_FILEARGS
4782 then # use "-" for standard input
4787 list_append _FILEARGS
"$@";
4788 if list_has _FILEARGS
'-'
4792 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4793 eval ${_UNSET} mpa_arg
;
4794 eval ${_UNSET} mpa_dpi
;
4795 eval ${_UNSET} mpa_opt
;
4796 eval ${_UNSET} mpa_optchar
;
4797 eval "${return_ok}";
4798 } # main_parse_args()
4801 # Called from main_parse_args() because double `case' is not possible.
4802 # Globals: $_OPT_DEVICE, $_OPT_MODE
4803 _check_device_with_mode
()
4805 func_check _check_device_with_mode
= 0 "$@";
4806 case "${_OPT_DEVICE}" in
4809 eval "${return_ok}";
4813 eval "${return_ok}";
4817 eval "${return_ok}";
4821 eval "${return_ok}";
4823 ascii|cp1047|latin1|utf8
)
4824 if obj _OPT_MODE is_not_equal text
4826 _OPT_MODE
=tty
; # default text mode
4828 eval "${return_ok}";
4832 eval "${return_ok}";
4834 *) # unknown device, go to groff mode
4836 eval "${return_ok}";
4839 eval "${return_error}";
4840 } # _check_device_with_mode() of main_parse_args()
4843 ########################################################################
4846 # Determine the display mode.
4849 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4850 # out: $_DISPLAY_MODE
4852 # Variable prefix: msm
4856 func_check main_set_mode
= 0 "$@";
4859 if obj _OPT_DISPLAY is_not_empty
4861 DISPLAY
="${_OPT_DISPLAY}";
4864 if obj _OPT_V is_yes
4866 list_append _ADDOPTS_GROFF
'-V';
4868 if obj _OPT_Z is_yes
4870 _DISPLAY_MODE
='groff';
4871 list_append _ADDOPTS_GROFF
'-Z';
4873 if obj _OPT_MODE is_equal
'groff'
4875 _DISPLAY_MODE
='groff';
4877 if obj _DISPLAY_MODE is_equal
'groff'
4879 eval ${_UNSET} msm_modes
;
4880 eval ${_UNSET} msm_viewer
;
4881 eval ${_UNSET} msm_viewers
;
4882 eval "${return_ok}";
4885 if obj _OPT_MODE is_equal
'source'
4887 _DISPLAY_MODE
='source';
4888 eval ${_UNSET} msm_modes
;
4889 eval ${_UNSET} msm_viewer
;
4890 eval ${_UNSET} msm_viewers
;
4891 eval "${return_ok}";
4894 case "${_OPT_MODE}" in
4895 '') # automatic mode
4896 case "${_OPT_DEVICE}" in
4900 error_user
"no X display found for device ${_OPT_DEVICE}";
4903 eval ${_UNSET} msm_modes
;
4904 eval ${_UNSET} msm_viewer
;
4905 eval ${_UNSET} msm_viewers
;
4906 eval "${return_ok}";
4908 ascii|cp1047|latin1|utf8
)
4909 if obj _DISPLAY_MODE is_not_equal
'text'
4911 _DISPLAY_MODE
='tty';
4913 eval ${_UNSET} msm_modes
;
4914 eval ${_UNSET} msm_viewer
;
4915 eval ${_UNSET} msm_viewers
;
4916 eval "${return_ok}";
4921 _DISPLAY_MODE
='tty';
4922 eval ${_UNSET} msm_modes
;
4923 eval ${_UNSET} msm_viewer
;
4924 eval ${_UNSET} msm_viewers
;
4925 eval "${return_ok}";
4928 if obj _OPT_DEFAULT_MODES is_empty
4930 msm_modes
="${_DEFAULT_MODES}";
4932 msm_modes
="${_OPT_DEFAULT_MODES}";
4936 _DISPLAY_MODE
='text';
4937 eval ${_UNSET} msm_modes
;
4938 eval ${_UNSET} msm_viewer
;
4939 eval ${_UNSET} msm_viewers
;
4940 eval "${return_ok}";
4943 _DISPLAY_MODE
='tty';
4944 eval ${_UNSET} msm_modes
;
4945 eval ${_UNSET} msm_viewer
;
4946 eval ${_UNSET} msm_viewers
;
4947 eval "${return_ok}";
4950 _DISPLAY_MODE
='html';
4951 msm_modes
="${_OPT_MODE}";
4953 *) # display mode was given
4956 error_user
"You must be in X Window for ${_OPT_MODE} mode.";
4958 msm_modes
="${_OPT_MODE}";
4962 # only viewer modes are left
4963 eval set x
"$(list_from_split "${msm_modes}" ',')";
4966 while test "$#" -gt 0
4972 if obj _OPT_VIEWER_DVI is_not_empty
4974 msm_viewer
="${_OPT_VIEWER_DVI}";
4976 msm_viewer
="$(_get_first_prog "$_VIEWER_DVI}")";
4979 if obj msm_viewer is_empty
4981 error
'No viewer for dvi mode available.';
4983 if is_not_equal
"$?" 0
4987 _DISPLAY_PROG
="${msm_viewer}";
4988 _DISPLAY_MODE
="dvi";
4989 eval ${_UNSET} msm_modes
;
4990 eval ${_UNSET} msm_viewer
;
4991 eval ${_UNSET} msm_viewers
;
4992 eval "${return_ok}";
4995 if obj _OPT_VIEWER_HTML is_not_empty
4997 msm_viewer
="${_OPT_VIEWER_HTML}";
5001 msm_viewers
="${_VIEWER_HTML_X}";
5003 msm_viewers
="${_VIEWER_HTML_TTY}";
5005 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
5008 if obj msm_viewer is_empty
5010 error
'No viewer for html mode available.';
5012 if is_not_equal
"$?" 0
5016 _DISPLAY_PROG
="${msm_viewer}";
5018 eval ${_UNSET} msm_modes
;
5019 eval ${_UNSET} msm_viewer
;
5020 eval ${_UNSET} msm_viewers
;
5021 eval "${return_ok}";
5024 if obj _OPT_VIEWER_PDF is_not_empty
5026 msm_viewer
="${_OPT_VIEWER_PDF}";
5028 msm_viewer
="$(_get_first_prog "${_VIEWER_PDF}")";
5031 if obj msm_viewer is_empty
5033 error
'No viewer for pdf mode available.';
5035 if is_not_equal
"$?" 0
5039 _DISPLAY_PROG
="${msm_viewer}";
5040 _DISPLAY_MODE
="pdf";
5041 eval ${_UNSET} msm_modes
;
5042 eval ${_UNSET} msm_viewer
;
5043 eval ${_UNSET} msm_viewers
;
5044 eval "${return_ok}";
5047 if obj _OPT_VIEWER_PS is_not_empty
5049 msm_viewer
="${_OPT_VIEWER_PS}";
5051 msm_viewer
="$(_get_first_prog "${_VIEWER_PS}")";
5054 if obj msm_viewer is_empty
5056 error
'No viewer for ps mode available.';
5058 if is_not_equal
"$?" 0
5062 _DISPLAY_PROG
="${msm_viewer}";
5064 eval ${_UNSET} msm_modes
;
5065 eval ${_UNSET} msm_viewer
;
5066 eval ${_UNSET} msm_viewers
;
5067 eval "${return_ok}";
5070 _DISPLAY_MODE
='text';
5071 eval ${_UNSET} msm_modes
;
5072 eval ${_UNSET} msm_viewer
;
5073 eval ${_UNSET} msm_viewers
;
5074 eval "${return_ok}";
5077 _DISPLAY_MODE
='tty';
5078 eval ${_UNSET} msm_modes
;
5079 eval ${_UNSET} msm_viewer
;
5080 eval ${_UNSET} msm_viewers
;
5081 eval "${return_ok}";
5084 if obj _OPT_VIEWER_X is_not_empty
5086 msm_viewer
="${_OPT_VIEWER_X}";
5088 msm_viewer
="$(_get_first_prog "${_VIEWER_X}")";
5091 if obj msm_viewer is_empty
5093 error
'No viewer for x mode available.';
5095 if is_not_equal
"$?" 0
5099 _DISPLAY_PROG
="${msm_viewer}";
5101 eval ${_UNSET} msm_modes
;
5102 eval ${_UNSET} msm_viewer
;
5103 eval ${_UNSET} msm_viewers
;
5104 eval "${return_ok}";
5108 eval ${_UNSET} msm_modes
;
5109 eval ${_UNSET} msm_viewer
;
5110 eval ${_UNSET} msm_viewers
;
5111 eval "${return_ok}";
5115 eval ${_UNSET} msm_modes
;
5116 eval ${_UNSET} msm_viewer
;
5117 eval ${_UNSET} msm_viewers
;
5118 error_user
"No suitable display mode found.";
5122 # _get_first_prog (<proglist>)
5124 # Retrieve first argument that represents an existing program in $PATH.
5125 # Local function for main_set_mode().
5127 # Arguments: 1; a comma-separated list of commands (with options),
5130 # Return : `1' if none found, `0' if found.
5131 # Output : the argument that succeded.
5133 # Variable prefix: _gfp
5139 error
"_get_first_prog() needs 1 argument.";
5145 eval set x
"$(list_from_split "$1" ',')";
5151 if obj _gfp_i is_empty
5155 if eval is_prog
"$(get_first_essential ${_gfp_i})"
5159 eval ${_UNSET} _gfp_i
;
5163 eval ${_UNSET} _gfp_i
;
5165 } # _get_first_prog() of main_set_mode()
5168 #######################################################################
5169 # main_do_fileargs ()
5171 # Process filespec arguments in $_FILEARGS.
5174 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
5176 # Variable prefix: mdfa
5180 func_check main_do_fileargs
= 0 "$@";
5182 eval set x
"${_FILEARGS}";
5184 eval ${_UNSET} _FILEARGS
;
5185 # temporary storage of all input to $_TMP_CAT
5186 while test "$#" -ge 2
5188 # test for `s name' arguments, with `s' a 1-char standard section
5192 case "${mdfa_filespec}" in
5198 if obj _OPT_APROPOS is_yes
5206 if obj _OPT_APROPOS is_yes
5211 if list_has_not _MAN_AUTO_SEC_LIST
"${mdfa_filespec}"
5214 do_filearg
"${mdfa_filespec}"
5218 _FILESPEC_ARG
="${_FILESPEC_ARG} $1";
5220 case "${mdfa_name}" in
5221 */*|man
:*|
*\
(*\
)|
*.
"${mdfa_filespec}")
5222 do_filearg
"${mdfa_filespec}"
5227 if do_filearg
"man:${mdfa_name}(${mdfa_filespec})"
5231 do_filearg
"${mdfa_filespec}"
5237 if obj _OPT_APROPOS is_yes
5241 do_filearg
"${mdfa_filespec}"
5245 done; # end of `s name' test
5246 while test "$#" -gt 0
5252 if obj _OPT_APROPOS is_yes
5256 do_filearg
"${mdfa_filespec}"
5258 obj _TMP_STDIN rm_file_with_debug
;
5259 eval ${_UNSET} mdfa_filespec
;
5260 eval ${_UNSET} mdfa_name
;
5261 eval "${return_ok}";
5262 } # main_do_fileargs()
5265 ########################################################################
5266 # main_set_resources ()
5268 # Determine options for setting X resources with $_DISPLAY_PROG.
5270 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
5272 # Variable prefix: msr
5274 main_set_resources
()
5276 func_check main_set_resources
= 0 "$@";
5277 # $msr_prog viewer program
5278 # $msr_rl resource list
5279 msr_title
="$(get_first_essential \
5280 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
5282 _OUTPUT_FILE_NAME
='';
5283 eval set x
"${msr_title}";
5285 until is_equal
"$#" 0
5293 msr_n
="$(echo1 "$1" | sed -e 's/^,,*//')";
5297 if obj msr_n is_empty
5301 if obj _OUTPUT_FILE_NAME is_not_empty
5303 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}"',';
5305 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}${msr_n}";
5308 case "${_OUTPUT_FILE_NAME}" in
5310 _OUTPUT_FILE_NAME
='-';
5313 error
"main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
5316 _OUTPUT_FILE_NAME
="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
5318 if obj _DISPLAY_PROG is_empty
5319 then # for example, for groff mode
5321 eval ${_UNSET} msr_n
;
5322 eval ${_UNSET} msr_prog
;
5323 eval ${_UNSET} msr_rl
;
5324 eval ${_UNSET} msr_title
;
5325 eval "${return_ok}";
5328 eval set x
"${_DISPLAY_PROG}";
5330 msr_prog
="$(base_name "$1")";
5335 if obj _DISPLAY_PROG is_empty
5339 _DISPLAY_ARGS
="$* ${_DISPLAY_ARGS}";
5343 if obj _OPT_BD is_not_empty
5345 case "${msr_prog}" in
5346 ghostview|gv|gxditview|xditview|xdvi
)
5347 list_append msr_rl
'-bd' "${_OPT_BD}";
5351 if obj _OPT_BG is_not_empty
5353 case "${msr_prog}" in
5354 ghostview|gv|gxditview|xditview|xdvi
)
5355 list_append msr_rl
'-bg' "${_OPT_BG}";
5358 list_append msr_rl
'--bg' "${_OPT_BG}";
5361 list_append msr_rl
'-papercolor' "${_OPT_BG}";
5365 if obj _OPT_BW is_not_empty
5367 case "${msr_prog}" in
5368 ghostview|gv|gxditview|xditview|xdvi
)
5369 _list_append msr_rl
'-bw' "${_OPT_BW}";
5373 if obj _OPT_FG is_not_empty
5375 case "${msr_prog}" in
5376 ghostview|gv|gxditview|xditview|xdvi
)
5377 list_append msr_rl
'-fg' "${_OPT_FG}";
5380 list_append msr_rl
'--fg' "${_OPT_FG}";
5384 if is_not_empty
"${_OPT_FN}"
5386 case "${msr_prog}" in
5387 ghostview|gv|gxditview|xditview|xdvi
)
5388 list_append msr_rl
'-fn' "${_OPT_FN}";
5391 list_append msr_rl
'--fn' "${_OPT_FN}";
5395 if is_not_empty
"${_OPT_GEOMETRY}"
5397 case "${msr_prog}" in
5398 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
5399 list_append msr_rl
'-geometry' "${_OPT_GEOMETRY}";
5402 list_append msr_rl
'--geometry' "${_OPT_GEOMETRY}";
5406 if is_empty
"${_OPT_RESOLUTION}"
5408 _OPT_RESOLUTION
="${_DEFAULT_RESOLUTION}";
5409 case "${msr_prog}" in
5411 list_append msr_rl
'-resolution' "${_DEFAULT_RESOLUTION}";
5414 case "${_DEFAULT_RESOLUTION}" in
5417 list_append msr_rl
'-z' '104';
5420 list_append msr_rl
'-z' '139';
5426 case "${msr_prog}" in
5427 ghostview|gv|gxditview|xditview|xdvi
)
5428 list_append msr_rl
'-resolution' "${_OPT_RESOLUTION}";
5431 case "${_OPT_RESOLUTION}" in
5433 list_append msr_rl
'-z' '104';
5434 # '100' corresponds to 72dpi
5437 list_append msr_rl
'-z' '139';
5443 if is_yes
"${_OPT_ICONIC}"
5445 case "${msr_prog}" in
5446 ghostview|gv|gxditview|xditview|xdvi
)
5447 list_append msr_rl
'-iconic';
5451 if is_yes
"${_OPT_RV}"
5453 case "${msr_prog}" in
5454 ghostview|gv|gxditview|xditview|xdvi
)
5455 list_append msr_rl
'-rv';
5459 if is_not_empty
"${_OPT_XRM}"
5461 case "${msr_prog}" in
5462 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
5463 eval set x
"${_OPT_XRM}";
5467 list_append msr_rl
'-xrm' "$i";
5472 if is_not_empty
"${msr_title}"
5474 case "${msr_prog}" in
5476 list_append msr_rl
'-title' "${msr_title}";
5480 _DISPLAY_ARGS
="${msr_rl}";
5481 eval ${_UNSET} msr_n
;
5482 eval ${_UNSET} msr_prog
;
5483 eval ${_UNSET} msr_rl
;
5484 eval ${_UNSET} msr_title
;
5485 eval "${return_ok}";
5486 } # main_set_resources
5489 ########################################################################
5492 # Do the actual display of the whole thing.
5495 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
5496 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
5497 # $_TMP_CAT, $_OPT_PAGER, $PAGER, $_MANOPT_PAGER,
5498 # $_OUTPUT_FILE_NAME
5500 # Variable prefix: md
5504 func_check main_display
= 0 "$@";
5510 if obj _TMP_CAT is_non_empty_file
5512 md_modefile
="${_OUTPUT_FILE_NAME}";
5514 echo2
'groffer: empty input.';
5516 eval ${_UNSET} md_modefile
;
5517 eval "${return_ok}";
5520 # go to the temporary directory to be able to access internal data files
5521 cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1;
5523 case "${_DISPLAY_MODE}" in
5525 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
5526 if obj _OPT_DEVICE is_not_empty
5528 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
5530 md_groggy
="$(tmp_cat | eval grog "${md_options}")";
5534 obj md_modefile rm_file
;
5535 mv "${_TMP_CAT}" "${md_modefile}";
5537 cat "${md_modefile}" | \
5540 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
5544 case "${_OPT_DEVICE}" in
5546 md_device
="$(get_first_essential \
5547 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
5550 ascii|cp1047|latin1|utf8
)
5551 md_device
="${_OPT_DEVICE}";
5554 warning
"main_display(): \
5555 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5558 md_addopts
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
5559 md_groggy
="$(tmp_cat | grog -T${md_device})";
5561 if obj _DISPLAY_MODE is_equal
'text'
5564 tmp_cat |
eval "${md_groggy}" "${md_addopts}";
5567 for p
in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
5568 'less -r -R' 'more' 'pager' 'cat'
5571 if eval is_prog
${md_p}
5572 then # no "" for is_prog() allows args for $p
5577 if obj md_pager is_empty
5579 error
'main_display(): no pager program found for tty mode';
5582 tmp_cat |
eval "${md_groggy}" "${md_addopts}" | \
5595 case "${_OPT_DEVICE}" in
5596 ''|dvi
) do_nothing
; ;;
5598 warning
"main_display(): \
5599 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
5602 md_modefile
="${md_modefile}".dvi
;
5603 md_groggy
="$(tmp_cat | grog -Tdvi)";
5608 case "${_OPT_DEVICE}" in
5609 ''|html
) do_nothing
; ;;
5611 warning
"main_display(): \
5612 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5615 md_modefile
="${md_modefile}".html
;
5616 md_groggy
="$(tmp_cat | grog -Thtml)";
5621 case "${_OPT_DEVICE}" in
5626 warning
"main_display(): \
5627 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5630 md_groggy
="$(tmp_cat | grog -Tps)";
5632 _do_display _make_pdf
;
5635 case "${_OPT_DEVICE}" in
5640 warning
"main_display(): \
5641 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5644 md_modefile
="${md_modefile}".ps
;
5645 md_groggy
="$(tmp_cat | grog -Tps)";
5650 case "${_OPT_DEVICE}" in
5652 md_device
="${_OPT_DEVICE}"
5655 case "${_OPT_RESOLUTION}" in
5658 if obj _OPT_GEOMETRY is_empty
5660 case "${_DISPLAY_PROG}" in
5662 # add width of 800dpi for resolution of 100dpi to the args
5663 list_append _DISPLAY_ARGS
'-geometry' '800';
5673 md_groggy
="$(tmp_cat | grog -T${md_device} -Z)";
5678 case "${_OPT_DEVICE}" in
5680 md_groggy
="$(tmp_cat | grog -X)";
5683 X
*|dvi|html|lbp|lj4|ps
)
5684 # these devices work with
5685 md_groggy
="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
5689 warning
"main_display(): \
5690 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5691 md_groggy
="$(tmp_cat | grog -Z)";
5698 error
"main_display(): unknown mode \`${_DISPLAY_MODE}'";
5701 eval ${_UNSET} md_addopts
;
5702 eval ${_UNSET} md_device
;
5703 eval ${_UNSET} md_groggy
;
5704 eval ${_UNSET} md_modefile
;
5705 eval ${_UNSET} md_options
;
5706 eval ${_UNSET} md_p
;
5707 eval ${_UNSET} md_pager
;
5708 eval "${return_ok}";
5712 ########################
5713 # _do_display ([<prog>])
5715 # Perform the generation of the output and view the result. If an
5716 # argument is given interpret it as a function name that is called in
5717 # the midst (actually only for `pdf').
5719 # Globals: $md_modefile, $md_groggy (from main_display())
5723 func_check _do_display
'>=' 0 "$@";
5725 if obj _DISPLAY_PROG is_empty
5730 eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}";
5733 obj md_modefile rm_file
;
5734 cat "${_TMP_CAT}" | \
5735 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
5736 if is_not_empty
"$1"
5740 obj _TMP_CAT rm_file_with_debug
;
5741 if obj _VIEWER_TERMINAL is_yes
# for programs that run on tty
5743 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5745 case "${_DISPLAY_PROG}" in
5746 # lynx\ *|less\ *|more\ *) # programs known to run on the terminal
5747 # eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5753 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5759 eval "${return_ok}";
5760 } # _do_display() of main_display()
5766 # Check on option `-V'; if set print the corresponding output and leave.
5768 # Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG,
5769 # $_DISPLAY_ARGS, $md_groggy, $md_modefile
5771 # Variable prefix: _doV
5775 func_check _do_opt_V
'=' 0 "$@";
5776 if obj _OPT_V is_yes
5779 echo1
"Parameters: ${_ALL_PARAMS}";
5780 echo1
"Display mode: ${_DISPLAY_MODE}";
5781 echo1
"Output file: ${md_modefile}";
5782 echo1
"Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
5783 a
="$(eval echo1 "'${_ADDOPTS_GROFF}'")";
5785 echo1
"Output of grog: ${md_groggy} $a";
5786 _doV_res
="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")";
5788 echo1
"groff -V: ${_doV_res}"
5791 eval "${return_ok}";
5792 } # _do_opt_V() of main_display()
5798 # Transform to pdf format; for pdf mode in _do_display().
5800 # Globals: $md_modefile (from main_display())
5802 # Variable prefix: _mp
5806 func_check _do_display
'=' 0 "$@";
5807 _mp_psfile
="${md_modefile}";
5808 md_modefile
="${md_modefile}.pdf";
5809 obj md_modefile rm_file
;
5810 if gs
-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
5811 -sOutputFile="${md_modefile}" -c save pop
-f "${_mp_psfile}"
5815 error
'_make_pdf: could not transform into pdf format.';
5817 obj _mp_psfile rm_file_with_debug
;
5818 eval ${_UNSET} _mp_psfile
;
5819 eval "${return_ok}";
5820 } # _make_pdf() of main_display()
5823 ########################################################################
5824 # main (<command_line_args>*)
5826 # The main function for groffer.
5832 func_check main
'>=' 0 "$@";
5833 # Do not change the sequence of the following functions!
5834 landmark
'13: main_init()';
5836 landmark
'14: main_parse_MANOPT()';
5838 landmark
'15: main_parse_args()';
5839 main_parse_args
"$@";
5840 landmark
'16: main_set_mode()';
5842 landmark
'17: main_do_fileargs()';
5844 landmark
'18: main_set_resources()';
5846 landmark
'19: main_display()';
5848 eval "${return_ok}";
5852 ########################################################################