/contrib/groff/contrib/groffer/groffer2.sh

https://bitbucket.org/freebsd/freebsd-head/ · Shell · 5854 lines · 4370 code · 361 blank · 1123 comment · 359 complexity · 56f108a0a126ad0a9df7a8b9539c98fa MD5 · raw file

Large files are truncated click here to view the full file

  1. #! /bin/sh
  2. # groffer - display groff files
  3. # Source file position: <groff-source>/contrib/groffer/groffer2.sh
  4. # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
  5. # This file should not be run independently. It is called by
  6. # `groffer.sh' in the source or by the installed `groffer' program.
  7. # Copyright (C) 2001,2002,2003,2004,2005
  8. # Free Software Foundation, Inc.
  9. # Written by Bernd Warken
  10. # Last update: 22 August 2005
  11. # This file is part of `groffer', which is part of `groff'.
  12. # `groff' is free software; you can redistribute it and/or modify it
  13. # under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation; either version 2, or (at your option)
  15. # any later version.
  16. # `groff' is distributed in the hope that it will be useful, but
  17. # WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. # General Public License for more details.
  20. # You should have received a copy of the GNU General Public License
  21. # along with `groff'; see the files COPYING and LICENSE in the top
  22. # directory of the `groff' source. If not, write to the Free Software
  23. # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
  24. # USA.
  25. ########################################################################
  26. # Test of rudimentary shell functionality
  27. ########################################################################
  28. ########################################################################
  29. # Test of `unset'
  30. #
  31. export _UNSET;
  32. export _foo;
  33. _foo=bar;
  34. _res="$(unset _foo 2>&1)";
  35. if unset _foo >${_NULL_DEV} 2>&1 && \
  36. test _"${_res}"_ = __ && test _"${_foo}"_ = __
  37. then
  38. _UNSET='unset';
  39. eval "${_UNSET}" _foo;
  40. eval "${_UNSET}" _res;
  41. else
  42. _UNSET=':';
  43. fi;
  44. ########################################################################
  45. # Test of `test'.
  46. #
  47. if test a = a && test a != b && test -f "${_GROFFER_SH}"
  48. then
  49. :;
  50. else
  51. echo '"test" did not work.' >&2;
  52. exit "${_ERROR}";
  53. fi;
  54. ########################################################################
  55. # Test of `echo' and the `$()' construct.
  56. #
  57. if echo '' >${_NULL_DEV}
  58. then
  59. :;
  60. else
  61. echo '"echo" did not work.' >&2;
  62. exit "${_ERROR}";
  63. fi;
  64. if test _"$(t1="$(echo te)" &&
  65. t2="$(echo '')" &&
  66. t3="$(echo 'st')" &&
  67. echo "${t1}${t2}${t3}")"_ \
  68. != _test_
  69. then
  70. echo 'The "$()" construct did not work' >&2;
  71. exit "${_ERROR}";
  72. fi;
  73. ########################################################################
  74. # Test of sed program; test in groffer.sh is not valid here.
  75. #
  76. if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_
  77. then
  78. echo 'The sed program did not work.' >&2;
  79. exit "${_ERROR}";
  80. fi;
  81. ########################################################################
  82. # Test of function definitions.
  83. #
  84. _t_e_s_t_f_u_n_c_()
  85. {
  86. return 0;
  87. }
  88. if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV}
  89. then
  90. :;
  91. else
  92. echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
  93. exit "${_ERROR}";
  94. fi;
  95. ########################################################################
  96. # debug - diagnostic messages
  97. ########################################################################
  98. export _DEBUG_STACKS;
  99. _DEBUG_STACKS='no'; # disable stack output in each function
  100. #_DEBUG_STACKS='yes'; # enable stack output in each function
  101. export _DEBUG_LM;
  102. _DEBUG_LM='no'; # disable landmark messages
  103. #_DEBUG_LM='yes'; # enable landmark messages
  104. export _DEBUG_KEEP_FILES;
  105. _DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
  106. #_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
  107. export _DEBUG_PRINT_PARAMS;
  108. _DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters
  109. #_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters
  110. export _DEBUG_PRINT_SHELL;
  111. _DEBUG_PRINT_SHELL='no'; # disable printing of the shell name
  112. #_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name
  113. export _DEBUG_PRINT_TMPDIR;
  114. _DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir
  115. #_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir
  116. export _DEBUG_USER_WITH_STACK;
  117. _DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user()
  118. #_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user()
  119. # determine all --debug* options
  120. case " $*" in
  121. *\ --debug*)
  122. case " $* " in
  123. *' --debug '*)
  124. # _DEBUG_STACKS='yes';
  125. # _DEBUG_LM='yes';
  126. _DEBUG_KEEP_FILES='yes';
  127. _DEBUG_PRINT_PARAMS='yes';
  128. _DEBUG_PRINT_SHELL='yes';
  129. _DEBUG_PRINT_TMPDIR='yes';
  130. _DEBUG_USER_WITH_STACK='yes';
  131. ;;
  132. esac;
  133. d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\
  134. '--debug-stacks --debug-tmpdir --debug-user ';
  135. for i
  136. do
  137. case "$i" in
  138. --debug-s)
  139. echo 'The abbreviation --debug-s has multiple options: '\
  140. '--debug-shell and --debug-stacks.' >&2
  141. exit "${_ERROR}";
  142. ;;
  143. esac;
  144. case "$d" in
  145. *\ ${i}*)
  146. # extract whole word of abbreviation $i
  147. s="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p'
  148. $d
  149. EOF
  150. )"
  151. case "$s" in
  152. '') continue; ;;
  153. --debug-all)
  154. _DEBUG_STACKS='yes';
  155. _DEBUG_LM='yes';
  156. _DEBUG_KEEP_FILES='yes';
  157. _DEBUG_PRINT_PARAMS='yes';
  158. _DEBUG_PRINT_SHELL='yes';
  159. _DEBUG_PRINT_TMPDIR='yes';
  160. _DEBUG_USER_WITH_STACK='yes';
  161. ;;
  162. --debug-keep)
  163. _DEBUG_PRINT_TMPDIR='yes';
  164. _DEBUG_KEEP_FILES='yes';
  165. ;;
  166. --debug-lm)
  167. _DEBUG_LM='yes';
  168. ;;
  169. --debug-params)
  170. _DEBUG_PRINT_PARAMS='yes';
  171. ;;
  172. --debug-shell)
  173. _DEBUG_PRINT_SHELL='yes';
  174. ;;
  175. --debug-stacks)
  176. _DEBUG_STACKS='yes';
  177. ;;
  178. --debug-tmpdir)
  179. _DEBUG_PRINT_TMPDIR='yes';
  180. ;;
  181. --debug-user)
  182. _DEBUG_USER_WITH_STACK='yes';
  183. ;;
  184. esac;
  185. ;;
  186. esac;
  187. done
  188. ;;
  189. esac;
  190. if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
  191. then
  192. echo "parameters: $@" >&2;
  193. fi;
  194. if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
  195. then
  196. if test _"${_SHELL}"_ = __
  197. then
  198. if test _"${POSIXLY_CORRECT}"_ = _y_
  199. then
  200. echo 'shell: bash as /bin/sh (none specified)' >&2;
  201. else
  202. echo 'shell: /bin/sh (none specified)' >&2;
  203. fi;
  204. else
  205. echo "shell: ${_SHELL}" >&2;
  206. fi;
  207. fi;
  208. ########################################################################
  209. # Environment Variables
  210. ########################################################################
  211. # Environment variables that exist only for this file start with an
  212. # underscore letter. Global variables to this file are written in
  213. # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
  214. # start with an underline and use only lower case letters and
  215. # underlines, e.g. $_local_variable .
  216. # [A-Z]* system variables, e.g. $MANPATH
  217. # _[A-Z_]* global file variables, e.g. $_MAN_PATH
  218. # _[a-z_]* temporary variables, e.g. $_manpath
  219. # Due to incompatibilities of the `ash' shell, the name of loop
  220. # variables in `for' must be single character
  221. # [a-z] local loop variables, e.g. $i
  222. ########################################################################
  223. # read-only variables (global to this file)
  224. ########################################################################
  225. # function return values; `0' means ok; other values are error codes
  226. export _ALL_EXIT;
  227. export _BAD;
  228. export _GOOD;
  229. export _NO;
  230. export _OK;
  231. export _YES;
  232. _GOOD='0'; # return ok
  233. _BAD='1'; # return negatively, error code `1'
  234. # $_ERROR was already defined as `7' in groffer.sh.
  235. _NO="${_BAD}";
  236. _YES="${_GOOD}";
  237. _OK="${_GOOD}";
  238. # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
  239. export return_ok;
  240. export return_good;
  241. export return_bad;
  242. export return_yes;
  243. export return_no;
  244. export return_error;
  245. export return_var;
  246. return_ok="func_pop; return ${_OK}";
  247. return_good="func_pop; return ${_GOOD}";
  248. return_bad="func_pop; return ${_BAD}";
  249. return_yes="func_pop; return ${_YES}";
  250. return_no="func_pop; return ${_NO}";
  251. return_error="func_pop; return ${_ERROR}";
  252. return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
  253. export _DEFAULT_MODES;
  254. _DEFAULT_MODES='x,ps,tty';
  255. export _DEFAULT_RESOLUTION;
  256. _DEFAULT_RESOLUTION='75';
  257. export _DEFAULT_TTY_DEVICE;
  258. _DEFAULT_TTY_DEVICE='latin1';
  259. # _VIEWER_* viewer programs for different modes (only X is necessary)
  260. # _VIEWER_* a comma-separated list of viewer programs (with options)
  261. export _VIEWER_DVI; # viewer program for dvi mode
  262. export _VIEWER_HTML_TTY; # viewer program for html mode in tty
  263. export _VIEWER_HTML_X; # viewer program for html mode in X
  264. export _VIEWER_PDF; # viewer program for pdf mode
  265. export _VIEWER_PS; # viewer program for ps mode
  266. export _VIEWER_X; # viewer program for X mode
  267. _VIEWER_DVI='kdvi,xdvi,dvilx';
  268. _VIEWER_HTML_TTY='lynx';
  269. _VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena';
  270. _VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
  271. _VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
  272. _VIEWER_X='gxditview,xditview';
  273. # Search automatically in standard sections `1' to `8', and in the
  274. # traditional sections `9', `n', and `o'. On many systems, there
  275. # exist even more sections, mostly containing a set of man pages
  276. # special to a specific program package. These aren't searched for
  277. # automatically, but must be specified on the command line.
  278. export _MAN_AUTO_SEC_LIST;
  279. _MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
  280. export _MAN_AUTO_SEC_CHARS;
  281. _MAN_AUTO_SEC_CHARS='[123456789no]';
  282. export _SPACE_SED;
  283. _SPACE_SED='['"${_SP}${_TAB}"']';
  284. export _SPACE_CASE;
  285. _SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']';
  286. export _PROCESS_ID; # for shutting down the program
  287. _PROCESS_ID="$$";
  288. ############ the command line options of the involved programs
  289. #
  290. # The naming scheme for the options environment names is
  291. # $_OPTS_<prog>_<length>[_<argspec>]
  292. #
  293. # <prog>: program name GROFFER, GROFF, or CMDLINE (for all
  294. # command line options)
  295. # <length>: LONG (long options) or SHORT (single character options)
  296. # <argspec>: ARG for options with argument, NA for no argument;
  297. # without _<argspec> both the ones with and without arg.
  298. #
  299. # Each option that takes an argument must be specified with a
  300. # trailing : (colon).
  301. # exports
  302. export _OPTS_GROFFER_SHORT_NA;
  303. export _OPTS_GROFFER_SHORT_ARG;
  304. export _OPTS_GROFFER_LONG_NA;
  305. export _OPTS_GROFFER_LONG_ARG;
  306. export _OPTS_GROFF_SHORT_NA;
  307. export _OPTS_GROFF_SHORT_ARG;
  308. export _OPTS_GROFF_LONG_NA;
  309. export _OPTS_GROFF_LONG_ARG;
  310. export _OPTS_X_SHORT_ARG;
  311. export _OPTS_X_SHORT_NA;
  312. export _OPTS_X_LONG_ARG;
  313. export _OPTS_X_LONG_NA;
  314. export _OPTS_MAN_SHORT_ARG;
  315. export _OPTS_MAN_SHORT_NA;
  316. export _OPTS_MAN_LONG_ARG;
  317. export _OPTS_MAN_LONG_NA;
  318. export _OPTS_MANOPT_SHORT_ARG;
  319. export _OPTS_MANOPT_SHORT_NA;
  320. export _OPTS_MANOPT_LONG_ARG;
  321. export _OPTS_MANOPT_LONG_NA;
  322. export _OPTS_CMDLINE_SHORT_NA;
  323. export _OPTS_CMDLINE_SHORT_ARG;
  324. export _OPTS_CMDLINE_LONG_NA;
  325. export _OPTS_CMDLINE_LONG_ARG;
  326. ###### groffer native options
  327. _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
  328. _OPTS_GROFFER_SHORT_ARG="'T'";
  329. _OPTS_GROFFER_LONG_NA="'auto' \
  330. 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
  331. 'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \
  332. 'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \
  333. 'groff' 'help' 'intermediate-output' 'html' 'man' \
  334. 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
  335. 'text' 'text-device' \
  336. 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
  337. _OPTS_GROFFER_LONG_ARG="\
  338. 'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
  339. 'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
  340. 'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
  341. 'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
  342. 'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
  343. ##### groffer options inhereted from groff
  344. _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
  345. 'R' 's' 'S' 't' 'U' 'z'";
  346. _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
  347. 'w' 'W'";
  348. _OPTS_GROFF_LONG_NA="";
  349. _OPTS_GROFF_LONG_ARG="";
  350. ##### groffer options inhereted from the X Window toolkit
  351. _OPTS_X_SHORT_NA="";
  352. _OPTS_X_SHORT_ARG="";
  353. _OPTS_X_LONG_NA="'iconic' 'rv'";
  354. _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
  355. 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
  356. 'resolution' 'title' 'xrm'";
  357. ###### groffer options inherited from man
  358. _OPTS_MAN_SHORT_NA="";
  359. _OPTS_MAN_SHORT_ARG="";
  360. _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
  361. 'local-file' 'location' 'troff' 'update'";
  362. _OPTS_MAN_LONG_ARG="'locale' 'manpath' \
  363. 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
  364. ###### additional options for parsing $MANOPT only
  365. _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
  366. 'V' 'w' 'Z'";
  367. _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
  368. _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
  369. 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
  370. 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
  371. _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
  372. 'config_file' 'encoding' 'extension' 'locale'";
  373. ###### collections of command line options
  374. _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
  375. ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
  376. _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
  377. ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
  378. _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
  379. ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
  380. _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
  381. ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
  382. ########################################################################
  383. # read-write variables (global to this file)
  384. ########################################################################
  385. export _ALL_PARAMS; # All options and file name parameters
  386. export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
  387. export _ADDOPTS_POST; # Transp. options postproc (`eval').
  388. export _ADDOPTS_X; # Transp. options X postproc (`eval').
  389. export _APROPOS_PROG; # Program to run apropos.
  390. export _APROPOS_SECTIONS; # Sections for different --apropos-*.
  391. export _DEFAULT_MODES; # Set default modes.
  392. export _DISPLAY_MODE; # Display mode.
  393. export _DISPLAY_PROG; # Viewer program to be used for display.
  394. export _DISPLAY_ARGS; # X resources for the viewer program.
  395. export _FILEARGS; # Stores filespec parameters.
  396. export _FILESPEC_ARG; # Stores the actual filespec parameter.
  397. export _FUNC_STACK; # Store debugging information.
  398. export _REGISTERED_TITLE; # Processed file names.
  399. # _HAS_* from availability tests
  400. export _HAS_COMPRESSION; # `yes' if gzip compression is available
  401. export _HAS_BZIP; # `yes' if bzip2 compression is available
  402. # _MAN_* finally used configuration of man searching
  403. export _MAN_ALL; # search all man pages per filespec
  404. export _MAN_ENABLE; # enable search for man pages
  405. export _MAN_EXT; # extension for man pages
  406. export _MAN_FORCE; # force file parameter to be man pages
  407. export _MAN_IS_SETUP; # setup man variables only once
  408. export _MAN_LANG; # language for man pages
  409. export _MAN_LANG2; # language for man pages
  410. export _MAN_LANG_DONE; # language dirs added to man path
  411. export _MAN_PATH; # search path for man pages
  412. export _MAN_SEC; # sections for man pages; sep. `:'
  413. export _MAN_SEC_DONE; # sections added to man path
  414. export _MAN_SYS; # system names for man pages; sep. `,'
  415. export _MAN_SYS; # system names added to man path
  416. # _MANOPT_* as parsed from $MANOPT
  417. export _MANOPT_ALL; # $MANOPT --all
  418. export _MANOPT_EXTENSION; # $MANOPT --extension
  419. export _MANOPT_LANG; # $MANOPT --locale
  420. export _MANOPT_PATH; # $MANOPT --manpath
  421. export _MANOPT_PAGER; # $MANOPT --pager
  422. export _MANOPT_SEC; # $MANOPT --sections
  423. export _MANOPT_SYS; # $MANOPT --systems
  424. # _OPT_* as parsed from groffer command line
  425. export _OPT_ALL; # display all suitable man pages.
  426. export _OPT_APROPOS; # call `apropos' program.
  427. export _OPT_BD; # set border color in some modes.
  428. export _OPT_BG; # set background color in some modes.
  429. export _OPT_BW; # set border width in some modes.
  430. export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given.
  431. export _OPT_DEVICE; # device option.
  432. export _OPT_DO_NOTHING; # do nothing in main_display().
  433. export _OPT_DISPLAY; # set X display.
  434. export _OPT_FG; # set foreground color in some modes.
  435. export _OPT_FN; # set font in some modes.
  436. export _OPT_GEOMETRY; # set size and position of viewer in X.
  437. export _OPT_ICONIC; # -iconic option for X viewers.
  438. export _OPT_LANG; # set language for man pages
  439. export _OPT_LOCATION; # print processed file names to stderr
  440. export _OPT_MODE; # values: X, tty, Q, Z, ""
  441. export _OPT_MANPATH; # manual setting of path for man-pages
  442. export _OPT_PAGER; # specify paging program for tty mode
  443. export _OPT_RESOLUTION; # set X resolution in dpi
  444. export _OPT_RV; # reverse fore- and background colors.
  445. export _OPT_SECTIONS; # sections for man page search
  446. export _OPT_SYSTEMS; # man pages of different OS's
  447. export _OPT_TITLE; # title for gxditview window
  448. export _OPT_TEXT_DEVICE; # set device for tty mode.
  449. export _OPT_V; # groff option -V.
  450. export _OPT_VIEWER_DVI; # viewer program for dvi mode
  451. export _OPT_VIEWER_PDF; # viewer program for pdf mode
  452. export _OPT_VIEWER_PS; # viewer program for ps mode
  453. export _OPT_VIEWER_HTML; # viewer program for html mode
  454. export _OPT_VIEWER_X; # viewer program for x mode
  455. export _OPT_WHATIS; # print the man description
  456. export _OPT_XRM; # specify X resource.
  457. export _OPT_Z; # groff option -Z.
  458. export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
  459. export _VIEWER_TERMINAL; # viewer options for terminal (--*-viewer-tty)
  460. # _TMP_* temporary directory and files
  461. export _TMP_DIR; # groffer directory for temporary files
  462. export _TMP_CAT; # stores concatenation of everything
  463. export _TMP_STDIN; # stores stdin, if any
  464. # these variables are preset in section `Preset' after the rudim. test
  465. ########################################################################
  466. # Preset and reset of read-write global variables
  467. ########################################################################
  468. export _START_DIR; # directory at start time of the script
  469. _START_DIR="$(pwd)";
  470. # For variables that can be reset by option `--default', see reset().
  471. _FILEARGS='';
  472. # _HAS_* from availability tests
  473. _HAS_COMPRESSION='';
  474. _HAS_BZIP='';
  475. # _TMP_* temporary files
  476. _TMP_DIR='';
  477. _TMP_CAT='';
  478. _TMP_CONF='';
  479. _TMP_STDIN='';
  480. ########################################################################
  481. # reset ()
  482. #
  483. # Reset the variables that can be affected by options to their default.
  484. #
  485. reset()
  486. {
  487. if test "$#" -ne 0
  488. then
  489. error "reset() does not have arguments.";
  490. fi;
  491. _ADDOPTS_GROFF='';
  492. _ADDOPTS_POST='';
  493. _ADDOPTS_X='';
  494. _APROPOS_PROG='';
  495. _APROPOS_SECTIONS='';
  496. _DISPLAY_ARGS='';
  497. _DISPLAY_MODE='';
  498. _DISPLAY_PROG='';
  499. _REGISTERED_TITLE='';
  500. # _MAN_* finally used configuration of man searching
  501. _MAN_ALL='no';
  502. _MAN_ENABLE='yes'; # do search for man-pages
  503. _MAN_EXT='';
  504. _MAN_FORCE='no'; # first local file, then search man page
  505. _MAN_IS_SETUP='no';
  506. _MAN_LANG='';
  507. _MAN_LANG2='';
  508. _MAN_PATH='';
  509. _MAN_SEC='';
  510. _MAN_SEC_DONE='no';
  511. _MAN_SYS='';
  512. _MAN_SYS_DONE='no';
  513. # _MANOPT_* as parsed from $MANOPT
  514. _MANOPT_ALL='no';
  515. _MANOPT_EXTENSION='';
  516. _MANOPT_LANG='';
  517. _MANOPT_PATH='';
  518. _MANOPT_PAGER='';
  519. _MANOPT_SEC='';
  520. _MANOPT_SYS='';
  521. # _OPT_* as parsed from groffer command line
  522. _OPT_ALL='no';
  523. _OPT_APROPOS='no';
  524. _OPT_BD='';
  525. _OPT_BG='';
  526. _OPT_BW='';
  527. _OPT_DEFAULT_MODES='';
  528. _OPT_DEVICE='';
  529. _OPT_DISPLAY='';
  530. _OPT_DO_NOTHING='no';
  531. _OPT_FG='';
  532. _OPT_FN='';
  533. _OPT_GEOMETRY='';
  534. _OPT_ICONIC='no';
  535. _OPT_LANG='';
  536. _OPT_LOCATION='no';
  537. _OPT_MODE='';
  538. _OPT_MANPATH='';
  539. _OPT_PAGER='';
  540. _OPT_RESOLUTION='';
  541. _OPT_RV='no';
  542. _OPT_SECTIONS='';
  543. _OPT_SYSTEMS='';
  544. _OPT_TITLE='';
  545. _OPT_TEXT_DEVICE='';
  546. _OPT_V='no';
  547. _OPT_VIEWER_DVI='';
  548. _OPT_VIEWER_PDF='';
  549. _OPT_VIEWER_PS='';
  550. _OPT_VIEWER_HTML='';
  551. _OPT_VIEWER_X='';
  552. _OPT_WHATIS='no';
  553. _OPT_XRM='';
  554. _OPT_Z='no';
  555. _VIEWER_TERMINAL='no';
  556. }
  557. reset;
  558. ########################################################################
  559. # Functions for error handling and debugging
  560. ########################################################################
  561. ##############
  562. # echo1 (<text>*)
  563. #
  564. # Output to stdout.
  565. #
  566. # Arguments : arbitrary text including `-'.
  567. #
  568. echo1()
  569. {
  570. cat <<EOF
  571. $@
  572. EOF
  573. }
  574. ##############
  575. # echo2 (<text>*)
  576. #
  577. # Output to stderr.
  578. #
  579. # Arguments : arbitrary text.
  580. #
  581. echo2()
  582. {
  583. cat >&2 <<EOF
  584. $@
  585. EOF
  586. }
  587. ##############
  588. # landmark (<text>)
  589. #
  590. # Print <text> to standard error as a debugging aid.
  591. #
  592. # Globals: $_DEBUG_LM
  593. #
  594. landmark()
  595. {
  596. if test _"${_DEBUG_LM}"_ = _yes_
  597. then
  598. echo2 "LM: $*";
  599. fi;
  600. }
  601. landmark "1: debugging functions";
  602. ##############
  603. # clean_up ()
  604. #
  605. # Clean up at exit.
  606. #
  607. clean_up()
  608. {
  609. cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
  610. if test _${_DEBUG_KEEP_FILES}_ = _yes_
  611. then
  612. echo2 "Kept temporary directory ${_TMP_DIR}."
  613. else
  614. if test _"${_TMP_DIR}"_ != __
  615. then
  616. if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}"
  617. then
  618. rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
  619. fi;
  620. fi;
  621. fi;
  622. }
  623. #############
  624. # diag (text>*)
  625. #
  626. # Output a diagnostic message to stderr
  627. #
  628. diag()
  629. {
  630. echo2 '>>>>>'"$*";
  631. }
  632. #############
  633. # error (<text>*)
  634. #
  635. # Print an error message to standard error, print the function stack,
  636. # exit with an error condition. The argument should contain the name
  637. # of the function from which it was called. This is for system errors.
  638. #
  639. error()
  640. {
  641. case "$#" in
  642. 1) echo2 'groffer error: '"$1"; ;;
  643. *) echo2 'groffer error: wrong number of arguments in error().'; ;;
  644. esac;
  645. func_stack_dump;
  646. if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
  647. then
  648. : >"${_TMP_DIR}"/,error;
  649. fi;
  650. exit "${_ERROR}";
  651. }
  652. #############
  653. # error_user (<text>*)
  654. #
  655. # Print an error message to standard error; exit with an error condition.
  656. # The error is supposed to be produce by the user. So the funtion stack
  657. # is omitted.
  658. #
  659. error_user()
  660. {
  661. case "$#" in
  662. 1)
  663. echo2 'groffer error: '"$1";
  664. ;;
  665. *)
  666. echo2 'groffer error: wrong number of arguments in error_user().';
  667. ;;
  668. esac;
  669. if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
  670. then
  671. func_stack_dump;
  672. fi;
  673. if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
  674. then
  675. : >"${_TMP_DIR}"/,error;
  676. fi;
  677. exit "${_ERROR}";
  678. }
  679. #############
  680. # exit_test ()
  681. #
  682. # Test whether the former command ended with error(). Exit again.
  683. #
  684. # Globals: $_ERROR
  685. #
  686. exit_test()
  687. {
  688. if test "$?" = "${_ERROR}"
  689. then
  690. exit ${_ERROR};
  691. fi;
  692. if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error
  693. then
  694. exit ${_ERROR};
  695. fi;
  696. }
  697. #############
  698. # func_check (<func_name> <rel_op> <nr_args> "$@")
  699. #
  700. # Check number of arguments and register to _FUNC_STACK.
  701. #
  702. # Arguments: >=3
  703. # <func_name>: name of the calling function.
  704. # <rel_op>: a relational operator: = != < > <= >=
  705. # <nr_args>: number of arguments to be checked against <operator>
  706. # "$@": the arguments of the calling function.
  707. #
  708. # Variable prefix: fc
  709. #
  710. func_check()
  711. {
  712. if test "$#" -lt 3
  713. then
  714. error 'func_check() needs at least 3 arguments.';
  715. fi;
  716. fc_fname="$1";
  717. case "$3" in
  718. 1)
  719. fc_nargs="$3";
  720. fc_s='';
  721. ;;
  722. 0|[2-9])
  723. fc_nargs="$3";
  724. fc_s='s';
  725. ;;
  726. *)
  727. error "func_check(): third argument must be a digit.";
  728. ;;
  729. esac;
  730. case "$2" in
  731. '='|'-eq')
  732. fc_op='-eq';
  733. fc_comp='exactly';
  734. ;;
  735. '>='|'-ge')
  736. fc_op='-ge';
  737. fc_comp='at least';
  738. ;;
  739. '<='|'-le')
  740. fc_op='-le';
  741. fc_comp='at most';
  742. ;;
  743. '<'|'-lt')
  744. fc_op='-lt';
  745. fc_comp='less than';
  746. ;;
  747. '>'|'-gt')
  748. fc_op='-gt';
  749. fc_comp='more than';
  750. ;;
  751. '!='|'-ne')
  752. fc_op='-ne';
  753. fc_comp='not';
  754. ;;
  755. *)
  756. error \
  757. 'func_check(): second argument is not a relational operator.';
  758. ;;
  759. esac;
  760. shift;
  761. shift;
  762. shift;
  763. if test "$#" "${fc_op}" "${fc_nargs}"
  764. then
  765. do_nothing;
  766. else
  767. error "func_check(): \
  768. ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
  769. fi;
  770. func_push "${fc_fname}";
  771. if test _"${_DEBUG_STACKS}"_ = _yes_
  772. then
  773. echo2 '+++ '"${fc_fname} $@";
  774. echo2 '>>> '"${_FUNC_STACK}";
  775. fi;
  776. eval ${_UNSET} fc_comp;
  777. eval ${_UNSET} fc_fname;
  778. eval ${_UNSET} fc_nargs;
  779. eval ${_UNSET} fc_op;
  780. eval ${_UNSET} fc_s;
  781. }
  782. #############
  783. # func_pop ()
  784. #
  785. # Retrieve the top element from the stack.
  786. #
  787. # The stack elements are separated by `!'; the popped element is
  788. # identical to the original element, except that all `!' characters
  789. # were removed.
  790. #
  791. # Arguments: 1
  792. #
  793. func_pop()
  794. {
  795. if test "$#" -ne 0
  796. then
  797. error 'func_pop() does not have arguments.';
  798. fi;
  799. case "${_FUNC_STACK}" in
  800. '')
  801. if test _"${_DEBUG_STACKS}"_ = _yes_
  802. then
  803. error 'func_pop(): stack is empty.';
  804. fi;
  805. ;;
  806. *!*)
  807. # split at first bang `!'.
  808. _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
  809. exit_test;
  810. ;;
  811. *)
  812. _FUNC_STACK='';
  813. ;;
  814. esac;
  815. if test _"${_DEBUG_STACKS}"_ = _yes_
  816. then
  817. echo2 '<<< '"${_FUNC_STACK}";
  818. fi;
  819. }
  820. #############
  821. # func_push (<element>)
  822. #
  823. # Store another element to stack.
  824. #
  825. # The stack elements are separated by `!'; if <element> contains a `!'
  826. # it is removed first.
  827. #
  828. # Arguments: 1
  829. #
  830. # Variable prefix: fp
  831. #
  832. func_push()
  833. {
  834. if test "$#" -ne 1
  835. then
  836. error 'func_push() needs 1 argument.';
  837. fi;
  838. case "$1" in
  839. *'!'*)
  840. # remove all bangs `!'.
  841. fp_element="$(echo1 "$1" | sed -e 's/!//g')";
  842. exit_test;
  843. ;;
  844. *)
  845. fp_element="$1";
  846. ;;
  847. esac;
  848. if test _"${_FUNC_STACK}"_ = __
  849. then
  850. _FUNC_STACK="${fp_element}";
  851. else
  852. _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
  853. fi;
  854. eval ${_UNSET} fp_element;
  855. }
  856. #############
  857. # func_stack_dump ()
  858. #
  859. # Print the content of the stack. Ignore the arguments.
  860. #
  861. func_stack_dump()
  862. {
  863. diag 'call stack: '"${_FUNC_STACK}";
  864. }
  865. ########################################################################
  866. # System Test
  867. ########################################################################
  868. landmark "2: system test";
  869. # Test the availability of the system utilities used in this script.
  870. ########################################################################
  871. # Test of function `sed'.
  872. #
  873. if test _"$(echo xTesTx \
  874. | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
  875. | sed -e 's|T|t|g')"_ != _test_
  876. then
  877. error 'Test of "sed" command failed.';
  878. fi;
  879. ########################################################################
  880. # Test of function `cat'.
  881. #
  882. if test _"$(echo test | cat)"_ != _test_
  883. then
  884. error 'Test of "cat" command failed.';
  885. fi;
  886. ########################################################################
  887. # Test for compression.
  888. #
  889. if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
  890. then
  891. _HAS_COMPRESSION='yes';
  892. if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
  893. && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
  894. | bzip2 -d -c 2>${_NULL_DEV})"_ \
  895. = _test_
  896. then
  897. _HAS_BZIP='yes';
  898. else
  899. _HAS_BZIP='no';
  900. fi;
  901. else
  902. _HAS_COMPRESSION='no';
  903. _HAS_BZIP='no';
  904. fi;
  905. ########################################################################
  906. # Definition of normal Functions in alphabetical order
  907. ########################################################################
  908. landmark "3: functions";
  909. ########################################################################
  910. # apropos_filespec ()
  911. #
  912. # Setup for the --apropos* options
  913. #
  914. apropos_filespec()
  915. {
  916. func_check apropos_filespec '=' 0 "$@";
  917. if obj _OPT_APROPOS is_yes
  918. then
  919. eval to_tmp_line \
  920. "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
  921. exit_test;
  922. if obj _APROPOS_PROG is_empty
  923. then
  924. error 'apropos_filespec: apropos_setup() must be run first.';
  925. fi;
  926. if obj _APROPOS_SECTIONS is_empty
  927. then
  928. if obj _OPT_SECTIONS is_empty
  929. then
  930. s='^.*(.*).*$';
  931. else
  932. s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
  933. fi;
  934. else
  935. s='^.*(['"${_APROPOS_SECTIONS}"']';
  936. fi;
  937. eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
  938. sed -n -e '
  939. /^'"${_FILESPEC_ARG}"': /p
  940. /'"$s"'/p
  941. ' | \
  942. sort |\
  943. sed -e '
  944. s/^\(.* (..*)\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/
  945. ' >>"${_TMP_CAT}";
  946. fi;
  947. eval "${return_ok}";
  948. }
  949. ########################################################################
  950. # apropos_setup ()
  951. #
  952. # Setup for the --apropos* options
  953. #
  954. apropos_setup()
  955. {
  956. func_check apropos_setup '=' 0 "$@";
  957. if obj _OPT_APROPOS is_yes
  958. then
  959. if is_prog apropos
  960. then
  961. _APROPOS_PROG='apropos';
  962. elif is_prog man
  963. then
  964. if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
  965. then
  966. _APROPOS_PROG='man --apropos';
  967. elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
  968. then
  969. _APROPOS_PROG='man -k';
  970. fi;
  971. fi;
  972. if obj _APROPOS_PROG is_empty
  973. then
  974. error 'apropos_setup: no apropos program available.';
  975. fi;
  976. to_tmp_line '.TH GROFFER APROPOS';
  977. fi;
  978. eval "${return_ok}";
  979. }
  980. ########################################################################
  981. # base_name (<path>)
  982. #
  983. # Get the file name part of <path>, i.e. delete everything up to last
  984. # `/' from the beginning of <path>. Remove final slashes, too, to get a
  985. # non-empty output.
  986. #
  987. # Arguments : 1
  988. # Output : the file name part (without slashes)
  989. #
  990. # Variable prefix: bn
  991. #
  992. base_name()
  993. {
  994. func_check base_name = 1 "$@";
  995. bn_name="$1";
  996. case "${bn_name}" in
  997. */)
  998. # delete all final slashes
  999. bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
  1000. exit_test;
  1001. ;;
  1002. esac;
  1003. case "${bn_name}" in
  1004. /|'')
  1005. eval ${_UNSET} bn_name;
  1006. eval "${return_bad}";
  1007. ;;
  1008. */*)
  1009. # delete everything before and including the last slash `/'.
  1010. echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
  1011. ;;
  1012. *)
  1013. obj bn_name echo1;
  1014. ;;
  1015. esac;
  1016. eval ${_UNSET} bn_name;
  1017. eval "${return_ok}";
  1018. }
  1019. ########################################################################
  1020. # cat_z (<file>)
  1021. #
  1022. # Decompress if possible or just print <file> to standard output.
  1023. #
  1024. # gzip, bzip2, and .Z decompression is supported.
  1025. #
  1026. # Arguments: 1, a file name.
  1027. # Output: the content of <file>, possibly decompressed.
  1028. #
  1029. if test _"${_HAS_COMPRESSION}"_ = _yes_
  1030. then
  1031. cat_z()
  1032. {
  1033. func_check cat_z = 1 "$@";
  1034. case "$1" in
  1035. '')
  1036. error 'cat_z(): empty file name';
  1037. ;;
  1038. '-')
  1039. error 'cat_z(): for standard input use save_stdin()';
  1040. ;;
  1041. esac;
  1042. if obj _HAS_BZIP is_yes
  1043. then
  1044. if bzip2 -t "$1" 2>${_NULL_DEV}
  1045. then
  1046. bzip2 -c -d "$1" 2>${_NULL_DEV};
  1047. eval "${return_ok}";
  1048. fi;
  1049. fi;
  1050. gzip -c -d -f "$1" 2>${_NULL_DEV};
  1051. eval "${return_ok}";
  1052. }
  1053. else
  1054. cat_z()
  1055. {
  1056. func_check cat_z = 1 "$@";
  1057. cat "$1";
  1058. eval "${return_ok}";
  1059. }
  1060. fi;
  1061. ########################################################################
  1062. # clean_up ()
  1063. #
  1064. # Do the final cleaning up before exiting; used by the trap calls.
  1065. #
  1066. # defined above
  1067. ########################################################################
  1068. # diag (<text>*)
  1069. #
  1070. # Print marked message to standard error; useful for debugging.
  1071. #
  1072. # defined above
  1073. ########################################################################
  1074. landmark '4: dirname()*';
  1075. ########################################################################
  1076. #######################################################################
  1077. # dirname_append (<dir> <name>)
  1078. #
  1079. # Append `name' to `dir' with clean handling of `/'.
  1080. #
  1081. # Arguments : 2
  1082. # Output : the generated new directory name <dir>/<name>
  1083. #
  1084. dirname_append()
  1085. {
  1086. func_check dirname_append = 2 "$@";
  1087. if is_empty "$1"
  1088. then
  1089. error "dir_append(): first argument is empty.";
  1090. fi;
  1091. if is_empty "$2"
  1092. then
  1093. echo1 "$1";
  1094. else
  1095. dirname_chop "$1"/"$2";
  1096. fi;
  1097. eval "${return_ok}";
  1098. }
  1099. ########################################################################
  1100. # dirname_chop (<name>)
  1101. #
  1102. # Remove unnecessary slashes from directory name.
  1103. #
  1104. # Argument: 1, a directory name.
  1105. # Output: path without double, or trailing slashes.
  1106. #
  1107. # Variable prefix: dc
  1108. #
  1109. dirname_chop()
  1110. {
  1111. func_check dirname_chop = 1 "$@";
  1112. # replace all multiple slashes by a single slash `/'.
  1113. dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
  1114. exit_test;
  1115. case "${dc_res}" in
  1116. ?*/)
  1117. # remove trailing slash '/';
  1118. echo1 "${dc_res}" | sed -e 's|/$||';
  1119. ;;
  1120. *)
  1121. obj dc_res echo1
  1122. ;;
  1123. esac;
  1124. eval ${_UNSET} dc_res;
  1125. eval "${return_ok}";
  1126. }
  1127. ########################################################################
  1128. # do_filearg (<filearg>)
  1129. #
  1130. # Append the file, man-page, or standard input corresponding to the
  1131. # argument to the temporary file. If this is compressed in the gzip
  1132. # or Z format it is decompressed. A title element is generated.
  1133. #
  1134. # Argument either:
  1135. # - name of an existing file.
  1136. # - `-' to represent standard input (several times allowed).
  1137. # - `man:name.(section)' the man-page for `name' in `section'.
  1138. # - `man:name.section' the man-page for `name' in `section'.
  1139. # - `man:name' the man-page for `name' in the lowest `section'.
  1140. # - `name.section' the man-page for `name' in `section'.
  1141. # - `name' the man-page for `name' in the lowest `section'.
  1142. # Globals :
  1143. # $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
  1144. #
  1145. # Output : none
  1146. # Return : $_GOOD if found, ${_BAD} otherwise.
  1147. #
  1148. # Variable prefix: df
  1149. #
  1150. do_filearg()
  1151. {
  1152. func_check do_filearg = 1 "$@";
  1153. df_filespec="$1";
  1154. # store sequence into positional parameters
  1155. case "${df_filespec}" in
  1156. '')
  1157. eval ${_UNSET} df_filespec;
  1158. eval "${return_good}";
  1159. ;;
  1160. '-')
  1161. register_file '-';
  1162. eval ${_UNSET} df_filespec;
  1163. eval "${return_good}";
  1164. ;;
  1165. */*) # with directory part; so no man search
  1166. set 'File';
  1167. ;;
  1168. *)
  1169. if obj _MAN_ENABLE is_yes
  1170. then
  1171. if obj _MAN_FORCE is_yes
  1172. then
  1173. set 'Manpage' 'File';
  1174. else
  1175. set 'File' 'Manpage';
  1176. fi;
  1177. else
  1178. set 'File';
  1179. fi;
  1180. ;;
  1181. esac;
  1182. for i
  1183. do
  1184. case "$i" in
  1185. File)
  1186. if test -f "${df_filespec}"
  1187. then
  1188. if test -r "${df_filespec}"
  1189. then
  1190. register_file "${df_filespec}";
  1191. eval ${_UNSET} df_filespec;
  1192. eval ${_UNSET} df_no_man;
  1193. eval "${return_good}";
  1194. else
  1195. echo2 "could not read \`${df_filespec}'";
  1196. eval ${_UNSET} df_filespec;
  1197. eval ${_UNSET} df_no_man;
  1198. eval "${return_bad}";
  1199. fi;
  1200. else
  1201. if obj df_no_man is_not_empty
  1202. then
  1203. if obj _OPT_WHATIS is_yes
  1204. then
  1205. to_tmp_line "This is neither a file nor a man page."
  1206. else
  1207. echo2 "\`${df_filespec}' is neither a file nor a man page."
  1208. fi;
  1209. fi;
  1210. df_no_file=yes;
  1211. continue;
  1212. fi;
  1213. ;;
  1214. Manpage) # parse filespec as man page
  1215. if obj _MAN_IS_SETUP is_not_yes
  1216. then
  1217. man_setup;
  1218. fi;
  1219. if man_do_filespec "${df_filespec}"
  1220. then
  1221. eval ${_UNSET} df_filespec;
  1222. eval ${_UNSET} df_no_file;
  1223. eval "${return_good}";
  1224. else
  1225. if obj df_no_file is_not_empty
  1226. then
  1227. if obj _OPT_WHATIS is_yes
  1228. then
  1229. to_tmp_line "This is neither a file nor a man page."
  1230. else
  1231. echo2 "\`${df_filespec}' is neither a file nor a man page."
  1232. fi;
  1233. fi;
  1234. df_no_man=yes;
  1235. continue;
  1236. fi;
  1237. ;;
  1238. esac;
  1239. done;
  1240. eval ${_UNSET} df_filespec;
  1241. eval ${_UNSET} df_no_file;
  1242. eval ${_UNSET} df_no_man;
  1243. eval "${return_bad}";
  1244. } # do_filearg()
  1245. ########################################################################
  1246. # do_nothing ()
  1247. #
  1248. # Dummy function.
  1249. #
  1250. do_nothing()
  1251. {
  1252. eval return "${_OK}";
  1253. }
  1254. ########################################################################
  1255. # echo2 (<text>*)
  1256. #
  1257. # Print to standard error with final line break.
  1258. #
  1259. # defined above
  1260. ########################################################################
  1261. # error (<text>*)
  1262. #
  1263. # Print error message and exit with error code.
  1264. #
  1265. # defined above
  1266. ########################################################################
  1267. # exit_test ()
  1268. #
  1269. # Test whether the former command ended with error(). Exit again.
  1270. #
  1271. # defined above
  1272. ########################################################################
  1273. # func_check (<func_name> <rel_op> <nr_args> "$@")
  1274. #
  1275. # Check number of arguments and register to _FUNC_STACK.
  1276. #
  1277. # Arguments: >=3
  1278. # <func_name>: name of the calling function.
  1279. # <rel_op>: a relational operator: = != < > <= >=
  1280. # <nr_args>: number of arguments to be checked against <operator>
  1281. # "$@": the arguments of the calling function.
  1282. #
  1283. # defined above
  1284. #########################################################################
  1285. # func_pop ()
  1286. #
  1287. # Delete the top element from the function call stack.
  1288. #
  1289. # defined above
  1290. ########################################################################
  1291. # func_push (<element>)
  1292. #
  1293. # Store another element to function call stack.
  1294. #
  1295. # defined above
  1296. ########################################################################
  1297. # func_stack_dump ()
  1298. #
  1299. # Print the content of the stack.
  1300. #
  1301. # defined above
  1302. ########################################################################
  1303. # get_first_essential (<arg>*)
  1304. #
  1305. # Retrieve first non-empty argument.
  1306. #
  1307. # Return : `1' if all arguments are empty, `0' if found.
  1308. # Output : the retrieved non-empty argument.
  1309. #
  1310. # Variable prefix: gfe
  1311. #
  1312. get_first_essential()
  1313. {
  1314. func_check get_first_essential '>=' 0 "$@";
  1315. if is_equal "$#" 0
  1316. then
  1317. eval "${return_ok}";
  1318. fi;
  1319. for i
  1320. do
  1321. gfe_var="$i";
  1322. if obj gfe_var is_not_empty
  1323. then
  1324. obj gfe_var echo1;
  1325. eval ${_UNSET} gfe_var;
  1326. eval "${return_ok}";
  1327. fi;
  1328. done;
  1329. eval ${_UNSET} gfe_var;
  1330. eval "${return_bad}";
  1331. }
  1332. ########################################################################
  1333. landmark '5: is_*()';
  1334. ########################################################################
  1335. ########################################################################
  1336. # is_dir (<name>)
  1337. #
  1338. # Test whether `name' is a directory.
  1339. #
  1340. # Arguments : 1
  1341. # Return : `0' if arg1 is a directory, `1' otherwise.
  1342. #
  1343. is_dir()
  1344. {
  1345. func_check is_dir '=' 1 "$@";
  1346. if test _"$1"_ != __ && test -d "$1" && test -r "$1"
  1347. then
  1348. eval "${return_yes}";
  1349. fi;
  1350. eval "${return_no}";
  1351. }
  1352. ########################################################################
  1353. # is_empty (<string>)
  1354. #
  1355. # Test whether `string' is empty.
  1356. #
  1357. # Arguments : <=1
  1358. # Return : `0' if arg1 is empty or does not exist, `1' otherwise.
  1359. #
  1360. is_empty()
  1361. {
  1362. func_check is_empty '=' 1 "$@";
  1363. if test _"$1"_ = __
  1364. then
  1365. eval "${return_yes}";
  1366. fi;
  1367. eval "${return_no}";
  1368. }
  1369. ########################################################################
  1370. # is_equal (<string1> <string2>)
  1371. #
  1372. # Test whether `string1' is equal to <string2>.
  1373. #
  1374. # Arguments : 2
  1375. # Return : `0' both arguments are equal strings, `1' otherwise.
  1376. #
  1377. is_equal()
  1378. {
  1379. func_check is_equal '=' 2 "$@";
  1380. if test _"$1"_ = _"$2"_
  1381. then
  1382. eval "${return_yes}";
  1383. fi;
  1384. eval "${return_no}";
  1385. }
  1386. ########################################################################
  1387. # is_existing (<name>)
  1388. #
  1389. # Test whether `name' is an existing file or directory. Solaris 2.5 does
  1390. # not have `test -e'.
  1391. #
  1392. # Arguments : 1
  1393. # Return : `0' if arg1 exists, `1' otherwise.
  1394. #
  1395. is_existing()
  1396. {
  1397. func_check is_existing '=' 1 "$@";
  1398. if test _"$1"_ = __
  1399. then
  1400. eval "${return_no}";
  1401. fi;
  1402. if test -f "$1" || test -d "$1" || test -c "$1"
  1403. then
  1404. eval "${return_yes}";
  1405. fi;
  1406. eval "${return_no}";
  1407. }
  1408. ########################################################################
  1409. # is_file (<name>)
  1410. #
  1411. # Test whether `name' is a readable file.
  1412. #
  1413. # Arguments : 1
  1414. # Return : `0' if arg1 is a readable file, `1' otherwise.
  1415. #
  1416. is_file()
  1417. {
  1418. func_check is_file '=' 1 "$@";
  1419. if is_not_empty "$1" && test -f "$1" && test -r "$1"
  1420. then
  1421. eval "${return_yes}";
  1422. fi;
  1423. eval "${return_no}";
  1424. }
  1425. ########################################################################
  1426. # is_non_empty_file (<file_name>)
  1427. #
  1428. # Test whether `file_name' is a non-empty existing file.
  1429. #
  1430. # Arguments : <=1
  1431. # Return :
  1432. # `0' if arg1 is a non-empty existing file
  1433. # `1' otherwise
  1434. #
  1435. is_non_empty_file()
  1436. {
  1437. func_check is_non_empty_file '=' 1 "$@";
  1438. if is_file "$1" && test -s "$1"
  1439. then
  1440. eval "${return_yes}";
  1441. fi;
  1442. eval "${return_no}";
  1443. }
  1444. ########################################################################
  1445. # is_not_dir (<name>)
  1446. #
  1447. # Test whether `name' is not a readable directory.
  1448. #
  1449. # Arguments : 1
  1450. # Return : `0' if arg1 is a directory, `1' otherwise.
  1451. #
  1452. is_not_dir()
  1453. {
  1454. func_check is_not_dir '=' 1 "$@";
  1455. if is_dir "$1"
  1456. then
  1457. eval "${return_no}";
  1458. fi;
  1459. eval "${return_yes}";
  1460. }
  1461. ########################################################################
  1462. # is_not_empty (<string>)
  1463. #
  1464. # Test whether `string' is not empty.
  1465. #
  1466. # Arguments : <=1
  1467. # Return : `0' if arg1 exists and is not empty, `1' otherwise.
  1468. #
  1469. is_not_empty()
  1470. {
  1471. func_check is_not_empty '=' 1 "$@";
  1472. if is_empty "$1"
  1473. then
  1474. eval "${return_no}";
  1475. fi;
  1476. eval "${return_yes}";
  1477. }
  1478. ########################################################################
  1479. # is_not_equal (<string1> <string2>)
  1480. #
  1481. # Test whether `string1' differs from `string2'.
  1482. #
  1483. # Arguments : 2
  1484. #
  1485. is_not_equal()
  1486. {
  1487. func_check is_not_equal '=' 2 "$@";
  1488. if is_equal "$1" "$2"
  1489. then
  1490. eval "${return_no}";
  1491. fi
  1492. eval "${return_yes}";
  1493. }
  1494. ########################################################################
  1495. # is_not_file (<filename>)
  1496. #
  1497. # Test whether `name' is a not readable file.
  1498. #
  1499. # Arguments : 1 (empty allowed)
  1500. #
  1501. is_not_file()
  1502. {
  1503. func_check is_not_file '=' 1 "$@";
  1504. if is_file "$1"
  1505. then
  1506. eval "${return_no}";
  1507. fi;
  1508. eval "${return_yes}";
  1509. }
  1510. ########################################################################
  1511. # is_not_prog ([<name> [<arg>*]])
  1512. #
  1513. # Verify that arg is a not program in $PATH.
  1514. #
  1515. # Arguments : >=0 (empty allowed)
  1516. # more args are ignored, this allows to specify progs with arguments
  1517. #
  1518. is_not_prog()
  1519. {
  1520. func_check is_not_prog '>=' 0 "$@";
  1521. case "$#" in
  1522. 0)
  1523. eval "${return_yes}";
  1524. ;;
  1525. *)
  1526. if where_is "$1" >${_NULL_DEV}
  1527. then
  1528. eval "${return_no}";
  1529. fi;
  1530. ;;
  1531. esac
  1532. eval "${return_yes}";
  1533. }
  1534. ########################################################################
  1535. # is_not_writable (<name>)
  1536. #
  1537. # Test whether `name' is a not a writable file or directory.
  1538. #
  1539. # Arguments : >=1 (empty allowed), more args are ignored
  1540. #
  1541. is_not_writable()
  1542. {
  1543. func_check is_not_writable '>=' 1 "$@";
  1544. if is_writable "$1"
  1545. then
  1546. eval "${return_no}";
  1547. fi;
  1548. eval "${return_yes}";
  1549. }
  1550. ########################################################################
  1551. # is_not_X ()
  1552. #
  1553. # Test whether not running in X Window by checking $DISPLAY
  1554. #
  1555. is_not_X()
  1556. {
  1557. func_check is_X '=' 0 "$@";
  1558. if obj DISPLAY is_empty
  1559. then
  1560. eval "${return_yes}";
  1561. fi;
  1562. eval "${return_no}";
  1563. }
  1564. ########################################################################
  1565. # is_not_yes (<string>)
  1566. #
  1567. # Test whether `string' is not "yes".
  1568. #
  1569. # Arguments : 1
  1570. #
  1571. is_not_yes()
  1572. {
  1573. func_check is_not_yes = 1 "$@";
  1574. if is_yes "$1"
  1575. then
  1576. eval "${return_no}";
  1577. fi;
  1578. eval "${return_yes}";
  1579. }
  1580. ########################################################################
  1581. # is_prog ([<name> [<arg>*]])
  1582. #
  1583. # Determine whether <name> is a program in $PATH
  1584. #
  1585. # Arguments : >=0 (empty allowed)
  1586. # <arg>* are ignored, this allows to specify progs with arguments.
  1587. #
  1588. is_prog()
  1589. {
  1590. func_check is_prog '>=' 0 "$@";
  1591. case "$#" in
  1592. 0)
  1593. eval "${return_no}";
  1594. ;;
  1595. *)
  1596. if where_is "$1" >${_NULL_DEV}
  1597. then
  1598. eval "${return_yes}";
  1599. fi;
  1600. ;;
  1601. esac
  1602. eval "${return_no}";
  1603. }
  1604. ########################################################################
  1605. # is_writable (<name>)
  1606. #
  1607. # Test whether `name' is a writable file or directory.
  1608. #
  1609. # Arguments : >=1 (empty allowed), more args are ignored
  1610. #
  1611. is_writable()
  1612. {
  1613. func_check is_writable '>=' 1 "$@";
  1614. if test _"$1"_ = __
  1615. then
  1616. eval "${return_no}";
  1617. fi;
  1618. if test -r "$1"
  1619. then
  1620. if test -w "$1"
  1621. then
  1622. eval "${return_yes}";
  1623. fi;
  1624. fi;
  1625. eval "${return_no}";
  1626. }
  1627. ########################################################################
  1628. # is_X ()
  1629. #
  1630. # Test whether running in X Window by checking $DISPLAY
  1631. #
  1632. is_X()
  1633. {
  1634. func_check is_X '=' 0 "$@";
  1635. if obj DISPLAY is_not_empty
  1636. then
  1637. eval "${return_yes}";
  1638. fi;
  1639. eval "${return_no}";
  1640. }
  1641. ########################################################################
  1642. # is_yes (<string>)
  1643. #
  1644. # Test whether `string' has value "yes".
  1645. #
  1646. # Return : `0' if arg1 is `yes', `1' otherwise.
  1647. #
  1648. is_yes()
  1649. {
  1650. func_check is_yes '=' 1 "$@";
  1651. if is_equal "$1" 'yes'
  1652. then
  1653. eval "${return_yes}";
  1654. fi;
  1655. eval "${return_no}";
  1656. }
  1657. ########################################################################
  1658. # landmark ()
  1659. #
  1660. # Print debugging information on standard error if $_DEBUG_LM is `yes'.
  1661. #
  1662. # Globals: $_DEBUG_LM
  1663. #
  1664. # Defined in section `Debugging functions'.
  1665. ########################################################################
  1666. # leave ([<code>])
  1667. #
  1668. # Clean exit without an error or with <code>.
  1669. #
  1670. leave()
  1671. {
  1672. clean_up;
  1673. if test $# = 0
  1674. then
  1675. exit "${_OK}";
  1676. else
  1677. exit "$1";
  1678. fi;
  1679. }
  1680. ########################################################################
  1681. landmark '6: list_*()';
  1682. ########################################################################
  1683. #
  1684. # `list' is an object class that represents an array or list. Its
  1685. # data consists of space-separated single-quoted elements. So a list
  1686. # has the form "'first' 'second' '...' 'last'". See list_append() for
  1687. # more details on the list structure. The array elements of `list'
  1688. # can be get by `eval set x "$list"; shift`.
  1689. ########################################################################
  1690. # list_append (<list> <element>...)
  1691. #
  1692. # Arguments: >=2
  1693. # <list>: a variable name for a list of single-quoted elements
  1694. # <element>: some sequence of characters.
  1695. # Output: none, but $<list> is set to
  1696. # if <list> is empty: "'<element>' '...'"
  1697. # otherwise: "$list '<element>' ..."
  1698. #
  1699. # Variable prefix: la
  1700. #
  1701. list_append()
  1702. {
  1703. func_check list_append '>=' 2 "$@";
  1704. la_name="$1";
  1705. eval la_list='"${'$1'}"';
  1706. shift;
  1707. for s
  1708. do
  1709. la_s="$s";
  1710. case "${la_s}" in
  1711. *\'*)
  1712. # escape each single quote by replacing each
  1713. # "'" (squote) by "'\''" (squote bslash squote squote);
  1714. # note that the backslash must be doubled in the following `sed'
  1715. la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
  1716. exit_test;
  1717. ;;
  1718. '')
  1719. la_element="";
  1720. ;;
  1721. *)
  1722. la_element="${la_s}";
  1723. ;;
  1724. esac;
  1725. if obj la_list is_empty
  1726. then
  1727. la_list="'${la_element}'";
  1728. else
  1729. la_list="${la_list} '${la_element}'";
  1730. fi;
  1731. done;
  1732. eval "${la_name}"='"${la_list}"';
  1733. eval ${_UNSET} la_element;
  1734. eval ${_UNSET} la_list;
  1735. eval ${_UNSET} la_name;
  1736. eval ${_UNSET} la_s;
  1737. eval "${return_ok}";
  1738. }
  1739. ########################################################################
  1740. # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
  1741. #
  1742. # Transform command line arguments into a normalized form.
  1743. #
  1744. # Options, option arguments, and file parameters are identified and
  1745. # output each as a single-quoted argument of its own. Options and
  1746. # file parameters are separated by a '--' argument.
  1747. #
  1748. # Arguments: >=1
  1749. # <pre_name>: common part of a set of 4 environment variable names:
  1750. # $<pre_name>_SHORT_NA: list of short options without an arg.
  1751. # $<pre_name>_SHORT_ARG: list of short options that have an arg.
  1752. # $<pre_name>_LONG_NA: list of long options without an arg.
  1753. # $<pre_name>_LONG_ARG: list of long options that have an arg.
  1754. # <cmdline_arg>...: the arguments from a command line, such as "$@",
  1755. # the content of a variable, or direct arguments.
  1756. #
  1757. # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
  1758. #
  1759. # Example:
  1760. # list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
  1761. # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
  1762. # none-empty option lists, this will result in printing:
  1763. # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
  1764. #
  1765. # Use this function in the following way:
  1766. # eval set x "$(args_norm PRE_NAME "$@")";
  1767. # shift;
  1768. # while test "$1" != '--'; do
  1769. # case "$1" in
  1770. # ...
  1771. # esac;
  1772. # shift;
  1773. # done;
  1774. # shift; #skip '--'
  1775. # # all positional parameters ("$@") left are file name parameters.
  1776. #
  1777. # Variable prefix: lfc
  1778. #
  1779. list_from_cmdline()
  1780. {
  1781. func_check list_from_cmdline '>=' 1 "$@";
  1782. lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
  1783. lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
  1784. lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
  1785. lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
  1786. exit_test;
  1787. if obj lfc_short_n is_empty
  1788. then
  1789. error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
  1790. fi;
  1791. if obj lfc_short_a is_empty
  1792. then
  1793. error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
  1794. fi;
  1795. if obj lfc_long_n is_empty
  1796. then
  1797. error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
  1798. fi;
  1799. if obj lfc_long_a is_empty
  1800. then
  1801. error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
  1802. fi;
  1803. shift;
  1804. if is_equal "$#" 0
  1805. then
  1806. echo1 --
  1807. eval ${_UNSET} lfc_fparams;
  1808. eval ${_UNSET} lfc_short_a;
  1809. eval ${_UNSET} lfc_short_n;
  1810. eval ${_UNSET} lfc_long_a;
  1811. eval ${_UNSET} lfc_long_n;
  1812. eval ${_UNSET} lfc_result;
  1813. eval "${return_ok}";
  1814. fi;
  1815. lfc_fparams='';
  1816. lfc_result='';
  1817. while test "$#" -ge 1