1#! /bin/sh 2 3# groffer - display groff files 4 5# Source file position: <groff-source>/contrib/groffer/groffer2.sh 6# Installed position: <prefix>/lib/groff/groffer/groffer2.sh 7 8# This file should not be run independently. It is called by 9# `groffer.sh' in the source or by the installed `groffer' program. 10 11# Copyright (C) 2001,2002,2003,2004,2005 12# Free Software Foundation, Inc. 13# Written by Bernd Warken 14 15# Last update: 22 August 2005 16 17# This file is part of `groffer', which is part of `groff'. 18 19# `groff' is free software; you can redistribute it and/or modify it 20# under the terms of the GNU General Public License as published by 21# the Free Software Foundation; either version 2, or (at your option) 22# any later version. 23 24# `groff' is distributed in the hope that it will be useful, but 25# WITHOUT ANY WARRANTY; without even the implied warranty of 26# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27# General Public License for more details. 28 29# You should have received a copy of the GNU General Public License 30# along with `groff'; see the files COPYING and LICENSE in the top 31# directory of the `groff' source. If not, write to the Free Software 32# Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, 33# USA. 34 35 36######################################################################## 37# Test of rudimentary shell functionality 38######################################################################## 39 40 41######################################################################## 42# Test of `unset' 43# 44export _UNSET; 45export _foo; 46_foo=bar; 47_res="$(unset _foo 2>&1)"; 48if unset _foo >${_NULL_DEV} 2>&1 && \ 49 test _"${_res}"_ = __ && test _"${_foo}"_ = __ 50then 51 _UNSET='unset'; 52 eval "${_UNSET}" _foo; 53 eval "${_UNSET}" _res; 54else 55 _UNSET=':'; 56fi; 57 58 59######################################################################## 60# Test of `test'. 61# 62if test a = a && test a != b && test -f "${_GROFFER_SH}" 63then 64 :; 65else 66 echo '"test" did not work.' >&2; 67 exit "${_ERROR}"; 68fi; 69 70 71######################################################################## 72# Test of `echo' and the `$()' construct. 73# 74if echo '' >${_NULL_DEV} 75then 76 :; 77else 78 echo '"echo" did not work.' >&2; 79 exit "${_ERROR}"; 80fi; 81if test _"$(t1="$(echo te)" && 82 t2="$(echo '')" && 83 t3="$(echo 'st')" && 84 echo "${t1}${t2}${t3}")"_ \ 85 != _test_ 86then 87 echo 'The "$()" construct did not work' >&2; 88 exit "${_ERROR}"; 89fi; 90 91 92######################################################################## 93# Test of sed program; test in groffer.sh is not valid here. 94# 95if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_ 96then 97 echo 'The sed program did not work.' >&2; 98 exit "${_ERROR}"; 99fi; 100 101 102######################################################################## 103# Test of function definitions. 104# 105_t_e_s_t_f_u_n_c_() 106{ 107 return 0; 108} 109 110if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV} 111then 112 :; 113else 114 echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2; 115 exit "${_ERROR}"; 116fi; 117 118 119######################################################################## 120# debug - diagnostic messages 121######################################################################## 122 123export _DEBUG_STACKS; 124_DEBUG_STACKS='no'; # disable stack output in each function 125#_DEBUG_STACKS='yes'; # enable stack output in each function 126 127export _DEBUG_LM; 128_DEBUG_LM='no'; # disable landmark messages 129#_DEBUG_LM='yes'; # enable landmark messages 130 131export _DEBUG_KEEP_FILES; 132_DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir 133#_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir 134 135export _DEBUG_PRINT_PARAMS; 136_DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters 137#_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters 138 139export _DEBUG_PRINT_SHELL; 140_DEBUG_PRINT_SHELL='no'; # disable printing of the shell name 141#_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name 142 143export _DEBUG_PRINT_TMPDIR; 144_DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir 145#_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir 146 147export _DEBUG_USER_WITH_STACK; 148_DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user() 149#_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user() 150 151# determine all --debug* options 152case " $*" in 153*\ --debug*) 154 case " $* " in 155 *' --debug '*) 156 # _DEBUG_STACKS='yes'; 157 # _DEBUG_LM='yes'; 158 _DEBUG_KEEP_FILES='yes'; 159 _DEBUG_PRINT_PARAMS='yes'; 160 _DEBUG_PRINT_SHELL='yes'; 161 _DEBUG_PRINT_TMPDIR='yes'; 162 _DEBUG_USER_WITH_STACK='yes'; 163 ;; 164 esac; 165 d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\ 166'--debug-stacks --debug-tmpdir --debug-user '; 167 for i 168 do 169 case "$i" in 170 --debug-s) 171 echo 'The abbreviation --debug-s has multiple options: '\ 172'--debug-shell and --debug-stacks.' >&2 173 exit "${_ERROR}"; 174 ;; 175 esac; 176 case "$d" in 177 *\ ${i}*) 178 # extract whole word of abbreviation $i 179 s="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p' 180$d 181EOF 182)" 183 case "$s" in 184 '') continue; ;; 185 --debug-all) 186 _DEBUG_STACKS='yes'; 187 _DEBUG_LM='yes'; 188 _DEBUG_KEEP_FILES='yes'; 189 _DEBUG_PRINT_PARAMS='yes'; 190 _DEBUG_PRINT_SHELL='yes'; 191 _DEBUG_PRINT_TMPDIR='yes'; 192 _DEBUG_USER_WITH_STACK='yes'; 193 ;; 194 --debug-keep) 195 _DEBUG_PRINT_TMPDIR='yes'; 196 _DEBUG_KEEP_FILES='yes'; 197 ;; 198 --debug-lm) 199 _DEBUG_LM='yes'; 200 ;; 201 --debug-params) 202 _DEBUG_PRINT_PARAMS='yes'; 203 ;; 204 --debug-shell) 205 _DEBUG_PRINT_SHELL='yes'; 206 ;; 207 --debug-stacks) 208 _DEBUG_STACKS='yes'; 209 ;; 210 --debug-tmpdir) 211 _DEBUG_PRINT_TMPDIR='yes'; 212 ;; 213 --debug-user) 214 _DEBUG_USER_WITH_STACK='yes'; 215 ;; 216 esac; 217 ;; 218 esac; 219 done 220 ;; 221esac; 222 223if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_ 224then 225 echo "parameters: $@" >&2; 226fi; 227 228if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_ 229then 230 if test _"${_SHELL}"_ = __ 231 then 232 if test _"${POSIXLY_CORRECT}"_ = _y_ 233 then 234 echo 'shell: bash as /bin/sh (none specified)' >&2; 235 else 236 echo 'shell: /bin/sh (none specified)' >&2; 237 fi; 238 else 239 echo "shell: ${_SHELL}" >&2; 240 fi; 241fi; 242 243 244######################################################################## 245# Environment Variables 246######################################################################## 247 248# Environment variables that exist only for this file start with an 249# underscore letter. Global variables to this file are written in 250# upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables 251# start with an underline and use only lower case letters and 252# underlines, e.g. $_local_variable . 253 254# [A-Z]* system variables, e.g. $MANPATH 255# _[A-Z_]* global file variables, e.g. $_MAN_PATH 256# _[a-z_]* temporary variables, e.g. $_manpath 257 258# Due to incompatibilities of the `ash' shell, the name of loop 259# variables in `for' must be single character 260# [a-z] local loop variables, e.g. $i 261 262 263######################################################################## 264# read-only variables (global to this file) 265######################################################################## 266 267# function return values; `0' means ok; other values are error codes 268export _ALL_EXIT; 269export _BAD; 270export _GOOD; 271export _NO; 272export _OK; 273export _YES; 274 275_GOOD='0'; # return ok 276_BAD='1'; # return negatively, error code `1' 277# $_ERROR was already defined as `7' in groffer.sh. 278 279_NO="${_BAD}"; 280_YES="${_GOOD}"; 281_OK="${_GOOD}"; 282 283# quasi-functions, call with `eval', e.g `eval "${return_ok}"' 284export return_ok; 285export return_good; 286export return_bad; 287export return_yes; 288export return_no; 289export return_error; 290export return_var; 291return_ok="func_pop; return ${_OK}"; 292return_good="func_pop; return ${_GOOD}"; 293return_bad="func_pop; return ${_BAD}"; 294return_yes="func_pop; return ${_YES}"; 295return_no="func_pop; return ${_NO}"; 296return_error="func_pop; return ${_ERROR}"; 297return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n' 298 299 300export _DEFAULT_MODES; 301_DEFAULT_MODES='x,ps,tty'; 302export _DEFAULT_RESOLUTION; 303_DEFAULT_RESOLUTION='75'; 304 305export _DEFAULT_TTY_DEVICE; 306_DEFAULT_TTY_DEVICE='latin1'; 307 308# _VIEWER_* viewer programs for different modes (only X is necessary) 309# _VIEWER_* a comma-separated list of viewer programs (with options) 310export _VIEWER_DVI; # viewer program for dvi mode 311export _VIEWER_HTML_TTY; # viewer program for html mode in tty 312export _VIEWER_HTML_X; # viewer program for html mode in X 313export _VIEWER_PDF; # viewer program for pdf mode 314export _VIEWER_PS; # viewer program for ps mode 315export _VIEWER_X; # viewer program for X mode 316_VIEWER_DVI='kdvi,xdvi,dvilx'; 317_VIEWER_HTML_TTY='lynx'; 318_VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena'; 319_VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf'; 320_VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs'; 321_VIEWER_X='gxditview,xditview'; 322 323# Search automatically in standard sections `1' to `8', and in the 324# traditional sections `9', `n', and `o'. On many systems, there 325# exist even more sections, mostly containing a set of man pages 326# special to a specific program package. These aren't searched for 327# automatically, but must be specified on the command line. 328export _MAN_AUTO_SEC_LIST; 329_MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"; 330export _MAN_AUTO_SEC_CHARS; 331_MAN_AUTO_SEC_CHARS='[123456789no]'; 332 333export _SPACE_SED; 334_SPACE_SED='['"${_SP}${_TAB}"']'; 335 336export _SPACE_CASE; 337_SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']'; 338 339export _PROCESS_ID; # for shutting down the program 340_PROCESS_ID="$$"; 341 342 343############ the command line options of the involved programs 344# 345# The naming scheme for the options environment names is 346# $_OPTS_<prog>_<length>[_<argspec>] 347# 348# <prog>: program name GROFFER, GROFF, or CMDLINE (for all 349# command line options) 350# <length>: LONG (long options) or SHORT (single character options) 351# <argspec>: ARG for options with argument, NA for no argument; 352# without _<argspec> both the ones with and without arg. 353# 354# Each option that takes an argument must be specified with a 355# trailing : (colon). 356 357# exports 358export _OPTS_GROFFER_SHORT_NA; 359export _OPTS_GROFFER_SHORT_ARG; 360export _OPTS_GROFFER_LONG_NA; 361export _OPTS_GROFFER_LONG_ARG; 362export _OPTS_GROFF_SHORT_NA; 363export _OPTS_GROFF_SHORT_ARG; 364export _OPTS_GROFF_LONG_NA; 365export _OPTS_GROFF_LONG_ARG; 366export _OPTS_X_SHORT_ARG; 367export _OPTS_X_SHORT_NA; 368export _OPTS_X_LONG_ARG; 369export _OPTS_X_LONG_NA; 370export _OPTS_MAN_SHORT_ARG; 371export _OPTS_MAN_SHORT_NA; 372export _OPTS_MAN_LONG_ARG; 373export _OPTS_MAN_LONG_NA; 374export _OPTS_MANOPT_SHORT_ARG; 375export _OPTS_MANOPT_SHORT_NA; 376export _OPTS_MANOPT_LONG_ARG; 377export _OPTS_MANOPT_LONG_NA; 378export _OPTS_CMDLINE_SHORT_NA; 379export _OPTS_CMDLINE_SHORT_ARG; 380export _OPTS_CMDLINE_LONG_NA; 381export _OPTS_CMDLINE_LONG_ARG; 382 383###### groffer native options 384 385_OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'"; 386_OPTS_GROFFER_SHORT_ARG="'T'"; 387 388_OPTS_GROFFER_LONG_NA="'auto' \ 389'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \ 390'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \ 391'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \ 392'groff' 'help' 'intermediate-output' 'html' 'man' \ 393'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \ 394'text' 'text-device' \ 395'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'"; 396 397_OPTS_GROFFER_LONG_ARG="\ 398'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \ 399'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \ 400'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \ 401'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \ 402'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'"; 403 404##### groffer options inhereted from groff 405 406_OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \ 407'R' 's' 'S' 't' 'U' 'z'"; 408_OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \ 409'w' 'W'"; 410_OPTS_GROFF_LONG_NA=""; 411_OPTS_GROFF_LONG_ARG=""; 412 413##### groffer options inhereted from the X Window toolkit 414 415_OPTS_X_SHORT_NA=""; 416_OPTS_X_SHORT_ARG=""; 417 418_OPTS_X_LONG_NA="'iconic' 'rv'"; 419 420_OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \ 421'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \ 422'resolution' 'title' 'xrm'"; 423 424###### groffer options inherited from man 425 426_OPTS_MAN_SHORT_NA=""; 427_OPTS_MAN_SHORT_ARG=""; 428 429_OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \ 430'local-file' 'location' 'troff' 'update'"; 431 432_OPTS_MAN_LONG_ARG="'locale' 'manpath' \ 433'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'"; 434 435###### additional options for parsing $MANOPT only 436 437_OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \ 438'V' 'w' 'Z'"; 439_OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'"; 440 441_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \ 442'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \ 443'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'"; 444 445_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \ 446'config_file' 'encoding' 'extension' 'locale'"; 447 448###### collections of command line options 449 450_OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \ 451${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}"; 452_OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \ 453${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}"; 454 455_OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \ 456${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}"; 457_OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \ 458${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}"; 459 460 461######################################################################## 462# read-write variables (global to this file) 463######################################################################## 464 465export _ALL_PARAMS; # All options and file name parameters 466export _ADDOPTS_GROFF; # Transp. options for groff (`eval'). 467export _ADDOPTS_POST; # Transp. options postproc (`eval'). 468export _ADDOPTS_X; # Transp. options X postproc (`eval'). 469export _APROPOS_PROG; # Program to run apropos. 470export _APROPOS_SECTIONS; # Sections for different --apropos-*. 471export _DEFAULT_MODES; # Set default modes. 472export _DISPLAY_MODE; # Display mode. 473export _DISPLAY_PROG; # Viewer program to be used for display. 474export _DISPLAY_ARGS; # X resources for the viewer program. 475export _FILEARGS; # Stores filespec parameters. 476export _FILESPEC_ARG; # Stores the actual filespec parameter. 477export _FUNC_STACK; # Store debugging information. 478export _REGISTERED_TITLE; # Processed file names. 479# _HAS_* from availability tests 480export _HAS_COMPRESSION; # `yes' if gzip compression is available 481export _HAS_BZIP; # `yes' if bzip2 compression is available 482# _MAN_* finally used configuration of man searching 483export _MAN_ALL; # search all man pages per filespec 484export _MAN_ENABLE; # enable search for man pages 485export _MAN_EXT; # extension for man pages 486export _MAN_FORCE; # force file parameter to be man pages 487export _MAN_IS_SETUP; # setup man variables only once 488export _MAN_LANG; # language for man pages 489export _MAN_LANG2; # language for man pages 490export _MAN_LANG_DONE; # language dirs added to man path 491export _MAN_PATH; # search path for man pages 492export _MAN_SEC; # sections for man pages; sep. `:' 493export _MAN_SEC_DONE; # sections added to man path 494export _MAN_SYS; # system names for man pages; sep. `,' 495export _MAN_SYS; # system names added to man path 496# _MANOPT_* as parsed from $MANOPT 497export _MANOPT_ALL; # $MANOPT --all 498export _MANOPT_EXTENSION; # $MANOPT --extension 499export _MANOPT_LANG; # $MANOPT --locale 500export _MANOPT_PATH; # $MANOPT --manpath 501export _MANOPT_PAGER; # $MANOPT --pager 502export _MANOPT_SEC; # $MANOPT --sections 503export _MANOPT_SYS; # $MANOPT --systems 504# _OPT_* as parsed from groffer command line 505export _OPT_ALL; # display all suitable man pages. 506export _OPT_APROPOS; # call `apropos' program. 507export _OPT_BD; # set border color in some modes. 508export _OPT_BG; # set background color in some modes. 509export _OPT_BW; # set border width in some modes. 510export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given. 511export _OPT_DEVICE; # device option. 512export _OPT_DO_NOTHING; # do nothing in main_display(). 513export _OPT_DISPLAY; # set X display. 514export _OPT_FG; # set foreground color in some modes. 515export _OPT_FN; # set font in some modes. 516export _OPT_GEOMETRY; # set size and position of viewer in X. 517export _OPT_ICONIC; # -iconic option for X viewers. 518export _OPT_LANG; # set language for man pages 519export _OPT_LOCATION; # print processed file names to stderr 520export _OPT_MODE; # values: X, tty, Q, Z, "" 521export _OPT_MANPATH; # manual setting of path for man-pages 522export _OPT_PAGER; # specify paging program for tty mode 523export _OPT_RESOLUTION; # set X resolution in dpi 524export _OPT_RV; # reverse fore- and background colors. 525export _OPT_SECTIONS; # sections for man page search 526export _OPT_SYSTEMS; # man pages of different OS's 527export _OPT_TITLE; # title for gxditview window 528export _OPT_TEXT_DEVICE; # set device for tty mode. 529export _OPT_V; # groff option -V. 530export _OPT_VIEWER_DVI; # viewer program for dvi mode 531export _OPT_VIEWER_PDF; # viewer program for pdf mode 532export _OPT_VIEWER_PS; # viewer program for ps mode 533export _OPT_VIEWER_HTML; # viewer program for html mode 534export _OPT_VIEWER_X; # viewer program for x mode 535export _OPT_WHATIS; # print the man description 536export _OPT_XRM; # specify X resource. 537export _OPT_Z; # groff option -Z. 538export _OUTPUT_FILE_NAME; # output generated, see main_set_res..() 539export _VIEWER_TERMINAL; # viewer options for terminal (--*-viewer-tty) 540# _TMP_* temporary directory and files 541export _TMP_DIR; # groffer directory for temporary files 542export _TMP_CAT; # stores concatenation of everything 543export _TMP_STDIN; # stores stdin, if any 544 545# these variables are preset in section `Preset' after the rudim. test 546 547 548######################################################################## 549# Preset and reset of read-write global variables 550######################################################################## 551 552 553export _START_DIR; # directory at start time of the script 554_START_DIR="$(pwd)"; 555 556# For variables that can be reset by option `--default', see reset(). 557 558_FILEARGS=''; 559 560# _HAS_* from availability tests 561_HAS_COMPRESSION=''; 562_HAS_BZIP=''; 563 564# _TMP_* temporary files 565_TMP_DIR=''; 566_TMP_CAT=''; 567_TMP_CONF=''; 568_TMP_STDIN=''; 569 570 571######################################################################## 572# reset () 573# 574# Reset the variables that can be affected by options to their default. 575# 576reset() 577{ 578 if test "$#" -ne 0 579 then 580 error "reset() does not have arguments."; 581 fi; 582 583 _ADDOPTS_GROFF=''; 584 _ADDOPTS_POST=''; 585 _ADDOPTS_X=''; 586 _APROPOS_PROG=''; 587 _APROPOS_SECTIONS=''; 588 _DISPLAY_ARGS=''; 589 _DISPLAY_MODE=''; 590 _DISPLAY_PROG=''; 591 _REGISTERED_TITLE=''; 592 593 # _MAN_* finally used configuration of man searching 594 _MAN_ALL='no'; 595 _MAN_ENABLE='yes'; # do search for man-pages 596 _MAN_EXT=''; 597 _MAN_FORCE='no'; # first local file, then search man page 598 _MAN_IS_SETUP='no'; 599 _MAN_LANG=''; 600 _MAN_LANG2=''; 601 _MAN_PATH=''; 602 _MAN_SEC=''; 603 _MAN_SEC_DONE='no'; 604 _MAN_SYS=''; 605 _MAN_SYS_DONE='no'; 606 607 # _MANOPT_* as parsed from $MANOPT 608 _MANOPT_ALL='no'; 609 _MANOPT_EXTENSION=''; 610 _MANOPT_LANG=''; 611 _MANOPT_PATH=''; 612 _MANOPT_PAGER=''; 613 _MANOPT_SEC=''; 614 _MANOPT_SYS=''; 615 616 # _OPT_* as parsed from groffer command line 617 _OPT_ALL='no'; 618 _OPT_APROPOS='no'; 619 _OPT_BD=''; 620 _OPT_BG=''; 621 _OPT_BW=''; 622 _OPT_DEFAULT_MODES=''; 623 _OPT_DEVICE=''; 624 _OPT_DISPLAY=''; 625 _OPT_DO_NOTHING='no'; 626 _OPT_FG=''; 627 _OPT_FN=''; 628 _OPT_GEOMETRY=''; 629 _OPT_ICONIC='no'; 630 _OPT_LANG=''; 631 _OPT_LOCATION='no'; 632 _OPT_MODE=''; 633 _OPT_MANPATH=''; 634 _OPT_PAGER=''; 635 _OPT_RESOLUTION=''; 636 _OPT_RV='no'; 637 _OPT_SECTIONS=''; 638 _OPT_SYSTEMS=''; 639 _OPT_TITLE=''; 640 _OPT_TEXT_DEVICE=''; 641 _OPT_V='no'; 642 _OPT_VIEWER_DVI=''; 643 _OPT_VIEWER_PDF=''; 644 _OPT_VIEWER_PS=''; 645 _OPT_VIEWER_HTML=''; 646 _OPT_VIEWER_X=''; 647 _OPT_WHATIS='no'; 648 _OPT_XRM=''; 649 _OPT_Z='no'; 650 _VIEWER_TERMINAL='no'; 651} 652 653reset; 654 655 656######################################################################## 657# Functions for error handling and debugging 658######################################################################## 659 660 661############## 662# echo1 (<text>*) 663# 664# Output to stdout. 665# 666# Arguments : arbitrary text including `-'. 667# 668echo1() 669{ 670 cat <<EOF 671$@ 672EOF 673} 674 675 676############## 677# echo2 (<text>*) 678# 679# Output to stderr. 680# 681# Arguments : arbitrary text. 682# 683echo2() 684{ 685 cat >&2 <<EOF 686$@ 687EOF 688} 689 690 691############## 692# landmark (<text>) 693# 694# Print <text> to standard error as a debugging aid. 695# 696# Globals: $_DEBUG_LM 697# 698landmark() 699{ 700 if test _"${_DEBUG_LM}"_ = _yes_ 701 then 702 echo2 "LM: $*"; 703 fi; 704} 705 706landmark "1: debugging functions"; 707 708 709############## 710# clean_up () 711# 712# Clean up at exit. 713# 714clean_up() 715{ 716 cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1; 717 if test _${_DEBUG_KEEP_FILES}_ = _yes_ 718 then 719 echo2 "Kept temporary directory ${_TMP_DIR}." 720 else 721 if test _"${_TMP_DIR}"_ != __ 722 then 723 if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}" 724 then 725 rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1; 726 fi; 727 fi; 728 fi; 729} 730 731 732############# 733# diag (text>*) 734# 735# Output a diagnostic message to stderr 736# 737diag() 738{ 739 echo2 '>>>>>'"$*"; 740} 741 742 743############# 744# error (<text>*) 745# 746# Print an error message to standard error, print the function stack, 747# exit with an error condition. The argument should contain the name 748# of the function from which it was called. This is for system errors. 749# 750error() 751{ 752 case "$#" in 753 1) echo2 'groffer error: '"$1"; ;; 754 *) echo2 'groffer error: wrong number of arguments in error().'; ;; 755 esac; 756 func_stack_dump; 757 if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" 758 then 759 : >"${_TMP_DIR}"/,error; 760 fi; 761 exit "${_ERROR}"; 762} 763 764 765############# 766# error_user (<text>*) 767# 768# Print an error message to standard error; exit with an error condition. 769# The error is supposed to be produce by the user. So the funtion stack 770# is omitted. 771# 772error_user() 773{ 774 case "$#" in 775 1) 776 echo2 'groffer error: '"$1"; 777 ;; 778 *) 779 echo2 'groffer error: wrong number of arguments in error_user().'; 780 ;; 781 esac; 782 if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_ 783 then 784 func_stack_dump; 785 fi; 786 if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" 787 then 788 : >"${_TMP_DIR}"/,error; 789 fi; 790 exit "${_ERROR}"; 791} 792 793 794############# 795# exit_test () 796# 797# Test whether the former command ended with error(). Exit again. 798# 799# Globals: $_ERROR 800# 801exit_test() 802{ 803 if test "$?" = "${_ERROR}" 804 then 805 exit ${_ERROR}; 806 fi; 807 if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error 808 then 809 exit ${_ERROR}; 810 fi; 811} 812 813 814############# 815# func_check (<func_name> <rel_op> <nr_args> "$@") 816# 817# Check number of arguments and register to _FUNC_STACK. 818# 819# Arguments: >=3 820# <func_name>: name of the calling function. 821# <rel_op>: a relational operator: = != < > <= >= 822# <nr_args>: number of arguments to be checked against <operator> 823# "$@": the arguments of the calling function. 824# 825# Variable prefix: fc 826# 827func_check() 828{ 829 if test "$#" -lt 3 830 then 831 error 'func_check() needs at least 3 arguments.'; 832 fi; 833 fc_fname="$1"; 834 case "$3" in 835 1) 836 fc_nargs="$3"; 837 fc_s=''; 838 ;; 839 0|[2-9]) 840 fc_nargs="$3"; 841 fc_s='s'; 842 ;; 843 *) 844 error "func_check(): third argument must be a digit."; 845 ;; 846 esac; 847 case "$2" in 848 '='|'-eq') 849 fc_op='-eq'; 850 fc_comp='exactly'; 851 ;; 852 '>='|'-ge') 853 fc_op='-ge'; 854 fc_comp='at least'; 855 ;; 856 '<='|'-le') 857 fc_op='-le'; 858 fc_comp='at most'; 859 ;; 860 '<'|'-lt') 861 fc_op='-lt'; 862 fc_comp='less than'; 863 ;; 864 '>'|'-gt') 865 fc_op='-gt'; 866 fc_comp='more than'; 867 ;; 868 '!='|'-ne') 869 fc_op='-ne'; 870 fc_comp='not'; 871 ;; 872 *) 873 error \ 874 'func_check(): second argument is not a relational operator.'; 875 ;; 876 esac; 877 shift; 878 shift; 879 shift; 880 if test "$#" "${fc_op}" "${fc_nargs}" 881 then 882 do_nothing; 883 else 884 error "func_check(): \ 885${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.'; 886 fi; 887 func_push "${fc_fname}"; 888 if test _"${_DEBUG_STACKS}"_ = _yes_ 889 then 890 echo2 '+++ '"${fc_fname} $@"; 891 echo2 '>>> '"${_FUNC_STACK}"; 892 fi; 893 eval ${_UNSET} fc_comp; 894 eval ${_UNSET} fc_fname; 895 eval ${_UNSET} fc_nargs; 896 eval ${_UNSET} fc_op; 897 eval ${_UNSET} fc_s; 898} 899 900 901############# 902# func_pop () 903# 904# Retrieve the top element from the stack. 905# 906# The stack elements are separated by `!'; the popped element is 907# identical to the original element, except that all `!' characters 908# were removed. 909# 910# Arguments: 1 911# 912func_pop() 913{ 914 if test "$#" -ne 0 915 then 916 error 'func_pop() does not have arguments.'; 917 fi; 918 case "${_FUNC_STACK}" in 919 '') 920 if test _"${_DEBUG_STACKS}"_ = _yes_ 921 then 922 error 'func_pop(): stack is empty.'; 923 fi; 924 ;; 925 *!*) 926 # split at first bang `!'. 927 _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')"; 928 exit_test; 929 ;; 930 *) 931 _FUNC_STACK=''; 932 ;; 933 esac; 934 if test _"${_DEBUG_STACKS}"_ = _yes_ 935 then 936 echo2 '<<< '"${_FUNC_STACK}"; 937 fi; 938} 939 940 941############# 942# func_push (<element>) 943# 944# Store another element to stack. 945# 946# The stack elements are separated by `!'; if <element> contains a `!' 947# it is removed first. 948# 949# Arguments: 1 950# 951# Variable prefix: fp 952# 953func_push() 954{ 955 if test "$#" -ne 1 956 then 957 error 'func_push() needs 1 argument.'; 958 fi; 959 case "$1" in 960 *'!'*) 961 # remove all bangs `!'. 962 fp_element="$(echo1 "$1" | sed -e 's/!//g')"; 963 exit_test; 964 ;; 965 *) 966 fp_element="$1"; 967 ;; 968 esac; 969 if test _"${_FUNC_STACK}"_ = __ 970 then 971 _FUNC_STACK="${fp_element}"; 972 else 973 _FUNC_STACK="${fp_element}!${_FUNC_STACK}"; 974 fi; 975 eval ${_UNSET} fp_element; 976} 977 978 979############# 980# func_stack_dump () 981# 982# Print the content of the stack. Ignore the arguments. 983# 984func_stack_dump() 985{ 986 diag 'call stack: '"${_FUNC_STACK}"; 987} 988 989 990######################################################################## 991# System Test 992######################################################################## 993 994landmark "2: system test"; 995 996# Test the availability of the system utilities used in this script. 997 998 999######################################################################## 1000# Test of function `sed'. 1001# 1002 1003if test _"$(echo xTesTx \ 1004 | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \ 1005 | sed -e 's|T|t|g')"_ != _test_ 1006then 1007 error 'Test of "sed" command failed.'; 1008fi; 1009 1010 1011######################################################################## 1012# Test of function `cat'. 1013# 1014if test _"$(echo test | cat)"_ != _test_ 1015then 1016 error 'Test of "cat" command failed.'; 1017fi; 1018 1019 1020######################################################################## 1021# Test for compression. 1022# 1023if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_ 1024then 1025 _HAS_COMPRESSION='yes'; 1026 if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \ 1027 && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \ 1028 | bzip2 -d -c 2>${_NULL_DEV})"_ \ 1029 = _test_ 1030 then 1031 _HAS_BZIP='yes'; 1032 else 1033 _HAS_BZIP='no'; 1034 fi; 1035else 1036 _HAS_COMPRESSION='no'; 1037 _HAS_BZIP='no'; 1038fi; 1039 1040 1041######################################################################## 1042# Definition of normal Functions in alphabetical order 1043######################################################################## 1044landmark "3: functions"; 1045 1046######################################################################## 1047# apropos_filespec () 1048# 1049# Setup for the --apropos* options 1050# 1051apropos_filespec() 1052{ 1053 1054 func_check apropos_filespec '=' 0 "$@"; 1055 if obj _OPT_APROPOS is_yes 1056 then 1057 eval to_tmp_line \ 1058 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'"; 1059 exit_test; 1060 if obj _APROPOS_PROG is_empty 1061 then 1062 error 'apropos_filespec: apropos_setup() must be run first.'; 1063 fi; 1064 if obj _APROPOS_SECTIONS is_empty 1065 then 1066 if obj _OPT_SECTIONS is_empty 1067 then 1068 s='^.*(.*).*$'; 1069 else 1070 s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']'; 1071 fi; 1072 else 1073 s='^.*(['"${_APROPOS_SECTIONS}"']'; 1074 fi; 1075 eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \ 1076 sed -n -e ' 1077/^'"${_FILESPEC_ARG}"': /p 1078/'"$s"'/p 1079' | \ 1080 sort |\ 1081 sed -e ' 1082s/^\(.* (..*)\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/ 1083' >>"${_TMP_CAT}"; 1084 fi; 1085 eval "${return_ok}"; 1086} 1087 1088 1089######################################################################## 1090# apropos_setup () 1091# 1092# Setup for the --apropos* options 1093# 1094apropos_setup() 1095{ 1096 func_check apropos_setup '=' 0 "$@"; 1097 if obj _OPT_APROPOS is_yes 1098 then 1099 if is_prog apropos 1100 then 1101 _APROPOS_PROG='apropos'; 1102 elif is_prog man 1103 then 1104 if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV} 1105 then 1106 _APROPOS_PROG='man --apropos'; 1107 elif man -k man >${_NULL_DEV} 2>${_NULL_DEV} 1108 then 1109 _APROPOS_PROG='man -k'; 1110 fi; 1111 fi; 1112 if obj _APROPOS_PROG is_empty 1113 then 1114 error 'apropos_setup: no apropos program available.'; 1115 fi; 1116 to_tmp_line '.TH GROFFER APROPOS'; 1117 fi; 1118 eval "${return_ok}"; 1119} 1120 1121 1122######################################################################## 1123# base_name (<path>) 1124# 1125# Get the file name part of <path>, i.e. delete everything up to last 1126# `/' from the beginning of <path>. Remove final slashes, too, to get a 1127# non-empty output. 1128# 1129# Arguments : 1 1130# Output : the file name part (without slashes) 1131# 1132# Variable prefix: bn 1133# 1134base_name() 1135{ 1136 func_check base_name = 1 "$@"; 1137 bn_name="$1"; 1138 case "${bn_name}" in 1139 */) 1140 # delete all final slashes 1141 bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')"; 1142 exit_test; 1143 ;; 1144 esac; 1145 case "${bn_name}" in 1146 /|'') 1147 eval ${_UNSET} bn_name; 1148 eval "${return_bad}"; 1149 ;; 1150 */*) 1151 # delete everything before and including the last slash `/'. 1152 echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|'; 1153 ;; 1154 *) 1155 obj bn_name echo1; 1156 ;; 1157 esac; 1158 eval ${_UNSET} bn_name; 1159 eval "${return_ok}"; 1160} 1161 1162 1163######################################################################## 1164# cat_z (<file>) 1165# 1166# Decompress if possible or just print <file> to standard output. 1167# 1168# gzip, bzip2, and .Z decompression is supported. 1169# 1170# Arguments: 1, a file name. 1171# Output: the content of <file>, possibly decompressed. 1172# 1173if test _"${_HAS_COMPRESSION}"_ = _yes_ 1174then 1175 cat_z() 1176 { 1177 func_check cat_z = 1 "$@"; 1178 case "$1" in 1179 '') 1180 error 'cat_z(): empty file name'; 1181 ;; 1182 '-') 1183 error 'cat_z(): for standard input use save_stdin()'; 1184 ;; 1185 esac; 1186 if obj _HAS_BZIP is_yes 1187 then 1188 if bzip2 -t "$1" 2>${_NULL_DEV} 1189 then 1190 bzip2 -c -d "$1" 2>${_NULL_DEV}; 1191 eval "${return_ok}"; 1192 fi; 1193 fi; 1194 gzip -c -d -f "$1" 2>${_NULL_DEV}; 1195 eval "${return_ok}"; 1196 } 1197else 1198 cat_z() 1199 { 1200 func_check cat_z = 1 "$@"; 1201 cat "$1"; 1202 eval "${return_ok}"; 1203 } 1204fi; 1205 1206 1207######################################################################## 1208# clean_up () 1209# 1210# Do the final cleaning up before exiting; used by the trap calls. 1211# 1212# defined above 1213 1214 1215######################################################################## 1216# diag (<text>*) 1217# 1218# Print marked message to standard error; useful for debugging. 1219# 1220# defined above 1221 1222 1223######################################################################## 1224landmark '4: dirname()*'; 1225######################################################################## 1226 1227####################################################################### 1228# dirname_append (<dir> <name>) 1229# 1230# Append `name' to `dir' with clean handling of `/'. 1231# 1232# Arguments : 2 1233# Output : the generated new directory name <dir>/<name> 1234# 1235dirname_append() 1236{ 1237 func_check dirname_append = 2 "$@"; 1238 if is_empty "$1" 1239 then 1240 error "dir_append(): first argument is empty."; 1241 fi; 1242 if is_empty "$2" 1243 then 1244 echo1 "$1"; 1245 else 1246 dirname_chop "$1"/"$2"; 1247 fi; 1248 eval "${return_ok}"; 1249} 1250 1251 1252######################################################################## 1253# dirname_chop (<name>) 1254# 1255# Remove unnecessary slashes from directory name. 1256# 1257# Argument: 1, a directory name. 1258# Output: path without double, or trailing slashes. 1259# 1260# Variable prefix: dc 1261# 1262dirname_chop() 1263{ 1264 func_check dirname_chop = 1 "$@"; 1265 # replace all multiple slashes by a single slash `/'. 1266 dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')"; 1267 exit_test; 1268 case "${dc_res}" in 1269 ?*/) 1270 # remove trailing slash '/'; 1271 echo1 "${dc_res}" | sed -e 's|/$||'; 1272 ;; 1273 *) 1274 obj dc_res echo1 1275 ;; 1276 esac; 1277 eval ${_UNSET} dc_res; 1278 eval "${return_ok}"; 1279} 1280 1281 1282######################################################################## 1283# do_filearg (<filearg>) 1284# 1285# Append the file, man-page, or standard input corresponding to the 1286# argument to the temporary file. If this is compressed in the gzip 1287# or Z format it is decompressed. A title element is generated. 1288# 1289# Argument either: 1290# - name of an existing file. 1291# - `-' to represent standard input (several times allowed). 1292# - `man:name.(section)' the man-page for `name' in `section'. 1293# - `man:name.section' the man-page for `name' in `section'. 1294# - `man:name' the man-page for `name' in the lowest `section'. 1295# - `name.section' the man-page for `name' in `section'. 1296# - `name' the man-page for `name' in the lowest `section'. 1297# Globals : 1298# $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN 1299# 1300# Output : none 1301# Return : $_GOOD if found, ${_BAD} otherwise. 1302# 1303# Variable prefix: df 1304# 1305do_filearg() 1306{ 1307 func_check do_filearg = 1 "$@"; 1308 df_filespec="$1"; 1309 # store sequence into positional parameters 1310 case "${df_filespec}" in 1311 '') 1312 eval ${_UNSET} df_filespec; 1313 eval "${return_good}"; 1314 ;; 1315 '-') 1316 register_file '-'; 1317 eval ${_UNSET} df_filespec; 1318 eval "${return_good}"; 1319 ;; 1320 */*) # with directory part; so no man search 1321 set 'File'; 1322 ;; 1323 *) 1324 if obj _MAN_ENABLE is_yes 1325 then 1326 if obj _MAN_FORCE is_yes 1327 then 1328 set 'Manpage' 'File'; 1329 else 1330 set 'File' 'Manpage'; 1331 fi; 1332 else 1333 set 'File'; 1334 fi; 1335 ;; 1336 esac; 1337 for i 1338 do 1339 case "$i" in 1340 File) 1341 if test -f "${df_filespec}" 1342 then 1343 if test -r "${df_filespec}" 1344 then 1345 register_file "${df_filespec}"; 1346 eval ${_UNSET} df_filespec; 1347 eval ${_UNSET} df_no_man; 1348 eval "${return_good}"; 1349 else 1350 echo2 "could not read \`${df_filespec}'"; 1351 eval ${_UNSET} df_filespec; 1352 eval ${_UNSET} df_no_man; 1353 eval "${return_bad}"; 1354 fi; 1355 else 1356 if obj df_no_man is_not_empty 1357 then 1358 if obj _OPT_WHATIS is_yes 1359 then 1360 to_tmp_line "This is neither a file nor a man page." 1361 else 1362 echo2 "\`${df_filespec}' is neither a file nor a man page." 1363 fi; 1364 fi; 1365 df_no_file=yes; 1366 continue; 1367 fi; 1368 ;; 1369 Manpage) # parse filespec as man page 1370 if obj _MAN_IS_SETUP is_not_yes 1371 then 1372 man_setup; 1373 fi; 1374 if man_do_filespec "${df_filespec}" 1375 then 1376 eval ${_UNSET} df_filespec; 1377 eval ${_UNSET} df_no_file; 1378 eval "${return_good}"; 1379 else 1380 if obj df_no_file is_not_empty 1381 then 1382 if obj _OPT_WHATIS is_yes 1383 then 1384 to_tmp_line "This is neither a file nor a man page." 1385 else 1386 echo2 "\`${df_filespec}' is neither a file nor a man page." 1387 fi; 1388 fi; 1389 df_no_man=yes; 1390 continue; 1391 fi; 1392 ;; 1393 esac; 1394 done; 1395 eval ${_UNSET} df_filespec; 1396 eval ${_UNSET} df_no_file; 1397 eval ${_UNSET} df_no_man; 1398 eval "${return_bad}"; 1399} # do_filearg() 1400 1401 1402######################################################################## 1403# do_nothing () 1404# 1405# Dummy function. 1406# 1407do_nothing() 1408{ 1409 eval return "${_OK}"; 1410} 1411 1412 1413######################################################################## 1414# echo2 (<text>*) 1415# 1416# Print to standard error with final line break. 1417# 1418# defined above 1419 1420 1421######################################################################## 1422# error (<text>*) 1423# 1424# Print error message and exit with error code. 1425# 1426# defined above 1427 1428 1429######################################################################## 1430# exit_test () 1431# 1432# Test whether the former command ended with error(). Exit again. 1433# 1434# defined above 1435 1436 1437######################################################################## 1438# func_check (<func_name> <rel_op> <nr_args> "$@") 1439# 1440# Check number of arguments and register to _FUNC_STACK. 1441# 1442# Arguments: >=3 1443# <func_name>: name of the calling function. 1444# <rel_op>: a relational operator: = != < > <= >= 1445# <nr_args>: number of arguments to be checked against <operator> 1446# "$@": the arguments of the calling function. 1447# 1448# defined above 1449 1450######################################################################### 1451# func_pop () 1452# 1453# Delete the top element from the function call stack. 1454# 1455# defined above 1456 1457 1458######################################################################## 1459# func_push (<element>) 1460# 1461# Store another element to function call stack. 1462# 1463# defined above 1464 1465 1466######################################################################## 1467# func_stack_dump () 1468# 1469# Print the content of the stack. 1470# 1471# defined above 1472 1473 1474######################################################################## 1475# get_first_essential (<arg>*) 1476# 1477# Retrieve first non-empty argument. 1478# 1479# Return : `1' if all arguments are empty, `0' if found. 1480# Output : the retrieved non-empty argument. 1481# 1482# Variable prefix: gfe 1483# 1484get_first_essential() 1485{ 1486 func_check get_first_essential '>=' 0 "$@"; 1487 if is_equal "$#" 0 1488 then 1489 eval "${return_ok}"; 1490 fi; 1491 for i 1492 do 1493 gfe_var="$i"; 1494 if obj gfe_var is_not_empty 1495 then 1496 obj gfe_var echo1; 1497 eval ${_UNSET} gfe_var; 1498 eval "${return_ok}"; 1499 fi; 1500 done; 1501 eval ${_UNSET} gfe_var; 1502 eval "${return_bad}"; 1503} 1504 1505 1506######################################################################## 1507landmark '5: is_*()'; 1508######################################################################## 1509 1510######################################################################## 1511# is_dir (<name>) 1512# 1513# Test whether `name' is a directory. 1514# 1515# Arguments : 1 1516# Return : `0' if arg1 is a directory, `1' otherwise. 1517# 1518is_dir() 1519{ 1520 func_check is_dir '=' 1 "$@"; 1521 if test _"$1"_ != __ && test -d "$1" && test -r "$1" 1522 then 1523 eval "${return_yes}"; 1524 fi; 1525 eval "${return_no}"; 1526} 1527 1528 1529######################################################################## 1530# is_empty (<string>) 1531# 1532# Test whether `string' is empty. 1533# 1534# Arguments : <=1 1535# Return : `0' if arg1 is empty or does not exist, `1' otherwise. 1536# 1537is_empty() 1538{ 1539 func_check is_empty '=' 1 "$@"; 1540 if test _"$1"_ = __ 1541 then 1542 eval "${return_yes}"; 1543 fi; 1544 eval "${return_no}"; 1545} 1546 1547 1548######################################################################## 1549# is_equal (<string1> <string2>) 1550# 1551# Test whether `string1' is equal to <string2>. 1552# 1553# Arguments : 2 1554# Return : `0' both arguments are equal strings, `1' otherwise. 1555# 1556is_equal() 1557{ 1558 func_check is_equal '=' 2 "$@"; 1559 if test _"$1"_ = _"$2"_ 1560 then 1561 eval "${return_yes}"; 1562 fi; 1563 eval "${return_no}"; 1564} 1565 1566 1567######################################################################## 1568# is_existing (<name>) 1569# 1570# Test whether `name' is an existing file or directory. Solaris 2.5 does 1571# not have `test -e'. 1572# 1573# Arguments : 1 1574# Return : `0' if arg1 exists, `1' otherwise. 1575# 1576is_existing() 1577{ 1578 func_check is_existing '=' 1 "$@"; 1579 if test _"$1"_ = __ 1580 then 1581 eval "${return_no}"; 1582 fi; 1583 if test -f "$1" || test -d "$1" || test -c "$1" 1584 then 1585 eval "${return_yes}"; 1586 fi; 1587 eval "${return_no}"; 1588} 1589 1590 1591######################################################################## 1592# is_file (<name>) 1593# 1594# Test whether `name' is a readable file. 1595# 1596# Arguments : 1 1597# Return : `0' if arg1 is a readable file, `1' otherwise. 1598# 1599is_file() 1600{ 1601 func_check is_file '=' 1 "$@"; 1602 if is_not_empty "$1" && test -f "$1" && test -r "$1" 1603 then 1604 eval "${return_yes}"; 1605 fi; 1606 eval "${return_no}"; 1607} 1608 1609 1610######################################################################## 1611# is_non_empty_file (<file_name>) 1612# 1613# Test whether `file_name' is a non-empty existing file. 1614# 1615# Arguments : <=1 1616# Return : 1617# `0' if arg1 is a non-empty existing file 1618# `1' otherwise 1619# 1620is_non_empty_file() 1621{ 1622 func_check is_non_empty_file '=' 1 "$@"; 1623 if is_file "$1" && test -s "$1" 1624 then 1625 eval "${return_yes}"; 1626 fi; 1627 eval "${return_no}"; 1628} 1629 1630 1631######################################################################## 1632# is_not_dir (<name>) 1633# 1634# Test whether `name' is not a readable directory. 1635# 1636# Arguments : 1 1637# Return : `0' if arg1 is a directory, `1' otherwise. 1638# 1639is_not_dir() 1640{ 1641 func_check is_not_dir '=' 1 "$@"; 1642 if is_dir "$1" 1643 then 1644 eval "${return_no}"; 1645 fi; 1646 eval "${return_yes}"; 1647} 1648 1649 1650######################################################################## 1651# is_not_empty (<string>) 1652# 1653# Test whether `string' is not empty. 1654# 1655# Arguments : <=1 1656# Return : `0' if arg1 exists and is not empty, `1' otherwise. 1657# 1658is_not_empty() 1659{ 1660 func_check is_not_empty '=' 1 "$@"; 1661 if is_empty "$1" 1662 then 1663 eval "${return_no}"; 1664 fi; 1665 eval "${return_yes}"; 1666} 1667 1668 1669######################################################################## 1670# is_not_equal (<string1> <string2>) 1671# 1672# Test whether `string1' differs from `string2'. 1673# 1674# Arguments : 2 1675# 1676is_not_equal() 1677{ 1678 func_check is_not_equal '=' 2 "$@"; 1679 if is_equal "$1" "$2" 1680 then 1681 eval "${return_no}"; 1682 fi 1683 eval "${return_yes}"; 1684} 1685 1686 1687######################################################################## 1688# is_not_file (<filename>) 1689# 1690# Test whether `name' is a not readable file. 1691# 1692# Arguments : 1 (empty allowed) 1693# 1694is_not_file() 1695{ 1696 func_check is_not_file '=' 1 "$@"; 1697 if is_file "$1" 1698 then 1699 eval "${return_no}"; 1700 fi; 1701 eval "${return_yes}"; 1702} 1703 1704 1705######################################################################## 1706# is_not_prog ([<name> [<arg>*]]) 1707# 1708# Verify that arg is a not program in $PATH. 1709# 1710# Arguments : >=0 (empty allowed) 1711# more args are ignored, this allows to specify progs with arguments 1712# 1713is_not_prog() 1714{ 1715 func_check is_not_prog '>=' 0 "$@"; 1716 case "$#" in 1717 0) 1718 eval "${return_yes}"; 1719 ;; 1720 *) 1721 if where_is "$1" >${_NULL_DEV} 1722 then 1723 eval "${return_no}"; 1724 fi; 1725 ;; 1726 esac 1727 eval "${return_yes}"; 1728} 1729 1730 1731######################################################################## 1732# is_not_writable (<name>) 1733# 1734# Test whether `name' is a not a writable file or directory. 1735# 1736# Arguments : >=1 (empty allowed), more args are ignored 1737# 1738is_not_writable() 1739{ 1740 func_check is_not_writable '>=' 1 "$@"; 1741 if is_writable "$1" 1742 then 1743 eval "${return_no}"; 1744 fi; 1745 eval "${return_yes}"; 1746} 1747 1748 1749######################################################################## 1750# is_not_X () 1751# 1752# Test whether not running in X Window by checking $DISPLAY 1753# 1754is_not_X() 1755{ 1756 func_check is_X '=' 0 "$@"; 1757 if obj DISPLAY is_empty 1758 then 1759 eval "${return_yes}"; 1760 fi; 1761 eval "${return_no}"; 1762} 1763 1764 1765######################################################################## 1766# is_not_yes (<string>) 1767# 1768# Test whether `string' is not "yes". 1769# 1770# Arguments : 1 1771# 1772is_not_yes() 1773{ 1774 func_check is_not_yes = 1 "$@"; 1775 if is_yes "$1" 1776 then 1777 eval "${return_no}"; 1778 fi; 1779 eval "${return_yes}"; 1780} 1781 1782 1783######################################################################## 1784# is_prog ([<name> [<arg>*]]) 1785# 1786# Determine whether <name> is a program in $PATH 1787# 1788# Arguments : >=0 (empty allowed) 1789# <arg>* are ignored, this allows to specify progs with arguments. 1790# 1791is_prog() 1792{ 1793 func_check is_prog '>=' 0 "$@"; 1794 case "$#" in 1795 0) 1796 eval "${return_no}"; 1797 ;; 1798 *) 1799 if where_is "$1" >${_NULL_DEV} 1800 then 1801 eval "${return_yes}"; 1802 fi; 1803 ;; 1804 esac 1805 eval "${return_no}"; 1806} 1807 1808 1809######################################################################## 1810# is_writable (<name>) 1811# 1812# Test whether `name' is a writable file or directory. 1813# 1814# Arguments : >=1 (empty allowed), more args are ignored 1815# 1816is_writable() 1817{ 1818 func_check is_writable '>=' 1 "$@"; 1819 if test _"$1"_ = __ 1820 then 1821 eval "${return_no}"; 1822 fi; 1823 if test -r "$1" 1824 then 1825 if test -w "$1" 1826 then 1827 eval "${return_yes}"; 1828 fi; 1829 fi; 1830 eval "${return_no}"; 1831} 1832 1833 1834######################################################################## 1835# is_X () 1836# 1837# Test whether running in X Window by checking $DISPLAY 1838# 1839is_X() 1840{ 1841 func_check is_X '=' 0 "$@"; 1842 if obj DISPLAY is_not_empty 1843 then 1844 eval "${return_yes}"; 1845 fi; 1846 eval "${return_no}"; 1847} 1848 1849 1850######################################################################## 1851# is_yes (<string>) 1852# 1853# Test whether `string' has value "yes". 1854# 1855# Return : `0' if arg1 is `yes', `1' otherwise. 1856# 1857is_yes() 1858{ 1859 func_check is_yes '=' 1 "$@"; 1860 if is_equal "$1" 'yes' 1861 then 1862 eval "${return_yes}"; 1863 fi; 1864 eval "${return_no}"; 1865} 1866 1867 1868######################################################################## 1869# landmark () 1870# 1871# Print debugging information on standard error if $_DEBUG_LM is `yes'. 1872# 1873# Globals: $_DEBUG_LM 1874# 1875# Defined in section `Debugging functions'. 1876 1877 1878######################################################################## 1879# leave ([<code>]) 1880# 1881# Clean exit without an error or with <code>. 1882# 1883leave() 1884{ 1885 clean_up; 1886 if test $# = 0 1887 then 1888 exit "${_OK}"; 1889 else 1890 exit "$1"; 1891 fi; 1892} 1893 1894 1895######################################################################## 1896landmark '6: list_*()'; 1897######################################################################## 1898# 1899# `list' is an object class that represents an array or list. Its 1900# data consists of space-separated single-quoted elements. So a list 1901# has the form "'first' 'second' '...' 'last'". See list_append() for 1902# more details on the list structure. The array elements of `list' 1903# can be get by `eval set x "$list"; shift`. 1904 1905 1906######################################################################## 1907# list_append (<list> <element>...) 1908# 1909# Arguments: >=2 1910# <list>: a variable name for a list of single-quoted elements 1911# <element>: some sequence of characters. 1912# Output: none, but $<list> is set to 1913# if <list> is empty: "'<element>' '...'" 1914# otherwise: "$list '<element>' ..." 1915# 1916# Variable prefix: la 1917# 1918list_append() 1919{ 1920 func_check list_append '>=' 2 "$@"; 1921 la_name="$1"; 1922 eval la_list='"${'$1'}"'; 1923 shift; 1924 for s 1925 do 1926 la_s="$s"; 1927 case "${la_s}" in 1928 *\'*) 1929 # escape each single quote by replacing each 1930 # "'" (squote) by "'\''" (squote bslash squote squote); 1931 # note that the backslash must be doubled in the following `sed' 1932 la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')"; 1933 exit_test; 1934 ;; 1935 '') 1936 la_element=""; 1937 ;; 1938 *) 1939 la_element="${la_s}"; 1940 ;; 1941 esac; 1942 if obj la_list is_empty 1943 then 1944 la_list="'${la_element}'"; 1945 else 1946 la_list="${la_list} '${la_element}'"; 1947 fi; 1948 done; 1949 eval "${la_name}"='"${la_list}"'; 1950 eval ${_UNSET} la_element; 1951 eval ${_UNSET} la_list; 1952 eval ${_UNSET} la_name; 1953 eval ${_UNSET} la_s; 1954 eval "${return_ok}"; 1955} 1956 1957 1958######################################################################## 1959# list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...]) 1960# 1961# Transform command line arguments into a normalized form. 1962# 1963# Options, option arguments, and file parameters are identified and 1964# output each as a single-quoted argument of its own. Options and 1965# file parameters are separated by a '--' argument. 1966# 1967# Arguments: >=1 1968# <pre_name>: common part of a set of 4 environment variable names: 1969# $<pre_name>_SHORT_NA: list of short options without an arg. 1970# $<pre_name>_SHORT_ARG: list of short options that have an arg. 1971# $<pre_name>_LONG_NA: list of long options without an arg. 1972# $<pre_name>_LONG_ARG: list of long options that have an arg. 1973# <cmdline_arg>...: the arguments from a command line, such as "$@", 1974# the content of a variable, or direct arguments. 1975# 1976# Output: ['-[-]opt' ['optarg']]... '--' ['filename']... 1977# 1978# Example: 1979# list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2 1980# If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are 1981# none-empty option lists, this will result in printing: 1982# '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2' 1983# 1984# Use this function in the following way: 1985# eval set x "$(args_norm PRE_NAME "$@")"; 1986# shift; 1987# while test "$1" != '--'; do 1988# case "$1" in 1989# ... 1990# esac; 1991# shift; 1992# done; 1993# shift; #skip '--' 1994# # all positional parameters ("$@") left are file name parameters. 1995# 1996# Variable prefix: lfc 1997# 1998list_from_cmdline() 1999{ 2000 func_check list_from_cmdline '>=' 1 "$@"; 2001 lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument 2002 lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument 2003 lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument 2004 lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument 2005 exit_test; 2006 if obj lfc_short_n is_empty 2007 then 2008 error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.'; 2009 fi; 2010 if obj lfc_short_a is_empty 2011 then 2012 error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.'; 2013 fi; 2014 if obj lfc_long_n is_empty 2015 then 2016 error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.'; 2017 fi; 2018 if obj lfc_long_a is_empty 2019 then 2020 error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.'; 2021 fi; 2022 2023 shift; 2024 if is_equal "$#" 0 2025 then 2026 echo1 -- 2027 eval ${_UNSET} lfc_fparams; 2028 eval ${_UNSET} lfc_short_a; 2029 eval ${_UNSET} lfc_short_n; 2030 eval ${_UNSET} lfc_long_a; 2031 eval ${_UNSET} lfc_long_n; 2032 eval ${_UNSET} lfc_result; 2033 eval "${return_ok}"; 2034 fi; 2035 2036 lfc_fparams=''; 2037 lfc_result=''; 2038 while test "$#" -ge 1 2039 do 2040 lfc_arg="$1"; 2041 shift; 2042 case "${lfc_arg}" in 2043 --) break; ;; 2044 --*=*) 2045 # delete leading '--'; 2046 lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')"; 2047 lfc_with_equal="${lfc_abbrev}"; 2048 # extract option by deleting from the first '=' to the end 2049 lfc_abbrev="$(echo1 "${lfc_with_equal}" | \ 2050 sed -e 's/^\([^=]*\)=.*$/\1/')"; 2051 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; 2052 exit_test; 2053 if obj lfc_opt is_empty 2054 then 2055 error_user "--${lfc_abbrev} is not an option."; 2056 else 2057 # get the option argument by deleting up to first `=' 2058 lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')"; 2059 exit_test; 2060 list_append lfc_result "--${lfc_opt}" "${lfc_optarg}"; 2061 continue; 2062 fi; 2063 ;; 2064 --*) 2065 # delete leading '--'; 2066 lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')"; 2067 if list_has lfc_long_n "${lfc_abbrev}" 2068 then 2069 lfc_opt="${lfc_abbrev}"; 2070 else 2071 exit_test; 2072 lfc_opt="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")"; 2073 exit_test; 2074 if obj lfc_opt is_not_empty && is_not_equal "$#" 0 2075 then 2076 a="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; 2077 exit_test; 2078 if obj a is_not_empty 2079 then 2080 error_user "The abbreviation ${lfc_arg} \ 2081has multiple options: --${lfc_opt} and --${a}."; 2082 fi; 2083 fi; 2084 fi; 2085 if obj lfc_opt is_not_empty 2086 then 2087 # long option, no argument 2088 list_append lfc_result "--${lfc_opt}"; 2089 continue; 2090 fi; 2091 lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; 2092 exit_test; 2093 if obj lfc_opt is_not_empty 2094 then 2095 # long option with argument 2096 if test "$#" -le 0 2097 then 2098 error_user "no argument for option --${lfc_opt}." 2099 fi; 2100 list_append lfc_result "--${lfc_opt}" "$1"; 2101 shift; 2102 continue; 2103 fi; 2104 error_user "${lfc_arg} is not an option."; 2105 ;; 2106 -?*) # short option (cluster) 2107 # delete leading `-'; 2108 lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')"; 2109 exit_test; 2110 while obj lfc_rest is_not_empty 2111 do 2112 # get next short option from cluster (first char of $lfc_rest) 2113 lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')"; 2114 # remove first character from ${lfc_rest}; 2115 lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')"; 2116 exit_test; 2117 if list_has lfc_short_n "${lfc_optchar}" 2118 then 2119 list_append lfc_result "-${lfc_optchar}"; 2120 continue; 2121 elif list_has lfc_short_a "${lfc_optchar}" 2122 then 2123 if obj lfc_rest is_empty 2124 then 2125 if test "$#" -ge 1 2126 then 2127 list_append lfc_result "-${lfc_optchar}" "$1"; 2128 shift; 2129 continue; 2130 else 2131 error_user "no argument for option -${lfc_optchar}."; 2132 fi; 2133 else # rest is the argument 2134 list_append lfc_result "-${lfc_optchar}" "${lfc_rest}"; 2135 lfc_rest=''; 2136 continue; 2137 fi; 2138 else 2139 error_user "unknown option -${lfc_optchar}."; 2140 fi; 2141 done; 2142 ;; 2143 *) 2144 # Here, $lfc_arg is not an option, so a file parameter. 2145 list_append lfc_fparams "${lfc_arg}"; 2146 2147 # Ignore the strange POSIX option handling to end option 2148 # parsing after the first file name argument. To reuse it, do 2149 # a `break' here if $POSIXLY_CORRECT of `bash' is not empty. 2150 # When `bash' is called as `sh' $POSIXLY_CORRECT is set 2151 # automatically to `y'. 2152 ;; 2153 esac; 2154 done; 2155 list_append lfc_result '--'; 2156 if obj lfc_fparams is_not_empty 2157 then 2158 lfc_result="${lfc_result} ${lfc_fparams}"; 2159 fi; 2160 if test "$#" -gt 0 2161 then 2162 list_append lfc_result "$@"; 2163 fi; 2164 obj lfc_result echo1; 2165 eval ${_UNSET} lfc_abbrev; 2166 eval ${_UNSET} lfc_fparams; 2167 eval ${_UNSET} lfc_short_a; 2168 eval ${_UNSET} lfc_short_n; 2169 eval ${_UNSET} lfc_long_a; 2170 eval ${_UNSET} lfc_long_n; 2171 eval ${_UNSET} lfc_result; 2172 eval ${_UNSET} lfc_arg; 2173 eval ${_UNSET} lfc_opt; 2174 eval ${_UNSET} lfc_opt_arg; 2175 eval ${_UNSET} lfc_opt_char; 2176 eval ${_UNSET} lfc_with_equal; 2177 eval ${_UNSET} lfc_rest; 2178 eval "${return_ok}"; 2179} # list_from_cmdline() 2180 2181 2182######################################################################## 2183# list_from_split (<string> <separator>) 2184# 2185# In <string>, escape all white space characters and replace each 2186# <separator> by space. 2187# 2188# Arguments: 2: a <string> that is to be split into parts divided by 2189# <separator> 2190# Output: the resulting list string 2191# 2192# Variable prefix: lfs 2193# 2194list_from_split() 2195{ 2196 func_check list_from_split = 2 "$@"; 2197 2198 # precede each space or tab by a backslash `\' (doubled for `sed') 2199 lfs_s="$(echo1 "$1" | sed -e 's/\('"${_SPACE_SED}"'\)/\\\1/g')"; 2200 exit_test; 2201 2202 # replace split character of string by the list separator ` ' (space). 2203 case "$2" in 2204 /) # cannot use normal `sed' separator 2205 echo1 "${lfs_s}" | sed -e 's|'"$2"'| |g'; 2206 ;; 2207 ?) # use normal `sed' separator 2208 echo1 "${lfs_s}" | sed -e 's/'"$2"'/ /g'; 2209 ;; 2210 ??*) 2211 error 'list_from_split(): separator must be a single character.'; 2212 ;; 2213 esac; 2214 eval ${_UNSET} lfs_s; 2215 eval "${return_ok}"; 2216} 2217 2218 2219######################################################################## 2220# list_get (<list>) 2221# 2222# Check whether <list> is a space-separated list of '-quoted elements. 2223# 2224# If the test fails an error is raised. 2225# If the test succeeds the argument is echoed. 2226# 2227# Testing criteria: 2228# A list has the form "'first' 'second' '...' 'last'". So it has a 2229# leading and a final quote and the elements are separated by "' '" 2230# constructs. If these are all removed there should not be any 2231# unescaped single-quotes left. Watch out for escaped single 2232# quotes; they have the form '\'' (sq bs sq sq). 2233 2234# Arguments: 1 2235# Output: the argument <list> unchanged, if the check succeeded. 2236# 2237# Variable prefix: lg 2238# 2239list_get() 2240{ 2241 func_check list_get = 1 "$@"; 2242 eval lg_list='"${'$1'}"'; 2243 # remove leading and final space characters 2244 lg_list="$(echo1 "${lg_list}" | sed -e ' 2245s/^'"${_SPACE_SED}"'*// 2246s/'"${_SPACE_SED}"'*$// 2247')"; 2248 exit_test; 2249 case "${lg_list}" in 2250 '') 2251 eval ${_UNSET} lg_list; 2252 eval "${return_ok}"; 2253 ;; 2254 \'*\') 2255 obj lg_list echo1; 2256 eval ${_UNSET} lg_list; 2257 eval "${return_ok}"; 2258 ;; 2259 *) 2260 error "list_get(): bad list: $1" 2261 ;; 2262 esac; 2263 eval ${_UNSET} lg_list; 2264 eval "${return_ok}"; 2265} 2266 2267 2268######################################################################## 2269# list_has (<var_name> <element>) 2270# 2271# Test whether the list <var_name> has the element <element>. 2272# 2273# Arguments: 2 2274# <var_name>: a variable name for a list of single-quoted elements 2275# <element>: some sequence of characters. 2276# 2277# Variable prefix: lh 2278# 2279list_has() 2280{ 2281 func_check list_has = 2 "$@"; 2282 eval lh_list='"${'$1'}"'; 2283 if obj lh_list is_empty 2284 then 2285 eval "${_UNSET}" lh_list; 2286 eval "${return_no}"; 2287 fi; 2288 case "$2" in 2289 \'*\') lh_element=" $2 "; ;; 2290 *) lh_element=" '$2' "; ;; 2291 esac; 2292 if string_contains " ${lh_list} " "${lh_element}" 2293 then 2294 eval "${_UNSET}" lh_list; 2295 eval "${_UNSET}" lh_element; 2296 eval "${return_yes}"; 2297 else 2298 eval "${_UNSET}" lh_list; 2299 eval "${_UNSET}" lh_element; 2300 eval "${return_no}"; 2301 fi; 2302} 2303 2304 2305######################################################################## 2306# list_has_abbrev (<var_name> <abbrev>) 2307# 2308# Test whether the list <var_name> has an element starting with <abbrev>. 2309# 2310# Arguments: 2 2311# <var_name>: a variable name for a list of single-quoted elements 2312# <abbrev>: some sequence of characters. 2313# 2314# Variable prefix: lha 2315# 2316list_has_abbrev() 2317{ 2318 func_check list_has_abbrev = 2 "$@"; 2319 eval lha_list='"${'$1'}"'; 2320 if obj lha_list is_empty 2321 then 2322 eval "${_UNSET}" lha_list; 2323 eval "${return_no}"; 2324 fi; 2325 case "$2" in 2326 \'*) 2327 lha_element="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')"; 2328 exit_test; 2329 ;; 2330 *) lha_element="'$2"; ;; 2331 esac; 2332 if string_contains " ${lha_list}" " ${lha_element}" 2333 then 2334 eval "${_UNSET}" lha_list; 2335 eval "${_UNSET}" lha_element; 2336 eval "${return_yes}"; 2337 else 2338 eval "${_UNSET}" lha_list; 2339 eval "${_UNSET}" lha_element; 2340 eval "${return_no}"; 2341 fi; 2342 eval "${return_ok}"; 2343} 2344 2345 2346######################################################################## 2347# list_has_not (<list> <element>) 2348# 2349# Test whether <list> has no <element>. 2350# 2351# Arguments: 2 2352# <list>: a space-separated list of single-quoted elements. 2353# <element>: some sequence of characters. 2354# 2355# Variable prefix: lhn 2356# 2357list_has_not() 2358{ 2359 func_check list_has_not = 2 "$@"; 2360 eval lhn_list='"${'$1'}"'; 2361 if obj lhn_list is_empty 2362 then 2363 eval "${_UNSET}" lhn_list; 2364 eval "${return_yes}"; 2365 fi; 2366 case "$2" in 2367 \'*\') lhn_element=" $2 "; ;; 2368 *) lhn_element=" '$2' "; ;; 2369 esac; 2370 if string_contains " ${lhn_list} " "${lhn_element}" 2371 then 2372 eval "${_UNSET}" lhn_list; 2373 eval "${_UNSET}" lhn_element; 2374 eval "${return_no}"; 2375 else 2376 eval "${_UNSET}" lhn_list; 2377 eval "${_UNSET}" lhn_element; 2378 eval "${return_yes}"; 2379 fi; 2380} 2381 2382 2383######################################################################## 2384# list_single_from_abbrev (<list> <abbrev>) 2385# 2386# Check whether the list has an element starting with <abbrev>. If 2387# there are more than a single element an error is created. 2388# 2389# Arguments: 2 2390# <list>: a variable name for a list of single-quoted elements 2391# <abbrev>: some sequence of characters. 2392# 2393# Output: the found element. 2394# 2395# Variable prefix: lsfa 2396# 2397list_single_from_abbrev() 2398{ 2399 func_check list_single_from_abbrev = 2 "$@"; 2400 eval lsfa_list='"${'$1'}"'; 2401 if obj lsfa_list is_empty 2402 then 2403 eval "${_UNSET}" lsfa_list; 2404 eval "${return_no}"; 2405 fi; 2406 lsfa_abbrev="$2"; 2407 if list_has lsfa_list "${lsfa_abbrev}" 2408 then 2409 obj lsfa_abbrev echo1; 2410 eval "${_UNSET}" lsfa_abbrev; 2411 eval "${_UNSET}" lsfa_list; 2412 eval "${return_yes}"; 2413 fi; 2414 if list_has_abbrev lsfa_list "${lsfa_abbrev}" 2415 then 2416 lsfa_element=''; 2417 eval set x "${lsfa_list}"; 2418 shift; 2419 for i 2420 do 2421 case "$i" in 2422 ${lsfa_abbrev}*) 2423 if obj lsfa_element is_not_empty 2424 then 2425 error_user "The abbreviation --${lsfa_abbrev} \ 2426has multiple options: --${lsfa_element} and --${i}."; 2427 fi; 2428 lsfa_element="$i"; 2429 ;; 2430 esac; 2431 done; 2432 obj lsfa_element echo1; 2433 eval "${_UNSET}" lsfa_abbrev; 2434 eval "${_UNSET}" lsfa_element; 2435 eval "${_UNSET}" lsfa_list; 2436 eval "${return_yes}"; 2437 else 2438 eval "${_UNSET}" lsfa_abbrev; 2439 eval "${_UNSET}" lsfa_element; 2440 eval "${_UNSET}" lsfa_list; 2441 eval "${return_no}"; 2442 fi; 2443} 2444 2445 2446######################################################################## 2447landmark '7: man_*()'; 2448######################################################################## 2449 2450######################################################################## 2451# man_do_filespec (<filespec>) 2452# 2453# Print suitable man page(s) for filespec to $_TMP_CAT. 2454# 2455# Arguments : 2 2456# <filespec>: argument of the form `man:name.section', `man:name', 2457# `man:name(section)', `name.section', `name'. 2458# 2459# Globals : $_OPT_ALL 2460# 2461# Output : none. 2462# Return : `0' if man page was found, `1' else. 2463# 2464# Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE 2465# are assumed (see man_setup()). 2466# 2467# Variable prefix: mdf 2468# 2469man_do_filespec() 2470{ 2471 func_check man_do_filespec = 1 "$@"; 2472 if obj _MAN_PATH is_empty 2473 then 2474 eval "${return_bad}"; 2475 fi; 2476 if is_empty "$1" 2477 then 2478 eval "${return_bad}"; 2479 fi; 2480 mdf_spec="$1"; 2481 mdf_name=''; 2482 mdf_section=''; 2483 case "${mdf_spec}" in 2484 */*) # not a man spec with containing '/' 2485 eval ${_UNSET} mdf_got_one; 2486 eval ${_UNSET} mdf_name; 2487 eval ${_UNSET} mdf_section; 2488 eval ${_UNSET} mdf_spec; 2489 eval "${return_bad}"; 2490 ;; 2491 man:?*\(?*\)) # man:name(section) 2492 mdf_name="$(echo1 "${mdf_spec}" \ 2493 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')"; 2494 mdf_section="$(echo1 "${mdf_spec}" \ 2495 | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')"; 2496 exit_test; 2497 ;; 2498 man:?*.${_MAN_AUTO_SEC_CHARS}) # man:name.section 2499 mdf_name="$(echo1 "${mdf_spec}" \ 2500 | sed -e 's/^man:\(..*\)\..$/\1/')"; 2501 mdf_section="$(echo1 "${mdf_spec}" \ 2502 | sed -e 's/^.*\(.\)$/\1/')"; 2503 exit_test; 2504 ;; 2505 man:?*) # man:name 2506 mdf_name="$(echo1 "${mdf_spec}" | sed -e 's/^man://')"; 2507 exit_test; 2508 ;; 2509 ?*\(?*\)) # name(section) 2510 mdf_name="$(echo1 "${mdf_spec}" \ 2511 | sed -e 's/^\(..*\)(\(..*\))$/\1/')"; 2512 mdf_section="$(echo1 "${mdf_spec}" \ 2513 | sed -e 's/^\(..*\)(\(..*\))$/\2/')"; 2514 exit_test; 2515 ;; 2516 ?*.${_MAN_AUTO_SEC_CHARS}) # name.section 2517 mdf_name="$(echo1 "${mdf_spec}" \ 2518 | sed -e 's/^\(..*\)\..$/\1/')"; 2519 mdf_section="$(echo1 "${mdf_spec}" \ 2520 | sed -e 's/^.*\(.\)$/\1/')"; 2521 exit_test; 2522 ;; 2523 ?*) 2524 mdf_name="${mdf_spec}"; 2525 ;; 2526 esac; 2527 if obj mdf_name is_empty 2528 then 2529 eval ${_UNSET} mdf_got_one; 2530 eval ${_UNSET} mdf_name; 2531 eval ${_UNSET} mdf_section; 2532 eval ${_UNSET} mdf_spec; 2533 eval "${return_bad}"; 2534 fi; 2535 mdf_got_one='no'; 2536 if obj mdf_section is_empty 2537 then 2538 if obj _OPT_SECTIONS is_empty 2539 then 2540 eval set x "${_MAN_AUTO_SEC_LIST}"; 2541 else 2542 # use --sections when no section is given to filespec 2543 eval set x "$(echo1 "${_OPT_SECTIONS}" | sed -e 's/:/ /g')"; 2544 fi; 2545 shift; 2546 for s 2547 do 2548 mdf_s="$s"; 2549 if man_search_section "${mdf_name}" "${mdf_s}" 2550 then # found 2551 if obj _MAN_ALL is_yes 2552 then 2553 mdf_got_one='yes'; 2554 else 2555 eval ${_UNSET} mdf_got_one; 2556 eval ${_UNSET} mdf_name; 2557 eval ${_UNSET} mdf_s; 2558 eval ${_UNSET} mdf_section; 2559 eval ${_UNSET} mdf_spec; 2560 eval "${return_good}"; 2561 fi; 2562 fi; 2563 done; 2564 else 2565 if man_search_section "${mdf_name}" "${mdf_section}" 2566 then 2567 eval ${_UNSET} mdf_got_one; 2568 eval ${_UNSET} mdf_name; 2569 eval ${_UNSET} mdf_s; 2570 eval ${_UNSET} mdf_section; 2571 eval ${_UNSET} mdf_spec; 2572 eval "${return_good}"; 2573 else 2574 eval ${_UNSET} mdf_got_one; 2575 eval ${_UNSET} mdf_name; 2576 eval ${_UNSET} mdf_section; 2577 eval ${_UNSET} mdf_spec; 2578 eval "${return_bad}"; 2579 fi; 2580 fi; 2581 if obj _MAN_ALL is_yes && obj mdf_got_one is_yes 2582 then 2583 eval ${_UNSET} mdf_got_one; 2584 eval ${_UNSET} mdf_name; 2585 eval ${_UNSET} mdf_s; 2586 eval ${_UNSET} mdf_section; 2587 eval ${_UNSET} mdf_spec; 2588 eval "${return_good}"; 2589 fi; 2590 eval ${_UNSET} mdf_got_one; 2591 eval ${_UNSET} mdf_name; 2592 eval ${_UNSET} mdf_s; 2593 eval ${_UNSET} mdf_section; 2594 eval ${_UNSET} mdf_spec; 2595 eval "${return_bad}"; 2596} # man_do_filespec() 2597 2598 2599######################################################################## 2600# man_register_file (<file> <name> [<section>]) 2601# 2602# Write a found man page file and register the title element. 2603# 2604# Arguments: 1, 2, or 3; maybe empty 2605# Output: none 2606# 2607man_register_file() 2608{ 2609 func_check man_register_file '>=' 2 "$@"; 2610 case "$#" in 2611 2|3) do_nothing; ;; 2612 *) 2613 error "man_register_file() expects 2 or 3 arguments."; 2614 ;; 2615 esac; 2616 if is_empty "$1" 2617 then 2618 error 'man_register_file(): file name is empty'; 2619 fi; 2620 to_tmp "$1"; 2621 case "$#" in 2622 2) 2623 register_title "man:$2"; 2624 eval "${return_ok}"; 2625 ;; 2626 3) 2627 register_title "$2.$3"; 2628 eval "${return_ok}"; 2629 ;; 2630 esac; 2631 eval "${return_ok}"; 2632} 2633 2634 2635######################################################################## 2636# man_search_section (<name> <section>) 2637# 2638# Retrieve man pages. 2639# 2640# Arguments : 2 2641# Globals : $_MAN_PATH, $_MAN_EXT 2642# Return : 0 if found, 1 otherwise 2643# 2644# Variable prefix: mss 2645# 2646man_search_section() 2647{ 2648 func_check man_search_section = 2 "$@"; 2649 if obj _MAN_PATH is_empty 2650 then 2651 eval "${return_bad}"; 2652 fi; 2653 if is_empty "$1" 2654 then 2655 eval "${return_bad}"; 2656 fi; 2657 if is_empty "$2" 2658 then 2659 eval "${return_bad}"; 2660 fi; 2661 mss_name="$1"; 2662 mss_section="$2"; 2663 eval set x "$(path_split "${_MAN_PATH}")"; 2664 exit_test; 2665 shift; 2666 mss_got_one='no'; 2667 if obj _MAN_EXT is_empty 2668 then 2669 for d 2670 do 2671 mss_dir="$(dirname_append "$d" "man${mss_section}")"; 2672 exit_test; 2673 if obj mss_dir is_dir 2674 then 2675 mss_prefix="$(\ 2676 dirname_append "${mss_dir}" "${mss_name}.${mss_section}")"; 2677 if obj _OPT_WHATIS is_yes 2678 then 2679 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | 2680 sed -e '\| found|s|.*||' 2681 )"; 2682 else 2683 mss_files="$(eval ls "'${mss_prefix}'"'*' 2>${_NULL_DEV} | 2684 sed -e '\| found|s|.*||' 2685 )"; 2686 fi; 2687 exit_test; 2688 if obj mss_files is_not_empty 2689 then 2690 # for f in $mss_files 2691 for f in $(eval set x ${mss_files}; shift; echo1 "$@") 2692 do 2693 exit_test; 2694 mss_f="$f"; 2695 if obj mss_f is_file 2696 then 2697 if is_yes "${mss_got_one}" 2698 then 2699 register_file "${mss_f}"; 2700 elif obj _MAN_ALL is_yes 2701 then 2702 man_register_file "${mss_f}" "${mss_name}"; 2703 else 2704 man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; 2705 eval ${_UNSET} mss_dir; 2706 eval ${_UNSET} mss_ext; 2707 eval ${_UNSET} mss_f; 2708 eval ${_UNSET} mss_files; 2709 eval ${_UNSET} mss_got_one; 2710 eval ${_UNSET} mss_name; 2711 eval ${_UNSET} mss_prefix; 2712 eval ${_UNSET} mss_section; 2713 eval "${return_good}"; 2714 fi; 2715 mss_got_one='yes'; 2716 fi; 2717 done; 2718 fi; 2719 fi; 2720 done; 2721 else 2722 mss_ext="${_MAN_EXT}"; 2723 # check for directory name having trailing extension 2724 for d 2725 do 2726 mss_dir="$(dirname_append $d man${mss_section}${mss_ext})"; 2727 exit_test; 2728 if obj mss_dir is_dir 2729 then 2730 mss_prefix=\ 2731 "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")"; 2732 mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | 2733 sed -e '\|not found|s|.*||' 2734 )"; 2735 exit_test; 2736 if obj mss_files is_not_empty 2737 then 2738 # for f in $mss_files 2739 for f in $(eval set x ${mss_files}; shift; echo1 "$@") 2740 do 2741 mss_f="$f"; 2742 if obj mss_f is_file 2743 then 2744 if is_yes "${mss_got_one}" 2745 then 2746 register_file "${mss_f}"; 2747 elif obj _MAN_ALL is_yes 2748 then 2749 man_register_file "${mss_f}" "${mss_name}"; 2750 else 2751 man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; 2752 eval ${_UNSET} mss_dir; 2753 eval ${_UNSET} mss_ext; 2754 eval ${_UNSET} mss_f; 2755 eval ${_UNSET} mss_files; 2756 eval ${_UNSET} mss_got_one; 2757 eval ${_UNSET} mss_name; 2758 eval ${_UNSET} mss_prefix; 2759 eval ${_UNSET} mss_section; 2760 eval "${return_good}"; 2761 fi; 2762 mss_got_one='yes'; 2763 fi; 2764 done; 2765 fi; 2766 fi; 2767 done; 2768 # check for files with extension in directories without extension 2769 for d 2770 do 2771 mss_dir="$(dirname_append "$d" "man${mss_section}")"; 2772 exit_test; 2773 if obj mss_dir is_dir 2774 then 2775 mss_prefix="$(dirname_append "${mss_dir}" \ 2776 "${mss_name}.${mss_section}${mss_ext}")"; 2777 mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | 2778 sed -e '\|not found|s|.*||' 2779 )"; 2780 exit_test; 2781 if obj mss_files is_not_empty 2782 then 2783 # for f in $mss_files 2784 for f in $(eval set x ${mss_files}; shift; echo1 "$@") 2785 do 2786 mss_f="$f"; 2787 if obj mss_f is_file 2788 then 2789 if is_yes "${mss_got_one}" 2790 then 2791 register_file "${mss_f}"; 2792 elif obj _MAN_ALL is_yes 2793 then 2794 man_register_file "${mss_f}" "${mss_name}"; 2795 else 2796 man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; 2797 eval ${_UNSET} mss_dir; 2798 eval ${_UNSET} mss_ext; 2799 eval ${_UNSET} mss_f; 2800 eval ${_UNSET} mss_files; 2801 eval ${_UNSET} mss_got_one; 2802 eval ${_UNSET} mss_name; 2803 eval ${_UNSET} mss_prefix; 2804 eval ${_UNSET} mss_section; 2805 eval "${return_good}"; 2806 fi; 2807 mss_got_one='yes'; 2808 fi; 2809 done; 2810 fi; 2811 fi; 2812 done; 2813 fi; 2814 if obj _MAN_ALL is_yes && is_yes "${mss_got_one}" 2815 then 2816 eval ${_UNSET} mss_dir; 2817 eval ${_UNSET} mss_ext; 2818 eval ${_UNSET} mss_f; 2819 eval ${_UNSET} mss_files; 2820 eval ${_UNSET} mss_got_one; 2821 eval ${_UNSET} mss_name; 2822 eval ${_UNSET} mss_prefix; 2823 eval ${_UNSET} mss_section; 2824 eval "${return_good}"; 2825 fi; 2826 eval ${_UNSET} mss_dir; 2827 eval ${_UNSET} mss_ext; 2828 eval ${_UNSET} mss_f; 2829 eval ${_UNSET} mss_files; 2830 eval ${_UNSET} mss_got_one; 2831 eval ${_UNSET} mss_name; 2832 eval ${_UNSET} mss_prefix; 2833 eval ${_UNSET} mss_section; 2834 eval "${return_bad}"; 2835} # man_search_section() 2836 2837 2838######################################################################## 2839# man_setup () 2840# 2841# Setup the variables $_MAN_* needed for man page searching. 2842# 2843# Globals: 2844# in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL, 2845# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT. 2846# out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2, 2847# $_MAN_SEC, $_MAN_ALL 2848# in/out: $_MAN_ENABLE 2849# 2850# The precedence for the variables related to `man' is that of GNU 2851# `man', i.e. 2852# 2853# $LANG; overridden by 2854# $LC_MESSAGES; overridden by 2855# $LC_ALL; this has the same precedence as 2856# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by 2857# $MANOPT; overridden by 2858# the groffer command line options. 2859# 2860# Variable prefix: ms 2861# 2862man_setup() 2863{ 2864 func_check main_man_setup = 0 "$@"; 2865 2866 if obj _MAN_IS_SETUP is_yes 2867 then 2868 eval "${return_ok}"; 2869 fi; 2870 _MAN_IS_SETUP='yes'; 2871 2872 if obj _MAN_ENABLE is_not_yes 2873 then 2874 eval "${return_ok}"; 2875 fi; 2876 2877 # determine basic path for man pages 2878 _MAN_PATH="$(get_first_essential \ 2879 "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")"; 2880 exit_test; 2881 if obj _MAN_PATH is_empty 2882 then 2883 manpath_set_from_path; 2884 else 2885 _MAN_PATH="$(path_clean "${_MAN_PATH}")"; 2886 exit_test; 2887 fi; 2888 if obj _MAN_PATH is_empty 2889 then 2890 if is_prog 'manpath' 2891 then 2892 _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available 2893 exit_test; 2894 fi; 2895 fi; 2896 if obj _MAN_PATH is_empty 2897 then 2898 _MAN_ENABLE="no"; 2899 eval "${return_ok}"; 2900 fi; 2901 2902 _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")"; 2903 exit_test; 2904 if obj _MAN_ALL is_empty 2905 then 2906 _MAN_ALL='no'; 2907 fi; 2908 2909 _MAN_SYS="$(get_first_essential \ 2910 "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")"; 2911 ms_lang="$(get_first_essential \ 2912 "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")"; 2913 exit_test; 2914 case "${ms_lang}" in 2915 C|POSIX) 2916 _MAN_LANG=""; 2917 _MAN_LANG2=""; 2918 ;; 2919 ?) 2920 _MAN_LANG="${ms_lang}"; 2921 _MAN_LANG2=""; 2922 ;; 2923 *) 2924 _MAN_LANG="${ms_lang}"; 2925 # get first two characters of $ms_lang 2926 _MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')"; 2927 exit_test; 2928 ;; 2929 esac; 2930 # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*. 2931 2932 manpath_add_lang_sys; # this is very slow 2933 2934 _MAN_SEC="$(get_first_essential \ 2935 "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")"; 2936 exit_test; 2937 if obj _MAN_PATH is_empty 2938 then 2939 _MAN_ENABLE="no"; 2940 eval ${_UNSET} ms_lang; 2941 eval "${return_ok}"; 2942 fi; 2943 2944 _MAN_EXT="$(get_first_essential \ 2945 "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")"; 2946 exit_test; 2947 eval ${_UNSET} ms_lang; 2948 eval "${return_ok}"; 2949} # man_setup() 2950 2951 2952######################################################################## 2953landmark '8: manpath_*()'; 2954######################################################################## 2955 2956######################################################################## 2957# manpath_add_lang_sys () 2958# 2959# Add language and operating system specific directories to man path. 2960# 2961# Arguments : 0 2962# Output : none 2963# Globals: 2964# in: $_MAN_SYS: has the form `os1,os2,...', a comma separated 2965# list of names of operating systems. 2966# $_MAN_LANG and $_MAN_LANG2: each a single name 2967# in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon 2968# separated list of directories. 2969# 2970# Variable prefix: mals 2971# 2972manpath_add_lang_sys() 2973{ 2974 func_check manpath_add_lang_sys = 0 "$@"; 2975 if obj _MAN_PATH is_empty 2976 then 2977 eval "${return_ok}"; 2978 fi; 2979 # twice test both sys and lang 2980 eval set x "$(path_split "${_MAN_PATH}")"; 2981 shift; 2982 exit_test; 2983 mals_mp=''; 2984 for p 2985 do # loop on man path directories 2986 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")"; 2987 exit_test; 2988 done; 2989 eval set x "$(path_split "${mals_mp}")"; 2990 shift; 2991 exit_test; 2992 for p 2993 do # loop on man path directories 2994 mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")"; 2995 exit_test; 2996 done; 2997 _MAN_PATH="$(path_chop "${mals_mp}")"; 2998 exit_test; 2999 eval ${_UNSET} mals_mp; 3000 eval "${return_ok}"; 3001} 3002 3003 3004# To the directory in $1 append existing sys/lang subdirectories 3005# Function is necessary to split the OS list. 3006# 3007# globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2 3008# argument: 2: `man_path' and `dir' 3009# output: colon-separated path of the retrieved subdirectories 3010# 3011# Variable prefix: _mals 3012# 3013_manpath_add_lang_sys_single() 3014{ 3015 func_check _manpath_add_lang_sys_single = 2 "$@"; 3016 _mals_res="$1"; 3017 _mals_parent="$2"; 3018 eval set x "$(list_from_split "${_MAN_SYS}" ',')"; 3019 shift; 3020 exit_test; 3021 for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}" 3022 do 3023 _mals_dir="$(dirname_append "${_mals_parent}" "$d")"; 3024 exit_test; 3025 if obj _mals_res path_not_contains "${_mals_dir}" && \ 3026 obj _mals_dir is_dir 3027 then 3028 _mals_res="${_mals_res}:${_mals_dir}"; 3029 fi; 3030 done; 3031 if path_not_contains "${_mals_res}" "${_mals_parent}" 3032 then 3033 _mals_res="${_mals_res}:${_mals_parent}"; 3034 fi; 3035 path_chop "${_mals_res}"; 3036 eval ${_UNSET} _mals_dir; 3037 eval ${_UNSET} _mals_parent; 3038 eval ${_UNSET} _mals_res; 3039 eval "${return_ok}"; 3040} 3041 3042# end manpath_add_lang_sys () 3043 3044 3045######################################################################## 3046# manpath_set_from_path () 3047# 3048# Determine basic search path for man pages from $PATH. 3049# 3050# Return: `0' if a valid man path was retrieved. 3051# Output: none 3052# Globals: 3053# in: $PATH 3054# out: $_MAN_PATH 3055# 3056# Variable prefix: msfp 3057# 3058manpath_set_from_path() 3059{ 3060 func_check manpath_set_from_path = 0 "$@"; 3061 3062 msfp_manpath=''; 3063 3064 # get a basic man path from $PATH 3065 if obj PATH is_not_empty 3066 then 3067 eval set x "$(path_split "${PATH}")"; 3068 shift; 3069 exit_test; 3070 for d 3071 do 3072 # delete the final `/bin' part 3073 msfp_base="$(echo1 "$d" | sed -e 's|//*bin/*$||')"; 3074 exit_test; 3075 for e in /share/man /man 3076 do 3077 msfp_mandir="${msfp_base}$e"; 3078 if test -d "${msfp_mandir}" && test -r "${msfp_mandir}" 3079 then 3080 msfp_manpath="${msfp_manpath}:${msfp_mandir}"; 3081 fi; 3082 done; 3083 done; 3084 fi; 3085 3086 # append some default directories 3087 for d in /usr/local/share/man /usr/local/man \ 3088 /usr/share/man /usr/man \ 3089 /usr/X11R6/man /usr/openwin/man \ 3090 /opt/share/man /opt/man \ 3091 /opt/gnome/man /opt/kde/man 3092 do 3093 msfp_d="$d"; 3094 if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir 3095 then 3096 msfp_manpath="${msfp_manpath}:${mfsp_d}"; 3097 fi; 3098 done; 3099 3100 _MAN_PATH="${msfp_manpath}"; 3101 eval ${_UNSET} msfp_base; 3102 eval ${_UNSET} msfp_d; 3103 eval ${_UNSET} msfp_mandir; 3104 eval ${_UNSET} msfp_manpath; 3105 eval "${return_ok}"; 3106} # manpath_set_from_path() 3107 3108 3109######################################################################## 3110landmark '9: obj_*()'; 3111######################################################################## 3112 3113######################################################################## 3114# obj (<object> <call_name> <arg>...) 3115# 3116# This works like a method (object function) call for an object. 3117# Run "<call_name> $<object> <arg> ...". 3118# 3119# The first argument represents an object whose data is given as first 3120# argument to <call_name>(). 3121# 3122# Argument: >=2 3123# <object>: variable name 3124# <call_name>: a program or function name 3125# 3126# Variable prefix: o 3127# 3128obj() 3129{ 3130 func_check obj '>=' 2 "$@"; 3131 eval o_arg1='"${'$1'}"'; 3132 if is_empty "$2" 3133 then 3134 error "obj(): function name is empty." 3135 else 3136 o_func="$2"; 3137 fi; 3138 shift; 3139 shift; 3140 eval "${o_func}"' "${o_arg1}" "$@"'; 3141 n="$?"; 3142 eval ${_UNSET} o_arg1; 3143 eval ${_UNSET} o_func; 3144 eval "${return_var} $n"; 3145} # obj() 3146 3147 3148######################################################################## 3149# obj_data (<object>) 3150# 3151# Print the data of <object>, i.e. the content of $<object>. 3152# For possible later extensions. 3153# 3154# Arguments: 1 3155# <object>: a variable name 3156# Output: the data of <object> 3157# 3158# Variable prefix: od 3159# 3160obj_data() 3161{ 3162 func_check obj '=' 1 "$@"; 3163 if is_empty "$1" 3164 then 3165 error "obj_data(): object name is empty." 3166 fi; 3167 eval od_res='"${'$1'}"'; 3168 obj od_res echo1; 3169 eval ${_UNSET} od_res; 3170 eval "${return_ok}"; 3171} 3172 3173 3174######################################################################## 3175# obj_from_output (<object> <call_name> <arg>...) 3176# 3177# Run '$<object>="$(<call_name> <arg>...)"' to set the result of a 3178# function call to a global variable. 3179# 3180# Arguments: >=2 3181# <object>: a variable name 3182# <call_name>: the name of a function or program 3183# <arg>: optional argument to <call_name> 3184# Output: none 3185# 3186# Variable prefix: ofo 3187# 3188obj_from_output() 3189{ 3190 func_check obj_from_output '>=' 2 "$@"; 3191 if is_empty "$1" 3192 then 3193 error "res(): variable name is empty."; 3194 elif is_empty "$2" 3195 then 3196 error "res(): function name is empty." 3197 else 3198 ofo_result_name="$1"; 3199 fi; 3200 shift; 3201 eval "${ofo_result_name}"'="$('"$@"')"'; 3202 exit_test; 3203 eval "${return_ok}"; 3204} 3205 3206 3207######################################################################## 3208# obj_set (<object> <data>) 3209# 3210# Set the data of <object>, i.e. call "$<object>=<data>". 3211# 3212# Arguments: 2 3213# <object>: a variable name 3214# <data>: a string 3215# Output:: none 3216# 3217obj_set() 3218{ 3219 func_check obj_set '=' 2 "$@"; 3220 if is_empty "$1" 3221 then 3222 error "obj_set(): object name is empty." 3223 fi; 3224 eval "$1"='"$2"'; 3225 eval "${return_ok}"; 3226} 3227 3228 3229######################################################################## 3230# path_chop (<path>) 3231# 3232# Remove unnecessary colons from path. 3233# 3234# Argument: 1, a colon separated path. 3235# Output: path without leading, double, or trailing colons. 3236# 3237path_chop() 3238{ 3239 func_check path_chop = 1 "$@"; 3240 3241 # replace multiple colons by a single colon `:' 3242 # remove leading and trailing colons 3243 echo1 "$1" | sed -e ' 3244s/^:*// 3245s/:::*/:/g 3246s/:*$// 3247'; 3248 eval "${return_ok}"; 3249} 3250 3251 3252######################################################################## 3253# path_clean (<path>) 3254# 3255# Remove non-existing directories from a colon-separated list. 3256# 3257# Argument: 1, a colon separated path. 3258# Output: colon-separated list of existing directories. 3259# 3260# Variable prefix: pc 3261# 3262path_clean() 3263{ 3264 func_check path_clean = 1 "$@"; 3265 if is_not_equal "$#" 1 3266 then 3267 error 'path_clean() needs 1 argument.'; 3268 fi; 3269 pc_arg="$1"; 3270 eval set x "$(path_split "${pc_arg}")"; 3271 exit_test; 3272 shift; 3273 pc_res=""; 3274 for i 3275 do 3276 pc_i="$i"; 3277 if obj pc_i is_not_empty \ 3278 && obj pc_res path_not_contains "${pc_i}" \ 3279 && obj pc_i is_dir 3280 then 3281 case "${pc_i}" in 3282 ?*/) 3283 pc_res="${pc_res}$(dirname_chop "${pc_i}")"; 3284 exit_test; 3285 ;; 3286 *) 3287 pc_res="${pc_res}:${pc_i}"; 3288 exit_test; 3289 ;; 3290 esac; 3291 fi; 3292 done; 3293 eval ${_UNSET} pc_arg; 3294 eval ${_UNSET} pc_i; 3295 eval ${_UNSET} pc_res; 3296 if path_chop "${pc_res}" 3297 then 3298 eval "${return_ok}"; 3299 else 3300 eval "${return_bad}"; 3301 fi; 3302} 3303 3304 3305######################################################################## 3306# path_contains (<path> <dir>) 3307#- 3308# Test whether `dir' is contained in `path', a list separated by `:'. 3309# 3310# Arguments : 2 arguments. 3311# Return : `0' if arg2 is substring of arg1, `1' otherwise. 3312# 3313path_contains() 3314{ 3315 func_check path_contains = 2 "$@"; 3316 case ":$1:" in 3317 *":$2:"*) 3318 eval "${return_yes}"; 3319 ;; 3320 *) 3321 eval "${return_no}"; 3322 ;; 3323 esac; 3324 eval "${return_ok}"; 3325} 3326 3327 3328######################################################################## 3329# path_not_contains (<path> <dir>) 3330# 3331# Test whether `dir' is not contained in colon separated `path'. 3332# 3333# Arguments : 2 arguments. 3334# 3335path_not_contains() 3336{ 3337 func_check path_not_contains = 2 "$@"; 3338 if path_contains "$1" "$2" 3339 then 3340 eval "${return_no}"; 3341 else 3342 eval "${return_yes}"; 3343 fi; 3344 eval "${return_ok}"; 3345} 3346 3347 3348######################################################################## 3349# path_split (<path>) 3350# 3351# In `path' escape white space and replace each colon by a space. 3352# 3353# Arguments: 1: a colon-separated path 3354# Output: the resulting list, process with `eval set' 3355# 3356path_split() 3357{ 3358 func_check path_split = 1 "$@"; 3359 list_from_split "$1" ':'; 3360 eval "${return_ok}"; 3361} 3362 3363 3364######################################################################## 3365landmark '10: register_*()'; 3366######################################################################## 3367 3368######################################################################## 3369# register_file (<filename>) 3370# 3371# Write a found file and register the title element. 3372# 3373# Arguments: 1: a file name 3374# Output: none 3375# 3376register_file() 3377{ 3378 func_check register_file = 1 "$@"; 3379 if is_empty "$1" 3380 then 3381 error 'register_file(): file name is empty'; 3382 fi; 3383 if is_equal "$1" '-' 3384 then 3385 to_tmp "${_TMP_STDIN}"; 3386 register_title 'stdin'; 3387 else 3388 to_tmp "$1"; 3389 register_title "$(base_name "$1")"; 3390 exit_test; 3391 fi; 3392 eval "${return_ok}"; 3393} # register_file() 3394 3395 3396######################################################################## 3397# register_title (<filespec>) 3398# 3399# Create title element from <filespec> and append to $_REGISTERED_TITLE 3400# 3401# Globals: $_REGISTERED_TITLE (rw) 3402# 3403# Variable prefix: rt 3404# 3405register_title() 3406{ 3407 func_check register_title '=' 1 "$@"; 3408 if is_empty "$1" 3409 then 3410 eval "${return_ok}"; 3411 fi; 3412 3413 case "${_REGISTERED_TITLE}" in 3414 *\ *\ *\ *) 3415 eval "${return_ok}"; 3416 ;; 3417 esac; 3418 3419 # remove directory part 3420 rt_title="$(base_name "$1")"; 3421 # replace space characters by `_' 3422 rt_title="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')"; 3423 # remove extension `.bz2' 3424 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')"; 3425 # remove extension `.gz' 3426 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')"; 3427 # remove extension `.Z' 3428 rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')"; 3429 exit_test; 3430 3431 if obj rt_title is_empty 3432 then 3433 eval ${_UNSET} rt_title; 3434 eval "${return_ok}"; 3435 fi; 3436 if obj _REGISTERED_TITLE is_empty 3437 then 3438 _REGISTERED_TITLE="${rt_title}"; 3439 else 3440 _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}"; 3441 fi; 3442 eval ${_UNSET} rt_title; 3443 eval "${return_ok}"; 3444} # register_title() 3445 3446 3447######################################################################## 3448# reset () 3449# 3450# Reset the variables that can be affected by options to their default. 3451# 3452# 3453# Defined in section `Preset' after the rudimentary shell tests. 3454 3455 3456######################################################################## 3457# rm_file (<file_name>) 3458# 3459# Remove file if $_DEBUG_KEEP_FILES allows it. 3460# 3461# Globals: $_DEBUG_KEEP_FILES 3462# 3463rm_file() 3464{ 3465 func_check rm_file '=' 1 "$@"; 3466 if is_file "$1" 3467 then 3468 rm -f "$1" >${_NULL_DEV} 2>&1; 3469 fi; 3470 if is_existing "$1" 3471 then 3472 eval "${return_bad}"; 3473 else 3474 eval "${return_good}"; 3475 fi; 3476} 3477 3478 3479######################################################################## 3480# rm_file_with_debug (<file_name>) 3481# 3482# Remove file if $_DEBUG_KEEP_FILES allows it. 3483# 3484# Globals: $_DEBUG_KEEP_FILES 3485# 3486rm_file_with_debug() 3487{ 3488 func_check rm_file_with_debug '=' 1 "$@"; 3489 if obj _DEBUG_KEEP_FILES is_not_yes 3490 then 3491 if is_file "$1" 3492 then 3493 rm -f "$1" >${_NULL_DEV} 2>&1; 3494 fi; 3495 fi; 3496 if is_existing "$1" 3497 then 3498 eval "${return_bad}"; 3499 else 3500 eval "${return_good}"; 3501 fi; 3502} 3503 3504 3505######################################################################## 3506# rm_tree (<dir_name>) 3507# 3508# Remove file if $_DEBUG_KEEP_FILES allows it. 3509# 3510# Globals: $_DEBUG_KEEP_FILES 3511# 3512rm_tree() 3513{ 3514 func_check rm_tree '=' 1 "$@"; 3515 if is_existing "$1" 3516 then 3517 rm -f -r "$1" >${_NULL_DEV} 2>&1; 3518 fi; 3519 if is_existing "$1" 3520 then 3521 eval "${return_bad}"; 3522 else 3523 eval "${return_good}"; 3524 fi; 3525} 3526 3527 3528######################################################################## 3529# save_stdin () 3530# 3531# Store standard input to temporary file (with decompression). 3532# 3533# Variable prefix: ss 3534# 3535if obj _HAS_COMPRESSION is_yes 3536then 3537 save_stdin() 3538 { 3539 func_check save_stdin '=' 0 "$@"; 3540 ss_f="${_TMP_DIR}"/INPUT; 3541 cat >"${ss_f}"; 3542 cat_z "${ss_f}" >"${_TMP_STDIN}"; 3543 rm_file "${ss_f}"; 3544 eval ${_UNSET} ss_f; 3545 eval "${return_ok}"; 3546 } 3547else 3548 save_stdin() 3549 { 3550 func_check save_stdin = 0 "$@"; 3551 cat >"${_TMP_STDIN}"; 3552 eval "${return_ok}"; 3553 } 3554fi; 3555 3556 3557######################################################################## 3558# special_filespec () 3559# 3560# Handle special modes like whatis and apropos. 3561# 3562special_filespec() 3563{ 3564 func_check special_setup '=' 0 "$@"; 3565 if obj _OPT_APROPOS is_yes 3566 then 3567 if obj _OPT_WHATIS is_yes 3568 then 3569 error \ 3570 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; 3571 fi; 3572 apropos_filespec; 3573 eval "${return_ok}"; 3574 fi; 3575 if obj _OPT_WHATIS is_yes 3576 then 3577 whatis_filespec; 3578 fi; 3579 eval "${return_ok}"; 3580} 3581 3582 3583######################################################################## 3584# special_setup () 3585# 3586# Handle special modes like whatis and apropos. 3587# 3588special_setup() 3589{ 3590 func_check special_setup '=' 0 "$@"; 3591 if obj _OPT_APROPOS is_yes 3592 then 3593 if obj _OPT_WHATIS is_yes 3594 then 3595 error \ 3596 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; 3597 fi; 3598 apropos_setup; 3599 eval "${return_ok}"; 3600 fi; 3601 if obj _OPT_WHATIS is_yes 3602 then 3603 whatis_header; 3604 fi; 3605 eval "${return_ok}"; 3606} 3607 3608 3609######################################################################## 3610landmark '11: stack_*()'; 3611######################################################################## 3612 3613######################################################################## 3614# string_contains (<string> <part>) 3615# 3616# Test whether `part' is contained in `string'. 3617# 3618# Arguments : 2 text arguments. 3619# Return : `0' if arg2 is substring of arg1, `1' otherwise. 3620# 3621string_contains() 3622{ 3623 func_check string_contains '=' 2 "$@"; 3624 case "$1" in 3625 *"$2"*) 3626 eval "${return_yes}"; 3627 ;; 3628 *) 3629 eval "${return_no}"; 3630 ;; 3631 esac; 3632 eval "${return_ok}"; 3633} 3634 3635 3636######################################################################## 3637# string_not_contains (<string> <part>) 3638# 3639# Test whether `part' is not substring of `string'. 3640# 3641# Arguments : 2 text arguments. 3642# Return : `0' if arg2 is substring of arg1, `1' otherwise. 3643# 3644string_not_contains() 3645{ 3646 func_check string_not_contains '=' 2 "$@"; 3647 if string_contains "$1" "$2" 3648 then 3649 eval "${return_no}"; 3650 else 3651 eval "${return_yes}"; 3652 fi; 3653 eval "${return_ok}"; 3654} 3655 3656 3657######################################################################## 3658landmark '12: tmp_*()'; 3659######################################################################## 3660 3661######################################################################## 3662# tmp_cat () 3663# 3664# output the temporary cat file (the concatenation of all input) 3665# 3666tmp_cat() 3667{ 3668 func_check tmp_cat '=' 0 "$@"; 3669 cat "${_TMP_CAT}"; 3670 eval "${return_var}" "$?"; 3671} 3672 3673 3674######################################################################## 3675# tmp_create (<suffix>?) 3676# 3677# Create temporary file. 3678# 3679# It's safe to use the shell process ID together with a suffix to 3680# have multiple temporary files. 3681# 3682# Globals: $_TMP_DIR 3683# 3684# Output : name of created file 3685# 3686# Variable prefix: tc 3687# 3688tmp_create() 3689{ 3690 func_check tmp_create '<=' 1 "$@"; 3691 # the output file does not have `,' as first character, so these are 3692 # different names from the output file. 3693 tc_tmp="${_TMP_DIR}/,$1"; 3694 : >"${tc_tmp}" 3695 obj tc_tmp echo1; 3696 eval ${_UNSET} tc_tmp; 3697 eval "${return_ok}"; 3698} 3699 3700 3701######################################################################## 3702# to_tmp (<filename>) 3703# 3704# print file (decompressed) to the temporary cat file 3705# 3706to_tmp() 3707{ 3708 func_check to_tmp '=' 1 "$@"; 3709 if obj _TMP_CAT is_empty 3710 then 3711 error 'to_tmp_line: $_TMP_CAT is not yet set'; 3712 fi; 3713 if is_file "$1" 3714 then 3715 if obj _OPT_LOCATION is_yes 3716 then 3717 echo2 "$1"; 3718 fi; 3719 if obj _OPT_WHATIS is_yes 3720 then 3721 whatis_filename "$1" >>"${_TMP_CAT}"; 3722 else 3723 cat_z "$1" >>"${_TMP_CAT}"; 3724 fi; 3725 else 3726 error "to_tmp(): could not read file \`$1'."; 3727 fi; 3728 eval "${return_ok}"; 3729} 3730 3731 3732######################################################################## 3733# to_tmp_line ([<text>]) 3734# 3735# print line to the temporary cat file 3736# 3737to_tmp_line() 3738{ 3739 func_check to_tmp '>=' 0 "$@"; 3740 if obj _TMP_CAT is_empty 3741 then 3742 error 'to_tmp_line: $_TMP_CAT is not yet set'; 3743 fi; 3744 echo1 "$*" >>"${_TMP_CAT}"; 3745 eval "${return_ok}"; 3746} 3747 3748 3749######################################################################## 3750# trap_set 3751# 3752# call function on signal 0 3753# 3754trap_set() 3755{ 3756 func_check trap_set '=' 0 "$@"; 3757 trap 'clean_up' 0 2>${_NULL_DEV} || :; 3758 eval "${return_ok}"; 3759} 3760 3761 3762######################################################################## 3763# trap_unset () 3764# 3765# disable trap on signal 0. 3766# 3767trap_unset() 3768{ 3769 func_check trap_unset '=' 0 "$@"; 3770 trap '' 0 2>${_NULL_DEV} || :; 3771 eval "${return_ok}"; 3772} 3773 3774 3775######################################################################## 3776# usage () 3777# 3778# print usage information to stderr; for groffer option --help. 3779# 3780usage() 3781{ 3782 func_check usage = 0 "$@"; 3783 echo; 3784 version; 3785 echo1 'Usage: groffer [option]... [filespec]...'; 3786 cat <<EOF 3787 3788Display roff files, standard input, and/or Unix manual pages with a X 3789Window viewer or in several text modes. All input is decompressed 3790on-the-fly with all formats that gzip can handle. 3791 3792"filespec" is one of 3793 "filename" name of a readable file 3794 "-" for standard input 3795 "man:name.n" man page "name" in section "n" 3796 "man:name" man page "name" in first section found 3797 "name.n" man page "name" in section "n" 3798 "name" man page "name" in first section found 3799and some more (see groffer(1) for details). 3800 3801-h --help print this usage message. 3802-Q --source output as roff source. 3803-T --device=name pass to groff using output device "name". 3804-v --version print version information. 3805-V display the groff execution pipe instead of formatting. 3806-X display with "gxditview" using groff -X. 3807-Z --ditroff --intermediate-output 3808 generate groff intermediate output without 3809 post-processing and viewing, like groff -Z. 3810All other short options are interpreted as "groff" formatting options. 3811 3812The most important groffer long options are 3813 3814--apropos=name start man's "apropos" program for "name". 3815--apropos-data=name 3816 "apropos" for "name" in man's data sections 4, 5, 7. 3817--apropos-devel=name 3818 "apropos" for "name" in development sections 2, 3, 9. 3819--apropos-progs=name 3820 "apropos" for "name" in man's program sections 1, 6, 8. 3821--auto choose mode automatically from the default mode list. 3822--default reset all options to the default value. 3823--default-modes=mode1,mode2,... 3824 set sequence of automatically tried modes. 3825--dvi display in a viewer for TeX device independent format. 3826--dvi-viewer=prog choose the viewer program for dvi mode. 3827--groff process like groff, disable viewing features. 3828--help display this helping output. 3829--html display in a web browser. 3830--html-viewer=program 3831 choose the web browser for html mode. 3832--man check file parameters first whether they are man pages. 3833--mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X 3834 choose display mode. 3835--no-man disable man-page facility. 3836--no-special disable --all, --apropos*, and --whatis 3837--pager=program preset the paging program for tty mode. 3838--pdf display in a PDF viewer. 3839--pdf-viewer=prog choose the viewer program for pdf mode. 3840--ps display in a Postscript viewer. 3841--ps-viewer=prog choose the viewer program for ps mode. 3842--shell=program specify a shell under which to run groffer2.sh. 3843--text output in a text device without a pager. 3844--tty display with a pager on text terminal even when in X. 3845--tty-viewer=prog select a pager for tty mode; same as --pager. 3846--whatis display the file name and description of man pages 3847--www same as --html. 3848--www-viewer=prog same as --html-viewer 3849--x --X display with "gxditview" using an X* device. 3850--x-viewer=prog choose viewer program for x mode (X mode). 3851--X-viewer=prog same as "--xviewer". 3852 3853Development options that are not useful for normal usage: 3854--debug, --debug-all, --debug-keep, --debug-lm, --debug-params, 3855--debug-shell, --debug-stacks, --debug-tmpdir, --debug-user, 3856--do-nothing, --print=text 3857 3858Viewer programs for the different modes that run on the terminal: 3859--dvi-viewer-tty=prog, --html-viewer-tty=prog, --pdf-viewer-tty=prog, 3860--ps-viewer-tty=prog, --tty-viewer-tty, --X-viewer-tty=prog, 3861--x-viewer-tty=prog, --www-viewer-tty=prog 3862 3863The usual X Windows toolkit options transformed into GNU long options: 3864--background=color, --bd=size, --bg=color, --bordercolor=color, 3865--borderwidth=size, --bw=size, --display=Xdisplay, --fg=color, 3866--fn=font, --font=font, --foreground=color, --geometry=geom, --iconic, 3867--resolution=dpi, --rv, --title=text, --xrm=resource 3868 3869Long options of GNU "man": 3870--all, --ascii, --ditroff, --extension=suffix, --locale=language, 3871--local-file=name, --location, --manpath=dir1:dir2:..., 3872--sections=s1:s2:..., --systems=s1,s2,..., --where, ... 3873 3874EOF 3875 eval "${return_ok}"; 3876} 3877 3878 3879######################################################################## 3880# version () 3881# 3882# print version information to stderr 3883# 3884version() 3885{ 3886 func_check version = 0 "$@"; 3887 echo1 "groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE}"; 3888 # also display groff's version, but not the called subprograms 3889 groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /'; 3890 eval "${return_ok}"; 3891} 3892 3893 3894######################################################################## 3895# warning (<string>) 3896# 3897# Print warning to stderr 3898# 3899warning() 3900{ 3901 echo2 "warning: $*"; 3902} 3903 3904 3905######################################################################## 3906# whatis_filename (<filename>) 3907# 3908# Interpret <filename> as a man page and display its `whatis' 3909# information as a fragment written in the groff language. 3910# 3911# Variable prefix: wf 3912# 3913whatis_filename() 3914{ 3915 func_check whatis_filename = 1 "$@"; 3916 wf_arg="$1"; 3917 if obj wf_arg is_not_file 3918 then 3919 error "whatis_filename(): argument is not a readable file." 3920 fi; 3921 wf_dot='^\.'"${_SPACE_SED}"'*'; 3922 if obj _FILESPEC_ARG is_equal '-' 3923 then 3924 wf_arg='stdin'; 3925 fi; 3926 cat <<EOF 3927\f[CR]${wf_arg}\f[]: 3928.br 3929EOF 3930 3931 # get the parts of the file name 3932 wf_name="$(base_name $1)"; 3933 wf_section="$(echo1 $1 | sed -n -e ' 3934s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p 3935')"; 3936 if obj wf_section is_not_empty 3937 then 3938 case "${wf_name}" in 3939 *.${wf_section}*) 3940 s='yes'; 3941 ;; 3942 *) 3943 s=''; 3944 wf_section=''; 3945 ;; 3946 esac 3947 if obj s is_yes 3948 then 3949 wf_name="$(echo1 ${wf_name} | sed -e ' 3950s/^\(.*\)\.'${wf_section}'.*$/\1/ 3951')"; 3952 fi; 3953 fi; 3954 3955 # traditional man style; grep the line containing `.TH' macro, if any 3956 wf_res="$(cat_z "$1" | sed -e ' 3957/'"${wf_dot}"'TH /p 3958d 3959')"; 3960 exit_test; 3961 if obj wf_res is_not_empty 3962 then # traditional man style 3963 # get the first line after the first `.SH' macro, by 3964 # - delete up to first .SH; 3965 # - print all lines before the next .SH; 3966 # - quit. 3967 wf_res="$(cat_z "$1" | sed -n -e ' 39681,/'"${wf_dot}"'SH/d 3969/'"${wf_dot}"'SH/q 3970p 3971')"; 3972 3973 if obj wf_section is_not_empty 3974 then 3975 case "${wf_res}" in 3976 ${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*) 3977 s='yes'; 3978 ;; 3979 *) 3980 s=''; 3981 ;; 3982 esac; 3983 if obj s is_yes 3984 then 3985 wf_res="$(obj wf_res echo1 | sed -e ' 3986s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/ 3987')"; 3988 fi; 3989 fi; 3990 obj wf_res echo1; 3991 echo; 3992 eval ${_UNSET} wf_arg; 3993 eval ${_UNSET} wf_dot; 3994 eval ${_UNSET} wf_name; 3995 eval ${_UNSET} wf_res; 3996 eval ${_UNSET} wf_section; 3997 eval "${return_ok}"; 3998 fi; 3999 4000 # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any 4001 wf_res="$(cat_z "$1" | sed -n -e '/'"${wf_dot}"'Nd /s///p')"; 4002 exit_test; 4003 if obj wf_res is_not_empty 4004 then # BSD doc style 4005 if obj wf_section is_not_empty 4006 then 4007 wf_res="$(obj wf_res echo1 | sed -n -e ' 4008s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p 4009')"; 4010 fi; 4011 obj wf_res echo1; 4012 echo; 4013 eval ${_UNSET} wf_arg; 4014 eval ${_UNSET} wf_dot; 4015 eval ${_UNSET} wf_name; 4016 eval ${_UNSET} wf_res; 4017 eval ${_UNSET} wf_section; 4018 eval "${return_ok}"; 4019 fi; 4020 echo1 'is not a man page'; 4021 echo; 4022 eval ${_UNSET} wf_arg; 4023 eval ${_UNSET} wf_dot; 4024 eval ${_UNSET} wf_name; 4025 eval ${_UNSET} wf_res; 4026 eval ${_UNSET} wf_section; 4027 eval "${return_bad}"; 4028} 4029 4030 4031######################################################################## 4032# whatis_filespec () 4033# 4034# Print the filespec name as .SH to the temporary cat file. 4035# 4036whatis_filespec() 4037{ 4038 func_check whatis_filespec '=' 0 "$@"; 4039 if obj _OPT_WHATIS is_yes 4040 then 4041 eval to_tmp_line \ 4042 "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'"; 4043 exit_test; 4044 fi; 4045 eval "${return_ok}"; 4046} 4047 4048 4049######################################################################## 4050# whatis_header () 4051# 4052# Print the whatis header to the temporary cat file. 4053# 4054whatis_header() 4055{ 4056 func_check whatis_header '=' 0 "$@"; 4057 if obj _OPT_WHATIS is_yes 4058 then 4059 to_tmp_line '.TH GROFFER WHATIS'; 4060 fi; 4061 eval "${return_ok}"; 4062} 4063 4064 4065######################################################################## 4066# where_is (<program>) 4067# 4068# Output path of a program if in $PATH. 4069# 4070# Arguments : >=1 (empty allowed) 4071# more args are ignored, this allows to specify progs with arguments 4072# Return : `0' if arg1 is a program in $PATH, `1' otherwise. 4073# 4074# Variable prefix: w 4075# 4076where_is() 4077{ 4078 func_check where_is '>=' 1 "$@"; 4079 w_arg="$1"; 4080 if obj w_arg is_empty 4081 then 4082 eval ${_UNSET} w_arg; 4083 eval "${return_bad}"; 4084 fi; 4085 case "${w_arg}" in 4086 /*) 4087 eval ${_UNSET} w_arg; 4088 eval ${_UNSET} w_file; 4089 if test -f "${w_arg}" && test -x "${w_arg}" 4090 then 4091 eval "${return_ok}"; 4092 else 4093 eval "${return_bad}"; 4094 fi; 4095 ;; 4096 esac; 4097 eval set x "$(path_split "${PATH}")"; 4098 exit_test; 4099 shift; 4100 for p 4101 do 4102 case "$p" in 4103 */) w_file=${p}${w_arg}; ;; 4104 *) w_file=${p}/${w_arg}; ;; 4105 esac; 4106 if test -f "${w_file}" && test -x "${w_file}" 4107 then 4108 obj w_file echo1; 4109 eval ${_UNSET} w_arg; 4110 eval ${_UNSET} w_file; 4111 eval "${return_ok}"; 4112 fi; 4113 done; 4114 eval ${_UNSET} w_arg; 4115 eval ${_UNSET} w_file; 4116 eval "${return_bad}"; 4117} 4118 4119 4120######################################################################## 4121# main* Functions 4122######################################################################## 4123 4124# The main area contains the following parts: 4125# - main_init(): initialize temporary files and set exit trap 4126# - main_parse_MANOPT(): parse $MANOPT 4127# - main_parse_args(): argument parsing 4128# - main_set_mode (): determine the display mode 4129# - main_do_fileargs(): process filespec arguments 4130# - main_set_resources(): setup X resources 4131# - main_display(): do the displaying 4132# - main(): the main function that calls all main_*() 4133 4134 4135####################################################################### 4136# main_init () 4137# 4138# set exit trap and create temporary files 4139# 4140# Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN 4141# 4142# Variable prefix: mi 4143# 4144main_init() 4145{ 4146 func_check main_init = 0 "$@"; 4147 # call clean_up() on shell termination. 4148 trap_set; 4149 4150 # create temporary directory 4151 umask 0022; 4152 _TMP_DIR=''; 4153 for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \ 4154 "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.' 4155 do 4156 mi_dir="$d"; 4157 if obj mi_dir is_empty || obj mi_dir is_not_dir || \ 4158 obj mi_dir is_not_writable 4159 then 4160 continue; 4161 fi; 4162 4163 case "${mi_dir}" in 4164 */) 4165 _TMP_DIR="${mi_dir}"; 4166 ;; 4167 *) 4168 _TMP_DIR="${mi_dir}"'/'; 4169 ;; 4170 esac; 4171 _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}"; 4172 if obj _TMP_DIR rm_tree 4173 then 4174 : 4175 else 4176 mi_tdir_="${_TMP_DIR}"_; 4177 mi_n=1; 4178 mi_tdir_n="${mi_tdir_}${mi_n}"; 4179 while obj mi_tdir_n is_existing 4180 do 4181 if obj mi_tdir_n rm_tree 4182 then 4183 # directory could not be removed 4184 mi_n="$(expr "${mi_n}" + 1)"; 4185 mi_tdir_n="${mi_tdir_}${mi_n}"; 4186 continue; 4187 fi; 4188 done; 4189 _TMP_DIR="${mi_tdir_n}"; 4190 fi; 4191 eval mkdir "${_TMP_DIR}"; 4192 if is_not_equal "$?" 0 4193 then 4194 obj _TMP_DIR rm_tree; 4195 _TMP_DIR=''; 4196 continue; 4197 fi; 4198 if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable 4199 then 4200 # $_TMP_DIR can now be used as temporary directory 4201 break; 4202 fi; 4203 obj _TMP_DIR rm_tree; 4204 _TMP_DIR=''; 4205 continue; 4206 done; 4207 if obj _TMP_DIR is_empty 4208 then 4209 error "main_init: \ 4210Couldn't create a directory for storing temporary files."; 4211 fi; 4212 if obj _DEBUG_PRINT_TMPDIR is_yes 4213 then 4214 echo2 "temporary directory: ${_TMP_DIR}"; 4215 fi; 4216 4217 _TMP_CAT="$(tmp_create groffer_cat)"; 4218 _TMP_STDIN="$(tmp_create groffer_input)"; 4219 exit_test; 4220 4221 eval ${_UNSET} mi_dir; 4222 eval ${_UNSET} mi_n; 4223 eval ${_UNSET} mi_tdir_; 4224 eval ${_UNSET} mi_tdir_n; 4225 eval "${return_ok}"; 4226} # main_init() 4227 4228 4229######################################################################## 4230# main_parse_MANOPT () 4231# 4232# Parse $MANOPT to retrieve man options, but only if it is a non-empty 4233# string; found man arguments can be overwritten by the command line. 4234# 4235# Globals: 4236# in: $MANOPT, $_OPTS_MANOPT_* 4237# out: $_MANOPT_* 4238# 4239# Variable prefix: mpm 4240# 4241main_parse_MANOPT() 4242{ 4243 func_check main_parse_MANOPT = 0 "$@"; 4244 4245 if obj MANOPT is_not_empty 4246 then 4247 # Delete leading and final spaces 4248 MANOPT="$(echo1 "${MANOPT}" | sed -e ' 4249s/^'"${_SPACE_SED}"'*// 4250s/'"${_SPACE_SED}"'*$// 4251')"; 4252 exit_test; 4253 fi; 4254 if obj MANOPT is_empty 4255 then 4256 eval "${return_ok}"; 4257 fi; 4258 4259 mpm_list=''; 4260 # add arguments in $MANOPT by mapping them to groffer options 4261 eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")"; 4262 exit_test; 4263 shift; 4264 until test "$#" -le 0 || is_equal "$1" '--' 4265 do 4266 mpm_opt="$1"; 4267 shift; 4268 case "${mpm_opt}" in 4269 -7|--ascii) 4270 list_append mpm_list '--ascii'; 4271 ;; 4272 -a|--all) 4273 list_append mpm_list '--all'; 4274 ;; 4275 -c|--catman) 4276 do_nothing; 4277 shift; 4278 ;; 4279 -d|--debug) 4280 do_nothing; 4281 ;; 4282 -D|--default) 4283 # undo all man options so far 4284 mpm_list=''; 4285 ;; 4286 -e|--extension) 4287 list_append mpm_list '--extension'; 4288 shift; 4289 ;; 4290 -f|--whatis) 4291 list_append mpm_list '--whatis'; 4292 shift; 4293 ;; 4294 -h|--help) 4295 do_nothing; 4296 shift; 4297 ;; 4298 -k|--apropos) 4299 # groffer's --apropos takes an argument, but man's does not, so 4300 do_nothing; 4301 ;; 4302 -l|--local-file) 4303 do_nothing; 4304 ;; 4305 -L|--locale) 4306 list_append mpm_list '--locale' "$1"; 4307 shift; 4308 ;; 4309 -m|--systems) 4310 list_append mpm_list '--systems' "$1"; 4311 shift; 4312 ;; 4313 -M|--manpath) 4314 list_append mpm_list '--manpath' "$1"; 4315 shift; 4316 ;; 4317 -p|--preprocessor) 4318 do_nothing; 4319 shift; 4320 ;; 4321 -P|--pager) 4322 list_append mpm_list '--pager' "$1"; 4323 shift; 4324 ;; 4325 -r|--prompt) 4326 do_nothing; 4327 shift; 4328 ;; 4329 -S|--sections) 4330 list_append mpm_list '--sections' "$1"; 4331 shift; 4332 ;; 4333 -t|--troff) 4334 do_nothing; 4335 shift; 4336 ;; 4337 -T|--device) 4338 list_append mpm_list '-T' "$1"; 4339 shift; 4340 ;; 4341 -u|--update) 4342 do_nothing; 4343 shift; 4344 ;; 4345 -V|--version) 4346 do_nothing; 4347 ;; 4348 -w|--where|--location) 4349 list_append mpm_list '--location'; 4350 ;; 4351 -Z|--ditroff) 4352 do_nothing; 4353 ;; 4354 # ignore all other options 4355 esac; 4356 done; 4357 4358 # prepend $mpm_list to the command line 4359 if obj mpm_list is_not_empty 4360 then 4361 eval set x "${mpm_list}" '"$@"'; 4362 shift; 4363 fi; 4364 4365 eval ${_UNSET} mpm_list; 4366 eval ${_UNSET} mpm_opt; 4367 eval "${return_ok}"; 4368} # main_parse_MANOPT() 4369 4370 4371######################################################################## 4372# main_parse_args (<command_line_args>*) 4373# 4374# Parse arguments; process options and filespec parameters 4375# 4376# Arguments: pass the command line arguments unaltered. 4377# Globals: 4378# in: $_OPTS_* 4379# out: $_OPT_*, $_ADDOPTS, $_FILEARGS 4380# 4381# Variable prefix: mpa 4382# 4383main_parse_args() 4384{ 4385 func_check main_parse_args '>=' 0 "$@"; 4386 _ALL_PARAMS="$(list_from_cmdline _OPTS_CMDLINE "$@")"; 4387 exit_test; 4388 if obj _DEBUG_PRINT_PARAMS is_yes 4389 then 4390 echo2 "parameters: ${_ALL_PARAMS}"; 4391 fi; 4392 eval set x "${_ALL_PARAMS}"; 4393 shift; 4394 4395 # By the call of `eval', unnecessary quoting was removed. So the 4396 # positional shell parameters ($1, $2, ...) are now guaranteed to 4397 # represent an option or an argument to the previous option, if any; 4398 # then a `--' argument for separating options and 4399 # parameters; followed by the filespec parameters if any. 4400 4401 # Note, the existence of arguments to options has already been checked. 4402 # So a check for `$#' or `--' should not be done for arguments. 4403 4404 until test "$#" -le 0 || is_equal "$1" '--' 4405 do 4406 mpa_opt="$1"; # $mpa_opt is fed into the option handler 4407 shift; 4408 case "${mpa_opt}" in 4409 -h|--help) 4410 usage; 4411 leave; 4412 ;; 4413 -Q|--source) # output source code (`Quellcode'). 4414 _OPT_MODE='source'; 4415 ;; 4416 -T|--device|--troff-device) # device; arg 4417 _OPT_DEVICE="$1"; 4418 _check_device_with_mode; 4419 shift; 4420 ;; 4421 -v|--version) 4422 version; 4423 leave; 4424 ;; 4425 -V) 4426 _OPT_V='yes'; 4427 ;; 4428 -Z|--ditroff|--intermediate-output) # groff intermediate output 4429 _OPT_Z='yes'; 4430 ;; 4431 -X) 4432 if is_X 4433 then 4434 _OPT_MODE=X; 4435 fi; 4436 ;; 4437 -?) 4438 # delete leading `-' 4439 mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')"; 4440 exit_test; 4441 if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}" 4442 then 4443 list_append _ADDOPTS_GROFF "${mpa_opt}"; 4444 elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}" 4445 then 4446 list_append _ADDOPTS_GROFF "${mpa_opt}" "$1"; 4447 shift; 4448 else 4449 error "main_parse_args(): Unknown option : \`$1'"; 4450 fi; 4451 ;; 4452 --all) 4453 _OPT_ALL='yes'; 4454 ;; 4455 --apropos) # run `apropos' 4456 _OPT_APROPOS='yes'; 4457 _APROPOS_SECTIONS=''; 4458 _OPT_WHATIS='no'; 4459 ;; 4460 --apropos-data) # run `apropos' for data sections 4461 _OPT_APROPOS='yes'; 4462 _APROPOS_SECTIONS='457'; 4463 _OPT_WHATIS='no'; 4464 ;; 4465 --apropos-devel) # run `apropos' for development sections 4466 _OPT_APROPOS='yes'; 4467 _APROPOS_SECTIONS='239'; 4468 _OPT_WHATIS='no'; 4469 ;; 4470 --apropos-progs) # run `apropos' for program sections 4471 _OPT_APROPOS='yes'; 4472 _APROPOS_SECTIONS='168'; 4473 _OPT_WHATIS='no'; 4474 ;; 4475 --ascii) 4476 list_append _ADDOPTS_GROFF '-mtty-char'; 4477 if obj _OPT_MODE is_empty 4478 then 4479 _OPT_MODE='text'; 4480 fi; 4481 ;; 4482 --auto) # the default automatic mode 4483 _OPT_MODE=''; 4484 ;; 4485 --bd) # border color for viewers, arg; 4486 _OPT_BD="$1"; 4487 shift; 4488 ;; 4489 --bg|--backgroud) # background color for viewers, arg; 4490 _OPT_BG="$1"; 4491 shift; 4492 ;; 4493 --bw) # border width for viewers, arg; 4494 _OPT_BW="$1"; 4495 shift; 4496 ;; 4497 --debug|--debug-all|--debug-keep|--debug-lm|--debug-params|\ 4498--debug-shell|--debug-stacks|--debug-tmpdir|--debug-user) 4499 # debug is handled at the beginning 4500 :; 4501 ;; 4502 --default) # reset variables to default 4503 reset; 4504 ;; 4505 --default-modes) # sequence of modes in auto mode; arg 4506 _OPT_DEFAULT_MODES="$1"; 4507 shift; 4508 ;; 4509 --display) # set X display, arg 4510 _OPT_DISPLAY="$1"; 4511 shift; 4512 ;; 4513 --do-nothing) 4514 _OPT_DO_NOTHING='yes'; 4515 ;; 4516 --dvi) 4517 if is_X 4518 then 4519 _OPT_MODE='dvi'; 4520 fi; 4521 ;; 4522 --dvi-viewer) # viewer program for dvi mode; arg 4523 _VIEWER_TERMINAL='no'; 4524 _OPT_VIEWER_DVI="$1"; 4525 shift; 4526 ;; 4527 --dvi-viewer-tty) # viewer program for dvi mode in tty; arg 4528 _VIEWER_TERMINAL='yes'; 4529 _OPT_VIEWER_DVI="$1"; 4530 shift; 4531 ;; 4532 --extension) # the extension for man pages, arg 4533 _OPT_EXTENSION="$1"; 4534 shift; 4535 ;; 4536 --fg|--foreground) # foreground color for viewers, arg; 4537 _OPT_FG="$1"; 4538 shift; 4539 ;; 4540 --fn|--font) # set font for viewers, arg; 4541 _OPT_FN="$1"; 4542 shift; 4543 ;; 4544 --geometry) # window geometry for viewers, arg; 4545 _OPT_GEOMETRY="$1"; 4546 shift; 4547 ;; 4548 --groff) 4549 _OPT_MODE='groff'; 4550 ;; 4551 --html|--www) # display with web browser 4552 _OPT_MODE=html; 4553 ;; 4554 --html-viewer|--www-viewer) # viewer program for html mode; arg 4555 _VIEWER_TERMINAL='no'; 4556 _OPT_VIEWER_HTML="$1"; 4557 shift; 4558 ;; 4559 --html-viewer-tty|--www-viewer-tty) # viewer for html mode in tty; arg 4560 _VIEWER_TERMINAL='yes'; 4561 _OPT_VIEWER_HTML="$1"; 4562 shift; 4563 ;; 4564 --iconic) # start viewers as icons 4565 _OPT_ICONIC='yes'; 4566 ;; 4567 --locale) # set language for man pages, arg 4568 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...) 4569 _OPT_LANG="$1"; 4570 shift; 4571 ;; 4572 --local-file) # force local files; same as `--no-man' 4573 _MAN_FORCE='no'; 4574 _MAN_ENABLE='no'; 4575 ;; 4576 --location|--where) # print file locations to stderr 4577 _OPT_LOCATION='yes'; 4578 ;; 4579 --man) # force all file params to be man pages 4580 _MAN_ENABLE='yes'; 4581 _MAN_FORCE='yes'; 4582 ;; 4583 --manpath) # specify search path for man pages, arg 4584 # arg is colon-separated list of directories 4585 _OPT_MANPATH="$1"; 4586 shift; 4587 ;; 4588 --mode) # display mode 4589 mpa_arg="$1"; 4590 shift; 4591 case "${mpa_arg}" in 4592 auto|'') # search mode automatically among default 4593 _OPT_MODE=''; 4594 ;; 4595 groff) # pass input to plain groff 4596 _OPT_MODE='groff'; 4597 ;; 4598 html|www) # display with a web browser 4599 _OPT_MODE='html'; 4600 ;; 4601 dvi) # display with xdvi viewer 4602 if is_X 4603 then 4604 _OPT_MODE='dvi'; 4605 fi; 4606 ;; 4607 pdf) # display with PDF viewer 4608 if is_X 4609 then 4610 _OPT_MODE='pdf'; 4611 fi; 4612 ;; 4613 ps) # display with Postscript viewer 4614 if is_X 4615 then 4616 _OPT_MODE='ps'; 4617 fi; 4618 ;; 4619 text) # output on terminal 4620 _OPT_MODE='text'; 4621 ;; 4622 tty) # output on terminal 4623 _OPT_MODE='tty'; 4624 ;; 4625 X|x) # output on X roff viewer 4626 if is_X 4627 then 4628 _OPT_MODE='x'; 4629 fi; 4630 ;; 4631 Q|source) # display source code 4632 _OPT_MODE="source"; 4633 ;; 4634 *) 4635 error "main_parse_args(): unknown mode ${mpa_arg}"; 4636 ;; 4637 esac; 4638 ;; 4639 --no-location) # disable former call to `--location' 4640 _OPT_LOCATION='yes'; 4641 ;; 4642 --no-man) # disable search for man pages 4643 # the same as --local-file 4644 _MAN_FORCE='no'; 4645 _MAN_ENABLE='no'; 4646 ;; 4647 --no-special) # disable some special former calls 4648 _OPT_ALL='no' 4649 _OPT_APROPOS='no' 4650 _OPT_WHATIS='no' 4651 ;; 4652 --pager|--tty-viewer|--tty-viewer-tty) 4653 # set paging program for tty mode, arg 4654 _VIEWER_TERMINAL='yes'; 4655 _OPT_PAGER="$1"; 4656 shift; 4657 ;; 4658 --pdf) 4659 if is_X 4660 then 4661 _OPT_MODE='pdf'; 4662 fi; 4663 ;; 4664 --pdf-viewer) # viewer program for ps mode; arg 4665 _VIEWER_TERMINAL='no'; 4666 _OPT_VIEWER_PDF="$1"; 4667 shift; 4668 ;; 4669 --pdf-viewer-tty) # viewer program for ps mode in tty; arg 4670 _VIEWER_TERMINAL='yes'; 4671 _OPT_VIEWER_PDF="$1"; 4672 shift; 4673 ;; 4674 --print) # for argument test 4675 echo2 "$1"; 4676 shift; 4677 ;; 4678 --ps) 4679 if is_X 4680 then 4681 _OPT_MODE='ps'; 4682 fi; 4683 ;; 4684 --ps-viewer) # viewer program for ps mode; arg 4685 _VIEWER_TERMINAL='no'; 4686 _OPT_VIEWER_PS="$1"; 4687 shift; 4688 ;; 4689 --ps-viewer-tty) # viewer program for ps mode in tty; arg 4690 _VIEWER_TERMINAL='yes'; 4691 _OPT_VIEWER_PS="$1"; 4692 shift; 4693 ;; 4694 --resolution) # set resolution for X devices, arg 4695 mpa_arg="$1"; 4696 shift; 4697 case "${mpa_arg}" in 4698 75|75dpi) 4699 mpa_dpi=75; 4700 ;; 4701 100|100dpi) 4702 mpa_dpi=100; 4703 ;; 4704 *) 4705 error "main_parse_args(): \ 4706only resoutions of 75 or 100 dpi are supported"; 4707 ;; 4708 esac; 4709 _OPT_RESOLUTION="${mpa_dpi}"; 4710 ;; 4711 --rv) 4712 _OPT_RV='yes'; 4713 ;; 4714 --sections) # specify sections for man pages, arg 4715 # arg is colon-separated list of section names 4716 _OPT_SECTIONS="$1"; 4717 shift; 4718 ;; 4719 --shell) 4720 # already done during the first run; so ignore the argument 4721 shift; 4722 ;; 4723 --systems) # man pages for different OS's, arg 4724 # argument is a comma-separated list 4725 _OPT_SYSTEMS="$1"; 4726 shift; 4727 ;; 4728 --text) # text mode without pager 4729 _OPT_MODE=text; 4730 ;; 4731 --title) # title for X viewers; arg 4732 _OPT_TITLE="$1"; 4733 shift; 4734 ;; 4735 --tty) # tty mode, text with pager 4736 _OPT_MODE=tty; 4737 ;; 4738 --text-device|--tty-device) # device for tty mode; arg 4739 _OPT_TEXT_DEVICE="$1"; 4740 shift; 4741 ;; 4742 --whatis) 4743 _OPT_WHATIS='yes'; 4744 _OPT_ALL='yes'; 4745 _OPT_APROPOS='no'; 4746 ;; 4747 --X|--x) 4748 if is_X 4749 then 4750 _OPT_MODE=x; 4751 fi; 4752 ;; 4753 --xrm) # pass X resource string, arg; 4754 list_append _OPT_XRM "$1"; 4755 shift; 4756 ;; 4757 --x-viewer|--X-viewer) # viewer program for x mode; arg 4758 _VIEWER_TERMINAL='no'; 4759 _OPT_VIEWER_X="$1"; 4760 shift; 4761 ;; 4762 --x-viewer-tty|--X-viewer-tty) # viewer program for x mode in tty; arg 4763 _VIEWER_TERMINAL='yes'; 4764 _OPT_VIEWER_X="$1"; 4765 shift; 4766 ;; 4767 *) 4768 error 'main_parse_args(): error on argument parsing : '"\`$*'"; 4769 ;; 4770 esac; 4771 done; 4772 shift; # remove `--' argument 4773 4774 if obj _OPT_DO_NOTHING is_yes 4775 then 4776 leave; 4777 fi; 4778 4779 # Remaining arguments are file names (filespecs). 4780 # Save them to list $_FILEARGS 4781 if is_equal "$#" 0 4782 then # use "-" for standard input 4783 set x '-'; 4784 shift; 4785 fi; 4786 _FILEARGS=''; 4787 list_append _FILEARGS "$@"; 4788 if list_has _FILEARGS '-' 4789 then 4790 save_stdin; 4791 fi; 4792 # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;' 4793 eval ${_UNSET} mpa_arg; 4794 eval ${_UNSET} mpa_dpi; 4795 eval ${_UNSET} mpa_opt; 4796 eval ${_UNSET} mpa_optchar; 4797 eval "${return_ok}"; 4798} # main_parse_args() 4799 4800 4801# Called from main_parse_args() because double `case' is not possible. 4802# Globals: $_OPT_DEVICE, $_OPT_MODE 4803_check_device_with_mode() 4804{ 4805 func_check _check_device_with_mode = 0 "$@"; 4806 case "${_OPT_DEVICE}" in 4807 dvi) 4808 _OPT_MODE=dvi; 4809 eval "${return_ok}"; 4810 ;; 4811 html) 4812 _OPT_MODE=html; 4813 eval "${return_ok}"; 4814 ;; 4815 lbp|lj4) 4816 _OPT_MODE=groff; 4817 eval "${return_ok}"; 4818 ;; 4819 ps) 4820 _OPT_MODE=ps; 4821 eval "${return_ok}"; 4822 ;; 4823 ascii|cp1047|latin1|utf8) 4824 if obj _OPT_MODE is_not_equal text 4825 then 4826 _OPT_MODE=tty; # default text mode 4827 fi; 4828 eval "${return_ok}"; 4829 ;; 4830 X*) 4831 _OPT_MODE=x; 4832 eval "${return_ok}"; 4833 ;; 4834 *) # unknown device, go to groff mode 4835 _OPT_MODE=groff; 4836 eval "${return_ok}"; 4837 ;; 4838 esac; 4839 eval "${return_error}"; 4840} # _check_device_with_mode() of main_parse_args() 4841 4842 4843######################################################################## 4844# main_set_mode () 4845# 4846# Determine the display mode. 4847# 4848# Globals: 4849# in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE 4850# out: $_DISPLAY_MODE 4851# 4852# Variable prefix: msm 4853# 4854main_set_mode() 4855{ 4856 func_check main_set_mode = 0 "$@"; 4857 4858 # set display 4859 if obj _OPT_DISPLAY is_not_empty 4860 then 4861 DISPLAY="${_OPT_DISPLAY}"; 4862 fi; 4863 4864 if obj _OPT_V is_yes 4865 then 4866 list_append _ADDOPTS_GROFF '-V'; 4867 fi; 4868 if obj _OPT_Z is_yes 4869 then 4870 _DISPLAY_MODE='groff'; 4871 list_append _ADDOPTS_GROFF '-Z'; 4872 fi; 4873 if obj _OPT_MODE is_equal 'groff' 4874 then 4875 _DISPLAY_MODE='groff'; 4876 fi; 4877 if obj _DISPLAY_MODE is_equal 'groff' 4878 then 4879 eval ${_UNSET} msm_modes; 4880 eval ${_UNSET} msm_viewer; 4881 eval ${_UNSET} msm_viewers; 4882 eval "${return_ok}"; 4883 fi; 4884 4885 if obj _OPT_MODE is_equal 'source' 4886 then 4887 _DISPLAY_MODE='source'; 4888 eval ${_UNSET} msm_modes; 4889 eval ${_UNSET} msm_viewer; 4890 eval ${_UNSET} msm_viewers; 4891 eval "${return_ok}"; 4892 fi; 4893 4894 case "${_OPT_MODE}" in 4895 '') # automatic mode 4896 case "${_OPT_DEVICE}" in 4897 X*) 4898 if is_not_X 4899 then 4900 error_user "no X display found for device ${_OPT_DEVICE}"; 4901 fi; 4902 _DISPLAY_MODE='x'; 4903 eval ${_UNSET} msm_modes; 4904 eval ${_UNSET} msm_viewer; 4905 eval ${_UNSET} msm_viewers; 4906 eval "${return_ok}"; 4907 ;; 4908 ascii|cp1047|latin1|utf8) 4909 if obj _DISPLAY_MODE is_not_equal 'text' 4910 then 4911 _DISPLAY_MODE='tty'; 4912 fi; 4913 eval ${_UNSET} msm_modes; 4914 eval ${_UNSET} msm_viewer; 4915 eval ${_UNSET} msm_viewers; 4916 eval "${return_ok}"; 4917 ;; 4918 esac; 4919 if is_not_X 4920 then 4921 _DISPLAY_MODE='tty'; 4922 eval ${_UNSET} msm_modes; 4923 eval ${_UNSET} msm_viewer; 4924 eval ${_UNSET} msm_viewers; 4925 eval "${return_ok}"; 4926 fi; 4927 4928 if obj _OPT_DEFAULT_MODES is_empty 4929 then 4930 msm_modes="${_DEFAULT_MODES}"; 4931 else 4932 msm_modes="${_OPT_DEFAULT_MODES}"; 4933 fi; 4934 ;; 4935 text) 4936 _DISPLAY_MODE='text'; 4937 eval ${_UNSET} msm_modes; 4938 eval ${_UNSET} msm_viewer; 4939 eval ${_UNSET} msm_viewers; 4940 eval "${return_ok}"; 4941 ;; 4942 tty) 4943 _DISPLAY_MODE='tty'; 4944 eval ${_UNSET} msm_modes; 4945 eval ${_UNSET} msm_viewer; 4946 eval ${_UNSET} msm_viewers; 4947 eval "${return_ok}"; 4948 ;; 4949 html) 4950 _DISPLAY_MODE='html'; 4951 msm_modes="${_OPT_MODE}"; 4952 ;; 4953 *) # display mode was given 4954 if is_not_X 4955 then 4956 error_user "You must be in X Window for ${_OPT_MODE} mode."; 4957 fi; 4958 msm_modes="${_OPT_MODE}"; 4959 ;; 4960 esac; 4961 4962 # only viewer modes are left 4963 eval set x "$(list_from_split "${msm_modes}" ',')"; 4964 exit_test; 4965 shift; 4966 while test "$#" -gt 0 4967 do 4968 m="$1"; 4969 shift; 4970 case "$m" in 4971 dvi) 4972 if obj _OPT_VIEWER_DVI is_not_empty 4973 then 4974 msm_viewer="${_OPT_VIEWER_DVI}"; 4975 else 4976 msm_viewer="$(_get_first_prog "$_VIEWER_DVI}")"; 4977 exit_test; 4978 fi; 4979 if obj msm_viewer is_empty 4980 then 4981 error 'No viewer for dvi mode available.'; 4982 fi; 4983 if is_not_equal "$?" 0 4984 then 4985 continue; 4986 fi; 4987 _DISPLAY_PROG="${msm_viewer}"; 4988 _DISPLAY_MODE="dvi"; 4989 eval ${_UNSET} msm_modes; 4990 eval ${_UNSET} msm_viewer; 4991 eval ${_UNSET} msm_viewers; 4992 eval "${return_ok}"; 4993 ;; 4994 html) 4995 if obj _OPT_VIEWER_HTML is_not_empty 4996 then 4997 msm_viewer="${_OPT_VIEWER_HTML}"; 4998 else 4999 if is_X 5000 then 5001 msm_viewers="${_VIEWER_HTML_X}"; 5002 else 5003 msm_viewers="${_VIEWER_HTML_TTY}"; 5004 fi; 5005 msm_viewer="$(_get_first_prog "${msm_viewers}")"; 5006 exit_test; 5007 fi; 5008 if obj msm_viewer is_empty 5009 then 5010 error 'No viewer for html mode available.'; 5011 fi; 5012 if is_not_equal "$?" 0 5013 then 5014 continue; 5015 fi; 5016 _DISPLAY_PROG="${msm_viewer}"; 5017 _DISPLAY_MODE=html; 5018 eval ${_UNSET} msm_modes; 5019 eval ${_UNSET} msm_viewer; 5020 eval ${_UNSET} msm_viewers; 5021 eval "${return_ok}"; 5022 ;; 5023 pdf) 5024 if obj _OPT_VIEWER_PDF is_not_empty 5025 then 5026 msm_viewer="${_OPT_VIEWER_PDF}"; 5027 else 5028 msm_viewer="$(_get_first_prog "${_VIEWER_PDF}")"; 5029 exit_test; 5030 fi; 5031 if obj msm_viewer is_empty 5032 then 5033 error 'No viewer for pdf mode available.'; 5034 fi; 5035 if is_not_equal "$?" 0 5036 then 5037 continue; 5038 fi; 5039 _DISPLAY_PROG="${msm_viewer}"; 5040 _DISPLAY_MODE="pdf"; 5041 eval ${_UNSET} msm_modes; 5042 eval ${_UNSET} msm_viewer; 5043 eval ${_UNSET} msm_viewers; 5044 eval "${return_ok}"; 5045 ;; 5046 ps) 5047 if obj _OPT_VIEWER_PS is_not_empty 5048 then 5049 msm_viewer="${_OPT_VIEWER_PS}"; 5050 else 5051 msm_viewer="$(_get_first_prog "${_VIEWER_PS}")"; 5052 exit_test; 5053 fi; 5054 if obj msm_viewer is_empty 5055 then 5056 error 'No viewer for ps mode available.'; 5057 fi; 5058 if is_not_equal "$?" 0 5059 then 5060 continue; 5061 fi; 5062 _DISPLAY_PROG="${msm_viewer}"; 5063 _DISPLAY_MODE="ps"; 5064 eval ${_UNSET} msm_modes; 5065 eval ${_UNSET} msm_viewer; 5066 eval ${_UNSET} msm_viewers; 5067 eval "${return_ok}"; 5068 ;; 5069 text) 5070 _DISPLAY_MODE='text'; 5071 eval ${_UNSET} msm_modes; 5072 eval ${_UNSET} msm_viewer; 5073 eval ${_UNSET} msm_viewers; 5074 eval "${return_ok}"; 5075 ;; 5076 tty) 5077 _DISPLAY_MODE='tty'; 5078 eval ${_UNSET} msm_modes; 5079 eval ${_UNSET} msm_viewer; 5080 eval ${_UNSET} msm_viewers; 5081 eval "${return_ok}"; 5082 ;; 5083 x) 5084 if obj _OPT_VIEWER_X is_not_empty 5085 then 5086 msm_viewer="${_OPT_VIEWER_X}"; 5087 else 5088 msm_viewer="$(_get_first_prog "${_VIEWER_X}")"; 5089 exit_test; 5090 fi; 5091 if obj msm_viewer is_empty 5092 then 5093 error 'No viewer for x mode available.'; 5094 fi; 5095 if is_not_equal "$?" 0 5096 then 5097 continue; 5098 fi; 5099 _DISPLAY_PROG="${msm_viewer}"; 5100 _DISPLAY_MODE='x'; 5101 eval ${_UNSET} msm_modes; 5102 eval ${_UNSET} msm_viewer; 5103 eval ${_UNSET} msm_viewers; 5104 eval "${return_ok}"; 5105 ;; 5106 X) 5107 _DISPLAY_MODE='X'; 5108 eval ${_UNSET} msm_modes; 5109 eval ${_UNSET} msm_viewer; 5110 eval ${_UNSET} msm_viewers; 5111 eval "${return_ok}"; 5112 ;; 5113 esac; 5114 done; 5115 eval ${_UNSET} msm_modes; 5116 eval ${_UNSET} msm_viewer; 5117 eval ${_UNSET} msm_viewers; 5118 error_user "No suitable display mode found."; 5119} # main_set_mode() 5120 5121 5122# _get_first_prog (<proglist>) 5123# 5124# Retrieve first argument that represents an existing program in $PATH. 5125# Local function for main_set_mode(). 5126# 5127# Arguments: 1; a comma-separated list of commands (with options), 5128# like $_VIEWER_*. 5129# 5130# Return : `1' if none found, `0' if found. 5131# Output : the argument that succeded. 5132# 5133# Variable prefix: _gfp 5134# 5135_get_first_prog() 5136{ 5137 if is_equal "$#" 0 5138 then 5139 error "_get_first_prog() needs 1 argument."; 5140 fi; 5141 if is_empty "$1" 5142 then 5143 return "${_BAD}"; 5144 fi; 5145 eval set x "$(list_from_split "$1" ',')"; 5146 exit_test; 5147 shift; 5148 for i 5149 do 5150 _gfp_i="$i"; 5151 if obj _gfp_i is_empty 5152 then 5153 continue; 5154 fi; 5155 if eval is_prog "$(get_first_essential ${_gfp_i})" 5156 then 5157 exit_test; 5158 obj _gfp_i echo1; 5159 eval ${_UNSET} _gfp_i; 5160 return "${_GOOD}"; 5161 fi; 5162 done; 5163 eval ${_UNSET} _gfp_i; 5164 return "${_BAD}"; 5165} # _get_first_prog() of main_set_mode() 5166 5167 5168####################################################################### 5169# main_do_fileargs () 5170# 5171# Process filespec arguments in $_FILEARGS. 5172# 5173# Globals: 5174# in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;') 5175# 5176# Variable prefix: mdfa 5177# 5178main_do_fileargs() 5179{ 5180 func_check main_do_fileargs = 0 "$@"; 5181 special_setup; 5182 eval set x "${_FILEARGS}"; 5183 shift; 5184 eval ${_UNSET} _FILEARGS; 5185 # temporary storage of all input to $_TMP_CAT 5186 while test "$#" -ge 2 5187 do 5188 # test for `s name' arguments, with `s' a 1-char standard section 5189 mdfa_filespec="$1"; 5190 _FILESPEC_ARG="$1"; 5191 shift; 5192 case "${mdfa_filespec}" in 5193 '') 5194 continue; 5195 ;; 5196 '-') 5197 special_filespec; 5198 if obj _OPT_APROPOS is_yes 5199 then 5200 continue; 5201 fi; 5202 register_file '-' 5203 continue; 5204 ;; 5205 ?) 5206 if obj _OPT_APROPOS is_yes 5207 then 5208 special_filespec; 5209 continue; 5210 fi; 5211 if list_has_not _MAN_AUTO_SEC_LIST "${mdfa_filespec}" 5212 then 5213 special_filespec; 5214 do_filearg "${mdfa_filespec}" 5215 continue; 5216 fi; 5217 mdfa_name="$1"; 5218 _FILESPEC_ARG="${_FILESPEC_ARG} $1"; 5219 special_filespec; 5220 case "${mdfa_name}" in 5221 */*|man:*|*\(*\)|*."${mdfa_filespec}") 5222 do_filearg "${mdfa_filespec}" 5223 continue; 5224 ;; 5225 esac; 5226 shift; 5227 if do_filearg "man:${mdfa_name}(${mdfa_filespec})" 5228 then 5229 continue; 5230 else 5231 do_filearg "${mdfa_filespec}" 5232 continue; 5233 fi; 5234 ;; 5235 *) 5236 special_filespec; 5237 if obj _OPT_APROPOS is_yes 5238 then 5239 continue; 5240 fi; 5241 do_filearg "${mdfa_filespec}" 5242 continue; 5243 ;; 5244 esac; 5245 done; # end of `s name' test 5246 while test "$#" -gt 0 5247 do 5248 mdfa_filespec="$1"; 5249 _FILESPEC_ARG="$1"; 5250 shift; 5251 special_filespec; 5252 if obj _OPT_APROPOS is_yes 5253 then 5254 continue; 5255 fi; 5256 do_filearg "${mdfa_filespec}" 5257 done; 5258 obj _TMP_STDIN rm_file_with_debug; 5259 eval ${_UNSET} mdfa_filespec; 5260 eval ${_UNSET} mdfa_name; 5261 eval "${return_ok}"; 5262} # main_do_fileargs() 5263 5264 5265######################################################################## 5266# main_set_resources () 5267# 5268# Determine options for setting X resources with $_DISPLAY_PROG. 5269# 5270# Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME 5271# 5272# Variable prefix: msr 5273# 5274main_set_resources() 5275{ 5276 func_check main_set_resources = 0 "$@"; 5277 # $msr_prog viewer program 5278 # $msr_rl resource list 5279 msr_title="$(get_first_essential \ 5280 "${_OPT_TITLE}" "${_REGISTERED_TITLE}")"; 5281 exit_test; 5282 _OUTPUT_FILE_NAME=''; 5283 eval set x "${msr_title}"; 5284 shift; 5285 until is_equal "$#" 0 5286 do 5287 msr_n="$1"; 5288 case "${msr_n}" in 5289 '') 5290 continue; 5291 ;; 5292 ,*) 5293 msr_n="$(echo1 "$1" | sed -e 's/^,,*//')"; 5294 exit_test; 5295 ;; 5296 esac 5297 if obj msr_n is_empty 5298 then 5299 continue; 5300 fi; 5301 if obj _OUTPUT_FILE_NAME is_not_empty 5302 then 5303 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"','; 5304 fi; 5305 _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}"; 5306 shift; 5307 done; 5308 case "${_OUTPUT_FILE_NAME}" in 5309 '') 5310 _OUTPUT_FILE_NAME='-'; 5311 ;; 5312 ,*) 5313 error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma."; 5314 ;; 5315 esac; 5316 _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}"; 5317 5318 if obj _DISPLAY_PROG is_empty 5319 then # for example, for groff mode 5320 _DISPLAY_ARGS=''; 5321 eval ${_UNSET} msr_n; 5322 eval ${_UNSET} msr_prog; 5323 eval ${_UNSET} msr_rl; 5324 eval ${_UNSET} msr_title; 5325 eval "${return_ok}"; 5326 fi; 5327 5328 eval set x "${_DISPLAY_PROG}"; 5329 shift; 5330 msr_prog="$(base_name "$1")"; 5331 exit_test; 5332 shift; 5333 if test $# != 0 5334 then 5335 if obj _DISPLAY_PROG is_empty 5336 then 5337 _DISPLAY_ARGS="$*"; 5338 else 5339 _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}"; 5340 fi; 5341 fi; 5342 msr_rl=''; 5343 if obj _OPT_BD is_not_empty 5344 then 5345 case "${msr_prog}" in 5346 ghostview|gv|gxditview|xditview|xdvi) 5347 list_append msr_rl '-bd' "${_OPT_BD}"; 5348 ;; 5349 esac; 5350 fi; 5351 if obj _OPT_BG is_not_empty 5352 then 5353 case "${msr_prog}" in 5354 ghostview|gv|gxditview|xditview|xdvi) 5355 list_append msr_rl '-bg' "${_OPT_BG}"; 5356 ;; 5357 kghostview) 5358 list_append msr_rl '--bg' "${_OPT_BG}"; 5359 ;; 5360 xpdf) 5361 list_append msr_rl '-papercolor' "${_OPT_BG}"; 5362 ;; 5363 esac; 5364 fi; 5365 if obj _OPT_BW is_not_empty 5366 then 5367 case "${msr_prog}" in 5368 ghostview|gv|gxditview|xditview|xdvi) 5369 _list_append msr_rl '-bw' "${_OPT_BW}"; 5370 ;; 5371 esac; 5372 fi; 5373 if obj _OPT_FG is_not_empty 5374 then 5375 case "${msr_prog}" in 5376 ghostview|gv|gxditview|xditview|xdvi) 5377 list_append msr_rl '-fg' "${_OPT_FG}"; 5378 ;; 5379 kghostview) 5380 list_append msr_rl '--fg' "${_OPT_FG}"; 5381 ;; 5382 esac; 5383 fi; 5384 if is_not_empty "${_OPT_FN}" 5385 then 5386 case "${msr_prog}" in 5387 ghostview|gv|gxditview|xditview|xdvi) 5388 list_append msr_rl '-fn' "${_OPT_FN}"; 5389 ;; 5390 kghostview) 5391 list_append msr_rl '--fn' "${_OPT_FN}"; 5392 ;; 5393 esac; 5394 fi; 5395 if is_not_empty "${_OPT_GEOMETRY}" 5396 then 5397 case "${msr_prog}" in 5398 ghostview|gv|gxditview|xditview|xdvi|xpdf) 5399 list_append msr_rl '-geometry' "${_OPT_GEOMETRY}"; 5400 ;; 5401 kghostview) 5402 list_append msr_rl '--geometry' "${_OPT_GEOMETRY}"; 5403 ;; 5404 esac; 5405 fi; 5406 if is_empty "${_OPT_RESOLUTION}" 5407 then 5408 _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}"; 5409 case "${msr_prog}" in 5410 gxditview|xditview) 5411 list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}"; 5412 ;; 5413 xpdf) 5414 case "${_DEFAULT_RESOLUTION}" in 5415 75) 5416 # 72dpi is '100' 5417 list_append msr_rl '-z' '104'; 5418 ;; 5419 100) 5420 list_append msr_rl '-z' '139'; 5421 ;; 5422 esac; 5423 ;; 5424 esac; 5425 else 5426 case "${msr_prog}" in 5427 ghostview|gv|gxditview|xditview|xdvi) 5428 list_append msr_rl '-resolution' "${_OPT_RESOLUTION}"; 5429 ;; 5430 xpdf) 5431 case "${_OPT_RESOLUTION}" in 5432 75) 5433 list_append msr_rl '-z' '104'; 5434 # '100' corresponds to 72dpi 5435 ;; 5436 100) 5437 list_append msr_rl '-z' '139'; 5438 ;; 5439 esac; 5440 ;; 5441 esac; 5442 fi; 5443 if is_yes "${_OPT_ICONIC}" 5444 then 5445 case "${msr_prog}" in 5446 ghostview|gv|gxditview|xditview|xdvi) 5447 list_append msr_rl '-iconic'; 5448 ;; 5449 esac; 5450 fi; 5451 if is_yes "${_OPT_RV}" 5452 then 5453 case "${msr_prog}" in 5454 ghostview|gv|gxditview|xditview|xdvi) 5455 list_append msr_rl '-rv'; 5456 ;; 5457 esac; 5458 fi; 5459 if is_not_empty "${_OPT_XRM}" 5460 then 5461 case "${msr_prog}" in 5462 ghostview|gv|gxditview|xditview|xdvi|xpdf) 5463 eval set x "${_OPT_XRM}"; 5464 shift; 5465 for i 5466 do 5467 list_append msr_rl '-xrm' "$i"; 5468 done; 5469 ;; 5470 esac; 5471 fi; 5472 if is_not_empty "${msr_title}" 5473 then 5474 case "${msr_prog}" in 5475 gxditview|xditview) 5476 list_append msr_rl '-title' "${msr_title}"; 5477 ;; 5478 esac; 5479 fi; 5480 _DISPLAY_ARGS="${msr_rl}"; 5481 eval ${_UNSET} msr_n; 5482 eval ${_UNSET} msr_prog; 5483 eval ${_UNSET} msr_rl; 5484 eval ${_UNSET} msr_title; 5485 eval "${return_ok}"; 5486} # main_set_resources 5487 5488 5489######################################################################## 5490# main_display () 5491# 5492# Do the actual display of the whole thing. 5493# 5494# Globals: 5495# in: $_DISPLAY_MODE, $_OPT_DEVICE, 5496# $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X, 5497# $_TMP_CAT, $_OPT_PAGER, $PAGER, $_MANOPT_PAGER, 5498# $_OUTPUT_FILE_NAME 5499# 5500# Variable prefix: md 5501# 5502main_display() 5503{ 5504 func_check main_display = 0 "$@"; 5505 5506 export md_addopts; 5507 export md_groggy; 5508 export md_modefile; 5509 5510 if obj _TMP_CAT is_non_empty_file 5511 then 5512 md_modefile="${_OUTPUT_FILE_NAME}"; 5513 else 5514 echo2 'groffer: empty input.'; 5515 clean_up; 5516 eval ${_UNSET} md_modefile; 5517 eval "${return_ok}"; 5518 fi; 5519 5520 # go to the temporary directory to be able to access internal data files 5521 cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1; 5522 5523 case "${_DISPLAY_MODE}" in 5524 groff) 5525 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; 5526 if obj _OPT_DEVICE is_not_empty 5527 then 5528 _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}"; 5529 fi; 5530 md_groggy="$(tmp_cat | eval grog "${md_options}")"; 5531 exit_test; 5532 _do_opt_V; 5533 5534 obj md_modefile rm_file; 5535 mv "${_TMP_CAT}" "${md_modefile}"; 5536 trap_unset; 5537 cat "${md_modefile}" | \ 5538 { 5539 trap_set; 5540 eval "${md_groggy}" "${_ADDOPTS_GROFF}"; 5541 } & 5542 ;; 5543 text|tty) 5544 case "${_OPT_DEVICE}" in 5545 '') 5546 md_device="$(get_first_essential \ 5547 "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")"; 5548 exit_test; 5549 ;; 5550 ascii|cp1047|latin1|utf8) 5551 md_device="${_OPT_DEVICE}"; 5552 ;; 5553 *) 5554 warning "main_display(): \ 5555wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; 5556 ;; 5557 esac; 5558 md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; 5559 md_groggy="$(tmp_cat | grog -T${md_device})"; 5560 exit_test; 5561 if obj _DISPLAY_MODE is_equal 'text' 5562 then 5563 _do_opt_V; 5564 tmp_cat | eval "${md_groggy}" "${md_addopts}"; 5565 else 5566 md_pager=''; 5567 for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \ 5568 'less -r -R' 'more' 'pager' 'cat' 5569 do 5570 md_p="$p"; 5571 if eval is_prog ${md_p} 5572 then # no "" for is_prog() allows args for $p 5573 md_pager="${md_p}"; 5574 break; 5575 fi; 5576 done; 5577 if obj md_pager is_empty 5578 then 5579 error 'main_display(): no pager program found for tty mode'; 5580 fi; 5581 _do_opt_V; 5582 tmp_cat | eval "${md_groggy}" "${md_addopts}" | \ 5583 eval "${md_pager}"; 5584 fi; 5585 clean_up; 5586 ;; 5587 source) 5588 tmp_cat; 5589 clean_up; 5590 ;; 5591 5592 #### viewer modes 5593 5594 dvi) 5595 case "${_OPT_DEVICE}" in 5596 ''|dvi) do_nothing; ;; 5597 *) 5598 warning "main_display(): \ 5599wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}" 5600 ;; 5601 esac; 5602 md_modefile="${md_modefile}".dvi; 5603 md_groggy="$(tmp_cat | grog -Tdvi)"; 5604 exit_test; 5605 _do_display; 5606 ;; 5607 html) 5608 case "${_OPT_DEVICE}" in 5609 ''|html) do_nothing; ;; 5610 *) 5611 warning "main_display(): \ 5612wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; 5613 ;; 5614 esac; 5615 md_modefile="${md_modefile}".html; 5616 md_groggy="$(tmp_cat | grog -Thtml)"; 5617 exit_test; 5618 _do_display; 5619 ;; 5620 pdf) 5621 case "${_OPT_DEVICE}" in 5622 ''|ps) 5623 do_nothing; 5624 ;; 5625 *) 5626 warning "main_display(): \ 5627wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; 5628 ;; 5629 esac; 5630 md_groggy="$(tmp_cat | grog -Tps)"; 5631 exit_test; 5632 _do_display _make_pdf; 5633 ;; 5634 ps) 5635 case "${_OPT_DEVICE}" in 5636 ''|ps) 5637 do_nothing; 5638 ;; 5639 *) 5640 warning "main_display(): \ 5641wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; 5642 ;; 5643 esac; 5644 md_modefile="${md_modefile}".ps; 5645 md_groggy="$(tmp_cat | grog -Tps)"; 5646 exit_test; 5647 _do_display; 5648 ;; 5649 x) 5650 case "${_OPT_DEVICE}" in 5651 X*) 5652 md_device="${_OPT_DEVICE}" 5653 ;; 5654 *) 5655 case "${_OPT_RESOLUTION}" in 5656 100) 5657 md_device='X100'; 5658 if obj _OPT_GEOMETRY is_empty 5659 then 5660 case "${_DISPLAY_PROG}" in 5661 gxditview|xditview) 5662 # add width of 800dpi for resolution of 100dpi to the args 5663 list_append _DISPLAY_ARGS '-geometry' '800'; 5664 ;; 5665 esac; 5666 fi; 5667 ;; 5668 *) 5669 md_device='X75-12'; 5670 ;; 5671 esac 5672 esac; 5673 md_groggy="$(tmp_cat | grog -T${md_device} -Z)"; 5674 exit_test; 5675 _do_display; 5676 ;; 5677 X) 5678 case "${_OPT_DEVICE}" in 5679 '') 5680 md_groggy="$(tmp_cat | grog -X)"; 5681 exit_test; 5682 ;; 5683 X*|dvi|html|lbp|lj4|ps) 5684 # these devices work with 5685 md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)"; 5686 exit_test; 5687 ;; 5688 *) 5689 warning "main_display(): \ 5690wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; 5691 md_groggy="$(tmp_cat | grog -Z)"; 5692 exit_test; 5693 ;; 5694 esac; 5695 _do_display; 5696 ;; 5697 *) 5698 error "main_display(): unknown mode \`${_DISPLAY_MODE}'"; 5699 ;; 5700 esac; 5701 eval ${_UNSET} md_addopts; 5702 eval ${_UNSET} md_device; 5703 eval ${_UNSET} md_groggy; 5704 eval ${_UNSET} md_modefile; 5705 eval ${_UNSET} md_options; 5706 eval ${_UNSET} md_p; 5707 eval ${_UNSET} md_pager; 5708 eval "${return_ok}"; 5709} # main_display() 5710 5711 5712######################## 5713# _do_display ([<prog>]) 5714# 5715# Perform the generation of the output and view the result. If an 5716# argument is given interpret it as a function name that is called in 5717# the midst (actually only for `pdf'). 5718# 5719# Globals: $md_modefile, $md_groggy (from main_display()) 5720# 5721_do_display() 5722{ 5723 func_check _do_display '>=' 0 "$@"; 5724 _do_opt_V; 5725 if obj _DISPLAY_PROG is_empty 5726 then 5727 trap_unset; 5728 { 5729 trap_set; 5730 eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}"; 5731 } & 5732 else 5733 obj md_modefile rm_file; 5734 cat "${_TMP_CAT}" | \ 5735 eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}"; 5736 if is_not_empty "$1" 5737 then 5738 eval "$1"; 5739 fi; 5740 obj _TMP_CAT rm_file_with_debug; 5741 if obj _VIEWER_TERMINAL is_yes # for programs that run on tty 5742 then 5743 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; 5744 else 5745 case "${_DISPLAY_PROG}" in 5746# lynx\ *|less\ *|more\ *) # programs known to run on the terminal 5747# eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; 5748# ;; 5749 *) 5750 trap_unset; 5751 { 5752 trap_set; 5753 eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; 5754 } & 5755 ;; 5756 esac; 5757 fi; 5758 fi; 5759 eval "${return_ok}"; 5760} # _do_display() of main_display() 5761 5762 5763############# 5764# _do_opt_V () 5765# 5766# Check on option `-V'; if set print the corresponding output and leave. 5767# 5768# Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG, 5769# $_DISPLAY_ARGS, $md_groggy, $md_modefile 5770# 5771# Variable prefix: _doV 5772# 5773_do_opt_V() 5774{ 5775 func_check _do_opt_V '=' 0 "$@"; 5776 if obj _OPT_V is_yes 5777 then 5778 _OPT_V='no'; 5779 echo1 "Parameters: ${_ALL_PARAMS}"; 5780 echo1 "Display mode: ${_DISPLAY_MODE}"; 5781 echo1 "Output file: ${md_modefile}"; 5782 echo1 "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}"; 5783 a="$(eval echo1 "'${_ADDOPTS_GROFF}'")"; 5784 exit_test; 5785 echo1 "Output of grog: ${md_groggy} $a"; 5786 _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")"; 5787 exit_test; 5788 echo1 "groff -V: ${_doV_res}" 5789 leave; 5790 fi; 5791 eval "${return_ok}"; 5792} # _do_opt_V() of main_display() 5793 5794 5795############## 5796# _make_pdf () 5797# 5798# Transform to pdf format; for pdf mode in _do_display(). 5799# 5800# Globals: $md_modefile (from main_display()) 5801# 5802# Variable prefix: _mp 5803# 5804_make_pdf() 5805{ 5806 func_check _do_display '=' 0 "$@"; 5807 _mp_psfile="${md_modefile}"; 5808 md_modefile="${md_modefile}.pdf"; 5809 obj md_modefile rm_file; 5810 if gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \ 5811 -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}" 5812 then 5813 :; 5814 else 5815 error '_make_pdf: could not transform into pdf format.'; 5816 fi; 5817 obj _mp_psfile rm_file_with_debug; 5818 eval ${_UNSET} _mp_psfile; 5819 eval "${return_ok}"; 5820} # _make_pdf() of main_display() 5821 5822 5823######################################################################## 5824# main (<command_line_args>*) 5825# 5826# The main function for groffer. 5827# 5828# Arguments: 5829# 5830main() 5831{ 5832 func_check main '>=' 0 "$@"; 5833 # Do not change the sequence of the following functions! 5834 landmark '13: main_init()'; 5835 main_init; 5836 landmark '14: main_parse_MANOPT()'; 5837 main_parse_MANOPT; 5838 landmark '15: main_parse_args()'; 5839 main_parse_args "$@"; 5840 landmark '16: main_set_mode()'; 5841 main_set_mode; 5842 landmark '17: main_do_fileargs()'; 5843 main_do_fileargs; 5844 landmark '18: main_set_resources()'; 5845 main_set_resources; 5846 landmark '19: main_display()'; 5847 main_display; 5848 eval "${return_ok}"; 5849} 5850 5851 5852######################################################################## 5853 5854main "$@"; 5855