3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/groffer2.sh
6 # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
8 # Copyright (C) 2001,2002,2003,2004,2005
9 # Free Software Foundation, Inc.
10 # Written by Bernd Warken
12 # Last update: 30 July 2005
14 # This file is part of groffer, which is part of groff.
16 # groff is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2, or (at your option)
21 # groff is distributed in the hope that it will be useful, but WITHOUT
22 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 # License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with groff; see the files COPYING and LICENSE in the top
28 # directory of the groff source. If not, write to the Free Software
29 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
32 ########################################################################
36 _DEBUG
='no'; # disable debugging information
37 #_DEBUG='yes'; # enable debugging information
40 _DEBUG_LM
='no'; # disable landmark messages
41 #_DEBUG_LM='yes'; # enable landmark messages
43 export _DEBUG_KEEP_FILES
;
44 _DEBUG_KEEP_FILES
='no' # disable file keeping in temporary dir
45 _DEBUG_KEEP_FILES
='yes' # enable file keeping in temporary dir
47 # test of $* on --debug
52 _DEBUG_KEEP_FILES
='yes';
57 ########################################################################
58 # Environment Variables
59 ########################################################################
61 # Environment variables that exist only for this file start with an
62 # underscore letter. Global variables to this file are written in
63 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
64 # start with an underline and use only lower case letters and
65 # underlines, e.g. $_local_variable .
67 # [A-Z]* system variables, e.g. $MANPATH
68 # _[A-Z_]* global file variables, e.g. $_MAN_PATH
69 # _[a-z_]* temporary variables, e.g. $_manpath
71 # Due to incompatibilities of the `ash' shell, the name of loop
72 # variables in `for' must be single character
73 # [a-z] local loop variables, e.g. $i
76 ########################################################################
77 # read-only variables (global to this file)
78 ########################################################################
90 # function return values; `0' means ok; other values are error codes
99 _GOOD
='0'; # return ok
100 _BAD
='1'; # return negatively, error code `1'
101 _ERROR
='7'; # for syntax errors; no `-1' in `ash'
103 _ALL_EXIT
="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
109 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
117 return_ok
="func_pop; return ${_OK}";
118 return_good
="func_pop; return ${_GOOD}";
119 return_bad
="func_pop; return ${_BAD}";
120 return_yes
="func_pop; return ${_YES}";
121 return_no
="func_pop; return ${_NO}";
122 return_error
="func_pop; return ${_ERROR}";
123 return_var
="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
126 export _DEFAULT_MODES
;
127 _DEFAULT_MODES
='x,ps,tty';
128 export _DEFAULT_RESOLUTION
;
129 _DEFAULT_RESOLUTION
='75';
131 export _DEFAULT_TTY_DEVICE
;
132 _DEFAULT_TTY_DEVICE
='latin1';
134 # _VIEWER_* viewer programs for different modes (only X is necessary)
135 # _VIEWER_* a comma-separated list of viewer programs (with options)
136 export _VIEWER_DVI
; # viewer program for dvi mode
137 export _VIEWER_PS
; # viewer program for ps mode
138 export _VIEWER_HTML_X
; # viewer program for html mode in X
139 export _VIEWER_HTML_TTY
; # viewer program for html mode in tty
140 _VIEWER_DVI
='kdvi,xdvi,dvilx';
141 _VIEWER_PDF
='kghostview,ggv,xpdf,acroread,kpdf';
142 _VIEWER_PS
='kghostview,ggv,gv,ghostview,gs_x11,gs';
143 _VIEWER_HTML
='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
144 _VIEWER_X
='gxditview,xditview';
146 # Search automatically in standard sections `1' to `8', and in the
147 # traditional sections `9', `n', and `o'. On many systems, there
148 # exist even more sections, mostly containing a set of man pages
149 # special to a specific program package. These aren't searched for
150 # automatically, but must be specified on the command line.
151 export _MAN_AUTO_SEC
;
152 _MAN_AUTO_SEC
="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
154 export _PROCESS_ID
; # for shutting down the program
158 ############ the command line options of the involved programs
160 # The naming scheme for the options environment names is
161 # $_OPTS_<prog>_<length>[_<argspec>]
163 # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
164 # command line options)
165 # <length>: LONG (long options) or SHORT (single character options)
166 # <argspec>: ARG for options with argument, NA for no argument;
167 # without _<argspec> both the ones with and without arg.
169 # Each option that takes an argument must be specified with a
170 # trailing : (colon).
173 export _OPTS_GROFFER_SHORT_NA
;
174 export _OPTS_GROFFER_SHORT_ARG
;
175 export _OPTS_GROFFER_LONG_NA
;
176 export _OPTS_GROFFER_LONG_ARG
;
177 export _OPTS_GROFF_SHORT_NA
;
178 export _OPTS_GROFF_SHORT_ARG
;
179 export _OPTS_GROFF_LONG_NA
;
180 export _OPTS_GROFF_LONG_ARG
;
181 export _OPTS_X_SHORT_ARG
;
182 export _OPTS_X_SHORT_NA
;
183 export _OPTS_X_LONG_ARG
;
184 export _OPTS_X_LONG_NA
;
185 export _OPTS_MAN_SHORT_ARG
;
186 export _OPTS_MAN_SHORT_NA
;
187 export _OPTS_MAN_LONG_ARG
;
188 export _OPTS_MAN_LONG_NA
;
189 export _OPTS_MANOPT_SHORT_ARG
;
190 export _OPTS_MANOPT_SHORT_NA
;
191 export _OPTS_MANOPT_LONG_ARG
;
192 export _OPTS_MANOPT_LONG_NA
;
193 export _OPTS_CMDLINE_SHORT_NA
;
194 export _OPTS_CMDLINE_SHORT_ARG
;
195 export _OPTS_CMDLINE_LONG_NA
;
196 export _OPTS_CMDLINE_LONG_ARG
;
198 ###### groffer native options
200 _OPTS_GROFFER_SHORT_NA
="'h' 'Q' 'v' 'V' 'X' 'Z'";
201 _OPTS_GROFFER_SHORT_ARG
="'T'";
203 _OPTS_GROFFER_LONG_NA
="'auto' 'debug' 'default' 'dvi' \
204 'groff' 'help' 'intermediate-output' 'html' 'man' \
205 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \
206 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
208 _OPTS_GROFFER_LONG_ARG
="\
209 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
210 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
211 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
212 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
214 ##### groffer options inhereted from groff
216 _OPTS_GROFF_SHORT_NA
="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
217 'R' 's' 'S' 't' 'U' 'z'";
218 _OPTS_GROFF_SHORT_ARG
="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
220 _OPTS_GROFF_LONG_NA
="";
221 _OPTS_GROFF_LONG_ARG
="";
223 ##### groffer options inhereted from the X Window toolkit
226 _OPTS_X_SHORT_ARG
="";
228 _OPTS_X_LONG_NA
="'iconic' 'rv'";
230 _OPTS_X_LONG_ARG
="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
231 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'
232 'resolution' 'title' 'xrm'";
234 ###### groffer options inherited from man
236 _OPTS_MAN_SHORT_NA
="";
237 _OPTS_MAN_SHORT_ARG
="";
239 _OPTS_MAN_LONG_NA
="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \
240 'local-file' 'location' 'pager' 'troff' 'update' 'version' \
243 _OPTS_MAN_LONG_ARG
="'extension' 'locale' 'manpath' \
244 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
246 ###### additional options for parsing $MANOPT only
248 _OPTS_MANOPT_SHORT_NA
="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
250 _OPTS_MANOPT_SHORT_ARG
="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
252 _OPTS_MANOPT_LONG_NA
="${_OPTS_MAN_LONG_NA} \
253 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
254 'match-case' 'troff' 'update' 'version' 'where-cat'";
256 _OPTS_MANOPT_LONG_ARG
="${_OPTS_MAN_LONG_NA} \
257 'config_file' 'encoding' 'locale'";
259 ###### collections of command line options
261 _OPTS_CMDLINE_SHORT_NA
="${_OPTS_GROFFER_SHORT_NA}\
262 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
263 _OPTS_CMDLINE_SHORT_ARG
="${_OPTS_GROFFER_SHORT_ARG} \
264 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
266 _OPTS_CMDLINE_LONG_NA
="${_OPTS_GROFFER_LONG_NA} \
267 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
268 _OPTS_CMDLINE_LONG_ARG
="${_OPTS_GROFFER_LONG_ARG} \
269 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
272 ########################################################################
273 # read-write variables (global to this file)
274 ########################################################################
276 export _ADDOPTS_GROFF
; # Transp. options for groff (`eval').
277 export _ADDOPTS_POST
; # Transp. options postproc (`eval').
278 export _ADDOPTS_X
; # Transp. options X postproc (`eval').
279 export _DEFAULT_MODES
; # Set default modes.
280 export _DISPLAY_MODE
; # Display mode.
281 export _DISPLAY_PROG
; # Viewer program to be used for display.
282 export _DISPLAY_ARGS
; # X resources for the viewer program.
283 export _FILEARGS
; # Stores filespec parameters.
284 export _FUNC_STACK
; # Store debugging information.
285 export _REGISTERED_TITLE
; # Processed file names.
286 # _HAS_* from availability tests
287 export _HAS_COMPRESSION
; # `yes' if gzip compression is available
288 export _HAS_BZIP
; # `yes' if bzip2 compression is available
289 # _MAN_* finally used configuration of man searching
290 export _MAN_ALL
; # search all man pages per filespec
291 export _MAN_ENABLE
; # enable search for man pages
292 export _MAN_EXT
; # extension for man pages
293 export _MAN_FORCE
; # force file parameter to be man pages
294 export _MAN_IS_SETUP
; # setup man variables only once
295 export _MAN_LANG
; # language for man pages
296 export _MAN_LANG2
; # language for man pages
297 export _MAN_LANG_DONE
; # language dirs added to man path
298 export _MAN_PATH
; # search path for man pages
299 export _MAN_SEC
; # sections for man pages; sep. `:'
300 export _MAN_SEC_DONE
; # sections added to man path
301 export _MAN_SYS
; # system names for man pages; sep. `,'
302 export _MAN_SYS
; # system names added to man path
303 # _MANOPT_* as parsed from $MANOPT
304 export _MANOPT_ALL
; # $MANOPT --all
305 export _MANOPT_EXTENSION
; # $MANOPT --extension
306 export _MANOPT_LANG
; # $MANOPT --locale
307 export _MANOPT_PATH
; # $MANOPT --manpath
308 export _MANOPT_PAGER
; # $MANOPT --pager
309 export _MANOPT_SEC
; # $MANOPT --sections
310 export _MANOPT_SYS
; # $MANOPT --systems
311 # _OPT_* as parsed from groffer command line
312 export _OPT_ALL
; # display all suitable man pages.
313 export _OPT_APROPOS
; # call `apropos' program.
314 export _OPT_APROPOS_DATA
; # `apropos' for man sections 4, 5, 7
315 export _OPT_APROPOS_DEVEL
; # `apropos' for man sections 2, 3, 9
316 export _OPT_APROPOS_PROGS
; # `apropos' for man sections 1, 6, 8
317 export _OPT_BD
; # set border color in some modes.
318 export _OPT_BG
; # set background color in some modes.
319 export _OPT_BW
; # set border width in some modes.
320 export _OPT_DEBUG
; # print debugging information on stderr.
321 export _OPT_DEFAULT_MODES
; # `,'-list of modes when no mode given.
322 export _OPT_DEVICE
; # device option.
323 export _OPT_DISPLAY
; # set X display.
324 export _OPT_FG
; # set foreground color in some modes.
325 export _OPT_FN
; # set font in some modes.
326 export _OPT_GEOMETRY
; # set size and position of viewer in X.
327 export _OPT_ICONIC
; # -iconic option for X viewers.
328 export _OPT_LANG
; # set language for man pages
329 export _OPT_LOCATION
; # print processed file names to stderr
330 export _OPT_MODE
; # values: X, tty, Q, Z, ""
331 export _OPT_MANPATH
; # manual setting of path for man-pages
332 export _OPT_PAGER
; # specify paging program for tty mode
333 export _OPT_RESOLUTION
; # set X resolution in dpi
334 export _OPT_RV
; # reverse fore- and background colors.
335 export _OPT_SECTIONS
; # sections for man page search
336 export _OPT_SYSTEMS
; # man pages of different OS's
337 export _OPT_TITLE
; # title for gxditview window
338 export _OPT_TEXT_DEVICE
; # set device for tty mode.
339 export _OPT_V
; # groff option -V.
340 export _OPT_VIEWER_DVI
; # viewer program for dvi mode
341 export _OPT_VIEWER_PDF
; # viewer program for pdf mode
342 export _OPT_VIEWER_PS
; # viewer program for ps mode
343 export _OPT_VIEWER_HTML
; # viewer program for html mode
344 export _OPT_VIEWER_X
; # viewer program for x mode
345 export _OPT_WHATIS
; # print the one-liner man info
346 export _OPT_XRM
; # specify X resource.
347 export _OPT_Z
; # groff option -Z.
348 # _TMP_* temporary files
349 export _TMP_DIR
; # groffer directory for temporary files
350 export _TMP_CAT
; # stores concatenation of everything
351 export _TMP_STDIN
; # stores stdin, if any
353 # these variables are preset in section `Preset' after the rudim. test
356 ########################################################################
357 # Test of rudimentary shell functionality
358 ########################################################################
361 ########################################################################
364 test "a" = "a" ||
exit 1;
367 ########################################################################
368 # Test of `echo' and the `$()' construct.
370 echo '' >${_NULL_DEV} ||
exit "${_ERROR}";
371 if test _
"$(t1="$
(echo te
)" &&
374 echo "${t1}${t2}${t3}")"_ \
381 ########################################################################
382 # Test of function definitions.
389 if _t_e_s_t_f_u_n_c_
2>${_NULL_DEV};
393 echo 'shell does not support function definitions.' >&2;
398 ########################################################################
399 # Preset and reset of read-write global variables
400 ########################################################################
403 # For variables that can be reset by option `--default', see reset().
407 # _HAS_* from availability tests
411 # _TMP_* temporary files
417 ########################################################################
420 # Reset the variables that can be affected by options to their default.
426 error
"reset() does not have arguments.";
435 _REGISTERED_TITLE
='';
437 # _MAN_* finally used configuration of man searching
439 _MAN_ENABLE
='yes'; # do search for man-pages
441 _MAN_FORCE
='no'; # first local file, then search man page
451 # _MANOPT_* as parsed from $MANOPT
453 _MANOPT_EXTENSION
='';
460 # _OPT_* as parsed from groffer command line
463 _OPT_APROPOS_DATA
='';
464 _OPT_APROPOS_DEVEL
='';
465 _OPT_APROPOS_PROGS
='';
470 _OPT_DEFAULT_MODES
='';
503 ########################################################################
504 # Functions for error handling and debugging
505 ########################################################################
513 # Arguments : arbitrary text.
526 # Print <text> to standard error as a debugging aid.
528 # Globals: $_DEBUG_LM
532 if test _
"${_DEBUG_LM}"_
= _yes_
;
538 landmark
"1: debugging functions";
548 if test -d "${_TMP_DIR}";
550 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
558 # Output a diagnostic message to stderr
569 # Print an error message to standard error; exit with an error condition
571 # Variable prefix: err
575 err_code
="${_ERROR}";
578 1) echo2
'groffer error: '"$1"; ;;
580 echo2
'groffer error: '"$1";
583 *) echo2
'groffer error: wrong number of arguments in error().'; ;;
587 kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
588 kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;
590 eval ${_UNSET} err_code
;
598 # Terminate program with error condition
602 error
"abort(): Program aborted.";
608 # func_check (<func_name> <rel_op> <nr_args> "$@")
610 # Check number of arguments and register to _FUNC_STACK.
613 # <func_name>: name of the calling function.
614 # <rel_op>: a relational operator: = != < > <= >=
615 # <nr_args>: number of arguments to be checked against <operator>
616 # "$@": the arguments of the calling function.
618 # Variable prefix: fc
624 error
'func_check() needs at least 3 arguments.';
637 error
"func_check(): third argument must be a digit.";
667 'func_check(): second argument is not a relational operator.';
673 if test "$#" "${fc_op}" "${fc_nargs}";
677 error
"func_check(): \
678 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
680 func_push
"${fc_fname}";
681 if test _
"${_DEBUG}"_
= _yes_
;
683 echo2
'+++ '"${fc_fname} $@";
684 echo2
'>>> '"${_FUNC_STACK}";
686 eval ${_UNSET} fc_comp
;
687 eval ${_UNSET} fc_fname
;
688 eval ${_UNSET} fc_nargs
;
689 eval ${_UNSET} fc_op
;
697 # Retrieve the top element from the stack.
699 # The stack elements are separated by `!'; the popped element is
700 # identical to the original element, except that all `!' characters
709 error
'func_pop() does not have arguments.';
711 case "${_FUNC_STACK}" in
713 if test _
"${_DEBUG}"_
= _yes_
;
715 error
'func_pop(): stack is empty.';
719 # split at first bang `!'.
720 _FUNC_STACK
="$(echo x"${_FUNC_STACK}" | sed -e '
729 if test _
"${_DEBUG}"_
= _yes_
;
731 echo2
'<<< '"${_FUNC_STACK}";
737 # func_push (<element>)
739 # Store another element to stack.
741 # The stack elements are separated by `!'; if <element> contains a `!'
742 # it is removed first.
746 # Variable prefix: fp
752 error
'func_push() needs 1 argument.';
756 # remove all bangs `!'.
757 fp_element
="$(echo x"$1" | sed -e '
766 if test _
"${_FUNC_STACK}"_
= __
;
768 _FUNC_STACK
="${fp_element}";
770 _FUNC_STACK
="${fp_element}!${_FUNC_STACK}";
772 eval ${_UNSET} fp_element
;
779 # Print the content of the stack. Ignore the arguments.
783 diag
'call stack: '"${_FUNC_STACK}";
787 ########################################################################
789 ########################################################################
791 landmark
"2: system test";
793 # Test the availability of the system utilities used in this script.
796 ########################################################################
797 # Test of function `sed'.
800 if test _
"$(echo xTesTx \
801 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
802 | sed -e 's|T|t|g')"_
!= _test_
;
804 error
'Test of "sed" command failed.';
808 ########################################################################
809 # Test of function `cat'.
811 if test _
"$(echo test | cat)"_
!= _test_
;
813 error
'Test of "cat" command failed.';
817 ########################################################################
818 # Test for compression.
820 if test _
"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_
= _test_
;
822 _HAS_COMPRESSION
='yes';
823 if echo 'test' |
bzip2 -c 2>${_NULL_DEV} |
bzip2 -t 2>${_NULL_DEV} \
824 && test _
"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
825 | bzip2 -d -c 2>${_NULL_DEV})"_ \
833 _HAS_COMPRESSION
='no';
838 ########################################################################
839 # Definition of normal Functions in alphabetical order
840 ########################################################################
841 landmark
"3: functions";
843 ########################################################################
846 # Unconditionally terminate the program with error code;
847 # useful for debugging.
852 ########################################################################
853 # apropos_run (<name>)
857 func_check apropos_run
= 1 "$@";
858 if apropos apropos
>${_NULL_DEV} 2>${_NULL_DEV};
861 elif man
--apropos man
>${_NULL_DEV} 2>${_NULL_DEV};
864 elif man
-k man
>${_NULL_DEV} 2>${_NULL_DEV};
872 ########################################################################
875 # Get the file name part of <path>, i.e. delete everything up to last
876 # `/' from the beginning of <path>. Remove final slashes, too, to get a
880 # Output : the file name part (without slashes)
882 # Variable prefix: bn
886 func_check base_name
= 1 "$@";
890 # delete all final slashes
891 bn_name
="$(echo x"${bn_name}" | sed -e '
899 eval ${_UNSET} bn_name
;
900 eval "${return_bad}";
903 # delete everything before and including the last slash `/'.
904 echo x
"${bn_name}" |
sed -e '
906 s|^.*//*\([^/]*\)$|\1|
915 eval ${_UNSET} bn_name
;
920 ########################################################################
923 # Decompress if possible or just print <file> to standard output.
925 # gzip, bzip2, and .Z decompression is supported.
927 # Arguments: 1, a file name.
928 # Output: the content of <file>, possibly decompressed.
930 if test _
"${_HAS_COMPRESSION}"_
= _yes_
;
934 func_check cat_z
= 1 "$@";
937 error
'cat_z(): empty file name';
940 error
'cat_z(): for standard input use save_stdin()';
943 if obj _HAS_BZIP is_yes
;
945 if bzip2 -t "$1" 2>${_NULL_DEV};
947 bzip2 -c -d "$1" 2>${_NULL_DEV};
951 gzip -c -d -f "$1" 2>${_NULL_DEV};
957 func_check cat_z
= 1 "$@";
964 ########################################################################
967 # Do the final cleaning up before exiting; used by the trap calls.
972 ########################################################################
975 # Print marked message to standard error; useful for debugging.
980 ########################################################################
981 landmark
'4: dirname()*';
982 ########################################################################
984 #######################################################################
985 # dirname_append (<dir> <name>)
987 # Append `name' to `dir' with clean handling of `/'.
990 # Output : the generated new directory name <dir>/<name>
994 func_check dirname_append
= 2 "$@";
997 error
"dir_append(): first argument is empty.";
1005 dirname_chop
"$1"/"$2";
1007 eval "${return_ok}";
1011 ########################################################################
1012 # dirname_chop (<name>)
1014 # Remove unnecessary slashes from directory name.
1016 # Argument: 1, a directory name.
1017 # Output: path without double, or trailing slashes.
1019 # Variable prefix: dc
1023 func_check dirname_chop
= 1 "$@";
1024 # replace all multiple slashes by a single slash `/'.
1025 dc_res
="$(echo x"$1" | sed -e '
1031 # remove trailing slash '/';
1032 echo x
"${dc_res}" |
sed -e '
1042 eval ${_UNSET} dc_res
;
1043 eval "${return_ok}";
1047 ########################################################################
1048 # do_filearg (<filearg>)
1050 # Append the file, man-page, or standard input corresponding to the
1051 # argument to the temporary file. If this is compressed in the gzip
1052 # or Z format it is decompressed. A title element is generated.
1055 # - name of an existing files.
1056 # - `-' to represent standard input (several times allowed).
1057 # - `man:name.(section)' the man-page for `name' in `section'.
1058 # - `man:name.section' the man-page for `name' in `section'.
1059 # - `man:name' the man-page for `name' in the lowest `section'.
1060 # - `name.section' the man-page for `name' in `section'.
1061 # - `name' the man-page for `name' in the lowest `section'.
1063 # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1066 # Return : $_GOOD if found, ${_BAD} otherwise.
1068 # Variable prefix: df
1072 func_check do_filearg
= 1 "$@";
1074 # store sequence into positional parameters
1075 case "${df_filespec}" in
1077 eval ${_UNSET} df_filespec
;
1078 eval "${return_good}";
1082 eval ${_UNSET} df_filespec
;
1083 eval "${return_good}";
1085 */*) # with directory part; so no man search
1089 if obj _MAN_ENABLE is_yes
;
1091 if obj _MAN_FORCE is_yes
;
1093 set 'Manpage' 'File';
1095 set 'File' 'Manpage';
1106 if test -f "${df_filespec}";
1108 if test -r "${df_filespec}";
1110 register_file
"${df_filespec}";
1111 eval ${_UNSET} df_filespec
;
1112 eval "${return_good}";
1114 echo2
"could not read \`${df_filespec}'";
1115 eval ${_UNSET} df_filespec
;
1116 eval "${return_bad}";
1122 Manpage
) # parse filespec as man page
1123 if obj _MAN_IS_SETUP is_not_yes
;
1127 if man_do_filespec
"${df_filespec}";
1129 eval ${_UNSET} df_filespec
;
1130 eval "${return_good}";
1137 eval ${_UNSET} df_filespec
;
1138 eval "${return_bad}";
1142 ########################################################################
1149 eval return "${_OK}";
1153 ########################################################################
1156 # Print to standard error with final line break.
1161 ########################################################################
1164 # Print error message and exit with error code.
1169 ########################################################################
1170 # func_check (<func_name> <rel_op> <nr_args> "$@")
1172 # Check number of arguments and register to _FUNC_STACK.
1175 # <func_name>: name of the calling function.
1176 # <rel_op>: a relational operator: = != < > <= >=
1177 # <nr_args>: number of arguments to be checked against <operator>
1178 # "$@": the arguments of the calling function.
1182 #########################################################################
1185 # Delete the top element from the function call stack.
1190 ########################################################################
1191 # func_push (<element>)
1193 # Store another element to function call stack.
1198 ########################################################################
1199 # func_stack_dump ()
1201 # Print the content of the stack.
1206 ########################################################################
1207 # get_first_essential (<arg>*)
1209 # Retrieve first non-empty argument.
1211 # Return : `1' if all arguments are empty, `0' if found.
1212 # Output : the retrieved non-empty argument.
1214 # Variable prefix: gfe
1216 get_first_essential
()
1218 func_check get_first_essential
'>=' 0 "$@";
1221 eval "${return_ok}";
1226 if obj gfe_var is_not_empty
;
1231 eval ${_UNSET} gfe_var
;
1232 eval "${return_ok}";
1235 eval ${_UNSET} gfe_var
;
1236 eval "${return_bad}";
1240 ########################################################################
1241 landmark
'5: is_*()';
1242 ########################################################################
1244 ########################################################################
1247 # Test whether `name' is a directory.
1250 # Return : `0' if arg1 is a directory, `1' otherwise.
1254 func_check is_dir
= 1 "$@";
1255 if test -d "$1" && test -r "$1";
1257 eval "${return_yes}";
1259 eval "${return_no}";
1263 ########################################################################
1264 # is_empty (<string>)
1266 # Test whether `string' is empty.
1269 # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
1273 func_check is_empty
= 1 "$@";
1274 if test _
"$1"_
= __
;
1276 eval "${return_yes}";
1278 eval "${return_no}";
1282 ########################################################################
1283 # is_equal (<string1> <string2>)
1285 # Test whether `string1' is equal to <string2>.
1288 # Return : `0' both arguments are equal strings, `1' otherwise.
1292 func_check is_equal
= 2 "$@";
1293 if test _
"$1"_
= _
"$2"_
;
1295 eval "${return_yes}";
1297 eval "${return_no}";
1301 ########################################################################
1302 # is_existing (<name>)
1304 # Test whether `name' is an existing file or directory. Solaris 2.5 does
1305 # not have `test -e'.
1308 # Return : `0' if arg1 exists, `1' otherwise.
1312 func_check is_existing
= 1 "$@";
1313 if test -f "$1" ||
test -d "$1";
1315 eval "${return_yes}";
1317 eval "${return_no}";
1321 ########################################################################
1324 # Test whether `name' is a readable file.
1327 # Return : `0' if arg1 is a readable file, `1' otherwise.
1331 func_check is_file
= 1 "$@";
1332 if test -f "$1" && test -r "$1";
1334 eval "${return_yes}";
1336 eval "${return_no}";
1340 ########################################################################
1341 # is_non_empty_file (<file_name>)
1343 # Test whether `file_name' is a non-empty existing file.
1347 # `0' if arg1 is a non-empty existing file
1352 func_check is_non_empty_file
= 1 "$@";
1353 if is_file
"$1" && test -s "$1";
1355 eval "${return_yes}";
1357 eval "${return_no}";
1361 ########################################################################
1362 # is_not_dir (<name>)
1364 # Test whether `name' is not a readable directory.
1367 # Return : `0' if arg1 is a directory, `1' otherwise.
1371 func_check is_not_dir
= 1 "$@";
1374 eval "${return_no}";
1376 eval "${return_yes}";
1380 ########################################################################
1381 # is_not_empty (<string>)
1383 # Test whether `string' is not empty.
1386 # Return : `0' if arg1 exists and is not empty, `1' otherwise.
1390 func_check is_not_empty
= 1 "$@";
1393 eval "${return_no}";
1395 eval "${return_yes}";
1399 ########################################################################
1400 # is_not_equal (<string1> <string2>)
1402 # Test whether `string1' differs from `string2'.
1408 func_check is_not_equal
= 2 "$@";
1409 if is_equal
"$1" "$2";
1411 eval "${return_no}";
1413 eval "${return_yes}";
1417 ########################################################################
1418 # is_not_file (<filename>)
1420 # Test whether `name' is a not readable file.
1422 # Arguments : >=1 (empty allowed), more args are ignored
1426 func_check is_not_file
'>=' 1 "$@";
1429 eval "${return_no}";
1431 eval "${return_yes}";
1435 ########################################################################
1436 # is_not_prog (<name>)
1438 # Verify that arg is a not program in $PATH.
1440 # Arguments : >=1 (empty allowed)
1441 # more args are ignored, this allows to specify progs with arguments
1445 func_check is_not_prog
'>=' 1 "$@";
1446 if where_is
"$1" >${_NULL_DEV};
1448 eval "${return_no}";
1450 eval "${return_yes}";
1454 ########################################################################
1455 # is_not_writable (<name>)
1457 # Test whether `name' is a not a writable file or directory.
1459 # Arguments : >=1 (empty allowed), more args are ignored
1463 func_check is_not_writable
'>=' 1 "$@";
1464 if is_writable
"$1";
1466 eval "${return_no}";
1468 eval "${return_yes}";
1472 ########################################################################
1473 # is_not_yes (<string>)
1475 # Test whether `string' is not "yes".
1481 func_check is_not_yes
= 1 "$@";
1484 eval "${return_no}";
1486 eval "${return_yes}";
1490 ########################################################################
1491 # is_prog (<name> [<arg>*])
1493 # Determine whether <name> is a program in $PATH
1495 # Arguments : >=0 (empty allowed)
1496 # <arg>* are ignored, this allows to specify progs with arguments.
1500 func_check is_prog
'>=' 0 "$@";
1503 eval "${return_no}";
1506 if where_is
"$1" >${_NULL_DEV};
1508 eval "${return_yes}";
1512 eval "${return_no}";
1516 ########################################################################
1517 # is_writable (<name>)
1519 # Test whether `name' is a writable file or directory.
1521 # Arguments : >=1 (empty allowed), more args are ignored
1525 func_check is_writable
'>=' 1 "$@";
1530 eval "${return_yes}";
1533 eval "${return_no}";
1537 ########################################################################
1540 # Test whether `string' has value "yes".
1543 # Return : `0' if arg1 is `yes', `1' otherwise.
1547 func_check is_yes
= 1 "$@";
1548 if is_equal
"$1" 'yes';
1550 eval "${return_yes}";
1552 eval "${return_no}";
1556 ########################################################################
1559 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
1561 # Globals: $_DEBUG_LM
1563 # Defined in section `Debugging functions'.
1566 ########################################################################
1569 # Clean exit without an error.
1578 ########################################################################
1579 landmark
'6: list_*()';
1580 ########################################################################
1582 # `list' is an object class that represents an array or list. Its
1583 # data consists of space-separated single-quoted elements. So a list
1584 # has the form "'first' 'second' '...' 'last'". See list_append() for
1585 # more details on the list structure. The array elements of `list'
1586 # can be get by `set x $list; shift`.
1589 ########################################################################
1590 # list_append (<list> <element>...)
1593 # <list>: a variable name for a list of single-quoted elements
1594 # <element>: some sequence of characters.
1595 # Output: none, but $<list> is set to
1596 # if <list> is empty: "'<element>' '...'"
1597 # otherwise: "$list '<element>' ..."
1599 # Variable prefix: la
1603 func_check list_append
'>=' 2 "$@";
1605 eval la_list
='"${'$1'}"';
1612 # escape each single quote by replacing each
1613 # "'" (squote) by "'\''" (squote bslash squote squote);
1614 # note that the backslash must be doubled in the following `sed'
1615 la_element
="$(echo x"${la_s}" | sed -e '
1617 s/'"${_SQUOTE}"'/&\\&&/g
1624 la_element
="${la_s}";
1627 if obj la_list is_empty
;
1629 la_list
="'${la_element}'";
1631 la_list
="${la_list} '${la_element}'";
1634 eval "${la_name}"='"${la_list}"';
1635 eval ${_UNSET} la_element
;
1636 eval ${_UNSET} la_list
;
1637 eval ${_UNSET} la_name
;
1638 eval ${_UNSET} la_s
;
1639 eval "${return_ok}";
1643 ########################################################################
1644 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1646 # Transform command line arguments into a normalized form.
1648 # Options, option arguments, and file parameters are identified and
1649 # output each as a single-quoted argument of its own. Options and
1650 # file parameters are separated by a '--' argument.
1653 # <pre_name>: common part of a set of 4 environment variable names:
1654 # $<pre_name>_SHORT_NA: list of short options without an arg.
1655 # $<pre_name>_SHORT_ARG: list of short options that have an arg.
1656 # $<pre_name>_LONG_NA: list of long options without an arg.
1657 # $<pre_name>_LONG_ARG: list of long options that have an arg.
1658 # <cmdline_arg>...: the arguments from a command line, such as "$@",
1659 # the content of a variable, or direct arguments.
1661 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1664 # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1665 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1666 # none-empty option lists, this will result in printing:
1667 # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1669 # Use this function in the following way:
1670 # eval set x "$(args_norm PRE_NAME "$@")";
1672 # while test "$1" != '--'; do
1679 # # all positional parameters ("$@") left are file name parameters.
1681 # Variable prefix: lfc
1685 func_check list_from_cmdline
'>=' 1 "$@";
1686 lfc_short_n
="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
1687 lfc_short_a
="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
1688 lfc_long_n
="$(obj_data "$1"_LONG_NA)"; # long options, no argument
1689 lfc_long_a
="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
1690 if obj lfc_short_n is_empty
;
1692 error
'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
1694 if obj lfc_short_a is_empty
;
1696 error
'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
1698 if obj lfc_long_n is_empty
;
1700 error
'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
1702 if obj lfc_long_a is_empty
;
1704 error
'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
1707 lfc_fn
='list_from_cmdline():'; # for error messages
1713 eval ${_UNSET} lfc_fparams
;
1714 eval ${_UNSET} lfc_fn
;
1715 eval ${_UNSET} lfc_short_a
;
1716 eval ${_UNSET} lfc_short_n
;
1717 eval ${_UNSET} lfc_long_a
;
1718 eval ${_UNSET} lfc_long_n
;
1719 eval ${_UNSET} lfc_result
;
1720 eval "${return_ok}";
1724 while test "$#" -ge 1;
1728 case "${lfc_arg}" in
1731 # delete leading '--';
1732 lfc_opt
="$(echo x"${lfc_arg}" | sed -e 's/^x--//')";
1733 if list_has lfc_long_n
"${lfc_opt}";
1735 # long option, no argument
1736 list_append lfc_result
"--${lfc_opt}";
1739 # test on `--opt=arg'
1740 if string_contains
"${lfc_opt}" '=';
1742 # extract option by deleting from the first '=' to the end
1743 lfc_lopt
="$(echo x"${lfc_opt}" | sed -e '
1747 if list_has lfc_long_a
"${lfc_lopt}";
1749 # get the option argument by deleting up to first `='
1750 lfc_optarg
="$(echo x"${lfc_opt}" | sed -e '
1754 list_append lfc_result
"--${lfc_lopt}" "${lfc_optarg}";
1758 if list_has lfc_long_a
"${lfc_opt}";
1760 # long option with argument
1763 error
"list_from_cmdline(): \
1764 ${lfc_fn} no argument for option --${lfc_opt}."
1766 list_append lfc_result
"--${lfc_opt}" "$1";
1770 error
"list_from_cmdline(): ${lfc_fn} --${lfc_opt} is not an option."
1772 -?
*) # short option (cluster)
1773 # delete leading `-';
1774 lfc_rest
="$(echo x"${lfc_arg}" | sed -e 's/^x-//')";
1775 while obj lfc_rest is_not_empty
;
1777 # get next short option from cluster (first char of $lfc_rest)
1778 lfc_optchar
="$(echo x"${lfc_rest}" | sed -e 's/^x\(.\).*$/\1/')";
1779 # remove first character from ${lfc_rest};
1780 lfc_rest
="$(echo x"${lfc_rest}" | sed -e 's/^x.//')";
1781 if list_has lfc_short_n
"${lfc_optchar}";
1783 list_append lfc_result
"-${lfc_optchar}";
1785 elif list_has lfc_short_a
"${lfc_optchar}";
1787 if obj lfc_rest is_empty
;
1791 list_append lfc_result
"-${lfc_optchar}" "$1";
1795 error
"list_from_cmdline(): \
1796 ${lfc_fn}"' no argument for option -'"${lfc_optchar}."
1798 else # rest is the argument
1799 list_append lfc_result
"-${lfc_optchar}" "${lfc_rest}";
1804 error
"list_from_cmdline(): \
1805 ${lfc_fn} unknown option -${lfc_optchar}."
1810 # Here, $lfc_arg is not an option, so a file parameter.
1811 list_append lfc_fparams
"${lfc_arg}";
1813 # Ignore the strange option handling of $POSIXLY_CORRECT to
1814 # end option parsing after the first file name argument. To
1815 # reuse it, do a `break' here if $POSIXLY_CORRECT is
1820 list_append lfc_result
'--';
1821 if obj lfc_fparams is_not_empty
;
1823 lfc_result
="${lfc_result} ${lfc_fparams}";
1827 list_append lfc_result
"$@";
1832 eval ${_UNSET} lfc_fparams
;
1833 eval ${_UNSET} lfc_fn
;
1834 eval ${_UNSET} lfc_short_a
;
1835 eval ${_UNSET} lfc_short_n
;
1836 eval ${_UNSET} lfc_long_a
;
1837 eval ${_UNSET} lfc_long_n
;
1838 eval ${_UNSET} lfc_result
;
1839 eval ${_UNSET} lfc_arg
;
1840 eval ${_UNSET} lfc_opt
;
1841 eval ${_UNSET} lfc_opt_arg
;
1842 eval ${_UNSET} lfc_opt_char
;
1843 eval ${_UNSET} lfc_lopt
;
1844 eval ${_UNSET} lfc_rest
;
1845 eval "${return_ok}";
1846 } # list_from_cmdline()
1849 ########################################################################
1850 # list_from_split (<string> <separator>)
1852 # In <string>, escape all white space characters and replace each
1853 # <separator> by space.
1855 # Arguments: 2: a <string> that is to be split into parts divided by
1857 # Output: the resulting list string
1859 # Variable prefix: lfs
1863 func_check list_from_split
= 2 "$@";
1865 # precede each space or tab by a backslash `\' (doubled for `sed')
1866 lfs_s
="$(echo x"$1" | sed -e '
1868 s/\(['"${_SPACE}${_TAB}"']\)/\\\1/g
1871 # replace split character of string by the list separator ` ' (space).
1873 /) # cannot use normal `sed' separator
1874 echo x
"${lfs_s}" |
sed -e '
1879 ?
) # use normal `sed' separator
1880 echo x
"${lfs_s}" |
sed -e '
1886 error
'list_from_split(): separator must be a single character.';
1889 eval ${_UNSET} lfs_s
;
1890 eval "${return_ok}";
1894 ########################################################################
1897 # Check whether <list> is a space-separated list of '-quoted elements.
1899 # If the test fails an error is raised.
1900 # If the test succeeds the argument is echoed.
1903 # A list has the form "'first' 'second' '...' 'last'". So it has a
1904 # leading and a final quote and the elements are separated by "' '"
1905 # constructs. If these are all removed there should not be any
1906 # unescaped single-quotes left. Watch out for escaped single
1907 # quotes; they have the form '\'' (sq bs sq sq).
1910 # Output: the argument <list> unchanged, if the check succeeded.
1912 # Variable prefix: lg
1916 func_check list_get
= 1 "$@";
1917 eval lg_list
='"${'$1'}"';
1918 # remove leading and final space characters
1919 lg_list
="$(echo x"${lg_list}" | sed -e '
1920 s/^x['"${_SPACE}${_TAB}"']*//
1921 s/['"${_SPACE}${_TAB}"']*$//
1923 case "${lg_list}" in
1925 eval ${_UNSET} lg_list
;
1926 eval "${return_ok}";
1932 eval ${_UNSET} lg_list
;
1933 eval "${return_ok}";
1936 error
"list_get(): bad list: $1"
1939 eval ${_UNSET} lg_list
;
1940 eval "${return_ok}";
1944 ########################################################################
1945 # list_has (<var_name> <element>)
1948 # <var_name>: a variable name for a list of single-quoted elements
1949 # <element>: some sequence of characters.
1951 # if <list> is empty: "'<element>' '...'"
1952 # otherwise: "list '<element>' ..."
1956 func_check list_has
= 2 "$@";
1957 eval _list
='"${'$1'}"';
1958 if obj _list is_empty
;
1960 eval "${return_no}";
1964 \'*\') _element
="$2"; ;;
1965 *) _element
="'$2'"; ;;
1967 if string_contains
"${_list}" "${_element}";
1969 eval "${return_yes}";
1971 eval "${return_no}";
1973 eval "${return_ok}";
1977 ########################################################################
1978 # list_has_not (<list> <element>)
1981 # <list>: a space-separated list of single-quoted elements.
1982 # <element>: some sequence of characters.
1984 # if <list> is empty: "'<element>' '...'"
1985 # otherwise: "<list> '<element>' ..."
1989 func_check list_has_not
= 2 "$@";
1990 eval _list
='"${'$1'}"';
1991 if obj _list is_empty
;
1993 eval "${return_yes}";
1997 \'*\') _element
="$2"; ;;
1998 *) _element
="'$2'"; ;;
2000 if string_contains
"${_list}" "${_element}";
2002 eval "${return_no}";
2004 eval "${return_yes}";
2006 eval "${return_ok}";
2010 ########################################################################
2011 landmark
'7: man_*()';
2012 ########################################################################
2014 ########################################################################
2015 # man_do_filespec (<filespec>)
2017 # Print suitable man page(s) for filespec to $_TMP_CAT.
2020 # <filespec>: argument of the form `man:name.section', `man:name',
2021 # `man:name(section)', `name.section', `name'.
2023 # Globals : $_OPT_ALL
2026 # Return : `0' if man page was found, `1' else.
2028 # Only called from do_fileargs(), checks on $MANPATH and
2029 # $_MAN_ENABLE are assumed.
2031 # Variable prefix: mdf
2035 func_check man_do_filespec
= 1 "$@";
2036 if obj _MAN_PATH is_empty
;
2038 eval "${return_bad}";
2042 eval "${return_bad}";
2047 case "${mdf_spec}" in
2048 */*) # not a man spec when it contains '/'
2049 eval ${_UNSET} mdf_got_one
;
2050 eval ${_UNSET} mdf_name
;
2051 eval ${_UNSET} mdf_section
;
2052 eval ${_UNSET} mdf_spec
;
2053 eval "${return_bad}";
2055 man
:?
*\
(?
*\
)) # man:name(section)
2056 mdf_name
="$(echo x"${mdf_spec}" \
2057 | sed -e 's/^xman:\(..*\)(\(..*\))$/\1/')";
2058 mdf_section
="$(echo x"${mdf_spec}" \
2059 | sed -e 's/^xman:\(..*\)(\(..*\))$/\2/')";
2061 man
:?
*.
[0-9on]) # man:name.section
2062 mdf_name
="$(echo x"${mdf_spec}" \
2063 | sed -e 's/^xman:\(..*\)\..$/\1/')";
2064 mdf_section
="$(echo x"${mdf_spec}" \
2065 | sed -e 's/^x.*\(.\)$/\1/')";
2068 mdf_name
="$(echo x"${mdf_spec}" | sed -e 's/^xman://')";
2070 ?
*\
(?
*\
)) # name(section)
2071 mdf_name
="$(echo x"${mdf_spec}" \
2072 | sed -e 's/^x\(..*\)(\(..*\))$/\1/')";
2073 mdf_section
="$(echo x"${mdf_spec}" \
2074 | sed -e 's/^x\(..*\)(\(..*\))$/\2/')";
2076 ?
*.
[0-9on]) # name.section
2077 mdf_name
="$(echo x"${mdf_spec}" \
2078 | sed -e 's/^x\(..*\)\..$/\1/')";
2079 mdf_section
="$(echo x"${mdf_spec}" \
2080 | sed -e 's/^x.*\(.\)$/\1/')";
2083 mdf_name
="${mdf_spec}";
2086 if obj mdf_name is_empty
;
2088 eval ${_UNSET} mdf_got_one
;
2089 eval ${_UNSET} mdf_name
;
2090 eval ${_UNSET} mdf_section
;
2091 eval ${_UNSET} mdf_spec
;
2092 eval "${return_bad}";
2095 if obj mdf_section is_empty
;
2097 eval set x
"${_MAN_AUTO_SEC}";
2102 if man_search_section
"${mdf_name}" "${mdf_s}";
2104 if obj _MAN_ALL is_yes
;
2108 eval ${_UNSET} mdf_got_one
;
2109 eval ${_UNSET} mdf_name
;
2110 eval ${_UNSET} mdf_s
;
2111 eval ${_UNSET} mdf_section
;
2112 eval ${_UNSET} mdf_spec
;
2113 eval "${return_good}";
2118 if man_search_section
"${mdf_name}" "${mdf_section}";
2120 eval ${_UNSET} mdf_got_one
;
2121 eval ${_UNSET} mdf_name
;
2122 eval ${_UNSET} mdf_s
;
2123 eval ${_UNSET} mdf_section
;
2124 eval ${_UNSET} mdf_spec
;
2125 eval "${return_good}";
2127 eval ${_UNSET} mdf_got_one
;
2128 eval ${_UNSET} mdf_name
;
2129 eval ${_UNSET} mdf_section
;
2130 eval ${_UNSET} mdf_spec
;
2131 eval "${return_bad}";
2134 if obj _MAN_ALL is_yes
&& is_yes
"${mdf_got_one}";
2136 eval ${_UNSET} mdf_got_one
;
2137 eval ${_UNSET} mdf_name
;
2138 eval ${_UNSET} mdf_s
;
2139 eval ${_UNSET} mdf_section
;
2140 eval ${_UNSET} mdf_spec
;
2141 eval "${return_good}";
2143 eval ${_UNSET} mdf_got_one
;
2144 eval ${_UNSET} mdf_name
;
2145 eval ${_UNSET} mdf_s
;
2146 eval ${_UNSET} mdf_section
;
2147 eval ${_UNSET} mdf_spec
;
2148 eval "${return_bad}";
2149 } # man_do_filespec()
2152 ########################################################################
2153 # man_register_file (<file> <name> [<section>])
2155 # Write a found man page file and register the title element.
2157 # Arguments: 1, 2, or 3; maybe empty
2162 func_check man_register_file
'>=' 2 "$@";
2166 error
"man_register_file() expects 2 or 3 arguments.";
2171 error
'man_register_file(): file name is empty';
2176 register_title
"man:$2";
2177 eval "${return_ok}";
2180 register_title
"$2.$3";
2181 eval "${return_ok}";
2184 eval "${return_ok}";
2188 ########################################################################
2189 # man_search_section (<name> <section>)
2191 # Retrieve man pages.
2194 # Globals : $_MAN_PATH, $_MAN_EXT
2195 # Return : 0 if found, 1 otherwise
2197 # Variable prefix: mss
2199 man_search_section
()
2201 func_check man_search_section
= 2 "$@";
2202 if obj _MAN_PATH is_empty
;
2204 eval "${return_bad}";
2208 eval "${return_bad}";
2212 eval "${return_bad}";
2216 eval set x
"$(path_split "${_MAN_PATH}")";
2219 if obj _MAN_EXT is_empty
;
2223 mss_dir
="$(dirname_append "$d" "man
${mss_section}")";
2224 if obj mss_dir is_dir
;
2227 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2228 mss_files
="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2229 sed -e '\| found|s|.*||'
2231 if obj mss_files is_not_empty
;
2233 # for f in $mss_files
2234 for f
in $
(eval set x
${mss_files}; shift; echo "$@")
2237 if obj mss_f is_file
;
2239 if is_yes
"${mss_got_one}";
2241 register_file
"${mss_f}";
2242 elif obj _MAN_ALL is_yes
;
2244 man_register_file
"${mss_f}" "${mss_name}";
2246 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2247 eval ${_UNSET} mss_dir
;
2248 eval ${_UNSET} mss_ext
;
2249 eval ${_UNSET} mss_f
;
2250 eval ${_UNSET} mss_files
;
2251 eval ${_UNSET} mss_got_one
;
2252 eval ${_UNSET} mss_name
;
2253 eval ${_UNSET} mss_prefix
;
2254 eval ${_UNSET} mss_section
;
2255 eval "${return_good}";
2264 mss_ext
="${_MAN_EXT}";
2265 # check for directory name having trailing extension
2268 mss_dir
="$(dirname_append $d man${mss_section}${mss_ext})";
2269 if obj mss_dir is_dir
;
2272 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
2273 mss_files
="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2274 sed -e '\|not found|s|.*||'
2276 if obj mss_files is_not_empty
;
2278 # for f in $mss_files
2279 for f
in $
(eval set x
${mss_files}; shift; echo "$@")
2282 if obj mss_f is_file
;
2284 if is_yes
"${mss_got_one}";
2286 register_file
"${mss_f}";
2287 elif obj _MAN_ALL is_yes
;
2289 man_register_file
"${mss_f}" "${mss_name}";
2291 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2292 eval ${_UNSET} mss_dir
;
2293 eval ${_UNSET} mss_ext
;
2294 eval ${_UNSET} mss_f
;
2295 eval ${_UNSET} mss_files
;
2296 eval ${_UNSET} mss_got_one
;
2297 eval ${_UNSET} mss_name
;
2298 eval ${_UNSET} mss_prefix
;
2299 eval ${_UNSET} mss_section
;
2300 eval "${return_good}";
2308 # check for files with extension in directories without extension
2311 mss_dir
="$(dirname_append "$d" "man
${mss_section}")";
2312 if obj mss_dir is_dir
;
2314 mss_prefix
="$(dirname_append "${mss_dir}" \
2315 "${mss_name}.${mss_section}${mss_ext}")";
2316 mss_files
="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
2317 sed -e '\|not found|s|.*||'
2319 if obj mss_files is_not_empty
;
2321 # for f in $mss_files
2322 for f
in $
(eval set x
${mss_files}; shift; echo "$@")
2325 if obj mss_f is_file
;
2327 if is_yes
"${mss_got_one}";
2329 register_file
"${mss_f}";
2330 elif obj _MAN_ALL is_yes
;
2332 man_register_file
"${mss_f}" "${mss_name}";
2334 man_register_file
"${mss_f}" "${mss_name}" "${mss_section}";
2335 eval ${_UNSET} mss_dir
;
2336 eval ${_UNSET} mss_ext
;
2337 eval ${_UNSET} mss_f
;
2338 eval ${_UNSET} mss_files
;
2339 eval ${_UNSET} mss_got_one
;
2340 eval ${_UNSET} mss_name
;
2341 eval ${_UNSET} mss_prefix
;
2342 eval ${_UNSET} mss_section
;
2343 eval "${return_good}";
2352 if obj _MAN_ALL is_yes
&& is_yes
"${mss_got_one}";
2354 eval ${_UNSET} mss_dir
;
2355 eval ${_UNSET} mss_ext
;
2356 eval ${_UNSET} mss_f
;
2357 eval ${_UNSET} mss_files
;
2358 eval ${_UNSET} mss_got_one
;
2359 eval ${_UNSET} mss_name
;
2360 eval ${_UNSET} mss_prefix
;
2361 eval ${_UNSET} mss_section
;
2362 eval "${return_good}";
2364 eval ${_UNSET} mss_dir
;
2365 eval ${_UNSET} mss_ext
;
2366 eval ${_UNSET} mss_f
;
2367 eval ${_UNSET} mss_files
;
2368 eval ${_UNSET} mss_got_one
;
2369 eval ${_UNSET} mss_name
;
2370 eval ${_UNSET} mss_prefix
;
2371 eval ${_UNSET} mss_section
;
2372 eval "${return_bad}";
2373 } # man_search_section()
2376 ########################################################################
2379 # Setup the variables $_MAN_* needed for man page searching.
2382 # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
2383 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
2384 # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
2385 # $_MAN_SEC, $_MAN_ALL
2386 # in/out: $_MAN_ENABLE
2388 # The precedence for the variables related to `man' is that of GNU
2391 # $LANG; overridden by
2392 # $LC_MESSAGES; overridden by
2393 # $LC_ALL; this has the same precedence as
2394 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
2395 # $MANOPT; overridden by
2396 # the groffer command line options.
2398 # Variable prefix: ms
2402 func_check main_man_setup
= 0 "$@";
2404 if obj _MAN_IS_SETUP is_yes
;
2406 eval "${return_ok}";
2408 _MAN_IS_SETUP
='yes';
2410 if obj _MAN_ENABLE is_not_yes
;
2412 eval "${return_ok}";
2415 # determine basic path for man pages
2416 _MAN_PATH
="$(get_first_essential \
2417 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
2418 if obj _MAN_PATH is_empty
;
2420 manpath_set_from_path
;
2422 _MAN_PATH
="$(path_clean "${_MAN_PATH}")";
2424 if obj _MAN_PATH is_empty
;
2426 if is_prog
'manpath';
2428 _MAN_PATH
="$(manpath 2>${_NULL_DEV})"; # not always available
2431 if obj _MAN_PATH is_empty
;
2434 eval "${return_ok}";
2437 _MAN_ALL
="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
2438 if obj _MAN_ALL is_empty
;
2443 _MAN_SYS
="$(get_first_essential \
2444 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
2445 ms_lang
="$(get_first_essential \
2446 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
2447 case "${ms_lang}" in
2453 _MAN_LANG
="${ms_lang}";
2457 _MAN_LANG
="${ms_lang}";
2458 # get first two characters of $ms_lang
2459 _MAN_LANG2
="$(echo x"${ms_lang}" | sed -e 's/^x\(..\).*$/\1/')";
2462 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
2464 manpath_add_lang_sys
; # this is very slow
2466 _MAN_SEC
="$(get_first_essential \
2467 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
2468 if obj _MAN_PATH is_empty
;
2471 eval ${_UNSET} ms_lang
;
2472 eval "${return_ok}";
2475 _MAN_EXT
="$(get_first_essential \
2476 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
2477 eval ${_UNSET} ms_lang
;
2478 eval "${return_ok}";
2482 ########################################################################
2483 landmark
'8: manpath_*()';
2484 ########################################################################
2486 ########################################################################
2487 # manpath_add_lang_sys ()
2489 # Add language and operating system specific directories to man path.
2494 # in: $_MAN_SYS: has the form `os1,os2,...', a comma separated
2495 # list of names of operating systems.
2496 # $_MAN_LANG and $_MAN_LANG2: each a single name
2497 # in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
2498 # separated list of directories.
2500 # Variable prefix: mals
2502 manpath_add_lang_sys
()
2504 func_check manpath_add_lang_sys
= 0 "$@";
2505 if obj _MAN_PATH is_empty
;
2507 eval "${return_ok}";
2509 # twice test both sys and lang
2510 eval set x
"$(path_split "${_MAN_PATH}")";
2514 do # loop on man path directories
2515 mals_mp
="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2517 eval set x
"$(path_split "${mals_mp}")";
2520 do # loop on man path directories
2521 mals_mp
="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
2523 _MAN_PATH
="$(path_chop "${mals_mp}")";
2524 eval ${_UNSET} mals_mp
;
2525 eval "${return_ok}";
2529 # To the directory in $1 append existing sys/lang subdirectories
2530 # Function is necessary to split the OS list.
2532 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
2533 # argument: 2: `man_path' and `dir'
2534 # output: colon-separated path of the retrieved subdirectories
2536 # Variable prefix: _mals
2538 _manpath_add_lang_sys_single
()
2540 func_check _manpath_add_lang_sys_single
= 2 "$@";
2543 eval set x
"$(list_from_split "${_MAN_SYS}" ',')";
2545 for d
in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
2547 _mals_dir
="$(dirname_append "${_mals_parent}" "$d")";
2548 if obj _mals_res path_not_contains
"${_mals_dir}" && \
2549 obj _mals_dir is_dir
;
2551 _mals_res
="${_mals_res}:${_mals_dir}";
2554 if path_not_contains
"${_mals_res}" "${_mals_parent}";
2556 _mals_res
="${_mals_res}:${_mals_parent}";
2558 path_chop
"${_mals_res}";
2559 eval ${_UNSET} _mals_dir
;
2560 eval ${_UNSET} _mals_parent
;
2561 eval ${_UNSET} _mals_res
;
2562 eval "${return_ok}";
2565 # end manpath_add_lang_sys ()
2568 ########################################################################
2569 # manpath_set_from_path ()
2571 # Determine basic search path for man pages from $PATH.
2573 # Return: `0' if a valid man path was retrieved.
2579 # Variable prefix: msfp
2581 manpath_set_from_path
()
2583 func_check manpath_set_from_path
= 0 "$@";
2587 # get a basic man path from $PATH
2588 if obj PATH is_not_empty
;
2590 eval set x
"$(path_split "${PATH}")";
2594 # delete the final `/bin' part
2595 msfp_base
="$(echo x"$d" | sed -e '
2599 for e
in /share
/man
/man
2601 msfp_mandir
="${msfp_base}$e";
2602 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}";
2604 msfp_manpath
="${msfp_manpath}:${msfp_mandir}";
2610 # append some default directories
2611 for d
in /usr
/local
/share
/man
/usr
/local
/man \
2612 /usr
/share
/man
/usr
/man \
2613 /usr
/X11R
6/man
/usr
/openwin
/man \
2614 /opt
/share
/man
/opt
/man \
2615 /opt
/gnome
/man
/opt
/kde
/man
2618 if obj msfp_manpath path_not_contains
"${msfp_d}" && obj mfsp_d is_dir
;
2620 msfp_manpath
="${msfp_manpath}:${mfsp_d}";
2624 _MAN_PATH
="${msfp_manpath}";
2625 eval ${_UNSET} msfp_base
;
2626 eval ${_UNSET} msfp_d
;
2627 eval ${_UNSET} msfp_mandir
;
2628 eval ${_UNSET} msfp_manpath
;
2629 eval "${return_ok}";
2630 } # manpath_set_from_path()
2633 ########################################################################
2634 landmark
'9: obj_*()';
2635 ########################################################################
2637 ########################################################################
2638 # obj (<object> <call_name> <arg>...)
2640 # This works like a method (object function) call for an object.
2641 # Run "<call_name> $<object> <arg> ...".
2643 # The first argument represents an object whose data is given as first
2644 # argument to <call_name>().
2647 # <object>: variable name
2648 # <call_name>: a program or function name
2650 # Variable prefix: o
2654 func_check obj
'>=' 2 "$@";
2657 error
"obj(): function name is empty."
2661 eval o_arg1
='"${'$1'}"';
2664 eval "${o_func}"' "${o_arg1}" "$@"';
2666 eval ${_UNSET} o_arg1
;
2667 eval ${_UNSET} o_func
;
2668 eval "${return_var} $n";
2672 ########################################################################
2673 # obj_data (<object>)
2675 # Print the data of <object>, i.e. the content of $<object>.
2676 # For possible later extensions.
2679 # <object>: a variable name
2680 # Output: the data of <object>
2682 # Variable prefix: od
2686 func_check obj
'=' 1 "$@";
2689 error
"obj_data(): object name is empty."
2691 eval od_res
='"${'$1'}"';
2695 eval ${_UNSET} od_res
;
2696 eval "${return_ok}";
2700 ########################################################################
2701 # obj_from_output (<object> <call_name> <arg>...)
2703 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
2704 # function call to a global variable.
2707 # <object>: a variable name
2708 # <call_name>: the name of a function or program
2709 # <arg>: optional argument to <call_name>
2712 # Variable prefix: ofo
2716 func_check obj_from_output
'>=' 2 "$@";
2719 error
"res(): variable name is empty.";
2722 error
"res(): function name is empty."
2724 ofo_result_name
="$1";
2727 eval "${ofo_result_name}"'="$('"$@"')"';
2728 eval "${return_ok}";
2732 ########################################################################
2733 # obj_set (<object> <data>)
2735 # Set the data of <object>, i.e. call "$<object>=<data>".
2738 # <object>: a variable name
2744 func_check obj_set
'=' 2 "$@";
2747 error
"obj_set(): object name is empty."
2750 eval "${return_ok}";
2754 ########################################################################
2755 # path_chop (<path>)
2757 # Remove unnecessary colons from path.
2759 # Argument: 1, a colon separated path.
2760 # Output: path without leading, double, or trailing colons.
2764 func_check path_chop
= 1 "$@";
2766 # replace multiple colons by a single colon `:'
2767 # remove leading and trailing colons
2768 echo x
"$1" |
sed -e '
2773 eval "${return_ok}";
2777 ########################################################################
2778 # path_clean (<path>)
2780 # Remove non-existing directories from a colon-separated list.
2782 # Argument: 1, a colon separated path.
2783 # Output: colon-separated list of existing directories.
2785 # Variable prefix: pc
2789 func_check path_clean
= 1 "$@";
2790 if is_not_equal
"$#" 1;
2792 error
'path_clean() needs 1 argument.';
2795 eval set x
"$(path_split "${pc_arg}")";
2801 if obj pc_i is_not_empty \
2802 && obj pc_res path_not_contains
"${pc_i}" \
2806 ?
*/) pc_res
="${pc_res}$(dirname_chop "${pc_i}")"; ;;
2807 *) pc_res
="${pc_res}:${pc_i}";
2811 eval ${_UNSET} pc_arg
;
2812 eval ${_UNSET} pc_i
;
2813 eval ${_UNSET} pc_res
;
2814 if path_chop
"${pc_res}";
2816 eval "${return_ok}";
2818 eval "${return_bad}";
2823 ########################################################################
2824 # path_contains (<path> <dir>)
2826 # Test whether `dir' is contained in `path', a list separated by `:'.
2828 # Arguments : 2 arguments.
2829 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
2833 func_check path_contains
= 2 "$@";
2836 eval "${return_yes}";
2839 eval "${return_no}";
2842 eval "${return_ok}";
2846 ########################################################################
2847 # path_not_contains (<path> <dir>)
2849 # Test whether `dir' is not contained in colon separated `path'.
2851 # Arguments : 2 arguments.
2855 func_check path_not_contains
= 2 "$@";
2856 if path_contains
"$1" "$2";
2858 eval "${return_no}";
2860 eval "${return_yes}";
2862 eval "${return_ok}";
2866 ########################################################################
2867 # path_split (<path>)
2869 # In `path' escape white space and replace each colon by a space.
2871 # Arguments: 1: a colon-separated path
2872 # Output: the resulting list, process with `eval set'
2876 func_check path_split
= 1 "$@";
2877 list_from_split
"$1" ':';
2878 eval "${return_ok}";
2882 ########################################################################
2883 landmark
'10: register_*()';
2884 ########################################################################
2886 ########################################################################
2887 # register_file (<filename>)
2889 # Write a found file and register the title element.
2891 # Arguments: 1: a file name
2896 func_check register_file
= 1 "$@";
2899 error
'register_file(): file name is empty';
2901 if is_equal
"$1" '-';
2903 to_tmp
"${_TMP_STDIN}";
2904 register_title
'stdin';
2907 register_title
"$(base_name "$1")";
2909 eval "${return_ok}";
2913 ########################################################################
2914 # register_title (<filespec>)
2916 # Create title element from <filespec> and append to $_REGISTERED_TITLE
2918 # Globals: $_REGISTERED_TITLE (rw)
2920 # Variable prefix: rt
2924 func_check register_title
= 1 "$@";
2927 eval "${return_ok}";
2929 rt_title
="$(base_name "$1")"; # remove directory part
2931 # remove extension `.gz'
2932 rt_title
="$(echo x"${rt_title}" | sed -e '
2936 # remove extension `.Z'
2937 rt_title
="$(echo x"${rt_title}" | sed -e '
2942 if obj rt_title is_empty
;
2944 eval "${return_ok}";
2946 _REGISTERED_TITLE
="${_REGISTERED_TITLE} ${rt_title}";
2947 eval ${_UNSET} rt_title
;
2948 eval "${return_ok}";
2952 ########################################################################
2955 # Reset the variables that can be affected by options to their default.
2958 # Defined in section `Preset' after the rudimentary shell tests.
2961 ########################################################################
2964 # Store standard input to temporary file (with decompression).
2966 # Variable prefix: ss
2968 if obj _HAS_COMPRESSION is_yes
;
2972 func_check save_stdin
= 0 "$@";
2973 ss_f
="${_TMP_DIR}"/INPUT
;
2975 cat_z
"${ss_f}" >"${_TMP_STDIN}";
2977 eval ${_UNSET} ss_f
;
2978 eval "${return_ok}";
2983 func_check save_stdin
= 0 "$@";
2984 cat >"${_TMP_STDIN}";
2985 eval "${return_ok}";
2990 ########################################################################
2991 landmark
'11: stack_*()';
2992 ########################################################################
2994 ########################################################################
2995 # string_contains (<string> <part>)
2997 # Test whether `part' is contained in `string'.
2999 # Arguments : 2 text arguments.
3000 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3004 func_check string_contains
= 2 "$@";
3007 eval "${return_yes}";
3010 eval "${return_no}";
3013 eval "${return_ok}";
3017 ########################################################################
3018 # string_not_contains (<string> <part>)
3020 # Test whether `part' is not substring of `string'.
3022 # Arguments : 2 text arguments.
3023 # Return : `0' if arg2 is substring of arg1, `1' otherwise.
3025 string_not_contains
()
3027 func_check string_not_contains
= 2 "$@";
3028 if string_contains
"$1" "$2";
3030 eval "${return_no}";
3032 eval "${return_yes}";
3034 eval "${return_ok}";
3038 ########################################################################
3039 landmark
'12: tmp_*()';
3040 ########################################################################
3042 ########################################################################
3045 # output the temporary cat file (the concatenation of all input)
3049 func_check tmp_cat
'=' 0 "$@";
3051 eval "${return_var}" "$?";
3055 ########################################################################
3056 # tmp_create (<suffix>?)
3058 # Create temporary file.
3060 # It's safe to use the shell process ID together with a suffix to
3061 # have multiple temporary files.
3063 # Globals: $_TMP_DIR
3065 # Output : name of created file
3067 # Variable prefix: tc
3071 func_check tmp_create
'<=' 1 "$@";
3072 # the output file does not have `,' as first character, so these are
3073 # different names from the output file.
3074 tc_tmp
="${_TMP_DIR}/,$1";
3079 eval ${_UNSET} tc_tmp
;
3080 eval "${return_ok}";
3084 ########################################################################
3085 # to_tmp (<filename>)
3087 # print file (decompressed) to the temporary cat file
3091 func_check to_tmp
= 1 "$@";
3094 if obj _OPT_LOCATION is_yes
;
3098 if obj _OPT_WHATIS is_yes
;
3100 what_is
"$1" >>"${_TMP_CAT}";
3102 cat_z
"$1" >>"${_TMP_CAT}";
3105 error
"to_tmp(): could not read file \`$1'.";
3107 eval "${return_ok}";
3111 ########################################################################
3114 # disable trap on all exit codes ($_ALL_EXIT)
3117 # Globals: $_ALL_EXIT
3121 func_check trap_clean
= 0 "$@";
3122 # for i in $_ALL_EXIT
3123 for i
in $
(eval set x
${_ALL_EXIT}; shift; echo "$@")
3125 trap "" "$i" 2>${_NULL_DEV} ||
:;
3127 eval "${return_ok}";
3131 ########################################################################
3132 # trap_set (<functionname>)
3134 # call function on all exit codes ($_ALL_EXIT)
3136 # Arguments: 1 (name of a shell function)
3137 # Globals: $_ALL_EXIT
3141 func_check trap_set
= 1 "$@";
3142 # for i in $_ALL_EXIT
3143 for i
in $
(eval set x
${_ALL_EXIT}; shift; echo "$@")
3145 trap "$1" "$i" 2>${_NULL_DEV} ||
:;
3147 eval "${return_ok}";
3151 ########################################################################
3154 # print usage information to stderr; for groffer option --help.
3158 func_check usage
= 0 "$@";
3161 echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';
3164 Display roff files, standard input, and/or Unix manual pages with a X
3165 Window viewer or in several text modes. All input is decompressed
3166 on-the-fly with all formats that gzip can handle.
3168 "filespec" is one of
3169 "filename" name of a readable file
3170 "-" for standard input
3171 "man:name.n" man page "name" in section "n"
3172 "man:name" man page "name" in first section found
3173 "name.n" man page "name" in section "n"
3174 "name" man page "name" in first section found
3175 and some more (see groffer(1) for details).
3177 -h --help print this usage message.
3178 -Q --source output as roff source.
3179 -T --device=name pass to groff using output device "name".
3180 -v --version print version information.
3181 -V display the groff execution pipe instead of formatting.
3182 -X --X --x display with "gxditview" using groff -X.
3183 -Z --ditroff --intermediate-output
3184 generate groff intermediate output without
3185 post-processing and viewing, like groff -Z.
3186 All other short options are interpreted as "groff" formatting options.
3188 The most important groffer long options are
3190 --apropos=name start man's "apropos" program for "name".
3192 "apropos" for "name" in man's data sections 4, 5, 7.
3193 --apropos-devel=name
3194 "apropos" for "name" in development sections 2, 3, 9.
3195 --apropos-progs=name
3196 "apropos" for "name" in man's program sections 1, 6, 8.
3197 --auto choose mode automatically from the default mode list.
3198 --default reset all options to the default value.
3199 --default-modes=mode1,mode2,...
3200 set sequence of automatically tried modes.
3201 --dvi display in a viewer for TeX device independent format.
3202 --dvi-viewer choose the viewer program for dvi mode.
3203 --groff process like groff, disable viewing features.
3204 --help display this helping output.
3205 --html --www display in a web browser.
3206 --html-viewer choose the web browser for www mode.
3207 --man check file parameters first whether they are man pages.
3208 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
3209 choose display mode.
3210 --no-man disable man-page facility.
3211 --pager=program preset the paging program for tty mode.
3212 --pdf display in a PDF viewer.
3213 --pdf-viewer choose the viewer program for pdf mode.
3214 --ps display in a Postscript viewer.
3215 --ps-viewer choose the viewer program for ps mode.
3216 --shell specify shell under which to run this program.
3217 --text output in a text device without a pager.
3218 --tty display with a pager on text terminal even when in X.
3219 --www-viewer same as --html-viewer
3220 --x-viewer choose viewer program for x mode (X mode).
3221 --X-viewer same as "--xviewer".
3223 The usual X Windows toolkit options transformed into GNU long options
3224 --background=color, --bd=size, --bg=color, --bordercolor=color,
3225 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
3226 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
3227 --resolution=dpi, --rv, --title=text, --xrm=resource
3229 Long options of GNU "man"
3230 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
3231 --local-file=name, --location, --manpath=dir1:dir2:...,
3232 --sections=s1:s2:..., --systems=s1,s2,..., --whatis, --where, ...
3235 eval "${return_ok}";
3239 ########################################################################
3242 # print version information to stderr
3246 func_check version
= 0 "$@";
3247 echo2
"${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
3248 # also display groff's version, but not the called subprograms
3249 groff -v 2>&1 |
sed -e '/^ *$/q' |
sed -e '1s/^/is part of /' >&2;
3250 eval "${return_ok}";
3254 ########################################################################
3255 # warning (<string>)
3257 # Print warning to stderr
3261 echo2
"warning: $*";
3265 ########################################################################
3266 # what_is (<filename>)
3268 # Interpret <filename> as a man page and display its `whatis'
3269 # information as a fragment written in the groff language.
3271 # Variable prefix: wi
3275 func_check what_is
= 1 "$@";
3276 if is_not_file
"$1";
3278 error
"what_is(): argument is not a readable file."
3280 wi_dot
='^\.['"${_SPACE}${_TAB}"']*';
3286 # grep the line containing `.TH' macro, if any
3287 wi_res
="$(cat_z "$1" | sed -e '/'"${wi_dot}"'TH /p
3289 if obj wi_res is_not_empty
;
3290 then # traditional man style
3291 # get the text between the first and the second `.SH' macro, by
3292 # - delete up to first .SH;
3293 # - of this, print everything up to next .SH, and delete the rest;
3294 # - of this, delete the final .SH line;
3295 cat_z
"$1" |
sed -e '1,/'"${wi_dot}"'SH/d' \
3296 |
sed -e '1,/'"${wi_dot}"'SH/p
3298 |
sed -e '/'"${wi_dot}"'SH/d';
3299 eval ${_UNSET} wi_dot
;
3300 eval ${_UNSET} wi_res
;
3301 eval "${return_ok}";
3303 # grep the line containing `.Dd' macro, if any
3304 wi_res
="$(cat_z "$1" | sed -e '/'"${wi_dot}"'Dd /p
3306 if obj wi_res is_not_empty
;
3307 then # BSD doc style
3308 # get the text between the first and the second `.Nd' macro, by
3309 # - delete up to first .Nd;
3310 # - of this, print everything up to next .Nd, and delete the rest;
3311 # - of this, delete the final .Nd line;
3312 cat_z
"$1" |
sed -e '1,/'"${wi_dot}"'Nd/d' \
3313 |
sed -e '1,/'"${wi_dot}"'Nd/p
3315 |
sed -e '/'"${wi_dot}"'Nd/d';
3316 eval ${_UNSET} wi_dot
;
3317 eval ${_UNSET} wi_res
;
3318 eval "${return_ok}";
3320 echo 'is not a man page.';
3321 eval ${_UNSET} wi_dot
;
3322 eval ${_UNSET} wi_res
;
3323 eval "${return_bad}";
3327 ########################################################################
3328 # where_is (<program>)
3330 # Output path of a program if in $PATH.
3332 # Arguments : >=1 (empty allowed)
3333 # more args are ignored, this allows to specify progs with arguments
3334 # Return : `0' if arg1 is a program in $PATH, `1' otherwise.
3336 # Variable prefix: w
3340 func_check where_is
'>=' 1 "$@";
3342 if obj w_arg is_empty
;
3344 eval ${_UNSET} w_arg
;
3345 eval "${return_bad}";
3349 eval ${_UNSET} w_arg
;
3350 eval ${_UNSET} w_file
;
3351 if test -f "${w_arg}" && test -x "${w_arg}";
3353 eval "${return_ok}";
3355 eval "${return_bad}";
3359 eval set x
"$(path_split "${PATH}")";
3364 */) w_file
=${p}${w_arg}; ;;
3365 *) w_file
=${p}/${w_arg}; ;;
3367 if test -f "${w_file}" && test -x "${w_file}";
3372 eval ${_UNSET} w_arg
;
3373 eval ${_UNSET} w_file
;
3374 eval "${return_ok}";
3377 eval ${_UNSET} w_arg
;
3378 eval ${_UNSET} w_file
;
3379 eval "${return_bad}";
3383 ########################################################################
3385 ########################################################################
3387 # The main area contains the following parts:
3388 # - main_init(): initialize temporary files and set exit trap
3389 # - main_parse_MANOPT(): parse $MANOPT
3390 # - main_parse_args(): argument parsing
3391 # - main_set_mode (): determine the display mode
3392 # - main_do_fileargs(): process filespec arguments
3393 # - main_set_resources(): setup X resources
3394 # - main_display(): do the displaying
3395 # - main(): the main function that calls all main_*()
3397 # These parts are implemented as functions, being defined below in the
3398 # sequence they are called in the main() function.
3401 landmark
'13: main_init()';
3402 #######################################################################
3405 # set exit trap and create temporary files
3407 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
3409 # Variable prefix: mi
3413 func_check main_init
= 0 "$@";
3414 # call clean_up() on any signal
3417 # create temporary directory
3420 for d
in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
3421 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
3424 if obj mi_dir is_empty || obj mi_dir is_not_dir || \
3425 obj mi_dir is_not_writable
;
3432 _TMP_DIR
="${mi_dir}";
3435 _TMP_DIR
="${mi_dir}"'/';
3438 _TMP_DIR
="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
3439 if obj _TMP_DIR is_existing
;
3441 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3442 if obj _TMP_DIR is_existing
;
3444 mi_tdir_
="${_TMP_DIR}"_
;
3446 mi_tdir_n
="${mi_tdir_}${mi_n}";
3447 while obj mi_tdir_n is_existing
;
3449 eval rm -f -r "'${mi_tdir_n}'" >${_NULL_DEV} 2>&1;
3450 if obj mi_tdir_n is_existing
;
3452 # directory could not be removed
3453 mi_n
="$(expr "${mi_n}" + 1)";
3454 mi_tdir_n
="${mi_tdir_}${mi_n}";
3458 _TMP_DIR
="${mi_tdir_n}";
3461 eval mkdir
"${_TMP_DIR}";
3462 if is_not_equal
"$?" 0;
3464 if obj _TMP_DIR is_existing
;
3466 eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3471 if obj _TMP_DIR is_dir
&& obj _TMP_DIR is_writable
;
3473 # $_TMP_DIR can now be used as temporary directory
3476 if obj _TMP_DIR is_existing
;
3478 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;
3483 if obj _TMP_DIR is_empty
;
3486 Couldn't create a directory for storing temporary files.";
3489 _TMP_CAT
="$(tmp_create groffer_cat)";
3490 _TMP_STDIN
="$(tmp_create groffer_input)";
3492 # groffer configuration files
3493 # for f in $_CONF_FILES
3494 for f
in $
(eval set x
${_CONF_FILES}; shift; echo "$@")
3497 if obj mi_file is_file
;
3499 echo '_groffer_opt=""' >>${_TMP_CAT};
3500 # collect the lines starting with a minus
3501 cat "$mi_file" |
sed -e '
3503 s/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"/
3505 # prepend the collected information to $GROFFER_OPT
3506 echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
3509 eval . "${_TMP_CAT}";
3510 _TMP_CAT="$(tmp_create groffer_cat)";
3512 eval ${_UNSET} mi_dir;
3513 eval ${_UNSET} mi_file;
3514 eval ${_UNSET} mi_n;
3515 eval ${_UNSET} mi_tdir_;
3516 eval ${_UNSET} mi_tdir_n;
3517 eval "${return_ok}";
3521 landmark '14: main_parse_MANOPT
()';
3522 ########################################################################
3523 # main_parse_MANOPT ()
3525 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
3526 # string; found man arguments can be overwritten by the command line.
3529 # in: $MANOPT, $_OPTS_MANOPT_*
3531 # in/out: $GROFFER_OPT
3533 # Variable prefix: mpm
3537 func_check main_parse_MANOPT = 0 "$@";
3539 if obj MANOPT is_not_empty;
3541 MANOPT="$(echo x"${MANOPT}" | sed -e 's/^x'"${_SPACE}${_SPACE}"'*//')";
3543 if obj MANOPT is_empty;
3545 eval ${_UNSET} mpm_list;
3546 eval ${_UNSET} mpm_opt;
3547 eval "${return_ok}";
3549 # add arguments in $MANOPT by mapping them to groffer options
3550 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
3552 until test "$#" -le 0 || is_equal "$1" '--';
3556 case "${mpm_opt}" in
3558 list_append mpm_list '--ascii';
3561 list_append mpm_list '--all';
3568 list_append mpm_list '--debug';
3571 # undo all man options so far
3575 list_append mpm_list '--extension';
3579 list_append mpm_list '--whatis';
3587 # groffer's
--apropos takes an argument
, but man
's does not, so
3592 list_append mpm_list '--local-file';
3595 list_append mpm_list '--locale' "$1";
3599 list_append mpm_list '--systems' "$1";
3603 list_append mpm_list '--manpath' "$1";
3610 -P|--pager|--tty-viewer)
3611 list_append mpm_list '--pager' "$1";
3619 list_append mpm_list '--sections' "$1";
3627 list_append mpm_list '-T' "$1";
3637 -w|--where|--location)
3638 list_append mpm_list '--location';
3641 list_append mpm_list '-Z' "$1";
3644 # ignore all other options
3647 # append the 2 lists in $mpm_list and $GROFFER_OPT to $GROFFER_OPT
3648 if obj GROFFER_OPT is_empty;
3650 GROFFER_OPT="${mpm_list}";
3651 elif obj mpm_list is_not_empty;
3653 GROFFER_OPT="${mpm_list} ${GROFFER_OPT}";
3655 eval ${_UNSET} mpm_list;
3656 eval ${_UNSET} mpm_opt;
3657 eval "${return_ok}";
3658 } # main_parse_MANOPT()
3661 landmark '15: main_parse_args
()';
3662 ########################################################################
3663 # main_parse_args (<command_line_args>*)
3665 # Parse arguments; process options and filespec parameters
3667 # Arguments: pass the command line arguments unaltered.
3670 # out: $_OPT_*, $_ADDOPTS, $_FILEARGS
3672 # Variable prefix: mpa
3676 func_check main_parse_args '>=' 0 "$@";
3678 eval set x "${GROFFER_OPT}" '"$@"';
3681 eval set x "$(list_from_cmdline _OPTS_CMDLINE "$@")";
3684 # By the call of `eval', unnecessary quoting was removed. So the
3685 # positional shell parameters ($1, $2, ...) are now guaranteed to
3686 # represent an option or an argument to the previous option, if any;
3687 # then a `--' argument for separating options and
3688 # parameters; followed by the filespec parameters if any.
3690 # Note, the existence of arguments to options has already been checked.
3691 # So a check for `$#' or `--' should not be done for arguments.
3693 until test "$#" -le 0 || is_equal
"$1" '--';
3695 mpa_opt
="$1"; # $mpa_opt is fed into the option handler
3697 case "${mpa_opt}" in
3702 -Q|
--source) # output source code (`Quellcode').
3705 -T|
--device|
--troff-device) # device; arg
3707 _check_device_with_mode
;
3717 -Z|
--ditroff|
--intermediate-output) # groff intermediate output
3724 # delete leading `-'
3725 mpa_optchar
="$(echo x"${mpa_opt}" | sed -e 's/^x-//')";
3726 if list_has _OPTS_GROFF_SHORT_NA
"${mpa_optchar}";
3728 list_append _ADDOPTS_GROFF
"${mpa_opt}";
3729 elif list_has _OPTS_GROFF_SHORT_ARG
"${mpa_optchar}";
3731 list_append _ADDOPTS_GROFF
"${mpa_opt}" "$1";
3734 error
"main_parse_args(): Unknown option : \`$1'";
3740 --apropos) # run `apropos'
3746 --apropos-data) # run `apropos' for data sections
3747 apropos_run
"$1" |
grep '^[^(]*([457][^)]*)';
3752 --apropos-devel) # run `apropos' for development sections
3753 apropos_run
"$1" |
grep '^[^(]*([239][^)]*)';
3758 --apropos-progs) # run `apropos' for program sections
3759 apropos_run
"$1" |
grep '^[^(]*([168][^)]*)';
3765 list_append _ADDOPTS_GROFF
'-mtty-char';
3766 if obj _OPT_MODE is_empty
;
3771 --auto) # the default automatic mode
3774 --bd) # border color for viewers, arg;
3778 --bg|
--backgroud) # background color for viewers, arg;
3782 --bw) # border width for viewers, arg;
3786 --default) # reset variables to default
3789 --default-modes) # sequence of modes in auto mode; arg
3790 _OPT_DEFAULT_MODES
="$1";
3793 --debug) # only for development
3796 --display) # set X display, arg
3803 --dvi-viewer) # viewer program for dvi mode; arg
3804 _OPT_VIEWER_DVI
="$1";
3807 --extension) # the extension for man pages, arg
3808 _OPT_EXTENSION
="$1";
3811 --fg|
--foreground) # foreground color for viewers, arg;
3815 --fn|
--font) # set font for viewers, arg;
3819 --geometry) # window geometry for viewers, arg;
3826 --html|
--www) # display with web browser
3829 --html-viewer|
--www-viewer) # viewer program for html mode; arg
3830 _OPT_VIEWER_HTML
="$1";
3833 --iconic) # start viewers as icons
3836 --locale) # set language for man pages, arg
3837 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
3841 --local-file) # force local files; same as `--no-man'
3845 --location|
--where) # print file locations to stderr
3846 _OPT_LOCATION
='yes';
3848 --man) # force all file params to be man pages
3852 --manpath) # specify search path for man pages, arg
3853 # arg is colon-separated list of directories
3857 --mode) # display mode
3860 case "${mpa_arg}" in
3861 auto|
'') # search mode automatically among default
3864 groff) # pass input to plain groff
3867 html|www
) # display with a web browser
3870 dvi
) # display with xdvi viewer
3873 pdf
) # display with PDF viewer
3876 ps
) # display with Postscript viewer
3879 text
) # output on terminal
3882 tty
) # output on terminal
3885 X|x
) # output on X roff viewer
3888 Q|
source) # display source code
3892 error
"main_parse_args(): unknown mode ${mpa_arg}";
3896 --no-location) # disable former call to `--location'
3897 _OPT_LOCATION
='yes';
3899 --no-man) # disable search for man pages
3900 # the same as --local-file
3904 --pager) # set paging program for tty mode, arg
3911 --pdf-viewer) # viewer program for ps mode; arg
3912 _OPT_VIEWER_PDF
="$1";
3918 --ps-viewer) # viewer program for ps mode; arg
3919 _OPT_VIEWER_PS
="$1";
3922 --resolution) # set resolution for X devices, arg
3925 case "${mpa_arg}" in
3933 error
"main_parse_args(): \
3934 only resoutions of 75 or 100 dpi are supported";
3937 _OPT_RESOLUTION
="${mpa_dpi}";
3942 --sections) # specify sections for man pages, arg
3943 # arg is colon-separated list of section names
3948 # already done during the first run; so ignore the argument
3951 --systems) # man pages for different OS's, arg
3952 # argument is a comma-separated list
3956 --text) # text mode without pager
3959 --title) # title for X viewers; arg
3963 --tty) # tty mode, text with pager
3966 --text-device|
--tty-device) # device for tty mode; arg
3967 _OPT_TEXT_DEVICE
="$1";
3976 --xrm) # pass X resource string, arg;
3977 list_append _OPT_XRM
"$1";
3980 --x-viewer|
--X-viewer) # viewer program for x mode; arg
3985 error
'main_parse_args(): error on argument parsing : '"\`$*'";
3989 shift; # remove `--' argument
3991 if obj _DEBUG is_not_yes
;
3993 if obj _OPT_DEBUG is_yes
;
3997 _DEBUG_KEEP_FILES
='yes';
4001 # Remaining arguments are file names (filespecs).
4002 # Save them to list $_FILEARGS
4004 then # use "-" for standard input
4009 list_append _FILEARGS
"$@";
4010 if list_has _FILEARGS
'-';
4014 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
4015 eval ${_UNSET} mpa_arg
;
4016 eval ${_UNSET} mpa_code
;
4017 eval ${_UNSET} mpa_dpi
;
4018 eval ${_UNSET} mpa_opt
;
4019 eval ${_UNSET} mpa_optchar
;
4020 eval "${return_ok}";
4021 } # main_parse_args()
4024 # Called from main_parse_args() because double `case' is not possible.
4025 # Globals: $_OPT_DEVICE, $_OPT_MODE
4026 _check_device_with_mode
()
4028 func_check _check_device_with_mode
= 0 "$@";
4029 case "${_OPT_DEVICE}" in
4032 eval "${return_ok}";
4036 eval "${return_ok}";
4040 eval "${return_ok}";
4044 eval "${return_ok}";
4046 ascii|cp1047|latin1|utf8
)
4047 if obj _OPT_MODE is_not_equal text
;
4049 _OPT_MODE
=tty
; # default text mode
4051 eval "${return_ok}";
4055 eval "${return_ok}";
4057 *) # unknown device, go to groff mode
4059 eval "${return_ok}";
4062 eval "${return_error}";
4063 } # _check_device_with_mode() of main_parse_args()
4066 landmark
'16: main_set_mode()';
4067 ########################################################################
4070 # Determine the display mode.
4073 # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
4074 # out: $_DISPLAY_MODE
4076 # Variable prefix: msm
4080 func_check main_set_mode
= 0 "$@";
4083 if obj _OPT_APROPOS is_not_empty
;
4085 apropos
"${_OPT_APROPOS}";
4090 if obj _OPT_APROPOS_DATA is_not_empty
;
4092 apropos
"$@" |
grep '^[^(]*([457])';
4097 if obj _OPT_APROPOS_DEVEL is_not_empty
;
4099 apropos
"$@" |
grep '^[^(]*([239])';
4104 if obj _OPT_APROPOS_PROGS is_not_empty
;
4106 apropos
"$@" |
grep '^[^(]*([168])';
4113 if obj _OPT_DISPLAY is_not_empty
;
4115 DISPLAY
="${_OPT_DISPLAY}";
4118 if obj _OPT_V is_yes
;
4120 list_append _ADDOPTS_GROFF
'-V';
4122 if obj _OPT_Z is_yes
;
4124 _DISPLAY_MODE
='groff';
4125 list_append _ADDOPTS_GROFF
'-Z';
4127 if obj _OPT_MODE is_equal
'groff';
4129 _DISPLAY_MODE
='groff';
4131 if obj _DISPLAY_MODE is_equal
'groff';
4133 eval ${_UNSET} msm_code
;
4134 eval ${_UNSET} msm_modes
;
4135 eval ${_UNSET} msm_viewer
;
4136 eval ${_UNSET} msm_viewers
;
4137 eval "${return_ok}";
4140 if obj _OPT_MODE is_equal
'source';
4142 _DISPLAY_MODE
='source';
4143 eval ${_UNSET} msm_code
;
4144 eval ${_UNSET} msm_modes
;
4145 eval ${_UNSET} msm_viewer
;
4146 eval ${_UNSET} msm_viewers
;
4147 eval "${return_ok}";
4150 case "${_OPT_MODE}" in
4151 '') # automatic mode
4152 case "${_OPT_DEVICE}" in
4154 if obj DISPLAY is_empty
;
4156 error
"main_set_mode(): \
4157 no X display found for device ${_OPT_DEVICE}";
4160 eval ${_UNSET} msm_code
;
4161 eval ${_UNSET} msm_modes
;
4162 eval ${_UNSET} msm_viewer
;
4163 eval ${_UNSET} msm_viewers
;
4164 eval "${return_ok}";
4166 ascii|cp1047|latin1|utf8
)
4167 if obj _DISPLAY_MODE is_not_equal
'text';
4169 _DISPLAY_MODE
='tty';
4171 eval ${_UNSET} msm_code
;
4172 eval ${_UNSET} msm_modes
;
4173 eval ${_UNSET} msm_viewer
;
4174 eval ${_UNSET} msm_viewers
;
4175 eval "${return_ok}";
4178 if obj DISPLAY is_empty
;
4180 _DISPLAY_MODE
='tty';
4181 eval ${_UNSET} msm_code
;
4182 eval ${_UNSET} msm_modes
;
4183 eval ${_UNSET} msm_viewer
;
4184 eval ${_UNSET} msm_viewers
;
4185 eval "${return_ok}";
4188 if obj _OPT_DEFAULT_MODES is_empty
;
4190 msm_modes
="${_DEFAULT_MODES}";
4192 msm_modes
="${_OPT_DEFAULT_MODES}";
4196 _DISPLAY_MODE
='text';
4197 eval ${_UNSET} msm_code
;
4198 eval ${_UNSET} msm_modes
;
4199 eval ${_UNSET} msm_viewer
;
4200 eval ${_UNSET} msm_viewers
;
4201 eval "${return_ok}";
4204 _DISPLAY_MODE
='tty';
4205 eval ${_UNSET} msm_code
;
4206 eval ${_UNSET} msm_modes
;
4207 eval ${_UNSET} msm_viewer
;
4208 eval ${_UNSET} msm_viewers
;
4209 eval "${return_ok}";
4211 *) # display mode was given
4212 if obj DISPLAY is_empty
;
4214 error
"main_set_mode(): \
4215 you must be in X Window for ${_OPT_MODE} mode.";
4217 msm_modes
="${_OPT_MODE}";
4221 # only viewer modes are left
4222 eval set x
"$(list_from_split "${msm_modes}" ',')";
4224 while test "$#" -gt 0;
4230 _DISPLAY_MODE
='text';
4231 eval ${_UNSET} msm_code
;
4232 eval ${_UNSET} msm_modes
;
4233 eval ${_UNSET} msm_viewer
;
4234 eval ${_UNSET} msm_viewers
;
4235 eval "${return_ok}";
4238 _DISPLAY_MODE
='tty';
4239 eval ${_UNSET} msm_code
;
4240 eval ${_UNSET} msm_modes
;
4241 eval ${_UNSET} msm_viewer
;
4242 eval ${_UNSET} msm_viewers
;
4243 eval "${return_ok}";
4246 if obj _OPT_VIEWER_X is_not_empty
;
4248 msm_viewers
="${_OPT_VIEWER_X}";
4250 msm_viewers
="${_VIEWER_X}";
4252 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
4253 if is_not_equal
"$?" 0;
4257 _DISPLAY_PROG
="${msm_viewer}";
4259 eval ${_UNSET} msm_code
;
4260 eval ${_UNSET} msm_modes
;
4261 eval ${_UNSET} msm_viewer
;
4262 eval ${_UNSET} msm_viewers
;
4263 eval "${return_ok}";
4267 eval ${_UNSET} msm_code
;
4268 eval ${_UNSET} msm_modes
;
4269 eval ${_UNSET} msm_viewer
;
4270 eval ${_UNSET} msm_viewers
;
4271 eval "${return_ok}";
4274 if obj _OPT_VIEWER_DVI is_not_empty
;
4276 msm_viewers
="${_OPT_VIEWER_DVI}";
4278 msm_viewers
="${_VIEWER_DVI}";
4280 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
4281 if is_not_equal
"$?" 0;
4285 _DISPLAY_PROG
="${msm_viewer}";
4286 _DISPLAY_MODE
="dvi";
4287 eval ${_UNSET} msm_code
;
4288 eval ${_UNSET} msm_modes
;
4289 eval ${_UNSET} msm_viewer
;
4290 eval ${_UNSET} msm_viewers
;
4291 eval "${return_ok}";
4294 if obj _OPT_VIEWER_PDF is_not_empty
;
4296 msm_viewers
="${_OPT_VIEWER_PDF}";
4298 msm_viewers
="${_VIEWER_PDF}";
4300 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
4301 if is_not_equal
"$?" 0;
4305 _DISPLAY_PROG
="${msm_viewer}";
4306 _DISPLAY_MODE
="pdf";
4307 eval ${_UNSET} msm_code
;
4308 eval ${_UNSET} msm_modes
;
4309 eval ${_UNSET} msm_viewer
;
4310 eval ${_UNSET} msm_viewers
;
4311 eval "${return_ok}";
4314 if obj _OPT_VIEWER_PS is_not_empty
;
4316 msm_viewers
="${_OPT_VIEWER_PS}";
4318 msm_viewers
="${_VIEWER_PS}";
4320 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
4321 if is_not_equal
"$?" 0;
4325 _DISPLAY_PROG
="${msm_viewer}";
4327 eval ${_UNSET} msm_code
;
4328 eval ${_UNSET} msm_modes
;
4329 eval ${_UNSET} msm_viewer
;
4330 eval ${_UNSET} msm_viewers
;
4331 eval "${return_ok}";
4334 if obj _OPT_VIEWER_HTML is_not_empty
;
4336 msm_viewers
="${_OPT_VIEWER_HTML}";
4338 msm_viewers
="${_VIEWER_HTML}";
4340 msm_viewer
="$(_get_first_prog "${msm_viewers}")";
4341 if is_not_equal
"$?" 0;
4345 _DISPLAY_PROG
="${msm_viewer}";
4347 eval ${_UNSET} msm_code
;
4348 eval ${_UNSET} msm_modes
;
4349 eval ${_UNSET} msm_viewer
;
4350 eval ${_UNSET} msm_viewers
;
4351 eval "${return_ok}";
4355 eval ${_UNSET} msm_code
;
4356 eval ${_UNSET} msm_modes
;
4357 eval ${_UNSET} msm_viewer
;
4358 eval ${_UNSET} msm_viewers
;
4359 error
"main_set_mode(): no suitable display mode found.";
4363 # _get_first_prog (<proglist>)
4365 # Retrieve first argument that represents an existing program in $PATH.
4366 # Local function for main_set_mode().
4368 # Arguments: 1; a comma-separated list of commands (with options),
4371 # Return : `1' if none found, `0' if found.
4372 # Output : the argument that succeded.
4374 # Variable prefix: _gfp
4380 error
"_get_first_prog() needs 1 argument.";
4386 eval set x
"$(list_from_split "$1" ',')";
4391 if obj _gfp_i is_empty
;
4395 if eval is_prog
"$(get_first_essential ${_gfp_i})";
4400 eval ${_UNSET} _gfp_i
;
4404 eval ${_UNSET} _gfp_i
;
4406 } # _get_first_prog() of main_set_mode()
4409 landmark
'17: main_do_fileargs()';
4410 #######################################################################
4411 # main_do_fileargs ()
4413 # Process filespec arguments in $_FILEARGS.
4416 # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
4418 # Variable prefix: mdfa
4422 func_check main_do_fileargs
= 0 "$@";
4423 mdfa_exitcode
="${_BAD}";
4424 eval set x
"${_FILEARGS}";
4426 eval ${_UNSET} _FILEARGS
;
4427 # temporary storage of all input to $_TMP_CAT
4428 while test "$#" -ge 2;
4430 # test for `s name' arguments, with `s' a 1-char standard section
4433 case "${mdfa_filespec}" in
4438 if register_file
'-';
4440 mdfa_exitcode
="${_GOOD}";
4445 if list_has_not _MAN_AUTO_SEC
"${mdfa_filespec}";
4447 if do_filearg
"${mdfa_filespec}";
4449 mdfa_exitcode
="${_GOOD}";
4454 case "${mdfa_name}" in
4455 */*|man
:*|
*\
(*\
)|
*.
"${mdfa_filespec}")
4456 if do_filearg
"${mdfa_filespec}";
4458 mdfa_exitcode
="${_GOOD}";
4463 if do_filearg
"man:${mdfa_name}(${mdfa_filespec})";
4465 mdfa_exitcode
="${_GOOD}";
4469 if do_filearg
"${mdfa_filespec}";
4471 mdfa_exitcode
="${_GOOD}";
4477 if do_filearg
"${mdfa_filespec}";
4479 mdfa_exitcode
="${_GOOD}";
4484 done; # end of `s name' test
4485 while test "$#" -gt 0;
4489 if do_filearg
"${mdfa_filespec}";
4491 mdfa_exitcode
="${_GOOD}";
4494 if obj _DEBUG_KEEP_FILES is_not_yes
;
4496 rm -f "${_TMP_STDIN}";
4498 if is_equal
"${mdfa_exitcode}" "${_BAD}";
4500 eval ${_UNSET} mdfa_exitcode
;
4501 eval ${_UNSET} mdfa_filespec
;
4502 eval ${_UNSET} mdfa_name
;
4503 eval "${return_bad}";
4505 eval ${_UNSET} mdfa_exitcode
;
4506 eval ${_UNSET} mdfa_filespec
;
4507 eval ${_UNSET} mdfa_name
;
4508 eval "${return_ok}";
4509 } # main_do_fileargs()
4512 landmark
'18: main_set_resources()';
4513 ########################################################################
4514 # main_set_resources ()
4516 # Determine options for setting X resources with $_DISPLAY_PROG.
4518 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
4520 # Variable prefix: msr
4522 main_set_resources
()
4524 func_check main_set_resources
= 0 "$@";
4525 # $msr_prog viewer program
4526 # $msr_rl resource list
4527 msr_title
="$(get_first_essential \
4528 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
4529 _OUTPUT_FILE_NAME
='';
4530 eval set x
"${msr_title}";
4532 until is_equal
"$#" 0;
4540 msr_n
="$(echo x"$1" | sed -e 's/^x,,*//')";
4543 if obj msr_n is_empty
;
4547 if obj _OUTPUT_FILE_NAME is_not_empty
;
4549 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}"',';
4551 _OUTPUT_FILE_NAME
="${_OUTPUT_FILE_NAME}${msr_n}";
4554 case "${_OUTPUT_FILE_NAME}" in
4556 _OUTPUT_FILE_NAME
='-';
4559 error
"main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
4562 _OUTPUT_FILE_NAME
="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
4564 if obj _DISPLAY_PROG is_empty
;
4565 then # for example, for groff mode
4567 eval ${_UNSET} msr_n
;
4568 eval ${_UNSET} msr_prog
;
4569 eval ${_UNSET} msr_rl
;
4570 eval ${_UNSET} msr_title
;
4571 eval "${return_ok}";
4574 eval set x
"${_DISPLAY_PROG}";
4576 msr_prog
="$(base_name "$1")";
4578 if obj _OPT_BD is_not_empty
;
4580 case "${msr_prog}" in
4581 ghostview|gv|gxditview|xditview|xdvi
)
4582 list_append msr_rl
'-bd' "${_OPT_BD}";
4586 if obj _OPT_BG is_not_empty
;
4588 case "${msr_prog}" in
4589 ghostview|gv|gxditview|xditview|xdvi
)
4590 list_append msr_rl
'-bg' "${_OPT_BG}";
4593 list_append msr_rl
'-papercolor' "${_OPT_BG}";
4597 if obj _OPT_BW is_not_empty
;
4599 case "${msr_prog}" in
4600 ghostview|gv|gxditview|xditview|xdvi
)
4601 _list_append msr_rl
'-bw' "${_OPT_BW}";
4605 if obj _OPT_FG is_not_empty
;
4607 case "${msr_prog}" in
4608 ghostview|gv|gxditview|xditview|xdvi
)
4609 list_append msr_rl
'-fg' "${_OPT_FG}";
4613 if is_not_empty
"${_OPT_FN}";
4615 case "${msr_prog}" in
4616 ghostview|gv|gxditview|xditview|xdvi
)
4617 list_append msr_rl
'-fn' "${_OPT_FN}";
4621 if is_not_empty
"${_OPT_GEOMETRY}";
4623 case "${msr_prog}" in
4624 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4625 list_append msr_rl
'-geometry' "${_OPT_GEOMETRY}";
4629 if is_empty
"${_OPT_RESOLUTION}";
4631 _OPT_RESOLUTION
="${_DEFAULT_RESOLUTION}";
4632 case "${msr_prog}" in
4634 list_append msr_rl
'-resolution' "${_DEFAULT_RESOLUTION}";
4637 case "${_DEFAULT_RESOLUTION}" in
4640 list_append msr_rl
'-z' '104';
4643 list_append msr_rl
'-z' '139';
4649 case "${msr_prog}" in
4650 ghostview|gv|gxditview|xditview|xdvi
)
4651 list_append msr_rl
'-resolution' "${_OPT_RESOLUTION}";
4654 case "${_OPT_RESOLUTION}" in
4656 list_append msr_rl
'-z' '104';
4657 # '100' corresponds to 72dpi
4660 list_append msr_rl
'-z' '139';
4666 if is_yes
"${_OPT_ICONIC}";
4668 case "${msr_prog}" in
4669 ghostview|gv|gxditview|xditview|xdvi
)
4670 list_append msr_rl
'-iconic';
4674 if is_yes
"${_OPT_RV}";
4676 case "${msr_prog}" in
4677 ghostview|gv|gxditview|xditview|xdvi
)
4678 list_append msr_rl
'-rv';
4682 if is_not_empty
"${_OPT_XRM}";
4684 case "${msr_prog}" in
4685 ghostview|gv|gxditview|xditview|xdvi|xpdf
)
4686 eval set x
"${_OPT_XRM}";
4690 list_append msr_rl
'-xrm' "$i";
4695 if is_not_empty
"${msr_title}";
4697 case "${msr_prog}" in
4699 list_append msr_rl
'-title' "${msr_title}";
4703 _DISPLAY_ARGS
="${msr_rl}";
4704 eval ${_UNSET} msr_n
;
4705 eval ${_UNSET} msr_prog
;
4706 eval ${_UNSET} msr_rl
;
4707 eval ${_UNSET} msr_title
;
4708 eval "${return_ok}";
4709 } # main_set_resources
4712 landmark
'19: main_display()';
4713 ########################################################################
4716 # Do the actual display of the whole thing.
4719 # in: $_DISPLAY_MODE, $_OPT_DEVICE,
4720 # $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
4721 # $_REGISTERED_TITLE, $_TMP_CAT,
4722 # $_OPT_PAGER $PAGER, $_MANOPT_PAGER,
4723 # $_OUTPUT_FILE_NAME
4725 # Variable prefix: md
4729 func_check main_display
= 0 "$@";
4735 if obj _TMP_CAT is_non_empty_file
;
4737 md_modefile
="${_OUTPUT_FILE_NAME}";
4740 echo2
'groffer: empty input.';
4741 eval ${_UNSET} md_modefile
;
4742 eval "${return_ok}";
4744 case "${_DISPLAY_MODE}" in
4746 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4747 if obj _OPT_DEVICE is_not_empty
;
4749 _ADDOPTS_GROFF
="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
4751 md_groggy
="$(tmp_cat | eval grog "${md_options}")";
4753 if obj _OPT_V is_yes
;
4755 echo "File: ${md_modefile}";
4756 echo "Mode: ${_DISPLAY_MODE}";
4757 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4758 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4761 # start a new shell program to get another process ID.
4764 test -f "${md_modefile}" && rm -f "${md_modefile}";
4765 mv "${_TMP_CAT}" "${md_modefile}";
4766 cat "${md_modefile}" | \
4770 if test -d "${_TMP_DIR}";
4772 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
4775 trap clean_up 0 2>${_NULL_DEV} || :;
4776 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4781 case "${_OPT_DEVICE}" in
4783 md_device
="$(get_first_essential \
4784 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
4786 ascii|cp1047|latin1|utf8
)
4787 md_device
="${_OPT_DEVICE}";
4790 warning
"main_display(): \
4791 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4794 md_addopts
="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
4795 md_groggy
="$(tmp_cat | grog -T${md_device})";
4796 if obj _DISPLAY_MODE is_equal
'text';
4798 if obj _OPT_V is_yes
;
4800 echo "File: ${md_modefile}";
4801 echo "Mode: ${_DISPLAY_MODE}";
4802 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4803 eval "${md_groggy}" "${md_addopts}";
4805 tmp_cat |
eval "${md_groggy}" "${md_addopts}";
4809 for p
in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
4810 'less -r -R' 'more' 'pager' 'cat'
4813 if eval is_prog
${md_p};
4814 then # no "" for is_prog() allows args for $p
4819 if obj md_pager is_empty
;
4821 error
'main_display(): no pager program found for tty mode';
4823 if obj _OPT_V is_yes
;
4825 echo "File: ${md_modefile}";
4826 echo "Mode: ${_DISPLAY_MODE}";
4827 echo "Display program: ${md_pager}";
4828 eval "${md_groggy}" "${md_addopts}";
4830 tmp_cat |
eval "${md_groggy}" "${md_addopts}" | \
4844 case "${_OPT_DEVICE}" in
4845 ''|dvi
) do_nothing
; ;;
4847 warning
"main_display(): \
4848 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
4851 md_modefile
="${md_modefile}".dvi
;
4852 md_groggy
="$(tmp_cat | grog -Tdvi)";
4856 case "${_OPT_DEVICE}" in
4857 ''|html
) do_nothing
; ;;
4859 warning
"main_display(): \
4860 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4863 md_modefile
="${md_modefile}".html
;
4864 md_groggy
="$(tmp_cat | grog -Thtml)";
4868 case "${_OPT_DEVICE}" in
4873 warning
"main_display(): \
4874 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4877 md_groggy
="$(tmp_cat | grog -Tps)";
4879 if obj _OPT_V is_yes
;
4881 echo "File: ${md_modefile}.pdf";
4882 echo "Mode: ${_DISPLAY_MODE}";
4883 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4884 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
4887 # start a new shell program to get another process ID.
4890 _psfile="${md_modefile}.ps";
4891 md_modefile="${md_modefile}.pdf";
4892 test -f "${_psfile}" && rm -f "${_psfile}";
4893 test -f "${md_modefile}" && rm -f "${md_modefile}";
4894 cat "${_TMP_CAT}" | \
4895 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";
4896 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
4897 -sOutputFile="${md_modefile}" -c save pop -f "${_psfile}";
4898 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
4900 test -f "${_psfile}" && rm -f "${_psfile}";
4901 test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";
4905 if test -d "${_TMP_DIR}";
4907 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
4910 trap clean_up 0 2>${_NULL_DEV} || :;
4911 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
4916 case "${_OPT_DEVICE}" in
4921 warning
"main_display(): \
4922 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4925 md_modefile
="${md_modefile}".ps
;
4926 md_groggy
="$(tmp_cat | grog -Tps)";
4930 case "${_OPT_DEVICE}" in
4932 md_device
="${_OPT_DEVICE}"
4935 case "${_OPT_RESOLUTION}" in
4938 if obj _OPT_GEOMETRY is_empty
4940 case "${_DISPLAY_PROG}" in
4942 # add width of 800dpi for resolution of 100dpi to the args
4943 list_append _DISPLAY_ARGS
'-geometry' '800';
4953 md_groggy
="$(tmp_cat | grog -T${md_device} -Z)";
4957 case "${_OPT_DEVICE}" in
4959 md_groggy
="$(tmp_cat | grog -X)";
4961 X
*|dvi|html|lbp|lj4|ps
)
4962 # these devices work with
4963 md_groggy
="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
4966 warning
"main_display(): \
4967 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
4968 md_groggy
="$(tmp_cat | grog -Z)";
4974 error
"main_display(): unknown mode \`${_DISPLAY_MODE}'";
4977 eval ${_UNSET} md_addopts
;
4978 eval ${_UNSET} md_device
;
4979 eval ${_UNSET} md_groggy
;
4980 eval ${_UNSET} md_modefile
;
4981 eval ${_UNSET} md_options
;
4982 eval ${_UNSET} md_p
;
4983 eval ${_UNSET} md_pager
;
4984 eval "${return_ok}";
4988 # $md_modefile and $md_groggy come from main_display()
4991 func_check _do_display
= 0 "$@";
4993 if obj _OPT_V is_yes
;
4995 echo "File: ${md_modefile}";
4996 echo "Mode: ${_DISPLAY_MODE}";
4997 echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
4998 eval "${md_groggy}" "${_ADDOPTS_GROFF}";
5001 # start a new shell program for another process ID and better
5002 # cleaning-up of the temporary files.
5005 test -f "${md_modefile}" && rm -f "${md_modefile}";
5006 cat "${_TMP_CAT}" | \
5007 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
5008 if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;
5010 rm -f "${_TMP_CAT}";
5014 if test -d "${_TMP_DIR}";
5016 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;
5019 trap clean_up 0 2>${_NULL_DEV} || :;
5020 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";
5023 eval "${return_ok}";
5024 } # _do_display() of main_display()
5027 ########################################################################
5028 # main (<command_line_args>*)
5030 # The main function for groffer.
5036 func_check main
'>=' 0 "$@";
5037 # Do not change the sequence of the following functions!
5040 main_parse_args
"$@";
5045 eval "${return_ok}";
5048 landmark
'20: end of function definitions';
5050 ########################################################################