* release of groffer 0.9.20
[s-roff.git] / contrib / groffer / groffer2.sh
blobd2253841d094ae4954fd7c7b386c57e400381ca7
1 #! /bin/sh
3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer2.sh
6 # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
8 # Copyright (C) 2001,2002,2003,2004,2005
9 # Free Software Foundation, Inc.
10 # Written by Bernd Warken
12 # Last update: 30 July 2005
14 # This file is part of groffer, which is part of groff.
16 # groff is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2, or (at your option)
19 # any later version.
21 # groff is distributed in the hope that it will be useful, but WITHOUT
22 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 # License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with groff; see the files COPYING and LICENSE in the top
28 # directory of the groff source. If not, write to the Free Software
29 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
32 ########################################################################
33 # diagnostic messages
35 export _DEBUG;
36 _DEBUG='no'; # disable debugging information
37 #_DEBUG='yes'; # enable debugging information
39 export _DEBUG_LM;
40 _DEBUG_LM='no'; # disable landmark messages
41 #_DEBUG_LM='yes'; # enable landmark messages
43 export _DEBUG_KEEP_FILES;
44 _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
45 _DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
47 # test of $* on --debug
48 case " $* " in
49 *' --debug '*)
50 _DEBUG='yes';
51 _DEBUG_LM='yes';
52 _DEBUG_KEEP_FILES='yes';
54 esac;
57 ########################################################################
58 # Environment Variables
59 ########################################################################
61 # Environment variables that exist only for this file start with an
62 # underscore letter. Global variables to this file are written in
63 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
64 # start with an underline and use only lower case letters and
65 # underlines, e.g. $_local_variable .
67 # [A-Z]* system variables, e.g. $MANPATH
68 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
69 # _[a-z_]* temporary variables, e.g. $_manpath
71 # Due to incompatibilities of the `ash' shell, the name of loop
72 # variables in `for' must be single character
73 # [a-z] local loop variables, e.g. $i
76 ########################################################################
77 # read-only variables (global to this file)
78 ########################################################################
80 # characters
82 export _SPACE;
83 export _SQUOTE;
84 export _TAB;
86 _SPACE=' ';
87 _SQUOTE="'";
88 _TAB=' ';
90 # function return values; `0' means ok; other values are error codes
91 export _ALL_EXIT;
92 export _BAD;
93 export _ERROR;
94 export _GOOD;
95 export _NO;
96 export _OK;
97 export _YES;
99 _GOOD='0'; # return ok
100 _BAD='1'; # return negatively, error code `1'
101 _ERROR='7'; # for syntax errors; no `-1' in `ash'
103 _ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
105 _NO="${_BAD}";
106 _YES="${_GOOD}";
107 _OK="${_GOOD}";
109 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
110 export return_ok;
111 export return_good;
112 export return_bad;
113 export return_yes;
114 export return_no;
115 export return_error;
116 export return_var;
117 return_ok="func_pop; return ${_OK}";
118 return_good="func_pop; return ${_GOOD}";
119 return_bad="func_pop; return ${_BAD}";
120 return_yes="func_pop; return ${_YES}";
121 return_no="func_pop; return ${_NO}";
122 return_error="func_pop; return ${_ERROR}";
123 return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
126 export _DEFAULT_MODES;
127 _DEFAULT_MODES='x,ps,tty';
128 export _DEFAULT_RESOLUTION;
129 _DEFAULT_RESOLUTION='75';
131 export _DEFAULT_TTY_DEVICE;
132 _DEFAULT_TTY_DEVICE='latin1';
134 # _VIEWER_* viewer programs for different modes (only X is necessary)
135 # _VIEWER_* a comma-separated list of viewer programs (with options)
136 export _VIEWER_DVI; # viewer program for dvi mode
137 export _VIEWER_PS; # viewer program for ps mode
138 export _VIEWER_HTML_X; # viewer program for html mode in X
139 export _VIEWER_HTML_TTY; # viewer program for html mode in tty
140 _VIEWER_DVI='kdvi,xdvi,dvilx';
141 _VIEWER_PDF='kghostview,ggv,xpdf,acroread,kpdf';
142 _VIEWER_PS='kghostview,ggv,gv,ghostview,gs_x11,gs';
143 _VIEWER_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
144 _VIEWER_X='gxditview,xditview';
146 # Search automatically in standard sections `1' to `8', and in the
147 # traditional sections `9', `n', and `o'. On many systems, there
148 # exist even more sections, mostly containing a set of man pages
149 # special to a specific program package. These aren't searched for
150 # automatically, but must be specified on the command line.
151 export _MAN_AUTO_SEC;
152 _MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
154 export _PROCESS_ID; # for shutting down the program
155 _PROCESS_ID="$$";
158 ############ the command line options of the involved programs
160 # The naming scheme for the options environment names is
161 # $_OPTS_<prog>_<length>[_<argspec>]
163 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
164 # command line options)
165 # <length>: LONG (long options) or SHORT (single character options)
166 # <argspec>: ARG for options with argument, NA for no argument;
167 # without _<argspec> both the ones with and without arg.
169 # Each option that takes an argument must be specified with a
170 # trailing : (colon).
172 # exports
173 export _OPTS_GROFFER_SHORT_NA;
174 export _OPTS_GROFFER_SHORT_ARG;
175 export _OPTS_GROFFER_LONG_NA;
176 export _OPTS_GROFFER_LONG_ARG;
177 export _OPTS_GROFF_SHORT_NA;
178 export _OPTS_GROFF_SHORT_ARG;
179 export _OPTS_GROFF_LONG_NA;
180 export _OPTS_GROFF_LONG_ARG;
181 export _OPTS_X_SHORT_ARG;
182 export _OPTS_X_SHORT_NA;
183 export _OPTS_X_LONG_ARG;
184 export _OPTS_X_LONG_NA;
185 export _OPTS_MAN_SHORT_ARG;
186 export _OPTS_MAN_SHORT_NA;
187 export _OPTS_MAN_LONG_ARG;
188 export _OPTS_MAN_LONG_NA;
189 export _OPTS_MANOPT_SHORT_ARG;
190 export _OPTS_MANOPT_SHORT_NA;
191 export _OPTS_MANOPT_LONG_ARG;
192 export _OPTS_MANOPT_LONG_NA;
193 export _OPTS_CMDLINE_SHORT_NA;
194 export _OPTS_CMDLINE_SHORT_ARG;
195 export _OPTS_CMDLINE_LONG_NA;
196 export _OPTS_CMDLINE_LONG_ARG;
198 ###### groffer native options
200 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
201 _OPTS_GROFFER_SHORT_ARG="'T'";
203 _OPTS_GROFFER_LONG_NA="'auto' 'debug' 'default' 'dvi' \
204 'groff' 'help' 'intermediate-output' 'html' 'man' \
205 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
206 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
208 _OPTS_GROFFER_LONG_ARG="\
209 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
210 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
211 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
212 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
214 ##### groffer options inhereted from groff
216 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
217 'R' 's' 'S' 't' 'U' 'z'";
218 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
219 'w' 'W'";
220 _OPTS_GROFF_LONG_NA="";
221 _OPTS_GROFF_LONG_ARG="";
223 ##### groffer options inhereted from the X Window toolkit
225 _OPTS_X_SHORT_NA="";
226 _OPTS_X_SHORT_ARG="";
228 _OPTS_X_LONG_NA="'iconic' 'rv'";
230 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
231 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'
232 'resolution' 'title' 'xrm'";
234 ###### groffer options inherited from man
236 _OPTS_MAN_SHORT_NA="";
237 _OPTS_MAN_SHORT_ARG="";
239 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \
240 'local-file' 'location' 'pager' 'troff' 'update' 'version' \
241 'whatis' 'where'";
243 _OPTS_MAN_LONG_ARG="'extension' 'locale' 'manpath' \
244 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
246 ###### additional options for parsing $MANOPT only
248 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
249 'V' 'w' 'Z'";
250 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
252 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
253 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
254 'match-case' 'troff' 'update' 'version' 'where-cat'";
256 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
257 'config_file' 'encoding' 'locale'";
259 ###### collections of command line options
261 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA}\
262 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
263 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
264 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
266 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
267 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
268 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
269 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
272 ########################################################################
273 # read-write variables (global to this file)
274 ########################################################################
276 export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
277 export _ADDOPTS_POST; # Transp. options postproc (`eval').
278 export _ADDOPTS_X; # Transp. options X postproc (`eval').
279 export _DEFAULT_MODES; # Set default modes.
280 export _DISPLAY_MODE; # Display mode.
281 export _DISPLAY_PROG; # Viewer program to be used for display.
282 export _DISPLAY_ARGS; # X resources for the viewer program.
283 export _FILEARGS; # Stores filespec parameters.
284 export _FUNC_STACK; # Store debugging information.
285 export _REGISTERED_TITLE; # Processed file names.
286 # _HAS_* from availability tests
287 export _HAS_COMPRESSION; # `yes' if gzip compression is available
288 export _HAS_BZIP; # `yes' if bzip2 compression is available
289 # _MAN_* finally used configuration of man searching
290 export _MAN_ALL; # search all man pages per filespec
291 export _MAN_ENABLE; # enable search for man pages
292 export _MAN_EXT; # extension for man pages
293 export _MAN_FORCE; # force file parameter to be man pages
294 export _MAN_IS_SETUP; # setup man variables only once
295 export _MAN_LANG; # language for man pages
296 export _MAN_LANG2; # language for man pages
297 export _MAN_LANG_DONE; # language dirs added to man path
298 export _MAN_PATH; # search path for man pages
299 export _MAN_SEC; # sections for man pages; sep. `:'
300 export _MAN_SEC_DONE; # sections added to man path
301 export _MAN_SYS; # system names for man pages; sep. `,'
302 export _MAN_SYS; # system names added to man path
303 # _MANOPT_* as parsed from $MANOPT
304 export _MANOPT_ALL; # $MANOPT --all
305 export _MANOPT_EXTENSION; # $MANOPT --extension
306 export _MANOPT_LANG; # $MANOPT --locale
307 export _MANOPT_PATH; # $MANOPT --manpath
308 export _MANOPT_PAGER; # $MANOPT --pager
309 export _MANOPT_SEC; # $MANOPT --sections
310 export _MANOPT_SYS; # $MANOPT --systems
311 # _OPT_* as parsed from groffer command line
312 export _OPT_ALL; # display all suitable man pages.
313 export _OPT_APROPOS; # call `apropos' program.
314 export _OPT_APROPOS_DATA; # `apropos' for man sections 4, 5, 7
315 export _OPT_APROPOS_DEVEL; # `apropos' for man sections 2, 3, 9
316 export _OPT_APROPOS_PROGS; # `apropos' for man sections 1, 6, 8
317 export _OPT_BD; # set border color in some modes.
318 export _OPT_BG; # set background color in some modes.
319 export _OPT_BW; # set border width in some modes.
320 export _OPT_DEBUG; # print debugging information on stderr.
321 export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
322 export _OPT_DEVICE; # device option.
323 export _OPT_DISPLAY; # set X display.
324 export _OPT_FG; # set foreground color in some modes.
325 export _OPT_FN; # set font in some modes.
326 export _OPT_GEOMETRY; # set size and position of viewer in X.
327 export _OPT_ICONIC; # -iconic option for X viewers.
328 export _OPT_LANG; # set language for man pages
329 export _OPT_LOCATION; # print processed file names to stderr
330 export _OPT_MODE; # values: X, tty, Q, Z, ""
331 export _OPT_MANPATH; # manual setting of path for man-pages
332 export _OPT_PAGER; # specify paging program for tty mode
333 export _OPT_RESOLUTION; # set X resolution in dpi
334 export _OPT_RV; # reverse fore- and background colors.
335 export _OPT_SECTIONS; # sections for man page search
336 export _OPT_SYSTEMS; # man pages of different OS's
337 export _OPT_TITLE; # title for gxditview window
338 export _OPT_TEXT_DEVICE; # set device for tty mode.
339 export _OPT_V; # groff option -V.
340 export _OPT_VIEWER_DVI; # viewer program for dvi mode
341 export _OPT_VIEWER_PDF; # viewer program for pdf mode
342 export _OPT_VIEWER_PS; # viewer program for ps mode
343 export _OPT_VIEWER_HTML; # viewer program for html mode
344 export _OPT_VIEWER_X; # viewer program for x mode
345 export _OPT_WHATIS; # print the one-liner man info
346 export _OPT_XRM; # specify X resource.
347 export _OPT_Z; # groff option -Z.
348 # _TMP_* temporary files
349 export _TMP_DIR; # groffer directory for temporary files
350 export _TMP_CAT; # stores concatenation of everything
351 export _TMP_STDIN; # stores stdin, if any
353 # these variables are preset in section `Preset' after the rudim. test
356 ########################################################################
357 # Test of rudimentary shell functionality
358 ########################################################################
361 ########################################################################
362 # Test of `test'.
364 test "a" = "a" || exit 1;
367 ########################################################################
368 # Test of `echo' and the `$()' construct.
370 echo '' >${_NULL_DEV} || exit "${_ERROR}";
371 if test _"$(t1="$(echo te)" &&
372 t2="$(echo '')" &&
373 t3="$(echo 'st')" &&
374 echo "${t1}${t2}${t3}")"_ \
375 != _test_;
376 then
377 exit "${_ERROR}";
381 ########################################################################
382 # Test of function definitions.
384 _t_e_s_t_f_u_n_c_()
386 return "${_OK}";
389 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV};
390 then
392 else
393 echo 'shell does not support function definitions.' >&2;
394 exit "${_ERROR}";
398 ########################################################################
399 # Preset and reset of read-write global variables
400 ########################################################################
403 # For variables that can be reset by option `--default', see reset().
405 _FILEARGS='';
407 # _HAS_* from availability tests
408 _HAS_COMPRESSION='';
409 _HAS_BZIP='';
411 # _TMP_* temporary files
412 _TMP_DIR='';
413 _TMP_CAT='';
414 _TMP_STDIN='';
417 ########################################################################
418 # reset ()
420 # Reset the variables that can be affected by options to their default.
422 reset()
424 if test "$#" -ne 0;
425 then
426 error "reset() does not have arguments.";
429 _ADDOPTS_GROFF='';
430 _ADDOPTS_POST='';
431 _ADDOPTS_X='';
432 _DISPLAY_ARGS='';
433 _DISPLAY_MODE='';
434 _DISPLAY_PROG='';
435 _REGISTERED_TITLE='';
437 # _MAN_* finally used configuration of man searching
438 _MAN_ALL='no';
439 _MAN_ENABLE='yes'; # do search for man-pages
440 _MAN_EXT='';
441 _MAN_FORCE='no'; # first local file, then search man page
442 _MAN_IS_SETUP='no';
443 _MAN_LANG='';
444 _MAN_LANG2='';
445 _MAN_PATH='';
446 _MAN_SEC='';
447 _MAN_SEC_DONE='no';
448 _MAN_SYS='';
449 _MAN_SYS_DONE='no';
451 # _MANOPT_* as parsed from $MANOPT
452 _MANOPT_ALL='no';
453 _MANOPT_EXTENSION='';
454 _MANOPT_LANG='';
455 _MANOPT_PATH='';
456 _MANOPT_PAGER='';
457 _MANOPT_SEC='';
458 _MANOPT_SYS='';
460 # _OPT_* as parsed from groffer command line
461 _OPT_ALL='no';
462 _OPT_APROPOS='';
463 _OPT_APROPOS_DATA='';
464 _OPT_APROPOS_DEVEL='';
465 _OPT_APROPOS_PROGS='';
466 _OPT_BD='';
467 _OPT_BG='';
468 _OPT_BW='';
469 _OPT_DEBUG='no';
470 _OPT_DEFAULT_MODES='';
471 _OPT_DEVICE='';
472 _OPT_DISPLAY='';
473 _OPT_FG='';
474 _OPT_FN='';
475 _OPT_GEOMETRY='';
476 _OPT_ICONIC='no';
477 _OPT_LANG='';
478 _OPT_LOCATION='no';
479 _OPT_MODE='';
480 _OPT_MANPATH='';
481 _OPT_PAGER='';
482 _OPT_RESOLUTION='';
483 _OPT_RV='no';
484 _OPT_SECTIONS='';
485 _OPT_SYSTEMS='';
486 _OPT_TITLE='';
487 _OPT_TEXT_DEVICE='';
488 _OPT_V='no';
489 _OPT_VIEWER_DVI='';
490 _OPT_VIEWER_PDF='';
491 _OPT_VIEWER_PS='';
492 _OPT_VIEWER_HTML='';
493 _OPT_VIEWER_X='';
494 _OPT_WHATIS='no';
495 _OPT_XRM='';
496 _OPT_Z='no';
500 reset;
503 ########################################################################
504 # Functions for error handling and debugging
505 ########################################################################
508 ##############
509 # echo2 (<text>*)
511 # Output to stderr.
513 # Arguments : arbitrary text.
515 echo2()
517 cat >&2 <<EOF
523 ##############
524 # landmark (<text>)
526 # Print <text> to standard error as a debugging aid.
528 # Globals: $_DEBUG_LM
530 landmark()
532 if test _"${_DEBUG_LM}"_ = _yes_;
533 then
534 echo2 "LM: $*" >&2;
538 landmark "1: debugging functions";
541 ##############
542 # clean_up ()
544 # Clean up at exit.
546 clean_up()
548 if test -d "${_TMP_DIR}";
549 then
550 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
555 #############
556 # diag (text>*)
558 # Output a diagnostic message to stderr
560 diag()
562 echo2 '>>>>>'"$*";
566 #############
567 # error (<text>*)
569 # Print an error message to standard error; exit with an error condition
571 # Variable prefix: err
573 error()
575 err_code="${_ERROR}";
576 case "$#" in
577 0) :; ;;
578 1) echo2 'groffer error: '"$1"; ;;
580 echo2 'groffer error: '"$1";
581 err_code="$2";
583 *) echo2 'groffer error: wrong number of arguments in error().'; ;;
584 esac;
585 func_stack_dump;
586 clean_up;
587 kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
588 kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
589 n="${err_code}";
590 eval ${_UNSET} err_code;
591 exit "$n";
595 #############
596 # abort (<text>*)
598 # Terminate program with error condition
600 abort()
602 error "abort(): Program aborted.";
603 exit 1;
607 #############
608 # func_check (<func_name> <rel_op> <nr_args> "$@")
610 # Check number of arguments and register to _FUNC_STACK.
612 # Arguments: >=3
613 # <func_name>: name of the calling function.
614 # <rel_op>: a relational operator: = != < > <= >=
615 # <nr_args>: number of arguments to be checked against <operator>
616 # "$@": the arguments of the calling function.
618 # Variable prefix: fc
620 func_check()
622 if test "$#" -lt 3;
623 then
624 error 'func_check() needs at least 3 arguments.';
626 fc_fname="$1";
627 case "$3" in
629 fc_nargs="$3";
630 fc_s='';
632 0|[2-9])
633 fc_nargs="$3";
634 fc_s='s';
637 error "func_check(): third argument must be a digit.";
639 esac;
640 case "$2" in
641 '='|'-eq')
642 fc_op='-eq';
643 fc_comp='exactly';
645 '>='|'-ge')
646 fc_op='-ge';
647 fc_comp='at least';
649 '<='|'-le')
650 fc_op='-le';
651 fc_comp='at most';
653 '<'|'-lt')
654 fc_op='-lt';
655 fc_comp='less than';
657 '>'|'-gt')
658 fc_op='-gt';
659 fc_comp='more than';
661 '!='|'-ne')
662 fc_op='-ne';
663 fc_comp='not';
666 error \
667 'func_check(): second argument is not a relational operator.';
669 esac;
670 shift;
671 shift;
672 shift;
673 if test "$#" "${fc_op}" "${fc_nargs}";
674 then
675 do_nothing;
676 else
677 error "func_check(): \
678 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
680 func_push "${fc_fname}";
681 if test _"${_DEBUG}"_ = _yes_;
682 then
683 echo2 '+++ '"${fc_fname} $@";
684 echo2 '>>> '"${_FUNC_STACK}";
686 eval ${_UNSET} fc_comp;
687 eval ${_UNSET} fc_fname;
688 eval ${_UNSET} fc_nargs;
689 eval ${_UNSET} fc_op;
690 eval ${_UNSET} fc_s;
694 #############
695 # func_pop ()
697 # Retrieve the top element from the stack.
699 # The stack elements are separated by `!'; the popped element is
700 # identical to the original element, except that all `!' characters
701 # were removed.
703 # Arguments: 1
705 func_pop()
707 if test "$#" -ne 0;
708 then
709 error 'func_pop() does not have arguments.';
711 case "${_FUNC_STACK}" in
713 if test _"${_DEBUG}"_ = _yes_;
714 then
715 error 'func_pop(): stack is empty.';
718 *!*)
719 # split at first bang `!'.
720 _FUNC_STACK="$(echo x"${_FUNC_STACK}" | sed -e '
721 s/^x//
722 s/^[^!]*!//
723 ')";
726 _FUNC_STACK='';
728 esac;
729 if test _"${_DEBUG}"_ = _yes_;
730 then
731 echo2 '<<< '"${_FUNC_STACK}";
736 #############
737 # func_push (<element>)
739 # Store another element to stack.
741 # The stack elements are separated by `!'; if <element> contains a `!'
742 # it is removed first.
744 # Arguments: 1
746 # Variable prefix: fp
748 func_push()
750 if test "$#" -ne 1;
751 then
752 error 'func_push() needs 1 argument.';
754 case "$1" in
755 *'!'*)
756 # remove all bangs `!'.
757 fp_element="$(echo x"$1" | sed -e '
758 s/^x//
759 s/!//g
760 ')";
763 fp_element="$1";
765 esac;
766 if test _"${_FUNC_STACK}"_ = __;
767 then
768 _FUNC_STACK="${fp_element}";
769 else
770 _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
772 eval ${_UNSET} fp_element;
776 #############
777 # func_stack_dump ()
779 # Print the content of the stack. Ignore the arguments.
781 func_stack_dump()
783 diag 'call stack: '"${_FUNC_STACK}";
787 ########################################################################
788 # System Test
789 ########################################################################
791 landmark "2: system test";
793 # Test the availability of the system utilities used in this script.
796 ########################################################################
797 # Test of function `sed'.
800 if test _"$(echo xTesTx \
801 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
802 | sed -e 's|T|t|g')"_ != _test_;
803 then
804 error 'Test of "sed" command failed.';
808 ########################################################################
809 # Test of function `cat'.
811 if test _"$(echo test | cat)"_ != _test_;
812 then
813 error 'Test of "cat" command failed.';
817 ########################################################################
818 # Test for compression.
820 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_;
821 then
822 _HAS_COMPRESSION='yes';
823 if echo 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
824 && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
825 | bzip2 -d -c 2>${_NULL_DEV})"_ \
826 = _test_;
827 then
828 _HAS_BZIP='yes';
829 else
830 _HAS_BZIP='no';
832 else
833 _HAS_COMPRESSION='no';
834 _HAS_BZIP='no';
838 ########################################################################
839 # Definition of normal Functions in alphabetical order
840 ########################################################################
841 landmark "3: functions";
843 ########################################################################
844 # abort (<text>*)
846 # Unconditionally terminate the program with error code;
847 # useful for debugging.
849 # defined above
852 ########################################################################
853 # apropos_run (<name>)
856 apropos_run() {
857 func_check apropos_run = 1 "$@";
858 if apropos apropos >${_NULL_DEV} 2>${_NULL_DEV};
859 then
860 apropos "$1";
861 elif man --apropos man >${_NULL_DEV} 2>${_NULL_DEV};
862 then
863 man --apropos "$1";
864 elif man -k man >${_NULL_DEV} 2>${_NULL_DEV};
865 then
866 man -k "$1";
868 eval "${return_ok}";
872 ########################################################################
873 # base_name (<path>)
875 # Get the file name part of <path>, i.e. delete everything up to last
876 # `/' from the beginning of <path>. Remove final slashes, too, to get a
877 # non-empty output.
879 # Arguments : 1
880 # Output : the file name part (without slashes)
882 # Variable prefix: bn
884 base_name()
886 func_check base_name = 1 "$@";
887 bn_name="$1";
888 case "${bn_name}" in
890 # delete all final slashes
891 bn_name="$(echo x"${bn_name}" | sed -e '
892 s/^x//
893 s|//*$||
894 ')";
896 esac;
897 case "${bn_name}" in
898 /|'')
899 eval ${_UNSET} bn_name;
900 eval "${return_bad}";
902 */*)
903 # delete everything before and including the last slash `/'.
904 echo x"${bn_name}" | sed -e '
905 s/^x//
906 s|^.*//*\([^/]*\)$|\1|
910 cat <<EOF
911 ${bn_name}
914 esac;
915 eval ${_UNSET} bn_name;
916 eval "${return_ok}";
920 ########################################################################
921 # cat_z (<file>)
923 # Decompress if possible or just print <file> to standard output.
925 # gzip, bzip2, and .Z decompression is supported.
927 # Arguments: 1, a file name.
928 # Output: the content of <file>, possibly decompressed.
930 if test _"${_HAS_COMPRESSION}"_ = _yes_;
931 then
932 cat_z()
934 func_check cat_z = 1 "$@";
935 case "$1" in
937 error 'cat_z(): empty file name';
939 '-')
940 error 'cat_z(): for standard input use save_stdin()';
942 esac;
943 if obj _HAS_BZIP is_yes;
944 then
945 if bzip2 -t "$1" 2>${_NULL_DEV};
946 then
947 bzip2 -c -d "$1" 2>${_NULL_DEV};
948 eval "${return_ok}";
951 gzip -c -d -f "$1" 2>${_NULL_DEV};
952 eval "${return_ok}";
954 else
955 cat_z()
957 func_check cat_z = 1 "$@";
958 cat "$1";
959 eval "${return_ok}";
964 ########################################################################
965 # clean_up ()
967 # Do the final cleaning up before exiting; used by the trap calls.
969 # defined above
972 ########################################################################
973 # diag (<text>*)
975 # Print marked message to standard error; useful for debugging.
977 # defined above
980 ########################################################################
981 landmark '4: dirname()*';
982 ########################################################################
984 #######################################################################
985 # dirname_append (<dir> <name>)
987 # Append `name' to `dir' with clean handling of `/'.
989 # Arguments : 2
990 # Output : the generated new directory name <dir>/<name>
992 dirname_append()
994 func_check dirname_append = 2 "$@";
995 if is_empty "$1";
996 then
997 error "dir_append(): first argument is empty.";
999 if is_empty "$2";
1000 then
1001 cat <<EOF
1004 else
1005 dirname_chop "$1"/"$2";
1007 eval "${return_ok}";
1011 ########################################################################
1012 # dirname_chop (<name>)
1014 # Remove unnecessary slashes from directory name.
1016 # Argument: 1, a directory name.
1017 # Output: path without double, or trailing slashes.
1019 # Variable prefix: dc
1021 dirname_chop()
1023 func_check dirname_chop = 1 "$@";
1024 # replace all multiple slashes by a single slash `/'.
1025 dc_res="$(echo x"$1" | sed -e '
1026 s/^x//
1027 s|///*|/|g
1028 ')";
1029 case "${dc_res}" in
1030 ?*/)
1031 # remove trailing slash '/';
1032 echo x"${dc_res}" | sed -e '
1033 s/^x//
1034 s|/$||
1037 *) cat <<EOF
1038 ${dc_res}
1041 esac;
1042 eval ${_UNSET} dc_res;
1043 eval "${return_ok}";
1047 ########################################################################
1048 # do_filearg (<filearg>)
1050 # Append the file, man-page, or standard input corresponding to the
1051 # argument to the temporary file. If this is compressed in the gzip
1052 # or Z format it is decompressed. A title element is generated.
1054 # Argument either:
1055 # - name of an existing files.
1056 # - `-' to represent standard input (several times allowed).
1057 # - `man:name.(section)' the man-page for `name' in `section'.
1058 # - `man:name.section' the man-page for `name' in `section'.
1059 # - `man:name' the man-page for `name' in the lowest `section'.
1060 # - `name.section' the man-page for `name' in `section'.
1061 # - `name' the man-page for `name' in the lowest `section'.
1062 # Globals :
1063 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1065 # Output : none
1066 # Return : $_GOOD if found, ${_BAD} otherwise.
1068 # Variable prefix: df
1070 do_filearg()
1072 func_check do_filearg = 1 "$@";
1073 df_filespec="$1";
1074 # store sequence into positional parameters
1075 case "${df_filespec}" in
1077 eval ${_UNSET} df_filespec;
1078 eval "${return_good}";
1080 '-')
1081 register_file '-';
1082 eval ${_UNSET} df_filespec;
1083 eval "${return_good}";
1085 */*) # with directory part; so no man search
1086 set 'File';
1089 if obj _MAN_ENABLE is_yes;
1090 then
1091 if obj _MAN_FORCE is_yes;
1092 then
1093 set 'Manpage' 'File';
1094 else
1095 set 'File' 'Manpage';
1097 else
1098 set 'File';
1101 esac;
1102 for i
1104 case "$i" in
1105 File)
1106 if test -f "${df_filespec}";
1107 then
1108 if test -r "${df_filespec}";
1109 then
1110 register_file "${df_filespec}";
1111 eval ${_UNSET} df_filespec;
1112 eval "${return_good}";
1113 else
1114 echo2 "could not read \`${df_filespec}'";
1115 eval ${_UNSET} df_filespec;
1116 eval "${return_bad}";
1118 else
1119 continue;
1122 Manpage) # parse filespec as man page
1123 if obj _MAN_IS_SETUP is_not_yes;
1124 then
1125 man_setup;
1127 if man_do_filespec "${df_filespec}";
1128 then
1129 eval ${_UNSET} df_filespec;
1130 eval "${return_good}";
1131 else
1132 continue;
1135 esac;
1136 done;
1137 eval ${_UNSET} df_filespec;
1138 eval "${return_bad}";
1139 } # do_filearg()
1142 ########################################################################
1143 # do_nothing ()
1145 # Dummy function.
1147 do_nothing()
1149 eval return "${_OK}";
1153 ########################################################################
1154 # echo2 (<text>*)
1156 # Print to standard error with final line break.
1158 # defined above
1161 ########################################################################
1162 # error (<text>*)
1164 # Print error message and exit with error code.
1166 # defined above
1169 ########################################################################
1170 # func_check (<func_name> <rel_op> <nr_args> "$@")
1172 # Check number of arguments and register to _FUNC_STACK.
1174 # Arguments: >=3
1175 # <func_name>: name of the calling function.
1176 # <rel_op>: a relational operator: = != < > <= >=
1177 # <nr_args>: number of arguments to be checked against <operator>
1178 # "$@": the arguments of the calling function.
1180 # defined above
1182 #########################################################################
1183 # func_pop ()
1185 # Delete the top element from the function call stack.
1187 # defined above
1190 ########################################################################
1191 # func_push (<element>)
1193 # Store another element to function call stack.
1195 # defined above
1198 ########################################################################
1199 # func_stack_dump ()
1201 # Print the content of the stack.
1203 # defined above
1206 ########################################################################
1207 # get_first_essential (<arg>*)
1209 # Retrieve first non-empty argument.
1211 # Return : `1' if all arguments are empty, `0' if found.
1212 # Output : the retrieved non-empty argument.
1214 # Variable prefix: gfe
1216 get_first_essential()
1218 func_check get_first_essential '>=' 0 "$@";
1219 if is_equal "$#" 0;
1220 then
1221 eval "${return_ok}";
1223 for i
1225 gfe_var="$i";
1226 if obj gfe_var is_not_empty;
1227 then
1228 cat <<EOF
1229 ${gfe_var}
1231 eval ${_UNSET} gfe_var;
1232 eval "${return_ok}";
1234 done;
1235 eval ${_UNSET} gfe_var;
1236 eval "${return_bad}";
1240 ########################################################################
1241 landmark '5: is_*()';
1242 ########################################################################
1244 ########################################################################
1245 # is_dir (<name>)
1247 # Test whether `name' is a directory.
1249 # Arguments : 1
1250 # Return : `0' if arg1 is a directory, `1' otherwise.
1252 is_dir()
1254 func_check is_dir = 1 "$@";
1255 if test -d "$1" && test -r "$1";
1256 then
1257 eval "${return_yes}";
1259 eval "${return_no}";
1263 ########################################################################
1264 # is_empty (<string>)
1266 # Test whether `string' is empty.
1268 # Arguments : <=1
1269 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1271 is_empty()
1273 func_check is_empty = 1 "$@";
1274 if test _"$1"_ = __;
1275 then
1276 eval "${return_yes}";
1278 eval "${return_no}";
1282 ########################################################################
1283 # is_equal (<string1> <string2>)
1285 # Test whether `string1' is equal to <string2>.
1287 # Arguments : 2
1288 # Return : `0' both arguments are equal strings, `1' otherwise.
1290 is_equal()
1292 func_check is_equal = 2 "$@";
1293 if test _"$1"_ = _"$2"_;
1294 then
1295 eval "${return_yes}";
1297 eval "${return_no}";
1301 ########################################################################
1302 # is_existing (<name>)
1304 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1305 # not have `test -e'.
1307 # Arguments : 1
1308 # Return : `0' if arg1 exists, `1' otherwise.
1310 is_existing()
1312 func_check is_existing = 1 "$@";
1313 if test -f "$1" || test -d "$1";
1314 then
1315 eval "${return_yes}";
1317 eval "${return_no}";
1321 ########################################################################
1322 # is_file (<name>)
1324 # Test whether `name' is a readable file.
1326 # Arguments : 1
1327 # Return : `0' if arg1 is a readable file, `1' otherwise.
1329 is_file()
1331 func_check is_file = 1 "$@";
1332 if test -f "$1" && test -r "$1";
1333 then
1334 eval "${return_yes}";
1336 eval "${return_no}";
1340 ########################################################################
1341 # is_non_empty_file (<file_name>)
1343 # Test whether `file_name' is a non-empty existing file.
1345 # Arguments : <=1
1346 # Return :
1347 # `0' if arg1 is a non-empty existing file
1348 # `1' otherwise
1350 is_non_empty_file()
1352 func_check is_non_empty_file = 1 "$@";
1353 if is_file "$1" && test -s "$1";
1354 then
1355 eval "${return_yes}";
1357 eval "${return_no}";
1361 ########################################################################
1362 # is_not_dir (<name>)
1364 # Test whether `name' is not a readable directory.
1366 # Arguments : 1
1367 # Return : `0' if arg1 is a directory, `1' otherwise.
1369 is_not_dir()
1371 func_check is_not_dir = 1 "$@";
1372 if is_dir "$1";
1373 then
1374 eval "${return_no}";
1376 eval "${return_yes}";
1380 ########################################################################
1381 # is_not_empty (<string>)
1383 # Test whether `string' is not empty.
1385 # Arguments : <=1
1386 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1388 is_not_empty()
1390 func_check is_not_empty = 1 "$@";
1391 if is_empty "$1";
1392 then
1393 eval "${return_no}";
1395 eval "${return_yes}";
1399 ########################################################################
1400 # is_not_equal (<string1> <string2>)
1402 # Test whether `string1' differs from `string2'.
1404 # Arguments : 2
1406 is_not_equal()
1408 func_check is_not_equal = 2 "$@";
1409 if is_equal "$1" "$2";
1410 then
1411 eval "${return_no}";
1413 eval "${return_yes}";
1417 ########################################################################
1418 # is_not_file (<filename>)
1420 # Test whether `name' is a not readable file.
1422 # Arguments : >=1 (empty allowed), more args are ignored
1424 is_not_file()
1426 func_check is_not_file '>=' 1 "$@";
1427 if is_file "$1";
1428 then
1429 eval "${return_no}";
1431 eval "${return_yes}";
1435 ########################################################################
1436 # is_not_prog (<name>)
1438 # Verify that arg is a not program in $PATH.
1440 # Arguments : >=1 (empty allowed)
1441 # more args are ignored, this allows to specify progs with arguments
1443 is_not_prog()
1445 func_check is_not_prog '>=' 1 "$@";
1446 if where_is "$1" >${_NULL_DEV};
1447 then
1448 eval "${return_no}";
1450 eval "${return_yes}";
1454 ########################################################################
1455 # is_not_writable (<name>)
1457 # Test whether `name' is a not a writable file or directory.
1459 # Arguments : >=1 (empty allowed), more args are ignored
1461 is_not_writable()
1463 func_check is_not_writable '>=' 1 "$@";
1464 if is_writable "$1";
1465 then
1466 eval "${return_no}";
1468 eval "${return_yes}";
1472 ########################################################################
1473 # is_not_yes (<string>)
1475 # Test whether `string' is not "yes".
1477 # Arguments : 1
1479 is_not_yes()
1481 func_check is_not_yes = 1 "$@";
1482 if is_yes "$1";
1483 then
1484 eval "${return_no}";
1486 eval "${return_yes}";
1490 ########################################################################
1491 # is_prog (<name> [<arg>*])
1493 # Determine whether <name> is a program in $PATH
1495 # Arguments : >=0 (empty allowed)
1496 # <arg>* are ignored, this allows to specify progs with arguments.
1498 is_prog()
1500 func_check is_prog '>=' 0 "$@";
1501 case "$#" in
1503 eval "${return_no}";
1506 if where_is "$1" >${_NULL_DEV};
1507 then
1508 eval "${return_yes}";
1511 esac
1512 eval "${return_no}";
1516 ########################################################################
1517 # is_writable (<name>)
1519 # Test whether `name' is a writable file or directory.
1521 # Arguments : >=1 (empty allowed), more args are ignored
1523 is_writable()
1525 func_check is_writable '>=' 1 "$@";
1526 if test -r "$1";
1527 then
1528 if test -w "$1";
1529 then
1530 eval "${return_yes}";
1533 eval "${return_no}";
1537 ########################################################################
1538 # is_yes (<string>)
1540 # Test whether `string' has value "yes".
1542 # Arguments : <=1
1543 # Return : `0' if arg1 is `yes', `1' otherwise.
1545 is_yes()
1547 func_check is_yes = 1 "$@";
1548 if is_equal "$1" 'yes';
1549 then
1550 eval "${return_yes}";
1552 eval "${return_no}";
1556 ########################################################################
1557 # landmark ()
1559 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1561 # Globals: $_DEBUG_LM
1563 # Defined in section `Debugging functions'.
1566 ########################################################################
1567 # leave ()
1569 # Clean exit without an error.
1571 leave()
1573 clean_up;
1574 exit "${_OK}";
1578 ########################################################################
1579 landmark '6: list_*()';
1580 ########################################################################
1582 # `list' is an object class that represents an array or list. Its
1583 # data consists of space-separated single-quoted elements. So a list
1584 # has the form "'first' 'second' '...' 'last'". See list_append() for
1585 # more details on the list structure. The array elements of `list'
1586 # can be get by `set x $list; shift`.
1589 ########################################################################
1590 # list_append (<list> <element>...)
1592 # Arguments: >=2
1593 # <list>: a variable name for a list of single-quoted elements
1594 # <element>: some sequence of characters.
1595 # Output: none, but $<list> is set to
1596 # if <list> is empty: "'<element>' '...'"
1597 # otherwise: "$list '<element>' ..."
1599 # Variable prefix: la
1601 list_append()
1603 func_check list_append '>=' 2 "$@";
1604 la_name="$1";
1605 eval la_list='"${'$1'}"';
1606 shift;
1607 for s
1609 la_s="$s";
1610 case "${la_s}" in
1611 *\'*)
1612 # escape each single quote by replacing each
1613 # "'" (squote) by "'\''" (squote bslash squote squote);
1614 # note that the backslash must be doubled in the following `sed'
1615 la_element="$(echo x"${la_s}" | sed -e '
1616 s/^x//
1617 s/'"${_SQUOTE}"'/&\\&&/g
1618 ')";
1621 la_element="";
1624 la_element="${la_s}";
1626 esac;
1627 if obj la_list is_empty;
1628 then
1629 la_list="'${la_element}'";
1630 else
1631 la_list="${la_list} '${la_element}'";
1633 done;
1634 eval "${la_name}"='"${la_list}"';
1635 eval ${_UNSET} la_element;
1636 eval ${_UNSET} la_list;
1637 eval ${_UNSET} la_name;
1638 eval ${_UNSET} la_s;
1639 eval "${return_ok}";
1643 ########################################################################
1644 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1646 # Transform command line arguments into a normalized form.
1648 # Options, option arguments, and file parameters are identified and
1649 # output each as a single-quoted argument of its own. Options and
1650 # file parameters are separated by a '--' argument.
1652 # Arguments: >=1
1653 # <pre_name>: common part of a set of 4 environment variable names:
1654 # $<pre_name>_SHORT_NA: list of short options without an arg.
1655 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1656 # $<pre_name>_LONG_NA: list of long options without an arg.
1657 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1658 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1659 # the content of a variable, or direct arguments.
1661 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1663 # Example:
1664 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1665 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1666 # none-empty option lists, this will result in printing:
1667 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1669 # Use this function in the following way:
1670 # eval set x "$(args_norm PRE_NAME "$@")";
1671 # shift;
1672 # while test "$1" != '--'; do
1673 # case "$1" in
1674 # ...
1675 # esac;
1676 # shift;
1677 # done;
1678 # shift; #skip '--'
1679 # # all positional parameters ("$@") left are file name parameters.
1681 # Variable prefix: lfc
1683 list_from_cmdline()
1685 func_check list_from_cmdline '>=' 1 "$@";
1686 lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1687 lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1688 lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1689 lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1690 if obj lfc_short_n is_empty;
1691 then
1692 error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1694 if obj lfc_short_a is_empty;
1695 then
1696 error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1698 if obj lfc_long_n is_empty;
1699 then
1700 error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1702 if obj lfc_long_a is_empty;
1703 then
1704 error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1706 shift;
1707 lfc_fn='list_from_cmdline():'; # for error messages
1708 if is_equal "$#" 0;
1709 then
1710 cat <<EOF
1713 eval ${_UNSET} lfc_fparams;
1714 eval ${_UNSET} lfc_fn;
1715 eval ${_UNSET} lfc_short_a;
1716 eval ${_UNSET} lfc_short_n;
1717 eval ${_UNSET} lfc_long_a;
1718 eval ${_UNSET} lfc_long_n;
1719 eval ${_UNSET} lfc_result;
1720 eval "${return_ok}";
1722 lfc_fparams='';
1723 lfc_result='';
1724 while test "$#" -ge 1;
1726 lfc_arg="$1";
1727 shift;
1728 case "${lfc_arg}" in
1729 --) break; ;;
1730 --?*)
1731 # delete leading '--';
1732 lfc_opt="$(echo x"${lfc_arg}" | sed -e 's/^x--//')";
1733 if list_has lfc_long_n "${lfc_opt}";
1734 then
1735 # long option, no argument
1736 list_append lfc_result "--${lfc_opt}";
1737 continue;
1739 # test on `--opt=arg'
1740 if string_contains "${lfc_opt}" '=';
1741 then
1742 # extract option by deleting from the first '=' to the end
1743 lfc_lopt="$(echo x"${lfc_opt}" | sed -e '
1744 s/^x//
1745 s/=.*$//
1746 ')";
1747 if list_has lfc_long_a "${lfc_lopt}";
1748 then
1749 # get the option argument by deleting up to first `='
1750 lfc_optarg="$(echo x"${lfc_opt}" | sed -e '
1751 s/^x//
1752 s/^[^=]*=//
1753 ')";
1754 list_append lfc_result "--${lfc_lopt}" "${lfc_optarg}";
1755 continue;
1758 if list_has lfc_long_a "${lfc_opt}";
1759 then
1760 # long option with argument
1761 if test "$#" -le 0;
1762 then
1763 error "list_from_cmdline(): \
1764 ${lfc_fn} no argument for option --${lfc_opt}."
1766 list_append lfc_result "--${lfc_opt}" "$1";
1767 shift;
1768 continue;
1770 error "list_from_cmdline(): ${lfc_fn} --${lfc_opt} is not an option."
1772 -?*) # short option (cluster)
1773 # delete leading `-';
1774 lfc_rest="$(echo x"${lfc_arg}" | sed -e 's/^x-//')";
1775 while obj lfc_rest is_not_empty;
1777 # get next short option from cluster (first char of $lfc_rest)
1778 lfc_optchar="$(echo x"${lfc_rest}" | sed -e 's/^x\(.\).*$/\1/')";
1779 # remove first character from ${lfc_rest};
1780 lfc_rest="$(echo x"${lfc_rest}" | sed -e 's/^x.//')";
1781 if list_has lfc_short_n "${lfc_optchar}";
1782 then
1783 list_append lfc_result "-${lfc_optchar}";
1784 continue;
1785 elif list_has lfc_short_a "${lfc_optchar}";
1786 then
1787 if obj lfc_rest is_empty;
1788 then
1789 if test "$#" -ge 1;
1790 then
1791 list_append lfc_result "-${lfc_optchar}" "$1";
1792 shift;
1793 continue;
1794 else
1795 error "list_from_cmdline(): \
1796 ${lfc_fn}"' no argument for option -'"${lfc_optchar}."
1798 else # rest is the argument
1799 list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
1800 lfc_rest='';
1801 continue;
1803 else
1804 error "list_from_cmdline(): \
1805 ${lfc_fn} unknown option -${lfc_optchar}."
1807 done;
1810 # Here, $lfc_arg is not an option, so a file parameter.
1811 list_append lfc_fparams "${lfc_arg}";
1813 # Ignore the strange option handling of $POSIXLY_CORRECT to
1814 # end option parsing after the first file name argument. To
1815 # reuse it, do a `break' here if $POSIXLY_CORRECT is
1816 # non-empty.
1818 esac;
1819 done;
1820 list_append lfc_result '--';
1821 if obj lfc_fparams is_not_empty;
1822 then
1823 lfc_result="${lfc_result} ${lfc_fparams}";
1825 if test "$#" -gt 0;
1826 then
1827 list_append lfc_result "$@";
1829 cat <<EOF
1830 ${lfc_result}
1832 eval ${_UNSET} lfc_fparams;
1833 eval ${_UNSET} lfc_fn;
1834 eval ${_UNSET} lfc_short_a;
1835 eval ${_UNSET} lfc_short_n;
1836 eval ${_UNSET} lfc_long_a;
1837 eval ${_UNSET} lfc_long_n;
1838 eval ${_UNSET} lfc_result;
1839 eval ${_UNSET} lfc_arg;
1840 eval ${_UNSET} lfc_opt;
1841 eval ${_UNSET} lfc_opt_arg;
1842 eval ${_UNSET} lfc_opt_char;
1843 eval ${_UNSET} lfc_lopt;
1844 eval ${_UNSET} lfc_rest;
1845 eval "${return_ok}";
1846 } # list_from_cmdline()
1849 ########################################################################
1850 # list_from_split (<string> <separator>)
1852 # In <string>, escape all white space characters and replace each
1853 # <separator> by space.
1855 # Arguments: 2: a <string> that is to be split into parts divided by
1856 # <separator>
1857 # Output: the resulting list string
1859 # Variable prefix: lfs
1861 list_from_split()
1863 func_check list_from_split = 2 "$@";
1865 # precede each space or tab by a backslash `\' (doubled for `sed')
1866 lfs_s="$(echo x"$1" | sed -e '
1867 s/^x//
1868 s/\(['"${_SPACE}${_TAB}"']\)/\\\1/g
1869 ')";
1871 # replace split character of string by the list separator ` ' (space).
1872 case "$2" in
1873 /) # cannot use normal `sed' separator
1874 echo x"${lfs_s}" | sed -e '
1875 s/^x//
1876 s|'"$2"'| |g
1879 ?) # use normal `sed' separator
1880 echo x"${lfs_s}" | sed -e '
1881 s/^x//
1882 s/'"$2"'/ /g
1885 ??*)
1886 error 'list_from_split(): separator must be a single character.';
1888 esac;
1889 eval ${_UNSET} lfs_s;
1890 eval "${return_ok}";
1894 ########################################################################
1895 # list_get (<list>)
1897 # Check whether <list> is a space-separated list of '-quoted elements.
1899 # If the test fails an error is raised.
1900 # If the test succeeds the argument is echoed.
1902 # Testing criteria:
1903 # A list has the form "'first' 'second' '...' 'last'". So it has a
1904 # leading and a final quote and the elements are separated by "' '"
1905 # constructs. If these are all removed there should not be any
1906 # unescaped single-quotes left. Watch out for escaped single
1907 # quotes; they have the form '\'' (sq bs sq sq).
1909 # Arguments: 1
1910 # Output: the argument <list> unchanged, if the check succeeded.
1912 # Variable prefix: lg
1914 list_get()
1916 func_check list_get = 1 "$@";
1917 eval lg_list='"${'$1'}"';
1918 # remove leading and final space characters
1919 lg_list="$(echo x"${lg_list}" | sed -e '
1920 s/^x['"${_SPACE}${_TAB}"']*//
1921 s/['"${_SPACE}${_TAB}"']*$//
1922 ')";
1923 case "${lg_list}" in
1925 eval ${_UNSET} lg_list;
1926 eval "${return_ok}";
1928 \'*\')
1929 cat <<EOF
1930 ${lg_list}
1932 eval ${_UNSET} lg_list;
1933 eval "${return_ok}";
1936 error "list_get(): bad list: $1"
1938 esac;
1939 eval ${_UNSET} lg_list;
1940 eval "${return_ok}";
1944 ########################################################################
1945 # list_has (<var_name> <element>)
1947 # Arguments: 2
1948 # <var_name>: a variable name for a list of single-quoted elements
1949 # <element>: some sequence of characters.
1950 # Output:
1951 # if <list> is empty: "'<element>' '...'"
1952 # otherwise: "list '<element>' ..."
1954 list_has()
1956 func_check list_has = 2 "$@";
1957 eval _list='"${'$1'}"';
1958 if obj _list is_empty;
1959 then
1960 eval "${return_no}";
1962 _element="$2";
1963 case "$2" in
1964 \'*\') _element="$2"; ;;
1965 *) _element="'$2'"; ;;
1966 esac;
1967 if string_contains "${_list}" "${_element}";
1968 then
1969 eval "${return_yes}";
1970 else
1971 eval "${return_no}";
1973 eval "${return_ok}";
1977 ########################################################################
1978 # list_has_not (<list> <element>)
1980 # Arguments: 2
1981 # <list>: a space-separated list of single-quoted elements.
1982 # <element>: some sequence of characters.
1983 # Output:
1984 # if <list> is empty: "'<element>' '...'"
1985 # otherwise: "<list> '<element>' ..."
1987 list_has_not()
1989 func_check list_has_not = 2 "$@";
1990 eval _list='"${'$1'}"';
1991 if obj _list is_empty;
1992 then
1993 eval "${return_yes}";
1995 _element="$2";
1996 case "$2" in
1997 \'*\') _element="$2"; ;;
1998 *) _element="'$2'"; ;;
1999 esac;
2000 if string_contains "${_list}" "${_element}";
2001 then
2002 eval "${return_no}";
2003 else
2004 eval "${return_yes}";
2006 eval "${return_ok}";
2010 ########################################################################
2011 landmark '7: man_*()';
2012 ########################################################################
2014 ########################################################################
2015 # man_do_filespec (<filespec>)
2017 # Print suitable man page(s) for filespec to $_TMP_CAT.
2019 # Arguments : 2
2020 # <filespec>: argument of the form `man:name.section', `man:name',
2021 # `man:name(section)', `name.section', `name'.
2023 # Globals : $_OPT_ALL
2025 # Output : none.
2026 # Return : `0' if man page was found, `1' else.
2028 # Only called from do_fileargs(), checks on $MANPATH and
2029 # $_MAN_ENABLE are assumed.
2031 # Variable prefix: mdf
2033 man_do_filespec()
2035 func_check man_do_filespec = 1 "$@";
2036 if obj _MAN_PATH is_empty;
2037 then
2038 eval "${return_bad}";
2040 if is_empty "$1";
2041 then
2042 eval "${return_bad}";
2044 mdf_spec="$1";
2045 mdf_name='';
2046 mdf_section='';
2047 case "${mdf_spec}" in
2048 */*) # not a man spec when it contains '/'
2049 eval ${_UNSET} mdf_got_one;
2050 eval ${_UNSET} mdf_name;
2051 eval ${_UNSET} mdf_section;
2052 eval ${_UNSET} mdf_spec;
2053 eval "${return_bad}";
2055 man:?*\(?*\)) # man:name(section)
2056 mdf_name="$(echo x"${mdf_spec}" \
2057 | sed -e 's/^xman:\(..*\)(\(..*\))$/\1/')";
2058 mdf_section="$(echo x"${mdf_spec}" \
2059 | sed -e 's/^xman:\(..*\)(\(..*\))$/\2/')";
2061 man:?*.[0-9on]) # man:name.section
2062 mdf_name="$(echo x"${mdf_spec}" \
2063 | sed -e 's/^xman:\(..*\)\..$/\1/')";
2064 mdf_section="$(echo x"${mdf_spec}" \
2065 | sed -e 's/^x.*\(.\)$/\1/')";
2067 man:?*) # man:name
2068 mdf_name="$(echo x"${mdf_spec}" | sed -e 's/^xman://')";
2070 ?*\(?*\)) # name(section)
2071 mdf_name="$(echo x"${mdf_spec}" \
2072 | sed -e 's/^x\(..*\)(\(..*\))$/\1/')";
2073 mdf_section="$(echo x"${mdf_spec}" \
2074 | sed -e 's/^x\(..*\)(\(..*\))$/\2/')";
2076 ?*.[0-9on]) # name.section
2077 mdf_name="$(echo x"${mdf_spec}" \
2078 | sed -e 's/^x\(..*\)\..$/\1/')";
2079 mdf_section="$(echo x"${mdf_spec}" \
2080 | sed -e 's/^x.*\(.\)$/\1/')";
2083 mdf_name="${mdf_spec}";
2085 esac;
2086 if obj mdf_name is_empty;
2087 then
2088 eval ${_UNSET} mdf_got_one;
2089 eval ${_UNSET} mdf_name;
2090 eval ${_UNSET} mdf_section;
2091 eval ${_UNSET} mdf_spec;
2092 eval "${return_bad}";
2094 mdf_got_one='no';
2095 if obj mdf_section is_empty;
2096 then
2097 eval set x "${_MAN_AUTO_SEC}";
2098 shift;
2099 for s
2101 mdf_s="$s";
2102 if man_search_section "${mdf_name}" "${mdf_s}";
2103 then # found
2104 if obj _MAN_ALL is_yes;
2105 then
2106 mdf_got_one='yes';
2107 else
2108 eval ${_UNSET} mdf_got_one;
2109 eval ${_UNSET} mdf_name;
2110 eval ${_UNSET} mdf_s;
2111 eval ${_UNSET} mdf_section;
2112 eval ${_UNSET} mdf_spec;
2113 eval "${return_good}";
2116 done;
2117 else
2118 if man_search_section "${mdf_name}" "${mdf_section}";
2119 then
2120 eval ${_UNSET} mdf_got_one;
2121 eval ${_UNSET} mdf_name;
2122 eval ${_UNSET} mdf_s;
2123 eval ${_UNSET} mdf_section;
2124 eval ${_UNSET} mdf_spec;
2125 eval "${return_good}";
2126 else
2127 eval ${_UNSET} mdf_got_one;
2128 eval ${_UNSET} mdf_name;
2129 eval ${_UNSET} mdf_section;
2130 eval ${_UNSET} mdf_spec;
2131 eval "${return_bad}";
2134 if obj _MAN_ALL is_yes && is_yes "${mdf_got_one}";
2135 then
2136 eval ${_UNSET} mdf_got_one;
2137 eval ${_UNSET} mdf_name;
2138 eval ${_UNSET} mdf_s;
2139 eval ${_UNSET} mdf_section;
2140 eval ${_UNSET} mdf_spec;
2141 eval "${return_good}";
2143 eval ${_UNSET} mdf_got_one;
2144 eval ${_UNSET} mdf_name;
2145 eval ${_UNSET} mdf_s;
2146 eval ${_UNSET} mdf_section;
2147 eval ${_UNSET} mdf_spec;
2148 eval "${return_bad}";
2149 } # man_do_filespec()
2152 ########################################################################
2153 # man_register_file (<file> <name> [<section>])
2155 # Write a found man page file and register the title element.
2157 # Arguments: 1, 2, or 3; maybe empty
2158 # Output: none
2160 man_register_file()
2162 func_check man_register_file '>=' 2 "$@";
2163 case "$#" in
2164 2|3) do_nothing; ;;
2166 error "man_register_file() expects 2 or 3 arguments.";
2168 esac;
2169 if is_empty "$1";
2170 then
2171 error 'man_register_file(): file name is empty';
2173 to_tmp "$1";
2174 case "$#" in
2176 register_title "man:$2";
2177 eval "${return_ok}";
2180 register_title "$2.$3";
2181 eval "${return_ok}";
2183 esac;
2184 eval "${return_ok}";
2188 ########################################################################
2189 # man_search_section (<name> <section>)
2191 # Retrieve man pages.
2193 # Arguments : 2
2194 # Globals : $_MAN_PATH, $_MAN_EXT
2195 # Return : 0 if found, 1 otherwise
2197 # Variable prefix: mss
2199 man_search_section()
2201 func_check man_search_section = 2 "$@";
2202 if obj _MAN_PATH is_empty;
2203 then
2204 eval "${return_bad}";
2206 if is_empty "$1";
2207 then
2208 eval "${return_bad}";
2210 if is_empty "$2";
2211 then
2212 eval "${return_bad}";
2214 mss_name="$1";
2215 mss_section="$2";
2216 eval set x "$(path_split "${_MAN_PATH}")";
2217 shift;
2218 mss_got_one='no';
2219 if obj _MAN_EXT is_empty;
2220 then
2221 for d
2223 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2224 if obj mss_dir is_dir;
2225 then
2226 mss_prefix="$(\
2227 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2228 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2229 sed -e '\| found|s|.*||'
2231 if obj mss_files is_not_empty;
2232 then
2233 # for f in $mss_files
2234 for f in $(eval set x ${mss_files}; shift; echo "$@")
2236 mss_f="$f";
2237 if obj mss_f is_file;
2238 then
2239 if is_yes "${mss_got_one}";
2240 then
2241 register_file "${mss_f}";
2242 elif obj _MAN_ALL is_yes;
2243 then
2244 man_register_file "${mss_f}" "${mss_name}";
2245 else
2246 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2247 eval ${_UNSET} mss_dir;
2248 eval ${_UNSET} mss_ext;
2249 eval ${_UNSET} mss_f;
2250 eval ${_UNSET} mss_files;
2251 eval ${_UNSET} mss_got_one;
2252 eval ${_UNSET} mss_name;
2253 eval ${_UNSET} mss_prefix;
2254 eval ${_UNSET} mss_section;
2255 eval "${return_good}";
2257 mss_got_one='yes';
2259 done;
2262 done;
2263 else
2264 mss_ext="${_MAN_EXT}";
2265 # check for directory name having trailing extension
2266 for d
2268 mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";
2269 if obj mss_dir is_dir;
2270 then
2271 mss_prefix=\
2272 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2273 mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2274 sed -e '\|not found|s|.*||'
2276 if obj mss_files is_not_empty;
2277 then
2278 # for f in $mss_files
2279 for f in $(eval set x ${mss_files}; shift; echo "$@")
2281 mss_f="$f";
2282 if obj mss_f is_file;
2283 then
2284 if is_yes "${mss_got_one}";
2285 then
2286 register_file "${mss_f}";
2287 elif obj _MAN_ALL is_yes;
2288 then
2289 man_register_file "${mss_f}" "${mss_name}";
2290 else
2291 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2292 eval ${_UNSET} mss_dir;
2293 eval ${_UNSET} mss_ext;
2294 eval ${_UNSET} mss_f;
2295 eval ${_UNSET} mss_files;
2296 eval ${_UNSET} mss_got_one;
2297 eval ${_UNSET} mss_name;
2298 eval ${_UNSET} mss_prefix;
2299 eval ${_UNSET} mss_section;
2300 eval "${return_good}";
2302 mss_got_one='yes';
2304 done;
2307 done;
2308 # check for files with extension in directories without extension
2309 for d
2311 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2312 if obj mss_dir is_dir;
2313 then
2314 mss_prefix="$(dirname_append "${mss_dir}" \
2315 "${mss_name}.${mss_section}${mss_ext}")";
2316 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2317 sed -e '\|not found|s|.*||'
2319 if obj mss_files is_not_empty;
2320 then
2321 # for f in $mss_files
2322 for f in $(eval set x ${mss_files}; shift; echo "$@")
2324 mss_f="$f";
2325 if obj mss_f is_file;
2326 then
2327 if is_yes "${mss_got_one}";
2328 then
2329 register_file "${mss_f}";
2330 elif obj _MAN_ALL is_yes;
2331 then
2332 man_register_file "${mss_f}" "${mss_name}";
2333 else
2334 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2335 eval ${_UNSET} mss_dir;
2336 eval ${_UNSET} mss_ext;
2337 eval ${_UNSET} mss_f;
2338 eval ${_UNSET} mss_files;
2339 eval ${_UNSET} mss_got_one;
2340 eval ${_UNSET} mss_name;
2341 eval ${_UNSET} mss_prefix;
2342 eval ${_UNSET} mss_section;
2343 eval "${return_good}";
2345 mss_got_one='yes';
2347 done;
2350 done;
2352 if obj _MAN_ALL is_yes && is_yes "${mss_got_one}";
2353 then
2354 eval ${_UNSET} mss_dir;
2355 eval ${_UNSET} mss_ext;
2356 eval ${_UNSET} mss_f;
2357 eval ${_UNSET} mss_files;
2358 eval ${_UNSET} mss_got_one;
2359 eval ${_UNSET} mss_name;
2360 eval ${_UNSET} mss_prefix;
2361 eval ${_UNSET} mss_section;
2362 eval "${return_good}";
2364 eval ${_UNSET} mss_dir;
2365 eval ${_UNSET} mss_ext;
2366 eval ${_UNSET} mss_f;
2367 eval ${_UNSET} mss_files;
2368 eval ${_UNSET} mss_got_one;
2369 eval ${_UNSET} mss_name;
2370 eval ${_UNSET} mss_prefix;
2371 eval ${_UNSET} mss_section;
2372 eval "${return_bad}";
2373 } # man_search_section()
2376 ########################################################################
2377 # man_setup ()
2379 # Setup the variables $_MAN_* needed for man page searching.
2381 # Globals:
2382 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2383 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2384 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2385 # $_MAN_SEC, $_MAN_ALL
2386 # in/out: $_MAN_ENABLE
2388 # The precedence for the variables related to `man' is that of GNU
2389 # `man', i.e.
2391 # $LANG; overridden by
2392 # $LC_MESSAGES; overridden by
2393 # $LC_ALL; this has the same precedence as
2394 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2395 # $MANOPT; overridden by
2396 # the groffer command line options.
2398 # Variable prefix: ms
2400 man_setup()
2402 func_check main_man_setup = 0 "$@";
2404 if obj _MAN_IS_SETUP is_yes;
2405 then
2406 eval "${return_ok}";
2408 _MAN_IS_SETUP='yes';
2410 if obj _MAN_ENABLE is_not_yes;
2411 then
2412 eval "${return_ok}";
2415 # determine basic path for man pages
2416 _MAN_PATH="$(get_first_essential \
2417 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2418 if obj _MAN_PATH is_empty;
2419 then
2420 manpath_set_from_path;
2421 else
2422 _MAN_PATH="$(path_clean "${_MAN_PATH}")";
2424 if obj _MAN_PATH is_empty;
2425 then
2426 if is_prog 'manpath';
2427 then
2428 _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available
2431 if obj _MAN_PATH is_empty;
2432 then
2433 _MAN_ENABLE="no";
2434 eval "${return_ok}";
2437 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2438 if obj _MAN_ALL is_empty;
2439 then
2440 _MAN_ALL='no';
2443 _MAN_SYS="$(get_first_essential \
2444 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2445 ms_lang="$(get_first_essential \
2446 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2447 case "${ms_lang}" in
2448 C|POSIX)
2449 _MAN_LANG="";
2450 _MAN_LANG2="";
2453 _MAN_LANG="${ms_lang}";
2454 _MAN_LANG2="";
2457 _MAN_LANG="${ms_lang}";
2458 # get first two characters of $ms_lang
2459 _MAN_LANG2="$(echo x"${ms_lang}" | sed -e 's/^x\(..\).*$/\1/')";
2461 esac;
2462 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2464 manpath_add_lang_sys; # this is very slow
2466 _MAN_SEC="$(get_first_essential \
2467 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2468 if obj _MAN_PATH is_empty;
2469 then
2470 _MAN_ENABLE="no";
2471 eval ${_UNSET} ms_lang;
2472 eval "${return_ok}";
2475 _MAN_EXT="$(get_first_essential \
2476 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2477 eval ${_UNSET} ms_lang;
2478 eval "${return_ok}";
2479 } # man_setup()
2482 ########################################################################
2483 landmark '8: manpath_*()';
2484 ########################################################################
2486 ########################################################################
2487 # manpath_add_lang_sys ()
2489 # Add language and operating system specific directories to man path.
2491 # Arguments : 0
2492 # Output : none
2493 # Globals:
2494 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2495 # list of names of operating systems.
2496 # $_MAN_LANG and $_MAN_LANG2: each a single name
2497 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2498 # separated list of directories.
2500 # Variable prefix: mals
2502 manpath_add_lang_sys()
2504 func_check manpath_add_lang_sys = 0 "$@";
2505 if obj _MAN_PATH is_empty;
2506 then
2507 eval "${return_ok}";
2509 # twice test both sys and lang
2510 eval set x "$(path_split "${_MAN_PATH}")";
2511 shift;
2512 mals_mp='';
2513 for p
2514 do # loop on man path directories
2515 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2516 done;
2517 eval set x "$(path_split "${mals_mp}")";
2518 shift;
2519 for p
2520 do # loop on man path directories
2521 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2522 done;
2523 _MAN_PATH="$(path_chop "${mals_mp}")";
2524 eval ${_UNSET} mals_mp;
2525 eval "${return_ok}";
2529 # To the directory in $1 append existing sys/lang subdirectories
2530 # Function is necessary to split the OS list.
2532 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2533 # argument: 2: `man_path' and `dir'
2534 # output: colon-separated path of the retrieved subdirectories
2536 # Variable prefix: _mals
2538 _manpath_add_lang_sys_single()
2540 func_check _manpath_add_lang_sys_single = 2 "$@";
2541 _mals_res="$1";
2542 _mals_parent="$2";
2543 eval set x "$(list_from_split "${_MAN_SYS}" ',')";
2544 shift;
2545 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
2547 _mals_dir="$(dirname_append "${_mals_parent}" "$d")";
2548 if obj _mals_res path_not_contains "${_mals_dir}" && \
2549 obj _mals_dir is_dir;
2550 then
2551 _mals_res="${_mals_res}:${_mals_dir}";
2553 done;
2554 if path_not_contains "${_mals_res}" "${_mals_parent}";
2555 then
2556 _mals_res="${_mals_res}:${_mals_parent}";
2558 path_chop "${_mals_res}";
2559 eval ${_UNSET} _mals_dir;
2560 eval ${_UNSET} _mals_parent;
2561 eval ${_UNSET} _mals_res;
2562 eval "${return_ok}";
2565 # end manpath_add_lang_sys ()
2568 ########################################################################
2569 # manpath_set_from_path ()
2571 # Determine basic search path for man pages from $PATH.
2573 # Return: `0' if a valid man path was retrieved.
2574 # Output: none
2575 # Globals:
2576 # in: $PATH
2577 # out: $_MAN_PATH
2579 # Variable prefix: msfp
2581 manpath_set_from_path()
2583 func_check manpath_set_from_path = 0 "$@";
2585 msfp_manpath='';
2587 # get a basic man path from $PATH
2588 if obj PATH is_not_empty;
2589 then
2590 eval set x "$(path_split "${PATH}")";
2591 shift;
2592 for d
2594 # delete the final `/bin' part
2595 msfp_base="$(echo x"$d" | sed -e '
2596 s/^x//
2597 s|//*bin/*$||
2598 ')";
2599 for e in /share/man /man
2601 msfp_mandir="${msfp_base}$e";
2602 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}";
2603 then
2604 msfp_manpath="${msfp_manpath}:${msfp_mandir}";
2606 done;
2607 done;
2610 # append some default directories
2611 for d in /usr/local/share/man /usr/local/man \
2612 /usr/share/man /usr/man \
2613 /usr/X11R6/man /usr/openwin/man \
2614 /opt/share/man /opt/man \
2615 /opt/gnome/man /opt/kde/man
2617 msfp_d="$d";
2618 if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir;
2619 then
2620 msfp_manpath="${msfp_manpath}:${mfsp_d}";
2622 done;
2624 _MAN_PATH="${msfp_manpath}";
2625 eval ${_UNSET} msfp_base;
2626 eval ${_UNSET} msfp_d;
2627 eval ${_UNSET} msfp_mandir;
2628 eval ${_UNSET} msfp_manpath;
2629 eval "${return_ok}";
2630 } # manpath_set_from_path()
2633 ########################################################################
2634 landmark '9: obj_*()';
2635 ########################################################################
2637 ########################################################################
2638 # obj (<object> <call_name> <arg>...)
2640 # This works like a method (object function) call for an object.
2641 # Run "<call_name> $<object> <arg> ...".
2643 # The first argument represents an object whose data is given as first
2644 # argument to <call_name>().
2646 # Argument: >=2
2647 # <object>: variable name
2648 # <call_name>: a program or function name
2650 # Variable prefix: o
2652 obj()
2654 func_check obj '>=' 2 "$@";
2655 if is_empty "$2";
2656 then
2657 error "obj(): function name is empty."
2658 else
2659 o_func="$2";
2661 eval o_arg1='"${'$1'}"';
2662 shift;
2663 shift;
2664 eval "${o_func}"' "${o_arg1}" "$@"';
2665 n="$?";
2666 eval ${_UNSET} o_arg1;
2667 eval ${_UNSET} o_func;
2668 eval "${return_var} $n";
2669 } # obj()
2672 ########################################################################
2673 # obj_data (<object>)
2675 # Print the data of <object>, i.e. the content of $<object>.
2676 # For possible later extensions.
2678 # Arguments: 1
2679 # <object>: a variable name
2680 # Output: the data of <object>
2682 # Variable prefix: od
2684 obj_data()
2686 func_check obj '=' 1 "$@";
2687 if is_empty "$1";
2688 then
2689 error "obj_data(): object name is empty."
2691 eval od_res='"${'$1'}"';
2692 cat <<EOF
2693 ${od_res}
2695 eval ${_UNSET} od_res;
2696 eval "${return_ok}";
2700 ########################################################################
2701 # obj_from_output (<object> <call_name> <arg>...)
2703 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2704 # function call to a global variable.
2706 # Arguments: >=2
2707 # <object>: a variable name
2708 # <call_name>: the name of a function or program
2709 # <arg>: optional argument to <call_name>
2710 # Output: none
2712 # Variable prefix: ofo
2714 obj_from_output()
2716 func_check obj_from_output '>=' 2 "$@";
2717 if is_empty "$1";
2718 then
2719 error "res(): variable name is empty.";
2720 elif is_empty "$2";
2721 then
2722 error "res(): function name is empty."
2723 else
2724 ofo_result_name="$1";
2726 shift;
2727 eval "${ofo_result_name}"'="$('"$@"')"';
2728 eval "${return_ok}";
2732 ########################################################################
2733 # obj_set (<object> <data>)
2735 # Set the data of <object>, i.e. call "$<object>=<data>".
2737 # Arguments: 2
2738 # <object>: a variable name
2739 # <data>: a string
2740 # Output:: none
2742 obj_set()
2744 func_check obj_set '=' 2 "$@";
2745 if is_empty "$1";
2746 then
2747 error "obj_set(): object name is empty."
2749 eval "$1"='"$2"';
2750 eval "${return_ok}";
2754 ########################################################################
2755 # path_chop (<path>)
2757 # Remove unnecessary colons from path.
2759 # Argument: 1, a colon separated path.
2760 # Output: path without leading, double, or trailing colons.
2762 path_chop()
2764 func_check path_chop = 1 "$@";
2766 # replace multiple colons by a single colon `:'
2767 # remove leading and trailing colons
2768 echo x"$1" | sed -e '
2769 s/^x:*//
2770 s/:::*/:/g
2771 s/:*$//
2773 eval "${return_ok}";
2777 ########################################################################
2778 # path_clean (<path>)
2780 # Remove non-existing directories from a colon-separated list.
2782 # Argument: 1, a colon separated path.
2783 # Output: colon-separated list of existing directories.
2785 # Variable prefix: pc
2787 path_clean()
2789 func_check path_clean = 1 "$@";
2790 if is_not_equal "$#" 1;
2791 then
2792 error 'path_clean() needs 1 argument.';
2794 pc_arg="$1";
2795 eval set x "$(path_split "${pc_arg}")";
2796 shift;
2797 pc_res="";
2798 for i
2800 pc_i="$i";
2801 if obj pc_i is_not_empty \
2802 && obj pc_res path_not_contains "${pc_i}" \
2803 && obj pc_i is_dir;
2804 then
2805 case "${pc_i}" in
2806 ?*/) pc_res="${pc_res}$(dirname_chop "${pc_i}")"; ;;
2807 *) pc_res="${pc_res}:${pc_i}";
2808 esac;
2810 done;
2811 eval ${_UNSET} pc_arg;
2812 eval ${_UNSET} pc_i;
2813 eval ${_UNSET} pc_res;
2814 if path_chop "${pc_res}";
2815 then
2816 eval "${return_ok}";
2817 else
2818 eval "${return_bad}";
2823 ########################################################################
2824 # path_contains (<path> <dir>)
2826 # Test whether `dir' is contained in `path', a list separated by `:'.
2828 # Arguments : 2 arguments.
2829 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2831 path_contains()
2833 func_check path_contains = 2 "$@";
2834 case ":$1:" in
2835 *":$2:"*)
2836 eval "${return_yes}";
2839 eval "${return_no}";
2841 esac;
2842 eval "${return_ok}";
2846 ########################################################################
2847 # path_not_contains (<path> <dir>)
2849 # Test whether `dir' is not contained in colon separated `path'.
2851 # Arguments : 2 arguments.
2853 path_not_contains()
2855 func_check path_not_contains = 2 "$@";
2856 if path_contains "$1" "$2";
2857 then
2858 eval "${return_no}";
2859 else
2860 eval "${return_yes}";
2862 eval "${return_ok}";
2866 ########################################################################
2867 # path_split (<path>)
2869 # In `path' escape white space and replace each colon by a space.
2871 # Arguments: 1: a colon-separated path
2872 # Output: the resulting list, process with `eval set'
2874 path_split()
2876 func_check path_split = 1 "$@";
2877 list_from_split "$1" ':';
2878 eval "${return_ok}";
2882 ########################################################################
2883 landmark '10: register_*()';
2884 ########################################################################
2886 ########################################################################
2887 # register_file (<filename>)
2889 # Write a found file and register the title element.
2891 # Arguments: 1: a file name
2892 # Output: none
2894 register_file()
2896 func_check register_file = 1 "$@";
2897 if is_empty "$1";
2898 then
2899 error 'register_file(): file name is empty';
2901 if is_equal "$1" '-';
2902 then
2903 to_tmp "${_TMP_STDIN}";
2904 register_title 'stdin';
2905 else
2906 to_tmp "$1";
2907 register_title "$(base_name "$1")";
2909 eval "${return_ok}";
2913 ########################################################################
2914 # register_title (<filespec>)
2916 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2918 # Globals: $_REGISTERED_TITLE (rw)
2920 # Variable prefix: rt
2922 register_title()
2924 func_check register_title = 1 "$@";
2925 if is_empty "$1";
2926 then
2927 eval "${return_ok}";
2929 rt_title="$(base_name "$1")"; # remove directory part
2931 # remove extension `.gz'
2932 rt_title="$(echo x"${rt_title}" | sed -e '
2933 s/^x//
2934 s/\.gz$//
2935 ')";
2936 # remove extension `.Z'
2937 rt_title="$(echo x"${rt_title}" | sed -e '
2938 s/^x//
2939 s/\.Z$//
2940 ')";
2942 if obj rt_title is_empty;
2943 then
2944 eval "${return_ok}";
2946 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";
2947 eval ${_UNSET} rt_title;
2948 eval "${return_ok}";
2952 ########################################################################
2953 # reset ()
2955 # Reset the variables that can be affected by options to their default.
2958 # Defined in section `Preset' after the rudimentary shell tests.
2961 ########################################################################
2962 # save_stdin ()
2964 # Store standard input to temporary file (with decompression).
2966 # Variable prefix: ss
2968 if obj _HAS_COMPRESSION is_yes;
2969 then
2970 save_stdin()
2972 func_check save_stdin = 0 "$@";
2973 ss_f="${_TMP_DIR}"/INPUT;
2974 cat >"${ss_f}";
2975 cat_z "${ss_f}" >"${_TMP_STDIN}";
2976 rm -f "${ss_f}";
2977 eval ${_UNSET} ss_f;
2978 eval "${return_ok}";
2980 else
2981 save_stdin()
2983 func_check save_stdin = 0 "$@";
2984 cat >"${_TMP_STDIN}";
2985 eval "${return_ok}";
2990 ########################################################################
2991 landmark '11: stack_*()';
2992 ########################################################################
2994 ########################################################################
2995 # string_contains (<string> <part>)
2997 # Test whether `part' is contained in `string'.
2999 # Arguments : 2 text arguments.
3000 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3002 string_contains()
3004 func_check string_contains = 2 "$@";
3005 case "$1" in
3006 *"$2"*)
3007 eval "${return_yes}";
3010 eval "${return_no}";
3012 esac;
3013 eval "${return_ok}";
3017 ########################################################################
3018 # string_not_contains (<string> <part>)
3020 # Test whether `part' is not substring of `string'.
3022 # Arguments : 2 text arguments.
3023 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3025 string_not_contains()
3027 func_check string_not_contains = 2 "$@";
3028 if string_contains "$1" "$2";
3029 then
3030 eval "${return_no}";
3031 else
3032 eval "${return_yes}";
3034 eval "${return_ok}";
3038 ########################################################################
3039 landmark '12: tmp_*()';
3040 ########################################################################
3042 ########################################################################
3043 # tmp_cat ()
3045 # output the temporary cat file (the concatenation of all input)
3047 tmp_cat()
3049 func_check tmp_cat '=' 0 "$@";
3050 cat "${_TMP_CAT}";
3051 eval "${return_var}" "$?";
3055 ########################################################################
3056 # tmp_create (<suffix>?)
3058 # Create temporary file.
3060 # It's safe to use the shell process ID together with a suffix to
3061 # have multiple temporary files.
3063 # Globals: $_TMP_DIR
3065 # Output : name of created file
3067 # Variable prefix: tc
3069 tmp_create()
3071 func_check tmp_create '<=' 1 "$@";
3072 # the output file does not have `,' as first character, so these are
3073 # different names from the output file.
3074 tc_tmp="${_TMP_DIR}/,$1";
3075 : >"${tc_tmp}"
3076 cat <<EOF
3077 ${tc_tmp}
3079 eval ${_UNSET} tc_tmp;
3080 eval "${return_ok}";
3084 ########################################################################
3085 # to_tmp (<filename>)
3087 # print file (decompressed) to the temporary cat file
3089 to_tmp()
3091 func_check to_tmp = 1 "$@";
3092 if is_file "$1";
3093 then
3094 if obj _OPT_LOCATION is_yes;
3095 then
3096 echo2 "$1";
3098 if obj _OPT_WHATIS is_yes;
3099 then
3100 what_is "$1" >>"${_TMP_CAT}";
3101 else
3102 cat_z "$1" >>"${_TMP_CAT}";
3104 else
3105 error "to_tmp(): could not read file \`$1'.";
3107 eval "${return_ok}";
3111 ########################################################################
3112 # trap_clean ()
3114 # disable trap on all exit codes ($_ALL_EXIT)
3116 # Arguments: 0
3117 # Globals: $_ALL_EXIT
3119 trap_clean()
3121 func_check trap_clean = 0 "$@";
3122 # for i in $_ALL_EXIT
3123 for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")
3125 trap "" "$i" 2>${_NULL_DEV} || :;
3126 done;
3127 eval "${return_ok}";
3131 ########################################################################
3132 # trap_set (<functionname>)
3134 # call function on all exit codes ($_ALL_EXIT)
3136 # Arguments: 1 (name of a shell function)
3137 # Globals: $_ALL_EXIT
3139 trap_set()
3141 func_check trap_set = 1 "$@";
3142 # for i in $_ALL_EXIT
3143 for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")
3145 trap "$1" "$i" 2>${_NULL_DEV} || :;
3146 done;
3147 eval "${return_ok}";
3151 ########################################################################
3152 # usage ()
3154 # print usage information to stderr; for groffer option --help.
3156 usage()
3158 func_check usage = 0 "$@";
3159 echo;
3160 version;
3161 echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';
3162 cat <<EOF
3164 Display roff files, standard input, and/or Unix manual pages with a X
3165 Window viewer or in several text modes. All input is decompressed
3166 on-the-fly with all formats that gzip can handle.
3168 "filespec" is one of
3169 "filename" name of a readable file
3170 "-" for standard input
3171 "man:name.n" man page "name" in section "n"
3172 "man:name" man page "name" in first section found
3173 "name.n" man page "name" in section "n"
3174 "name" man page "name" in first section found
3175 and some more (see groffer(1) for details).
3177 -h --help print this usage message.
3178 -Q --source output as roff source.
3179 -T --device=name pass to groff using output device "name".
3180 -v --version print version information.
3181 -V display the groff execution pipe instead of formatting.
3182 -X --X --x display with "gxditview" using groff -X.
3183 -Z --ditroff --intermediate-output
3184 generate groff intermediate output without
3185 post-processing and viewing, like groff -Z.
3186 All other short options are interpreted as "groff" formatting options.
3188 The most important groffer long options are
3190 --apropos=name start man's "apropos" program for "name".
3191 --apropos-data=name
3192 "apropos" for "name" in man's data sections 4, 5, 7.
3193 --apropos-devel=name
3194 "apropos" for "name" in development sections 2, 3, 9.
3195 --apropos-progs=name
3196 "apropos" for "name" in man's program sections 1, 6, 8.
3197 --auto choose mode automatically from the default mode list.
3198 --default reset all options to the default value.
3199 --default-modes=mode1,mode2,...
3200 set sequence of automatically tried modes.
3201 --dvi display in a viewer for TeX device independent format.
3202 --dvi-viewer choose the viewer program for dvi mode.
3203 --groff process like groff, disable viewing features.
3204 --help display this helping output.
3205 --html --www display in a web browser.
3206 --html-viewer choose the web browser for www mode.
3207 --man check file parameters first whether they are man pages.
3208 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3209 choose display mode.
3210 --no-man disable man-page facility.
3211 --pager=program preset the paging program for tty mode.
3212 --pdf display in a PDF viewer.
3213 --pdf-viewer choose the viewer program for pdf mode.
3214 --ps display in a Postscript viewer.
3215 --ps-viewer choose the viewer program for ps mode.
3216 --shell specify shell under which to run this program.
3217 --text output in a text device without a pager.
3218 --tty display with a pager on text terminal even when in X.
3219 --www-viewer same as --html-viewer
3220 --x-viewer choose viewer program for x mode (X mode).
3221 --X-viewer same as "--xviewer".
3223 The usual X Windows toolkit options transformed into GNU long options
3224 --background=color, --bd=size, --bg=color, --bordercolor=color,
3225 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3226 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3227 --resolution=dpi, --rv, --title=text, --xrm=resource
3229 Long options of GNU "man"
3230 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3231 --local-file=name, --location, --manpath=dir1:dir2:...,
3232 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3235 eval "${return_ok}";
3239 ########################################################################
3240 # version ()
3242 # print version information to stderr
3244 version()
3246 func_check version = 0 "$@";
3247 echo2 "${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3248 # also display groff's version, but not the called subprograms
3249 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2;
3250 eval "${return_ok}";
3254 ########################################################################
3255 # warning (<string>)
3257 # Print warning to stderr
3259 warning()
3261 echo2 "warning: $*";
3265 ########################################################################
3266 # what_is (<filename>)
3268 # Interpret <filename> as a man page and display its `whatis'
3269 # information as a fragment written in the groff language.
3271 # Variable prefix: wi
3273 what_is()
3275 func_check what_is = 1 "$@";
3276 if is_not_file "$1";
3277 then
3278 error "what_is(): argument is not a readable file."
3280 wi_dot='^\.['"${_SPACE}${_TAB}"']*';
3281 cat <<EOF
3286 # grep the line containing `.TH' macro, if any
3287 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'TH /p
3288 d')";
3289 if obj wi_res is_not_empty;
3290 then # traditional man style
3291 # get the text between the first and the second `.SH' macro, by
3292 # - delete up to first .SH;
3293 # - of this, print everything up to next .SH, and delete the rest;
3294 # - of this, delete the final .SH line;
3295 cat_z "$1" | sed -e '1,/'"${wi_dot}"'SH/d' \
3296 | sed -e '1,/'"${wi_dot}"'SH/p
3297 d' \
3298 | sed -e '/'"${wi_dot}"'SH/d';
3299 eval ${_UNSET} wi_dot;
3300 eval ${_UNSET} wi_res;
3301 eval "${return_ok}";
3303 # grep the line containing `.Dd' macro, if any
3304 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'Dd /p
3305 d')";
3306 if obj wi_res is_not_empty;
3307 then # BSD doc style
3308 # get the text between the first and the second `.Nd' macro, by
3309 # - delete up to first .Nd;
3310 # - of this, print everything up to next .Nd, and delete the rest;
3311 # - of this, delete the final .Nd line;
3312 cat_z "$1" | sed -e '1,/'"${wi_dot}"'Nd/d' \
3313 | sed -e '1,/'"${wi_dot}"'Nd/p
3314 d' \
3315 | sed -e '/'"${wi_dot}"'Nd/d';
3316 eval ${_UNSET} wi_dot;
3317 eval ${_UNSET} wi_res;
3318 eval "${return_ok}";
3320 echo 'is not a man page.';
3321 eval ${_UNSET} wi_dot;
3322 eval ${_UNSET} wi_res;
3323 eval "${return_bad}";
3327 ########################################################################
3328 # where_is (<program>)
3330 # Output path of a program if in $PATH.
3332 # Arguments : >=1 (empty allowed)
3333 # more args are ignored, this allows to specify progs with arguments
3334 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3336 # Variable prefix: w
3338 where_is()
3340 func_check where_is '>=' 1 "$@";
3341 w_arg="$1";
3342 if obj w_arg is_empty;
3343 then
3344 eval ${_UNSET} w_arg;
3345 eval "${return_bad}";
3347 case "${w_arg}" in
3349 eval ${_UNSET} w_arg;
3350 eval ${_UNSET} w_file;
3351 if test -f "${w_arg}" && test -x "${w_arg}";
3352 then
3353 eval "${return_ok}";
3354 else
3355 eval "${return_bad}";
3358 esac;
3359 eval set x "$(path_split "${PATH}")";
3360 shift;
3361 for p
3363 case "$p" in
3364 */) w_file=${p}${w_arg}; ;;
3365 *) w_file=${p}/${w_arg}; ;;
3366 esac;
3367 if test -f "${w_file}" && test -x "${w_file}";
3368 then
3369 cat <<EOF
3370 ${w_file}
3372 eval ${_UNSET} w_arg;
3373 eval ${_UNSET} w_file;
3374 eval "${return_ok}";
3376 done;
3377 eval ${_UNSET} w_arg;
3378 eval ${_UNSET} w_file;
3379 eval "${return_bad}";
3383 ########################################################################
3384 # main* Functions
3385 ########################################################################
3387 # The main area contains the following parts:
3388 # - main_init(): initialize temporary files and set exit trap
3389 # - main_parse_MANOPT(): parse $MANOPT
3390 # - main_parse_args(): argument parsing
3391 # - main_set_mode (): determine the display mode
3392 # - main_do_fileargs(): process filespec arguments
3393 # - main_set_resources(): setup X resources
3394 # - main_display(): do the displaying
3395 # - main(): the main function that calls all main_*()
3397 # These parts are implemented as functions, being defined below in the
3398 # sequence they are called in the main() function.
3401 landmark '13: main_init()';
3402 #######################################################################
3403 # main_init ()
3405 # set exit trap and create temporary files
3407 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3409 # Variable prefix: mi
3411 main_init()
3413 func_check main_init = 0 "$@";
3414 # call clean_up() on any signal
3415 trap_set clean_up;
3417 # create temporary directory
3418 umask 0022;
3419 _TMP_DIR='';
3420 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3421 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
3423 mi_dir="$d";
3424 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
3425 obj mi_dir is_not_writable;
3426 then
3427 continue;
3430 case "${mi_dir}" in
3432 _TMP_DIR="${mi_dir}";
3435 _TMP_DIR="${mi_dir}"'/';
3437 esac;
3438 _TMP_DIR="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
3439 if obj _TMP_DIR is_existing;
3440 then
3441 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3442 if obj _TMP_DIR is_existing;
3443 then
3444 mi_tdir_="${_TMP_DIR}"_;
3445 mi_n=1;
3446 mi_tdir_n="${mi_tdir_}${mi_n}";
3447 while obj mi_tdir_n is_existing;
3449 eval rm -f -r "'${mi_tdir_n}'" >${_NULL_DEV} 2>&1;
3450 if obj mi_tdir_n is_existing;
3451 then
3452 # directory could not be removed
3453 mi_n="$(expr "${mi_n}" + 1)";
3454 mi_tdir_n="${mi_tdir_}${mi_n}";
3455 continue;
3457 done;
3458 _TMP_DIR="${mi_tdir_n}";
3461 eval mkdir "${_TMP_DIR}";
3462 if is_not_equal "$?" 0;
3463 then
3464 if obj _TMP_DIR is_existing;
3465 then
3466 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3468 _TMP_DIR='';
3469 continue;
3471 if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable;
3472 then
3473 # $_TMP_DIR can now be used as temporary directory
3474 break;
3476 if obj _TMP_DIR is_existing;
3477 then
3478 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3480 _TMP_DIR='';
3481 continue;
3482 done;
3483 if obj _TMP_DIR is_empty;
3484 then
3485 error "main_init: \
3486 Couldn't create a directory for storing temporary files.";
3489 _TMP_CAT="$(tmp_create groffer_cat)";
3490 _TMP_STDIN="$(tmp_create groffer_input)";
3492 # groffer configuration files
3493 # for f in $_CONF_FILES
3494 for f in $(eval set x ${_CONF_FILES}; shift; echo "$@")
3496 mi_file="$f";
3497 if obj mi_file is_file;
3498 then
3499 echo '_groffer_opt=""' >>${_TMP_CAT};
3500 # collect the lines starting with a minus
3501 cat "$mi_file" | sed -e '
3502 /^[ ]*#/d
3503 s/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"/
3504 ' >>${_TMP_CAT};
3505 # prepend the collected information to $GROFFER_OPT
3506 echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
3508 done;
3509 eval . "${_TMP_CAT}";
3510 _TMP_CAT="$(tmp_create groffer_cat)";
3512 eval ${_UNSET} mi_dir;
3513 eval ${_UNSET} mi_file;
3514 eval ${_UNSET} mi_n;
3515 eval ${_UNSET} mi_tdir_;
3516 eval ${_UNSET} mi_tdir_n;
3517 eval "${return_ok}";
3518 } # main_init()
3521 landmark '14: main_parse_MANOPT()';
3522 ########################################################################
3523 # main_parse_MANOPT ()
3525 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3526 # string; found man arguments can be overwritten by the command line.
3528 # Globals:
3529 # in: $MANOPT, $_OPTS_MANOPT_*
3530 # out: $_MANOPT_*
3531 # in/out: $GROFFER_OPT
3533 # Variable prefix: mpm
3535 main_parse_MANOPT()
3537 func_check main_parse_MANOPT = 0 "$@";
3538 mpm_list='';
3539 if obj MANOPT is_not_empty;
3540 then
3541 MANOPT="$(echo x"${MANOPT}" | sed -e 's/^x'"${_SPACE}${_SPACE}"'*//')";
3543 if obj MANOPT is_empty;
3544 then
3545 eval ${_UNSET} mpm_list;
3546 eval ${_UNSET} mpm_opt;
3547 eval "${return_ok}";
3549 # add arguments in $MANOPT by mapping them to groffer options
3550 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3551 shift;
3552 until test "$#" -le 0 || is_equal "$1" '--';
3554 mpm_opt="$1";
3555 shift;
3556 case "${mpm_opt}" in
3557 -7|--ascii)
3558 list_append mpm_list '--ascii';
3560 -a|--all)
3561 list_append mpm_list '--all';
3563 -c|--catman)
3564 do_nothing;
3565 shift;
3567 -d|--debug)
3568 list_append mpm_list '--debug';
3570 -D|--default)
3571 # undo all man options so far
3572 mpm_list='';
3574 -e|--extension)
3575 list_append mpm_list '--extension';
3576 shift;
3578 -f|--whatis)
3579 list_append mpm_list '--whatis';
3580 shift;
3582 -h|--help)
3583 do_nothing;
3584 shift;
3586 -k|--apropos)
3587 # groffer's --apropos takes an argument, but man's does not, so
3588 do_nothing;
3589 shift;
3591 -l|--local-file)
3592 list_append mpm_list '--local-file';
3594 -L|--locale)
3595 list_append mpm_list '--locale' "$1";
3596 shift;
3598 -m|--systems)
3599 list_append mpm_list '--systems' "$1";
3600 shift;
3602 -M|--manpath)
3603 list_append mpm_list '--manpath' "$1";
3604 shift;
3606 -p|--preprocessor)
3607 do_nothing;
3608 shift;
3610 -P|--pager|--tty-viewer)
3611 list_append mpm_list '--pager' "$1";
3612 shift;
3614 -r|--prompt)
3615 do_nothing;
3616 shift;
3618 -S|--sections)
3619 list_append mpm_list '--sections' "$1";
3620 shift;
3622 -t|--troff)
3623 do_nothing;
3624 shift;
3626 -T|--device)
3627 list_append mpm_list '-T' "$1";
3628 shift;
3630 -u|--update)
3631 do_nothing;
3632 shift;
3634 -V|--version)
3635 do_nothing;
3637 -w|--where|--location)
3638 list_append mpm_list '--location';
3640 -Z|--ditroff)
3641 list_append mpm_list '-Z' "$1";
3642 shift;
3644 # ignore all other options
3645 esac;
3646 done;
3647 # append the 2 lists in $mpm_list and $GROFFER_OPT to $GROFFER_OPT
3648 if obj GROFFER_OPT is_empty;
3649 then
3650 GROFFER_OPT="${mpm_list}";
3651 elif obj mpm_list is_not_empty;
3652 then
3653 GROFFER_OPT="${mpm_list} ${GROFFER_OPT}";
3655 eval ${_UNSET} mpm_list;
3656 eval ${_UNSET} mpm_opt;
3657 eval "${return_ok}";
3658 } # main_parse_MANOPT()
3661 landmark '15: main_parse_args()';
3662 ########################################################################
3663 # main_parse_args (<command_line_args>*)
3665 # Parse arguments; process options and filespec parameters
3667 # Arguments: pass the command line arguments unaltered.
3668 # Globals:
3669 # in: $_OPTS_*
3670 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3672 # Variable prefix: mpa
3674 main_parse_args()
3676 func_check main_parse_args '>=' 0 "$@";
3678 eval set x "${GROFFER_OPT}" '"$@"';
3679 shift;
3681 eval set x "$(list_from_cmdline _OPTS_CMDLINE "$@")";
3682 shift;
3684 # By the call of `eval', unnecessary quoting was removed. So the
3685 # positional shell parameters ($1, $2, ...) are now guaranteed to
3686 # represent an option or an argument to the previous option, if any;
3687 # then a `--' argument for separating options and
3688 # parameters; followed by the filespec parameters if any.
3690 # Note, the existence of arguments to options has already been checked.
3691 # So a check for `$#' or `--' should not be done for arguments.
3693 until test "$#" -le 0 || is_equal "$1" '--';
3695 mpa_opt="$1"; # $mpa_opt is fed into the option handler
3696 shift;
3697 case "${mpa_opt}" in
3698 -h|--help)
3699 usage;
3700 leave;
3702 -Q|--source) # output source code (`Quellcode').
3703 _OPT_MODE='source';
3705 -T|--device|--troff-device) # device; arg
3706 _OPT_DEVICE="$1";
3707 _check_device_with_mode;
3708 shift;
3710 -v|--version)
3711 version;
3712 leave;
3715 _OPT_V='yes';
3717 -Z|--ditroff|--intermediate-output) # groff intermediate output
3718 _OPT_Z='yes';
3721 _OPT_MODE=X;
3724 # delete leading `-'
3725 mpa_optchar="$(echo x"${mpa_opt}" | sed -e 's/^x-//')";
3726 if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}";
3727 then
3728 list_append _ADDOPTS_GROFF "${mpa_opt}";
3729 elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}";
3730 then
3731 list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
3732 shift;
3733 else
3734 error "main_parse_args(): Unknown option : \`$1'";
3737 --all)
3738 _OPT_ALL="yes";
3740 --apropos) # run `apropos'
3741 apropos_run "$1";
3742 mpa_code="$?";
3743 clean_up;
3744 exit "${mpa_code}";
3746 --apropos-data) # run `apropos' for data sections
3747 apropos_run "$1" | grep '^[^(]*([457][^)]*)';
3748 mpa_code="$?";
3749 clean_up;
3750 exit "${mpa_code}";
3752 --apropos-devel) # run `apropos' for development sections
3753 apropos_run "$1" | grep '^[^(]*([239][^)]*)';
3754 mpa_code="$?";
3755 clean_up;
3756 exit "${mpa_code}";
3758 --apropos-progs) # run `apropos' for program sections
3759 apropos_run "$1" | grep '^[^(]*([168][^)]*)';
3760 mpa_code="$?";
3761 clean_up;
3762 exit "${mpa_code}";
3764 --ascii)
3765 list_append _ADDOPTS_GROFF '-mtty-char';
3766 if obj _OPT_MODE is_empty;
3767 then
3768 _OPT_MODE='text';
3771 --auto) # the default automatic mode
3772 _OPT_MODE='';
3774 --bd) # border color for viewers, arg;
3775 _OPT_BD="$1";
3776 shift;
3778 --bg|--backgroud) # background color for viewers, arg;
3779 _OPT_BG="$1";
3780 shift;
3782 --bw) # border width for viewers, arg;
3783 _OPT_BW="$1";
3784 shift;
3786 --default) # reset variables to default
3787 reset;
3789 --default-modes) # sequence of modes in auto mode; arg
3790 _OPT_DEFAULT_MODES="$1";
3791 shift;
3793 --debug) # only for development
3794 _OPT_DEBUG='yes';
3796 --display) # set X display, arg
3797 _OPT_DISPLAY="$1";
3798 shift;
3800 --dvi)
3801 _OPT_MODE='dvi';
3803 --dvi-viewer) # viewer program for dvi mode; arg
3804 _OPT_VIEWER_DVI="$1";
3805 shift;
3807 --extension) # the extension for man pages, arg
3808 _OPT_EXTENSION="$1";
3809 shift;
3811 --fg|--foreground) # foreground color for viewers, arg;
3812 _OPT_FG="$1";
3813 shift;
3815 --fn|--font) # set font for viewers, arg;
3816 _OPT_FN="$1";
3817 shift;
3819 --geometry) # window geometry for viewers, arg;
3820 _OPT_GEOMETRY="$1";
3821 shift;
3823 --groff)
3824 _OPT_MODE='groff';
3826 --html|--www) # display with web browser
3827 _OPT_MODE=html;
3829 --html-viewer|--www-viewer) # viewer program for html mode; arg
3830 _OPT_VIEWER_HTML="$1";
3831 shift;
3833 --iconic) # start viewers as icons
3834 _OPT_ICONIC='yes';
3836 --locale) # set language for man pages, arg
3837 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3838 _OPT_LANG="$1";
3839 shift;
3841 --local-file) # force local files; same as `--no-man'
3842 _MAN_FORCE='no';
3843 _MAN_ENABLE='no';
3845 --location|--where) # print file locations to stderr
3846 _OPT_LOCATION='yes';
3848 --man) # force all file params to be man pages
3849 _MAN_ENABLE='yes';
3850 _MAN_FORCE='yes';
3852 --manpath) # specify search path for man pages, arg
3853 # arg is colon-separated list of directories
3854 _OPT_MANPATH="$1";
3855 shift;
3857 --mode) # display mode
3858 mpa_arg="$1";
3859 shift;
3860 case "${mpa_arg}" in
3861 auto|'') # search mode automatically among default
3862 _OPT_MODE='';
3864 groff) # pass input to plain groff
3865 _OPT_MODE='groff';
3867 html|www) # display with a web browser
3868 _OPT_MODE='html';
3870 dvi) # display with xdvi viewer
3871 _OPT_MODE='dvi';
3873 pdf) # display with PDF viewer
3874 _OPT_MODE='pdf';
3876 ps) # display with Postscript viewer
3877 _OPT_MODE='ps';
3879 text) # output on terminal
3880 _OPT_MODE='text';
3882 tty) # output on terminal
3883 _OPT_MODE='tty';
3885 X|x) # output on X roff viewer
3886 _OPT_MODE='x';
3888 Q|source) # display source code
3889 _OPT_MODE="source";
3892 error "main_parse_args(): unknown mode ${mpa_arg}";
3894 esac;
3896 --no-location) # disable former call to `--location'
3897 _OPT_LOCATION='yes';
3899 --no-man) # disable search for man pages
3900 # the same as --local-file
3901 _MAN_FORCE="no";
3902 _MAN_ENABLE="no";
3904 --pager) # set paging program for tty mode, arg
3905 _OPT_PAGER="$1";
3906 shift;
3908 --pdf)
3909 _OPT_MODE='pdf';
3911 --pdf-viewer) # viewer program for ps mode; arg
3912 _OPT_VIEWER_PDF="$1";
3913 shift;
3915 --ps)
3916 _OPT_MODE='ps';
3918 --ps-viewer) # viewer program for ps mode; arg
3919 _OPT_VIEWER_PS="$1";
3920 shift;
3922 --resolution) # set resolution for X devices, arg
3923 mpa_arg="$1";
3924 shift;
3925 case "${mpa_arg}" in
3926 75|75dpi)
3927 mpa_dpi=75;
3929 100|100dpi)
3930 mpa_dpi=100;
3933 error "main_parse_args(): \
3934 only resoutions of 75 or 100 dpi are supported";
3936 esac;
3937 _OPT_RESOLUTION="${mpa_dpi}";
3939 --rv)
3940 _OPT_RV='yes';
3942 --sections) # specify sections for man pages, arg
3943 # arg is colon-separated list of section names
3944 _OPT_SECTIONS="$1";
3945 shift;
3947 --shell)
3948 # already done during the first run; so ignore the argument
3949 shift;
3951 --systems) # man pages for different OS's, arg
3952 # argument is a comma-separated list
3953 _OPT_SYSTEMS="$1";
3954 shift;
3956 --text) # text mode without pager
3957 _OPT_MODE=text;
3959 --title) # title for X viewers; arg
3960 _OPT_TITLE="$1";
3961 shift;
3963 --tty) # tty mode, text with pager
3964 _OPT_MODE=tty;
3966 --text-device|--tty-device) # device for tty mode; arg
3967 _OPT_TEXT_DEVICE="$1";
3968 shift;
3970 --whatis)
3971 _OPT_WHATIS='yes';
3973 --X|--x)
3974 _OPT_MODE=x;
3976 --xrm) # pass X resource string, arg;
3977 list_append _OPT_XRM "$1";
3978 shift;
3980 --x-viewer|--X-viewer) # viewer program for x mode; arg
3981 _OPT_VIEWER_X="$1";
3982 shift;
3985 error 'main_parse_args(): error on argument parsing : '"\`$*'";
3987 esac;
3988 done;
3989 shift; # remove `--' argument
3991 if obj _DEBUG is_not_yes;
3992 then
3993 if obj _OPT_DEBUG is_yes;
3994 then
3995 _DEBUG='yes';
3996 _DEBUG_LM='yes';
3997 _DEBUG_KEEP_FILES='yes';
4001 # Remaining arguments are file names (filespecs).
4002 # Save them to list $_FILEARGS
4003 if is_equal "$#" 0;
4004 then # use "-" for standard input
4005 set x '-';
4006 shift;
4008 _FILEARGS='';
4009 list_append _FILEARGS "$@";
4010 if list_has _FILEARGS '-';
4011 then
4012 save_stdin;
4014 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4015 eval ${_UNSET} mpa_arg;
4016 eval ${_UNSET} mpa_code;
4017 eval ${_UNSET} mpa_dpi;
4018 eval ${_UNSET} mpa_opt;
4019 eval ${_UNSET} mpa_optchar;
4020 eval "${return_ok}";
4021 } # main_parse_args()
4024 # Called from main_parse_args() because double `case' is not possible.
4025 # Globals: $_OPT_DEVICE, $_OPT_MODE
4026 _check_device_with_mode()
4028 func_check _check_device_with_mode = 0 "$@";
4029 case "${_OPT_DEVICE}" in
4030 dvi)
4031 _OPT_MODE=dvi;
4032 eval "${return_ok}";
4034 html)
4035 _OPT_MODE=html;
4036 eval "${return_ok}";
4038 lbp|lj4)
4039 _OPT_MODE=groff;
4040 eval "${return_ok}";
4043 _OPT_MODE=ps;
4044 eval "${return_ok}";
4046 ascii|cp1047|latin1|utf8)
4047 if obj _OPT_MODE is_not_equal text;
4048 then
4049 _OPT_MODE=tty; # default text mode
4051 eval "${return_ok}";
4054 _OPT_MODE=x;
4055 eval "${return_ok}";
4057 *) # unknown device, go to groff mode
4058 _OPT_MODE=groff;
4059 eval "${return_ok}";
4061 esac;
4062 eval "${return_error}";
4063 } # _check_device_with_mode() of main_parse_args()
4066 landmark '16: main_set_mode()';
4067 ########################################################################
4068 # main_set_mode ()
4070 # Determine the display mode.
4072 # Globals:
4073 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4074 # out: $_DISPLAY_MODE
4076 # Variable prefix: msm
4078 main_set_mode()
4080 func_check main_set_mode = 0 "$@";
4082 # handle apropos
4083 if obj _OPT_APROPOS is_not_empty;
4084 then
4085 apropos "${_OPT_APROPOS}";
4086 msm_code="$?";
4087 clean_up;
4088 exit "${msm_code}";
4090 if obj _OPT_APROPOS_DATA is_not_empty;
4091 then
4092 apropos "$@" | grep '^[^(]*([457])';
4093 msm_code="$?";
4094 clean_up;
4095 exit "${msm_code}";
4097 if obj _OPT_APROPOS_DEVEL is_not_empty;
4098 then
4099 apropos "$@" | grep '^[^(]*([239])';
4100 msm_code="$?";
4101 clean_up;
4102 exit "${msm_code}";
4104 if obj _OPT_APROPOS_PROGS is_not_empty;
4105 then
4106 apropos "$@" | grep '^[^(]*([168])';
4107 msm_code="$?";
4108 clean_up;
4109 exit "${msm_code}";
4112 # set display
4113 if obj _OPT_DISPLAY is_not_empty;
4114 then
4115 DISPLAY="${_OPT_DISPLAY}";
4118 if obj _OPT_V is_yes;
4119 then
4120 list_append _ADDOPTS_GROFF '-V';
4122 if obj _OPT_Z is_yes;
4123 then
4124 _DISPLAY_MODE='groff';
4125 list_append _ADDOPTS_GROFF '-Z';
4127 if obj _OPT_MODE is_equal 'groff';
4128 then
4129 _DISPLAY_MODE='groff';
4131 if obj _DISPLAY_MODE is_equal 'groff';
4132 then
4133 eval ${_UNSET} msm_code;
4134 eval ${_UNSET} msm_modes;
4135 eval ${_UNSET} msm_viewer;
4136 eval ${_UNSET} msm_viewers;
4137 eval "${return_ok}";
4140 if obj _OPT_MODE is_equal 'source';
4141 then
4142 _DISPLAY_MODE='source';
4143 eval ${_UNSET} msm_code;
4144 eval ${_UNSET} msm_modes;
4145 eval ${_UNSET} msm_viewer;
4146 eval ${_UNSET} msm_viewers;
4147 eval "${return_ok}";
4150 case "${_OPT_MODE}" in
4151 '') # automatic mode
4152 case "${_OPT_DEVICE}" in
4154 if obj DISPLAY is_empty;
4155 then
4156 error "main_set_mode(): \
4157 no X display found for device ${_OPT_DEVICE}";
4159 _DISPLAY_MODE='x';
4160 eval ${_UNSET} msm_code;
4161 eval ${_UNSET} msm_modes;
4162 eval ${_UNSET} msm_viewer;
4163 eval ${_UNSET} msm_viewers;
4164 eval "${return_ok}";
4166 ascii|cp1047|latin1|utf8)
4167 if obj _DISPLAY_MODE is_not_equal 'text';
4168 then
4169 _DISPLAY_MODE='tty';
4171 eval ${_UNSET} msm_code;
4172 eval ${_UNSET} msm_modes;
4173 eval ${_UNSET} msm_viewer;
4174 eval ${_UNSET} msm_viewers;
4175 eval "${return_ok}";
4177 esac;
4178 if obj DISPLAY is_empty;
4179 then
4180 _DISPLAY_MODE='tty';
4181 eval ${_UNSET} msm_code;
4182 eval ${_UNSET} msm_modes;
4183 eval ${_UNSET} msm_viewer;
4184 eval ${_UNSET} msm_viewers;
4185 eval "${return_ok}";
4188 if obj _OPT_DEFAULT_MODES is_empty;
4189 then
4190 msm_modes="${_DEFAULT_MODES}";
4191 else
4192 msm_modes="${_OPT_DEFAULT_MODES}";
4195 text)
4196 _DISPLAY_MODE='text';
4197 eval ${_UNSET} msm_code;
4198 eval ${_UNSET} msm_modes;
4199 eval ${_UNSET} msm_viewer;
4200 eval ${_UNSET} msm_viewers;
4201 eval "${return_ok}";
4203 tty)
4204 _DISPLAY_MODE='tty';
4205 eval ${_UNSET} msm_code;
4206 eval ${_UNSET} msm_modes;
4207 eval ${_UNSET} msm_viewer;
4208 eval ${_UNSET} msm_viewers;
4209 eval "${return_ok}";
4211 *) # display mode was given
4212 if obj DISPLAY is_empty;
4213 then
4214 error "main_set_mode(): \
4215 you must be in X Window for ${_OPT_MODE} mode.";
4217 msm_modes="${_OPT_MODE}";
4219 esac;
4221 # only viewer modes are left
4222 eval set x "$(list_from_split "${msm_modes}" ',')";
4223 shift;
4224 while test "$#" -gt 0;
4226 m="$1";
4227 shift;
4228 case "$m" in
4229 text)
4230 _DISPLAY_MODE='text';
4231 eval ${_UNSET} msm_code;
4232 eval ${_UNSET} msm_modes;
4233 eval ${_UNSET} msm_viewer;
4234 eval ${_UNSET} msm_viewers;
4235 eval "${return_ok}";
4237 tty)
4238 _DISPLAY_MODE='tty';
4239 eval ${_UNSET} msm_code;
4240 eval ${_UNSET} msm_modes;
4241 eval ${_UNSET} msm_viewer;
4242 eval ${_UNSET} msm_viewers;
4243 eval "${return_ok}";
4246 if obj _OPT_VIEWER_X is_not_empty;
4247 then
4248 msm_viewers="${_OPT_VIEWER_X}";
4249 else
4250 msm_viewers="${_VIEWER_X}";
4252 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4253 if is_not_equal "$?" 0;
4254 then
4255 continue;
4257 _DISPLAY_PROG="${msm_viewer}";
4258 _DISPLAY_MODE='x';
4259 eval ${_UNSET} msm_code;
4260 eval ${_UNSET} msm_modes;
4261 eval ${_UNSET} msm_viewer;
4262 eval ${_UNSET} msm_viewers;
4263 eval "${return_ok}";
4266 _DISPLAY_MODE='X';
4267 eval ${_UNSET} msm_code;
4268 eval ${_UNSET} msm_modes;
4269 eval ${_UNSET} msm_viewer;
4270 eval ${_UNSET} msm_viewers;
4271 eval "${return_ok}";
4273 dvi)
4274 if obj _OPT_VIEWER_DVI is_not_empty;
4275 then
4276 msm_viewers="${_OPT_VIEWER_DVI}";
4277 else
4278 msm_viewers="${_VIEWER_DVI}";
4280 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4281 if is_not_equal "$?" 0;
4282 then
4283 continue;
4285 _DISPLAY_PROG="${msm_viewer}";
4286 _DISPLAY_MODE="dvi";
4287 eval ${_UNSET} msm_code;
4288 eval ${_UNSET} msm_modes;
4289 eval ${_UNSET} msm_viewer;
4290 eval ${_UNSET} msm_viewers;
4291 eval "${return_ok}";
4293 pdf)
4294 if obj _OPT_VIEWER_PDF is_not_empty;
4295 then
4296 msm_viewers="${_OPT_VIEWER_PDF}";
4297 else
4298 msm_viewers="${_VIEWER_PDF}";
4300 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4301 if is_not_equal "$?" 0;
4302 then
4303 continue;
4305 _DISPLAY_PROG="${msm_viewer}";
4306 _DISPLAY_MODE="pdf";
4307 eval ${_UNSET} msm_code;
4308 eval ${_UNSET} msm_modes;
4309 eval ${_UNSET} msm_viewer;
4310 eval ${_UNSET} msm_viewers;
4311 eval "${return_ok}";
4314 if obj _OPT_VIEWER_PS is_not_empty;
4315 then
4316 msm_viewers="${_OPT_VIEWER_PS}";
4317 else
4318 msm_viewers="${_VIEWER_PS}";
4320 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4321 if is_not_equal "$?" 0;
4322 then
4323 continue;
4325 _DISPLAY_PROG="${msm_viewer}";
4326 _DISPLAY_MODE="ps";
4327 eval ${_UNSET} msm_code;
4328 eval ${_UNSET} msm_modes;
4329 eval ${_UNSET} msm_viewer;
4330 eval ${_UNSET} msm_viewers;
4331 eval "${return_ok}";
4333 html)
4334 if obj _OPT_VIEWER_HTML is_not_empty;
4335 then
4336 msm_viewers="${_OPT_VIEWER_HTML}";
4337 else
4338 msm_viewers="${_VIEWER_HTML}";
4340 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4341 if is_not_equal "$?" 0;
4342 then
4343 continue;
4345 _DISPLAY_PROG="${msm_viewer}";
4346 _DISPLAY_MODE=html;
4347 eval ${_UNSET} msm_code;
4348 eval ${_UNSET} msm_modes;
4349 eval ${_UNSET} msm_viewer;
4350 eval ${_UNSET} msm_viewers;
4351 eval "${return_ok}";
4353 esac;
4354 done;
4355 eval ${_UNSET} msm_code;
4356 eval ${_UNSET} msm_modes;
4357 eval ${_UNSET} msm_viewer;
4358 eval ${_UNSET} msm_viewers;
4359 error "main_set_mode(): no suitable display mode found.";
4360 } # main_set_mode()
4363 # _get_first_prog (<proglist>)
4365 # Retrieve first argument that represents an existing program in $PATH.
4366 # Local function for main_set_mode().
4368 # Arguments: 1; a comma-separated list of commands (with options),
4369 # like $_VIEWER_*.
4371 # Return : `1' if none found, `0' if found.
4372 # Output : the argument that succeded.
4374 # Variable prefix: _gfp
4376 _get_first_prog()
4378 if is_equal "$#" 0;
4379 then
4380 error "_get_first_prog() needs 1 argument.";
4382 if is_empty "$1";
4383 then
4384 return "${_BAD}";
4386 eval set x "$(list_from_split "$1" ',')";
4387 shift;
4388 for i
4390 _gfp_i="$i";
4391 if obj _gfp_i is_empty;
4392 then
4393 continue;
4395 if eval is_prog "$(get_first_essential ${_gfp_i})";
4396 then
4397 cat <<EOF
4398 ${_gfp_i}
4400 eval ${_UNSET} _gfp_i;
4401 return "${_GOOD}";
4403 done;
4404 eval ${_UNSET} _gfp_i;
4405 return "${_BAD}";
4406 } # _get_first_prog() of main_set_mode()
4409 landmark '17: main_do_fileargs()';
4410 #######################################################################
4411 # main_do_fileargs ()
4413 # Process filespec arguments in $_FILEARGS.
4415 # Globals:
4416 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
4418 # Variable prefix: mdfa
4420 main_do_fileargs()
4422 func_check main_do_fileargs = 0 "$@";
4423 mdfa_exitcode="${_BAD}";
4424 eval set x "${_FILEARGS}";
4425 shift;
4426 eval ${_UNSET} _FILEARGS;
4427 # temporary storage of all input to $_TMP_CAT
4428 while test "$#" -ge 2;
4430 # test for `s name' arguments, with `s' a 1-char standard section
4431 mdfa_filespec="$1";
4432 shift;
4433 case "${mdfa_filespec}" in
4435 continue;
4437 '-')
4438 if register_file '-';
4439 then
4440 mdfa_exitcode="${_GOOD}";
4442 continue;
4445 if list_has_not _MAN_AUTO_SEC "${mdfa_filespec}";
4446 then
4447 if do_filearg "${mdfa_filespec}";
4448 then
4449 mdfa_exitcode="${_GOOD}";
4451 continue;
4453 mdfa_name="$1";
4454 case "${mdfa_name}" in
4455 */*|man:*|*\(*\)|*."${mdfa_filespec}")
4456 if do_filearg "${mdfa_filespec}";
4457 then
4458 mdfa_exitcode="${_GOOD}";
4460 continue;
4462 esac;
4463 if do_filearg "man:${mdfa_name}(${mdfa_filespec})";
4464 then
4465 mdfa_exitcode="${_GOOD}";
4466 shift;
4467 continue;
4468 else
4469 if do_filearg "${mdfa_filespec}";
4470 then
4471 mdfa_exitcode="${_GOOD}";
4473 continue;
4477 if do_filearg "${mdfa_filespec}";
4478 then
4479 mdfa_exitcode="${_GOOD}";
4481 continue;
4483 esac;
4484 done; # end of `s name' test
4485 while test "$#" -gt 0;
4487 mdfa_filespec="$1";
4488 shift;
4489 if do_filearg "${mdfa_filespec}";
4490 then
4491 mdfa_exitcode="${_GOOD}";
4493 done;
4494 if obj _DEBUG_KEEP_FILES is_not_yes;
4495 then
4496 rm -f "${_TMP_STDIN}";
4498 if is_equal "${mdfa_exitcode}" "${_BAD}";
4499 then
4500 eval ${_UNSET} mdfa_exitcode;
4501 eval ${_UNSET} mdfa_filespec;
4502 eval ${_UNSET} mdfa_name;
4503 eval "${return_bad}";
4505 eval ${_UNSET} mdfa_exitcode;
4506 eval ${_UNSET} mdfa_filespec;
4507 eval ${_UNSET} mdfa_name;
4508 eval "${return_ok}";
4509 } # main_do_fileargs()
4512 landmark '18: main_set_resources()';
4513 ########################################################################
4514 # main_set_resources ()
4516 # Determine options for setting X resources with $_DISPLAY_PROG.
4518 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4520 # Variable prefix: msr
4522 main_set_resources()
4524 func_check main_set_resources = 0 "$@";
4525 # $msr_prog viewer program
4526 # $msr_rl resource list
4527 msr_title="$(get_first_essential \
4528 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4529 _OUTPUT_FILE_NAME='';
4530 eval set x "${msr_title}";
4531 shift;
4532 until is_equal "$#" 0;
4534 msr_n="$1";
4535 case "${msr_n}" in
4537 continue;
4540 msr_n="$(echo x"$1" | sed -e 's/^x,,*//')";
4542 esac
4543 if obj msr_n is_empty;
4544 then
4545 continue;
4547 if obj _OUTPUT_FILE_NAME is_not_empty;
4548 then
4549 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
4551 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
4552 shift;
4553 done;
4554 case "${_OUTPUT_FILE_NAME}" in
4556 _OUTPUT_FILE_NAME='-';
4559 error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
4561 esac;
4562 _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4564 if obj _DISPLAY_PROG is_empty;
4565 then # for example, for groff mode
4566 _DISPLAY_ARGS='';
4567 eval ${_UNSET} msr_n;
4568 eval ${_UNSET} msr_prog;
4569 eval ${_UNSET} msr_rl;
4570 eval ${_UNSET} msr_title;
4571 eval "${return_ok}";
4574 eval set x "${_DISPLAY_PROG}";
4575 shift;
4576 msr_prog="$(base_name "$1")";
4577 msr_rl='';
4578 if obj _OPT_BD is_not_empty;
4579 then
4580 case "${msr_prog}" in
4581 ghostview|gv|gxditview|xditview|xdvi)
4582 list_append msr_rl '-bd' "${_OPT_BD}";
4584 esac;
4586 if obj _OPT_BG is_not_empty;
4587 then
4588 case "${msr_prog}" in
4589 ghostview|gv|gxditview|xditview|xdvi)
4590 list_append msr_rl '-bg' "${_OPT_BG}";
4592 xpdf)
4593 list_append msr_rl '-papercolor' "${_OPT_BG}";
4595 esac;
4597 if obj _OPT_BW is_not_empty;
4598 then
4599 case "${msr_prog}" in
4600 ghostview|gv|gxditview|xditview|xdvi)
4601 _list_append msr_rl '-bw' "${_OPT_BW}";
4603 esac;
4605 if obj _OPT_FG is_not_empty;
4606 then
4607 case "${msr_prog}" in
4608 ghostview|gv|gxditview|xditview|xdvi)
4609 list_append msr_rl '-fg' "${_OPT_FG}";
4611 esac;
4613 if is_not_empty "${_OPT_FN}";
4614 then
4615 case "${msr_prog}" in
4616 ghostview|gv|gxditview|xditview|xdvi)
4617 list_append msr_rl '-fn' "${_OPT_FN}";
4619 esac;
4621 if is_not_empty "${_OPT_GEOMETRY}";
4622 then
4623 case "${msr_prog}" in
4624 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4625 list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
4627 esac;
4629 if is_empty "${_OPT_RESOLUTION}";
4630 then
4631 _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
4632 case "${msr_prog}" in
4633 gxditview|xditview)
4634 list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
4636 xpdf)
4637 case "${_DEFAULT_RESOLUTION}" in
4639 # 72dpi is '100'
4640 list_append msr_rl '-z' '104';
4642 100)
4643 list_append msr_rl '-z' '139';
4645 esac;
4647 esac;
4648 else
4649 case "${msr_prog}" in
4650 ghostview|gv|gxditview|xditview|xdvi)
4651 list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
4653 xpdf)
4654 case "${_OPT_RESOLUTION}" in
4656 list_append msr_rl '-z' '104';
4657 # '100' corresponds to 72dpi
4659 100)
4660 list_append msr_rl '-z' '139';
4662 esac;
4664 esac;
4666 if is_yes "${_OPT_ICONIC}";
4667 then
4668 case "${msr_prog}" in
4669 ghostview|gv|gxditview|xditview|xdvi)
4670 list_append msr_rl '-iconic';
4672 esac;
4674 if is_yes "${_OPT_RV}";
4675 then
4676 case "${msr_prog}" in
4677 ghostview|gv|gxditview|xditview|xdvi)
4678 list_append msr_rl '-rv';
4680 esac;
4682 if is_not_empty "${_OPT_XRM}";
4683 then
4684 case "${msr_prog}" in
4685 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4686 eval set x "${_OPT_XRM}";
4687 shift;
4688 for i
4690 list_append msr_rl '-xrm' "$i";
4691 done;
4693 esac;
4695 if is_not_empty "${msr_title}";
4696 then
4697 case "${msr_prog}" in
4698 gxditview|xditview)
4699 list_append msr_rl '-title' "${msr_title}";
4701 esac;
4703 _DISPLAY_ARGS="${msr_rl}";
4704 eval ${_UNSET} msr_n;
4705 eval ${_UNSET} msr_prog;
4706 eval ${_UNSET} msr_rl;
4707 eval ${_UNSET} msr_title;
4708 eval "${return_ok}";
4709 } # main_set_resources
4712 landmark '19: main_display()';
4713 ########################################################################
4714 # main_display ()
4716 # Do the actual display of the whole thing.
4718 # Globals:
4719 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4720 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4721 # $_REGISTERED_TITLE, $_TMP_CAT,
4722 # $_OPT_PAGER $PAGER, $_MANOPT_PAGER,
4723 # $_OUTPUT_FILE_NAME
4725 # Variable prefix: md
4727 main_display()
4729 func_check main_display = 0 "$@";
4731 export md_addopts;
4732 export md_groggy;
4733 export md_modefile;
4735 if obj _TMP_CAT is_non_empty_file;
4736 then
4737 md_modefile="${_OUTPUT_FILE_NAME}";
4738 else
4739 clean_up;
4740 echo2 'groffer: empty input.';
4741 eval ${_UNSET} md_modefile;
4742 eval "${return_ok}";
4744 case "${_DISPLAY_MODE}" in
4745 groff)
4746 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4747 if obj _OPT_DEVICE is_not_empty;
4748 then
4749 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4751 md_groggy="$(tmp_cat | eval grog "${md_options}")";
4752 trap_clean;
4753 if obj _OPT_V is_yes;
4754 then
4755 echo "File: ${md_modefile}";
4756 echo "Mode: ${_DISPLAY_MODE}";
4757 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4758 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4759 clean_up;
4760 else
4761 # start a new shell program to get another process ID.
4762 /bin/sh -c '
4763 set -e;
4764 test -f "${md_modefile}" && rm -f "${md_modefile}";
4765 mv "${_TMP_CAT}" "${md_modefile}";
4766 cat "${md_modefile}" | \
4768 clean_up()
4770 if test -d "${_TMP_DIR}";
4771 then
4772 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
4775 trap clean_up 0 2>${_NULL_DEV} || :;
4776 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4777 ) &'
4780 text|tty)
4781 case "${_OPT_DEVICE}" in
4783 md_device="$(get_first_essential \
4784 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4786 ascii|cp1047|latin1|utf8)
4787 md_device="${_OPT_DEVICE}";
4790 warning "main_display(): \
4791 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4793 esac;
4794 md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4795 md_groggy="$(tmp_cat | grog -T${md_device})";
4796 if obj _DISPLAY_MODE is_equal 'text';
4797 then
4798 if obj _OPT_V is_yes;
4799 then
4800 echo "File: ${md_modefile}";
4801 echo "Mode: ${_DISPLAY_MODE}";
4802 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4803 eval "${md_groggy}" "${md_addopts}";
4804 else
4805 tmp_cat | eval "${md_groggy}" "${md_addopts}";
4807 else
4808 md_pager='';
4809 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4810 'less -r -R' 'more' 'pager' 'cat'
4812 md_p="$p";
4813 if eval is_prog ${md_p};
4814 then # no "" for is_prog() allows args for $p
4815 md_pager="${md_p}";
4816 break;
4818 done;
4819 if obj md_pager is_empty;
4820 then
4821 error 'main_display(): no pager program found for tty mode';
4823 if obj _OPT_V is_yes;
4824 then
4825 echo "File: ${md_modefile}";
4826 echo "Mode: ${_DISPLAY_MODE}";
4827 echo "Display program: ${md_pager}";
4828 eval "${md_groggy}" "${md_addopts}";
4829 else
4830 tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
4831 eval "${md_pager}";
4834 clean_up;
4836 source)
4837 tmp_cat;
4838 clean_up;
4841 #### viewer modes
4843 dvi)
4844 case "${_OPT_DEVICE}" in
4845 ''|dvi) do_nothing; ;;
4847 warning "main_display(): \
4848 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
4850 esac;
4851 md_modefile="${md_modefile}".dvi;
4852 md_groggy="$(tmp_cat | grog -Tdvi)";
4853 _do_display;
4855 html)
4856 case "${_OPT_DEVICE}" in
4857 ''|html) do_nothing; ;;
4859 warning "main_display(): \
4860 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4862 esac;
4863 md_modefile="${md_modefile}".html;
4864 md_groggy="$(tmp_cat | grog -Thtml)";
4865 _do_display;
4867 pdf)
4868 case "${_OPT_DEVICE}" in
4869 ''|ps)
4870 do_nothing;
4873 warning "main_display(): \
4874 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4876 esac;
4877 md_groggy="$(tmp_cat | grog -Tps)";
4878 trap_clean;
4879 if obj _OPT_V is_yes;
4880 then
4881 echo "File: ${md_modefile}.pdf";
4882 echo "Mode: ${_DISPLAY_MODE}";
4883 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4884 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4885 clean_up;
4886 else
4887 # start a new shell program to get another process ID.
4888 /bin/sh -c '
4889 set -e;
4890 _psfile="${md_modefile}.ps";
4891 md_modefile="${md_modefile}.pdf";
4892 test -f "${_psfile}" && rm -f "${_psfile}";
4893 test -f "${md_modefile}" && rm -f "${md_modefile}";
4894 cat "${_TMP_CAT}" | \
4895 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4896 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4897 -sOutputFile="${md_modefile}" -c save pop -f "${_psfile}";
4898 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
4899 then
4900 test -f "${_psfile}" && rm -f "${_psfile}";
4901 test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";
4904 clean_up() {
4905 if test -d "${_TMP_DIR}";
4906 then
4907 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
4910 trap clean_up 0 2>${_NULL_DEV} || :;
4911 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
4912 ) &'
4916 case "${_OPT_DEVICE}" in
4917 ''|ps)
4918 do_nothing;
4921 warning "main_display(): \
4922 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4924 esac;
4925 md_modefile="${md_modefile}".ps;
4926 md_groggy="$(tmp_cat | grog -Tps)";
4927 _do_display;
4930 case "${_OPT_DEVICE}" in
4932 md_device="${_OPT_DEVICE}"
4935 case "${_OPT_RESOLUTION}" in
4936 100)
4937 md_device='X100';
4938 if obj _OPT_GEOMETRY is_empty
4939 then
4940 case "${_DISPLAY_PROG}" in
4941 gxditview|xditview)
4942 # add width of 800dpi for resolution of 100dpi to the args
4943 list_append _DISPLAY_ARGS '-geometry' '800';
4945 esac;
4949 md_device='X75-12';
4951 esac
4952 esac;
4953 md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
4954 _do_display;
4957 case "${_OPT_DEVICE}" in
4959 md_groggy="$(tmp_cat | grog -X)";
4961 X*|dvi|html|lbp|lj4|ps)
4962 # these devices work with
4963 md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
4966 warning "main_display(): \
4967 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4968 md_groggy="$(tmp_cat | grog -Z)";
4970 esac;
4971 _do_display;
4974 error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
4976 esac;
4977 eval ${_UNSET} md_addopts;
4978 eval ${_UNSET} md_device;
4979 eval ${_UNSET} md_groggy;
4980 eval ${_UNSET} md_modefile;
4981 eval ${_UNSET} md_options;
4982 eval ${_UNSET} md_p;
4983 eval ${_UNSET} md_pager;
4984 eval "${return_ok}";
4985 } # main_display()
4988 # $md_modefile and $md_groggy come from main_display()
4989 _do_display()
4991 func_check _do_display = 0 "$@";
4992 trap_clean;
4993 if obj _OPT_V is_yes;
4994 then
4995 echo "File: ${md_modefile}";
4996 echo "Mode: ${_DISPLAY_MODE}";
4997 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4998 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4999 clean_up;
5000 else
5001 # start a new shell program for another process ID and better
5002 # cleaning-up of the temporary files.
5003 /bin/sh -c '
5004 set -e;
5005 test -f "${md_modefile}" && rm -f "${md_modefile}";
5006 cat "${_TMP_CAT}" | \
5007 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
5008 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
5009 then
5010 rm -f "${_TMP_CAT}";
5013 clean_up() {
5014 if test -d "${_TMP_DIR}";
5015 then
5016 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
5019 trap clean_up 0 2>${_NULL_DEV} || :;
5020 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
5021 ) &'
5023 eval "${return_ok}";
5024 } # _do_display() of main_display()
5027 ########################################################################
5028 # main (<command_line_args>*)
5030 # The main function for groffer.
5032 # Arguments:
5034 main()
5036 func_check main '>=' 0 "$@";
5037 # Do not change the sequence of the following functions!
5038 main_init;
5039 main_parse_MANOPT;
5040 main_parse_args "$@";
5041 main_set_mode;
5042 main_do_fileargs;
5043 main_set_resources;
5044 main_display;
5045 eval "${return_ok}";
5048 landmark '20: end of function definitions';
5050 ########################################################################
5052 main "$@";