* release of groffer 0.9.19
[s-roff.git] / contrib / groffer / groffer.sh
blobfaccc240f17390b5ce7579ac8335cc772a7c3f26
1 #! /bin/sh
3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer.sh
7 # Copyright (C) 2001,2002,2003,2004,2005 Free Software Foundation,
8 # Inc.
9 # Written by Bernd Warken
11 # This file is part of groff version @VERSION@ (eventually 1.19.2).
13 # groff is free software; you can redistribute it and/or modify it
14 # under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2, or (at your option)
16 # any later version.
18 # groff is distributed in the hope that it will be useful, but WITHOUT
19 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
21 # License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with groff; see the files COPYING and LICENSE in the top
25 # directory of the groff source. If not, write to the Free Software
26 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
28 _PROGRAM_NAME='groffer';
29 _PROGRAM_VERSION='0.9.19';
30 _LAST_UPDATE='7 July 2005';
33 ########################################################################
34 # Determine the shell under which to run this script from the command
35 # line arguments or $GROFF_OPT; if none is specified, just go on with
36 # the starting shell.
38 if test _"${_GROFFER_RUN}"_ = __;
39 then
40 # only reached during the first run of the script
42 export _GROFFER_RUN; # counter for the runs of groffer
43 _GROFFER_RUN='first';
45 export _PROGRAM_NAME;
46 export _PROGRAM_VERSION;
47 export _LAST_UPDATE;
49 export GROFFER_OPT; # option environment for groffer
50 export _GROFFER_SH; # file name of this shell script
51 export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
53 export _CONF_FILES; # configuration files
54 _CONF_FILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
56 case "$0" in
57 *${_PROGRAM_NAME}*)
58 _GROFFER_SH="$0";
59 # was: _GROFFER_SH="@BINDIR@/${_PROGRAM_NAME}";
62 echo "The ${_PROGRAM_NAME} script should be started directly." >&2
63 exit 1;
65 esac;
67 export _NULL_DEV;
68 if test -c /dev/null;
69 then
70 _NULL_DEV="/dev/null";
71 else
72 _NULL_DEV="NUL";
73 fi;
76 # test of `unset'
77 export _UNSET;
78 export _foo;
79 _foo=bar;
80 _res="$(unset _foo 2>&1)";
81 if unset _foo >${_NULL_DEV} 2>&1 && \
82 test _"${_res}"_ = __ && test _"${_foo}"_ = __
83 then
84 _UNSET='unset';
85 eval "${_UNSET}" _res;
86 else
87 _UNSET=':';
88 fi;
91 ###########################
92 # _get_opt_shell ("$@")
94 # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
95 # if so, echo its argument.
97 # Output: the shell name if it was specified
99 _get_opt_shell()
101 case " ${GROFFER_OPT} $*" in
102 *\ --shell\ *|*\ --shell=*)
104 eval set x "${GROFFER_OPT}" '"$@"';
105 shift;
106 _sh='';
107 while test $# != 0
109 case "$1" in
110 --shell)
111 if test "$#" -ge 2;
112 then
113 _sh="$2";
114 shift;
117 --shell=?*)
118 # delete up to first `=' character
119 _sh="$(echo x"$1" | sed -e '
120 s/^x//
121 s/^[^=]*=//
122 ')";
124 esac;
125 shift;
126 done;
127 cat <<EOF
128 ${_sh}
132 esac;
136 ###########################
137 # _test_on_shell (<name>)
139 # Test whether <name> is a shell program of Bourne type (POSIX sh).
141 _test_on_shell()
143 if test "$#" -le 0 || test _"$1"_ = __;
144 then
145 return 1;
147 # do not quote $1 to allow arguments
148 test _"$(eval $1 -c "'"'s=ok; echo $s'"'" 2>${_NULL_DEV})"_ = _ok_;
152 ###########################
153 # do the shell determination from command line and $GROFFER_OPT
154 _shell="$(_get_opt_shell "$@")";
155 if test _"${_shell}"_ = __;
156 then
157 # none found, so look at the `--shell' lines in configuration files
158 export f;
159 # for f in $_CONF_FILES
160 for f in $(eval set x ${_CONF_FILES}; shift; echo "$@")
162 if test -f "$f";
163 then
164 _all="$(cat "$f" | sed -n -e 's/^--shell[= ] *\([^ ]*\)$/\1/p')"
165 # for s in $_all
166 for s in $(eval set x ${_all}; shift; echo "$@")
168 _shell="$s";
169 done;
171 done;
172 eval ${_UNSET} f;
173 eval ${_UNSET} s;
174 eval ${_UNSET} _all;
177 # restart the script with the last found $_shell, if it is a shell
178 if _test_on_shell "${_shell}";
179 then
180 _GROFFER_RUN='second';
181 # do not quote $_shell to allow arguments
182 eval exec ${_shell} "'${_GROFFER_SH}'" '"$@"';
183 exit;
186 _GROFFER_RUN='second';
187 eval ${_UNSET} _shell;
189 fi; # end of first run
191 if test _"${_GROFFER_RUN}"_ != _second_;
192 then
193 echo "$_GROFFER_RUN should be 'second' here." >&2
194 exit 1
197 eval ${_UNSET} _GROFFER_RUN
200 ########################################################################
201 # diagnostic messages
203 export _DEBUG;
204 _DEBUG='no'; # disable debugging information
205 #_DEBUG='yes'; # enable debugging information
207 export _DEBUG_LM;
208 _DEBUG_LM='no'; # disable landmark messages
209 #_DEBUG_LM='yes'; # enable landmark messages
211 export _DEBUG_KEEP_FILES;
212 _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
213 _DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
215 # test of $* on --debug
216 case " $* " in
217 *' --debug '*)
218 _DEBUG='yes';
219 _DEBUG_LM='yes';
220 _DEBUG_KEEP_FILES='yes';
222 esac;
225 ########################################################################
226 # Environment Variables
227 ########################################################################
229 # Environment variables that exist only for this file start with an
230 # underscore letter. Global variables to this file are written in
231 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
232 # start with an underline and use only lower case letters and
233 # underlines, e.g. $_local_variable .
235 # [A-Z]* system variables, e.g. $MANPATH
236 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
237 # _[a-z_]* temporary variables, e.g. $_manpath
239 # Due to incompatibilities of the `ash' shell, the name of loop
240 # variables in `for' must be single character
241 # [a-z] local loop variables, e.g. $i
244 ########################################################################
245 # read-only variables (global to this file)
246 ########################################################################
248 # characters
250 export _SPACE;
251 export _SQUOTE;
252 export _TAB;
254 _SPACE=' ';
255 _SQUOTE="'";
256 _TAB=' ';
258 # function return values; `0' means ok; other values are error codes
259 export _ALL_EXIT;
260 export _BAD;
261 export _ERROR;
262 export _GOOD;
263 export _NO;
264 export _OK;
265 export _YES;
267 _GOOD='0'; # return ok
268 _BAD='1'; # return negatively, error code `1'
269 _ERROR='7'; # for syntax errors; no `-1' in `ash'
271 _ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
273 _NO="${_BAD}";
274 _YES="${_GOOD}";
275 _OK="${_GOOD}";
277 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
278 export return_ok;
279 export return_good;
280 export return_bad;
281 export return_yes;
282 export return_no;
283 export return_error;
284 export return_var;
285 return_ok="func_pop; return ${_OK}";
286 return_good="func_pop; return ${_GOOD}";
287 return_bad="func_pop; return ${_BAD}";
288 return_yes="func_pop; return ${_YES}";
289 return_no="func_pop; return ${_NO}";
290 return_error="func_pop; return ${_ERROR}";
291 return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
294 export _DEFAULT_MODES;
295 _DEFAULT_MODES='x,ps,tty';
296 export _DEFAULT_RESOLUTION;
297 _DEFAULT_RESOLUTION='75';
299 export _DEFAULT_TTY_DEVICE;
300 _DEFAULT_TTY_DEVICE='latin1';
302 # _VIEWER_* viewer programs for different modes (only X is necessary)
303 # _VIEWER_* a comma-separated list of viewer programs (with options)
304 export _VIEWER_DVI; # viewer program for dvi mode
305 export _VIEWER_PS; # viewer program for ps mode
306 export _VIEWER_HTML_X; # viewer program for html mode in X
307 export _VIEWER_HTML_TTY; # viewer program for html mode in tty
308 _VIEWER_DVI='kdvi,xdvi,dvilx';
309 _VIEWER_PDF='kghostview,ggv,xpdf,acroread,kpdf';
310 _VIEWER_PS='kghostview,ggv,gv,ghostview,gs_x11,gs';
311 _VIEWER_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
312 _VIEWER_X='gxditview,xditview';
314 # Search automatically in standard sections `1' to `8', and in the
315 # traditional sections `9', `n', and `o'. On many systems, there
316 # exist even more sections, mostly containing a set of man pages
317 # special to a specific program package. These aren't searched for
318 # automatically, but must be specified on the command line.
319 export _MAN_AUTO_SEC;
320 _MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
322 export _PROCESS_ID; # for shutting down the program
323 _PROCESS_ID="$$";
326 ############ the command line options of the involved programs
328 # The naming scheme for the options environment names is
329 # $_OPTS_<prog>_<length>[_<argspec>]
331 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
332 # command line options)
333 # <length>: LONG (long options) or SHORT (single character options)
334 # <argspec>: ARG for options with argument, NA for no argument;
335 # without _<argspec> both the ones with and without arg.
337 # Each option that takes an argument must be specified with a
338 # trailing : (colon).
340 # exports
341 export _OPTS_GROFFER_SHORT_NA;
342 export _OPTS_GROFFER_SHORT_ARG;
343 export _OPTS_GROFFER_LONG_NA;
344 export _OPTS_GROFFER_LONG_ARG;
345 export _OPTS_GROFF_SHORT_NA;
346 export _OPTS_GROFF_SHORT_ARG;
347 export _OPTS_GROFF_LONG_NA;
348 export _OPTS_GROFF_LONG_ARG;
349 export _OPTS_X_SHORT_ARG;
350 export _OPTS_X_SHORT_NA;
351 export _OPTS_X_LONG_ARG;
352 export _OPTS_X_LONG_NA;
353 export _OPTS_MAN_SHORT_ARG;
354 export _OPTS_MAN_SHORT_NA;
355 export _OPTS_MAN_LONG_ARG;
356 export _OPTS_MAN_LONG_NA;
357 export _OPTS_MANOPT_SHORT_ARG;
358 export _OPTS_MANOPT_SHORT_NA;
359 export _OPTS_MANOPT_LONG_ARG;
360 export _OPTS_MANOPT_LONG_NA;
361 export _OPTS_CMDLINE_SHORT_NA;
362 export _OPTS_CMDLINE_SHORT_ARG;
363 export _OPTS_CMDLINE_LONG_NA;
364 export _OPTS_CMDLINE_LONG_ARG;
366 ###### groffer native options
368 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
369 _OPTS_GROFFER_SHORT_ARG="'T'";
371 _OPTS_GROFFER_LONG_NA="'auto' 'debug' 'default' 'dvi' \
372 'groff' 'help' 'intermediate-output' 'html' 'man' \
373 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
374 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
376 _OPTS_GROFFER_LONG_ARG="\
377 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
378 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
379 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
380 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
382 ##### groffer options inhereted from groff
384 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
385 'R' 's' 'S' 't' 'U' 'z'";
386 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
387 'w' 'W'";
388 _OPTS_GROFF_LONG_NA="";
389 _OPTS_GROFF_LONG_ARG="";
391 ##### groffer options inhereted from the X Window toolkit
393 _OPTS_X_SHORT_NA="";
394 _OPTS_X_SHORT_ARG="";
396 _OPTS_X_LONG_NA="'iconic' 'rv'";
398 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
399 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'
400 'resolution' 'title' 'xrm'";
402 ###### groffer options inherited from man
404 _OPTS_MAN_SHORT_NA="";
405 _OPTS_MAN_SHORT_ARG="";
407 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \
408 'local-file' 'location' 'pager' 'troff' 'update' 'version' \
409 'whatis' 'where'";
411 _OPTS_MAN_LONG_ARG="'extension' 'locale' 'manpath' \
412 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
414 ###### additional options for parsing $MANOPT only
416 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
417 'V' 'w' 'Z'";
418 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
420 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
421 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
422 'match-case' 'troff' 'update' 'version' 'where-cat'";
424 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
425 'config_file' 'encoding' 'locale'";
427 ###### collections of command line options
429 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA}\
430 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
431 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
432 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
434 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
435 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
436 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
437 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
440 ########################################################################
441 # read-write variables (global to this file)
442 ########################################################################
444 export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
445 export _ADDOPTS_POST; # Transp. options postproc (`eval').
446 export _ADDOPTS_X; # Transp. options X postproc (`eval').
447 export _DEFAULT_MODES; # Set default modes.
448 export _DISPLAY_MODE; # Display mode.
449 export _DISPLAY_PROG; # Viewer program to be used for display.
450 export _DISPLAY_ARGS; # X resources for the viewer program.
451 export _FILEARGS; # Stores filespec parameters.
452 export _FUNC_STACK; # Store debugging information.
453 export _REGISTERED_TITLE; # Processed file names.
454 # _HAS_* from availability tests
455 export _HAS_COMPRESSION; # `yes' if gzip compression is available
456 export _HAS_BZIP; # `yes' if bzip2 compression is available
457 # _MAN_* finally used configuration of man searching
458 export _MAN_ALL; # search all man pages per filespec
459 export _MAN_ENABLE; # enable search for man pages
460 export _MAN_EXT; # extension for man pages
461 export _MAN_FORCE; # force file parameter to be man pages
462 export _MAN_IS_SETUP; # setup man variables only once
463 export _MAN_LANG; # language for man pages
464 export _MAN_LANG2; # language for man pages
465 export _MAN_LANG_DONE; # language dirs added to man path
466 export _MAN_PATH; # search path for man pages
467 export _MAN_SEC; # sections for man pages; sep. `:'
468 export _MAN_SEC_DONE; # sections added to man path
469 export _MAN_SYS; # system names for man pages; sep. `,'
470 export _MAN_SYS; # system names added to man path
471 # _MANOPT_* as parsed from $MANOPT
472 export _MANOPT_ALL; # $MANOPT --all
473 export _MANOPT_EXTENSION; # $MANOPT --extension
474 export _MANOPT_LANG; # $MANOPT --locale
475 export _MANOPT_PATH; # $MANOPT --manpath
476 export _MANOPT_PAGER; # $MANOPT --pager
477 export _MANOPT_SEC; # $MANOPT --sections
478 export _MANOPT_SYS; # $MANOPT --systems
479 # _OPT_* as parsed from groffer command line
480 export _OPT_ALL; # display all suitable man pages.
481 export _OPT_APROPOS; # call `apropos' program.
482 export _OPT_APROPOS_DATA; # `apropos' for man sections 4, 5, 7
483 export _OPT_APROPOS_DEVEL; # `apropos' for man sections 2, 3, 9
484 export _OPT_APROPOS_PROGS; # `apropos' for man sections 1, 6, 8
485 export _OPT_BD; # set border color in some modes.
486 export _OPT_BG; # set background color in some modes.
487 export _OPT_BW; # set border width in some modes.
488 export _OPT_DEBUG; # print debugging information on stderr.
489 export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
490 export _OPT_DEVICE; # device option.
491 export _OPT_DISPLAY; # set X display.
492 export _OPT_FG; # set foreground color in some modes.
493 export _OPT_FN; # set font in some modes.
494 export _OPT_GEOMETRY; # set size and position of viewer in X.
495 export _OPT_ICONIC; # -iconic option for X viewers.
496 export _OPT_LANG; # set language for man pages
497 export _OPT_LOCATION; # print processed file names to stderr
498 export _OPT_MODE; # values: X, tty, Q, Z, ""
499 export _OPT_MANPATH; # manual setting of path for man-pages
500 export _OPT_PAGER; # specify paging program for tty mode
501 export _OPT_RESOLUTION; # set X resolution in dpi
502 export _OPT_RV; # reverse fore- and background colors.
503 export _OPT_SECTIONS; # sections for man page search
504 export _OPT_SYSTEMS; # man pages of different OS's
505 export _OPT_TITLE; # title for gxditview window
506 export _OPT_TEXT_DEVICE; # set device for tty mode.
507 export _OPT_V; # groff option -V.
508 export _OPT_VIEWER_DVI; # viewer program for dvi mode
509 export _OPT_VIEWER_PDF; # viewer program for pdf mode
510 export _OPT_VIEWER_PS; # viewer program for ps mode
511 export _OPT_VIEWER_HTML; # viewer program for html mode
512 export _OPT_VIEWER_X; # viewer program for x mode
513 export _OPT_WHATIS; # print the one-liner man info
514 export _OPT_XRM; # specify X resource.
515 export _OPT_Z; # groff option -Z.
516 # _TMP_* temporary files
517 export _TMP_DIR; # groffer directory for temporary files
518 export _TMP_CAT; # stores concatenation of everything
519 export _TMP_STDIN; # stores stdin, if any
521 # these variables are preset in section `Preset' after the rudim. test
524 ########################################################################
525 # Test of rudimentary shell functionality
526 ########################################################################
529 ########################################################################
530 # Test of `test'.
532 test "a" = "a" || exit 1;
535 ########################################################################
536 # Test of `echo' and the `$()' construct.
538 echo '' >${_NULL_DEV} || exit "${_ERROR}";
539 if test _"$(t1="$(echo te)" &&
540 t2="$(echo '')" &&
541 t3="$(echo 'st')" &&
542 echo "${t1}${t2}${t3}")"_ \
543 != _test_;
544 then
545 exit "${_ERROR}";
549 ########################################################################
550 # Test of function definitions.
552 _t_e_s_t_f_u_n_c_()
554 return "${_OK}";
557 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV};
558 then
560 else
561 echo 'shell does not support function definitions.' >&2;
562 exit "${_ERROR}";
566 ########################################################################
567 # Preset and reset of read-write global variables
568 ########################################################################
571 # For variables that can be reset by option `--default', see reset().
573 _FILEARGS='';
575 # _HAS_* from availability tests
576 _HAS_COMPRESSION='';
577 _HAS_BZIP='';
579 # _TMP_* temporary files
580 _TMP_DIR='';
581 _TMP_CAT='';
582 _TMP_STDIN='';
585 ########################################################################
586 # reset ()
588 # Reset the variables that can be affected by options to their default.
590 reset()
592 if test "$#" -ne 0;
593 then
594 error "reset() does not have arguments.";
597 _ADDOPTS_GROFF='';
598 _ADDOPTS_POST='';
599 _ADDOPTS_X='';
600 _DISPLAY_ARGS='';
601 _DISPLAY_MODE='';
602 _DISPLAY_PROG='';
603 _REGISTERED_TITLE='';
605 # _MAN_* finally used configuration of man searching
606 _MAN_ALL='no';
607 _MAN_ENABLE='yes'; # do search for man-pages
608 _MAN_EXT='';
609 _MAN_FORCE='no'; # first local file, then search man page
610 _MAN_IS_SETUP='no';
611 _MAN_LANG='';
612 _MAN_LANG2='';
613 _MAN_PATH='';
614 _MAN_SEC='';
615 _MAN_SEC_DONE='no';
616 _MAN_SYS='';
617 _MAN_SYS_DONE='no';
619 # _MANOPT_* as parsed from $MANOPT
620 _MANOPT_ALL='no';
621 _MANOPT_EXTENSION='';
622 _MANOPT_LANG='';
623 _MANOPT_PATH='';
624 _MANOPT_PAGER='';
625 _MANOPT_SEC='';
626 _MANOPT_SYS='';
628 # _OPT_* as parsed from groffer command line
629 _OPT_ALL='no';
630 _OPT_APROPOS='';
631 _OPT_APROPOS_DATA='';
632 _OPT_APROPOS_DEVEL='';
633 _OPT_APROPOS_PROGS='';
634 _OPT_BD='';
635 _OPT_BG='';
636 _OPT_BW='';
637 _OPT_DEBUG='no';
638 _OPT_DEFAULT_MODES='';
639 _OPT_DEVICE='';
640 _OPT_DISPLAY='';
641 _OPT_FG='';
642 _OPT_FN='';
643 _OPT_GEOMETRY='';
644 _OPT_ICONIC='no';
645 _OPT_LANG='';
646 _OPT_LOCATION='no';
647 _OPT_MODE='';
648 _OPT_MANPATH='';
649 _OPT_PAGER='';
650 _OPT_RESOLUTION='';
651 _OPT_RV='no';
652 _OPT_SECTIONS='';
653 _OPT_SYSTEMS='';
654 _OPT_TITLE='';
655 _OPT_TEXT_DEVICE='';
656 _OPT_V='no';
657 _OPT_VIEWER_DVI='';
658 _OPT_VIEWER_PDF='';
659 _OPT_VIEWER_PS='';
660 _OPT_VIEWER_HTML='';
661 _OPT_VIEWER_X='';
662 _OPT_WHATIS='no';
663 _OPT_XRM='';
664 _OPT_Z='no';
668 reset;
671 ########################################################################
672 # Functions for error handling and debugging
673 ########################################################################
676 ##############
677 # echo2 (<text>*)
679 # Output to stderr.
681 # Arguments : arbitrary text.
683 echo2()
685 cat >&2 <<EOF
691 ##############
692 # landmark (<text>)
694 # Print <text> to standard error as a debugging aid.
696 # Globals: $_DEBUG_LM
698 landmark()
700 if test _"${_DEBUG_LM}"_ = _yes_;
701 then
702 echo2 "LM: $*" >&2;
706 landmark "1: debugging functions";
709 ##############
710 # clean_up ()
712 # Clean up at exit.
714 clean_up()
716 if test -d "${_TMP_DIR}";
717 then
718 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
723 #############
724 # diag (text>*)
726 # Output a diagnostic message to stderr
728 diag()
730 echo2 '>>>>>'"$*";
734 #############
735 # error (<text>*)
737 # Print an error message to standard error; exit with an error condition
739 # Variable prefix: err
741 error()
743 err_code="${_ERROR}";
744 case "$#" in
745 0) :; ;;
746 1) echo2 'groffer error: '"$1"; ;;
748 echo2 'groffer error: '"$1";
749 err_code="$2";
751 *) echo2 'groffer error: wrong number of arguments in error().'; ;;
752 esac;
753 func_stack_dump;
754 clean_up;
755 kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
756 kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
757 n="${err_code}";
758 eval ${_UNSET} err_code;
759 exit "$n";
763 #############
764 # abort (<text>*)
766 # Terminate program with error condition
768 abort()
770 error "abort(): Program aborted.";
771 exit 1;
775 #############
776 # func_check (<func_name> <rel_op> <nr_args> "$@")
778 # Check number of arguments and register to _FUNC_STACK.
780 # Arguments: >=3
781 # <func_name>: name of the calling function.
782 # <rel_op>: a relational operator: = != < > <= >=
783 # <nr_args>: number of arguments to be checked against <operator>
784 # "$@": the arguments of the calling function.
786 # Variable prefix: fc
788 func_check()
790 if test "$#" -lt 3;
791 then
792 error 'func_check() needs at least 3 arguments.';
794 fc_fname="$1";
795 case "$3" in
797 fc_nargs="$3";
798 fc_s='';
800 0|[2-9])
801 fc_nargs="$3";
802 fc_s='s';
805 error "func_check(): third argument must be a digit.";
807 esac;
808 case "$2" in
809 '='|'-eq')
810 fc_op='-eq';
811 fc_comp='exactly';
813 '>='|'-ge')
814 fc_op='-ge';
815 fc_comp='at least';
817 '<='|'-le')
818 fc_op='-le';
819 fc_comp='at most';
821 '<'|'-lt')
822 fc_op='-lt';
823 fc_comp='less than';
825 '>'|'-gt')
826 fc_op='-gt';
827 fc_comp='more than';
829 '!='|'-ne')
830 fc_op='-ne';
831 fc_comp='not';
834 error \
835 'func_check(): second argument is not a relational operator.';
837 esac;
838 shift;
839 shift;
840 shift;
841 if test "$#" "${fc_op}" "${fc_nargs}";
842 then
843 do_nothing;
844 else
845 error "func_check(): \
846 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
848 func_push "${fc_fname}";
849 if test _"${_DEBUG}"_ = _yes_;
850 then
851 echo2 '+++ '"${fc_fname} $@";
852 echo2 '>>> '"${_FUNC_STACK}";
854 eval ${_UNSET} fc_comp;
855 eval ${_UNSET} fc_fname;
856 eval ${_UNSET} fc_nargs;
857 eval ${_UNSET} fc_op;
858 eval ${_UNSET} fc_s;
862 #############
863 # func_pop ()
865 # Retrieve the top element from the stack.
867 # The stack elements are separated by `!'; the popped element is
868 # identical to the original element, except that all `!' characters
869 # were removed.
871 # Arguments: 1
873 func_pop()
875 if test "$#" -ne 0;
876 then
877 error 'func_pop() does not have arguments.';
879 case "${_FUNC_STACK}" in
881 if test _"${_DEBUG}"_ = _yes_;
882 then
883 error 'func_pop(): stack is empty.';
886 *!*)
887 # split at first bang `!'.
888 _FUNC_STACK="$(echo x"${_FUNC_STACK}" | sed -e '
889 s/^x//
890 s/^[^!]*!//
891 ')";
894 _FUNC_STACK='';
896 esac;
897 if test _"${_DEBUG}"_ = _yes_;
898 then
899 echo2 '<<< '"${_FUNC_STACK}";
904 #############
905 # func_push (<element>)
907 # Store another element to stack.
909 # The stack elements are separated by `!'; if <element> contains a `!'
910 # it is removed first.
912 # Arguments: 1
914 # Variable prefix: fp
916 func_push()
918 if test "$#" -ne 1;
919 then
920 error 'func_push() needs 1 argument.';
922 case "$1" in
923 *'!'*)
924 # remove all bangs `!'.
925 fp_element="$(echo x"$1" | sed -e '
926 s/^x//
927 s/!//g
928 ')";
931 fp_element="$1";
933 esac;
934 if test _"${_FUNC_STACK}"_ = __;
935 then
936 _FUNC_STACK="${fp_element}";
937 else
938 _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
940 eval ${_UNSET} fp_element;
944 #############
945 # func_stack_dump ()
947 # Print the content of the stack. Ignore the arguments.
949 func_stack_dump()
951 diag 'call stack: '"${_FUNC_STACK}";
955 ########################################################################
956 # System Test
957 ########################################################################
959 landmark "2: system test";
961 # Test the availability of the system utilities used in this script.
964 ########################################################################
965 # Test of function `sed'.
968 if test _"$(echo xTesTx \
969 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
970 | sed -e 's|T|t|g')"_ != _test_;
971 then
972 error 'Test of "sed" command failed.';
976 ########################################################################
977 # Test of function `cat'.
979 if test _"$(echo test | cat)"_ != _test_;
980 then
981 error 'Test of "cat" command failed.';
985 ########################################################################
986 # Test for compression.
988 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_;
989 then
990 _HAS_COMPRESSION='yes';
991 if echo 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
992 && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
993 | bzip2 -d -c 2>${_NULL_DEV})"_ \
994 = _test_;
995 then
996 _HAS_BZIP='yes';
997 else
998 _HAS_BZIP='no';
1000 else
1001 _HAS_COMPRESSION='no';
1002 _HAS_BZIP='no';
1006 ########################################################################
1007 # Definition of normal Functions in alphabetical order
1008 ########################################################################
1009 landmark "3: functions";
1011 ########################################################################
1012 # abort (<text>*)
1014 # Unconditionally terminate the program with error code;
1015 # useful for debugging.
1017 # defined above
1020 ########################################################################
1021 # apropos_run (<name>)
1024 apropos_run() {
1025 func_check apropos_run = 1 "$@";
1026 if apropos apropos >${_NULL_DEV} 2>${_NULL_DEV};
1027 then
1028 apropos "$1";
1029 elif man --apropos man >${_NULL_DEV} 2>${_NULL_DEV};
1030 then
1031 man --apropos "$1";
1032 elif man -k man >${_NULL_DEV} 2>${_NULL_DEV};
1033 then
1034 man -k "$1";
1036 eval "${return_ok}";
1040 ########################################################################
1041 # base_name (<path>)
1043 # Get the file name part of <path>, i.e. delete everything up to last
1044 # `/' from the beginning of <path>. Remove final slashes, too, to get a
1045 # non-empty output.
1047 # Arguments : 1
1048 # Output : the file name part (without slashes)
1050 # Variable prefix: bn
1052 base_name()
1054 func_check base_name = 1 "$@";
1055 bn_name="$1";
1056 case "${bn_name}" in
1058 # delete all final slashes
1059 bn_name="$(echo x"${bn_name}" | sed -e '
1060 s/^x//
1061 s|//*$||
1062 ')";
1064 esac;
1065 case "${bn_name}" in
1066 /|'')
1067 eval ${_UNSET} bn_name;
1068 eval "${return_bad}";
1070 */*)
1071 # delete everything before and including the last slash `/'.
1072 echo x"${bn_name}" | sed -e '
1073 s/^x//
1074 s|^.*//*\([^/]*\)$|\1|
1078 cat <<EOF
1079 ${bn_name}
1082 esac;
1083 eval ${_UNSET} bn_name;
1084 eval "${return_ok}";
1088 ########################################################################
1089 # cat_z (<file>)
1091 # Decompress if possible or just print <file> to standard output.
1093 # gzip, bzip2, and .Z decompression is supported.
1095 # Arguments: 1, a file name.
1096 # Output: the content of <file>, possibly decompressed.
1098 if test _"${_HAS_COMPRESSION}"_ = _yes_;
1099 then
1100 cat_z()
1102 func_check cat_z = 1 "$@";
1103 case "$1" in
1105 error 'cat_z(): empty file name';
1107 '-')
1108 error 'cat_z(): for standard input use save_stdin()';
1110 esac;
1111 if obj _HAS_BZIP is_yes;
1112 then
1113 if bzip2 -t "$1" 2>${_NULL_DEV};
1114 then
1115 bzip2 -c -d "$1" 2>${_NULL_DEV};
1116 eval "${return_ok}";
1119 gzip -c -d -f "$1" 2>${_NULL_DEV};
1120 eval "${return_ok}";
1122 else
1123 cat_z()
1125 func_check cat_z = 1 "$@";
1126 cat "$1";
1127 eval "${return_ok}";
1132 ########################################################################
1133 # clean_up ()
1135 # Do the final cleaning up before exiting; used by the trap calls.
1137 # defined above
1140 ########################################################################
1141 # diag (<text>*)
1143 # Print marked message to standard error; useful for debugging.
1145 # defined above
1148 ########################################################################
1149 landmark '4: dirname()*';
1150 ########################################################################
1152 #######################################################################
1153 # dirname_append (<dir> <name>)
1155 # Append `name' to `dir' with clean handling of `/'.
1157 # Arguments : 2
1158 # Output : the generated new directory name <dir>/<name>
1160 dirname_append()
1162 func_check dirname_append = 2 "$@";
1163 if is_empty "$1";
1164 then
1165 error "dir_append(): first argument is empty.";
1167 if is_empty "$2";
1168 then
1169 cat <<EOF
1172 else
1173 dirname_chop "$1"/"$2";
1175 eval "${return_ok}";
1179 ########################################################################
1180 # dirname_chop (<name>)
1182 # Remove unnecessary slashes from directory name.
1184 # Argument: 1, a directory name.
1185 # Output: path without double, or trailing slashes.
1187 # Variable prefix: dc
1189 dirname_chop()
1191 func_check dirname_chop = 1 "$@";
1192 # replace all multiple slashes by a single slash `/'.
1193 dc_res="$(echo x"$1" | sed -e '
1194 s/^x//
1195 s|///*|/|g
1196 ')";
1197 case "${dc_res}" in
1198 ?*/)
1199 # remove trailing slash '/';
1200 echo x"${dc_res}" | sed -e '
1201 s/^x//
1202 s|/$||
1205 *) cat <<EOF
1206 ${dc_res}
1209 esac;
1210 eval ${_UNSET} dc_res;
1211 eval "${return_ok}";
1215 ########################################################################
1216 # do_filearg (<filearg>)
1218 # Append the file, man-page, or standard input corresponding to the
1219 # argument to the temporary file. If this is compressed in the gzip
1220 # or Z format it is decompressed. A title element is generated.
1222 # Argument either:
1223 # - name of an existing files.
1224 # - `-' to represent standard input (several times allowed).
1225 # - `man:name.(section)' the man-page for `name' in `section'.
1226 # - `man:name.section' the man-page for `name' in `section'.
1227 # - `man:name' the man-page for `name' in the lowest `section'.
1228 # - `name.section' the man-page for `name' in `section'.
1229 # - `name' the man-page for `name' in the lowest `section'.
1230 # Globals :
1231 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1233 # Output : none
1234 # Return : $_GOOD if found, ${_BAD} otherwise.
1236 # Variable prefix: df
1238 do_filearg()
1240 func_check do_filearg = 1 "$@";
1241 df_filespec="$1";
1242 # store sequence into positional parameters
1243 case "${df_filespec}" in
1245 eval ${_UNSET} df_filespec;
1246 eval "${return_good}";
1248 '-')
1249 register_file '-';
1250 eval ${_UNSET} df_filespec;
1251 eval "${return_good}";
1253 */*) # with directory part; so no man search
1254 set 'File';
1257 if obj _MAN_ENABLE is_yes;
1258 then
1259 if obj _MAN_FORCE is_yes;
1260 then
1261 set 'Manpage' 'File';
1262 else
1263 set 'File' 'Manpage';
1265 else
1266 set 'File';
1269 esac;
1270 for i
1272 case "$i" in
1273 File)
1274 if test -f "${df_filespec}";
1275 then
1276 if test -r "${df_filespec}";
1277 then
1278 register_file "${df_filespec}";
1279 eval ${_UNSET} df_filespec;
1280 eval "${return_good}";
1281 else
1282 echo2 "could not read \`${df_filespec}'";
1283 eval ${_UNSET} df_filespec;
1284 eval "${return_bad}";
1286 else
1287 continue;
1290 Manpage) # parse filespec as man page
1291 if obj _MAN_IS_SETUP is_not_yes;
1292 then
1293 man_setup;
1295 if man_do_filespec "${df_filespec}";
1296 then
1297 eval ${_UNSET} df_filespec;
1298 eval "${return_good}";
1299 else
1300 continue;
1303 esac;
1304 done;
1305 eval ${_UNSET} df_filespec;
1306 eval "${return_bad}";
1307 } # do_filearg()
1310 ########################################################################
1311 # do_nothing ()
1313 # Dummy function.
1315 do_nothing()
1317 eval return "${_OK}";
1321 ########################################################################
1322 # echo2 (<text>*)
1324 # Print to standard error with final line break.
1326 # defined above
1329 ########################################################################
1330 # error (<text>*)
1332 # Print error message and exit with error code.
1334 # defined above
1337 ########################################################################
1338 # func_check (<func_name> <rel_op> <nr_args> "$@")
1340 # Check number of arguments and register to _FUNC_STACK.
1342 # Arguments: >=3
1343 # <func_name>: name of the calling function.
1344 # <rel_op>: a relational operator: = != < > <= >=
1345 # <nr_args>: number of arguments to be checked against <operator>
1346 # "$@": the arguments of the calling function.
1348 # defined above
1350 #########################################################################
1351 # func_pop ()
1353 # Delete the top element from the function call stack.
1355 # defined above
1358 ########################################################################
1359 # func_push (<element>)
1361 # Store another element to function call stack.
1363 # defined above
1366 ########################################################################
1367 # func_stack_dump ()
1369 # Print the content of the stack.
1371 # defined above
1374 ########################################################################
1375 # get_first_essential (<arg>*)
1377 # Retrieve first non-empty argument.
1379 # Return : `1' if all arguments are empty, `0' if found.
1380 # Output : the retrieved non-empty argument.
1382 # Variable prefix: gfe
1384 get_first_essential()
1386 func_check get_first_essential '>=' 0 "$@";
1387 if is_equal "$#" 0;
1388 then
1389 eval "${return_ok}";
1391 for i
1393 gfe_var="$i";
1394 if obj gfe_var is_not_empty;
1395 then
1396 cat <<EOF
1397 ${gfe_var}
1399 eval ${_UNSET} gfe_var;
1400 eval "${return_ok}";
1402 done;
1403 eval ${_UNSET} gfe_var;
1404 eval "${return_bad}";
1408 ########################################################################
1409 landmark '5: is_*()';
1410 ########################################################################
1412 ########################################################################
1413 # is_dir (<name>)
1415 # Test whether `name' is a directory.
1417 # Arguments : 1
1418 # Return : `0' if arg1 is a directory, `1' otherwise.
1420 is_dir()
1422 func_check is_dir = 1 "$@";
1423 if test -d "$1" && test -r "$1";
1424 then
1425 eval "${return_yes}";
1427 eval "${return_no}";
1431 ########################################################################
1432 # is_empty (<string>)
1434 # Test whether `string' is empty.
1436 # Arguments : <=1
1437 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1439 is_empty()
1441 func_check is_empty = 1 "$@";
1442 if test _"$1"_ = __;
1443 then
1444 eval "${return_yes}";
1446 eval "${return_no}";
1450 ########################################################################
1451 # is_equal (<string1> <string2>)
1453 # Test whether `string1' is equal to <string2>.
1455 # Arguments : 2
1456 # Return : `0' both arguments are equal strings, `1' otherwise.
1458 is_equal()
1460 func_check is_equal = 2 "$@";
1461 if test _"$1"_ = _"$2"_;
1462 then
1463 eval "${return_yes}";
1465 eval "${return_no}";
1469 ########################################################################
1470 # is_existing (<name>)
1472 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1473 # not have `test -e'.
1475 # Arguments : 1
1476 # Return : `0' if arg1 exists, `1' otherwise.
1478 is_existing()
1480 func_check is_existing = 1 "$@";
1481 if test -f "$1" || test -d "$1";
1482 then
1483 eval "${return_yes}";
1485 eval "${return_no}";
1489 ########################################################################
1490 # is_file (<name>)
1492 # Test whether `name' is a readable file.
1494 # Arguments : 1
1495 # Return : `0' if arg1 is a readable file, `1' otherwise.
1497 is_file()
1499 func_check is_file = 1 "$@";
1500 if test -f "$1" && test -r "$1";
1501 then
1502 eval "${return_yes}";
1504 eval "${return_no}";
1508 ########################################################################
1509 # is_non_empty_file (<file_name>)
1511 # Test whether `file_name' is a non-empty existing file.
1513 # Arguments : <=1
1514 # Return :
1515 # `0' if arg1 is a non-empty existing file
1516 # `1' otherwise
1518 is_non_empty_file()
1520 func_check is_non_empty_file = 1 "$@";
1521 if is_file "$1" && test -s "$1";
1522 then
1523 eval "${return_yes}";
1525 eval "${return_no}";
1529 ########################################################################
1530 # is_not_dir (<name>)
1532 # Test whether `name' is not a readable directory.
1534 # Arguments : 1
1535 # Return : `0' if arg1 is a directory, `1' otherwise.
1537 is_not_dir()
1539 func_check is_not_dir = 1 "$@";
1540 if is_dir "$1";
1541 then
1542 eval "${return_no}";
1544 eval "${return_yes}";
1548 ########################################################################
1549 # is_not_empty (<string>)
1551 # Test whether `string' is not empty.
1553 # Arguments : <=1
1554 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1556 is_not_empty()
1558 func_check is_not_empty = 1 "$@";
1559 if is_empty "$1";
1560 then
1561 eval "${return_no}";
1563 eval "${return_yes}";
1567 ########################################################################
1568 # is_not_equal (<string1> <string2>)
1570 # Test whether `string1' differs from `string2'.
1572 # Arguments : 2
1574 is_not_equal()
1576 func_check is_not_equal = 2 "$@";
1577 if is_equal "$1" "$2";
1578 then
1579 eval "${return_no}";
1581 eval "${return_yes}";
1585 ########################################################################
1586 # is_not_file (<filename>)
1588 # Test whether `name' is a not readable file.
1590 # Arguments : >=1 (empty allowed), more args are ignored
1592 is_not_file()
1594 func_check is_not_file '>=' 1 "$@";
1595 if is_file "$1";
1596 then
1597 eval "${return_no}";
1599 eval "${return_yes}";
1603 ########################################################################
1604 # is_not_prog (<name>)
1606 # Verify that arg is a not program in $PATH.
1608 # Arguments : >=1 (empty allowed)
1609 # more args are ignored, this allows to specify progs with arguments
1611 is_not_prog()
1613 func_check is_not_prog '>=' 1 "$@";
1614 if where_is "$1" >${_NULL_DEV};
1615 then
1616 eval "${return_no}";
1618 eval "${return_yes}";
1622 ########################################################################
1623 # is_not_writable (<name>)
1625 # Test whether `name' is a not a writable file or directory.
1627 # Arguments : >=1 (empty allowed), more args are ignored
1629 is_not_writable()
1631 func_check is_not_writable '>=' 1 "$@";
1632 if is_writable "$1";
1633 then
1634 eval "${return_no}";
1636 eval "${return_yes}";
1640 ########################################################################
1641 # is_not_yes (<string>)
1643 # Test whether `string' is not "yes".
1645 # Arguments : 1
1647 is_not_yes()
1649 func_check is_not_yes = 1 "$@";
1650 if is_yes "$1";
1651 then
1652 eval "${return_no}";
1654 eval "${return_yes}";
1658 ########################################################################
1659 # is_prog (<name> [<arg>*])
1661 # Determine whether <name> is a program in $PATH
1663 # Arguments : >=0 (empty allowed)
1664 # <arg>* are ignored, this allows to specify progs with arguments.
1666 is_prog()
1668 func_check is_prog '>=' 0 "$@";
1669 case "$#" in
1671 eval "${return_no}";
1674 if where_is "$1" >${_NULL_DEV};
1675 then
1676 eval "${return_yes}";
1679 esac
1680 eval "${return_no}";
1684 ########################################################################
1685 # is_writable (<name>)
1687 # Test whether `name' is a writable file or directory.
1689 # Arguments : >=1 (empty allowed), more args are ignored
1691 is_writable()
1693 func_check is_writable '>=' 1 "$@";
1694 if test -r "$1";
1695 then
1696 if test -w "$1";
1697 then
1698 eval "${return_yes}";
1701 eval "${return_no}";
1705 ########################################################################
1706 # is_yes (<string>)
1708 # Test whether `string' has value "yes".
1710 # Arguments : <=1
1711 # Return : `0' if arg1 is `yes', `1' otherwise.
1713 is_yes()
1715 func_check is_yes = 1 "$@";
1716 if is_equal "$1" 'yes';
1717 then
1718 eval "${return_yes}";
1720 eval "${return_no}";
1724 ########################################################################
1725 # landmark ()
1727 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1729 # Globals: $_DEBUG_LM
1731 # Defined in section `Debugging functions'.
1734 ########################################################################
1735 # leave ()
1737 # Clean exit without an error.
1739 leave()
1741 clean_up;
1742 exit "${_OK}";
1746 ########################################################################
1747 landmark '6: list_*()';
1748 ########################################################################
1750 # `list' is an object class that represents an array or list. Its
1751 # data consists of space-separated single-quoted elements. So a list
1752 # has the form "'first' 'second' '...' 'last'". See list_append() for
1753 # more details on the list structure. The array elements of `list'
1754 # can be get by `set x $list; shift`.
1757 ########################################################################
1758 # list_append (<list> <element>...)
1760 # Arguments: >=2
1761 # <list>: a variable name for a list of single-quoted elements
1762 # <element>: some sequence of characters.
1763 # Output: none, but $<list> is set to
1764 # if <list> is empty: "'<element>' '...'"
1765 # otherwise: "$list '<element>' ..."
1767 # Variable prefix: la
1769 list_append()
1771 func_check list_append '>=' 2 "$@";
1772 la_name="$1";
1773 eval la_list='"${'$1'}"';
1774 shift;
1775 for s
1777 la_s="$s";
1778 case "${la_s}" in
1779 *\'*)
1780 # escape each single quote by replacing each
1781 # "'" (squote) by "'\''" (squote bslash squote squote);
1782 # note that the backslash must be doubled in the following `sed'
1783 la_element="$(echo x"${la_s}" | sed -e '
1784 s/^x//
1785 s/'"${_SQUOTE}"'/&\\&&/g
1786 ')";
1789 la_element="";
1792 la_element="${la_s}";
1794 esac;
1795 if obj la_list is_empty;
1796 then
1797 la_list="'${la_element}'";
1798 else
1799 la_list="${la_list} '${la_element}'";
1801 done;
1802 eval "${la_name}"='"${la_list}"';
1803 eval ${_UNSET} la_element;
1804 eval ${_UNSET} la_list;
1805 eval ${_UNSET} la_name;
1806 eval ${_UNSET} la_s;
1807 eval "${return_ok}";
1811 ########################################################################
1812 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1814 # Transform command line arguments into a normalized form.
1816 # Options, option arguments, and file parameters are identified and
1817 # output each as a single-quoted argument of its own. Options and
1818 # file parameters are separated by a '--' argument.
1820 # Arguments: >=1
1821 # <pre_name>: common part of a set of 4 environment variable names:
1822 # $<pre_name>_SHORT_NA: list of short options without an arg.
1823 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1824 # $<pre_name>_LONG_NA: list of long options without an arg.
1825 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1826 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1827 # the content of a variable, or direct arguments.
1829 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1831 # Example:
1832 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1833 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1834 # none-empty option lists, this will result in printing:
1835 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1837 # Use this function in the following way:
1838 # eval set x "$(args_norm PRE_NAME "$@")";
1839 # shift;
1840 # while test "$1" != '--'; do
1841 # case "$1" in
1842 # ...
1843 # esac;
1844 # shift;
1845 # done;
1846 # shift; #skip '--'
1847 # # all positional parameters ("$@") left are file name parameters.
1849 # Variable prefix: lfc
1851 list_from_cmdline()
1853 func_check list_from_cmdline '>=' 1 "$@";
1854 lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1855 lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1856 lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1857 lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1858 if obj lfc_short_n is_empty;
1859 then
1860 error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1862 if obj lfc_short_a is_empty;
1863 then
1864 error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1866 if obj lfc_long_n is_empty;
1867 then
1868 error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1870 if obj lfc_long_a is_empty;
1871 then
1872 error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1874 shift;
1875 lfc_fn='list_from_cmdline():'; # for error messages
1876 if is_equal "$#" 0;
1877 then
1878 cat <<EOF
1881 eval ${_UNSET} lfc_fparams;
1882 eval ${_UNSET} lfc_fn;
1883 eval ${_UNSET} lfc_short_a;
1884 eval ${_UNSET} lfc_short_n;
1885 eval ${_UNSET} lfc_long_a;
1886 eval ${_UNSET} lfc_long_n;
1887 eval ${_UNSET} lfc_result;
1888 eval "${return_ok}";
1890 lfc_fparams='';
1891 lfc_result='';
1892 while test "$#" -ge 1;
1894 lfc_arg="$1";
1895 shift;
1896 case "${lfc_arg}" in
1897 --) break; ;;
1898 --?*)
1899 # delete leading '--';
1900 lfc_opt="$(echo x"${lfc_arg}" | sed -e 's/^x--//')";
1901 if list_has lfc_long_n "${lfc_opt}";
1902 then
1903 # long option, no argument
1904 list_append lfc_result "--${lfc_opt}";
1905 continue;
1907 # test on `--opt=arg'
1908 if string_contains "${lfc_opt}" '=';
1909 then
1910 # extract option by deleting from the first '=' to the end
1911 lfc_lopt="$(echo x"${lfc_opt}" | sed -e '
1912 s/^x//
1913 s/=.*$//
1914 ')";
1915 if list_has lfc_long_a "${lfc_lopt}";
1916 then
1917 # get the option argument by deleting up to first `='
1918 lfc_optarg="$(echo x"${lfc_opt}" | sed -e '
1919 s/^x//
1920 s/^[^=]*=//
1921 ')";
1922 list_append lfc_result "--${lfc_lopt}" "${lfc_optarg}";
1923 continue;
1926 if list_has lfc_long_a "${lfc_opt}";
1927 then
1928 # long option with argument
1929 if test "$#" -le 0;
1930 then
1931 error "list_from_cmdline(): \
1932 ${lfc_fn} no argument for option --${lfc_opt}."
1934 list_append lfc_result "--${lfc_opt}" "$1";
1935 shift;
1936 continue;
1938 error "list_from_cmdline(): ${lfc_fn} --${lfc_opt} is not an option."
1940 -?*) # short option (cluster)
1941 # delete leading `-';
1942 lfc_rest="$(echo x"${lfc_arg}" | sed -e 's/^x-//')";
1943 while obj lfc_rest is_not_empty;
1945 # get next short option from cluster (first char of $lfc_rest)
1946 lfc_optchar="$(echo x"${lfc_rest}" | sed -e 's/^x\(.\).*$/\1/')";
1947 # remove first character from ${lfc_rest};
1948 lfc_rest="$(echo x"${lfc_rest}" | sed -e 's/^x.//')";
1949 if list_has lfc_short_n "${lfc_optchar}";
1950 then
1951 list_append lfc_result "-${lfc_optchar}";
1952 continue;
1953 elif list_has lfc_short_a "${lfc_optchar}";
1954 then
1955 if obj lfc_rest is_empty;
1956 then
1957 if test "$#" -ge 1;
1958 then
1959 list_append lfc_result "-${lfc_optchar}" "$1";
1960 shift;
1961 continue;
1962 else
1963 error "list_from_cmdline(): \
1964 ${lfc_fn}"' no argument for option -'"${lfc_optchar}."
1966 else # rest is the argument
1967 list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
1968 lfc_rest='';
1969 continue;
1971 else
1972 error "list_from_cmdline(): \
1973 ${lfc_fn} unknown option -${lfc_optchar}."
1975 done;
1978 # Here, $lfc_arg is not an option, so a file parameter.
1979 list_append lfc_fparams "${lfc_arg}";
1981 # Ignore the strange option handling of $POSIXLY_CORRECT to
1982 # end option parsing after the first file name argument. To
1983 # reuse it, do a `break' here if $POSIXLY_CORRECT is
1984 # non-empty.
1986 esac;
1987 done;
1988 list_append lfc_result '--';
1989 if obj lfc_fparams is_not_empty;
1990 then
1991 lfc_result="${lfc_result} ${lfc_fparams}";
1993 if test "$#" -gt 0;
1994 then
1995 list_append lfc_result "$@";
1997 cat <<EOF
1998 ${lfc_result}
2000 eval ${_UNSET} lfc_fparams;
2001 eval ${_UNSET} lfc_fn;
2002 eval ${_UNSET} lfc_short_a;
2003 eval ${_UNSET} lfc_short_n;
2004 eval ${_UNSET} lfc_long_a;
2005 eval ${_UNSET} lfc_long_n;
2006 eval ${_UNSET} lfc_result;
2007 eval ${_UNSET} lfc_arg;
2008 eval ${_UNSET} lfc_opt;
2009 eval ${_UNSET} lfc_opt_arg;
2010 eval ${_UNSET} lfc_opt_char;
2011 eval ${_UNSET} lfc_lopt;
2012 eval ${_UNSET} lfc_rest;
2013 eval "${return_ok}";
2014 } # list_from_cmdline()
2017 ########################################################################
2018 # list_from_split (<string> <separator>)
2020 # In <string>, escape all white space characters and replace each
2021 # <separator> by space.
2023 # Arguments: 2: a <string> that is to be split into parts divided by
2024 # <separator>
2025 # Output: the resulting list string
2027 # Variable prefix: lfs
2029 list_from_split()
2031 func_check list_from_split = 2 "$@";
2033 # precede each space or tab by a backslash `\' (doubled for `sed')
2034 lfs_s="$(echo x"$1" | sed -e '
2035 s/^x//
2036 s/\(['"${_SPACE}${_TAB}"']\)/\\\1/g
2037 ')";
2039 # replace split character of string by the list separator ` ' (space).
2040 case "$2" in
2041 /) # cannot use normal `sed' separator
2042 echo x"${lfs_s}" | sed -e '
2043 s/^x//
2044 s|'"$2"'| |g
2047 ?) # use normal `sed' separator
2048 echo x"${lfs_s}" | sed -e '
2049 s/^x//
2050 s/'"$2"'/ /g
2053 ??*)
2054 error 'list_from_split(): separator must be a single character.';
2056 esac;
2057 eval ${_UNSET} lfs_s;
2058 eval "${return_ok}";
2062 ########################################################################
2063 # list_get (<list>)
2065 # Check whether <list> is a space-separated list of '-quoted elements.
2067 # If the test fails an error is raised.
2068 # If the test succeeds the argument is echoed.
2070 # Testing criteria:
2071 # A list has the form "'first' 'second' '...' 'last'". So it has a
2072 # leading and a final quote and the elements are separated by "' '"
2073 # constructs. If these are all removed there should not be any
2074 # unescaped single-quotes left. Watch out for escaped single
2075 # quotes; they have the form '\'' (sq bs sq sq).
2077 # Arguments: 1
2078 # Output: the argument <list> unchanged, if the check succeeded.
2080 # Variable prefix: lg
2082 list_get()
2084 func_check list_get = 1 "$@";
2085 eval lg_list='"${'$1'}"';
2086 # remove leading and final space characters
2087 lg_list="$(echo x"${lg_list}" | sed -e '
2088 s/^x['"${_SPACE}${_TAB}"']*//
2089 s/['"${_SPACE}${_TAB}"']*$//
2090 ')";
2091 case "${lg_list}" in
2093 eval ${_UNSET} lg_list;
2094 eval "${return_ok}";
2096 \'*\')
2097 cat <<EOF
2098 ${lg_list}
2100 eval ${_UNSET} lg_list;
2101 eval "${return_ok}";
2104 error "list_get(): bad list: $1"
2106 esac;
2107 eval ${_UNSET} lg_list;
2108 eval "${return_ok}";
2112 ########################################################################
2113 # list_has (<var_name> <element>)
2115 # Arguments: 2
2116 # <var_name>: a variable name for a list of single-quoted elements
2117 # <element>: some sequence of characters.
2118 # Output:
2119 # if <list> is empty: "'<element>' '...'"
2120 # otherwise: "list '<element>' ..."
2122 list_has()
2124 func_check list_has = 2 "$@";
2125 eval _list='"${'$1'}"';
2126 if obj _list is_empty;
2127 then
2128 eval "${return_no}";
2130 _element="$2";
2131 case "$2" in
2132 \'*\') _element="$2"; ;;
2133 *) _element="'$2'"; ;;
2134 esac;
2135 if string_contains "${_list}" "${_element}";
2136 then
2137 eval "${return_yes}";
2138 else
2139 eval "${return_no}";
2141 eval "${return_ok}";
2145 ########################################################################
2146 # list_has_not (<list> <element>)
2148 # Arguments: 2
2149 # <list>: a space-separated list of single-quoted elements.
2150 # <element>: some sequence of characters.
2151 # Output:
2152 # if <list> is empty: "'<element>' '...'"
2153 # otherwise: "<list> '<element>' ..."
2155 list_has_not()
2157 func_check list_has_not = 2 "$@";
2158 eval _list='"${'$1'}"';
2159 if obj _list is_empty;
2160 then
2161 eval "${return_yes}";
2163 _element="$2";
2164 case "$2" in
2165 \'*\') _element="$2"; ;;
2166 *) _element="'$2'"; ;;
2167 esac;
2168 if string_contains "${_list}" "${_element}";
2169 then
2170 eval "${return_no}";
2171 else
2172 eval "${return_yes}";
2174 eval "${return_ok}";
2178 ########################################################################
2179 landmark '7: man_*()';
2180 ########################################################################
2182 ########################################################################
2183 # man_do_filespec (<filespec>)
2185 # Print suitable man page(s) for filespec to $_TMP_CAT.
2187 # Arguments : 2
2188 # <filespec>: argument of the form `man:name.section', `man:name',
2189 # `man:name(section)', `name.section', `name'.
2191 # Globals : $_OPT_ALL
2193 # Output : none.
2194 # Return : `0' if man page was found, `1' else.
2196 # Only called from do_fileargs(), checks on $MANPATH and
2197 # $_MAN_ENABLE are assumed.
2199 # Variable prefix: mdf
2201 man_do_filespec()
2203 func_check man_do_filespec = 1 "$@";
2204 if obj _MAN_PATH is_empty;
2205 then
2206 eval "${return_bad}";
2208 if is_empty "$1";
2209 then
2210 eval "${return_bad}";
2212 mdf_spec="$1";
2213 mdf_name='';
2214 mdf_section='';
2215 case "${mdf_spec}" in
2216 */*) # not a man spec when it contains '/'
2217 eval ${_UNSET} mdf_got_one;
2218 eval ${_UNSET} mdf_name;
2219 eval ${_UNSET} mdf_section;
2220 eval ${_UNSET} mdf_spec;
2221 eval "${return_bad}";
2223 man:?*\(?*\)) # man:name(section)
2224 mdf_name="$(echo x"${mdf_spec}" \
2225 | sed -e 's/^xman:\(..*\)(\(..*\))$/\1/')";
2226 mdf_section="$(echo x"${mdf_spec}" \
2227 | sed -e 's/^xman:\(..*\)(\(..*\))$/\2/')";
2229 man:?*.[0-9on]) # man:name.section
2230 mdf_name="$(echo x"${mdf_spec}" \
2231 | sed -e 's/^xman:\(..*\)\..$/\1/')";
2232 mdf_section="$(echo x"${mdf_spec}" \
2233 | sed -e 's/^x.*\(.\)$/\1/')";
2235 man:?*) # man:name
2236 mdf_name="$(echo x"${mdf_spec}" | sed -e 's/^xman://')";
2238 ?*\(?*\)) # name(section)
2239 mdf_name="$(echo x"${mdf_spec}" \
2240 | sed -e 's/^x\(..*\)(\(..*\))$/\1/')";
2241 mdf_section="$(echo x"${mdf_spec}" \
2242 | sed -e 's/^x\(..*\)(\(..*\))$/\2/')";
2244 ?*.[0-9on]) # name.section
2245 mdf_name="$(echo x"${mdf_spec}" \
2246 | sed -e 's/^x\(..*\)\..$/\1/')";
2247 mdf_section="$(echo x"${mdf_spec}" \
2248 | sed -e 's/^x.*\(.\)$/\1/')";
2251 mdf_name="${mdf_spec}";
2253 esac;
2254 if obj mdf_name is_empty;
2255 then
2256 eval ${_UNSET} mdf_got_one;
2257 eval ${_UNSET} mdf_name;
2258 eval ${_UNSET} mdf_section;
2259 eval ${_UNSET} mdf_spec;
2260 eval "${return_bad}";
2262 mdf_got_one='no';
2263 if obj mdf_section is_empty;
2264 then
2265 eval set x "${_MAN_AUTO_SEC}";
2266 shift;
2267 for s
2269 mdf_s="$s";
2270 if man_search_section "${mdf_name}" "${mdf_s}";
2271 then # found
2272 if obj _MAN_ALL is_yes;
2273 then
2274 mdf_got_one='yes';
2275 else
2276 eval ${_UNSET} mdf_got_one;
2277 eval ${_UNSET} mdf_name;
2278 eval ${_UNSET} mdf_s;
2279 eval ${_UNSET} mdf_section;
2280 eval ${_UNSET} mdf_spec;
2281 eval "${return_good}";
2284 done;
2285 else
2286 if man_search_section "${mdf_name}" "${mdf_section}";
2287 then
2288 eval ${_UNSET} mdf_got_one;
2289 eval ${_UNSET} mdf_name;
2290 eval ${_UNSET} mdf_s;
2291 eval ${_UNSET} mdf_section;
2292 eval ${_UNSET} mdf_spec;
2293 eval "${return_good}";
2294 else
2295 eval ${_UNSET} mdf_got_one;
2296 eval ${_UNSET} mdf_name;
2297 eval ${_UNSET} mdf_section;
2298 eval ${_UNSET} mdf_spec;
2299 eval "${return_bad}";
2302 if obj _MAN_ALL is_yes && is_yes "${mdf_got_one}";
2303 then
2304 eval ${_UNSET} mdf_got_one;
2305 eval ${_UNSET} mdf_name;
2306 eval ${_UNSET} mdf_s;
2307 eval ${_UNSET} mdf_section;
2308 eval ${_UNSET} mdf_spec;
2309 eval "${return_good}";
2311 eval ${_UNSET} mdf_got_one;
2312 eval ${_UNSET} mdf_name;
2313 eval ${_UNSET} mdf_s;
2314 eval ${_UNSET} mdf_section;
2315 eval ${_UNSET} mdf_spec;
2316 eval "${return_bad}";
2317 } # man_do_filespec()
2320 ########################################################################
2321 # man_register_file (<file> <name> [<section>])
2323 # Write a found man page file and register the title element.
2325 # Arguments: 1, 2, or 3; maybe empty
2326 # Output: none
2328 man_register_file()
2330 func_check man_register_file '>=' 2 "$@";
2331 case "$#" in
2332 2|3) do_nothing; ;;
2334 error "man_register_file() expects 2 or 3 arguments.";
2336 esac;
2337 if is_empty "$1";
2338 then
2339 error 'man_register_file(): file name is empty';
2341 to_tmp "$1";
2342 case "$#" in
2344 register_title "man:$2";
2345 eval "${return_ok}";
2348 register_title "$2.$3";
2349 eval "${return_ok}";
2351 esac;
2352 eval "${return_ok}";
2356 ########################################################################
2357 # man_search_section (<name> <section>)
2359 # Retrieve man pages.
2361 # Arguments : 2
2362 # Globals : $_MAN_PATH, $_MAN_EXT
2363 # Return : 0 if found, 1 otherwise
2365 # Variable prefix: mss
2367 man_search_section()
2369 func_check man_search_section = 2 "$@";
2370 if obj _MAN_PATH is_empty;
2371 then
2372 eval "${return_bad}";
2374 if is_empty "$1";
2375 then
2376 eval "${return_bad}";
2378 if is_empty "$2";
2379 then
2380 eval "${return_bad}";
2382 mss_name="$1";
2383 mss_section="$2";
2384 eval set x "$(path_split "${_MAN_PATH}")";
2385 shift;
2386 mss_got_one='no';
2387 if obj _MAN_EXT is_empty;
2388 then
2389 for d
2391 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2392 if obj mss_dir is_dir;
2393 then
2394 mss_prefix="$(\
2395 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2396 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2397 sed -e '\| found|s|.*||'
2399 if obj mss_files is_not_empty;
2400 then
2401 # for f in $mss_files
2402 for f in $(eval set x ${mss_files}; shift; echo "$@")
2404 mss_f="$f";
2405 if obj mss_f is_file;
2406 then
2407 if is_yes "${mss_got_one}";
2408 then
2409 register_file "${mss_f}";
2410 elif obj _MAN_ALL is_yes;
2411 then
2412 man_register_file "${mss_f}" "${mss_name}";
2413 else
2414 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2415 eval ${_UNSET} mss_dir;
2416 eval ${_UNSET} mss_ext;
2417 eval ${_UNSET} mss_f;
2418 eval ${_UNSET} mss_files;
2419 eval ${_UNSET} mss_got_one;
2420 eval ${_UNSET} mss_name;
2421 eval ${_UNSET} mss_prefix;
2422 eval ${_UNSET} mss_section;
2423 eval "${return_good}";
2425 mss_got_one='yes';
2427 done;
2430 done;
2431 else
2432 mss_ext="${_MAN_EXT}";
2433 # check for directory name having trailing extension
2434 for d
2436 mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";
2437 if obj mss_dir is_dir;
2438 then
2439 mss_prefix=\
2440 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2441 mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2442 sed -e '\|not found|s|.*||'
2444 if obj mss_files is_not_empty;
2445 then
2446 # for f in $mss_files
2447 for f in $(eval set x ${mss_files}; shift; echo "$@")
2449 mss_f="$f";
2450 if obj mss_f is_file;
2451 then
2452 if is_yes "${mss_got_one}";
2453 then
2454 register_file "${mss_f}";
2455 elif obj _MAN_ALL is_yes;
2456 then
2457 man_register_file "${mss_f}" "${mss_name}";
2458 else
2459 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2460 eval ${_UNSET} mss_dir;
2461 eval ${_UNSET} mss_ext;
2462 eval ${_UNSET} mss_f;
2463 eval ${_UNSET} mss_files;
2464 eval ${_UNSET} mss_got_one;
2465 eval ${_UNSET} mss_name;
2466 eval ${_UNSET} mss_prefix;
2467 eval ${_UNSET} mss_section;
2468 eval "${return_good}";
2470 mss_got_one='yes';
2472 done;
2475 done;
2476 # check for files with extension in directories without extension
2477 for d
2479 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2480 if obj mss_dir is_dir;
2481 then
2482 mss_prefix="$(dirname_append "${mss_dir}" \
2483 "${mss_name}.${mss_section}${mss_ext}")";
2484 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2485 sed -e '\|not found|s|.*||'
2487 if obj mss_files is_not_empty;
2488 then
2489 # for f in $mss_files
2490 for f in $(eval set x ${mss_files}; shift; echo "$@")
2492 mss_f="$f";
2493 if obj mss_f is_file;
2494 then
2495 if is_yes "${mss_got_one}";
2496 then
2497 register_file "${mss_f}";
2498 elif obj _MAN_ALL is_yes;
2499 then
2500 man_register_file "${mss_f}" "${mss_name}";
2501 else
2502 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2503 eval ${_UNSET} mss_dir;
2504 eval ${_UNSET} mss_ext;
2505 eval ${_UNSET} mss_f;
2506 eval ${_UNSET} mss_files;
2507 eval ${_UNSET} mss_got_one;
2508 eval ${_UNSET} mss_name;
2509 eval ${_UNSET} mss_prefix;
2510 eval ${_UNSET} mss_section;
2511 eval "${return_good}";
2513 mss_got_one='yes';
2515 done;
2518 done;
2520 if obj _MAN_ALL is_yes && is_yes "${mss_got_one}";
2521 then
2522 eval ${_UNSET} mss_dir;
2523 eval ${_UNSET} mss_ext;
2524 eval ${_UNSET} mss_f;
2525 eval ${_UNSET} mss_files;
2526 eval ${_UNSET} mss_got_one;
2527 eval ${_UNSET} mss_name;
2528 eval ${_UNSET} mss_prefix;
2529 eval ${_UNSET} mss_section;
2530 eval "${return_good}";
2532 eval ${_UNSET} mss_dir;
2533 eval ${_UNSET} mss_ext;
2534 eval ${_UNSET} mss_f;
2535 eval ${_UNSET} mss_files;
2536 eval ${_UNSET} mss_got_one;
2537 eval ${_UNSET} mss_name;
2538 eval ${_UNSET} mss_prefix;
2539 eval ${_UNSET} mss_section;
2540 eval "${return_bad}";
2541 } # man_search_section()
2544 ########################################################################
2545 # man_setup ()
2547 # Setup the variables $_MAN_* needed for man page searching.
2549 # Globals:
2550 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2551 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2552 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2553 # $_MAN_SEC, $_MAN_ALL
2554 # in/out: $_MAN_ENABLE
2556 # The precedence for the variables related to `man' is that of GNU
2557 # `man', i.e.
2559 # $LANG; overridden by
2560 # $LC_MESSAGES; overridden by
2561 # $LC_ALL; this has the same precedence as
2562 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2563 # $MANOPT; overridden by
2564 # the groffer command line options.
2566 # Variable prefix: ms
2568 man_setup()
2570 func_check main_man_setup = 0 "$@";
2572 if obj _MAN_IS_SETUP is_yes;
2573 then
2574 eval "${return_ok}";
2576 _MAN_IS_SETUP='yes';
2578 if obj _MAN_ENABLE is_not_yes;
2579 then
2580 eval "${return_ok}";
2583 # determine basic path for man pages
2584 _MAN_PATH="$(get_first_essential \
2585 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2586 if obj _MAN_PATH is_empty;
2587 then
2588 manpath_set_from_path;
2589 else
2590 _MAN_PATH="$(path_clean "${_MAN_PATH}")";
2592 if obj _MAN_PATH is_empty;
2593 then
2594 if is_prog 'manpath';
2595 then
2596 _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available
2599 if obj _MAN_PATH is_empty;
2600 then
2601 _MAN_ENABLE="no";
2602 eval "${return_ok}";
2605 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2606 if obj _MAN_ALL is_empty;
2607 then
2608 _MAN_ALL='no';
2611 _MAN_SYS="$(get_first_essential \
2612 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2613 ms_lang="$(get_first_essential \
2614 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2615 case "${ms_lang}" in
2616 C|POSIX)
2617 _MAN_LANG="";
2618 _MAN_LANG2="";
2621 _MAN_LANG="${ms_lang}";
2622 _MAN_LANG2="";
2625 _MAN_LANG="${ms_lang}";
2626 # get first two characters of $ms_lang
2627 _MAN_LANG2="$(echo x"${ms_lang}" | sed -e 's/^x\(..\).*$/\1/')";
2629 esac;
2630 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2632 manpath_add_lang_sys; # this is very slow
2634 _MAN_SEC="$(get_first_essential \
2635 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2636 if obj _MAN_PATH is_empty;
2637 then
2638 _MAN_ENABLE="no";
2639 eval ${_UNSET} ms_lang;
2640 eval "${return_ok}";
2643 _MAN_EXT="$(get_first_essential \
2644 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2645 eval ${_UNSET} ms_lang;
2646 eval "${return_ok}";
2647 } # man_setup()
2650 ########################################################################
2651 landmark '8: manpath_*()';
2652 ########################################################################
2654 ########################################################################
2655 # manpath_add_lang_sys ()
2657 # Add language and operating system specific directories to man path.
2659 # Arguments : 0
2660 # Output : none
2661 # Globals:
2662 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2663 # list of names of operating systems.
2664 # $_MAN_LANG and $_MAN_LANG2: each a single name
2665 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2666 # separated list of directories.
2668 # Variable prefix: mals
2670 manpath_add_lang_sys()
2672 func_check manpath_add_lang_sys = 0 "$@";
2673 if obj _MAN_PATH is_empty;
2674 then
2675 eval "${return_ok}";
2677 # twice test both sys and lang
2678 eval set x "$(path_split "${_MAN_PATH}")";
2679 shift;
2680 mals_mp='';
2681 for p
2682 do # loop on man path directories
2683 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2684 done;
2685 eval set x "$(path_split "${mals_mp}")";
2686 shift;
2687 for p
2688 do # loop on man path directories
2689 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2690 done;
2691 _MAN_PATH="$(path_chop "${mals_mp}")";
2692 eval ${_UNSET} mals_mp;
2693 eval "${return_ok}";
2697 # To the directory in $1 append existing sys/lang subdirectories
2698 # Function is necessary to split the OS list.
2700 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2701 # argument: 2: `man_path' and `dir'
2702 # output: colon-separated path of the retrieved subdirectories
2704 # Variable prefix: _mals
2706 _manpath_add_lang_sys_single()
2708 func_check _manpath_add_lang_sys_single = 2 "$@";
2709 _mals_res="$1";
2710 _mals_parent="$2";
2711 eval set x "$(list_from_split "${_MAN_SYS}" ',')";
2712 shift;
2713 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
2715 _mals_dir="$(dirname_append "${_mals_parent}" "$d")";
2716 if obj _mals_res path_not_contains "${_mals_dir}" && \
2717 obj _mals_dir is_dir;
2718 then
2719 _mals_res="${_mals_res}:${_mals_dir}";
2721 done;
2722 if path_not_contains "${_mals_res}" "${_mals_parent}";
2723 then
2724 _mals_res="${_mals_res}:${_mals_parent}";
2726 path_chop "${_mals_res}";
2727 eval ${_UNSET} _mals_dir;
2728 eval ${_UNSET} _mals_parent;
2729 eval ${_UNSET} _mals_res;
2730 eval "${return_ok}";
2733 # end manpath_add_lang_sys ()
2736 ########################################################################
2737 # manpath_set_from_path ()
2739 # Determine basic search path for man pages from $PATH.
2741 # Return: `0' if a valid man path was retrieved.
2742 # Output: none
2743 # Globals:
2744 # in: $PATH
2745 # out: $_MAN_PATH
2747 # Variable prefix: msfp
2749 manpath_set_from_path()
2751 func_check manpath_set_from_path = 0 "$@";
2753 msfp_manpath='';
2755 # get a basic man path from $PATH
2756 if obj PATH is_not_empty;
2757 then
2758 eval set x "$(path_split "${PATH}")";
2759 shift;
2760 for d
2762 # delete the final `/bin' part
2763 msfp_base="$(echo x"$d" | sed -e '
2764 s/^x//
2765 s|//*bin/*$||
2766 ')";
2767 for e in /share/man /man
2769 msfp_mandir="${msfp_base}$e";
2770 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}";
2771 then
2772 msfp_manpath="${msfp_manpath}:${msfp_mandir}";
2774 done;
2775 done;
2778 # append some default directories
2779 for d in /usr/local/share/man /usr/local/man \
2780 /usr/share/man /usr/man \
2781 /usr/X11R6/man /usr/openwin/man \
2782 /opt/share/man /opt/man \
2783 /opt/gnome/man /opt/kde/man
2785 msfp_d="$d";
2786 if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir;
2787 then
2788 msfp_manpath="${msfp_manpath}:${mfsp_d}";
2790 done;
2792 _MAN_PATH="${msfp_manpath}";
2793 eval ${_UNSET} msfp_base;
2794 eval ${_UNSET} msfp_d;
2795 eval ${_UNSET} msfp_mandir;
2796 eval ${_UNSET} msfp_manpath;
2797 eval "${return_ok}";
2798 } # manpath_set_from_path()
2801 ########################################################################
2802 landmark '9: obj_*()';
2803 ########################################################################
2805 ########################################################################
2806 # obj (<object> <call_name> <arg>...)
2808 # This works like a method (object function) call for an object.
2809 # Run "<call_name> $<object> <arg> ...".
2811 # The first argument represents an object whose data is given as first
2812 # argument to <call_name>().
2814 # Argument: >=2
2815 # <object>: variable name
2816 # <call_name>: a program or function name
2818 # Variable prefix: o
2820 obj()
2822 func_check obj '>=' 2 "$@";
2823 if is_empty "$2";
2824 then
2825 error "obj(): function name is empty."
2826 else
2827 o_func="$2";
2829 eval o_arg1='"${'$1'}"';
2830 shift;
2831 shift;
2832 eval "${o_func}"' "${o_arg1}" "$@"';
2833 n="$?";
2834 eval ${_UNSET} o_arg1;
2835 eval ${_UNSET} o_func;
2836 eval "${return_var} $n";
2837 } # obj()
2840 ########################################################################
2841 # obj_data (<object>)
2843 # Print the data of <object>, i.e. the content of $<object>.
2844 # For possible later extensions.
2846 # Arguments: 1
2847 # <object>: a variable name
2848 # Output: the data of <object>
2850 # Variable prefix: od
2852 obj_data()
2854 func_check obj '=' 1 "$@";
2855 if is_empty "$1";
2856 then
2857 error "obj_data(): object name is empty."
2859 eval od_res='"${'$1'}"';
2860 cat <<EOF
2861 ${od_res}
2863 eval ${_UNSET} od_res;
2864 eval "${return_ok}";
2868 ########################################################################
2869 # obj_from_output (<object> <call_name> <arg>...)
2871 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2872 # function call to a global variable.
2874 # Arguments: >=2
2875 # <object>: a variable name
2876 # <call_name>: the name of a function or program
2877 # <arg>: optional argument to <call_name>
2878 # Output: none
2880 # Variable prefix: ofo
2882 obj_from_output()
2884 func_check obj_from_output '>=' 2 "$@";
2885 if is_empty "$1";
2886 then
2887 error "res(): variable name is empty.";
2888 elif is_empty "$2";
2889 then
2890 error "res(): function name is empty."
2891 else
2892 ofo_result_name="$1";
2894 shift;
2895 eval "${ofo_result_name}"'="$('"$@"')"';
2896 eval "${return_ok}";
2900 ########################################################################
2901 # obj_set (<object> <data>)
2903 # Set the data of <object>, i.e. call "$<object>=<data>".
2905 # Arguments: 2
2906 # <object>: a variable name
2907 # <data>: a string
2908 # Output:: none
2910 obj_set()
2912 func_check obj_set '=' 2 "$@";
2913 if is_empty "$1";
2914 then
2915 error "obj_set(): object name is empty."
2917 eval "$1"='"$2"';
2918 eval "${return_ok}";
2922 ########################################################################
2923 # path_chop (<path>)
2925 # Remove unnecessary colons from path.
2927 # Argument: 1, a colon separated path.
2928 # Output: path without leading, double, or trailing colons.
2930 path_chop()
2932 func_check path_chop = 1 "$@";
2934 # replace multiple colons by a single colon `:'
2935 # remove leading and trailing colons
2936 echo x"$1" | sed -e '
2937 s/^x:*//
2938 s/:::*/:/g
2939 s/:*$//
2941 eval "${return_ok}";
2945 ########################################################################
2946 # path_clean (<path>)
2948 # Remove non-existing directories from a colon-separated list.
2950 # Argument: 1, a colon separated path.
2951 # Output: colon-separated list of existing directories.
2953 # Variable prefix: pc
2955 path_clean()
2957 func_check path_clean = 1 "$@";
2958 if is_not_equal "$#" 1;
2959 then
2960 error 'path_clean() needs 1 argument.';
2962 pc_arg="$1";
2963 eval set x "$(path_split "${pc_arg}")";
2964 shift;
2965 pc_res="";
2966 for i
2968 pc_i="$i";
2969 if obj pc_i is_not_empty \
2970 && obj pc_res path_not_contains "${pc_i}" \
2971 && obj pc_i is_dir;
2972 then
2973 case "${pc_i}" in
2974 ?*/) pc_res="${pc_res}$(dirname_chop "${pc_i}")"; ;;
2975 *) pc_res="${pc_res}:${pc_i}";
2976 esac;
2978 done;
2979 eval ${_UNSET} pc_arg;
2980 eval ${_UNSET} pc_i;
2981 eval ${_UNSET} pc_res;
2982 if path_chop "${pc_res}";
2983 then
2984 eval "${return_ok}";
2985 else
2986 eval "${return_bad}";
2991 ########################################################################
2992 # path_contains (<path> <dir>)
2994 # Test whether `dir' is contained in `path', a list separated by `:'.
2996 # Arguments : 2 arguments.
2997 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2999 path_contains()
3001 func_check path_contains = 2 "$@";
3002 case ":$1:" in
3003 *":$2:"*)
3004 eval "${return_yes}";
3007 eval "${return_no}";
3009 esac;
3010 eval "${return_ok}";
3014 ########################################################################
3015 # path_not_contains (<path> <dir>)
3017 # Test whether `dir' is not contained in colon separated `path'.
3019 # Arguments : 2 arguments.
3021 path_not_contains()
3023 func_check path_not_contains = 2 "$@";
3024 if path_contains "$1" "$2";
3025 then
3026 eval "${return_no}";
3027 else
3028 eval "${return_yes}";
3030 eval "${return_ok}";
3034 ########################################################################
3035 # path_split (<path>)
3037 # In `path' escape white space and replace each colon by a space.
3039 # Arguments: 1: a colon-separated path
3040 # Output: the resulting list, process with `eval set'
3042 path_split()
3044 func_check path_split = 1 "$@";
3045 list_from_split "$1" ':';
3046 eval "${return_ok}";
3050 ########################################################################
3051 landmark '10: register_*()';
3052 ########################################################################
3054 ########################################################################
3055 # register_file (<filename>)
3057 # Write a found file and register the title element.
3059 # Arguments: 1: a file name
3060 # Output: none
3062 register_file()
3064 func_check register_file = 1 "$@";
3065 if is_empty "$1";
3066 then
3067 error 'register_file(): file name is empty';
3069 if is_equal "$1" '-';
3070 then
3071 to_tmp "${_TMP_STDIN}";
3072 register_title 'stdin';
3073 else
3074 to_tmp "$1";
3075 register_title "$(base_name "$1")";
3077 eval "${return_ok}";
3081 ########################################################################
3082 # register_title (<filespec>)
3084 # Create title element from <filespec> and append to $_REGISTERED_TITLE
3086 # Globals: $_REGISTERED_TITLE (rw)
3088 # Variable prefix: rt
3090 register_title()
3092 func_check register_title = 1 "$@";
3093 if is_empty "$1";
3094 then
3095 eval "${return_ok}";
3097 rt_title="$(base_name "$1")"; # remove directory part
3099 # remove extension `.gz'
3100 rt_title="$(echo x"${rt_title}" | sed -e '
3101 s/^x//
3102 s/\.gz$//
3103 ')";
3104 # remove extension `.Z'
3105 rt_title="$(echo x"${rt_title}" | sed -e '
3106 s/^x//
3107 s/\.Z$//
3108 ')";
3110 if obj rt_title is_empty;
3111 then
3112 eval "${return_ok}";
3114 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";
3115 eval ${_UNSET} rt_title;
3116 eval "${return_ok}";
3120 ########################################################################
3121 # reset ()
3123 # Reset the variables that can be affected by options to their default.
3126 # Defined in section `Preset' after the rudimentary shell tests.
3129 ########################################################################
3130 # save_stdin ()
3132 # Store standard input to temporary file (with decompression).
3134 # Variable prefix: ss
3136 if obj _HAS_COMPRESSION is_yes;
3137 then
3138 save_stdin()
3140 func_check save_stdin = 0 "$@";
3141 ss_f="${_TMP_DIR}"/INPUT;
3142 cat >"${ss_f}";
3143 cat_z "${ss_f}" >"${_TMP_STDIN}";
3144 rm -f "${ss_f}";
3145 eval ${_UNSET} ss_f;
3146 eval "${return_ok}";
3148 else
3149 save_stdin()
3151 func_check save_stdin = 0 "$@";
3152 cat >"${_TMP_STDIN}";
3153 eval "${return_ok}";
3158 ########################################################################
3159 landmark '11: stack_*()';
3160 ########################################################################
3162 ########################################################################
3163 # string_contains (<string> <part>)
3165 # Test whether `part' is contained in `string'.
3167 # Arguments : 2 text arguments.
3168 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3170 string_contains()
3172 func_check string_contains = 2 "$@";
3173 case "$1" in
3174 *"$2"*)
3175 eval "${return_yes}";
3178 eval "${return_no}";
3180 esac;
3181 eval "${return_ok}";
3185 ########################################################################
3186 # string_not_contains (<string> <part>)
3188 # Test whether `part' is not substring of `string'.
3190 # Arguments : 2 text arguments.
3191 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3193 string_not_contains()
3195 func_check string_not_contains = 2 "$@";
3196 if string_contains "$1" "$2";
3197 then
3198 eval "${return_no}";
3199 else
3200 eval "${return_yes}";
3202 eval "${return_ok}";
3206 ########################################################################
3207 landmark '12: tmp_*()';
3208 ########################################################################
3210 ########################################################################
3211 # tmp_cat ()
3213 # output the temporary cat file (the concatenation of all input)
3215 tmp_cat()
3217 func_check tmp_cat '=' 0 "$@";
3218 cat "${_TMP_CAT}";
3219 eval "${return_var}" "$?";
3223 ########################################################################
3224 # tmp_create (<suffix>?)
3226 # Create temporary file.
3228 # It's safe to use the shell process ID together with a suffix to
3229 # have multiple temporary files.
3231 # Globals: $_TMP_DIR
3233 # Output : name of created file
3235 # Variable prefix: tc
3237 tmp_create()
3239 func_check tmp_create '<=' 1 "$@";
3240 # the output file does not have `,' as first character, so these are
3241 # different names from the output file.
3242 tc_tmp="${_TMP_DIR}/,$1";
3243 : >"${tc_tmp}"
3244 cat <<EOF
3245 ${tc_tmp}
3247 eval ${_UNSET} tc_tmp;
3248 eval "${return_ok}";
3252 ########################################################################
3253 # to_tmp (<filename>)
3255 # print file (decompressed) to the temporary cat file
3257 to_tmp()
3259 func_check to_tmp = 1 "$@";
3260 if is_file "$1";
3261 then
3262 if obj _OPT_LOCATION is_yes;
3263 then
3264 echo2 "$1";
3266 if obj _OPT_WHATIS is_yes;
3267 then
3268 what_is "$1" >>"${_TMP_CAT}";
3269 else
3270 cat_z "$1" >>"${_TMP_CAT}";
3272 else
3273 error "to_tmp(): could not read file \`$1'.";
3275 eval "${return_ok}";
3279 ########################################################################
3280 # trap_clean ()
3282 # disable trap on all exit codes ($_ALL_EXIT)
3284 # Arguments: 0
3285 # Globals: $_ALL_EXIT
3287 trap_clean()
3289 func_check trap_clean = 0 "$@";
3290 # for i in $_ALL_EXIT
3291 for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")
3293 trap "" "$i" 2>${_NULL_DEV} || :;
3294 done;
3295 eval "${return_ok}";
3299 ########################################################################
3300 # trap_set (<functionname>)
3302 # call function on all exit codes ($_ALL_EXIT)
3304 # Arguments: 1 (name of a shell function)
3305 # Globals: $_ALL_EXIT
3307 trap_set()
3309 func_check trap_set = 1 "$@";
3310 # for i in $_ALL_EXIT
3311 for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")
3313 trap "$1" "$i" 2>${_NULL_DEV} || :;
3314 done;
3315 eval "${return_ok}";
3319 ########################################################################
3320 # usage ()
3322 # print usage information to stderr; for groffer option --help.
3324 usage()
3326 func_check usage = 0 "$@";
3327 echo;
3328 version;
3329 echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';
3330 cat <<EOF
3332 Display roff files, standard input, and/or Unix manual pages with a X
3333 Window viewer or in several text modes. All input is decompressed
3334 on-the-fly with all formats that gzip can handle.
3336 "filespec" is one of
3337 "filename" name of a readable file
3338 "-" for standard input
3339 "man:name.n" man page "name" in section "n"
3340 "man:name" man page "name" in first section found
3341 "name.n" man page "name" in section "n"
3342 "name" man page "name" in first section found
3343 and some more (see groffer(1) for details).
3345 -h --help print this usage message.
3346 -Q --source output as roff source.
3347 -T --device=name pass to groff using output device "name".
3348 -v --version print version information.
3349 -V display the groff execution pipe instead of formatting.
3350 -X --X --x display with "gxditview" using groff -X.
3351 -Z --ditroff --intermediate-output
3352 generate groff intermediate output without
3353 post-processing and viewing, like groff -Z.
3354 All other short options are interpreted as "groff" formatting options.
3356 The most important groffer long options are
3358 --apropos=name start man's "apropos" program for "name".
3359 --apropos-data=name
3360 "apropos" for "name" in man's data sections 4, 5, 7.
3361 --apropos-devel=name
3362 "apropos" for "name" in development sections 2, 3, 9.
3363 --apropos-progs=name
3364 "apropos" for "name" in man's program sections 1, 6, 8.
3365 --auto choose mode automatically from the default mode list.
3366 --default reset all options to the default value.
3367 --default-modes=mode1,mode2,...
3368 set sequence of automatically tried modes.
3369 --dvi display in a viewer for TeX device independent format.
3370 --dvi-viewer choose the viewer program for dvi mode.
3371 --groff process like groff, disable viewing features.
3372 --help display this helping output.
3373 --html --www display in a web browser.
3374 --html-viewer choose the web browser for www mode.
3375 --man check file parameters first whether they are man pages.
3376 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3377 choose display mode.
3378 --no-man disable man-page facility.
3379 --pager=program preset the paging program for tty mode.
3380 --pdf display in a PDF viewer.
3381 --pdf-viewer choose the viewer program for pdf mode.
3382 --ps display in a Postscript viewer.
3383 --ps-viewer choose the viewer program for ps mode.
3384 --shell specify shell under which to run this program.
3385 --text output in a text device without a pager.
3386 --tty display with a pager on text terminal even when in X.
3387 --www-viewer same as --html-viewer
3388 --x-viewer choose viewer program for x mode (X mode).
3389 --X-viewer same as "--xviewer".
3391 The usual X Windows toolkit options transformed into GNU long options
3392 --background=color, --bd=size, --bg=color, --bordercolor=color,
3393 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3394 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3395 --resolution=dpi, --rv, --title=text, --xrm=resource
3397 Long options of GNU "man"
3398 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3399 --local-file=name, --location, --manpath=dir1:dir2:...,
3400 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3403 eval "${return_ok}";
3407 ########################################################################
3408 # version ()
3410 # print version information to stderr
3412 version()
3414 func_check version = 0 "$@";
3415 echo2 "${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3416 # also display groff's version, but not the called subprograms
3417 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2;
3418 eval "${return_ok}";
3422 ########################################################################
3423 # warning (<string>)
3425 # Print warning to stderr
3427 warning()
3429 echo2 "warning: $*";
3433 ########################################################################
3434 # what_is (<filename>)
3436 # Interpret <filename> as a man page and display its `whatis'
3437 # information as a fragment written in the groff language.
3439 # Variable prefix: wi
3441 what_is()
3443 func_check what_is = 1 "$@";
3444 if is_not_file "$1";
3445 then
3446 error "what_is(): argument is not a readable file."
3448 wi_dot='^\.['"${_SPACE}${_TAB}"']*';
3449 cat <<EOF
3454 # grep the line containing `.TH' macro, if any
3455 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'TH /p
3456 d')";
3457 if obj wi_res is_not_empty;
3458 then # traditional man style
3459 # get the text between the first and the second `.SH' macro, by
3460 # - delete up to first .SH;
3461 # - of this, print everything up to next .SH, and delete the rest;
3462 # - of this, delete the final .SH line;
3463 cat_z "$1" | sed -e '1,/'"${wi_dot}"'SH/d' \
3464 | sed -e '1,/'"${wi_dot}"'SH/p
3465 d' \
3466 | sed -e '/'"${wi_dot}"'SH/d';
3467 eval ${_UNSET} wi_dot;
3468 eval ${_UNSET} wi_res;
3469 eval "${return_ok}";
3471 # grep the line containing `.Dd' macro, if any
3472 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'Dd /p
3473 d')";
3474 if obj wi_res is_not_empty;
3475 then # BSD doc style
3476 # get the text between the first and the second `.Nd' macro, by
3477 # - delete up to first .Nd;
3478 # - of this, print everything up to next .Nd, and delete the rest;
3479 # - of this, delete the final .Nd line;
3480 cat_z "$1" | sed -e '1,/'"${wi_dot}"'Nd/d' \
3481 | sed -e '1,/'"${wi_dot}"'Nd/p
3482 d' \
3483 | sed -e '/'"${wi_dot}"'Nd/d';
3484 eval ${_UNSET} wi_dot;
3485 eval ${_UNSET} wi_res;
3486 eval "${return_ok}";
3488 echo 'is not a man page.';
3489 eval ${_UNSET} wi_dot;
3490 eval ${_UNSET} wi_res;
3491 eval "${return_bad}";
3495 ########################################################################
3496 # where_is (<program>)
3498 # Output path of a program if in $PATH.
3500 # Arguments : >=1 (empty allowed)
3501 # more args are ignored, this allows to specify progs with arguments
3502 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3504 # Variable prefix: w
3506 where_is()
3508 func_check where_is '>=' 1 "$@";
3509 w_arg="$1";
3510 if obj w_arg is_empty;
3511 then
3512 eval ${_UNSET} w_arg;
3513 eval "${return_bad}";
3515 case "${w_arg}" in
3517 eval ${_UNSET} w_arg;
3518 eval ${_UNSET} w_file;
3519 if test -f "${w_arg}" && test -x "${w_arg}";
3520 then
3521 eval "${return_ok}";
3522 else
3523 eval "${return_bad}";
3526 esac;
3527 eval set x "$(path_split "${PATH}")";
3528 shift;
3529 for p
3531 case "$p" in
3532 */) w_file=${p}${w_arg}; ;;
3533 *) w_file=${p}/${w_arg}; ;;
3534 esac;
3535 if test -f "${w_file}" && test -x "${w_file}";
3536 then
3537 cat <<EOF
3538 ${w_file}
3540 eval ${_UNSET} w_arg;
3541 eval ${_UNSET} w_file;
3542 eval "${return_ok}";
3544 done;
3545 eval ${_UNSET} w_arg;
3546 eval ${_UNSET} w_file;
3547 eval "${return_bad}";
3551 ########################################################################
3552 # main* Functions
3553 ########################################################################
3555 # The main area contains the following parts:
3556 # - main_init(): initialize temporary files and set exit trap
3557 # - main_parse_MANOPT(): parse $MANOPT
3558 # - main_parse_args(): argument parsing
3559 # - main_set_mode (): determine the display mode
3560 # - main_do_fileargs(): process filespec arguments
3561 # - main_set_resources(): setup X resources
3562 # - main_display(): do the displaying
3563 # - main(): the main function that calls all main_*()
3565 # These parts are implemented as functions, being defined below in the
3566 # sequence they are called in the main() function.
3569 landmark '13: main_init()';
3570 #######################################################################
3571 # main_init ()
3573 # set exit trap and create temporary files
3575 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3577 # Variable prefix: mi
3579 main_init()
3581 func_check main_init = 0 "$@";
3582 # call clean_up() on any signal
3583 trap_set clean_up;
3585 # create temporary directory
3586 umask 0022;
3587 _TMP_DIR='';
3588 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3589 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
3591 mi_dir="$d";
3592 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
3593 obj mi_dir is_not_writable;
3594 then
3595 continue;
3598 case "${mi_dir}" in
3600 _TMP_DIR="${mi_dir}";
3603 _TMP_DIR="${mi_dir}"'/';
3605 esac;
3606 _TMP_DIR="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
3607 if obj _TMP_DIR is_existing;
3608 then
3609 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3610 if obj _TMP_DIR is_existing;
3611 then
3612 mi_tdir_="${_TMP_DIR}"_;
3613 mi_n=1;
3614 mi_tdir_n="${mi_tdir_}${mi_n}";
3615 while obj mi_tdir_n is_existing;
3617 eval rm -f -r "'${mi_tdir_n}'" >${_NULL_DEV} 2>&1;
3618 if obj mi_tdir_n is_existing;
3619 then
3620 # directory could not be removed
3621 mi_n="$(expr "${mi_n}" + 1)";
3622 mi_tdir_n="${mi_tdir_}${mi_n}";
3623 continue;
3625 done;
3626 _TMP_DIR="${mi_tdir_n}";
3629 eval mkdir "${_TMP_DIR}";
3630 if is_not_equal "$?" 0;
3631 then
3632 if obj _TMP_DIR is_existing;
3633 then
3634 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3636 _TMP_DIR='';
3637 continue;
3639 if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable;
3640 then
3641 # $_TMP_DIR can now be used as temporary directory
3642 break;
3644 if obj _TMP_DIR is_existing;
3645 then
3646 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3648 _TMP_DIR='';
3649 continue;
3650 done;
3651 if obj _TMP_DIR is_empty;
3652 then
3653 error "main_init: \
3654 Couldn't create a directory for storing temporary files.";
3657 _TMP_CAT="$(tmp_create groffer_cat)";
3658 _TMP_STDIN="$(tmp_create groffer_input)";
3660 # groffer configuration files
3661 # for f in $_CONF_FILES
3662 for f in $(eval set x ${_CONF_FILES}; shift; echo "$@")
3664 mi_file="$f";
3665 if obj mi_file is_file;
3666 then
3667 echo '_groffer_opt=""' >>${_TMP_CAT};
3668 # collect the lines starting with a minus
3669 cat "$mi_file" | sed -e '
3670 /^[ ]*#/d
3671 s/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"/
3672 ' >>${_TMP_CAT};
3673 # prepend the collected information to $GROFFER_OPT
3674 echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
3676 done;
3677 eval . "${_TMP_CAT}";
3678 _TMP_CAT="$(tmp_create groffer_cat)";
3680 eval ${_UNSET} mi_dir;
3681 eval ${_UNSET} mi_file;
3682 eval ${_UNSET} mi_n;
3683 eval ${_UNSET} mi_tdir_;
3684 eval ${_UNSET} mi_tdir_n;
3685 eval "${return_ok}";
3686 } # main_init()
3689 landmark '14: main_parse_MANOPT()';
3690 ########################################################################
3691 # main_parse_MANOPT ()
3693 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3694 # string; found man arguments can be overwritten by the command line.
3696 # Globals:
3697 # in: $MANOPT, $_OPTS_MANOPT_*
3698 # out: $_MANOPT_*
3699 # in/out: $GROFFER_OPT
3701 # Variable prefix: mpm
3703 main_parse_MANOPT()
3705 func_check main_parse_MANOPT = 0 "$@";
3706 mpm_list='';
3707 if obj MANOPT is_not_empty;
3708 then
3709 MANOPT="$(echo x"${MANOPT}" | sed -e 's/^x'"${_SPACE}${_SPACE}"'*//')";
3711 if obj MANOPT is_empty;
3712 then
3713 eval ${_UNSET} mpm_list;
3714 eval ${_UNSET} mpm_opt;
3715 eval "${return_ok}";
3717 # add arguments in $MANOPT by mapping them to groffer options
3718 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3719 shift;
3720 until test "$#" -le 0 || is_equal "$1" '--';
3722 mpm_opt="$1";
3723 shift;
3724 case "${mpm_opt}" in
3725 -7|--ascii)
3726 list_append mpm_list '--ascii';
3728 -a|--all)
3729 list_append mpm_list '--all';
3731 -c|--catman)
3732 do_nothing;
3733 shift;
3735 -d|--debug)
3736 list_append mpm_list '--debug';
3738 -D|--default)
3739 # undo all man options so far
3740 mpm_list='';
3742 -e|--extension)
3743 list_append mpm_list '--extension';
3744 shift;
3746 -f|--whatis)
3747 list_append mpm_list '--whatis';
3748 shift;
3750 -h|--help)
3751 do_nothing;
3752 shift;
3754 -k|--apropos)
3755 # groffer's --apropos takes an argument, but man's does not, so
3756 do_nothing;
3757 shift;
3759 -l|--local-file)
3760 list_append mpm_list '--local-file';
3762 -L|--locale)
3763 list_append mpm_list '--locale' "$1";
3764 shift;
3766 -m|--systems)
3767 list_append mpm_list '--systems' "$1";
3768 shift;
3770 -M|--manpath)
3771 list_append mpm_list '--manpath' "$1";
3772 shift;
3774 -p|--preprocessor)
3775 do_nothing;
3776 shift;
3778 -P|--pager|--tty-viewer)
3779 list_append mpm_list '--pager' "$1";
3780 shift;
3782 -r|--prompt)
3783 do_nothing;
3784 shift;
3786 -S|--sections)
3787 list_append mpm_list '--sections' "$1";
3788 shift;
3790 -t|--troff)
3791 do_nothing;
3792 shift;
3794 -T|--device)
3795 list_append mpm_list '-T' "$1";
3796 shift;
3798 -u|--update)
3799 do_nothing;
3800 shift;
3802 -V|--version)
3803 do_nothing;
3805 -w|--where|--location)
3806 list_append mpm_list '--location';
3808 -Z|--ditroff)
3809 list_append mpm_list '-Z' "$1";
3810 shift;
3812 # ignore all other options
3813 esac;
3814 done;
3815 # append the 2 lists in $mpm_list and $GROFFER_OPT to $GROFFER_OPT
3816 if obj GROFFER_OPT is_empty;
3817 then
3818 GROFFER_OPT="${mpm_list}";
3819 elif obj mpm_list is_not_empty;
3820 then
3821 GROFFER_OPT="${mpm_list} ${GROFFER_OPT}";
3823 eval ${_UNSET} mpm_list;
3824 eval ${_UNSET} mpm_opt;
3825 eval "${return_ok}";
3826 } # main_parse_MANOPT()
3829 landmark '15: main_parse_args()';
3830 ########################################################################
3831 # main_parse_args (<command_line_args>*)
3833 # Parse arguments; process options and filespec parameters
3835 # Arguments: pass the command line arguments unaltered.
3836 # Globals:
3837 # in: $_OPTS_*
3838 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3840 # Variable prefix: mpa
3842 main_parse_args()
3844 func_check main_parse_args '>=' 0 "$@";
3846 eval set x "${GROFFER_OPT}" '"$@"';
3847 shift;
3849 eval set x "$(list_from_cmdline _OPTS_CMDLINE "$@")";
3850 shift;
3852 # By the call of `eval', unnecessary quoting was removed. So the
3853 # positional shell parameters ($1, $2, ...) are now guaranteed to
3854 # represent an option or an argument to the previous option, if any;
3855 # then a `--' argument for separating options and
3856 # parameters; followed by the filespec parameters if any.
3858 # Note, the existence of arguments to options has already been checked.
3859 # So a check for `$#' or `--' should not be done for arguments.
3861 until test "$#" -le 0 || is_equal "$1" '--';
3863 mpa_opt="$1"; # $mpa_opt is fed into the option handler
3864 shift;
3865 case "${mpa_opt}" in
3866 -h|--help)
3867 usage;
3868 leave;
3870 -Q|--source) # output source code (`Quellcode').
3871 _OPT_MODE='source';
3873 -T|--device|--troff-device) # device; arg
3874 _OPT_DEVICE="$1";
3875 _check_device_with_mode;
3876 shift;
3878 -v|--version)
3879 version;
3880 leave;
3883 _OPT_V='yes';
3885 -Z|--ditroff|--intermediate-output) # groff intermediate output
3886 _OPT_Z='yes';
3889 _OPT_MODE=X;
3892 # delete leading `-'
3893 mpa_optchar="$(echo x"${mpa_opt}" | sed -e 's/^x-//')";
3894 if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}";
3895 then
3896 list_append _ADDOPTS_GROFF "${mpa_opt}";
3897 elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}";
3898 then
3899 list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
3900 shift;
3901 else
3902 error "main_parse_args(): Unknown option : \`$1'";
3905 --all)
3906 _OPT_ALL="yes";
3908 --apropos) # run `apropos'
3909 apropos_run "$1";
3910 mpa_code="$?";
3911 clean_up;
3912 exit "${mpa_code}";
3914 --apropos-data) # run `apropos' for data sections
3915 apropos_run "$1" | grep '^[^(]*([457][^)]*)';
3916 mpa_code="$?";
3917 clean_up;
3918 exit "${mpa_code}";
3920 --apropos-devel) # run `apropos' for development sections
3921 apropos_run "$1" | grep '^[^(]*([239][^)]*)';
3922 mpa_code="$?";
3923 clean_up;
3924 exit "${mpa_code}";
3926 --apropos-progs) # run `apropos' for program sections
3927 apropos_run "$1" | grep '^[^(]*([168][^)]*)';
3928 mpa_code="$?";
3929 clean_up;
3930 exit "${mpa_code}";
3932 --ascii)
3933 list_append _ADDOPTS_GROFF '-mtty-char';
3934 if obj _OPT_MODE is_empty;
3935 then
3936 _OPT_MODE='text';
3939 --auto) # the default automatic mode
3940 _OPT_MODE='';
3942 --bd) # border color for viewers, arg;
3943 _OPT_BD="$1";
3944 shift;
3946 --bg|--backgroud) # background color for viewers, arg;
3947 _OPT_BG="$1";
3948 shift;
3950 --bw) # border width for viewers, arg;
3951 _OPT_BW="$1";
3952 shift;
3954 --default) # reset variables to default
3955 reset;
3957 --default-modes) # sequence of modes in auto mode; arg
3958 _OPT_DEFAULT_MODES="$1";
3959 shift;
3961 --debug) # only for development
3962 _OPT_DEBUG='yes';
3964 --display) # set X display, arg
3965 _OPT_DISPLAY="$1";
3966 shift;
3968 --dvi)
3969 _OPT_MODE='dvi';
3971 --dvi-viewer) # viewer program for dvi mode; arg
3972 _OPT_VIEWER_DVI="$1";
3973 shift;
3975 --extension) # the extension for man pages, arg
3976 _OPT_EXTENSION="$1";
3977 shift;
3979 --fg|--foreground) # foreground color for viewers, arg;
3980 _OPT_FG="$1";
3981 shift;
3983 --fn|--font) # set font for viewers, arg;
3984 _OPT_FN="$1";
3985 shift;
3987 --geometry) # window geometry for viewers, arg;
3988 _OPT_GEOMETRY="$1";
3989 shift;
3991 --groff)
3992 _OPT_MODE='groff';
3994 --html|--www) # display with web browser
3995 _OPT_MODE=html;
3997 --html-viewer|--www-viewer) # viewer program for html mode; arg
3998 _OPT_VIEWER_HTML="$1";
3999 shift;
4001 --iconic) # start viewers as icons
4002 _OPT_ICONIC='yes';
4004 --locale) # set language for man pages, arg
4005 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
4006 _OPT_LANG="$1";
4007 shift;
4009 --local-file) # force local files; same as `--no-man'
4010 _MAN_FORCE='no';
4011 _MAN_ENABLE='no';
4013 --location|--where) # print file locations to stderr
4014 _OPT_LOCATION='yes';
4016 --man) # force all file params to be man pages
4017 _MAN_ENABLE='yes';
4018 _MAN_FORCE='yes';
4020 --manpath) # specify search path for man pages, arg
4021 # arg is colon-separated list of directories
4022 _OPT_MANPATH="$1";
4023 shift;
4025 --mode) # display mode
4026 mpa_arg="$1";
4027 shift;
4028 case "${mpa_arg}" in
4029 auto|'') # search mode automatically among default
4030 _OPT_MODE='';
4032 groff) # pass input to plain groff
4033 _OPT_MODE='groff';
4035 html|www) # display with a web browser
4036 _OPT_MODE='html';
4038 dvi) # display with xdvi viewer
4039 _OPT_MODE='dvi';
4041 pdf) # display with PDF viewer
4042 _OPT_MODE='pdf';
4044 ps) # display with Postscript viewer
4045 _OPT_MODE='ps';
4047 text) # output on terminal
4048 _OPT_MODE='text';
4050 tty) # output on terminal
4051 _OPT_MODE='tty';
4053 X|x) # output on X roff viewer
4054 _OPT_MODE='x';
4056 Q|source) # display source code
4057 _OPT_MODE="source";
4060 error "main_parse_args(): unknown mode ${mpa_arg}";
4062 esac;
4064 --no-location) # disable former call to `--location'
4065 _OPT_LOCATION='yes';
4067 --no-man) # disable search for man pages
4068 # the same as --local-file
4069 _MAN_FORCE="no";
4070 _MAN_ENABLE="no";
4072 --pager) # set paging program for tty mode, arg
4073 _OPT_PAGER="$1";
4074 shift;
4076 --pdf)
4077 _OPT_MODE='pdf';
4079 --pdf-viewer) # viewer program for ps mode; arg
4080 _OPT_VIEWER_PDF="$1";
4081 shift;
4083 --ps)
4084 _OPT_MODE='ps';
4086 --ps-viewer) # viewer program for ps mode; arg
4087 _OPT_VIEWER_PS="$1";
4088 shift;
4090 --resolution) # set resolution for X devices, arg
4091 mpa_arg="$1";
4092 shift;
4093 case "${mpa_arg}" in
4094 75|75dpi)
4095 mpa_dpi=75;
4097 100|100dpi)
4098 mpa_dpi=100;
4101 error "main_parse_args(): \
4102 only resoutions of 75 or 100 dpi are supported";
4104 esac;
4105 _OPT_RESOLUTION="${mpa_dpi}";
4107 --rv)
4108 _OPT_RV='yes';
4110 --sections) # specify sections for man pages, arg
4111 # arg is colon-separated list of section names
4112 _OPT_SECTIONS="$1";
4113 shift;
4115 --shell)
4116 # already done during the first run; so ignore the argument
4117 shift;
4119 --systems) # man pages for different OS's, arg
4120 # argument is a comma-separated list
4121 _OPT_SYSTEMS="$1";
4122 shift;
4124 --text) # text mode without pager
4125 _OPT_MODE=text;
4127 --title) # title for X viewers; arg
4128 _OPT_TITLE="$1";
4129 shift;
4131 --tty) # tty mode, text with pager
4132 _OPT_MODE=tty;
4134 --text-device|--tty-device) # device for tty mode; arg
4135 _OPT_TEXT_DEVICE="$1";
4136 shift;
4138 --whatis)
4139 _OPT_WHATIS='yes';
4141 --X|--x)
4142 _OPT_MODE=x;
4144 --xrm) # pass X resource string, arg;
4145 list_append _OPT_XRM "$1";
4146 shift;
4148 --x-viewer|--X-viewer) # viewer program for x mode; arg
4149 _OPT_VIEWER_X="$1";
4150 shift;
4153 error 'main_parse_args(): error on argument parsing : '"\`$*'";
4155 esac;
4156 done;
4157 shift; # remove `--' argument
4159 if obj _DEBUG is_not_yes;
4160 then
4161 if obj _OPT_DEBUG is_yes;
4162 then
4163 _DEBUG='yes';
4164 _DEBUG_LM='yes';
4165 _DEBUG_KEEP_FILES='yes';
4169 # Remaining arguments are file names (filespecs).
4170 # Save them to list $_FILEARGS
4171 if is_equal "$#" 0;
4172 then # use "-" for standard input
4173 set x '-';
4174 shift;
4176 _FILEARGS='';
4177 list_append _FILEARGS "$@";
4178 if list_has _FILEARGS '-';
4179 then
4180 save_stdin;
4182 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4183 eval ${_UNSET} mpa_arg;
4184 eval ${_UNSET} mpa_code;
4185 eval ${_UNSET} mpa_dpi;
4186 eval ${_UNSET} mpa_opt;
4187 eval ${_UNSET} mpa_optchar;
4188 eval "${return_ok}";
4189 } # main_parse_args()
4192 # Called from main_parse_args() because double `case' is not possible.
4193 # Globals: $_OPT_DEVICE, $_OPT_MODE
4194 _check_device_with_mode()
4196 func_check _check_device_with_mode = 0 "$@";
4197 case "${_OPT_DEVICE}" in
4198 dvi)
4199 _OPT_MODE=dvi;
4200 eval "${return_ok}";
4202 html)
4203 _OPT_MODE=html;
4204 eval "${return_ok}";
4206 lbp|lj4)
4207 _OPT_MODE=groff;
4208 eval "${return_ok}";
4211 _OPT_MODE=ps;
4212 eval "${return_ok}";
4214 ascii|cp1047|latin1|utf8)
4215 if obj _OPT_MODE is_not_equal text;
4216 then
4217 _OPT_MODE=tty; # default text mode
4219 eval "${return_ok}";
4222 _OPT_MODE=x;
4223 eval "${return_ok}";
4225 *) # unknown device, go to groff mode
4226 _OPT_MODE=groff;
4227 eval "${return_ok}";
4229 esac;
4230 eval "${return_error}";
4231 } # _check_device_with_mode() of main_parse_args()
4234 landmark '16: main_set_mode()';
4235 ########################################################################
4236 # main_set_mode ()
4238 # Determine the display mode.
4240 # Globals:
4241 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4242 # out: $_DISPLAY_MODE
4244 # Variable prefix: msm
4246 main_set_mode()
4248 func_check main_set_mode = 0 "$@";
4250 # handle apropos
4251 if obj _OPT_APROPOS is_not_empty;
4252 then
4253 apropos "${_OPT_APROPOS}";
4254 msm_code="$?";
4255 clean_up;
4256 exit "${msm_code}";
4258 if obj _OPT_APROPOS_DATA is_not_empty;
4259 then
4260 apropos "$@" | grep '^[^(]*([457])';
4261 msm_code="$?";
4262 clean_up;
4263 exit "${msm_code}";
4265 if obj _OPT_APROPOS_DEVEL is_not_empty;
4266 then
4267 apropos "$@" | grep '^[^(]*([239])';
4268 msm_code="$?";
4269 clean_up;
4270 exit "${msm_code}";
4272 if obj _OPT_APROPOS_PROGS is_not_empty;
4273 then
4274 apropos "$@" | grep '^[^(]*([168])';
4275 msm_code="$?";
4276 clean_up;
4277 exit "${msm_code}";
4280 # set display
4281 if obj _OPT_DISPLAY is_not_empty;
4282 then
4283 DISPLAY="${_OPT_DISPLAY}";
4286 if obj _OPT_V is_yes;
4287 then
4288 list_append _ADDOPTS_GROFF '-V';
4290 if obj _OPT_Z is_yes;
4291 then
4292 _DISPLAY_MODE='groff';
4293 list_append _ADDOPTS_GROFF '-Z';
4295 if obj _OPT_MODE is_equal 'groff';
4296 then
4297 _DISPLAY_MODE='groff';
4299 if obj _DISPLAY_MODE is_equal 'groff';
4300 then
4301 eval ${_UNSET} msm_code;
4302 eval ${_UNSET} msm_modes;
4303 eval ${_UNSET} msm_viewer;
4304 eval ${_UNSET} msm_viewers;
4305 eval "${return_ok}";
4308 if obj _OPT_MODE is_equal 'source';
4309 then
4310 _DISPLAY_MODE='source';
4311 eval ${_UNSET} msm_code;
4312 eval ${_UNSET} msm_modes;
4313 eval ${_UNSET} msm_viewer;
4314 eval ${_UNSET} msm_viewers;
4315 eval "${return_ok}";
4318 case "${_OPT_MODE}" in
4319 '') # automatic mode
4320 case "${_OPT_DEVICE}" in
4322 if obj DISPLAY is_empty;
4323 then
4324 error "main_set_mode(): \
4325 no X display found for device ${_OPT_DEVICE}";
4327 _DISPLAY_MODE='x';
4328 eval ${_UNSET} msm_code;
4329 eval ${_UNSET} msm_modes;
4330 eval ${_UNSET} msm_viewer;
4331 eval ${_UNSET} msm_viewers;
4332 eval "${return_ok}";
4334 ascii|cp1047|latin1|utf8)
4335 if obj _DISPLAY_MODE is_not_equal 'text';
4336 then
4337 _DISPLAY_MODE='tty';
4339 eval ${_UNSET} msm_code;
4340 eval ${_UNSET} msm_modes;
4341 eval ${_UNSET} msm_viewer;
4342 eval ${_UNSET} msm_viewers;
4343 eval "${return_ok}";
4345 esac;
4346 if obj DISPLAY is_empty;
4347 then
4348 _DISPLAY_MODE='tty';
4349 eval ${_UNSET} msm_code;
4350 eval ${_UNSET} msm_modes;
4351 eval ${_UNSET} msm_viewer;
4352 eval ${_UNSET} msm_viewers;
4353 eval "${return_ok}";
4356 if obj _OPT_DEFAULT_MODES is_empty;
4357 then
4358 msm_modes="${_DEFAULT_MODES}";
4359 else
4360 msm_modes="${_OPT_DEFAULT_MODES}";
4363 text)
4364 _DISPLAY_MODE='text';
4365 eval ${_UNSET} msm_code;
4366 eval ${_UNSET} msm_modes;
4367 eval ${_UNSET} msm_viewer;
4368 eval ${_UNSET} msm_viewers;
4369 eval "${return_ok}";
4371 tty)
4372 _DISPLAY_MODE='tty';
4373 eval ${_UNSET} msm_code;
4374 eval ${_UNSET} msm_modes;
4375 eval ${_UNSET} msm_viewer;
4376 eval ${_UNSET} msm_viewers;
4377 eval "${return_ok}";
4379 *) # display mode was given
4380 if obj DISPLAY is_empty;
4381 then
4382 error "main_set_mode(): \
4383 you must be in X Window for ${_OPT_MODE} mode.";
4385 msm_modes="${_OPT_MODE}";
4387 esac;
4389 # only viewer modes are left
4390 eval set x "$(list_from_split "${msm_modes}" ',')";
4391 shift;
4392 while test "$#" -gt 0;
4394 m="$1";
4395 shift;
4396 case "$m" in
4397 text)
4398 _DISPLAY_MODE='text';
4399 eval ${_UNSET} msm_code;
4400 eval ${_UNSET} msm_modes;
4401 eval ${_UNSET} msm_viewer;
4402 eval ${_UNSET} msm_viewers;
4403 eval "${return_ok}";
4405 tty)
4406 _DISPLAY_MODE='tty';
4407 eval ${_UNSET} msm_code;
4408 eval ${_UNSET} msm_modes;
4409 eval ${_UNSET} msm_viewer;
4410 eval ${_UNSET} msm_viewers;
4411 eval "${return_ok}";
4414 if obj _OPT_VIEWER_X is_not_empty;
4415 then
4416 msm_viewers="${_OPT_VIEWER_X}";
4417 else
4418 msm_viewers="${_VIEWER_X}";
4420 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4421 if is_not_equal "$?" 0;
4422 then
4423 continue;
4425 _DISPLAY_PROG="${msm_viewer}";
4426 _DISPLAY_MODE='x';
4427 eval ${_UNSET} msm_code;
4428 eval ${_UNSET} msm_modes;
4429 eval ${_UNSET} msm_viewer;
4430 eval ${_UNSET} msm_viewers;
4431 eval "${return_ok}";
4434 _DISPLAY_MODE='X';
4435 eval ${_UNSET} msm_code;
4436 eval ${_UNSET} msm_modes;
4437 eval ${_UNSET} msm_viewer;
4438 eval ${_UNSET} msm_viewers;
4439 eval "${return_ok}";
4441 dvi)
4442 if obj _OPT_VIEWER_DVI is_not_empty;
4443 then
4444 msm_viewers="${_OPT_VIEWER_DVI}";
4445 else
4446 msm_viewers="${_VIEWER_DVI}";
4448 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4449 if is_not_equal "$?" 0;
4450 then
4451 continue;
4453 _DISPLAY_PROG="${msm_viewer}";
4454 _DISPLAY_MODE="dvi";
4455 eval ${_UNSET} msm_code;
4456 eval ${_UNSET} msm_modes;
4457 eval ${_UNSET} msm_viewer;
4458 eval ${_UNSET} msm_viewers;
4459 eval "${return_ok}";
4461 pdf)
4462 if obj _OPT_VIEWER_PDF is_not_empty;
4463 then
4464 msm_viewers="${_OPT_VIEWER_PDF}";
4465 else
4466 msm_viewers="${_VIEWER_PDF}";
4468 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4469 if is_not_equal "$?" 0;
4470 then
4471 continue;
4473 _DISPLAY_PROG="${msm_viewer}";
4474 _DISPLAY_MODE="pdf";
4475 eval ${_UNSET} msm_code;
4476 eval ${_UNSET} msm_modes;
4477 eval ${_UNSET} msm_viewer;
4478 eval ${_UNSET} msm_viewers;
4479 eval "${return_ok}";
4482 if obj _OPT_VIEWER_PS is_not_empty;
4483 then
4484 msm_viewers="${_OPT_VIEWER_PS}";
4485 else
4486 msm_viewers="${_VIEWER_PS}";
4488 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4489 if is_not_equal "$?" 0;
4490 then
4491 continue;
4493 _DISPLAY_PROG="${msm_viewer}";
4494 _DISPLAY_MODE="ps";
4495 eval ${_UNSET} msm_code;
4496 eval ${_UNSET} msm_modes;
4497 eval ${_UNSET} msm_viewer;
4498 eval ${_UNSET} msm_viewers;
4499 eval "${return_ok}";
4501 html)
4502 if obj _OPT_VIEWER_HTML is_not_empty;
4503 then
4504 msm_viewers="${_OPT_VIEWER_HTML}";
4505 else
4506 msm_viewers="${_VIEWER_HTML}";
4508 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4509 if is_not_equal "$?" 0;
4510 then
4511 continue;
4513 _DISPLAY_PROG="${msm_viewer}";
4514 _DISPLAY_MODE=html;
4515 eval ${_UNSET} msm_code;
4516 eval ${_UNSET} msm_modes;
4517 eval ${_UNSET} msm_viewer;
4518 eval ${_UNSET} msm_viewers;
4519 eval "${return_ok}";
4521 esac;
4522 done;
4523 eval ${_UNSET} msm_code;
4524 eval ${_UNSET} msm_modes;
4525 eval ${_UNSET} msm_viewer;
4526 eval ${_UNSET} msm_viewers;
4527 error "main_set_mode(): no suitable display mode found.";
4528 } # main_set_mode()
4531 # _get_first_prog (<proglist>)
4533 # Retrieve first argument that represents an existing program in $PATH.
4534 # Local function for main_set_mode().
4536 # Arguments: 1; a comma-separated list of commands (with options),
4537 # like $_VIEWER_*.
4539 # Return : `1' if none found, `0' if found.
4540 # Output : the argument that succeded.
4542 # Variable prefix: _gfp
4544 _get_first_prog()
4546 if is_equal "$#" 0;
4547 then
4548 error "_get_first_prog() needs 1 argument.";
4550 if is_empty "$1";
4551 then
4552 return "${_BAD}";
4554 eval set x "$(list_from_split "$1" ',')";
4555 shift;
4556 for i
4558 _gfp_i="$i";
4559 if obj _gfp_i is_empty;
4560 then
4561 continue;
4563 if eval is_prog "$(get_first_essential ${_gfp_i})";
4564 then
4565 cat <<EOF
4566 ${_gfp_i}
4568 eval ${_UNSET} _gfp_i;
4569 return "${_GOOD}";
4571 done;
4572 eval ${_UNSET} _gfp_i;
4573 return "${_BAD}";
4574 } # _get_first_prog() of main_set_mode()
4577 landmark '17: main_do_fileargs()';
4578 #######################################################################
4579 # main_do_fileargs ()
4581 # Process filespec arguments in $_FILEARGS.
4583 # Globals:
4584 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
4586 # Variable prefix: mdfa
4588 main_do_fileargs()
4590 func_check main_do_fileargs = 0 "$@";
4591 mdfa_exitcode="${_BAD}";
4592 eval set x "${_FILEARGS}";
4593 shift;
4594 eval ${_UNSET} _FILEARGS;
4595 # temporary storage of all input to $_TMP_CAT
4596 while test "$#" -ge 2;
4598 # test for `s name' arguments, with `s' a 1-char standard section
4599 mdfa_filespec="$1";
4600 shift;
4601 case "${mdfa_filespec}" in
4603 continue;
4605 '-')
4606 if register_file '-';
4607 then
4608 mdfa_exitcode="${_GOOD}";
4610 continue;
4613 if list_has_not _MAN_AUTO_SEC "${mdfa_filespec}";
4614 then
4615 if do_filearg "${mdfa_filespec}";
4616 then
4617 mdfa_exitcode="${_GOOD}";
4619 continue;
4621 mdfa_name="$1";
4622 case "${mdfa_name}" in
4623 */*|man:*|*\(*\)|*."${mdfa_filespec}")
4624 if do_filearg "${mdfa_filespec}";
4625 then
4626 mdfa_exitcode="${_GOOD}";
4628 continue;
4630 esac;
4631 if do_filearg "man:${mdfa_name}(${mdfa_filespec})";
4632 then
4633 mdfa_exitcode="${_GOOD}";
4634 shift;
4635 continue;
4636 else
4637 if do_filearg "${mdfa_filespec}";
4638 then
4639 mdfa_exitcode="${_GOOD}";
4641 continue;
4645 if do_filearg "${mdfa_filespec}";
4646 then
4647 mdfa_exitcode="${_GOOD}";
4649 continue;
4651 esac;
4652 done; # end of `s name' test
4653 while test "$#" -gt 0;
4655 mdfa_filespec="$1";
4656 shift;
4657 if do_filearg "${mdfa_filespec}";
4658 then
4659 mdfa_exitcode="${_GOOD}";
4661 done;
4662 if obj _DEBUG_KEEP_FILES is_not_yes;
4663 then
4664 rm -f "${_TMP_STDIN}";
4666 if is_equal "${mdfa_exitcode}" "${_BAD}";
4667 then
4668 eval ${_UNSET} mdfa_exitcode;
4669 eval ${_UNSET} mdfa_filespec;
4670 eval ${_UNSET} mdfa_name;
4671 eval "${return_bad}";
4673 eval ${_UNSET} mdfa_exitcode;
4674 eval ${_UNSET} mdfa_filespec;
4675 eval ${_UNSET} mdfa_name;
4676 eval "${return_ok}";
4677 } # main_do_fileargs()
4680 landmark '18: main_set_resources()';
4681 ########################################################################
4682 # main_set_resources ()
4684 # Determine options for setting X resources with $_DISPLAY_PROG.
4686 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4688 # Variable prefix: msr
4690 main_set_resources()
4692 func_check main_set_resources = 0 "$@";
4693 # $msr_prog viewer program
4694 # $msr_rl resource list
4695 msr_title="$(get_first_essential \
4696 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4697 _OUTPUT_FILE_NAME='';
4698 eval set x "${msr_title}";
4699 shift;
4700 until is_equal "$#" 0;
4702 msr_n="$1";
4703 case "${msr_n}" in
4705 continue;
4708 msr_n="$(echo x"$1" | sed -e 's/^x,,*//')";
4710 esac
4711 if obj msr_n is_empty;
4712 then
4713 continue;
4715 if obj _OUTPUT_FILE_NAME is_not_empty;
4716 then
4717 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
4719 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
4720 shift;
4721 done;
4722 case "${_OUTPUT_FILE_NAME}" in
4724 _OUTPUT_FILE_NAME='-';
4727 error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
4729 esac;
4730 _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4732 if obj _DISPLAY_PROG is_empty;
4733 then # for example, for groff mode
4734 _DISPLAY_ARGS='';
4735 eval ${_UNSET} msr_n;
4736 eval ${_UNSET} msr_prog;
4737 eval ${_UNSET} msr_rl;
4738 eval ${_UNSET} msr_title;
4739 eval "${return_ok}";
4742 eval set x "${_DISPLAY_PROG}";
4743 shift;
4744 msr_prog="$(base_name "$1")";
4745 msr_rl='';
4746 if obj _OPT_BD is_not_empty;
4747 then
4748 case "${msr_prog}" in
4749 ghostview|gv|gxditview|xditview|xdvi)
4750 list_append msr_rl '-bd' "${_OPT_BD}";
4752 esac;
4754 if obj _OPT_BG is_not_empty;
4755 then
4756 case "${msr_prog}" in
4757 ghostview|gv|gxditview|xditview|xdvi)
4758 list_append msr_rl '-bg' "${_OPT_BG}";
4760 xpdf)
4761 list_append msr_rl '-papercolor' "${_OPT_BG}";
4763 esac;
4765 if obj _OPT_BW is_not_empty;
4766 then
4767 case "${msr_prog}" in
4768 ghostview|gv|gxditview|xditview|xdvi)
4769 _list_append msr_rl '-bw' "${_OPT_BW}";
4771 esac;
4773 if obj _OPT_FG is_not_empty;
4774 then
4775 case "${msr_prog}" in
4776 ghostview|gv|gxditview|xditview|xdvi)
4777 list_append msr_rl '-fg' "${_OPT_FG}";
4779 esac;
4781 if is_not_empty "${_OPT_FN}";
4782 then
4783 case "${msr_prog}" in
4784 ghostview|gv|gxditview|xditview|xdvi)
4785 list_append msr_rl '-fn' "${_OPT_FN}";
4787 esac;
4789 if is_not_empty "${_OPT_GEOMETRY}";
4790 then
4791 case "${msr_prog}" in
4792 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4793 list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
4795 esac;
4797 if is_empty "${_OPT_RESOLUTION}";
4798 then
4799 _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
4800 case "${msr_prog}" in
4801 gxditview|xditview)
4802 list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
4804 xpdf)
4805 case "${_DEFAULT_RESOLUTION}" in
4807 # 72dpi is '100'
4808 list_append msr_rl '-z' '104';
4810 100)
4811 list_append msr_rl '-z' '139';
4813 esac;
4815 esac;
4816 else
4817 case "${msr_prog}" in
4818 ghostview|gv|gxditview|xditview|xdvi)
4819 list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
4821 xpdf)
4822 case "${_OPT_RESOLUTION}" in
4824 list_append msr_rl '-z' '104';
4825 # '100' corresponds to 72dpi
4827 100)
4828 list_append msr_rl '-z' '139';
4830 esac;
4832 esac;
4834 if is_yes "${_OPT_ICONIC}";
4835 then
4836 case "${msr_prog}" in
4837 ghostview|gv|gxditview|xditview|xdvi)
4838 list_append msr_rl '-iconic';
4840 esac;
4842 if is_yes "${_OPT_RV}";
4843 then
4844 case "${msr_prog}" in
4845 ghostview|gv|gxditview|xditview|xdvi)
4846 list_append msr_rl '-rv';
4848 esac;
4850 if is_not_empty "${_OPT_XRM}";
4851 then
4852 case "${msr_prog}" in
4853 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4854 eval set x "${_OPT_XRM}";
4855 shift;
4856 for i
4858 list_append msr_rl '-xrm' "$i";
4859 done;
4861 esac;
4863 if is_not_empty "${msr_title}";
4864 then
4865 case "${msr_prog}" in
4866 gxditview|xditview)
4867 list_append msr_rl '-title' "${msr_title}";
4869 esac;
4871 _DISPLAY_ARGS="${msr_rl}";
4872 eval ${_UNSET} msr_n;
4873 eval ${_UNSET} msr_prog;
4874 eval ${_UNSET} msr_rl;
4875 eval ${_UNSET} msr_title;
4876 eval "${return_ok}";
4877 } # main_set_resources
4880 landmark '19: main_display()';
4881 ########################################################################
4882 # main_display ()
4884 # Do the actual display of the whole thing.
4886 # Globals:
4887 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4888 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4889 # $_REGISTERED_TITLE, $_TMP_CAT,
4890 # $_OPT_PAGER $PAGER, $_MANOPT_PAGER,
4891 # $_OUTPUT_FILE_NAME
4893 # Variable prefix: md
4895 main_display()
4897 func_check main_display = 0 "$@";
4899 export md_addopts;
4900 export md_groggy;
4901 export md_modefile;
4903 if obj _TMP_CAT is_non_empty_file;
4904 then
4905 md_modefile="${_OUTPUT_FILE_NAME}";
4906 else
4907 clean_up;
4908 echo2 'groffer: empty input.';
4909 eval ${_UNSET} md_modefile;
4910 eval "${return_ok}";
4912 case "${_DISPLAY_MODE}" in
4913 groff)
4914 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4915 if obj _OPT_DEVICE is_not_empty;
4916 then
4917 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4919 md_groggy="$(tmp_cat | eval grog "${md_options}")";
4920 trap_clean;
4921 if obj _OPT_V is_yes;
4922 then
4923 echo "File: ${md_modefile}";
4924 echo "Mode: ${_DISPLAY_MODE}";
4925 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4926 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4927 clean_up;
4928 else
4929 # start a new shell program to get another process ID.
4930 /bin/sh -c '
4931 set -e;
4932 test -f "${md_modefile}" && rm -f "${md_modefile}";
4933 mv "${_TMP_CAT}" "${md_modefile}";
4934 cat "${md_modefile}" | \
4936 clean_up()
4938 if test -d "${_TMP_DIR}";
4939 then
4940 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
4943 trap clean_up 0 2>${_NULL_DEV} || :;
4944 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4945 ) &'
4948 text|tty)
4949 case "${_OPT_DEVICE}" in
4951 md_device="$(get_first_essential \
4952 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4954 ascii|cp1047|latin1|utf8)
4955 md_device="${_OPT_DEVICE}";
4958 warning "main_display(): \
4959 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4961 esac;
4962 md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4963 md_groggy="$(tmp_cat | grog -T${md_device})";
4964 if obj _DISPLAY_MODE is_equal 'text';
4965 then
4966 if obj _OPT_V is_yes;
4967 then
4968 echo "File: ${md_modefile}";
4969 echo "Mode: ${_DISPLAY_MODE}";
4970 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4971 eval "${md_groggy}" "${md_addopts}";
4972 else
4973 tmp_cat | eval "${md_groggy}" "${md_addopts}";
4975 else
4976 md_pager='';
4977 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4978 'less -r -R' 'more' 'pager' 'cat'
4980 md_p="$p";
4981 if eval is_prog ${md_p};
4982 then # no "" for is_prog() allows args for $p
4983 md_pager="${md_p}";
4984 break;
4986 done;
4987 if obj md_pager is_empty;
4988 then
4989 error 'main_display(): no pager program found for tty mode';
4991 if obj _OPT_V is_yes;
4992 then
4993 echo "File: ${md_modefile}";
4994 echo "Mode: ${_DISPLAY_MODE}";
4995 echo "Display program: ${md_pager}";
4996 eval "${md_groggy}" "${md_addopts}";
4997 else
4998 tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
4999 eval "${md_pager}";
5002 clean_up;
5004 source)
5005 tmp_cat;
5006 clean_up;
5009 #### viewer modes
5011 dvi)
5012 case "${_OPT_DEVICE}" in
5013 ''|dvi) do_nothing; ;;
5015 warning "main_display(): \
5016 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
5018 esac;
5019 md_modefile="${md_modefile}".dvi;
5020 md_groggy="$(tmp_cat | grog -Tdvi)";
5021 _do_display;
5023 html)
5024 case "${_OPT_DEVICE}" in
5025 ''|html) do_nothing; ;;
5027 warning "main_display(): \
5028 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5030 esac;
5031 md_modefile="${md_modefile}".html;
5032 md_groggy="$(tmp_cat | grog -Thtml)";
5033 _do_display;
5035 pdf)
5036 case "${_OPT_DEVICE}" in
5037 ''|ps)
5038 do_nothing;
5041 warning "main_display(): \
5042 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5044 esac;
5045 md_groggy="$(tmp_cat | grog -Tps)";
5046 trap_clean;
5047 if obj _OPT_V is_yes;
5048 then
5049 echo "File: ${md_modefile}.pdf";
5050 echo "Mode: ${_DISPLAY_MODE}";
5051 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
5052 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
5053 clean_up;
5054 else
5055 # start a new shell program to get another process ID.
5056 /bin/sh -c '
5057 set -e;
5058 _psfile="${md_modefile}.ps";
5059 md_modefile="${md_modefile}.pdf";
5060 test -f "${_psfile}" && rm -f "${_psfile}";
5061 test -f "${md_modefile}" && rm -f "${md_modefile}";
5062 cat "${_TMP_CAT}" | \
5063 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
5064 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
5065 -sOutputFile="${md_modefile}" -c save pop -f "${_psfile}";
5066 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
5067 then
5068 test -f "${_psfile}" && rm -f "${_psfile}";
5069 test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";
5072 clean_up() {
5073 if test -d "${_TMP_DIR}";
5074 then
5075 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
5078 trap clean_up 0 2>${_NULL_DEV} || :;
5079 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
5080 ) &'
5084 case "${_OPT_DEVICE}" in
5085 ''|ps)
5086 do_nothing;
5089 warning "main_display(): \
5090 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5092 esac;
5093 md_modefile="${md_modefile}".ps;
5094 md_groggy="$(tmp_cat | grog -Tps)";
5095 _do_display;
5098 case "${_OPT_DEVICE}" in
5100 md_device="${_OPT_DEVICE}"
5103 case "${_OPT_RESOLUTION}" in
5104 100)
5105 md_device='X100';
5106 if obj _OPT_GEOMETRY is_empty
5107 then
5108 case "${_DISPLAY_PROG}" in
5109 gxditview|xditview)
5110 # add width of 800dpi for resolution of 100dpi to the args
5111 list_append _DISPLAY_ARGS '-geometry' '800';
5113 esac;
5117 md_device='X75-12';
5119 esac
5120 esac;
5121 md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
5122 _do_display;
5125 case "${_OPT_DEVICE}" in
5127 md_groggy="$(tmp_cat | grog -X)";
5129 X*|dvi|html|lbp|lj4|ps)
5130 # these devices work with
5131 md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
5134 warning "main_display(): \
5135 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5136 md_groggy="$(tmp_cat | grog -Z)";
5138 esac;
5139 _do_display;
5142 error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
5144 esac;
5145 eval ${_UNSET} md_addopts;
5146 eval ${_UNSET} md_device;
5147 eval ${_UNSET} md_groggy;
5148 eval ${_UNSET} md_modefile;
5149 eval ${_UNSET} md_options;
5150 eval ${_UNSET} md_p;
5151 eval ${_UNSET} md_pager;
5152 eval "${return_ok}";
5153 } # main_display()
5156 # $md_modefile and $md_groggy come from main_display()
5157 _do_display()
5159 func_check _do_display = 0 "$@";
5160 trap_clean;
5161 if obj _OPT_V is_yes;
5162 then
5163 echo "File: ${md_modefile}";
5164 echo "Mode: ${_DISPLAY_MODE}";
5165 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
5166 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
5167 clean_up;
5168 else
5169 # start a new shell program for another process ID and better
5170 # cleaning-up of the temporary files.
5171 /bin/sh -c '
5172 set -e;
5173 test -f "${md_modefile}" && rm -f "${md_modefile}";
5174 cat "${_TMP_CAT}" | \
5175 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
5176 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
5177 then
5178 rm -f "${_TMP_CAT}";
5181 clean_up() {
5182 if test -d "${_TMP_DIR}";
5183 then
5184 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
5187 trap clean_up 0 2>${_NULL_DEV} || :;
5188 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
5189 ) &'
5191 eval "${return_ok}";
5192 } # _do_display() of main_display()
5195 ########################################################################
5196 # main (<command_line_args>*)
5198 # The main function for groffer.
5200 # Arguments:
5202 main()
5204 func_check main '>=' 0 "$@";
5205 # Do not change the sequence of the following functions!
5206 main_init;
5207 main_parse_MANOPT;
5208 main_parse_args "$@";
5209 main_set_mode;
5210 main_do_fileargs;
5211 main_set_resources;
5212 main_display;
5213 eval "${return_ok}";
5216 landmark '20: end of function definitions';
5218 ########################################################################
5220 main "$@";