* release of groffer 0.9.21
[s-roff.git] / contrib / groffer / groffer2.sh
blob0563eade7b20ff441f5d0d35b56e56bb47d0e92c
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 # This file should not be run independently. It is called by
9 # `groffer.sh' in the source or by the installed `groffer' program.
11 # Copyright (C) 2001,2002,2003,2004,2005
12 # Free Software Foundation, Inc.
13 # Written by Bernd Warken
15 # Last update: 2 August 2005
17 # This file is part of `groffer', which is part of `groff'.
19 # `groff' is free software; you can redistribute it and/or modify it
20 # under the terms of the GNU General Public License as published by
21 # the Free Software Foundation; either version 2, or (at your option)
22 # any later version.
24 # `groff' is distributed in the hope that it will be useful, but
25 # WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 # General Public License for more details.
29 # You should have received a copy of the GNU General Public License
30 # along with `groff'; see the files COPYING and LICENSE in the top
31 # directory of the `groff' source. If not, write to the Free Software
32 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
33 # USA.
36 ########################################################################
37 # diagnostic messages for debugging
39 export _DEBUG;
40 _DEBUG='no'; # disable debugging information
41 #_DEBUG='yes'; # enable debugging information
43 export _DEBUG_LM;
44 _DEBUG_LM='no'; # disable landmark messages
45 #_DEBUG_LM='yes'; # enable landmark messages
47 export _DEBUG_KEEP_FILES;
48 _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
49 #_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
51 export _DEBUG_PRINT_PARAMS;
52 _DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters
53 #_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters
55 export _DEBUG_PRINT_SHELL;
56 _DEBUG_PRINT_SHELL='no'; # disable printing of the shell name
57 #_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name
60 # test of $GROFFER_OPT and $* on `--debug' with shortest abbreviation `--deb'
61 case " ${GROFFER_OPT} $* " in
62 *' --deb '*|*' --debu '*|*' --debug '*)
63 _DEBUG='yes';
64 _DEBUG_LM='yes';
65 _DEBUG_KEEP_FILES='yes';
66 _DEBUG_PRINT_PARAMS='yes';
67 _DEBUG_PRINT_SHELL='yes';
69 esac;
71 if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
72 then
73 echo "parameters: ${GROFFER_OPT} $@" >&2;
74 fi;
76 if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
77 then
78 if test _"${_SHELL}"_ = __
79 then
80 if test _"${POSIXLY_CORRECT}"_ = _y_
81 then
82 echo 'shell: bash as /bin/sh (none specified)' >&2;
83 else
84 echo 'shell: /bin/sh (none specified)' >&2;
85 fi;
86 else
87 echo "shell: ${_SHELL}" >&2;
88 fi;
89 fi;
92 ########################################################################
93 # Environment Variables
94 ########################################################################
96 # Environment variables that exist only for this file start with an
97 # underscore letter. Global variables to this file are written in
98 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
99 # start with an underline and use only lower case letters and
100 # underlines, e.g. $_local_variable .
102 # [A-Z]* system variables, e.g. $MANPATH
103 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
104 # _[a-z_]* temporary variables, e.g. $_manpath
106 # Due to incompatibilities of the `ash' shell, the name of loop
107 # variables in `for' must be single character
108 # [a-z] local loop variables, e.g. $i
111 ########################################################################
112 # read-only variables (global to this file)
113 ########################################################################
115 # function return values; `0' means ok; other values are error codes
116 export _ALL_EXIT;
117 export _BAD;
118 export _ERROR;
119 export _GOOD;
120 export _NO;
121 export _OK;
122 export _YES;
124 _GOOD='0'; # return ok
125 _BAD='1'; # return negatively, error code `1'
126 _ERROR='7'; # for syntax errors; no `-1' in `ash'
128 # all exit codes (for `trap_set()')
129 _ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}";
131 _NO="${_BAD}";
132 _YES="${_GOOD}";
133 _OK="${_GOOD}";
135 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
136 export return_ok;
137 export return_good;
138 export return_bad;
139 export return_yes;
140 export return_no;
141 export return_error;
142 export return_var;
143 return_ok="func_pop; return ${_OK}";
144 return_good="func_pop; return ${_GOOD}";
145 return_bad="func_pop; return ${_BAD}";
146 return_yes="func_pop; return ${_YES}";
147 return_no="func_pop; return ${_NO}";
148 return_error="func_pop; return ${_ERROR}";
149 return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
152 export _DEFAULT_MODES;
153 _DEFAULT_MODES='x,ps,tty';
154 export _DEFAULT_RESOLUTION;
155 _DEFAULT_RESOLUTION='75';
157 export _DEFAULT_TTY_DEVICE;
158 _DEFAULT_TTY_DEVICE='latin1';
160 # _VIEWER_* viewer programs for different modes (only X is necessary)
161 # _VIEWER_* a comma-separated list of viewer programs (with options)
162 export _VIEWER_DVI; # viewer program for dvi mode
163 export _VIEWER_PS; # viewer program for ps mode
164 export _VIEWER_HTML_X; # viewer program for html mode in X
165 export _VIEWER_HTML_TTY; # viewer program for html mode in tty
166 _VIEWER_DVI='kdvi,xdvi,dvilx';
167 _VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
168 _VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
169 _VIEWER_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
170 _VIEWER_X='gxditview,xditview';
172 # Search automatically in standard sections `1' to `8', and in the
173 # traditional sections `9', `n', and `o'. On many systems, there
174 # exist even more sections, mostly containing a set of man pages
175 # special to a specific program package. These aren't searched for
176 # automatically, but must be specified on the command line.
177 export _MAN_AUTO_SEC;
178 _MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
180 export _PROCESS_ID; # for shutting down the program
181 _PROCESS_ID="$$";
184 ############ the command line options of the involved programs
186 # The naming scheme for the options environment names is
187 # $_OPTS_<prog>_<length>[_<argspec>]
189 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
190 # command line options)
191 # <length>: LONG (long options) or SHORT (single character options)
192 # <argspec>: ARG for options with argument, NA for no argument;
193 # without _<argspec> both the ones with and without arg.
195 # Each option that takes an argument must be specified with a
196 # trailing : (colon).
198 # exports
199 export _OPTS_GROFFER_SHORT_NA;
200 export _OPTS_GROFFER_SHORT_ARG;
201 export _OPTS_GROFFER_LONG_NA;
202 export _OPTS_GROFFER_LONG_ARG;
203 export _OPTS_GROFF_SHORT_NA;
204 export _OPTS_GROFF_SHORT_ARG;
205 export _OPTS_GROFF_LONG_NA;
206 export _OPTS_GROFF_LONG_ARG;
207 export _OPTS_X_SHORT_ARG;
208 export _OPTS_X_SHORT_NA;
209 export _OPTS_X_LONG_ARG;
210 export _OPTS_X_LONG_NA;
211 export _OPTS_MAN_SHORT_ARG;
212 export _OPTS_MAN_SHORT_NA;
213 export _OPTS_MAN_LONG_ARG;
214 export _OPTS_MAN_LONG_NA;
215 export _OPTS_MANOPT_SHORT_ARG;
216 export _OPTS_MANOPT_SHORT_NA;
217 export _OPTS_MANOPT_LONG_ARG;
218 export _OPTS_MANOPT_LONG_NA;
219 export _OPTS_CMDLINE_SHORT_NA;
220 export _OPTS_CMDLINE_SHORT_ARG;
221 export _OPTS_CMDLINE_LONG_NA;
222 export _OPTS_CMDLINE_LONG_ARG;
224 ###### groffer native options
226 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
227 _OPTS_GROFFER_SHORT_ARG="'T'";
229 _OPTS_GROFFER_LONG_NA="'auto' 'debug' 'default' 'do-nothing' 'dvi' \
230 'groff' 'help' 'intermediate-output' 'html' 'man' \
231 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
232 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
234 _OPTS_GROFFER_LONG_ARG="\
235 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
236 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
237 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
238 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
240 ##### groffer options inhereted from groff
242 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
243 'R' 's' 'S' 't' 'U' 'z'";
244 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
245 'w' 'W'";
246 _OPTS_GROFF_LONG_NA="";
247 _OPTS_GROFF_LONG_ARG="";
249 ##### groffer options inhereted from the X Window toolkit
251 _OPTS_X_SHORT_NA="";
252 _OPTS_X_SHORT_ARG="";
254 _OPTS_X_LONG_NA="'iconic' 'rv'";
256 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
257 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
258 'resolution' 'title' 'xrm'";
260 ###### groffer options inherited from man
262 _OPTS_MAN_SHORT_NA="";
263 _OPTS_MAN_SHORT_ARG="";
265 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
266 'local-file' 'location' 'troff' 'update'";
268 _OPTS_MAN_LONG_ARG="'locale' 'manpath' \
269 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
271 ###### additional options for parsing $MANOPT only
273 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
274 'V' 'w' 'Z'";
275 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
277 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
278 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
279 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
281 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
282 'config_file' 'encoding' 'extension' 'locale'";
284 ###### collections of command line options
286 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
287 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
288 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
289 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
291 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
292 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
293 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
294 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
297 ########################################################################
298 # read-write variables (global to this file)
299 ########################################################################
301 export _ALL_PARAMS; # All options and file name parameters
302 export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
303 export _ADDOPTS_POST; # Transp. options postproc (`eval').
304 export _ADDOPTS_X; # Transp. options X postproc (`eval').
305 export _DEFAULT_MODES; # Set default modes.
306 export _DISPLAY_MODE; # Display mode.
307 export _DISPLAY_PROG; # Viewer program to be used for display.
308 export _DISPLAY_ARGS; # X resources for the viewer program.
309 export _FILEARGS; # Stores filespec parameters.
310 export _FUNC_STACK; # Store debugging information.
311 export _REGISTERED_TITLE; # Processed file names.
312 # _HAS_* from availability tests
313 export _HAS_COMPRESSION; # `yes' if gzip compression is available
314 export _HAS_BZIP; # `yes' if bzip2 compression is available
315 # _MAN_* finally used configuration of man searching
316 export _MAN_ALL; # search all man pages per filespec
317 export _MAN_ENABLE; # enable search for man pages
318 export _MAN_EXT; # extension for man pages
319 export _MAN_FORCE; # force file parameter to be man pages
320 export _MAN_IS_SETUP; # setup man variables only once
321 export _MAN_LANG; # language for man pages
322 export _MAN_LANG2; # language for man pages
323 export _MAN_LANG_DONE; # language dirs added to man path
324 export _MAN_PATH; # search path for man pages
325 export _MAN_SEC; # sections for man pages; sep. `:'
326 export _MAN_SEC_DONE; # sections added to man path
327 export _MAN_SYS; # system names for man pages; sep. `,'
328 export _MAN_SYS; # system names added to man path
329 # _MANOPT_* as parsed from $MANOPT
330 export _MANOPT_ALL; # $MANOPT --all
331 export _MANOPT_EXTENSION; # $MANOPT --extension
332 export _MANOPT_LANG; # $MANOPT --locale
333 export _MANOPT_PATH; # $MANOPT --manpath
334 export _MANOPT_PAGER; # $MANOPT --pager
335 export _MANOPT_SEC; # $MANOPT --sections
336 export _MANOPT_SYS; # $MANOPT --systems
337 # _OPT_* as parsed from groffer command line
338 export _OPT_ALL; # display all suitable man pages.
339 export _OPT_APROPOS; # call `apropos' program.
340 export _OPT_APROPOS_DATA; # `apropos' for man sections 4, 5, 7
341 export _OPT_APROPOS_DEVEL; # `apropos' for man sections 2, 3, 9
342 export _OPT_APROPOS_PROGS; # `apropos' for man sections 1, 6, 8
343 export _OPT_BD; # set border color in some modes.
344 export _OPT_BG; # set background color in some modes.
345 export _OPT_BW; # set border width in some modes.
346 export _OPT_DEBUG; # print debugging information on stderr.
347 export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
348 export _OPT_DEVICE; # device option.
349 export _OPT_DISPLAY; # set X display.
350 export _OPT_FG; # set foreground color in some modes.
351 export _OPT_FN; # set font in some modes.
352 export _OPT_GEOMETRY; # set size and position of viewer in X.
353 export _OPT_ICONIC; # -iconic option for X viewers.
354 export _OPT_LANG; # set language for man pages
355 export _OPT_LOCATION; # print processed file names to stderr
356 export _OPT_MODE; # values: X, tty, Q, Z, ""
357 export _OPT_MANPATH; # manual setting of path for man-pages
358 export _OPT_PAGER; # specify paging program for tty mode
359 export _OPT_RESOLUTION; # set X resolution in dpi
360 export _OPT_RV; # reverse fore- and background colors.
361 export _OPT_SECTIONS; # sections for man page search
362 export _OPT_SYSTEMS; # man pages of different OS's
363 export _OPT_TITLE; # title for gxditview window
364 export _OPT_TEXT_DEVICE; # set device for tty mode.
365 export _OPT_V; # groff option -V.
366 export _OPT_VIEWER_DVI; # viewer program for dvi mode
367 export _OPT_VIEWER_PDF; # viewer program for pdf mode
368 export _OPT_VIEWER_PS; # viewer program for ps mode
369 export _OPT_VIEWER_HTML; # viewer program for html mode
370 export _OPT_VIEWER_X; # viewer program for x mode
371 export _OPT_WHATIS; # print the one-liner man info
372 export _OPT_XRM; # specify X resource.
373 export _OPT_Z; # groff option -Z.
374 # _TMP_* temporary directory and files
375 export _TMP_DIR; # groffer directory for temporary files
376 export _TMP_CAT; # stores concatenation of everything
377 export _TMP_STDIN; # stores stdin, if any
379 # these variables are preset in section `Preset' after the rudim. test
382 ########################################################################
383 # Test of rudimentary shell functionality
384 ########################################################################
387 ########################################################################
388 # Test of `unset'
390 export _UNSET;
391 export _foo;
392 _foo=bar;
393 _res="$(unset _foo 2>&1)";
394 if unset _foo >${_NULL_DEV} 2>&1 && \
395 test _"${_res}"_ = __ && test _"${_foo}"_ = __
396 then
397 _UNSET='unset';
398 eval "${_UNSET}" _res;
399 else
400 _UNSET=':';
404 ########################################################################
405 # Test of `test'.
407 if test a = a && test a != b && test -f "${_GROFFER_SH}"
408 then
410 else
411 echo '"test" did not work.' >&2;
412 exit "${_ERROR}";
416 ########################################################################
417 # Test of `echo' and the `$()' construct.
419 if echo '' >${_NULL_DEV}
420 then
422 else
423 echo '"echo" did not work.' >&2;
424 exit "${_ERROR}";
426 if test _"$(t1="$(echo te)" &&
427 t2="$(echo '')" &&
428 t3="$(echo 'st')" &&
429 echo "${t1}${t2}${t3}")"_ \
430 != _test_
431 then
432 echo 'The "$()" construct did not work' >&2;
433 exit "${_ERROR}";
437 ########################################################################
438 # Test of function definitions.
440 _t_e_s_t_f_u_n_c_()
442 return "${_OK}";
445 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV}
446 then
448 else
449 echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
450 exit "${_ERROR}";
454 ########################################################################
455 # Preset and reset of read-write global variables
456 ########################################################################
459 export _START_DIR; # directory at start time of the script
460 _START_DIR="$(pwd)";
462 # For variables that can be reset by option `--default', see reset().
464 _FILEARGS='';
466 # _HAS_* from availability tests
467 _HAS_COMPRESSION='';
468 _HAS_BZIP='';
470 # _TMP_* temporary files
471 _TMP_DIR='';
472 _TMP_CAT='';
473 _TMP_CONF='';
474 _TMP_STDIN='';
477 ########################################################################
478 # reset ()
480 # Reset the variables that can be affected by options to their default.
482 reset()
484 if test "$#" -ne 0
485 then
486 error "reset() does not have arguments.";
489 _ADDOPTS_GROFF='';
490 _ADDOPTS_POST='';
491 _ADDOPTS_X='';
492 _DISPLAY_ARGS='';
493 _DISPLAY_MODE='';
494 _DISPLAY_PROG='';
495 _REGISTERED_TITLE='';
497 # _MAN_* finally used configuration of man searching
498 _MAN_ALL='no';
499 _MAN_ENABLE='yes'; # do search for man-pages
500 _MAN_EXT='';
501 _MAN_FORCE='no'; # first local file, then search man page
502 _MAN_IS_SETUP='no';
503 _MAN_LANG='';
504 _MAN_LANG2='';
505 _MAN_PATH='';
506 _MAN_SEC='';
507 _MAN_SEC_DONE='no';
508 _MAN_SYS='';
509 _MAN_SYS_DONE='no';
511 # _MANOPT_* as parsed from $MANOPT
512 _MANOPT_ALL='no';
513 _MANOPT_EXTENSION='';
514 _MANOPT_LANG='';
515 _MANOPT_PATH='';
516 _MANOPT_PAGER='';
517 _MANOPT_SEC='';
518 _MANOPT_SYS='';
520 # _OPT_* as parsed from groffer command line
521 _OPT_ALL='no';
522 _OPT_APROPOS='';
523 _OPT_APROPOS_DATA='';
524 _OPT_APROPOS_DEVEL='';
525 _OPT_APROPOS_PROGS='';
526 _OPT_BD='';
527 _OPT_BG='';
528 _OPT_BW='';
529 _OPT_DEBUG='no';
530 _OPT_DEFAULT_MODES='';
531 _OPT_DEVICE='';
532 _OPT_DISPLAY='';
533 _OPT_FG='';
534 _OPT_FN='';
535 _OPT_GEOMETRY='';
536 _OPT_ICONIC='no';
537 _OPT_LANG='';
538 _OPT_LOCATION='no';
539 _OPT_MODE='';
540 _OPT_MANPATH='';
541 _OPT_PAGER='';
542 _OPT_RESOLUTION='';
543 _OPT_RV='no';
544 _OPT_SECTIONS='';
545 _OPT_SYSTEMS='';
546 _OPT_TITLE='';
547 _OPT_TEXT_DEVICE='';
548 _OPT_V='no';
549 _OPT_VIEWER_DVI='';
550 _OPT_VIEWER_PDF='';
551 _OPT_VIEWER_PS='';
552 _OPT_VIEWER_HTML='';
553 _OPT_VIEWER_X='';
554 _OPT_WHATIS='no';
555 _OPT_XRM='';
556 _OPT_Z='no';
560 reset;
563 ########################################################################
564 # Functions for error handling and debugging
565 ########################################################################
568 ##############
569 # echo1 (<text>*)
571 # Output to stdout.
573 # Arguments : arbitrary text including `-'.
575 echo1()
577 cat <<EOF
583 ##############
584 # echo2 (<text>*)
586 # Output to stderr.
588 # Arguments : arbitrary text.
590 echo2()
592 cat >&2 <<EOF
598 ##############
599 # landmark (<text>)
601 # Print <text> to standard error as a debugging aid.
603 # Globals: $_DEBUG_LM
605 landmark()
607 if test _"${_DEBUG_LM}"_ = _yes_
608 then
609 echo2 "LM: $*";
613 landmark "1: debugging functions";
616 ##############
617 # clean_up ()
619 # Clean up at exit.
621 clean_up()
623 cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
624 if test _"${_TMP_DIR}"_ != __
625 then
626 if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}"
627 then
628 rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
629 fi;
634 #############
635 # diag (text>*)
637 # Output a diagnostic message to stderr
639 diag()
641 echo2 '>>>>>'"$*";
645 #############
646 # error (<text>*)
648 # Print an error message to standard error; exit with an error condition
650 # Variable prefix: err
652 error()
654 err_code="${_ERROR}";
655 case "$#" in
656 0) :; ;;
657 1) echo2 'groffer error: '"$1"; ;;
659 echo2 'groffer error: '"$1";
660 err_code="$2";
662 *) echo2 'groffer error: wrong number of arguments in error().'; ;;
663 esac;
664 func_stack_dump;
665 clean_up;
666 kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
667 kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
668 n="${err_code}";
669 eval ${_UNSET} err_code;
670 exit "$n";
674 #############
675 # abort (<text>*)
677 # Terminate program with error condition
679 abort()
681 error "abort(): Program aborted.";
682 exit 1;
686 #############
687 # func_check (<func_name> <rel_op> <nr_args> "$@")
689 # Check number of arguments and register to _FUNC_STACK.
691 # Arguments: >=3
692 # <func_name>: name of the calling function.
693 # <rel_op>: a relational operator: = != < > <= >=
694 # <nr_args>: number of arguments to be checked against <operator>
695 # "$@": the arguments of the calling function.
697 # Variable prefix: fc
699 func_check()
701 if test "$#" -lt 3
702 then
703 error 'func_check() needs at least 3 arguments.';
705 fc_fname="$1";
706 case "$3" in
708 fc_nargs="$3";
709 fc_s='';
711 0|[2-9])
712 fc_nargs="$3";
713 fc_s='s';
716 error "func_check(): third argument must be a digit.";
718 esac;
719 case "$2" in
720 '='|'-eq')
721 fc_op='-eq';
722 fc_comp='exactly';
724 '>='|'-ge')
725 fc_op='-ge';
726 fc_comp='at least';
728 '<='|'-le')
729 fc_op='-le';
730 fc_comp='at most';
732 '<'|'-lt')
733 fc_op='-lt';
734 fc_comp='less than';
736 '>'|'-gt')
737 fc_op='-gt';
738 fc_comp='more than';
740 '!='|'-ne')
741 fc_op='-ne';
742 fc_comp='not';
745 error \
746 'func_check(): second argument is not a relational operator.';
748 esac;
749 shift;
750 shift;
751 shift;
752 if test "$#" "${fc_op}" "${fc_nargs}"
753 then
754 do_nothing;
755 else
756 error "func_check(): \
757 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
759 func_push "${fc_fname}";
760 if test _"${_DEBUG}"_ = _yes_
761 then
762 echo2 '+++ '"${fc_fname} $@";
763 echo2 '>>> '"${_FUNC_STACK}";
765 eval ${_UNSET} fc_comp;
766 eval ${_UNSET} fc_fname;
767 eval ${_UNSET} fc_nargs;
768 eval ${_UNSET} fc_op;
769 eval ${_UNSET} fc_s;
773 #############
774 # func_pop ()
776 # Retrieve the top element from the stack.
778 # The stack elements are separated by `!'; the popped element is
779 # identical to the original element, except that all `!' characters
780 # were removed.
782 # Arguments: 1
784 func_pop()
786 if test "$#" -ne 0
787 then
788 error 'func_pop() does not have arguments.';
790 case "${_FUNC_STACK}" in
792 if test _"${_DEBUG}"_ = _yes_
793 then
794 error 'func_pop(): stack is empty.';
797 *!*)
798 # split at first bang `!'.
799 _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
802 _FUNC_STACK='';
804 esac;
805 if test _"${_DEBUG}"_ = _yes_
806 then
807 echo2 '<<< '"${_FUNC_STACK}";
812 #############
813 # func_push (<element>)
815 # Store another element to stack.
817 # The stack elements are separated by `!'; if <element> contains a `!'
818 # it is removed first.
820 # Arguments: 1
822 # Variable prefix: fp
824 func_push()
826 if test "$#" -ne 1
827 then
828 error 'func_push() needs 1 argument.';
830 case "$1" in
831 *'!'*)
832 # remove all bangs `!'.
833 fp_element="$(echo1 "$1" | sed -e 's/!//g')";
836 fp_element="$1";
838 esac;
839 if test _"${_FUNC_STACK}"_ = __
840 then
841 _FUNC_STACK="${fp_element}";
842 else
843 _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
845 eval ${_UNSET} fp_element;
849 #############
850 # func_stack_dump ()
852 # Print the content of the stack. Ignore the arguments.
854 func_stack_dump()
856 diag 'call stack: '"${_FUNC_STACK}";
860 ########################################################################
861 # System Test
862 ########################################################################
864 landmark "2: system test";
866 # Test the availability of the system utilities used in this script.
869 ########################################################################
870 # Test of function `sed'.
873 if test _"$(echo xTesTx \
874 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
875 | sed -e 's|T|t|g')"_ != _test_
876 then
877 error 'Test of "sed" command failed.';
881 ########################################################################
882 # Test of function `cat'.
884 if test _"$(echo test | cat)"_ != _test_
885 then
886 error 'Test of "cat" command failed.';
890 ########################################################################
891 # Test for compression.
893 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
894 then
895 _HAS_COMPRESSION='yes';
896 if echo 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
897 && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
898 | bzip2 -d -c 2>${_NULL_DEV})"_ \
899 = _test_
900 then
901 _HAS_BZIP='yes';
902 else
903 _HAS_BZIP='no';
905 else
906 _HAS_COMPRESSION='no';
907 _HAS_BZIP='no';
911 ########################################################################
912 # Definition of normal Functions in alphabetical order
913 ########################################################################
914 landmark "3: functions";
916 ########################################################################
917 # abort (<text>*)
919 # Unconditionally terminate the program with error code;
920 # useful for debugging.
922 # defined above
925 ########################################################################
926 # apropos_run (<name>)
929 apropos_run() {
930 func_check apropos_run = 1 "$@";
931 if apropos apropos >${_NULL_DEV} 2>${_NULL_DEV}
932 then
933 apropos "$1";
934 elif man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
935 then
936 man --apropos "$1";
937 elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
938 then
939 man -k "$1";
941 eval "${return_ok}";
945 ########################################################################
946 # base_name (<path>)
948 # Get the file name part of <path>, i.e. delete everything up to last
949 # `/' from the beginning of <path>. Remove final slashes, too, to get a
950 # non-empty output.
952 # Arguments : 1
953 # Output : the file name part (without slashes)
955 # Variable prefix: bn
957 base_name()
959 func_check base_name = 1 "$@";
960 bn_name="$1";
961 case "${bn_name}" in
963 # delete all final slashes
964 bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
966 esac;
967 case "${bn_name}" in
968 /|'')
969 eval ${_UNSET} bn_name;
970 eval "${return_bad}";
972 */*)
973 # delete everything before and including the last slash `/'.
974 echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
977 obj bn_name echo1;
979 esac;
980 eval ${_UNSET} bn_name;
981 eval "${return_ok}";
985 ########################################################################
986 # cat_z (<file>)
988 # Decompress if possible or just print <file> to standard output.
990 # gzip, bzip2, and .Z decompression is supported.
992 # Arguments: 1, a file name.
993 # Output: the content of <file>, possibly decompressed.
995 if test _"${_HAS_COMPRESSION}"_ = _yes_
996 then
997 cat_z()
999 func_check cat_z = 1 "$@";
1000 case "$1" in
1002 error 'cat_z(): empty file name';
1004 '-')
1005 error 'cat_z(): for standard input use save_stdin()';
1007 esac;
1008 if obj _HAS_BZIP is_yes
1009 then
1010 if bzip2 -t "$1" 2>${_NULL_DEV}
1011 then
1012 bzip2 -c -d "$1" 2>${_NULL_DEV};
1013 eval "${return_ok}";
1016 gzip -c -d -f "$1" 2>${_NULL_DEV};
1017 eval "${return_ok}";
1019 else
1020 cat_z()
1022 func_check cat_z = 1 "$@";
1023 cat "$1";
1024 eval "${return_ok}";
1029 ########################################################################
1030 # clean_up ()
1032 # Do the final cleaning up before exiting; used by the trap calls.
1034 # defined above
1037 ########################################################################
1038 # diag (<text>*)
1040 # Print marked message to standard error; useful for debugging.
1042 # defined above
1045 ########################################################################
1046 landmark '4: dirname()*';
1047 ########################################################################
1049 #######################################################################
1050 # dirname_append (<dir> <name>)
1052 # Append `name' to `dir' with clean handling of `/'.
1054 # Arguments : 2
1055 # Output : the generated new directory name <dir>/<name>
1057 dirname_append()
1059 func_check dirname_append = 2 "$@";
1060 if is_empty "$1"
1061 then
1062 error "dir_append(): first argument is empty.";
1064 if is_empty "$2"
1065 then
1066 echo1 "$1";
1067 else
1068 dirname_chop "$1"/"$2";
1070 eval "${return_ok}";
1074 ########################################################################
1075 # dirname_chop (<name>)
1077 # Remove unnecessary slashes from directory name.
1079 # Argument: 1, a directory name.
1080 # Output: path without double, or trailing slashes.
1082 # Variable prefix: dc
1084 dirname_chop()
1086 func_check dirname_chop = 1 "$@";
1087 # replace all multiple slashes by a single slash `/'.
1088 dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
1089 case "${dc_res}" in
1090 ?*/)
1091 # remove trailing slash '/';
1092 echo1 "${dc_res}" | sed -e 's|/$||';
1095 obj dc_res echo1
1097 esac;
1098 eval ${_UNSET} dc_res;
1099 eval "${return_ok}";
1103 ########################################################################
1104 # do_filearg (<filearg>)
1106 # Append the file, man-page, or standard input corresponding to the
1107 # argument to the temporary file. If this is compressed in the gzip
1108 # or Z format it is decompressed. A title element is generated.
1110 # Argument either:
1111 # - name of an existing files.
1112 # - `-' to represent standard input (several times allowed).
1113 # - `man:name.(section)' the man-page for `name' in `section'.
1114 # - `man:name.section' the man-page for `name' in `section'.
1115 # - `man:name' the man-page for `name' in the lowest `section'.
1116 # - `name.section' the man-page for `name' in `section'.
1117 # - `name' the man-page for `name' in the lowest `section'.
1118 # Globals :
1119 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1121 # Output : none
1122 # Return : $_GOOD if found, ${_BAD} otherwise.
1124 # Variable prefix: df
1126 do_filearg()
1128 func_check do_filearg = 1 "$@";
1129 df_filespec="$1";
1130 # store sequence into positional parameters
1131 case "${df_filespec}" in
1133 eval ${_UNSET} df_filespec;
1134 eval "${return_good}";
1136 '-')
1137 register_file '-';
1138 eval ${_UNSET} df_filespec;
1139 eval "${return_good}";
1141 */*) # with directory part; so no man search
1142 set 'File';
1145 if obj _MAN_ENABLE is_yes
1146 then
1147 if obj _MAN_FORCE is_yes
1148 then
1149 set 'Manpage' 'File';
1150 else
1151 set 'File' 'Manpage';
1153 else
1154 set 'File';
1157 esac;
1158 for i
1160 case "$i" in
1161 File)
1162 if test -f "${df_filespec}"
1163 then
1164 if test -r "${df_filespec}"
1165 then
1166 register_file "${df_filespec}";
1167 eval ${_UNSET} df_filespec;
1168 eval ${_UNSET} df_no_man;
1169 eval "${return_good}";
1170 else
1171 echo2 "could not read \`${df_filespec}'";
1172 eval ${_UNSET} df_filespec;
1173 eval ${_UNSET} df_no_man;
1174 eval "${return_bad}";
1176 else
1177 if obj df_no_man is_not_empty
1178 then
1179 echo2 "\`${df_filespec}' is neither a file nor a man page."
1181 df_no_file=yes;
1182 continue;
1185 Manpage) # parse filespec as man page
1186 if obj _MAN_IS_SETUP is_not_yes
1187 then
1188 man_setup;
1190 if man_do_filespec "${df_filespec}"
1191 then
1192 eval ${_UNSET} df_filespec;
1193 eval ${_UNSET} df_no_file;
1194 eval "${return_good}";
1195 else
1196 if obj df_no_file is_not_empty
1197 then
1198 echo2 "\`${df_filespec}' is neither a file nor a man page."
1200 df_no_man=yes;
1201 continue;
1204 esac;
1205 done;
1206 eval ${_UNSET} df_filespec;
1207 eval ${_UNSET} df_no_file;
1208 eval ${_UNSET} df_no_man;
1209 eval "${return_bad}";
1210 } # do_filearg()
1213 ########################################################################
1214 # do_nothing ()
1216 # Dummy function.
1218 do_nothing()
1220 eval return "${_OK}";
1224 ########################################################################
1225 # echo2 (<text>*)
1227 # Print to standard error with final line break.
1229 # defined above
1232 ########################################################################
1233 # error (<text>*)
1235 # Print error message and exit with error code.
1237 # defined above
1240 ########################################################################
1241 # func_check (<func_name> <rel_op> <nr_args> "$@")
1243 # Check number of arguments and register to _FUNC_STACK.
1245 # Arguments: >=3
1246 # <func_name>: name of the calling function.
1247 # <rel_op>: a relational operator: = != < > <= >=
1248 # <nr_args>: number of arguments to be checked against <operator>
1249 # "$@": the arguments of the calling function.
1251 # defined above
1253 #########################################################################
1254 # func_pop ()
1256 # Delete the top element from the function call stack.
1258 # defined above
1261 ########################################################################
1262 # func_push (<element>)
1264 # Store another element to function call stack.
1266 # defined above
1269 ########################################################################
1270 # func_stack_dump ()
1272 # Print the content of the stack.
1274 # defined above
1277 ########################################################################
1278 # get_first_essential (<arg>*)
1280 # Retrieve first non-empty argument.
1282 # Return : `1' if all arguments are empty, `0' if found.
1283 # Output : the retrieved non-empty argument.
1285 # Variable prefix: gfe
1287 get_first_essential()
1289 func_check get_first_essential '>=' 0 "$@";
1290 if is_equal "$#" 0
1291 then
1292 eval "${return_ok}";
1294 for i
1296 gfe_var="$i";
1297 if obj gfe_var is_not_empty
1298 then
1299 obj gfe_var echo1;
1300 eval ${_UNSET} gfe_var;
1301 eval "${return_ok}";
1303 done;
1304 eval ${_UNSET} gfe_var;
1305 eval "${return_bad}";
1309 ########################################################################
1310 landmark '5: is_*()';
1311 ########################################################################
1313 ########################################################################
1314 # is_dir (<name>)
1316 # Test whether `name' is a directory.
1318 # Arguments : 1
1319 # Return : `0' if arg1 is a directory, `1' otherwise.
1321 is_dir()
1323 func_check is_dir = 1 "$@";
1324 if test _"$1"_ != __ && test -d "$1" && test -r "$1"
1325 then
1326 eval "${return_yes}";
1328 eval "${return_no}";
1332 ########################################################################
1333 # is_empty (<string>)
1335 # Test whether `string' is empty.
1337 # Arguments : <=1
1338 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1340 is_empty()
1342 func_check is_empty = 1 "$@";
1343 if test _"$1"_ = __
1344 then
1345 eval "${return_yes}";
1347 eval "${return_no}";
1351 ########################################################################
1352 # is_equal (<string1> <string2>)
1354 # Test whether `string1' is equal to <string2>.
1356 # Arguments : 2
1357 # Return : `0' both arguments are equal strings, `1' otherwise.
1359 is_equal()
1361 func_check is_equal = 2 "$@";
1362 if test _"$1"_ = _"$2"_
1363 then
1364 eval "${return_yes}";
1366 eval "${return_no}";
1370 ########################################################################
1371 # is_existing (<name>)
1373 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1374 # not have `test -e'.
1376 # Arguments : 1
1377 # Return : `0' if arg1 exists, `1' otherwise.
1379 is_existing()
1381 func_check is_existing = 1 "$@";
1382 if test _"$1"_ = __
1383 then
1384 eval "${return_no}";
1386 if test -f "$1" || test -d "$1" || test -c "$1"
1387 then
1388 eval "${return_yes}";
1390 eval "${return_no}";
1394 ########################################################################
1395 # is_file (<name>)
1397 # Test whether `name' is a readable file.
1399 # Arguments : 1
1400 # Return : `0' if arg1 is a readable file, `1' otherwise.
1402 is_file()
1404 func_check is_file = 1 "$@";
1405 if test _"$1"_ != __ && test -f "$1" && test -r "$1"
1406 then
1407 eval "${return_yes}";
1409 eval "${return_no}";
1413 ########################################################################
1414 # is_non_empty_file (<file_name>)
1416 # Test whether `file_name' is a non-empty existing file.
1418 # Arguments : <=1
1419 # Return :
1420 # `0' if arg1 is a non-empty existing file
1421 # `1' otherwise
1423 is_non_empty_file()
1425 func_check is_non_empty_file = 1 "$@";
1426 if is_file "$1" && test -s "$1"
1427 then
1428 eval "${return_yes}";
1430 eval "${return_no}";
1434 ########################################################################
1435 # is_not_dir (<name>)
1437 # Test whether `name' is not a readable directory.
1439 # Arguments : 1
1440 # Return : `0' if arg1 is a directory, `1' otherwise.
1442 is_not_dir()
1444 func_check is_not_dir = 1 "$@";
1445 if is_dir "$1"
1446 then
1447 eval "${return_no}";
1449 eval "${return_yes}";
1453 ########################################################################
1454 # is_not_empty (<string>)
1456 # Test whether `string' is not empty.
1458 # Arguments : <=1
1459 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1461 is_not_empty()
1463 func_check is_not_empty = 1 "$@";
1464 if is_empty "$1"
1465 then
1466 eval "${return_no}";
1468 eval "${return_yes}";
1472 ########################################################################
1473 # is_not_equal (<string1> <string2>)
1475 # Test whether `string1' differs from `string2'.
1477 # Arguments : 2
1479 is_not_equal()
1481 func_check is_not_equal = 2 "$@";
1482 if is_equal "$1" "$2"
1483 then
1484 eval "${return_no}";
1486 eval "${return_yes}";
1490 ########################################################################
1491 # is_not_file (<filename>)
1493 # Test whether `name' is a not readable file.
1495 # Arguments : >=1 (empty allowed), more args are ignored
1497 is_not_file()
1499 func_check is_not_file '>=' 1 "$@";
1500 if is_file "$1"
1501 then
1502 eval "${return_no}";
1504 eval "${return_yes}";
1508 ########################################################################
1509 # is_not_prog (<name>)
1511 # Verify that arg is a not program in $PATH.
1513 # Arguments : >=1 (empty allowed)
1514 # more args are ignored, this allows to specify progs with arguments
1516 is_not_prog()
1518 func_check is_not_prog '>=' 1 "$@";
1519 if where_is "$1" >${_NULL_DEV}
1520 then
1521 eval "${return_no}";
1523 eval "${return_yes}";
1527 ########################################################################
1528 # is_not_writable (<name>)
1530 # Test whether `name' is a not a writable file or directory.
1532 # Arguments : >=1 (empty allowed), more args are ignored
1534 is_not_writable()
1536 func_check is_not_writable '>=' 1 "$@";
1537 if is_writable "$1"
1538 then
1539 eval "${return_no}";
1541 eval "${return_yes}";
1545 ########################################################################
1546 # is_not_yes (<string>)
1548 # Test whether `string' is not "yes".
1550 # Arguments : 1
1552 is_not_yes()
1554 func_check is_not_yes = 1 "$@";
1555 if is_yes "$1"
1556 then
1557 eval "${return_no}";
1559 eval "${return_yes}";
1563 ########################################################################
1564 # is_prog (<name> [<arg>*])
1566 # Determine whether <name> is a program in $PATH
1568 # Arguments : >=0 (empty allowed)
1569 # <arg>* are ignored, this allows to specify progs with arguments.
1571 is_prog()
1573 func_check is_prog '>=' 0 "$@";
1574 case "$#" in
1576 eval "${return_no}";
1579 if where_is "$1" >${_NULL_DEV}
1580 then
1581 eval "${return_yes}";
1584 esac
1585 eval "${return_no}";
1589 ########################################################################
1590 # is_writable (<name>)
1592 # Test whether `name' is a writable file or directory.
1594 # Arguments : >=1 (empty allowed), more args are ignored
1596 is_writable()
1598 func_check is_writable '>=' 1 "$@";
1599 if test _"$1"_ = __
1600 then
1601 eval "${return_no}";
1603 if test -r "$1"
1604 then
1605 if test -w "$1"
1606 then
1607 eval "${return_yes}";
1610 eval "${return_no}";
1614 ########################################################################
1615 # is_yes (<string>)
1617 # Test whether `string' has value "yes".
1619 # Arguments : <=1
1620 # Return : `0' if arg1 is `yes', `1' otherwise.
1622 is_yes()
1624 func_check is_yes = 1 "$@";
1625 if is_equal "$1" 'yes'
1626 then
1627 eval "${return_yes}";
1629 eval "${return_no}";
1633 ########################################################################
1634 # landmark ()
1636 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1638 # Globals: $_DEBUG_LM
1640 # Defined in section `Debugging functions'.
1643 ########################################################################
1644 # leave ([<code>])
1646 # Clean exit without an error or with <code>.
1648 leave()
1650 clean_up;
1651 if test $# = 0
1652 then
1653 exit "${_OK}";
1654 else
1655 exit "$1";
1660 ########################################################################
1661 landmark '6: list_*()';
1662 ########################################################################
1664 # `list' is an object class that represents an array or list. Its
1665 # data consists of space-separated single-quoted elements. So a list
1666 # has the form "'first' 'second' '...' 'last'". See list_append() for
1667 # more details on the list structure. The array elements of `list'
1668 # can be get by `eval set x "$list"; shift`.
1671 ########################################################################
1672 # list_append (<list> <element>...)
1674 # Arguments: >=2
1675 # <list>: a variable name for a list of single-quoted elements
1676 # <element>: some sequence of characters.
1677 # Output: none, but $<list> is set to
1678 # if <list> is empty: "'<element>' '...'"
1679 # otherwise: "$list '<element>' ..."
1681 # Variable prefix: la
1683 list_append()
1685 func_check list_append '>=' 2 "$@";
1686 la_name="$1";
1687 eval la_list='"${'$1'}"';
1688 shift;
1689 for s
1691 la_s="$s";
1692 case "${la_s}" in
1693 *\'*)
1694 # escape each single quote by replacing each
1695 # "'" (squote) by "'\''" (squote bslash squote squote);
1696 # note that the backslash must be doubled in the following `sed'
1697 la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
1700 la_element="";
1703 la_element="${la_s}";
1705 esac;
1706 if obj la_list is_empty
1707 then
1708 la_list="'${la_element}'";
1709 else
1710 la_list="${la_list} '${la_element}'";
1712 done;
1713 eval "${la_name}"='"${la_list}"';
1714 eval ${_UNSET} la_element;
1715 eval ${_UNSET} la_list;
1716 eval ${_UNSET} la_name;
1717 eval ${_UNSET} la_s;
1718 eval "${return_ok}";
1722 ########################################################################
1723 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1725 # Transform command line arguments into a normalized form.
1727 # Options, option arguments, and file parameters are identified and
1728 # output each as a single-quoted argument of its own. Options and
1729 # file parameters are separated by a '--' argument.
1731 # Arguments: >=1
1732 # <pre_name>: common part of a set of 4 environment variable names:
1733 # $<pre_name>_SHORT_NA: list of short options without an arg.
1734 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1735 # $<pre_name>_LONG_NA: list of long options without an arg.
1736 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1737 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1738 # the content of a variable, or direct arguments.
1740 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1742 # Example:
1743 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1744 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1745 # none-empty option lists, this will result in printing:
1746 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1748 # Use this function in the following way:
1749 # eval set x "$(args_norm PRE_NAME "$@")";
1750 # shift;
1751 # while test "$1" != '--'; do
1752 # case "$1" in
1753 # ...
1754 # esac;
1755 # shift;
1756 # done;
1757 # shift; #skip '--'
1758 # # all positional parameters ("$@") left are file name parameters.
1760 # Variable prefix: lfc
1762 list_from_cmdline()
1764 func_check list_from_cmdline '>=' 1 "$@";
1765 lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1766 lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1767 lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1768 lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1769 if obj lfc_short_n is_empty
1770 then
1771 error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1773 if obj lfc_short_a is_empty
1774 then
1775 error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1777 if obj lfc_long_n is_empty
1778 then
1779 error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1781 if obj lfc_long_a is_empty
1782 then
1783 error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1785 shift;
1786 if is_equal "$#" 0
1787 then
1788 echo1 --
1789 eval ${_UNSET} lfc_fparams;
1790 eval ${_UNSET} lfc_short_a;
1791 eval ${_UNSET} lfc_short_n;
1792 eval ${_UNSET} lfc_long_a;
1793 eval ${_UNSET} lfc_long_n;
1794 eval ${_UNSET} lfc_result;
1795 eval "${return_ok}";
1797 lfc_fparams='';
1798 lfc_result='';
1799 while test "$#" -ge 1
1801 lfc_arg="$1";
1802 shift;
1803 case "${lfc_arg}" in
1804 --) break; ;;
1805 --?*)
1806 # delete leading '--';
1807 lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
1808 lfc_opt="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")";
1809 if obj lfc_opt is_not_empty
1810 then
1811 # long option, no argument
1812 list_append lfc_result "--${lfc_opt}";
1813 continue;
1815 # test on `--opt=arg'
1816 if string_contains "${lfc_abbrev}" '='
1817 then
1818 lfc_with_equal="${lfc_abbrev}";
1819 # extract option by deleting from the first '=' to the end
1820 lfc_abbrev="$(echo1 "${lfc_with_equal}" | \
1821 sed -e 's/^\([^=]*\)=.*$/\1/')";
1822 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
1823 if obj lfc_opt is_not_empty
1824 then
1825 # get the option argument by deleting up to first `='
1826 lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')";
1827 list_append lfc_result "--${lfc_opt}" "${lfc_optarg}";
1828 continue;
1831 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
1832 if obj lfc_opt is_not_empty
1833 then
1834 # long option with argument
1835 if test "$#" -le 0
1836 then
1837 error "list_from_cmdline(): no argument for option --${lfc_opt}."
1839 list_append lfc_result "--${lfc_opt}" "$1";
1840 shift;
1841 continue;
1843 error "list_from_cmdline(): --${lfc_opt} is not an option."
1845 -?*) # short option (cluster)
1846 # delete leading `-';
1847 lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')";
1848 while obj lfc_rest is_not_empty
1850 # get next short option from cluster (first char of $lfc_rest)
1851 lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')";
1852 # remove first character from ${lfc_rest};
1853 lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')";
1854 if list_has lfc_short_n "${lfc_optchar}"
1855 then
1856 list_append lfc_result "-${lfc_optchar}";
1857 continue;
1858 elif list_has lfc_short_a "${lfc_optchar}"
1859 then
1860 if obj lfc_rest is_empty
1861 then
1862 if test "$#" -ge 1
1863 then
1864 list_append lfc_result "-${lfc_optchar}" "$1";
1865 shift;
1866 continue;
1867 else
1868 error 'list_from_cmdline(): no argument for option -'\
1869 "${lfc_optchar}."
1871 else # rest is the argument
1872 list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
1873 lfc_rest='';
1874 continue;
1876 else
1877 error "list_from_cmdline(): unknown option -${lfc_optchar}."
1879 done;
1882 # Here, $lfc_arg is not an option, so a file parameter.
1883 list_append lfc_fparams "${lfc_arg}";
1885 # Ignore the strange POSIX option handling to end option
1886 # parsing after the first file name argument. To reuse it, do
1887 # a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
1888 # When `bash' is called as `sh' $POSIXLY_CORRECT is set
1889 # automatically to `y'.
1891 esac;
1892 done;
1893 list_append lfc_result '--';
1894 if obj lfc_fparams is_not_empty
1895 then
1896 lfc_result="${lfc_result} ${lfc_fparams}";
1898 if test "$#" -gt 0
1899 then
1900 list_append lfc_result "$@";
1902 obj lfc_result echo1;
1903 eval ${_UNSET} lfc_abbrev;
1904 eval ${_UNSET} lfc_fparams;
1905 eval ${_UNSET} lfc_short_a;
1906 eval ${_UNSET} lfc_short_n;
1907 eval ${_UNSET} lfc_long_a;
1908 eval ${_UNSET} lfc_long_n;
1909 eval ${_UNSET} lfc_result;
1910 eval ${_UNSET} lfc_arg;
1911 eval ${_UNSET} lfc_opt;
1912 eval ${_UNSET} lfc_opt_arg;
1913 eval ${_UNSET} lfc_opt_char;
1914 eval ${_UNSET} lfc_with_equal;
1915 eval ${_UNSET} lfc_rest;
1916 eval "${return_ok}";
1917 } # list_from_cmdline()
1920 ########################################################################
1921 # list_from_split (<string> <separator>)
1923 # In <string>, escape all white space characters and replace each
1924 # <separator> by space.
1926 # Arguments: 2: a <string> that is to be split into parts divided by
1927 # <separator>
1928 # Output: the resulting list string
1930 # Variable prefix: lfs
1932 list_from_split()
1934 func_check list_from_split = 2 "$@";
1936 # precede each space or tab by a backslash `\' (doubled for `sed')
1937 lfs_s="$(echo1 "$1" | sed -e 's/\(['"${_SP}${_TAB}"']\)/\\\1/g')";
1939 # replace split character of string by the list separator ` ' (space).
1940 case "$2" in
1941 /) # cannot use normal `sed' separator
1942 echo1 "${lfs_s}" | sed -e 's|'"$2"'| |g';
1944 ?) # use normal `sed' separator
1945 echo1 "${lfs_s}" | sed -e 's/'"$2"'/ /g';
1947 ??*)
1948 error 'list_from_split(): separator must be a single character.';
1950 esac;
1951 eval ${_UNSET} lfs_s;
1952 eval "${return_ok}";
1956 ########################################################################
1957 # list_get (<list>)
1959 # Check whether <list> is a space-separated list of '-quoted elements.
1961 # If the test fails an error is raised.
1962 # If the test succeeds the argument is echoed.
1964 # Testing criteria:
1965 # A list has the form "'first' 'second' '...' 'last'". So it has a
1966 # leading and a final quote and the elements are separated by "' '"
1967 # constructs. If these are all removed there should not be any
1968 # unescaped single-quotes left. Watch out for escaped single
1969 # quotes; they have the form '\'' (sq bs sq sq).
1971 # Arguments: 1
1972 # Output: the argument <list> unchanged, if the check succeeded.
1974 # Variable prefix: lg
1976 list_get()
1978 func_check list_get = 1 "$@";
1979 eval lg_list='"${'$1'}"';
1980 # remove leading and final space characters
1981 lg_list="$(echo1 "${lg_list}" | sed -e '
1982 s/^['"${_SP}${_TAB}"']*//
1983 s/['"${_SP}${_TAB}"']*$//
1984 ')";
1985 case "${lg_list}" in
1987 eval ${_UNSET} lg_list;
1988 eval "${return_ok}";
1990 \'*\')
1991 obj lg_list echo1;
1992 eval ${_UNSET} lg_list;
1993 eval "${return_ok}";
1996 error "list_get(): bad list: $1"
1998 esac;
1999 eval ${_UNSET} lg_list;
2000 eval "${return_ok}";
2004 ########################################################################
2005 # list_has (<var_name> <element>)
2007 # Test whether the list <var_name> has the element <element>.
2009 # Arguments: 2
2010 # <var_name>: a variable name for a list of single-quoted elements
2011 # <element>: some sequence of characters.
2013 # Variable prefix: lh
2015 list_has()
2017 func_check list_has = 2 "$@";
2018 eval lh_list='"${'$1'}"';
2019 if obj lh_list is_empty
2020 then
2021 eval "${_UNSET}" lh_list;
2022 eval "${return_no}";
2024 case "$2" in
2025 \'*\') lh_element=" $2 "; ;;
2026 *) lh_element=" '$2' "; ;;
2027 esac;
2028 if string_contains " ${lh_list} " "${lh_element}"
2029 then
2030 eval "${_UNSET}" lh_list;
2031 eval "${_UNSET}" lh_element;
2032 eval "${return_yes}";
2033 else
2034 eval "${_UNSET}" lh_list;
2035 eval "${_UNSET}" lh_element;
2036 eval "${return_no}";
2041 ########################################################################
2042 # list_has_abbrev (<var_name> <abbrev>)
2044 # Test whether the list <var_name> has an element starting with <abbrev>.
2046 # Arguments: 2
2047 # <var_name>: a variable name for a list of single-quoted elements
2048 # <abbrev>: some sequence of characters.
2050 # Variable prefix: lha
2052 list_has_abbrev()
2054 func_check list_has_abbrev = 2 "$@";
2055 eval lha_list='"${'$1'}"';
2056 if obj lha_list is_empty
2057 then
2058 eval "${_UNSET}" lha_list;
2059 eval "${return_no}";
2061 case "$2" in
2062 \'*) lha_element=" $(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')"; ;;
2063 *) lha_element=" '$2"; ;;
2064 esac;
2065 if string_contains " ${lha_list}" "${lha_element}"
2066 then
2067 eval "${_UNSET}" lha_list;
2068 eval "${_UNSET}" lha_element;
2069 eval "${return_yes}";
2070 else
2071 eval "${_UNSET}" lha_list;
2072 eval "${_UNSET}" lha_element;
2073 eval "${return_no}";
2075 eval "${return_ok}";
2079 ########################################################################
2080 # list_has_not (<list> <element>)
2082 # Test whether <list> has no <element>.
2084 # Arguments: 2
2085 # <list>: a space-separated list of single-quoted elements.
2086 # <element>: some sequence of characters.
2088 # Variable prefix: lhn
2090 list_has_not()
2092 func_check list_has_not = 2 "$@";
2093 eval lhn_list='"${'$1'}"';
2094 if obj lhn_list is_empty
2095 then
2096 eval "${_UNSET}" lhn_list;
2097 eval "${return_yes}";
2099 case "$2" in
2100 \'*\') lhn_element=" $2 "; ;;
2101 *) lhn_element="' $2 '"; ;;
2102 esac;
2103 if string_contains " ${lhn_list} " "${lhn_element}"
2104 then
2105 eval "${_UNSET}" lhn_list;
2106 eval "${_UNSET}" lhn_element;
2107 eval "${return_no}";
2108 else
2109 eval "${_UNSET}" lhn_list;
2110 eval "${_UNSET}" lhn_element;
2111 eval "${return_yes}";
2116 ########################################################################
2117 # list_single_from_abbrev (<list> <abbrev>)
2119 # Check whether the list has an element starting with <abbrev>. If
2120 # there are more than a single element an error is created.
2122 # Arguments: 2
2123 # <list>: a variable name for a list of single-quoted elements
2124 # <abbrev>: some sequence of characters.
2126 # Output: the found element.
2128 # Variable prefix: lsfa
2130 list_single_from_abbrev()
2132 func_check list_single_from_abbrev = 2 "$@";
2133 eval lsfa_list='"${'$1'}"';
2134 if obj lsfa_list is_empty
2135 then
2136 eval "${_UNSET}" lsfa_list;
2137 eval "${return_no}";
2139 lsfa_abbrev="$2";
2140 if list_has lsfa_list "${lsfa_abbrev}"
2141 then
2142 obj lsfa_abbrev echo1;
2143 eval "${_UNSET}" lsfa_abbrev;
2144 eval "${_UNSET}" lsfa_list;
2145 eval "${return_yes}";
2147 if list_has_abbrev lsfa_list "${lsfa_abbrev}"
2148 then
2149 lsfa_element='';
2150 eval set x "${lsfa_list}";
2151 shift;
2152 for i
2154 case "$i" in
2155 ${lsfa_abbrev}*)
2156 if obj lsfa_element is_not_empty
2157 then
2158 error "list_single_from_abbrev: the abbreviation ${lsfa_abbrev} \
2159 has multiple options: ${lsfa_element} and ${i}.";
2161 lsfa_element="$i";
2163 esac;
2164 done;
2165 obj lsfa_element echo1;
2166 eval "${_UNSET}" lsfa_abbrev;
2167 eval "${_UNSET}" lsfa_element;
2168 eval "${_UNSET}" lsfa_list;
2169 eval "${return_yes}";
2170 else
2171 eval "${_UNSET}" lsfa_abbrev;
2172 eval "${_UNSET}" lsfa_element;
2173 eval "${_UNSET}" lsfa_list;
2174 eval "${return_no}";
2179 ########################################################################
2180 landmark '7: man_*()';
2181 ########################################################################
2183 ########################################################################
2184 # man_do_filespec (<filespec>)
2186 # Print suitable man page(s) for filespec to $_TMP_CAT.
2188 # Arguments : 2
2189 # <filespec>: argument of the form `man:name.section', `man:name',
2190 # `man:name(section)', `name.section', `name'.
2192 # Globals : $_OPT_ALL
2194 # Output : none.
2195 # Return : `0' if man page was found, `1' else.
2197 # Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE
2198 # are assumed (see man_setup()).
2200 # Variable prefix: mdf
2202 man_do_filespec()
2204 func_check man_do_filespec = 1 "$@";
2205 if obj _MAN_PATH is_empty
2206 then
2207 eval "${return_bad}";
2209 if is_empty "$1"
2210 then
2211 eval "${return_bad}";
2213 mdf_spec="$1";
2214 mdf_name='';
2215 mdf_section='';
2216 case "${mdf_spec}" in
2217 */*) # not a man spec when it contains '/'
2218 eval ${_UNSET} mdf_got_one;
2219 eval ${_UNSET} mdf_name;
2220 eval ${_UNSET} mdf_section;
2221 eval ${_UNSET} mdf_spec;
2222 eval "${return_bad}";
2224 man:?*\(?*\)) # man:name(section)
2225 mdf_name="$(echo1 "${mdf_spec}" \
2226 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2227 mdf_section="$(echo1 "${mdf_spec}" \
2228 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2230 man:?*.[0-9on]) # man:name.section
2231 mdf_name="$(echo1 "${mdf_spec}" \
2232 | sed -e 's/^man:\(..*\)\..$/\1/')";
2233 mdf_section="$(echo1 "${mdf_spec}" \
2234 | sed -e 's/^.*\(.\)$/\1/')";
2236 man:?*) # man:name
2237 mdf_name="$(echo1 "${mdf_spec}" | sed -e 's/^man://')";
2239 ?*\(?*\)) # name(section)
2240 mdf_name="$(echo1 "${mdf_spec}" \
2241 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2242 mdf_section="$(echo1 "${mdf_spec}" \
2243 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2245 ?*.[0-9on]) # name.section
2246 mdf_name="$(echo1 "${mdf_spec}" \
2247 | sed -e 's/^\(..*\)\..$/\1/')";
2248 mdf_section="$(echo1 "${mdf_spec}" \
2249 | sed -e 's/^.*\(.\)$/\1/')";
2252 mdf_name="${mdf_spec}";
2254 esac;
2255 if obj mdf_name is_empty
2256 then
2257 eval ${_UNSET} mdf_got_one;
2258 eval ${_UNSET} mdf_name;
2259 eval ${_UNSET} mdf_section;
2260 eval ${_UNSET} mdf_spec;
2261 eval "${return_bad}";
2263 mdf_got_one='no';
2264 if obj mdf_section is_empty
2265 then
2266 eval set x "${_MAN_AUTO_SEC}";
2267 shift;
2268 for s
2270 mdf_s="$s";
2271 if man_search_section "${mdf_name}" "${mdf_s}"
2272 then # found
2273 if obj _MAN_ALL is_yes
2274 then
2275 mdf_got_one='yes';
2276 else
2277 eval ${_UNSET} mdf_got_one;
2278 eval ${_UNSET} mdf_name;
2279 eval ${_UNSET} mdf_s;
2280 eval ${_UNSET} mdf_section;
2281 eval ${_UNSET} mdf_spec;
2282 eval "${return_good}";
2285 done;
2286 else
2287 if man_search_section "${mdf_name}" "${mdf_section}"
2288 then
2289 eval ${_UNSET} mdf_got_one;
2290 eval ${_UNSET} mdf_name;
2291 eval ${_UNSET} mdf_s;
2292 eval ${_UNSET} mdf_section;
2293 eval ${_UNSET} mdf_spec;
2294 eval "${return_good}";
2295 else
2296 eval ${_UNSET} mdf_got_one;
2297 eval ${_UNSET} mdf_name;
2298 eval ${_UNSET} mdf_section;
2299 eval ${_UNSET} mdf_spec;
2300 eval "${return_bad}";
2303 if obj _MAN_ALL is_yes && is_yes "${mdf_got_one}"
2304 then
2305 eval ${_UNSET} mdf_got_one;
2306 eval ${_UNSET} mdf_name;
2307 eval ${_UNSET} mdf_s;
2308 eval ${_UNSET} mdf_section;
2309 eval ${_UNSET} mdf_spec;
2310 eval "${return_good}";
2312 eval ${_UNSET} mdf_got_one;
2313 eval ${_UNSET} mdf_name;
2314 eval ${_UNSET} mdf_s;
2315 eval ${_UNSET} mdf_section;
2316 eval ${_UNSET} mdf_spec;
2317 eval "${return_bad}";
2318 } # man_do_filespec()
2321 ########################################################################
2322 # man_register_file (<file> <name> [<section>])
2324 # Write a found man page file and register the title element.
2326 # Arguments: 1, 2, or 3; maybe empty
2327 # Output: none
2329 man_register_file()
2331 func_check man_register_file '>=' 2 "$@";
2332 case "$#" in
2333 2|3) do_nothing; ;;
2335 error "man_register_file() expects 2 or 3 arguments.";
2337 esac;
2338 if is_empty "$1"
2339 then
2340 error 'man_register_file(): file name is empty';
2342 to_tmp "$1";
2343 case "$#" in
2345 register_title "man:$2";
2346 eval "${return_ok}";
2349 register_title "$2.$3";
2350 eval "${return_ok}";
2352 esac;
2353 eval "${return_ok}";
2357 ########################################################################
2358 # man_search_section (<name> <section>)
2360 # Retrieve man pages.
2362 # Arguments : 2
2363 # Globals : $_MAN_PATH, $_MAN_EXT
2364 # Return : 0 if found, 1 otherwise
2366 # Variable prefix: mss
2368 man_search_section()
2370 func_check man_search_section = 2 "$@";
2371 if obj _MAN_PATH is_empty
2372 then
2373 eval "${return_bad}";
2375 if is_empty "$1"
2376 then
2377 eval "${return_bad}";
2379 if is_empty "$2"
2380 then
2381 eval "${return_bad}";
2383 mss_name="$1";
2384 mss_section="$2";
2385 eval set x "$(path_split "${_MAN_PATH}")";
2386 shift;
2387 mss_got_one='no';
2388 if obj _MAN_EXT is_empty
2389 then
2390 for d
2392 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2393 if obj mss_dir is_dir
2394 then
2395 mss_prefix="$(\
2396 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2397 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2398 sed -e '\| found|s|.*||'
2400 if obj mss_files is_not_empty
2401 then
2402 # for f in $mss_files
2403 for f in $(eval set x ${mss_files}; shift; echo "$@")
2405 mss_f="$f";
2406 if obj mss_f is_file
2407 then
2408 if is_yes "${mss_got_one}"
2409 then
2410 register_file "${mss_f}";
2411 elif obj _MAN_ALL is_yes
2412 then
2413 man_register_file "${mss_f}" "${mss_name}";
2414 else
2415 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2416 eval ${_UNSET} mss_dir;
2417 eval ${_UNSET} mss_ext;
2418 eval ${_UNSET} mss_f;
2419 eval ${_UNSET} mss_files;
2420 eval ${_UNSET} mss_got_one;
2421 eval ${_UNSET} mss_name;
2422 eval ${_UNSET} mss_prefix;
2423 eval ${_UNSET} mss_section;
2424 eval "${return_good}";
2426 mss_got_one='yes';
2428 done;
2431 done;
2432 else
2433 mss_ext="${_MAN_EXT}";
2434 # check for directory name having trailing extension
2435 for d
2437 mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";
2438 if obj mss_dir is_dir
2439 then
2440 mss_prefix=\
2441 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2442 mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2443 sed -e '\|not found|s|.*||'
2445 if obj mss_files is_not_empty
2446 then
2447 # for f in $mss_files
2448 for f in $(eval set x ${mss_files}; shift; echo "$@")
2450 mss_f="$f";
2451 if obj mss_f is_file
2452 then
2453 if is_yes "${mss_got_one}"
2454 then
2455 register_file "${mss_f}";
2456 elif obj _MAN_ALL is_yes
2457 then
2458 man_register_file "${mss_f}" "${mss_name}";
2459 else
2460 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2461 eval ${_UNSET} mss_dir;
2462 eval ${_UNSET} mss_ext;
2463 eval ${_UNSET} mss_f;
2464 eval ${_UNSET} mss_files;
2465 eval ${_UNSET} mss_got_one;
2466 eval ${_UNSET} mss_name;
2467 eval ${_UNSET} mss_prefix;
2468 eval ${_UNSET} mss_section;
2469 eval "${return_good}";
2471 mss_got_one='yes';
2473 done;
2476 done;
2477 # check for files with extension in directories without extension
2478 for d
2480 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2481 if obj mss_dir is_dir
2482 then
2483 mss_prefix="$(dirname_append "${mss_dir}" \
2484 "${mss_name}.${mss_section}${mss_ext}")";
2485 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2486 sed -e '\|not found|s|.*||'
2488 if obj mss_files is_not_empty
2489 then
2490 # for f in $mss_files
2491 for f in $(eval set x ${mss_files}; shift; echo "$@")
2493 mss_f="$f";
2494 if obj mss_f is_file
2495 then
2496 if is_yes "${mss_got_one}"
2497 then
2498 register_file "${mss_f}";
2499 elif obj _MAN_ALL is_yes
2500 then
2501 man_register_file "${mss_f}" "${mss_name}";
2502 else
2503 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2504 eval ${_UNSET} mss_dir;
2505 eval ${_UNSET} mss_ext;
2506 eval ${_UNSET} mss_f;
2507 eval ${_UNSET} mss_files;
2508 eval ${_UNSET} mss_got_one;
2509 eval ${_UNSET} mss_name;
2510 eval ${_UNSET} mss_prefix;
2511 eval ${_UNSET} mss_section;
2512 eval "${return_good}";
2514 mss_got_one='yes';
2516 done;
2519 done;
2521 if obj _MAN_ALL is_yes && is_yes "${mss_got_one}"
2522 then
2523 eval ${_UNSET} mss_dir;
2524 eval ${_UNSET} mss_ext;
2525 eval ${_UNSET} mss_f;
2526 eval ${_UNSET} mss_files;
2527 eval ${_UNSET} mss_got_one;
2528 eval ${_UNSET} mss_name;
2529 eval ${_UNSET} mss_prefix;
2530 eval ${_UNSET} mss_section;
2531 eval "${return_good}";
2533 eval ${_UNSET} mss_dir;
2534 eval ${_UNSET} mss_ext;
2535 eval ${_UNSET} mss_f;
2536 eval ${_UNSET} mss_files;
2537 eval ${_UNSET} mss_got_one;
2538 eval ${_UNSET} mss_name;
2539 eval ${_UNSET} mss_prefix;
2540 eval ${_UNSET} mss_section;
2541 eval "${return_bad}";
2542 } # man_search_section()
2545 ########################################################################
2546 # man_setup ()
2548 # Setup the variables $_MAN_* needed for man page searching.
2550 # Globals:
2551 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2552 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2553 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2554 # $_MAN_SEC, $_MAN_ALL
2555 # in/out: $_MAN_ENABLE
2557 # The precedence for the variables related to `man' is that of GNU
2558 # `man', i.e.
2560 # $LANG; overridden by
2561 # $LC_MESSAGES; overridden by
2562 # $LC_ALL; this has the same precedence as
2563 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2564 # $MANOPT; overridden by
2565 # the groffer command line options.
2567 # Variable prefix: ms
2569 man_setup()
2571 func_check main_man_setup = 0 "$@";
2573 if obj _MAN_IS_SETUP is_yes
2574 then
2575 eval "${return_ok}";
2577 _MAN_IS_SETUP='yes';
2579 if obj _MAN_ENABLE is_not_yes
2580 then
2581 eval "${return_ok}";
2584 # determine basic path for man pages
2585 _MAN_PATH="$(get_first_essential \
2586 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2587 if obj _MAN_PATH is_empty
2588 then
2589 manpath_set_from_path;
2590 else
2591 _MAN_PATH="$(path_clean "${_MAN_PATH}")";
2593 if obj _MAN_PATH is_empty
2594 then
2595 if is_prog 'manpath'
2596 then
2597 _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available
2600 if obj _MAN_PATH is_empty
2601 then
2602 _MAN_ENABLE="no";
2603 eval "${return_ok}";
2606 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2607 if obj _MAN_ALL is_empty
2608 then
2609 _MAN_ALL='no';
2612 _MAN_SYS="$(get_first_essential \
2613 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2614 ms_lang="$(get_first_essential \
2615 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2616 case "${ms_lang}" in
2617 C|POSIX)
2618 _MAN_LANG="";
2619 _MAN_LANG2="";
2622 _MAN_LANG="${ms_lang}";
2623 _MAN_LANG2="";
2626 _MAN_LANG="${ms_lang}";
2627 # get first two characters of $ms_lang
2628 _MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')";
2630 esac;
2631 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2633 manpath_add_lang_sys; # this is very slow
2635 _MAN_SEC="$(get_first_essential \
2636 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2637 if obj _MAN_PATH is_empty
2638 then
2639 _MAN_ENABLE="no";
2640 eval ${_UNSET} ms_lang;
2641 eval "${return_ok}";
2644 _MAN_EXT="$(get_first_essential \
2645 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2646 eval ${_UNSET} ms_lang;
2647 eval "${return_ok}";
2648 } # man_setup()
2651 ########################################################################
2652 landmark '8: manpath_*()';
2653 ########################################################################
2655 ########################################################################
2656 # manpath_add_lang_sys ()
2658 # Add language and operating system specific directories to man path.
2660 # Arguments : 0
2661 # Output : none
2662 # Globals:
2663 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2664 # list of names of operating systems.
2665 # $_MAN_LANG and $_MAN_LANG2: each a single name
2666 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2667 # separated list of directories.
2669 # Variable prefix: mals
2671 manpath_add_lang_sys()
2673 func_check manpath_add_lang_sys = 0 "$@";
2674 if obj _MAN_PATH is_empty
2675 then
2676 eval "${return_ok}";
2678 # twice test both sys and lang
2679 eval set x "$(path_split "${_MAN_PATH}")";
2680 shift;
2681 mals_mp='';
2682 for p
2683 do # loop on man path directories
2684 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2685 done;
2686 eval set x "$(path_split "${mals_mp}")";
2687 shift;
2688 for p
2689 do # loop on man path directories
2690 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2691 done;
2692 _MAN_PATH="$(path_chop "${mals_mp}")";
2693 eval ${_UNSET} mals_mp;
2694 eval "${return_ok}";
2698 # To the directory in $1 append existing sys/lang subdirectories
2699 # Function is necessary to split the OS list.
2701 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2702 # argument: 2: `man_path' and `dir'
2703 # output: colon-separated path of the retrieved subdirectories
2705 # Variable prefix: _mals
2707 _manpath_add_lang_sys_single()
2709 func_check _manpath_add_lang_sys_single = 2 "$@";
2710 _mals_res="$1";
2711 _mals_parent="$2";
2712 eval set x "$(list_from_split "${_MAN_SYS}" ',')";
2713 shift;
2714 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
2716 _mals_dir="$(dirname_append "${_mals_parent}" "$d")";
2717 if obj _mals_res path_not_contains "${_mals_dir}" && \
2718 obj _mals_dir is_dir
2719 then
2720 _mals_res="${_mals_res}:${_mals_dir}";
2722 done;
2723 if path_not_contains "${_mals_res}" "${_mals_parent}"
2724 then
2725 _mals_res="${_mals_res}:${_mals_parent}";
2727 path_chop "${_mals_res}";
2728 eval ${_UNSET} _mals_dir;
2729 eval ${_UNSET} _mals_parent;
2730 eval ${_UNSET} _mals_res;
2731 eval "${return_ok}";
2734 # end manpath_add_lang_sys ()
2737 ########################################################################
2738 # manpath_set_from_path ()
2740 # Determine basic search path for man pages from $PATH.
2742 # Return: `0' if a valid man path was retrieved.
2743 # Output: none
2744 # Globals:
2745 # in: $PATH
2746 # out: $_MAN_PATH
2748 # Variable prefix: msfp
2750 manpath_set_from_path()
2752 func_check manpath_set_from_path = 0 "$@";
2754 msfp_manpath='';
2756 # get a basic man path from $PATH
2757 if obj PATH is_not_empty
2758 then
2759 eval set x "$(path_split "${PATH}")";
2760 shift;
2761 for d
2763 # delete the final `/bin' part
2764 msfp_base="$(echo1 "$d" | sed -e 's|//*bin/*$||')";
2765 for e in /share/man /man
2767 msfp_mandir="${msfp_base}$e";
2768 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}"
2769 then
2770 msfp_manpath="${msfp_manpath}:${msfp_mandir}";
2772 done;
2773 done;
2776 # append some default directories
2777 for d in /usr/local/share/man /usr/local/man \
2778 /usr/share/man /usr/man \
2779 /usr/X11R6/man /usr/openwin/man \
2780 /opt/share/man /opt/man \
2781 /opt/gnome/man /opt/kde/man
2783 msfp_d="$d";
2784 if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir
2785 then
2786 msfp_manpath="${msfp_manpath}:${mfsp_d}";
2788 done;
2790 _MAN_PATH="${msfp_manpath}";
2791 eval ${_UNSET} msfp_base;
2792 eval ${_UNSET} msfp_d;
2793 eval ${_UNSET} msfp_mandir;
2794 eval ${_UNSET} msfp_manpath;
2795 eval "${return_ok}";
2796 } # manpath_set_from_path()
2799 ########################################################################
2800 landmark '9: obj_*()';
2801 ########################################################################
2803 ########################################################################
2804 # obj (<object> <call_name> <arg>...)
2806 # This works like a method (object function) call for an object.
2807 # Run "<call_name> $<object> <arg> ...".
2809 # The first argument represents an object whose data is given as first
2810 # argument to <call_name>().
2812 # Argument: >=2
2813 # <object>: variable name
2814 # <call_name>: a program or function name
2816 # Variable prefix: o
2818 obj()
2820 func_check obj '>=' 2 "$@";
2821 if is_empty "$2"
2822 then
2823 error "obj(): function name is empty."
2824 else
2825 o_func="$2";
2827 eval o_arg1='"${'$1'}"';
2828 shift;
2829 shift;
2830 eval "${o_func}"' "${o_arg1}" "$@"';
2831 n="$?";
2832 eval ${_UNSET} o_arg1;
2833 eval ${_UNSET} o_func;
2834 eval "${return_var} $n";
2835 } # obj()
2838 ########################################################################
2839 # obj_data (<object>)
2841 # Print the data of <object>, i.e. the content of $<object>.
2842 # For possible later extensions.
2844 # Arguments: 1
2845 # <object>: a variable name
2846 # Output: the data of <object>
2848 # Variable prefix: od
2850 obj_data()
2852 func_check obj '=' 1 "$@";
2853 if is_empty "$1"
2854 then
2855 error "obj_data(): object name is empty."
2857 eval od_res='"${'$1'}"';
2858 obj od_res echo1;
2859 eval ${_UNSET} od_res;
2860 eval "${return_ok}";
2864 ########################################################################
2865 # obj_from_output (<object> <call_name> <arg>...)
2867 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2868 # function call to a global variable.
2870 # Arguments: >=2
2871 # <object>: a variable name
2872 # <call_name>: the name of a function or program
2873 # <arg>: optional argument to <call_name>
2874 # Output: none
2876 # Variable prefix: ofo
2878 obj_from_output()
2880 func_check obj_from_output '>=' 2 "$@";
2881 if is_empty "$1"
2882 then
2883 error "res(): variable name is empty.";
2884 elif is_empty "$2"
2885 then
2886 error "res(): function name is empty."
2887 else
2888 ofo_result_name="$1";
2890 shift;
2891 eval "${ofo_result_name}"'="$('"$@"')"';
2892 eval "${return_ok}";
2896 ########################################################################
2897 # obj_set (<object> <data>)
2899 # Set the data of <object>, i.e. call "$<object>=<data>".
2901 # Arguments: 2
2902 # <object>: a variable name
2903 # <data>: a string
2904 # Output:: none
2906 obj_set()
2908 func_check obj_set '=' 2 "$@";
2909 if is_empty "$1"
2910 then
2911 error "obj_set(): object name is empty."
2913 eval "$1"='"$2"';
2914 eval "${return_ok}";
2918 ########################################################################
2919 # path_chop (<path>)
2921 # Remove unnecessary colons from path.
2923 # Argument: 1, a colon separated path.
2924 # Output: path without leading, double, or trailing colons.
2926 path_chop()
2928 func_check path_chop = 1 "$@";
2930 # replace multiple colons by a single colon `:'
2931 # remove leading and trailing colons
2932 echo1 "$1" | sed -e '
2933 s/^:*//
2934 s/:::*/:/g
2935 s/:*$//
2937 eval "${return_ok}";
2941 ########################################################################
2942 # path_clean (<path>)
2944 # Remove non-existing directories from a colon-separated list.
2946 # Argument: 1, a colon separated path.
2947 # Output: colon-separated list of existing directories.
2949 # Variable prefix: pc
2951 path_clean()
2953 func_check path_clean = 1 "$@";
2954 if is_not_equal "$#" 1
2955 then
2956 error 'path_clean() needs 1 argument.';
2958 pc_arg="$1";
2959 eval set x "$(path_split "${pc_arg}")";
2960 shift;
2961 pc_res="";
2962 for i
2964 pc_i="$i";
2965 if obj pc_i is_not_empty \
2966 && obj pc_res path_not_contains "${pc_i}" \
2967 && obj pc_i is_dir
2968 then
2969 case "${pc_i}" in
2970 ?*/) pc_res="${pc_res}$(dirname_chop "${pc_i}")"; ;;
2971 *) pc_res="${pc_res}:${pc_i}";
2972 esac;
2974 done;
2975 eval ${_UNSET} pc_arg;
2976 eval ${_UNSET} pc_i;
2977 eval ${_UNSET} pc_res;
2978 if path_chop "${pc_res}"
2979 then
2980 eval "${return_ok}";
2981 else
2982 eval "${return_bad}";
2987 ########################################################################
2988 # path_contains (<path> <dir>)
2990 # Test whether `dir' is contained in `path', a list separated by `:'.
2992 # Arguments : 2 arguments.
2993 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2995 path_contains()
2997 func_check path_contains = 2 "$@";
2998 case ":$1:" in
2999 *":$2:"*)
3000 eval "${return_yes}";
3003 eval "${return_no}";
3005 esac;
3006 eval "${return_ok}";
3010 ########################################################################
3011 # path_not_contains (<path> <dir>)
3013 # Test whether `dir' is not contained in colon separated `path'.
3015 # Arguments : 2 arguments.
3017 path_not_contains()
3019 func_check path_not_contains = 2 "$@";
3020 if path_contains "$1" "$2"
3021 then
3022 eval "${return_no}";
3023 else
3024 eval "${return_yes}";
3026 eval "${return_ok}";
3030 ########################################################################
3031 # path_split (<path>)
3033 # In `path' escape white space and replace each colon by a space.
3035 # Arguments: 1: a colon-separated path
3036 # Output: the resulting list, process with `eval set'
3038 path_split()
3040 func_check path_split = 1 "$@";
3041 list_from_split "$1" ':';
3042 eval "${return_ok}";
3046 ########################################################################
3047 landmark '10: register_*()';
3048 ########################################################################
3050 ########################################################################
3051 # register_file (<filename>)
3053 # Write a found file and register the title element.
3055 # Arguments: 1: a file name
3056 # Output: none
3058 register_file()
3060 func_check register_file = 1 "$@";
3061 if is_empty "$1"
3062 then
3063 error 'register_file(): file name is empty';
3065 if is_equal "$1" '-'
3066 then
3067 to_tmp "${_TMP_STDIN}";
3068 register_title 'stdin';
3069 else
3070 to_tmp "$1";
3071 register_title "$(base_name "$1")";
3073 eval "${return_ok}";
3077 ########################################################################
3078 # register_title (<filespec>)
3080 # Create title element from <filespec> and append to $_REGISTERED_TITLE
3082 # Globals: $_REGISTERED_TITLE (rw)
3084 # Variable prefix: rt
3086 register_title()
3088 func_check register_title '=' 1 "$@";
3089 if is_empty "$1"
3090 then
3091 eval "${return_ok}";
3093 rt_title="$(base_name "$1")"; # remove directory part
3095 # replace space characters by `_'
3096 rt_title="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')";
3097 # remove extension `.gz'
3098 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')";
3099 # remove extension `.Z'
3100 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')";
3102 if obj rt_title is_empty
3103 then
3104 eval "${return_ok}";
3106 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";
3107 eval ${_UNSET} rt_title;
3108 eval "${return_ok}";
3112 ########################################################################
3113 # reset ()
3115 # Reset the variables that can be affected by options to their default.
3118 # Defined in section `Preset' after the rudimentary shell tests.
3121 ########################################################################
3122 # rm_file (<file_name>)
3124 # Remove file if $_DEBUG_KEEP_FILES allows it.
3126 # Globals: $_DEBUG_KEEP_FILES
3128 rm_file()
3130 func_check rm_file '=' 1 "$@";
3131 if is_file "$1"
3132 then
3133 rm -f "$1" >${_NULL_DEV} 2>&1;
3135 if is_existing "$1"
3136 then
3137 eval "${return_bad}";
3138 else
3139 eval "${return_good}";
3144 ########################################################################
3145 # rm_file_with_debug (<file_name>)
3147 # Remove file if $_DEBUG_KEEP_FILES allows it.
3149 # Globals: $_DEBUG_KEEP_FILES
3151 rm_file_with_debug()
3153 func_check rm_file_with_debug '=' 1 "$@";
3154 if obj _DEBUG_KEEP_FILES is_not_yes
3155 then
3156 if is_file "$1"
3157 then
3158 rm -f "$1" >${_NULL_DEV} 2>&1;
3161 if is_existing "$1"
3162 then
3163 eval "${return_bad}";
3164 else
3165 eval "${return_good}";
3170 ########################################################################
3171 # rm_tree (<dir_name>)
3173 # Remove file if $_DEBUG_KEEP_FILES allows it.
3175 # Globals: $_DEBUG_KEEP_FILES
3177 rm_tree()
3179 func_check rm_tree '=' 1 "$@";
3180 if is_existing "$1"
3181 then
3182 rm -f -r "$1" >${_NULL_DEV} 2>&1;
3183 fi;
3184 if is_existing "$1"
3185 then
3186 eval "${return_bad}";
3187 else
3188 eval "${return_good}";
3193 ########################################################################
3194 # save_stdin ()
3196 # Store standard input to temporary file (with decompression).
3198 # Variable prefix: ss
3200 if obj _HAS_COMPRESSION is_yes
3201 then
3202 save_stdin()
3204 func_check save_stdin '=' 0 "$@";
3205 ss_f="${_TMP_DIR}"/INPUT;
3206 cat >"${ss_f}";
3207 cat_z "${ss_f}" >"${_TMP_STDIN}";
3208 rm_file "${ss_f}";
3209 eval ${_UNSET} ss_f;
3210 eval "${return_ok}";
3212 else
3213 save_stdin()
3215 func_check save_stdin = 0 "$@";
3216 cat >"${_TMP_STDIN}";
3217 eval "${return_ok}";
3222 ########################################################################
3223 landmark '11: stack_*()';
3224 ########################################################################
3226 ########################################################################
3227 # string_contains (<string> <part>)
3229 # Test whether `part' is contained in `string'.
3231 # Arguments : 2 text arguments.
3232 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3234 string_contains()
3236 func_check string_contains '=' 2 "$@";
3237 case "$1" in
3238 *"$2"*)
3239 eval "${return_yes}";
3242 eval "${return_no}";
3244 esac;
3245 eval "${return_ok}";
3249 ########################################################################
3250 # string_not_contains (<string> <part>)
3252 # Test whether `part' is not substring of `string'.
3254 # Arguments : 2 text arguments.
3255 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3257 string_not_contains()
3259 func_check string_not_contains '=' 2 "$@";
3260 if string_contains "$1" "$2"
3261 then
3262 eval "${return_no}";
3263 else
3264 eval "${return_yes}";
3266 eval "${return_ok}";
3270 ########################################################################
3271 landmark '12: tmp_*()';
3272 ########################################################################
3274 ########################################################################
3275 # tmp_cat ()
3277 # output the temporary cat file (the concatenation of all input)
3279 tmp_cat()
3281 func_check tmp_cat '=' 0 "$@";
3282 cat "${_TMP_CAT}";
3283 eval "${return_var}" "$?";
3287 ########################################################################
3288 # tmp_create (<suffix>?)
3290 # Create temporary file.
3292 # It's safe to use the shell process ID together with a suffix to
3293 # have multiple temporary files.
3295 # Globals: $_TMP_DIR
3297 # Output : name of created file
3299 # Variable prefix: tc
3301 tmp_create()
3303 func_check tmp_create '<=' 1 "$@";
3304 # the output file does not have `,' as first character, so these are
3305 # different names from the output file.
3306 tc_tmp="${_TMP_DIR}/,$1";
3307 : >"${tc_tmp}"
3308 obj tc_tmp echo1;
3309 eval ${_UNSET} tc_tmp;
3310 eval "${return_ok}";
3314 ########################################################################
3315 # to_tmp (<filename>)
3317 # print file (decompressed) to the temporary cat file
3319 to_tmp()
3321 func_check to_tmp = 1 "$@";
3322 if is_file "$1"
3323 then
3324 if obj _OPT_LOCATION is_yes
3325 then
3326 echo2 "$1";
3328 if obj _OPT_WHATIS is_yes
3329 then
3330 what_is "$1" >>"${_TMP_CAT}";
3331 else
3332 cat_z "$1" >>"${_TMP_CAT}";
3334 else
3335 error "to_tmp(): could not read file \`$1'.";
3337 eval "${return_ok}";
3341 ########################################################################
3342 # trap_clean ()
3344 # disable trap on all exit codes ($_ALL_EXIT)
3346 # Arguments: 0
3347 # Globals: $_ALL_EXIT
3349 trap_clean()
3351 func_check trap_clean = 0 "$@";
3352 # for i in $_ALL_EXIT
3353 for i in $(eval set x "${_ALL_EXIT}"; shift; echo "$@")
3355 trap "" "$i" 2>${_NULL_DEV} || :;
3356 done;
3357 eval "${return_ok}";
3361 ########################################################################
3362 # trap_set (<functionname>)
3364 # call function on all exit codes ($_ALL_EXIT)
3366 # Arguments: 1 (name of a shell function)
3367 # Globals: $_ALL_EXIT
3369 trap_set()
3371 func_check trap_set = 1 "$@";
3372 # for i in $_ALL_EXIT
3373 for i in $(eval set x "${_ALL_EXIT}"; shift; echo "$@")
3375 trap "$1" "$i" 2>${_NULL_DEV} || :;
3376 done;
3377 eval "${return_ok}";
3381 ########################################################################
3382 # usage ()
3384 # print usage information to stderr; for groffer option --help.
3386 usage()
3388 func_check usage = 0 "$@";
3389 echo;
3390 version;
3391 echo 'Usage: groffer [option]... [filespec]...';
3392 cat <<EOF
3394 Display roff files, standard input, and/or Unix manual pages with a X
3395 Window viewer or in several text modes. All input is decompressed
3396 on-the-fly with all formats that gzip can handle.
3398 "filespec" is one of
3399 "filename" name of a readable file
3400 "-" for standard input
3401 "man:name.n" man page "name" in section "n"
3402 "man:name" man page "name" in first section found
3403 "name.n" man page "name" in section "n"
3404 "name" man page "name" in first section found
3405 and some more (see groffer(1) for details).
3407 -h --help print this usage message.
3408 -Q --source output as roff source.
3409 -T --device=name pass to groff using output device "name".
3410 -v --version print version information.
3411 -V display the groff execution pipe instead of formatting.
3412 -X display with "gxditview" using groff -X.
3413 -Z --ditroff --intermediate-output
3414 generate groff intermediate output without
3415 post-processing and viewing, like groff -Z.
3416 All other short options are interpreted as "groff" formatting options.
3418 The most important groffer long options are
3420 --apropos=name start man's "apropos" program for "name".
3421 --apropos-data=name
3422 "apropos" for "name" in man's data sections 4, 5, 7.
3423 --apropos-devel=name
3424 "apropos" for "name" in development sections 2, 3, 9.
3425 --apropos-progs=name
3426 "apropos" for "name" in man's program sections 1, 6, 8.
3427 --auto choose mode automatically from the default mode list.
3428 --default reset all options to the default value.
3429 --default-modes=mode1,mode2,...
3430 set sequence of automatically tried modes.
3431 --dvi display in a viewer for TeX device independent format.
3432 --dvi-viewer=prog choose the viewer program for dvi mode.
3433 --groff process like groff, disable viewing features.
3434 --help display this helping output.
3435 --html display in a web browser.
3436 --html-viewer=program
3437 choose the web browser for html mode.
3438 --man check file parameters first whether they are man pages.
3439 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3440 choose display mode.
3441 --no-man disable man-page facility.
3442 --pager=program preset the paging program for tty mode.
3443 --pdf display in a PDF viewer.
3444 --pdf-viewer=prog choose the viewer program for pdf mode.
3445 --ps display in a Postscript viewer.
3446 --ps-viewer=prog choose the viewer program for ps mode.
3447 --shell=program specify shell under which to run groffer2.sh.
3448 --text output in a text device without a pager.
3449 --tty display with a pager on text terminal even when in X.
3450 --tty-viewer=prog select a pager for tty mode; same as --pager.
3451 --www same as --html.
3452 --www-viewer=prog same as --html-viewer
3453 --x --X display with "gxditview" using an X* device.
3454 --x-viewer=prog choose viewer program for x mode (X mode).
3455 --X-viewer=prog same as "--xviewer".
3457 The usual X Windows toolkit options transformed into GNU long options
3458 --background=color, --bd=size, --bg=color, --bordercolor=color,
3459 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3460 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3461 --resolution=dpi, --rv, --title=text, --xrm=resource
3463 Long options of GNU "man"
3464 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3465 --local-file=name, --location, --manpath=dir1:dir2:...,
3466 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3469 eval "${return_ok}";
3473 ########################################################################
3474 # version ()
3476 # print version information to stderr
3478 version()
3480 func_check version = 0 "$@";
3481 echo2 "groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3482 # also display groff's version, but not the called subprograms
3483 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2;
3484 eval "${return_ok}";
3488 ########################################################################
3489 # warning (<string>)
3491 # Print warning to stderr
3493 warning()
3495 echo2 "warning: $*";
3499 ########################################################################
3500 # what_is (<filename>)
3502 # Interpret <filename> as a man page and display its `whatis'
3503 # information as a fragment written in the groff language.
3505 # Variable prefix: wi
3507 what_is()
3509 func_check what_is = 1 "$@";
3510 if is_not_file "$1"
3511 then
3512 error "what_is(): argument is not a readable file."
3514 wi_dot='^\.['"${_SP}${_TAB}"']*';
3515 cat <<EOF
3520 # grep the line containing `.TH' macro, if any
3521 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'TH /p
3522 d')";
3523 if obj wi_res is_not_empty
3524 then # traditional man style
3525 # get the text between the first and the second `.SH' macro, by
3526 # - delete up to first .SH;
3527 # - of this, print everything up to next .SH, and delete the rest;
3528 # - of this, delete the final .SH line;
3529 cat_z "$1" | sed -e '1,/'"${wi_dot}"'SH/d' \
3530 | sed -e '1,/'"${wi_dot}"'SH/p
3531 d' \
3532 | sed -e '/'"${wi_dot}"'SH/d';
3533 eval ${_UNSET} wi_dot;
3534 eval ${_UNSET} wi_res;
3535 eval "${return_ok}";
3537 # grep the line containing `.Dd' macro, if any
3538 wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'Dd /p
3539 d')";
3540 if obj wi_res is_not_empty
3541 then # BSD doc style
3542 # get the text between the first and the second `.Nd' macro, by
3543 # - delete up to first .Nd;
3544 # - of this, print everything up to next .Nd, and delete the rest;
3545 # - of this, delete the final .Nd line;
3546 cat_z "$1" | sed -e '1,/'"${wi_dot}"'Nd/d' \
3547 | sed -e '1,/'"${wi_dot}"'Nd/p
3548 d' \
3549 | sed -e '/'"${wi_dot}"'Nd/d';
3550 eval ${_UNSET} wi_dot;
3551 eval ${_UNSET} wi_res;
3552 eval "${return_ok}";
3554 echo 'is not a man page.';
3555 eval ${_UNSET} wi_dot;
3556 eval ${_UNSET} wi_res;
3557 eval "${return_bad}";
3561 ########################################################################
3562 # where_is (<program>)
3564 # Output path of a program if in $PATH.
3566 # Arguments : >=1 (empty allowed)
3567 # more args are ignored, this allows to specify progs with arguments
3568 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3570 # Variable prefix: w
3572 where_is()
3574 func_check where_is '>=' 1 "$@";
3575 w_arg="$1";
3576 if obj w_arg is_empty
3577 then
3578 eval ${_UNSET} w_arg;
3579 eval "${return_bad}";
3581 case "${w_arg}" in
3583 eval ${_UNSET} w_arg;
3584 eval ${_UNSET} w_file;
3585 if test -f "${w_arg}" && test -x "${w_arg}"
3586 then
3587 eval "${return_ok}";
3588 else
3589 eval "${return_bad}";
3592 esac;
3593 eval set x "$(path_split "${PATH}")";
3594 shift;
3595 for p
3597 case "$p" in
3598 */) w_file=${p}${w_arg}; ;;
3599 *) w_file=${p}/${w_arg}; ;;
3600 esac;
3601 if test -f "${w_file}" && test -x "${w_file}"
3602 then
3603 obj w_file echo1;
3604 eval ${_UNSET} w_arg;
3605 eval ${_UNSET} w_file;
3606 eval "${return_ok}";
3608 done;
3609 eval ${_UNSET} w_arg;
3610 eval ${_UNSET} w_file;
3611 eval "${return_bad}";
3615 ########################################################################
3616 # main* Functions
3617 ########################################################################
3619 # The main area contains the following parts:
3620 # - main_init(): initialize temporary files and set exit trap
3621 # - main_parse_MANOPT(): parse $MANOPT
3622 # - main_parse_args(): argument parsing
3623 # - main_set_mode (): determine the display mode
3624 # - main_do_fileargs(): process filespec arguments
3625 # - main_set_resources(): setup X resources
3626 # - main_display(): do the displaying
3627 # - main(): the main function that calls all main_*()
3629 # These parts are implemented as functions, being defined below in the
3630 # sequence they are called in the main() function.
3633 #######################################################################
3634 # main_init ()
3636 # set exit trap and create temporary files
3638 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3640 # Variable prefix: mi
3642 main_init()
3644 func_check main_init = 0 "$@";
3645 # call clean_up() on any signal
3646 trap_set clean_up;
3648 # create temporary directory
3649 umask 0022;
3650 _TMP_DIR='';
3651 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3652 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
3654 mi_dir="$d";
3655 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
3656 obj mi_dir is_not_writable
3657 then
3658 continue;
3661 case "${mi_dir}" in
3663 _TMP_DIR="${mi_dir}";
3666 _TMP_DIR="${mi_dir}"'/';
3668 esac;
3669 _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}";
3670 if obj _TMP_DIR rm_tree
3671 then
3673 else
3674 mi_tdir_="${_TMP_DIR}"_;
3675 mi_n=1;
3676 mi_tdir_n="${mi_tdir_}${mi_n}";
3677 while obj mi_tdir_n is_existing
3679 if obj mi_tdir_n rm_tree
3680 then
3681 # directory could not be removed
3682 mi_n="$(expr "${mi_n}" + 1)";
3683 mi_tdir_n="${mi_tdir_}${mi_n}";
3684 continue;
3686 done;
3687 _TMP_DIR="${mi_tdir_n}";
3689 eval mkdir "${_TMP_DIR}";
3690 if is_not_equal "$?" 0
3691 then
3692 obj _TMP_DIR rm_tree;
3693 _TMP_DIR='';
3694 continue;
3696 if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable
3697 then
3698 # $_TMP_DIR can now be used as temporary directory
3699 break;
3701 obj _TMP_DIR rm_tree;
3702 _TMP_DIR='';
3703 continue;
3704 done;
3705 if obj _TMP_DIR is_empty
3706 then
3707 error "main_init: \
3708 Couldn't create a directory for storing temporary files.";
3711 _TMP_CAT="$(tmp_create groffer_cat)";
3712 _TMP_STDIN="$(tmp_create groffer_input)";
3714 eval ${_UNSET} mi_dir;
3715 eval ${_UNSET} mi_n;
3716 eval ${_UNSET} mi_tdir_;
3717 eval ${_UNSET} mi_tdir_n;
3718 eval "${return_ok}";
3719 } # main_init()
3722 ########################################################################
3723 # main_parse_MANOPT ()
3725 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3726 # string; found man arguments can be overwritten by the command line.
3728 # Globals:
3729 # in: $MANOPT, $_OPTS_MANOPT_*
3730 # out: $_MANOPT_*
3731 # in/out: $GROFFER_OPT
3733 # Variable prefix: mpm
3735 main_parse_MANOPT()
3737 func_check main_parse_MANOPT = 0 "$@";
3739 if obj MANOPT is_not_empty
3740 then
3741 # Delete leading and final spaces
3742 MANOPT="$(echo1 "${MANOPT}" | sed -e '
3743 s/^['"${_SP}${_TAB}"']*//
3744 s/['"${_SP}${_TAB}"']*$//
3745 ')";
3747 if obj MANOPT is_empty
3748 then
3749 eval "${return_ok}";
3752 mpm_list='';
3753 # add arguments in $MANOPT by mapping them to groffer options
3754 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3755 shift;
3756 until test "$#" -le 0 || is_equal "$1" '--'
3758 mpm_opt="$1";
3759 shift;
3760 case "${mpm_opt}" in
3761 -7|--ascii)
3762 list_append mpm_list '--ascii';
3764 -a|--all)
3765 list_append mpm_list '--all';
3767 -c|--catman)
3768 do_nothing;
3769 shift;
3771 -d|--debug)
3772 do_nothing;
3774 -D|--default)
3775 # undo all man options so far
3776 mpm_list='';
3778 -e|--extension)
3779 list_append mpm_list '--extension';
3780 shift;
3782 -f|--whatis)
3783 list_append mpm_list '--whatis';
3784 shift;
3786 -h|--help)
3787 do_nothing;
3788 shift;
3790 -k|--apropos)
3791 # groffer's --apropos takes an argument, but man's does not, so
3792 do_nothing;
3794 -l|--local-file)
3795 do_nothing;
3797 -L|--locale)
3798 list_append mpm_list '--locale' "$1";
3799 shift;
3801 -m|--systems)
3802 list_append mpm_list '--systems' "$1";
3803 shift;
3805 -M|--manpath)
3806 list_append mpm_list '--manpath' "$1";
3807 shift;
3809 -p|--preprocessor)
3810 do_nothing;
3811 shift;
3813 -P|--pager)
3814 list_append mpm_list '--pager' "$1";
3815 shift;
3817 -r|--prompt)
3818 do_nothing;
3819 shift;
3821 -S|--sections)
3822 list_append mpm_list '--sections' "$1";
3823 shift;
3825 -t|--troff)
3826 do_nothing;
3827 shift;
3829 -T|--device)
3830 list_append mpm_list '-T' "$1";
3831 shift;
3833 -u|--update)
3834 do_nothing;
3835 shift;
3837 -V|--version)
3838 do_nothing;
3840 -w|--where|--location)
3841 list_append mpm_list '--location';
3843 -Z|--ditroff)
3844 do_nothing;
3846 # ignore all other options
3847 esac;
3848 done;
3850 # prepend $mpm_list to $GROFFER_OPT
3851 if obj GROFFER_OPT is_empty
3852 then
3853 GROFFER_OPT="${mpm_list}";
3854 elif obj mpm_list is_not_empty
3855 then
3856 GROFFER_OPT="${mpm_list} ${GROFFER_OPT}";
3859 eval ${_UNSET} mpm_list;
3860 eval ${_UNSET} mpm_opt;
3861 eval "${return_ok}";
3862 } # main_parse_MANOPT()
3865 ########################################################################
3866 # main_parse_args (<command_line_args>*)
3868 # Parse arguments; process options and filespec parameters
3870 # Arguments: pass the command line arguments unaltered.
3871 # Globals:
3872 # in: $_OPTS_*
3873 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3875 # Variable prefix: mpa
3877 main_parse_args()
3879 func_check main_parse_args '>=' 0 "$@";
3880 eval set x "${GROFFER_OPT}" '"$@"';
3881 shift;
3883 _ALL_PARAMS="$(list_from_cmdline _OPTS_CMDLINE "$@")";
3884 if obj _DEBUG_PRINT_PARAMS is_yes
3885 then
3886 echo2 "parameters: ${_ALL_PARAMS}";
3888 eval set x "${_ALL_PARAMS}";
3889 shift;
3891 # By the call of `eval', unnecessary quoting was removed. So the
3892 # positional shell parameters ($1, $2, ...) are now guaranteed to
3893 # represent an option or an argument to the previous option, if any;
3894 # then a `--' argument for separating options and
3895 # parameters; followed by the filespec parameters if any.
3897 # Note, the existence of arguments to options has already been checked.
3898 # So a check for `$#' or `--' should not be done for arguments.
3900 until test "$#" -le 0 || is_equal "$1" '--'
3902 mpa_opt="$1"; # $mpa_opt is fed into the option handler
3903 shift;
3904 case "${mpa_opt}" in
3905 -h|--help)
3906 usage;
3907 leave;
3909 -Q|--source) # output source code (`Quellcode').
3910 _OPT_MODE='source';
3912 -T|--device|--troff-device) # device; arg
3913 _OPT_DEVICE="$1";
3914 _check_device_with_mode;
3915 shift;
3917 -v|--version)
3918 version;
3919 leave;
3922 _OPT_V='yes';
3924 -Z|--ditroff|--intermediate-output) # groff intermediate output
3925 _OPT_Z='yes';
3928 _OPT_MODE=X;
3931 # delete leading `-'
3932 mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')";
3933 if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}"
3934 then
3935 list_append _ADDOPTS_GROFF "${mpa_opt}";
3936 elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}"
3937 then
3938 list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
3939 shift;
3940 else
3941 error "main_parse_args(): Unknown option : \`$1'";
3944 --all)
3945 _OPT_ALL="yes";
3947 --apropos) # run `apropos'
3948 apropos_run "$1";
3949 leave "$?";
3951 --apropos-data) # run `apropos' for data sections
3952 apropos_run "$1" | grep '^[^(]*([457][^)]*)';
3953 leave "$?";
3955 --apropos-devel) # run `apropos' for development sections
3956 apropos_run "$1" | grep '^[^(]*([239][^)]*)';
3957 leave "$?";
3959 --apropos-progs) # run `apropos' for program sections
3960 apropos_run "$1" | grep '^[^(]*([168][^)]*)';
3961 leave "$?";
3963 --ascii)
3964 list_append _ADDOPTS_GROFF '-mtty-char';
3965 if obj _OPT_MODE is_empty
3966 then
3967 _OPT_MODE='text';
3970 --auto) # the default automatic mode
3971 _OPT_MODE='';
3973 --bd) # border color for viewers, arg;
3974 _OPT_BD="$1";
3975 shift;
3977 --bg|--backgroud) # background color for viewers, arg;
3978 _OPT_BG="$1";
3979 shift;
3981 --bw) # border width for viewers, arg;
3982 _OPT_BW="$1";
3983 shift;
3985 --default) # reset variables to default
3986 reset;
3988 --default-modes) # sequence of modes in auto mode; arg
3989 _OPT_DEFAULT_MODES="$1";
3990 shift;
3992 --debug) # only for development
3993 _OPT_DEBUG='yes';
3995 --display) # set X display, arg
3996 _OPT_DISPLAY="$1";
3997 shift;
3999 --do-nothing)
4000 leave;
4002 --dvi)
4003 _OPT_MODE='dvi';
4005 --dvi-viewer) # viewer program for dvi mode; arg
4006 _OPT_VIEWER_DVI="$1";
4007 shift;
4009 --extension) # the extension for man pages, arg
4010 _OPT_EXTENSION="$1";
4011 shift;
4013 --fg|--foreground) # foreground color for viewers, arg;
4014 _OPT_FG="$1";
4015 shift;
4017 --fn|--font) # set font for viewers, arg;
4018 _OPT_FN="$1";
4019 shift;
4021 --geometry) # window geometry for viewers, arg;
4022 _OPT_GEOMETRY="$1";
4023 shift;
4025 --groff)
4026 _OPT_MODE='groff';
4028 --html|--www) # display with web browser
4029 _OPT_MODE=html;
4031 --html-viewer|--www-viewer) # viewer program for html mode; arg
4032 _OPT_VIEWER_HTML="$1";
4033 shift;
4035 --iconic) # start viewers as icons
4036 _OPT_ICONIC='yes';
4038 --locale) # set language for man pages, arg
4039 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
4040 _OPT_LANG="$1";
4041 shift;
4043 --local-file) # force local files; same as `--no-man'
4044 _MAN_FORCE='no';
4045 _MAN_ENABLE='no';
4047 --location|--where) # print file locations to stderr
4048 _OPT_LOCATION='yes';
4050 --man) # force all file params to be man pages
4051 _MAN_ENABLE='yes';
4052 _MAN_FORCE='yes';
4054 --manpath) # specify search path for man pages, arg
4055 # arg is colon-separated list of directories
4056 _OPT_MANPATH="$1";
4057 shift;
4059 --mode) # display mode
4060 mpa_arg="$1";
4061 shift;
4062 case "${mpa_arg}" in
4063 auto|'') # search mode automatically among default
4064 _OPT_MODE='';
4066 groff) # pass input to plain groff
4067 _OPT_MODE='groff';
4069 html|www) # display with a web browser
4070 _OPT_MODE='html';
4072 dvi) # display with xdvi viewer
4073 _OPT_MODE='dvi';
4075 pdf) # display with PDF viewer
4076 _OPT_MODE='pdf';
4078 ps) # display with Postscript viewer
4079 _OPT_MODE='ps';
4081 text) # output on terminal
4082 _OPT_MODE='text';
4084 tty) # output on terminal
4085 _OPT_MODE='tty';
4087 X|x) # output on X roff viewer
4088 _OPT_MODE='x';
4090 Q|source) # display source code
4091 _OPT_MODE="source";
4094 error "main_parse_args(): unknown mode ${mpa_arg}";
4096 esac;
4098 --no-location) # disable former call to `--location'
4099 _OPT_LOCATION='yes';
4101 --no-man) # disable search for man pages
4102 # the same as --local-file
4103 _MAN_FORCE="no";
4104 _MAN_ENABLE="no";
4106 --pager|--tty-viewer) # set paging program for tty mode, arg
4107 _OPT_PAGER="$1";
4108 shift;
4110 --pdf)
4111 _OPT_MODE='pdf';
4113 --pdf-viewer) # viewer program for ps mode; arg
4114 _OPT_VIEWER_PDF="$1";
4115 shift;
4117 --ps)
4118 _OPT_MODE='ps';
4120 --ps-viewer) # viewer program for ps mode; arg
4121 _OPT_VIEWER_PS="$1";
4122 shift;
4124 --resolution) # set resolution for X devices, arg
4125 mpa_arg="$1";
4126 shift;
4127 case "${mpa_arg}" in
4128 75|75dpi)
4129 mpa_dpi=75;
4131 100|100dpi)
4132 mpa_dpi=100;
4135 error "main_parse_args(): \
4136 only resoutions of 75 or 100 dpi are supported";
4138 esac;
4139 _OPT_RESOLUTION="${mpa_dpi}";
4141 --rv)
4142 _OPT_RV='yes';
4144 --sections) # specify sections for man pages, arg
4145 # arg is colon-separated list of section names
4146 _OPT_SECTIONS="$1";
4147 shift;
4149 --shell)
4150 # already done during the first run; so ignore the argument
4151 shift;
4153 --systems) # man pages for different OS's, arg
4154 # argument is a comma-separated list
4155 _OPT_SYSTEMS="$1";
4156 shift;
4158 --text) # text mode without pager
4159 _OPT_MODE=text;
4161 --title) # title for X viewers; arg
4162 _OPT_TITLE="$1";
4163 shift;
4165 --tty) # tty mode, text with pager
4166 _OPT_MODE=tty;
4168 --text-device|--tty-device) # device for tty mode; arg
4169 _OPT_TEXT_DEVICE="$1";
4170 shift;
4172 --whatis)
4173 _OPT_WHATIS='yes';
4175 --X|--x)
4176 _OPT_MODE=x;
4178 --xrm) # pass X resource string, arg;
4179 list_append _OPT_XRM "$1";
4180 shift;
4182 --x-viewer|--X-viewer) # viewer program for x mode; arg
4183 _OPT_VIEWER_X="$1";
4184 shift;
4187 error 'main_parse_args(): error on argument parsing : '"\`$*'";
4189 esac;
4190 done;
4191 shift; # remove `--' argument
4192 if obj _DEBUG is_not_yes
4193 then
4194 if obj _OPT_DEBUG is_yes
4195 then
4196 _DEBUG='yes';
4197 _DEBUG_LM='yes';
4198 _DEBUG_KEEP_FILES='yes';
4199 _DEBUG_PRINT_PARAMS='yes';
4200 _DEBUG_PRINT_SHELL='yes';
4204 # Remaining arguments are file names (filespecs).
4205 # Save them to list $_FILEARGS
4206 if is_equal "$#" 0
4207 then # use "-" for standard input
4208 set x '-';
4209 shift;
4211 _FILEARGS='';
4212 list_append _FILEARGS "$@";
4213 if list_has _FILEARGS '-'
4214 then
4215 save_stdin;
4217 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4218 eval ${_UNSET} mpa_arg;
4219 eval ${_UNSET} mpa_dpi;
4220 eval ${_UNSET} mpa_opt;
4221 eval ${_UNSET} mpa_optchar;
4222 eval "${return_ok}";
4223 } # main_parse_args()
4226 # Called from main_parse_args() because double `case' is not possible.
4227 # Globals: $_OPT_DEVICE, $_OPT_MODE
4228 _check_device_with_mode()
4230 func_check _check_device_with_mode = 0 "$@";
4231 case "${_OPT_DEVICE}" in
4232 dvi)
4233 _OPT_MODE=dvi;
4234 eval "${return_ok}";
4236 html)
4237 _OPT_MODE=html;
4238 eval "${return_ok}";
4240 lbp|lj4)
4241 _OPT_MODE=groff;
4242 eval "${return_ok}";
4245 _OPT_MODE=ps;
4246 eval "${return_ok}";
4248 ascii|cp1047|latin1|utf8)
4249 if obj _OPT_MODE is_not_equal text
4250 then
4251 _OPT_MODE=tty; # default text mode
4253 eval "${return_ok}";
4256 _OPT_MODE=x;
4257 eval "${return_ok}";
4259 *) # unknown device, go to groff mode
4260 _OPT_MODE=groff;
4261 eval "${return_ok}";
4263 esac;
4264 eval "${return_error}";
4265 } # _check_device_with_mode() of main_parse_args()
4268 ########################################################################
4269 # main_set_mode ()
4271 # Determine the display mode.
4273 # Globals:
4274 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4275 # out: $_DISPLAY_MODE
4277 # Variable prefix: msm
4279 main_set_mode()
4281 func_check main_set_mode = 0 "$@";
4283 # handle apropos
4284 if obj _OPT_APROPOS is_not_empty
4285 then
4286 apropos "${_OPT_APROPOS}";
4287 leave "$?";
4289 if obj _OPT_APROPOS_DATA is_not_empty
4290 then
4291 apropos "$@" | grep '^[^(]*([457])';
4292 leave "$?";
4294 if obj _OPT_APROPOS_DEVEL is_not_empty
4295 then
4296 apropos "$@" | grep '^[^(]*([239])';
4297 leave "$?";
4299 if obj _OPT_APROPOS_PROGS is_not_empty
4300 then
4301 apropos "$@" | grep '^[^(]*([168])';
4302 leave "$?";
4305 # set display
4306 if obj _OPT_DISPLAY is_not_empty
4307 then
4308 DISPLAY="${_OPT_DISPLAY}";
4311 if obj _OPT_V is_yes
4312 then
4313 list_append _ADDOPTS_GROFF '-V';
4315 if obj _OPT_Z is_yes
4316 then
4317 _DISPLAY_MODE='groff';
4318 list_append _ADDOPTS_GROFF '-Z';
4320 if obj _OPT_MODE is_equal 'groff'
4321 then
4322 _DISPLAY_MODE='groff';
4324 if obj _DISPLAY_MODE is_equal 'groff'
4325 then
4326 eval ${_UNSET} msm_modes;
4327 eval ${_UNSET} msm_viewer;
4328 eval ${_UNSET} msm_viewers;
4329 eval "${return_ok}";
4332 if obj _OPT_MODE is_equal 'source'
4333 then
4334 _DISPLAY_MODE='source';
4335 eval ${_UNSET} msm_modes;
4336 eval ${_UNSET} msm_viewer;
4337 eval ${_UNSET} msm_viewers;
4338 eval "${return_ok}";
4341 case "${_OPT_MODE}" in
4342 '') # automatic mode
4343 case "${_OPT_DEVICE}" in
4345 if obj DISPLAY is_empty
4346 then
4347 error "main_set_mode(): \
4348 no X display found for device ${_OPT_DEVICE}";
4350 _DISPLAY_MODE='x';
4351 eval ${_UNSET} msm_modes;
4352 eval ${_UNSET} msm_viewer;
4353 eval ${_UNSET} msm_viewers;
4354 eval "${return_ok}";
4356 ascii|cp1047|latin1|utf8)
4357 if obj _DISPLAY_MODE is_not_equal 'text'
4358 then
4359 _DISPLAY_MODE='tty';
4361 eval ${_UNSET} msm_modes;
4362 eval ${_UNSET} msm_viewer;
4363 eval ${_UNSET} msm_viewers;
4364 eval "${return_ok}";
4366 esac;
4367 if obj DISPLAY is_empty
4368 then
4369 _DISPLAY_MODE='tty';
4370 eval ${_UNSET} msm_modes;
4371 eval ${_UNSET} msm_viewer;
4372 eval ${_UNSET} msm_viewers;
4373 eval "${return_ok}";
4376 if obj _OPT_DEFAULT_MODES is_empty
4377 then
4378 msm_modes="${_DEFAULT_MODES}";
4379 else
4380 msm_modes="${_OPT_DEFAULT_MODES}";
4383 text)
4384 _DISPLAY_MODE='text';
4385 eval ${_UNSET} msm_modes;
4386 eval ${_UNSET} msm_viewer;
4387 eval ${_UNSET} msm_viewers;
4388 eval "${return_ok}";
4390 tty)
4391 _DISPLAY_MODE='tty';
4392 eval ${_UNSET} msm_modes;
4393 eval ${_UNSET} msm_viewer;
4394 eval ${_UNSET} msm_viewers;
4395 eval "${return_ok}";
4397 *) # display mode was given
4398 if obj DISPLAY is_empty
4399 then
4400 error "main_set_mode(): \
4401 you must be in X Window for ${_OPT_MODE} mode.";
4403 msm_modes="${_OPT_MODE}";
4405 esac;
4407 # only viewer modes are left
4408 eval set x "$(list_from_split "${msm_modes}" ',')";
4409 shift;
4410 while test "$#" -gt 0
4412 m="$1";
4413 shift;
4414 case "$m" in
4415 text)
4416 _DISPLAY_MODE='text';
4417 eval ${_UNSET} msm_modes;
4418 eval ${_UNSET} msm_viewer;
4419 eval ${_UNSET} msm_viewers;
4420 eval "${return_ok}";
4422 tty)
4423 _DISPLAY_MODE='tty';
4424 eval ${_UNSET} msm_modes;
4425 eval ${_UNSET} msm_viewer;
4426 eval ${_UNSET} msm_viewers;
4427 eval "${return_ok}";
4430 if obj _OPT_VIEWER_X is_not_empty
4431 then
4432 msm_viewers="${_OPT_VIEWER_X}";
4433 else
4434 msm_viewers="${_VIEWER_X}";
4436 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4437 if is_not_equal "$?" 0
4438 then
4439 continue;
4441 _DISPLAY_PROG="${msm_viewer}";
4442 _DISPLAY_MODE='x';
4443 eval ${_UNSET} msm_modes;
4444 eval ${_UNSET} msm_viewer;
4445 eval ${_UNSET} msm_viewers;
4446 eval "${return_ok}";
4449 _DISPLAY_MODE='X';
4450 eval ${_UNSET} msm_modes;
4451 eval ${_UNSET} msm_viewer;
4452 eval ${_UNSET} msm_viewers;
4453 eval "${return_ok}";
4455 dvi)
4456 if obj _OPT_VIEWER_DVI is_not_empty
4457 then
4458 msm_viewers="${_OPT_VIEWER_DVI}";
4459 else
4460 msm_viewers="${_VIEWER_DVI}";
4462 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4463 if is_not_equal "$?" 0
4464 then
4465 continue;
4467 _DISPLAY_PROG="${msm_viewer}";
4468 _DISPLAY_MODE="dvi";
4469 eval ${_UNSET} msm_modes;
4470 eval ${_UNSET} msm_viewer;
4471 eval ${_UNSET} msm_viewers;
4472 eval "${return_ok}";
4474 pdf)
4475 if obj _OPT_VIEWER_PDF is_not_empty
4476 then
4477 msm_viewers="${_OPT_VIEWER_PDF}";
4478 else
4479 msm_viewers="${_VIEWER_PDF}";
4481 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4482 if is_not_equal "$?" 0
4483 then
4484 continue;
4486 _DISPLAY_PROG="${msm_viewer}";
4487 _DISPLAY_MODE="pdf";
4488 eval ${_UNSET} msm_modes;
4489 eval ${_UNSET} msm_viewer;
4490 eval ${_UNSET} msm_viewers;
4491 eval "${return_ok}";
4494 if obj _OPT_VIEWER_PS is_not_empty
4495 then
4496 msm_viewers="${_OPT_VIEWER_PS}";
4497 else
4498 msm_viewers="${_VIEWER_PS}";
4500 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4501 if is_not_equal "$?" 0
4502 then
4503 continue;
4505 _DISPLAY_PROG="${msm_viewer}";
4506 _DISPLAY_MODE="ps";
4507 eval ${_UNSET} msm_modes;
4508 eval ${_UNSET} msm_viewer;
4509 eval ${_UNSET} msm_viewers;
4510 eval "${return_ok}";
4512 html)
4513 if obj _OPT_VIEWER_HTML is_not_empty
4514 then
4515 msm_viewers="${_OPT_VIEWER_HTML}";
4516 else
4517 msm_viewers="${_VIEWER_HTML}";
4519 msm_viewer="$(_get_first_prog "${msm_viewers}")";
4520 if is_not_equal "$?" 0
4521 then
4522 continue;
4524 _DISPLAY_PROG="${msm_viewer}";
4525 _DISPLAY_MODE=html;
4526 eval ${_UNSET} msm_modes;
4527 eval ${_UNSET} msm_viewer;
4528 eval ${_UNSET} msm_viewers;
4529 eval "${return_ok}";
4531 esac;
4532 done;
4533 eval ${_UNSET} msm_modes;
4534 eval ${_UNSET} msm_viewer;
4535 eval ${_UNSET} msm_viewers;
4536 error "main_set_mode(): no suitable display mode found.";
4537 } # main_set_mode()
4540 # _get_first_prog (<proglist>)
4542 # Retrieve first argument that represents an existing program in $PATH.
4543 # Local function for main_set_mode().
4545 # Arguments: 1; a comma-separated list of commands (with options),
4546 # like $_VIEWER_*.
4548 # Return : `1' if none found, `0' if found.
4549 # Output : the argument that succeded.
4551 # Variable prefix: _gfp
4553 _get_first_prog()
4555 if is_equal "$#" 0
4556 then
4557 error "_get_first_prog() needs 1 argument.";
4559 if is_empty "$1"
4560 then
4561 return "${_BAD}";
4563 eval set x "$(list_from_split "$1" ',')";
4564 shift;
4565 for i
4567 _gfp_i="$i";
4568 if obj _gfp_i is_empty
4569 then
4570 continue;
4572 if eval is_prog "$(get_first_essential ${_gfp_i})"
4573 then
4574 obj _gfp_i echo1;
4575 eval ${_UNSET} _gfp_i;
4576 return "${_GOOD}";
4578 done;
4579 eval ${_UNSET} _gfp_i;
4580 return "${_BAD}";
4581 } # _get_first_prog() of main_set_mode()
4584 #######################################################################
4585 # main_do_fileargs ()
4587 # Process filespec arguments in $_FILEARGS.
4589 # Globals:
4590 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
4592 # Variable prefix: mdfa
4594 main_do_fileargs()
4596 func_check main_do_fileargs = 0 "$@";
4597 mdfa_exitcode="${_BAD}";
4598 eval set x "${_FILEARGS}";
4599 shift;
4600 eval ${_UNSET} _FILEARGS;
4601 # temporary storage of all input to $_TMP_CAT
4602 while test "$#" -ge 2
4604 # test for `s name' arguments, with `s' a 1-char standard section
4605 mdfa_filespec="$1";
4606 shift;
4607 case "${mdfa_filespec}" in
4609 continue;
4611 '-')
4612 if register_file '-'
4613 then
4614 mdfa_exitcode="${_GOOD}";
4616 continue;
4619 if list_has_not _MAN_AUTO_SEC "${mdfa_filespec}"
4620 then
4621 if do_filearg "${mdfa_filespec}"
4622 then
4623 mdfa_exitcode="${_GOOD}";
4625 continue;
4627 mdfa_name="$1";
4628 case "${mdfa_name}" in
4629 */*|man:*|*\(*\)|*."${mdfa_filespec}")
4630 if do_filearg "${mdfa_filespec}"
4631 then
4632 mdfa_exitcode="${_GOOD}";
4634 continue;
4636 esac;
4637 if do_filearg "man:${mdfa_name}(${mdfa_filespec})"
4638 then
4639 mdfa_exitcode="${_GOOD}";
4640 shift;
4641 continue;
4642 else
4643 if do_filearg "${mdfa_filespec}"
4644 then
4645 mdfa_exitcode="${_GOOD}";
4647 continue;
4651 if do_filearg "${mdfa_filespec}"
4652 then
4653 mdfa_exitcode="${_GOOD}";
4655 continue;
4657 esac;
4658 done; # end of `s name' test
4659 while test "$#" -gt 0
4661 mdfa_filespec="$1";
4662 shift;
4663 if do_filearg "${mdfa_filespec}"
4664 then
4665 mdfa_exitcode="${_GOOD}";
4667 done;
4668 obj _TMP_STDIN rm_file_with_debug;
4669 if is_equal "${mdfa_exitcode}" "${_BAD}"
4670 then
4671 eval ${_UNSET} mdfa_exitcode;
4672 eval ${_UNSET} mdfa_filespec;
4673 eval ${_UNSET} mdfa_name;
4674 eval "${return_bad}";
4676 eval ${_UNSET} mdfa_exitcode;
4677 eval ${_UNSET} mdfa_filespec;
4678 eval ${_UNSET} mdfa_name;
4679 eval "${return_ok}";
4680 } # main_do_fileargs()
4683 ########################################################################
4684 # main_set_resources ()
4686 # Determine options for setting X resources with $_DISPLAY_PROG.
4688 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4690 # Variable prefix: msr
4692 main_set_resources()
4694 func_check main_set_resources = 0 "$@";
4695 # $msr_prog viewer program
4696 # $msr_rl resource list
4697 msr_title="$(get_first_essential \
4698 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4699 _OUTPUT_FILE_NAME='';
4700 eval set x "${msr_title}";
4701 shift;
4702 until is_equal "$#" 0
4704 msr_n="$1";
4705 case "${msr_n}" in
4707 continue;
4710 msr_n="$(echo1 "$1" | sed -e 's/^,,*//')";
4712 esac
4713 if obj msr_n is_empty
4714 then
4715 continue;
4717 if obj _OUTPUT_FILE_NAME is_not_empty
4718 then
4719 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
4721 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
4722 shift;
4723 done;
4724 case "${_OUTPUT_FILE_NAME}" in
4726 _OUTPUT_FILE_NAME='-';
4729 error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
4731 esac;
4732 _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4734 if obj _DISPLAY_PROG is_empty
4735 then # for example, for groff mode
4736 _DISPLAY_ARGS='';
4737 eval ${_UNSET} msr_n;
4738 eval ${_UNSET} msr_prog;
4739 eval ${_UNSET} msr_rl;
4740 eval ${_UNSET} msr_title;
4741 eval "${return_ok}";
4744 eval set x "${_DISPLAY_PROG}";
4745 shift;
4746 msr_prog="$(base_name "$1")";
4747 shift;
4748 if test $# != 0
4749 then
4750 if obj _DISPLAY_PROG is_empty
4751 then
4752 _DISPLAY_ARGS="$*";
4753 else
4754 _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}";
4757 msr_rl='';
4758 if obj _OPT_BD is_not_empty
4759 then
4760 case "${msr_prog}" in
4761 ghostview|gv|gxditview|xditview|xdvi)
4762 list_append msr_rl '-bd' "${_OPT_BD}";
4764 esac;
4766 if obj _OPT_BG is_not_empty
4767 then
4768 case "${msr_prog}" in
4769 ghostview|gv|gxditview|xditview|xdvi)
4770 list_append msr_rl '-bg' "${_OPT_BG}";
4772 kghostview)
4773 list_append msr_rl '--bg' "${_OPT_BG}";
4775 xpdf)
4776 list_append msr_rl '-papercolor' "${_OPT_BG}";
4778 esac;
4780 if obj _OPT_BW is_not_empty
4781 then
4782 case "${msr_prog}" in
4783 ghostview|gv|gxditview|xditview|xdvi)
4784 _list_append msr_rl '-bw' "${_OPT_BW}";
4786 esac;
4788 if obj _OPT_FG is_not_empty
4789 then
4790 case "${msr_prog}" in
4791 ghostview|gv|gxditview|xditview|xdvi)
4792 list_append msr_rl '-fg' "${_OPT_FG}";
4794 kghostview)
4795 list_append msr_rl '--fg' "${_OPT_FG}";
4797 esac;
4799 if is_not_empty "${_OPT_FN}"
4800 then
4801 case "${msr_prog}" in
4802 ghostview|gv|gxditview|xditview|xdvi)
4803 list_append msr_rl '-fn' "${_OPT_FN}";
4805 kghostview)
4806 list_append msr_rl '--fn' "${_OPT_FN}";
4808 esac;
4810 if is_not_empty "${_OPT_GEOMETRY}"
4811 then
4812 case "${msr_prog}" in
4813 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4814 list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
4816 kghostview)
4817 list_append msr_rl '--geometry' "${_OPT_GEOMETRY}";
4819 esac;
4821 if is_empty "${_OPT_RESOLUTION}"
4822 then
4823 _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
4824 case "${msr_prog}" in
4825 gxditview|xditview)
4826 list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
4828 xpdf)
4829 case "${_DEFAULT_RESOLUTION}" in
4831 # 72dpi is '100'
4832 list_append msr_rl '-z' '104';
4834 100)
4835 list_append msr_rl '-z' '139';
4837 esac;
4839 esac;
4840 else
4841 case "${msr_prog}" in
4842 ghostview|gv|gxditview|xditview|xdvi)
4843 list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
4845 xpdf)
4846 case "${_OPT_RESOLUTION}" in
4848 list_append msr_rl '-z' '104';
4849 # '100' corresponds to 72dpi
4851 100)
4852 list_append msr_rl '-z' '139';
4854 esac;
4856 esac;
4858 if is_yes "${_OPT_ICONIC}"
4859 then
4860 case "${msr_prog}" in
4861 ghostview|gv|gxditview|xditview|xdvi)
4862 list_append msr_rl '-iconic';
4864 esac;
4866 if is_yes "${_OPT_RV}"
4867 then
4868 case "${msr_prog}" in
4869 ghostview|gv|gxditview|xditview|xdvi)
4870 list_append msr_rl '-rv';
4872 esac;
4874 if is_not_empty "${_OPT_XRM}"
4875 then
4876 case "${msr_prog}" in
4877 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4878 eval set x "${_OPT_XRM}";
4879 shift;
4880 for i
4882 list_append msr_rl '-xrm' "$i";
4883 done;
4885 esac;
4887 if is_not_empty "${msr_title}"
4888 then
4889 case "${msr_prog}" in
4890 gxditview|xditview)
4891 list_append msr_rl '-title' "${msr_title}";
4893 esac;
4895 _DISPLAY_ARGS="${msr_rl}";
4896 eval ${_UNSET} msr_n;
4897 eval ${_UNSET} msr_prog;
4898 eval ${_UNSET} msr_rl;
4899 eval ${_UNSET} msr_title;
4900 eval "${return_ok}";
4901 } # main_set_resources
4904 ########################################################################
4905 # main_display ()
4907 # Do the actual display of the whole thing.
4909 # Globals:
4910 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4911 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4912 # $_REGISTERED_TITLE, $_TMP_CAT,
4913 # $_OPT_PAGER $PAGER, $_MANOPT_PAGER,
4914 # $_OUTPUT_FILE_NAME
4916 # Variable prefix: md
4918 main_display()
4920 func_check main_display = 0 "$@";
4922 export md_addopts;
4923 export md_groggy;
4924 export md_modefile;
4926 if obj _TMP_CAT is_non_empty_file
4927 then
4928 md_modefile="${_OUTPUT_FILE_NAME}";
4929 else
4930 echo2 'groffer: empty input.';
4931 clean_up;
4932 eval ${_UNSET} md_modefile;
4933 eval "${return_ok}";
4936 # go to the temporary directory to be able to access internal data files
4937 cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1;
4939 case "${_DISPLAY_MODE}" in
4940 groff)
4941 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4942 if obj _OPT_DEVICE is_not_empty
4943 then
4944 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4946 md_groggy="$(tmp_cat | eval grog "${md_options}")";
4947 trap_clean;
4948 _do_opt_V;
4950 obj md_modefile rm_file;
4951 mv "${_TMP_CAT}" "${md_modefile}";
4952 cat "${md_modefile}" | \
4954 trap clean_up 0 2>${_NULL_DEV} || :;
4955 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4956 clean_up;
4959 text|tty)
4960 case "${_OPT_DEVICE}" in
4962 md_device="$(get_first_essential \
4963 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4965 ascii|cp1047|latin1|utf8)
4966 md_device="${_OPT_DEVICE}";
4969 warning "main_display(): \
4970 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4972 esac;
4973 md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4974 md_groggy="$(tmp_cat | grog -T${md_device})";
4975 if obj _DISPLAY_MODE is_equal 'text'
4976 then
4977 _do_opt_V;
4978 tmp_cat | eval "${md_groggy}" "${md_addopts}";
4979 else
4980 md_pager='';
4981 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4982 'less -r -R' 'more' 'pager' 'cat'
4984 md_p="$p";
4985 if eval is_prog ${md_p}
4986 then # no "" for is_prog() allows args for $p
4987 md_pager="${md_p}";
4988 break;
4990 done;
4991 if obj md_pager is_empty
4992 then
4993 error 'main_display(): no pager program found for tty mode';
4995 _do_opt_V;
4996 tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
4997 eval "${md_pager}";
4999 clean_up;
5001 source)
5002 tmp_cat;
5003 clean_up;
5006 #### viewer modes
5008 dvi)
5009 case "${_OPT_DEVICE}" in
5010 ''|dvi) do_nothing; ;;
5012 warning "main_display(): \
5013 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
5015 esac;
5016 md_modefile="${md_modefile}".dvi;
5017 md_groggy="$(tmp_cat | grog -Tdvi)";
5018 _do_display;
5020 html)
5021 case "${_OPT_DEVICE}" in
5022 ''|html) do_nothing; ;;
5024 warning "main_display(): \
5025 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5027 esac;
5028 md_modefile="${md_modefile}".html;
5029 md_groggy="$(tmp_cat | grog -Thtml)";
5030 _do_display;
5032 pdf)
5033 case "${_OPT_DEVICE}" in
5034 ''|ps)
5035 do_nothing;
5038 warning "main_display(): \
5039 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5041 esac;
5042 md_groggy="$(tmp_cat | grog -Tps)";
5043 _do_display _make_pdf;
5046 case "${_OPT_DEVICE}" in
5047 ''|ps)
5048 do_nothing;
5051 warning "main_display(): \
5052 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5054 esac;
5055 md_modefile="${md_modefile}".ps;
5056 md_groggy="$(tmp_cat | grog -Tps)";
5057 _do_display;
5060 case "${_OPT_DEVICE}" in
5062 md_device="${_OPT_DEVICE}"
5065 case "${_OPT_RESOLUTION}" in
5066 100)
5067 md_device='X100';
5068 if obj _OPT_GEOMETRY is_empty
5069 then
5070 case "${_DISPLAY_PROG}" in
5071 gxditview|xditview)
5072 # add width of 800dpi for resolution of 100dpi to the args
5073 list_append _DISPLAY_ARGS '-geometry' '800';
5075 esac;
5079 md_device='X75-12';
5081 esac
5082 esac;
5083 md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
5084 _do_display;
5087 case "${_OPT_DEVICE}" in
5089 md_groggy="$(tmp_cat | grog -X)";
5091 X*|dvi|html|lbp|lj4|ps)
5092 # these devices work with
5093 md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
5096 warning "main_display(): \
5097 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5098 md_groggy="$(tmp_cat | grog -Z)";
5100 esac;
5101 _do_display;
5104 error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
5106 esac;
5107 eval ${_UNSET} md_addopts;
5108 eval ${_UNSET} md_device;
5109 eval ${_UNSET} md_groggy;
5110 eval ${_UNSET} md_modefile;
5111 eval ${_UNSET} md_options;
5112 eval ${_UNSET} md_p;
5113 eval ${_UNSET} md_pager;
5114 eval "${return_ok}";
5115 } # main_display()
5118 ########################
5119 # _do_display ([<prog>])
5121 # Perform the generation of the output and view the result. If an
5122 # argument is given interpret it as a function name that is called in
5123 # the midst.
5125 # Globals: $md_modefile, $md_groggy (from main_display())
5127 _do_display()
5129 func_check _do_display '>=' 0 "$@";
5130 trap_clean;
5131 _do_opt_V;
5132 obj md_modefile rm_file;
5133 if cat "${_TMP_CAT}" | \
5134 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}"
5135 then
5137 else
5138 error "_do_display: error on groff call";
5140 if is_not_empty "$1"
5141 then
5142 eval "$1";
5144 obj _TMP_CAT rm_file_with_debug;
5146 trap clean_up 0 2>${_NULL_DEV} || :;
5147 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5148 clean_up;
5150 eval "${return_ok}";
5151 } # _do_display() of main_display()
5154 #############
5155 # _do_opt_V ()
5157 # Check on option `-V'; if set print the corresponding output and leave.
5159 # Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG,
5160 # $_DISPLAY_ARGS, $md_groggy, $md_modefile
5162 # Variable prefix: _doV
5164 _do_opt_V()
5166 func_check _do_opt_V '=' 0 "$@";
5167 if obj _OPT_V is_yes
5168 then
5169 _OPT_V='no';
5170 echo "Output file: ${md_modefile}";
5171 echo "Display mode: ${_DISPLAY_MODE}";
5172 echo "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
5173 echo "Parameters: ${_ALL_PARAMS}";
5174 echo "Output of grog: ${md_groggy} $(eval echo1 "'${_ADDOPTS_GROFF}'")";
5175 _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")";
5176 echo "groff -V: ${_doV_res}"
5177 leave;
5179 eval "${return_ok}";
5180 } # _do_opt_V() of main_display()
5183 ##############
5184 # _make_pdf ()
5186 # Transform to pdf format; for pdf mode in _do_display().
5188 # Globals: $md_modefile (from main_display())
5190 # Variable prefix: _mp
5192 _make_pdf()
5194 func_check _do_display '=' 0 "$@";
5195 _mp_psfile="${md_modefile}";
5196 md_modefile="${md_modefile}.pdf";
5197 obj md_modefile rm_file;
5198 if gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
5199 -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}"
5200 then
5202 else
5203 error '_make_pdf: could not transform into pdf format.';
5205 obj _mp_psfile rm_file_with_debug;
5206 eval ${_UNSET} _mp_psfile;
5207 eval "${return_ok}";
5208 } # _make_pdf() of main_display()
5211 ########################################################################
5212 # main (<command_line_args>*)
5214 # The main function for groffer.
5216 # Arguments:
5218 main()
5220 func_check main '>=' 0 "$@";
5221 # Do not change the sequence of the following functions!
5222 landmark '13: main_init()';
5223 main_init;
5224 landmark '14: main_parse_MANOPT()';
5225 main_parse_MANOPT;
5226 landmark '15: main_parse_args()';
5227 main_parse_args "$@";
5228 landmark '16: main_set_mode()';
5229 main_set_mode;
5230 landmark '17: main_do_fileargs()';
5231 main_do_fileargs;
5232 landmark '18: main_set_resources()';
5233 main_set_resources;
5234 landmark '19: main_display()';
5235 main_display;
5236 eval "${return_ok}";
5239 landmark '20: end of function definitions';
5241 ########################################################################
5243 main "$@";