Update to groff 1.19.2.
[dragonfly.git] / contrib / groff-1.19 / contrib / groffer / groffer2.sh
blob60ca91130f6f22cf117eb04214b7b0a70eb0714f
1 #! /bin/sh
3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer2.sh
6 # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
8 # This file should not be run independently. It is called by
9 # `groffer.sh' in the source or by the installed `groffer' program.
11 # Copyright (C) 2001,2002,2003,2004,2005
12 # Free Software Foundation, Inc.
13 # Written by Bernd Warken
15 # Last update: 22 August 2005
17 # This file is part of `groffer', which is part of `groff'.
19 # `groff' is free software; you can redistribute it and/or modify it
20 # under the terms of the GNU General Public License as published by
21 # the Free Software Foundation; either version 2, or (at your option)
22 # any later version.
24 # `groff' is distributed in the hope that it will be useful, but
25 # WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 # General Public License for more details.
29 # You should have received a copy of the GNU General Public License
30 # along with `groff'; see the files COPYING and LICENSE in the top
31 # directory of the `groff' source. If not, write to the Free Software
32 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
33 # USA.
36 ########################################################################
37 # Test of rudimentary shell functionality
38 ########################################################################
41 ########################################################################
42 # Test of `unset'
44 export _UNSET;
45 export _foo;
46 _foo=bar;
47 _res="$(unset _foo 2>&1)";
48 if unset _foo >${_NULL_DEV} 2>&1 && \
49 test _"${_res}"_ = __ && test _"${_foo}"_ = __
50 then
51 _UNSET='unset';
52 eval "${_UNSET}" _foo;
53 eval "${_UNSET}" _res;
54 else
55 _UNSET=':';
56 fi;
59 ########################################################################
60 # Test of `test'.
62 if test a = a && test a != b && test -f "${_GROFFER_SH}"
63 then
65 else
66 echo '"test" did not work.' >&2;
67 exit "${_ERROR}";
68 fi;
71 ########################################################################
72 # Test of `echo' and the `$()' construct.
74 if echo '' >${_NULL_DEV}
75 then
77 else
78 echo '"echo" did not work.' >&2;
79 exit "${_ERROR}";
80 fi;
81 if test _"$(t1="$(echo te)" &&
82 t2="$(echo '')" &&
83 t3="$(echo 'st')" &&
84 echo "${t1}${t2}${t3}")"_ \
85 != _test_
86 then
87 echo 'The "$()" construct did not work' >&2;
88 exit "${_ERROR}";
89 fi;
92 ########################################################################
93 # Test of sed program; test in groffer.sh is not valid here.
95 if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_
96 then
97 echo 'The sed program did not work.' >&2;
98 exit "${_ERROR}";
99 fi;
102 ########################################################################
103 # Test of function definitions.
105 _t_e_s_t_f_u_n_c_()
107 return 0;
110 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV}
111 then
113 else
114 echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
115 exit "${_ERROR}";
119 ########################################################################
120 # debug - diagnostic messages
121 ########################################################################
123 export _DEBUG_STACKS;
124 _DEBUG_STACKS='no'; # disable stack output in each function
125 #_DEBUG_STACKS='yes'; # enable stack output in each function
127 export _DEBUG_LM;
128 _DEBUG_LM='no'; # disable landmark messages
129 #_DEBUG_LM='yes'; # enable landmark messages
131 export _DEBUG_KEEP_FILES;
132 _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
133 #_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
135 export _DEBUG_PRINT_PARAMS;
136 _DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters
137 #_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters
139 export _DEBUG_PRINT_SHELL;
140 _DEBUG_PRINT_SHELL='no'; # disable printing of the shell name
141 #_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name
143 export _DEBUG_PRINT_TMPDIR;
144 _DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir
145 #_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir
147 export _DEBUG_USER_WITH_STACK;
148 _DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user()
149 #_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user()
151 # determine all --debug* options
152 case " $*" in
153 *\ --debug*)
154 case " $* " in
155 *' --debug '*)
156 # _DEBUG_STACKS='yes';
157 # _DEBUG_LM='yes';
158 _DEBUG_KEEP_FILES='yes';
159 _DEBUG_PRINT_PARAMS='yes';
160 _DEBUG_PRINT_SHELL='yes';
161 _DEBUG_PRINT_TMPDIR='yes';
162 _DEBUG_USER_WITH_STACK='yes';
164 esac;
165 d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\
166 '--debug-stacks --debug-tmpdir --debug-user ';
167 for i
169 case "$i" in
170 --debug-s)
171 echo 'The abbreviation --debug-s has multiple options: '\
172 '--debug-shell and --debug-stacks.' >&2
173 exit "${_ERROR}";
175 esac;
176 case "$d" in
177 *\ ${i}*)
178 # extract whole word of abbreviation $i
179 s="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p'
183 case "$s" in
184 '') continue; ;;
185 --debug-all)
186 _DEBUG_STACKS='yes';
187 _DEBUG_LM='yes';
188 _DEBUG_KEEP_FILES='yes';
189 _DEBUG_PRINT_PARAMS='yes';
190 _DEBUG_PRINT_SHELL='yes';
191 _DEBUG_PRINT_TMPDIR='yes';
192 _DEBUG_USER_WITH_STACK='yes';
194 --debug-keep)
195 _DEBUG_PRINT_TMPDIR='yes';
196 _DEBUG_KEEP_FILES='yes';
198 --debug-lm)
199 _DEBUG_LM='yes';
201 --debug-params)
202 _DEBUG_PRINT_PARAMS='yes';
204 --debug-shell)
205 _DEBUG_PRINT_SHELL='yes';
207 --debug-stacks)
208 _DEBUG_STACKS='yes';
210 --debug-tmpdir)
211 _DEBUG_PRINT_TMPDIR='yes';
213 --debug-user)
214 _DEBUG_USER_WITH_STACK='yes';
216 esac;
218 esac;
219 done
221 esac;
223 if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
224 then
225 echo "parameters: $@" >&2;
228 if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
229 then
230 if test _"${_SHELL}"_ = __
231 then
232 if test _"${POSIXLY_CORRECT}"_ = _y_
233 then
234 echo 'shell: bash as /bin/sh (none specified)' >&2;
235 else
236 echo 'shell: /bin/sh (none specified)' >&2;
238 else
239 echo "shell: ${_SHELL}" >&2;
244 ########################################################################
245 # Environment Variables
246 ########################################################################
248 # Environment variables that exist only for this file start with an
249 # underscore letter. Global variables to this file are written in
250 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
251 # start with an underline and use only lower case letters and
252 # underlines, e.g. $_local_variable .
254 # [A-Z]* system variables, e.g. $MANPATH
255 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
256 # _[a-z_]* temporary variables, e.g. $_manpath
258 # Due to incompatibilities of the `ash' shell, the name of loop
259 # variables in `for' must be single character
260 # [a-z] local loop variables, e.g. $i
263 ########################################################################
264 # read-only variables (global to this file)
265 ########################################################################
267 # function return values; `0' means ok; other values are error codes
268 export _ALL_EXIT;
269 export _BAD;
270 export _GOOD;
271 export _NO;
272 export _OK;
273 export _YES;
275 _GOOD='0'; # return ok
276 _BAD='1'; # return negatively, error code `1'
277 # $_ERROR was already defined as `7' in groffer.sh.
279 _NO="${_BAD}";
280 _YES="${_GOOD}";
281 _OK="${_GOOD}";
283 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
284 export return_ok;
285 export return_good;
286 export return_bad;
287 export return_yes;
288 export return_no;
289 export return_error;
290 export return_var;
291 return_ok="func_pop; return ${_OK}";
292 return_good="func_pop; return ${_GOOD}";
293 return_bad="func_pop; return ${_BAD}";
294 return_yes="func_pop; return ${_YES}";
295 return_no="func_pop; return ${_NO}";
296 return_error="func_pop; return ${_ERROR}";
297 return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
300 export _DEFAULT_MODES;
301 _DEFAULT_MODES='x,ps,tty';
302 export _DEFAULT_RESOLUTION;
303 _DEFAULT_RESOLUTION='75';
305 export _DEFAULT_TTY_DEVICE;
306 _DEFAULT_TTY_DEVICE='latin1';
308 # _VIEWER_* viewer programs for different modes (only X is necessary)
309 # _VIEWER_* a comma-separated list of viewer programs (with options)
310 export _VIEWER_DVI; # viewer program for dvi mode
311 export _VIEWER_HTML_TTY; # viewer program for html mode in tty
312 export _VIEWER_HTML_X; # viewer program for html mode in X
313 export _VIEWER_PDF; # viewer program for pdf mode
314 export _VIEWER_PS; # viewer program for ps mode
315 export _VIEWER_X; # viewer program for X mode
316 _VIEWER_DVI='kdvi,xdvi,dvilx';
317 _VIEWER_HTML_TTY='lynx';
318 _VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena';
319 _VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
320 _VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
321 _VIEWER_X='gxditview,xditview';
323 # Search automatically in standard sections `1' to `8', and in the
324 # traditional sections `9', `n', and `o'. On many systems, there
325 # exist even more sections, mostly containing a set of man pages
326 # special to a specific program package. These aren't searched for
327 # automatically, but must be specified on the command line.
328 export _MAN_AUTO_SEC_LIST;
329 _MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
330 export _MAN_AUTO_SEC_CHARS;
331 _MAN_AUTO_SEC_CHARS='[123456789no]';
333 export _SPACE_SED;
334 _SPACE_SED='['"${_SP}${_TAB}"']';
336 export _SPACE_CASE;
337 _SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']';
339 export _PROCESS_ID; # for shutting down the program
340 _PROCESS_ID="$$";
343 ############ the command line options of the involved programs
345 # The naming scheme for the options environment names is
346 # $_OPTS_<prog>_<length>[_<argspec>]
348 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
349 # command line options)
350 # <length>: LONG (long options) or SHORT (single character options)
351 # <argspec>: ARG for options with argument, NA for no argument;
352 # without _<argspec> both the ones with and without arg.
354 # Each option that takes an argument must be specified with a
355 # trailing : (colon).
357 # exports
358 export _OPTS_GROFFER_SHORT_NA;
359 export _OPTS_GROFFER_SHORT_ARG;
360 export _OPTS_GROFFER_LONG_NA;
361 export _OPTS_GROFFER_LONG_ARG;
362 export _OPTS_GROFF_SHORT_NA;
363 export _OPTS_GROFF_SHORT_ARG;
364 export _OPTS_GROFF_LONG_NA;
365 export _OPTS_GROFF_LONG_ARG;
366 export _OPTS_X_SHORT_ARG;
367 export _OPTS_X_SHORT_NA;
368 export _OPTS_X_LONG_ARG;
369 export _OPTS_X_LONG_NA;
370 export _OPTS_MAN_SHORT_ARG;
371 export _OPTS_MAN_SHORT_NA;
372 export _OPTS_MAN_LONG_ARG;
373 export _OPTS_MAN_LONG_NA;
374 export _OPTS_MANOPT_SHORT_ARG;
375 export _OPTS_MANOPT_SHORT_NA;
376 export _OPTS_MANOPT_LONG_ARG;
377 export _OPTS_MANOPT_LONG_NA;
378 export _OPTS_CMDLINE_SHORT_NA;
379 export _OPTS_CMDLINE_SHORT_ARG;
380 export _OPTS_CMDLINE_LONG_NA;
381 export _OPTS_CMDLINE_LONG_ARG;
383 ###### groffer native options
385 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
386 _OPTS_GROFFER_SHORT_ARG="'T'";
388 _OPTS_GROFFER_LONG_NA="'auto' \
389 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
390 'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \
391 'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \
392 'groff' 'help' 'intermediate-output' 'html' 'man' \
393 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
394 'text' 'text-device' \
395 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
397 _OPTS_GROFFER_LONG_ARG="\
398 'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
399 'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
400 'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
401 'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
402 'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
404 ##### groffer options inhereted from groff
406 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
407 'R' 's' 'S' 't' 'U' 'z'";
408 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
409 'w' 'W'";
410 _OPTS_GROFF_LONG_NA="";
411 _OPTS_GROFF_LONG_ARG="";
413 ##### groffer options inhereted from the X Window toolkit
415 _OPTS_X_SHORT_NA="";
416 _OPTS_X_SHORT_ARG="";
418 _OPTS_X_LONG_NA="'iconic' 'rv'";
420 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
421 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
422 'resolution' 'title' 'xrm'";
424 ###### groffer options inherited from man
426 _OPTS_MAN_SHORT_NA="";
427 _OPTS_MAN_SHORT_ARG="";
429 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
430 'local-file' 'location' 'troff' 'update'";
432 _OPTS_MAN_LONG_ARG="'locale' 'manpath' \
433 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
435 ###### additional options for parsing $MANOPT only
437 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
438 'V' 'w' 'Z'";
439 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
441 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
442 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
443 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
445 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
446 'config_file' 'encoding' 'extension' 'locale'";
448 ###### collections of command line options
450 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
451 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
452 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
453 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
455 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
456 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
457 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
458 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
461 ########################################################################
462 # read-write variables (global to this file)
463 ########################################################################
465 export _ALL_PARAMS; # All options and file name parameters
466 export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
467 export _ADDOPTS_POST; # Transp. options postproc (`eval').
468 export _ADDOPTS_X; # Transp. options X postproc (`eval').
469 export _APROPOS_PROG; # Program to run apropos.
470 export _APROPOS_SECTIONS; # Sections for different --apropos-*.
471 export _DEFAULT_MODES; # Set default modes.
472 export _DISPLAY_MODE; # Display mode.
473 export _DISPLAY_PROG; # Viewer program to be used for display.
474 export _DISPLAY_ARGS; # X resources for the viewer program.
475 export _FILEARGS; # Stores filespec parameters.
476 export _FILESPEC_ARG; # Stores the actual filespec parameter.
477 export _FUNC_STACK; # Store debugging information.
478 export _REGISTERED_TITLE; # Processed file names.
479 # _HAS_* from availability tests
480 export _HAS_COMPRESSION; # `yes' if gzip compression is available
481 export _HAS_BZIP; # `yes' if bzip2 compression is available
482 # _MAN_* finally used configuration of man searching
483 export _MAN_ALL; # search all man pages per filespec
484 export _MAN_ENABLE; # enable search for man pages
485 export _MAN_EXT; # extension for man pages
486 export _MAN_FORCE; # force file parameter to be man pages
487 export _MAN_IS_SETUP; # setup man variables only once
488 export _MAN_LANG; # language for man pages
489 export _MAN_LANG2; # language for man pages
490 export _MAN_LANG_DONE; # language dirs added to man path
491 export _MAN_PATH; # search path for man pages
492 export _MAN_SEC; # sections for man pages; sep. `:'
493 export _MAN_SEC_DONE; # sections added to man path
494 export _MAN_SYS; # system names for man pages; sep. `,'
495 export _MAN_SYS; # system names added to man path
496 # _MANOPT_* as parsed from $MANOPT
497 export _MANOPT_ALL; # $MANOPT --all
498 export _MANOPT_EXTENSION; # $MANOPT --extension
499 export _MANOPT_LANG; # $MANOPT --locale
500 export _MANOPT_PATH; # $MANOPT --manpath
501 export _MANOPT_PAGER; # $MANOPT --pager
502 export _MANOPT_SEC; # $MANOPT --sections
503 export _MANOPT_SYS; # $MANOPT --systems
504 # _OPT_* as parsed from groffer command line
505 export _OPT_ALL; # display all suitable man pages.
506 export _OPT_APROPOS; # call `apropos' program.
507 export _OPT_BD; # set border color in some modes.
508 export _OPT_BG; # set background color in some modes.
509 export _OPT_BW; # set border width in some modes.
510 export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
511 export _OPT_DEVICE; # device option.
512 export _OPT_DO_NOTHING; # do nothing in main_display().
513 export _OPT_DISPLAY; # set X display.
514 export _OPT_FG; # set foreground color in some modes.
515 export _OPT_FN; # set font in some modes.
516 export _OPT_GEOMETRY; # set size and position of viewer in X.
517 export _OPT_ICONIC; # -iconic option for X viewers.
518 export _OPT_LANG; # set language for man pages
519 export _OPT_LOCATION; # print processed file names to stderr
520 export _OPT_MODE; # values: X, tty, Q, Z, ""
521 export _OPT_MANPATH; # manual setting of path for man-pages
522 export _OPT_PAGER; # specify paging program for tty mode
523 export _OPT_RESOLUTION; # set X resolution in dpi
524 export _OPT_RV; # reverse fore- and background colors.
525 export _OPT_SECTIONS; # sections for man page search
526 export _OPT_SYSTEMS; # man pages of different OS's
527 export _OPT_TITLE; # title for gxditview window
528 export _OPT_TEXT_DEVICE; # set device for tty mode.
529 export _OPT_V; # groff option -V.
530 export _OPT_VIEWER_DVI; # viewer program for dvi mode
531 export _OPT_VIEWER_PDF; # viewer program for pdf mode
532 export _OPT_VIEWER_PS; # viewer program for ps mode
533 export _OPT_VIEWER_HTML; # viewer program for html mode
534 export _OPT_VIEWER_X; # viewer program for x mode
535 export _OPT_WHATIS; # print the man description
536 export _OPT_XRM; # specify X resource.
537 export _OPT_Z; # groff option -Z.
538 export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
539 export _VIEWER_TERMINAL; # viewer options for terminal (--*-viewer-tty)
540 # _TMP_* temporary directory and files
541 export _TMP_DIR; # groffer directory for temporary files
542 export _TMP_CAT; # stores concatenation of everything
543 export _TMP_STDIN; # stores stdin, if any
545 # these variables are preset in section `Preset' after the rudim. test
548 ########################################################################
549 # Preset and reset of read-write global variables
550 ########################################################################
553 export _START_DIR; # directory at start time of the script
554 _START_DIR="$(pwd)";
556 # For variables that can be reset by option `--default', see reset().
558 _FILEARGS='';
560 # _HAS_* from availability tests
561 _HAS_COMPRESSION='';
562 _HAS_BZIP='';
564 # _TMP_* temporary files
565 _TMP_DIR='';
566 _TMP_CAT='';
567 _TMP_CONF='';
568 _TMP_STDIN='';
571 ########################################################################
572 # reset ()
574 # Reset the variables that can be affected by options to their default.
576 reset()
578 if test "$#" -ne 0
579 then
580 error "reset() does not have arguments.";
583 _ADDOPTS_GROFF='';
584 _ADDOPTS_POST='';
585 _ADDOPTS_X='';
586 _APROPOS_PROG='';
587 _APROPOS_SECTIONS='';
588 _DISPLAY_ARGS='';
589 _DISPLAY_MODE='';
590 _DISPLAY_PROG='';
591 _REGISTERED_TITLE='';
593 # _MAN_* finally used configuration of man searching
594 _MAN_ALL='no';
595 _MAN_ENABLE='yes'; # do search for man-pages
596 _MAN_EXT='';
597 _MAN_FORCE='no'; # first local file, then search man page
598 _MAN_IS_SETUP='no';
599 _MAN_LANG='';
600 _MAN_LANG2='';
601 _MAN_PATH='';
602 _MAN_SEC='';
603 _MAN_SEC_DONE='no';
604 _MAN_SYS='';
605 _MAN_SYS_DONE='no';
607 # _MANOPT_* as parsed from $MANOPT
608 _MANOPT_ALL='no';
609 _MANOPT_EXTENSION='';
610 _MANOPT_LANG='';
611 _MANOPT_PATH='';
612 _MANOPT_PAGER='';
613 _MANOPT_SEC='';
614 _MANOPT_SYS='';
616 # _OPT_* as parsed from groffer command line
617 _OPT_ALL='no';
618 _OPT_APROPOS='no';
619 _OPT_BD='';
620 _OPT_BG='';
621 _OPT_BW='';
622 _OPT_DEFAULT_MODES='';
623 _OPT_DEVICE='';
624 _OPT_DISPLAY='';
625 _OPT_DO_NOTHING='no';
626 _OPT_FG='';
627 _OPT_FN='';
628 _OPT_GEOMETRY='';
629 _OPT_ICONIC='no';
630 _OPT_LANG='';
631 _OPT_LOCATION='no';
632 _OPT_MODE='';
633 _OPT_MANPATH='';
634 _OPT_PAGER='';
635 _OPT_RESOLUTION='';
636 _OPT_RV='no';
637 _OPT_SECTIONS='';
638 _OPT_SYSTEMS='';
639 _OPT_TITLE='';
640 _OPT_TEXT_DEVICE='';
641 _OPT_V='no';
642 _OPT_VIEWER_DVI='';
643 _OPT_VIEWER_PDF='';
644 _OPT_VIEWER_PS='';
645 _OPT_VIEWER_HTML='';
646 _OPT_VIEWER_X='';
647 _OPT_WHATIS='no';
648 _OPT_XRM='';
649 _OPT_Z='no';
650 _VIEWER_TERMINAL='no';
653 reset;
656 ########################################################################
657 # Functions for error handling and debugging
658 ########################################################################
661 ##############
662 # echo1 (<text>*)
664 # Output to stdout.
666 # Arguments : arbitrary text including `-'.
668 echo1()
670 cat <<EOF
676 ##############
677 # echo2 (<text>*)
679 # Output to stderr.
681 # Arguments : arbitrary text.
683 echo2()
685 cat >&2 <<EOF
691 ##############
692 # landmark (<text>)
694 # Print <text> to standard error as a debugging aid.
696 # Globals: $_DEBUG_LM
698 landmark()
700 if test _"${_DEBUG_LM}"_ = _yes_
701 then
702 echo2 "LM: $*";
706 landmark "1: debugging functions";
709 ##############
710 # clean_up ()
712 # Clean up at exit.
714 clean_up()
716 cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
717 if test _${_DEBUG_KEEP_FILES}_ = _yes_
718 then
719 echo2 "Kept temporary directory ${_TMP_DIR}."
720 else
721 if test _"${_TMP_DIR}"_ != __
722 then
723 if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}"
724 then
725 rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
726 fi;
732 #############
733 # diag (text>*)
735 # Output a diagnostic message to stderr
737 diag()
739 echo2 '>>>>>'"$*";
743 #############
744 # error (<text>*)
746 # Print an error message to standard error, print the function stack,
747 # exit with an error condition. The argument should contain the name
748 # of the function from which it was called. This is for system errors.
750 error()
752 case "$#" in
753 1) echo2 'groffer error: '"$1"; ;;
754 *) echo2 'groffer error: wrong number of arguments in error().'; ;;
755 esac;
756 func_stack_dump;
757 if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
758 then
759 : >"${_TMP_DIR}"/,error;
761 exit "${_ERROR}";
765 #############
766 # error_user (<text>*)
768 # Print an error message to standard error; exit with an error condition.
769 # The error is supposed to be produce by the user. So the funtion stack
770 # is omitted.
772 error_user()
774 case "$#" in
776 echo2 'groffer error: '"$1";
779 echo2 'groffer error: wrong number of arguments in error_user().';
781 esac;
782 if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
783 then
784 func_stack_dump;
786 if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
787 then
788 : >"${_TMP_DIR}"/,error;
790 exit "${_ERROR}";
794 #############
795 # exit_test ()
797 # Test whether the former command ended with error(). Exit again.
799 # Globals: $_ERROR
801 exit_test()
803 if test "$?" = "${_ERROR}"
804 then
805 exit ${_ERROR};
807 if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error
808 then
809 exit ${_ERROR};
814 #############
815 # func_check (<func_name> <rel_op> <nr_args> "$@")
817 # Check number of arguments and register to _FUNC_STACK.
819 # Arguments: >=3
820 # <func_name>: name of the calling function.
821 # <rel_op>: a relational operator: = != < > <= >=
822 # <nr_args>: number of arguments to be checked against <operator>
823 # "$@": the arguments of the calling function.
825 # Variable prefix: fc
827 func_check()
829 if test "$#" -lt 3
830 then
831 error 'func_check() needs at least 3 arguments.';
833 fc_fname="$1";
834 case "$3" in
836 fc_nargs="$3";
837 fc_s='';
839 0|[2-9])
840 fc_nargs="$3";
841 fc_s='s';
844 error "func_check(): third argument must be a digit.";
846 esac;
847 case "$2" in
848 '='|'-eq')
849 fc_op='-eq';
850 fc_comp='exactly';
852 '>='|'-ge')
853 fc_op='-ge';
854 fc_comp='at least';
856 '<='|'-le')
857 fc_op='-le';
858 fc_comp='at most';
860 '<'|'-lt')
861 fc_op='-lt';
862 fc_comp='less than';
864 '>'|'-gt')
865 fc_op='-gt';
866 fc_comp='more than';
868 '!='|'-ne')
869 fc_op='-ne';
870 fc_comp='not';
873 error \
874 'func_check(): second argument is not a relational operator.';
876 esac;
877 shift;
878 shift;
879 shift;
880 if test "$#" "${fc_op}" "${fc_nargs}"
881 then
882 do_nothing;
883 else
884 error "func_check(): \
885 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
887 func_push "${fc_fname}";
888 if test _"${_DEBUG_STACKS}"_ = _yes_
889 then
890 echo2 '+++ '"${fc_fname} $@";
891 echo2 '>>> '"${_FUNC_STACK}";
893 eval ${_UNSET} fc_comp;
894 eval ${_UNSET} fc_fname;
895 eval ${_UNSET} fc_nargs;
896 eval ${_UNSET} fc_op;
897 eval ${_UNSET} fc_s;
901 #############
902 # func_pop ()
904 # Retrieve the top element from the stack.
906 # The stack elements are separated by `!'; the popped element is
907 # identical to the original element, except that all `!' characters
908 # were removed.
910 # Arguments: 1
912 func_pop()
914 if test "$#" -ne 0
915 then
916 error 'func_pop() does not have arguments.';
918 case "${_FUNC_STACK}" in
920 if test _"${_DEBUG_STACKS}"_ = _yes_
921 then
922 error 'func_pop(): stack is empty.';
925 *!*)
926 # split at first bang `!'.
927 _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
928 exit_test;
931 _FUNC_STACK='';
933 esac;
934 if test _"${_DEBUG_STACKS}"_ = _yes_
935 then
936 echo2 '<<< '"${_FUNC_STACK}";
941 #############
942 # func_push (<element>)
944 # Store another element to stack.
946 # The stack elements are separated by `!'; if <element> contains a `!'
947 # it is removed first.
949 # Arguments: 1
951 # Variable prefix: fp
953 func_push()
955 if test "$#" -ne 1
956 then
957 error 'func_push() needs 1 argument.';
959 case "$1" in
960 *'!'*)
961 # remove all bangs `!'.
962 fp_element="$(echo1 "$1" | sed -e 's/!//g')";
963 exit_test;
966 fp_element="$1";
968 esac;
969 if test _"${_FUNC_STACK}"_ = __
970 then
971 _FUNC_STACK="${fp_element}";
972 else
973 _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
975 eval ${_UNSET} fp_element;
979 #############
980 # func_stack_dump ()
982 # Print the content of the stack. Ignore the arguments.
984 func_stack_dump()
986 diag 'call stack: '"${_FUNC_STACK}";
990 ########################################################################
991 # System Test
992 ########################################################################
994 landmark "2: system test";
996 # Test the availability of the system utilities used in this script.
999 ########################################################################
1000 # Test of function `sed'.
1003 if test _"$(echo xTesTx \
1004 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1005 | sed -e 's|T|t|g')"_ != _test_
1006 then
1007 error 'Test of "sed" command failed.';
1011 ########################################################################
1012 # Test of function `cat'.
1014 if test _"$(echo test | cat)"_ != _test_
1015 then
1016 error 'Test of "cat" command failed.';
1020 ########################################################################
1021 # Test for compression.
1023 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
1024 then
1025 _HAS_COMPRESSION='yes';
1026 if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
1027 && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
1028 | bzip2 -d -c 2>${_NULL_DEV})"_ \
1029 = _test_
1030 then
1031 _HAS_BZIP='yes';
1032 else
1033 _HAS_BZIP='no';
1035 else
1036 _HAS_COMPRESSION='no';
1037 _HAS_BZIP='no';
1041 ########################################################################
1042 # Definition of normal Functions in alphabetical order
1043 ########################################################################
1044 landmark "3: functions";
1046 ########################################################################
1047 # apropos_filespec ()
1049 # Setup for the --apropos* options
1051 apropos_filespec()
1054 func_check apropos_filespec '=' 0 "$@";
1055 if obj _OPT_APROPOS is_yes
1056 then
1057 eval to_tmp_line \
1058 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
1059 exit_test;
1060 if obj _APROPOS_PROG is_empty
1061 then
1062 error 'apropos_filespec: apropos_setup() must be run first.';
1064 if obj _APROPOS_SECTIONS is_empty
1065 then
1066 if obj _OPT_SECTIONS is_empty
1067 then
1068 s='^.*(.*).*$';
1069 else
1070 s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
1072 else
1073 s='^.*(['"${_APROPOS_SECTIONS}"']';
1075 eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
1076 sed -n -e '
1077 /^'"${_FILESPEC_ARG}"': /p
1078 /'"$s"'/p
1079 ' | \
1080 sort |\
1081 sed -e '
1082 s/^\(.* (..*)\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/
1083 ' >>"${_TMP_CAT}";
1085 eval "${return_ok}";
1089 ########################################################################
1090 # apropos_setup ()
1092 # Setup for the --apropos* options
1094 apropos_setup()
1096 func_check apropos_setup '=' 0 "$@";
1097 if obj _OPT_APROPOS is_yes
1098 then
1099 if is_prog apropos
1100 then
1101 _APROPOS_PROG='apropos';
1102 elif is_prog man
1103 then
1104 if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
1105 then
1106 _APROPOS_PROG='man --apropos';
1107 elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
1108 then
1109 _APROPOS_PROG='man -k';
1112 if obj _APROPOS_PROG is_empty
1113 then
1114 error 'apropos_setup: no apropos program available.';
1116 to_tmp_line '.TH GROFFER APROPOS';
1118 eval "${return_ok}";
1122 ########################################################################
1123 # base_name (<path>)
1125 # Get the file name part of <path>, i.e. delete everything up to last
1126 # `/' from the beginning of <path>. Remove final slashes, too, to get a
1127 # non-empty output.
1129 # Arguments : 1
1130 # Output : the file name part (without slashes)
1132 # Variable prefix: bn
1134 base_name()
1136 func_check base_name = 1 "$@";
1137 bn_name="$1";
1138 case "${bn_name}" in
1140 # delete all final slashes
1141 bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
1142 exit_test;
1144 esac;
1145 case "${bn_name}" in
1146 /|'')
1147 eval ${_UNSET} bn_name;
1148 eval "${return_bad}";
1150 */*)
1151 # delete everything before and including the last slash `/'.
1152 echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
1155 obj bn_name echo1;
1157 esac;
1158 eval ${_UNSET} bn_name;
1159 eval "${return_ok}";
1163 ########################################################################
1164 # cat_z (<file>)
1166 # Decompress if possible or just print <file> to standard output.
1168 # gzip, bzip2, and .Z decompression is supported.
1170 # Arguments: 1, a file name.
1171 # Output: the content of <file>, possibly decompressed.
1173 if test _"${_HAS_COMPRESSION}"_ = _yes_
1174 then
1175 cat_z()
1177 func_check cat_z = 1 "$@";
1178 case "$1" in
1180 error 'cat_z(): empty file name';
1182 '-')
1183 error 'cat_z(): for standard input use save_stdin()';
1185 esac;
1186 if obj _HAS_BZIP is_yes
1187 then
1188 if bzip2 -t "$1" 2>${_NULL_DEV}
1189 then
1190 bzip2 -c -d "$1" 2>${_NULL_DEV};
1191 eval "${return_ok}";
1194 gzip -c -d -f "$1" 2>${_NULL_DEV};
1195 eval "${return_ok}";
1197 else
1198 cat_z()
1200 func_check cat_z = 1 "$@";
1201 cat "$1";
1202 eval "${return_ok}";
1207 ########################################################################
1208 # clean_up ()
1210 # Do the final cleaning up before exiting; used by the trap calls.
1212 # defined above
1215 ########################################################################
1216 # diag (<text>*)
1218 # Print marked message to standard error; useful for debugging.
1220 # defined above
1223 ########################################################################
1224 landmark '4: dirname()*';
1225 ########################################################################
1227 #######################################################################
1228 # dirname_append (<dir> <name>)
1230 # Append `name' to `dir' with clean handling of `/'.
1232 # Arguments : 2
1233 # Output : the generated new directory name <dir>/<name>
1235 dirname_append()
1237 func_check dirname_append = 2 "$@";
1238 if is_empty "$1"
1239 then
1240 error "dir_append(): first argument is empty.";
1242 if is_empty "$2"
1243 then
1244 echo1 "$1";
1245 else
1246 dirname_chop "$1"/"$2";
1248 eval "${return_ok}";
1252 ########################################################################
1253 # dirname_chop (<name>)
1255 # Remove unnecessary slashes from directory name.
1257 # Argument: 1, a directory name.
1258 # Output: path without double, or trailing slashes.
1260 # Variable prefix: dc
1262 dirname_chop()
1264 func_check dirname_chop = 1 "$@";
1265 # replace all multiple slashes by a single slash `/'.
1266 dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
1267 exit_test;
1268 case "${dc_res}" in
1269 ?*/)
1270 # remove trailing slash '/';
1271 echo1 "${dc_res}" | sed -e 's|/$||';
1274 obj dc_res echo1
1276 esac;
1277 eval ${_UNSET} dc_res;
1278 eval "${return_ok}";
1282 ########################################################################
1283 # do_filearg (<filearg>)
1285 # Append the file, man-page, or standard input corresponding to the
1286 # argument to the temporary file. If this is compressed in the gzip
1287 # or Z format it is decompressed. A title element is generated.
1289 # Argument either:
1290 # - name of an existing file.
1291 # - `-' to represent standard input (several times allowed).
1292 # - `man:name.(section)' the man-page for `name' in `section'.
1293 # - `man:name.section' the man-page for `name' in `section'.
1294 # - `man:name' the man-page for `name' in the lowest `section'.
1295 # - `name.section' the man-page for `name' in `section'.
1296 # - `name' the man-page for `name' in the lowest `section'.
1297 # Globals :
1298 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1300 # Output : none
1301 # Return : $_GOOD if found, ${_BAD} otherwise.
1303 # Variable prefix: df
1305 do_filearg()
1307 func_check do_filearg = 1 "$@";
1308 df_filespec="$1";
1309 # store sequence into positional parameters
1310 case "${df_filespec}" in
1312 eval ${_UNSET} df_filespec;
1313 eval "${return_good}";
1315 '-')
1316 register_file '-';
1317 eval ${_UNSET} df_filespec;
1318 eval "${return_good}";
1320 */*) # with directory part; so no man search
1321 set 'File';
1324 if obj _MAN_ENABLE is_yes
1325 then
1326 if obj _MAN_FORCE is_yes
1327 then
1328 set 'Manpage' 'File';
1329 else
1330 set 'File' 'Manpage';
1332 else
1333 set 'File';
1336 esac;
1337 for i
1339 case "$i" in
1340 File)
1341 if test -f "${df_filespec}"
1342 then
1343 if test -r "${df_filespec}"
1344 then
1345 register_file "${df_filespec}";
1346 eval ${_UNSET} df_filespec;
1347 eval ${_UNSET} df_no_man;
1348 eval "${return_good}";
1349 else
1350 echo2 "could not read \`${df_filespec}'";
1351 eval ${_UNSET} df_filespec;
1352 eval ${_UNSET} df_no_man;
1353 eval "${return_bad}";
1355 else
1356 if obj df_no_man is_not_empty
1357 then
1358 if obj _OPT_WHATIS is_yes
1359 then
1360 to_tmp_line "This is neither a file nor a man page."
1361 else
1362 echo2 "\`${df_filespec}' is neither a file nor a man page."
1365 df_no_file=yes;
1366 continue;
1369 Manpage) # parse filespec as man page
1370 if obj _MAN_IS_SETUP is_not_yes
1371 then
1372 man_setup;
1374 if man_do_filespec "${df_filespec}"
1375 then
1376 eval ${_UNSET} df_filespec;
1377 eval ${_UNSET} df_no_file;
1378 eval "${return_good}";
1379 else
1380 if obj df_no_file is_not_empty
1381 then
1382 if obj _OPT_WHATIS is_yes
1383 then
1384 to_tmp_line "This is neither a file nor a man page."
1385 else
1386 echo2 "\`${df_filespec}' is neither a file nor a man page."
1389 df_no_man=yes;
1390 continue;
1393 esac;
1394 done;
1395 eval ${_UNSET} df_filespec;
1396 eval ${_UNSET} df_no_file;
1397 eval ${_UNSET} df_no_man;
1398 eval "${return_bad}";
1399 } # do_filearg()
1402 ########################################################################
1403 # do_nothing ()
1405 # Dummy function.
1407 do_nothing()
1409 eval return "${_OK}";
1413 ########################################################################
1414 # echo2 (<text>*)
1416 # Print to standard error with final line break.
1418 # defined above
1421 ########################################################################
1422 # error (<text>*)
1424 # Print error message and exit with error code.
1426 # defined above
1429 ########################################################################
1430 # exit_test ()
1432 # Test whether the former command ended with error(). Exit again.
1434 # defined above
1437 ########################################################################
1438 # func_check (<func_name> <rel_op> <nr_args> "$@")
1440 # Check number of arguments and register to _FUNC_STACK.
1442 # Arguments: >=3
1443 # <func_name>: name of the calling function.
1444 # <rel_op>: a relational operator: = != < > <= >=
1445 # <nr_args>: number of arguments to be checked against <operator>
1446 # "$@": the arguments of the calling function.
1448 # defined above
1450 #########################################################################
1451 # func_pop ()
1453 # Delete the top element from the function call stack.
1455 # defined above
1458 ########################################################################
1459 # func_push (<element>)
1461 # Store another element to function call stack.
1463 # defined above
1466 ########################################################################
1467 # func_stack_dump ()
1469 # Print the content of the stack.
1471 # defined above
1474 ########################################################################
1475 # get_first_essential (<arg>*)
1477 # Retrieve first non-empty argument.
1479 # Return : `1' if all arguments are empty, `0' if found.
1480 # Output : the retrieved non-empty argument.
1482 # Variable prefix: gfe
1484 get_first_essential()
1486 func_check get_first_essential '>=' 0 "$@";
1487 if is_equal "$#" 0
1488 then
1489 eval "${return_ok}";
1491 for i
1493 gfe_var="$i";
1494 if obj gfe_var is_not_empty
1495 then
1496 obj gfe_var echo1;
1497 eval ${_UNSET} gfe_var;
1498 eval "${return_ok}";
1500 done;
1501 eval ${_UNSET} gfe_var;
1502 eval "${return_bad}";
1506 ########################################################################
1507 landmark '5: is_*()';
1508 ########################################################################
1510 ########################################################################
1511 # is_dir (<name>)
1513 # Test whether `name' is a directory.
1515 # Arguments : 1
1516 # Return : `0' if arg1 is a directory, `1' otherwise.
1518 is_dir()
1520 func_check is_dir '=' 1 "$@";
1521 if test _"$1"_ != __ && test -d "$1" && test -r "$1"
1522 then
1523 eval "${return_yes}";
1525 eval "${return_no}";
1529 ########################################################################
1530 # is_empty (<string>)
1532 # Test whether `string' is empty.
1534 # Arguments : <=1
1535 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1537 is_empty()
1539 func_check is_empty '=' 1 "$@";
1540 if test _"$1"_ = __
1541 then
1542 eval "${return_yes}";
1544 eval "${return_no}";
1548 ########################################################################
1549 # is_equal (<string1> <string2>)
1551 # Test whether `string1' is equal to <string2>.
1553 # Arguments : 2
1554 # Return : `0' both arguments are equal strings, `1' otherwise.
1556 is_equal()
1558 func_check is_equal '=' 2 "$@";
1559 if test _"$1"_ = _"$2"_
1560 then
1561 eval "${return_yes}";
1563 eval "${return_no}";
1567 ########################################################################
1568 # is_existing (<name>)
1570 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1571 # not have `test -e'.
1573 # Arguments : 1
1574 # Return : `0' if arg1 exists, `1' otherwise.
1576 is_existing()
1578 func_check is_existing '=' 1 "$@";
1579 if test _"$1"_ = __
1580 then
1581 eval "${return_no}";
1583 if test -f "$1" || test -d "$1" || test -c "$1"
1584 then
1585 eval "${return_yes}";
1587 eval "${return_no}";
1591 ########################################################################
1592 # is_file (<name>)
1594 # Test whether `name' is a readable file.
1596 # Arguments : 1
1597 # Return : `0' if arg1 is a readable file, `1' otherwise.
1599 is_file()
1601 func_check is_file '=' 1 "$@";
1602 if is_not_empty "$1" && test -f "$1" && test -r "$1"
1603 then
1604 eval "${return_yes}";
1606 eval "${return_no}";
1610 ########################################################################
1611 # is_non_empty_file (<file_name>)
1613 # Test whether `file_name' is a non-empty existing file.
1615 # Arguments : <=1
1616 # Return :
1617 # `0' if arg1 is a non-empty existing file
1618 # `1' otherwise
1620 is_non_empty_file()
1622 func_check is_non_empty_file '=' 1 "$@";
1623 if is_file "$1" && test -s "$1"
1624 then
1625 eval "${return_yes}";
1627 eval "${return_no}";
1631 ########################################################################
1632 # is_not_dir (<name>)
1634 # Test whether `name' is not a readable directory.
1636 # Arguments : 1
1637 # Return : `0' if arg1 is a directory, `1' otherwise.
1639 is_not_dir()
1641 func_check is_not_dir '=' 1 "$@";
1642 if is_dir "$1"
1643 then
1644 eval "${return_no}";
1646 eval "${return_yes}";
1650 ########################################################################
1651 # is_not_empty (<string>)
1653 # Test whether `string' is not empty.
1655 # Arguments : <=1
1656 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1658 is_not_empty()
1660 func_check is_not_empty '=' 1 "$@";
1661 if is_empty "$1"
1662 then
1663 eval "${return_no}";
1665 eval "${return_yes}";
1669 ########################################################################
1670 # is_not_equal (<string1> <string2>)
1672 # Test whether `string1' differs from `string2'.
1674 # Arguments : 2
1676 is_not_equal()
1678 func_check is_not_equal '=' 2 "$@";
1679 if is_equal "$1" "$2"
1680 then
1681 eval "${return_no}";
1683 eval "${return_yes}";
1687 ########################################################################
1688 # is_not_file (<filename>)
1690 # Test whether `name' is a not readable file.
1692 # Arguments : 1 (empty allowed)
1694 is_not_file()
1696 func_check is_not_file '=' 1 "$@";
1697 if is_file "$1"
1698 then
1699 eval "${return_no}";
1701 eval "${return_yes}";
1705 ########################################################################
1706 # is_not_prog ([<name> [<arg>*]])
1708 # Verify that arg is a not program in $PATH.
1710 # Arguments : >=0 (empty allowed)
1711 # more args are ignored, this allows to specify progs with arguments
1713 is_not_prog()
1715 func_check is_not_prog '>=' 0 "$@";
1716 case "$#" in
1718 eval "${return_yes}";
1721 if where_is "$1" >${_NULL_DEV}
1722 then
1723 eval "${return_no}";
1726 esac
1727 eval "${return_yes}";
1731 ########################################################################
1732 # is_not_writable (<name>)
1734 # Test whether `name' is a not a writable file or directory.
1736 # Arguments : >=1 (empty allowed), more args are ignored
1738 is_not_writable()
1740 func_check is_not_writable '>=' 1 "$@";
1741 if is_writable "$1"
1742 then
1743 eval "${return_no}";
1745 eval "${return_yes}";
1749 ########################################################################
1750 # is_not_X ()
1752 # Test whether not running in X Window by checking $DISPLAY
1754 is_not_X()
1756 func_check is_X '=' 0 "$@";
1757 if obj DISPLAY is_empty
1758 then
1759 eval "${return_yes}";
1761 eval "${return_no}";
1765 ########################################################################
1766 # is_not_yes (<string>)
1768 # Test whether `string' is not "yes".
1770 # Arguments : 1
1772 is_not_yes()
1774 func_check is_not_yes = 1 "$@";
1775 if is_yes "$1"
1776 then
1777 eval "${return_no}";
1779 eval "${return_yes}";
1783 ########################################################################
1784 # is_prog ([<name> [<arg>*]])
1786 # Determine whether <name> is a program in $PATH
1788 # Arguments : >=0 (empty allowed)
1789 # <arg>* are ignored, this allows to specify progs with arguments.
1791 is_prog()
1793 func_check is_prog '>=' 0 "$@";
1794 case "$#" in
1796 eval "${return_no}";
1799 if where_is "$1" >${_NULL_DEV}
1800 then
1801 eval "${return_yes}";
1804 esac
1805 eval "${return_no}";
1809 ########################################################################
1810 # is_writable (<name>)
1812 # Test whether `name' is a writable file or directory.
1814 # Arguments : >=1 (empty allowed), more args are ignored
1816 is_writable()
1818 func_check is_writable '>=' 1 "$@";
1819 if test _"$1"_ = __
1820 then
1821 eval "${return_no}";
1823 if test -r "$1"
1824 then
1825 if test -w "$1"
1826 then
1827 eval "${return_yes}";
1830 eval "${return_no}";
1834 ########################################################################
1835 # is_X ()
1837 # Test whether running in X Window by checking $DISPLAY
1839 is_X()
1841 func_check is_X '=' 0 "$@";
1842 if obj DISPLAY is_not_empty
1843 then
1844 eval "${return_yes}";
1846 eval "${return_no}";
1850 ########################################################################
1851 # is_yes (<string>)
1853 # Test whether `string' has value "yes".
1855 # Return : `0' if arg1 is `yes', `1' otherwise.
1857 is_yes()
1859 func_check is_yes '=' 1 "$@";
1860 if is_equal "$1" 'yes'
1861 then
1862 eval "${return_yes}";
1864 eval "${return_no}";
1868 ########################################################################
1869 # landmark ()
1871 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1873 # Globals: $_DEBUG_LM
1875 # Defined in section `Debugging functions'.
1878 ########################################################################
1879 # leave ([<code>])
1881 # Clean exit without an error or with <code>.
1883 leave()
1885 clean_up;
1886 if test $# = 0
1887 then
1888 exit "${_OK}";
1889 else
1890 exit "$1";
1895 ########################################################################
1896 landmark '6: list_*()';
1897 ########################################################################
1899 # `list' is an object class that represents an array or list. Its
1900 # data consists of space-separated single-quoted elements. So a list
1901 # has the form "'first' 'second' '...' 'last'". See list_append() for
1902 # more details on the list structure. The array elements of `list'
1903 # can be get by `eval set x "$list"; shift`.
1906 ########################################################################
1907 # list_append (<list> <element>...)
1909 # Arguments: >=2
1910 # <list>: a variable name for a list of single-quoted elements
1911 # <element>: some sequence of characters.
1912 # Output: none, but $<list> is set to
1913 # if <list> is empty: "'<element>' '...'"
1914 # otherwise: "$list '<element>' ..."
1916 # Variable prefix: la
1918 list_append()
1920 func_check list_append '>=' 2 "$@";
1921 la_name="$1";
1922 eval la_list='"${'$1'}"';
1923 shift;
1924 for s
1926 la_s="$s";
1927 case "${la_s}" in
1928 *\'*)
1929 # escape each single quote by replacing each
1930 # "'" (squote) by "'\''" (squote bslash squote squote);
1931 # note that the backslash must be doubled in the following `sed'
1932 la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
1933 exit_test;
1936 la_element="";
1939 la_element="${la_s}";
1941 esac;
1942 if obj la_list is_empty
1943 then
1944 la_list="'${la_element}'";
1945 else
1946 la_list="${la_list} '${la_element}'";
1948 done;
1949 eval "${la_name}"='"${la_list}"';
1950 eval ${_UNSET} la_element;
1951 eval ${_UNSET} la_list;
1952 eval ${_UNSET} la_name;
1953 eval ${_UNSET} la_s;
1954 eval "${return_ok}";
1958 ########################################################################
1959 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1961 # Transform command line arguments into a normalized form.
1963 # Options, option arguments, and file parameters are identified and
1964 # output each as a single-quoted argument of its own. Options and
1965 # file parameters are separated by a '--' argument.
1967 # Arguments: >=1
1968 # <pre_name>: common part of a set of 4 environment variable names:
1969 # $<pre_name>_SHORT_NA: list of short options without an arg.
1970 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1971 # $<pre_name>_LONG_NA: list of long options without an arg.
1972 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1973 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1974 # the content of a variable, or direct arguments.
1976 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1978 # Example:
1979 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1980 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1981 # none-empty option lists, this will result in printing:
1982 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1984 # Use this function in the following way:
1985 # eval set x "$(args_norm PRE_NAME "$@")";
1986 # shift;
1987 # while test "$1" != '--'; do
1988 # case "$1" in
1989 # ...
1990 # esac;
1991 # shift;
1992 # done;
1993 # shift; #skip '--'
1994 # # all positional parameters ("$@") left are file name parameters.
1996 # Variable prefix: lfc
1998 list_from_cmdline()
2000 func_check list_from_cmdline '>=' 1 "$@";
2001 lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
2002 lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
2003 lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
2004 lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
2005 exit_test;
2006 if obj lfc_short_n is_empty
2007 then
2008 error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
2010 if obj lfc_short_a is_empty
2011 then
2012 error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
2014 if obj lfc_long_n is_empty
2015 then
2016 error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
2018 if obj lfc_long_a is_empty
2019 then
2020 error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
2023 shift;
2024 if is_equal "$#" 0
2025 then
2026 echo1 --
2027 eval ${_UNSET} lfc_fparams;
2028 eval ${_UNSET} lfc_short_a;
2029 eval ${_UNSET} lfc_short_n;
2030 eval ${_UNSET} lfc_long_a;
2031 eval ${_UNSET} lfc_long_n;
2032 eval ${_UNSET} lfc_result;
2033 eval "${return_ok}";
2036 lfc_fparams='';
2037 lfc_result='';
2038 while test "$#" -ge 1
2040 lfc_arg="$1";
2041 shift;
2042 case "${lfc_arg}" in
2043 --) break; ;;
2044 --*=*)
2045 # delete leading '--';
2046 lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
2047 lfc_with_equal="${lfc_abbrev}";
2048 # extract option by deleting from the first '=' to the end
2049 lfc_abbrev="$(echo1 "${lfc_with_equal}" | \
2050 sed -e 's/^\([^=]*\)=.*$/\1/')";
2051 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2052 exit_test;
2053 if obj lfc_opt is_empty
2054 then
2055 error_user "--${lfc_abbrev} is not an option.";
2056 else
2057 # get the option argument by deleting up to first `='
2058 lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')";
2059 exit_test;
2060 list_append lfc_result "--${lfc_opt}" "${lfc_optarg}";
2061 continue;
2064 --*)
2065 # delete leading '--';
2066 lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
2067 if list_has lfc_long_n "${lfc_abbrev}"
2068 then
2069 lfc_opt="${lfc_abbrev}";
2070 else
2071 exit_test;
2072 lfc_opt="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")";
2073 exit_test;
2074 if obj lfc_opt is_not_empty && is_not_equal "$#" 0
2075 then
2076 a="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2077 exit_test;
2078 if obj a is_not_empty
2079 then
2080 error_user "The abbreviation ${lfc_arg} \
2081 has multiple options: --${lfc_opt} and --${a}.";
2085 if obj lfc_opt is_not_empty
2086 then
2087 # long option, no argument
2088 list_append lfc_result "--${lfc_opt}";
2089 continue;
2091 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
2092 exit_test;
2093 if obj lfc_opt is_not_empty
2094 then
2095 # long option with argument
2096 if test "$#" -le 0
2097 then
2098 error_user "no argument for option --${lfc_opt}."
2100 list_append lfc_result "--${lfc_opt}" "$1";
2101 shift;
2102 continue;
2104 error_user "${lfc_arg} is not an option.";
2106 -?*) # short option (cluster)
2107 # delete leading `-';
2108 lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')";
2109 exit_test;
2110 while obj lfc_rest is_not_empty
2112 # get next short option from cluster (first char of $lfc_rest)
2113 lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')";
2114 # remove first character from ${lfc_rest};
2115 lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')";
2116 exit_test;
2117 if list_has lfc_short_n "${lfc_optchar}"
2118 then
2119 list_append lfc_result "-${lfc_optchar}";
2120 continue;
2121 elif list_has lfc_short_a "${lfc_optchar}"
2122 then
2123 if obj lfc_rest is_empty
2124 then
2125 if test "$#" -ge 1
2126 then
2127 list_append lfc_result "-${lfc_optchar}" "$1";
2128 shift;
2129 continue;
2130 else
2131 error_user "no argument for option -${lfc_optchar}.";
2133 else # rest is the argument
2134 list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
2135 lfc_rest='';
2136 continue;
2138 else
2139 error_user "unknown option -${lfc_optchar}.";
2141 done;
2144 # Here, $lfc_arg is not an option, so a file parameter.
2145 list_append lfc_fparams "${lfc_arg}";
2147 # Ignore the strange POSIX option handling to end option
2148 # parsing after the first file name argument. To reuse it, do
2149 # a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
2150 # When `bash' is called as `sh' $POSIXLY_CORRECT is set
2151 # automatically to `y'.
2153 esac;
2154 done;
2155 list_append lfc_result '--';
2156 if obj lfc_fparams is_not_empty
2157 then
2158 lfc_result="${lfc_result} ${lfc_fparams}";
2160 if test "$#" -gt 0
2161 then
2162 list_append lfc_result "$@";
2164 obj lfc_result echo1;
2165 eval ${_UNSET} lfc_abbrev;
2166 eval ${_UNSET} lfc_fparams;
2167 eval ${_UNSET} lfc_short_a;
2168 eval ${_UNSET} lfc_short_n;
2169 eval ${_UNSET} lfc_long_a;
2170 eval ${_UNSET} lfc_long_n;
2171 eval ${_UNSET} lfc_result;
2172 eval ${_UNSET} lfc_arg;
2173 eval ${_UNSET} lfc_opt;
2174 eval ${_UNSET} lfc_opt_arg;
2175 eval ${_UNSET} lfc_opt_char;
2176 eval ${_UNSET} lfc_with_equal;
2177 eval ${_UNSET} lfc_rest;
2178 eval "${return_ok}";
2179 } # list_from_cmdline()
2182 ########################################################################
2183 # list_from_split (<string> <separator>)
2185 # In <string>, escape all white space characters and replace each
2186 # <separator> by space.
2188 # Arguments: 2: a <string> that is to be split into parts divided by
2189 # <separator>
2190 # Output: the resulting list string
2192 # Variable prefix: lfs
2194 list_from_split()
2196 func_check list_from_split = 2 "$@";
2198 # precede each space or tab by a backslash `\' (doubled for `sed')
2199 lfs_s="$(echo1 "$1" | sed -e 's/\('"${_SPACE_SED}"'\)/\\\1/g')";
2200 exit_test;
2202 # replace split character of string by the list separator ` ' (space).
2203 case "$2" in
2204 /) # cannot use normal `sed' separator
2205 echo1 "${lfs_s}" | sed -e 's|'"$2"'| |g';
2207 ?) # use normal `sed' separator
2208 echo1 "${lfs_s}" | sed -e 's/'"$2"'/ /g';
2210 ??*)
2211 error 'list_from_split(): separator must be a single character.';
2213 esac;
2214 eval ${_UNSET} lfs_s;
2215 eval "${return_ok}";
2219 ########################################################################
2220 # list_get (<list>)
2222 # Check whether <list> is a space-separated list of '-quoted elements.
2224 # If the test fails an error is raised.
2225 # If the test succeeds the argument is echoed.
2227 # Testing criteria:
2228 # A list has the form "'first' 'second' '...' 'last'". So it has a
2229 # leading and a final quote and the elements are separated by "' '"
2230 # constructs. If these are all removed there should not be any
2231 # unescaped single-quotes left. Watch out for escaped single
2232 # quotes; they have the form '\'' (sq bs sq sq).
2234 # Arguments: 1
2235 # Output: the argument <list> unchanged, if the check succeeded.
2237 # Variable prefix: lg
2239 list_get()
2241 func_check list_get = 1 "$@";
2242 eval lg_list='"${'$1'}"';
2243 # remove leading and final space characters
2244 lg_list="$(echo1 "${lg_list}" | sed -e '
2245 s/^'"${_SPACE_SED}"'*//
2246 s/'"${_SPACE_SED}"'*$//
2247 ')";
2248 exit_test;
2249 case "${lg_list}" in
2251 eval ${_UNSET} lg_list;
2252 eval "${return_ok}";
2254 \'*\')
2255 obj lg_list echo1;
2256 eval ${_UNSET} lg_list;
2257 eval "${return_ok}";
2260 error "list_get(): bad list: $1"
2262 esac;
2263 eval ${_UNSET} lg_list;
2264 eval "${return_ok}";
2268 ########################################################################
2269 # list_has (<var_name> <element>)
2271 # Test whether the list <var_name> has the element <element>.
2273 # Arguments: 2
2274 # <var_name>: a variable name for a list of single-quoted elements
2275 # <element>: some sequence of characters.
2277 # Variable prefix: lh
2279 list_has()
2281 func_check list_has = 2 "$@";
2282 eval lh_list='"${'$1'}"';
2283 if obj lh_list is_empty
2284 then
2285 eval "${_UNSET}" lh_list;
2286 eval "${return_no}";
2288 case "$2" in
2289 \'*\') lh_element=" $2 "; ;;
2290 *) lh_element=" '$2' "; ;;
2291 esac;
2292 if string_contains " ${lh_list} " "${lh_element}"
2293 then
2294 eval "${_UNSET}" lh_list;
2295 eval "${_UNSET}" lh_element;
2296 eval "${return_yes}";
2297 else
2298 eval "${_UNSET}" lh_list;
2299 eval "${_UNSET}" lh_element;
2300 eval "${return_no}";
2305 ########################################################################
2306 # list_has_abbrev (<var_name> <abbrev>)
2308 # Test whether the list <var_name> has an element starting with <abbrev>.
2310 # Arguments: 2
2311 # <var_name>: a variable name for a list of single-quoted elements
2312 # <abbrev>: some sequence of characters.
2314 # Variable prefix: lha
2316 list_has_abbrev()
2318 func_check list_has_abbrev = 2 "$@";
2319 eval lha_list='"${'$1'}"';
2320 if obj lha_list is_empty
2321 then
2322 eval "${_UNSET}" lha_list;
2323 eval "${return_no}";
2325 case "$2" in
2326 \'*)
2327 lha_element="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')";
2328 exit_test;
2330 *) lha_element="'$2"; ;;
2331 esac;
2332 if string_contains " ${lha_list}" " ${lha_element}"
2333 then
2334 eval "${_UNSET}" lha_list;
2335 eval "${_UNSET}" lha_element;
2336 eval "${return_yes}";
2337 else
2338 eval "${_UNSET}" lha_list;
2339 eval "${_UNSET}" lha_element;
2340 eval "${return_no}";
2342 eval "${return_ok}";
2346 ########################################################################
2347 # list_has_not (<list> <element>)
2349 # Test whether <list> has no <element>.
2351 # Arguments: 2
2352 # <list>: a space-separated list of single-quoted elements.
2353 # <element>: some sequence of characters.
2355 # Variable prefix: lhn
2357 list_has_not()
2359 func_check list_has_not = 2 "$@";
2360 eval lhn_list='"${'$1'}"';
2361 if obj lhn_list is_empty
2362 then
2363 eval "${_UNSET}" lhn_list;
2364 eval "${return_yes}";
2366 case "$2" in
2367 \'*\') lhn_element=" $2 "; ;;
2368 *) lhn_element=" '$2' "; ;;
2369 esac;
2370 if string_contains " ${lhn_list} " "${lhn_element}"
2371 then
2372 eval "${_UNSET}" lhn_list;
2373 eval "${_UNSET}" lhn_element;
2374 eval "${return_no}";
2375 else
2376 eval "${_UNSET}" lhn_list;
2377 eval "${_UNSET}" lhn_element;
2378 eval "${return_yes}";
2383 ########################################################################
2384 # list_single_from_abbrev (<list> <abbrev>)
2386 # Check whether the list has an element starting with <abbrev>. If
2387 # there are more than a single element an error is created.
2389 # Arguments: 2
2390 # <list>: a variable name for a list of single-quoted elements
2391 # <abbrev>: some sequence of characters.
2393 # Output: the found element.
2395 # Variable prefix: lsfa
2397 list_single_from_abbrev()
2399 func_check list_single_from_abbrev = 2 "$@";
2400 eval lsfa_list='"${'$1'}"';
2401 if obj lsfa_list is_empty
2402 then
2403 eval "${_UNSET}" lsfa_list;
2404 eval "${return_no}";
2406 lsfa_abbrev="$2";
2407 if list_has lsfa_list "${lsfa_abbrev}"
2408 then
2409 obj lsfa_abbrev echo1;
2410 eval "${_UNSET}" lsfa_abbrev;
2411 eval "${_UNSET}" lsfa_list;
2412 eval "${return_yes}";
2414 if list_has_abbrev lsfa_list "${lsfa_abbrev}"
2415 then
2416 lsfa_element='';
2417 eval set x "${lsfa_list}";
2418 shift;
2419 for i
2421 case "$i" in
2422 ${lsfa_abbrev}*)
2423 if obj lsfa_element is_not_empty
2424 then
2425 error_user "The abbreviation --${lsfa_abbrev} \
2426 has multiple options: --${lsfa_element} and --${i}.";
2428 lsfa_element="$i";
2430 esac;
2431 done;
2432 obj lsfa_element echo1;
2433 eval "${_UNSET}" lsfa_abbrev;
2434 eval "${_UNSET}" lsfa_element;
2435 eval "${_UNSET}" lsfa_list;
2436 eval "${return_yes}";
2437 else
2438 eval "${_UNSET}" lsfa_abbrev;
2439 eval "${_UNSET}" lsfa_element;
2440 eval "${_UNSET}" lsfa_list;
2441 eval "${return_no}";
2446 ########################################################################
2447 landmark '7: man_*()';
2448 ########################################################################
2450 ########################################################################
2451 # man_do_filespec (<filespec>)
2453 # Print suitable man page(s) for filespec to $_TMP_CAT.
2455 # Arguments : 2
2456 # <filespec>: argument of the form `man:name.section', `man:name',
2457 # `man:name(section)', `name.section', `name'.
2459 # Globals : $_OPT_ALL
2461 # Output : none.
2462 # Return : `0' if man page was found, `1' else.
2464 # Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE
2465 # are assumed (see man_setup()).
2467 # Variable prefix: mdf
2469 man_do_filespec()
2471 func_check man_do_filespec = 1 "$@";
2472 if obj _MAN_PATH is_empty
2473 then
2474 eval "${return_bad}";
2476 if is_empty "$1"
2477 then
2478 eval "${return_bad}";
2480 mdf_spec="$1";
2481 mdf_name='';
2482 mdf_section='';
2483 case "${mdf_spec}" in
2484 */*) # not a man spec with containing '/'
2485 eval ${_UNSET} mdf_got_one;
2486 eval ${_UNSET} mdf_name;
2487 eval ${_UNSET} mdf_section;
2488 eval ${_UNSET} mdf_spec;
2489 eval "${return_bad}";
2491 man:?*\(?*\)) # man:name(section)
2492 mdf_name="$(echo1 "${mdf_spec}" \
2493 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
2494 mdf_section="$(echo1 "${mdf_spec}" \
2495 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
2496 exit_test;
2498 man:?*.${_MAN_AUTO_SEC_CHARS}) # man:name.section
2499 mdf_name="$(echo1 "${mdf_spec}" \
2500 | sed -e 's/^man:\(..*\)\..$/\1/')";
2501 mdf_section="$(echo1 "${mdf_spec}" \
2502 | sed -e 's/^.*\(.\)$/\1/')";
2503 exit_test;
2505 man:?*) # man:name
2506 mdf_name="$(echo1 "${mdf_spec}" | sed -e 's/^man://')";
2507 exit_test;
2509 ?*\(?*\)) # name(section)
2510 mdf_name="$(echo1 "${mdf_spec}" \
2511 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
2512 mdf_section="$(echo1 "${mdf_spec}" \
2513 | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
2514 exit_test;
2516 ?*.${_MAN_AUTO_SEC_CHARS}) # name.section
2517 mdf_name="$(echo1 "${mdf_spec}" \
2518 | sed -e 's/^\(..*\)\..$/\1/')";
2519 mdf_section="$(echo1 "${mdf_spec}" \
2520 | sed -e 's/^.*\(.\)$/\1/')";
2521 exit_test;
2524 mdf_name="${mdf_spec}";
2526 esac;
2527 if obj mdf_name is_empty
2528 then
2529 eval ${_UNSET} mdf_got_one;
2530 eval ${_UNSET} mdf_name;
2531 eval ${_UNSET} mdf_section;
2532 eval ${_UNSET} mdf_spec;
2533 eval "${return_bad}";
2535 mdf_got_one='no';
2536 if obj mdf_section is_empty
2537 then
2538 if obj _OPT_SECTIONS is_empty
2539 then
2540 eval set x "${_MAN_AUTO_SEC_LIST}";
2541 else
2542 # use --sections when no section is given to filespec
2543 eval set x "$(echo1 "${_OPT_SECTIONS}" | sed -e 's/:/ /g')";
2545 shift;
2546 for s
2548 mdf_s="$s";
2549 if man_search_section "${mdf_name}" "${mdf_s}"
2550 then # found
2551 if obj _MAN_ALL is_yes
2552 then
2553 mdf_got_one='yes';
2554 else
2555 eval ${_UNSET} mdf_got_one;
2556 eval ${_UNSET} mdf_name;
2557 eval ${_UNSET} mdf_s;
2558 eval ${_UNSET} mdf_section;
2559 eval ${_UNSET} mdf_spec;
2560 eval "${return_good}";
2563 done;
2564 else
2565 if man_search_section "${mdf_name}" "${mdf_section}"
2566 then
2567 eval ${_UNSET} mdf_got_one;
2568 eval ${_UNSET} mdf_name;
2569 eval ${_UNSET} mdf_s;
2570 eval ${_UNSET} mdf_section;
2571 eval ${_UNSET} mdf_spec;
2572 eval "${return_good}";
2573 else
2574 eval ${_UNSET} mdf_got_one;
2575 eval ${_UNSET} mdf_name;
2576 eval ${_UNSET} mdf_section;
2577 eval ${_UNSET} mdf_spec;
2578 eval "${return_bad}";
2581 if obj _MAN_ALL is_yes && obj mdf_got_one is_yes
2582 then
2583 eval ${_UNSET} mdf_got_one;
2584 eval ${_UNSET} mdf_name;
2585 eval ${_UNSET} mdf_s;
2586 eval ${_UNSET} mdf_section;
2587 eval ${_UNSET} mdf_spec;
2588 eval "${return_good}";
2590 eval ${_UNSET} mdf_got_one;
2591 eval ${_UNSET} mdf_name;
2592 eval ${_UNSET} mdf_s;
2593 eval ${_UNSET} mdf_section;
2594 eval ${_UNSET} mdf_spec;
2595 eval "${return_bad}";
2596 } # man_do_filespec()
2599 ########################################################################
2600 # man_register_file (<file> <name> [<section>])
2602 # Write a found man page file and register the title element.
2604 # Arguments: 1, 2, or 3; maybe empty
2605 # Output: none
2607 man_register_file()
2609 func_check man_register_file '>=' 2 "$@";
2610 case "$#" in
2611 2|3) do_nothing; ;;
2613 error "man_register_file() expects 2 or 3 arguments.";
2615 esac;
2616 if is_empty "$1"
2617 then
2618 error 'man_register_file(): file name is empty';
2620 to_tmp "$1";
2621 case "$#" in
2623 register_title "man:$2";
2624 eval "${return_ok}";
2627 register_title "$2.$3";
2628 eval "${return_ok}";
2630 esac;
2631 eval "${return_ok}";
2635 ########################################################################
2636 # man_search_section (<name> <section>)
2638 # Retrieve man pages.
2640 # Arguments : 2
2641 # Globals : $_MAN_PATH, $_MAN_EXT
2642 # Return : 0 if found, 1 otherwise
2644 # Variable prefix: mss
2646 man_search_section()
2648 func_check man_search_section = 2 "$@";
2649 if obj _MAN_PATH is_empty
2650 then
2651 eval "${return_bad}";
2653 if is_empty "$1"
2654 then
2655 eval "${return_bad}";
2657 if is_empty "$2"
2658 then
2659 eval "${return_bad}";
2661 mss_name="$1";
2662 mss_section="$2";
2663 eval set x "$(path_split "${_MAN_PATH}")";
2664 exit_test;
2665 shift;
2666 mss_got_one='no';
2667 if obj _MAN_EXT is_empty
2668 then
2669 for d
2671 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2672 exit_test;
2673 if obj mss_dir is_dir
2674 then
2675 mss_prefix="$(\
2676 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2677 if obj _OPT_WHATIS is_yes
2678 then
2679 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2680 sed -e '\| found|s|.*||'
2682 else
2683 mss_files="$(eval ls "'${mss_prefix}'"'*' 2>${_NULL_DEV} |
2684 sed -e '\| found|s|.*||'
2687 exit_test;
2688 if obj mss_files is_not_empty
2689 then
2690 # for f in $mss_files
2691 for f in $(eval set x ${mss_files}; shift; echo1 "$@")
2693 exit_test;
2694 mss_f="$f";
2695 if obj mss_f is_file
2696 then
2697 if is_yes "${mss_got_one}"
2698 then
2699 register_file "${mss_f}";
2700 elif obj _MAN_ALL is_yes
2701 then
2702 man_register_file "${mss_f}" "${mss_name}";
2703 else
2704 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2705 eval ${_UNSET} mss_dir;
2706 eval ${_UNSET} mss_ext;
2707 eval ${_UNSET} mss_f;
2708 eval ${_UNSET} mss_files;
2709 eval ${_UNSET} mss_got_one;
2710 eval ${_UNSET} mss_name;
2711 eval ${_UNSET} mss_prefix;
2712 eval ${_UNSET} mss_section;
2713 eval "${return_good}";
2715 mss_got_one='yes';
2717 done;
2720 done;
2721 else
2722 mss_ext="${_MAN_EXT}";
2723 # check for directory name having trailing extension
2724 for d
2726 mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";
2727 exit_test;
2728 if obj mss_dir is_dir
2729 then
2730 mss_prefix=\
2731 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2732 mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2733 sed -e '\|not found|s|.*||'
2735 exit_test;
2736 if obj mss_files is_not_empty
2737 then
2738 # for f in $mss_files
2739 for f in $(eval set x ${mss_files}; shift; echo1 "$@")
2741 mss_f="$f";
2742 if obj mss_f is_file
2743 then
2744 if is_yes "${mss_got_one}"
2745 then
2746 register_file "${mss_f}";
2747 elif obj _MAN_ALL is_yes
2748 then
2749 man_register_file "${mss_f}" "${mss_name}";
2750 else
2751 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2752 eval ${_UNSET} mss_dir;
2753 eval ${_UNSET} mss_ext;
2754 eval ${_UNSET} mss_f;
2755 eval ${_UNSET} mss_files;
2756 eval ${_UNSET} mss_got_one;
2757 eval ${_UNSET} mss_name;
2758 eval ${_UNSET} mss_prefix;
2759 eval ${_UNSET} mss_section;
2760 eval "${return_good}";
2762 mss_got_one='yes';
2764 done;
2767 done;
2768 # check for files with extension in directories without extension
2769 for d
2771 mss_dir="$(dirname_append "$d" "man${mss_section}")";
2772 exit_test;
2773 if obj mss_dir is_dir
2774 then
2775 mss_prefix="$(dirname_append "${mss_dir}" \
2776 "${mss_name}.${mss_section}${mss_ext}")";
2777 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2778 sed -e '\|not found|s|.*||'
2780 exit_test;
2781 if obj mss_files is_not_empty
2782 then
2783 # for f in $mss_files
2784 for f in $(eval set x ${mss_files}; shift; echo1 "$@")
2786 mss_f="$f";
2787 if obj mss_f is_file
2788 then
2789 if is_yes "${mss_got_one}"
2790 then
2791 register_file "${mss_f}";
2792 elif obj _MAN_ALL is_yes
2793 then
2794 man_register_file "${mss_f}" "${mss_name}";
2795 else
2796 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
2797 eval ${_UNSET} mss_dir;
2798 eval ${_UNSET} mss_ext;
2799 eval ${_UNSET} mss_f;
2800 eval ${_UNSET} mss_files;
2801 eval ${_UNSET} mss_got_one;
2802 eval ${_UNSET} mss_name;
2803 eval ${_UNSET} mss_prefix;
2804 eval ${_UNSET} mss_section;
2805 eval "${return_good}";
2807 mss_got_one='yes';
2809 done;
2812 done;
2814 if obj _MAN_ALL is_yes && is_yes "${mss_got_one}"
2815 then
2816 eval ${_UNSET} mss_dir;
2817 eval ${_UNSET} mss_ext;
2818 eval ${_UNSET} mss_f;
2819 eval ${_UNSET} mss_files;
2820 eval ${_UNSET} mss_got_one;
2821 eval ${_UNSET} mss_name;
2822 eval ${_UNSET} mss_prefix;
2823 eval ${_UNSET} mss_section;
2824 eval "${return_good}";
2826 eval ${_UNSET} mss_dir;
2827 eval ${_UNSET} mss_ext;
2828 eval ${_UNSET} mss_f;
2829 eval ${_UNSET} mss_files;
2830 eval ${_UNSET} mss_got_one;
2831 eval ${_UNSET} mss_name;
2832 eval ${_UNSET} mss_prefix;
2833 eval ${_UNSET} mss_section;
2834 eval "${return_bad}";
2835 } # man_search_section()
2838 ########################################################################
2839 # man_setup ()
2841 # Setup the variables $_MAN_* needed for man page searching.
2843 # Globals:
2844 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2845 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2846 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2847 # $_MAN_SEC, $_MAN_ALL
2848 # in/out: $_MAN_ENABLE
2850 # The precedence for the variables related to `man' is that of GNU
2851 # `man', i.e.
2853 # $LANG; overridden by
2854 # $LC_MESSAGES; overridden by
2855 # $LC_ALL; this has the same precedence as
2856 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2857 # $MANOPT; overridden by
2858 # the groffer command line options.
2860 # Variable prefix: ms
2862 man_setup()
2864 func_check main_man_setup = 0 "$@";
2866 if obj _MAN_IS_SETUP is_yes
2867 then
2868 eval "${return_ok}";
2870 _MAN_IS_SETUP='yes';
2872 if obj _MAN_ENABLE is_not_yes
2873 then
2874 eval "${return_ok}";
2877 # determine basic path for man pages
2878 _MAN_PATH="$(get_first_essential \
2879 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2880 exit_test;
2881 if obj _MAN_PATH is_empty
2882 then
2883 manpath_set_from_path;
2884 else
2885 _MAN_PATH="$(path_clean "${_MAN_PATH}")";
2886 exit_test;
2888 if obj _MAN_PATH is_empty
2889 then
2890 if is_prog 'manpath'
2891 then
2892 _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available
2893 exit_test;
2896 if obj _MAN_PATH is_empty
2897 then
2898 _MAN_ENABLE="no";
2899 eval "${return_ok}";
2902 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2903 exit_test;
2904 if obj _MAN_ALL is_empty
2905 then
2906 _MAN_ALL='no';
2909 _MAN_SYS="$(get_first_essential \
2910 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2911 ms_lang="$(get_first_essential \
2912 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2913 exit_test;
2914 case "${ms_lang}" in
2915 C|POSIX)
2916 _MAN_LANG="";
2917 _MAN_LANG2="";
2920 _MAN_LANG="${ms_lang}";
2921 _MAN_LANG2="";
2924 _MAN_LANG="${ms_lang}";
2925 # get first two characters of $ms_lang
2926 _MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')";
2927 exit_test;
2929 esac;
2930 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2932 manpath_add_lang_sys; # this is very slow
2934 _MAN_SEC="$(get_first_essential \
2935 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2936 exit_test;
2937 if obj _MAN_PATH is_empty
2938 then
2939 _MAN_ENABLE="no";
2940 eval ${_UNSET} ms_lang;
2941 eval "${return_ok}";
2944 _MAN_EXT="$(get_first_essential \
2945 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2946 exit_test;
2947 eval ${_UNSET} ms_lang;
2948 eval "${return_ok}";
2949 } # man_setup()
2952 ########################################################################
2953 landmark '8: manpath_*()';
2954 ########################################################################
2956 ########################################################################
2957 # manpath_add_lang_sys ()
2959 # Add language and operating system specific directories to man path.
2961 # Arguments : 0
2962 # Output : none
2963 # Globals:
2964 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2965 # list of names of operating systems.
2966 # $_MAN_LANG and $_MAN_LANG2: each a single name
2967 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2968 # separated list of directories.
2970 # Variable prefix: mals
2972 manpath_add_lang_sys()
2974 func_check manpath_add_lang_sys = 0 "$@";
2975 if obj _MAN_PATH is_empty
2976 then
2977 eval "${return_ok}";
2979 # twice test both sys and lang
2980 eval set x "$(path_split "${_MAN_PATH}")";
2981 shift;
2982 exit_test;
2983 mals_mp='';
2984 for p
2985 do # loop on man path directories
2986 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2987 exit_test;
2988 done;
2989 eval set x "$(path_split "${mals_mp}")";
2990 shift;
2991 exit_test;
2992 for p
2993 do # loop on man path directories
2994 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2995 exit_test;
2996 done;
2997 _MAN_PATH="$(path_chop "${mals_mp}")";
2998 exit_test;
2999 eval ${_UNSET} mals_mp;
3000 eval "${return_ok}";
3004 # To the directory in $1 append existing sys/lang subdirectories
3005 # Function is necessary to split the OS list.
3007 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
3008 # argument: 2: `man_path' and `dir'
3009 # output: colon-separated path of the retrieved subdirectories
3011 # Variable prefix: _mals
3013 _manpath_add_lang_sys_single()
3015 func_check _manpath_add_lang_sys_single = 2 "$@";
3016 _mals_res="$1";
3017 _mals_parent="$2";
3018 eval set x "$(list_from_split "${_MAN_SYS}" ',')";
3019 shift;
3020 exit_test;
3021 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
3023 _mals_dir="$(dirname_append "${_mals_parent}" "$d")";
3024 exit_test;
3025 if obj _mals_res path_not_contains "${_mals_dir}" && \
3026 obj _mals_dir is_dir
3027 then
3028 _mals_res="${_mals_res}:${_mals_dir}";
3030 done;
3031 if path_not_contains "${_mals_res}" "${_mals_parent}"
3032 then
3033 _mals_res="${_mals_res}:${_mals_parent}";
3035 path_chop "${_mals_res}";
3036 eval ${_UNSET} _mals_dir;
3037 eval ${_UNSET} _mals_parent;
3038 eval ${_UNSET} _mals_res;
3039 eval "${return_ok}";
3042 # end manpath_add_lang_sys ()
3045 ########################################################################
3046 # manpath_set_from_path ()
3048 # Determine basic search path for man pages from $PATH.
3050 # Return: `0' if a valid man path was retrieved.
3051 # Output: none
3052 # Globals:
3053 # in: $PATH
3054 # out: $_MAN_PATH
3056 # Variable prefix: msfp
3058 manpath_set_from_path()
3060 func_check manpath_set_from_path = 0 "$@";
3062 msfp_manpath='';
3064 # get a basic man path from $PATH
3065 if obj PATH is_not_empty
3066 then
3067 eval set x "$(path_split "${PATH}")";
3068 shift;
3069 exit_test;
3070 for d
3072 # delete the final `/bin' part
3073 msfp_base="$(echo1 "$d" | sed -e 's|//*bin/*$||')";
3074 exit_test;
3075 for e in /share/man /man
3077 msfp_mandir="${msfp_base}$e";
3078 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}"
3079 then
3080 msfp_manpath="${msfp_manpath}:${msfp_mandir}";
3082 done;
3083 done;
3086 # append some default directories
3087 for d in /usr/local/share/man /usr/local/man \
3088 /usr/share/man /usr/man \
3089 /usr/X11R6/man /usr/openwin/man \
3090 /opt/share/man /opt/man \
3091 /opt/gnome/man /opt/kde/man
3093 msfp_d="$d";
3094 if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir
3095 then
3096 msfp_manpath="${msfp_manpath}:${mfsp_d}";
3098 done;
3100 _MAN_PATH="${msfp_manpath}";
3101 eval ${_UNSET} msfp_base;
3102 eval ${_UNSET} msfp_d;
3103 eval ${_UNSET} msfp_mandir;
3104 eval ${_UNSET} msfp_manpath;
3105 eval "${return_ok}";
3106 } # manpath_set_from_path()
3109 ########################################################################
3110 landmark '9: obj_*()';
3111 ########################################################################
3113 ########################################################################
3114 # obj (<object> <call_name> <arg>...)
3116 # This works like a method (object function) call for an object.
3117 # Run "<call_name> $<object> <arg> ...".
3119 # The first argument represents an object whose data is given as first
3120 # argument to <call_name>().
3122 # Argument: >=2
3123 # <object>: variable name
3124 # <call_name>: a program or function name
3126 # Variable prefix: o
3128 obj()
3130 func_check obj '>=' 2 "$@";
3131 eval o_arg1='"${'$1'}"';
3132 if is_empty "$2"
3133 then
3134 error "obj(): function name is empty."
3135 else
3136 o_func="$2";
3138 shift;
3139 shift;
3140 eval "${o_func}"' "${o_arg1}" "$@"';
3141 n="$?";
3142 eval ${_UNSET} o_arg1;
3143 eval ${_UNSET} o_func;
3144 eval "${return_var} $n";
3145 } # obj()
3148 ########################################################################
3149 # obj_data (<object>)
3151 # Print the data of <object>, i.e. the content of $<object>.
3152 # For possible later extensions.
3154 # Arguments: 1
3155 # <object>: a variable name
3156 # Output: the data of <object>
3158 # Variable prefix: od
3160 obj_data()
3162 func_check obj '=' 1 "$@";
3163 if is_empty "$1"
3164 then
3165 error "obj_data(): object name is empty."
3167 eval od_res='"${'$1'}"';
3168 obj od_res echo1;
3169 eval ${_UNSET} od_res;
3170 eval "${return_ok}";
3174 ########################################################################
3175 # obj_from_output (<object> <call_name> <arg>...)
3177 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
3178 # function call to a global variable.
3180 # Arguments: >=2
3181 # <object>: a variable name
3182 # <call_name>: the name of a function or program
3183 # <arg>: optional argument to <call_name>
3184 # Output: none
3186 # Variable prefix: ofo
3188 obj_from_output()
3190 func_check obj_from_output '>=' 2 "$@";
3191 if is_empty "$1"
3192 then
3193 error "res(): variable name is empty.";
3194 elif is_empty "$2"
3195 then
3196 error "res(): function name is empty."
3197 else
3198 ofo_result_name="$1";
3200 shift;
3201 eval "${ofo_result_name}"'="$('"$@"')"';
3202 exit_test;
3203 eval "${return_ok}";
3207 ########################################################################
3208 # obj_set (<object> <data>)
3210 # Set the data of <object>, i.e. call "$<object>=<data>".
3212 # Arguments: 2
3213 # <object>: a variable name
3214 # <data>: a string
3215 # Output:: none
3217 obj_set()
3219 func_check obj_set '=' 2 "$@";
3220 if is_empty "$1"
3221 then
3222 error "obj_set(): object name is empty."
3224 eval "$1"='"$2"';
3225 eval "${return_ok}";
3229 ########################################################################
3230 # path_chop (<path>)
3232 # Remove unnecessary colons from path.
3234 # Argument: 1, a colon separated path.
3235 # Output: path without leading, double, or trailing colons.
3237 path_chop()
3239 func_check path_chop = 1 "$@";
3241 # replace multiple colons by a single colon `:'
3242 # remove leading and trailing colons
3243 echo1 "$1" | sed -e '
3244 s/^:*//
3245 s/:::*/:/g
3246 s/:*$//
3248 eval "${return_ok}";
3252 ########################################################################
3253 # path_clean (<path>)
3255 # Remove non-existing directories from a colon-separated list.
3257 # Argument: 1, a colon separated path.
3258 # Output: colon-separated list of existing directories.
3260 # Variable prefix: pc
3262 path_clean()
3264 func_check path_clean = 1 "$@";
3265 if is_not_equal "$#" 1
3266 then
3267 error 'path_clean() needs 1 argument.';
3269 pc_arg="$1";
3270 eval set x "$(path_split "${pc_arg}")";
3271 exit_test;
3272 shift;
3273 pc_res="";
3274 for i
3276 pc_i="$i";
3277 if obj pc_i is_not_empty \
3278 && obj pc_res path_not_contains "${pc_i}" \
3279 && obj pc_i is_dir
3280 then
3281 case "${pc_i}" in
3282 ?*/)
3283 pc_res="${pc_res}$(dirname_chop "${pc_i}")";
3284 exit_test;
3287 pc_res="${pc_res}:${pc_i}";
3288 exit_test;
3290 esac;
3292 done;
3293 eval ${_UNSET} pc_arg;
3294 eval ${_UNSET} pc_i;
3295 eval ${_UNSET} pc_res;
3296 if path_chop "${pc_res}"
3297 then
3298 eval "${return_ok}";
3299 else
3300 eval "${return_bad}";
3305 ########################################################################
3306 # path_contains (<path> <dir>)
3308 # Test whether `dir' is contained in `path', a list separated by `:'.
3310 # Arguments : 2 arguments.
3311 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3313 path_contains()
3315 func_check path_contains = 2 "$@";
3316 case ":$1:" in
3317 *":$2:"*)
3318 eval "${return_yes}";
3321 eval "${return_no}";
3323 esac;
3324 eval "${return_ok}";
3328 ########################################################################
3329 # path_not_contains (<path> <dir>)
3331 # Test whether `dir' is not contained in colon separated `path'.
3333 # Arguments : 2 arguments.
3335 path_not_contains()
3337 func_check path_not_contains = 2 "$@";
3338 if path_contains "$1" "$2"
3339 then
3340 eval "${return_no}";
3341 else
3342 eval "${return_yes}";
3344 eval "${return_ok}";
3348 ########################################################################
3349 # path_split (<path>)
3351 # In `path' escape white space and replace each colon by a space.
3353 # Arguments: 1: a colon-separated path
3354 # Output: the resulting list, process with `eval set'
3356 path_split()
3358 func_check path_split = 1 "$@";
3359 list_from_split "$1" ':';
3360 eval "${return_ok}";
3364 ########################################################################
3365 landmark '10: register_*()';
3366 ########################################################################
3368 ########################################################################
3369 # register_file (<filename>)
3371 # Write a found file and register the title element.
3373 # Arguments: 1: a file name
3374 # Output: none
3376 register_file()
3378 func_check register_file = 1 "$@";
3379 if is_empty "$1"
3380 then
3381 error 'register_file(): file name is empty';
3383 if is_equal "$1" '-'
3384 then
3385 to_tmp "${_TMP_STDIN}";
3386 register_title 'stdin';
3387 else
3388 to_tmp "$1";
3389 register_title "$(base_name "$1")";
3390 exit_test;
3392 eval "${return_ok}";
3393 } # register_file()
3396 ########################################################################
3397 # register_title (<filespec>)
3399 # Create title element from <filespec> and append to $_REGISTERED_TITLE
3401 # Globals: $_REGISTERED_TITLE (rw)
3403 # Variable prefix: rt
3405 register_title()
3407 func_check register_title '=' 1 "$@";
3408 if is_empty "$1"
3409 then
3410 eval "${return_ok}";
3413 case "${_REGISTERED_TITLE}" in
3414 *\ *\ *\ *)
3415 eval "${return_ok}";
3417 esac;
3419 # remove directory part
3420 rt_title="$(base_name "$1")";
3421 # replace space characters by `_'
3422 rt_title="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')";
3423 # remove extension `.bz2'
3424 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')";
3425 # remove extension `.gz'
3426 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')";
3427 # remove extension `.Z'
3428 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')";
3429 exit_test;
3431 if obj rt_title is_empty
3432 then
3433 eval ${_UNSET} rt_title;
3434 eval "${return_ok}";
3436 if obj _REGISTERED_TITLE is_empty
3437 then
3438 _REGISTERED_TITLE="${rt_title}";
3439 else
3440 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";
3442 eval ${_UNSET} rt_title;
3443 eval "${return_ok}";
3444 } # register_title()
3447 ########################################################################
3448 # reset ()
3450 # Reset the variables that can be affected by options to their default.
3453 # Defined in section `Preset' after the rudimentary shell tests.
3456 ########################################################################
3457 # rm_file (<file_name>)
3459 # Remove file if $_DEBUG_KEEP_FILES allows it.
3461 # Globals: $_DEBUG_KEEP_FILES
3463 rm_file()
3465 func_check rm_file '=' 1 "$@";
3466 if is_file "$1"
3467 then
3468 rm -f "$1" >${_NULL_DEV} 2>&1;
3470 if is_existing "$1"
3471 then
3472 eval "${return_bad}";
3473 else
3474 eval "${return_good}";
3479 ########################################################################
3480 # rm_file_with_debug (<file_name>)
3482 # Remove file if $_DEBUG_KEEP_FILES allows it.
3484 # Globals: $_DEBUG_KEEP_FILES
3486 rm_file_with_debug()
3488 func_check rm_file_with_debug '=' 1 "$@";
3489 if obj _DEBUG_KEEP_FILES is_not_yes
3490 then
3491 if is_file "$1"
3492 then
3493 rm -f "$1" >${_NULL_DEV} 2>&1;
3496 if is_existing "$1"
3497 then
3498 eval "${return_bad}";
3499 else
3500 eval "${return_good}";
3505 ########################################################################
3506 # rm_tree (<dir_name>)
3508 # Remove file if $_DEBUG_KEEP_FILES allows it.
3510 # Globals: $_DEBUG_KEEP_FILES
3512 rm_tree()
3514 func_check rm_tree '=' 1 "$@";
3515 if is_existing "$1"
3516 then
3517 rm -f -r "$1" >${_NULL_DEV} 2>&1;
3518 fi;
3519 if is_existing "$1"
3520 then
3521 eval "${return_bad}";
3522 else
3523 eval "${return_good}";
3528 ########################################################################
3529 # save_stdin ()
3531 # Store standard input to temporary file (with decompression).
3533 # Variable prefix: ss
3535 if obj _HAS_COMPRESSION is_yes
3536 then
3537 save_stdin()
3539 func_check save_stdin '=' 0 "$@";
3540 ss_f="${_TMP_DIR}"/INPUT;
3541 cat >"${ss_f}";
3542 cat_z "${ss_f}" >"${_TMP_STDIN}";
3543 rm_file "${ss_f}";
3544 eval ${_UNSET} ss_f;
3545 eval "${return_ok}";
3547 else
3548 save_stdin()
3550 func_check save_stdin = 0 "$@";
3551 cat >"${_TMP_STDIN}";
3552 eval "${return_ok}";
3557 ########################################################################
3558 # special_filespec ()
3560 # Handle special modes like whatis and apropos.
3562 special_filespec()
3564 func_check special_setup '=' 0 "$@";
3565 if obj _OPT_APROPOS is_yes
3566 then
3567 if obj _OPT_WHATIS is_yes
3568 then
3569 error \
3570 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
3572 apropos_filespec;
3573 eval "${return_ok}";
3575 if obj _OPT_WHATIS is_yes
3576 then
3577 whatis_filespec;
3579 eval "${return_ok}";
3583 ########################################################################
3584 # special_setup ()
3586 # Handle special modes like whatis and apropos.
3588 special_setup()
3590 func_check special_setup '=' 0 "$@";
3591 if obj _OPT_APROPOS is_yes
3592 then
3593 if obj _OPT_WHATIS is_yes
3594 then
3595 error \
3596 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
3598 apropos_setup;
3599 eval "${return_ok}";
3601 if obj _OPT_WHATIS is_yes
3602 then
3603 whatis_header;
3604 fi;
3605 eval "${return_ok}";
3609 ########################################################################
3610 landmark '11: stack_*()';
3611 ########################################################################
3613 ########################################################################
3614 # string_contains (<string> <part>)
3616 # Test whether `part' is contained in `string'.
3618 # Arguments : 2 text arguments.
3619 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3621 string_contains()
3623 func_check string_contains '=' 2 "$@";
3624 case "$1" in
3625 *"$2"*)
3626 eval "${return_yes}";
3629 eval "${return_no}";
3631 esac;
3632 eval "${return_ok}";
3636 ########################################################################
3637 # string_not_contains (<string> <part>)
3639 # Test whether `part' is not substring of `string'.
3641 # Arguments : 2 text arguments.
3642 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3644 string_not_contains()
3646 func_check string_not_contains '=' 2 "$@";
3647 if string_contains "$1" "$2"
3648 then
3649 eval "${return_no}";
3650 else
3651 eval "${return_yes}";
3653 eval "${return_ok}";
3657 ########################################################################
3658 landmark '12: tmp_*()';
3659 ########################################################################
3661 ########################################################################
3662 # tmp_cat ()
3664 # output the temporary cat file (the concatenation of all input)
3666 tmp_cat()
3668 func_check tmp_cat '=' 0 "$@";
3669 cat "${_TMP_CAT}";
3670 eval "${return_var}" "$?";
3674 ########################################################################
3675 # tmp_create (<suffix>?)
3677 # Create temporary file.
3679 # It's safe to use the shell process ID together with a suffix to
3680 # have multiple temporary files.
3682 # Globals: $_TMP_DIR
3684 # Output : name of created file
3686 # Variable prefix: tc
3688 tmp_create()
3690 func_check tmp_create '<=' 1 "$@";
3691 # the output file does not have `,' as first character, so these are
3692 # different names from the output file.
3693 tc_tmp="${_TMP_DIR}/,$1";
3694 : >"${tc_tmp}"
3695 obj tc_tmp echo1;
3696 eval ${_UNSET} tc_tmp;
3697 eval "${return_ok}";
3701 ########################################################################
3702 # to_tmp (<filename>)
3704 # print file (decompressed) to the temporary cat file
3706 to_tmp()
3708 func_check to_tmp '=' 1 "$@";
3709 if obj _TMP_CAT is_empty
3710 then
3711 error 'to_tmp_line: $_TMP_CAT is not yet set';
3713 if is_file "$1"
3714 then
3715 if obj _OPT_LOCATION is_yes
3716 then
3717 echo2 "$1";
3719 if obj _OPT_WHATIS is_yes
3720 then
3721 whatis_filename "$1" >>"${_TMP_CAT}";
3722 else
3723 cat_z "$1" >>"${_TMP_CAT}";
3725 else
3726 error "to_tmp(): could not read file \`$1'.";
3728 eval "${return_ok}";
3732 ########################################################################
3733 # to_tmp_line ([<text>])
3735 # print line to the temporary cat file
3737 to_tmp_line()
3739 func_check to_tmp '>=' 0 "$@";
3740 if obj _TMP_CAT is_empty
3741 then
3742 error 'to_tmp_line: $_TMP_CAT is not yet set';
3744 echo1 "$*" >>"${_TMP_CAT}";
3745 eval "${return_ok}";
3749 ########################################################################
3750 # trap_set
3752 # call function on signal 0
3754 trap_set()
3756 func_check trap_set '=' 0 "$@";
3757 trap 'clean_up' 0 2>${_NULL_DEV} || :;
3758 eval "${return_ok}";
3762 ########################################################################
3763 # trap_unset ()
3765 # disable trap on signal 0.
3767 trap_unset()
3769 func_check trap_unset '=' 0 "$@";
3770 trap '' 0 2>${_NULL_DEV} || :;
3771 eval "${return_ok}";
3775 ########################################################################
3776 # usage ()
3778 # print usage information to stderr; for groffer option --help.
3780 usage()
3782 func_check usage = 0 "$@";
3783 echo;
3784 version;
3785 echo1 'Usage: groffer [option]... [filespec]...';
3786 cat <<EOF
3788 Display roff files, standard input, and/or Unix manual pages with a X
3789 Window viewer or in several text modes. All input is decompressed
3790 on-the-fly with all formats that gzip can handle.
3792 "filespec" is one of
3793 "filename" name of a readable file
3794 "-" for standard input
3795 "man:name.n" man page "name" in section "n"
3796 "man:name" man page "name" in first section found
3797 "name.n" man page "name" in section "n"
3798 "name" man page "name" in first section found
3799 and some more (see groffer(1) for details).
3801 -h --help print this usage message.
3802 -Q --source output as roff source.
3803 -T --device=name pass to groff using output device "name".
3804 -v --version print version information.
3805 -V display the groff execution pipe instead of formatting.
3806 -X display with "gxditview" using groff -X.
3807 -Z --ditroff --intermediate-output
3808 generate groff intermediate output without
3809 post-processing and viewing, like groff -Z.
3810 All other short options are interpreted as "groff" formatting options.
3812 The most important groffer long options are
3814 --apropos=name start man's "apropos" program for "name".
3815 --apropos-data=name
3816 "apropos" for "name" in man's data sections 4, 5, 7.
3817 --apropos-devel=name
3818 "apropos" for "name" in development sections 2, 3, 9.
3819 --apropos-progs=name
3820 "apropos" for "name" in man's program sections 1, 6, 8.
3821 --auto choose mode automatically from the default mode list.
3822 --default reset all options to the default value.
3823 --default-modes=mode1,mode2,...
3824 set sequence of automatically tried modes.
3825 --dvi display in a viewer for TeX device independent format.
3826 --dvi-viewer=prog choose the viewer program for dvi mode.
3827 --groff process like groff, disable viewing features.
3828 --help display this helping output.
3829 --html display in a web browser.
3830 --html-viewer=program
3831 choose the web browser for html mode.
3832 --man check file parameters first whether they are man pages.
3833 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3834 choose display mode.
3835 --no-man disable man-page facility.
3836 --no-special disable --all, --apropos*, and --whatis
3837 --pager=program preset the paging program for tty mode.
3838 --pdf display in a PDF viewer.
3839 --pdf-viewer=prog choose the viewer program for pdf mode.
3840 --ps display in a Postscript viewer.
3841 --ps-viewer=prog choose the viewer program for ps mode.
3842 --shell=program specify a shell under which to run groffer2.sh.
3843 --text output in a text device without a pager.
3844 --tty display with a pager on text terminal even when in X.
3845 --tty-viewer=prog select a pager for tty mode; same as --pager.
3846 --whatis display the file name and description of man pages
3847 --www same as --html.
3848 --www-viewer=prog same as --html-viewer
3849 --x --X display with "gxditview" using an X* device.
3850 --x-viewer=prog choose viewer program for x mode (X mode).
3851 --X-viewer=prog same as "--xviewer".
3853 Development options that are not useful for normal usage:
3854 --debug, --debug-all, --debug-keep, --debug-lm, --debug-params,
3855 --debug-shell, --debug-stacks, --debug-tmpdir, --debug-user,
3856 --do-nothing, --print=text
3858 Viewer programs for the different modes that run on the terminal:
3859 --dvi-viewer-tty=prog, --html-viewer-tty=prog, --pdf-viewer-tty=prog,
3860 --ps-viewer-tty=prog, --tty-viewer-tty, --X-viewer-tty=prog,
3861 --x-viewer-tty=prog, --www-viewer-tty=prog
3863 The usual X Windows toolkit options transformed into GNU long options:
3864 --background=color, --bd=size, --bg=color, --bordercolor=color,
3865 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3866 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3867 --resolution=dpi, --rv, --title=text, --xrm=resource
3869 Long options of GNU "man":
3870 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3871 --local-file=name, --location, --manpath=dir1:dir2:...,
3872 --sections=s1:s2:..., --systems=s1,s2,..., --where, ...
3875 eval "${return_ok}";
3879 ########################################################################
3880 # version ()
3882 # print version information to stderr
3884 version()
3886 func_check version = 0 "$@";
3887 echo1 "groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3888 # also display groff's version, but not the called subprograms
3889 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /';
3890 eval "${return_ok}";
3894 ########################################################################
3895 # warning (<string>)
3897 # Print warning to stderr
3899 warning()
3901 echo2 "warning: $*";
3905 ########################################################################
3906 # whatis_filename (<filename>)
3908 # Interpret <filename> as a man page and display its `whatis'
3909 # information as a fragment written in the groff language.
3911 # Variable prefix: wf
3913 whatis_filename()
3915 func_check whatis_filename = 1 "$@";
3916 wf_arg="$1";
3917 if obj wf_arg is_not_file
3918 then
3919 error "whatis_filename(): argument is not a readable file."
3921 wf_dot='^\.'"${_SPACE_SED}"'*';
3922 if obj _FILESPEC_ARG is_equal '-'
3923 then
3924 wf_arg='stdin';
3926 cat <<EOF
3927 \f[CR]${wf_arg}\f[]:
3931 # get the parts of the file name
3932 wf_name="$(base_name $1)";
3933 wf_section="$(echo1 $1 | sed -n -e '
3934 s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p
3935 ')";
3936 if obj wf_section is_not_empty
3937 then
3938 case "${wf_name}" in
3939 *.${wf_section}*)
3940 s='yes';
3943 s='';
3944 wf_section='';
3946 esac
3947 if obj s is_yes
3948 then
3949 wf_name="$(echo1 ${wf_name} | sed -e '
3950 s/^\(.*\)\.'${wf_section}'.*$/\1/
3951 ')";
3955 # traditional man style; grep the line containing `.TH' macro, if any
3956 wf_res="$(cat_z "$1" | sed -e '
3957 /'"${wf_dot}"'TH /p
3959 ')";
3960 exit_test;
3961 if obj wf_res is_not_empty
3962 then # traditional man style
3963 # get the first line after the first `.SH' macro, by
3964 # - delete up to first .SH;
3965 # - print all lines before the next .SH;
3966 # - quit.
3967 wf_res="$(cat_z "$1" | sed -n -e '
3968 1,/'"${wf_dot}"'SH/d
3969 /'"${wf_dot}"'SH/q
3971 ')";
3973 if obj wf_section is_not_empty
3974 then
3975 case "${wf_res}" in
3976 ${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*)
3977 s='yes';
3980 s='';
3982 esac;
3983 if obj s is_yes
3984 then
3985 wf_res="$(obj wf_res echo1 | sed -e '
3986 s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/
3987 ')";
3990 obj wf_res echo1;
3991 echo;
3992 eval ${_UNSET} wf_arg;
3993 eval ${_UNSET} wf_dot;
3994 eval ${_UNSET} wf_name;
3995 eval ${_UNSET} wf_res;
3996 eval ${_UNSET} wf_section;
3997 eval "${return_ok}";
4000 # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
4001 wf_res="$(cat_z "$1" | sed -n -e '/'"${wf_dot}"'Nd /s///p')";
4002 exit_test;
4003 if obj wf_res is_not_empty
4004 then # BSD doc style
4005 if obj wf_section is_not_empty
4006 then
4007 wf_res="$(obj wf_res echo1 | sed -n -e '
4008 s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p
4009 ')";
4011 obj wf_res echo1;
4012 echo;
4013 eval ${_UNSET} wf_arg;
4014 eval ${_UNSET} wf_dot;
4015 eval ${_UNSET} wf_name;
4016 eval ${_UNSET} wf_res;
4017 eval ${_UNSET} wf_section;
4018 eval "${return_ok}";
4020 echo1 'is not a man page';
4021 echo;
4022 eval ${_UNSET} wf_arg;
4023 eval ${_UNSET} wf_dot;
4024 eval ${_UNSET} wf_name;
4025 eval ${_UNSET} wf_res;
4026 eval ${_UNSET} wf_section;
4027 eval "${return_bad}";
4031 ########################################################################
4032 # whatis_filespec ()
4034 # Print the filespec name as .SH to the temporary cat file.
4036 whatis_filespec()
4038 func_check whatis_filespec '=' 0 "$@";
4039 if obj _OPT_WHATIS is_yes
4040 then
4041 eval to_tmp_line \
4042 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
4043 exit_test;
4045 eval "${return_ok}";
4049 ########################################################################
4050 # whatis_header ()
4052 # Print the whatis header to the temporary cat file.
4054 whatis_header()
4056 func_check whatis_header '=' 0 "$@";
4057 if obj _OPT_WHATIS is_yes
4058 then
4059 to_tmp_line '.TH GROFFER WHATIS';
4061 eval "${return_ok}";
4065 ########################################################################
4066 # where_is (<program>)
4068 # Output path of a program if in $PATH.
4070 # Arguments : >=1 (empty allowed)
4071 # more args are ignored, this allows to specify progs with arguments
4072 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
4074 # Variable prefix: w
4076 where_is()
4078 func_check where_is '>=' 1 "$@";
4079 w_arg="$1";
4080 if obj w_arg is_empty
4081 then
4082 eval ${_UNSET} w_arg;
4083 eval "${return_bad}";
4085 case "${w_arg}" in
4087 eval ${_UNSET} w_arg;
4088 eval ${_UNSET} w_file;
4089 if test -f "${w_arg}" && test -x "${w_arg}"
4090 then
4091 eval "${return_ok}";
4092 else
4093 eval "${return_bad}";
4096 esac;
4097 eval set x "$(path_split "${PATH}")";
4098 exit_test;
4099 shift;
4100 for p
4102 case "$p" in
4103 */) w_file=${p}${w_arg}; ;;
4104 *) w_file=${p}/${w_arg}; ;;
4105 esac;
4106 if test -f "${w_file}" && test -x "${w_file}"
4107 then
4108 obj w_file echo1;
4109 eval ${_UNSET} w_arg;
4110 eval ${_UNSET} w_file;
4111 eval "${return_ok}";
4113 done;
4114 eval ${_UNSET} w_arg;
4115 eval ${_UNSET} w_file;
4116 eval "${return_bad}";
4120 ########################################################################
4121 # main* Functions
4122 ########################################################################
4124 # The main area contains the following parts:
4125 # - main_init(): initialize temporary files and set exit trap
4126 # - main_parse_MANOPT(): parse $MANOPT
4127 # - main_parse_args(): argument parsing
4128 # - main_set_mode (): determine the display mode
4129 # - main_do_fileargs(): process filespec arguments
4130 # - main_set_resources(): setup X resources
4131 # - main_display(): do the displaying
4132 # - main(): the main function that calls all main_*()
4135 #######################################################################
4136 # main_init ()
4138 # set exit trap and create temporary files
4140 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
4142 # Variable prefix: mi
4144 main_init()
4146 func_check main_init = 0 "$@";
4147 # call clean_up() on shell termination.
4148 trap_set;
4150 # create temporary directory
4151 umask 0022;
4152 _TMP_DIR='';
4153 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
4154 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
4156 mi_dir="$d";
4157 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
4158 obj mi_dir is_not_writable
4159 then
4160 continue;
4163 case "${mi_dir}" in
4165 _TMP_DIR="${mi_dir}";
4168 _TMP_DIR="${mi_dir}"'/';
4170 esac;
4171 _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}";
4172 if obj _TMP_DIR rm_tree
4173 then
4175 else
4176 mi_tdir_="${_TMP_DIR}"_;
4177 mi_n=1;
4178 mi_tdir_n="${mi_tdir_}${mi_n}";
4179 while obj mi_tdir_n is_existing
4181 if obj mi_tdir_n rm_tree
4182 then
4183 # directory could not be removed
4184 mi_n="$(expr "${mi_n}" + 1)";
4185 mi_tdir_n="${mi_tdir_}${mi_n}";
4186 continue;
4188 done;
4189 _TMP_DIR="${mi_tdir_n}";
4191 eval mkdir "${_TMP_DIR}";
4192 if is_not_equal "$?" 0
4193 then
4194 obj _TMP_DIR rm_tree;
4195 _TMP_DIR='';
4196 continue;
4198 if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable
4199 then
4200 # $_TMP_DIR can now be used as temporary directory
4201 break;
4203 obj _TMP_DIR rm_tree;
4204 _TMP_DIR='';
4205 continue;
4206 done;
4207 if obj _TMP_DIR is_empty
4208 then
4209 error "main_init: \
4210 Couldn't create a directory for storing temporary files.";
4212 if obj _DEBUG_PRINT_TMPDIR is_yes
4213 then
4214 echo2 "temporary directory: ${_TMP_DIR}";
4217 _TMP_CAT="$(tmp_create groffer_cat)";
4218 _TMP_STDIN="$(tmp_create groffer_input)";
4219 exit_test;
4221 eval ${_UNSET} mi_dir;
4222 eval ${_UNSET} mi_n;
4223 eval ${_UNSET} mi_tdir_;
4224 eval ${_UNSET} mi_tdir_n;
4225 eval "${return_ok}";
4226 } # main_init()
4229 ########################################################################
4230 # main_parse_MANOPT ()
4232 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
4233 # string; found man arguments can be overwritten by the command line.
4235 # Globals:
4236 # in: $MANOPT, $_OPTS_MANOPT_*
4237 # out: $_MANOPT_*
4239 # Variable prefix: mpm
4241 main_parse_MANOPT()
4243 func_check main_parse_MANOPT = 0 "$@";
4245 if obj MANOPT is_not_empty
4246 then
4247 # Delete leading and final spaces
4248 MANOPT="$(echo1 "${MANOPT}" | sed -e '
4249 s/^'"${_SPACE_SED}"'*//
4250 s/'"${_SPACE_SED}"'*$//
4251 ')";
4252 exit_test;
4254 if obj MANOPT is_empty
4255 then
4256 eval "${return_ok}";
4259 mpm_list='';
4260 # add arguments in $MANOPT by mapping them to groffer options
4261 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
4262 exit_test;
4263 shift;
4264 until test "$#" -le 0 || is_equal "$1" '--'
4266 mpm_opt="$1";
4267 shift;
4268 case "${mpm_opt}" in
4269 -7|--ascii)
4270 list_append mpm_list '--ascii';
4272 -a|--all)
4273 list_append mpm_list '--all';
4275 -c|--catman)
4276 do_nothing;
4277 shift;
4279 -d|--debug)
4280 do_nothing;
4282 -D|--default)
4283 # undo all man options so far
4284 mpm_list='';
4286 -e|--extension)
4287 list_append mpm_list '--extension';
4288 shift;
4290 -f|--whatis)
4291 list_append mpm_list '--whatis';
4292 shift;
4294 -h|--help)
4295 do_nothing;
4296 shift;
4298 -k|--apropos)
4299 # groffer's --apropos takes an argument, but man's does not, so
4300 do_nothing;
4302 -l|--local-file)
4303 do_nothing;
4305 -L|--locale)
4306 list_append mpm_list '--locale' "$1";
4307 shift;
4309 -m|--systems)
4310 list_append mpm_list '--systems' "$1";
4311 shift;
4313 -M|--manpath)
4314 list_append mpm_list '--manpath' "$1";
4315 shift;
4317 -p|--preprocessor)
4318 do_nothing;
4319 shift;
4321 -P|--pager)
4322 list_append mpm_list '--pager' "$1";
4323 shift;
4325 -r|--prompt)
4326 do_nothing;
4327 shift;
4329 -S|--sections)
4330 list_append mpm_list '--sections' "$1";
4331 shift;
4333 -t|--troff)
4334 do_nothing;
4335 shift;
4337 -T|--device)
4338 list_append mpm_list '-T' "$1";
4339 shift;
4341 -u|--update)
4342 do_nothing;
4343 shift;
4345 -V|--version)
4346 do_nothing;
4348 -w|--where|--location)
4349 list_append mpm_list '--location';
4351 -Z|--ditroff)
4352 do_nothing;
4354 # ignore all other options
4355 esac;
4356 done;
4358 # prepend $mpm_list to the command line
4359 if obj mpm_list is_not_empty
4360 then
4361 eval set x "${mpm_list}" '"$@"';
4362 shift;
4365 eval ${_UNSET} mpm_list;
4366 eval ${_UNSET} mpm_opt;
4367 eval "${return_ok}";
4368 } # main_parse_MANOPT()
4371 ########################################################################
4372 # main_parse_args (<command_line_args>*)
4374 # Parse arguments; process options and filespec parameters
4376 # Arguments: pass the command line arguments unaltered.
4377 # Globals:
4378 # in: $_OPTS_*
4379 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
4381 # Variable prefix: mpa
4383 main_parse_args()
4385 func_check main_parse_args '>=' 0 "$@";
4386 _ALL_PARAMS="$(list_from_cmdline _OPTS_CMDLINE "$@")";
4387 exit_test;
4388 if obj _DEBUG_PRINT_PARAMS is_yes
4389 then
4390 echo2 "parameters: ${_ALL_PARAMS}";
4392 eval set x "${_ALL_PARAMS}";
4393 shift;
4395 # By the call of `eval', unnecessary quoting was removed. So the
4396 # positional shell parameters ($1, $2, ...) are now guaranteed to
4397 # represent an option or an argument to the previous option, if any;
4398 # then a `--' argument for separating options and
4399 # parameters; followed by the filespec parameters if any.
4401 # Note, the existence of arguments to options has already been checked.
4402 # So a check for `$#' or `--' should not be done for arguments.
4404 until test "$#" -le 0 || is_equal "$1" '--'
4406 mpa_opt="$1"; # $mpa_opt is fed into the option handler
4407 shift;
4408 case "${mpa_opt}" in
4409 -h|--help)
4410 usage;
4411 leave;
4413 -Q|--source) # output source code (`Quellcode').
4414 _OPT_MODE='source';
4416 -T|--device|--troff-device) # device; arg
4417 _OPT_DEVICE="$1";
4418 _check_device_with_mode;
4419 shift;
4421 -v|--version)
4422 version;
4423 leave;
4426 _OPT_V='yes';
4428 -Z|--ditroff|--intermediate-output) # groff intermediate output
4429 _OPT_Z='yes';
4432 if is_X
4433 then
4434 _OPT_MODE=X;
4438 # delete leading `-'
4439 mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')";
4440 exit_test;
4441 if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}"
4442 then
4443 list_append _ADDOPTS_GROFF "${mpa_opt}";
4444 elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}"
4445 then
4446 list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
4447 shift;
4448 else
4449 error "main_parse_args(): Unknown option : \`$1'";
4452 --all)
4453 _OPT_ALL='yes';
4455 --apropos) # run `apropos'
4456 _OPT_APROPOS='yes';
4457 _APROPOS_SECTIONS='';
4458 _OPT_WHATIS='no';
4460 --apropos-data) # run `apropos' for data sections
4461 _OPT_APROPOS='yes';
4462 _APROPOS_SECTIONS='457';
4463 _OPT_WHATIS='no';
4465 --apropos-devel) # run `apropos' for development sections
4466 _OPT_APROPOS='yes';
4467 _APROPOS_SECTIONS='239';
4468 _OPT_WHATIS='no';
4470 --apropos-progs) # run `apropos' for program sections
4471 _OPT_APROPOS='yes';
4472 _APROPOS_SECTIONS='168';
4473 _OPT_WHATIS='no';
4475 --ascii)
4476 list_append _ADDOPTS_GROFF '-mtty-char';
4477 if obj _OPT_MODE is_empty
4478 then
4479 _OPT_MODE='text';
4482 --auto) # the default automatic mode
4483 _OPT_MODE='';
4485 --bd) # border color for viewers, arg;
4486 _OPT_BD="$1";
4487 shift;
4489 --bg|--backgroud) # background color for viewers, arg;
4490 _OPT_BG="$1";
4491 shift;
4493 --bw) # border width for viewers, arg;
4494 _OPT_BW="$1";
4495 shift;
4497 --debug|--debug-all|--debug-keep|--debug-lm|--debug-params|\
4498 --debug-shell|--debug-stacks|--debug-tmpdir|--debug-user)
4499 # debug is handled at the beginning
4502 --default) # reset variables to default
4503 reset;
4505 --default-modes) # sequence of modes in auto mode; arg
4506 _OPT_DEFAULT_MODES="$1";
4507 shift;
4509 --display) # set X display, arg
4510 _OPT_DISPLAY="$1";
4511 shift;
4513 --do-nothing)
4514 _OPT_DO_NOTHING='yes';
4516 --dvi)
4517 if is_X
4518 then
4519 _OPT_MODE='dvi';
4522 --dvi-viewer) # viewer program for dvi mode; arg
4523 _VIEWER_TERMINAL='no';
4524 _OPT_VIEWER_DVI="$1";
4525 shift;
4527 --dvi-viewer-tty) # viewer program for dvi mode in tty; arg
4528 _VIEWER_TERMINAL='yes';
4529 _OPT_VIEWER_DVI="$1";
4530 shift;
4532 --extension) # the extension for man pages, arg
4533 _OPT_EXTENSION="$1";
4534 shift;
4536 --fg|--foreground) # foreground color for viewers, arg;
4537 _OPT_FG="$1";
4538 shift;
4540 --fn|--font) # set font for viewers, arg;
4541 _OPT_FN="$1";
4542 shift;
4544 --geometry) # window geometry for viewers, arg;
4545 _OPT_GEOMETRY="$1";
4546 shift;
4548 --groff)
4549 _OPT_MODE='groff';
4551 --html|--www) # display with web browser
4552 _OPT_MODE=html;
4554 --html-viewer|--www-viewer) # viewer program for html mode; arg
4555 _VIEWER_TERMINAL='no';
4556 _OPT_VIEWER_HTML="$1";
4557 shift;
4559 --html-viewer-tty|--www-viewer-tty) # viewer for html mode in tty; arg
4560 _VIEWER_TERMINAL='yes';
4561 _OPT_VIEWER_HTML="$1";
4562 shift;
4564 --iconic) # start viewers as icons
4565 _OPT_ICONIC='yes';
4567 --locale) # set language for man pages, arg
4568 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
4569 _OPT_LANG="$1";
4570 shift;
4572 --local-file) # force local files; same as `--no-man'
4573 _MAN_FORCE='no';
4574 _MAN_ENABLE='no';
4576 --location|--where) # print file locations to stderr
4577 _OPT_LOCATION='yes';
4579 --man) # force all file params to be man pages
4580 _MAN_ENABLE='yes';
4581 _MAN_FORCE='yes';
4583 --manpath) # specify search path for man pages, arg
4584 # arg is colon-separated list of directories
4585 _OPT_MANPATH="$1";
4586 shift;
4588 --mode) # display mode
4589 mpa_arg="$1";
4590 shift;
4591 case "${mpa_arg}" in
4592 auto|'') # search mode automatically among default
4593 _OPT_MODE='';
4595 groff) # pass input to plain groff
4596 _OPT_MODE='groff';
4598 html|www) # display with a web browser
4599 _OPT_MODE='html';
4601 dvi) # display with xdvi viewer
4602 if is_X
4603 then
4604 _OPT_MODE='dvi';
4607 pdf) # display with PDF viewer
4608 if is_X
4609 then
4610 _OPT_MODE='pdf';
4613 ps) # display with Postscript viewer
4614 if is_X
4615 then
4616 _OPT_MODE='ps';
4619 text) # output on terminal
4620 _OPT_MODE='text';
4622 tty) # output on terminal
4623 _OPT_MODE='tty';
4625 X|x) # output on X roff viewer
4626 if is_X
4627 then
4628 _OPT_MODE='x';
4631 Q|source) # display source code
4632 _OPT_MODE="source";
4635 error "main_parse_args(): unknown mode ${mpa_arg}";
4637 esac;
4639 --no-location) # disable former call to `--location'
4640 _OPT_LOCATION='yes';
4642 --no-man) # disable search for man pages
4643 # the same as --local-file
4644 _MAN_FORCE='no';
4645 _MAN_ENABLE='no';
4647 --no-special) # disable some special former calls
4648 _OPT_ALL='no'
4649 _OPT_APROPOS='no'
4650 _OPT_WHATIS='no'
4652 --pager|--tty-viewer|--tty-viewer-tty)
4653 # set paging program for tty mode, arg
4654 _VIEWER_TERMINAL='yes';
4655 _OPT_PAGER="$1";
4656 shift;
4658 --pdf)
4659 if is_X
4660 then
4661 _OPT_MODE='pdf';
4664 --pdf-viewer) # viewer program for ps mode; arg
4665 _VIEWER_TERMINAL='no';
4666 _OPT_VIEWER_PDF="$1";
4667 shift;
4669 --pdf-viewer-tty) # viewer program for ps mode in tty; arg
4670 _VIEWER_TERMINAL='yes';
4671 _OPT_VIEWER_PDF="$1";
4672 shift;
4674 --print) # for argument test
4675 echo2 "$1";
4676 shift;
4678 --ps)
4679 if is_X
4680 then
4681 _OPT_MODE='ps';
4684 --ps-viewer) # viewer program for ps mode; arg
4685 _VIEWER_TERMINAL='no';
4686 _OPT_VIEWER_PS="$1";
4687 shift;
4689 --ps-viewer-tty) # viewer program for ps mode in tty; arg
4690 _VIEWER_TERMINAL='yes';
4691 _OPT_VIEWER_PS="$1";
4692 shift;
4694 --resolution) # set resolution for X devices, arg
4695 mpa_arg="$1";
4696 shift;
4697 case "${mpa_arg}" in
4698 75|75dpi)
4699 mpa_dpi=75;
4701 100|100dpi)
4702 mpa_dpi=100;
4705 error "main_parse_args(): \
4706 only resoutions of 75 or 100 dpi are supported";
4708 esac;
4709 _OPT_RESOLUTION="${mpa_dpi}";
4711 --rv)
4712 _OPT_RV='yes';
4714 --sections) # specify sections for man pages, arg
4715 # arg is colon-separated list of section names
4716 _OPT_SECTIONS="$1";
4717 shift;
4719 --shell)
4720 # already done during the first run; so ignore the argument
4721 shift;
4723 --systems) # man pages for different OS's, arg
4724 # argument is a comma-separated list
4725 _OPT_SYSTEMS="$1";
4726 shift;
4728 --text) # text mode without pager
4729 _OPT_MODE=text;
4731 --title) # title for X viewers; arg
4732 _OPT_TITLE="$1";
4733 shift;
4735 --tty) # tty mode, text with pager
4736 _OPT_MODE=tty;
4738 --text-device|--tty-device) # device for tty mode; arg
4739 _OPT_TEXT_DEVICE="$1";
4740 shift;
4742 --whatis)
4743 _OPT_WHATIS='yes';
4744 _OPT_ALL='yes';
4745 _OPT_APROPOS='no';
4747 --X|--x)
4748 if is_X
4749 then
4750 _OPT_MODE=x;
4753 --xrm) # pass X resource string, arg;
4754 list_append _OPT_XRM "$1";
4755 shift;
4757 --x-viewer|--X-viewer) # viewer program for x mode; arg
4758 _VIEWER_TERMINAL='no';
4759 _OPT_VIEWER_X="$1";
4760 shift;
4762 --x-viewer-tty|--X-viewer-tty) # viewer program for x mode in tty; arg
4763 _VIEWER_TERMINAL='yes';
4764 _OPT_VIEWER_X="$1";
4765 shift;
4768 error 'main_parse_args(): error on argument parsing : '"\`$*'";
4770 esac;
4771 done;
4772 shift; # remove `--' argument
4774 if obj _OPT_DO_NOTHING is_yes
4775 then
4776 leave;
4779 # Remaining arguments are file names (filespecs).
4780 # Save them to list $_FILEARGS
4781 if is_equal "$#" 0
4782 then # use "-" for standard input
4783 set x '-';
4784 shift;
4786 _FILEARGS='';
4787 list_append _FILEARGS "$@";
4788 if list_has _FILEARGS '-'
4789 then
4790 save_stdin;
4792 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4793 eval ${_UNSET} mpa_arg;
4794 eval ${_UNSET} mpa_dpi;
4795 eval ${_UNSET} mpa_opt;
4796 eval ${_UNSET} mpa_optchar;
4797 eval "${return_ok}";
4798 } # main_parse_args()
4801 # Called from main_parse_args() because double `case' is not possible.
4802 # Globals: $_OPT_DEVICE, $_OPT_MODE
4803 _check_device_with_mode()
4805 func_check _check_device_with_mode = 0 "$@";
4806 case "${_OPT_DEVICE}" in
4807 dvi)
4808 _OPT_MODE=dvi;
4809 eval "${return_ok}";
4811 html)
4812 _OPT_MODE=html;
4813 eval "${return_ok}";
4815 lbp|lj4)
4816 _OPT_MODE=groff;
4817 eval "${return_ok}";
4820 _OPT_MODE=ps;
4821 eval "${return_ok}";
4823 ascii|cp1047|latin1|utf8)
4824 if obj _OPT_MODE is_not_equal text
4825 then
4826 _OPT_MODE=tty; # default text mode
4828 eval "${return_ok}";
4831 _OPT_MODE=x;
4832 eval "${return_ok}";
4834 *) # unknown device, go to groff mode
4835 _OPT_MODE=groff;
4836 eval "${return_ok}";
4838 esac;
4839 eval "${return_error}";
4840 } # _check_device_with_mode() of main_parse_args()
4843 ########################################################################
4844 # main_set_mode ()
4846 # Determine the display mode.
4848 # Globals:
4849 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4850 # out: $_DISPLAY_MODE
4852 # Variable prefix: msm
4854 main_set_mode()
4856 func_check main_set_mode = 0 "$@";
4858 # set display
4859 if obj _OPT_DISPLAY is_not_empty
4860 then
4861 DISPLAY="${_OPT_DISPLAY}";
4864 if obj _OPT_V is_yes
4865 then
4866 list_append _ADDOPTS_GROFF '-V';
4868 if obj _OPT_Z is_yes
4869 then
4870 _DISPLAY_MODE='groff';
4871 list_append _ADDOPTS_GROFF '-Z';
4873 if obj _OPT_MODE is_equal 'groff'
4874 then
4875 _DISPLAY_MODE='groff';
4877 if obj _DISPLAY_MODE is_equal 'groff'
4878 then
4879 eval ${_UNSET} msm_modes;
4880 eval ${_UNSET} msm_viewer;
4881 eval ${_UNSET} msm_viewers;
4882 eval "${return_ok}";
4885 if obj _OPT_MODE is_equal 'source'
4886 then
4887 _DISPLAY_MODE='source';
4888 eval ${_UNSET} msm_modes;
4889 eval ${_UNSET} msm_viewer;
4890 eval ${_UNSET} msm_viewers;
4891 eval "${return_ok}";
4894 case "${_OPT_MODE}" in
4895 '') # automatic mode
4896 case "${_OPT_DEVICE}" in
4898 if is_not_X
4899 then
4900 error_user "no X display found for device ${_OPT_DEVICE}";
4902 _DISPLAY_MODE='x';
4903 eval ${_UNSET} msm_modes;
4904 eval ${_UNSET} msm_viewer;
4905 eval ${_UNSET} msm_viewers;
4906 eval "${return_ok}";
4908 ascii|cp1047|latin1|utf8)
4909 if obj _DISPLAY_MODE is_not_equal 'text'
4910 then
4911 _DISPLAY_MODE='tty';
4913 eval ${_UNSET} msm_modes;
4914 eval ${_UNSET} msm_viewer;
4915 eval ${_UNSET} msm_viewers;
4916 eval "${return_ok}";
4918 esac;
4919 if is_not_X
4920 then
4921 _DISPLAY_MODE='tty';
4922 eval ${_UNSET} msm_modes;
4923 eval ${_UNSET} msm_viewer;
4924 eval ${_UNSET} msm_viewers;
4925 eval "${return_ok}";
4928 if obj _OPT_DEFAULT_MODES is_empty
4929 then
4930 msm_modes="${_DEFAULT_MODES}";
4931 else
4932 msm_modes="${_OPT_DEFAULT_MODES}";
4935 text)
4936 _DISPLAY_MODE='text';
4937 eval ${_UNSET} msm_modes;
4938 eval ${_UNSET} msm_viewer;
4939 eval ${_UNSET} msm_viewers;
4940 eval "${return_ok}";
4942 tty)
4943 _DISPLAY_MODE='tty';
4944 eval ${_UNSET} msm_modes;
4945 eval ${_UNSET} msm_viewer;
4946 eval ${_UNSET} msm_viewers;
4947 eval "${return_ok}";
4949 html)
4950 _DISPLAY_MODE='html';
4951 msm_modes="${_OPT_MODE}";
4953 *) # display mode was given
4954 if is_not_X
4955 then
4956 error_user "You must be in X Window for ${_OPT_MODE} mode.";
4958 msm_modes="${_OPT_MODE}";
4960 esac;
4962 # only viewer modes are left
4963 eval set x "$(list_from_split "${msm_modes}" ',')";
4964 exit_test;
4965 shift;
4966 while test "$#" -gt 0
4968 m="$1";
4969 shift;
4970 case "$m" in
4971 dvi)
4972 if obj _OPT_VIEWER_DVI is_not_empty
4973 then
4974 msm_viewer="${_OPT_VIEWER_DVI}";
4975 else
4976 msm_viewer="$(_get_first_prog "$_VIEWER_DVI}")";
4977 exit_test;
4979 if obj msm_viewer is_empty
4980 then
4981 error 'No viewer for dvi mode available.';
4983 if is_not_equal "$?" 0
4984 then
4985 continue;
4987 _DISPLAY_PROG="${msm_viewer}";
4988 _DISPLAY_MODE="dvi";
4989 eval ${_UNSET} msm_modes;
4990 eval ${_UNSET} msm_viewer;
4991 eval ${_UNSET} msm_viewers;
4992 eval "${return_ok}";
4994 html)
4995 if obj _OPT_VIEWER_HTML is_not_empty
4996 then
4997 msm_viewer="${_OPT_VIEWER_HTML}";
4998 else
4999 if is_X
5000 then
5001 msm_viewers="${_VIEWER_HTML_X}";
5002 else
5003 msm_viewers="${_VIEWER_HTML_TTY}";
5005 msm_viewer="$(_get_first_prog "${msm_viewers}")";
5006 exit_test;
5008 if obj msm_viewer is_empty
5009 then
5010 error 'No viewer for html mode available.';
5012 if is_not_equal "$?" 0
5013 then
5014 continue;
5016 _DISPLAY_PROG="${msm_viewer}";
5017 _DISPLAY_MODE=html;
5018 eval ${_UNSET} msm_modes;
5019 eval ${_UNSET} msm_viewer;
5020 eval ${_UNSET} msm_viewers;
5021 eval "${return_ok}";
5023 pdf)
5024 if obj _OPT_VIEWER_PDF is_not_empty
5025 then
5026 msm_viewer="${_OPT_VIEWER_PDF}";
5027 else
5028 msm_viewer="$(_get_first_prog "${_VIEWER_PDF}")";
5029 exit_test;
5031 if obj msm_viewer is_empty
5032 then
5033 error 'No viewer for pdf mode available.';
5035 if is_not_equal "$?" 0
5036 then
5037 continue;
5039 _DISPLAY_PROG="${msm_viewer}";
5040 _DISPLAY_MODE="pdf";
5041 eval ${_UNSET} msm_modes;
5042 eval ${_UNSET} msm_viewer;
5043 eval ${_UNSET} msm_viewers;
5044 eval "${return_ok}";
5047 if obj _OPT_VIEWER_PS is_not_empty
5048 then
5049 msm_viewer="${_OPT_VIEWER_PS}";
5050 else
5051 msm_viewer="$(_get_first_prog "${_VIEWER_PS}")";
5052 exit_test;
5054 if obj msm_viewer is_empty
5055 then
5056 error 'No viewer for ps mode available.';
5058 if is_not_equal "$?" 0
5059 then
5060 continue;
5062 _DISPLAY_PROG="${msm_viewer}";
5063 _DISPLAY_MODE="ps";
5064 eval ${_UNSET} msm_modes;
5065 eval ${_UNSET} msm_viewer;
5066 eval ${_UNSET} msm_viewers;
5067 eval "${return_ok}";
5069 text)
5070 _DISPLAY_MODE='text';
5071 eval ${_UNSET} msm_modes;
5072 eval ${_UNSET} msm_viewer;
5073 eval ${_UNSET} msm_viewers;
5074 eval "${return_ok}";
5076 tty)
5077 _DISPLAY_MODE='tty';
5078 eval ${_UNSET} msm_modes;
5079 eval ${_UNSET} msm_viewer;
5080 eval ${_UNSET} msm_viewers;
5081 eval "${return_ok}";
5084 if obj _OPT_VIEWER_X is_not_empty
5085 then
5086 msm_viewer="${_OPT_VIEWER_X}";
5087 else
5088 msm_viewer="$(_get_first_prog "${_VIEWER_X}")";
5089 exit_test;
5091 if obj msm_viewer is_empty
5092 then
5093 error 'No viewer for x mode available.';
5095 if is_not_equal "$?" 0
5096 then
5097 continue;
5099 _DISPLAY_PROG="${msm_viewer}";
5100 _DISPLAY_MODE='x';
5101 eval ${_UNSET} msm_modes;
5102 eval ${_UNSET} msm_viewer;
5103 eval ${_UNSET} msm_viewers;
5104 eval "${return_ok}";
5107 _DISPLAY_MODE='X';
5108 eval ${_UNSET} msm_modes;
5109 eval ${_UNSET} msm_viewer;
5110 eval ${_UNSET} msm_viewers;
5111 eval "${return_ok}";
5113 esac;
5114 done;
5115 eval ${_UNSET} msm_modes;
5116 eval ${_UNSET} msm_viewer;
5117 eval ${_UNSET} msm_viewers;
5118 error_user "No suitable display mode found.";
5119 } # main_set_mode()
5122 # _get_first_prog (<proglist>)
5124 # Retrieve first argument that represents an existing program in $PATH.
5125 # Local function for main_set_mode().
5127 # Arguments: 1; a comma-separated list of commands (with options),
5128 # like $_VIEWER_*.
5130 # Return : `1' if none found, `0' if found.
5131 # Output : the argument that succeded.
5133 # Variable prefix: _gfp
5135 _get_first_prog()
5137 if is_equal "$#" 0
5138 then
5139 error "_get_first_prog() needs 1 argument.";
5141 if is_empty "$1"
5142 then
5143 return "${_BAD}";
5145 eval set x "$(list_from_split "$1" ',')";
5146 exit_test;
5147 shift;
5148 for i
5150 _gfp_i="$i";
5151 if obj _gfp_i is_empty
5152 then
5153 continue;
5155 if eval is_prog "$(get_first_essential ${_gfp_i})"
5156 then
5157 exit_test;
5158 obj _gfp_i echo1;
5159 eval ${_UNSET} _gfp_i;
5160 return "${_GOOD}";
5162 done;
5163 eval ${_UNSET} _gfp_i;
5164 return "${_BAD}";
5165 } # _get_first_prog() of main_set_mode()
5168 #######################################################################
5169 # main_do_fileargs ()
5171 # Process filespec arguments in $_FILEARGS.
5173 # Globals:
5174 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
5176 # Variable prefix: mdfa
5178 main_do_fileargs()
5180 func_check main_do_fileargs = 0 "$@";
5181 special_setup;
5182 eval set x "${_FILEARGS}";
5183 shift;
5184 eval ${_UNSET} _FILEARGS;
5185 # temporary storage of all input to $_TMP_CAT
5186 while test "$#" -ge 2
5188 # test for `s name' arguments, with `s' a 1-char standard section
5189 mdfa_filespec="$1";
5190 _FILESPEC_ARG="$1";
5191 shift;
5192 case "${mdfa_filespec}" in
5194 continue;
5196 '-')
5197 special_filespec;
5198 if obj _OPT_APROPOS is_yes
5199 then
5200 continue;
5202 register_file '-'
5203 continue;
5206 if obj _OPT_APROPOS is_yes
5207 then
5208 special_filespec;
5209 continue;
5211 if list_has_not _MAN_AUTO_SEC_LIST "${mdfa_filespec}"
5212 then
5213 special_filespec;
5214 do_filearg "${mdfa_filespec}"
5215 continue;
5217 mdfa_name="$1";
5218 _FILESPEC_ARG="${_FILESPEC_ARG} $1";
5219 special_filespec;
5220 case "${mdfa_name}" in
5221 */*|man:*|*\(*\)|*."${mdfa_filespec}")
5222 do_filearg "${mdfa_filespec}"
5223 continue;
5225 esac;
5226 shift;
5227 if do_filearg "man:${mdfa_name}(${mdfa_filespec})"
5228 then
5229 continue;
5230 else
5231 do_filearg "${mdfa_filespec}"
5232 continue;
5236 special_filespec;
5237 if obj _OPT_APROPOS is_yes
5238 then
5239 continue;
5241 do_filearg "${mdfa_filespec}"
5242 continue;
5244 esac;
5245 done; # end of `s name' test
5246 while test "$#" -gt 0
5248 mdfa_filespec="$1";
5249 _FILESPEC_ARG="$1";
5250 shift;
5251 special_filespec;
5252 if obj _OPT_APROPOS is_yes
5253 then
5254 continue;
5256 do_filearg "${mdfa_filespec}"
5257 done;
5258 obj _TMP_STDIN rm_file_with_debug;
5259 eval ${_UNSET} mdfa_filespec;
5260 eval ${_UNSET} mdfa_name;
5261 eval "${return_ok}";
5262 } # main_do_fileargs()
5265 ########################################################################
5266 # main_set_resources ()
5268 # Determine options for setting X resources with $_DISPLAY_PROG.
5270 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
5272 # Variable prefix: msr
5274 main_set_resources()
5276 func_check main_set_resources = 0 "$@";
5277 # $msr_prog viewer program
5278 # $msr_rl resource list
5279 msr_title="$(get_first_essential \
5280 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
5281 exit_test;
5282 _OUTPUT_FILE_NAME='';
5283 eval set x "${msr_title}";
5284 shift;
5285 until is_equal "$#" 0
5287 msr_n="$1";
5288 case "${msr_n}" in
5290 continue;
5293 msr_n="$(echo1 "$1" | sed -e 's/^,,*//')";
5294 exit_test;
5296 esac
5297 if obj msr_n is_empty
5298 then
5299 continue;
5301 if obj _OUTPUT_FILE_NAME is_not_empty
5302 then
5303 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
5305 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
5306 shift;
5307 done;
5308 case "${_OUTPUT_FILE_NAME}" in
5310 _OUTPUT_FILE_NAME='-';
5313 error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
5315 esac;
5316 _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
5318 if obj _DISPLAY_PROG is_empty
5319 then # for example, for groff mode
5320 _DISPLAY_ARGS='';
5321 eval ${_UNSET} msr_n;
5322 eval ${_UNSET} msr_prog;
5323 eval ${_UNSET} msr_rl;
5324 eval ${_UNSET} msr_title;
5325 eval "${return_ok}";
5328 eval set x "${_DISPLAY_PROG}";
5329 shift;
5330 msr_prog="$(base_name "$1")";
5331 exit_test;
5332 shift;
5333 if test $# != 0
5334 then
5335 if obj _DISPLAY_PROG is_empty
5336 then
5337 _DISPLAY_ARGS="$*";
5338 else
5339 _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}";
5342 msr_rl='';
5343 if obj _OPT_BD is_not_empty
5344 then
5345 case "${msr_prog}" in
5346 ghostview|gv|gxditview|xditview|xdvi)
5347 list_append msr_rl '-bd' "${_OPT_BD}";
5349 esac;
5351 if obj _OPT_BG is_not_empty
5352 then
5353 case "${msr_prog}" in
5354 ghostview|gv|gxditview|xditview|xdvi)
5355 list_append msr_rl '-bg' "${_OPT_BG}";
5357 kghostview)
5358 list_append msr_rl '--bg' "${_OPT_BG}";
5360 xpdf)
5361 list_append msr_rl '-papercolor' "${_OPT_BG}";
5363 esac;
5365 if obj _OPT_BW is_not_empty
5366 then
5367 case "${msr_prog}" in
5368 ghostview|gv|gxditview|xditview|xdvi)
5369 _list_append msr_rl '-bw' "${_OPT_BW}";
5371 esac;
5373 if obj _OPT_FG is_not_empty
5374 then
5375 case "${msr_prog}" in
5376 ghostview|gv|gxditview|xditview|xdvi)
5377 list_append msr_rl '-fg' "${_OPT_FG}";
5379 kghostview)
5380 list_append msr_rl '--fg' "${_OPT_FG}";
5382 esac;
5384 if is_not_empty "${_OPT_FN}"
5385 then
5386 case "${msr_prog}" in
5387 ghostview|gv|gxditview|xditview|xdvi)
5388 list_append msr_rl '-fn' "${_OPT_FN}";
5390 kghostview)
5391 list_append msr_rl '--fn' "${_OPT_FN}";
5393 esac;
5395 if is_not_empty "${_OPT_GEOMETRY}"
5396 then
5397 case "${msr_prog}" in
5398 ghostview|gv|gxditview|xditview|xdvi|xpdf)
5399 list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
5401 kghostview)
5402 list_append msr_rl '--geometry' "${_OPT_GEOMETRY}";
5404 esac;
5406 if is_empty "${_OPT_RESOLUTION}"
5407 then
5408 _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
5409 case "${msr_prog}" in
5410 gxditview|xditview)
5411 list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
5413 xpdf)
5414 case "${_DEFAULT_RESOLUTION}" in
5416 # 72dpi is '100'
5417 list_append msr_rl '-z' '104';
5419 100)
5420 list_append msr_rl '-z' '139';
5422 esac;
5424 esac;
5425 else
5426 case "${msr_prog}" in
5427 ghostview|gv|gxditview|xditview|xdvi)
5428 list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
5430 xpdf)
5431 case "${_OPT_RESOLUTION}" in
5433 list_append msr_rl '-z' '104';
5434 # '100' corresponds to 72dpi
5436 100)
5437 list_append msr_rl '-z' '139';
5439 esac;
5441 esac;
5443 if is_yes "${_OPT_ICONIC}"
5444 then
5445 case "${msr_prog}" in
5446 ghostview|gv|gxditview|xditview|xdvi)
5447 list_append msr_rl '-iconic';
5449 esac;
5451 if is_yes "${_OPT_RV}"
5452 then
5453 case "${msr_prog}" in
5454 ghostview|gv|gxditview|xditview|xdvi)
5455 list_append msr_rl '-rv';
5457 esac;
5459 if is_not_empty "${_OPT_XRM}"
5460 then
5461 case "${msr_prog}" in
5462 ghostview|gv|gxditview|xditview|xdvi|xpdf)
5463 eval set x "${_OPT_XRM}";
5464 shift;
5465 for i
5467 list_append msr_rl '-xrm' "$i";
5468 done;
5470 esac;
5472 if is_not_empty "${msr_title}"
5473 then
5474 case "${msr_prog}" in
5475 gxditview|xditview)
5476 list_append msr_rl '-title' "${msr_title}";
5478 esac;
5480 _DISPLAY_ARGS="${msr_rl}";
5481 eval ${_UNSET} msr_n;
5482 eval ${_UNSET} msr_prog;
5483 eval ${_UNSET} msr_rl;
5484 eval ${_UNSET} msr_title;
5485 eval "${return_ok}";
5486 } # main_set_resources
5489 ########################################################################
5490 # main_display ()
5492 # Do the actual display of the whole thing.
5494 # Globals:
5495 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
5496 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
5497 # $_TMP_CAT, $_OPT_PAGER, $PAGER, $_MANOPT_PAGER,
5498 # $_OUTPUT_FILE_NAME
5500 # Variable prefix: md
5502 main_display()
5504 func_check main_display = 0 "$@";
5506 export md_addopts;
5507 export md_groggy;
5508 export md_modefile;
5510 if obj _TMP_CAT is_non_empty_file
5511 then
5512 md_modefile="${_OUTPUT_FILE_NAME}";
5513 else
5514 echo2 'groffer: empty input.';
5515 clean_up;
5516 eval ${_UNSET} md_modefile;
5517 eval "${return_ok}";
5520 # go to the temporary directory to be able to access internal data files
5521 cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1;
5523 case "${_DISPLAY_MODE}" in
5524 groff)
5525 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
5526 if obj _OPT_DEVICE is_not_empty
5527 then
5528 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
5530 md_groggy="$(tmp_cat | eval grog "${md_options}")";
5531 exit_test;
5532 _do_opt_V;
5534 obj md_modefile rm_file;
5535 mv "${_TMP_CAT}" "${md_modefile}";
5536 trap_unset;
5537 cat "${md_modefile}" | \
5539 trap_set;
5540 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
5543 text|tty)
5544 case "${_OPT_DEVICE}" in
5546 md_device="$(get_first_essential \
5547 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
5548 exit_test;
5550 ascii|cp1047|latin1|utf8)
5551 md_device="${_OPT_DEVICE}";
5554 warning "main_display(): \
5555 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5557 esac;
5558 md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
5559 md_groggy="$(tmp_cat | grog -T${md_device})";
5560 exit_test;
5561 if obj _DISPLAY_MODE is_equal 'text'
5562 then
5563 _do_opt_V;
5564 tmp_cat | eval "${md_groggy}" "${md_addopts}";
5565 else
5566 md_pager='';
5567 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
5568 'less -r -R' 'more' 'pager' 'cat'
5570 md_p="$p";
5571 if eval is_prog ${md_p}
5572 then # no "" for is_prog() allows args for $p
5573 md_pager="${md_p}";
5574 break;
5576 done;
5577 if obj md_pager is_empty
5578 then
5579 error 'main_display(): no pager program found for tty mode';
5581 _do_opt_V;
5582 tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
5583 eval "${md_pager}";
5585 clean_up;
5587 source)
5588 tmp_cat;
5589 clean_up;
5592 #### viewer modes
5594 dvi)
5595 case "${_OPT_DEVICE}" in
5596 ''|dvi) do_nothing; ;;
5598 warning "main_display(): \
5599 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
5601 esac;
5602 md_modefile="${md_modefile}".dvi;
5603 md_groggy="$(tmp_cat | grog -Tdvi)";
5604 exit_test;
5605 _do_display;
5607 html)
5608 case "${_OPT_DEVICE}" in
5609 ''|html) do_nothing; ;;
5611 warning "main_display(): \
5612 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5614 esac;
5615 md_modefile="${md_modefile}".html;
5616 md_groggy="$(tmp_cat | grog -Thtml)";
5617 exit_test;
5618 _do_display;
5620 pdf)
5621 case "${_OPT_DEVICE}" in
5622 ''|ps)
5623 do_nothing;
5626 warning "main_display(): \
5627 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5629 esac;
5630 md_groggy="$(tmp_cat | grog -Tps)";
5631 exit_test;
5632 _do_display _make_pdf;
5635 case "${_OPT_DEVICE}" in
5636 ''|ps)
5637 do_nothing;
5640 warning "main_display(): \
5641 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5643 esac;
5644 md_modefile="${md_modefile}".ps;
5645 md_groggy="$(tmp_cat | grog -Tps)";
5646 exit_test;
5647 _do_display;
5650 case "${_OPT_DEVICE}" in
5652 md_device="${_OPT_DEVICE}"
5655 case "${_OPT_RESOLUTION}" in
5656 100)
5657 md_device='X100';
5658 if obj _OPT_GEOMETRY is_empty
5659 then
5660 case "${_DISPLAY_PROG}" in
5661 gxditview|xditview)
5662 # add width of 800dpi for resolution of 100dpi to the args
5663 list_append _DISPLAY_ARGS '-geometry' '800';
5665 esac;
5669 md_device='X75-12';
5671 esac
5672 esac;
5673 md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
5674 exit_test;
5675 _do_display;
5678 case "${_OPT_DEVICE}" in
5680 md_groggy="$(tmp_cat | grog -X)";
5681 exit_test;
5683 X*|dvi|html|lbp|lj4|ps)
5684 # these devices work with
5685 md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
5686 exit_test;
5689 warning "main_display(): \
5690 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
5691 md_groggy="$(tmp_cat | grog -Z)";
5692 exit_test;
5694 esac;
5695 _do_display;
5698 error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
5700 esac;
5701 eval ${_UNSET} md_addopts;
5702 eval ${_UNSET} md_device;
5703 eval ${_UNSET} md_groggy;
5704 eval ${_UNSET} md_modefile;
5705 eval ${_UNSET} md_options;
5706 eval ${_UNSET} md_p;
5707 eval ${_UNSET} md_pager;
5708 eval "${return_ok}";
5709 } # main_display()
5712 ########################
5713 # _do_display ([<prog>])
5715 # Perform the generation of the output and view the result. If an
5716 # argument is given interpret it as a function name that is called in
5717 # the midst (actually only for `pdf').
5719 # Globals: $md_modefile, $md_groggy (from main_display())
5721 _do_display()
5723 func_check _do_display '>=' 0 "$@";
5724 _do_opt_V;
5725 if obj _DISPLAY_PROG is_empty
5726 then
5727 trap_unset;
5729 trap_set;
5730 eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}";
5732 else
5733 obj md_modefile rm_file;
5734 cat "${_TMP_CAT}" | \
5735 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
5736 if is_not_empty "$1"
5737 then
5738 eval "$1";
5740 obj _TMP_CAT rm_file_with_debug;
5741 if obj _VIEWER_TERMINAL is_yes # for programs that run on tty
5742 then
5743 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5744 else
5745 case "${_DISPLAY_PROG}" in
5746 # lynx\ *|less\ *|more\ *) # programs known to run on the terminal
5747 # eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5748 # ;;
5750 trap_unset;
5752 trap_set;
5753 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
5756 esac;
5759 eval "${return_ok}";
5760 } # _do_display() of main_display()
5763 #############
5764 # _do_opt_V ()
5766 # Check on option `-V'; if set print the corresponding output and leave.
5768 # Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG,
5769 # $_DISPLAY_ARGS, $md_groggy, $md_modefile
5771 # Variable prefix: _doV
5773 _do_opt_V()
5775 func_check _do_opt_V '=' 0 "$@";
5776 if obj _OPT_V is_yes
5777 then
5778 _OPT_V='no';
5779 echo1 "Parameters: ${_ALL_PARAMS}";
5780 echo1 "Display mode: ${_DISPLAY_MODE}";
5781 echo1 "Output file: ${md_modefile}";
5782 echo1 "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
5783 a="$(eval echo1 "'${_ADDOPTS_GROFF}'")";
5784 exit_test;
5785 echo1 "Output of grog: ${md_groggy} $a";
5786 _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")";
5787 exit_test;
5788 echo1 "groff -V: ${_doV_res}"
5789 leave;
5791 eval "${return_ok}";
5792 } # _do_opt_V() of main_display()
5795 ##############
5796 # _make_pdf ()
5798 # Transform to pdf format; for pdf mode in _do_display().
5800 # Globals: $md_modefile (from main_display())
5802 # Variable prefix: _mp
5804 _make_pdf()
5806 func_check _do_display '=' 0 "$@";
5807 _mp_psfile="${md_modefile}";
5808 md_modefile="${md_modefile}.pdf";
5809 obj md_modefile rm_file;
5810 if gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
5811 -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}"
5812 then
5814 else
5815 error '_make_pdf: could not transform into pdf format.';
5817 obj _mp_psfile rm_file_with_debug;
5818 eval ${_UNSET} _mp_psfile;
5819 eval "${return_ok}";
5820 } # _make_pdf() of main_display()
5823 ########################################################################
5824 # main (<command_line_args>*)
5826 # The main function for groffer.
5828 # Arguments:
5830 main()
5832 func_check main '>=' 0 "$@";
5833 # Do not change the sequence of the following functions!
5834 landmark '13: main_init()';
5835 main_init;
5836 landmark '14: main_parse_MANOPT()';
5837 main_parse_MANOPT;
5838 landmark '15: main_parse_args()';
5839 main_parse_args "$@";
5840 landmark '16: main_set_mode()';
5841 main_set_mode;
5842 landmark '17: main_do_fileargs()';
5843 main_do_fileargs;
5844 landmark '18: main_set_resources()';
5845 main_set_resources;
5846 landmark '19: main_display()';
5847 main_display;
5848 eval "${return_ok}";
5852 ########################################################################
5854 main "$@";