* src/roff/troff/nroff.cpp (space_node::get_breakpoints,
[s-roff.git] / contrib / groffer / groffer.sh
blobf019e20665f72441fcb6104c508e44720cbeacc6
1 #!/bin/sh
3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer.sh
7 # Copyright (C) 2001,2002,2003 Free Software Foundation, Inc.
8 # Written by Bernd Warken <bwarken@mayn.de>
10 # This file is part of groff.
12 # groff is free software; you can redistribute it and/or modify it
13 # under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2, or (at your option)
15 # any later version.
17 # groff is distributed in the hope that it will be useful, but WITHOUT
18 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 # License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with groff; see the file COPYING. If not, write to the
24 # Free Software Foundation, 59 Temple Place - Suite 330, Boston,
25 # MA 02111-1307, USA.
27 export _PROGRAM_NAME;
28 export _PROGRAM_VERSION;
29 export _LAST_UPDATE;
31 _PROGRAM_NAME='groffer';
32 _PROGRAM_VERSION='0.9.4';
33 _LAST_UPDATE='22 Jan 2003';
35 # This program is installed with groff version @VERSION@.
37 ########################################################################
38 # Determine the shell under which to run this script;
39 # if `ash' is available restart the script using `ash';
40 # otherwise just go on.
42 if test "${_groffer_run}" != 'second'; then
43 # only reached during the first run of the script
45 export GROFFER_OPT;
46 export _groffer_run;
47 export _this;
49 _this="@BINDIR@/${_PROGRAM_NAME}";
51 ###########################
52 # _get_opt_shell ("$@")
54 # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
55 # if so echo its argument.
57 _get_opt_shell()
59 local i;
60 local _sh;
61 case " ${GROFFER_OPT} $*" in
62 *\ --shell\ *|*\ --shell=*)
64 eval set -- "${GROFFER_OPT}" '"$@"';
65 _sh='';
66 for i in "$@"; do
67 case "$1" in
68 --shell)
69 if test "$#" -ge 2; then
70 _sh="$2";
71 shift;
72 fi;
74 --shell=?*)
75 # delete up to first `=' character
76 _sh="$(echo -n "$1" | sed -e 's/^[^=]*=//')";
78 esac;
79 shift;
80 done;
81 echo -n "${_sh}";
84 esac;
88 ###########################
89 # _test_on_shell (<name>)
91 # Test whether <name> is a shell program of Bourne type (POSIX sh).
93 _test_on_shell()
95 if test "$#" -le 0 || test "$1" = ''; then
96 return 1;
97 fi;
98 # do not quote $1 to allow arguments
99 test "$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)" = 'ok';
102 # do the shell determination
103 _shell="$(_get_opt_shell "$@")";
104 if test "${_shell}" = ''; then
105 _shell='ash';
107 if _test_on_shell "${_shell}"; then
108 _groffer_run='second';
109 # do not quote $_shell to allow arguments
110 exec ${_shell} "${_this}" "$@";
111 exit;
114 # clean-up of shell determination
115 unset _shell;
116 unset _this;
117 unset _groffer_run;
118 _get_opt_shell()
120 return 0;
122 _test_on_shell()
124 return 0;
130 ########################################################################
131 # diagnostic messages
133 export _DEBUG;
134 _DEBUG='no'; # disable debugging information
135 #_DEBUG='yes'; # enable debugging information
137 export _DEBUG_LM;
138 _DEBUG_LM='no'; # disable landmark messages
139 #_DEBUG_LM='yes'; # enable landmark messages
142 ########################################################################
143 # Description
144 ########################################################################
146 # Display groff files and man pages on X or tty, even when compressed.
149 ### Usage
151 # Input comes from either standard input or command line parameters
152 # that represent either names of exisiting roff files or standardized
153 # specifications for man pages. All of these can be compressed in a
154 # format that is decompressible by `gzip'.
156 # The following displaying modes are available:
157 # - Display formatted input with the X roff viewer `gxditview',
158 # - with a Prostcript viewer,
159 # - with a dvi viewer,
160 # - with a web browser.
161 # - Display formatted input in a text terminal using a text device.
162 # - Generate output for some groff device on stdout without a viewer.
163 # - Output only the source code without any groff processing.
164 # - Generate the troff intermediate output on standard output
165 # without groff postprocessing.
166 # By default, the program tries to display with `gxditview' (1); if
167 # this does not work, text display (2) is used.
170 ### Error handling
172 # Error handling and exit behavior is complicated by the fact that
173 # `exit' can only escape from the current shell; trouble occurs in
174 # subshells. This was solved by sending kill signals, see
175 # $_PROCESS_ID and error().
178 ### Compatibility
180 # This shell script is compatible to the both the GNU and the POSIX
181 # shell and utilities. Care was taken to restrict the programming
182 # technics used here in order to achieve POSIX compatibility as far
183 # back as POSIX P1003.2 Draft 11.2 of September 1991.
185 # The only non-builtin used here is POSIX `sed'. This script was
186 # tested under `bash', `ash', and `ksh'. The speed under `ash' is
187 # more than double when compared to the larger shells.
189 # This script provides its own option parser. It is compatible to the
190 # usual GNU style command line (option clusters, long options, mixing
191 # of options and non-option file names), except that it is not
192 # possible to abbreviate long option names.
194 # The mixing of options and file names can be prohibited by setting
195 # the environment variable `$POSIXLY_CORRECT' to a non-empty value.
196 # This enables the rather wicked POSIX behavior to terminate option
197 # parsing when the first non-option command line argument is found.
200 ########################################################################
201 # Survey of functions defined in this document
202 ########################################################################
204 # The elements specified within paranthesis `(<>)' give hints to what
205 # the arguments are meant to be; the argument names are irrelevant.
206 # <>? 0 or 1
207 # <>* arbitrarily many such arguments, incl. none
208 # <>+ one or more such arguments
209 # <> exactly 1
211 # A function that starts with an underscore `_' is an internal
212 # function for some function. The internal functions are defined just
213 # after their corresponding function; they are not mentioned in the
214 # following.
216 # abort (text>*)
217 # base_name (path)
218 # catz (<file>)
219 # clean_up ()
220 # diag (text>*)
221 # dirname_append (<path> [<dir...>])
222 # dirname_chop (<path>)
223 # do_filearg (<filearg>)
224 # do_nothing ()
225 # echo2 (<text>*)
226 # echo2n (<text>*)
227 # error (<text>*)
228 # get_first_essential (<arg>*)
229 # is_dir (<name>)
230 # is_empty (<string>)
231 # is_equal (<string1> <string2>)
232 # is_file (<name>)
233 # is_not_empty (<string>)
234 # is_not_equal (<string1> <string2>)
235 # is_not_file (<name>)
236 # is_not_prog (<name>)
237 # is_prog (<name>)
238 # is_yes (<string>)
239 # leave ()
240 # landmark (<text>)
241 # list_append (<list> <element>...)
242 # list_check (<list>)
243 # list_from_args (<arg>...)
244 # list_from_cmdline (<s_n> <s_a> <l_n> <l_n> [<cmdline_arg>...])
245 # list_from_split (<string> <separator>)
246 # list_has (<list> <element>)
247 # list_has_not (<list> <element>)
248 # list_length (<list>)
249 # main_*(), see after the functions
250 # man_do_filespec (<filespec>)
251 # man_setup ()
252 # man_register_file (<file> [<name> [<section>]])
253 # man_search_section (<name> <section>)
254 # man_set()
255 # manpath_add_lang(<path> <language>)
256 # manpath_add_system()
257 # manpath_from_path ()
258 # normalize_args (<shortopts> <longopts> <arg>*)
259 # path_chop (<path>)
260 # path_clean (<path>)
261 # path_contains (<path> <dir>)
262 # path_not_contains (<path> <dir>)
263 # path_split (<path>)
264 # register_file (<filename>)
265 # register_title (<filespec>)
266 # reset ()
267 # save_stdin ()
268 # string_contains (<string> <part>)
269 # string_not_contains (<string> <part>)
270 # tmp_cat ()
271 # tmp_create (<suffix>?)
272 # to_tmp (<filename>)
273 # trap_clean ()
274 # trap_set (<functionname>)
275 # usage ()
276 # version ()
277 # warning (<string>)
278 # whatis (<filename>)
279 # where (<program>)
282 ########################################################################
283 # Environment Variables
284 ########################################################################
286 # Environment variables that exist only for this file start with an
287 # underscore letter. Global variables to this file are written in
288 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
289 # start with an underline and use only lower case letters and
290 # underlines, e.g. $_local_variable .
292 # [A-Z]* system variables, e.g. $MANPATH
293 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
294 # _[a-z_]* temporary variables, e.g. $_manpath
296 # Due to incompatibilities of the `ash' shell, the name of loop
297 # variables in `for' must be single character
298 # [a-z] local loop variables, e.g. $i
301 ########################################################################
302 # External environment variables
304 # If these variables are exported here then the `ash' shell coughs
305 # when calling `groff' in `main_display()'.
307 if test "${GROFFER_EXPORT_EXTERNALS}" = 'yes'; then
309 # external system environment variables that are explicitly used
310 export DISPLAY; # Presets the X display.
311 export LANG; # For language specific man pages.
312 export LC_ALL; # For language specific man pages.
313 export LC_MESSAGES; # For language specific man pages.
314 export PAGER; # Paging program for tty mode.
315 export PATH; # Path for the programs called (: list).
317 # groffer native environment variables
318 export GROFFER_OPT # preset options for groffer.
320 # all groff environment variables are used, see groff(1)
321 export GROFF_BIN_PATH; # Path for all groff programs.
322 export GROFF_COMMAND_PREFIX; # '' (normally) or 'g' (several troffs).
323 export GROFF_FONT_PATH; # Path to non-default groff fonts.
324 export GROFF_TMAC_PATH; # Path to non-default groff macro files.
325 export GROFF_TMPDIR; # Directory for groff temporary files.
326 export GROFF_TYPESETTER; # Preset default device.
328 # all GNU man environment variables are used, see man(1).
329 export MANOPT; # Preset options for man pages.
330 export MANPATH; # Search path for man pages (: list).
331 export MANROFFSEQ; # Ignored because of grog guessing.
332 export MANSECT; # Search man pages only in sections (:).
333 export SYSTEM; # Man pages for different OS's (, list).
338 ########################################################################
339 # read-only variables (global to this file)
340 ########################################################################
342 # characters
344 export _BQUOTE;
345 export _BSLASH;
346 export _DQUOTE;
347 export _NEWLINE;
348 export _LBRACK;
349 export _LPAR;
350 export _RBRACK;
351 export _RPAR;
352 export _SPACE;
353 export _SQUOTE;
354 export _TAB;
356 _BQUOTE='`';
357 _BSLASH='\';
358 _DQUOTE='"';
359 _NEWLINE='
361 _LBRACK='[';
362 _LPAR='(';
363 _RBRACK=']';
364 _RPAR=')';
365 _SPACE=' ';
366 _SQUOTE="'";
367 _TAB=' ';
369 # function return values; `0' means ok; other values are error codes
370 export _ALL_EXIT;
371 export _BAD;
372 export _ERROR;
373 export _GOOD;
374 export _NO;
375 export _OK;
376 export _YES;
378 _GOOD='0'; # return ok
379 _BAD='1'; # return negatively, error code `1'
380 _ERROR='7'; # for syntax errors; no `-1' in `ash'
382 _ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
384 _NO="${_BAD}";
385 _YES="${_GOOD}";
386 _OK="${_GOOD}";
388 # quasi-functions, call with `eval'
389 export return_ok;
390 export return_good;
391 export return_bad;
392 export return_yes;
393 export return_no;
394 export return_error;
395 return_ok="func_pop; return ${_OK}";
396 return_good="func_pop; return ${_GOOD}";
397 return_bad="func_pop; return ${_BAD}";
398 return_yes="func_pop; return ${_YES}";
399 return_no="func_pop; return ${_NO}";
400 return_error="func_pop; return ${_ERROR}";
403 export _CONFFILES;
404 _CONFFILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
406 export _DEFAULT_MODES;
407 _DEFAULT_MODES='ps,x,tty';
408 export _DEFAULT_RESOLUTION;
409 _DEFAULT_RESOLUTION='100';
411 export _DEFAULT_TTY_DEVICE;
412 _DEFAULT_TTY_DEVICE='latin1';
414 # _VIEWER_* viewer programs for different modes (only X is necessary)
415 # _VIEWER_* a comma-separated list of viewer programs (with options)
416 export _VIEWER_DVI; # viewer program for dvi mode
417 export _VIEWER_PS; # viewer program for ps mode
418 export _VIEWER_WWW_X; # viewer program for www mode in X
419 export _VIEWER_WWW_TTY; # viewer program for www mode in tty
420 _VIEWER_DVI='xdvi,dvilx';
421 _VIEWER_PDF='xpdf,acroread';
422 _VIEWER_PS='gv,ghostview,gs_x11,gs';
423 _VIEWER_WWW='mozilla,netscape,opera,amaya,arena';
424 _VIEWER_X='gxditview,xditview';
426 # Search automatically in standard sections `1' to `8', and in the
427 # traditional sections `9', `n', and `o'. On many systems, there
428 # exist even more sections, mostly containing a set of man pages
429 # special to a specific program package. These aren't searched for
430 # automatically, but must be specified on the command line.
431 export _MAN_AUTO_SEC;
432 _MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
434 export _PROCESS_ID; # for shutting down the program
435 _PROCESS_ID="$$";
438 ############ the command line options of the involved programs
440 # The naming scheme for the options environment names is
441 # $_OPTS_<prog>_<length>[_<argspec>]
443 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
444 # command line options)
445 # <length>: LONG (long options) or SHORT (single character options)
446 # <argspec>: ARG for options with argument, NA for no argument;
447 # without _<argspec> both the ones with and without arg.
449 # Each option that takes an argument must be specified with a
450 # trailing : (colon).
452 # exports
453 export _OPTS_GROFFER_SHORT_NA;
454 export _OPTS_GROFFER_SHORT_ARG;
455 export _OPTS_GROFFER_LONG_NA;
456 export _OPTS_GROFFER_LONG_ARG;
457 export _OPTS_GROFF_SHORT_NA;
458 export _OPTS_GROFF_SHORT_ARG;
459 export _OPTS_GROFF_LONG_NA;
460 export _OPTS_GROFF_LONG_ARG;
461 export _OPTS_MAN_SHORT_ARG;
462 export _OPTS_MAN_SHORT_NA;
463 export _OPTS_MAN_LONG_ARG;
464 export _OPTS_MAN_LONG_NA;
465 export _OPTS_GROFFER_LONG;
466 export _OPTS_GROFFER_SHORT;
467 export _OPTS_GROFF_LONG;
468 export _OPTS_GROFF_SHORT;
469 export _OPTS_CMDLINE_SHORT_NA;
470 export _OPTS_CMDLINE_SHORT_ARG;
471 export _OPTS_CMDLINE_SHORT;
472 export _OPTS_CMDLINE_LONG_NA;
473 export _OPTS_CMDLINE_LONG_ARG;
474 export _OPTS_CMDLINE_LONG;
477 ###### native groffer options
479 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
480 _OPTS_GROFFER_SHORT_ARG="'T'";
482 _OPTS_GROFFER_LONG_NA="'all' 'apropos' 'ascii' 'auto' 'default' 'dvi' \
483 'groff' 'help' 'intermediate-output' 'local-file' 'location' 'man' \
484 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'tty' 'tty-device' \
485 'version' 'whatis' 'where' 'www' 'x'";
487 _OPTS_GROFFER_LONG_ARG="'background' 'bd' 'bg' 'bw' 'default-modes' \
488 'device' 'display' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
489 'foreground' 'geometry' 'locale' 'manpath' 'mode' 'pager' \
490 'pdf-viewer' 'ps-viewer' 'resolution' 'sections' 'shell' \
491 'systems' 'title' 'troff-device' 'www-viewer' 'xrm' 'x-viewer'";
493 ##### options inhereted from groff
495 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
496 'R' 's' 'S' 't' 'U' 'V' 'z'";
497 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
498 'w' 'W'";
499 _OPTS_GROFF_LONG_NA="";
500 _OPTS_GROFF_LONG_ARG="";
502 ###### man options (for parsing $MANOPT only)
504 _OPTS_MAN_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
505 'V' 'w' 'Z'";
506 _OPTS_MAN_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
508 _OPTS_MAN_LONG_NA="'all' 'ascii' 'apropos' 'catman' 'debug' 'default' \
509 'ditroff' 'help' 'local-file' 'location' 'troff' 'update' 'version' \
510 'whatis' 'where'";
512 _OPTS_MAN_LONG_ARG="'extension' 'locale' 'manpath' \
513 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
515 ###### collections of options
517 # groffer
519 _OPTS_GROFFER_LONG="${_OPTS_GROFFER_LONG_ARG} ${_OPTS_GROFFER_LONG_NA}";
520 _OPTS_GROFFER_SHORT=\
521 "${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFFER_SHORT_NA}";
523 # groff
525 _OPTS_GROFF_LONG="${_OPTS_GROFF_LONG_ARG} ${_OPTS_GROFF_LONG_NA}";
526 _OPTS_GROFF_SHORT="${_OPTS_GROFF_SHORT_ARG} ${_OPTS_GROFF_SHORT_NA}";
528 # all command line options
530 _OPTS_CMDLINE_SHORT_NA="\
531 ${_OPTS_GROFFER_SHORT_NA} ${_OPTS_GROFF_SHORT_NA}";
532 _OPTS_CMDLINE_SHORT_ARG="\
533 ${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFF_SHORT_ARG}";
534 _OPTS_CMDLINE_SHORT="${_OPTS_GROFFER_SHORT} ${_OPTS_GROFF_SHORT}";
536 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
537 ${_OPTS_GROFF_LONG_NA} ${_OPTS_MAN_LONG_NA}";
538 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
539 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG}";
540 _OPTS_CMDLINE_LONG="${_OPTS_GROFFER_LONG} ${_OPTS_GROFF_LONG}";
543 ########################################################################
544 # read-write variables (global to this file)
545 ########################################################################
547 export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
548 export _ADDOPTS_POST; # Transp. options postproc (`eval').
549 export _ADDOPTS_X; # Transp. options X postproc (`eval').
550 export _DEFAULT_MODES; # Set default modes.
551 export _DISPLAY_MODE; # Display mode.
552 export _DISPLAY_PROG; # Viewer program to be used for display.
553 export _DISPLAY_ARGS; # X resources for the viewer program.
554 export _FILEARGS; # Stores filespec parameters.
555 export _FUNC_STACK; # Store debugging information.
556 export _REGISTERED_TITLE; # Processed file names.
557 # _HAS_* from availability tests
558 export _HAS_COMPRESSION; # `yes' if compression is available
559 export _HAS_OPTS_GNU; # `yes' if GNU `getopt' is available
560 export _HAS_OPTS_POSIX; # `yes' if POSIX `getopts' is available
561 # _MAN_* finally used configuration of man searching
562 export _MAN_ALL; # search all man pages per filespec
563 export _MAN_ENABLE; # enable search for man pages
564 export _MAN_EXT; # extension for man pages
565 export _MAN_FORCE; # force file parameter to be man pages
566 export _MAN_IS_SETUP; # setup man variables only once
567 export _MAN_LANG; # language for man pages
568 export _MAN_LANG_DONE; # language dirs added to man path
569 export _MAN_PATH; # search path for man pages
570 export _MAN_SEC; # sections for man pages; sep. `:'
571 export _MAN_SEC_DONE; # sections added to man path
572 export _MAN_SYS; # system names for man pages; sep. `,'
573 export _MAN_SYS; # system names added to man path
574 # _MANOPT_* as parsed from $MANOPT
575 export _MANOPT_ALL; # $MANOPT --all
576 export _MANOPT_EXTENSION; # $MANOPT --extension
577 export _MANOPT_LANG; # $MANOPT --locale
578 export _MANOPT_PATH; # $MANOPT --manpath
579 export _MANOPT_PAGER; # $MANOPT --pager
580 export _MANOPT_SEC; # $MANOPT --sections
581 export _MANOPT_SYS; # $MANOPT --systems
582 # _OPT_* as parsed from groffer command line
583 export _OPT_ALL; # display all suitable man pages.
584 export _OPT_APROPOS; # branch to `apropos' program.
585 export _OPT_BD; # set border color in some modes.
586 export _OPT_BG; # set background color in some modes.
587 export _OPT_BW; # set border width in some modes.
588 export _OPT_DEBUG; # print debugging information on stderr.
589 export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
590 export _OPT_DEVICE; # device option.
591 export _OPT_DISPLAY; # set X display.
592 export _OPT_FG; # set foreground color in some modes.
593 export _OPT_FN; # set font in some modes.
594 export _OPT_GEOMETRY; # set size and position of viewer in X.
595 export _OPT_LANG; # set language for man pages
596 export _OPT_LOCATION; # print processed file names to stderr
597 export _OPT_MODE; # values: X, tty, Q, Z, ""
598 export _OPT_MANPATH; # manual setting of path for man-pages
599 export _OPT_PAGER; # specify paging program for tty mode
600 export _OPT_RESOLUTION; # set X resolution in dpi
601 export _OPT_RV; # reverse fore- and background colors.
602 export _OPT_SECTIONS; # sections for man page search
603 export _OPT_SYSTEMS; # man pages of different OS's
604 export _OPT_TITLE; # title for gxditview window
605 export _OPT_TTY_DEVICE; # set device for tty mode.
606 export _OPT_V; # groff option -V.
607 export _OPT_VIEWER_DVI; # viewer program for dvi mode
608 export _OPT_VIEWER_PDF; # viewer program for pdf mode
609 export _OPT_VIEWER_PS; # viewer program for ps mode
610 export _OPT_VIEWER_WWW; # viewer program for www mode
611 export _OPT_VIEWER_X; # viewer program for x mode
612 export _OPT_WHATIS; # print the one-liner man info
613 export _OPT_X; # groff option -X.
614 export _OPT_XRM; # specify X resource.
615 export _OPT_Z; # groff option -Z.
616 # _TMP_* temporary files
617 export _TMP_DIR; # groff directory for temporary files
618 export _TMP_DIR_SUB; # groffer directory for temporary files
619 export _TMP_CAT; # stores concatenation of everything
620 export _TMP_STDIN; # stores stdin, if any
622 # these variables are preset in section `Preset' after the rudim. test
625 ########################################################################
626 # Test of rudimentary shell functionality
627 ########################################################################
630 ########################################################################
631 # Test of `test'.
633 test "a" = "a" || exit 1;
636 ########################################################################
637 # Test of `echo' and the `$()' construct.
639 echo -n '' >/dev/null || exit "${_ERROR}";
640 if test "$(echo -n 'te' && echo -n '' && echo -n 'st')" != "test"; then
641 exit "${_ERROR}";
645 ########################################################################
646 # Test of function definitions.
648 _t_e_s_t_f_u_n_c_()
650 return "${_OK}";
653 if _t_e_s_t_f_u_n_c_ 2>/dev/null; then
655 else
656 echo 'shell does not support function definitions.' >&2;
657 exit "${_ERROR}";
661 ########################################################################
662 # Preset and reset of read-write global variables
663 ########################################################################
666 # For variables that can be reset by option `--default', see reset().
668 _FILEARGS='';
670 # _HAS_* from availability tests
671 _HAS_COMPRESSION='';
672 _HAS_OPTS_GNU='';
673 _HAS_OPTS_POSIX='';
675 # _TMP_* temporary files
676 _TMP_DIR='';
677 _TMP_DIR_SUB='';
678 _TMP_CAT='';
679 _TMP_STDIN='';
682 ########################################################################
683 # reset ()
685 # Reset the variables that can be affected by options to their default.
687 reset()
689 if test "$#" -ne 0; then
690 error "reset() does not have arguments.";
693 _ADDOPTS_GROFF='';
694 _ADDOPTS_POST='';
695 _ADDOPTS_X='';
696 _DISPLAY_ARGS='';
697 _DISPLAY_MODE='';
698 _DISPLAY_PROG='';
699 _REGISTERED_TITLE='';
701 # _MAN_* finally used configuration of man searching
702 _MAN_ALL='no';
703 _MAN_ENABLE='yes'; # do search for man-pages
704 _MAN_EXT='';
705 _MAN_FORCE='no'; # first local file, then search man page
706 _MAN_IS_SETUP='no';
707 _MAN_LANG='';
708 _MAN_LANG_DONE='no';
709 _MAN_PATH='';
710 _MAN_SEC='';
711 _MAN_SEC_DONE='no';
712 _MAN_SYS='';
713 _MAN_SYS_DONE='no';
715 # _MANOPT_* as parsed from $MANOPT
716 _MANOPT_ALL='no';
717 _MANOPT_EXTENSION='';
718 _MANOPT_LANG='';
719 _MANOPT_PATH='';
720 _MANOPT_PAGER='';
721 _MANOPT_SEC='';
722 _MANOPT_SYS='';
724 # _OPT_* as parsed from groffer command line
725 _OPT_ALL='no';
726 _OPT_APROPOS='no';
727 _OPT_BD='';
728 _OPT_BG='';
729 _OPT_BW='';
730 _OPT_DEBUG='no';
731 _OPT_DEFAULT_MODES='';
732 _OPT_DEVICE='';
733 _OPT_DISPLAY='';
734 _OPT_FG='';
735 _OPT_FN='';
736 _OPT_GEOMETRY='';
737 _OPT_LANG='';
738 _OPT_LOCATION='no';
739 _OPT_MODE='';
740 _OPT_MANPATH='';
741 _OPT_PAGER='';
742 _OPT_RESOLUTION='';
743 _OPT_RV='';
744 _OPT_SECTIONS='';
745 _OPT_SYSTEMS='';
746 _OPT_TITLE='';
747 _OPT_TTY_DEVICE='';
748 _OPT_V='no';
749 _OPT_VIEWER_DVI='';
750 _OPT_VIEWER_PDF='';
751 _OPT_VIEWER_PS='';
752 _OPT_VIEWER_WWW='';
753 _OPT_VIEWER_X='';
754 _OPT_WHATIS='no';
755 _OPT_X='no';
756 _OPT_XRM='';
757 _OPT_Z='no';
761 reset;
764 ########################################################################
765 # Functions for error handling and debugging
766 ########################################################################
769 ##############
770 # landmark (<text>)
772 # Print <text> to standard error as a debugging aid.
774 # Globals: $_DEBUG_LM
776 landmark()
778 if test "${_DEBUG_LM}" = 'yes'; then
779 echo ">>> $*" >&2;
783 landmark "1: debugging functions";
786 ##############
787 # clean_up ()
789 # Clean up at exit.
791 clean_up()
793 if test -d "${_TMP_DIR}"; then
794 rm -f "${_TMP_DIR}"/*;
795 rmdir "${_TMP_DIR}";
800 ##############
801 # echo2 (<text>*)
803 # Output to stderr.
805 # Arguments : arbitrary text.
807 echo2()
809 echo "$*" >&2;
813 ##############
814 # echo2n (<text>*)
816 # Output to stderr.
818 # Arguments : arbitrary text.
820 echo2n()
822 echo -n "$*" >&2;
826 #############
827 # diag (text>*)
829 # Output a diagnostic message to stderr
831 diag()
833 echo2 '>>>>>'"$*";
837 #############
838 # error (<text>*)
840 # Print an error message to standard error; exit with an error condition
842 error()
844 local i;
845 local _code;
846 _code="${_ERROR}";
847 case "$#" in
848 0) true; ;;
849 1) echo2 'groffer error: '"$1"; ;;
851 echo2 'groffer error: '"$1";
852 _code="$2";
854 *) echo2 'groffer error: wrong number of arguments in error().'; ;;
855 esac;
856 if test "${_DEBUG}" = 'yes'; then
857 func_stack_dump;
859 clean_up;
860 kill "${_PROCESS_ID}" >/dev/null 2>&1;
861 kill -9 "${_PROCESS_ID}" >/dev/null 2>&1;
862 exit "${_code}";
866 #############
867 # abort (<text>*)
869 # Terminate program with error condition
871 abort()
873 error "Program aborted.";
874 exit 1;
878 #############
879 # func_check (<func_name> <rel_op> <nr_args> "$@")
881 # Check number of arguments and register to _FUNC_STACK.
883 # Arguments: >=3
884 # <func_name>: name of the calling function.
885 # <rel_op>: a relational operator: = != < > <= >=
886 # <nr_args>: number of arguments to be checked against <operator>
887 # "$@": the arguments of the calling function.
889 func_check()
891 local _comp;
892 local _fname;
893 local _nargs;
894 local _op;
895 local _s;
896 if test "$#" -lt 3; then
897 error 'func_check() needs at least 3 arguments.';
899 _fname="$1";
900 case "$3" in
902 _nargs="$3";
903 _s='';
905 0|[2-9])
906 _nargs="$3";
907 _s='s';
910 error "func_check(): third argument must be a digit.";
912 esac;
913 case "$2" in
914 '='|'-eq')
915 _op='-eq';
916 _comp='exactly';
918 '>='|'-ge')
919 _op='-ge';
920 _comp='at least';
922 '<='|'-le')
923 _op='-le';
924 _comp='at most';
926 '<'|'-lt')
927 _op='-lt';
928 _comp='less than';
930 '>'|'-gt')
931 _op='-gt';
932 _comp='more than';
934 '!='|'-ne')
935 _op='-ne';
936 _comp='not';
939 error \
940 'func_check(): second argument is not a relational operator.';
942 esac;
943 shift 3;
944 if test "$#" "${_op}" "${_nargs}"; then
945 do_nothing;
946 else
947 error \
948 "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
950 if test "${_DEBUG}" = 'yes'; then
951 func_push "${_fname} $*";
956 #############
957 # func_pop ()
959 # Retrieve the top element from the stack.
961 # The stack elements are separated by `!'; the popped element is
962 # identical to the original element, except that all `!' characters
963 # were removed.
965 # Arguments: 1
967 func_pop()
969 if test "${_DEBUG}" = 'yes'; then
970 if test "$#" -ne 0; then
971 error 'func_pop() does not have arguments.';
973 case "${_FUNC_STACK}" in
975 error 'func_pop(): stack is empty.';
977 *!*)
978 # split at first bang `!'.
979 _FUNC_STACK="$(echo -n ${_FUNC_STACK} \
980 | sed -e 's/^[^!]*!//')";
983 _FUNC_STACK='';
985 esac;
990 #############
991 # func_push (<element>)
993 # Store another element to stack.
995 # The stack elements are separated by `!'; if <element> contains a `!'
996 # it is removed first.
998 # Arguments: 1
1000 func_push()
1002 local _element;
1003 if test "${_DEBUG}" = 'yes'; then
1004 if test "$#" -ne 1; then
1005 error 'func_push() needs 1 argument.';
1007 case "$1" in
1008 *'!'*)
1009 # remove all bangs `!'.
1010 _element="$(echo -n "$1" | sed -e 's/!//g')";
1013 _element="$1";
1015 esac;
1016 if test "${_FUNC_STACK}" = ''; then
1017 _FUNC_STACK="${_element}";
1018 else
1019 _FUNC_STACK="${_element}!${_FUNC_STACK}";
1025 #############
1026 # func_stack_dump ()
1028 # Print the content of the stack. Ignore the arguments.
1030 func_stack_dump()
1032 diag 'call stack:';
1033 case "${_FUNC_STACK}" in
1034 *!*)
1035 _rest="${_FUNC_STACK}";
1036 while test "${_rest}" != ''; do
1037 # get part before the first bang `!'.
1038 diag "$(echo -n "${_rest}" | sed -e 's/!.*$//')";
1039 # delete part before and including the first bang `!'.
1040 _rest="$(echo -n "${_rest}" | sed -e 's/^[^!]*!//')";
1041 done;
1044 diag "${_FUNC_STACK}";
1046 esac;
1050 ########################################################################
1051 # System Test
1052 ########################################################################
1054 landmark "2: system test";
1056 # Test the availability of the system utilities used in this script.
1059 ########################################################################
1060 # Test of `true'.
1062 if true >/dev/null 2>&1; then
1063 true;
1064 else
1065 true()
1067 return "${_GOOD}";
1070 false()
1072 return "${_BAD}";
1077 ########################################################################
1078 # Test of `unset'.
1080 _test='test';
1081 if unset _test >/dev/null 2>&1 && test "${_test}" = ''; then
1082 true;
1083 else
1084 unset()
1086 for v in "$@"; do
1087 eval "$v"='';
1088 done;
1091 unset _test;
1093 ########################################################################
1094 # Test of builtin `local'
1097 _t_e_s_t_f_u_n_c_()
1099 local _test >/dev/null 2>&1 || return "${_BAD}";
1102 if _t_e_s_t_f_u_n_c_; then
1104 else
1105 local()
1107 if test "$1" != ''; then
1108 error "overriding global variable \`$1' with local value.";
1114 ########################################################################
1115 # Test of global setting in functions
1117 _global='outside';
1118 _clobber='outside';
1120 _t_e_s_t_f_u_n_c_()
1122 local _clobber;
1123 _global='inside';
1124 _clobber='inside';
1127 _t_e_s_t_f_u_n_c_;
1128 if test "${_global}" != 'inside' || test "${_clobber}" != 'outside';
1129 then
1130 error "Cannot assign to global variables from within functions.";
1133 unset _global;
1134 unset _clobber;
1137 ########################################################################
1138 # Test of function `sed'.
1140 if test "$(echo xTesTx \
1141 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1142 | sed -e '\|T|s||t|g')" != 'test';
1143 then
1144 error 'Test of "sed" command failed.';
1148 ########################################################################
1149 # Test of function `cat'.
1151 if test "$(echo test | cat)" != "test"; then
1152 error 'Test of "cat" command failed.';
1156 ########################################################################
1157 # Test for compression.
1159 if test "$(echo 'test' | gzip -c -d -f - 2>/dev/null)" = 'test'; then
1160 _HAS_COMPRESSION='yes';
1161 if echo 'test' | bzip2 -c 2>/dev/null | bzip2 -t 2>/dev/null \
1162 && test "$(echo 'test' | bzip2 -c 2>/dev/null \
1163 | bzip2 -d -c 2>/dev/null)" \
1164 = 'test'; then
1165 _HAS_BZIP='yes';
1166 else
1167 _HAS_BZIP='no';
1169 else
1170 _HAS_COMPRESSION='no';
1171 _HAS_BZIP='no';
1175 ########################################################################
1176 _t_e_s_t_f_u_n_c_()
1182 ########################################################################
1183 # Definition of normal Functions
1184 ########################################################################
1185 landmark "3: functions";
1187 ########################################################################
1188 # abort (<text>*)
1190 # Unconditionally terminate the program with error code;
1191 # useful for debugging.
1193 # defined above
1196 ########################################################################
1197 # base_name (<path>)
1199 # Get the file name part of <path>, i.e. delete everything up to last
1200 # `/' from the beginning of <path>.
1202 # Arguments : 1
1203 # Output : the file name part (without slashes)
1205 base_name()
1207 func_check base_name = 1 "$@";
1208 case "$1" in
1210 do_nothing;
1212 */*)
1213 # delete everything before and including the last slash `/'.
1214 echo -n "$1" | sed -e '\|^.*//*\([^/]*\)$|s||\1|';
1217 echo -n "$1";
1219 esac;
1220 eval "${return_ok}";
1224 ########################################################################
1225 # catz (<file>)
1227 # Decompress if possible or just print <file> to standard output.
1229 # gzip, bzip2, and .Z decompression is supported.
1231 # Arguments: 1, a file name.
1232 # Output: the content of <file>, possibly decompressed.
1234 if test "${_HAS_COMPRESSION}" = 'yes'; then
1235 catz()
1237 func_check catz = 1 "$@";
1238 case "$1" in
1240 error 'catz(): empty file name';
1242 '-')
1243 error 'catz(): for standard input use save_stdin()';
1245 esac;
1246 if is_yes "${_HAS_BZIP}"; then
1247 if bzip2 -t "$1" 2>/dev/null; then
1248 bzip2 -c -d "$1" 2>/dev/null;
1249 eval "${return_ok}";
1252 gzip -c -d -f "$1" 2>/dev/null;
1253 eval "${return_ok}";
1255 else
1256 catz()
1258 func_check catz = 1 "$@";
1259 cat "$1";
1260 eval "${return_ok}";
1265 ########################################################################
1266 # clean_up ()
1268 # Do the final cleaning up before exiting; used by the trap calls.
1270 # defined above
1273 ########################################################################
1274 # diag (<text>*)
1276 # Print marked message to standard error; useful for debugging.
1278 # defined above
1281 ########################################################################
1282 landmark '4: dirname()*';
1283 ########################################################################
1285 #######################################################################
1286 # dirname_append (<dir> <name>)
1288 # Append `name' to `dir' with clean handling of `/'.
1290 # Arguments : 2
1291 # Output : the generated new directory name <dir>/<name>
1293 dirname_append()
1295 func_check dirname_append = 2 "$@";
1296 local _res;
1297 if is_empty "$1"; then
1298 error "dir_append(): first argument is empty.";
1300 if is_empty "$2"; then
1301 echo -n "$1";
1302 else
1303 dirname_chop "$1"/"$2";
1305 eval "${return_ok}";
1309 ########################################################################
1310 # dirname_chop (<name>)
1312 # Remove unnecessary slashes from directory name.
1314 # Argument: 1, a directory name.
1315 # Output: path without double, or trailing slashes.
1317 dirname_chop()
1319 func_check dirname_chop = 1 "$@";
1320 local _arg;
1321 local _res;
1322 local _sep;
1323 # replace all multiple slashes by a single slash `/'.
1324 _res="$(echo -n "$1" | sed -e '\|///*|s||/|g')";
1325 case "${_res}" in
1326 ?*/)
1327 # remove trailing slash '/';
1328 echo -n "${_res}" | sed -e '\|/$|s|||';
1330 *) echo -n "${_res}"; ;;
1331 esac;
1332 eval "${return_ok}";
1336 ########################################################################
1337 # do_filearg (<filearg>)
1339 # Append the file, man-page, or standard input corresponding to the
1340 # argument to the temporary file. If this is compressed in the gzip
1341 # or Z format it is decompressed. A title element is generated.
1343 # Argument either:
1344 # - name of an existing files.
1345 # - `-' to represent standard input (several times allowed).
1346 # - `man:name.(section)' the man-page for `name' in `section'.
1347 # - `man:name.section' the man-page for `name' in `section'.
1348 # - `man:name' the man-page for `name' in the lowest `section'.
1349 # - `name.section' the man-page for `name' in `section'.
1350 # - `name' the man-page for `name' in the lowest `section'.
1351 # Globals :
1352 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1354 # Output : none
1355 # Return : $_GOOD if found, ${_BAD} otherwise.
1357 do_filearg()
1359 func_check do_filearg = 1 "$@";
1360 local _filespec;
1361 local i;
1362 _filespec="$1";
1363 # store sequence into positional parameters
1364 case "${_filespec}" in
1366 eval "${return_good}";
1368 '-')
1369 register_file '-';
1370 eval "${return_good}";
1372 */*) # with directory part; so no man search
1373 set -- 'File';
1376 if is_yes "${_MAN_ENABLE}"; then
1377 if is_yes "${_MAN_FORCE}"; then
1378 set -- 'Manpage' 'File';
1379 else
1380 set -- 'File' 'Manpage';
1382 else
1383 set -- 'File';
1386 esac;
1387 for i in "$@"; do
1388 case "$i" in
1389 File)
1390 if test -f "${_filespec}"; then
1391 if test -r "${_filespec}"; then
1392 register_file "${_filespec}";
1393 eval "${return_good}";
1394 else
1395 echo2 "could not read \`${_filespec}'";
1396 eval "${return_bad}";
1398 else
1399 continue;
1402 Manpage) # parse filespec as man page
1403 if is_not_yes "${_MAN_IS_SETUP}"; then
1404 man_setup;
1406 if man_do_filespec "${_filespec}"; then
1407 eval "${return_good}";
1408 else
1409 continue;
1412 esac;
1413 done;
1414 eval "${return_bad}";
1415 } # do_filearg()
1418 ########################################################################
1419 # do_nothing ()
1421 # Dummy function.
1423 do_nothing()
1425 return "${_OK}";
1429 ########################################################################
1430 # echo2 (<text>*)
1432 # Print to standard error with final line break.
1434 # defined above
1437 ########################################################################
1438 # echo2n (<text>*)
1440 # Print to standard error without final line break.
1442 # defined above
1445 ########################################################################
1446 # error (<text>*)
1448 # Print error message and exit with error code.
1450 # defined above
1453 ########################################################################
1454 # func_check (<func_name> <rel_op> <nr_args> "$@")
1456 # Check number of arguments and register to _FUNC_STACK.
1458 # Arguments: >=3
1459 # <func_name>: name of the calling function.
1460 # <rel_op>: a relational operator: = != < > <= >=
1461 # <nr_args>: number of arguments to be checked against <operator>
1462 # "$@": the arguments of the calling function.
1464 # defined above
1466 #########################################################################
1467 # func_pop ()
1469 # Delete the top element from the function call stack.
1471 # defined above
1474 ########################################################################
1475 # func_push (<element>)
1477 # Store another element to function call stack.
1479 # defined above
1482 ########################################################################
1483 # func_stack_dump ()
1485 # Print the content of the stack.
1487 # defined above
1490 ########################################################################
1491 # get_first_essential (<arg>*)
1493 # Retrieve first non-empty argument.
1495 # Return : `1' if all arguments are empty, `0' if found.
1496 # Output : the retrieved non-empty argument.
1498 get_first_essential()
1500 func_check get_first_essential '>=' 0 "$@";
1501 local i;
1502 if test "$#" -eq 0; then
1503 eval "${return_ok}";
1505 for i in "$@"; do
1506 if is_not_empty "$i"; then
1507 echo -n "$i";
1508 eval "${return_ok}";
1510 done;
1511 eval "${return_bad}";
1515 ########################################################################
1516 landmark '5: is_*()';
1517 ########################################################################
1519 ########################################################################
1520 # is_dir (<name>)
1522 # Test whether `name' is a directory.
1524 # Arguments : 1
1525 # Return : `0' if arg1 is a directory, `1' otherwise.
1527 is_dir()
1529 func_check is_dir = 1 "$@";
1530 if is_not_empty "$1" && test -d "$1" && test -r "$1"; then
1531 eval "${return_yes}";
1532 else
1533 eval "${return_no}";
1535 eval "${return_ok}";
1539 ########################################################################
1540 # is_empty (<string>)
1542 # Test whether `string' is empty.
1544 # Arguments : <=1
1545 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1547 is_empty()
1549 func_check is_empty = 1 "$@";
1550 if test -z "$1"; then
1551 eval "${return_yes}";
1552 else
1553 eval "${return_no}";
1555 eval "${return_ok}";
1559 ########################################################################
1560 # is_equal (<string1> <string2>)
1562 # Test whether `string1' is equal to <string2>.
1564 # Arguments : 2
1565 # Return : `0' both arguments are equal strings, `1' otherwise.
1567 is_equal()
1569 func_check is_equal = 2 "$@";
1570 if test "$1" = "$2"; then
1571 eval "${return_yes}";
1572 else
1573 eval "${return_no}";
1575 eval "${return_ok}";
1579 ########################################################################
1580 # is_file (<name>)
1582 # Test whether `name' is a readable file.
1584 # Arguments : 1
1585 # Return : `0' if arg1 is a readable file, `1' otherwise.
1587 is_file()
1589 func_check is_file = 1 "$@";
1590 if is_not_empty "$1" && test -f "$1" && test -r "$1"; then
1591 eval "${return_yes}";
1592 else
1593 eval "${return_no}";
1595 eval "${return_ok}";
1599 ########################################################################
1600 # is_not_dir (<name>)
1602 # Test whether `name' is not a readable directory.
1604 # Arguments : 1
1605 # Return : `0' if arg1 is a directory, `1' otherwise.
1607 is_not_dir()
1609 func_check is_not_dir = 1 "$@";
1610 if is_dir "$1"; then
1611 eval "${return_no}";
1612 else
1613 eval "${return_yes}";
1615 eval "${return_ok}";
1619 ########################################################################
1620 # is_not_empty (<string>)
1622 # Test whether `string' is not empty.
1624 # Arguments : <=1
1625 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1627 is_not_empty()
1629 func_check is_not_empty = 1 "$@";
1630 if is_empty "$1"; then
1631 eval "${return_no}";
1632 else
1633 eval "${return_yes}";
1635 eval "${return_ok}";
1639 ########################################################################
1640 # is_not_equal (<string1> <string2>)
1642 # Test whether `string1' and <string2> differ.
1644 # Arguments : 2
1646 is_not_equal()
1648 func_check is_not_equal = 2 "$@";
1649 if is_equal "$1" "$2"; then
1650 eval "${return_no}";
1651 else
1652 eval "${return_yes}";
1654 eval "${return_ok}";
1658 ########################################################################
1659 # is_not_file (<filename>)
1661 # Test whether `name' is a not readable file.
1663 # Arguments : >=1 (empty allowed), more args are ignored
1665 is_not_file()
1667 func_check is_not_file '>=' 1 "$@";
1668 if is_file "$1"; then
1669 eval "${return_no}";
1670 else
1671 eval "${return_yes}";
1673 eval "${return_ok}";
1677 ########################################################################
1678 # is_not_prog (<name>)
1680 # Verify that arg is a not program in $PATH.
1682 # Arguments : >=1 (empty allowed)
1683 # more args are ignored, this allows to specify progs with arguments
1685 is_not_prog()
1687 func_check is_not_prog '>=' 1 "$@";
1688 if where "$1" >/dev/null; then
1689 eval "${return_no}";
1690 else
1691 eval "${return_yes}";
1693 eval "${return_ok}";
1697 ########################################################################
1698 # is_not_yes (<string>)
1700 # Test whether `string' is not "yes".
1702 # Arguments : 1
1704 is_not_yes()
1706 func_check is_not_yes = 1 "$@";
1707 if test "$1" = 'yes'; then
1708 eval "${return_no}";
1709 else
1710 eval "${return_yes}";
1712 eval "${return_ok}";
1716 ########################################################################
1717 # is_prog (<name>)
1719 # Determine whether arg is a program in $PATH
1721 # Arguments : >=1 (empty allowed)
1722 # more args are ignored, this allows to specify progs with arguments
1724 is_prog()
1726 func_check is_prog '>=' 1 "$@";
1727 if where "$1" >/dev/null; then
1728 eval "${return_yes}";
1729 else
1730 eval "${return_no}";
1732 eval "${return_ok}";
1736 ########################################################################
1737 # is_yes (<string>)
1739 # Test whether `string' has value "yes".
1741 # Arguments : <=1
1742 # Return : `0' if arg1 is `yes', `1' otherwise.
1744 is_yes()
1746 func_check is_yes = 1 "$@";
1747 if test "$1" = 'yes'; then
1748 eval "${return_yes}";
1749 else
1750 eval "${return_no}";
1752 eval "${return_ok}";
1756 ########################################################################
1757 # landmark ()
1759 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1761 # Globals: $_DEBUG_LM
1763 # Defined in section `Debugging functions'.
1766 ########################################################################
1767 # leave ()
1769 # Clean exit without an error.
1771 leave()
1773 clean_up;
1774 exit "${_OK}";
1778 ########################################################################
1779 landmark '6: list_*()';
1780 ########################################################################
1782 ########################################################################
1783 # list_append (<list> <element>...)
1785 # Arguments: >=2
1786 # <list>: a space-separated list of single-quoted elements.
1787 # <element>: some sequence of characters.
1788 # Output:
1789 # if <list> is empty: "'<element>' '...'"
1790 # otherwise: "<list> '<element>' ..."
1792 list_append()
1794 func_check list_append '>=' 2 "$@";
1795 local _element;
1796 local _res;
1797 _res="$1";
1798 shift;
1799 for s in "$@"; do
1800 case "$s" in
1801 *\'*)
1802 # escape each single quote by replacing each "'" (squote)
1803 # by "'\''" (squote bslash squote squote);
1804 # note that the backslash must be doubled for `sed'.
1805 _element="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')";
1808 _element="$s";
1810 esac;
1811 _res="${_res} '${_element}'";
1812 done;
1813 echo -n "${_res}";
1814 eval "${return_ok}";
1818 ########################################################################
1819 # list_check (<list>)
1821 # Check whether <list> is a space-separated list of '-quoted elements.
1823 # If the test fails an error is raised.
1824 # If the test succeeds the argument is echoed.
1826 # Testing criteria:
1827 # A list has the form "'first' 'second' '...' 'last'".
1828 # So it has a leading and a final quote and the elements are separated
1829 # by "' '" constructs. If these are all removed there should not be
1830 # any single-quotes left. Watch out for escaped single quotes; they
1831 # have the form '\'' (sq bs sq sq).
1833 # Arguments: 1
1834 # Output: the argument <list> unchanged, it the check succeeded.
1836 list_check()
1838 func_check list_check = 1 "$@";
1839 local _list;
1840 if is_empty "$1"; then
1841 eval "${return_ok}";
1843 case "$1" in
1844 \'*\') _list="$1"; ;;
1846 error "list_check() bad list: $1"
1848 esac;
1849 # Remove leading single quote,
1850 # remove final single quote,
1851 # remove escaped single quotes (squote bslash squote squote)
1852 # [note that `sed' doubles the backslash (bslash bslash)],
1853 # remove field separators (squote space squote).
1854 _list="$(echo -n "${_list}" \
1855 | sed -e 's/^'"${_SQUOTE}"'//' \
1856 | sed -e 's/'"${_SQUOTE}"'$//' \
1857 | sed -e \
1858 's/'"${_SQUOTE}${_BSLASH}${_BSLASH}${_SQUOTE}${_SQUOTE}"'//g' \
1859 | sed -e 's/'"${_SQUOTE}${_SPACE}${_SPACE}"'*'"${_SQUOTE}"'//g')";
1860 case "${_list}" in
1861 *\'*) # criterium fails if squote is left
1862 error 'list_check() bad list: '"${_list}";
1864 esac;
1865 echo -n "$1";
1866 eval "${return_ok}";
1870 ########################################################################
1871 # list_element_from_arg (<arg>)
1873 # Arguments: 1
1874 # <arg>: some sequence of characters (also single quotes allowed).
1875 # Output: the list element generated from <arg>.
1877 list_element_from_arg()
1879 func_check list_element_from_arg = 1 "$@";
1880 local _res;
1881 echo -n "'";
1882 # replace each single quote "'" by "'\''".
1883 echo -n "$1" | sed -e 's/'\''/&\\&&/g'; # ' for emacs
1884 echo -n "'";
1885 eval "${return_ok}";
1889 ########################################################################
1890 # list_from_args (<arg>...)
1892 # Generate a space-separated list of single-quoted elements from args.
1894 # Arguments:
1895 # <arg>: some sequence of characters.
1896 # Output: "'<arg>' '...'"
1898 list_from_args()
1900 func_check list_from_args '>=' 1 "$@";
1901 local _list;
1902 _list="";
1903 for s in "$@"; do
1904 _list="$(list_append "${_list}" "$s")";
1905 done;
1906 echo -n "${_list}";
1907 eval "${return_ok}";
1911 ########################################################################
1912 # list_from_cmdline (<s_n> <s_a> <l_n> <l_a> [<cmdline_arg>...])
1914 # Transform command line arguments into a normalized form.
1916 # Options, option arguments, and file parameters are identified and
1917 # output each as a single-quoted argument of its own. Options and
1918 # file parameters are separated by a '--' argument.
1920 # Arguments: >=4
1921 # <s_n>: space-separated list of short options without an arg.
1922 # <s_a>: space-separated list of short options that have an arg.
1923 # <l_n>: space-separated list of long options without an arg.
1924 # <l_a>: space-separated list of long options that have an arg.
1925 # <cmdline_arg>...: the arguments from the command line (by "$@").
1927 # Globals: $POSIXLY_CORRECT (only kept for compatibility).
1929 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1931 # Example:
1932 # list_normalize 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1933 # will result in printing:
1934 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1935 # If $POSIXLY_CORRECT is not empty, the result will be:
1936 # '-a' '--' 'f1' '-bcarg' '--long=larg' 'f2'
1938 # Rationale:
1939 # In POSIX, the first non-option ends the option processing.
1940 # In GNU mode (default), non-options are sorted behind the options.
1942 # Use this function only in the following way:
1943 # eval set -- "$(args_norm '...' '...' '...' '...' "$@")";
1944 # while test "$1" != '--'; do
1945 # case "$1" in
1946 # ...
1947 # esac;
1948 # shift;
1949 # done;
1950 # shift; #skip '--'
1951 # # all positional parameters ("$@") left are file name parameters.
1953 list_from_cmdline()
1955 func_check list_from_cmdline '>=' 4 "$@";
1956 local _fparams;
1957 local _fn;
1958 local _result;
1959 local _long_a;
1960 local _long_n;
1961 local _short_a;
1962 local _short_n;
1963 _short_n="$(list_check "$1")"; # short options, no argument
1964 _short_a="$(list_check "$2")"; # short options with argument
1965 _long_n="$(list_check "$3")"; # long options, no argument
1966 _long_a="$(list_check "$4")"; # long options with argument
1967 shift 4;
1968 _fn='list_from_cmdline():'; # for error messages
1969 if test "$#" -eq 0; then
1970 echo -n "'--'";
1971 eval "${return_ok}";
1973 _fparams='';
1974 _result='';
1975 while test "$#" -ge 1; do
1976 _arg="$1";
1977 shift;
1978 case "$_arg" in
1979 --) break; ;;
1980 --?*)
1981 # delete leading '--';
1982 _opt="$(echo -n "${_arg}" | sed -e 's/^..//')";
1983 if list_has "${_long_n}" "${_opt}"; then
1984 # long option, no argument
1985 _result="$(list_append "${_result}" "--${_opt}")";
1986 continue;
1988 if list_has "${_long_a}" "${_opt}"; then
1989 # long option with argument
1990 _result="$(list_append "${_result}" "--${_opt}")";
1991 if test "$#" -le 0; then
1992 error "${_fn} no argument for option --${_opt}."
1994 _result="$(list_append "${_result}" "$1")";
1995 shift;
1996 continue;
1998 # test on `--opt=arg'
1999 if string_contains "${_opt}" '='; then
2000 # extract option by deleting from the first '=' to the end
2001 _lopt="$(echo -n "${_opt}" | sed -e 's/=.*$//')";
2002 if list_has "${_long_a}" "${_lopt}"; then
2003 # get the option argument by deleting up to first `='
2004 _optarg="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')";
2005 _result="$(list_append "${_result}" \
2006 "--${_lopt}" "${_optarg}")";
2007 continue;
2010 error "${_fn} --${_opt} is not an option."
2012 -?*) # short option (cluster)
2013 # delete leading `-';
2014 _rest="$(echo -n "${_arg}" | sed -e 's/^.//')";
2015 while is_not_empty "${_rest}"; do
2016 # get next short option from cluster (first char of $_rest)
2017 _optchar="$(echo -n "${_rest}" | sed -e 's/^\(.\).*$/\1/')";
2018 # remove first character from ${_rest};
2019 _rest="$(echo -n "${_rest}" | sed -e 's/^.//')";
2020 if list_has "${_short_n}" "${_optchar}"; then
2021 _result="$(list_append "${_result}" "-${_optchar}")";
2022 continue;
2023 elif list_has "${_short_a}" "${_optchar}"; then
2024 # remove leading character
2025 case "${_optchar}" in
2027 _rest="$(echo -n "${_rest}" | sed -e '\|^.|s|||')";
2030 _rest="$(echo -n "${_rest}" | sed -e 's/^.//')";
2032 ??*)
2033 error "${_fn} several chars parsed for short option."
2035 esac;
2036 if is_empty "${_rest}"; then
2037 if test "$#" -ge 1; then
2038 _result="$(list_append "${_result}" \
2039 "-${_optchar}" "$1")";
2040 shift;
2041 continue;
2042 else
2043 error \
2044 "${_fn}"' no argument for option -'"${_optchar}."
2046 else # rest is the argument
2047 _result="$(list_append "${_result}" \
2048 "-${_optchar}" "${_rest}")";
2049 _rest='';
2050 continue;
2052 else
2053 error "${_fn} unknown option -${_optchar}."
2055 done;
2058 # Here, $_arg is not an option, so a file parameter.
2059 # When $POSIXLY_CORRECT is set this ends option parsing;
2060 # otherwise, the argument is stored as a file parameter and
2061 # option processing is continued.
2062 _fparams="$(list_append "${_fparams}" "${_arg}")";
2063 if is_not_empty "$POSIXLY_CORRECT"; then
2064 break;
2067 esac;
2068 done;
2069 _result="$(list_append "${_result}" '--')";
2070 if is_not_empty "${_fparams}"; then
2071 _result="${_result} ${_fparams}";
2073 if test "$#" -gt 0; then
2074 _result="$(list_append "${_result}" "$@")";
2076 echo -n "$_result";
2077 eval "${return_ok}";
2078 } # list_from_cmdline()
2081 ########################################################################
2082 # list_from_lists (<list1> <list2>...)
2084 # Generate a list from the concatenation of the lists in the arguments.
2086 # Arguments: >=2
2087 # <list*>: string of space-separated single-quoted elements.
2088 # Output: "'<element1_of_list1>' ..."
2090 list_from_lists()
2092 func_check list_from_lists '>=' 2 "$@";
2093 _list='';
2094 echo -n "$*";
2095 eval "${return_ok}";
2098 ########################################################################
2099 # list_from_split (<string> <separator>)
2101 # In <string> escape white space and replace each <separator> by space.
2103 # Arguments: 2: a <string> that is to be split into parts divided by
2104 # <separator>
2105 # Output: the resulting string
2107 list_from_split()
2109 func_check list_from_split = 2 "$@";
2110 local _s;
2112 # precede each space or tab by a backslash `\' (doubled for `sed')
2113 _s="$(echo -n "$1" | sed -e 's/\(['"${_SPACE}${_TAB}"']\)/\\\1/g')";
2115 # replace split character of string by the list separator ` ' (space).
2116 case "$2" in
2117 /) # cannot use normal `sed' separator
2118 echo -n "${_s}" | sed -e '\|'"$2"'|s|| |g';
2120 ?) # use normal `sed' separator
2121 echo -n "${_s}" | sed -e 's/'"$2"'/ /g';
2123 ??*)
2124 error 'list_from_split(): separator must be a single character.';
2126 esac;
2127 eval "${return_ok}";
2131 ########################################################################
2132 # list_has (<list> <element>)
2134 # Arguments: 2
2135 # <list>: a space-separated list of single-quoted elements.
2136 # <element>: some sequence of characters.
2137 # Output:
2138 # if <list> is empty: "'<element>' '...'"
2139 # otherwise: "<list> '<element>' ..."
2141 list_has()
2143 func_check list_has = 2 "$@";
2144 if is_empty "$1"; then
2145 eval "${return_no}";
2147 _list="$1";
2148 _element="$2";
2149 case "$2" in
2150 \'*\') _element="$2"; ;;
2151 *) _element="'$2'"; ;;
2152 esac;
2153 if string_contains "${_list}" "${_element}"; then
2154 eval "${return_yes}";
2155 else
2156 eval "${return_no}";
2158 eval "${return_ok}";
2162 ########################################################################
2163 # list_has_not (<list> <element>)
2165 # Arguments: 2
2166 # <list>: a space-separated list of single-quoted elements.
2167 # <element>: some sequence of characters.
2168 # Output:
2169 # if <list> is empty: "'<element>' '...'"
2170 # otherwise: "<list> '<element>' ..."
2172 list_has_not()
2174 func_check list_has_not = 2 "$@";
2175 if is_empty "$1"; then
2176 eval "${return_yes}";
2178 _list="$1";
2179 _element="$2";
2180 case "$2" in
2181 \'*\') _element="$2"; ;;
2182 *) _element="'$2'"; ;;
2183 esac;
2184 if string_contains "${_list}" "${_element}"; then
2185 eval "${return_no}";
2186 else
2187 eval "${return_yes}";
2189 eval "${return_ok}";
2193 ########################################################################
2194 # list_length (<list>)
2196 # Arguments: 1
2197 # <list>: a space-separated list of single-quoted elements.
2198 # Output: the number of elements in <list>
2200 list_length()
2202 func_check list_length = 1 "$@";
2203 eval set -- "$1";
2204 echo -n "$#";
2205 eval "${return_ok}";
2209 ########################################################################
2210 # list_prepend (<list> <element>...)
2212 # Insert new <element> at the beginning of <list>
2214 # Arguments: >=2
2215 # <list>: a space-separated list of single-quoted elements.
2216 # <element>: some sequence of characters.
2217 # Output:
2218 # if <list> is empty: "'<element>' ..."
2219 # otherwise: "'<element>' ... <list>"
2221 list_prepend()
2223 func_check list_prepend '>=' 2 "$@";
2224 local _res;
2225 _res="$1";
2226 shift;
2227 for s in "$@"; do
2228 # escape single quotes in list style (squote bslash squote squote).
2229 _element="$(echo -n "$s" | sed -e 's/'\''/&\\&&/g')";
2230 _res="'${_element}' ${_res}";
2231 done;
2232 echo -n "${_res}";
2233 eval "${return_ok}";
2237 ########################################################################
2238 landmark '7: man_*()';
2239 ########################################################################
2241 ########################################################################
2242 # man_do_filespec (<filespec>)
2244 # Print suitable man page(s) for filespec to $_TMP_CAT.
2246 # Arguments : 2
2247 # <filespec>: argument of the form `man:name.section', `man:name',
2248 # `man:name(section)', `name.section', `name'.
2250 # Globals : $_OPT_ALL
2252 # Output : none.
2253 # Return : `0' if man page was found, `1' else.
2255 # Only called from do_fileargs(), checks on $MANPATH and
2256 # $_MAN_ENABLE are assumed.
2258 man_do_filespec()
2260 func_check man_do_filespec = 1 "$@";
2261 local _got_one;
2262 local _name;
2263 local _prevsec;
2264 local _res;
2265 local _section;
2266 local _spec;
2267 local _string;
2268 local s;
2269 if is_empty "${_MAN_PATH}"; then
2270 eval "${return_bad}";
2272 if is_empty "$1"; then
2273 eval "${return_bad}";
2275 _spec="$1";
2276 _name='';
2277 _section='';
2278 case "${_spec}" in
2279 */*) # not a man spec when it contains '/'
2280 eval "${return_bad}";
2282 man:?*\(?*\)) # man:name(section)
2283 _name="$(echo -n "${_spec}" \
2284 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2285 _section="$(echo -n "${_spec}" \
2286 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2288 man:?*.?*) # man:name.section
2289 _name="$(echo -n "${_spec}" \
2290 | sed -e 's/^man:\(..*\)\.\(..*\)$/\1/')";
2291 _section="$(echo -n "${_spec}" \
2292 | sed -e 's/^man:\(..*\)\.\(..*\)$/\2/')";
2294 man:?*) # man:name
2295 _name="$(echo -n "${_spec}" | sed -e 's/^man://')";
2297 ?*\(?*\)) # name(section)
2298 _name="$(echo -n "${_spec}" \
2299 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2300 _section="$(echo -n "${_spec}" \
2301 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2303 ?*.?*) # name.section
2304 _name="$(echo -n "${_spec}" \
2305 | sed -e 's/^\(..*\)\.\(..*\)$/\1/')";
2306 _section="$(echo -n "${_spec}" \
2307 | sed -e 's/^\(..*\)\.\(..*\)$/\2/')";
2310 _name="${_filespec}";
2312 esac;
2313 if is_empty "${_name}"; then
2314 eval "${return_bad}";
2316 _got_one='no';
2317 if is_empty "${_section}"; then
2318 eval set -- "${_MAN_AUTO_SEC}";
2319 for s in "$@"; do
2320 if man_search_section "${_name}" "$s"; then # found
2321 if is_yes "${_MAN_ALL}"; then
2322 _got_one='yes';
2323 else
2324 eval "${return_good}";
2327 done;
2328 else
2329 if man_search_section "${_name}" "${_section}"; then
2330 eval "${return_good}";
2331 else
2332 eval "${return_bad}";
2335 if is_yes "${_MAN_ALL}" && is_yes "${_got_one}"; then
2336 eval "${return_good}";
2338 eval "${return_bad}";
2339 } # man_do_filespec()
2342 ########################################################################
2343 # man_register_file (<file> <name> [<section>])
2345 # Write a found man page file and register the title element.
2347 # Arguments: 1, 2, or 3; maybe empty
2348 # Output: none
2350 man_register_file()
2352 func_check man_register_file '>=' 2 "$@";
2353 case "$#" in
2354 2|3) do_nothing; ;;
2356 error "man_register_file() expects 2 or 3 arguments.";
2358 esac;
2359 if is_empty "$1"; then
2360 error 'man_register_file(): file name is empty';
2362 to_tmp "$1";
2363 case "$#" in
2365 register_title "man:$2";
2366 eval "${return_ok}";
2369 register_title "$2($3)";
2370 eval "${return_ok}";
2372 esac;
2373 eval "${return_ok}";
2377 ########################################################################
2378 # man_search_section (<name> <section>)
2380 # Retrieve man pages.
2382 # Arguments : 2
2383 # Globals : $_MAN_PATH, $_MAN_EXT
2384 # Return : 0 if found, 1 otherwise
2386 man_search_section()
2388 func_check man_search_section = 2 "$@";
2389 local _dir;
2390 local _ext;
2391 local _got_one;
2392 local _name;
2393 local _prefix
2394 local _section;
2395 local d;
2396 local f;
2397 if is_empty "${_MAN_PATH}"; then
2398 eval "${return_bad}";
2400 if is_empty "$1"; then
2401 eval "${return_bad}";
2403 if is_empty "$2"; then
2404 eval "${return_bad}";
2406 _name="$1";
2407 _section="$2";
2408 eval set -- "$(path_split "${_MAN_PATH}")";
2409 _got_one='no';
2410 if is_empty "${_MAN_EXT}"; then
2411 for d in "$@"; do
2412 _dir="$(dirname_append "$d" "man${_section}")";
2413 if is_dir "${_dir}"; then
2414 _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")";
2415 for f in $(echo -n ${_prefix}*); do
2416 if is_file "$f"; then
2417 if is_yes "${_got_one}"; then
2418 register_file "$f";
2419 elif is_yes "${_MAN_ALL}"; then
2420 man_register_file "$f" "${_name}";
2421 else
2422 man_register_file "$f" "${_name}" "${_section}";
2423 eval "${return_good}";
2425 _got_one='yes';
2427 done;
2429 done;
2430 else
2431 _ext="${_MAN_EXT}";
2432 # check for directory name having trailing extension
2433 for d in "$@"; do
2434 _dir="$(dirname_append $d man${_section}${_ext})";
2435 if is_dir "${_dir}"; then
2436 _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")";
2437 for f in ${_prefix}*; do
2438 if is_file "$f"; then
2439 if is_yes "${_got_one}"; then
2440 register_file "$f";
2441 elif is_yes "${_MAN_ALL}"; then
2442 man_register_file "$f" "${_name}";
2443 else
2444 man_register_file "$f" "${_name}" "${_section}";
2445 eval "${return_good}";
2447 _got_one='yes';
2449 done;
2451 done;
2452 # check for files with extension in directories without extension
2453 for d in "$@"; do
2454 _dir="$(dirname_append "$d" "man${_section}")";
2455 if is_dir "${_dir}"; then
2456 _prefix="$(dirname_append "${_dir}" \
2457 "${_name}.${_section}${_ext}")";
2458 for f in ${_prefix}*; do
2459 if is_file "$f"; then
2460 if is_yes "${_got_one}"; then
2461 register_file "$f";
2462 elif is_yes "${_MAN_ALL}"; then
2463 man_register_file "$f" "${_name}";
2464 else
2465 man_register_file "$f" "${_name}" "${_section}";
2466 eval "${return_good}";
2468 _got_one='yes';
2470 done;
2472 done;
2474 if is_yes "${_MAN_ALL}" && is_yes "${_got_one}"; then
2475 eval "${return_good}";
2477 eval "${return_bad}";
2478 } # man_search_section()
2481 ########################################################################
2482 # man_setup ()
2484 # Setup the variables $_MAN_* needed for man page searching.
2486 # Globals:
2487 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2488 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2489 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2490 # $_MAN_SEC, $_MAN_ALL
2491 # in/out: $_MAN_ENABLE
2493 # The precedence for the variables related to `man' is that of GNU
2494 # `man', i.e.
2496 # $LANG; overridden by
2497 # $LC_MESSAGES; overridden by
2498 # $LC_ALL; this has the same precedence as
2499 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2500 # $MANOPT; overridden by
2501 # the groffer command line options.
2503 man_setup()
2505 func_check main_man_setup = 0 "$@";
2506 local _lang;
2508 if is_yes "${_MAN_IS_SETUP}"; then
2509 eval "${return_ok}";
2511 _MAN_IS_SETUP='yes';
2513 if is_not_yes "${_MAN_ENABLE}"; then
2514 eval "${return_ok}";
2517 # determine basic path for man pages
2518 _MAN_PATH="$(get_first_essential \
2519 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2520 if is_empty "${_MAN_PATH}"; then
2521 if is_prog 'manpath'; then
2522 _MAN_PATH="$(manpath 2>/dev/null)"; # not always available
2525 if is_empty "${_MAN_PATH}"; then
2526 manpath_set_from_path;
2527 else
2528 _MAN_PATH="$(path_clean "${_MAN_PATH}")";
2530 if is_empty "${_MAN_PATH}"; then
2531 _MAN_ENABLE="no";
2532 eval "${return_ok}";
2535 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2536 if is_empty "${_MAN_ALL}"; then
2537 _MAN_ALL='no';
2540 _MAN_SYS="$(get_first_essential \
2541 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2542 _lang="$(get_first_essential \
2543 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2544 case "${_lang}" in
2545 C|POSIX)
2546 _MAN_LANG="";
2547 _MAN_LANG2="";
2550 _MAN_LANG="${_lang}";
2551 _MAN_LANG2="";
2554 _MAN_LANG="${_lang}";
2555 # get first two characters of $_lang
2556 _MAN_LANG2="$(echo -n "${_lang}" | sed -e 's/^\(..\).*$/\1/')";
2558 esac;
2559 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2561 manpath_add_lang_sys; # this is very slow
2563 _MAN_SEC="$(get_first_essential \
2564 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2565 if is_empty "${_MAN_PATH}"; then
2566 _MAN_ENABLE="no";
2567 eval "${return_ok}";
2570 _MAN_EXT="$(get_first_essential \
2571 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2572 eval "${return_ok}";
2573 } # man_setup()
2576 ########################################################################
2577 landmark '8: manpath_*()';
2578 ########################################################################
2580 ########################################################################
2581 # manpath_add_lang_sys ()
2583 # Add language and operating system specific directories to man path.
2585 # Arguments : 0
2586 # Output : none
2587 # Globals:
2588 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2589 # list of names of operating systems.
2590 # $_MAN_LANG and $_MAN_LANG2: each a single name
2591 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2592 # separated list of directories.
2594 manpath_add_lang_sys()
2596 func_check manpath_add_lang_sys = 0 "$@";
2597 local p;
2598 local _mp;
2599 if is_empty "${_MAN_PATH}"; then
2600 eval "${return_ok}";
2602 # twice test both sys and lang
2603 eval set -- "$(path_split "${_MAN_PATH}")";
2604 _mp='';
2605 for p in "$@"; do # loop on man path directories
2606 _mp="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2607 done;
2608 eval set -- "$(path_split "${_mp}")";
2609 for p in "$@"; do # loop on man path directories
2610 _mp="$(_manpath_add_lang_sys_single "${_mp}" "$p")";
2611 done;
2612 _MAN_PATH="$(path_chop "${_mp}")";
2613 eval "${return_ok}";
2617 _manpath_add_lang_sys_single()
2619 # To the directory in $1 append existing sys/lang subdirectories
2620 # Function is necessary to split the OS list.
2622 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2623 # argument: 2: `man_path' and `dir'
2624 # output: colon-separated path of the retrieved subdirectories
2626 local d;
2627 # if test "$#" -ne 2; then
2628 # error "manpath_add_system_single() needs 2 arguments.";
2629 # fi;
2630 _res="$1";
2631 _parent="$2";
2632 eval set -- "$(list_from_split "${_MAN_SYS}" ',')";
2633 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"; do
2634 _dir="$(dirname_append "${_parent}" "$d")";
2635 if path_not_contains "${_res}" "${_dir}" && is_dir "${_dir}"; then
2636 _res="${_res}:${_dir}";
2638 done;
2639 if path_not_contains "${_res}" "${_parent}"; then
2640 _res="${_res}:${_parent}";
2642 path_chop "${_res}";
2645 # end manpath_add_lang_sys ()
2648 ########################################################################
2649 # manpath_set_from_path ()
2651 # Determine basic search path for man pages from $PATH.
2653 # Return: `0' if a valid man path was retrieved.
2654 # Output: none
2655 # Globals:
2656 # in: $PATH
2657 # out: $_MAN_PATH
2659 manpath_set_from_path()
2661 func_check manpath_set_from_path = 0 "$@";
2662 local _base;
2663 local _mandir;
2664 local _manpath;
2665 local d;
2666 local e;
2667 _manpath='';
2669 # get a basic man path from $PATH
2670 if is_not_empty "${PATH}"; then
2671 eval set -- "$(path_split "${PATH}")";
2672 for d in "$@"; do
2673 # delete the final `/bin' part
2674 _base="$(echo -n "$d" | sed -e '\|//*bin/*$|s|||')";
2675 for e in /share/man /man; do
2676 _mandir="${_base}$e";
2677 if test -d "${_mandir}" && test -r "${_mandir}"; then
2678 _manpath="${_manpath}:${_mandir}";
2680 done;
2681 done;
2684 # append some default directories
2685 for d in /usr/local/share/man /usr/local/man \
2686 /usr/share/man /usr/man \
2687 /usr/X11R6/man /usr/openwin/man \
2688 /opt/share/man /opt/man \
2689 /opt/gnome/man /opt/kde/man; do
2690 if path_not_contains "${_manpath}" "$d" && is_dir "$d"; then
2691 _manpath="${_manpath}:$d";
2693 done;
2695 _MAN_PATH="${_manpath}";
2696 eval "${return_ok}";
2697 } # manpath_set_from_path()
2700 ########################################################################
2701 landmark '9: path_*()';
2702 ########################################################################
2704 ########################################################################
2705 # path_chop (<path>)
2707 # Remove unnecessary colons from path.
2709 # Argument: 1, a colon separated path.
2710 # Output: path without leading, double, or trailing colons.
2712 path_chop()
2714 func_check path_chop = 1 "$@";
2715 local _res;
2717 # replace multiple colons by a single colon `:'
2718 # remove leading and trailing colons
2719 echo -n "$1" | sed -e 's/:::*/:/g' |
2720 sed -e 's/^:*//' |
2721 sed -e 's/:*$//';
2722 eval "${return_ok}";
2726 ########################################################################
2727 # path_clean (<path>)
2729 # Remove non-existing directories from a colon-separated list.
2731 # Argument: 1, a colon separated path.
2732 # Output: colon-separated list of existing directories.
2734 path_clean()
2736 func_check path_clean = 1 "$@";
2737 local _arg;
2738 local _dir;
2739 local _res;
2740 local i;
2741 if test "$#" -ne 1; then
2742 error 'path_clean() needs 1 argument.';
2744 _arg="$1";
2745 eval set -- "$(path_split "${_arg}")";
2746 _res="";
2747 for i in "$@"; do
2748 if is_not_empty "$i" \
2749 && path_not_contains "${_res}" "$i" \
2750 && is_dir "$i";
2751 then
2752 case "$i" in
2753 ?*/) _res="${_res}$(dirname_chop "$i")"; ;;
2754 *) _res="${_res}:$i";
2755 esac;
2757 done;
2758 if path_chop "${_res}"; then
2759 eval "${return_ok}";
2760 else
2761 eval "${return_badk}";
2766 ########################################################################
2767 # path_contains (<path> <dir>)
2769 # Test whether `dir' is contained in `path', a list separated by `:'.
2771 # Arguments : 2 arguments.
2772 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2774 path_contains()
2776 func_check path_contains = 2 "$@";
2777 case ":$1:" in
2778 *":$2:"*)
2779 eval "${return_yes}";
2782 eval "${return_no}";
2784 esac;
2785 eval "${return_ok}";
2789 ########################################################################
2790 # path_not_contains (<path> <dir>)
2792 # Test whether `dir' is not contained in colon separated `path'.
2794 # Arguments : 2 arguments.
2796 path_not_contains()
2798 func_check path_not_contains = 2 "$@";
2799 if path_contains "$1" "$2"; then
2800 eval "${return_no}";
2801 else
2802 eval "${return_yes}";
2804 eval "${return_ok}";
2808 ########################################################################
2809 # path_split (<path>)
2811 # In `path' escape white space and replace each colon by a space.
2813 # Arguments: 1: a colon-separated path
2814 # Output: the resulting list, process with `eval set --'
2816 path_split()
2818 func_check path_split = 1 "$@";
2819 list_from_split "$1" ':';
2820 eval "${return_ok}";
2824 ########################################################################
2825 # reset ()
2827 # Reset the variables that can be affected by options to their default.
2830 # Defined in section `Preset' after the rudimentary shell tests.
2833 ########################################################################
2834 landmark '10: register_*()';
2835 ########################################################################
2837 ########################################################################
2838 # register_file (<filename>)
2840 # Write a found file and register the title element.
2842 # Arguments: 1: a file name
2843 # Output: none
2845 register_file()
2847 func_check register_file = 1 "$@";
2848 if is_empty "$1"; then
2849 error 'register_file(): file name is empty';
2851 if is_equal "$1" '-'; then
2852 to_tmp "${_TMP_STDIN}";
2853 register_title '-';
2854 else
2855 to_tmp "$1";
2856 register_title "$(base_name "$1")";
2858 eval "${return_ok}";
2862 ########################################################################
2863 # register_title (<filespec>)
2865 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2867 # Globals: $_REGISTERED_TITLE (rw)
2869 register_title()
2871 func_check register_title = 1 "$@";
2872 local _title;
2873 if is_empty "$1"; then
2874 eval "${return_ok}";
2876 _title="$(base_name "$1")"; # remove directory part
2878 # remove extension `.gz'
2879 _title="$(echo -n "${_title}" | sed -e 's/\.gz$//')";
2880 # remove extension `.Z'
2881 _title="$(echo -n "${_title}" | sed -e 's/\.Z$//')";
2883 if is_empty "${_title}"; then
2884 eval "${return_ok}";
2886 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${_title}";
2887 eval "${return_ok}";
2891 ########################################################################
2892 # save_stdin ()
2894 # Store standard input to temporary file (with decompression).
2896 if test "${_HAS_COMPRESSION}" = 'yes'; then
2897 save_stdin()
2899 local _f;
2900 func_check save_stdin = 0 "$@";
2901 _f="${_TMP_DIR}"/INPUT;
2902 cat >"${_f}";
2903 catz "${_f}" >"${_TMP_STDIN}";
2904 rm -f "${_f}";
2905 eval "${return_ok}";
2907 else
2908 save_stdin()
2910 func_check save_stdin = 0 "$@";
2911 cat >"${_TMP_STDIN}";
2912 eval "${return_ok}";
2917 ########################################################################
2918 landmark '11: stack_*()';
2919 ########################################################################
2921 ########################################################################
2922 # string_contains (<string> <part>)
2924 # Test whether `part' is contained in `string'.
2926 # Arguments : 2 text arguments.
2927 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2929 string_contains()
2931 func_check string_contains = 2 "$@";
2932 case "$1" in
2933 *"$2"*)
2934 eval "${return_yes}";
2937 eval "${return_no}";
2939 esac;
2940 eval "${return_ok}";
2944 ########################################################################
2945 # string_not_contains (<string> <part>)
2947 # Test whether `part' is not substring of `string'.
2949 # Arguments : 2 text arguments.
2950 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2952 string_not_contains()
2954 func_check string_not_contains = 2 "$@";
2955 if string_contains "$1" "$2"; then
2956 eval "${return_no}";
2957 else
2958 eval "${return_yes}";
2960 eval "${return_ok}";
2964 ########################################################################
2965 landmark '12: tmp_*()';
2966 ########################################################################
2968 ########################################################################
2969 # tmp_cat ()
2971 # output the temporary cat file (the concatenation of all input)
2973 tmp_cat()
2975 cat "${_TMP_CAT}";
2979 ########################################################################
2980 # tmp_create (<suffix>?)
2982 # create temporary file
2984 # It's safe to use the shell process ID together with a suffix to
2985 # have multiple temporary files.
2987 # Output : name of created file
2989 tmp_create()
2991 func_check tmp_create '<=' 1 "$@";
2992 local _tmp;
2993 _tmp="${_TMP_DIR}/$1";
2994 echo -n >"${_tmp}";
2995 echo -n "${_tmp}"; # output file name
2996 eval "${return_ok}";
3000 ########################################################################
3001 # to_tmp (<filename>)
3003 # print file (decompressed) to the temporary cat file
3005 to_tmp()
3007 func_check to_tmp = 1 "$@";
3008 if is_file "$1"; then
3009 if is_yes "${_OPT_LOCATION}"; then
3010 echo2 "$1";
3012 if is_yes "${_OPT_WHATIS}"; then
3013 what_is "$1" >>"${_TMP_CAT}";
3014 else
3015 catz "$1" >>"${_TMP_CAT}";
3017 else
3018 error "to_tmp(): could not read file \`$1'.";
3020 eval "${return_ok}";
3024 ########################################################################
3025 # trap_clean ()
3027 # disable trap on all exit codes ($_ALL_EXIT)
3029 # Arguments: 0
3030 # Globals: $_ALL_EXIT
3032 trap_clean()
3034 func_check trap_clean = 0 "$@";
3035 local i;
3036 for i in ${_ALL_EXIT}; do
3037 trap "" "$i" 2>/dev/null || true;
3038 done;
3039 eval "${return_ok}";
3043 ########################################################################
3044 # trap_set (<functionname>)
3046 # call function on all exit codes ($_ALL_EXIT)
3048 # Arguments: 1 (name of a shell function)
3049 # Globals: $_ALL_EXIT
3051 trap_set()
3053 func_check trap_set = 1 "$@";
3054 local i;
3055 for i in ${_ALL_EXIT}; do
3056 trap "$1" "$i" 2>/dev/null || true;
3057 done;
3058 eval "${return_ok}";
3062 ########################################################################
3063 # usage ()
3065 # print usage information to stderr
3067 usage()
3069 func_check usage = 0 "$@";
3070 echo2;
3071 version;
3072 cat >&2 <<EOF
3073 Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3074 This is free software licensed under the GNU General Public License.
3078 echo2 "Usage: ${_PROGRAM_NAME} [option]... [filespec]...";
3080 cat >&2 <<EOF
3082 where "filespec" is one of
3083 "filename" name of a readable file
3084 "-" for standard input
3085 "man:name.n" man page "name" in section "n"
3086 "man:name" man page "name" in first section found
3087 "name.n" man page "name" in section "n"
3088 "name" man page "name" in first section found
3089 and some more (see groffer(1) for details).
3091 Display roff files, standard input, and/or Unix manual pages with
3092 in a X window viewer or in a text pager.
3093 "-" stands for including standard input.
3094 "manpage" is the name of a man page, "x" its section.
3095 All input is decompressed on-the-fly (by gzip).
3097 -h --help print this usage message.
3098 -Q --source output as roff source.
3099 -T --device=name pass to groff using output device "name".
3100 -v --version print version information.
3102 All other short options are interpreted as "groff" formatting
3103 parameters and are transferred unmodified. The following groff
3104 options imply groff mode (groffer viewing disabled):
3106 -X display with "gxditview" using groff -X.
3107 -V display the groff execution pipe instead of formatting.
3108 -Z --ditroff --intermediate-output
3109 generate groff intermediate output without
3110 post-processing and viewing like groff -Z.
3112 The most important long options are
3114 --auto-modes=mode1,mode2,...
3115 set sequence of automatically tried modes.
3116 --bg set background color (not for all modes).
3117 --default reset effects of option processing so far.
3118 --display set the X device when displaying in X.
3119 --dpi=res set resolution to "res" ("75" (default) or "100").
3120 --dvi display in a viewer for TeX device independent format.
3121 --dvi-viewer choose the viewer program for dvi mode.
3122 --extension=ext restrict man pages to section suffix.
3123 --fg set foreground color (not for all modes).
3124 --geometry=geom set the window size and position when displaying in X.
3125 --groff process like groff, disable viewing features.
3126 --local-file same as --no-man.
3127 --locale=lang preset the language for man pages.
3128 --location print file locations additionally to standard error.
3129 --man check file parameters first whether they are man pages.
3130 --mode=auto|dvi|groff|pdf|ps|source|tty|www|x
3131 choose display mode.
3132 --no-location disable former call to "--location".
3133 --no-man disable man-page facility.
3134 --pager=program preset the paging program for tty mode.
3135 --pdf display in a PDF viewer.
3136 --pdf-viewer choose the viewer program for pdf mode.
3137 --ps display in a Postscript viewer.
3138 --ps-viewer choose the viewer program for ps mode.
3139 --shell specify shell under which to run this program.
3140 --systems=os1,os2,...
3141 search man pages for different operating systems.
3142 --title='text' set the title of the viewer window (not in all modes.
3143 --tty force paging on text terminal even when in X.
3144 --www display in a web browser.
3145 --www-viewer choose the web browser for www mode.
3146 --x display in an X roff viewer.
3147 --x-viewer choose viewer program for x mode.
3148 --xrm='resource' set X resouce.
3151 eval "${return_ok}";
3155 ########################################################################
3156 # version ()
3158 # print version information to stderr
3160 version()
3162 echo2 "${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3163 # also display groff's version, but not the called subprograms
3164 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2;
3168 ########################################################################
3169 # warning (<string>)
3171 # Print warning to stderr
3173 warning()
3175 echo2 "warning: $*";
3179 ########################################################################
3180 # what_is (<filename>)
3182 # Interpret <filename> as a man page and display its `whatis'
3183 # information as a fragment written in the groff language.
3185 what_is()
3187 func_check what_is = 1 "$@";
3188 local _res;
3189 local _dot;
3190 if is_not_file "$1"; then
3191 error "what_is(): argument is not a readable file."
3193 _dot='^\.['"${_SPACE}${_TAB}"']*';
3194 echo '.br';
3195 echo "$1: ";
3196 echo '.br';
3197 echo -n ' ';
3198 # grep the line containing `.TH' macro, if any
3199 _res="$(catz "$1" | sed -e '/'"${_dot}"'TH /p
3200 d')";
3201 if is_not_empty "${_res}"; then # traditional man style
3202 # get the text between the first and the second `.SH' macro, by
3203 # - delete up to first .SH;
3204 # - of this, print everything up to next .SH, and delete the rest;
3205 # - of this, delete the final .SH line;
3206 catz "$1" | sed -e '1,/'"${_dot}"'SH/d' \
3207 | sed -e '1,/'"${_dot}"'SH/p
3208 d' \
3209 | sed -e '/'"${_dot}"'SH/d';
3210 eval "${return_ok}";
3212 # grep the line containing `.Dd' macro, if any
3213 _res="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p
3214 d')";
3215 if is_not_empty "${_res}"; then # BSD doc style
3216 # get the text between the first and the second `.Nd' macro, by
3217 # - delete up to first .Nd;
3218 # - of this, print everything up to next .Nd, and delete the rest;
3219 # - of this, delete the final .Nd line;
3220 catz "$1" | sed -e '1,/'"${_dot}"'Nd/d' \
3221 | sed -e '1,/'"${_dot}"'Nd/p
3222 d' \
3223 | sed -e '/'"${_dot}"'Nd/d';
3224 eval "${return_ok}";
3226 echo 'is not a man page.';
3227 eval "${return_bad}";
3231 ########################################################################
3232 # where (<program>)
3234 # Output path of a program if in $PATH.
3236 # Arguments : >=1 (empty allowed)
3237 # more args are ignored, this allows to specify progs with arguments
3238 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3240 where()
3242 func_check where '>=' 1 "$@";
3243 local _file;
3244 local _arg;
3245 local p;
3246 _arg="$1";
3247 if is_empty "${_arg}"; then
3248 eval "${return_bad}";
3250 case "${_arg}" in
3252 if test -f "${_arg}" && test -x "${_arg}"; then
3253 eval "${return_ok}";
3254 else
3255 eval "${return_bad}";
3258 esac;
3259 eval set -- "$(path_split "${PATH}")";
3260 for p in "$@"; do
3261 case "$p" in
3262 */) _file=$p${_arg}; ;;
3263 *) _file=$p/${_arg}; ;;
3264 esac;
3265 if test -f "${_file}" && test -x "${_file}"; then
3266 echo -n "${_file}";
3267 eval "${return_ok}";
3269 done;
3270 eval "${return_bad}";
3274 ########################################################################
3275 # main
3276 ########################################################################
3278 # The main area contains the following parts:
3279 # - main_init(): initialize temporary files and set exit trap
3280 # - parse $MANOPT
3281 # - main_parse_args(): argument parsing
3282 # - determine display mode
3283 # - process filespec arguments
3284 # - setup X resources
3285 # - do the displaying
3287 # These parts are implemented as functions, being defined below in the
3288 # sequence they are called in the main() function.
3291 #######################################################################
3292 # main_init ()
3294 # set exit trap and create temporary files
3296 # Globals: $_TMP_CAT, $_TMP_STDIN
3298 landmark '13: main_init()';
3299 main_init()
3301 func_check main_init = 0 "$@";
3302 # call clean_up() on any signal
3303 trap_set clean_up;
3305 for f in ${_CONFFILES}; do
3306 if is_file "$f"; then
3307 . "$f";
3309 done;
3311 # determine temporary directory
3312 umask 000;
3313 _TMP_DIR='';
3314 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3315 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.';
3317 if test "$d" != ""; then
3318 if test -d "$d" && test -r "$d" && test -w "$d"; then
3319 _TMP_DIR="${d}/${_PROGRAM_NAME}${_PROCESS_ID}";
3320 if test -d "${_TMP_DIR}"; then
3321 rm -f "${_TMP_DIR}"/*;
3322 break;
3323 else
3324 mkdir "${_TMP_DIR}";
3325 if test ! -d "${_TMP_DIR}"; then
3326 _TMP_DIR='';
3327 continue;
3329 break;
3332 if test ! -w "${_TMP_DIR}"; then
3333 _TMP_DIR='';
3334 continue;
3337 done;
3338 unset d;
3339 if test "${_TMP_DIR}" = ''; then
3340 error "Couldn't create a directory for storing temporary files.";
3343 _TMP_CAT="$(tmp_create groffer_cat)";
3344 _TMP_STDIN="$(tmp_create groffer_input)";
3345 eval "${return_ok}";
3346 } # main_init()
3349 ########################################################################
3350 # main_parse_MANOPT ()
3352 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3353 # string; found man arguments can be overwritten by the command line.
3355 # Globals:
3356 # in: $MANOPT, $_OPTS_MAN_*
3357 # out: $_MANOPT_*
3358 # in/out: $GROFFER_OPT
3360 landmark '14: main_parse_MANOPT()';
3361 main_parse_MANOPT()
3363 func_check main_parse_MANOPT = 0 "$@";
3364 local _opt;
3365 local _list;
3366 _list='';
3367 if test "${MANOPT}" != ''; then
3368 MANOPT="$(echo -n "${MANOPT}" | \
3369 sed -e 's/^'"${_SPACE}${_SPACE}"'*//')";
3371 if test "${MANOPT}" = ''; then
3372 eval "${return_ok}";
3374 # add arguments in $MANOPT by mapping them to groffer options
3375 eval set -- "$(list_from_cmdline \
3376 "${_OPTS_MAN_SHORT_NA}" "${_OPTS_MAN_SHORT_ARG}" \
3377 "${_OPTS_MAN_LONG_NA}" "${_OPTS_MAN_LONG_ARG}" \
3378 "${MANOPT}")";
3379 until test "$#" -le 0 || is_equal "$1" '--'; do
3380 _opt="$1";
3381 shift;
3382 case "${_opt}" in
3383 -7|--ascii)
3384 _list="$(list_append "${_list}" '--ascii')";
3386 -a|--all)
3387 _list="$(list_append "${_list}" '--all')";
3389 -c|--catman)
3390 do_nothing;
3391 shift;
3393 -d|--debug)
3394 _list="$(list_append "${_list}" '--debug')";
3396 -D|--default)
3397 # undo all man options so far
3398 _list='';
3400 -e|--extension)
3401 _list="$(list_append "${_list}" '--extension')";
3402 shift;
3404 -f|--whatis)
3405 _list="$(list_append "${_list}" '--whatis')";
3406 shift;
3408 -h|--help)
3409 do_nothing;
3410 shift;
3412 -k|--apropos)
3413 _list="$(list_append "${_list}" '--apropos')";
3414 shift;
3416 -l|--local-file)
3417 _list="$(list_append "${_list}" '--local-file')";
3419 -L|--locale)
3420 _list="$(list_append "${_list}" '--locale' "$1")";
3421 shift;
3423 -m|--systems)
3424 _list="$(list_append "${_list}" '--systems' "$1")";
3425 shift;
3427 -M|--manpath)
3428 _list="$(list_append "${_list}" '--manpath' "$1")";
3429 shift;
3431 -p|--preprocessor)
3432 do_nothing;
3433 shift;
3435 -P|--pager)
3436 _list="$(list_append "${_list}" '--pager' "$1")";
3437 shift;
3439 -r|--prompt)
3440 do_nothing;
3441 shift;
3443 -S|--sections)
3444 _list="$(list_append "${_list}" '--sections' "$1")";
3445 shift;
3447 -t|--troff)
3448 do_nothing;
3449 shift;
3451 -T|--device)
3452 _list="$(list_append "${_list}" '-T' "$1")";
3453 shift;
3455 -u|--update)
3456 do_nothing;
3457 shift;
3459 -V|--version)
3460 do_nothing;
3462 -w|--where|--location)
3463 _list="$(list_append "${_list}" '--location')";
3465 -Z|--ditroff)
3466 _list="$(list_append "${_list}" '-Z' "$1")";
3467 shift;
3469 # ignore all other options
3470 esac;
3471 done;
3472 GROFFER_OPT="$(list_from_lists "${_list}" "${GROFFER_OPT}")";
3473 eval "${return_ok}";
3474 } # main_parse_MANOPT()
3477 ########################################################################
3478 # main_parse_args (<command_line_args>*)
3480 # Parse arguments; process options and filespec parameters
3482 # Arguments: pass the command line arguments unaltered.
3483 # Globals:
3484 # in: $_OPTS_*
3485 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3487 landmark '15: main_parse_args()';
3488 main_parse_args()
3490 func_check main_parse_args '>=' 0 "$@";
3491 local _arg;
3492 local _code;
3493 local _dpi;
3494 local _longopt;
3495 local _mode;
3496 local _opt;
3497 local _optchar;
3498 local _optarg;
3499 local _opts;
3500 local _string;
3502 eval set -- "${GROFFER_OPT}" '"$@"';
3504 eval set -- "$(list_from_cmdline \
3505 "$_OPTS_CMDLINE_SHORT_NA" "$_OPTS_CMDLINE_SHORT_ARG" \
3506 "$_OPTS_CMDLINE_LONG_NA" "$_OPTS_CMDLINE_LONG_ARG" \
3507 "$@")";
3509 # By the call of `eval', unnecessary quoting was removed. So the
3510 # positional shell parameters ($1, $2, ...) are now guaranteed to
3511 # represent an option or an argument to the previous option, if any;
3512 # then a `--' argument for separating options and
3513 # parameters; followed by the filespec parameters if any.
3515 # Note, the existence of arguments to options has already been checked.
3516 # So a check for `$#' or `--' should not be done for arguments.
3518 until test "$#" -le 0 || is_equal "$1" '--'; do
3519 _opt="$1"; # $_opt is fed into the option handler
3520 shift;
3521 case "${_opt}" in
3522 -h|--help)
3523 usage;
3524 leave;
3526 -Q|--source) # output source code (`Quellcode').
3527 _OPT_MODE='source';
3529 -T|--device|--troff-device)
3530 # device; arg
3531 _OPT_DEVICE="$1";
3532 shift;
3534 -v|--version)
3535 version;
3536 leave;
3539 _OPT_V='yes';
3542 _OPT_X='yes';
3544 -Z|--ditroff|--intermediate-output)
3545 # groff intermediate output
3546 _OPT_Z='yes';
3549 # delete leading `-'
3550 _optchar="$(echo -n "${_opt}" | sed -e 's/^.//')";
3551 if list_has "${_OPTS_GROFF_SHORT_NA}" "${_optchar}";
3552 then
3553 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \
3554 "${_opt}")";
3555 elif list_has "${_OPTS_GROFF_SHORT_ARG}" "${_optchar}";
3556 then
3557 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \
3558 "${_opt}" "$1")";
3559 shift;
3560 else
3561 error "Unknown option : \`$1'";
3564 --all)
3565 _OPT_ALL="yes";
3567 --ascii)
3568 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \
3569 '-mtty-char')";
3571 --apropos)
3572 _OPT_APROPOS="yes";
3574 --auto) # the default automatic mode
3575 _mode='';
3577 --bd) # border color for viewers, arg;
3578 _OPT_BD="$1";
3579 shift;
3581 --bg|--backgroud) # background color for viewers, arg;
3582 _OPT_BG="$1";
3583 shift;
3585 --bw) # border width for viewers, arg;
3586 _OPT_BW="$1";
3587 shift;
3589 --default) # reset variables to default
3590 reset;
3592 --default-modes) # sequence of modes in auto mode; arg
3593 _OPT_DEFAULT_MODES="$1";
3594 shift;
3596 --debug) # sequence of modes in auto mode; arg
3597 _OPT_DEBUG='yes';
3599 --display) # set X display, arg
3600 _OPT_DISPLAY="$1";
3601 shift;
3603 --dvi)
3604 _OPT_MODE='dvi';
3606 --dvi-viewer) # viewer program for dvi mode; arg
3607 _OPT_VIEWER_DVI="$1";
3608 shift;
3610 --extension) # the extension for man pages, arg
3611 _OPT_EXTENSION="$1";
3612 shift;
3614 --fg|--foreground) # foreground color for viewers, arg;
3615 _OPT_FG="$1";
3616 shift;
3618 --fn|--font) # set font for viewers, arg;
3619 _OPT_FN="$1";
3620 shift;
3622 --geometry) # window geometry for viewers, arg;
3623 _OPT_GEOMETRY="$1";
3624 shift;
3626 --groff)
3627 _OPT_MODE='groff';
3629 --locale) # set language for man pages, arg
3630 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3631 _OPT_LANG="$1";
3632 shift;
3634 --local-file) # force local files; same as `--no-man'
3635 _MAN_FORCE='no';
3636 _MAN_ENABLE='no';
3638 --location|--where) # print file locations to stderr
3639 _OPT_LOCATION='yes';
3641 --man) # force all file params to be man pages
3642 _MAN_ENABLE='yes';
3643 _MAN_FORCE='yes';
3645 --manpath) # specify search path for man pages, arg
3646 # arg is colon-separated list of directories
3647 _OPT_MANPATH="$1";
3648 shift;
3650 --mode) # display mode
3651 _arg="$1";
3652 shift;
3653 case "${_arg}" in
3654 auto|'') # the default automatic mode
3655 _mode='';
3657 groff) # pass input to plain groff
3658 _mode='groff';
3660 dvi) # display with xdvi viewer
3661 _mode='dvi';
3663 pdf) # display with PDF viewer
3664 _mode='pdf';
3666 ps) # display with Postscript viewer
3667 _mode='ps';
3669 X|x) # output on X roff viewer
3670 _mode='x';
3672 tty) # output on terminal
3673 _mode='tty';
3675 Q|source) # display source code
3676 _mode="source";
3679 error "unknown mode ${_arg}";
3681 esac;
3682 _OPT_MODE="${_mode}";
3684 --no-location) # disable former call to `--location'
3685 _OPT_LOCATION='yes';
3687 --no-man) # disable search for man pages
3688 # the same as --local-file
3689 _MAN_FORCE="no";
3690 _MAN_ENABLE="no";
3692 --pager) # set paging program for tty mode, arg
3693 _OPT_PAGER="$1";
3694 shift;
3696 --pdf)
3697 _OPT_MODE='pdf';
3699 --pdf-viewer) # viewer program for ps mode; arg
3700 _OPT_VIEWER_PDF="$1";
3701 shift;
3703 --ps)
3704 _OPT_MODE='ps';
3706 --ps-viewer) # viewer program for ps mode; arg
3707 _OPT_VIEWER_PS="$1";
3708 shift;
3710 --resolution) # set resolution for X devices, arg
3711 _arg="$1";
3712 shift;
3713 case "${_arg}" in
3714 75|75dpi)
3715 _dpi=75;
3717 100|100dpi)
3718 _dpi=100;
3721 error "only resoutions of 75 or 100 dpi are supported";
3723 esac;
3724 _OPT_RESOLUTION="${_dpi}";
3726 --rv)
3727 _OPT_RV='yes';
3729 --sections) # specify sections for man pages, arg
3730 # arg is colon-separated list of section names
3731 _OPT_SECTIONS="$1";
3732 shift;
3734 --shell)
3735 shift;
3737 --systems) # man pages for different OS's, arg
3738 # argument is a comma-separated list
3739 _OPT_SYSTEMS="$1";
3740 shift;
3742 --title) # title for X viewers; arg
3743 _OPT_TITLE="$1";
3744 shift;
3746 --tty)
3747 _OPT_MODE="tty";
3749 --tty-device) # device for tty mode; arg
3750 _OPT_TTY_DEVICE="$1";
3751 shift;
3753 --whatis)
3754 _OPT_WHATIS='yes';
3756 --www) # display with web browser
3757 _OPT_MODE='www';
3759 --www-viewer) # viewer program for www mode; arg
3760 _OPT_VIEWER_WWW="$1";
3761 shift;
3763 --x)
3764 _OPT_MODE='x';
3766 --xrm) # pass X resource string, arg;
3767 _OPT_XRM="$(list_append "${_OPT_XRM}" "$1")";
3768 shift;
3770 --x-viewer) # viewer program for x mode; arg
3771 _OPT_VIEWER_X="$1";
3772 shift;
3775 error 'error on argument parsing : '"\`$*'";
3777 esac;
3778 done;
3779 shift; # remove `--' argument
3781 if test "${_DEBUG}" != 'yes'; then
3782 if test "${_OPT_DEBUG}" = 'yes'; then
3783 _DEBUG='yes';
3787 # Remaining arguments are file names (filespecs).
3788 # Save them to list $_FILEARGS
3789 if test "$#" -eq 0; then # use "-" for standard input
3790 set -- '-';
3792 _FILEARGS="$(list_from_args "$@")";
3793 if list_has "$_FILEARGS" '-'; then
3794 save_stdin;
3796 # $_FILEARGS must be retrieved with `eval set -- "$_FILEARGS"'
3797 eval "${return_ok}";
3798 } # main_parse_args()
3801 ########################################################################
3802 # main_set_mode ()
3804 # Determine the display mode.
3806 # Globals:
3807 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
3808 # out: $_DISPLAY_MODE
3811 # _get_first_prog (<proglist>)
3813 # Retrieve first argument that represents an existing program in $PATH.
3814 # Local function for main_set_mode().
3816 # Arguments: 1; a comma-separated list of commands (with options),
3817 # like $_VIEWER_*.
3819 # Return : `1' if none found, `0' if found.
3820 # Output : the argument that succeded.
3822 landmark '16: main_set_mode()';
3823 main_set_mode()
3825 func_check main_set_mode = 0 "$@";
3826 local m;
3827 local _modes;
3828 local _viewer;
3829 local _viewers;
3831 # handle apropos
3832 if is_yes "${_OPT_APROPOS}"; then
3833 apropos "$@";
3834 _code="$?";
3835 clean_up;
3836 exit "${_code}";
3839 # set display
3840 if is_not_empty "${_OPT_DISPLAY}"; then
3841 DISPLAY="${_OPT_DISPLAY}";
3844 if is_yes "${_OPT_V}"; then
3845 _DISPLAY_MODE='groff';
3846 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-V')";
3848 if is_yes "${_OPT_X}"; then
3849 _DISPLAY_MODE='groff';
3850 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-X')";
3852 if is_yes "${_OPT_Z}"; then
3853 _DISPLAY_MODE='groff';
3854 _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-Z')";
3856 if is_equal "${_OPT_MODE}" 'groff'; then
3857 _DISPLAY_MODE='groff';
3859 if is_equal "${_DISPLAY_MODE}" 'groff'; then
3860 eval "${return_ok}";
3863 if is_equal "${_OPT_MODE}" 'source'; then
3864 _DISPLAY_MODE='source';
3865 eval "${return_ok}";
3868 case "${_OPT_MODE}" in
3869 '') # automatic mode
3870 case "${_OPT_DEVICE}" in
3872 if is_empty "${DISPLAY}"; then
3873 error "no X display found for device ${_OPT_DEVICE}";
3875 _DISPLAY_MODE='x';
3876 eval "${return_ok}";
3878 ascii|cp1047|latin1|utf8)
3879 _DISPLAY_MODE='tty';
3880 eval "${return_ok}";
3882 esac;
3883 if is_empty "${DISPLAY}"; then
3884 _DISPLAY_MODE='tty';
3885 eval "${return_ok}";
3888 if is_empty "${_OPT_DEFAULT_MODES}"; then
3889 _modes="${_DEFAULT_MODES}";
3890 else
3891 _modes="${_OPT_DEFAULT_MODES}";
3894 tty)
3895 _DISPLAY_MODE='tty';
3896 eval "${return_ok}";
3898 *) # display mode was given
3899 if is_empty "${DISPLAY}"; then
3900 error "you must be in X Window for ${_OPT_MODE} mode.";
3902 _modes="${_OPT_MODE}";
3904 esac;
3906 # only viewer modes are left
3907 eval set -- "$(list_from_split "${_modes}" ',')";
3908 while test "$#" -gt 0; do
3909 m="$1";
3910 shift;
3911 case "$m" in
3912 tty)
3913 _DISPLAY_MODE='tty';
3914 eval "${return_ok}";
3917 if is_not_empty "${_OPT_VIEWER_X}"; then
3918 _viewers="${_OPT_VIEWER_X}";
3919 else
3920 _viewers="${_VIEWER_X}";
3922 _viewer="$(_get_first_prog "${_viewers}")";
3923 if test "$?" -ne 0; then
3924 continue;
3926 _DISPLAY_PROG="${_viewer}";
3927 _DISPLAY_MODE='x';
3928 eval "${return_ok}";
3930 dvi)
3931 if is_not_empty "${_OPT_VIEWER_DVI}"; then
3932 _viewers="${_OPT_VIEWER_DVI}";
3933 else
3934 _viewers="${_VIEWER_DVI}";
3936 _viewer="$(_get_first_prog "${_viewers}")";
3937 if test "$?" -ne 0; then
3938 continue;
3940 _DISPLAY_PROG="${_viewer}";
3941 _DISPLAY_MODE="dvi";
3942 eval "${return_ok}";
3944 pdf)
3945 if is_not_empty "${_OPT_VIEWER_PDF}"; then
3946 _viewers="${_OPT_VIEWER_PDF}";
3947 else
3948 _viewers="${_VIEWER_PDF}";
3950 _viewer="$(_get_first_prog "${_viewers}")";
3951 if test "$?" -ne 0; then
3952 continue;
3954 _DISPLAY_PROG="${_viewer}";
3955 _DISPLAY_MODE="pdf";
3956 eval "${return_ok}";
3959 if is_not_empty "${_OPT_VIEWER_PS}"; then
3960 _viewers="${_OPT_VIEWER_PS}";
3961 else
3962 _viewers="${_VIEWER_PS}";
3964 _viewer="$(_get_first_prog "${_viewers}")";
3965 if test "$?" -ne 0; then
3966 continue;
3968 _DISPLAY_PROG="${_viewer}";
3969 _DISPLAY_MODE="ps";
3970 eval "${return_ok}";
3972 www)
3973 if is_not_empty "${_OPT_VIEWER_WWW}"; then
3974 _viewers="${_OPT_VIEWER_WWW}";
3975 else
3976 _viewers="${_VIEWER_WWW}";
3978 _viewer="$(_get_first_prog "${_viewers}")";
3979 if test "$?" -ne 0; then
3980 continue;
3982 _DISPLAY_PROG="${_viewer}";
3983 _DISPLAY_MODE="www";
3984 eval "${return_ok}";
3986 esac;
3987 done;
3988 error "no suitable display mode found.";
3991 _get_first_prog()
3993 local i;
3994 if test "$#" -eq 0; then
3995 error "_get_first_prog() needs 1 argument.";
3997 if is_empty "$1"; then
3998 return "${_BAD}";
4000 eval set -- "$(list_from_split "$1" ',')";
4001 for i in "$@"; do
4002 if is_empty "$i"; then
4003 continue;
4005 if is_prog "$(get_first_essential $i)"; then
4006 echo -n "$i";
4007 return "${_GOOD}";
4009 done;
4010 return "${_BAD}";
4011 } # main_set_mode()
4014 #######################################################################
4015 # main_do_fileargs ()
4017 # Process filespec arguments in $_FILEARGS.
4019 # Globals:
4020 # in: $_FILEARGS (process with `eval set -- "$_FILEARGS"')
4022 landmark '17: main_do_fileargs()';
4023 main_do_fileargs()
4025 func_check main_do_fileargs = 0 "$@";
4026 local _exitcode;
4027 local _filespec;
4028 local _name;
4029 _exitcode="${_BAD}";
4030 eval set -- "${_FILEARGS}";
4031 unset _FILEARGS;
4032 # temporary storage of all input to $_TMP_CAT
4033 while test "$#" -ge 2; do
4034 # test for `s name' arguments, with `s' a 1-char standard section
4035 _filespec="$1";
4036 shift;
4037 case "${_filespec}" in
4039 continue;
4041 '-')
4042 if register_file '-'; then
4043 _exitcode="${_GOOD}";
4045 continue;
4048 if list_has_not "${_MAN_AUTO_SEC}" "${_filespec}"; then
4049 if do_filearg "${_filespec}"; then
4050 _exitcode="${_GOOD}";
4052 continue;
4054 _name="$1";
4055 case "${_name}" in
4056 */*|man:*|*\(*\)|*."${_filespec}")
4057 if do_filearg "${_filespec}"; then
4058 _exitcode="${_GOOD}";
4060 continue;
4062 esac;
4063 if do_filearg "man:${_name}(${_filespec})"; then
4064 _exitcode="${_GOOD}";
4065 shift;
4066 continue;
4067 else
4068 if do_filearg "${_filespec}"; then
4069 _exitcode="${_GOOD}";
4071 continue;
4075 if do_filearg "${_filespec}"; then
4076 _exitcode="${_GOOD}";
4078 continue;
4080 esac;
4081 done; # end of `s name' test
4082 while test "$#" -gt 0; do
4083 _filespec="$1";
4084 shift;
4085 if do_filearg "${_filespec}"; then
4086 _exitcode="${_GOOD}";
4088 done;
4089 rm -f "${_TMP_STDIN}";
4090 if is_equal "${_exitcode}" "${_BAD}"; then
4091 eval "${return_bad}";
4093 eval "${return_ok}";
4094 } # main_do_fileargs()
4097 ########################################################################
4098 # main_set_resources ()
4100 # Determine options for setting X resources with $_DISPLAY_PROG.
4102 landmark '18: main_set_resources()';
4103 main_set_resources()
4105 func_check main_set_resources = 0 "$@";
4106 local _prog; # viewer program
4107 local _rl; # resource list
4108 _rl='';
4109 if is_empty "${_DISPLAY_PROG}"; then
4110 eval "${return_ok}";
4112 set -- ${_DISPLAY_PROG};
4113 _prog="$(base_name "$1")";
4114 if is_not_empty "${_OPT_BD}"; then
4115 case "${_prog}" in
4116 ghostview|gv|gxditview|xditview|xdvi)
4117 _rl="$(list_append "$_rl" '-bd' "${_OPT_BD}")";
4119 esac;
4121 if is_not_empty "${_OPT_BG}"; then
4122 case "${_prog}" in
4123 ghostview|gv|gxditview|xditview|xdvi)
4124 _rl="$(list_append "$_rl" '-bg' "${_OPT_BG}")";
4126 xpdf)
4127 _rl="$(list_append "$_rl" '-papercolor' "${_OPT_BG}")";
4129 esac;
4131 if is_not_empty "${_OPT_BW}"; then
4132 case "${_prog}" in
4133 ghostview|gv|gxditview|xditview|xdvi)
4134 _rl="$(list_append "$_rl" '-bw' "${_OPT_BW}")";
4136 esac;
4138 if is_not_empty "${_OPT_FG}"; then
4139 case "${_prog}" in
4140 ghostview|gv|gxditview|xditview|xdvi)
4141 _rl="$(list_append "$_rl" '-fg' "${_OPT_FG}")";
4143 esac;
4145 if is_not_empty "${_OPT_FN}"; then
4146 case "${_prog}" in
4147 ghostview|gv|gxditview|xditview|xdvi)
4148 _rl="$(list_append "$_rl" '-fn' "${_OPT_FN}")";
4150 esac;
4152 if is_not_empty "${_OPT_GEOMETRY}"; then
4153 case "${_prog}" in
4154 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4155 _rl="$(list_append "$_rl" '-geometry' "${_OPT_GEOMETRY}")";
4157 esac;
4159 if is_empty "${_OPT_RESOLUTION}"; then
4160 case "${_prog}" in
4161 gxditview|xditview)
4162 _rl="$(list_append "$_rl" \
4163 '-resolution' "${_DEFAULT_RESOLUTION}")";
4165 xpdf)
4166 case "${_DEFAULT_RESOLUTION}" in
4168 _rl="$(list_append "$_rl" '-z' '2')";
4170 100)
4171 _rl="$(list_append "$_rl" '-z' '3')";
4173 esac;
4175 esac;
4176 else
4177 case "${_prog}" in
4178 ghostview|gv|gxditview|xditview|xdvi)
4179 _rl="$(list_append "$_rl" '-resolution' "${_OPT_RESOLUTION}")";
4181 xpdf)
4182 case "${_OPT_RESOLUTION}" in
4184 _rl="$(list_append "$_rl" '-z' '2')";
4186 100)
4187 _rl="$(list_append "$_rl" '-z' '3')";
4189 esac;
4191 esac;
4193 if is_not_empty "${_OPT_RV}"; then
4194 case "${_prog}" in
4195 ghostview|gv|gxditview|xditview|xdvi)
4196 _rl="$(list_append "$_rl" '-rv')";
4198 esac;
4200 if is_not_empty "${_OPT_XRM}"; then
4201 case "${_prog}" in
4202 ghostview|gv|gxditview|xditview|xdvi|xpdf)
4203 eval set -- "{$_OPT_XRM}";
4204 for i in "$@"; do
4205 _rl="$(list_append "$_rl" '-xrm' "$i")";
4206 done;
4208 esac;
4210 _title="$(get_first_essential \
4211 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4212 if is_not_empty "${_title}"; then
4213 case "${_prog}" in
4214 gxditview|xditview)
4215 _rl="$(list_append "$_rl" '-title' "${_title}")";
4217 esac;
4219 _DISPLAY_ARGS="${_rl}";
4220 eval "${return_ok}";
4221 } # main_set_resources
4224 ########################################################################
4225 # main_display ()
4227 # Do the actual display of the whole thing.
4229 # Globals:
4230 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4231 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4232 # $_REGISTERED_TITLE, $_TMP_CAT,
4233 # $_OPT_PAGER $PAGER $_MANOPT_PAGER
4235 landmark '19: main_display()';
4236 main_display()
4238 func_check main_display = 0 "$@";
4239 local p;
4240 local _addopts;
4241 local _device;
4242 local _groggy;
4243 local _modefile;
4244 local _options;
4245 local _pager;
4246 local _title;
4247 export _addopts;
4248 export _groggy;
4249 export _modefile;
4251 # Some display programs have trouble with empty input.
4252 # This is avoided by feeding a space character in this case.
4253 # Test on non-empty file by tracking a line with at least 1 character.
4254 if is_empty "$(tmp_cat | sed -e '/./q')"; then
4255 echo ' ' > "${_TMP_CAT}";
4258 case "${_DISPLAY_MODE}" in
4259 groff)
4260 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4261 if is_not_empty "${_OPT_DEVICE}"; then
4262 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4264 _groggy="$(tmp_cat | eval grog "${_options}")";
4265 trap_clean;
4266 # start a new shell program to get another process ID.
4267 sh -c '
4268 set -e;
4269 _PROCESS_ID="$$";
4270 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4271 rm -f "${_modefile}";
4272 mv "${_TMP_CAT}" "${_modefile}";
4273 rm -f "${_TMP_CAT}";
4274 cat "${_modefile}" | \
4276 clean_up()
4278 rm -f "${_modefile}";
4280 trap clean_up 0 2>/dev/null || true;
4281 eval "${_groggy}" "${_ADDOPTS_GROFF}";
4282 ) &'
4284 tty)
4285 case "${_OPT_DEVICE}" in
4287 _device="$(get_first_essential \
4288 "${_OPT_TTY_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4290 ascii|cp1047|latin1|utf8)
4291 _device="${_OPT_DEVICE}";
4294 warning \
4295 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4297 esac;
4298 _addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4299 _groggy="$(tmp_cat | grog -T${_device})";
4300 _pager='';
4301 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4302 'less' 'more' 'cat'; do
4303 if is_prog "$p"; then
4304 _pager="$p";
4305 break;
4307 done;
4308 if is_empty "${_pager}"; then
4309 error 'no pager program found for tty mode';
4311 tmp_cat | eval "${_groggy}" "${_addopts}" | \
4312 eval "${_pager}";
4313 clean_up;
4316 #### viewer modes
4318 dvi)
4319 case "${_OPT_DEVICE}" in
4320 ''|dvi) do_nothing; ;;
4322 warning \
4323 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4325 esac;
4326 _groggy="$(tmp_cat | grog -Tdvi)";
4327 _do_display;
4329 pdf)
4330 case "${_OPT_DEVICE}" in
4331 ''|ps)
4332 do_nothing;
4335 warning \
4336 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4338 esac;
4339 _groggy="$(tmp_cat | grog -Tps)";
4340 trap_clean;
4341 # start a new shell program to get another process ID.
4342 sh -c '
4343 set -e;
4344 _PROCESS_ID="$$";
4345 _psfile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4346 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}.pdf";
4347 rm -f "${_psfile}";
4348 rm -f "${_modefile}";
4349 cat "${_TMP_CAT}" | \
4350 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4351 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4352 -sOutputFile="${_modefile}" -c save pop -f "${_psfile}";
4353 rm -f "${_psfile}";
4354 rm -f "${_TMP_CAT}";
4356 clean_up()
4358 rm -f "${_modefile}";
4360 trap clean_up 0 2>/dev/null || true;
4361 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4362 ) &'
4365 case "${_OPT_DEVICE}" in
4366 ''|ps)
4367 do_nothing;
4370 warning \
4371 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4373 esac;
4374 _groggy="$(tmp_cat | grog -Tps)";
4375 _do_display;
4377 source)
4378 tmp_cat;
4379 clean_up;
4381 www)
4382 case "${_OPT_DEVICE}" in
4383 ''|html) do_nothing; ;;
4385 warning \
4386 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4388 esac;
4389 _groggy="$(tmp_cat | grog -Thtml)";
4390 _do_display;
4393 case "${_OPT_DEVICE}" in
4395 _groggy="$(tmp_cat | grog -Z)";
4397 X*|ps)
4398 _groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -Z)";
4401 warning \
4402 "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4403 _groggy="$(tmp_cat | grog -Z)";
4405 esac;
4406 _do_display;
4409 error "unknown mode \`${_DISPLAY_MODE}'";
4411 esac;
4412 eval "${return_ok}";
4413 } # main_display()
4415 _do_display()
4417 trap_clean;
4418 # start a new shell program for another process ID and better
4419 # cleaning-up of the temporary files.
4420 sh -c '
4421 set -e;
4422 _PROCESS_ID="$$";
4423 _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}";
4424 rm -f "${_modefile}";
4425 cat "${_TMP_CAT}" | \
4426 eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}";
4427 rm -f "${_TMP_CAT}";
4429 clean_up()
4431 if test -d "${_TMP_DIR}"; then
4432 rm -f "${_TMP_DIR}"/*;
4433 rmdir "${_TMP_DIR}";
4436 trap clean_up 0 2>/dev/null || true;
4437 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}";
4438 ) &'
4442 ########################################################################
4443 # main (<command_line_args>*)
4445 # The main function for groffer.
4447 # Arguments:
4449 main()
4451 func_check main '>=' 0 "$@";
4452 # Do not change the sequence of the following functions!
4453 main_init;
4454 main_parse_MANOPT;
4455 main_parse_args "$@";
4456 main_set_mode;
4457 main_do_fileargs;
4458 main_set_resources;
4459 main_display;
4460 eval "${return_ok}";
4463 landmark '20: end of function definitions';
4465 ########################################################################
4467 main "$@";