#! /bin/sh # groffer - display groff files # Source file position: /contrib/groffer/shell/groffer2.sh # Installed position: /lib/groff/groffer/groffer2.sh # This file should not be run independently. It is called by # `groffer.sh' in the source or by the installed `groffer' program. # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # Written by Bernd Warken . # Last update: 5 Jan 2009 # This file is part of `groffer', which is part of `groff'. # `groff' is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # `groff' is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . ######################################################################## # Test of rudimentary shell functionality ######################################################################## # Zsh is not Bourne compatible without the following: if test -n "$ZSH_VERSION"; then emulate sh NULLCMD=: fi ######################################################################## # Test of `unset' # export _UNSET; export _foo; _foo=bar; _res="$(unset _foo 2>&1)"; if unset _foo >${_NULL_DEV} 2>&1 && \ test _"${_res}"_ = __ && test _"${_foo}"_ = __ then _UNSET='unset'; eval "${_UNSET}" _foo; eval "${_UNSET}" _res; else _UNSET=':'; fi; ######################################################################## # Test of `test'. # if test a = a && test a != b && test -f "${_GROFFER_SH}" then :; else echo '"test" did not work.' >&2; exit "${_ERROR}"; fi; ######################################################################## # Test of `echo' and the `$()' construct. # if echo '' >${_NULL_DEV} then :; else echo '"echo" did not work.' >&2; exit "${_ERROR}"; fi; if test _"$(t1="$(echo te)" && t2="$(echo '')" && t3="$(echo 'st')" && echo "${t1}${t2}${t3}")"_ \ != _test_ then echo 'The "$()" construct did not work' >&2; exit "${_ERROR}"; fi; ######################################################################## # Test of sed program; test in groffer.sh is not valid here. # if test _"$(echo xTesTx \ | sed -n 's/^.\([Tt]e*x*sTT*\).*$/\1/p' \ | sed 's|T|t|g')"_ != _test_ then echo 'The sed program did not work.' >&2; exit "${_ERROR}"; fi; ######################################################################## # Test of `cat'. # if test _"$(echo test | cat)"_ != _test_ then error 'Test of "cat" command failed.'; fi; ######################################################################## # Test of function definitions. # _t_e_s_t_f_u_n_c_() { return 0; } _test_func() { echo test; } if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV} && \ test _"$(_test_func 2>${_NULL_DEV})"_ = _test_ then :; else echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2; exit "${_ERROR}"; fi; ######################################################################## # landmark () # # Print to standard error as a debugging aid. # # Globals: $_DEBUG_LM # landmark() { if test _"${_DEBUG_LM}"_ = _yes_ then echo "LM: $*" >&2; fi; } # landmark() ######################################################################## # test for compression. # export _HAS_COMPRESSION; export _HAS_BZIP; if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_ then _HAS_COMPRESSION='yes'; if echo 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \ && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \ | bzip2 -d -c 2>${_NULL_DEV})"_ \ = _test_ then _HAS_BZIP='yes'; else _HAS_BZIP='no'; fi; else _HAS_COMPRESSION='no'; _HAS_BZIP='no'; fi; ######################################################################## # debug - diagnostic messages ######################################################################## export _DEBUG_FUNC_CHECK; if test _"${_BEFORE_MAKE}"_ = _yes_ then _DEBUG_FUNC_CHECK='yes'; else _DEBUG_FUNC_CHECK='no'; fi; _DEBUG_FUNC_CHECK='no'; # disable function checking #_DEBUG_FUNC_CHECK='yes'; # enable function checking export _DEBUG_STACKS; _DEBUG_STACKS='no'; # disable stack output in each function #_DEBUG_STACKS='yes'; # enable stack output in each function export _DEBUG_USER_WITH_STACK; _DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user() #_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user() export _DEBUG_LM; _DEBUG_LM='no'; # disable landmark messages #_DEBUG_LM='yes'; # enable landmark messages export _DEBUG_GROG; _DEBUG_GROG='no'; # disable grog output #_DEBUG_GROG='yes'; # enable grog output export _DEBUG_KEEP_FILES; _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir #_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir export _DEBUG_PRINT_PARAMS; _DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters #_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters export _DEBUG_PRINT_SHELL; _DEBUG_PRINT_SHELL='no'; # disable printing of the shell name #_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name export _DEBUG_PRINT_TMPDIR; _DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir #_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir export _DEBUG_PRINT_FILENAMES; _DEBUG_PRINT_FILENAMES='no'; # disable printing of the found file names #_DEBUG_PRINT_FILENAMES='yes'; # enable printing of the found file names # determine all --debug* options case " $*" in *\ --deb*|*\ --d*-*) # --debug-* options d=' --debug-all --debug-filenames --debug-func --debug-grog '\ '--debug-not-func --debug-keep --debug-lm --debug-params '\ '--debug-shell --debug-stacks --debug-tmpdir --debug-user '; # non-debug options with scheme --d*-* n=' --do-nothing --default-modes --dvi-viewer --dvi-viewer-tty '; for i do case "$i" in --deb|--debu|--debug) _DEBUG_FUNC_CHECK='yes'; # _DEBUG_STACKS='yes'; _DEBUG_USER_WITH_STACK='yes'; # _DEBUG_LM='yes'; _DEBUG_GROG='yes'; _DEBUG_KEEP_FILES='yes'; _DEBUG_PRINT_PARAMS='yes'; _DEBUG_PRINT_SHELL='yes'; _DEBUG_PRINT_TMPDIR='yes'; _DEBUG_PRINT_FILENAMES='yes'; continue; ;; --d*-*) # before `-' b="$(echo x"$i" | sed 's/^x--\([^-]*\)-.*$/\1/')"; # after `-' a="$(echo x"$i" | sed 's/^x--[^-]*-\(.*\)$/\1/')"; ;; *) continue; ;; esac; case "$n" in *\ --$b*-$a*) continue; ;; esac; case "$d" in *\ --$b*-$a*) case "$a" in f|s) # double --debug-* options continue; ;; esac; # extract whole word of double abbreviation s="$(cat <&2; fi; if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_ then if test _"${_SHELL}"_ = __ then if test _"${POSIXLY_CORRECT}"_ = _y_ then echo 'shell: bash as /bin/sh (none specified)' >&2; else echo 'shell: /bin/sh (none specified)' >&2; fi; else echo "shell: ${_SHELL}" >&2; fi; fi; ######################################################################## # Environment Variables ######################################################################## landmark "1: environment variables"; # Environment variables that exist only for this file start with an # underscore letter. Global variables to this file are written in # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables # start with an underline and use only lower case letters and # underlines, e.g. $_local_variable. # [A-Z]* system variables, e.g. $MANPATH # _[A-Z_]* global file variables, e.g. $_MAN_PATH # _[a-z_]* temporary variables, e.g. $_manpath # Due to incompatibilities of the `ash' shell, the name of loop # variables in `for' must be a single character. # [a-z] local loop variables, e.g. $i # In functions, other writings are used for variables. As some shells # do not support the `local' command a unique prefix in lower case is # constructed for each function, most are the abbreviation of the # function name. All variable names start with this prefix. # ${prefix}_[a-z_]* variable name in a function, e.g. $msm_modes ######################################################################## # read-only variables (global to this file) ######################################################################## # function return values; `0' means ok; other values are error codes export _BAD; export _GOOD; export _NO; export _OK; export _YES; _GOOD='0'; # return ok _BAD='1'; # return negatively, error code `1' # $_ERROR was already defined as `7' in groffer.sh. _NO="${_BAD}"; _YES="${_GOOD}"; _OK="${_GOOD}"; # quasi-functions, call with `eval', e.g `eval "${return_ok}"' export return_ok; export return_good; export return_bad; export return_yes; export return_no; export return_error; export return_var; return_ok="func_pop; return ${_OK}"; return_good="func_pop; return ${_GOOD}"; return_bad="func_pop; return ${_BAD}"; return_yes="func_pop; return ${_YES}"; return_no="func_pop; return ${_NO}"; return_error="func_pop; return ${_ERROR}"; return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n' export _DEFAULT_MODES; _DEFAULT_MODES="'pdf' 'html' 'ps' 'x' 'dvi' 'tty'"; export _DEFAULT_RESOLUTION; _DEFAULT_RESOLUTION='75'; export _DEFAULT_TTY_DEVICE; _DEFAULT_TTY_DEVICE='latin1'; # _VIEWER_* viewer programs for different modes constructed as lists export _VIEWER_DVI_TTY; # viewer program for dvi mode in tty export _VIEWER_DVI_X; # viewer program for dvi mode in X export _VIEWER_HTML_TTY; # viewer program for html mode in tty export _VIEWER_HTML_X; # viewer program for html mode in X export _VIEWER_PDF_TTY; # viewer program for pdf mode in tty export _VIEWER_PDF_X; # viewer program for pdf mode in X export _VIEWER_PS_TTY; # viewer program for ps mode in tty export _VIEWER_PS_X; # viewer program for ps mode in X export _VIEWER_TTY_TTY; # viewer program for X/x mode in tty export _VIEWER_TTY_X; # viewer program for X/x mode in X export _VIEWER_X_TTY; # viewer program for X/x mode in tty export _VIEWER_X_X; # viewer program for X/x mode in X _VIEWER_DVI_TTY=""; _VIEWER_DVI_X="'kdvi' 'xdvi' 'dvilx'"; _VIEWER_HTML_TTY="'lynx' 'w3m'"; _VIEWER_HTML_X="'konqueror' 'epiphany' 'mozilla-firefox' 'firefox' 'mozilla' \ 'netscape' 'galeon' 'opera' 'amaya' 'arena' 'mosaic'"; _VIEWER_PDF_TTY=""; _VIEWER_PDF_X="'kpdf' 'acroread' 'evince' 'xpdf -z 150' 'gpdf' \ 'kghostview --scale 1.45' 'ggv'"; _VIEWER_PS_TTY=""; _VIEWER_PS_X="'kpdf' 'kghostview --scale 1.45' 'evince' 'ggv' 'gv' \ 'ghostview' 'gs_x11,gs'"; _VIEWER_TTY_TTY="'less -r -R' 'more' 'pager'"; _VIEWER_TTY_X="'xless'"; _VIEWER_X_TTY=""; _VIEWER_X_X="'gxditview' 'xditview'"; # Search automatically in standard sections `1' to `8', and in the # traditional sections `9', `n', and `o'. On many systems, there # exist even more sections, mostly containing a set of man pages # special to a specific program package. These aren't searched for # automatically, but must be specified on the command line. export _MAN_AUTO_SEC_LIST; _MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"; export _MAN_AUTO_SEC_CHARS; _MAN_AUTO_SEC_CHARS='[123456789no]'; export _SPACE_SED; _SPACE_SED='['"${_SP}${_TAB}"']'; export _SPACE_CASE; _SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']'; export _PROCESS_ID; # for shutting down the program _PROCESS_ID="$$"; export _START_DIR; # directory at start time of the script _START_DIR="$(pwd)"; ############ the command line options of the involved programs # # The naming scheme for the options environment names is # $_OPTS__[_] # # : program name GROFFER, GROFF, or CMDLINE (for all # command line options) # : LONG (long options) or SHORT (single character options) # : ARG for options with argument, NA for no argument; # without _ both the ones with and without arg. # # Each option that takes an argument must be specified with a # trailing : (colon). # exports export _OPTS_GROFFER_SHORT_NA; export _OPTS_GROFFER_SHORT_ARG; export _OPTS_GROFFER_LONG_NA; export _OPTS_GROFFER_LONG_ARG; export _OPTS_GROFF_SHORT_NA; export _OPTS_GROFF_SHORT_ARG; export _OPTS_GROFF_LONG_NA; export _OPTS_GROFF_LONG_ARG; export _OPTS_X_SHORT_ARG; export _OPTS_X_SHORT_NA; export _OPTS_X_LONG_ARG; export _OPTS_X_LONG_NA; export _OPTS_MAN_SHORT_ARG; export _OPTS_MAN_SHORT_NA; export _OPTS_MAN_LONG_ARG; export _OPTS_MAN_LONG_NA; export _OPTS_MANOPT_SHORT_ARG; export _OPTS_MANOPT_SHORT_NA; export _OPTS_MANOPT_LONG_ARG; export _OPTS_MANOPT_LONG_NA; export _OPTS_CMDLINE_SHORT_NA; export _OPTS_CMDLINE_SHORT_ARG; export _OPTS_CMDLINE_LONG_NA; export _OPTS_CMDLINE_LONG_ARG; ###### groffer native options _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'"; _OPTS_GROFFER_SHORT_ARG="'T'"; _OPTS_GROFFER_LONG_NA="'auto' \ 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \ 'debug' 'debug-all' 'debug-filenames' \ 'debug-func' 'debug-not-func' 'debug-grog' 'debug-keep' 'debug-lm' \ 'debug-params' 'debug-shell' 'debug-stacks' 'debug-tmpdir' 'debug-user' \ 'default' 'do-nothing' 'dvi' 'groff' 'help' 'intermediate-output' 'html' \ 'man' 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \ 'text' 'to-stdout' 'text-device' 'tty' 'tty-device' \ 'version' 'whatis' 'www' 'x' 'X'"; _OPTS_GROFFER_LONG_ARG="\ 'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \ 'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \ 'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \ 'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \ 'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'"; ##### groffer options inhereted from groff _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'k' 'l' 'N' 'p' \ 'R' 's' 'S' 't' 'U' 'z'"; _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'K' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \ 'w' 'W'"; _OPTS_GROFF_LONG_NA=""; _OPTS_GROFF_LONG_ARG=""; ##### groffer options inhereted from the X Window toolkit _OPTS_X_SHORT_NA=""; _OPTS_X_SHORT_ARG=""; _OPTS_X_LONG_NA="'iconic' 'rv'"; _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \ 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \ 'resolution' 'title' 'xrm'"; ###### groffer options inherited from man _OPTS_MAN_SHORT_NA=""; _OPTS_MAN_SHORT_ARG=""; _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \ 'local-file' 'location' 'troff' 'update' 'where'"; _OPTS_MAN_LONG_ARG="'locale' 'manpath' \ 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'"; ###### additional options for parsing $MANOPT only _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \ 'V' 'w' 'Z'"; _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'"; _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \ 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \ 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'"; _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \ 'config_file' 'encoding' 'extension' 'locale'"; ###### collections of command line options _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \ ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}"; _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \ ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}"; _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \ ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}"; _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \ ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}"; ######################################################################## # read-write variables (global to this file) ######################################################################## export _ALL_PARAMS; # All options and file name parameters export _ADDOPTS_GROFF; # Transp. options for groff (`eval'). export _APROPOS_PROG; # Program to run apropos. export _APROPOS_SECTIONS; # Sections for different --apropos-*. export _DISPLAY_MODE; # Display mode. export _DISPLAY_PROG; # Viewer program to be used for display. export _DISPLAY_ARGS; # X resources for the viewer program. export _FILE_NR; # number for temporary `,file,*' export _FILEARGS; # Stores filespec parameters. export _FILESPEC_ARG; # Stores the actual filespec parameter. export _FILESPEC_IS_MAN; # filespec is for searching a man page export _FUNC_STACK; # Store debugging information. export _MACRO_PACKAGES; # groff's macro packages. export _MACRO_PKG; # Macro package for each found file. export _NO_FILESPECS; # Yes, if there are no filespec arguments. export _OUTPUT_FILE_NAME; # output generated, see main_set_res..() export _REG_TITLE_LIST; # Processed file names. export _SOELIM_R; # option -r for soelim export _SPECIAL_FILESPEC; # Filespec ran for apropos or whatis. export _SPECIAL_SETUP; # Test on setup for apropos or whatis. export _VIEWER_BACKGROUND; # viewer shall be run in the background or not # _MAN_* finally used configuration of man searching export _MAN_ALL; # search all man pages per filespec export _MAN_ENABLE; # enable search for man pages export _MAN_EXT; # extension for man pages export _MAN_FORCE; # force file parameter to be man pages export _MAN_IS_SETUP; # setup man variables only once export _MAN_LANG; # language for man pages export _MAN_LANG2; # language for man pages export _MAN_PATH; # search path for man pages as a list export _MAN_SEC; # sections for man pages; sep. `:' export _MAN_SEC_CHARS; # sections for man pages as [] construct export _MAN_SEC_LIST; # sections for man pages as a list export _MAN_SYS; # system names for man pages as a list # _MANOPT_* as parsed from $MANOPT export _MANOPT_ALL; # $MANOPT --all export _MANOPT_EXTENSION; # $MANOPT --extension export _MANOPT_LANG; # $MANOPT --locale export _MANOPT_PATH; # $MANOPT --manpath export _MANOPT_PAGER; # $MANOPT --pager export _MANOPT_SEC; # $MANOPT --sections export _MANOPT_SYS; # $MANOPT --systems # variables for mode pdf export _PDF_DID_NOT_WORK; export _PDF_HAS_GS; export _PDF_HAS_PS2PDF; # _OPT_* as parsed from groffer command line export _OPT_ALL; # display all suitable man pages export _OPT_APROPOS; # call `apropos' program export _OPT_BD; # set border color in some modes export _OPT_BG; # set background color in some modes export _OPT_BW; # set border width in some modes export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given export _OPT_DEVICE; # device option export _OPT_DO_NOTHING; # do nothing in main_display() export _OPT_DISPLAY; # set X display export _OPT_EXTENSION; # set extension for man page search export _OPT_FG; # set foreground color in some modes export _OPT_FN; # set font in some modes export _OPT_GEOMETRY; # set size and position of viewer in X export _OPT_ICONIC; # -iconic option for X viewers export _OPT_LANG; # set language for man pages export _OPT_MODE; # values: X, tty, Q, Z, "" export _OPT_MANPATH; # manual setting of path for man-pages export _OPT_PAGER; # specify paging program for tty mode export _OPT_RESOLUTION; # set X resolution in dpi export _OPT_RV; # reverse fore- and background colors export _OPT_SECTIONS; # sections for man page search export _OPT_STDOUT; # print mode file to standard output export _OPT_SYSTEMS; # man pages of different OS's export _OPT_TITLE; # title for gxditview window export _OPT_TEXT_DEVICE; # set device for tty mode export _OPT_V; # groff option -V export _OPT_VIEWER_DVI; # viewer program for dvi mode export _OPT_VIEWER_HTML; # viewer program for html mode export _OPT_VIEWER_PDF; # viewer program for pdf mode export _OPT_VIEWER_PS; # viewer program for ps mode export _OPT_VIEWER_X; # viewer program for x mode export _OPT_WHATIS; # print the man description export _OPT_XRM; # specify X resource export _OPT_Z; # groff option -Z # _TMP_* temporary directory and files export _TMP_DIR; # groffer directory for temporary files export _TMP_CAT; # stores concatenation of everything export _TMP_MAN; # stores find of man path export _TMP_MANSPEC; # filters man pages with filespec export _TMP_STDIN; # stores stdin, if any # these variables are preset in section `Preset' after the rudim. test ######################################################################## # Preset and reset of read-write global variables ######################################################################## # For variables that can be reset by option `--default', see reset(). _FILE_NR=0; _FILEARGS=''; _MACRO_PACKAGES="'-man' '-mdoc' '-me' '-mm' '-mom' '-ms'"; _SPECIAL_FILESPEC='no'; _SPECIAL_SETUP='no'; # _TMP_* temporary files _TMP_DIR=''; _TMP_CAT=''; _TMP_MAN=''; _TMP_CONF=''; _TMP_STDIN=''; # variables for mode pdf _PDF_DID_NOT_WORK='no'; _PDF_HAS_GS='no'; _PDF_HAS_PS2PDF='no'; # option -r for soelim if : | soelim -r 2>${_NULL_DEV} >${_NULL_DEV} then _SOELIM_R='-r'; else _SOELIM_R=''; fi; ######################################################################## # reset () # # Reset the variables that can be affected by options to their default. # reset() { if test "$#" -ne 0 then error "reset() does not have arguments."; fi; _ADDOPTS_GROFF=''; _APROPOS_PROG=''; _APROPOS_SECTIONS=''; _DISPLAY_ARGS=''; _DISPLAY_MODE=''; _DISPLAY_PROG=''; _MACRO_PKG=''; _NO_FILESPECS=''; _REG_TITLE_LIST=''; # _MAN_* finally used configuration of man searching _MAN_ALL='no'; _MAN_ENABLE='yes'; # do search for man-pages _MAN_EXT=''; _MAN_FORCE='no'; # first local file, then search man page _MAN_IS_SETUP='no'; _MAN_LANG=''; _MAN_LANG2=''; _MAN_PATH=''; _MAN_SEC=''; _MAN_SEC_CHARS=''; _MAN_SEC_LIST=''; _MAN_SYS=''; # _MANOPT_* as parsed from $MANOPT _MANOPT_ALL='no'; _MANOPT_EXTENSION=''; _MANOPT_LANG=''; _MANOPT_PATH=''; _MANOPT_PAGER=''; _MANOPT_SEC=''; _MANOPT_SYS=''; # _OPT_* as parsed from groffer command line _OPT_ALL='no'; _OPT_APROPOS='no'; _OPT_BD=''; _OPT_BG=''; _OPT_BW=''; _OPT_DEFAULT_MODES=''; _OPT_DEVICE=''; _OPT_DISPLAY=''; _OPT_DO_NOTHING='no'; _OPT_EXTENSION=''; _OPT_FG=''; _OPT_FN=''; _OPT_GEOMETRY=''; _OPT_ICONIC='no'; _OPT_LANG=''; _OPT_MODE=''; _OPT_MANPATH=''; _OPT_PAGER=''; _OPT_RESOLUTION=''; _OPT_RV='no'; _OPT_SECTIONS=''; _OPT_SYSTEMS=''; _OPT_STDOUT='no'; _OPT_TITLE=''; _OPT_TEXT_DEVICE=''; _OPT_V='no'; _OPT_VIEWER_DVI=''; _OPT_VIEWER_PDF=''; _OPT_VIEWER_PS=''; _OPT_VIEWER_HTML=''; _OPT_VIEWER_X=''; _OPT_WHATIS='no'; _OPT_XRM=''; _OPT_Z='no'; _VIEWER_BACKGROUND='no'; } reset; ######################################################################## # Preliminary functions for error handling ######################################################################## landmark "2: preliminary functions"; # These functions do not have a func-check frame. Basically they could be # moved to the functions in alphabetical order. ############## # echo1 (*) # # Output to stdout with final line break. # # Arguments : arbitrary text including `-'. # echo1() { cat <*) # # Output to stderr with final line break. # # Arguments : arbitrary text including `-'. # echo2() { cat >&2 <"${_NULL_DEV}" 2>&1; if test _${_DEBUG_KEEP_FILES}_ = _yes_ then if test _"$cu_already"_ = _yes_ then eval "${return_ok}"; fi; cu_already=yes; echo2 "Kept temporary directory ${_TMP_DIR}." else if test _"${_TMP_DIR}"_ != __ then if test -e "${_TMP_DIR}" then rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1; fi; fi; fi; eval "${return_ok}"; } # clean_up() ############# # diag (text>*) # # Output a diagnostic message to stderr. # diag() { echo2 '>>>>>'"$*"; } # diag() ############# # error (*) # # Print an error message to standard error, print the function stack, # exit with an error condition. The argument should contain the name # of the function from which it was called. This is for system errors. # error() { case "$#" in 1) echo2 'groffer error: '"$1"; ;; *) echo2 'groffer error: wrong number of arguments in error().'; ;; esac; func_stack_dump; if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" then : >"${_TMP_DIR}"/,error; fi; exit "${_ERROR}"; } # error() ############# # error_user (*) # # Print an error message to standard error; exit with an error condition. # The error is supposed to be produced by the user. So the funtion stack # is omitted. # error_user() { case "$#" in 1) echo2 'groffer error: '"$1"; ;; *) echo2 'groffer error: wrong number of arguments in error_user().'; ;; esac; if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_ then func_stack_dump; fi; if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" then : >"${_TMP_DIR}"/,error; fi; exit "${_ERROR}"; } # error_user() ############# # exit_test () # # Test whether the former command ended with error(). Exit again. # # Globals: $_ERROR # exit_test() { if test "$?" = "${_ERROR}" then exit ${_ERROR}; fi; if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error then exit ${_ERROR}; fi; } # exit_test() ######################################################################## # Definition of normal Functions in alphabetical order ######################################################################## landmark "3: functions"; ######################################################################## # apropos_filespec () # # Compose temporary file for filspec. # # Globals: in: $_OPT_APROPOS, $_SPECIAL_SETUP, $_FILESPEC_ARG, # $_APROPOS_PROG, $_APROPOS_SECTIONS, $_OPT_SECTIONS # out: $_SPECIAL_FILESPEC # # Variable prefix: af # apropos_filespec() { func_check apropos_filespec '=' 0 "$@"; if obj _OPT_APROPOS is_yes then if obj _SPECIAL_SETUP is_not_yes then error 'apropos_filespec(): apropos_setup() must be run first.'; fi; _SPECIAL_FILESPEC='yes'; if obj _NO_FILESPECS is_yes then to_tmp_line '.SH no filespec'; eval "${_APROPOS_PROG}" | sed 's/^/\\\&/' >>"${_TMP_CAT}"; eval "${return_ok}"; fi; eval to_tmp_line \ "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'"; exit_test; if obj _APROPOS_SECTIONS is_empty then if obj _OPT_SECTIONS is_empty then s='^.*(..*).*$'; else s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed 's/://g')"']'; fi; else s='^.*(['"${_APROPOS_SECTIONS}"']'; fi; ### apropos_filespec() af_filespec="$(echo1 "${_FILESPEC_ARG}" | sed ' s,/,\\/,g s/\./\\./g ')"; eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \ sed -n ' /^'"${af_filespec}"': /s/^\(.*\)$/\\\&\1/p /'"$s"'/p ' | \ sort |\ sed ' s/^\(.*(..*).*\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \"\1\"\n\\\&\2/ ' >>"${_TMP_CAT}"; eval ${_UNSET} af_filespec; eval "${return_ok}"; else eval "${return_bad}"; fi; } # apropos_filespec() ######################################################################## # apropos_setup () # # Setup for the --apropos* options, just 2 global variables are set. # # Globals: in: $_OPT_APROPOS # out: $_SPECIAL_SETUP, $_APROPOS_PROG # apropos_setup() { func_check apropos_setup '=' 0 "$@"; if obj _OPT_APROPOS is_yes then if is_prog apropos then _APROPOS_PROG='apropos'; elif is_prog man then if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV} then _APROPOS_PROG='man --apropos'; elif man -k man >${_NULL_DEV} 2>${_NULL_DEV} then _APROPOS_PROG='man -k'; fi; fi; if obj _APROPOS_PROG is_empty then error 'apropos_setup(): no apropos program available.'; fi; to_tmp_line '.TH GROFFER APROPOS'; _SPECIAL_SETUP='yes'; if obj _OPT_TITLE is_empty then _OPT_TITLE='apropos'; fi; eval "${return_ok}"; else eval "${return_bad}"; fi; } # apropos_setup() ######################################################################## # base_name () # # Get the file name part of , i.e. delete everything up to last # `/' from the beginning of . Remove final slashes, too, to get # a non-empty output. The output is constructed according the shell # program `basename'. # # Arguments : 1 # Output : the file name part (without slashes) # # Variable prefix: bn # base_name() { func_check base_name = 1 "$@"; bn_name="$1"; case "${bn_name}" in */) # delete all final slashes bn_name="$(echo1 "${bn_name}" | sed 's|//*$||')"; exit_test; ;; esac; case "${bn_name}" in '') eval ${_UNSET} bn_name; eval "${return_bad}"; ;; /) # this is like `basename' does echo1 '/'; ;; */*) # delete everything before and including the last slash `/'. echo1 "${bn_name}" | sed 's|^.*//*\([^/]*\)$|\1|'; ;; *) obj bn_name echo1; ;; esac; eval ${_UNSET} bn_name; eval "${return_ok}"; } # base_name() ######################################################################## # cat_z () # # Decompress if possible or just print to standard output. # gzip, bzip2, and .Z decompression is supported. # # Arguments: 1, a file name. # Output: the content of , possibly decompressed. # cat_z() { func_check cat_z = 1 "$@"; case "$1" in '') error 'cat_z(): empty file name.'; ;; '-') error 'cat_z(): for standard input use save_stdin().'; ;; esac; if is_file "$1" then :; else error 'cat_z(): argument $1 is not a file.'; fi; if test -s "$1" then :; else eval "${return_ok}"; fi; if obj _HAS_COMPRESSION is_yes then if obj _HAS_BZIP is_yes then # test whether being compressed with bz2 if bzip2 -t "$1" 2>${_NULL_DEV} then bzip2 -c -d "$1" 2>${_NULL_DEV}; eval "${return_ok}"; fi; fi; # if not compressed gzip acts like `cat' gzip -c -d -f "$1" 2>${_NULL_DEV}; else cat "$1"; fi; eval "${return_ok}"; } # cat_z() ######################################################################## # clean_up () # # Do the final cleaning up before exiting; used by the trap calls. # # defined above ######################################################################## # diag (*) # # Print marked message to standard error; useful for debugging. # # defined above ######################################################################## landmark '4: dir_name()*'; ######################################################################## ####################################################################### # dir_name () # # Get the directory name of . The output is constructed # according to the shell program `dirname'. # # Arguments : 1 # Output : the directory part of # # Variable prefix: dn # dir_name() { func_check dir_name = 1 "$@"; obj_from_output dn_name dir_name_chop "$1"; case "${dn_name}" in ''|.) echo1 '.'; ;; /) echo1 '/'; ;; */*) echo1 "$(echo1 "${dn_name}" | sed 's#/*[^/][^/]*$##')"; ;; *) echo1 "${dn_name}"; ;; esac; eval "${return_ok}"; } # dir_name() ####################################################################### # dir_name_append ( ) # # Append `name' to `dir' with clean handling of `/'. # # Arguments : 2 # Output : the generated new directory name / # dir_name_append() { func_check dir_name_append = 2 "$@"; if is_empty "$1" then echo1 "$2"; elif is_empty "$2" then echo1 "$1"; else dir_name_chop "$1"/"$2"; fi; eval "${return_ok}"; } # dir_name_append() ######################################################################## # dir_name_chop () # # Remove unnecessary slashes from directory name. # # Argument: 1, a directory name. # Output: path without double, or trailing slashes. # # Variable prefix: dc # dir_name_chop() { func_check dir_name_chop = 1 "$@"; # replace all multiple slashes by a single slash `/'. dc_res="$(echo1 "$1" | sed 's|///*|/|g')"; exit_test; case "${dc_res}" in ?*/) # remove trailing slash '/'; echo1 "${dc_res}" | sed 's|/$||'; ;; *) obj dc_res echo1 ;; esac; eval ${_UNSET} dc_res; eval "${return_ok}"; } # dir_name_chop() ######################################################################## # do_nothing () # # Dummy function that does nothing. # do_nothing() { eval return "${_OK}"; } # do_nothing() ######################################################################## # echo1 (*) # # Print to standard output with final line break. # # defined above ######################################################################## # echo2 (*) # # Print to standard error with final line break. # # defined above ######################################################################## # error (*) # # Print error message and exit with error code. # # defined above ######################################################################## # exit_test () # # Test whether the former command ended with error(). Exit again. # # defined above if test _"${_DEBUG_FUNC_CHECK}"_ = _yes_ then ############# # func_check ( "$@") # # This is called at the first line of each function. It checks the # number of arguments of function and registers the # function call to _FUNC_STACK. # # Arguments: >=3 # : name of the calling function. # : a relational operator: = != < > <= >= # : number of arguments to be checked against # "$@": the arguments of the calling function. # # Variable prefix: fc # func_check() { if test "$#" -lt 3 then error 'func_check() needs at least 3 arguments.'; fi; fc_fname="$1"; case "$3" in 1) fc_nargs="$3"; fc_s=''; ;; 0|[2-9]) fc_nargs="$3"; fc_s='s'; ;; *) error "func_check(): third argument must be a digit."; ;; esac; ### func_check() case "$2" in '='|'-eq') fc_op='-eq'; fc_comp='exactly'; ;; '>='|'-ge') fc_op='-ge'; fc_comp='at least'; ;; '<='|'-le') fc_op='-le'; fc_comp='at most'; ;; '<'|'-lt') fc_op='-lt'; fc_comp='less than'; ;; '>'|'-gt') fc_op='-gt'; fc_comp='more than'; ;; '!='|'-ne') fc_op='-ne'; fc_comp='not'; ;; ### func_check() *) error \ 'func_check(): second argument is not a relational operator.'; ;; esac; shift; shift; shift; if test "$#" "${fc_op}" "${fc_nargs}" then do_nothing; else error "func_check(): \ ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.'; fi; func_push "${fc_fname}"; if test _"${_DEBUG_STACKS}"_ = _yes_ then echo2 '+++ '"${fc_fname} $@"; echo2 '>>> '"${_FUNC_STACK}"; fi; eval ${_UNSET} fc_comp; eval ${_UNSET} fc_fname; eval ${_UNSET} fc_nargs; eval ${_UNSET} fc_op; eval ${_UNSET} fc_s; } # func_check() ############# # func_pop () # # Retrieve the top element from the function stack. This is called # by every return variable in each function. # # The stack elements are separated by `!'; the popped element is # identical to the original element, except that all `!' characters # were removed. # # Arguments: 1 # func_pop() { if test "$#" -ne 0 then error 'func_pop() does not have arguments.'; fi; case "${_FUNC_STACK}" in '') if test _"${_DEBUG_STACKS}"_ = _yes_ then error 'func_pop(): stack is empty.'; fi; ;; *!*) # split at first bang `!'. _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed 's/^[^!]*!//')"; exit_test; ;; *) _FUNC_STACK=''; ;; esac; if test _"${_DEBUG_STACKS}"_ = _yes_ then echo2 '<<< '"${_FUNC_STACK}"; fi; } # func_pop() ############# # func_push () # # Store another element to the function stack. This is called by # func_check() at the beginning of each function. # # The stack elements are separated by `!'; if contains a `!' # it is removed first. # # Arguments: 1 # # Variable prefix: fp # func_push() { if test "$#" -ne 1 then error 'func_push() needs 1 argument.'; fi; case "$1" in *'!'*) # remove all bangs `!'. fp_element="$(echo1 "$1" | sed 's/!//g')"; exit_test; ;; *) fp_element="$1"; ;; esac; if test _"${_FUNC_STACK}"_ = __ then _FUNC_STACK="${fp_element}"; else _FUNC_STACK="${fp_element}!${_FUNC_STACK}"; fi; eval ${_UNSET} fp_element; } # func_push() ############# # func_stack_dump () # # Print the content of the function stack. Ignore the arguments. # func_stack_dump() { diag 'call stack(): '"${_FUNC_STACK}"; } # func_stack_dump() else # $_DEBUG_FUNC_CHECK is not `yes' func_check() { return; } func_pop() { return; } func_push() { return; } func_stack_dump() { return; } fi; # test of $_DEBUG_FUNC_CHECK ######################################################################## # get_first_essential (*) # # Retrieve first non-empty argument. # # Return : `1' if all arguments are empty, `0' if found. # Output : the retrieved non-empty argument. # # Variable prefix: gfe # get_first_essential() { func_check get_first_essential '>=' 0 "$@"; if is_equal "$#" 0 then eval "${return_ok}"; fi; for i do gfe_var="$i"; if obj gfe_var is_not_empty then obj gfe_var echo1; eval ${_UNSET} gfe_var; eval "${return_ok}"; fi; done; eval ${_UNSET} gfe_var; eval "${return_bad}"; } # get_first_essential() ######################################################################## landmark '5: is_*()'; ######################################################################## ######################################################################## # is_dir () # # Test whether `name' is a readable directory. # # Arguments : 1 # Return : `0' if arg1 is a directory, `1' otherwise. # is_dir() { func_check is_dir '=' 1 "$@"; if is_not_empty "$1" && test -d "$1" && test -r "$1" then eval "${return_yes}"; fi; eval "${return_no}"; } # is_dir() ######################################################################## # is_empty () # # Test whether is empty. # # Arguments : <=1 # Return : `0' if arg1 is empty or does not exist, `1' otherwise. # is_empty() { func_check is_empty '=' 1 "$@"; if test _"$1"_ = __ then eval "${return_yes}"; fi; eval "${return_no}"; } # is_empty() ######################################################################## # is_empty_file () # # Test whether is an empty existing file. # # Arguments : <=1 # Return : # `0' if arg1 is an empty existing file # `1' otherwise # is_empty_file() { func_check is_empty_file '=' 1 "$@"; if is_file "$1" then if test -s "$1" then eval "${return_no}"; else eval "${return_yes}"; fi; fi; eval "${return_no}"; } # is_empty_file() ######################################################################## # is_equal ( ) # # Test whether is equal to . # # Arguments : 2 # Return : `0' both arguments are equal strings, `1' otherwise. # is_equal() { func_check is_equal '=' 2 "$@"; if test _"$1"_ = _"$2"_ then eval "${return_yes}"; fi; eval "${return_no}"; } # is_equal() ######################################################################## # is_existing () # # Test whether is an existing file or directory. Solaris 2.5 does # not have `test -e'. # # Arguments : 1 # Return : `0' if arg1 exists, `1' otherwise. # is_existing() { func_check is_existing '=' 1 "$@"; if is_empty "$1" then eval "${return_no}"; fi; if test -f "$1" || test -d "$1" || test -c "$1" then eval "${return_yes}"; fi; eval "${return_no}"; } # is_existing() ######################################################################## # is_file () # # Test whether is a readable file. # # Arguments : 1 # Return : `0' if arg1 is a readable file, `1' otherwise. # is_file() { func_check is_file '=' 1 "$@"; if is_not_empty "$1" && test -f "$1" && test -r "$1" then eval "${return_yes}"; fi; eval "${return_no}"; } # is_file() ######################################################################## # is_greater_than ( ) # # Test whether is greater than . # # Arguments : 2 # Return : `0' if is a greater integer than , # `1' otherwise. # is_greater_than() { func_check is_greater_than '=' 2 "$@"; if is_integer "$1" && is_integer "$2" && test "$1" -gt "$2" then eval "${return_yes}"; fi; eval "${return_no}"; } # is_greater_than() ######################################################################## # is_integer () # # Test whether `string' is an integer. # # Arguments : 1 # Return : `0' if argument is an integer, `1' otherwise. # is_integer() { func_check is_integer '=' 1 "$@"; if is_equal "$(echo1 "$1" | sed -n ' s/^[0-9][0-9]*$/ok/p s/^[-+][0-9][0-9]*$/ok/p ')" 'ok' then eval "${return_yes}"; fi; eval "${return_no}"; } # is_integer() ######################################################################## # is_not_empty_file () # # Test whether is a non-empty existing file. # # Arguments : <=1 # Return : # `0' if arg1 is a non-empty existing file # `1' otherwise # is_not_empty_file() { func_check is_not_empty_file '=' 1 "$@"; if is_file "$1" && test -s "$1" then eval "${return_yes}"; fi; eval "${return_no}"; } # is_not_empty_file() ######################################################################## # is_not_dir () # # Test whether is not a readable directory. # # Arguments : 1 # Return : `0' if arg1 is a directory, `1' otherwise. # is_not_dir() { func_check is_not_dir '=' 1 "$@"; if is_dir "$1" then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_dir() ######################################################################## # is_not_empty () # # Test whether is not empty. # # Arguments : <=1 # Return : `0' if arg1 exists and is not empty, `1' otherwise. # is_not_empty() { func_check is_not_empty '=' 1 "$@"; if is_empty "$1" then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_empty() ######################################################################## # is_not_equal ( ) # # Test whether differs from . # # Arguments : 2 # is_not_equal() { func_check is_not_equal '=' 2 "$@"; if is_equal "$1" "$2" then eval "${return_no}"; fi eval "${return_yes}"; } # is_not_equal() ######################################################################## # is_not_file () # # Test whether is a not readable file. # # Arguments : 1 (empty allowed) # is_not_file() { func_check is_not_file '=' 1 "$@"; if is_file "$1" then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_file() ######################################################################## # is_not_prog () # # Verify that is not a command in $PATH. # # Arguments : 1, can have spaces and arguments. # is_not_prog() { func_check is_not_prog '=' 1 "$@"; if where_is_prog "$1" >${_NULL_DEV} then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_prog() ######################################################################## # is_not_writable () # # Test whether is not a writable file or directory. # # Arguments : >=1 (empty allowed), more args are ignored # is_not_writable() { func_check is_not_writable '>=' 1 "$@"; if is_writable "$1" then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_writable() ######################################################################## # is_not_X () # # Test whether the script is not running in X Window by checking $DISPLAY. # is_not_X() { func_check is_not_X '=' 0 "$@"; if obj DISPLAY is_empty then eval "${return_yes}"; fi; eval "${return_no}"; } # is_not_X() ######################################################################## # is_not_yes () # # Test whether is not `yes'. # # Arguments : 1 # is_not_yes() { func_check is_not_yes = 1 "$@"; if is_yes "$1" then eval "${return_no}"; fi; eval "${return_yes}"; } # is_not_yes() ######################################################################## # is_prog () # # Determine whether is a program in $PATH. # # Arguments : 1, can have spaces and arguments. # is_prog() { func_check is_prog '=' 1 "$@"; if where_is_prog "$1" >${_NULL_DEV} then eval "${return_yes}"; fi; eval "${return_no}"; } # is_prog() ######################################################################## # is_writable () # # Test whether is a writable file or directory. # # Arguments : >=1 (empty allowed), more args are ignored # is_writable() { func_check is_writable '>=' 1 "$@"; if is_empty "$1" then eval "${return_no}"; fi; if test -r "$1" then if test -w "$1" then eval "${return_yes}"; fi; fi; eval "${return_no}"; } # is_writable() ######################################################################## # is_X () # # Test whether the script is running in X Window by checking $DISPLAY. # is_X() { func_check is_X '=' 0 "$@"; if obj DISPLAY is_not_empty then eval "${return_yes}"; fi; eval "${return_no}"; } # is_X() ######################################################################## # is_yes () # # Test whether has value `yes'. # # Return : `0' if arg1 is `yes', `1' otherwise. # is_yes() { func_check is_yes '=' 1 "$@"; if is_equal "$1" 'yes' then eval "${return_yes}"; fi; eval "${return_no}"; } # is_yes() ######################################################################## # landmark () # # Print debugging information on standard error if $_DEBUG_LM is `yes'. # # Globals: $_DEBUG_LM # # Defined in section `Debugging functions'. ######################################################################## # leave ([]) # # Clean exit without an error or with error . # leave() { clean_up; if test $# = 0 then exit "${_OK}"; else exit "$1"; fi; } # leave() ######################################################################## landmark '6: list_*()'; ######################################################################## # # `list' is an object class that represents an array or list. Its # data consists of space-separated single-quoted elements. So a list # has the form "'first' 'second' '...' 'last'". See list_append() for # more details on the list structure. The array elements of `list' # can be get by `eval set x "$list"; shift`. ######################################################################## # list_append ( ...) # # Add one or more elements to an existing list. may also be # empty. # # Arguments: >=2 # : a variable name for a list of single-quoted elements # : some sequence of characters. # Output: none, but $ is set to # if is empty: "'' '...'" # otherwise: "$list '' ..." # # Variable prefix: la # list_append() { func_check list_append '>=' 2 "$@"; la_name="$1"; eval la_list='"${'"$1"'}"'; shift; for s do la_s="$s"; case "${la_s}" in *\'*) # escape each single quote by replacing each # "'" (squote) by "'\''" (squote bslash squote squote); # note that the backslash must be doubled in the following `sed' la_element="$(echo1 "${la_s}" | sed 's/'"${_SQ}"'/&\\&&/g')"; exit_test; ;; '') la_element=""; ;; *) la_element="${la_s}"; ;; esac; ### list_append() if obj la_list is_empty then la_list="'${la_element}'"; else la_list="${la_list} '${la_element}'"; fi; done; eval "${la_name}"='"${la_list}"'; eval ${_UNSET} la_element; eval ${_UNSET} la_list; eval ${_UNSET} la_name; eval ${_UNSET} la_s; eval "${return_ok}"; } # list_append() ######################################################################## # list_from_cmdline ( [...]) # # Transform command line arguments into a normalized form. # # Options, option arguments, and file parameters are identified and # output each as a single-quoted argument of its own. Options and # file parameters are separated by a '--' argument. # # Arguments: >=1 # : common part of a set of 4 environment variable names: # $_SHORT_NA: list of short options without an arg. # $_SHORT_ARG: list of short options that have an arg. # $_LONG_NA: list of long options without an arg. # $_LONG_ARG: list of long options that have an arg. # ...: the arguments from a command line, such as "$@", # the content of a variable, or direct arguments. # # Output: ['-[-]opt' ['optarg']]... '--' ['filename']... # # Example: # list_from_cmdline PRE -a f1 -bcarg --lon=larg f2 low larg2 # PRE_SHORT_NA="'a' 'b'" # PRE_SHORT_ARG="'c' 'd'" # PRE_LONG_NA="'help' 'version'" # PRE_LONG_ARG="'longer' 'lower'" # This will result in printing: # '-a' '-b' '-c' 'arg' '--longer' 'larg' '--lower' 'larg2' '--' 'f1' 'f2' # # Use this function in the following way: # eval set x "$(list_from_cmdline PRE_NAME "$@")"; # shift; # while test "$1" != '--'; do # case "$1" in # ... # esac; # shift; # done; # shift; #skip '--' # # all positional parameters ("$@") left are file name parameters. # # Variable prefix: lfc # list_from_cmdline() { func_check list_from_cmdline '>=' 1 "$@"; # short options, no argument obj_from_output lfc_short_n obj_data "$1"_SHORT_NA; # short options, with argument obj_from_output lfc_short_a obj_data "$1"_SHORT_ARG; # long options, no argument obj_from_output lfc_long_n obj_data "$1"_LONG_NA; # long options, with argument obj_from_output lfc_long_a obj_data "$1"_LONG_ARG; if obj lfc_short_n is_empty then error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.'; fi; if obj lfc_short_a is_empty then error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.'; fi; if obj lfc_long_n is_empty then error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.'; fi; if obj lfc_long_a is_empty then error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.'; fi; shift; if is_equal "$#" 0 then echo1 "'--'" eval ${_UNSET} lfc_fparams; eval ${_UNSET} lfc_short_a; eval ${_UNSET} lfc_short_n; ### list_from_cmdline() eval ${_UNSET} lfc_long_a; eval ${_UNSET} lfc_long_n; eval ${_UNSET} lfc_result; eval "${return_ok}"; fi; lfc_fparams=''; lfc_result=''; while is_greater_than "$#" 0 do lfc_arg="$1"; shift; case "${lfc_arg}" in --) break; ;; --*=*) # delete leading '--'; lfc_with_equal="$(echo1 "${lfc_arg}" | sed 's/^--//')"; # extract option by deleting from the first '=' to the end lfc_abbrev="$(echo1 "${lfc_with_equal}" | \ sed 's/^\([^=]*\)=.*$/\1/')"; obj_from_output lfc_opt \ list_single_from_abbrev lfc_long_a "${lfc_abbrev}"; if obj lfc_opt is_empty then error_user "--${lfc_abbrev} is not an option."; else # get the option argument by deleting up to first `=' lfc_optarg="$(echo1 "${lfc_with_equal}" | sed 's/^[^=]*=//')"; exit_test; list_append lfc_result "--${lfc_opt}" "${lfc_optarg}"; continue; fi; ### list_from_cmdline() ;; --*) # delete leading '--'; lfc_abbrev="$(echo1 "${lfc_arg}" | sed 's/^--//')"; if list_has lfc_long_n "${lfc_abbrev}" then lfc_opt="${lfc_abbrev}"; else obj_from_output lfc_opt \ list_single_from_abbrev lfc_long_n "${lfc_abbrev}"; if obj lfc_opt is_not_empty && is_not_equal "$#" 0 then obj_from_output a \ list_single_from_abbrev lfc_long_a "${lfc_abbrev}"; if obj a is_not_empty then error_user "The abbreviation ${lfc_arg} \ has multiple options: --${lfc_opt} and --${a}."; fi; fi; fi; # if list_has lfc_long_n "${lfc_abbrev}" if obj lfc_opt is_not_empty then # long option, no argument list_append lfc_result "--${lfc_opt}"; continue; fi; obj_from_output lfc_opt \ list_single_from_abbrev lfc_long_a "${lfc_abbrev}"; if obj lfc_opt is_not_empty then ### list_from_cmdline() # long option with argument if is_equal "$#" 0 then error_user "no argument for option --${lfc_opt}." fi; list_append lfc_result "--${lfc_opt}" "$1"; shift; continue; fi; # if obj lfc_opt is_not_empty error_user "${lfc_arg} is not an option."; ;; -?*) # short option (cluster) # delete leading `-'; lfc_rest="$(echo1 "${lfc_arg}" | sed 's/^-//')"; exit_test; while obj lfc_rest is_not_empty do # get next short option from cluster (first char of $lfc_rest) lfc_optchar="$(echo1 "${lfc_rest}" | sed 's/^\(.\).*$/\1/')"; # remove first character from ${lfc_rest}; lfc_rest="$(echo1 "${lfc_rest}" | sed 's/^.//')"; exit_test; if list_has lfc_short_n "${lfc_optchar}" then list_append lfc_result "-${lfc_optchar}"; continue; elif list_has lfc_short_a "${lfc_optchar}" then if obj lfc_rest is_empty then if is_greater_than "$#" 0 then ### list_from_cmdline() list_append lfc_result "-${lfc_optchar}" "$1"; shift; continue; else error_user "no argument for option -${lfc_optchar}."; fi; else # rest is the argument list_append lfc_result "-${lfc_optchar}" "${lfc_rest}"; lfc_rest=''; continue; fi; # if obj lfc_rest is_empty else error_user "unknown option -${lfc_optchar}."; fi; # if list_has lfc_short_n "${lfc_optchar}" done; # while obj lfc_rest is_not_empty ;; *) # Here, $lfc_arg is not an option, so a file parameter. list_append lfc_fparams "${lfc_arg}"; # Ignore the strange POSIX option handling to end option # parsing after the first file name argument. To reuse it, do # a `break' here if $POSIXLY_CORRECT of `bash' is not empty. # When `bash' is called as `sh' $POSIXLY_CORRECT is set # automatically to `y'. ;; esac; # case "${lfc_arg}" in done; # while is_greater_than "$#" 0 list_append lfc_result '--'; if obj lfc_fparams is_not_empty then lfc_result="${lfc_result} ${lfc_fparams}"; fi; ### list_from_cmdline() if is_greater_than "$#" 0 then list_append lfc_result "$@"; fi; obj lfc_result echo1; eval ${_UNSET} lfc_abbrev; eval ${_UNSET} lfc_fparams; eval ${_UNSET} lfc_short_a; eval ${_UNSET} lfc_short_n; eval ${_UNSET} lfc_long_a; eval ${_UNSET} lfc_long_n; eval ${_UNSET} lfc_result; eval ${_UNSET} lfc_arg; eval ${_UNSET} lfc_opt; eval ${_UNSET} lfc_opt_arg; eval ${_UNSET} lfc_opt_char; eval ${_UNSET} lfc_with_equal; eval ${_UNSET} lfc_rest; eval "${return_ok}"; } # list_from_cmdline() ######################################################################## # list_from_cmdline_with_minus ( [...]) # # Transform command line arguments into a normalized form with a double # abbreviation before and after an internal `-' sign. # # Options, option arguments, and file parameters are identified and # output each as a single-quoted argument of its own. Options and # file parameters are separated by a `--' argument. # # Arguments: >=1 # : common part of a set of 4 environment variable names: # $_SHORT_NA: list of short options without an arg. # $_SHORT_ARG: list of short options that have an arg. # $_LONG_NA: list of long options without an arg. # $_LONG_ARG: list of long options that have an arg. # ...: the arguments from a command line, such as "$@", # the content of a variable, or direct arguments. # # Output: ['-[-]opt' ['optarg']]... '--' ['filename']... # # Example: # list_from_cmdline PRE -a f1 -bcarg --lon=larg --h-n f2 low larg2 # PRE_SHORT_NA="'a' 'b'" # PRE_SHORT_ARG="'c' 'd'" # PRE_LONG_NA="'help' 'version' 'hi-non-arg'" # PRE_LONG_ARG="'long-arg' 'low-arg'" # This will result in printing: # '-a' '-b' '-c' 'arg' '--long-arg' 'larg' '--hi-non-arg' \ # '--low-arg' 'larg2' '--' 'f1' 'f2' # # Use this function in the following way: # eval set x "$(list_from_cmdline_with_minus PRE_NAME "$@")"; # shift; # while test "$1" != '--'; do # case "$1" in # ... # esac; # shift; # done; # shift; #skip '--' # # all positional parameters ("$@") left are file name parameters. # # Variable prefix: lfcwm # list_from_cmdline_with_minus() { func_check list_from_cmdline_with_minus '>=' 1 "$@"; # short options, no argument obj_from_output lfcwm_short_n obj_data "$1"_SHORT_NA; # short options, with argument obj_from_output lfcwm_short_a obj_data "$1"_SHORT_ARG; # long options, no argument obj_from_output lfcwm_long_n obj_data "$1"_LONG_NA; # long options, with argument obj_from_output lfcwm_long_a obj_data "$1"_LONG_ARG; if obj lfcwm_short_n is_empty then error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.'; fi; if obj lfcwm_short_a is_empty then error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.'; fi; if obj lfcwm_long_n is_empty then error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.'; fi; if obj lfcwm_long_a is_empty then error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.'; fi; shift; if is_equal "$#" 0 then echo1 "'--'"; eval ${_UNSET} lfcwm_short_a; eval ${_UNSET} lfcwm_short_n; ### list_from_cmdline_with_minus() eval ${_UNSET} lfcwm_long_a; eval ${_UNSET} lfcwm_long_n; eval "${return_ok}"; fi; obj_from_output lfcwm_long_both lists_combine lfcwm_long_a lfcwm_long_n; lfcwm_fparams=''; lfcwm_result=''; while is_greater_than "$#" 0 # command line arguments do lfcwm_arg="$1"; shift; lfcwm_optarg=''; case "${lfcwm_arg}" in --) break; ;; --*=*) # delete leading '--'; lfcwm_with_equal="$(echo1 "${lfcwm_arg}" | sed 's/^--//')"; # extract option by deleting from the first '=' to the end lfcwm_abbrev="$(echo1 "${lfcwm_with_equal}" | \ sed 's/^\([^=]*\)=.*$/\1/')"; # extract option argument by deleting up to the first '=' lfcwm_optarg="$(echo1 "${lfcwm_with_equal}" | \ sed 's/^[^=]*=\(.*\)$/\1/')"; ### list_from_cmdline_with_minus() if list_has lfcwm_long_a "${lfcwm_abbrev}" then lfcwm_opt="${lfcwm_abbrev}"; else obj_from_output lfcwm_opt \ _search_abbrev lfcwm_long_a "${lfcwm_abbrev}"; fi; list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}"; continue; ;; --*) # delete leading '--'; lfcwm_abbrev="$(echo1 "${lfcwm_arg}" | sed 's/^--//')"; if list_has lfcwm_long_both "${lfcwm_abbrev}" then lfcwm_opt="${lfcwm_abbrev}"; else obj_from_output lfcwm_opt \ _search_abbrev lfcwm_long_both "${lfcwm_abbrev}"; fi; ### list_from_cmdline_with_minus() if list_has lfcwm_long_a "${lfcwm_opt}" then if is_equal "$#" 0 then error_user "Option ${lfcwm_opt} needs an argument."; fi; lfcwm_optarg="$1"; shift; list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}"; else list_append lfcwm_result "--${lfcwm_opt}"; fi; continue; ;; -?*) # short option (cluster) # delete leading '-'; lfcwm_rest="$(echo1 "${lfcwm_arg}" | sed 's/^-//')"; while obj lfcwm_rest is_not_empty do # get next short option from cluster (first char of $lfcwm_rest) lfcwm_optchar="$(echo1 "${lfcwm_rest}" | sed 's/^\(.\).*$/\1/')"; # remove first character from ${lfcwm_rest}; lfcwm_rest="$(echo1 "${lfcwm_rest}" | sed 's/^.//')"; if list_has lfcwm_short_n "${lfcwm_optchar}" then list_append lfcwm_result "-${lfcwm_optchar}"; continue; elif list_has lfcwm_short_a "${lfcwm_optchar}" then if obj lfcwm_rest is_empty then if is_greater_than "$#" 0 then ### list_from_cmdline_with_minus() list_append lfcwm_result "-${lfcwm_optchar}" "$1"; shift; continue; else error_user "no argument for option -${lfcwm_optchar}."; fi; else # rest is the argument list_append lfcwm_result "-${lfcwm_optchar}" "${lfcwm_rest}"; lfcwm_rest=''; continue; fi; # if obj lfcwm_rest is_empty else error_user "unknown option -${lfcwm_optchar}."; fi; # if list_has lfcwm_short_n "${lfcwm_optchar}" done; # while obj lfcwm_rest is_not_empty ;; *) # Here, $lfcwm_arg is not an option, so a file parameter. list_append lfcwm_fparams "${lfcwm_arg}"; # Ignore the strange POSIX option handling to end option # parsing after the first file name argument. To reuse it, do # a `break' here if $POSIXLY_CORRECT of `bash' is not empty. # When `bash' is called as `sh' $POSIXLY_CORRECT is set # automatically to `y'. ;; esac; done; list_append lfcwm_result '--'; if obj lfcwm_fparams is_not_empty then lfcwm_result="${lfcwm_result} ${lfcwm_fparams}"; fi; ### list_from_cmdline_with_minus() if is_greater_than "$#" 0 then list_append lfcwm_result "$@"; fi; obj lfcwm_result echo1; eval ${_UNSET} lfcwm_abbrev; eval ${_UNSET} lfcwm_fparams; eval ${_UNSET} lfcwm_short_a; eval ${_UNSET} lfcwm_short_n; eval ${_UNSET} lfcwm_long_a; eval ${_UNSET} lfcwm_long_both; eval ${_UNSET} lfcwm_long_n; eval ${_UNSET} lfcwm_result; eval ${_UNSET} lfcwm_arg; eval ${_UNSET} lfcwm_opt; eval ${_UNSET} lfcwm_optarg; eval ${_UNSET} lfcwm_optchar; eval ${_UNSET} lfcwm_with_equal; eval ${_UNSET} lfcwm_rest; eval "${return_ok}"; } # list_from_cmdline_with_minus() # _search_abbrev ( ) # # Check whether has an element constructed from the abbreviation # . All `-' in are replaced by `-*'. This construction # is searched first with `[^-]*'. If there is more than a # single element an error is created. If none is found `*' # is searched. Again an error is created for several results. # This function was constructed from the former function # list_single_from_abbrev(). # # This is a local function of list_from_cmdline_with_minus(). # # Arguments: 2 # : a variable name for a list of single-quoted elements # : some sequence of characters. # # Output: the found element (always not empty), error when none found. # # Variable prefix: _sa # _search_abbrev() { func_check _search_abbrev '=' 2 "$@"; eval _sa_list='"${'$1'}"'; if obj _sa_list is_empty then error "_search_abbrev(): list is empty."; fi; _sa_abbrev="$2"; if obj _sa_abbrev is_empty then error "_search_abbrev(): abbreviation argument is empty."; fi; _sa_case="$(echo1 "${_sa_abbrev}" | sed 's/-/\*-/g')"; _sa_opt=''; case " ${_sa_list}" in *\ \'${_sa_case}*) # list has the abbreviation _sa_m1=''; _sa_m2=''; _sa_nm=''; eval set x "${_sa_list}"; shift; for i # over the option list do _sa_i="$i"; ### _search_abbrev() of list_from_cmdline_with_minus() case "${_sa_i}" in ${_sa_case}*-*) if obj _sa_m1 is_empty then _sa_m1="${_sa_i}"; continue; fi; _sa_m2="${_sa_i}"; continue; ;; ${_sa_case}*) if obj _sa_nm is_empty then _sa_nm="${_sa_i}"; continue; fi; error_user "The abbreviation --${_sa_abbrev} has multiple options "\ "--${_sa_nm} and --${_sa_i}."; ;; esac; done; if obj _sa_nm is_empty then if obj _sa_m2 is_not_empty then error_user "The abbreviation --${_sa_abbrev} has multiple options "\ "--${_sa_m1} and --${_sa_m2}."; fi; ### _search_abbrev() of list_from_cmdline_with_minus() if obj _sa_m1 is_not_empty then _sa_opt="${_sa_m1}"; fi; else _sa_opt="${_sa_nm}"; fi; ;; esac; if obj _sa_opt is_empty then error_user "--${_sa_abbrev} is not an option."; fi; obj _sa_opt echo1; eval "${_UNSET}" _sa_abbrev; eval "${_UNSET}" _sa_case; eval "${_UNSET}" _sa_i; eval "${_UNSET}" _sa_list; eval "${_UNSET}" _sa_m1; eval "${_UNSET}" _sa_m2; eval "${_UNSET}" _sa_nm; eval "${_UNSET}" _sa_opt; eval "${return_ok}"; } # _search_abbrev() of list_from_cmdline_with_minus() ######################################################################## # list_from_file ( ) # # Extrect the lines from and store them as elements to list # . # # Arguments: 2 # : a variable name for output, a list of single-quoted elts # : the name of an existing file # # Variable prefix: lff # list_from_file() { func_check list_from_file '=' 2 "$@"; if is_not_file "$2" then eval "${return_bad}"; fi; lff_n="$(wc -l "$2" | eval sed "'s/^[ ${_TAB}]*\([0-9]\+\).*$/\1/'")"; eval "$1"="''"; if obj lff_n is_equal 0 then eval "${return_good}"; fi; lff_i=0; while obj lff_i is_not_equal "${lff_n}" do lff_i="$(expr "${lff_i}" + 1)"; list_append "$1" "$(eval sed -n "'${lff_i}p ${lff_i}q'" "'$2'")"; done; eval "${_UNSET}" lff_i; eval "${_UNSET}" lff_n; eval "${return_good}"; } # list_from_file() ######################################################################## # list_from_split ( ) # # Split by into a list, omitting the separator. # # Arguments: 2: a that is to be split into parts divided by # character # Output: the resulting list string # # Variable prefix: lfs # list_from_split() { func_check list_from_split = 2 "$@"; if is_empty "$1" then eval "${return_ok}"; fi; case "$2" in ?) lfs_splitter="$2"; ;; '\:') lfs_splitter=':'; ;; *) error "list_from_split(): split argument $2 must be a single character."; ;; esac; lfs_list=''; lfs_rest="$1"; while : do case "${lfs_rest}" in *${lfs_splitter}*) case "${lfs_splitter}" in /) lfs_elt="$(echo1 ${lfs_rest} | sed \ 's|^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*|\1|')"; lfs_rest="$(echo1 ${lfs_rest} | sed \ 's|^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$|\1|')"; ;; *) ### list_from_split() lfs_elt="$(echo1 ${lfs_rest} | sed \ 's/^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*/\1/')"; lfs_rest="$(echo1 ${lfs_rest} | sed \ 's/^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$/\1/')"; ;; esac; list_append lfs_list "${lfs_elt}" continue; ;; *) list_append lfs_list "${lfs_rest}" break ;; esac; done echo1 "${lfs_list}"; eval ${_UNSET} lfs_elt; eval ${_UNSET} lfs_list; eval ${_UNSET} lfs_rest; eval ${_UNSET} lfs_splitter; eval "${return_ok}"; } # list_from_split() ######################################################################## # list_has ( ) # # Test whether the list has the element . # # Arguments: 2 # : a variable name for a list of single-quoted elements # : some sequence of characters. # # Variable prefix: lh # list_has() { func_check list_has = 2 "$@"; eval lh_list='"${'$1'}"'; if obj lh_list is_empty then eval "${_UNSET}" lh_list; eval "${return_no}"; fi; case "$2" in \'*\') lh_element=" $2 "; ;; *) lh_element=" '$2' "; ;; esac; if string_contains " ${lh_list} " "${lh_element}" then eval "${_UNSET}" lh_list; eval "${_UNSET}" lh_element; eval "${return_yes}"; else eval "${_UNSET}" lh_list; eval "${_UNSET}" lh_element; eval "${return_no}"; fi; } # list_has() ######################################################################## # list_has_abbrev ( ) # # Test whether the list of has an element starting with # . # # Arguments: 2 # : a variable name for a list of single-quoted elements # : some sequence of characters. # # Variable prefix: lha # list_has_abbrev() { func_check list_has_abbrev '=' 2 "$@"; eval lha_list='"${'$1'}"'; if obj lha_list is_empty then eval "${_UNSET}" lha_list; eval "${return_no}"; fi; case "$2" in \'*) lha_element="$(echo1 "$2" | sed 's/'"${_SQ}"'$//')"; ;; *) lha_element="'$2"; ;; esac; if string_contains " ${lha_list}" " ${lha_element}" then eval "${_UNSET}" lha_list; eval "${_UNSET}" lha_element; eval "${return_yes}"; else eval "${_UNSET}" lha_list; eval "${_UNSET}" lha_element; eval "${return_no}"; fi; eval "${return_ok}"; } # list_has_abbrev() ######################################################################## # list_has_not ( ) # # Test whether has no . # # Arguments: 2 # : a space-separated list of single-quoted elements. # : some sequence of characters. # # Variable prefix: lhn # list_has_not() { func_check list_has_not = 2 "$@"; eval lhn_list='"${'$1'}"'; if obj lhn_list is_empty then eval "${_UNSET}" lhn_list; eval "${return_yes}"; fi; case "$2" in \'*\') lhn_element=" $2 "; ;; *) lhn_element=" '$2' "; ;; esac; if string_contains " ${lhn_list} " "${lhn_element}" then eval "${_UNSET}" lhn_list; eval "${_UNSET}" lhn_element; eval "${return_no}"; else eval "${_UNSET}" lhn_list; eval "${_UNSET}" lhn_element; eval "${return_yes}"; fi; } # list_has_not() ######################################################################## # list_single_from_abbrev ( ) # # Check whether the list has an element starting with . If # there are more than a single element an error is raised. # # Arguments: 2 # : a variable name for a list of single-quoted elements # : some sequence of characters. # # Output: the found element. # # Variable prefix: lsfa # list_single_from_abbrev() { func_check list_single_from_abbrev '=' 2 "$@"; eval lsfa_list='"${'$1'}"'; if obj lsfa_list is_empty then eval "${_UNSET}" lsfa_list; eval "${return_no}"; fi; lsfa_abbrev="$2"; if list_has lsfa_list "${lsfa_abbrev}" then obj lsfa_abbrev echo1; eval "${_UNSET}" lsfa_abbrev; eval "${_UNSET}" lsfa_list; eval "${return_yes}"; fi; if list_has_abbrev lsfa_list "${lsfa_abbrev}" then lsfa_element=''; eval set x "${lsfa_list}"; shift; ### list_single_from_abbrev() for i do case "$i" in ${lsfa_abbrev}*) if obj lsfa_element is_not_empty then error_user "The abbreviation --${lsfa_abbrev} \ has multiple options: --${lsfa_element} and --${i}."; fi; lsfa_element="$i"; ;; esac; done; obj lsfa_element echo1; eval "${_UNSET}" lsfa_abbrev; eval "${_UNSET}" lsfa_element; eval "${_UNSET}" lsfa_list; eval "${return_yes}"; else eval "${_UNSET}" lsfa_abbrev; eval "${_UNSET}" lsfa_element; eval "${_UNSET}" lsfa_list; eval "${return_no}"; fi; } # list_single_from_abbrev() ######################################################################## # list_uniq () # # Generate a list with only unique elements. # # Output: the corrected list # # Variable prefix: lu # list_uniq() { func_check list_uniq '=' 1 "$@"; if is_empty "$1" then eval "${return_ok}"; fi; eval a='"${'"$1"'}"'; if obj a is_empty then eval "${return_ok}"; fi; eval set x "$a"; shift; lu_list=''; for i do lu_i="$i"; if list_has lu_list "${lu_i}" then continue; else list_append lu_list ${lu_i}; fi; done; obj lu_list echo1; eval "${_UNSET}" lu_i; eval "${_UNSET}" lu_list; eval "${return_ok}"; } # list_uniq() ######################################################################## # lists_combine ( ...) # # Combine several lists to a single list. All arguments are list names. # # Output: the combined list # # Variable prefix: lc # lists_combine() { func_check lists_combine '>=' 2 "$@"; lc_list=''; for i do eval lc_arg='"${'"$i"'}"'; case "${lc_arg}" in '') :; ;; "'"*"'") if obj lc_list is_empty then lc_list="${lc_arg}"; else lc_list="${lc_list} ${lc_arg}"; fi; ;; *) error 'lists_combine(): $'"$i"' is not a list.'; ;; esac; done; obj lc_list echo1; eval "${_UNSET}" lc_arg; eval "${_UNSET}" lc_list; eval "${return_ok}"; } # lists_combine() ######################################################################## landmark '7: man_*()'; ######################################################################## ######################################################################## # Information on the search of man pages in groffer # The search of man pages is based on a set of directories. That # starts with the so-called man path. This is determined in function # man_setup() either by the command-line option --manpath, by $MANOPT, # or by $MANPATH. There is also a program `manpath'. If all of this # does not work a man path is created from $PATH with function # manpath_set_from_path(). We now have a set of existing directories # for the search of man pages; usually they end with `/man'. # The directory set of the man path can be changed in 2 ways. If # operating system names are given in $SYSTEM or by --systems on the # command-line all man path directory will be appended by these names. # The appended system names replace the original man path; but if no # system name is set, the original man path is kept. In `groffer', # this is done by the function manpath_add_lang_sys() in man_setup(). # The next addition for directories is the language. It is specified # by --locale or by one of the environment variables $LC_ALL, # $LC_MESSAGES, and $LANG. The language name of `C' or `POSIX' means # the return to the default language (usually English); this deletes # former language specifications. The language name and its # abbreviation with 2 characters is appended to the man page # directories. But these new arising directories are added to the man # page, they do not replace it such as the system names did. This is # done by function manpath_add_lang_sys() in man_setup() as well. # Now we have the basic set of directories for the search of man pages # for given filespec arguments. The real directories with the man # page source files are gotten by appending `man
' to each # directory, where section is a single character of the form # `[1-9on]'. # There you find files named according to the form # .
[][], where `[]' means # optional this time. is the name of the man page;
# is the single character from the last paragraphe; the optional # consists of some letters denoting special aspects for # the section; and the optional is something like `.gz', # `.Z', or `.bz2', meaning that the file is compressed. # If name, section. and extension are specified on the command-line # the file of the form .
with or without # are handled. The first one found according to the # directory set for the section is shown. # If just name and section are specified on the command-line then # first .
with or without are searched. # If no matching file was found, .
with or # without are searched for all possible extensions. # If only name is specified on the command-line then the section # directories are searched by and by, starting with section `1', until # a file is matched. # The function man_is_man() determines all suitable man files for a # command-line argument, while man_get() searches the single matching # file for display. ######################################################################## # man_get ( [
[]]) # # Write a man page to the temporary file. # # Globals in: $_TMP_MANSPEC, $_MAN_SEC_CHARS, $_MAN_EXT, $_MAN_ALL # # Arguments: 1, 2, or 3 # # Variable prefix: mg # man_get() { func_check man_get '>=' 1 "$@"; if obj _TMP_MANSPEC is_empty then error 'man_get(): man_is_man() must be run first on '"$*".; fi; mg_name="$1"; mg_sec="$2"; if is_empty "$2" then mg_sec="${_MAN_SEC_CHARS}"; # take care it is not a single section fi; mg_ext="$3"; if is_empty "$3" then mg_ext="${_MAN_EXT}"; fi; if obj _TMP_MANSPEC is_not_equal "${_TMP_DIR}/,man:$1:${mg_sec}${mg_ext}" then error 'man_get(): $_TMP_MANSPEC does not suit to the arguments '"$*".; fi; ### man_get() if obj _MAN_ALL is_yes then list_from_file mg_list "${_TMP_MANSPEC}"; eval set x ${mg_list}; shift; mg_ok='no'; mg_list=''; for f do mg_f="$f"; if list_has mg_list "${mg_f}" then continue; else list_append mg_list "${mg_f}"; fi; ### man_get() if obj mg_f is_file then to_tmp "${mg_f}" && mg_ok='yes'; fi; done; if obj mg_ok is_yes then register_title man:"${mg_name}"; fi; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_sec; eval "${return_ok}"; else # $_MAN_ALL is not 'yes' if is_empty "$2" then # no section from command line if obj _MAN_SEC_LIST is_empty then m="${_MAN_AUTO_SEC_LIST}"; # list of all sections else m="${_MAN_SEC_LIST}"; # from --sections fi; ### man_get() for s in $(eval set x $m; shift; echo1 "$@") do mg_s="$s"; list_from_file mg_list "${_TMP_MANSPEC}"; eval set x ${mg_list}; shift; if obj mg_ext is_empty then for f do mg_f="$f"; case "${mg_f}" in */man"${mg_s}"/"${mg_name}"."${mg_s}"|*/man"${mg_s}"/"${mg_name}"."${mg_s}".*) if obj mg_f is_file then to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; # "$mg_f" done; # for f fi; # mg_ext is_empty ### man_get() for f do mg_f="$f"; case "${mg_f}" in */man"${mg_s}"/"${mg_name}"."${mg_s}""${mg_ext}"*) if obj mg_f is_file then to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; # "$mg_f" done; # for f done; # for s else # $mg_sec is not empty, do with section list_from_file mg_list "${_TMP_MANSPEC}"; eval set x ${mg_list}; shift; if obj mg_ext is_empty then for f do mg_f="$f"; ### man_get() case "${mg_f}" in */man"${mg_sec}"/"${mg_name}"."${mg_sec}"|\ */man"${mg_sec}"/"${mg_name}"."${mg_sec}".*) if obj mg_f is_file then obj mg_f to_tmp && \ register_title "${mg_name}(${mg_sec})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; done; # for f for f do mg_f="$f"; ### man_get() case "${mg_f}" in */man"${mg_sec}"/"${mg_name}"."${mg_sec}"*) if obj mg_f is_file then obj mg_f to_tmp && \ register_title "${mg_name}(${mg_sec})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; done; # for f else # mg_ext is not empty for f do mg_f="$f"; ### man_get() case "${mg_f}" in */man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"|\ */man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}".*) if obj mg_f is_file then obj mg_f to_tmp && \ register_title "${mg_name}(${mg_sec}${mg_ext})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; done; # for f for f do mg_f="$f"; ### man_get() case "${mg_f}" in */man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"*) if obj mg_f is_file then obj mg_f to_tmp && \ register_title "${mg_name}(${mg_sec}${mg_ext})"; eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_s; eval ${_UNSET} mg_sec; eval "${return_ok}"; fi; ;; esac; done; # for f fi; fi; # $mg_sec fi; # $_MAN_ALL eval ${_UNSET} mg_ext; eval ${_UNSET} mg_f; eval ${_UNSET} mg_list; eval ${_UNSET} mg_name; eval ${_UNSET} mg_sec; eval ${_UNSET} mg_s; eval "${return_ok}"; } # man_get() ######################################################################## # man_is_man ( [
[]]) # # Test whether exists as man page. # # Globals: in: $_TMP_MAN, $_MAN_SEC_CHARS, $_TMP_DIR, $_MAN_EXT, # $_MAN_AUTO_SEC_CHARS # out: $_TMP_MANSPEC # # Arguments: 1, 2, or 3 # # Variable prefix: mim # man_is_man() { func_check man_is_man '>=' 1 "$@"; if is_empty "$1" then _TMP_MANSPEC=''; eval "${return_no}"; fi; if obj _TMP_DIR is_empty then error 'man_is_man(): main_init() must be run first.'; fi; if obj _MAN_IS_SETUP is_not_yes then error 'man_is_man(): man_setup() must be run first.'; fi; mim_sec="$2"; if is_empty "$2" then mim_sec="${_MAN_SEC_CHARS}"; fi; if is_empty "$3" then mim_ext="${_MAN_EXT}"; else mim_ext="$3"; fi; _TMP_MANSPEC="${_TMP_DIR}/,man:$1:${mim_sec}${mim_ext}"; ### man_is_man() if obj _TMP_MANSPEC is_not_file then if obj mim_sec is_empty then m="${_MAN_AUTO_SEC_CHARS}"; eval grep "'/man$m/$1\.$m${mim_ext}'" \ "${_TMP_MAN}" > "${_TMP_MANSPEC}"; else eval grep "'/man${mim_sec}/$1\.${mim_sec}${mim_ext}'" \ "${_TMP_MAN}" > "${_TMP_MANSPEC}"; fi; fi; eval ${_UNSET} mim_ext; eval ${_UNSET} mim_sec; if obj _TMP_MANSPEC is_empty_file then rm_file_with_debug "${_TMP_MANSPEC}"; eval "${return_no}"; else eval "${return_yes}"; fi; } # man_is_man() ######################################################################## # man_setup () # # Setup the variables $_MAN_* needed for man page searching. # # Globals: # in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL, # $MANPATH, $MANSEC, $PAGER, $SYSTEM, $MANOPT. # out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2, # $_MAN_SEC, $_MAN_ALL, $_TMP_MAN # in/out: $_MAN_ENABLE # # The precedence for the variables related to `man' is that of GNU # `man', i.e. # # $LANG; overridden by # $LC_MESSAGES; overridden by # $LC_ALL; this has the same precedence as # $MANPATH, $MANSEC, $PAGER, $SYSTEM; overridden by # $MANOPT; overridden by # the groffer command line options. # # $MANROFFSEQ is ignored because grog determines the preprocessors. # # Variable prefix: ms # man_setup() { func_check man_setup '=' 0 "$@"; if obj _MAN_IS_SETUP is_yes then eval "${return_ok}"; fi; _MAN_IS_SETUP='yes'; if obj _MAN_ENABLE is_not_yes then eval "${return_ok}"; fi; # determine basic path for man pages obj_from_output ms_path \ get_first_essential "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}"; if obj ms_path is_empty && is_prog 'manpath' then obj_from_output ms_path manpath 2>${_NULL_DEV}; # not always available fi; if obj ms_path is_empty then manpath_set_from_path; else obj_from_output _MAN_PATH path_list "${ms_path}"; fi; if obj _MAN_PATH is_empty then _MAN_ENABLE="no"; echo2 "man_setup(): man path is empty"; eval ${_UNSET} ms_path; eval "${return_ok}"; fi; obj_from_output _MAN_PATH list_uniq _MAN_PATH; ### man_setup() if obj _MAN_ALL is_not_yes then if obj _OPT_ALL is_yes || obj _MANOPT_ALL is_yes then _MAN_ALL='yes'; else _MAN_ALL='no'; fi; fi; ms_sys="$(get_first_essential \ "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")"; if obj ms_sys is_not_empty then obj_from_output _MAN_SYS list_from_split "${ms_sys}" ','; fi; obj_from_output ms_lang get_first_essential \ "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}"; case "${ms_lang}" in C|POSIX) _MAN_LANG=""; _MAN_LANG2=""; ;; ?) _MAN_LANG="${ms_lang}"; _MAN_LANG2=""; ;; ??) _MAN_LANG="${ms_lang}"; _MAN_LANG2="${ms_lang}"; ;; ### man_setup() *) _MAN_LANG="${ms_lang}"; # get first two characters of $ms_lang _MAN_LANG2="$(echo1 "${ms_lang}" | sed 's/^\(..\).*$/\1/')"; exit_test; ;; esac; # from now on, use only $_MAN_LANG*, forget about $_OPT_LANG, $LC_*. manpath_add_lang_sys; obj_from_output _MAN_PATH list_uniq _MAN_PATH; obj_from_output _MAN_SEC get_first_essential \ "${_OPT_SECTIONS}" "${_MANOPT_SEC}" "${MANSEC}"; _MAN_SEC_LIST=""; _MAN_SEC_CHARS=""; case "${_MAN_SEC}" in *:*) eval set x "$(list_from_split "${_MAN_SEC}" :)"; shift; for s do if list_has _MAN_AUTO_SEC_LIST "$s" then list_append _MAN_SEC_LIST "$s"; _MAN_SEC_CHARS="${_MAN_SEC_CHARS}$s"; fi; done if obj _MAN_SEC_CHARS is_not_empty then _MAN_SEC_CHARS="[${_MAN_SEC_CHARS}]"; fi; ;; *) if list_has _MAN_AUTO_SEC_LIST "${_MAN_SEC}" then list_append _MAN_SEC_LIST "${_MAN_SEC}"; _MAN_SEC_CHARS="[${_MAN_SEC}]"; fi; ;; esac; ### man_setup() obj_from_output _MAN_EXT get_first_essential \ "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}" "${EXTENSION}"; _TMP_MAN="$(tmp_create man)"; eval set x "${_MAN_PATH}"; shift; if is_not_equal "$#" 0 then for i do for j in "$i"/man* do if obj j is_dir then find "$j" >>"${_TMP_MAN}"; fi; done done; fi; eval ${_UNSET} ms_lang; eval ${_UNSET} ms_list; eval ${_UNSET} ms_path; eval ${_UNSET} ms_sys; eval "${return_ok}"; } # man_setup() ######################################################################## landmark '8: manpath_*()'; ######################################################################## ######################################################################## # manpath_add_lang_sys () # # Add language and operating system specific directories to man path. # # Arguments : 0 # Output : none # Globals: # in: $_MAN_SYS: a list of names of operating systems. # $_MAN_LANG and $_MAN_LANG2: each a single name # in/out: $_MAN_PATH: list of directories which shall have the `man?' # subdirectories. # # Variable prefix: mals # manpath_add_lang_sys() { func_check manpath_add_lang_sys '=' 0 "$@"; if obj _MAN_PATH is_empty then eval "${return_ok}"; fi; if obj _MAN_SYS is_empty then mals_mp="${_MAN_PATH}"; else mals_mp=''; eval set x "${_MAN_SYS}"; shift; for s do _manpath_add_sys "$s"; done; fi; if obj mals_mp is_not_empty then mals_lang_path=''; if is_equal "$_MAN_LANG" "$_MAN_LANG2" then mals_man_lang2=''; else mals_man_lang2="${_MAN_LANG2}"; fi; for i in "${_MAN_LANG}" "${mals_man_lang2}" do if obj i is_empty then continue; fi; ### manpath_add_lang_sys() mals_lang="$i"; eval set x "${mals_mp}"; shift; for p do obj_from_output mals_dir dir_name_append "${p}" "${mals_lang}"; if obj mals_dir is_dir then list_append mals_lang_path "${mals_dir}"; fi; done; done; obj_from_output mals_mp lists_combine mals_lang_path mals_mp; fi; _MAN_PATH="${mals_mp}"; eval ${_UNSET} mals_dir; eval ${_UNSET} mals_lang; eval ${_UNSET} mals_lang_path; eval ${_UNSET} mals_man_lang2; eval ${_UNSET} mals_mp; eval "${return_ok}"; } # manpath_add_lang_sys() # _manpath_add_sys () # # Append the existing subdirectories of man path directories to # the list $mals_mp. # # Local function to manpath_add_lang_sys(). # # Argument: 1, a operating system name (for appending to a man path # directory) # # Globals in: $_MAN_PATH # Globals in/out: $mals_mp # # Variable prefix: _mas # _manpath_add_sys() { func_check _manpath_add_sys '=' 1 "$@"; case "$1" in '') :; ;; man) obj_from_output mals_mp lists_combine mals_mp _MAN_PATH; ;; *) _mas_sys="$1"; eval set x "${_MAN_PATH}"; shift; for p do obj_from_output _mas_dir dir_name_append "${p}" "${_mas_sys}"; if obj _mas_dir is_dir then list_append mals_mp "${_mas_dir}"; fi; done; ;; esac; eval ${_UNSET} _mas_dir; eval ${_UNSET} _mas_sys; eval "${return_ok}"; } # _manpath_add_sys() of manpath_add_lang_sys() ######################################################################## # manpath_set_from_path () # # Determine basic search path for man pages from $PATH. # # Return: `0' if a valid man path was retrieved. # Output: none # Globals: # in: $PATH # out: $_MAN_PATH # # Variable prefix: msfp # manpath_set_from_path() { func_check manpath_set_from_path '=' 0 "$@"; msfp_manpath=''; # get a basic man path from $PATH if obj PATH is_not_empty then # delete the final `/bin' part p="$(echo1 "${PATH}" | sed 's|//*bin/*:|:|g')"; obj_from_output msfp_list path_list "$p"; # append some default directories for b in /usr/local /usr/local /usr /usr \ /usr/X11R6 /usr/openwin \ /opt /opt/gnome /opt/kde do msfp_base="$b"; if list_has_not msfp_list "${msfp_base}" && obj msfp_base is_dir then list_append msfp_list "${msfp_base}"; fi; done; eval set x "${msfp_list}"; shift; for d do # including empty for former `/bin'. msfp_base="$d"; for e in /share/man /share/MAN /man /MAN do msfp_mandir="${msfp_base}$e"; if obj msfp_mandir is_dir then list_append msfp_manpath "${msfp_mandir}"; fi; done; done; fi; _MAN_PATH="${msfp_manpath}"; eval ${_UNSET} msfp_base; eval ${_UNSET} msfp_list; eval ${_UNSET} msfp_mandir; eval ${_UNSET} msfp_manpath; eval "${return_ok}"; } # manpath_set_from_path() ######################################################################## landmark '9: obj_*()'; ######################################################################## ######################################################################## # obj ( ...) # # This works like a method (object function) call for an object. # Run " $ ...". # # The first argument represents an object name whose data is given as # first argument to (). # # Argument: >=2 # : variable name # : a program or function name # # Variable prefix: o # obj() { func_check obj '>=' 2 "$@"; eval o_arg1='"${'$1'}"'; if is_empty "$2" then error "obj(): function name is empty." else o_func="$2"; fi; shift; shift; eval "${o_func}"' "${o_arg1}" "$@"'; n="$?"; eval ${_UNSET} o_arg1; eval ${_UNSET} o_func; eval "${return_var} $n"; } # obj() ######################################################################## # obj_data () # # Print the data of , i.e. the content of $. # For possible later extensions. # # Arguments: 1 # : a variable name # Output: the data of # # Variable prefix: od # obj_data() { func_check obj_data '=' 1 "$@"; if is_empty "$1" then error "obj_data(): object name is empty." fi; eval od_res='"${'"$1"'}"'; obj od_res echo1; eval ${_UNSET} od_res; eval "${return_ok}"; } # obj_data() ######################################################################## # obj_from_output ( ...) # # Run '$="$( ...)"' to set the result of a # function call to a global variable. Variables are not stored. # # Arguments: >=2 # : a variable name # : the name of a function or program # : optional argument to # Output: none # # Variable prefix: ofo # obj_from_output() { func_check obj_from_output '>=' 2 "$@"; if is_empty "$1" then error "obj_from_output(): variable name is empty."; fi; if is_empty "$2" then error "obj_from_output(): function name is empty." fi; ofo_result_name="$1"; shift; ofo_return=0; if is_equal "$#" 0 then eval "${ofo_result_name}"'=""'; else ofo_list=''; for i do list_append ofo_list "$i"; done; eval "${ofo_result_name}"'="$('"${ofo_list}"')"'; ofo_return="$?"; exit_test; fi; r="${ofo_return}"; eval ${_UNSET} ofo_list; eval ${_UNSET} ofo_return; eval ${_UNSET} ofo_result_name; eval "${return_var} $r"; } # obj_from_output() ######################################################################## # obj_set ( ) # # Set the data of , i.e. call "$=". # # Arguments: 2 # : a variable name # : a string # Output:: none # obj_set() { func_check obj_set '=' 2 "$@"; if is_empty "$1" then error "obj_set(): object name is empty." fi; eval "$1"='"$2"'; eval "${return_ok}"; } # obj_set() ######################################################################## # path_chop () # # Remove unnecessary colons from path. # # Argument: 1, a colon separated path. # Output: path without leading, double, or trailing colons. # path_chop() { func_check path_chop = 1 "$@"; # replace multiple colons by a single colon `:' # remove leading and trailing colons echo1 "$1" | sed ' s/^:*// s/:::*/:/g s/:*$// '; eval "${return_ok}"; } # path_chop() ######################################################################## # path_clean () # # Remove non-existing directories from a colon-separated list. # # Argument: 1, a colon separated path. # Output: colon-separated list of existing directories. # # Variable prefix: pc # path_clean() { func_check path_clean = 1 "$@"; if is_not_equal "$#" 1 then error 'path_clean() needs 1 argument.'; fi; pc_arg="$1"; eval set x "$(path_list "${pc_arg}")"; exit_test; shift; pc_res=""; for i do pc_i="$i"; if obj pc_i is_not_empty \ && obj pc_res path_not_contains "${pc_i}" \ && obj pc_i is_dir then case "${pc_i}" in ?*/) pc_res="${pc_res}:$(dir_name_chop "${pc_i}")"; exit_test; ;; *) pc_res="${pc_res}:${pc_i}"; ;; esac; fi; done; path_chop "${pc_res}"; eval ${_UNSET} pc_arg; eval ${_UNSET} pc_i; eval ${_UNSET} pc_res; eval "${return_ok}"; } # path_clean() ######################################################################## # path_contains ( ) # # Test whether is contained in , a list separated by `:'. # # Arguments : 2 # Return : `0' if arg2 is substring of arg1, `1' otherwise. # path_contains() { func_check path_contains = 2 "$@"; case ":$1:" in *:${2}:*) eval "${return_yes}"; ;; *) eval "${return_no}"; ;; esac; eval "${return_ok}"; } # path_contains() ######################################################################## # path_not_contains ( ) # # Test whether is not contained in colon separated . # # Arguments : 2 # path_not_contains() { func_check path_not_contains = 2 "$@"; if path_contains "$1" "$2" then eval "${return_no}"; else eval "${return_yes}"; fi; eval "${return_ok}"; } # path_not_contains() ######################################################################## # path_list () # # From a `:' separated path generate a list with unique elements. # # Arguments: 1: a colon-separated path # Output: the resulting list, process it with `eval set' # # Variable prefix: pl # path_list() { func_check path_list = 1 "$@"; eval set x "$(list_from_split "$1" '\:')"; shift; pl_list=''; for e do pl_elt="$e"; if list_has pl_list "${pl_elt}" then continue; else list_append pl_list "${pl_elt}"; fi; done; obj pl_list echo1; eval ${_UNSET} pl_elt; eval ${_UNSET} pl_list; eval "${return_ok}"; } # path_list() ######################################################################## landmark '10: register_*()'; ######################################################################## ######################################################################## # register_file () # # Write a found file and register the title element. # # Arguments: 1: a file name # Output: none # register_file() { func_check register_file = 1 "$@"; if is_empty "$1" then error 'register_file(): file name is empty'; fi; if is_equal "$1" '-' then to_tmp "${_TMP_STDIN}" && register_title 'stdin'; else to_tmp "$1" && register_title "$1"; exit_test; fi; eval "${return_ok}"; } # register_file() ######################################################################## # register_title () # # Create title element from and append to $_REG_TITLE_LIST. # Basename is created. # # Globals: $_REG_TITLE_LIST (rw) # # Variable prefix: rt # register_title() { func_check register_title '=' 1 "$@"; if is_empty "$1" then eval "${return_ok}"; fi; if obj _DEBUG_PRINT_FILENAMES is_yes then if is_equal "$1" 'stdin' then echo2 "file: standard input"; else if obj _FILESPEC_IS_MAN is_yes then echo2 "file title: $1"; else echo2 "file: $1"; fi; fi; fi; case "${_REG_TITLE_LIST}" in *\ *\ *\ *) eval "${return_ok}"; ;; esac; # remove directory part obj_from_output rt_title base_name "$1"; # replace space characters by `_' rt_title="$(echo1 "${rt_title}" | sed 's/[ ]/_/g')"; # remove extension `.bz2' rt_title="$(echo1 "${rt_title}" | sed 's/\.bz2$//')"; # remove extension `.gz' rt_title="$(echo1 "${rt_title}" | sed 's/\.gz$//')"; # remove extension `.Z' rt_title="$(echo1 "${rt_title}" | sed 's/\.Z$//')"; if obj rt_title is_empty then eval ${_UNSET} rt_title; eval "${return_ok}"; fi; list_append _REG_TITLE_LIST "${rt_title}"; eval ${_UNSET} rt_title; eval "${return_ok}"; } # register_title() ######################################################################## # reset () # # Reset the variables that can be affected by options to their default. # # # Defined in section `Preset' after the rudimentary shell tests. ######################################################################## # rm_file () # # Remove file. # rm_file() { func_check rm_file '=' 1 "$@"; if is_file "$1" then rm -f "$1" >${_NULL_DEV} 2>&1; fi; if is_existing "$1" then eval "${return_bad}"; else eval "${return_good}"; fi; } # rm_file() ######################################################################## # rm_file_with_debug () # # Remove file if $_DEBUG_KEEP_FILES allows it. # # Globals: $_DEBUG_KEEP_FILES # rm_file_with_debug() { func_check rm_file_with_debug '=' 1 "$@"; if obj _DEBUG_KEEP_FILES is_not_yes then if is_file "$1" then rm -f "$1" >${_NULL_DEV} 2>&1; fi; fi; if is_existing "$1" then eval "${return_bad}"; else eval "${return_good}"; fi; } # rm_file_with_debug() ######################################################################## # rm_tree () # # Remove a file or a complete directory tree. # # Globals: $_DEBUG_KEEP_FILES # rm_tree() { func_check rm_tree '=' 1 "$@"; if is_existing "$1" then rm -f -r "$1" >${_NULL_DEV} 2>&1; fi; if is_existing "$1" then eval "${return_bad}"; else eval "${return_good}"; fi; } # rm_tree() ######################################################################## # save_stdin () # # Store standard input to temporary file (with decompression). # # Variable prefix: ss # if obj _HAS_COMPRESSION is_yes then save_stdin() { func_check save_stdin '=' 0 "$@"; ss_f="${_TMP_DIR}"/INPUT; cat >"${ss_f}"; cat_z "${ss_f}" >"${_TMP_STDIN}"; rm_file "${ss_f}"; eval ${_UNSET} ss_f; eval "${return_ok}"; } # save_stdin() else # no compression save_stdin() { func_check save_stdin '=' 0 "$@"; cat >"${_TMP_STDIN}"; eval "${return_ok}"; } # save_stdin() fi; ######################################################################## # special_filespec () # # Handle special modes like whatis and apropos. Run their filespec # functions if suitable. # # Globals: in: $_OPT_APROPOS, $_OPT_WHATIS, $_SPECIAL_SETUP # out: $_SPECIAL_FILESPEC (internal) # special_filespec() { func_check special_filespec '=' 0 "$@"; if obj _OPT_APROPOS is_not_yes && obj _OPT_WHATIS is_not_yes then eval "${return_bad}"; fi; if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes then error \ 'special_filespec(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; fi; if obj _SPECIAL_SETUP is_not_yes then error 'special_filespec(): setup for apropos or whatis must be run first.'; fi; if apropos_filespec || whatis_filespec; then eval "${return_ok}"; else eval "${return_bad}"; fi; } # special_filespec() ######################################################################## # special_setup () # # Handle special modes like whatis and apropos. Run their setup # functions if suitable. # special_setup() { func_check special_setup '=' 0 "$@"; if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes then error \ 'special_setup(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; fi; if apropos_setup || whatis_setup then eval "${return_ok}"; else eval "${return_bad}"; fi; } # special_setup() ######################################################################## landmark '11: stack_*()'; ######################################################################## ######################################################################## # string_contains ( ) # # Test whether is contained in . # # Arguments : 2 text arguments. # Return : `0' if arg2 is substring of arg1, `1' otherwise. # string_contains() { func_check string_contains '=' 2 "$@"; case "$1" in *${2}*) eval "${return_yes}"; ;; *) eval "${return_no}"; ;; esac; eval "${return_ok}"; } # string_contains() ######################################################################## # string_not_contains ( ) # # Test whether is not substring of . # # Arguments : 2 text arguments. # Return : `0' if arg2 is substring of arg1, `1' otherwise. # string_not_contains() { func_check string_not_contains '=' 2 "$@"; if string_contains "$1" "$2" then eval "${return_no}"; else eval "${return_yes}"; fi; eval "${return_ok}"; } # string_not_contains() ######################################################################## landmark '12: tmp_*()'; ######################################################################## ######################################################################## # tmp_cat () # # Output the temporary cat file (the concatenation of all input). # tmp_cat() { func_check tmp_cat '=' 0 "$@"; cat "${_TMP_CAT}"; eval "${return_var}" "$?"; } # tmp_cat() ######################################################################## # tmp_create (?) # # Create temporary file. The generated name is `,' followed by # . # # Argument: 0 or 1 # # Globals: $_TMP_DIR # # Output : name of created file # # Variable prefix: tc # tmp_create() { func_check tmp_create '<=' 1 "$@"; if obj _TMP_DIR is_empty || obj _TMP_DIR is_not_dir then error 'tmp_create(): there is no temporary directory.'; else # the output file does not have `,' as first character, so these are # different names from the output file. tc_tmp="${_TMP_DIR}/,$1"; obj tc_tmp rm_file; : >"${tc_tmp}" obj tc_tmp echo1; fi; eval ${_UNSET} tc_tmp; eval "${return_ok}"; } # tmp_create() ######################################################################## # to_tmp () # # Print file (decompressed) to the temporary cat file. # # Variable prefix: tt # to_tmp() { func_check to_tmp '=' 1 "$@"; if obj _TMP_CAT is_empty then error 'to_tmp(): $_TMP_CAT is not yet set'; fi; tt_1="$1"; tt_so_nr=0; # number for temporary `,so,*,*' if is_file "${tt_1}" then tt_dir="$(dir_name "${tt_1}")"; if obj _OPT_WHATIS is_yes then whatis_filename "${tt_1}" >>"${_TMP_CAT}"; else _FILE_NR="$(expr ${_FILE_NR} + 1)"; tt_file="${_TMP_DIR}/,file${_FILE_NR}"; if obj _FILESPEC_IS_MAN is_yes then if obj _DEBUG_PRINT_FILENAMES is_yes then echo2 "file: ${tt_1}"; fi; tt_tmp="${_TMP_DIR}/,tmp"; cat_z "${tt_1}" >"${tt_file}"; grep '^\.[ ]*so[ ]' "${tt_file}" | sed 's/^\.[ ]*so[ ]*//' >"${tt_tmp}"; list_from_file tt_list "${tt_tmp}"; eval set x ${tt_list}; shift; for i do tt_i="$i"; tt_so_nr="$(expr ${tt_so_nr} + 1)"; tt_sofile="${_TMP_DIR}/,so${_FILE_NR}_${tt_so_nr}"; tt_sofiles="${tt_sofiles} ${tt_sofile}"; _do_man_so "${tt_i}"; done; rm_file "${tt_tmp}"; mv "${tt_file}" "${tt_tmp}"; cat "${tt_tmp}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}"; for f in ${tt_sofiles} do rm_file_with_debug $f; done; rm_file "${tt_tmp}"; else # $_FILESPEC_IS_MAN ist not yes cat_z "${tt_1}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}"; fi; ### to_tmp() obj_from_output tt_grog grog "${tt_file}"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${tt_grog}"; case " ${tt_grog} " in *\ -m*) eval set x "$(echo1 " ${tt_grog} " | sed ' s/'"${_TAB}"'/ /g s/ */ /g s/ -m / -m/g s/ -mm\([^ ]\)/ -m\1/g ')"; shift; for i do tt_i="$i"; case "${tt_i}" in -m*) if list_has _MACRO_PACKAGES "${tt_i}" then case "${_MACRO_PKG}" in '') _MACRO_PKG="${tt_i}"; ;; ${tt_i}) :; ;; -m*) echo2 "Ignore ${tt_1} because it needs ${tt_i} instead "\ "of ${_MACRO_PKG}." rm_file_with_debug "${tt_file}"; eval ${_UNSET} tt_1; eval ${_UNSET} tt_dir; eval ${_UNSET} tt_file; eval ${_UNSET} tt_grog; eval ${_UNSET} tt_i; eval ${_UNSET} tt_so_nr; eval ${_UNSET} tt_sofile; eval ${_UNSET} tt_sofiles; eval ${_UNSET} tt_sofound; eval ${_UNSET} tt_list; eval ${_UNSET} tt_tmp; eval "${return_bad}"; ;; ### to_tmp() *) error \ 'to_tmp(): $_MACRO_PKG does not start with -m: '"${_MACRO_PKG}"; ;; esac; fi; ;; esac; done; ;; esac; cat "${tt_file}" >>"${_TMP_CAT}"; rm_file_with_debug "${tt_file}"; fi; else error "to_tmp(): could not read file \`${tt_1}'."; fi; eval ${_UNSET} tt_1; eval ${_UNSET} tt_dir; eval ${_UNSET} tt_file; eval ${_UNSET} tt_grog; eval ${_UNSET} tt_i; eval ${_UNSET} tt_so_nr; eval ${_UNSET} tt_sofile; eval ${_UNSET} tt_sofiles; eval ${_UNSET} tt_sofound; eval ${_UNSET} tt_list; eval ${_UNSET} tt_tmp; eval "${return_ok}"; } # to_tmp() ############# # _do_man_so () # # Handle single .so file name for man pages. # # Local function to to_tmp(). # # Globals from to_tmp(): $tt_tmp, $tt_sofile, $tt_file # Globals: $_TMP_MAN # # Variable prefix: dms # _do_man_so() { func_check _do_man_so '=' 1 "$@"; _dms_so="$1"; # evt. with `\ ' _dms_soname="$(echo $1 | sed 's/\\[ ]/ /g')"; # without `\ ' case "${_dms_soname}" in /*) # absolute path if test -f "${_dms_soname}" then eval "${return_ok}"; fi; if test -f "${_dms_soname}"'.gz' then _dms_sofound="${_dms_soname}"'.gz'; elif test -f "${_dms_soname}"'.Z' then _dms_sofound="${_dms_soname}"'.Z'; elif test -f "${_dms_soname}"'.bz2' then _dms_sofound="${_dms_soname}"'.bz2'; else eval ${_UNSET} _dms_so; eval ${_UNSET} _dms_soname; eval "${return_ok}"; fi; ;; ### _do_man_so() of to_tmp() *) # relative to man path eval grep "'/${_dms_soname}\$'" "${_TMP_MAN}" >"${tt_tmp}"; if is_empty_file "${tt_tmp}" then eval grep "'/${_dms_soname}.gz\$'" "${_TMP_MAN}" >"${tt_tmp}"; if is_empty_file "${tt_tmp}" then eval grep "'/${_dms_soname}.Z\$'" "${_TMP_MAN}" >"${tt_tmp}"; if is_empty_file "${tt_tmp}" then eval grep "'/${_dms_soname}.bz2\$'" "${_TMP_MAN}" >"${tt_tmp}"; fi; fi; fi; if is_empty_file "${tt_tmp}" then eval "${return_ok}"; fi; _dms_done='no'; list_from_file _dms_list "${tt_tmp}"; eval set x ${_dms_list}; shift; for i do _dms_sofound="$i"; if obj _dms_sofound is_empty then continue; fi; _dms_done='yes'; break; done; ### _do_man_so() of to_tmp() if obj _dms_done is_not_yes then eval ${_UNSET} _dms_done; eval ${_UNSET} _dms_sofound; eval "${return_ok}"; fi; ;; esac; if obj _DEBUG_PRINT_FILENAMES is_yes then echo2 "file from .so: ${_dms_so}"; fi; cat_z "${_dms_sofound}" >"${tt_sofile}"; _dms_esc="$(echo ${_dms_so} | sed 's/\\/\\\\/g')"; cat "${tt_file}" | eval sed \ "'s#^\\.[ ]*so[ ]*\(${_dms_so}\|${_dms_esc}\|${_dms_soname}\)[ ]*\$'"\ "'#.so ${tt_sofile}#'" \ >"${tt_tmp}"; rm_file "${tt_file}"; mv "${tt_tmp}" "${tt_file}"; eval ${_UNSET} _dms_done; eval ${_UNSET} _dms_esc; eval ${_UNSET} _dms_so; eval ${_UNSET} _dms_sofound; eval ${_UNSET} _dms_soname; eval "${return_ok}"; } # _do_man_so() of to_tmp() ######################################################################## # to_tmp_line (...) # # Print single line with to the temporary cat file. # to_tmp_line() { func_check to_tmp_line '>=' 1 "$@"; if obj _TMP_CAT is_empty then error 'to_tmp_line(): $_TMP_CAT is not yet set'; fi; echo1 "$*" >>"${_TMP_CAT}"; eval "${return_ok}"; } # to_tmp_line() ######################################################################## # trap_set # # Call function on signal 0. # trap_set() { func_check trap_set '=' 0 "$@"; trap 'clean_up' 0 2>${_NULL_DEV} || :; eval "${return_ok}"; } # trap_set() ######################################################################## # trap_unset () # # Disable trap on signal 0. # trap_unset() { func_check trap_unset '=' 0 "$@"; trap '' 0 2>${_NULL_DEV} || :; eval "${return_ok}"; } # trap_unset() ######################################################################## # usage () # # Print usage information to standard output; for groffer option --help. # usage() { func_check usage = 0 "$@"; echo; version; cat <) # # Print warning to stderr. # warning() { echo2 "warning: $*"; } # warning() ######################################################################## # whatis_filename () # # Interpret as a man page and display its `whatis' # information as a fragment written in the groff language. # # Globals: in: $_OPT_WHATIS, $_SPECIAL_SETUP, $_SPECIAL_FILESPEC, # $_FILESPEC_ARG # # Variable prefix: wf # whatis_filename() { func_check whatis_filename = 1 "$@"; if obj _OPT_WHATIS is_not_yes then error 'whatis_filename(): $_OPT_WHATIS is not yes.'; fi; if obj _SPECIAL_SETUP is_not_yes then error \ 'whatis_filename(): setup for whatis whatis_setup() must be run first.'; fi; if obj _SPECIAL_FILESPEC is_not_yes then error 'whatis_filename(): whatis_filespec() must be run first.'; fi; wf_arg="$1"; if obj wf_arg is_not_file then error "whatis_filename(): argument is not a readable file." fi; wf_dot='^\.'"${_SPACE_SED}"'*'; ### whatis_filename() if obj _FILESPEC_ARG is_equal '-' then wf_arg='stdin'; fi; cat <) # # Output path of a program and the given arguments if in $PATH. # # Arguments : 1, can have spaces and arguments. # Output : list of 2 elements: prog name (with directory) and arguments # Return : `0' if arg1 is a program in $PATH, `1' otherwise. # # Variable prefix: wip # where_is_prog() { func_check where_is_prog '=' 1 "$@"; if is_empty "$1" then eval "${return_bad}"; fi; # Remove disturbing multiple spaces and tabs wip_1="$(echo1 "$1" | sed 's/[ ][ ]*/ /g' | \ sed 's/\(\\\)* / /g' | sed 's/^ //' | sed 's/ $//')"; wip_noarg="$(echo1 "${wip_1}" | sed 's/ -.*$//')"; exit_test; if obj wip_noarg is_empty then eval ${_UNSET} wip_1; eval ${_UNSET} wip_noarg; eval "${return_bad}"; fi; case "${wip_1}" in *\ -*) wip_args="$(echo1 "${wip_1}" | eval sed "'s#^${wip_noarg} ##'")"; exit_test; ;; *) wip_args=''; ;; esac; wip_result=''; ### where_is_prog() if test -f "${wip_noarg}" && test -x "${wip_noarg}" then list_append wip_result "${wip_noarg}" "${wip_args}"; exit_test; obj wip_result echo1; exit_test; eval ${_UNSET} wip_1; eval ${_UNSET} wip_args; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_ok}"; fi; # test whether $wip_noarg has directory, so it is not tested with $PATH case "${wip_noarg}" in */*) # now $wip_noarg (with /) is not an executable file # test name with space obj_from_output wip_name base_name "${wip_noarg}"; obj_from_output wip_dir dir_name "${wip_noarg}"; case "${wip_name}" in *\ *) wip_base="$(echo1 "${wip_name}" | sed 's/ .*$//')"; exit_test; obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}"; exit_test; ### where_is_prog() if test -f "${wip_file}" && test -x "${wip_file}" then wip_baseargs="$(echo1 "${wip_name}" | eval sed "'s#^${wip_base} ##'")"; exit_test; if obj wip_args is_empty then wip_args="${wip_baseargs}"; else wip_args="${wip_baseargs} ${wip_args}"; fi; list_append wip_result "${wip_file}" "${wip_args}"; exit_test; obj wip_result echo1; exit_test; eval ${_UNSET} wip_1; eval ${_UNSET} wip_args; eval ${_UNSET} wip_base; eval ${_UNSET} wip_baseargs; eval ${_UNSET} wip_dir; eval ${_UNSET} wip_file; eval ${_UNSET} wip_name; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_ok}"; fi; # test ${wip_file} ;; esac; # end of test name with space ### where_is_prog() eval ${_UNSET} wip_1; eval ${_UNSET} wip_args; eval ${_UNSET} wip_base; eval ${_UNSET} wip_dir; eval ${_UNSET} wip_name; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_bad}"; ;; esac; # test of $wip_noarg on path with directory # now $wip_noarg does not have a /, so it is checked with $PATH. eval set x "$(path_list "${PATH}")"; exit_test; shift; # test path with $win_noarg, evt. with spaces for d do wip_dir="$d"; obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_noarg}"; ### where_is_prog() # test $win_file on executable file if test -f "${wip_file}" && test -x "${wip_file}" then list_append wip_result "${wip_file}" "${wip_args}"; exit_test; obj wip_result echo1; exit_test; eval ${_UNSET} wip_1; eval ${_UNSET} wip_dir; eval ${_UNSET} wip_file; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_ok}"; fi; # test $win_file on executable file done; # test path with $win_prog with spaces case "${wip_noarg}" in *\ *) # test on path with base name without space wip_base="$(echo1 "${wip_noarg}" | sed 's/^\([^ ]*\) .*$/\1/')"; exit_test; for d do wip_dir="$d"; obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}"; exit_test; ### where_is_prog() # test $win_file on executable file if test -f "${wip_file}" && test -x "${wip_file}" then wip_baseargs="$(echo1 "${wip_noarg}" | sed 's/[^ ]* \(.*\)$/\1/')"; exit_test; if obj wip_args is_empty then wip_args="${wip_baseargs}"; else wip_args="${wip_args} ${wip_baseargs}"; fi; list_append wip_result "${wip_file}" "${wip_args}"; exit_test; obj wip_result echo1; exit_test; eval ${_UNSET} wip_1; eval ${_UNSET} wip_args; eval ${_UNSET} wip_base; eval ${_UNSET} wip_baseargs; eval ${_UNSET} wip_dir; eval ${_UNSET} wip_file; eval ${_UNSET} wip_name; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_ok}"; fi; # test of $wip_file on executable file done; # test path with base name without space ### where_is_prog() ;; esac; # test of $wip_noarg on space eval ${_UNSET} wip_1; eval ${_UNSET} wip_args; eval ${_UNSET} wip_base; eval ${_UNSET} wip_baseargs; eval ${_UNSET} wip_dir; eval ${_UNSET} wip_file; eval ${_UNSET} wip_name; eval ${_UNSET} wip_noarg; eval ${_UNSET} wip_result; eval "${return_bad}"; } # where_is_prog() ######################################################################## # main* Functions ######################################################################## # The main area contains the following parts: # - main_init(): initialize temporary files and set exit trap # - main_parse_MANOPT(): parse $MANOPT # - main_parse_args(): argument parsing # - main_set_mode (): determine the display mode # - main_do_fileargs(): process filespec arguments # - main_set_resources(): setup X resources # - main_display(): do the displaying # - main(): the main function that calls all main_*() ####################################################################### # main_init () # # Set exit trap and create temporary directory and some temporary files. # # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN # # Variable prefix: mi # main_init() { func_check main_init = 0 "$@"; # call clean_up() on shell termination. trap_set; # create temporary directory umask 0077; _TMP_DIR=''; for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \ "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.' do mi_dir="$d"; if obj mi_dir is_empty || obj mi_dir is_not_dir || \ obj mi_dir is_not_writable then continue; fi; case "${mi_dir}" in */) _TMP_DIR="${mi_dir}"; ;; *) _TMP_DIR="${mi_dir}"'/'; ;; esac; _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}"; if obj _TMP_DIR rm_tree then : else mi_tdir_="${_TMP_DIR}"_; mi_n=1; mi_tdir_n="${mi_tdir_}${mi_n}"; ### main_init() while obj mi_tdir_n is_existing do if obj mi_tdir_n rm_tree then # directory could not be removed mi_n="$(expr "${mi_n}" + 1)"; mi_tdir_n="${mi_tdir_}${mi_n}"; continue; fi; done; _TMP_DIR="${mi_tdir_n}"; fi; eval mkdir "${_TMP_DIR}"; if is_not_equal "$?" 0 then obj _TMP_DIR rm_tree; _TMP_DIR=''; continue; fi; if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable then # $_TMP_DIR can now be used as temporary directory break; fi; obj _TMP_DIR rm_tree; _TMP_DIR=''; continue; done; if obj _TMP_DIR is_empty then error "main_init(): \ Couldn't create a directory for storing temporary files."; fi; ### main_init() if obj _DEBUG_PRINT_TMPDIR is_yes then echo2 "temporary directory: ${_TMP_DIR}"; fi; obj_from_output _TMP_CAT tmp_create groffer_cat; obj_from_output _TMP_STDIN tmp_create groffer_input; eval ${_UNSET} mi_dir; eval ${_UNSET} mi_n; eval ${_UNSET} mi_tdir_; eval ${_UNSET} mi_tdir_n; eval "${return_ok}"; } # main_init() ######################################################################## # main_parse_MANOPT () # # Parse $MANOPT to retrieve man options, but only if it is a non-empty # string; found man arguments can be overwritten by the command line. # # Globals: # in: $MANOPT, $_OPTS_MANOPT_* # out: $_MANOPT_* # # Variable prefix: mpm # main_parse_MANOPT() { func_check main_parse_MANOPT = 0 "$@"; if obj MANOPT is_not_empty then # Delete leading and final spaces MANOPT="$(echo1 "${MANOPT}" | sed ' s/^'"${_SPACE_SED}"'*// s/'"${_SPACE_SED}"'*$// ')"; exit_test; fi; if obj MANOPT is_empty then eval "${return_ok}"; fi; mpm_list=''; # add arguments in $MANOPT by mapping them to groffer options eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")"; exit_test; shift; until test "$#" -le 0 || is_equal "$1" '--' do mpm_opt="$1"; shift; case "${mpm_opt}" in -7|--ascii) list_append mpm_list '--ascii'; ;; -a|--all) list_append mpm_list '--all'; ;; ### main_parse_MANOPT() -c|--catman) do_nothing; shift; ;; -d|--debug) do_nothing; ;; -D|--default) # undo all man options so far mpm_list=''; ;; -e|--extension) list_append mpm_list '--extension'; shift; ;; -f|--whatis) list_append mpm_list '--whatis'; shift; ;; -h|--help) do_nothing; ;; -k|--apropos) # groffer's --apropos takes an argument, but man's does not, so do_nothing; ;; -l|--local-file) do_nothing; ;; -L|--locale) list_append mpm_list '--locale' "$1"; shift; ;; ### main_parse_MANOPT() -m|--systems) list_append mpm_list '--systems' "$1"; shift; ;; -M|--manpath) list_append mpm_list '--manpath' "$1"; shift; ;; -p|--preprocessor) do_nothing; shift; ;; -P|--pager) list_append mpm_list '--pager' "$1"; shift; ;; -r|--prompt) do_nothing; shift; ;; -S|--sections) list_append mpm_list '--sections' "$1"; shift; ;; -t|--troff) do_nothing; ;; -T|--device) list_append mpm_list '-T' "$1"; shift; ;; ### main_parse_MANOPT() -u|--update) do_nothing; ;; -V|--version) do_nothing; ;; -w|--where|--location) list_append mpm_list '--location'; ;; -Z|--ditroff) do_nothing; ;; # ignore all other options esac; done; # prepend $mpm_list to the command line if obj mpm_list is_not_empty then eval set x "${mpm_list}" '"$@"'; shift; fi; eval ${_UNSET} mpm_list; eval ${_UNSET} mpm_opt; eval "${return_ok}"; } # main_parse_MANOPT() ######################################################################## # main_parse_args (*) # # Parse arguments; process options and filespec parameters. # # Arguments: pass the command line arguments unaltered. # Globals: # in: $_OPTS_* # out: $_OPT_*, $_ADDOPTS, $_FILEARGS # # Variable prefix: mpa # main_parse_args() { func_check main_parse_args '>=' 0 "$@"; obj_from_output _ALL_PARAMS list_from_cmdline_with_minus _OPTS_CMDLINE "$@"; if obj _DEBUG_PRINT_PARAMS is_yes then echo2 "parameters: ${_ALL_PARAMS}"; fi; eval set x "${_ALL_PARAMS}"; shift; # By the call of `eval', unnecessary quoting was removed. So the # positional shell parameters ($1, $2, ...) are now guaranteed to # represent an option or an argument to the previous option, if any; # then a `--' argument for separating options and # parameters; followed by the filespec parameters if any. # Note, the existence of arguments to options has already been checked. # So a check for `$#' or `--' should not be done for arguments. until test "$#" -le 0 || is_equal "$1" '--' do mpa_opt="$1"; # $mpa_opt is fed into the option handler shift; case "${mpa_opt}" in -h|--help) usage; leave; ;; -Q|--source) # output source code (`Quellcode'). _OPT_MODE='source'; ;; ### main_parse_args() -T|--device|--troff-device) # device; arg _OPT_DEVICE="$1"; _check_device_with_mode; shift; ;; -v|--version) version; leave; ;; -V) _OPT_V='yes'; ;; -Z|--ditroff|--intermediate-output) # groff intermediate output _OPT_Z='yes'; ;; -X) _OPT_MODE=X; ;; -?) # delete leading `-' mpa_optchar="$(echo1 "${mpa_opt}" | sed 's/^-//')"; exit_test; if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}" then list_append _ADDOPTS_GROFF "${mpa_opt}"; elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}" then list_append _ADDOPTS_GROFF "${mpa_opt}" "$1"; shift; ### main_parse_args() else error "main_parse_args(): Unknown option : \`$1'"; fi; ;; --all) _OPT_ALL='yes'; ;; --apropos) # run `apropos' _OPT_APROPOS='yes'; _APROPOS_SECTIONS=''; _OPT_WHATIS='no'; ;; --apropos-data) # run `apropos' for data sections _OPT_APROPOS='yes'; _APROPOS_SECTIONS='457'; _OPT_WHATIS='no'; ;; --apropos-devel) # run `apropos' for development sections _OPT_APROPOS='yes'; _APROPOS_SECTIONS='239'; _OPT_WHATIS='no'; ;; --apropos-progs) # run `apropos' for program sections _OPT_APROPOS='yes'; _APROPOS_SECTIONS='168'; _OPT_WHATIS='no'; ;; ### main_parse_args() --ascii) list_append _ADDOPTS_GROFF '-mtty-char'; if obj _OPT_MODE is_empty then _OPT_MODE='text'; fi; ;; --auto) # the default automatic mode _OPT_MODE=''; ;; --bd|--bordercolor) # border color for viewers, arg; _OPT_BD="$1"; shift; ;; --bg|--backgroud) # background color for viewers, arg; _OPT_BG="$1"; shift; ;; --bw|--borderwidth) # border width for viewers, arg; _OPT_BW="$1"; shift; ;; --debug|--debug-all|--debug-filenames|--debug-func|--debug-not-func|\ --debug-grog|--debug-keep|--debug-lm|--debug-params|--debug-shell|\ --debug-stacks|--debug-tmpdir|--debug-user) # debug is handled at the beginning :; ;; --default) # reset variables to default reset; ;; ### main_parse_args() --default-modes) # sequence of modes in auto mode; arg _OPT_DEFAULT_MODES="$1"; shift; ;; --display) # set X display, arg _OPT_DISPLAY="$1"; shift; ;; --do-nothing) _OPT_DO_NOTHING='yes'; ;; --dvi) _OPT_MODE='dvi'; ;; --dvi-viewer|--dvi-viewer-tty) # viewer program for dvi mode; arg _OPT_VIEWER_DVI="$1"; shift; ;; --extension) # the extension for man pages, arg _OPT_EXTENSION="$1"; shift; ;; ### main_parse_args() --fg|--foreground) # foreground color for viewers, arg; _OPT_FG="$1"; shift; ;; --fn|--ft|--font) # set font for viewers, arg; _OPT_FN="$1"; shift; ;; --geometry) # window geometry for viewers, arg; _OPT_GEOMETRY="$1"; shift; ;; --groff) _OPT_MODE='groff'; ;; --html|--www) # display with web browser _OPT_MODE=html; ;; --html-viewer|--www-viewer|--html-viewer-tty|--www-viewer-tty) # viewer program for html mode; arg _OPT_VIEWER_HTML="$1"; shift; ;; --iconic) # start viewers as icons _OPT_ICONIC='yes'; ;; ### main_parse_args() --locale) # set language for man pages, arg # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...) _OPT_LANG="$1"; shift; ;; --local-file) # force local files; same as `--no-man' _MAN_FORCE='no'; _MAN_ENABLE='no'; ;; --location|--where) # print file locations to stderr _DEBUG_PRINT_FILENAMES='yes'; ;; --man) # force all file params to be man pages _MAN_ENABLE='yes'; _MAN_FORCE='yes'; ;; --manpath) # specify search path for man pages, arg # arg is colon-separated list of directories _OPT_MANPATH="$1"; shift; ;; --mode) # display mode mpa_arg="$1"; shift; case "${mpa_arg}" in auto|'') # search mode automatically among default _OPT_MODE=''; ;; groff) # pass input to plain groff _OPT_MODE='groff'; ;; ### main_parse_args() html|www) # display with a web browser _OPT_MODE='html'; ;; dvi) # display with xdvi viewer _OPT_MODE='dvi'; ;; pdf) # display with PDF viewer _OPT_MODE='pdf'; ;; ps) # display with Postscript viewer _OPT_MODE='ps'; ;; text) # output on terminal _OPT_MODE='text'; ;; tty) # output on terminal _OPT_MODE='tty'; ;; X|x) # output on X roff viewer _OPT_MODE='x'; ;; ### main_parse_args() Q|source) # display source code _OPT_MODE="source"; ;; *) error "main_parse_args(): unknown mode ${mpa_arg}"; ;; esac; ;; --no-location) # disable former call to `--location' _DEBUG_PRINT_FILENAMES='no'; ;; --no-man) # disable search for man pages # the same as --local-file _MAN_FORCE='no'; _MAN_ENABLE='no'; ;; --no-special) # disable some special former calls _OPT_ALL='no' _OPT_APROPOS='no' _OPT_WHATIS='no' ;; --pager|--tty-viewer|--tty-viewer-tty) # set paging program for tty mode, arg _OPT_PAGER="$1"; shift; ;; --pdf) _OPT_MODE='pdf'; ;; ### main_parse_args() --pdf-viewer|--pdf-viewer-tty) # viewer program for pdf mode; arg _OPT_VIEWER_PDF="$1"; shift; ;; --print) # for argument test echo2 "$1"; shift; ;; --ps) _OPT_MODE='ps'; ;; --ps-viewer|--ps-viewer-tty) # viewer program for ps mode; arg _OPT_VIEWER_PS="$1"; shift; ;; ### main_parse_args() --resolution) # set resolution for X devices, arg mpa_arg="$1"; shift; case "${mpa_arg}" in 75|75dpi) mpa_dpi=75; ;; 100|100dpi) mpa_dpi=100; ;; *) error "main_parse_args(): \ only resoutions of 75 or 100 dpi are supported"; ;; esac; _OPT_RESOLUTION="${mpa_dpi}"; ;; --rv) _OPT_RV='yes'; ;; --sections) # specify sections for man pages, arg # arg is colon-separated list of section names _OPT_SECTIONS="$1"; shift; ;; --shell) # already done during the first run; so ignore the argument shift; ;; ### main_parse_args() --systems) # man pages for different OS's, arg # argument is a comma-separated list _OPT_SYSTEMS="$1"; shift; ;; --text) # text mode without pager _OPT_MODE=text; ;; --title) # title for X viewers; arg if is_not_empty "$1" then list_append _OPT_TITLE "$1"; fi; shift; ;; --to-stdout) # print mode file without display _OPT_STDOUT='yes'; ;; --tty) # tty mode, text with pager _OPT_MODE=tty; ;; --text-device|--tty-device) # device for tty mode; arg _OPT_TEXT_DEVICE="$1"; shift; ;; --whatis) _OPT_WHATIS='yes'; _OPT_APROPOS='no'; ;; --X|--x) _OPT_MODE=x; ;; ### main_parse_args() --xrm) # pass X resource string, arg; list_append _OPT_XRM "$1"; shift; ;; --x-viewer|--X-viewer|--x-viewer-tty|--X-viewer-tty) # viewer program for x mode; arg _OPT_VIEWER_X="$1"; shift; ;; *) error 'main_parse_args(): unknown option '"\`${mpa_opt}'."; ;; esac; done; shift; # remove `--' argument if obj _OPT_WHATIS is_yes then _MAN_ALL='yes'; _APROPOS_SECTIONS=''; fi; if obj _OPT_DO_NOTHING is_yes then leave; fi; ### main_parse_args() case "$_OPT_DEFAULT_MODES" in '') :; ;; *,*) obj_from_output _OPT_DEFAULT_MODES \ obj _OPT_DEFAULT_MODES list_from_split ','; ;; *) :; ;; esac; # Remaining arguments are file names (filespecs). # Save them to list $_FILEARGS if is_equal "$#" 0 then # use "-" for standard input _NO_FILESPECS='yes'; set x '-'; shift; fi; _FILEARGS=''; list_append _FILEARGS "$@"; # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;' eval ${_UNSET} mpa_arg; eval ${_UNSET} mpa_dpi; eval ${_UNSET} mpa_opt; eval ${_UNSET} mpa_optchar; eval "${return_ok}"; } # main_parse_args() # Called from main_parse_args() because double `case' is not possible. # Globals: $_OPT_DEVICE, $_OPT_MODE _check_device_with_mode() { func_check _check_device_with_mode = 0 "$@"; case "${_OPT_DEVICE}" in dvi) _OPT_MODE=dvi; eval "${return_ok}"; ;; html) _OPT_MODE=html; eval "${return_ok}"; ;; lbp|lj4) _OPT_MODE=groff; eval "${return_ok}"; ;; ps) _OPT_MODE=ps; eval "${return_ok}"; ;; ascii|cp1047|latin1|utf8) if obj _OPT_MODE is_not_equal text then _OPT_MODE=tty; # default text mode fi; eval "${return_ok}"; ;; X*) _OPT_MODE=x; eval "${return_ok}"; ;; *) # unknown device, go to groff mode _OPT_MODE=groff; eval "${return_ok}"; ;; esac; eval "${return_error}"; } # _check_device_with_mode() of main_parse_args() ######################################################################## # main_set_mode () # # Determine the display mode and the corresponding viewer program. # # Globals: # in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE # out: $_DISPLAY_MODE # # Variable prefix: msm # main_set_mode() { func_check main_set_mode = 0 "$@"; # set display if obj _OPT_DISPLAY is_not_empty then DISPLAY="${_OPT_DISPLAY}"; fi; if obj _OPT_V is_yes then list_append _ADDOPTS_GROFF '-V'; fi; if obj _OPT_Z is_yes then _DISPLAY_MODE='groff'; list_append _ADDOPTS_GROFF '-Z'; fi; if obj _OPT_MODE is_equal 'groff' then _DISPLAY_MODE='groff'; fi; if obj _DISPLAY_MODE is_equal 'groff' then eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; fi; ### main_set_mode() case "${_OPT_MODE}" in '') # automatic mode case "${_OPT_DEVICE}" in X*) if is_not_X then error_user "no X display found for device ${_OPT_DEVICE}"; fi; _DISPLAY_MODE='x'; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ascii|cp1047|latin1|utf8) if obj _DISPLAY_MODE is_not_equal 'text' then _DISPLAY_MODE='tty'; fi; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ### main_set_mode() esac; if is_not_X then _DISPLAY_MODE='tty'; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; fi; if obj _OPT_DEFAULT_MODES is_empty then msm_modes="${_DEFAULT_MODES}"; else msm_modes="${_OPT_DEFAULT_MODES}"; fi; ;; source) _DISPLAY_MODE='source'; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; text) _DISPLAY_MODE='text'; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; tty) _DISPLAY_MODE='tty'; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ### main_set_mode() html) _DISPLAY_MODE='html'; msm_modes="${_OPT_MODE}"; ;; *) # display mode was given msm_modes="${_OPT_MODE}"; ;; esac; eval set x "${msm_modes}"; shift; while is_greater_than "$#" 0 do msm_1="$1"; shift; _VIEWER_BACKGROUND='no'; case "${msm_1}" in dvi) _get_prog_args DVI; if is_not_equal "$?" 0 then continue; fi; if obj _DISPLAY_PROG is_empty then if is_equal "$#" 0 then error 'main_set_mode(): No viewer for dvi mode available.'; else continue; fi; fi; ### main_set_mode() _DISPLAY_MODE="dvi"; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; html) _get_prog_args HTML; if is_not_equal "$?" 0 then continue; fi; if obj _DISPLAY_PROG is_empty then if is_equal "$#" 0 then error 'main_set_mode(): No viewer for html mode available.'; else continue; fi; fi; ### main_set_mode() _DISPLAY_MODE=html; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; pdf) if obj _PDF_DID_NOT_WORK is_yes then if is_equal "$#" 0 then error 'main_set_mode(): pdf mode did not work.'; else continue; fi; fi; if obj _PDF_HAS_PS2PDF is_not_yes then if is_prog ps2pdf then _PDF_HAS_PS2PDF='yes'; fi; fi; if obj _PDF_HAS_GS is_not_yes then if is_prog gs then _PDF_HAS_GS='yes'; fi; fi; _get_prog_args PDF; if is_not_equal "$?" 0 then _PDF_DID_NOT_WORK='yes'; continue; fi; if obj _DISPLAY_PROG is_empty then _PDF_DID_NOT_WORK='yes'; if is_equal "$#" 0 then error 'main_set_mode(): No viewer for pdf mode available.'; else continue; fi; fi; _DISPLAY_MODE="pdf"; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ### main_set_mode() ps) _get_prog_args PS; if is_not_equal "$?" 0 then continue; fi; if obj _DISPLAY_PROG is_empty then if is_equal "$#" 0 then error 'main_set_mode(): No viewer for ps mode available.'; else continue; fi; fi; _DISPLAY_MODE="ps"; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; text) _DISPLAY_MODE='text'; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ### main_set_mode() tty) _DISPLAY_MODE='tty'; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; x) _get_prog_args x; if is_not_equal "$?" 0 then continue; fi; if obj _DISPLAY_PROG is_empty then if is_equal "$#" 0 then error 'main_set_mode(): No viewer for x mode available.'; else continue; fi; fi; _DISPLAY_MODE='x'; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; ### main_set_mode() X) _DISPLAY_MODE='X'; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; eval "${return_ok}"; ;; esac; done; eval ${_UNSET} msm_1; eval ${_UNSET} msm_modes; eval ${_UNSET} msm_viewers; error_user "No suitable display mode found."; } # main_set_mode() # _get_prog_args () # # Simplification for loop in main_set_mode(). # # Globals in/out: $_VIEWER_BACKGROUND # Globals in : $_OPT_VIEWER_, $_VIEWER__X, $_VIEWER__TTY # # Variable prefix: _gpa # _get_prog_args() { func_check _get_prog_args '=' 1 "$@"; x="$(echo1 $1 | tr [a-z] [A-Z])"; eval _gpa_opt='"${_OPT_VIEWER_'"$x"'}"'; _gpa_xlist=_VIEWER_"$x"_X; _gpa_ttylist=_VIEWER_"$x"_TTY; if obj _gpa_opt is_empty then _VIEWER_BACKGROUND='no'; if is_X then _get_first_prog "${_gpa_xlist}"; x="$?"; if is_equal "$x" 0 then _VIEWER_BACKGROUND='yes'; fi; else _get_first_prog "${_gpa_ttylist}"; x="$?"; fi; exit_test; eval ${_UNSET} _gpa_opt; eval ${_UNSET} _gpa_prog; eval ${_UNSET} _gpa_ttylist; eval ${_UNSET} _gpa_xlist; eval "${return_var} $x"; ### _get_prog_args() of main_set_mode() else # $_gpa_opt is not empty obj_from_output _gpa_prog where_is_prog "${_gpa_opt}"; if is_not_equal "$?" 0 || obj _gpa_prog is_empty then exit_test; echo2 "_get_prog_args(): '${_gpa_opt}' is not an existing program."; eval ${_UNSET} _gpa_opt; eval ${_UNSET} _gpa_prog; eval ${_UNSET} _gpa_ttylist; eval ${_UNSET} _gpa_xlist; eval "${return_bad}"; fi; exit_test; # $_gpa_prog from opt is an existing program ### _get_prog_args() of main_set_mode() if is_X then eval _check_prog_on_list ${_gpa_prog} ${_gpa_xlist}; if is_equal "$?" 0 then _VIEWER_BACKGROUND='yes'; else _VIEWER_BACKGROUND='no'; eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist}; fi; else # is not X _VIEWER_BACKGROUND='no'; eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist}; fi; # is_X fi; # test of $_gpa_opt eval ${_UNSET} _gpa_opt; eval ${_UNSET} _gpa_prog; eval ${_UNSET} _gpa_ttylist; eval ${_UNSET} _gpa_xlist; eval "${return_good}"; } # _get_prog_args() of main_set_mode() # _get_first_prog () # # Retrieve from the elements of the list in the argument the first # existing program in $PATH. # # Local function for main_set_mode(). # # Return : `1' if none found, `0' if found. # Output : none # # Variable prefix: _gfp # _get_first_prog() { func_check _get_first_prog '=' 1 "$@"; eval x='"${'"$1"'}"'; eval set x "$x"; shift; for i do _gfp_i="$i"; if obj _gfp_i is_empty then continue; fi; obj_from_output _gfp_result where_is_prog "${_gfp_i}"; if is_equal "$?" 0 && obj _gfp_result is_not_empty then exit_test; eval set x ${_gfp_result}; shift; _DISPLAY_PROG="$1"; _DISPLAY_ARGS="$2"; eval ${_UNSET} _gfp_i; eval ${_UNSET} _gfp_result; eval "${return_good}"; fi; exit_test; done; eval ${_UNSET} _gfp_i; eval ${_UNSET} _gfp_result; eval "${return_bad}"; } # _get_first_prog() of main_set_mode() # _check_prog_on_list ( ) # # Check whether the content of is in the list . # The globals are set correspondingly. # # Local function for main_set_mode(). # # Arguments: 3 # # Return : `1' if not a part of the list, `0' if found in the list. # Output : none # # Globals in : $_VIEWER__X, $_VIEWER__TTY # Globals in/out: $_DISPLAY_PROG, $_DISPLAY_ARGS # # Variable prefix: _cpol # _check_prog_on_list() { func_check _check_prog_on_list '=' 3 "$@"; _DISPLAY_PROG="$1"; _DISPLAY_ARGS="$2"; eval _cpol_3='"${'"$3"'}"'; eval set x "${_cpol_3}"; shift; eval ${_UNSET} _cpol_3; for i do _cpol_i="$i"; obj_from_output _cpol_list where_is_prog "${_cpol_i}"; if is_not_equal "$?" 0 || obj _cpol_list is_empty then exit_test; continue; fi; exit_test; _cpol_prog="$(eval set x ${_cpol_list}; shift; echo1 "$1")"; if is_not_equal "${_DISPLAY_PROG}" "${_cpol_prog}" then exit_test; continue; fi; exit_test; ### _check_prog_on_list() of main_set_mode() # equal, prog found _cpol_args="$(eval set x ${_cpol_list}; shift; echo1 "$2")"; eval ${_UNSET} _cpol_list; if obj _cpol_args is_not_empty then if obj _DISPLAY_ARGS is_empty then _DISPLAY_ARGS="${_cpol_args}"; else _DISPLAY_ARGS="${_cpol_args} ${_DISPLAY_ARGS}"; fi; fi; eval ${_UNSET} _cpol_i; eval ${_UNSET} _cpol_args; eval ${_UNSET} _cpol_prog; eval "${return_good}"; done; # for vars in list # prog was not in the list eval ${_UNSET} _cpol_i; eval ${_UNSET} _cpol_args; eval ${_UNSET} _cpol_list; eval ${_UNSET} _cpol_prog; eval "${return_bad}"; } # _check_prog_on_list() of main_set_mode() ####################################################################### # main_do_fileargs () # # Process filespec arguments. # # Globals: # in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;') # # Variable prefix: mdfa # main_do_fileargs() { func_check main_do_fileargs = 0 "$@"; special_setup; if obj _OPT_APROPOS is_yes then if obj _NO_FILESPECS is_yes then apropos_filespec; eval "${return_ok}"; fi; else if list_has _FILEARGS '-' then save_stdin; fi; fi; eval set x "${_FILEARGS}"; shift; eval ${_UNSET} _FILEARGS; ### main_do_fileargs() while is_greater_than "$#" 0 do mdfa_filespec="$1"; _FILESPEC_ARG="$1"; shift; _FILESPEC_IS_MAN='no'; _TMP_MANSPEC=''; _SPECIAL_FILESPEC='no'; case "${mdfa_filespec}" in '') continue; ;; esac; # check for file case "${mdfa_filespec}" in '-') special_filespec; if obj _OPT_APROPOS is_yes then continue; fi; register_file '-'; continue; ;; ### main_do_fileargs() */*) special_filespec; if obj _OPT_APROPOS is_yes then continue; fi; if obj mdfa_filespec is_file then obj mdfa_filespec register_file; else echo2 "The argument ${mdfa_filespec} is not a file."; fi; continue; ;; *) if obj _OPT_APROPOS is_yes then special_filespec; continue; fi; # check whether filespec is an existing file if obj _MAN_FORCE is_not_yes then if obj mdfa_filespec is_file then special_filespec; obj mdfa_filespec register_file; continue; fi; fi; ;; esac; ### main_do_fileargs() # now it must be a man page pattern if obj _MACRO_PKG is_not_empty && obj _MACRO_PKG is_not_equal '-man' then echo2 "${mdfa_filespec} is not a file, man pages are ignored "\ "due to ${_MACRO_PKG}."; continue; fi; # check for man page if obj _MAN_ENABLE is_not_yes then echo2 "The argument ${mdfa_filespec} is not a file."; continue; fi; if obj _MAN_FORCE is_yes then mdfa_errmsg='is not a man page.'; else mdfa_errmsg='is neither a file nor a man page.'; fi; ### main_do_fileargs() man_setup; _FILESPEC_IS_MAN='yes'; # test filespec with `man:...' or `...(...)' on man page mdfa_name=''; mdfa_section=''; mdfa_ext=''; mdfa_names="${mdfa_filespec}"; case "${mdfa_filespec}" in man:*) mdfa_names="${mdfa_names} "\ "$(obj mdfa_filespec echo1 | sed 's/^man://')"; ;; esac; mdfa_continue='no'; for i in ${mdfa_names} do mdfa_i=$i; if obj mdfa_i man_is_man then special_filespec; obj mdfa_i man_get; mdfa_continue='yes'; break; fi; case "${mdfa_i}" in *\(${_MAN_AUTO_SEC_CHARS}*\)) mdfa_section="$(obj mdfa_i echo1 | sed 's/^[^(]*(\(.\).*)$/\1/')"; mdfa_name="$(obj mdfa_i echo1 | sed 's/^\([^(]*\)(.*)$/\1/')"; mdfa_ext="$(obj mdfa_i echo1 | sed 's/^[^(]*(.\(.*\))$/\1/')"; if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}" then special_filespec; man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"; mdfa_continue='yes'; break; fi; ;; *.${_MAN_AUTO_SEC_CHARS}*) mdfa_name="$(obj mdfa_i echo1 | \ sed 's/^\(.*\)\.'"${_MAN_AUTO_SEC_CHARS}"'.*$/\1/')"; mdfa_section="$(obj mdfa_i echo1 | \ sed 's/^.*\.\('"${_MAN_AUTO_SEC_CHARS}"'\).*$/\1/')"; mdfa_ext="$(obj mdfa_i echo1 | \ sed 's/^.*\.'"${_MAN_AUTO_SEC_CHARS}"'\(.*\)$/\1/')"; if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}" then special_filespec; man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"; mdfa_continue='yes'; break; fi; ;; esac; done; if obj mdfa_continue is_yes then continue; fi; ### main_do_fileargs() # check on "s name", where "s" is a section with or without an extension if is_not_empty "$1" then mdfa_name="$1"; case "${mdfa_filespec}" in ${_MAN_AUTO_SEC_CHARS}) mdfa_section="${mdfa_filespec}"; mdfa_ext=''; ;; ${_MAN_AUTO_SEC_CHARS}*) mdfa_section="$(echo1 "${mdfa_filespec}" | \ sed 's/^\(.\).*$/\1/')"; mdfa_ext="$(echo1 "${mdfa_filespec}" | \ sed 's/^.\(.*\)$/\1/')"; ;; *) echo2 "${mdfa_filespec} ${mdfa_errmsg}"; continue; ;; esac; shift; if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}" then _FILESPEC_ARG="${mdfa_filespec} ${mdfa_name}"; special_filespec; man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"; continue; else echo2 "No man page for ${mdfa_name} with section ${mdfa_filespec}."; continue; fi; fi; ### main_do_fileargs() echo2 "${mdfa_filespec} ${mdfa_errmsg}"; continue; done; obj _TMP_STDIN rm_file_with_debug; eval ${_UNSET} mdfa_filespec; eval ${_UNSET} mdfa_i; eval ${_UNSET} mdfa_name; eval ${_UNSET} mdfa_names; eval "${return_ok}"; } # main_do_fileargs() ######################################################################## # main_set_resources () # # Determine options for setting X resources with $_DISPLAY_PROG. # # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME # # Variable prefix: msr # main_set_resources() { func_check main_set_resources = 0 "$@"; # $msr_prog viewer program # $msr_rl resource list for f in ${_TMP_DIR}/,man* do rm_file_with_debug $f; done; obj_from_output msr_title \ get_first_essential "${_OPT_TITLE}" "${_REG_TITLE_LIST}"; _OUTPUT_FILE_NAME=''; eval set x "${msr_title}"; shift; until is_equal "$#" 0 do msr_n="$1"; case "${msr_n}" in '') continue; ;; ,*) msr_n="$(echo1 "$1" | sed 's/^,,*//')"; exit_test; ;; esac; if obj msr_n is_empty then continue; fi; if obj _OUTPUT_FILE_NAME is_not_empty then _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"','; fi; _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}"; shift; done; # until $# is 0 ### main_set_resources() case "${_OUTPUT_FILE_NAME}" in '') _OUTPUT_FILE_NAME='-'; ;; ,*) error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma."; ;; esac; _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}"; if obj _DISPLAY_PROG is_empty then # for example, for groff mode _DISPLAY_ARGS=''; eval ${_UNSET} msr_n; eval ${_UNSET} msr_prog; eval ${_UNSET} msr_rl; eval ${_UNSET} msr_title; eval "${return_ok}"; fi; eval set x "${_DISPLAY_PROG}"; shift; obj_from_output msr_prog base_name "$1"; shift; if is_greater_than $# 0 then if obj _DISPLAY_ARGS is_empty then _DISPLAY_ARGS="$*"; else _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}"; fi; fi; ### main_set_resources() msr_rl=''; if obj _OPT_BD is_not_empty then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-bd' "${_OPT_BD}"; ;; esac; fi; if obj _OPT_BG is_not_empty then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-bg' "${_OPT_BG}"; ;; kghostview) list_append msr_rl '--bg' "${_OPT_BG}"; ;; xpdf) list_append msr_rl '-papercolor' "${_OPT_BG}"; ;; esac; fi; if obj _OPT_BW is_not_empty then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) _list_append msr_rl '-bw' "${_OPT_BW}"; ;; esac; fi; ### main_set_resources() if obj _OPT_FG is_not_empty then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-fg' "${_OPT_FG}"; ;; kghostview) list_append msr_rl '--fg' "${_OPT_FG}"; ;; esac; fi; if is_not_empty "${_OPT_FN}" then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-fn' "${_OPT_FN}"; ;; kghostview) list_append msr_rl '--fn' "${_OPT_FN}"; ;; esac; fi; if is_not_empty "${_OPT_GEOMETRY}" then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi|xpdf) list_append msr_rl '-geometry' "${_OPT_GEOMETRY}"; ;; kghostview) list_append msr_rl '--geometry' "${_OPT_GEOMETRY}"; ;; esac; fi; ### main_set_resources() if is_empty "${_OPT_RESOLUTION}" then _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}"; case "${msr_prog}" in gxditview|xditview) list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}"; ;; xpdf) case "${_DISPLAY_PROG}" in *-z*) :; ;; *) # if xpdf does not have option -z case "${_DEFAULT_RESOLUTION}" in 75) # 72dpi is '100' list_append msr_rl '-z' '104'; ;; 100) list_append msr_rl '-z' '139'; ;; esac; ;; esac; ;; esac; else case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-resolution' "${_OPT_RESOLUTION}"; ;; xpdf) case "${_DISPLAY_PROG}" in *-z*) :; ;; *) # if xpdf does not have option -z case "${_OPT_RESOLUTION}" in 75) list_append msr_rl '-z' '104'; # '100' corresponds to 72dpi ;; ### main_set_resources() 100) list_append msr_rl '-z' '139'; ;; esac; ;; esac; ;; esac; fi; if is_yes "${_OPT_ICONIC}" then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-iconic'; ;; esac; fi; if is_yes "${_OPT_RV}" then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi) list_append msr_rl '-rv'; ;; esac; fi; if is_not_empty "${_OPT_XRM}" then case "${msr_prog}" in ghostview|gv|gxditview|xditview|xdvi|xpdf) eval set x "${_OPT_XRM}"; shift; for i do list_append msr_rl '-xrm' "$i"; done; ### main_set_resources() ;; esac; fi; if is_not_empty "${msr_title}" then case "${msr_prog}" in gxditview|xditview) list_append msr_rl '-title' "${msr_title}"; ;; esac; fi; if obj _DISPLAY_ARGS is_empty then _DISPLAY_ARGS="${msr_rl}"; else _DISPLAY_ARGS="${msr_l} ${_DISPLAY_ARGS}"; fi; eval ${_UNSET} msr_n; eval ${_UNSET} msr_prog; eval ${_UNSET} msr_rl; eval ${_UNSET} msr_title; eval "${return_ok}"; } # main_set_resources ######################################################################## # main_display () # # Do the actual display of the whole thing. # # Globals: # in: $_DISPLAY_MODE, $_OPT_DEVICE, $_ADDOPTS_GROFF, # $_TMP_CAT, $_OPT_PAGER, $_MANOPT_PAGER, $_OUTPUT_FILE_NAME # # Variable prefix: md # main_display() { func_check main_display = 0 "$@"; export md_addopts; export md_groggy; export md_modefile; if obj _TMP_CAT is_empty_file then echo2 'groffer: empty input.'; clean_up; eval "${return_ok}"; fi; md_modefile="${_OUTPUT_FILE_NAME}"; # go to the temporary directory to be able to access internal data files cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1; case "${_DISPLAY_MODE}" in groff) if obj _OPT_DEVICE is_not_empty then _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}"; fi; md_groggy="$(tmp_cat | eval grog)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_opt_V; ### main_display() obj md_modefile rm_file; mv "${_TMP_CAT}" "${md_modefile}"; trap_unset; cat "${md_modefile}" | \ { trap_set; eval "${md_groggy}" "${_ADDOPTS_GROFF}"; } & ;; text|tty) case "${_OPT_DEVICE}" in '') obj_from_output md_device \ get_first_essential "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}"; ;; ascii|cp1047|latin1|utf8) md_device="${_OPT_DEVICE}"; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; ;; esac; md_addopts="${_ADDOPTS_GROFF}"; md_groggy="$(tmp_cat | grog -T${md_device})"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; if obj _DISPLAY_MODE is_equal 'text' then _do_opt_V; tmp_cat | eval "${md_groggy}" "${md_addopts}"; else # $_DISPLAY_MODE is 'tty' ### main_display() md_pager=''; for p in "${_OPT_PAGER}" "${_MANOPT_PAGER}" "${PAGER}" do if obj p is_empty then continue; fi; obj_from_output md_pager where_is_prog "$p"; if is_not_equal "$?" 0 || obj md_pager is_empty then md_pager=''; continue; fi; eval set x $md_pager; shift; case "$1" in */less) if is_empty "$2" then md_pager="$1"' -r -R'; else md_pager="$1"' -r -R '"$2"; fi; ;; ### main_display() *) if is_empty "$2" then md_pager="$1"; else md_pager="$1 $2"; fi; ;; esac; break; done; if obj md_pager is_empty then eval set x ${_VIEWER_TTY_TTY} ${_VIEWER_TTY_X} 'cat'; shift; # that is: 'less -r -R' 'more' 'pager' 'xless' 'cat' for p do if obj p is_empty then continue; fi; md_p="$p"; if is_prog "${md_p}" then md_pager="${md_p}"; break; fi; done; fi; ### main_display() if obj md_pager is_empty then error 'main_display(): no pager program found for tty mode'; fi; _do_opt_V; tmp_cat | eval "${md_groggy}" "${md_addopts}" | \ eval "${md_pager}"; fi; # $_DISPLAY_MODE clean_up; ;; # text|tty) source) tmp_cat; clean_up; ;; #### viewer modes ### main_display() dvi) case "${_OPT_DEVICE}" in ''|dvi) do_nothing; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}" ;; esac; md_modefile="${md_modefile}".dvi; md_groggy="$(tmp_cat | grog -Tdvi)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_display; ;; html) case "${_OPT_DEVICE}" in ''|html) do_nothing; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; ;; esac; md_modefile="${md_modefile}".html; md_groggy="$(tmp_cat | grog -Thtml)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_display; ;; ### main_display() pdf) case "${_OPT_DEVICE}" in ''|ps) do_nothing; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; ;; esac; md_groggy="$(tmp_cat | grog -Tps)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_display _make_pdf; ;; ps) case "${_OPT_DEVICE}" in ''|ps) do_nothing; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; ;; esac; md_modefile="${md_modefile}".ps; md_groggy="$(tmp_cat | grog -Tps)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_display; ;; ### main_display() x) case "${_OPT_DEVICE}" in X*) md_device="${_OPT_DEVICE}" ;; *) case "${_OPT_RESOLUTION}" in 100) md_device='X100'; if obj _OPT_GEOMETRY is_empty then case "${_DISPLAY_PROG}" in gxditview|xditview) # add width of 800dpi for resolution of 100dpi to the args list_append _DISPLAY_ARGS '-geometry' '800'; ;; esac; fi; ;; *) md_device='X75-12'; ;; esac esac; md_groggy="$(tmp_cat | grog -T${md_device} -Z)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; _do_display; ;; ### main_display() X) case "${_OPT_DEVICE}" in '') md_groggy="$(tmp_cat | grog -X)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; ;; X*|dvi|html|lbp|lj4|ps) # these devices work with md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; ;; *) warning "main_display(): \ wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; md_groggy="$(tmp_cat | grog -Z)"; if is_not_equal "$?" 0 then exit "${_ERROR}"; fi; echo2 "grog output: ${md_groggy}"; exit_test; ;; esac; _do_display; ;; *) error "main_display(): unknown mode \`${_DISPLAY_MODE}'"; ;; esac; eval ${_UNSET} md_addopts; eval ${_UNSET} md_device; eval ${_UNSET} md_groggy; eval ${_UNSET} md_modefile; eval ${_UNSET} md_p; eval ${_UNSET} md_pager; eval "${return_ok}"; } # main_display() ######################## # _do_display ([]) # # Perform the generation of the output and view the result. If an # argument is given interpret it as a function name that is called in # the midst (actually only for `pdf'). # # Globals: $md_modefile, $md_groggy (from main_display()) # _do_display() { func_check _do_display '>=' 0 "$@"; _do_opt_V; if obj _DISPLAY_PROG is_empty then trap_unset; { trap_set; eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}"; } & else obj md_modefile rm_file; cat "${_TMP_CAT}" | \ eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}"; if obj md_modefile is_empty_file then echo2 '_do_display(): empty output.'; clean_up; exit; fi; if is_not_empty "$1" then eval "$1"; fi; ### _do_display() of main_display() obj _TMP_CAT rm_file_with_debug; if obj _OPT_STDOUT is_yes then cat "${md_modefile}"; clean_up; exit; fi; if obj _VIEWER_BACKGROUND is_not_yes # for programs that run on tty then eval "'${_DISPLAY_PROG}'" ${_DISPLAY_ARGS} "\"${md_modefile}\""; else trap_unset; { trap_set; eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; } & fi; fi; eval "${return_ok}"; } # _do_display() of main_display() ############# # _do_opt_V () # # Check on option `-V'; if set print the corresponding output and leave. # # Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG, # $_DISPLAY_ARGS, $md_groggy, $md_modefile # # Variable prefix: _doV # _do_opt_V() { func_check _do_opt_V '=' 0 "$@"; if obj _OPT_V is_yes then _OPT_V='no'; echo1 "Parameters: ${_ALL_PARAMS}"; echo1 "Display mode: ${_DISPLAY_MODE}"; echo1 "Output file: ${md_modefile}"; echo1 "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}"; a="$(eval echo1 "'${_ADDOPTS_GROFF}'")"; exit_test; echo1 "Output of grog: ${md_groggy} $a"; _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")"; exit_test; echo1 "groff -V: ${_doV_res}" leave; fi; eval "${return_ok}"; } # _do_opt_V() of main_display() ############## # _make_pdf () # # Transform to pdf format; for pdf mode in _do_display(). # # Globals: $md_modefile (from main_display()) # # Variable prefix: _mp # _make_pdf() { func_check _make_pdf '=' 0 "$@"; _mp_psfile="${md_modefile}"; md_modefile="${md_modefile}.pdf"; obj md_modefile rm_file; if obj _PDF_HAS_PS2PDF is_yes && ps2pdf "${_mp_psfile}" "${md_modefile}"; then :; elif obj _PDF_HAS_GS is_yes && gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \ -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}"; then :; else _PDF_DID_NOT_WORK='yes'; echo2 '_make_pdf(): Could not transform into pdf format. '\ 'The Postscript mode (ps) is used instead.'; _OPT_MODE='ps'; main_set_mode; main_set_resources; main_display; exit; fi; obj _mp_psfile rm_file_with_debug; eval ${_UNSET} _mp_psfile; eval "${return_ok}"; } # _make_pdf() of main_display() ######################################################################## # main (*) # # The main function for groffer. # # Arguments: # main() { func_check main '>=' 0 "$@"; # Do not change the sequence of the following functions! landmark '13: main_init()'; main_init; landmark '14: main_parse_MANOPT()'; main_parse_MANOPT; landmark '15: main_parse_args()'; main_parse_args "$@"; landmark '16: main_set_mode()'; main_set_mode; landmark '17: main_do_fileargs()'; main_do_fileargs; landmark '18: main_set_resources()'; main_set_resources; landmark '19: main_display()'; main_display; eval "${return_ok}"; } ######################################################################## main "$@";