diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Makefile.am | 75 | ||||
-rw-r--r-- | doc/Makefile.in | 2170 | ||||
-rw-r--r-- | doc/fdl.texi | 505 | ||||
-rw-r--r-- | doc/find-maint.info | 1585 | ||||
-rw-r--r-- | doc/find-maint.texi | 1141 | ||||
-rw-r--r-- | doc/find.info | 186 | ||||
-rw-r--r-- | doc/find.info-1 | 7261 | ||||
-rw-r--r-- | doc/find.info-2 | bin | 0 -> 11618 bytes | |||
-rw-r--r-- | doc/find.texi | 5712 | ||||
-rwxr-xr-x | doc/mdate-sh | 224 | ||||
-rw-r--r-- | doc/parse-datetime.texi | 594 | ||||
-rw-r--r-- | doc/perm.texi | 508 | ||||
-rw-r--r-- | doc/regexprops.texi | 592 | ||||
-rw-r--r-- | doc/stamp-1 | 4 | ||||
-rw-r--r-- | doc/stamp-vti | 4 | ||||
-rw-r--r-- | doc/texinfo.tex | 10174 | ||||
-rw-r--r-- | doc/version.texi | 4 | ||||
-rw-r--r-- | doc/versionmaint.texi | 4 |
18 files changed, 30743 insertions, 0 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..f6f7443 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,75 @@ +# Copyright (C) 1996,1999,2000,2001,2003-2015 Free Software Foundation, Inc. +# +# This program 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. +# +# This program 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 <http://www.gnu.org/licenses/>. +AM_CFLAGS = $(WARN_CFLAGS) + +info_TEXINFOS = find.texi find-maint.texi +find_TEXINFOS = perm.texi parse-datetime.texi regexprops.texi fdl.texi +BUILT_SOURCES = dblocation.texi +nodist_find_TEXINFOS = dblocation.texi +find_maint_TEXINFOS = fdl.texi +MOSTLYCLEANFILES = find.cps +CLEANFILES = find.txt find_mono.html findutils.texi_html_node.tar.gz dblocation.texi + +MAKEINFOTXT = $(MAKEINFO) --plaintext + +find.txt: find.texi $(srcdir)/version.texi $(find_TEXINFOS) + +# find.txt is a file which we need to know how to build +# because it gets put on the www.gnu.org website. +# This rule is derived from the .texi.html rule. +.texi.txt: + rm -rf $(@:.txt=.tmp) + if $(MAKEINFOTXT) $(AM_MAKEINFOTXTFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.txt=.tmp) $<; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.txt=.tmp) && test -d $(@:.txt=); then \ + mv $(@:.txt=) $@; else mv $(@:.txt=.tmp) $@; fi; \ + else \ + if test ! -d $(@:.txt=.tmp) && test -d $(@:.txt=); then \ + rm -rf $(@:.txt=); else rm -Rf $(@:.txt=.tmp) $@; fi; \ + exit 1; \ + fi + + +# find_mono.html is a file which we need to know how to build +# because it gets put on the www.gnu.org website. +# This rule is derived from the generic .texi.html rule. +find_mono.html: find.texi + rm -rf $(@:.html=.htp) + if $(MAKEINFOHTML) --no-split $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) $<; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ + else \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ + exit 1; \ + fi + + +# findutils.texi_html_node.tar.gz is a file which we need to know +# how to build because it gets put on the www.gnu.org website. +# This rule depends on GNU tar, but it's principally used +# by the maintainer, and we don't need to build the file +# for "make all" or "make install" (or even "make check"). +findutils.texi_html_node.tar.gz: find.html + tar zcf $@ $< + + +dblocation.texi: ../locate/dblocation.texi + $(LN_S) ../locate/dblocation.texi $@ diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..54d4e4e --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,2170 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs $(find_TEXINFOS) \ + $(top_srcdir)/build-aux/mdate-sh $(srcdir)/version.texi \ + $(srcdir)/stamp-vti $(find_maint_TEXINFOS) \ + $(srcdir)/versionmaint.texi $(srcdir)/stamp-1 \ + $(top_srcdir)/build-aux/texinfo.tex mdate-sh texinfo.tex +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/findlib.m4 \ + $(top_srcdir)/m4/mkinstalldirs.m4 $(top_srcdir)/m4/noreturn.m4 \ + $(top_srcdir)/m4/nullsort.m4 $(top_srcdir)/m4/withfts.m4 \ + $(top_srcdir)/gl/m4/00gnulib.m4 \ + $(top_srcdir)/gl/m4/absolute-header.m4 \ + $(top_srcdir)/gl/m4/alloca.m4 \ + $(top_srcdir)/gl/m4/arpa_inet_h.m4 \ + $(top_srcdir)/gl/m4/assert.m4 $(top_srcdir)/gl/m4/bison.m4 \ + $(top_srcdir)/gl/m4/btowc.m4 $(top_srcdir)/gl/m4/byteswap.m4 \ + $(top_srcdir)/gl/m4/canonicalize.m4 \ + $(top_srcdir)/gl/m4/chdir-long.m4 \ + $(top_srcdir)/gl/m4/check-math-lib.m4 \ + $(top_srcdir)/gl/m4/clock_time.m4 \ + $(top_srcdir)/gl/m4/close-stream.m4 \ + $(top_srcdir)/gl/m4/close.m4 $(top_srcdir)/gl/m4/closedir.m4 \ + $(top_srcdir)/gl/m4/closein.m4 $(top_srcdir)/gl/m4/closeout.m4 \ + $(top_srcdir)/gl/m4/codeset.m4 \ + $(top_srcdir)/gl/m4/configmake.m4 $(top_srcdir)/gl/m4/ctype.m4 \ + $(top_srcdir)/gl/m4/cycle-check.m4 \ + $(top_srcdir)/gl/m4/d-ino.m4 $(top_srcdir)/gl/m4/d-type.m4 \ + $(top_srcdir)/gl/m4/dirent-safer.m4 \ + $(top_srcdir)/gl/m4/dirent_h.m4 $(top_srcdir)/gl/m4/dirfd.m4 \ + $(top_srcdir)/gl/m4/dirname.m4 \ + $(top_srcdir)/gl/m4/double-slash-root.m4 \ + $(top_srcdir)/gl/m4/dup.m4 $(top_srcdir)/gl/m4/dup2.m4 \ + $(top_srcdir)/gl/m4/eealloc.m4 $(top_srcdir)/gl/m4/environ.m4 \ + $(top_srcdir)/gl/m4/errno_h.m4 $(top_srcdir)/gl/m4/error.m4 \ + $(top_srcdir)/gl/m4/euidaccess.m4 \ + $(top_srcdir)/gl/m4/exponentd.m4 \ + $(top_srcdir)/gl/m4/exponentf.m4 \ + $(top_srcdir)/gl/m4/exponentl.m4 \ + $(top_srcdir)/gl/m4/extensions.m4 \ + $(top_srcdir)/gl/m4/extern-inline.m4 \ + $(top_srcdir)/gl/m4/faccessat.m4 $(top_srcdir)/gl/m4/fchdir.m4 \ + $(top_srcdir)/gl/m4/fcntl-o.m4 \ + $(top_srcdir)/gl/m4/fcntl-safer.m4 \ + $(top_srcdir)/gl/m4/fcntl.m4 $(top_srcdir)/gl/m4/fcntl_h.m4 \ + $(top_srcdir)/gl/m4/fdopen.m4 $(top_srcdir)/gl/m4/fdopendir.m4 \ + $(top_srcdir)/gl/m4/fflush.m4 \ + $(top_srcdir)/gl/m4/fileblocks.m4 \ + $(top_srcdir)/gl/m4/filemode.m4 \ + $(top_srcdir)/gl/m4/filenamecat.m4 \ + $(top_srcdir)/gl/m4/flexmember.m4 \ + $(top_srcdir)/gl/m4/float_h.m4 $(top_srcdir)/gl/m4/fnmatch.m4 \ + $(top_srcdir)/gl/m4/fopen.m4 $(top_srcdir)/gl/m4/fpending.m4 \ + $(top_srcdir)/gl/m4/fpieee.m4 $(top_srcdir)/gl/m4/fpurge.m4 \ + $(top_srcdir)/gl/m4/freadahead.m4 \ + $(top_srcdir)/gl/m4/freading.m4 $(top_srcdir)/gl/m4/fseek.m4 \ + $(top_srcdir)/gl/m4/fseeko.m4 $(top_srcdir)/gl/m4/fstat.m4 \ + $(top_srcdir)/gl/m4/fstatat.m4 \ + $(top_srcdir)/gl/m4/fstypename.m4 $(top_srcdir)/gl/m4/ftell.m4 \ + $(top_srcdir)/gl/m4/ftello.m4 $(top_srcdir)/gl/m4/ftruncate.m4 \ + $(top_srcdir)/gl/m4/fts.m4 \ + $(top_srcdir)/gl/m4/getcwd-abort-bug.m4 \ + $(top_srcdir)/gl/m4/getcwd-path-max.m4 \ + $(top_srcdir)/gl/m4/getcwd.m4 $(top_srcdir)/gl/m4/getdelim.m4 \ + $(top_srcdir)/gl/m4/getdtablesize.m4 \ + $(top_srcdir)/gl/m4/getgroups.m4 \ + $(top_srcdir)/gl/m4/gethostname.m4 \ + $(top_srcdir)/gl/m4/getline.m4 $(top_srcdir)/gl/m4/getopt.m4 \ + $(top_srcdir)/gl/m4/getpagesize.m4 \ + $(top_srcdir)/gl/m4/gettext.m4 $(top_srcdir)/gl/m4/gettime.m4 \ + $(top_srcdir)/gl/m4/gettimeofday.m4 \ + $(top_srcdir)/gl/m4/glibc21.m4 \ + $(top_srcdir)/gl/m4/gnulib-common.m4 \ + $(top_srcdir)/gl/m4/gnulib-comp.m4 \ + $(top_srcdir)/gl/m4/group-member.m4 \ + $(top_srcdir)/gl/m4/human.m4 $(top_srcdir)/gl/m4/i-ring.m4 \ + $(top_srcdir)/gl/m4/iconv.m4 $(top_srcdir)/gl/m4/idcache.m4 \ + $(top_srcdir)/gl/m4/include_next.m4 \ + $(top_srcdir)/gl/m4/inet_pton.m4 $(top_srcdir)/gl/m4/inline.m4 \ + $(top_srcdir)/gl/m4/intlmacosx.m4 \ + $(top_srcdir)/gl/m4/intmax_t.m4 \ + $(top_srcdir)/gl/m4/inttostr.m4 \ + $(top_srcdir)/gl/m4/inttypes-pri.m4 \ + $(top_srcdir)/gl/m4/inttypes.m4 \ + $(top_srcdir)/gl/m4/inttypes_h.m4 $(top_srcdir)/gl/m4/ioctl.m4 \ + $(top_srcdir)/gl/m4/isblank.m4 $(top_srcdir)/gl/m4/isfinite.m4 \ + $(top_srcdir)/gl/m4/isinf.m4 $(top_srcdir)/gl/m4/isnand.m4 \ + $(top_srcdir)/gl/m4/isnanf.m4 $(top_srcdir)/gl/m4/isnanl.m4 \ + $(top_srcdir)/gl/m4/iswblank.m4 \ + $(top_srcdir)/gl/m4/langinfo_h.m4 \ + $(top_srcdir)/gl/m4/largefile.m4 \ + $(top_srcdir)/gl/m4/lcmessage.m4 $(top_srcdir)/gl/m4/lib-ld.m4 \ + $(top_srcdir)/gl/m4/lib-link.m4 \ + $(top_srcdir)/gl/m4/lib-prefix.m4 \ + $(top_srcdir)/gl/m4/libunistring-base.m4 \ + $(top_srcdir)/gl/m4/localcharset.m4 \ + $(top_srcdir)/gl/m4/locale-fr.m4 \ + $(top_srcdir)/gl/m4/locale-ja.m4 \ + $(top_srcdir)/gl/m4/locale-tr.m4 \ + $(top_srcdir)/gl/m4/locale-zh.m4 \ + $(top_srcdir)/gl/m4/locale_h.m4 \ + $(top_srcdir)/gl/m4/localeconv.m4 \ + $(top_srcdir)/gl/m4/localename.m4 $(top_srcdir)/gl/m4/lock.m4 \ + $(top_srcdir)/gl/m4/longlong.m4 \ + $(top_srcdir)/gl/m4/ls-mntd-fs.m4 $(top_srcdir)/gl/m4/lseek.m4 \ + $(top_srcdir)/gl/m4/lstat.m4 $(top_srcdir)/gl/m4/malloc.m4 \ + $(top_srcdir)/gl/m4/malloca.m4 \ + $(top_srcdir)/gl/m4/manywarnings.m4 \ + $(top_srcdir)/gl/m4/math_h.m4 $(top_srcdir)/gl/m4/mathfunc.m4 \ + $(top_srcdir)/gl/m4/mbchar.m4 $(top_srcdir)/gl/m4/mbiter.m4 \ + $(top_srcdir)/gl/m4/mbrtowc.m4 $(top_srcdir)/gl/m4/mbsinit.m4 \ + $(top_srcdir)/gl/m4/mbslen.m4 $(top_srcdir)/gl/m4/mbsrtowcs.m4 \ + $(top_srcdir)/gl/m4/mbstate_t.m4 \ + $(top_srcdir)/gl/m4/mbswidth.m4 $(top_srcdir)/gl/m4/mbtowc.m4 \ + $(top_srcdir)/gl/m4/memchr.m4 $(top_srcdir)/gl/m4/mempcpy.m4 \ + $(top_srcdir)/gl/m4/memrchr.m4 $(top_srcdir)/gl/m4/mktime.m4 \ + $(top_srcdir)/gl/m4/mmap-anon.m4 $(top_srcdir)/gl/m4/mode_t.m4 \ + $(top_srcdir)/gl/m4/modechange.m4 $(top_srcdir)/gl/m4/modf.m4 \ + $(top_srcdir)/gl/m4/mountlist.m4 \ + $(top_srcdir)/gl/m4/msvc-inval.m4 \ + $(top_srcdir)/gl/m4/msvc-nothrow.m4 \ + $(top_srcdir)/gl/m4/multiarch.m4 \ + $(top_srcdir)/gl/m4/nanosleep.m4 \ + $(top_srcdir)/gl/m4/netinet_in_h.m4 \ + $(top_srcdir)/gl/m4/nl_langinfo.m4 $(top_srcdir)/gl/m4/nls.m4 \ + $(top_srcdir)/gl/m4/nocrash.m4 $(top_srcdir)/gl/m4/off_t.m4 \ + $(top_srcdir)/gl/m4/onceonly.m4 $(top_srcdir)/gl/m4/open.m4 \ + $(top_srcdir)/gl/m4/openat.m4 $(top_srcdir)/gl/m4/opendir.m4 \ + $(top_srcdir)/gl/m4/parse-datetime.m4 \ + $(top_srcdir)/gl/m4/pathmax.m4 $(top_srcdir)/gl/m4/perror.m4 \ + $(top_srcdir)/gl/m4/pipe.m4 $(top_srcdir)/gl/m4/po.m4 \ + $(top_srcdir)/gl/m4/printf.m4 $(top_srcdir)/gl/m4/priv-set.m4 \ + $(top_srcdir)/gl/m4/progtest.m4 $(top_srcdir)/gl/m4/putenv.m4 \ + $(top_srcdir)/gl/m4/quote.m4 $(top_srcdir)/gl/m4/quotearg.m4 \ + $(top_srcdir)/gl/m4/raise.m4 $(top_srcdir)/gl/m4/read.m4 \ + $(top_srcdir)/gl/m4/readdir.m4 $(top_srcdir)/gl/m4/readlink.m4 \ + $(top_srcdir)/gl/m4/readlinkat.m4 \ + $(top_srcdir)/gl/m4/realloc.m4 $(top_srcdir)/gl/m4/regex.m4 \ + $(top_srcdir)/gl/m4/rewinddir.m4 $(top_srcdir)/gl/m4/rmdir.m4 \ + $(top_srcdir)/gl/m4/rpmatch.m4 \ + $(top_srcdir)/gl/m4/safe-read.m4 $(top_srcdir)/gl/m4/same.m4 \ + $(top_srcdir)/gl/m4/save-cwd.m4 $(top_srcdir)/gl/m4/savedir.m4 \ + $(top_srcdir)/gl/m4/select.m4 \ + $(top_srcdir)/gl/m4/selinux-context-h.m4 \ + $(top_srcdir)/gl/m4/selinux-selinux-h.m4 \ + $(top_srcdir)/gl/m4/setenv.m4 $(top_srcdir)/gl/m4/setlocale.m4 \ + $(top_srcdir)/gl/m4/sigaction.m4 \ + $(top_srcdir)/gl/m4/signal_h.m4 \ + $(top_srcdir)/gl/m4/signalblocking.m4 \ + $(top_srcdir)/gl/m4/size_max.m4 $(top_srcdir)/gl/m4/sleep.m4 \ + $(top_srcdir)/gl/m4/snprintf.m4 \ + $(top_srcdir)/gl/m4/socketlib.m4 \ + $(top_srcdir)/gl/m4/sockets.m4 $(top_srcdir)/gl/m4/socklen.m4 \ + $(top_srcdir)/gl/m4/sockpfaf.m4 $(top_srcdir)/gl/m4/ssize_t.m4 \ + $(top_srcdir)/gl/m4/st_dm_mode.m4 \ + $(top_srcdir)/gl/m4/stat-size.m4 \ + $(top_srcdir)/gl/m4/stat-time.m4 $(top_srcdir)/gl/m4/stat.m4 \ + $(top_srcdir)/gl/m4/stdalign.m4 $(top_srcdir)/gl/m4/stdarg.m4 \ + $(top_srcdir)/gl/m4/stdbool.m4 $(top_srcdir)/gl/m4/stddef_h.m4 \ + $(top_srcdir)/gl/m4/stdint.m4 $(top_srcdir)/gl/m4/stdint_h.m4 \ + $(top_srcdir)/gl/m4/stdio_h.m4 $(top_srcdir)/gl/m4/stdlib_h.m4 \ + $(top_srcdir)/gl/m4/stpcpy.m4 $(top_srcdir)/gl/m4/strcase.m4 \ + $(top_srcdir)/gl/m4/strcasestr.m4 \ + $(top_srcdir)/gl/m4/strdup.m4 $(top_srcdir)/gl/m4/strerror.m4 \ + $(top_srcdir)/gl/m4/strerror_r.m4 \ + $(top_srcdir)/gl/m4/strftime.m4 \ + $(top_srcdir)/gl/m4/string_h.m4 \ + $(top_srcdir)/gl/m4/strings_h.m4 \ + $(top_srcdir)/gl/m4/strndup.m4 $(top_srcdir)/gl/m4/strnlen.m4 \ + $(top_srcdir)/gl/m4/strstr.m4 $(top_srcdir)/gl/m4/strtoull.m4 \ + $(top_srcdir)/gl/m4/strtoumax.m4 \ + $(top_srcdir)/gl/m4/symlink.m4 \ + $(top_srcdir)/gl/m4/symlinkat.m4 \ + $(top_srcdir)/gl/m4/sys_ioctl_h.m4 \ + $(top_srcdir)/gl/m4/sys_select_h.m4 \ + $(top_srcdir)/gl/m4/sys_socket_h.m4 \ + $(top_srcdir)/gl/m4/sys_stat_h.m4 \ + $(top_srcdir)/gl/m4/sys_time_h.m4 \ + $(top_srcdir)/gl/m4/sys_types_h.m4 \ + $(top_srcdir)/gl/m4/sys_uio_h.m4 \ + $(top_srcdir)/gl/m4/sys_utsname_h.m4 \ + $(top_srcdir)/gl/m4/sys_wait_h.m4 \ + $(top_srcdir)/gl/m4/thread.m4 $(top_srcdir)/gl/m4/threadlib.m4 \ + $(top_srcdir)/gl/m4/time_h.m4 $(top_srcdir)/gl/m4/time_r.m4 \ + $(top_srcdir)/gl/m4/time_rz.m4 $(top_srcdir)/gl/m4/timegm.m4 \ + $(top_srcdir)/gl/m4/timespec.m4 \ + $(top_srcdir)/gl/m4/tm_gmtoff.m4 $(top_srcdir)/gl/m4/trunc.m4 \ + $(top_srcdir)/gl/m4/uname.m4 $(top_srcdir)/gl/m4/ungetc.m4 \ + $(top_srcdir)/gl/m4/unistd-safer.m4 \ + $(top_srcdir)/gl/m4/unistd_h.m4 $(top_srcdir)/gl/m4/unlink.m4 \ + $(top_srcdir)/gl/m4/unlinkat.m4 \ + $(top_srcdir)/gl/m4/unlinkdir.m4 \ + $(top_srcdir)/gl/m4/vasnprintf.m4 \ + $(top_srcdir)/gl/m4/version-etc.m4 \ + $(top_srcdir)/gl/m4/warn-on-use.m4 \ + $(top_srcdir)/gl/m4/warnings.m4 $(top_srcdir)/gl/m4/wchar_h.m4 \ + $(top_srcdir)/gl/m4/wchar_t.m4 $(top_srcdir)/gl/m4/wcrtomb.m4 \ + $(top_srcdir)/gl/m4/wctob.m4 $(top_srcdir)/gl/m4/wctomb.m4 \ + $(top_srcdir)/gl/m4/wctype_h.m4 $(top_srcdir)/gl/m4/wcwidth.m4 \ + $(top_srcdir)/gl/m4/wint_t.m4 $(top_srcdir)/gl/m4/xalloc.m4 \ + $(top_srcdir)/gl/m4/xgetcwd.m4 $(top_srcdir)/gl/m4/xsize.m4 \ + $(top_srcdir)/gl/m4/xstrndup.m4 $(top_srcdir)/gl/m4/xstrtod.m4 \ + $(top_srcdir)/gl/m4/xstrtol.m4 $(top_srcdir)/gl/m4/yesno.m4 \ + $(top_srcdir)/gl/m4/yield.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +AM_V_DVIPS = $(am__v_DVIPS_@AM_V@) +am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@) +am__v_DVIPS_0 = @echo " DVIPS " $@; +am__v_DVIPS_1 = +AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@) +am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@) +am__v_MAKEINFO_0 = @echo " MAKEINFO" $@; +am__v_MAKEINFO_1 = +AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@) +am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@) +am__v_INFOHTML_0 = @echo " INFOHTML" $@; +am__v_INFOHTML_1 = +AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@) +am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@) +am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@; +am__v_TEXI2DVI_1 = +AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@) +am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@) +am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@; +am__v_TEXI2PDF_1 = +AM_V_texinfo = $(am__v_texinfo_@AM_V@) +am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@) +am__v_texinfo_0 = -q +am__v_texinfo_1 = +AM_V_texidevnull = $(am__v_texidevnull_@AM_V@) +am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@) +am__v_texidevnull_0 = > /dev/null +am__v_texidevnull_1 = +INFO_DEPS = $(srcdir)/find.info $(srcdir)/find-maint.info +TEXINFO_TEX = $(top_srcdir)/build-aux/texinfo.tex +am__TEXINFO_TEX_DIR = $(top_srcdir)/build-aux +DVIS = find.dvi find-maint.dvi +PDFS = find.pdf find-maint.pdf +PSS = find.ps find-maint.ps +HTMLS = find.html find-maint.html +TEXINFOS = find.texi find-maint.texi +TEXI2DVI = texi2dvi +TEXI2PDF = $(TEXI2DVI) --pdf --batch +MAKEINFOHTML = $(MAKEINFO) --html +AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) +DVIPS = dvips +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__installdirs = "$(DESTDIR)$(infodir)" +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkglibexecdir = @pkglibexecdir@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AUXDIR = @AUXDIR@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BYTESWAP_H = @BYTESWAP_H@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONFIG_INCLUDE = @CONFIG_INCLUDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_ARG_SIZE = @DEFAULT_ARG_SIZE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXEEXT = @EXEEXT@ +FAKETIME = @FAKETIME@ +FINDLIBOBJS = @FINDLIBOBJS@ +FINDLIBS = @FINDLIBS@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +GETHOSTNAME_LIB = @GETHOSTNAME_LIB@ +GETOPT_H = @GETOPT_H@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_ACCEPT = @GNULIB_ACCEPT@ +GNULIB_ACCEPT4 = @GNULIB_ACCEPT4@ +GNULIB_ACOSF = @GNULIB_ACOSF@ +GNULIB_ACOSL = @GNULIB_ACOSL@ +GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ +GNULIB_ASINF = @GNULIB_ASINF@ +GNULIB_ASINL = @GNULIB_ASINL@ +GNULIB_ATAN2F = @GNULIB_ATAN2F@ +GNULIB_ATANF = @GNULIB_ATANF@ +GNULIB_ATANL = @GNULIB_ATANL@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_BIND = @GNULIB_BIND@ +GNULIB_BTOWC = @GNULIB_BTOWC@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CBRT = @GNULIB_CBRT@ +GNULIB_CBRTF = @GNULIB_CBRTF@ +GNULIB_CBRTL = @GNULIB_CBRTL@ +GNULIB_CEIL = @GNULIB_CEIL@ +GNULIB_CEILF = @GNULIB_CEILF@ +GNULIB_CEILL = @GNULIB_CEILL@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ +GNULIB_CONNECT = @GNULIB_CONNECT@ +GNULIB_COPYSIGN = @GNULIB_COPYSIGN@ +GNULIB_COPYSIGNF = @GNULIB_COPYSIGNF@ +GNULIB_COPYSIGNL = @GNULIB_COPYSIGNL@ +GNULIB_COSF = @GNULIB_COSF@ +GNULIB_COSHF = @GNULIB_COSHF@ +GNULIB_COSL = @GNULIB_COSL@ +GNULIB_DIRFD = @GNULIB_DIRFD@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_EXP2 = @GNULIB_EXP2@ +GNULIB_EXP2F = @GNULIB_EXP2F@ +GNULIB_EXP2L = @GNULIB_EXP2L@ +GNULIB_EXPF = @GNULIB_EXPF@ +GNULIB_EXPL = @GNULIB_EXPL@ +GNULIB_EXPM1 = @GNULIB_EXPM1@ +GNULIB_EXPM1F = @GNULIB_EXPM1F@ +GNULIB_EXPM1L = @GNULIB_EXPM1L@ +GNULIB_FABSF = @GNULIB_FABSF@ +GNULIB_FABSL = @GNULIB_FABSL@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFS = @GNULIB_FFS@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FLOOR = @GNULIB_FLOOR@ +GNULIB_FLOORF = @GNULIB_FLOORF@ +GNULIB_FLOORL = @GNULIB_FLOORL@ +GNULIB_FMA = @GNULIB_FMA@ +GNULIB_FMAF = @GNULIB_FMAF@ +GNULIB_FMAL = @GNULIB_FMAL@ +GNULIB_FMOD = @GNULIB_FMOD@ +GNULIB_FMODF = @GNULIB_FMODF@ +GNULIB_FMODL = @GNULIB_FMODL@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FREXP = @GNULIB_FREXP@ +GNULIB_FREXPF = @GNULIB_FREXPF@ +GNULIB_FREXPL = @GNULIB_FREXPL@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETPEERNAME = @GNULIB_GETPEERNAME@ +GNULIB_GETSOCKNAME = @GNULIB_GETSOCKNAME@ +GNULIB_GETSOCKOPT = @GNULIB_GETSOCKOPT@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_HYPOT = @GNULIB_HYPOT@ +GNULIB_HYPOTF = @GNULIB_HYPOTF@ +GNULIB_HYPOTL = @GNULIB_HYPOTL@ +GNULIB_ILOGB = @GNULIB_ILOGB@ +GNULIB_ILOGBF = @GNULIB_ILOGBF@ +GNULIB_ILOGBL = @GNULIB_ILOGBL@ +GNULIB_IMAXABS = @GNULIB_IMAXABS@ +GNULIB_IMAXDIV = @GNULIB_IMAXDIV@ +GNULIB_INET_NTOP = @GNULIB_INET_NTOP@ +GNULIB_INET_PTON = @GNULIB_INET_PTON@ +GNULIB_IOCTL = @GNULIB_IOCTL@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_ISBLANK = @GNULIB_ISBLANK@ +GNULIB_ISFINITE = @GNULIB_ISFINITE@ +GNULIB_ISINF = @GNULIB_ISINF@ +GNULIB_ISNAN = @GNULIB_ISNAN@ +GNULIB_ISNAND = @GNULIB_ISNAND@ +GNULIB_ISNANF = @GNULIB_ISNANF@ +GNULIB_ISNANL = @GNULIB_ISNANL@ +GNULIB_ISWBLANK = @GNULIB_ISWBLANK@ +GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LDEXPF = @GNULIB_LDEXPF@ +GNULIB_LDEXPL = @GNULIB_LDEXPL@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LISTEN = @GNULIB_LISTEN@ +GNULIB_LOCALECONV = @GNULIB_LOCALECONV@ +GNULIB_LOG = @GNULIB_LOG@ +GNULIB_LOG10 = @GNULIB_LOG10@ +GNULIB_LOG10F = @GNULIB_LOG10F@ +GNULIB_LOG10L = @GNULIB_LOG10L@ +GNULIB_LOG1P = @GNULIB_LOG1P@ +GNULIB_LOG1PF = @GNULIB_LOG1PF@ +GNULIB_LOG1PL = @GNULIB_LOG1PL@ +GNULIB_LOG2 = @GNULIB_LOG2@ +GNULIB_LOG2F = @GNULIB_LOG2F@ +GNULIB_LOG2L = @GNULIB_LOG2L@ +GNULIB_LOGB = @GNULIB_LOGB@ +GNULIB_LOGBF = @GNULIB_LOGBF@ +GNULIB_LOGBL = @GNULIB_LOGBL@ +GNULIB_LOGF = @GNULIB_LOGF@ +GNULIB_LOGL = @GNULIB_LOGL@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBRLEN = @GNULIB_MBRLEN@ +GNULIB_MBRTOWC = @GNULIB_MBRTOWC@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSINIT = @GNULIB_MBSINIT@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_MODF = @GNULIB_MODF@ +GNULIB_MODFF = @GNULIB_MODFF@ +GNULIB_MODFL = @GNULIB_MODFL@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_OPENDIR = @GNULIB_OPENDIR@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_POWF = @GNULIB_POWF@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PSELECT = @GNULIB_PSELECT@ +GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RAISE = @GNULIB_RAISE@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READDIR = @GNULIB_READDIR@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_RECV = @GNULIB_RECV@ +GNULIB_RECVFROM = @GNULIB_RECVFROM@ +GNULIB_REMAINDER = @GNULIB_REMAINDER@ +GNULIB_REMAINDERF = @GNULIB_REMAINDERF@ +GNULIB_REMAINDERL = @GNULIB_REMAINDERL@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_REWINDDIR = @GNULIB_REWINDDIR@ +GNULIB_RINT = @GNULIB_RINT@ +GNULIB_RINTF = @GNULIB_RINTF@ +GNULIB_RINTL = @GNULIB_RINTL@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_ROUND = @GNULIB_ROUND@ +GNULIB_ROUNDF = @GNULIB_ROUNDF@ +GNULIB_ROUNDL = @GNULIB_ROUNDL@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANDIR = @GNULIB_SCANDIR@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SELECT = @GNULIB_SELECT@ +GNULIB_SEND = @GNULIB_SEND@ +GNULIB_SENDTO = @GNULIB_SENDTO@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SETLOCALE = @GNULIB_SETLOCALE@ +GNULIB_SETSOCKOPT = @GNULIB_SETSOCKOPT@ +GNULIB_SHUTDOWN = @GNULIB_SHUTDOWN@ +GNULIB_SIGACTION = @GNULIB_SIGACTION@ +GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@ +GNULIB_SIGNBIT = @GNULIB_SIGNBIT@ +GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@ +GNULIB_SINF = @GNULIB_SINF@ +GNULIB_SINHF = @GNULIB_SINHF@ +GNULIB_SINL = @GNULIB_SINL@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SOCKET = @GNULIB_SOCKET@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_SQRTF = @GNULIB_SQRTF@ +GNULIB_SQRTL = @GNULIB_SQRTL@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TANF = @GNULIB_TANF@ +GNULIB_TANHF = @GNULIB_TANHF@ +GNULIB_TANL = @GNULIB_TANL@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TIME_RZ = @GNULIB_TIME_RZ@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@ +GNULIB_TRUNC = @GNULIB_TRUNC@ +GNULIB_TRUNCF = @GNULIB_TRUNCF@ +GNULIB_TRUNCL = @GNULIB_TRUNCL@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_UNAME = @GNULIB_UNAME@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WAITPID = @GNULIB_WAITPID@ +GNULIB_WCPCPY = @GNULIB_WCPCPY@ +GNULIB_WCPNCPY = @GNULIB_WCPNCPY@ +GNULIB_WCRTOMB = @GNULIB_WCRTOMB@ +GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@ +GNULIB_WCSCAT = @GNULIB_WCSCAT@ +GNULIB_WCSCHR = @GNULIB_WCSCHR@ +GNULIB_WCSCMP = @GNULIB_WCSCMP@ +GNULIB_WCSCOLL = @GNULIB_WCSCOLL@ +GNULIB_WCSCPY = @GNULIB_WCSCPY@ +GNULIB_WCSCSPN = @GNULIB_WCSCSPN@ +GNULIB_WCSDUP = @GNULIB_WCSDUP@ +GNULIB_WCSLEN = @GNULIB_WCSLEN@ +GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@ +GNULIB_WCSNCAT = @GNULIB_WCSNCAT@ +GNULIB_WCSNCMP = @GNULIB_WCSNCMP@ +GNULIB_WCSNCPY = @GNULIB_WCSNCPY@ +GNULIB_WCSNLEN = @GNULIB_WCSNLEN@ +GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@ +GNULIB_WCSPBRK = @GNULIB_WCSPBRK@ +GNULIB_WCSRCHR = @GNULIB_WCSRCHR@ +GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@ +GNULIB_WCSSPN = @GNULIB_WCSSPN@ +GNULIB_WCSSTR = @GNULIB_WCSSTR@ +GNULIB_WCSTOK = @GNULIB_WCSTOK@ +GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@ +GNULIB_WCSXFRM = @GNULIB_WCSXFRM@ +GNULIB_WCTOB = @GNULIB_WCTOB@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WCTRANS = @GNULIB_WCTRANS@ +GNULIB_WCTYPE = @GNULIB_WCTYPE@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNULIB_WMEMCHR = @GNULIB_WMEMCHR@ +GNULIB_WMEMCMP = @GNULIB_WMEMCMP@ +GNULIB_WMEMCPY = @GNULIB_WMEMCPY@ +GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@ +GNULIB_WMEMSET = @GNULIB_WMEMSET@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GREP = @GREP@ +HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ACOSF = @HAVE_ACOSF@ +HAVE_ACOSL = @HAVE_ACOSL@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ARPA_INET_H = @HAVE_ARPA_INET_H@ +HAVE_ASINF = @HAVE_ASINF@ +HAVE_ASINL = @HAVE_ASINL@ +HAVE_ATAN2F = @HAVE_ATAN2F@ +HAVE_ATANF = @HAVE_ATANF@ +HAVE_ATANL = @HAVE_ATANL@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_ATTRIBUTE_NORETURN = @HAVE_ATTRIBUTE_NORETURN@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CBRT = @HAVE_CBRT@ +HAVE_CBRTF = @HAVE_CBRTF@ +HAVE_CBRTL = @HAVE_CBRTL@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_COPYSIGN = @HAVE_COPYSIGN@ +HAVE_COPYSIGNL = @HAVE_COPYSIGNL@ +HAVE_COSF = @HAVE_COSF@ +HAVE_COSHF = @HAVE_COSHF@ +HAVE_COSL = @HAVE_COSL@ +HAVE_DECL_ACOSL = @HAVE_DECL_ACOSL@ +HAVE_DECL_ASINL = @HAVE_DECL_ASINL@ +HAVE_DECL_ATANL = @HAVE_DECL_ATANL@ +HAVE_DECL_CBRTF = @HAVE_DECL_CBRTF@ +HAVE_DECL_CBRTL = @HAVE_DECL_CBRTL@ +HAVE_DECL_CEILF = @HAVE_DECL_CEILF@ +HAVE_DECL_CEILL = @HAVE_DECL_CEILL@ +HAVE_DECL_COPYSIGNF = @HAVE_DECL_COPYSIGNF@ +HAVE_DECL_COSL = @HAVE_DECL_COSL@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_EXP2 = @HAVE_DECL_EXP2@ +HAVE_DECL_EXP2F = @HAVE_DECL_EXP2F@ +HAVE_DECL_EXP2L = @HAVE_DECL_EXP2L@ +HAVE_DECL_EXPL = @HAVE_DECL_EXPL@ +HAVE_DECL_EXPM1L = @HAVE_DECL_EXPM1L@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FLOORF = @HAVE_DECL_FLOORF@ +HAVE_DECL_FLOORL = @HAVE_DECL_FLOORL@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FREXPL = @HAVE_DECL_FREXPL@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_INET_NTOP = @HAVE_DECL_INET_NTOP@ +HAVE_DECL_INET_PTON = @HAVE_DECL_INET_PTON@ +HAVE_DECL_LDEXPL = @HAVE_DECL_LDEXPL@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_LOG10L = @HAVE_DECL_LOG10L@ +HAVE_DECL_LOG2 = @HAVE_DECL_LOG2@ +HAVE_DECL_LOG2F = @HAVE_DECL_LOG2F@ +HAVE_DECL_LOG2L = @HAVE_DECL_LOG2L@ +HAVE_DECL_LOGB = @HAVE_DECL_LOGB@ +HAVE_DECL_LOGL = @HAVE_DECL_LOGL@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_REMAINDER = @HAVE_DECL_REMAINDER@ +HAVE_DECL_REMAINDERL = @HAVE_DECL_REMAINDERL@ +HAVE_DECL_RINTF = @HAVE_DECL_RINTF@ +HAVE_DECL_ROUND = @HAVE_DECL_ROUND@ +HAVE_DECL_ROUNDF = @HAVE_DECL_ROUNDF@ +HAVE_DECL_ROUNDL = @HAVE_DECL_ROUNDL@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SINL = @HAVE_DECL_SINL@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_SQRTL = @HAVE_DECL_SQRTL@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TANL = @HAVE_DECL_TANL@ +HAVE_DECL_TRUNC = @HAVE_DECL_TRUNC@ +HAVE_DECL_TRUNCF = @HAVE_DECL_TRUNCF@ +HAVE_DECL_TRUNCL = @HAVE_DECL_TRUNCL@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_EXPF = @HAVE_EXPF@ +HAVE_EXPL = @HAVE_EXPL@ +HAVE_EXPM1 = @HAVE_EXPM1@ +HAVE_EXPM1F = @HAVE_EXPM1F@ +HAVE_FABSF = @HAVE_FABSF@ +HAVE_FABSL = @HAVE_FABSL@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFS = @HAVE_FFS@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FMA = @HAVE_FMA@ +HAVE_FMAF = @HAVE_FMAF@ +HAVE_FMAL = @HAVE_FMAL@ +HAVE_FMODF = @HAVE_FMODF@ +HAVE_FMODL = @HAVE_FMODL@ +HAVE_FREXPF = @HAVE_FREXPF@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_HYPOTF = @HAVE_HYPOTF@ +HAVE_HYPOTL = @HAVE_HYPOTL@ +HAVE_ILOGB = @HAVE_ILOGB@ +HAVE_ILOGBF = @HAVE_ILOGBF@ +HAVE_ILOGBL = @HAVE_ILOGBL@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISBLANK = @HAVE_ISBLANK@ +HAVE_ISNAND = @HAVE_ISNAND@ +HAVE_ISNANF = @HAVE_ISNANF@ +HAVE_ISNANL = @HAVE_ISNANL@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LDEXPF = @HAVE_LDEXPF@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LOG10F = @HAVE_LOG10F@ +HAVE_LOG10L = @HAVE_LOG10L@ +HAVE_LOG1P = @HAVE_LOG1P@ +HAVE_LOG1PF = @HAVE_LOG1PF@ +HAVE_LOG1PL = @HAVE_LOG1PL@ +HAVE_LOGBF = @HAVE_LOGBF@ +HAVE_LOGBL = @HAVE_LOGBL@ +HAVE_LOGF = @HAVE_LOGF@ +HAVE_LOGL = @HAVE_LOGL@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MEMCHR = @HAVE_MEMCHR@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MODFF = @HAVE_MODFF@ +HAVE_MODFL = @HAVE_MODFL@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_POWF = @HAVE_POWF@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_REMAINDER = @HAVE_REMAINDER@ +HAVE_REMAINDERF = @HAVE_REMAINDERF@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RINT = @HAVE_RINT@ +HAVE_RINTL = @HAVE_RINTL@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = @HAVE_SAME_LONG_DOUBLE_AS_DOUBLE@ +HAVE_SA_FAMILY_T = @HAVE_SA_FAMILY_T@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SINF = @HAVE_SINF@ +HAVE_SINHF = @HAVE_SINHF@ +HAVE_SINL = @HAVE_SINL@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_SQRTF = @HAVE_SQRTF@ +HAVE_SQRTL = @HAVE_SQRTL@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRINGS_H = @HAVE_STRINGS_H@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_SOCKADDR_STORAGE = @HAVE_STRUCT_SOCKADDR_STORAGE@ +HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = @HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRUCT_UTSNAME = @HAVE_STRUCT_UTSNAME@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_IOCTL_H = @HAVE_SYS_IOCTL_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_SYS_UIO_H = @HAVE_SYS_UIO_H@ +HAVE_SYS_UTSNAME_H = @HAVE_SYS_UTSNAME_H@ +HAVE_TANF = @HAVE_TANF@ +HAVE_TANHF = @HAVE_TANHF@ +HAVE_TANL = @HAVE_TANL@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNAME = @HAVE_UNAME@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INET_PTON_LIB = @INET_PTON_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISFINITE_LIBM = @ISFINITE_LIBM@ +ISINF_LIBM = @ISINF_LIBM@ +LDFLAGS = @LDFLAGS@ +LIBGNULIB_LIBDEPS = @LIBGNULIB_LIBDEPS@ +LIBGNULIB_LTLIBDEPS = @LIBGNULIB_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBSOCKET = @LIBSOCKET@ +LIBTESTS_LIBDEPS = @LIBTESTS_LIBDEPS@ +LIBTHREAD = @LIBTHREAD@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ +LIB_NANOSLEEP = @LIB_NANOSLEEP@ +LIB_SELECT = @LIB_SELECT@ +LIB_SELINUX = @LIB_SELINUX@ +LN_S = @LN_S@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_TR_UTF8 = @LOCALE_TR_UTF8@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MODF_LIBM = @MODF_LIBM@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_ARPA_INET_H = @NEXT_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H = @NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_CTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_CTYPE_H@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_MATH_H = @NEXT_AS_FIRST_DIRECTIVE_MATH_H@ +NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H = @NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H@ +NEXT_AS_FIRST_DIRECTIVE_SELINUX_SELINUX_H = @NEXT_AS_FIRST_DIRECTIVE_SELINUX_SELINUX_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDARG_H = @NEXT_AS_FIRST_DIRECTIVE_STDARG_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UTSNAME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UTSNAME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_CTYPE_H = @NEXT_CTYPE_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_MATH_H = @NEXT_MATH_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_SELINUX_SELINUX_H = @NEXT_SELINUX_SELINUX_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDARG_H = @NEXT_STDARG_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRINGS_H = @NEXT_STRINGS_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_IOCTL_H = @NEXT_SYS_IOCTL_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_UIO_H = @NEXT_SYS_UIO_H@ +NEXT_SYS_UTSNAME_H = @NEXT_SYS_UTSNAME_H@ +NEXT_SYS_WAIT_H = @NEXT_SYS_WAIT_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CBRTF = @REPLACE_CBRTF@ +REPLACE_CBRTL = @REPLACE_CBRTL@ +REPLACE_CEIL = @REPLACE_CEIL@ +REPLACE_CEILF = @REPLACE_CEILF@ +REPLACE_CEILL = @REPLACE_CEILL@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_EXP2 = @REPLACE_EXP2@ +REPLACE_EXP2L = @REPLACE_EXP2L@ +REPLACE_EXPM1 = @REPLACE_EXPM1@ +REPLACE_EXPM1F = @REPLACE_EXPM1F@ +REPLACE_FABSL = @REPLACE_FABSL@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FLOOR = @REPLACE_FLOOR@ +REPLACE_FLOORF = @REPLACE_FLOORF@ +REPLACE_FLOORL = @REPLACE_FLOORL@ +REPLACE_FMA = @REPLACE_FMA@ +REPLACE_FMAF = @REPLACE_FMAF@ +REPLACE_FMAL = @REPLACE_FMAL@ +REPLACE_FMOD = @REPLACE_FMOD@ +REPLACE_FMODF = @REPLACE_FMODF@ +REPLACE_FMODL = @REPLACE_FMODL@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FREXP = @REPLACE_FREXP@ +REPLACE_FREXPF = @REPLACE_FREXPF@ +REPLACE_FREXPL = @REPLACE_FREXPL@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_HUGE_VAL = @REPLACE_HUGE_VAL@ +REPLACE_HYPOT = @REPLACE_HYPOT@ +REPLACE_HYPOTF = @REPLACE_HYPOTF@ +REPLACE_HYPOTL = @REPLACE_HYPOTL@ +REPLACE_ILOGB = @REPLACE_ILOGB@ +REPLACE_ILOGBF = @REPLACE_ILOGBF@ +REPLACE_INET_NTOP = @REPLACE_INET_NTOP@ +REPLACE_INET_PTON = @REPLACE_INET_PTON@ +REPLACE_IOCTL = @REPLACE_IOCTL@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISFINITE = @REPLACE_ISFINITE@ +REPLACE_ISINF = @REPLACE_ISINF@ +REPLACE_ISNAN = @REPLACE_ISNAN@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LDEXPL = @REPLACE_LDEXPL@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LOG = @REPLACE_LOG@ +REPLACE_LOG10 = @REPLACE_LOG10@ +REPLACE_LOG10F = @REPLACE_LOG10F@ +REPLACE_LOG10L = @REPLACE_LOG10L@ +REPLACE_LOG1P = @REPLACE_LOG1P@ +REPLACE_LOG1PF = @REPLACE_LOG1PF@ +REPLACE_LOG1PL = @REPLACE_LOG1PL@ +REPLACE_LOG2 = @REPLACE_LOG2@ +REPLACE_LOG2F = @REPLACE_LOG2F@ +REPLACE_LOG2L = @REPLACE_LOG2L@ +REPLACE_LOGB = @REPLACE_LOGB@ +REPLACE_LOGBF = @REPLACE_LOGBF@ +REPLACE_LOGBL = @REPLACE_LOGBL@ +REPLACE_LOGF = @REPLACE_LOGF@ +REPLACE_LOGL = @REPLACE_LOGL@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_MODF = @REPLACE_MODF@ +REPLACE_MODFF = @REPLACE_MODFF@ +REPLACE_MODFL = @REPLACE_MODFL@ +REPLACE_NAN = @REPLACE_NAN@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMAINDER = @REPLACE_REMAINDER@ +REPLACE_REMAINDERF = @REPLACE_REMAINDERF@ +REPLACE_REMAINDERL = @REPLACE_REMAINDERL@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_ROUND = @REPLACE_ROUND@ +REPLACE_ROUNDF = @REPLACE_ROUNDF@ +REPLACE_ROUNDL = @REPLACE_ROUNDL@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SIGNBIT = @REPLACE_SIGNBIT@ +REPLACE_SIGNBIT_USING_GCC = @REPLACE_SIGNBIT_USING_GCC@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_SQRTL = @REPLACE_SQRTL@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TRUNC = @REPLACE_TRUNC@ +REPLACE_TRUNCF = @REPLACE_TRUNCF@ +REPLACE_TRUNCL = @REPLACE_TRUNCL@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SED = @SED@ +SELINUX_CONTEXT_H = @SELINUX_CONTEXT_H@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SORT = @SORT@ +SORT_SUPPORTS_Z = @SORT_SUPPORTS_Z@ +STDALIGN_H = @STDALIGN_H@ +STDARG_H = @STDARG_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_IOCTL_H_HAVE_WINSOCK2_H = @SYS_IOCTL_H_HAVE_WINSOCK2_H@ +SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +TRUNC_LIBM = @TRUNC_LIBM@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +YIELD_LIB = @YIELD_LIB@ +abs_aux_dir = @abs_aux_dir@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +lispdir = @lispdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Copyright (C) 1996,1999,2000,2001,2003-2015 Free Software Foundation, Inc. +# +# This program 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. +# +# This program 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 <http://www.gnu.org/licenses/>. +AM_CFLAGS = $(WARN_CFLAGS) +info_TEXINFOS = find.texi find-maint.texi +find_TEXINFOS = perm.texi parse-datetime.texi regexprops.texi fdl.texi +BUILT_SOURCES = dblocation.texi +nodist_find_TEXINFOS = dblocation.texi +find_maint_TEXINFOS = fdl.texi +MOSTLYCLEANFILES = find.cps +CLEANFILES = find.txt find_mono.html findutils.texi_html_node.tar.gz dblocation.texi +MAKEINFOTXT = $(MAKEINFO) --plaintext +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .dvi .html .info .pdf .ps .texi .txt +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +.texi.info: + $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \ + am__cwd=`pwd` && $(am__cd) $(srcdir) && \ + rm -rf $$backupdir && mkdir $$backupdir && \ + if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ + for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ + if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ + done; \ + else :; fi && \ + cd "$$am__cwd"; \ + if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $@ $<; \ + then \ + rc=0; \ + $(am__cd) $(srcdir); \ + else \ + rc=$$?; \ + $(am__cd) $(srcdir) && \ + $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ + fi; \ + rm -rf $$backupdir; exit $$rc + +.texi.dvi: + $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \ + $< + +.texi.pdf: + $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \ + $< + +.texi.html: + $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp) + $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) $<; \ + then \ + rm -rf $@ && mv $(@:.html=.htp) $@; \ + else \ + rm -rf $(@:.html=.htp); exit 1; \ + fi +$(srcdir)/find.info: find.texi $(srcdir)/version.texi $(find_TEXINFOS) +find.dvi: find.texi $(srcdir)/version.texi $(find_TEXINFOS) +find.pdf: find.texi $(srcdir)/version.texi $(find_TEXINFOS) +find.html: find.texi $(srcdir)/version.texi $(find_TEXINFOS) +$(srcdir)/version.texi: $(srcdir)/stamp-vti +$(srcdir)/stamp-vti: find.texi $(top_srcdir)/configure + @(dir=.; test -f ./find.texi || dir=$(srcdir); \ + set `$(SHELL) $(top_srcdir)/build-aux/mdate-sh $$dir/find.texi`; \ + echo "@set UPDATED $$1 $$2 $$3"; \ + echo "@set UPDATED-MONTH $$2 $$3"; \ + echo "@set EDITION $(VERSION)"; \ + echo "@set VERSION $(VERSION)") > vti.tmp + @cmp -s vti.tmp $(srcdir)/version.texi \ + || (echo "Updating $(srcdir)/version.texi"; \ + cp vti.tmp $(srcdir)/version.texi) + -@rm -f vti.tmp + @cp $(srcdir)/version.texi $@ + +mostlyclean-vti: + -rm -f vti.tmp + +maintainer-clean-vti: + -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi +$(srcdir)/find-maint.info: find-maint.texi $(srcdir)/versionmaint.texi $(find_maint_TEXINFOS) +find-maint.dvi: find-maint.texi $(srcdir)/versionmaint.texi $(find_maint_TEXINFOS) +find-maint.pdf: find-maint.texi $(srcdir)/versionmaint.texi $(find_maint_TEXINFOS) +find-maint.html: find-maint.texi $(srcdir)/versionmaint.texi $(find_maint_TEXINFOS) +$(srcdir)/versionmaint.texi: $(srcdir)/stamp-1 +$(srcdir)/stamp-1: find-maint.texi $(top_srcdir)/configure + @(dir=.; test -f ./find-maint.texi || dir=$(srcdir); \ + set `$(SHELL) $(top_srcdir)/build-aux/mdate-sh $$dir/find-maint.texi`; \ + echo "@set UPDATED $$1 $$2 $$3"; \ + echo "@set UPDATED-MONTH $$2 $$3"; \ + echo "@set EDITION $(VERSION)"; \ + echo "@set VERSION $(VERSION)") > 1.tmp + @cmp -s 1.tmp $(srcdir)/versionmaint.texi \ + || (echo "Updating $(srcdir)/versionmaint.texi"; \ + cp 1.tmp $(srcdir)/versionmaint.texi) + -@rm -f 1.tmp + @cp $(srcdir)/versionmaint.texi $@ + +mostlyclean-1: + -rm -f 1.tmp + +maintainer-clean-1: + -rm -f $(srcdir)/stamp-1 $(srcdir)/versionmaint.texi +.dvi.ps: + $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + $(DVIPS) $(AM_V_texinfo) -o $@ $< + +uninstall-dvi-am: + @$(NORMAL_UNINSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ + rm -f "$(DESTDIR)$(dvidir)/$$f"; \ + done + +uninstall-html-am: + @$(NORMAL_UNINSTALL) + @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ + rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ + done + +uninstall-info-am: + @$(PRE_UNINSTALL) + @if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ + if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ + then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ + done; \ + else :; fi + @$(NORMAL_UNINSTALL) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ + (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ + echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ + rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ + else :; fi); \ + done + +uninstall-pdf-am: + @$(NORMAL_UNINSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ + rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ + done + +uninstall-ps-am: + @$(NORMAL_UNINSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ + rm -f "$(DESTDIR)$(psdir)/$$f"; \ + done + +dist-info: $(INFO_DEPS) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + case $$base in \ + $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ + for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ + if test -f $$file; then \ + relfile=`expr "$$file" : "$$d/\(.*\)"`; \ + test -f "$(distdir)/$$relfile" || \ + cp -p $$file "$(distdir)/$$relfile"; \ + else :; fi; \ + done; \ + done + +mostlyclean-aminfo: + -rm -rf find.t2d find.t2p find-maint.t2d find-maint.t2p + +clean-aminfo: + -test -z "find.dvi find.pdf find.ps find.html find-maint.dvi find-maint.pdf \ + find-maint.ps find-maint.html" \ + || rm -rf find.dvi find.pdf find.ps find.html find-maint.dvi find-maint.pdf \ + find-maint.ps find-maint.html + +maintainer-clean-aminfo: + @list='$(INFO_DEPS)'; for i in $$list; do \ + i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ + echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ + rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ + done +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-info +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(INFO_DEPS) +installdirs: + for dir in "$(DESTDIR)$(infodir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-aminfo clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: $(DVIS) + +html: html-am + +html-am: $(HTMLS) + +info: info-am + +info-am: $(INFO_DEPS) + +install-data-am: install-info-am + +install-dvi: install-dvi-am + +install-dvi-am: $(DVIS) + @$(NORMAL_INSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ + done +install-exec-am: + +install-html: install-html-am + +install-html-am: $(HTMLS) + @$(NORMAL_INSTALL) + @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ + $(am__strip_dir) \ + d2=$$d$$p; \ + if test -d "$$d2"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ + echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ + else \ + list2="$$list2 $$d2"; \ + fi; \ + done; \ + test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ + done; } +install-info: install-info-am + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \ + fi; \ + for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ + for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ + $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ + if test -f $$ifile; then \ + echo "$$ifile"; \ + else : ; fi; \ + done; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done + @$(POST_INSTALL) + @if $(am__can_run_installinfo); then \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ + done; \ + else : ; fi +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: $(PDFS) + @$(NORMAL_INSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done +install-ps: install-ps-am + +install-ps-am: $(PSS) + @$(NORMAL_INSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-1 \ + maintainer-clean-aminfo maintainer-clean-generic \ + maintainer-clean-vti + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-1 mostlyclean-aminfo mostlyclean-generic \ + mostlyclean-vti + +pdf: pdf-am + +pdf-am: $(PDFS) + +ps: ps-am + +ps-am: $(PSS) + +uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ + uninstall-pdf-am uninstall-ps-am + +.MAKE: all check install install-am install-strip + +.PHONY: all all-am check check-am clean clean-aminfo clean-generic \ + cscopelist-am ctags-am dist-info distclean distclean-generic \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-1 maintainer-clean-aminfo \ + maintainer-clean-generic maintainer-clean-vti mostlyclean \ + mostlyclean-1 mostlyclean-aminfo mostlyclean-generic \ + mostlyclean-vti pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-dvi-am uninstall-html-am \ + uninstall-info-am uninstall-pdf-am uninstall-ps-am + + +find.txt: find.texi $(srcdir)/version.texi $(find_TEXINFOS) + +# find.txt is a file which we need to know how to build +# because it gets put on the www.gnu.org website. +# This rule is derived from the .texi.html rule. +.texi.txt: + rm -rf $(@:.txt=.tmp) + if $(MAKEINFOTXT) $(AM_MAKEINFOTXTFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.txt=.tmp) $<; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.txt=.tmp) && test -d $(@:.txt=); then \ + mv $(@:.txt=) $@; else mv $(@:.txt=.tmp) $@; fi; \ + else \ + if test ! -d $(@:.txt=.tmp) && test -d $(@:.txt=); then \ + rm -rf $(@:.txt=); else rm -Rf $(@:.txt=.tmp) $@; fi; \ + exit 1; \ + fi + +# find_mono.html is a file which we need to know how to build +# because it gets put on the www.gnu.org website. +# This rule is derived from the generic .texi.html rule. +find_mono.html: find.texi + rm -rf $(@:.html=.htp) + if $(MAKEINFOHTML) --no-split $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) $<; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ + else \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ + exit 1; \ + fi + +# findutils.texi_html_node.tar.gz is a file which we need to know +# how to build because it gets put on the www.gnu.org website. +# This rule depends on GNU tar, but it's principally used +# by the maintainer, and we don't need to build the file +# for "make all" or "make install" (or even "make check"). +findutils.texi_html_node.tar.gz: find.html + tar zcf $@ $< + +dblocation.texi: ../locate/dblocation.texi + $(LN_S) ../locate/dblocation.texi $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/fdl.texi b/doc/fdl.texi new file mode 100644 index 0000000..9c3bbe5 --- /dev/null +++ b/doc/fdl.texi @@ -0,0 +1,505 @@ +@c The GNU Free Documentation License. +@center Version 1.3, 3 November 2008 + +@c This file is intended to be included within another document, +@c hence no sectioning command or @node. + +@display +Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. +@uref{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, La@TeX{} input +format, SGML or XML using a publicly available +DTD, and standard-conforming simple HTML, +PostScript or PDF designed for human modification. Examples +of transparent image formats include PNG, XCF and +JPG@. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, SGML or +XML for which the DTD and/or processing tools are +not generally available, and the machine-generated HTML, +PostScript or PDF produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The ``publisher'' means any person or entity that distributes copies +of the Document to the public. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +@item +RELICENSING + +``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the +site means any set of copyrightable works thus published on the MMC +site. + +``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +``Incorporate'' means to publish or republish a Document, in whole or +in part, as part of another Document. + +An MMC is ``eligible for relicensing'' if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole +or in part into the MMC, (1) had no cover texts or invariant sections, +and (2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + +@end enumerate + +@page +@heading ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with@dots{}Texts.''@: line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: diff --git a/doc/find-maint.info b/doc/find-maint.info new file mode 100644 index 0000000..2052013 --- /dev/null +++ b/doc/find-maint.info @@ -0,0 +1,1585 @@ +This is find-maint.info, produced by makeinfo version 5.2 from +find-maint.texi. + +This manual explains how GNU findutils is maintained, how changes should +be made and tested, and what resources exist to help developers. + + This is edition 4.6.0, for findutils version 4.6.0. + + Copyright (C) 2007, 2008, 2010-2015 Free Software Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled "GNU Free +Documentation License". +INFO-DIR-SECTION GNU organization +START-INFO-DIR-ENTRY +* Maintaining Findutils: (find-maint). Maintaining GNU findutils +END-INFO-DIR-ENTRY + + +File: find-maint.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) + +Maintaining GNU Findutils +************************* + +This manual explains how GNU findutils is maintained, how changes should +be made and tested, and what resources exist to help developers. + + This is edition 4.6.0, for findutils version 4.6.0. + + Copyright (C) 2007, 2008, 2010-2015 Free Software Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled "GNU Free +Documentation License". + +* Menu: + +* Introduction:: +* Maintaining GNU Programs:: +* Design Issues:: +* Coding Conventions:: +* Tools:: +* Using the GNU Portability Library:: +* Documentation:: +* Testing:: +* Bugs:: +* Distributions:: +* Internationalisation:: +* Security:: +* Making Releases:: +* GNU Free Documentation License:: + + +File: find-maint.info, Node: Introduction, Next: Maintaining GNU Programs, Up: Top + +1 Introduction +************** + +This document explains how to contribute to and maintain GNU Findutils. +It concentrates on developer-specific issues. For information about how +to use the software please refer to *Note Introduction: +(find)Introduction. + + This manual aims to be useful without necessarily being verbose. +It's also a recent document, so there will be a many areas in which +improvements can be made. If you find that the document misses out +important information or any part of the document is be so terse as to +be unuseful, please ask for help on the <bug-findutils@gnu.org> mailing +list. We'll try to improve this document too. + + +File: find-maint.info, Node: Maintaining GNU Programs, Next: Design Issues, Prev: Introduction, Up: Top + +2 Maintaining GNU Programs +************************** + +GNU Findutils is part of the GNU Project and so there are a number of +documents which set out standards for the maintenance of GNU software. + +'standards.texi' + GNU Project Coding Standards. All changes to findutils should + comply with these standards. In some areas we go somewhat beyond + the requirements of the standards, but these cases are explained in + this manual. +'maintain.texi' + Information for Maintainers of GNU Software. This document + provides guidance for GNU maintainers. Everybody with commit + access should read this document. Everybody else is welcome to do + so too, of course. + + +File: find-maint.info, Node: Design Issues, Next: Coding Conventions, Prev: Maintaining GNU Programs, Up: Top + +3 Design Issues +*************** + +The findutils package is installed on many many systems, usually as a +fundamental component. The programs in the package are often used in +order to successfully boot or fix the system. + + This fact means that for findutils we bear in mind considerations +that may not apply so much as for other packages. For example, the fact +that findutils is often a base component motivates us to + * Limit dependencies on libraries + * Avoid dependencies on other large packages (for example, + interpreters) + * Be conservative when making changes to the 'stable' release branch + + All those considerations come before functionality. Functional +enhancements are still made to findutils, but these are almost +exclusively introduced in the 'development' release branch, to allow +extensive testing and proving. + + Sometimes it is useful to have a priority list to provide guidance +when making design trade-offs. For findutils, that priority list is: + + 1. Correctness + 2. Standards compliance + 3. Security + 4. Backward compatibility + 5. Performance + 6. Functionality + + For example, we support the '-exec' action because POSIX compliance +requires this, even though there are security problems with it and we +would otherwise prefer people to use '-execdir'. There are also cases +where some performance is sacrificed in the name of security. For +example, the sanity checks that 'find' performs while traversing a +directory tree may slow it down. We adopt functional changes, and +functional changes are allowed to make 'find' slower, but only if there +is no detectable impact on users who don't use the feature. + + Backward-incompatible changes do get made in order to comply with +standards (for example the behaviour of '-perm -...' changed in order to +comply with POSIX). However, they don't get made in order to provide +better ease of use; for example the semantics of '-size -2G' are almost +always unexpected by users, but we retain the current behaviour because +of backward compatibility and for its similarity to the block-rounding +behaviour of '-size -30'. We might introduce a change which does not +have the unfortunate rounding behaviour, but we would choose another +syntax (for example '-size '<2G'') for this. + + In a general sense, we try to do test-driven development of the +findutils code; that is, we try to implement test cases for new features +and bug fixes before modifying the code to make the test pass. Some +features of the code are tested well, but the test coverage for other +features is less good. If you are about to modify the code for a +predicate and aren't sure about the test coverage, use 'grep' on the +test directories and measure the coverage with 'lcov' or another test +coverage tool. + + You should be able to use the 'coverage' Makefile target (it's +defined in 'maint.mk' to generate a test coverage report for findutils. +Due to limitations in 'lcov', this only works if your build directory is +the same asthe source directory (that is, you're not using a VPATH build +configuration). + + Lastly, we try not to depend on having a "working system". The +findutils suite is used for diagnosis of problems, and this applies +especially to 'find'. We should ensure that 'find' still works on +relatively broken systems, for example systems with damaged +'/etc/passwd' or '/etc/fstab' files. Another interesting example is the +case where a system is a client of one or more unresponsive NFS servers. +On such a system, if you try to stat all mount points, your program will +hang indefinitely, waiting for the remote NFS server to respond. + + Another interesting but unusual case is broken NFS servers and +corrupt filesystems; sometimes they return 'impossible' file modes. +It's important that find does not entirely fail when encountering such a +file. + + +File: find-maint.info, Node: Coding Conventions, Next: Tools, Prev: Design Issues, Up: Top + +4 Coding Conventions +******************** + +Coding style documents which set out to establish a uniform look and +feel to source code have worthy goals, for example greater ease of +maintenance and readability. However, I do not believe that in general +coding style guide authors can envisage every situation, and it is +always possible that it might on occasion be necessary to break the +letter of the style guide in order to honour its spirit, or to better +achieve the style guide's goals. + + I've certainly seen many style guides outside the free software world +which make bald statements such as "functions shall have exactly one +return statement". The desire to ensure consistency and obviousness of +control flow is laudable, but it is all too common for such bald +requirements to be followed unthinkingly. Certainly I've seen such +coding standards result in unmaintainable code with terrible +infelicities such as functions containing 'if' statements nested nine +levels deep. I suppose such coding standards don't survive in free +software projects because they tend to drive away potential contributors +or tend to generate heated discussions on mailing lists. Equally, a +nine-level-deep function in a free software program would quickly get +refactored, assuming it is obvious what the function is supposed to +do... + + Be that as it may, the approach I will take for this document is to +explain some idioms and practices in use in the findutils source code, +and leave it up to the reader's engineering judgement to decide which +considerations apply to the code they are working on, and whether or not +there is sufficient reason to ignore the guidance in current +circumstances. + +* Menu: + +* Make the Compiler Find the Bugs:: +* Factor Out Repeated Code:: +* Debugging is For Users Too:: +* Don't Trust the File System Contents:: +* The File System Is Being Modified:: + + +File: find-maint.info, Node: Make the Compiler Find the Bugs, Next: Factor Out Repeated Code, Up: Coding Conventions + +4.1 Make the Compiler Find the Bugs +=================================== + +Finding bugs is tedious. If I have a filesystem containing two million +files, and a find command line should print one million of them, but in +fact it misses out 1%, you can tell the program is printing the wrong +result only if you know the right answer for that filesystem at that +time. If you don't know this, you may just not find out about that bug. +For this reason it is important to have a comprehensive test suite. + + The test suite is of course not the only way to find the bugs. The +findutils source code makes liberal use of the assert macro. While on +the one hand these might be a performance drain, the performance impact +of most of these is negligible compared to the time taken to fetch even +one sector from a disk drive. + + Assertions should not be used to check the results of operations +which may be affected by the program's external environment. For +example, never assert that a file could be opened successfully. Errors +relating to problems with the program's execution environment should be +diagnosed with a user-oriented error message. An assertion failure +should always denote a bug in the program. + + Don't use 'assert' to catch not-fuly-implemented features of your +code. Finish the implementation, disable the code, or leave the +unfinished version on a local branch. + + Several programs in the findutils suite perform self-checks. See for +example the function 'pred_sanity_check' in 'find/pred.c'. This is +generally desirable. + + There are also a number of small ways in which we can help the +compiler to find the bugs for us. + +4.1.1 Constants in Equality Testing +----------------------------------- + +It's a common error to write '=' when '==' is meant. Sometimes this +happens in new code and is simply due to finger trouble. Sometimes it +is the result of the inadvertent deletion of a character. In any case, +there is a subset of cases where we can persuade the compiler to +generate an error message when we make this mistake; this is where the +equality test is with a constant. + + This is an example of a vulnerable piece of code. + + if (x == 2) + ... + + A simple typo converts the above into + + if (x = 2) + ... + + We've introduced a bug; the condition is always true, and the value +of 'x' has been changed. However, a simple change to our practice would +have made us immune to this problem: + + if (2 == x) + ... + + Usually, the Emacs keystroke 'M-t' can be used to swap the operands. + +4.1.2 Spelling of ASCII NUL +--------------------------- + +Strings in C are just sequences of characters terminated by a NUL. The +ASCII NUL character has the numerical value zero. It is normally +represented in C code as '\0'. Here is a typical piece of C code: + + *p = '\0'; + + Consider what happens if there is an unfortunate typo: + + *p = '0'; + + We have changed the meaning of our program and the compiler cannot +diagnose this as an error. Our string is no longer terminated. Bad +things will probably happen. It would be better if the compiler could +help us diagnose this problem. + + In C, the type of ''\0'' is in fact int, not char. This provides us +with a simple way to avoid this error. The constant '0' has the same +value and type as the constant ''\0''. However, it is not as vulnerable +to typos. For this reason I normally prefer to use this code: + + *p = 0; + + +File: find-maint.info, Node: Factor Out Repeated Code, Next: Debugging is For Users Too, Prev: Make the Compiler Find the Bugs, Up: Coding Conventions + +4.2 Factor Out Repeated Code +============================ + +Repeated code imposes a greater maintenance burden and increases the +exposure to bugs. For example, if you discover that something you want +to implement has some similarity with an existing piece of code, don't +cut and paste it. Instead, factor the code out. The risk of cutting +and pasting the code, particularly if you do this several times, is that +you end up with several copies of the same code. + + If the original code had a bug, you now have N places where this +needs to be fixed. It's all to easy to miss some out when trying to fix +the bug. Equally, it's quite possible that when pasting the code into +some function, the pasted code was not quite adapted correctly to its +new environment. To pick a contrived example, perhaps it modifies a +global variable which it that code shouldn't be touching in its new +home. Worse, perhaps it makes some unstated assumption about the nature +of the input arguments which is in fact not true for the context of the +now duplicated code. + + A good example of the use of refactoring in findutils is the +'collect_arg' function in 'find/parser.c'. A less clear-cut but larger +example is the factoring out of code which would otherwise have been +duplicated between 'find/oldfind.c' and 'find/ftsfind.c'. + + The findutils test suite is comprehensive enough that refactoring +code should not generally be a daunting prospect from a testing point of +view. Nevertheless there are some areas which are only lightly-tested: + + 1. Tests on the ages of files + 2. Code which deals with the values returned by operating system calls + (for example handling of ENOENT) + 3. Code dealing with OS limits (for example, limits on path length or + exec arguments) + 4. Code relating to features not all systems have (for example Solaris + Doors) + + Please exercise caution when working in those areas. + + +File: find-maint.info, Node: Debugging is For Users Too, Next: Don't Trust the File System Contents, Prev: Factor Out Repeated Code, Up: Coding Conventions + +4.3 Debugging is For Users Too +============================== + +Debug and diagnostic code is often used to verify that a program is +working in the way its author thinks it should be. But users are often +uncertain about what a program is doing, too. Exposing them a little +more diagnostic information can help. Much of the diagnostic code in +'find', for example, is controlled by the '-D' flag, as opposed to C +preprocessor directives. + + Making diagnostic messages available to users also means that the +phrasing of the diagnostic messages becomes important, too. + + +File: find-maint.info, Node: Don't Trust the File System Contents, Next: The File System Is Being Modified, Prev: Debugging is For Users Too, Up: Coding Conventions + +4.4 Don't Trust the File System Contents +======================================== + +People use 'find' to search in directories created by other people. +Sometimes they do this to check to suspicious activity (for example to +look for new setuid binaries). This means that it would be bad if +'find' were vulnerable to, say, a security problem exploitable by +constructing a specially-crafted filename. The same consideration would +apply to 'locate' and 'updatedb'. + + Henry Spencer said this well in his fifth commandment: + Thou shalt check the array bounds of all strings (indeed, all + arrays), for surely where thou typest 'foo' someone someday shall + type 'supercalifragilisticexpialidocious'. + + Symbolic links can often be a problem. If 'find' calls 'lstat' on +something and discovers that it is a directory, it's normal for 'find' +to recurse into it. Even if the 'chdir' system call is used +immediately, there is still a window of opportunity between the 'lstat' +and the 'chdir' in which a malicious person could rename the directory +and substitute a symbolic link to some other directory. + + +File: find-maint.info, Node: The File System Is Being Modified, Prev: Don't Trust the File System Contents, Up: Coding Conventions + +4.5 The File System Is Being Modified +===================================== + +The filesystem gets modified while you are traversing it. For, example, +it's normal for files to get deleted while 'find' is traversing a +directory. Issuing an error message seems helpful when a file is +deleted from the one directory you are interested in, but if 'find' is +searching 15000 directories, such a message becomes less helpful. + + Bear in mind also that it is possible for the directory 'find' is +currently searching could be moved to another point in the filesystem, +and that the directory in which 'find' was started could be deleted. + + Henry Spencer's sixth commandment is also apposite here: + If a function be advertised to return an error code in the event of + difficulties, thou shalt check for that code, yea, even though the + checks triple the size of thy code and produce aches in thy typing + fingers, for if thou thinkest "it cannot happen to me", the gods + shall surely punish thee for thy arrogance. + + There are a lot of files out there. They come in all dates and +sizes. There is a condition out there in the real world to exercise +every bit of the code base. So we try to test that code base before +someone falls over a bug. + + +File: find-maint.info, Node: Tools, Next: Using the GNU Portability Library, Prev: Coding Conventions, Up: Top + +5 Tools +******* + +Most of the tools required to build findutils are mentioned in the file +'README-hacking'. We also use some other tools: + +System call traces + Much of the execution time of find is spent waiting for filesystem + operations. A system call trace (for example, that provided by + 'strace') shows what system calls are being made. Using this + information we can work to remove unnecessary file system + operations. + +Valgrind + Valgrind is a tool which dynamically verifies the memory accesses a + program makes to ensure that they are valid (for example, that the + behaviour of the program does not in any way depend on the contents + of uninitialized memory). + +DejaGnu + DejaGnu is the test framework used to run the findutils test suite + (the 'runtest' program is part of DejaGnu). It would be ideal if + everybody building 'findutils' also ran the test suite, but many + people don't have DejaGnu installed. When changes are made to + findutils, DejaGnu is invoked a lot. *Note Testing::, for more + information. + + +File: find-maint.info, Node: Using the GNU Portability Library, Next: Documentation, Prev: Tools, Up: Top + +6 Using the GNU Portability Library +*********************************** + +The Gnulib library (<http://www.gnu.org/software/gnulib/>) makes a +variety of systems look more like a GNU/Linux system and also applies a +bunch of automatic bug fixes and workarounds. Some of these also apply +to GNU/Linux systems too. For example, the Gnulib regex implementation +is used when we determine that we are building on a GNU libc system with +a bug in the regex implementation. + +6.1 How and Why we Import the Gnulib Code +========================================= + +Gnulib does not have a release process which results in a source tarball +you can download. Instead, the code is simply made available by GIT, so +we import gnulib via the submodule feature. The bootstrap script +performs the necessary steps. + + Findutils does not use all the Gnulib code. The modules we need are +listed in the file 'bootstrap.conf'. + + The upshot of all this is that we can use the findutils git +repository to track which version of Gnulib every findutils release +uses. + + A small number of files are installed by automake and will therefore +vary according to which version of automake was used to generate a +release. This includes for example boiler-plate GNU files such as +'ABOUT-NLS', 'INSTALL' and 'COPYING'. + +6.2 How We Fix Gnulib Bugs +========================== + +Gnulib is used by quite a number of GNU projects, and this means that it +gets plenty of testing. Therefore there are relatively few bugs in the +Gnulib code, but it does happen from time to time. + + However, since there is no waiting around for a Gnulib source release +tarball, Gnulib bugs are generally fixed quickly. Here is an outline of +the way we would contribute a fix to Gnulib (assuming you know it is not +already fixed in the current Gnulib git tree): + +Check you already completed a copyright assignment for Gnulib +Begin with a vanilla git tree + Download the Findutils source code from git (or use the tree you + have already) +Run the bootstrap script +Run configure +Build findutils + Build findutils and run the test suite, which should pass. In our + example we assume you have just noticed a bug in Gnulib, not that + recent Gnulib changes broke the findutils regression tests. +Write a test case + If in fact Gnulib did break the findutils regression tests, you can + probably skip this step, since you already have a test case + demonstrating the problem. Otherwise, write a findutils test case + for the bug and/or a Gnulib test case. +Fix the Gnulib bug + Make sure your editor follows symbolic links so that your changes + to 'gnulib/...' actually affect the files in the git working + directory you checked out earlier. Observe that your test now + passes. +Prepare a Gnulib patch + In the gnulib subdirectory, use 'git format-patch' to prepare the + patch. Follow the normal usage for checkin comments (take a look + at the output of 'git log'). Check that the patch conforms with + the GNU coding standards, and email it to the Gnulib mailing list. +Wait for the patch to be applied + Once your bug fix has been applied, you can update your gnulib + directory from git, and then check in the change to the submodule + as normal (you can check 'git help submodule' for details). + + There is an alternative to the method above; it is possible to store +local diffs to be patched into gnulib beneath the 'gnulib-local'. +Normally however, there is no need for this, since gnulib updates are +very prompt. + + +File: find-maint.info, Node: Documentation, Next: Testing, Prev: Using the GNU Portability Library, Up: Top + +7 Documentation +*************** + +The findutils git tree includes several different types of +documentation. + +7.1 git change log +================== + +The git change log for the source tree contains check-in messages which +describe each check-in. These have a standard format: + + Summary of the change. + + (ChangeLog-style detail) + + Here, the format of the detail part follows the standard GNU +ChangeLog style, but without whitespace in the left margin and without +author/date headers. Take a look at the output of 'git log' to see some +examples. The README-hacking file also contains an example with an +explanation. + +7.2 User Documentation +====================== + +User-oriented documentation is provided as manual pages and in Texinfo. +See *note Introduction: (find)Introduction. + + Please make sure both sets of documentation are updated if you make a +change to the code. The GNU coding standards do not normally call for +maintaining manual pages on the grounds of effort duplication. However, +the manual page format is more convenient for quick reference, and so +it's worth maintaining both types of documentation. However, the manual +pages are normally rather more terse than the Texinfo documentation. +The manual pages are suitable for reference use, but the Texinfo manual +should also include introductory and tutorial material. + +7.3 Build Guidance +================== + +'ABOUT-NLS' + Describes the Free Translation Project, the translation status of + various GNU projects, and how to participate by translating an + application. +'AUTHORS' + Lists the authors of findutils. +'COPYING' + The copyright license covering findutils; currently, the GNU GPL, + version 3. +'INSTALL' + Generic installation instructions for installing GNU programs. +'README' + Information about how to compile findutils in particular +'README-alpha' + A README file which is included with testing releases of findutils. +'README-hacking' + Describes how to build findutils from the code in git. +'THANKS' + Thanks for people who contributed to findutils. Generally, if + someone's contribution was significant enough to need a copyright + assignment, their name should go in here. +'TODO' + Mainly obsolete. Please add bugs to the Savannah bug tracker + instead of adding entries to this file. + +7.4 Release Information +======================= + +'NEWS' + Enumerates the user-visible change in each release. Typical + changes are fixed bugs, functionality changes and documentation + changes. Include the date when a release is made. +'ChangeLog' + This file enumerates all changes to the findutils source code (with + the possible exception of '.cvsignore' and '.gitignore' changes). + The level of detail used for this file should be sufficient to + answer the questions "what changed?" and "why was it changed?". + The file is generated from the git commit messages during 'make + dist'. If a change fixes a bug, always give the bug reference + number in the 'NEWS' file and of course also in the checkin + message. In general, it should be possible to enumerate all + material changes to a function by searching for its name in + 'ChangeLog'. Mention when each release is made. + + +File: find-maint.info, Node: Testing, Next: Bugs, Prev: Documentation, Up: Top + +8 Testing +********* + +This chapter will explain the general procedures for adding tests to the +test suite, and the functions defined in the findutils-specific DejaGnu +configuration. Where appropriate references will be made to the DejaGnu +documentation. + + +File: find-maint.info, Node: Bugs, Next: Distributions, Prev: Testing, Up: Top + +9 Bugs +****** + +Bugs are logged in the Savannah bug tracker +<http://savannah.gnu.org/bugs/?group=findutils>. The tracker offers +several fields but their use is largely obvious. The life-cycle of a +bug is like this: + +Open + Someone, usually a maintainer, a distribution maintainer or a user, + creates a bug by filling in the form. They fill in field values as + they see fit. This will generate an email to + <bug-findutils@gnu.org>. + +Triage + The bug hangs around with 'Status=None' until someone begins to + work on it. At that point they set the "Assigned To" field and + will sometimes set the status to 'In Progress', especially if the + bug will take a while to fix. + +Non-bugs + Quite a lot of reports are not actually bugs; for these the usual + procedure is to explain why the problem is not a bug, set the + status to 'Invalid' and close the bug. Make sure you set the + 'Assigned to' field to yourself before closing the bug. + +Fixing + When you commit a bug fix into git (or in the case of a contributed + patch, commit the change), mark the bug as 'Fixed'. Make sure you + include a new test case where this is relevant. If you can figure + out which releases are affected, please also set the 'Release' + field to the earliest release which is affected by the bug. + Indicate which source branch the fix is included in (for example, + 4.2.x or 4.3.x). Don't close the bug yet. + +Release + When a release is made which includes the bug fix, make sure the + bug is listed in the NEWS file. Once the release is made, fill in + the 'Fixed Release' field and close the bug. + + +File: find-maint.info, Node: Distributions, Next: Internationalisation, Prev: Bugs, Up: Top + +10 Distributions +**************** + +Almost all GNU/Linux distributions include findutils, but only some of +them have a package maintainer who is a member of the mailing list. +Distributions don't often feed back patches to the +<bug-findutils@gnu.org> list, but on the other hand many of their +patches relate only to standards for file locations and so forth, and +are therefore distribution specific. On an irregular basis I check the +current patches being used by one or two distributions, but the total +number of GNU/Linux distributions is large enough that we could not hope +to cover them all. + + Often, bugs are raised against a distribution's bug tracker instead +of GNU's. Periodically (about every six months) I take a look at some +of the more accessible bug trackers to indicate which bugs have been +fixed upstream. + + Many distributions include both findutils and the slocate package, +which provides a replacement 'locate'. + + +File: find-maint.info, Node: Internationalisation, Next: Security, Prev: Distributions, Up: Top + +11 Internationalisation +*********************** + +Translation is essentially automated from the maintainer's point of +view. The TP mails the maintainer when a new PO file is available, and +we just download it and check it in. We copy the '.po' files into the +git repository. For more information, please see +<http://translationproject.org/domain/findutils.html>. + + +File: find-maint.info, Node: Security, Next: Making Releases, Prev: Internationalisation, Up: Top + +12 Security +*********** + +See *note Security Considerations: (find)Security Considerations, for a +full description of the findutils approach to security considerations +and discussion of particular tools. + + If someone reports a security bug publicly, we should fix this as +rapidly as possible. If necessary, this can mean issuing a fixed +release containing just the one bug fix. We try to avoid issuing +releases which include both significant security fixes and functional +changes. + + Where someone reports a security problem privately, we generally try +to construct and test a patch without pushing the intermediate code to +the public repository. + + Once everything has been tested, this allows us to make a release and +push the patch. The advantage of doing things this way is that we avoid +situations where people watching for git commits can figure out and +exploit a security problem before a fixed release is available. + + It's important that security problems be fixed promptly, but don't +rush so much that things go wrong. Make sure the new release really +fixes the problem. It's usually best not to include functional changes +in your security-fix release. + + If the security problem is serious, send an alert to +<vendor-sec@lst.de>. The members of the list include most GNU/Linux +distributions. The point of doing this is to allow them to prepare to +release your security fix to their customers, once the fix becomes +available. Here is an example alert:- + + GNU findutils heap buffer overrun (potential privilege escalation) + + + + I. BACKGROUND + ============= + + GNU findutils is a set of programs which search for files on Unix-like + systems. It is maintained by the GNU Project of the Free Software + Foundation. For more information, see + <http://www.gnu.org/software/findutils>. + + + II. DESCRIPTION + =============== + + When GNU locate reads filenames from an old-format locate database, + they are read into a fixed-length buffer allocated on the heap. + Filenames longer than the 1026-byte buffer can cause a buffer overrun. + The overrunning data can be chosen by any person able to control the + names of filenames created on the local system. This will normally + include all local users, but in many cases also remote users (for + example in the case of FTP servers allowing uploads). + + III. ANALYSIS + ============= + + Findutils supports three different formats of locate database, its + native format "LOCATE02", the slocate variant of LOCATE02, and a + traditional ("old") format that locate uses on other Unix systems. + + When locate reads filenames from a LOCATE02 database (the default + format), the buffer into which data is read is automatically extended + to accommodate the length of the filenames. + + This automatic buffer extension does not happen for old-format + databases. Instead a 1026-byte buffer is used. When a longer + pathname appears in the locate database, the end of this buffer is + overrun. The buffer is allocated on the heap (not the stack). + + If the locate database is in the default LOCATE02 format, the locate + program does perform automatic buffer extension, and the program is + not vulnerable to this problem. The software used to build the + old-format locate database is not itself vulnerable to the same + attack. + + Most installations of GNU findutils do not use the old database + format, and so will not be vulnerable. + + + IV. DETECTION + ============= + + Software + -------- + All existing releases of findutils are affected. + + + Installations + ------------- + + To discover the longest path name on a given system, you can use the + following command (requires GNU findutils and GNU coreutils): + + find / -print0 | tr -c '\0' 'x' | tr '\0' '\n' | wc -L + + V. EXAMPLE + ========== + + This section includes a shell script which determines which of a list + of locate binaries is vulnerable to the problem. The shell script has + been tested only on glibc based systems having a mktemp binary. + + NOTE: This script deliberately overruns the buffer in order to + determine if a binary is affected. Therefore running it on your + system may have undesirable effects. We recommend that you read the + script before running it. + + #! /bin/sh + set +m + if vanilla_db="$(mktemp nicedb.XXXXXX)" ; then + if updatedb --prunepaths="" --old-format --localpaths="/tmp" \ + --output="$@{vanilla_db@}" ; then + true + else + rm -f "$@{vanilla_db@}" + vanilla_db="" + echo "Failed to create old-format locate database; skipping the sanity checks" >&2 + fi + fi + + make_overrun_db() @{ + # Start with a valid database + cat "$@{vanilla_db@}" + # Make the final entry really long + dd if=/dev/zero bs=1 count=1500 2>/dev/null | tr '\000' 'x' + @} + + + + ulimit -c 0 + + usage() @{ echo "usage: $0 binary [binary...]" >&2; exit $1; @} + [ $# -eq 0 ] && usage 1 + + bad="" + good="" + ugly="" + if dbfile="$(mktemp nasty.XXXXXX)" + then + make_overrun_db > "$dbfile" + for locate ; do + ver="$locate = $("$locate" --version | head -1)" + if [ -z "$vanilla_db" ] || "$locate" -d "$vanilla_db" "" >/dev/null ; then + "$locate" -d "$dbfile" "" >/dev/null + if [ $? -gt 128 ] ; then + bad="$bad + vulnerable: $ver" + else + good="$good + good: $ver" + fi + else + # the regular locate failed + ugly="$ugly + buggy, may or may not be vulnerable: $ver" + fi + done + rm -f "$@{dbfile@}" "$@{vanilla_db@}" + # good: unaffected. bad: affected (vulnerable). + # ugly: doesn't even work for a normal old-format database. + echo "$good" + echo "$bad" + echo "$ugly" + else + exit 1 + fi + + + + + VI. VENDOR RESPONSE + =================== + + The GNU project discovered the problem while 'locate' was being worked + on; this is the first public announcement of the problem. + + The GNU findutils mantainer has issued a patch as p[art of this + announcement. The patch appears below. + + A source release of findutils-4.2.31 will be issued on 2007-05-30. + That release will of course include the patch. The patch will be + committed to the public CVS repository at the same time. Public + announcements of the release, including a description of the bug, will + be made at the same time as the release. + + A release of findutils-4.3.x will follow and will also include the + patch. + + + VII. PATCH + ========== + + This patch should apply to findutils-4.2.23 and later. + Findutils-4.2.23 was released almost two years ago. + Index: locate/locate.c + =================================================================== + RCS file: /cvsroot/findutils/findutils/locate/locate.c,v + retrieving revision 1.58.2.2 + diff -u -p -r1.58.2.2 locate.c + --- locate/locate.c 22 Apr 2007 16:57:42 -0000 1.58.2.2 + +++ locate/locate.c 28 May 2007 10:18:16 -0000 + @@@@ -124,9 +124,9 @@@@ extern int errno; + + #include "locatedb.h" + #include <getline.h> + -#include "../gnulib/lib/xalloc.h" + -#include "../gnulib/lib/error.h" + -#include "../gnulib/lib/human.h" + +#include "xalloc.h" + +#include "error.h" + +#include "human.h" + #include "dirname.h" + #include "closeout.h" + #include "nextelem.h" + @@@@ -468,10 +468,36 @@@@ visit_justprint_unquoted(struct process_ + return VISIT_CONTINUE; + @} + + +static void + +toolong (struct process_data *procdata) + +@{ + + error (EXIT_FAILURE, 0, + + _("locate database %s contains a " + + "filename longer than locate can handle"), + + procdata->dbfile); + +@} + + + +static void + +extend (struct process_data *procdata, size_t siz1, size_t siz2) + +@{ + + /* Figure out if the addition operation is safe before performing it. */ + + if (SIZE_MAX - siz1 < siz2) + + @{ + + toolong (procdata); + + @} + + else if (procdata->pathsize < (siz1+siz2)) + + @{ + + procdata->pathsize = siz1+siz2; + + procdata->original_filename = x2nrealloc (procdata->original_filename, + + &procdata->pathsize, + + 1); + + @} + +@} + + + static int + visit_old_format(struct process_data *procdata, void *context) + @{ + - register char *s; + + register size_t i; + (void) context; + + /* Get the offset in the path where this path info starts. */ + @@@@ -479,20 +505,35 @@@@ visit_old_format(struct process_data *pr + procdata->count += getw (procdata->fp) - LOCATEDB_OLD_OFFSET; + else + procdata->count += procdata->c - LOCATEDB_OLD_OFFSET; + + assert(procdata->count > 0); + + - /* Overlay the old path with the remainder of the new. */ + - for (s = procdata->original_filename + procdata->count; + + /* Overlay the old path with the remainder of the new. Read + + * more data until we get to the next filename. + + */ + + for (i=procdata->count; + (procdata->c = getc (procdata->fp)) > LOCATEDB_OLD_ESCAPE;) + - if (procdata->c < 0200) + - *s++ = procdata->c; /* An ordinary character. */ + - else + - @{ + - /* Bigram markers have the high bit set. */ + - procdata->c &= 0177; + - *s++ = procdata->bigram1[procdata->c]; + - *s++ = procdata->bigram2[procdata->c]; + - @} + - *s-- = '\0'; + + @{ + + if (procdata->c < 0200) + + @{ + + /* An ordinary character. */ + + extend (procdata, i, 1u); + + procdata->original_filename[i++] = procdata->c; + + @} + + else + + @{ + + /* Bigram markers have the high bit set. */ + + extend (procdata, i, 2u); + + procdata->c &= 0177; + + procdata->original_filename[i++] = procdata->bigram1[procdata->c]; + + procdata->original_filename[i++] = procdata->bigram2[procdata->c]; + + @} + + @} + + + + /* Consider the case where we executed the loop body zero times; we + + * still need space for the terminating null byte. + + */ + + extend (procdata, i, 1u); + + procdata->original_filename[i] = 0; + + procdata->munged_filename = procdata->original_filename; + + + VIII. THANKS + ============ + + Thanks to Rob Holland <rob@inversepath.com> and Tavis Ormandy. + + + VIII. CVE INFORMATION + ===================== + + No CVE candidate number has yet been assigned for this vulnerability. + If someone provides one, I will include it in the public announcement + and change logs. + + The original announcement above was sent out with a cleartext PGP +signature, of course, but that has been omitted from the example. + + Once a fixed release is available, announce the new release using the +normal channels. Any CVE number assigned for the problem should be +included in the 'ChangeLog' and 'NEWS' entries. See +<http://cve.mitre.org/> for an explanation of CVE numbers. + + +File: find-maint.info, Node: Making Releases, Next: GNU Free Documentation License, Prev: Security, Up: Top + +13 Making Releases +****************** + +This section will explain how to make a findutils release. For the time +being here is a terse description of the main steps: + + 1. Commit changes; make sure your working directory has no uncommitted + changes. + 2. Test; make sure that all changes you have made have tests, and that + the tests pass. Verify this with 'make distcheck'. + 3. Bugs; make sure all Savannah bug entries fixed in this release are + fixed. + 4. NEWS; make sure that the NEWS and configure.in file are updated + with the new release number (and checked in). + 5. Build the release tarball; do this with 'make distcheck'. Copy the + tarball somewhere safe. + 6. Tag the release; findutils releases are tagged like this for + example: v4.5.5. Previously a different format was in use: + FINDUTILS_4_3_8-1. You can create a tag with the a command like + this: 'git tag -s -m "Findutils release v4.5.7" v4.5.7'. + 7. Prepare the upload and upload it. *Note Automated FTP Uploads: + (maintain)Automated FTP Uploads, for detailed upload instructions. + 8. Make a release announcement; include an extract from the NEWS file + which explains what's changed. Announcements for test releases + should just go to <bug-findutils@gnu.org>. Announcements for + stable releases should go to <info-gnu@gnu.org> as well. + 9. Bump the release numbers in git; edit the 'configure.in' and 'NEWS' + files to advance the release numbers. For example, if you have + just released '4.6.2', bump the release number to '4.6.3-git'. The + point of the '-git' suffix here is that a findutils binary built + from git will bear a release number indicating it's not built from + the "official" source release. + 10. Close bugs; any bugs recorded on Savannah which were fixed in this + release should now be marked as closed. Update the 'Fixed Release' + field of these bugs appropriately and make sure the 'Assigned to' + field is populated. + + +File: find-maint.info, Node: GNU Free Documentation License, Prev: Making Releases, Up: Top + +Appendix A GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + <http://fsf.org/> + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled "History" in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + "History" section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + <http://www.gnu.org/copyleft/>. + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A "Massive Multiauthor Collaboration" (or "MMC") contained in the + site means any set of copyrightable works thus published on the MMC + site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + + + +Tag Table: +Node: Top866 +Node: Introduction1937 +Node: Maintaining GNU Programs2674 +Node: Design Issues3474 +Node: Coding Conventions7414 +Node: Make the Compiler Find the Bugs9382 +Node: Factor Out Repeated Code12926 +Node: Debugging is For Users Too14992 +Node: Don't Trust the File System Contents15723 +Node: The File System Is Being Modified17005 +Node: Tools18401 +Node: Using the GNU Portability Library19602 +Node: Documentation23240 +Node: Testing26612 +Node: Bugs26953 +Node: Distributions28695 +Node: Internationalisation29728 +Node: Security30197 +Node: Making Releases41557 +Node: GNU Free Documentation License43671 + +End Tag Table diff --git a/doc/find-maint.texi b/doc/find-maint.texi new file mode 100644 index 0000000..a6c65b8 --- /dev/null +++ b/doc/find-maint.texi @@ -0,0 +1,1141 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename find-maint.info +@settitle Maintaining Findutils +@c For double-sided printing, uncomment: +@c @setchapternewpage odd +@c %**end of header + +@include versionmaint.texi + +@iftex +@finalout +@end iftex + +@dircategory GNU organization +@direntry +* Maintaining Findutils: (find-maint). Maintaining GNU findutils +@end direntry + +@copying +This manual explains how GNU findutils is maintained, how changes should +be made and tested, and what resources exist to help developers. + +This is edition @value{EDITION}, for findutils version @value{VERSION}. + +Copyright @copyright{} 2007, 2008, 2010-2015 Free Software Foundation, +Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover +Texts. +A copy of the license is included in the section entitled ``GNU +Free Documentation License''. +@end copying + +@titlepage +@title Maintaining Findutils +@subtitle Edition @value{EDITION}, for GNU findutils version @value{VERSION} +@subtitle @value{UPDATED} +@author by James Youngman + +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top, Introduction, (dir), (dir) +@top Maintaining GNU Findutils + +@insertcopying +@end ifnottex + +@menu +* Introduction:: +* Maintaining GNU Programs:: +* Design Issues:: +* Coding Conventions:: +* Tools:: +* Using the GNU Portability Library:: +* Documentation:: +* Testing:: +* Bugs:: +* Distributions:: +* Internationalisation:: +* Security:: +* Making Releases:: +* GNU Free Documentation License:: +@end menu + + + + + +@node Introduction +@chapter Introduction + +This document explains how to contribute to and maintain GNU +Findutils. It concentrates on developer-specific issues. For +information about how to use the software please refer to +@xref{Introduction, ,Introduction,find,The Findutils manual}. + +This manual aims to be useful without necessarily being verbose. It's +also a recent document, so there will be a many areas in which +improvements can be made. If you find that the document misses out +important information or any part of the document is be so terse as to +be unuseful, please ask for help on the @email{bug-findutils@@gnu.org} +mailing list. We'll try to improve this document too. + + +@node Maintaining GNU Programs +@chapter Maintaining GNU Programs + +GNU Findutils is part of the GNU Project and so there are a number of +documents which set out standards for the maintenance of GNU +software. + +@table @file +@item standards.texi +GNU Project Coding Standards. All changes to findutils should comply +with these standards. In some areas we go somewhat beyond the +requirements of the standards, but these cases are explained in this +manual. +@item maintain.texi +Information for Maintainers of GNU Software. This document provides +guidance for GNU maintainers. Everybody with commit access should +read this document. Everybody else is welcome to do so too, of +course. +@end table + + + +@node Design Issues +@chapter Design Issues + +The findutils package is installed on many many systems, usually as a +fundamental component. The programs in the package are often used in +order to successfully boot or fix the system. + +This fact means that for findutils we bear in mind considerations that +may not apply so much as for other packages. For example, the fact +that findutils is often a base component motivates us to +@itemize +@item Limit dependencies on libraries +@item Avoid dependencies on other large packages (for example, interpreters) +@item Be conservative when making changes to the 'stable' release branch +@end itemize + +All those considerations come before functionality. Functional +enhancements are still made to findutils, but these are almost +exclusively introduced in the 'development' release branch, to allow +extensive testing and proving. + +Sometimes it is useful to have a priority list to provide guidance +when making design trade-offs. For findutils, that priority list is: + +@enumerate +@item Correctness +@item Standards compliance +@item Security +@item Backward compatibility +@item Performance +@item Functionality +@end enumerate + +For example, we support the @code{-exec} action because POSIX +compliance requires this, even though there are security problems with +it and we would otherwise prefer people to use @code{-execdir}. There +are also cases where some performance is sacrificed in the name of +security. For example, the sanity checks that @code{find} performs +while traversing a directory tree may slow it down. We adopt +functional changes, and functional changes are allowed to make +@code{find} slower, but only if there is no detectable impact on users +who don't use the feature. + +Backward-incompatible changes do get made in order to comply with +standards (for example the behaviour of @code{-perm -...} changed in +order to comply with POSIX). However, they don't get made in order to +provide better ease of use; for example the semantics of @code{-size +-2G} are almost always unexpected by users, but we retain the current +behaviour because of backward compatibility and for its similarity to +the block-rounding behaviour of @code{-size -30}. We might introduce +a change which does not have the unfortunate rounding behaviour, but +we would choose another syntax (for example @code{-size '<2G'}) for +this. + +In a general sense, we try to do test-driven development of the +findutils code; that is, we try to implement test cases for new +features and bug fixes before modifying the code to make the test +pass. Some features of the code are tested well, but the test +coverage for other features is less good. If you are about to modify +the code for a predicate and aren't sure about the test coverage, use +@code{grep} on the test directories and measure the coverage with +@code{lcov} or another test coverage tool. + +You should be able to use the @code{coverage} Makefile target (it's +defined in @code{maint.mk} to generate a test coverage report for +findutils. Due to limitations in @code{lcov}, this only works if +your build directory is the same asthe source directory (that is, +you're not using a VPATH build configuration). + +Lastly, we try not to depend on having a ``working system''. The +findutils suite is used for diagnosis of problems, and this applies +especially to @code{find}. We should ensure that @code{find} still +works on relatively broken systems, for example systems with damaged +@file{/etc/passwd} or @code{/etc/fstab} files. Another interesting +example is the case where a system is a client of one or more +unresponsive NFS servers. On such a system, if you try to stat all +mount points, your program will hang indefinitely, waiting for the +remote NFS server to respond. + +Another interesting but unusual case is broken NFS servers and corrupt +filesystems; sometimes they return `impossible' file modes. It's +important that find does not entirely fail when encountering such a +file. + + +@node Coding Conventions +@chapter Coding Conventions + +Coding style documents which set out to establish a uniform look and +feel to source code have worthy goals, for example greater ease of +maintenance and readability. However, I do not believe that in +general coding style guide authors can envisage every situation, and +it is always possible that it might on occasion be necessary to break +the letter of the style guide in order to honour its spirit, or to +better achieve the style guide's goals. + +I've certainly seen many style guides outside the free software world +which make bald statements such as ``functions shall have exactly one +return statement''. The desire to ensure consistency and obviousness +of control flow is laudable, but it is all too common for such bald +requirements to be followed unthinkingly. Certainly I've seen such +coding standards result in unmaintainable code with terrible +infelicities such as functions containing @code{if} statements nested +nine levels deep. I suppose such coding standards don't survive in +free software projects because they tend to drive away potential +contributors or tend to generate heated discussions on mailing lists. +Equally, a nine-level-deep function in a free software program would +quickly get refactored, assuming it is obvious what the function is +supposed to do... + +Be that as it may, the approach I will take for this document is to +explain some idioms and practices in use in the findutils source code, +and leave it up to the reader's engineering judgement to decide which +considerations apply to the code they are working on, and whether or +not there is sufficient reason to ignore the guidance in current +circumstances. + + +@menu +* Make the Compiler Find the Bugs:: +* Factor Out Repeated Code:: +* Debugging is For Users Too:: +* Don't Trust the File System Contents:: +* The File System Is Being Modified:: +@end menu + +@node Make the Compiler Find the Bugs +@section Make the Compiler Find the Bugs + +Finding bugs is tedious. If I have a filesystem containing two +million files, and a find command line should print one million of +them, but in fact it misses out 1%, you can tell the program is +printing the wrong result only if you know the right answer for that +filesystem at that time. If you don't know this, you may just not +find out about that bug. For this reason it is important to have a +comprehensive test suite. + +The test suite is of course not the only way to find the bugs. The +findutils source code makes liberal use of the assert macro. While on +the one hand these might be a performance drain, the performance +impact of most of these is negligible compared to the time taken to +fetch even one sector from a disk drive. + +Assertions should not be used to check the results of operations which +may be affected by the program's external environment. For example, +never assert that a file could be opened successfully. Errors +relating to problems with the program's execution environment should +be diagnosed with a user-oriented error message. An assertion failure +should always denote a bug in the program. + +Don't use @code{assert} to catch not-fuly-implemented features of your +code. Finish the implementation, disable the code, or leave the +unfinished version on a local branch. + +Several programs in the findutils suite perform self-checks. See for +example the function @code{pred_sanity_check} in @file{find/pred.c}. +This is generally desirable. + +There are also a number of small ways in which we can help the +compiler to find the bugs for us. + +@subsection Constants in Equality Testing + +It's a common error to write @code{=} when @code{==} is meant. +Sometimes this happens in new code and is simply due to finger +trouble. Sometimes it is the result of the inadvertent deletion of a +character. In any case, there is a subset of cases where we can +persuade the compiler to generate an error message when we make this +mistake; this is where the equality test is with a constant. + +This is an example of a vulnerable piece of code. + +@example +if (x == 2) + ... +@end example + +A simple typo converts the above into + +@example +if (x = 2) + ... +@end example + +We've introduced a bug; the condition is always true, and the value of +@code{x} has been changed. However, a simple change to our practice +would have made us immune to this problem: + +@example +if (2 == x) + ... +@end example + +Usually, the Emacs keystroke @kbd{M-t} can be used to swap the operands. + + +@subsection Spelling of ASCII NUL + +Strings in C are just sequences of characters terminated by a NUL. +The ASCII NUL character has the numerical value zero. It is normally +represented in C code as @samp{\0}. Here is a typical piece of C +code: + +@example +*p = '\0'; +@end example + +Consider what happens if there is an unfortunate typo: + +@example +*p = '0'; +@end example + +We have changed the meaning of our program and the compiler cannot +diagnose this as an error. Our string is no longer terminated. Bad +things will probably happen. It would be better if the compiler could +help us diagnose this problem. + +In C, the type of @code{'\0'} is in fact int, not char. This provides +us with a simple way to avoid this error. The constant @code{0} has +the same value and type as the constant @code{'\0'}. However, it is +not as vulnerable to typos. For this reason I normally prefer to +use this code: + +@example +*p = 0; +@end example + + +@node Factor Out Repeated Code +@section Factor Out Repeated Code + +Repeated code imposes a greater maintenance burden and increases the +exposure to bugs. For example, if you discover that something you +want to implement has some similarity with an existing piece of code, +don't cut and paste it. Instead, factor the code out. The risk of +cutting and pasting the code, particularly if you do this several +times, is that you end up with several copies of the same code. + +If the original code had a bug, you now have N places where this needs +to be fixed. It's all to easy to miss some out when trying to fix the +bug. Equally, it's quite possible that when pasting the code into +some function, the pasted code was not quite adapted correctly to its +new environment. To pick a contrived example, perhaps it modifies a +global variable which it that code shouldn't be touching in its new +home. Worse, perhaps it makes some unstated assumption about the +nature of the input arguments which is in fact not true for the +context of the now duplicated code. + +A good example of the use of refactoring in findutils is the +@code{collect_arg} function in @file{find/parser.c}. A less clear-cut +but larger example is the factoring out of code which would otherwise +have been duplicated between @file{find/oldfind.c} and +@code{find/ftsfind.c}. + +The findutils test suite is comprehensive enough that refactoring code +should not generally be a daunting prospect from a testing point of +view. Nevertheless there are some areas which are only +lightly-tested: + +@enumerate +@item Tests on the ages of files +@item Code which deals with the values returned by operating system calls (for example handling of ENOENT) +@item Code dealing with OS limits (for example, limits on path length +or exec arguments) +@item Code relating to features not all systems have (for example +Solaris Doors) +@end enumerate + +Please exercise caution when working in those areas. + + +@node Debugging is For Users Too +@section Debugging is For Users Too + +Debug and diagnostic code is often used to verify that a program is +working in the way its author thinks it should be. But users are +often uncertain about what a program is doing, too. Exposing them a +little more diagnostic information can help. Much of the diagnostic +code in @code{find}, for example, is controlled by the @samp{-D} flag, +as opposed to C preprocessor directives. + +Making diagnostic messages available to users also means that the +phrasing of the diagnostic messages becomes important, too. + + +@node Don't Trust the File System Contents +@section Don't Trust the File System Contents + +People use @code{find} to search in directories created by other +people. Sometimes they do this to check to suspicious activity (for +example to look for new setuid binaries). This means that it would be +bad if @code{find} were vulnerable to, say, a security problem +exploitable by constructing a specially-crafted filename. The same +consideration would apply to @code{locate} and @code{updatedb}. + +Henry Spencer said this well in his fifth commandment: +@quotation +Thou shalt check the array bounds of all strings (indeed, all arrays), +for surely where thou typest @samp{foo} someone someday shall type +@samp{supercalifragilisticexpialidocious}. +@end quotation + +Symbolic links can often be a problem. If @code{find} calls +@code{lstat} on something and discovers that it is a directory, it's +normal for @code{find} to recurse into it. Even if the @code{chdir} +system call is used immediately, there is still a window of +opportunity between the @code{lstat} and the @code{chdir} in which a +malicious person could rename the directory and substitute a symbolic +link to some other directory. + +@node The File System Is Being Modified +@section The File System Is Being Modified + +The filesystem gets modified while you are traversing it. For, +example, it's normal for files to get deleted while @code{find} is +traversing a directory. Issuing an error message seems helpful when a +file is deleted from the one directory you are interested in, but if +@code{find} is searching 15000 directories, such a message becomes +less helpful. + +Bear in mind also that it is possible for the directory @code{find} is +currently searching could be moved to another point in the filesystem, +and that the directory in which @code{find} was started could be +deleted. + +Henry Spencer's sixth commandment is also apposite here: +@quotation +If a function be advertised to return an error code in the event of +difficulties, thou shalt check for that code, yea, even though the +checks triple the size of thy code and produce aches in thy typing +fingers, for if thou thinkest ``it cannot happen to me'', the gods +shall surely punish thee for thy arrogance. +@end quotation + +There are a lot of files out there. They come in all dates and +sizes. There is a condition out there in the real world to exercise +every bit of the code base. So we try to test that code base before +someone falls over a bug. + + +@node Tools +@chapter Tools +Most of the tools required to build findutils are mentioned in the +file @file{README-hacking}. We also use some other tools: + +@table @asis +@item System call traces +Much of the execution time of find is spent waiting for filesystem +operations. A system call trace (for example, that provided by +@code{strace}) shows what system calls are being made. Using this +information we can work to remove unnecessary file system operations. + +@item Valgrind +Valgrind is a tool which dynamically verifies the memory accesses a +program makes to ensure that they are valid (for example, that the +behaviour of the program does not in any way depend on the contents of +uninitialized memory). + +@item DejaGnu +DejaGnu is the test framework used to run the findutils test suite +(the @code{runtest} program is part of DejaGnu). It would be ideal if +everybody building @code{findutils} also ran the test suite, but many +people don't have DejaGnu installed. When changes are made to +findutils, DejaGnu is invoked a lot. @xref{Testing}, for more +information. +@end table + +@node Using the GNU Portability Library +@chapter Using the GNU Portability Library +The Gnulib library (@url{http://www.gnu.org/software/gnulib/}) makes a +variety of systems look more like a GNU/Linux system and also applies +a bunch of automatic bug fixes and workarounds. Some of these also +apply to GNU/Linux systems too. For example, the Gnulib regex +implementation is used when we determine that we are building on a +GNU libc system with a bug in the regex implementation. + + +@section How and Why we Import the Gnulib Code +Gnulib does not have a release process which results in a source +tarball you can download. Instead, the code is simply made available +by GIT, so we import gnulib via the submodule feature. The bootstrap +script performs the necessary steps. + +Findutils does not use all the Gnulib code. The modules we need are +listed in the file @file{bootstrap.conf}. + +The upshot of all this is that we can use the findutils git repository +to track which version of Gnulib every findutils release uses. + +A small number of files are installed by automake and will therefore +vary according to which version of automake was used to generate a +release. This includes for example boiler-plate GNU files such as +@file{ABOUT-NLS}, @file{INSTALL} and @file{COPYING}. + + +@section How We Fix Gnulib Bugs +Gnulib is used by quite a number of GNU projects, and this means that +it gets plenty of testing. Therefore there are relatively few bugs in +the Gnulib code, but it does happen from time to time. + +However, since there is no waiting around for a Gnulib source release +tarball, Gnulib bugs are generally fixed quickly. Here is an outline +of the way we would contribute a fix to Gnulib (assuming you know it +is not already fixed in the current Gnulib git tree): + +@table @asis +@item Check you already completed a copyright assignment for Gnulib +@item Begin with a vanilla git tree +Download the Findutils source code from git (or use the tree you have +already) +@item Run the bootstrap script +@item Run configure +@item Build findutils +Build findutils and run the test suite, which should pass. In our +example we assume you have just noticed a bug in Gnulib, not that +recent Gnulib changes broke the findutils regression tests. +@item Write a test case +If in fact Gnulib did break the findutils regression tests, you can probably +skip this step, since you already have a test case demonstrating the problem. +Otherwise, write a findutils test case for the bug and/or a Gnulib test case. +@item Fix the Gnulib bug +Make sure your editor follows symbolic links so that your changes to +@file{gnulib/...} actually affect the files in the git working +directory you checked out earlier. Observe that your test now passes. +@item Prepare a Gnulib patch +In the gnulib subdirectory, use @code{git format-patch} to prepare the +patch. Follow the normal usage for checkin comments (take a look at +the output of @code{git log}). Check that the patch conforms with the +GNU coding standards, and email it to the Gnulib mailing list. +@item Wait for the patch to be applied +Once your bug fix has been applied, you can update your gnulib +directory from git, and then check in the change to the submodule as +normal (you can check @code{git help submodule} for details). +@end table + +There is an alternative to the method above; it is possible to store +local diffs to be patched into gnulib beneath the +@file{gnulib-local}. Normally however, there is no need for this, +since gnulib updates are very prompt. + + +@node Documentation +@chapter Documentation + +The findutils git tree includes several different types of +documentation. + +@section git change log +The git change log for the source tree contains check-in messages +which describe each check-in. These have a standard format: + +@smallexample +Summary of the change. + +(ChangeLog-style detail) +@end smallexample + +Here, the format of the detail part follows the standard GNU ChangeLog +style, but without whitespace in the left margin and without +author/date headers. Take a look at the output of @code{git log} to +see some examples. The README-hacking file also contains an example +with an explanation. + +@section User Documentation +User-oriented documentation is provided as manual pages and in +Texinfo. See +@ref{Introduction,,Introduction,find,The Findutils manual}. + +Please make sure both sets of documentation are updated if you make a +change to the code. The GNU coding standards do not normally call for +maintaining manual pages on the grounds of effort duplication. +However, the manual page format is more convenient for quick +reference, and so it's worth maintaining both types of documentation. +However, the manual pages are normally rather more terse than the +Texinfo documentation. The manual pages are suitable for reference +use, but the Texinfo manual should also include introductory and +tutorial material. + + +@section Build Guidance + +@table @file +@item ABOUT-NLS +Describes the Free Translation Project, the translation status of +various GNU projects, and how to participate by translating an +application. +@item AUTHORS +Lists the authors of findutils. +@item COPYING +The copyright license covering findutils; currently, the GNU GPL, +version 3. +@item INSTALL +Generic installation instructions for installing GNU programs. +@item README +Information about how to compile findutils in particular +@item README-alpha +A README file which is included with testing releases of findutils. +@item README-hacking +Describes how to build findutils from the code in git. +@item THANKS +Thanks for people who contributed to findutils. Generally, if +someone's contribution was significant enough to need a copyright +assignment, their name should go in here. +@item TODO +Mainly obsolete. Please add bugs to the Savannah bug tracker instead +of adding entries to this file. +@end table + + +@section Release Information +@table @file +@item NEWS +Enumerates the user-visible change in each release. Typical changes +are fixed bugs, functionality changes and documentation changes. +Include the date when a release is made. +@item ChangeLog +This file enumerates all changes to the findutils source code (with +the possible exception of @file{.cvsignore} and @code{.gitignore} +changes). The level of detail used for this file should be sufficient +to answer the questions ``what changed?'' and ``why was it changed?''. +The file is generated from the git commit messages during @code{make dist}. +If a change fixes a bug, always give the bug reference number in the +@file{NEWS} file and of course also in the checkin message. +In general, it should be possible to enumerate all +material changes to a function by searching for its name in +@file{ChangeLog}. Mention when each release is made. +@end table + +@node Testing +@chapter Testing +This chapter will explain the general procedures for adding tests to +the test suite, and the functions defined in the findutils-specific +DejaGnu configuration. Where appropriate references will be made to +the DejaGnu documentation. + +@node Bugs +@chapter Bugs + +Bugs are logged in the Savannah bug tracker +@url{http://savannah.gnu.org/bugs/?group=findutils}. The tracker +offers several fields but their use is largely obvious. The +life-cycle of a bug is like this: + + +@table @asis +@item Open +Someone, usually a maintainer, a distribution maintainer or a user, +creates a bug by filling in the form. They fill in field values as +they see fit. This will generate an email to +@email{bug-findutils@@gnu.org}. + +@item Triage +The bug hangs around with @samp{Status=None} until someone begins to +work on it. At that point they set the ``Assigned To'' field and will +sometimes set the status to @samp{In Progress}, especially if the bug +will take a while to fix. + +@item Non-bugs +Quite a lot of reports are not actually bugs; for these the usual +procedure is to explain why the problem is not a bug, set the status +to @samp{Invalid} and close the bug. Make sure you set the +@samp{Assigned to} field to yourself before closing the bug. + +@item Fixing +When you commit a bug fix into git (or in the case of a contributed +patch, commit the change), mark the bug as @samp{Fixed}. Make sure +you include a new test case where this is relevant. If you can figure +out which releases are affected, please also set the @samp{Release} +field to the earliest release which is affected by the bug. +Indicate which source branch the fix is included in (for example, +4.2.x or 4.3.x). Don't close the bug yet. + +@item Release +When a release is made which includes the bug fix, make sure the bug +is listed in the NEWS file. Once the release is made, fill in the +@samp{Fixed Release} field and close the bug. +@end table + + +@node Distributions +@chapter Distributions +Almost all GNU/Linux distributions include findutils, but only some of +them have a package maintainer who is a member of the mailing list. +Distributions don't often feed back patches to the +@email{bug-findutils@@gnu.org} list, but on the other hand many of +their patches relate only to standards for file locations and so +forth, and are therefore distribution specific. On an irregular basis +I check the current patches being used by one or two distributions, +but the total number of GNU/Linux distributions is large enough that +we could not hope to cover them all. + +Often, bugs are raised against a distribution's bug tracker instead of +GNU's. Periodically (about every six months) I take a look at some +of the more accessible bug trackers to indicate which bugs have been +fixed upstream. + +Many distributions include both findutils and the slocate package, +which provides a replacement @code{locate}. + + +@node Internationalisation +@chapter Internationalisation +Translation is essentially automated from the maintainer's point of +view. The TP mails the maintainer when a new PO file is available, +and we just download it and check it in. We copy the @file{.po} files +into the git repository. For more information, please see +@url{http://translationproject.org/domain/findutils.html}. + + +@node Security +@chapter Security + +See @ref{Security Considerations, ,Security Considerations,find,The +Findutils manual}, for a full description of the findutils approach to +security considerations and discussion of particular tools. + +If someone reports a security bug publicly, we should fix this as +rapidly as possible. If necessary, this can mean issuing a fixed +release containing just the one bug fix. We try to avoid issuing +releases which include both significant security fixes and functional +changes. + +Where someone reports a security problem privately, we generally try +to construct and test a patch without pushing the intermediate code to +the public repository. + +Once everything has been tested, this allows us to make a release and +push the patch. The advantage of doing things this way is that we +avoid situations where people watching for git commits can figure out +and exploit a security problem before a fixed release is available. + +It's important that security problems be fixed promptly, but don't +rush so much that things go wrong. Make sure the new release really +fixes the problem. It's usually best not to include functional +changes in your security-fix release. + +If the security problem is serious, send an alert to +@email{vendor-sec@@lst.de}. The members of the list include most +GNU/Linux distributions. The point of doing this is to allow them to +prepare to release your security fix to their customers, once the fix +becomes available. Here is an example alert:- + +@smallexample +GNU findutils heap buffer overrun (potential privilege escalation) + + + +I. BACKGROUND +============= + +GNU findutils is a set of programs which search for files on Unix-like +systems. It is maintained by the GNU Project of the Free Software +Foundation. For more information, see +@url{http://www.gnu.org/software/findutils}. + + +II. DESCRIPTION +=============== + +When GNU locate reads filenames from an old-format locate database, +they are read into a fixed-length buffer allocated on the heap. +Filenames longer than the 1026-byte buffer can cause a buffer overrun. +The overrunning data can be chosen by any person able to control the +names of filenames created on the local system. This will normally +include all local users, but in many cases also remote users (for +example in the case of FTP servers allowing uploads). + +III. ANALYSIS +============= + +Findutils supports three different formats of locate database, its +native format "LOCATE02", the slocate variant of LOCATE02, and a +traditional ("old") format that locate uses on other Unix systems. + +When locate reads filenames from a LOCATE02 database (the default +format), the buffer into which data is read is automatically extended +to accommodate the length of the filenames. + +This automatic buffer extension does not happen for old-format +databases. Instead a 1026-byte buffer is used. When a longer +pathname appears in the locate database, the end of this buffer is +overrun. The buffer is allocated on the heap (not the stack). + +If the locate database is in the default LOCATE02 format, the locate +program does perform automatic buffer extension, and the program is +not vulnerable to this problem. The software used to build the +old-format locate database is not itself vulnerable to the same +attack. + +Most installations of GNU findutils do not use the old database +format, and so will not be vulnerable. + + +IV. DETECTION +============= + +Software +-------- +All existing releases of findutils are affected. + + +Installations +------------- + +To discover the longest path name on a given system, you can use the +following command (requires GNU findutils and GNU coreutils): + +@verbatim +find / -print0 | tr -c '\0' 'x' | tr '\0' '\n' | wc -L +@end verbatim + +V. EXAMPLE +========== + +This section includes a shell script which determines which of a list +of locate binaries is vulnerable to the problem. The shell script has +been tested only on glibc based systems having a mktemp binary. + +NOTE: This script deliberately overruns the buffer in order to +determine if a binary is affected. Therefore running it on your +system may have undesirable effects. We recommend that you read the +script before running it. + +@verbatim +#! /bin/sh +set +m +if vanilla_db="$(mktemp nicedb.XXXXXX)" ; then + if updatedb --prunepaths="" --old-format --localpaths="/tmp" \ + --output="$@{vanilla_db@}" ; then + true + else + rm -f "$@{vanilla_db@}" + vanilla_db="" + echo "Failed to create old-format locate database; skipping the sanity checks" >&2 + fi +fi + +make_overrun_db() @{ + # Start with a valid database + cat "$@{vanilla_db@}" + # Make the final entry really long + dd if=/dev/zero bs=1 count=1500 2>/dev/null | tr '\000' 'x' +@} + + + +ulimit -c 0 + +usage() @{ echo "usage: $0 binary [binary...]" >&2; exit $1; @} +[ $# -eq 0 ] && usage 1 + +bad="" +good="" +ugly="" +if dbfile="$(mktemp nasty.XXXXXX)" +then + make_overrun_db > "$dbfile" + for locate ; do + ver="$locate = $("$locate" --version | head -1)" + if [ -z "$vanilla_db" ] || "$locate" -d "$vanilla_db" "" >/dev/null ; then + "$locate" -d "$dbfile" "" >/dev/null + if [ $? -gt 128 ] ; then + bad="$bad +vulnerable: $ver" + else + good="$good +good: $ver" + fi + else + # the regular locate failed + ugly="$ugly +buggy, may or may not be vulnerable: $ver" + fi + done + rm -f "$@{dbfile@}" "$@{vanilla_db@}" + # good: unaffected. bad: affected (vulnerable). + # ugly: doesn't even work for a normal old-format database. + echo "$good" + echo "$bad" + echo "$ugly" +else + exit 1 +fi +@end verbatim + + + + +VI. VENDOR RESPONSE +=================== + +The GNU project discovered the problem while 'locate' was being worked +on; this is the first public announcement of the problem. + +The GNU findutils mantainer has issued a patch as p[art of this +announcement. The patch appears below. + +A source release of findutils-4.2.31 will be issued on 2007-05-30. +That release will of course include the patch. The patch will be +committed to the public CVS repository at the same time. Public +announcements of the release, including a description of the bug, will +be made at the same time as the release. + +A release of findutils-4.3.x will follow and will also include the +patch. + + +VII. PATCH +========== + +This patch should apply to findutils-4.2.23 and later. +Findutils-4.2.23 was released almost two years ago. +@verbatim +Index: locate/locate.c +=================================================================== +RCS file: /cvsroot/findutils/findutils/locate/locate.c,v +retrieving revision 1.58.2.2 +diff -u -p -r1.58.2.2 locate.c +--- locate/locate.c 22 Apr 2007 16:57:42 -0000 1.58.2.2 ++++ locate/locate.c 28 May 2007 10:18:16 -0000 +@@@@ -124,9 +124,9 @@@@ extern int errno; + + #include "locatedb.h" + #include <getline.h> +-#include "../gnulib/lib/xalloc.h" +-#include "../gnulib/lib/error.h" +-#include "../gnulib/lib/human.h" ++#include "xalloc.h" ++#include "error.h" ++#include "human.h" + #include "dirname.h" + #include "closeout.h" + #include "nextelem.h" +@@@@ -468,10 +468,36 @@@@ visit_justprint_unquoted(struct process_ + return VISIT_CONTINUE; + @} + ++static void ++toolong (struct process_data *procdata) ++@{ ++ error (EXIT_FAILURE, 0, ++ _("locate database %s contains a " ++ "filename longer than locate can handle"), ++ procdata->dbfile); ++@} ++ ++static void ++extend (struct process_data *procdata, size_t siz1, size_t siz2) ++@{ ++ /* Figure out if the addition operation is safe before performing it. */ ++ if (SIZE_MAX - siz1 < siz2) ++ @{ ++ toolong (procdata); ++ @} ++ else if (procdata->pathsize < (siz1+siz2)) ++ @{ ++ procdata->pathsize = siz1+siz2; ++ procdata->original_filename = x2nrealloc (procdata->original_filename, ++ &procdata->pathsize, ++ 1); ++ @} ++@} ++ + static int + visit_old_format(struct process_data *procdata, void *context) + @{ +- register char *s; ++ register size_t i; + (void) context; + + /* Get the offset in the path where this path info starts. */ +@@@@ -479,20 +505,35 @@@@ visit_old_format(struct process_data *pr + procdata->count += getw (procdata->fp) - LOCATEDB_OLD_OFFSET; + else + procdata->count += procdata->c - LOCATEDB_OLD_OFFSET; ++ assert(procdata->count > 0); + +- /* Overlay the old path with the remainder of the new. */ +- for (s = procdata->original_filename + procdata->count; ++ /* Overlay the old path with the remainder of the new. Read ++ * more data until we get to the next filename. ++ */ ++ for (i=procdata->count; + (procdata->c = getc (procdata->fp)) > LOCATEDB_OLD_ESCAPE;) +- if (procdata->c < 0200) +- *s++ = procdata->c; /* An ordinary character. */ +- else +- @{ +- /* Bigram markers have the high bit set. */ +- procdata->c &= 0177; +- *s++ = procdata->bigram1[procdata->c]; +- *s++ = procdata->bigram2[procdata->c]; +- @} +- *s-- = '\0'; ++ @{ ++ if (procdata->c < 0200) ++ @{ ++ /* An ordinary character. */ ++ extend (procdata, i, 1u); ++ procdata->original_filename[i++] = procdata->c; ++ @} ++ else ++ @{ ++ /* Bigram markers have the high bit set. */ ++ extend (procdata, i, 2u); ++ procdata->c &= 0177; ++ procdata->original_filename[i++] = procdata->bigram1[procdata->c]; ++ procdata->original_filename[i++] = procdata->bigram2[procdata->c]; ++ @} ++ @} ++ ++ /* Consider the case where we executed the loop body zero times; we ++ * still need space for the terminating null byte. ++ */ ++ extend (procdata, i, 1u); ++ procdata->original_filename[i] = 0; + + procdata->munged_filename = procdata->original_filename; +@end verbatim + + +VIII. THANKS +============ + +Thanks to Rob Holland <rob@@inversepath.com> and Tavis Ormandy. + + +VIII. CVE INFORMATION +===================== + +No CVE candidate number has yet been assigned for this vulnerability. +If someone provides one, I will include it in the public announcement +and change logs. +@end smallexample + +The original announcement above was sent out with a cleartext PGP +signature, of course, but that has been omitted from the example. + +Once a fixed release is available, announce the new release using the +normal channels. Any CVE number assigned for the problem should be +included in the @file{ChangeLog} and @file{NEWS} entries. See +@url{http://cve.mitre.org/} for an explanation of CVE numbers. + + + +@node Making Releases +@chapter Making Releases +This section will explain how to make a findutils release. For the +time being here is a terse description of the main steps: + +@enumerate +@item Commit changes; make sure your working directory has no +uncommitted changes. +@item Test; make sure that all changes you have made have tests, and +that the tests pass. Verify this with @code{make distcheck}. +@item Bugs; make sure all Savannah bug entries fixed in this release +are fixed. +@item NEWS; make sure that the NEWS and configure.in file are updated +with the new release number (and checked in). +@item Build the release tarball; do this with @code{make distcheck}. +Copy the tarball somewhere safe. +@item Tag the release; findutils releases are tagged like this for +example: v4.5.5. Previously a different format was in use: +FINDUTILS_4_3_8-1. You can create a tag with the a command like this: +@code{git tag -s -m "Findutils release v4.5.7" v4.5.7}. +@item Prepare the upload and upload it. +@xref{Automated FTP Uploads, ,Automated FTP +Uploads, maintain, Information for Maintainers of GNU Software}, +for detailed upload instructions. +@item Make a release announcement; include an extract from the NEWS +file which explains what's changed. Announcements for test releases +should just go to @email{bug-findutils@@gnu.org}. Announcements for +stable releases should go to @email{info-gnu@@gnu.org} as well. +@item Bump the release numbers in git; edit the @file{configure.in} +and @file{NEWS} files to advance the release numbers. For example, +if you have just released @samp{4.6.2}, bump the release number to +@samp{4.6.3-git}. The point of the @samp{-git} suffix here is that a +findutils binary built from git will bear a release number indicating +it's not built from the ``official'' source release. +@item Close bugs; any bugs recorded on Savannah which were fixed in this +release should now be marked as closed. Update the @samp{Fixed +Release} field of these bugs appropriately and make sure the +@samp{Assigned to} field is populated. +@end enumerate + + +@node GNU Free Documentation License +@appendix GNU Free Documentation License +@include fdl.texi + +@bye + +@comment texi related words used by Emacs' spell checker ispell.el + +@comment LocalWords: texinfo setfilename settitle setchapternewpage +@comment LocalWords: iftex finalout ifinfo DIR titlepage vskip pt +@comment LocalWords: filll dir samp dfn noindent xref pxref +@comment LocalWords: var deffn texi deffnx itemx emph asis +@comment LocalWords: findex smallexample subsubsection cindex +@comment LocalWords: dircategory direntry itemize + +@comment other words used by Emacs' spell checker ispell.el +@comment LocalWords: README fred updatedb xargs Plett Rendell akefile +@comment LocalWords: args grep Filesystems fo foo fOo wildcards iname +@comment LocalWords: ipath regex iregex expr fubar regexps +@comment LocalWords: metacharacters macs sr sc inode lname ilname +@comment LocalWords: sysdep noleaf ls inum xdev filesystems usr atime +@comment LocalWords: ctime mtime amin cmin mmin al daystart Sladkey rm +@comment LocalWords: anewer cnewer bckw rf xtype uname gname uid gid +@comment LocalWords: nouser nogroup chown chgrp perm ch maxdepth +@comment LocalWords: mindepth cpio src CD AFS statted stat fstype ufs +@comment LocalWords: nfs tmp mfs printf fprint dils rw djm Nov lwall +@comment LocalWords: POSIXLY fls fprintf strftime locale's EDT GMT AP +@comment LocalWords: EST diff perl backquotes sprintf Falstad Oct cron +@comment LocalWords: eg vmunix mkdir afs allexec allwrite ARG bigram +@comment LocalWords: bigrams cd chmod comp crc CVS dbfile eof +@comment LocalWords: fileserver filesystem fn frcode Ghazi Hnewc iXX +@comment LocalWords: joeuser Kaveh localpaths localuser LOGNAME +@comment LocalWords: Meyering mv netpaths netuser nonblank nonblanks +@comment LocalWords: ois ok Pinard printindex proc procs prunefs +@comment LocalWords: prunepaths pwd RFS rmadillo rmdir rsh sbins str +@comment LocalWords: su Timar ubins ug unstripped vf VM Weitzel +@comment LocalWords: wildcard zlogout basename execdir wholename iwholename +@comment LocalWords: timestamp timestamps Solaris FreeBSD OpenBSD POSIX diff --git a/doc/find.info b/doc/find.info new file mode 100644 index 0000000..4741b71 --- /dev/null +++ b/doc/find.info @@ -0,0 +1,186 @@ +This is find.info, produced by makeinfo version 5.2 from find.texi. + +This file documents the GNU utilities for finding files that match +certain criteria and performing various operations on them. + + Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003-2015 Free Software +Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled "GNU Free +Documentation License". +INFO-DIR-SECTION Basics +START-INFO-DIR-ENTRY +* Finding files: (find). Operating on files matching certain criteria. +END-INFO-DIR-ENTRY + +INFO-DIR-SECTION Individual utilities +START-INFO-DIR-ENTRY +* find: (find)Invoking find. Finding and acting on files. +* locate: (find)Invoking locate. Finding files in a database. +* updatedb: (find)Invoking updatedb. Building the locate database. +* xargs: (find)Invoking xargs. Operating on many files. +END-INFO-DIR-ENTRY + + +Indirect: +find.info-1: 1185 +find.info-2: 302079 + +Tag Table: +(Indirect) +Node: Top1185 +Node: Introduction3046 +Node: Scope5969 +Node: Overview7902 +Node: find Expressions9772 +Node: Finding Files11599 +Node: Name12064 +Node: Base Name Patterns12692 +Ref: Base Name Patterns-Footnote-114021 +Node: Full Name Patterns14233 +Node: Fast Full Name Search18236 +Node: Shell Pattern Matching21285 +Node: Links23374 +Node: Symbolic Links23809 +Node: Hard Links28865 +Node: Time31420 +Node: Age Ranges32395 +Node: Comparing Timestamps34079 +Node: Size36940 +Node: Type38785 +Node: Owner40455 +Node: Mode Bits41274 +Node: Contents46631 +Node: Directories47802 +Node: Filesystems53077 +Node: Combining Primaries With Operators54428 +Node: Actions56046 +Node: Print File Name56606 +Node: Print File Information57624 +Node: Escapes61570 +Node: Format Directives62311 +Node: Name Directives63557 +Node: Ownership Directives64539 +Node: Size Directives65543 +Node: Location Directives66912 +Node: Time Directives68023 +Node: Other Directives68921 +Node: Reserved and Unknown Directives69196 +Node: Time Formats70064 +Node: Time Components70525 +Node: Date Components71484 +Node: Combined Time Formats72296 +Node: Formatting Flags73175 +Node: Run Commands73785 +Node: Single File74143 +Node: Multiple Files76810 +Node: Unsafe File Name Handling81562 +Node: Safe File Name Handling83275 +Node: Unusual Characters in File Names84851 +Node: Limiting Command Size88013 +Node: Controlling Parallelism90449 +Node: Interspersing File Names96301 +Node: Querying98756 +Node: Delete Files101013 +Node: Adding Tests101660 +Node: Databases104299 +Node: Database Locations105016 +Node: Database Formats106463 +Node: LOCATE02 Database Format107571 +Node: Sample LOCATE02 Database109263 +Node: slocate Database Format109947 +Node: Old Database Format110955 +Node: Newline Handling114142 +Node: File Permissions115587 +Node: Mode Structure116165 +Node: Symbolic Modes119300 +Node: Setting Permissions120397 +Node: Copying Permissions122938 +Node: Changing Special Permissions123751 +Node: Conditional Executability125295 +Node: Multiple Changes125827 +Node: Umask and Protection127484 +Node: Numeric Modes128582 +Node: Date input formats130273 +Node: General date syntax132684 +Node: Calendar date items135662 +Node: Time of day items137660 +Node: Time zone items139857 +Node: Combined date and time of day items141109 +Node: Day of week items141965 +Node: Relative items in date strings142974 +Node: Pure numbers in date strings145777 +Node: Seconds since the Epoch146759 +Node: Specifying time zone rules148382 +Node: Authors of parse_datetime150756 +Ref: Authors of get_date150936 +Node: Configuration151899 +Node: Leaf Optimisation152680 +Node: d_type Optimisation153792 +Node: fts154094 +Node: Reference154698 +Node: Invoking find155043 +Node: Filesystem Traversal Options156525 +Node: Warning Messages157616 +Node: Optimisation Options159674 +Node: Debug Options161619 +Node: Find Expressions162669 +Node: Invoking locate163035 +Node: Invoking updatedb169222 +Node: Invoking xargs172884 +Node: xargs options173604 +Node: Invoking the shell from xargs178852 +Node: Regular Expressions182652 +Node: findutils-default regular expression syntax184131 +Node: awk regular expression syntax186632 +Node: egrep regular expression syntax188499 +Node: emacs regular expression syntax190802 +Node: gnu-awk regular expression syntax193326 +Node: grep regular expression syntax195789 +Node: posix-awk regular expression syntax198440 +Node: posix-basic regular expression syntax200738 +Node: posix-egrep regular expression syntax201039 +Node: posix-extended regular expression syntax201348 +Node: Environment Variables203819 +Node: Common Tasks206787 +Node: Viewing And Editing207212 +Node: Archiving208931 +Node: Cleaning Up210564 +Node: Strange File Names213452 +Node: Fixing Permissions215101 +Node: Classifying Files215665 +Node: Worked Examples216383 +Node: Deleting Files217088 +Node: Copying A Subset of Files230123 +Node: Updating A Timestamp File232142 +Node: Finding the Shallowest Instance238129 +Node: Security Considerations240065 +Node: Levels of Risk241632 +Ref: Levels of Risk-Footnote-1244430 +Node: Security Considerations for find244609 +Ref: Security Considerations for find-Footnote-1246933 +Node: Problems with -exec and filenames247006 +Node: Changing the Current Working Directory248640 +Node: O_NOFOLLOW250411 +Ref: O_NOFOLLOW-Footnote-1252465 +Node: Systems without O_NOFOLLOW252567 +Ref: Systems without O_NOFOLLOW-Footnote-1254720 +Node: Race Conditions with -exec254782 +Node: Race Conditions with -print and -print0257699 +Node: Security Considerations for xargs258628 +Node: Security Considerations for locate261130 +Node: Security Summary263511 +Node: Further Reading on Security264306 +Node: Error Messages265485 +Node: Error Messages From find266514 +Node: Error Messages From xargs271637 +Node: Error Messages From locate274101 +Node: Error Messages From updatedb275333 +Node: GNU Free Documentation License275740 +Node: Primary Index302079 + +End Tag Table diff --git a/doc/find.info-1 b/doc/find.info-1 new file mode 100644 index 0000000..fff2111 --- /dev/null +++ b/doc/find.info-1 @@ -0,0 +1,7261 @@ +This is find.info, produced by makeinfo version 5.2 from find.texi. + +This file documents the GNU utilities for finding files that match +certain criteria and performing various operations on them. + + Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003-2015 Free Software +Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled "GNU Free +Documentation License". +INFO-DIR-SECTION Basics +START-INFO-DIR-ENTRY +* Finding files: (find). Operating on files matching certain criteria. +END-INFO-DIR-ENTRY + +INFO-DIR-SECTION Individual utilities +START-INFO-DIR-ENTRY +* find: (find)Invoking find. Finding and acting on files. +* locate: (find)Invoking locate. Finding files in a database. +* updatedb: (find)Invoking updatedb. Building the locate database. +* xargs: (find)Invoking xargs. Operating on many files. +END-INFO-DIR-ENTRY + + +File: find.info, Node: Top, Next: Introduction, Up: (dir) + +GNU Findutils +************* + +This file documents the GNU utilities for finding files that match +certain criteria and performing various operations on them. + + Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003-2015 Free Software +Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled "GNU Free +Documentation License". + + This file documents the GNU utilities for finding files that match +certain criteria and performing various actions on them. + + This is edition 4.6.0, for 'find' version 4.6.0. + +* Menu: + +* Introduction:: Summary of the tasks this manual describes. +* Finding Files:: Finding files that match certain criteria. +* Actions:: Doing things to files you have found. +* Databases:: Maintaining file name databases. +* File Permissions:: How to control access to files. +* Date input formats:: Specifying literal times. +* Configuration:: Options you can select at compile time. +* Reference:: Summary of how to invoke the programs. +* Common Tasks:: Solutions to common real-world problems. +* Worked Examples:: Examples demonstrating more complex points. +* Security Considerations:: Security issues relating to findutils. +* Error Messages:: Explanations of some messages you might see. +* GNU Free Documentation License:: Copying and sharing this manual. +* Primary Index:: The components of 'find' expressions. + + +File: find.info, Node: Introduction, Next: Finding Files, Prev: Top, Up: Top + +1 Introduction +************** + +This manual shows how to find files that meet criteria you specify, and +how to perform various actions on the files that you find. The +principal programs that you use to perform these tasks are 'find', +'locate', and 'xargs'. Some of the examples in this manual use +capabilities specific to the GNU versions of those programs. + + GNU 'find' was originally written by Eric Decker, with enhancements +by David MacKenzie, Jay Plett, and Tim Wood. GNU 'xargs' was originally +written by Mike Rendell, with enhancements by David MacKenzie. GNU +'locate' and its associated utilities were originally written by James +Woods, with enhancements by David MacKenzie. The idea for 'find +-print0' and 'xargs -0' came from Dan Bernstein. The current maintainer +of GNU findutils (and this manual) is James Youngman. Many other people +have contributed bug fixes, small improvements, and helpful suggestions. +Thanks! + + To report a bug in GNU findutils, please use the form on the Savannah +web site at 'http://savannah.gnu.org/bugs/?group=findutils'. Reporting +bugs this way means that you will then be able to track progress in +fixing the problem. + + If you don't have web access, you can also just send mail to the +mailing list. The mailing list <bug-findutils@gnu.org> carries +discussion of bugs in findutils, questions and answers about the +software and discussion of the development of the programs. To join the +list, send email to <bug-findutils-request@gnu.org>. + + Please read any relevant sections of this manual before asking for +help on the mailing list. You may also find it helpful to read the +NON-BUGS section of the 'find' manual page. + + If you ask for help on the mailing list, people will be able to help +you much more effectively if you include the following things: + + * The version of the software you are running. You can find this out + by running 'locate --version'. + * What you were trying to do + * The _exact_ command line you used + * The _exact_ output you got (if this is very long, try to find a + smaller example which exhibits the same problem) + * The output you expected to get + + It may also be the case that the bug you are describing has already +been fixed, if it is a bug. Please check the most recent findutils +releases at <ftp://ftp.gnu.org/gnu/findutils> and, if possible, the +development branch at <ftp://alpha.gnu.org/gnu/findutils>. If you take +the time to check that your bug still exists in current releases, this +will greatly help people who want to help you solve your problem. +Please also be aware that if you obtained findutils as part of the +GNU/Linux 'distribution', the distributions often lag seriously behind +findutils releases, even the stable release. Please check the GNU FTP +site. + +* Menu: + +* Scope:: +* Overview:: +* find Expressions:: + + +File: find.info, Node: Scope, Next: Overview, Up: Introduction + +1.1 Scope +========= + +For brevity, the word "file" in this manual means a regular file, a +directory, a symbolic link, or any other kind of node that has a +directory entry. A directory entry is also called a "file name". A +file name may contain some, all, or none of the directories in a path +that leads to the file. These are all examples of what this manual +calls "file names": + + parser.c + README + ./budget/may-94.sc + fred/.cshrc + /usr/local/include/termcap.h + + A "directory tree" is a directory and the files it contains, all of +its subdirectories and the files they contain, etc. It can also be a +single non-directory file. + + These programs enable you to find the files in one or more directory +trees that: + + * have names that contain certain text or match a certain pattern; + * are links to certain files; + * were last used during a certain period of time; + * are within a certain size range; + * are of a certain type (regular file, directory, symbolic link, + etc.); + * are owned by a certain user or group; + * have certain access permissions or special mode bits; + * contain text that matches a certain pattern; + * are within a certain depth in the directory tree; + * or some combination of the above. + + Once you have found the files you're looking for (or files that are +potentially the ones you're looking for), you can do more to them than +simply list their names. You can get any combination of the files' +attributes, or process the files in many ways, either individually or in +groups of various sizes. Actions that you might want to perform on the +files you have found include, but are not limited to: + + * view or edit + * store in an archive + * remove or rename + * change access permissions + * classify into groups + + This manual describes how to perform each of those tasks, and more. + + +File: find.info, Node: Overview, Next: find Expressions, Prev: Scope, Up: Introduction + +1.2 Overview +============ + +The principal programs used for making lists of files that match given +criteria and running commands on them are 'find', 'locate', and 'xargs'. +An additional command, 'updatedb', is used by system administrators to +create databases for 'locate' to use. + + 'find' searches for files in a directory hierarchy and prints +information about the files it found. It is run like this: + + find [FILE...] [EXPRESSION] + +Here is a typical use of 'find'. This example prints the names of all +files in the directory tree rooted in '/usr/src' whose name ends with +'.c' and that are larger than 100 Kilobytes. + find /usr/src -name '*.c' -size +100k -print + + Notice that the wildcard must be enclosed in quotes in order to +protect it from expansion by the shell. + + 'locate' searches special file name databases for file names that +match patterns. The system administrator runs the 'updatedb' program to +create the databases. 'locate' is run like this: + + locate [OPTION...] PATTERN... + +This example prints the names of all files in the default file name +database whose name ends with 'Makefile' or 'makefile'. Which file +names are stored in the database depends on how the system administrator +ran 'updatedb'. + locate '*[Mm]akefile' + + The name 'xargs', pronounced EX-args, means "combine arguments." +'xargs' builds and executes command lines by gathering together +arguments it reads on the standard input. Most often, these arguments +are lists of file names generated by 'find'. 'xargs' is run like this: + + xargs [OPTION...] [COMMAND [INITIAL-ARGUMENTS]] + +The following command searches the files listed in the file 'file-list' +and prints all of the lines in them that contain the word 'typedef'. + xargs grep typedef < file-list + + +File: find.info, Node: find Expressions, Prev: Overview, Up: Introduction + +1.3 'find' Expressions +====================== + +The expression that 'find' uses to select files consists of one or more +"primaries", each of which is a separate command line argument to +'find'. 'find' evaluates the expression each time it processes a file. +An expression can contain any of the following types of primaries: + +"options" + affect overall operation rather than the processing of a specific + file; +"tests" + return a true or false value, depending on the file's attributes; +"actions" + have side effects and return a true or false value; and +"operators" + connect the other arguments and affect when and whether they are + evaluated. + + You can omit the operator between two primaries; it defaults to +'-and'. *Note Combining Primaries With Operators::, for ways to connect +primaries into more complex expressions. If the expression contains no +actions other than '-prune', '-print' is performed on all files for +which the entire expression is true (*note Print File Name::). + + Options take effect immediately, rather than being evaluated for each +file when their place in the expression is reached. Therefore, for +clarity, it is best to place them at the beginning of the expression. +There are two exceptions to this; '-daystart' and '-follow' have +different effects depending on where in the command line they appear. +This can be confusing, so it's best to keep them at the beginning, too. + + Many of the primaries take arguments, which immediately follow them +in the next command line argument to 'find'. Some arguments are file +names, patterns, or other strings; others are numbers. Numeric +arguments can be specified as + +'+N' + for greater than N, +'-N' + for less than N, +'N' + for exactly N. + + +File: find.info, Node: Finding Files, Next: Actions, Prev: Introduction, Up: Top + +2 Finding Files +*************** + +By default, 'find' prints to the standard output the names of the files +that match the given criteria. *Note Actions::, for how to get more +information about the matching files. + +* Menu: + +* Name:: +* Links:: +* Time:: +* Size:: +* Type:: +* Owner:: +* Mode Bits:: +* Contents:: +* Directories:: +* Filesystems:: +* Combining Primaries With Operators:: + + +File: find.info, Node: Name, Next: Links, Up: Finding Files + +2.1 Name +======== + +Here are ways to search for files whose name matches a certain pattern. +*Note Shell Pattern Matching::, for a description of the PATTERN +arguments to these tests. + + Each of these tests has a case-sensitive version and a +case-insensitive version, whose name begins with 'i'. In a +case-insensitive comparison, the patterns 'fo*' and 'F??' match the file +names 'Foo', 'FOO', 'foo', 'fOo', etc. + +* Menu: + +* Base Name Patterns:: +* Full Name Patterns:: +* Fast Full Name Search:: +* Shell Pattern Matching:: Wildcards used by these programs. + + +File: find.info, Node: Base Name Patterns, Next: Full Name Patterns, Up: Name + +2.1.1 Base Name Patterns +------------------------ + + -- Test: -name pattern + -- Test: -iname pattern + True if the base of the file name (the path with the leading + directories removed) matches shell pattern PATTERN. For '-iname', + the match is case-insensitive.(1) To ignore a whole directory + tree, use '-prune' (*note Directories::). As an example, to find + Texinfo source files in '/usr/local/doc': + + find /usr/local/doc -name '*.texi' + + Notice that the wildcard must be enclosed in quotes in order to + protect it from expansion by the shell. + + As of findutils version 4.2.2, patterns for '-name' and '-iname' + will match a file name with a leading '.'. For example the command + 'find /tmp -name \*bar' will match the file '/tmp/.foobar'. Braces + within the pattern ('{}') are not considered to be special (that + is, 'find . -name 'foo{1,2}'' matches a file named 'foo{1,2}', not + the files 'foo1' and 'foo2'. + + Because the leading directories are removed, the file names + considered for a match with '-name' will never include a slash, so + '-name a/b' will never match anything (you probably need to use + '-path' instead). + + ---------- Footnotes ---------- + + (1) Because we need to perform case-insensitive matching, the GNU +fnmatch implementation is always used; if the C library includes the GNU +implementation, we use that and otherwise we use the one from gnulib + + +File: find.info, Node: Full Name Patterns, Next: Fast Full Name Search, Prev: Base Name Patterns, Up: Name + +2.1.2 Full Name Patterns +------------------------ + + -- Test: -path pattern + -- Test: -wholename pattern + True if the entire file name, starting with the command line + argument under which the file was found, matches shell pattern + PATTERN. To ignore a whole directory tree, use '-prune' rather + than checking every file in the tree (*note Directories::). The + "entire file name" as used by 'find' starts with the starting-point + specified on the command line, and is not converted to an absolute + pathname, so for example 'cd /; find tmp -wholename /tmp' will + never match anything. + + Find compares the '-path' argument with the concatenation of a + directory name and the base name of the file it's considering. + Since the concatenation will never end with a slash, '-path' + arguments ending in '/' will match nothing (except perhaps a start + point specified on the command line). + + The name '-wholename' is GNU-specific, but '-path' is more + portable; it is supported by HP-UX 'find' and is part of the POSIX + 2008 standard. + + -- Test: -ipath pattern + -- Test: -iwholename pattern + These tests are like '-wholename' and '-path', but the match is + case-insensitive. + + In the context of the tests '-path', '-wholename', '-ipath' and +'-wholename', a "full path" is the name of all the directories traversed +from 'find''s start point to the file being tested, followed by the base +name of the file itself. These paths are often not absolute paths; for +example + + $ cd /tmp + $ mkdir -p foo/bar/baz + $ find foo -path foo/bar -print + foo/bar + $ find foo -path /tmp/foo/bar -print + $ find /tmp/foo -path /tmp/foo/bar -print + /tmp/foo/bar + + Notice that the second 'find' command prints nothing, even though +'/tmp/foo/bar' exists and was examined by 'find'. + + Unlike file name expansion on the command line, a '*' in the pattern +will match both '/' and leading dots in file names: + + $ find . -path '*f' + ./quux/bar/baz/f + $ find . -path '*/*config' + ./quux/bar/baz/.config + + -- Test: -regex expr + -- Test: -iregex expr + True if the entire file name matches regular expression EXPR. This + is a match on the whole path, not a search. For example, to match + a file named './fubar3', you can use the regular expression + '.*bar.' or '.*b.*3', but not 'f.*r3'. *Note Syntax of Regular + Expressions: (emacs)Regexps, for a description of the syntax of + regular expressions. For '-iregex', the match is case-insensitive. + + As for '-path', the candidate file name never ends with a slash, so + regular expressions which only match something that ends in slash + will always fail. + + There are several varieties of regular expressions; by default this + test uses POSIX basic regular expressions, but this can be changed + with the option '-regextype'. + + -- Option: -regextype name + This option controls the variety of regular expression syntax + understood by the '-regex' and '-iregex' tests. This option is + positional; that is, it only affects regular expressions which + occur later in the command line. If this option is not given, GNU + Emacs regular expressions are assumed. Currently-implemented types + are + + 'emacs' + Regular expressions compatible with GNU Emacs; this is also + the default behaviour if this option is not used. + 'posix-awk' + Regular expressions compatible with the POSIX awk command (not + GNU awk) + 'posix-basic' + POSIX Basic Regular Expressions. + 'posix-egrep' + Regular expressions compatible with the POSIX egrep command + 'posix-extended' + POSIX Extended Regular Expressions + + *note Regular Expressions:: for more information on the regular + expression dialects understood by GNU findutils. + + +File: find.info, Node: Fast Full Name Search, Next: Shell Pattern Matching, Prev: Full Name Patterns, Up: Name + +2.1.3 Fast Full Name Search +--------------------------- + +To search for files by name without having to actually scan the +directories on the disk (which can be slow), you can use the 'locate' +program. For each shell pattern you give it, 'locate' searches one or +more databases of file names and displays the file names that contain +the pattern. *Note Shell Pattern Matching::, for details about shell +patterns. + + If a pattern is a plain string - it contains no metacharacters - +'locate' displays all file names in the database that contain that +string. If a pattern contains metacharacters, 'locate' only displays +file names that match the pattern exactly. As a result, patterns that +contain metacharacters should usually begin with a '*', and will most +often end with one as well. The exceptions are patterns that are +intended to explicitly match the beginning or end of a file name. + + If you only want 'locate' to match against the last component of the +file names (the "base name" of the files) you can use the '--basename' +option. The opposite behaviour is the default, but can be selected +explicitly by using the option '--wholename'. + + The command + locate PATTERN + + is almost equivalent to + find DIRECTORIES -name PATTERN + + where DIRECTORIES are the directories for which the file name +databases contain information. The differences are that the 'locate' +information might be out of date, and that 'locate' handles wildcards in +the pattern slightly differently than 'find' (*note Shell Pattern +Matching::). + + The file name databases contain lists of files that were on the +system when the databases were last updated. The system administrator +can choose the file name of the default database, the frequency with +which the databases are updated, and the directories for which they +contain entries. + + Here is how to select which file name databases 'locate' searches. +The default is system-dependent. At the time this document was +generated, the default was '/usr/local/var/locatedb'. + +'--database=PATH' +'-d PATH' + Instead of searching the default file name database, search the + file name databases in PATH, which is a colon-separated list of + database file names. You can also use the environment variable + 'LOCATE_PATH' to set the list of database files to search. The + option overrides the environment variable if both are used. + + GNU 'locate' can read file name databases generated by the 'slocate' +package. However, these generally contain a list of all the files on +the system, and so when using this database, 'locate' will produce +output only for files which are accessible to you. *Note Invoking +locate::, for a description of the '--existing' option which is used to +do this. + + The 'updatedb' program can also generate database in a format +compatible with 'slocate'. *Note Invoking updatedb::, for a description +of its '--dbformat' and '--output' options. + + +File: find.info, Node: Shell Pattern Matching, Prev: Fast Full Name Search, Up: Name + +2.1.4 Shell Pattern Matching +---------------------------- + +'find' and 'locate' can compare file names, or parts of file names, to +shell patterns. A "shell pattern" is a string that may contain the +following special characters, which are known as "wildcards" or +"metacharacters". + + You must quote patterns that contain metacharacters to prevent the +shell from expanding them itself. Double and single quotes both work; +so does escaping with a backslash. + +'*' + Matches any zero or more characters. + +'?' + Matches any one character. + +'[STRING]' + Matches exactly one character that is a member of the string + STRING. This is called a "character class". As a shorthand, + STRING may contain ranges, which consist of two characters with a + dash between them. For example, the class '[a-z0-9_]' matches a + lowercase letter, a number, or an underscore. You can negate a + class by placing a '!' or '^' immediately after the opening + bracket. Thus, '[^A-Z@]' matches any character except an uppercase + letter or an at sign. + +'\' + Removes the special meaning of the character that follows it. This + works even in character classes. + + In the 'find' tests that do shell pattern matching ('-name', +'-wholename', etc.), wildcards in the pattern will match a '.' at the +beginning of a file name. This is also the case for 'locate'. Thus, +'find -name '*macs'' will match a file named '.emacs', as will 'locate +'*macs''. + + Slash characters have no special significance in the shell pattern +matching that 'find' and 'locate' do, unlike in the shell, in which +wildcards do not match them. Therefore, a pattern 'foo*bar' can match a +file name 'foo3/bar', and a pattern './sr*sc' can match a file name +'./src/misc'. + + If you want to locate some files with the 'locate' command but don't +need to see the full list you can use the '--limit' option to see just a +small number of results, or the '--count' option to display only the +total number of matches. + + +File: find.info, Node: Links, Next: Time, Prev: Name, Up: Finding Files + +2.2 Links +========= + +There are two ways that files can be linked together. "Symbolic links" +are a special type of file whose contents are a portion of the name of +another file. "Hard links" are multiple directory entries for one file; +the file names all have the same index node ("inode") number on the +disk. + +* Menu: + +* Symbolic Links:: +* Hard Links:: + + +File: find.info, Node: Symbolic Links, Next: Hard Links, Up: Links + +2.2.1 Symbolic Links +-------------------- + +Symbolic links are names that reference other files. GNU 'find' will +handle symbolic links in one of two ways; firstly, it can dereference +the links for you - this means that if it comes across a symbolic link, +it examines the file that the link points to, in order to see if it +matches the criteria you have specified. Secondly, it can check the +link itself in case you might be looking for the actual link. If the +file that the symbolic link points to is also within the directory +hierarchy you are searching with the 'find' command, you may not see a +great deal of difference between these two alternatives. + + By default, 'find' examines symbolic links themselves when it finds +them (and, if it later comes across the linked-to file, it will examine +that, too). If you would prefer 'find' to dereference the links and +examine the file that each link points to, specify the '-L' option to +'find'. You can explicitly specify the default behaviour by using the +'-P' option. The '-H' option is a half-way-between option which ensures +that any symbolic links listed on the command line are dereferenced, but +other symbolic links are not. + + Symbolic links are different from "hard links" in the sense that you +need permission to search the directories in the linked-to file name to +dereference the link. This can mean that even if you specify the '-L' +option, 'find' may not be able to determine the properties of the file +that the link points to (because you don't have sufficient permission). +In this situation, 'find' uses the properties of the link itself. This +also occurs if a symbolic link exists but points to a file that is +missing. + + The options controlling the behaviour of 'find' with respect to links +are as follows: + +'-P' + 'find' does not dereference symbolic links at all. This is the + default behaviour. This option must be specified before any of the + file names on the command line. +'-H' + 'find' does not dereference symbolic links (except in the case of + file names on the command line, which are dereferenced). If a + symbolic link cannot be dereferenced, the information for the + symbolic link itself is used. This option must be specified before + any of the file names on the command line. +'-L' + 'find' dereferences symbolic links where possible, and where this + is not possible it uses the properties of the symbolic link itself. + This option must be specified before any of the file names on the + command line. Use of this option also implies the same behaviour + as the '-noleaf' option. If you later use the '-H' or '-P' + options, this does not turn off '-noleaf'. + + Actions that can cause symbolic links to become broken while 'find' + is executing (for example '-delete') can give rise to confusing + behaviour. Take for example the command line 'find -L . -type d + -delete'. This will delete empty directories. If a subtree + includes only directories and symbolic links to directoires, this + command may still not successfully delete it, since deletion of the + target of the symbolic link will cause the symbolic link to become + broken and '-type d' is false for broken symbolic links. + +'-follow' + This option forms part of the "expression" and must be specified + after the file names, but it is otherwise equivalent to '-L'. The + '-follow' option affects only those tests which appear after it on + the command line. This option is deprecated. Where possible, you + should use '-L' instead. + + The following differences in behaviour occur when the '-L' option is +used: + + * 'find' follows symbolic links to directories when searching + directory trees. + * '-lname' and '-ilname' always return false (unless they happen to + match broken symbolic links). + * '-type' reports the types of the files that symbolic links point + to. This means that in combination with '-L', '-type l' will be + true only for broken symbolic links. To check for symbolic links + when '-L' has been specified, use '-xtype l'. + * Implies '-noleaf' (*note Directories::). + + If the '-L' option or the '-H' option is used, the file names used as +arguments to '-newer', '-anewer', and '-cnewer' are dereferenced and the +timestamp from the pointed-to file is used instead (if possible - +otherwise the timestamp from the symbolic link is used). + + -- Test: -lname pattern + -- Test: -ilname pattern + True if the file is a symbolic link whose contents match shell + pattern PATTERN. For '-ilname', the match is case-insensitive. + *Note Shell Pattern Matching::, for details about the PATTERN + argument. If the '-L' option is in effect, this test will always + return false for symbolic links unless they are broken. So, to + list any symbolic links to 'sysdep.c' in the current directory and + its subdirectories, you can do: + + find . -lname '*sysdep.c' + + +File: find.info, Node: Hard Links, Prev: Symbolic Links, Up: Links + +2.2.2 Hard Links +---------------- + +Hard links allow more than one name to refer to the same file. To find +all the names which refer to the same file as NAME, use '-samefile +NAME'. If you are not using the '-L' option, you can confine your +search to one filesystem using the '-xdev' option. This is useful +because hard links cannot point outside a single filesystem, so this can +cut down on needless searching. + + If the '-L' option is in effect, and NAME is in fact a symbolic link, +the symbolic link will be dereferenced. Hence you are searching for +other links (hard or symbolic) to the file pointed to by NAME. If '-L' +is in effect but NAME is not itself a symbolic link, other symbolic +links to the file NAME will be matched. + + You can also search for files by inode number. This can occasionally +be useful in diagnosing problems with filesystems for example, because +'fsck' tends to print inode numbers. Inode numbers also occasionally +turn up in log messages for some types of software, and are used to +support the 'ftok()' library function. + + You can learn a file's inode number and the number of links to it by +running 'ls -li' or 'find -ls'. + + You can search for hard links to inode number NUM by using '-inum +NUM'. If there are any filesystem mount points below the directory +where you are starting the search, use the '-xdev' option unless you are +also using the '-L' option. Using '-xdev' this saves needless +searching, since hard links to a file must be on the same filesystem. +*Note Filesystems::. + + -- Test: -samefile NAME + File is a hard link to the same inode as NAME. If the '-L' option + is in effect, symbolic links to the same file as NAME points to are + also matched. + + -- Test: -inum n + File has inode number N. The '+' and '-' qualifiers also work, + though these are rarely useful. Much of the time it is easier to + use '-samefile' rather than this option. + + You can also search for files that have a certain number of links, +with '-links'. Directories normally have at least two hard links; their +'.' entry is the second one. If they have subdirectories, each of those +also has a hard link called '..' to its parent directory. The '.' and +'..' directory entries are not normally searched unless they are +mentioned on the 'find' command line. + + -- Test: -links n + File has N hard links. + + -- Test: -links +n + File has more than N hard links. + + -- Test: -links -n + File has fewer than N hard links. + + +File: find.info, Node: Time, Next: Size, Prev: Links, Up: Finding Files + +2.3 Time +======== + +Each file has three time stamps, which record the last time that certain +operations were performed on the file: + + 1. access (read the file's contents) + 2. change the status (modify the file or its attributes) + 3. modify (change the file's contents) + + Some systems also provide a timestamp that indicates when a file was +_created_. For example, the UFS2 filesystem under NetBSD-3.1 records +the _birth time_ of each file. This information is also available under +other versions of BSD and some versions of Cygwin. However, even on +systems which support file birth time, files may exist for which this +information was not recorded (for example, UFS1 file systems simply do +not contain this information). + + You can search for files whose time stamps are within a certain age +range, or compare them to other time stamps. + +* Menu: + +* Age Ranges:: +* Comparing Timestamps:: + + +File: find.info, Node: Age Ranges, Next: Comparing Timestamps, Up: Time + +2.3.1 Age Ranges +---------------- + +These tests are mainly useful with ranges ('+N' and '-N'). + + -- Test: -atime n + -- Test: -ctime n + -- Test: -mtime n + True if the file was last accessed (or its status changed, or it + was modified) N*24 hours ago. The number of 24-hour periods since + the file's timestamp is always rounded down; therefore 0 means + "less than 24 hours ago", 1 means "between 24 and 48 hours ago", + and so forth. Fractional values are supported but this only really + makes sense for the case where ranges ('+N' and '-N') are used. + + -- Test: -amin n + -- Test: -cmin n + -- Test: -mmin n + True if the file was last accessed (or its status changed, or it + was modified) N minutes ago. These tests provide finer granularity + of measurement than '-atime' et al., but rounding is done in a + similar way (again, fractions are supported). For example, to list + files in '/u/bill' that were last read from 2 to 6 minutes ago: + + find /u/bill -amin +2 -amin -6 + + -- Option: -daystart + Measure times from the beginning of today rather than from 24 hours + ago. So, to list the regular files in your home directory that + were modified yesterday, do + + find ~/ -daystart -type f -mtime 1 + + The '-daystart' option is unlike most other options in that it has + an effect on the way that other tests are performed. The affected + tests are '-amin', '-cmin', '-mmin', '-atime', '-ctime' and + '-mtime'. The '-daystart' option only affects the behaviour of any + tests which appear after it on the command line. + + +File: find.info, Node: Comparing Timestamps, Prev: Age Ranges, Up: Time + +2.3.2 Comparing Timestamps +-------------------------- + + -- Test: -newerXY reference + Succeeds if timestamp 'X' of the file being considered is newer + than timestamp 'Y' of the file 'reference'. The letters 'X' and + 'Y' can be any of the following letters: + + 'a' + Last-access time of 'reference' + 'B' + Birth time of 'reference' (when this is not known, the test + cannot succeed) + 'c' + Last-change time of 'reference' + 'm' + Last-modification time of 'reference' + 't' + The 'reference' argument is interpreted as a literal time, + rather than the name of a file. *Note Date input formats::, + for a description of how the timestamp is understood. Tests + of the form '-newerXt' are valid but tests of the form + '-newertY' are not. + + For example the test '-newerac /tmp/foo' succeeds for all files + which have been accessed more recently than '/tmp/foo' was changed. + Here 'X' is 'a' and 'Y' is 'c'. + + Not all files have a known birth time. If 'Y' is 'b' and the birth + time of 'reference' is not available, 'find' exits with an + explanatory error message. If 'X' is 'b' and we do not know the + birth time the file currently being considered, the test simply + fails (that is, it behaves like '-false' does). + + Some operating systems (for example, most implementations of Unix) + do not support file birth times. Some others, for example + NetBSD-3.1, do. Even on operating systems which support file birth + times, the information may not be available for specific files. + For example, under NetBSD, file birth times are supported on UFS2 + file systems, but not UFS1 file systems. + + There are two ways to list files in '/usr' modified after February 1 +of the current year. One uses '-newermt': + + find /usr -newermt "Feb 1" + + The other way of doing this works on the versions of find before +4.3.3: + + touch -t 02010000 /tmp/stamp$$ + find /usr -newer /tmp/stamp$$ + rm -f /tmp/stamp$$ + + -- Test: -anewer file + -- Test: -cnewer file + -- Test: -newer file + True if the file was last accessed (or its status changed, or it + was modified) more recently than FILE was modified. These tests + are affected by '-follow' only if '-follow' comes before them on + the command line. *Note Symbolic Links::, for more information on + '-follow'. As an example, to list any files modified since + '/bin/sh' was last modified: + + find . -newer /bin/sh + + -- Test: -used n + True if the file was last accessed N days after its status was last + changed. Useful for finding files that are not being used, and + could perhaps be archived or removed to save disk space. + + +File: find.info, Node: Size, Next: Type, Prev: Time, Up: Finding Files + +2.4 Size +======== + + -- Test: -size n[bckwMG] + True if the file uses N units of space, rounding up. The units are + 512-byte blocks by default, but they can be changed by adding a + one-character suffix to N: + + 'b' + 512-byte blocks (never 1024) + 'c' + bytes + 'k' + kilobytes (1024 bytes) + 'w' + 2-byte words + 'M' + Megabytes (units of 1048576 bytes) + 'G' + Gigabytes (units of 1073741824 bytes) + + The 'b' suffix always considers blocks to be 512 bytes. This is + not affected by the setting (or non-setting) of the + 'POSIXLY_CORRECT' environment variable. This behaviour is + different from the behaviour of the '-ls' action). If you want to + use 1024-byte units, use the 'k' suffix instead. + + The number can be prefixed with a '+' or a '-'. A plus sign + indicates that the test should succeed if the file uses at least N + units of storage (a common use of this test) and a minus sign + indicates that the test should succeed if the file uses less than N + units of storage. There is no '=' prefix, because that's the + default anyway. + + The size does not count indirect blocks, but it does count blocks + in sparse files that are not actually allocated. In other words, + it's consistent with the result you get for 'ls -l' or 'wc -c'. + This handling of sparse files differs from the output of the '%k' + and '%b' format specifiers for the '-printf' predicate. + + -- Test: -empty + True if the file is empty and is either a regular file or a + directory. This might help determine good candidates for deletion. + This test is useful with '-depth' (*note Directories::) and + '-delete' (*note Single File::). + + +File: find.info, Node: Type, Next: Owner, Prev: Size, Up: Finding Files + +2.5 Type +======== + + -- Test: -type c + True if the file is of type C: + + 'b' + block (buffered) special + 'c' + character (unbuffered) special + 'd' + directory + 'p' + named pipe (FIFO) + 'f' + regular file + 'l' + symbolic link; if '-L' is in effect, this is true only for + broken symbolic links. If you want to search for symbolic + links when '-L' is in effect, use '-xtype' instead of '-type'. + 's' + socket + 'D' + door (Solaris) + + -- Test: -xtype c + This test behaves the same as '-type' unless the file is a symbolic + link. If the file is a symbolic link, the result is as follows (in + the table below, 'X' should be understood to represent any letter + except 'l'): + + ''-P -xtype l'' + True if the symbolic link is broken + ''-P -xtype X'' + True if the (ultimate) target file is of type 'X'. + ''-L -xtype l'' + Always true + ''-L -xtype X'' + False unless the symbolic link is broken + + In other words, for symbolic links, '-xtype' checks the type of the + file that '-type' does not check. + + The '-H' option also affects the behaviour of '-xtype'. When '-H' + is in effect, '-xtype' behaves as if '-L' had been specified when + examining files listed on the command line, and as if '-P' had been + specified otherwise. If neither '-H' nor '-L' was specified, + '-xtype' behaves as if '-P' had been specified. + + *Note Symbolic Links::, for more information on '-follow' and '-L'. + + +File: find.info, Node: Owner, Next: Mode Bits, Prev: Type, Up: Finding Files + +2.6 Owner +========= + + -- Test: -user uname + -- Test: -group gname + True if the file is owned by user UNAME (belongs to group GNAME). + A numeric ID is allowed. + + -- Test: -uid n + -- Test: -gid n + True if the file's numeric user ID (group ID) is N. These tests + support ranges ('+N' and '-N'), unlike '-user' and '-group'. + + -- Test: -nouser + -- Test: -nogroup + True if no user corresponds to the file's numeric user ID (no group + corresponds to the numeric group ID). These cases usually mean that + the files belonged to users who have since been removed from the + system. You probably should change the ownership of such files to + an existing user or group, using the 'chown' or 'chgrp' program. + + +File: find.info, Node: Mode Bits, Next: Contents, Prev: Owner, Up: Finding Files + +2.7 File Mode Bits +================== + +*Note File Permissions::, for information on how file mode bits are +structured and how to specify them. + + Four tests determine what users can do with files. These are +'-readable', '-writable', '-executable' and '-perm'. The first three +tests ask the operating system if the current user can perform the +relevant operation on a file, while '-perm' just examines the file's +mode. The file mode may give a misleading impression of what the user +can actually do, because the file may have an access control list, or +exist on a read-only filesystem, for example. Of these four tests +though, only '-perm' is specified by the POSIX standard. + + The '-readable', '-writable' and '-executable' tests are implemented +via the 'access' system call. This is implemented within the operating +system itself. If the file being considered is on an NFS filesystem, +the remote system may allow or forbid read or write operations for +reasons of which the NFS client cannot take account. This includes +user-ID mapping, either in the general sense or the more restricted +sense in which remote superusers are treated by the NFS server as if +they are the local user 'nobody' on the NFS server. + + None of the tests in this section should be used to verify that a +user is authorised to perform any operation (on the file being tested or +any other file) because of the possibility of a race condition. That +is, the situation may change between the test and an action being taken +on the basis of the result of that test. + + -- Test: -readable + True if the file can be read by the invoking user. + + -- Test: -writable + True if the file can be written by the invoking user. This is an + in-principle check, and other things may prevent a successful write + operation; for example, the filesystem might be full. + + -- Test: -executable + True if the file can be executed/searched by the invoking user. + + -- Test: -perm pmode + + True if the file's mode bits match PMODE, which can be either a + symbolic or numeric MODE (*note File Permissions::) optionally + prefixed by '-' or '/'. + + A PMODE that starts with neither '-' nor '/' matches if MODE + exactly matches the file mode bits. (To avoid confusion with an + obsolete GNU extension, MODE must not start with a '+' immediately + followed by an octal digit.) + + A PMODE that starts with '-' matches if _all_ the file mode bits + set in MODE are set for the file; bits not set in MODE are ignored. + + A PMODE that starts with '/' matches if _any_ of the file mode bits + set in MODE are set for the file; bits not set in MODE are ignored. + This is a GNU extension. + + If you don't use the '/' or '-' form with a symbolic mode string, + you may have to specify a rather complex mode string. For example + '-perm g=w' will only match files that have mode 0020 (that is, + ones for which group write permission is the only file mode bit + set). It is more likely that you will want to use the '/' or '-' + forms, for example '-perm -g=w', which matches any file with group + write permission. + + '-perm 664' + Match files that have read and write permission for their + owner, and group, but that the rest of the world can read but + not write to. Do not match files that meet these criteria but + have other file mode bits set (for example if someone can + execute/search the file). + + '-perm -664' + Match files that have read and write permission for their + owner, and group, but that the rest of the world can read but + not write to, without regard to the presence of any extra file + mode bits (for example the executable bit). This matches a + file with mode 0777, for example. + + '-perm /222' + Match files that are writable by somebody (their owner, or + their group, or anybody else). + + '-perm /022' + Match files that are writable by either their owner or their + group. The files don't have to be writable by both the owner + and group to be matched; either will do. + + '-perm /g+w,o+w' + As above. + + '-perm /g=w,o=w' + As above. + + '-perm -022' + Match files that are writable by both their owner and their + group. + + '-perm -444 -perm /222 ! -perm /111' + Match files that are readable for everybody, have at least one + write bit set (i.e., somebody can write to them), but that + cannot be executed/searched by anybody. Note that in some + shells the '!' must be escaped;. + + '-perm -a+r -perm /a+w ! -perm /a+x' + As above. + + '-perm -g+w,o+w' + As above. + + Warning: If you specify '-perm /000' or '-perm /mode' where + the symbolic mode 'mode' has no bits set, the test matches all + files. Versions of GNU 'find' prior to 4.3.3 matched no files + in this situation. + + -- Test: -context pattern + True if file's SELinux context matches the pattern PATTERN. The + pattern uses shell glob matching. + + This predicate is supported only on 'find' versions compiled with + SELinux support and only when SELinux is enabled. + + +File: find.info, Node: Contents, Next: Directories, Prev: Mode Bits, Up: Finding Files + +2.8 Contents +============ + +To search for files based on their contents, you can use the 'grep' +program. For example, to find out which C source files in the current +directory contain the string 'thing', you can do: + + grep -l thing *.[ch] + + If you also want to search for the string in files in subdirectories, +you can combine 'grep' with 'find' and 'xargs', like this: + + find . -name '*.[ch]' | xargs grep -l thing + + The '-l' option causes 'grep' to print only the names of files that +contain the string, rather than the lines that contain it. The string +argument ('thing') is actually a regular expression, so it can contain +metacharacters. This method can be refined a little by using the '-r' +option to make 'xargs' not run 'grep' if 'find' produces no output, and +using the 'find' action '-print0' and the 'xargs' option '-0' to avoid +misinterpreting files whose names contain spaces: + + find . -name '*.[ch]' -print0 | xargs -r -0 grep -l thing + + For a fuller treatment of finding files whose contents match a +pattern, see the manual page for 'grep'. + + +File: find.info, Node: Directories, Next: Filesystems, Prev: Contents, Up: Finding Files + +2.9 Directories +=============== + +Here is how to control which directories 'find' searches, and how it +searches them. These two options allow you to process a horizontal +slice of a directory tree. + + -- Option: -maxdepth levels + Descend at most LEVELS (a non-negative integer) levels of + directories below the command line arguments. '-maxdepth 0' means + only apply the tests and actions to the command line arguments. + + -- Option: -mindepth levels + Do not apply any tests or actions at levels less than LEVELS (a + non-negative integer). '-mindepth 1' means process all files + except the command line arguments. + + -- Option: -depth + Process each directory's contents before the directory itself. + Doing this is a good idea when producing lists of files to archive + with 'cpio' or 'tar'. If a directory does not have write + permission for its owner, its contents can still be restored from + the archive since the directory's permissions are restored after + its contents. + + -- Option: -d + This is a deprecated synonym for '-depth', for compatibility with + Mac OS X, FreeBSD and OpenBSD. The '-depth' option is a POSIX + feature, so it is better to use that. + + -- Action: -prune + If the file is a directory, do not descend into it. The result is + true. For example, to skip the directory 'src/emacs' and all files + and directories under it, and print the names of the other files + found: + + find . -wholename './src/emacs' -prune -o -print + + The above command will not print './src/emacs' among its list of + results. This however is not due to the effect of the '-prune' + action (which only prevents further descent, it doesn't make sure + we ignore that item). Instead, this effect is due to the use of + '-o'. Since the left hand side of the "or" condition has succeeded + for './src/emacs', it is not necessary to evaluate the + right-hand-side ('-print') at all for this particular file. If you + wanted to print that directory name you could use either an extra + '-print' action: + + find . -wholename './src/emacs' -prune -print -o -print + + or use the comma operator: + + find . -wholename './src/emacs' -prune , -print + + If the '-depth' option is in effect, the subdirectories will have + already been visited in any case. Hence '-prune' has no effect in + this case. + + Because '-delete' implies '-depth', using '-prune' in combination + with '-delete' may well result in the deletion of more files than + you intended. + + -- Action: -quit + Exit immediately (with return value zero if no errors have + occurred). This is different to '-prune' because '-prune' only + applies to the contents of pruned directories, while '-quit' simply + makes 'find' stop immediately. No child processes will be left + running, but no more files specified on the command line will be + processed. For example, 'find /tmp/foo /tmp/bar -print -quit' will + print only '/tmp/foo'. Any command lines which have been built by + '-exec ... \+' or '-execdir ... \+' are invoked before the program + is exited. + + -- Option: -noleaf + Do not optimize by assuming that directories contain 2 fewer + subdirectories than their hard link count. This option is needed + when searching filesystems that do not follow the Unix + directory-link convention, such as CD-ROM or MS-DOS filesystems or + AFS volume mount points. Each directory on a normal Unix + filesystem has at least 2 hard links: its name and its '.' entry. + Additionally, its subdirectories (if any) each have a '..' entry + linked to that directory. When 'find' is examining a directory, + after it has statted 2 fewer subdirectories than the directory's + link count, it knows that the rest of the entries in the directory + are non-directories ("leaf" files in the directory tree). If only + the files' names need to be examined, there is no need to stat + them; this gives a significant increase in search speed. + + -- Option: -ignore_readdir_race + If a file disappears after its name has been read from a directory + but before 'find' gets around to examining the file with 'stat', + don't issue an error message. If you don't specify this option, an + error message will be issued. This option can be useful in system + scripts (cron scripts, for example) that examine areas of the + filesystem that change frequently (mail queues, temporary + directories, and so forth), because this scenario is common for + those sorts of directories. Completely silencing error messages + from 'find' is undesirable, so this option neatly solves the + problem. There is no way to search one part of the filesystem with + this option on and part of it with this option off, though. When + this option is turned on and find discovers that one of the + start-point files specified on the command line does not exist, no + error message will be issued. + + -- Option: -noignore_readdir_race + This option reverses the effect of the '-ignore_readdir_race' + option. + + +File: find.info, Node: Filesystems, Next: Combining Primaries With Operators, Prev: Directories, Up: Finding Files + +2.10 Filesystems +================ + +A "filesystem" is a section of a disk, either on the local host or +mounted from a remote host over a network. Searching network +filesystems can be slow, so it is common to make 'find' avoid them. + + There are two ways to avoid searching certain filesystems. One way +is to tell 'find' to only search one filesystem: + + -- Option: -xdev + -- Option: -mount + Don't descend directories on other filesystems. These options are + synonyms. + + The other way is to check the type of filesystem each file is on, and +not descend directories that are on undesirable filesystem types: + + -- Test: -fstype type + True if the file is on a filesystem of type TYPE. The valid + filesystem types vary among different versions of Unix; an + incomplete list of filesystem types that are accepted on some + version of Unix or another is: + ext2 ext3 proc sysfs ufs 4.2 4.3 nfs tmp mfs S51K S52K + You can use '-printf' with the '%F' directive to see the types of + your filesystems. The '%D' directive shows the device number. + *Note Print File Information::. '-fstype' is usually used with + '-prune' to avoid searching remote filesystems (*note + Directories::). + + +File: find.info, Node: Combining Primaries With Operators, Prev: Filesystems, Up: Finding Files + +2.11 Combining Primaries With Operators +======================================= + +Operators build a complex expression from tests and actions. The +operators are, in order of decreasing precedence: + +'( EXPR )' + Force precedence. True if EXPR is true. + +'! EXPR' +'-not EXPR' + True if EXPR is false. In some shells, it is necessary to protect + the '!' from shell interpretation by quoting it. + +'EXPR1 EXPR2' +'EXPR1 -a EXPR2' +'EXPR1 -and EXPR2' + And; EXPR2 is not evaluated if EXPR1 is false. + +'EXPR1 -o EXPR2' +'EXPR1 -or EXPR2' + Or; EXPR2 is not evaluated if EXPR1 is true. + +'EXPR1 , EXPR2' + List; both EXPR1 and EXPR2 are always evaluated. True if EXPR2 is + true. The value of EXPR1 is discarded. This operator lets you do + multiple independent operations on one traversal, without depending + on whether other operations succeeded. The two operations EXPR1 + and EXPR2 are not always fully independent, since EXPR1 might have + side effects like touching or deleting files, or it might use + '-prune' which would also affect EXPR2. + + 'find' searches the directory tree rooted at each file name by +evaluating the expression from left to right, according to the rules of +precedence, until the outcome is known (the left hand side is false for +'-and', true for '-or'), at which point 'find' moves on to the next file +name. + + There are two other tests that can be useful in complex expressions: + + -- Test: -true + Always true. + + -- Test: -false + Always false. + + +File: find.info, Node: Actions, Next: Databases, Prev: Finding Files, Up: Top + +3 Actions +********* + +There are several ways you can print information about the files that +match the criteria you gave in the 'find' expression. You can print the +information either to the standard output or to a file that you name. +You can also execute commands that have the file names as arguments. +You can use those commands as further filters to select files. + +* Menu: + +* Print File Name:: +* Print File Information:: +* Run Commands:: +* Delete Files:: +* Adding Tests:: + + +File: find.info, Node: Print File Name, Next: Print File Information, Up: Actions + +3.1 Print File Name +=================== + + -- Action: -print + True; print the entire file name on the standard output, followed + by a newline. If there is the faintest possibility that one of the + files for which you are searching might contain a newline, you + should use '-print0' instead. + + -- Action: -fprint file + True; print the entire file name into file FILE, followed by a + newline. If FILE does not exist when 'find' is run, it is created; + if it does exist, it is truncated to 0 bytes. The named output + file is always created, even if no output is sent to it. The file + names '/dev/stdout' and '/dev/stderr' are handled specially; they + refer to the standard output and standard error output, + respectively. + + If there is the faintest possibility that one of the files for + which you are searching might contain a newline, you should use + '-fprint0' instead. + + +File: find.info, Node: Print File Information, Next: Run Commands, Prev: Print File Name, Up: Actions + +3.2 Print File Information +========================== + + -- Action: -ls + True; list the current file in 'ls -dils' format on the standard + output. The output looks like this: + + 204744 17 -rw-r--r-- 1 djm staff 17337 Nov 2 1992 ./lwall-quotes + + The fields are: + + 1. The inode number of the file. *Note Hard Links::, for how to + find files based on their inode number. + + 2. the number of blocks in the file. The block counts are of 1K + blocks, unless the environment variable 'POSIXLY_CORRECT' is + set, in which case 512-byte blocks are used. *Note Size::, + for how to find files based on their size. + + 3. The file's type and file mode bits. The type is shown as a + dash for a regular file; for other file types, a letter like + for '-type' is used (*note Type::). The file mode bits are + read, write, and execute/search for the file's owner, its + group, and other users, respectively; a dash means the + permission is not granted. *Note File Permissions::, for more + details about file permissions. *Note Mode Bits::, for how to + find files based on their file mode bits. + + 4. The number of hard links to the file. + + 5. The user who owns the file. + + 6. The file's group. + + 7. The file's size in bytes. + + 8. The date the file was last modified. + + 9. The file's name. '-ls' quotes non-printable characters in the + file names using C-like backslash escapes. This may change + soon, as the treatment of unprintable characters is harmonised + for '-ls', '-fls', '-print', '-fprint', '-printf' and + '-fprintf'. + + -- Action: -fls file + True; like '-ls' but write to FILE like '-fprint' (*note Print File + Name::). The named output file is always created, even if no + output is sent to it. + + -- Action: -printf format + True; print FORMAT on the standard output, interpreting '\' escapes + and '%' directives (more details in the following sections). + + Field widths and precisions can be specified as with the 'printf' C + function. Format flags (like '#' for example) may not work as you + expect because many of the fields, even numeric ones, are printed + with %s. Numeric flags which are affected in this way include 'G', + 'U', 'b', 'D', 'k' and 'n'. This difference in behaviour means + though that the format flag '-' will work; it forces left-alignment + of the field. Unlike '-print', '-printf' does not add a newline at + the end of the string. If you want a newline at the end of the + string, add a '\n'. + + As an example, an approximate equivalent of '-ls' with + null-terminated filenames can be achieved with this '-printf' + format: + + find -printf "%i %4k %M %3n %-8u %-8g %8s %T+ %p\n->%l\0" | cat + + A practical reason for doing this would be to get literal filenames + in the output, instead of '-ls''s backslash-escaped names. (Using + 'cat' here prevents this happening for the '%p' format specifier; + *note Unusual Characters in File Names::). This format also + outputs a uniform timestamp format. + + As for symlinks, the format above outputs the symlink target on a + second line, following '\n->'. There is nothing following the + arrow for non-symlinks. Another approach, for complete + consistency, would be to '-fprintf' the symlinks into a separate + file, so they too can be null-terminated. + + -- Action: -fprintf file format + True; like '-printf' but write to FILE like '-fprint' (*note Print + File Name::). The output file is always created, even if no output + is ever sent to it. + +* Menu: + +* Escapes:: +* Format Directives:: +* Time Formats:: +* Formatting Flags:: + + +File: find.info, Node: Escapes, Next: Format Directives, Up: Print File Information + +3.2.1 Escapes +------------- + +The escapes that '-printf' and '-fprintf' recognise are: + +'\a' + Alarm bell. +'\b' + Backspace. +'\c' + Stop printing from this format immediately and flush the output. +'\f' + Form feed. +'\n' + Newline. +'\r' + Carriage return. +'\t' + Horizontal tab. +'\v' + Vertical tab. +'\\' + A literal backslash ('\'). +'\0' + ASCII NUL. +'\NNN' + The character whose ASCII code is NNN (octal). + + A '\' character followed by any other character is treated as an +ordinary character, so they both are printed, and a warning message is +printed to the standard error output (because it was probably a typo). + + +File: find.info, Node: Format Directives, Next: Time Formats, Prev: Escapes, Up: Print File Information + +3.2.2 Format Directives +----------------------- + +'-printf' and '-fprintf' support the following format directives to +print information about the file being processed. The C 'printf' +function, field width and precision specifiers are supported, as applied +to string (%s) types. That is, you can specify "minimum field +width"."maximum field width" for each directive. Format flags (like '#' +for example) may not work as you expect because many of the fields, even +numeric ones, are printed with %s. The format flag '-' does work; it +forces left-alignment of the field. + + '%%' is a literal percent sign. *Note Reserved and Unknown +Directives::, for a description of how format directives not mentioned +below are handled. + + A '%' at the end of the format argument causes undefined behaviour +since there is no following character. In some locales, it may hide +your door keys, while in others it may remove the final page from the +novel you are reading. + +* Menu: + +* Name Directives:: +* Ownership Directives:: +* Size Directives:: +* Location Directives:: +* Time Directives:: +* Other Directives:: +* Reserved and Unknown Directives:: + + +File: find.info, Node: Name Directives, Next: Ownership Directives, Up: Format Directives + +3.2.2.1 Name Directives +....................... + +'%p' + File's name (not the absolute path name, but the name of the file + as it was encountered by 'find' - that is, as a relative path from + one of the starting points). +'%f' + File's name with any leading directories removed (only the last + element). +'%h' + Leading directories of file's name (all but the last element and + the slash before it). If the file's name contains no slashes (for + example because it was named on the command line and is in the + current working directory), then "%h" expands to ".". This + prevents "%h/%f" expanding to "/foo", which would be surprising and + probably not desirable. +'%P' + File's name with the name of the command line argument under which + it was found removed from the beginning. +'%H' + Command line argument under which file was found. + + +File: find.info, Node: Ownership Directives, Next: Size Directives, Prev: Name Directives, Up: Format Directives + +3.2.2.2 Ownership Directives +............................ + +'%g' + File's group name, or numeric group ID if the group has no name. +'%G' + File's numeric group ID. +'%u' + File's user name, or numeric user ID if the user has no name. +'%U' + File's numeric user ID. +'%m' + File's mode bits (in octal). If you always want to have a leading + zero on the number, use the '#' format flag, for example '%#m'. + + The file mode bit numbers used are the traditional Unix numbers, + which will be as expected on most systems, but if your system's + file mode bit layout differs from the traditional Unix semantics, + you will see a difference between the mode as printed by '%m' and + the mode as it appears in 'struct stat'. + +'%M' + File's type and mode bits (in symbolic form, as for 'ls'). This + directive is supported in findutils 4.2.5 and later. + + +File: find.info, Node: Size Directives, Next: Location Directives, Prev: Ownership Directives, Up: Format Directives + +3.2.2.3 Size Directives +....................... + +'%k' + The amount of disk space used for this file in 1K blocks. Since + disk space is allocated in multiples of the filesystem block size + this is usually greater than %s/1024, but it can also be smaller if + the file is a sparse file (that is, it has "holes"). +'%b' + The amount of disk space used for this file in 512-byte blocks. + Since disk space is allocated in multiples of the filesystem block + size this is usually greater than %s/512, but it can also be + smaller if the file is a sparse file (that is, it has "holes"). +'%s' + File's size in bytes. +'%S' + File's sparseness. This is calculated as '(BLOCKSIZE*st_blocks / + st_size)'. The exact value you will get for an ordinary file of a + certain length is system-dependent. However, normally sparse files + will have values less than 1.0, and files which use indirect blocks + and have few holes may have a value which is greater than 1.0. The + value used for BLOCKSIZE is system-dependent, but is usually 512 + bytes. If the file size is zero, the value printed is undefined. + On systems which lack support for st_blocks, a file's sparseness is + assumed to be 1.0. + + +File: find.info, Node: Location Directives, Next: Time Directives, Prev: Size Directives, Up: Format Directives + +3.2.2.4 Location Directives +........................... + +'%d' + File's depth in the directory tree (depth below a file named on the + command line, not depth below the root directory). Files named on + the command line have a depth of 0. Subdirectories immediately + below them have a depth of 1, and so on. +'%D' + The device number on which the file exists (the 'st_dev' field of + 'struct stat'), in decimal. +'%F' + Type of the filesystem the file is on; this value can be used for + '-fstype' (*note Directories::). +'%l' + Object of symbolic link (empty string if file is not a symbolic + link). +'%i' + File's inode number (in decimal). +'%n' + Number of hard links to file. +'%y' + Type of the file as used with '-type'. If the file is a symbolic + link, 'l' will be printed. +'%Y' + Type of the file as used with '-type'. If the file is a symbolic + link, it is dereferenced. If the file is a broken symbolic link, + 'N' is printed. + + +File: find.info, Node: Time Directives, Next: Other Directives, Prev: Location Directives, Up: Format Directives + +3.2.2.5 Time Directives +....................... + +Some of these directives use the C 'ctime' function. Its output depends +on the current locale, but it typically looks like + + Wed Nov 2 00:42:36 1994 + +'%a' + File's last access time in the format returned by the C 'ctime' + function. +'%AK' + File's last access time in the format specified by K (*note Time + Formats::). +'%c' + File's last status change time in the format returned by the C + 'ctime' function. +'%CK' + File's last status change time in the format specified by K (*note + Time Formats::). +'%t' + File's last modification time in the format returned by the C + 'ctime' function. +'%TK' + File's last modification time in the format specified by K (*note + Time Formats::). + + +File: find.info, Node: Other Directives, Next: Reserved and Unknown Directives, Prev: Time Directives, Up: Format Directives + +3.2.2.6 Other Directives +........................ + +'%Z' + File's SELinux context, or empty string if the file has no SELinux + context. + + +File: find.info, Node: Reserved and Unknown Directives, Prev: Other Directives, Up: Format Directives + +3.2.2.7 Reserved and Unknown Directives +....................................... + +The '%(', '%{' and '%[' format directives, with or without field with +and precision specifications, are reserved for future use. Don't use +them and don't rely on current experiment to predict future behaviour. +To print '(', simply use '(' rather than '%('. Likewise for '{' and +'['. + + Similarly, a '%' character followed by any other unrecognised +character (i.e., not a known directive or 'printf' field width and +precision specifier), is discarded (but the unrecognised character is +printed), and a warning message is printed to the standard error output +(because it was probably a typo). Don't rely on this behaviour, because +other directives may be added in the future. + + +File: find.info, Node: Time Formats, Next: Formatting Flags, Prev: Format Directives, Up: Print File Information + +3.2.3 Time Formats +------------------ + +Below are the formats for the directives '%A', '%C', and '%T', which +print the file's timestamps. Some of these formats might not be +available on all systems, due to differences in the C 'strftime' +function between systems. + +* Menu: + +* Time Components:: +* Date Components:: +* Combined Time Formats:: + + +File: find.info, Node: Time Components, Next: Date Components, Up: Time Formats + +3.2.3.1 Time Components +....................... + +The following format directives print single components of the time. + +'H' + hour (00..23) +'I' + hour (01..12) +'k' + hour ( 0..23) +'l' + hour ( 1..12) +'p' + locale's AM or PM +'Z' + time zone (e.g., EDT), or nothing if no time zone is determinable +'M' + minute (00..59) +'S' + second (00..61). There is a fractional part. +'@' + seconds since Jan. 1, 1970, 00:00 GMT, with fractional part. + + The fractional part of the seconds field is of indeterminate length +and precision. That is, the length of the fractional part of the +seconds field will in general vary between findutils releases and +between systems. This means that it is unwise to assume that field has +any specific length. The length of this field is not usually a guide to +the precision of timestamps in the underlying file system. + + +File: find.info, Node: Date Components, Next: Combined Time Formats, Prev: Time Components, Up: Time Formats + +3.2.3.2 Date Components +....................... + +The following format directives print single components of the date. + +'a' + locale's abbreviated weekday name (Sun..Sat) +'A' + locale's full weekday name, variable length (Sunday..Saturday) +'b' +'h' + locale's abbreviated month name (Jan..Dec) +'B' + locale's full month name, variable length (January..December) +'m' + month (01..12) +'d' + day of month (01..31) +'w' + day of week (0..6) +'j' + day of year (001..366) +'U' + week number of year with Sunday as first day of week (00..53) +'W' + week number of year with Monday as first day of week (00..53) +'Y' + year (1970...) +'y' + last two digits of year (00..99) + + +File: find.info, Node: Combined Time Formats, Prev: Date Components, Up: Time Formats + +3.2.3.3 Combined Time Formats +............................. + +The following format directives print combinations of time and date +components. + +'r' + time, 12-hour (hh:mm:ss [AP]M) +'T' + time, 24-hour (hh:mm:ss) +'X' + locale's time representation (H:M:S) +'c' + locale's date and time in ctime format (Sat Nov 04 12:02:33 EST + 1989). This format does not include any fractional part in the + seconds field. +'D' + date (mm/dd/yy) +'x' + locale's date representation (mm/dd/yy) +'+' + Date and time, separated by '+', for example + '2004-04-28+22:22:05.0000000000'. The time is given in the current + timezone (which may be affected by setting the TZ environment + variable). This is a GNU extension. The seconds field includes a + fractional part. + + +File: find.info, Node: Formatting Flags, Prev: Time Formats, Up: Print File Information + +3.2.4 Formatting Flags +---------------------- + +The '%m' and '%d' directives support the '#', '0' and '+' flags, but the +other directives do not, even if they print numbers. Numeric directives +that do not support these flags include + + 'G', 'U', 'b', 'D', 'k' and 'n'. + + All fields support the format flag '-', which makes fields +left-aligned. That is, if the field width is greater than the actual +contents of the field, the requisite number of spaces are printed after +the field content instead of before it. + + +File: find.info, Node: Run Commands, Next: Delete Files, Prev: Print File Information, Up: Actions + +3.3 Run Commands +================ + +You can use the list of file names created by 'find' or 'locate' as +arguments to other commands. In this way you can perform arbitrary +actions on the files. + +* Menu: + +* Single File:: +* Multiple Files:: +* Querying:: + + +File: find.info, Node: Single File, Next: Multiple Files, Up: Run Commands + +3.3.1 Single File +----------------- + +Here is how to run a command on one file at a time. + + -- Action: -execdir command ; + Execute COMMAND; true if COMMAND returns zero. 'find' takes all + arguments after '-execdir' to be part of the command until an + argument consisting of ';' is reached. It replaces the string '{}' + by the current file name being processed everywhere it occurs in + the command. Both of these constructions need to be escaped (with + a '\') or quoted to protect them from expansion by the shell. The + command is executed in the directory which 'find' was searching at + the time the action was executed (that is, {} will expand to a file + in the local directory). + + For example, to compare each C header file in or below the current + directory with the file '/tmp/master': + + find . -name '*.h' -execdir diff -u '{}' /tmp/master ';' + + If you use '-execdir', you must ensure that the '$PATH' variable +contains only absolute directory names. Having an empty element in +'$PATH' or explicitly including '.' (or any other non-absolute name) is +insecure. GNU find will refuse to run if you use '-execdir' and it +thinks your '$PATH' setting is insecure. For example: + +'/bin:/usr/bin:' + Insecure; empty path element (at the end) +':/bin:/usr/bin:/usr/local/bin' + Insecure; empty path element (at the start) +'/bin:/usr/bin::/usr/local/bin' + Insecure; empty path element (two colons in a row) +'/bin:/usr/bin:.:/usr/local/bin' + Insecure; '.' is a path element ('.' is not an absolute file name) +'/bin:/usr/bin:sbin:/usr/local/bin' + Insecure; 'sbin' is not an absolute file name +'/bin:/usr/bin:/sbin:/usr/local/bin' + Secure (if you control the contents of those directories and any + access to them) + + Another similar option, '-exec' is supported, but is less secure. +*Note Security Considerations::, for a discussion of the security +problems surrounding '-exec'. + + -- Action: -exec command ; + This insecure variant of the '-execdir' action is specified by + POSIX. Like '-execdir command ;' it is true if zero is returned by + COMMAND. The main difference is that the command is executed in + the directory from which 'find' was invoked, meaning that '{}' is + expanded to a relative path starting with the name of one of the + starting directories, rather than just the basename of the matched + file. + + While some implementations of 'find' replace the '{}' only where it + appears on its own in an argument, GNU 'find' replaces '{}' + wherever it appears. + + +File: find.info, Node: Multiple Files, Next: Querying, Prev: Single File, Up: Run Commands + +3.3.2 Multiple Files +-------------------- + +Sometimes you need to process files one at a time. But usually this is +not necessary, and, it is faster to run a command on as many files as +possible at a time, rather than once per file. Doing this saves on the +time it takes to start up the command each time. + + The '-execdir' and '-exec' actions have variants that build command +lines containing as many matched files as possible. + + -- Action: -execdir command {} + + This works as for '-execdir command ;', except that the result is + always true, and the '{}' at the end of the command is expanded to + a list of names of matching files. This expansion is done in such + a way as to avoid exceeding the maximum command line length + available on the system. Only one '{}' is allowed within the + command, and it must appear at the end, immediately before the '+'. + A '+' appearing in any position other than immediately after '{}' + is not considered to be special (that is, it does not terminate the + command). + + -- Action: -exec command {} + + This insecure variant of the '-execdir' action is specified by + POSIX. The main difference is that the command is executed in the + directory from which 'find' was invoked, meaning that '{}' is + expanded to a relative path starting with the name of one of the + starting directories, rather than just the basename of the matched + file. The result is always true. + + Before 'find' exits, any partially-built command lines are executed. +This happens even if the exit was caused by the '-quit' action. +However, some types of error (for example not being able to invoke +'stat()' on the current directory) can cause an immediate fatal exit. +In this situation, any partially-built command lines will not be invoked +(this prevents possible infinite loops). + + At first sight, it looks like the list of filenames to be processed +can only be at the end of the command line, and that this might be a +problem for some commands ('cp' and 'rsync' for example). + + However, there is a slightly obscure but powerful workaround for this +problem which takes advantage of the behaviour of 'sh -c': + + find startpoint -tests ... -exec sh -c 'scp "$@" remote:/dest' sh {} + + + In the example above, the filenames we want to work on need to occur +on the 'scp' command line before the name of the destination. We use +the shell to invoke the command 'scp "$@" remote:/dest' and the shell +expands '"$@"' to the list of filenames we want to process. + + Another, but less secure, way to run a command on more than one file +at once, is to use the 'xargs' command, which is invoked like this: + + xargs [OPTION...] [COMMAND [INITIAL-ARGUMENTS]] + + 'xargs' normally reads arguments from the standard input. These +arguments are delimited by blanks (which can be protected with double or +single quotes or a backslash) or newlines. It executes the COMMAND (the +default is 'echo') one or more times with any INITIAL-ARGUMENTS followed +by arguments read from standard input. Blank lines on the standard +input are ignored. If the '-L' option is in use, trailing blanks +indicate that 'xargs' should consider the following line to be part of +this one. + + Instead of blank-delimited names, it is safer to use 'find -print0' +or 'find -fprint0' and process the output by giving the '-0' or '--null' +option to GNU 'xargs', GNU 'tar', GNU 'cpio', or 'perl'. The 'locate' +command also has a '-0' or '--null' option which does the same thing. + + You can use shell command substitution (backquotes) to process a list +of arguments, like this: + + grep -l sprintf `find $HOME -name '*.c' -print` + + However, that method produces an error if the length of the '.c' file +names exceeds the operating system's command line length limit. 'xargs' +avoids that problem by running the command as many times as necessary +without exceeding the limit: + + find $HOME -name '*.c' -print | xargs grep -l sprintf + + However, if the command needs to have its standard input be a +terminal ('less', for example), you have to use the shell command +substitution method or use the '--arg-file' option of 'xargs'. + + The 'xargs' command will process all its input, building command +lines and executing them, unless one of the commands exits with a status +of 255 (this will cause xargs to issue an error message and stop) or it +reads a line contains the end of file string specified with the '--eof' +option. + +* Menu: + +* Unsafe File Name Handling:: +* Safe File Name Handling:: +* Unusual Characters in File Names:: +* Limiting Command Size:: +* Controlling Parallelism:: +* Interspersing File Names:: + + +File: find.info, Node: Unsafe File Name Handling, Next: Safe File Name Handling, Up: Multiple Files + +3.3.2.1 Unsafe File Name Handling +................................. + +Because file names can contain quotes, backslashes, blank characters, +and even newlines, it is not safe to process them using 'xargs' in its +default mode of operation. But since most files' names do not contain +blanks, this problem occurs only infrequently. If you are only +searching through files that you know have safe names, then you need not +be concerned about it. + + Error messages issued by 'find' and 'locate' quote unusual characters +in file names in order to prevent unwanted changes in the terminal's +state. + + In many applications, if 'xargs' botches processing a file because +its name contains special characters, some data might be lost. The +importance of this problem depends on the importance of the data and +whether anyone notices the loss soon enough to correct it. However, +here is an extreme example of the problems that using blank-delimited +names can cause. If the following command is run daily from 'cron', +then any user can remove any file on the system: + + find / -name '#*' -atime +7 -print | xargs rm + + For example, you could do something like this: + + eg$ echo > '# + vmunix' + +and then 'cron' would delete '/vmunix', if it ran 'xargs' with '/' as +its current directory. + + To delete other files, for example '/u/joeuser/.plan', you could do +this: + + eg$ mkdir '# + ' + eg$ cd '# + ' + eg$ mkdir u u/joeuser u/joeuser/.plan' + ' + eg$ echo > u/joeuser/.plan' + /#foo' + eg$ cd .. + eg$ find . -name '#*' -print | xargs echo + ./# ./# /u/joeuser/.plan /#foo + + +File: find.info, Node: Safe File Name Handling, Next: Unusual Characters in File Names, Prev: Unsafe File Name Handling, Up: Multiple Files + +3.3.2.2 Safe File Name Handling +............................... + +Here is how to make 'find' output file names so that they can be used by +other programs without being mangled or misinterpreted. You can process +file names generated this way by giving the '-0' or '--null' option to +GNU 'xargs', GNU 'tar', GNU 'cpio', or 'perl'. + + -- Action: -print0 + True; print the entire file name on the standard output, followed + by a null character. + + -- Action: -fprint0 file + True; like '-print0' but write to FILE like '-fprint' (*note Print + File Name::). The output file is always created. + + As of findutils version 4.2.4, the 'locate' program also has a +'--null' option which does the same thing. For similarity with 'xargs', +the short form of the option '-0' can also be used. + + If you want to be able to handle file names safely but need to run +commands which want to be connected to a terminal on their input, you +can use the '--arg-file' option to 'xargs' like this: + + find / -name xyzzy -print0 > list + xargs --null --arg-file=list munge + + The example above runs the 'munge' program on all the files named +'xyzzy' that we can find, but 'munge''s input will still be the terminal +(or whatever the shell was using as standard input). If your shell has +the "process substitution" feature '<(...)', you can do this in just one +step: + + xargs --null --arg-file=<(find / -name xyzzy -print0) munge + + +File: find.info, Node: Unusual Characters in File Names, Next: Limiting Command Size, Prev: Safe File Name Handling, Up: Multiple Files + +3.3.2.3 Unusual Characters in File Names +........................................ + +As discussed above, you often need to be careful about how the names of +files are handled by 'find' and other programs. If the output of 'find' +is not going to another program but instead is being shown on a +terminal, this can still be a problem. For example, some character +sequences can reprogram the function keys on some terminals. *Note +Security Considerations::, for a discussion of other security problems +relating to 'find'. + + Unusual characters are handled differently by various actions, as +described below. + +'-print0' +'-fprint0' + Always print the exact file name, unchanged, even if the output is + going to a terminal. +'-ok' +'-okdir' + Always print the exact file name, unchanged. This will probably + change in a future release. +'-ls' +'-fls' + Unusual characters are always escaped. White space, backslash, and + double quote characters are printed using C-style escaping (for + example '\f', '\"'). Other unusual characters are printed using an + octal escape. Other printable characters (for '-ls' and '-fls' + these are the characters between octal 041 and 0176) are printed + as-is. +'-printf' +'-fprintf' + If the output is not going to a terminal, it is printed as-is. + Otherwise, the result depends on which directive is in use: + + %D, %F, %H, %Y, %y + These expand to values which are not under control of files' + owners, and so are printed as-is. + %a, %b, %c, %d, %g, %G, %i, %k, %m, %M, %n, %s, %t, %u, %U + These have values which are under the control of files' owners + but which cannot be used to send arbitrary data to the + terminal, and so these are printed as-is. + %f, %h, %l, %p, %P + The output of these directives is quoted if the output is + going to a terminal. The setting of the 'LC_CTYPE' + environment variable is used to determine which characters + need to be quoted. + + This quoting is performed in the same way as for GNU 'ls'. + This is not the same quoting mechanism as the one used for + '-ls' and 'fls'. If you are able to decide what format to use + for the output of 'find' then it is normally better to use + '\0' as a terminator than to use newline, as file names can + contain white space and newline characters. +'-print' +'-fprint' + Quoting is handled in the same way as for the '%p' directive of + '-printf' and '-fprintf'. If you are using 'find' in a script or + in a situation where the matched files might have arbitrary names, + you should consider using '-print0' instead of '-print'. + + The 'locate' program quotes and escapes unusual characters in file +names in the same way as 'find''s '-print' action. + + The behaviours described above may change soon, as the treatment of +unprintable characters is harmonised for '-ls', '-fls', '-print', +'-fprint', '-printf' and '-fprintf'. + + +File: find.info, Node: Limiting Command Size, Next: Controlling Parallelism, Prev: Unusual Characters in File Names, Up: Multiple Files + +3.3.2.4 Limiting Command Size +............................. + +'xargs' gives you control over how many arguments it passes to the +command each time it executes it. By default, it uses up to 'ARG_MAX' - +2k, or 128k, whichever is smaller, characters per command. It uses as +many lines and arguments as fit within that limit. The following +options modify those values. + +'--no-run-if-empty' +'-r' + If the standard input does not contain any nonblanks, do not run + the command. By default, the command is run once even if there is + no input. This option is a GNU extension. + +'--max-lines[=MAX-LINES]' +'-L MAX-LINES' +'-l[MAX-LINES]' + Use at most MAX-LINES nonblank input lines per command line; + MAX-LINES defaults to 1 if omitted; omitting the argument is not + allowed in the case of the '-L' option. Trailing blanks cause an + input line to be logically continued on the next input line, for + the purpose of counting the lines. Implies '-x'. The preferred + name for this option is '-L' as this is specified by POSIX. + +'--max-args=MAX-ARGS' +'-n MAX-ARGS' + Use at most MAX-ARGS arguments per command line. Fewer than + MAX-ARGS arguments will be used if the size (see the '-s' option) + is exceeded, unless the '-x' option is given, in which case 'xargs' + will exit. + +'--max-chars=MAX-CHARS' +'-s MAX-CHARS' + Use at most MAX-CHARS characters per command line, including the + command initial arguments and the terminating nulls at the ends of + the argument strings. If you specify a value for this option which + is too large or small, a warning message is printed and the + appropriate upper or lower limit is used instead. You can use + '--show-limits' option to understand the command-line limits + applying to 'xargs' and how this is affected by any other options. + The POSIX limits shown when you do this have already been adjusted + to take into account the size of your environment variables. + + The largest allowed value is system-dependent, and is calculated as + the argument length limit for exec, less the size of your + environment, less 2048 bytes of headroom. If this value is more + than 128KiB, 128Kib is used as the default value; otherwise, the + default value is the maximum. + + +File: find.info, Node: Controlling Parallelism, Next: Interspersing File Names, Prev: Limiting Command Size, Up: Multiple Files + +3.3.2.5 Controlling Parallelism +............................... + +Normally, 'xargs' runs one command at a time. This is called "serial" +execution; the commands happen in a series, one after another. If you'd +like 'xargs' to do things in "parallel", you can ask it to do so, either +when you invoke it, or later while it is running. Running several +commands at one time can make the entire operation go more quickly, if +the commands are independent, and if your system has enough resources to +handle the load. When parallelism works in your application, 'xargs' +provides an easy way to get your work done faster. + +'--max-procs=MAX-PROCS' +'-P MAX-PROCS' + Run up to MAX-PROCS processes at a time; the default is 1. If + MAX-PROCS is 0, 'xargs' will run as many processes as possible at a + time. Use the '-n', '-s', or '-L' option with '-P'; otherwise + chances are that the command will be run only once. + + For example, suppose you have a directory tree of large image files +and a 'makeallsizes' script that takes a single file name and creates +various sized images from it (thumbnail-sized, web-page-sized, +printer-sized, and the original large file). The script is doing enough +work that it takes significant time to run, even on a single image. You +could run: + + find originals -name '*.jpg' | xargs -1 makeallsizes + + This will run 'makeallsizes FILENAME' once for each '.jpg' file in +the 'originals' directory. However, if your system has two central +processors, this script will only keep one of them busy. Instead, you +could probably finish in about half the time by running: + + find originals -name '*.jpg' | xargs -1 -P 2 makeallsizes + + 'xargs' will run the first two commands in parallel, and then +whenever one of them terminates, it will start another one, until the +entire job is done. + + The same idea can be generalized to as many processors as you have +handy. It also generalizes to other resources besides processors. For +example, if 'xargs' is running commands that are waiting for a response +from a distant network connection, running a few in parallel may reduce +the overall latency by overlapping their waiting time. + + If you are running commands in parallel, you need to think about how +they should arbitrate access to any resources that they share. For +example, if more than one of them tries to print to stdout, the ouptut +will be produced in an indeterminate order (and very likely mixed up) +unless the processes collaborate in some way to prevent this. Using +some kind of locking scheme is one way to prevent such problems. In +general, using a locking scheme will help ensure correct output but +reduce performance. If you don't want to tolerate the performance +difference, simply arrange for each process to produce a separate output +file (or otherwise use separate resources). + + 'xargs' also allows you to "turn up" or "turn down" its parallelism +in the middle of a run. Suppose you are keeping your four-processor +system busy for hours, processing thousands of images using '-P 4'. +Now, in the middle of the run, you or someone else wants you to reduce +your load on the system, so that something else will run faster. If you +interrupt 'xargs', your job will be half-done, and it may take +significant manual work to resume it only for the remaining images. If +you suspend 'xargs' using your shell's job controls (e.g. 'control-Z'), +then it will get no work done while suspended. + + Find out the process ID of the 'xargs' process, either from your +shell or with the 'ps' command. After you send it the signal 'SIGUSR2', +'xargs' will run one fewer command in parallel. If you send it the +signal 'SIGUSR1', it will run one more command in parallel. For +example: + + shell$ xargs <allimages -1 -P 4 makeallsizes & + [4] 27643 + ... at some later point ... + shell$ kill -USR2 27643 + shell$ kill -USR2 %4 + + The first 'kill' command will cause 'xargs' to wait for two commands +to terminate before starting the next command (reducing the parallelism +from 4 to 3). The second 'kill' will reduce it from 3 to 2. ('%4' +works in some shells as a shorthand for the process ID of the background +job labeled '[4]'.) + + Similarly, if you started a long 'xargs' job without parallelism, you +can easily switch it to start running two commands in parallel by +sending it a 'SIGUSR1'. + + 'xargs' will never terminate any existing commands when you ask it to +run fewer processes. It merely waits for the excess commands to finish. +If you ask it to run more commands, it will start the next one +immediately (if it has more work to do). If the degree of parallelism +is already 1, sending 'SIGUSR2' will have no further effect (since +'--max-procs=0' means that there should be no limit on the number of +processes to run). + + There is an implementation-defined limit on the number of processes. +This limit is shown with 'xargs --show-limits'. The limit is at least +127 on all systems (and on the author's system it is 2147483647). + + If you send several identical signals quickly, the operating system +does not guarantee that each of them will be delivered to 'xargs'. This +means that you can't rapidly increase or decrease the parallelism by +more than one command at a time. You can avoid this problem by sending +a signal, observing the result, then sending the next one; or merely by +delaying for a few seconds between signals (unless your system is very +heavily loaded). + + Whether or not parallel execution will work well for you depends on +the nature of the commmand you are running in parallel, on the +configuration of the system on which you are running the command, and on +the other work being done on the system at the time. + + +File: find.info, Node: Interspersing File Names, Prev: Controlling Parallelism, Up: Multiple Files + +3.3.2.6 Interspersing File Names +................................ + +'xargs' can insert the name of the file it is processing between +arguments you give for the command. Unless you also give options to +limit the command size (*note Limiting Command Size::), this mode of +operation is equivalent to 'find -exec' (*note Single File::). + +'--replace[=REPLACE-STR]' +'-I REPLACE-STR' +'-i REPLACE-STR' + Replace occurrences of REPLACE-STR in the initial arguments with + names read from the input. Also, unquoted blanks do not terminate + arguments; instead, the input is split at newlines only. For the + '-i' option, if REPLACE-STR is omitted for '--replace' or '-i', it + defaults to '{}' (like for 'find -exec'). Implies '-x' and '-l 1'. + '-i' is deprecated in favour of '-I'. As an example, to sort each + file in the 'bills' directory, leaving the output in that file name + with '.sorted' appended, you could do: + + find bills -type f | xargs -I XX sort -o XX.sorted XX + + The equivalent command using 'find -execdir' is: + + find bills -type f -execdir sort -o '{}.sorted' '{}' ';' + + When you use the '-I' option, each line read from the input is +buffered internally. This means that there is an upper limit on the +length of input line that 'xargs' will accept when used with the '-I' +option. To work around this limitation, you can use the '-s' option to +increase the amount of buffer space that xargs uses, and you can also +use an extra invocation of xargs to ensure that very long lines do not +occur. For example: + + somecommand | xargs -s 50000 echo | xargs -I '{}' -s 100000 rm '{}' + + Here, the first invocation of 'xargs' has no input line length limit +because it doesn't use the '-I' option. The second invocation of +'xargs' does have such a limit, but we have ensured that it never +encounters a line which is longer than it can handle. + + This is not an ideal solution. Instead, the '-I' option should not +impose a line length limit (apart from any limit imposed by the +operating system) and so one might consider this limitation to be a bug. +A better solution would be to allow 'xargs -I' to automatically move to +a larger value for the '-s' option when this is needed. + + This sort of problem doesn't occur with the output of 'find' because +it emits just one filename per line. + + +File: find.info, Node: Querying, Prev: Multiple Files, Up: Run Commands + +3.3.3 Querying +-------------- + +To ask the user whether to execute a command on a single file, you can +use the 'find' primary '-okdir' instead of '-execdir', and the 'find' +primary '-ok' instead of '-exec': + + -- Action: -okdir command ; + Like '-execdir' (*note Single File::), but ask the user first. If + the user does not agree to run the command, just return false. + Otherwise, run it, with standard input redirected from '/dev/null'. + + The response to the prompt is matched against a pair of regular + expressions to determine if it is a yes or no response. These + regular expressions are obtained from the system ('nl_langinfo' + items YESEXPR and NOEXPR are used) if the 'POSIXLY_CORRECT' + environment variable is set and the system has such patterns + available. Otherwise, 'find''s message translations are used. In + either case, the 'LC_MESSAGES' environment variable will determine + the regular expressions used to determine if the answer is + affirmative or negative. The interpretation of the regular + expressions themselves will be affected by the environment + variables 'LC_CTYPE' (character classes) and 'LC_COLLATE' + (character ranges and equivalence classes). + + -- Action: -ok command ; + This insecure variant of the '-okdir' action is specified by POSIX. + The main difference is that the command is executed in the + directory from which 'find' was invoked, meaning that '{}' is + expanded to a relative path starting with the name of one of the + starting directories, rather than just the basename of the matched + file. If the command is run, its standard input is redirected from + '/dev/null'. + + When processing multiple files with a single command, to query the +user you give 'xargs' the following option. When using this option, you +might find it useful to control the number of files processed per +invocation of the command (*note Limiting Command Size::). + +'--interactive' +'-p' + Prompt the user about whether to run each command line and read a + line from the terminal. Only run the command line if the response + starts with 'y' or 'Y'. Implies '-t'. + + +File: find.info, Node: Delete Files, Next: Adding Tests, Prev: Run Commands, Up: Actions + +3.4 Delete Files +================ + + -- Action: -delete + Delete files or directories; true if removal succeeded. If the + removal failed, an error message is issued. + + The use of the '-delete' action on the command line automatically + turns on the '-depth' option (*note find Expressions::). This can + be surprising if you were previously just testing with '-print', so + it is usually best to remember to use '-depth' explicitly. + + If '-delete' fails, 'find''s exit status will be nonzero (when it + eventually exits). + + +File: find.info, Node: Adding Tests, Prev: Delete Files, Up: Actions + +3.5 Adding Tests +================ + +You can test for file attributes that none of the 'find' builtin tests +check. To do this, use 'xargs' to run a program that filters a list of +files printed by 'find'. If possible, use 'find' builtin tests to pare +down the list, so the program run by 'xargs' has less work to do. The +tests builtin to 'find' will likely run faster than tests that other +programs perform. + + For reasons of efficiency it is often useful to limit the number of +times an external program has to be run. For this reason, it is often a +good idea to implement "extended" tests by using 'xargs'. + + For example, here is a way to print the names of all of the +unstripped binaries in the '/usr/local' directory tree. Builtin tests +avoid running 'file' on files that are not regular files or are not +executable. + + find /usr/local -type f -perm /a=x | xargs file | + grep 'not stripped' | cut -d: -f1 + +The 'cut' program removes everything after the file name from the output +of 'file'. + + However, using 'xargs' can present important security problems (*note +Security Considerations::). These can be avoided by using '-execdir'. +The '-execdir' action is also a useful way of putting your own test in +the middle of a set of other tests or actions for 'find' (for example, +you might want to use '-prune'). + + To place a special test somewhere in the middle of a 'find' +expression, you can use '-execdir' (or, less securely, '-exec') to run a +program that performs the test. Because '-execdir' evaluates to the +exit status of the executed program, you can use a program (which can be +a shell script) that tests for a special attribute and make it exit with +a true (zero) or false (non-zero) status. It is a good idea to place +such a special test _after_ the builtin tests, because it starts a new +process which could be avoided if a builtin test evaluates to false. + + Here is a shell script called 'unstripped' that checks whether its +argument is an unstripped binary file: + + #! /bin/sh + file "$1" | grep -q "not stripped" + + This script relies on the shell exiting with the status of the last +command in the pipeline, in this case 'grep'. The 'grep' command exits +with a true status if it found any matches, false if not. Here is an +example of using the script (assuming it is in your search path). It +lists the stripped executables (and shell scripts) in the file 'sbins' +and the unstripped ones in 'ubins'. + + find /usr/local -type f -perm /a=x \ + \( -execdir unstripped '{}' \; -fprint ubins -o -fprint sbins \) + + +File: find.info, Node: Databases, Next: File Permissions, Prev: Actions, Up: Top + +4 File Name Databases +********************* + +The file name databases used by 'locate' contain lists of files that +were in particular directory trees when the databases were last updated. +The file name of the default database is determined when 'locate' and +'updatedb' are configured and installed. The frequency with which the +databases are updated and the directories for which they contain entries +depend on how often 'updatedb' is run, and with which arguments. + + You can obtain some statistics about the databases by using 'locate +--statistics'. + +* Menu: + +* Database Locations:: +* Database Formats:: +* Newline Handling:: + + +File: find.info, Node: Database Locations, Next: Database Formats, Up: Databases + +4.1 Database Locations +====================== + +There can be multiple file name databases. Users can select which +databases 'locate' searches using the 'LOCATE_PATH' environment variable +or a command line option. The system administrator can choose the file +name of the default database, the frequency with which the databases are +updated, and the directories for which they contain entries. File name +databases are updated by running the 'updatedb' program, typically +nightly. + + In networked environments, it often makes sense to build a database +at the root of each filesystem, containing the entries for that +filesystem. 'updatedb' is then run for each filesystem on the +fileserver where that filesystem is on a local disk, to prevent +thrashing the network. + + *Note Invoking updatedb::, for the description of the options to +'updatedb'. These options can be used to specify which directories are +indexed by each database file. + + The default location for the locate database depends on how findutils +is built, but the findutils installation accompanying this manual uses +the default location '/usr/local/var/locatedb'. + + If no database exists at '/usr/local/var/locatedb' but the user did +not specify where to look (by using '-d' or setting 'LOCATE_PATH'), then +'locate' will also check for a "secure" database in +'/var/lib/slocate/slocate.db'. + + +File: find.info, Node: Database Formats, Next: Newline Handling, Prev: Database Locations, Up: Databases + +4.2 Database Formats +==================== + +The file name databases contain lists of files that were in particular +directory trees when the databases were last updated. The file name +database format changed starting with GNU 'locate' version 4.0 to allow +machines with different byte orderings to share the databases. + + GNU 'locate' can read both the old and new database formats. +However, old versions of 'locate' (on other Unix systems, or GNU +'locate' before version 4.0) produce incorrect results if run against a +database in something other than the old format. + + Support for the old database format will eventually be discontinued, +first in 'updatedb' and later in 'locate'. + + If you run 'locate --statistics', the resulting summary indicates the +type of each 'locate' database. You select which database format +'updatedb' will use with the '--dbformat' option. + +* Menu: + +* LOCATE02 Database Format:: +* Sample LOCATE02 Database:: +* slocate Database Format:: +* Old Database Format:: + + +File: find.info, Node: LOCATE02 Database Format, Next: Sample LOCATE02 Database, Up: Database Formats + +4.2.1 LOCATE02 Database Format +------------------------------ + +'updatedb' runs a program called 'frcode' to "front-compress" the list +of file names, which reduces the database size by a factor of 4 to 5. +Front-compression (also known as incremental encoding) works as follows. + + The database entries are a sorted list (case-insensitively, for +users' convenience). Since the list is sorted, each entry is likely to +share a prefix (initial string) with the previous entry. Each database +entry begins with an offset-differential count byte, which is the +additional number of characters of prefix of the preceding entry to use +beyond the number that the preceding entry is using of its predecessor. +(The counts can be negative.) Following the count is a null-terminated +ASCII remainder - the part of the name that follows the shared prefix. + + If the offset-differential count is larger than can be stored in a +byte (+/-127), the byte has the value 0x80 and the count follows in a +2-byte word, with the high byte first (network byte order). + + Every database begins with a dummy entry for a file called +'LOCATE02', which 'locate' checks for to ensure that the database file +has the correct format; it ignores the entry in doing the search. + + Databases cannot be concatenated together, even if the first (dummy) +entry is trimmed from all but the first database. This is because the +offset-differential count in the first entry of the second and following +databases will be wrong. + + In the output of 'locate --statistics', the new database format is +referred to as 'LOCATE02'. + + +File: find.info, Node: Sample LOCATE02 Database, Next: slocate Database Format, Prev: LOCATE02 Database Format, Up: Database Formats + +4.2.2 Sample LOCATE02 Database +------------------------------ + +Sample input to 'frcode': + + /usr/src + /usr/src/cmd/aardvark.c + /usr/src/cmd/armadillo.c + /usr/tmp/zoo + + Length of the longest prefix of the preceding entry to share: + + 0 /usr/src + 8 /cmd/aardvark.c + 14 rmadillo.c + 5 tmp/zoo + + Output from 'frcode', with trailing nulls changed to newlines and +count bytes made printable: + + 0 LOCATE02 + 0 /usr/src + 8 /cmd/aardvark.c + 6 rmadillo.c + -9 tmp/zoo + + (6 = 14 - 8, and -9 = 5 - 14) + + +File: find.info, Node: slocate Database Format, Next: Old Database Format, Prev: Sample LOCATE02 Database, Up: Database Formats + +4.2.3 slocate Database Format +----------------------------- + +The 'slocate' program uses a database format similar to, but not quite +the same as, GNU 'locate'. The first byte of the database specifies its +"security level". If the security level is 0, 'slocate' will read, +match and print filenames on the basis of the information in the +database only. However, if the security level byte is 1, 'slocate' +omits entries from its output if the invoking user is unable to access +them. The second byte of the database is zero. The second byte is +immediately followed by the first database entry. The first entry in +the database is not preceded by any differential count or dummy entry. +Instead the differential count for the first item is assumed to be zero. + + Starting with the second entry (if any) in the database, data is +interpreted as for the GNU LOCATE02 format. + + +File: find.info, Node: Old Database Format, Prev: slocate Database Format, Up: Database Formats + +4.2.4 Old Database Format +------------------------- + +The old database format is used by Unix 'locate' and 'find' programs and +earlier releases of the GNU ones. 'updatedb' produces this format if +given the '--old-format' option. + + 'updatedb' runs programs called 'bigram' and 'code' to produce +old-format databases. The old format differs from the new one in the +following ways. Instead of each entry starting with an +offset-differential count byte and ending with a null, byte values from +0 through 28 indicate offset-differential counts from -14 through 14. +The byte value indicating that a long offset-differential count follows +is 0x1e (30), not 0x80. The long counts are stored in host byte order, +which is not necessarily network byte order, and host integer word size, +which is usually 4 bytes. They also represent a count 14 less than +their value. The database lines have no termination byte; the start of +the next line is indicated by its first byte having a value <= 30. + + In addition, instead of starting with a dummy entry, the old database +format starts with a 256 byte table containing the 128 most common +bigrams in the file list. A bigram is a pair of adjacent bytes. Bytes +in the database that have the high bit set are indexes (with the high +bit cleared) into the bigram table. The bigram and offset-differential +count coding makes these databases 20-25% smaller than the new format, +but makes them not 8-bit clean. Any byte in a file name that is in the +ranges used for the special codes is replaced in the database by a +question mark, which not coincidentally is the shell wildcard to match a +single character. + + The old format therefore cannot faithfully store entries with +non-ASCII characters. It therefore should not be used in +internationalised environments. That is, most installations should not +use it. + + Because the long counts are stored by the 'code' program as +native-order machine words, the database format is not easily used in +environments which differ in terms of byte order. If locate databases +are to be shared between machines, the LOCATE02 database format should +be used. This has other benefits as discussed above. However, the +length of the filename currently being processed can normally be used to +place reasonable limits on the long counts and so this information is +used by locate to help it guess the byte ordering of the old format +database. Unless it finds evidence to the contrary, 'locate' will +assume that the byte order of the database is the same as the native +byte order of the machine running 'locate'. The output of 'locate +--statistics' also includes information about the byte order of +old-format databases. + + The output of 'locate --statistics' will give an incorrect count of +the number of file names containing newlines or high-bit characters for +old-format databases. + + Old versions of GNU 'locate' fail to correctly handle very long file +names, possibly leading to security problems relating to a heap buffer +overrun. *Note Security Considerations for locate::, for a detailed +explanation. + + +File: find.info, Node: Newline Handling, Prev: Database Formats, Up: Databases + +4.3 Newline Handling +==================== + +Within the database, file names are terminated with a null character. +This is the case for both the old and the new format. + + When the new database format is being used, the compression technique +used to generate the database though relies on the ability to sort the +list of files before they are presented to 'frcode'. + + If the system's sort command allows its input list of files to be +separated with null characters via the '-z' option, this option is used +and therefore 'updatedb' and 'locate' will both correctly handle file +names containing newlines. If the 'sort' command lacks support for +this, the list of files is delimited with the newline character, meaning +that parts of file names containing newlines will be incorrectly sorted. +This can result in both incorrect matches and incorrect failures to +match. + + On the other hand, if you are using the old database format, file +names with embedded newlines are not correctly handled. There is no +technical limitation which enforces this, it's just that the 'bigram' +program has not been updated to support lists of file names separated by +nulls. + + So, if you are using the new database format (this is the default) +and your system uses GNU 'sort', newlines will be correctly handled at +all times. Otherwise, newlines may not be correctly handled. + + +File: find.info, Node: File Permissions, Next: Date input formats, Prev: Databases, Up: Top + +5 File Permissions +****************** + +Each file has a set of "permissions" that control the kinds of access +that users have to that file. The permissions for a file are also +called its "access mode". They can be represented either in symbolic +form or as an octal number. + +* Menu: + +* Mode Structure:: Structure of file permissions. +* Symbolic Modes:: Mnemonic permissions representation. +* Numeric Modes:: Permissions as octal numbers. + + +File: find.info, Node: Mode Structure, Next: Symbolic Modes, Up: File Permissions + +5.1 Structure of File Permissions +================================= + +There are three kinds of permissions that a user can have for a file: + + 1. permission to read the file. For directories, this means + permission to list the contents of the directory. + 2. permission to write to (change) the file. For directories, this + means permission to create and remove files in the directory. + 3. permission to execute the file (run it as a program). For + directories, this means permission to access files in the + directory. + + There are three categories of users who may have different +permissions to perform any of the above operations on a file: + + 1. the file's owner; + 2. other users who are in the file's group; + 3. everyone else. + + Files are given an owner and group when they are created. Usually +the owner is the current user and the group is the group of the +directory the file is in, but this varies with the operating system, the +file system the file is created on, and the way the file is created. +You can change the owner and group of a file by using the 'chown' and +'chgrp' commands. + + In addition to the three sets of three permissions listed above, a +file's permissions have three special components, which affect only +executable files (programs) and, on some systems, directories: + + 1. Set the process's effective user ID to that of the file upon + execution (called the "setuid bit"). No effect on directories. + 2. Set the process's effective group ID to that of the file upon + execution (called the "setgid bit"). For directories on some + systems, put files created in the directory into the same group as + the directory, no matter what group the user who creates them is + in. + 3. prevent users from removing or renaming a file in a directory + unless they own the file or the directory; this is called the + "restricted deletion flag" for the directory. For regular files on + some systems, save the program's text image on the swap device so + it will load more quickly when run; this is called the "sticky + bit". + + In addition to the permissions listed above, there may be file +attributes specific to the file system, e.g: access control lists +(ACLs), whether a file is compressed, whether a file can be modified +(immutability), whether a file can be dumped. These are usually set +using programs specific to the file system. For example: + +ext2 + On GNU and GNU/Linux the file permissions ("attributes") specific + to the ext2 file system are set using 'chattr'. + +FFS + On FreeBSD the file permissions ("flags") specific to the FFS file + system are set using 'chrflags'. + + Although a file's permission "bits" allow an operation on that file, +that operation may still fail, because: + + * the file-system-specific permissions do not permit it; + + * the file system is mounted as read-only. + + For example, if the immutable attribute is set on a file, it cannot +be modified, regardless of the fact that you may have just run 'chmod +a+w FILE'. + + +File: find.info, Node: Symbolic Modes, Next: Numeric Modes, Prev: Mode Structure, Up: File Permissions + +5.2 Symbolic Modes +================== + +"Symbolic modes" represent changes to files' permissions as operations +on single-character symbols. They allow you to modify either all or +selected parts of files' permissions, optionally based on their previous +values, and perhaps on the current 'umask' as well (*note Umask and +Protection::). + + The format of symbolic modes is: + + [ugoa...][+-=]PERMS...[,...] + +where PERMS is either zero or more letters from the set 'rwxXst', or a +single letter from the set 'ugo'. + + The following sections describe the operators and other details of +symbolic modes. + +* Menu: + +* Setting Permissions:: Basic operations on permissions. +* Copying Permissions:: Copying existing permissions. +* Changing Special Permissions:: Special permissions. +* Conditional Executability:: Conditionally affecting executability. +* Multiple Changes:: Making multiple changes. +* Umask and Protection:: The effect of the umask. + + +File: find.info, Node: Setting Permissions, Next: Copying Permissions, Up: Symbolic Modes + +5.2.1 Setting Permissions +------------------------- + +The basic symbolic operations on a file's permissions are adding, +removing, and setting the permission that certain users have to read, +write, and execute the file. These operations have the following +format: + + USERS OPERATION PERMISSIONS + +The spaces between the three parts above are shown for readability only; +symbolic modes cannot contain spaces. + + The USERS part tells which users' access to the file is changed. It +consists of one or more of the following letters (or it can be empty; +*note Umask and Protection::, for a description of what happens then). +When more than one of these letters is given, the order that they are in +does not matter. + +'u' + the user who owns the file; +'g' + other users who are in the file's group; +'o' + all other users; +'a' + all users; the same as 'ugo'. + + The OPERATION part tells how to change the affected users' access to +the file, and is one of the following symbols: + +'+' + to add the PERMISSIONS to whatever permissions the USERS already + have for the file; +'-' + to remove the PERMISSIONS from whatever permissions the USERS + already have for the file; +'=' + to make the PERMISSIONS the only permissions that the USERS have + for the file. + + The PERMISSIONS part tells what kind of access to the file should be +changed; it is normally zero or more of the following letters. As with +the USERS part, the order does not matter when more than one letter is +given. Omitting the PERMISSIONS part is useful only with the '=' +operation, where it gives the specified USERS no access at all to the +file. + +'r' + the permission the USERS have to read the file; +'w' + the permission the USERS have to write to the file; +'x' + the permission the USERS have to execute the file. + + For example, to give everyone permission to read and write a file, +but not to execute it, use: + + a=rw + + To remove write permission for all users other than the file's owner, +use: + + go-w + +The above command does not affect the access that the owner of the file +has to it, nor does it affect whether other users can read or execute +the file. + + To give everyone except a file's owner no permission to do anything +with that file, use the mode below. Other users could still remove the +file, if they have write permission on the directory it is in. + + go= + +Another way to specify the same thing is: + + og-rwx + + +File: find.info, Node: Copying Permissions, Next: Changing Special Permissions, Prev: Setting Permissions, Up: Symbolic Modes + +5.2.2 Copying Existing Permissions +---------------------------------- + +You can base a file's permissions on its existing permissions. To do +this, instead of using a series of 'r', 'w', or 'x' letters after the +operator, you use the letter 'u', 'g', or 'o'. For example, the mode + + o+g + +adds the permissions for users who are in a file's group to the +permissions that other users have for the file. Thus, if the file +started out as mode 664 ('rw-rw-r--'), the above mode would change it to +mode 666 ('rw-rw-rw-'). If the file had started out as mode 741 +('rwxr----x'), the above mode would change it to mode 745 ('rwxr--r-x'). +The '-' and '=' operations work analogously. + + +File: find.info, Node: Changing Special Permissions, Next: Conditional Executability, Prev: Copying Permissions, Up: Symbolic Modes + +5.2.3 Changing Special Permissions +---------------------------------- + +In addition to changing a file's read, write, and execute permissions, +you can change its special permissions. *Note Mode Structure::, for a +summary of these permissions. + + To change a file's permission to set the user ID on execution, use +'u' in the USERS part of the symbolic mode and 's' in the PERMISSIONS +part. + + To change a file's permission to set the group ID on execution, use +'g' in the USERS part of the symbolic mode and 's' in the PERMISSIONS +part. + + To change a file's permission to set the restricted deletion flag or +sticky bit, omit the USERS part of the symbolic mode (or use 'a') and +put 't' in the PERMISSIONS part. + + For example, to add set-user-ID permission to a program, you can use +the mode: + + u+s + + To remove both set-user-ID and set-group-ID permission from it, you +can use the mode: + + ug-s + + To set the restricted deletion flag or sticky bit, you can use the +mode: + + +t + + The combination 'o+s' has no effect. On GNU systems the combinations +'u+t' and 'g+t' have no effect, and 'o+t' acts like plain '+t'. + + The '=' operator is not very useful with special permissions; for +example, the mode: + + o=t + +does set the restricted deletion flag or sticky bit, but it also removes +all read, write, and execute permissions that users not in the file's +group might have had for it. + + +File: find.info, Node: Conditional Executability, Next: Multiple Changes, Prev: Changing Special Permissions, Up: Symbolic Modes + +5.2.4 Conditional Executability +------------------------------- + +There is one more special type of symbolic permission: if you use 'X' +instead of 'x', execute permission is affected only if the file is a +directory or already had execute permission. + + For example, this mode: + + a+X + +gives all users permission to search directories, or to execute files if +anyone could execute them before. + + +File: find.info, Node: Multiple Changes, Next: Umask and Protection, Prev: Conditional Executability, Up: Symbolic Modes + +5.2.5 Making Multiple Changes +----------------------------- + +The format of symbolic modes is actually more complex than described +above (*note Setting Permissions::). It provides two ways to make +multiple changes to files' permissions. + + The first way is to specify multiple OPERATION and PERMISSIONS parts +after a USERS part in the symbolic mode. + + For example, the mode: + + og+rX-w + +gives users other than the owner of the file read permission and, if it +is a directory or if someone already had execute permission to it, gives +them execute permission; and it also denies them write permission to the +file. It does not affect the permission that the owner of the file has +for it. The above mode is equivalent to the two modes: + + og+rX + og-w + + The second way to make multiple changes is to specify more than one +simple symbolic mode, separated by commas. For example, the mode: + + a+r,go-w + +gives everyone permission to read the file and removes write permission +on it for all users except its owner. Another example: + + u=rwx,g=rx,o= + +sets all of the non-special permissions for the file explicitly. (It +gives users who are not in the file's group no permission at all for +it.) + + The two methods can be combined. The mode: + + a+r,g+x-w + +gives all users permission to read the file, and gives users who are in +the file's group permission to execute it, as well, but not permission +to write to it. The above mode could be written in several different +ways; another is: + + u+r,g+rx,o+r,g-w + + +File: find.info, Node: Umask and Protection, Prev: Multiple Changes, Up: Symbolic Modes + +5.2.6 The Umask and Protection +------------------------------ + +If the USERS part of a symbolic mode is omitted, it defaults to 'a' +(affect all users), except that any permissions that are _set_ in the +system variable 'umask' are _not affected_. The value of 'umask' can be +set using the 'umask' command. Its default value varies from system to +system. + + Omitting the USERS part of a symbolic mode is generally not useful +with operations other than '+'. It is useful with '+' because it allows +you to use 'umask' as an easily customizable protection against giving +away more permission to files than you intended to. + + As an example, if 'umask' has the value 2, which removes write +permission for users who are not in the file's group, then the mode: + + +w + +adds permission to write to the file to its owner and to other users who +are in the file's group, but _not_ to other users. In contrast, the +mode: + + a+w + +ignores 'umask', and _does_ give write permission for the file to all +users. + + +File: find.info, Node: Numeric Modes, Prev: Symbolic Modes, Up: File Permissions + +5.3 Numeric Modes +================= + +As an alternative to giving a symbolic mode, you can give an octal (base +8) number that represents the new mode. This number is always +interpreted in octal; you do not have to add a leading 0, as you do in +C. Mode 0055 is the same as mode 55. + + A numeric mode is usually shorter than the corresponding symbolic +mode, but it is limited in that it cannot take into account a file's +previous permissions; it can only set them absolutely. + + The permissions granted to the user, to other users in the file's +group, and to other users not in the file's group each require three +bits, which are represented as one octal digit. The three special +permissions also require one bit each, and they are as a group +represented as another octal digit. Here is how the bits are arranged, +starting with the lowest valued bit: + + Value in Corresponding + Mode Permission + + Other users not in the file's group: + 1 Execute + 2 Write + 4 Read + + Other users in the file's group: + 10 Execute + 20 Write + 40 Read + + The file's owner: + 100 Execute + 200 Write + 400 Read + + Special permissions: + 1000 Restricted deletion flag or sticky bit + 2000 Set group ID on execution + 4000 Set user ID on execution + + For example, numeric mode 4755 corresponds to symbolic mode +'u=rwxs,go=rx', and numeric mode 664 corresponds to symbolic mode +'ug=rw,o=r'. Numeric mode 0 corresponds to symbolic mode 'a='. + + +File: find.info, Node: Date input formats, Next: Configuration, Prev: File Permissions, Up: Top + +6 Date input formats +******************** + +First, a quote: + + Our units of temporal measurement, from seconds on up to months, + are so complicated, asymmetrical and disjunctive so as to make + coherent mental reckoning in time all but impossible. Indeed, had + some tyrannical god contrived to enslave our minds to time, to make + it all but impossible for us to escape subjection to sodden + routines and unpleasant surprises, he could hardly have done better + than handing down our present system. It is like a set of + trapezoidal building blocks, with no vertical or horizontal + surfaces, like a language in which the simplest thought demands + ornate constructions, useless particles and lengthy + circumlocutions. Unlike the more successful patterns of language + and science, which enable us to face experience boldly or at least + level-headedly, our system of temporal calculation silently and + persistently encourages our terror of time. + + ... It is as though architects had to measure length in feet, width + in meters and height in ells; as though basic instruction manuals + demanded a knowledge of five different languages. It is no wonder + then that we often look into our own immediate past or future, last + Tuesday or a week from Sunday, with feelings of helpless confusion. + ... + + --Robert Grudin, 'Time and the Art of Living'. + + This section describes the textual date representations that GNU +programs accept. These are the strings you, as a user, can supply as +arguments to the various programs. The C interface (via the +'parse_datetime' function) is not described here. + +* Menu: + +* General date syntax:: Common rules. +* Calendar date items:: 19 Dec 1994. +* Time of day items:: 9:20pm. +* Time zone items:: EST, PDT, UTC, ... +* Combined date and time of day items:: 1972-09-24T20:02:00,000000-0500. +* Day of week items:: Monday and others. +* Relative items in date strings:: next tuesday, 2 years ago. +* Pure numbers in date strings:: 19931219, 1440. +* Seconds since the Epoch:: @1078100502. +* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0". +* Authors of parse_datetime:: Bellovin, Eggert, Salz, Berets, et al. + + +File: find.info, Node: General date syntax, Next: Calendar date items, Up: Date input formats + +6.1 General date syntax +======================= + +A "date" is a string, possibly empty, containing many items separated by +whitespace. The whitespace may be omitted when no ambiguity arises. +The empty string means the beginning of today (i.e., midnight). Order +of the items is immaterial. A date string may contain many flavors of +items: + + * calendar date items + * time of day items + * time zone items + * combined date and time of day items + * day of the week items + * relative items + * pure numbers. + +We describe each of these item types in turn, below. + + A few ordinal numbers may be written out in words in some contexts. +This is most useful for specifying day of the week items or relative +items (see below). Among the most commonly used ordinal numbers, the +word 'last' stands for -1, 'this' stands for 0, and 'first' and 'next' +both stand for 1. Because the word 'second' stands for the unit of time +there is no way to write the ordinal number 2, but for convenience +'third' stands for 3, 'fourth' for 4, 'fifth' for 5, 'sixth' for 6, +'seventh' for 7, 'eighth' for 8, 'ninth' for 9, 'tenth' for 10, +'eleventh' for 11 and 'twelfth' for 12. + + When a month is written this way, it is still considered to be +written numerically, instead of being "spelled in full"; this changes +the allowed strings. + + In the current implementation, only English is supported for words +and abbreviations like 'AM', 'DST', 'EST', 'first', 'January', 'Sunday', +'tomorrow', and 'year'. + + The output of the 'date' command is not always acceptable as a date +string, not only because of the language problem, but also because there +is no standard meaning for time zone items like 'IST'. When using +'date' to generate a date string intended to be parsed later, specify a +date format that is independent of language and that does not use time +zone items other than 'UTC' and 'Z'. Here are some ways to do this: + + $ LC_ALL=C TZ=UTC0 date + Mon Mar 1 00:21:42 UTC 2004 + $ TZ=UTC0 date +'%Y-%m-%d %H:%M:%SZ' + 2004-03-01 00:21:42Z + $ date --rfc-3339=ns # --rfc-3339 is a GNU extension. + 2004-02-29 16:21:42.692722128-08:00 + $ date --rfc-2822 # a GNU extension + Sun, 29 Feb 2004 16:21:42 -0800 + $ date +'%Y-%m-%d %H:%M:%S %z' # %z is a GNU extension. + 2004-02-29 16:21:42 -0800 + $ date +'@%s.%N' # %s and %N are GNU extensions. + @1078100502.692722128 + + Alphabetic case is completely ignored in dates. Comments may be +introduced between round parentheses, as long as included parentheses +are properly nested. Hyphens not followed by a digit are currently +ignored. Leading zeros on numbers are ignored. + + Invalid dates like '2005-02-29' or times like '24:00' are rejected. +In the typical case of a host that does not support leap seconds, a time +like '23:59:60' is rejected even if it corresponds to a valid leap +second. + + +File: find.info, Node: Calendar date items, Next: Time of day items, Prev: General date syntax, Up: Date input formats + +6.2 Calendar date items +======================= + +A "calendar date item" specifies a day of the year. It is specified +differently, depending on whether the month is specified numerically or +literally. All these strings specify the same calendar date: + + 1972-09-24 # ISO 8601. + 72-9-24 # Assume 19xx for 69 through 99, + # 20xx for 00 through 68. + 72-09-24 # Leading zeros are ignored. + 9/24/72 # Common U.S. writing. + 24 September 1972 + 24 Sept 72 # September has a special abbreviation. + 24 Sep 72 # Three-letter abbreviations always allowed. + Sep 24, 1972 + 24-sep-72 + 24sep72 + + The year can also be omitted. In this case, the last specified year +is used, or the current year if none. For example: + + 9/24 + sep 24 + + Here are the rules. + + For numeric months, the ISO 8601 format 'YEAR-MONTH-DAY' is allowed, +where YEAR is any positive number, MONTH is a number between 01 and 12, +and DAY is a number between 01 and 31. A leading zero must be present +if a number is less than ten. If YEAR is 68 or smaller, then 2000 is +added to it; otherwise, if YEAR is less than 100, then 1900 is added to +it. The construct 'MONTH/DAY/YEAR', popular in the United States, is +accepted. Also 'MONTH/DAY', omitting the year. + + Literal months may be spelled out in full: 'January', 'February', +'March', 'April', 'May', 'June', 'July', 'August', 'September', +'October', 'November' or 'December'. Literal months may be abbreviated +to their first three letters, possibly followed by an abbreviating dot. +It is also permitted to write 'Sept' instead of 'September'. + + When months are written literally, the calendar date may be given as +any of the following: + + DAY MONTH YEAR + DAY MONTH + MONTH DAY YEAR + DAY-MONTH-YEAR + + Or, omitting the year: + + MONTH DAY + + +File: find.info, Node: Time of day items, Next: Time zone items, Prev: Calendar date items, Up: Date input formats + +6.3 Time of day items +===================== + +A "time of day item" in date strings specifies the time on a given day. +Here are some examples, all of which represent the same time: + + 20:02:00.000000 + 20:02 + 8:02pm + 20:02-0500 # In EST (U.S. Eastern Standard Time). + + More generally, the time of day may be given as 'HOUR:MINUTE:SECOND', +where HOUR is a number between 0 and 23, MINUTE is a number between 0 +and 59, and SECOND is a number between 0 and 59 possibly followed by '.' +or ',' and a fraction containing one or more digits. Alternatively, +':SECOND' can be omitted, in which case it is taken to be zero. On the +rare hosts that support leap seconds, SECOND may be 60. + + If the time is followed by 'am' or 'pm' (or 'a.m.' or 'p.m.'), HOUR +is restricted to run from 1 to 12, and ':MINUTE' may be omitted (taken +to be zero). 'am' indicates the first half of the day, 'pm' indicates +the second half of the day. In this notation, 12 is the predecessor of +1: midnight is '12am' while noon is '12pm'. (This is the zero-oriented +interpretation of '12am' and '12pm', as opposed to the old tradition +derived from Latin which uses '12m' for noon and '12pm' for midnight.) + + The time may alternatively be followed by a time zone correction, +expressed as 'SHHMM', where S is '+' or '-', HH is a number of zone +hours and MM is a number of zone minutes. The zone minutes term, MM, +may be omitted, in which case the one- or two-digit correction is +interpreted as a number of hours. You can also separate HH from MM with +a colon. When a time zone correction is given this way, it forces +interpretation of the time relative to Coordinated Universal Time (UTC), +overriding any previous specification for the time zone or the local +time zone. For example, '+0530' and '+05:30' both stand for the time +zone 5.5 hours ahead of UTC (e.g., India). This is the best way to +specify a time zone correction by fractional parts of an hour. The +maximum zone correction is 24 hours. + + Either 'am'/'pm' or a time zone correction may be specified, but not +both. + + +File: find.info, Node: Time zone items, Next: Combined date and time of day items, Prev: Time of day items, Up: Date input formats + +6.4 Time zone items +=================== + +A "time zone item" specifies an international time zone, indicated by a +small set of letters, e.g., 'UTC' or 'Z' for Coordinated Universal Time. +Any included periods are ignored. By following a non-daylight-saving +time zone by the string 'DST' in a separate word (that is, separated by +some white space), the corresponding daylight saving time zone may be +specified. Alternatively, a non-daylight-saving time zone can be +followed by a time zone correction, to add the two values. This is +normally done only for 'UTC'; for example, 'UTC+05:30' is equivalent to +'+05:30'. + + Time zone items other than 'UTC' and 'Z' are obsolescent and are not +recommended, because they are ambiguous; for example, 'EST' has a +different meaning in Australia than in the United States. Instead, it's +better to use unambiguous numeric time zone corrections like '-0500', as +described in the previous section. + + If neither a time zone item nor a time zone correction is supplied, +time stamps are interpreted using the rules of the default time zone +(*note Specifying time zone rules::). + + +File: find.info, Node: Combined date and time of day items, Next: Day of week items, Prev: Time zone items, Up: Date input formats + +6.5 Combined date and time of day items +======================================= + +The ISO 8601 date and time of day extended format consists of an ISO +8601 date, a 'T' character separator, and an ISO 8601 time of day. This +format is also recognized if the 'T' is replaced by a space. + + In this format, the time of day should use 24-hour notation. +Fractional seconds are allowed, with either comma or period preceding +the fraction. ISO 8601 fractional minutes and hours are not supported. +Typically, hosts support nanosecond timestamp resolution; excess +precision is silently discarded. + + Here are some examples: + + 2012-09-24T20:02:00.052-05:00 + 2012-12-31T23:59:59,999999999+11:00 + 1970-01-01 00:00Z + + +File: find.info, Node: Day of week items, Next: Relative items in date strings, Prev: Combined date and time of day items, Up: Date input formats + +6.6 Day of week items +===================== + +The explicit mention of a day of the week will forward the date (only if +necessary) to reach that day of the week in the future. + + Days of the week may be spelled out in full: 'Sunday', 'Monday', +'Tuesday', 'Wednesday', 'Thursday', 'Friday' or 'Saturday'. Days may be +abbreviated to their first three letters, optionally followed by a +period. The special abbreviations 'Tues' for 'Tuesday', 'Wednes' for +'Wednesday' and 'Thur' or 'Thurs' for 'Thursday' are also allowed. + + A number may precede a day of the week item to move forward +supplementary weeks. It is best used in expression like 'third monday'. +In this context, 'last DAY' or 'next DAY' is also acceptable; they move +one week before or after the day that DAY by itself would represent. + + A comma following a day of the week item is ignored. + + +File: find.info, Node: Relative items in date strings, Next: Pure numbers in date strings, Prev: Day of week items, Up: Date input formats + +6.7 Relative items in date strings +================================== + +"Relative items" adjust a date (or the current date if none) forward or +backward. The effects of relative items accumulate. Here are some +examples: + + 1 year + 1 year ago + 3 years + 2 days + + The unit of time displacement may be selected by the string 'year' or +'month' for moving by whole years or months. These are fuzzy units, as +years and months are not all of equal duration. More precise units are +'fortnight' which is worth 14 days, 'week' worth 7 days, 'day' worth 24 +hours, 'hour' worth 60 minutes, 'minute' or 'min' worth 60 seconds, and +'second' or 'sec' worth one second. An 's' suffix on these units is +accepted and ignored. + + The unit of time may be preceded by a multiplier, given as an +optionally signed number. Unsigned numbers are taken as positively +signed. No number at all implies 1 for a multiplier. Following a +relative item by the string 'ago' is equivalent to preceding the unit by +a multiplier with value -1. + + The string 'tomorrow' is worth one day in the future (equivalent to +'day'), the string 'yesterday' is worth one day in the past (equivalent +to 'day ago'). + + The strings 'now' or 'today' are relative items corresponding to +zero-valued time displacement, these strings come from the fact a +zero-valued time displacement represents the current time when not +otherwise changed by previous items. They may be used to stress other +items, like in '12:00 today'. The string 'this' also has the meaning of +a zero-valued time displacement, but is preferred in date strings like +'this thursday'. + + When a relative item causes the resulting date to cross a boundary +where the clocks were adjusted, typically for daylight saving time, the +resulting date and time are adjusted accordingly. + + The fuzz in units can cause problems with relative items. For +example, '2003-07-31 -1 month' might evaluate to 2003-07-01, because +2003-06-31 is an invalid date. To determine the previous month more +reliably, you can ask for the month before the 15th of the current +month. For example: + + $ date -R + Thu, 31 Jul 2003 13:02:39 -0700 + $ date --date='-1 month' +'Last month was %B?' + Last month was July? + $ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!' + Last month was June! + + Also, take care when manipulating dates around clock changes such as +daylight saving leaps. In a few cases these have added or subtracted as +much as 24 hours from the clock, so it is often wise to adopt universal +time by setting the 'TZ' environment variable to 'UTC0' before embarking +on calendrical calculations. + + +File: find.info, Node: Pure numbers in date strings, Next: Seconds since the Epoch, Prev: Relative items in date strings, Up: Date input formats + +6.8 Pure numbers in date strings +================================ + +The precise interpretation of a pure decimal number depends on the +context in the date string. + + If the decimal number is of the form YYYYMMDD and no other calendar +date item (*note Calendar date items::) appears before it in the date +string, then YYYY is read as the year, MM as the month number and DD as +the day of the month, for the specified calendar date. + + If the decimal number is of the form HHMM and no other time of day +item appears before it in the date string, then HH is read as the hour +of the day and MM as the minute of the hour, for the specified time of +day. MM can also be omitted. + + If both a calendar date and a time of day appear to the left of a +number in the date string, but no relative item, then the number +overrides the year. + + +File: find.info, Node: Seconds since the Epoch, Next: Specifying time zone rules, Prev: Pure numbers in date strings, Up: Date input formats + +6.9 Seconds since the Epoch +=========================== + +If you precede a number with '@', it represents an internal time stamp +as a count of seconds. The number can contain an internal decimal point +(either '.' or ','); any excess precision not supported by the internal +representation is truncated toward minus infinity. Such a number cannot +be combined with any other date item, as it specifies a complete time +stamp. + + Internally, computer times are represented as a count of seconds +since an epoch--a well-defined point of time. On GNU and POSIX systems, +the epoch is 1970-01-01 00:00:00 UTC, so '@0' represents this time, '@1' +represents 1970-01-01 00:00:01 UTC, and so forth. GNU and most other +POSIX-compliant systems support such times as an extension to POSIX, +using negative counts, so that '@-1' represents 1969-12-31 23:59:59 UTC. + + Traditional Unix systems count seconds with 32-bit two's-complement +integers and can represent times from 1901-12-13 20:45:52 through +2038-01-19 03:14:07 UTC. More modern systems use 64-bit counts of +seconds with nanosecond subcounts, and can represent all the times in +the known lifetime of the universe to a resolution of 1 nanosecond. + + On most hosts, these counts ignore the presence of leap seconds. For +example, on most hosts '@915148799' represents 1998-12-31 23:59:59 UTC, +'@915148800' represents 1999-01-01 00:00:00 UTC, and there is no way to +represent the intervening leap second 1998-12-31 23:59:60 UTC. + + +File: find.info, Node: Specifying time zone rules, Next: Authors of parse_datetime, Prev: Seconds since the Epoch, Up: Date input formats + +6.10 Specifying time zone rules +=============================== + +Normally, dates are interpreted using the rules of the current time +zone, which in turn are specified by the 'TZ' environment variable, or +by a system default if 'TZ' is not set. To specify a different set of +default time zone rules that apply just to one date, start the date with +a string of the form 'TZ="RULE"'. The two quote characters ('"') must +be present in the date, and any quotes or backslashes within RULE must +be escaped by a backslash. + + For example, with the GNU 'date' command you can answer the question +"What time is it in New York when a Paris clock shows 6:30am on October +31, 2004?" by using a date beginning with 'TZ="Europe/Paris"' as shown +in the following shell transcript: + + $ export TZ="America/New_York" + $ date --date='TZ="Europe/Paris" 2004-10-31 06:30' + Sun Oct 31 01:30:00 EDT 2004 + + In this example, the '--date' operand begins with its own 'TZ' +setting, so the rest of that operand is processed according to +'Europe/Paris' rules, treating the string '2004-10-31 06:30' as if it +were in Paris. However, since the output of the 'date' command is +processed according to the overall time zone rules, it uses New York +time. (Paris was normally six hours ahead of New York in 2004, but this +example refers to a brief Halloween period when the gap was five hours.) + + A 'TZ' value is a rule that typically names a location in the 'tz' +database (http://www.twinsun.com/tz/tz-link.htm). A recent catalog of +location names appears in the TWiki Date and Time Gateway +(http://twiki.org/cgi-bin/xtra/tzdate). A few non-GNU hosts require a +colon before a location name in a 'TZ' setting, e.g., +'TZ=":America/New_York"'. + + The 'tz' database includes a wide variety of locations ranging from +'Arctic/Longyearbyen' to 'Antarctica/South_Pole', but if you are at sea +and have your own private time zone, or if you are using a non-GNU host +that does not support the 'tz' database, you may need to use a POSIX +rule instead. Simple POSIX rules like 'UTC0' specify a time zone +without daylight saving time; other rules can specify simple daylight +saving regimes. *Note Specifying the Time Zone with 'TZ': (libc)TZ +Variable. + + +File: find.info, Node: Authors of parse_datetime, Prev: Specifying time zone rules, Up: Date input formats + +6.11 Authors of 'parse_datetime' +================================ + +'parse_datetime' started life as 'getdate', as originally implemented by +Steven M. Bellovin (<smb@research.att.com>) while at the University of +North Carolina at Chapel Hill. The code was later tweaked by a couple +of people on Usenet, then completely overhauled by Rich $alz +(<rsalz@bbn.com>) and Jim Berets (<jberets@bbn.com>) in August, 1990. +Various revisions for the GNU system were made by David MacKenzie, Jim +Meyering, Paul Eggert and others, including renaming it to 'get_date' to +avoid a conflict with the alternative Posix function 'getdate', and a +later rename to 'parse_datetime'. The Posix function 'getdate' can +parse more locale-specific dates using 'strptime', but relies on an +environment variable and external file, and lacks the thread-safety of +'parse_datetime'. + + This chapter was originally produced by Franc,ois Pinard +(<pinard@iro.umontreal.ca>) from the 'parse_datetime.y' source code, and +then edited by K. Berry (<kb@cs.umb.edu>). + + +File: find.info, Node: Configuration, Next: Reference, Prev: Date input formats, Up: Top + +7 Configuration +*************** + +The findutils source distribution includes a 'configure' script which +examines the system and generates files required to build findutils. +See the files 'README' and 'INSTALL'. + + A number of options can be specified on the 'configure' command line, +and many of these are straightforward, adequately documented in the +'--help' output, or not normally useful. Options which are useful or +which are not obvious are explained here. + +* Menu: + +* Leaf Optimisation:: Take advantage of Unix file system semantics. +* d_type Optimisation:: Take advantage of file type information. +* fts:: A non-recursive file system search. + + +File: find.info, Node: Leaf Optimisation, Next: d_type Optimisation, Up: Configuration + +7.1 Leaf Optimisation +===================== + +Files in Unix file systems have a link count which indicates how many +names point to the same inode. Directories in Unix filssytems have a +'..' entry which functions as a hard link to the parent directory and a +'.' entry which functions as a link to the directory itself. The '..' +entry of the root directory also points to the root. This means that +'find' can deduce the number of subdirectories a directory has, simply +by subtracting 2 from the directory's link count. This allows 'find' +the calls to 'stat' which would otherwise be needed to discover which +directory entries are subdirectories. + + File systems which don't have these semantics should simply return a +value less than 2 in the 'st_nlinks' member of 'struct stat' in response +to a successful call to 'stat'. + + If you are building 'find' for a system on which the value of +'st_nlinks' is unreliable, you can specify '--disable-leaf-optimisation' +to 'configure' to prevent this assumption being made. + + +File: find.info, Node: d_type Optimisation, Next: fts, Prev: Leaf Optimisation, Up: Configuration + +7.2 d_type Optimisation +======================= + +When this feature is enabled, 'find' takes advantage of the fact that on +some systems 'readdir' will return the type of a file in 'struct +dirent'. + + +File: find.info, Node: fts, Prev: d_type Optimisation, Up: Configuration + +7.3 fts +======= + +The findutils source distribution contains two different implementations +of 'find'. The older implementation descends the file system +recursively, while the newer one uses 'fts'. Both are normally +installed. + + If the option '--without-fts' was passed to 'configure', the +recursive implementation is installed as 'find' and the fts-based +implementation is installed as 'ftsfind'. Otherwise, the fts-based +implementation is installed as 'find' and the recursive implementation +is installed as 'oldfind'. + + +File: find.info, Node: Reference, Next: Common Tasks, Prev: Configuration, Up: Top + +8 Reference +*********** + +Below are summaries of the command line syntax for the programs +discussed in this manual. + +* Menu: + +* Invoking find:: +* Invoking locate:: +* Invoking updatedb:: +* Invoking xargs:: +* Regular Expressions:: +* Environment Variables:: + + +File: find.info, Node: Invoking find, Next: Invoking locate, Up: Reference + +8.1 Invoking 'find' +=================== + + find [-H] [-L] [-P] [-D DEBUGOPTIONS] [-OLEVEL] [FILE...] [EXPRESSION] + + 'find' searches the directory tree rooted at each file name FILE by +evaluating the EXPRESSION on each file it finds in the tree. + + The command line may begin with the '-H', '-L', '-P', '-D' and '-O' +options. These are followed by a list of files or directories that +should be searched. If no files to search are specified, the current +directory ('.') is used. + + This list of files to search is followed by a list of expressions +describing the files we wish to search for. The first part of the +expression is recognised by the fact that it begins with '-' followed by +some other letters (for example '-print'), or is either '(' or '!'. Any +arguments after it are the rest of the expression. + + If no expression is given, the expression '-print' is used. + + The 'find' command exits with status zero if all files matched are +processed successfully, greater than zero if errors occur. + + The 'find' program also recognises two options for administrative +use: + +'--help' + Print a summary of the command line usage and exit. +'--version' + Print the version number of 'find' and exit. + + The '-version' option is a synonym for '--version' + +* Menu: + +* Filesystem Traversal Options:: +* Warning Messages:: +* Optimisation Options:: +* Debug Options:: +* Find Expressions:: + + +File: find.info, Node: Filesystem Traversal Options, Next: Warning Messages, Up: Invoking find + +8.1.1 Filesystem Traversal Options +---------------------------------- + +The options '-H', '-L' or '-P' may be specified at the start of the +command line (if none of these is specified, '-P' is assumed). If you +specify more than one of these options, the last one specified takes +effect (but note that the '-follow' option is equivalent to '-L'). + +'-P' + Never follow symbolic links (this is the default), except in the + case of the '-xtype' predicate. +'-L' + Always follow symbolic links, except in the case of the '-xtype' + predicate. +'-H' + Follow symbolic links specified in the list of files to search, or + which are otherwise specified on the command line. + + If 'find' would follow a symbolic link, but cannot for any reason +(for example, because it has insufficient permissions or the link is +broken), it falls back on using the properties of the symbolic link +itself. *note Symbolic Links:: for a more complete description of how +symbolic links are handled. + + +File: find.info, Node: Warning Messages, Next: Optimisation Options, Prev: Filesystem Traversal Options, Up: Invoking find + +8.1.2 Warning Messages +---------------------- + +If there is an error on the 'find' command line, an error message is +normally issued. However, there are some usages that are inadvisable +but which 'find' should still accept. Under these circumstances, 'find' +may issue a warning message. + + By default, warnings are enabled only if 'find' is being run +interactively (specifically, if the standard input is a terminal) and +the 'POSIXLY_CORRECT' environment variable is not set. Warning messages +can be controlled explicitly by the use of options on the command line: + +'-warn' + Issue warning messages where appropriate. +'-nowarn' + Do not issue warning messages. + + These options take effect at the point on the command line where they +are specified. Therefore it's not useful to specify '-nowarn' at the +end of the command line. The warning messages affected by the above +options are triggered by: + + - Use of the '-d' option which is deprecated; please use '-depth' + instead, since the latter is POSIX-compliant. + - Use of the '-ipath' option which is deprecated; please use + '-iwholename' instead. + - Specifying an option (for example '-mindepth') after a non-option + (for example '-type' or '-print') on the command line. + - Use of the '-name' or '-iname' option with a slash character in the + pattern. Since the name predicates only compare against the + basename of the visited files, the only file that can match a slash + is the root directory itself. + + The default behaviour above is designed to work in that way so that +existing shell scripts don't generate spurious errors, but people will +be made aware of the problem. + + Some warning messages are issued for less common or more serious +problems, and consequently cannot be turned off: + + - Use of an unrecognised backslash escape sequence with '-fprintf' + - Use of an unrecognised formatting directive with '-fprintf' + + +File: find.info, Node: Optimisation Options, Next: Debug Options, Prev: Warning Messages, Up: Invoking find + +8.1.3 Optimisation Options +-------------------------- + +The '-OLEVEL' option sets 'find''s optimisation level to LEVEL. The +default optimisation level is 1. + + At certain optimisation levels, 'find' reorders tests to speed up +execution while preserving the overall effect; that is, predicates with +side effects are not reordered relative to each other. The +optimisations performed at each optimisation level are as follows. + +'0' + Currently equivalent to optimisation level 1. + +'1' + This is the default optimisation level and corresponds to the + traditional behaviour. Expressions are reordered so that tests + based only on the names of files (for example' -name' and '-regex') + are performed first. + +'2' + Any '-type' or '-xtype' tests are performed after any tests based + only on the names of files, but before any tests that require + information from the inode. On many modern versions of Unix, file + types are returned by 'readdir()' and so these predicates are + faster to evaluate than predicates which need to stat the file + first. + + If you use the '-fstype FOO' predicate and specify a filsystem type + 'FOO' which is not known (that is, present in '/etc/mtab') at the + time 'find' starts, that predicate is equivalent to '-false'. + +'3' + At this optimisation level, the full cost-based query optimiser is + enabled. The order of tests is modified so that cheap (i.e., fast) + tests are performed first and more expensive ones are performed + later, if necessary. Within each cost band, predicates are + evaluated earlier or later according to whether they are likely to + succeed or not. For '-o', predicates which are likely to succeed + are evaluated earlier, and for '-a', predicates which are likely to + fail are evaluated earlier. + + +File: find.info, Node: Debug Options, Next: Find Expressions, Prev: Optimisation Options, Up: Invoking find + +8.1.4 Debug Options +------------------- + +The '-D' option makes 'find' produce diagnostic output. Much of the +information is useful only for diagnosing problems, and so most people +will not find this option helpful. + + The list of debug options should be comma separated. Compatibility +of the debug options is not guaranteed between releases of findutils. +For a complete list of valid debug options, see the output of 'find -D +help'. Valid debug options include: +'help' + Explain the debugging options. +'tree' + Show the expression tree in its original and optimised form. +'stat' + Print messages as files are examined with the stat and lstat system + calls. The find program tries to minimise such calls. +'opt' + Prints diagnostic information relating to the optimisation of the + expression tree; see the '-O' option. +'rates' + Prints a summary indicating how often each predicate succeeded or + failed. + + +File: find.info, Node: Find Expressions, Prev: Debug Options, Up: Invoking find + +8.1.5 Find Expressions +---------------------- + +The final part of the 'find' command line is a list of expressions. +*Note Primary Index::, for a summary of all of the tests, actions, and +options that the expression can contain. If the expression is missing, +'-print' is assumed. + + +File: find.info, Node: Invoking locate, Next: Invoking updatedb, Prev: Invoking find, Up: Reference + +8.2 Invoking 'locate' +===================== + + locate [OPTION...] PATTERN... + + For each PATTERN given 'locate' searches one or more file name +databases returning each match of PATTERN. + +'--all' +'-A' + Print only names which match all non-option arguments, not those + matching one or more non-option arguments. + +'--basename' +'-b' + The specified pattern is matched against just the last component of + the name of a file in the 'locate' database. This last component + is also called the "base name". For example, the base name of + '/tmp/mystuff/foo.old.c' is 'foo.old.c'. If the pattern contains + metacharacters, it must match the base name exactly. If not, it + must match part of the base name. + +'--count' +'-c' + Instead of printing the matched file names, just print the total + number of matches found, unless '--print' ('-p') is also present. + +'--database=PATH' +'-d PATH' + Instead of searching the default 'locate' database + '/usr/local/var/locatedb', 'locate' searches the file name + databases in PATH, which is a colon-separated list of database file + names. You can also use the environment variable 'LOCATE_PATH' to + set the list of database files to search. The option overrides the + environment variable if both are used. Empty elements in PATH + (that is, a leading or trailing colon, or two colons in a row) are + taken to stand for the default database. A database can be + supplied on stdin, using '-' as an element of 'path'. If more than + one element of 'path' is '-', later instances are ignored (but a + warning message is printed). + +'--existing' +'-e' + Only print out such names which currently exist (instead of such + names which existed when the database was created). Note that this + may slow down the program a lot, if there are many matches in the + database. The way in which broken symbolic links are treated is + affected by the '-L', '-P' and '-H' options. Please note that it + is possible for the file to be deleted after 'locate' has checked + that it exists, but before you use it. This option is + automatically turned on when reading an 'slocate' database in + secure mode (*note slocate Database Format::). + +'--non-existing' +'-E' + Only print out such names which currently do not exist (instead of + such names which existed when the database was created). Note that + this may slow down the program a lot, if there are many matches in + the database. The way in which broken symbolic links are treated + is affected by the '-L', '-P' and '-H' options. Please note that + 'locate' checks that the file does not exist, but a file of the + same name might be created after 'locate''s check but before you + read 'locate''s output. + +'--follow' +'-L' + If testing for the existence of files (with the '-e' or '-E' + options), consider broken symbolic links to be non-existing. This + is the default behaviour. + +'--nofollow' +'-P' +'-H' + If testing for the existence of files (with the '-e' or '-E' + options), treat broken symbolic links as if they were existing + files. The '-H' form of this option is provided purely for + similarity with 'find'; the use of '-P' is recommended over '-H'. + +'--ignore-case' +'-i' + Ignore case distinctions in both the pattern and the file names. + +'--limit=N' +'-l N' + Limit the number of results printed to N. When used with the + '--count' option, the value printed will never be larger than this + limit. +'--max-database-age=D' + Normally, 'locate' will issue a warning message when it searches a + database which is more than 8 days old. This option changes that + value to something other than 8. The effect of specifying a + negative value is undefined. +'--mmap' +'-m' + Accepted but does nothing. The option is supported only to provide + compatibility with BSD's 'locate'. + +'--null' +'-0' + Results are separated with the ASCII NUL character rather than the + newline character. To get the full benefit of this option, use the + new 'locate' database format (that is the default anyway). + +'--print' +'-p' + Print search results when they normally would not be due to use of + '--statistics' ('-S') or '--count' ('-c'). + +'--wholename' +'-w' + The specified pattern is matched against the whole name of the file + in the 'locate' database. If the pattern contains metacharacters, + it must match exactly. If not, it must match part of the whole + file name. This is the default behaviour. + +'--regex' +'-r' + Instead of using substring or shell glob matching, the pattern + specified on the command line is understood to be a regular + expression. GNU Emacs-style regular expressions are assumed unless + the '--regextype' option is also given. File names from the + 'locate' database are matched using the specified regular + expression. If the '-i' flag is also given, matching is + case-insensitive. Matches are performed against the whole path + name, and so by default a pathname will be matched if any part of + it matches the specified regular expression. The regular + expression may use '^' or '$' to anchor a match at the beginning or + end of a pathname. + +'--regextype' + This option changes the regular expression syntax and behaviour + used by the '--regex' option. *note Regular Expressions:: for more + information on the regular expression dialects understood by GNU + findutils. + +'--stdio' +'-s' + Accepted but does nothing. The option is supported only to provide + compatibility with BSD's 'locate'. + +'--statistics' +'-S' + Print some summary information for each 'locate' database. No + search is performed unless non-option arguments are given. + Although the BSD version of locate also has this option, the format + of the output is different. + +'--help' + Print a summary of the command line usage for 'locate' and exit. + +'--version' + Print the version number of 'locate' and exit. + + +File: find.info, Node: Invoking updatedb, Next: Invoking xargs, Prev: Invoking locate, Up: Reference + +8.3 Invoking 'updatedb' +======================= + + updatedb [OPTION...] + + 'updatedb' creates and updates the database of file names used by +'locate'. 'updatedb' generates a list of files similar to the output of +'find' and then uses utilities for optimizing the database for +performance. 'updatedb' is often run periodically as a 'cron' job and +configured with environment variables or command options. Typically, +operating systems have a shell script that "exports" configurations for +variable definitions and uses another shell script that "sources" the +configuration file into the environment and then executes 'updatedb' in +the environment. + +'--findoptions='OPTION...'' + Global options to pass on to 'find'. The environment variable + 'FINDOPTIONS' also sets this value. Default is none. + +'--localpaths='PATH...'' + Non-network directories to put in the database. Default is '/'. + +'--netpaths='PATH...'' + Network (NFS, AFS, RFS, etc.) directories to put in the database. + The environment variable 'NETPATHS' also sets this value. Default + is none. + +'--prunepaths='PATH...'' + Directories to omit from the database, which would otherwise be + included. The environment variable 'PRUNEPATHS' also sets this + value. Default is '/tmp /usr/tmp /var/tmp /afs'. The paths are + used as regular expressions (with 'find ... -regex', so you need to + specify these paths in the same way that 'find' will encounter + them. This means for example that the paths must not include + trailing slashes. + +'--prunefs='PATH...'' + Filesystems to omit from the database, which would otherwise be + included. Note that files are pruned when a filesystem is reached; + Any filesystem mounted under an undesired filesystem will be + ignored. The environment variable 'PRUNEFS' also sets this value. + Default is 'nfs NFS proc'. + +'--output=DBFILE' + The database file to build. The default is system-dependent, but + when this document was formatted it was '/usr/local/var/locatedb'. + +'--localuser=USER' + The user to search the non-network directories as, using 'su'. + Default is to search the non-network directories as the current + user. You can also use the environment variable 'LOCALUSER' to set + this user. + +'--netuser=USER' + The user to search network directories as, using 'su'. Default + 'user' is 'daemon'. You can also use the environment variable + 'NETUSER' to set this user. + +'--old-format' + Generate a 'locate' database in the old format, for compatibility + with versions of 'locate' other than GNU 'locate'. Using this + option means that 'locate' will not be able to properly handle + non-ASCII characters in file names (that is, file names containing + characters which have the eighth bit set, such as many of the + characters from the ISO-8859-1 character set). *Note Database + Formats::, for a detailed description of the supported database + formats. + +'--dbformat=FORMAT' + Generate the locate database in format 'FORMAT'. Supported + database formats include 'LOCATE02' (which is the default), 'old' + and 'slocate'. The 'old' format exists for compatibility with + implementations of 'locate' on other Unix systems. The 'slocate' + format exists for compatibility with 'slocate'. *Note Database + Formats::, for a detailed description of each format. + +'--help' + Print a summary of the command line usage and exit. +'--version' + Print the version number of 'updatedb' and exit. + + +File: find.info, Node: Invoking xargs, Next: Regular Expressions, Prev: Invoking updatedb, Up: Reference + +8.4 Invoking 'xargs' +==================== + + xargs [OPTION...] [COMMAND [INITIAL-ARGUMENTS]] + + 'xargs' exits with the following status: + +0 + if it succeeds +123 + if any invocation of the command exited with status 1-125 +124 + if the command exited with status 255 +125 + if the command is killed by a signal +126 + if the command cannot be run +127 + if the command is not found +1 + if some other error occurred. + + Exit codes greater than 128 are used by the shell to indicate that a +program died due to a fatal signal. + +* Menu: + +* xargs options:: +* Invoking the shell from xargs:: + + +File: find.info, Node: xargs options, Next: Invoking the shell from xargs, Up: Invoking xargs + +8.4.1 xargs options +------------------- + +'--arg-file=INPUTFILE' +'-a INPUTFILE' + Read names from the file INPUTFILE instead of standard input. If + you use this option, the standard input stream remains unchanged + when commands are run. Otherwise, stdin is redirected from + '/dev/null'. + +'--null' +'-0' + Input file names are terminated by a null character instead of by + whitespace, and any quotes and backslash characters are not + considered special (every character is taken literally). Disables + the end of file string, which is treated like any other argument. + +'--delimiter DELIM' +'-d DELIM' + + Input file names are terminated by the specified character DELIM + instead of by whitespace, and any quotes and backslash characters + are not considered special (every character is taken literally). + Disables the logical end of file marker string, which is treated + like any other argument. + + The specified delimiter may be a single character, a C-style + character escape such as '\n', or an octal or hexadecimal escape + code. Octal and hexadecimal escape codes are understood as for the + 'printf' command. Multibyte characters are not supported. + +'-E EOF-STR' +'--eof[=EOF-STR]' +'-e[EOF-STR]' + + Set the logical end of file marker string to EOF-STR. If the + logical end of file marker string occurs as a line of input, the + rest of the input is ignored. If EOF-STR is omitted ('-e') or + blank (either '-e' or '-E'), there is no logical end of file marker + string. The '-e' form of this option is deprecated in favour of + the POSIX-compliant '-E' option, which you should use instead. As + of GNU 'xargs' version 4.2.9, the default behaviour of 'xargs' is + not to have a logical end of file marker string. The POSIX + standard (IEEE Std 1003.1, 2004 Edition) allows this. + + The logical end of file marker string is not treated specially if + the '-d' or the '-0' options are in effect. That is, when either + of these options are in effect, the whole input file will be read + even if '-E' was used. + +'--help' + Print a summary of the options to 'xargs' and exit. + +'-I REPLACE-STR' +'--replace[=REPLACE-STR]' +'-i[REPLACE-STR]' + Replace occurrences of REPLACE-STR in the initial arguments with + names read from standard input. Also, unquoted blanks do not + terminate arguments; instead, the input is split at newlines only. + If REPLACE-STR is omitted (omitting it is allowed only for '-i'), + it defaults to '{}' (like for 'find -exec'). Implies '-x' and '-l + 1'. The '-i' option is deprecated in favour of the '-I' option. + +'-L MAX-LINES' +'--max-lines[=MAX-LINES]' +'-l[MAX-LINES]' + Use at most MAX-LINES non-blank input lines per command line. For + '-l', MAX-LINES defaults to 1 if omitted. For '-L', the argument + is mandatory. Trailing blanks cause an input line to be logically + continued on the next input line, for the purpose of counting the + lines. Implies '-x'. The '-l' form of this option is deprecated + in favour of the POSIX-compliant '-L' option. + +'--max-args=MAX-ARGS' +'-n MAX-ARGS' + Use at most MAX-ARGS arguments per command line. Fewer than + MAX-ARGS arguments will be used if the size (see the '-s' option) + is exceeded, unless the '-x' option is given, in which case 'xargs' + will exit. + +'--interactive' +'-p' + Prompt the user about whether to run each command line and read a + line from the terminal. Only run the command line if the response + starts with 'y' or 'Y'. Implies '-t'. + +'--no-run-if-empty' +'-r' + If the standard input is completely empty, do not run the command. + By default, the command is run once even if there is no input. + +'--max-chars=MAX-CHARS' +'-s MAX-CHARS' + Use at most MAX-CHARS characters per command line, including the + command, initial arguments and any terminating nulls at the ends of + the argument strings. + +'--show-limits' + Display the limits on the command-line length which are imposed by + the operating system, 'xargs'' choice of buffer size and the '-s' + option. Pipe the input from '/dev/null' (and perhaps specify + '--no-run-if-empty') if you don't want 'xargs' to do anything. + +'--verbose' +'-t' + Print the command line on the standard error output before + executing it. + +'--version' + Print the version number of 'xargs' and exit. + +'--exit' +'-x' + Exit if the size (see the '-s' option) is exceeded. + +'--max-procs=MAX-PROCS' +'-P MAX-PROCS' + Run simultaneously up to MAX-PROCS processes at once; the default + is 1. If MAX-PROCS is 0, 'xargs' will run as many processes as + possible simultaneously. *Note Controlling Parallelism::, for + information on dynamically controlling parallelism. + +'--process-slot-var=ENVIRONMENT-VARIABLE-NAME' + Set the environment variable ENVIRONMENT-VARIABLE-NAME to a unique + value in each running child process. Each value is a decimal + integer. Values are reused once child processes exit. This can be + used in a rudimentary load distribution scheme, for example. + + +File: find.info, Node: Invoking the shell from xargs, Prev: xargs options, Up: Invoking xargs + +8.4.2 Invoking the shell from xargs +----------------------------------- + +Normally, 'xargs' will exec the command you specified directly, without +invoking a shell. This is normally the behaviour one would want. It's +somewhat more efficient and avoids problems with shell metacharacters, +for example. However, sometimes it is necessary to manipulate the +environment of a command before it is run, in a way that 'xargs' does +not directly support. + + Invoking a shell from 'xargs' is a good way of performing such +manipulations. However, some care must be taken to prevent problems, +for example unwanted interpretation of shell metacharacters. + + This command moves a set of files into an archive directory: + + find /foo -maxdepth 1 -atime +366 -exec mv {} /archive \; + + However, this will only move one file at a time. We cannot in this +case use '-exec ... +' because the matched file names are added at the +end of the command line, while the destination directory would need to +be specified last. We also can't use 'xargs' in the obvious way for the +same reason. One way of working around this problem is to make use of +the special properties of GNU 'mv'; it has a '-t' option that allows the +target directory to be specified before the list of files to be moved. +However, while this technique works for GNU 'mv', it doesn't solve the +more general problem. + + Here is a more general technique for solving this problem: + + find /foo -maxdepth 1 -atime +366 -print0 | + xargs -r0 sh -c 'mv "$@" /archive' move + + Here, a shell is being invoked. There are two shell instances to +think about. The first is the shell which launches the 'xargs' command +(this might be the shell into which you are typing, for example). The +second is the shell launched by 'xargs' (in fact it will probably launch +several, one after the other, depending on how many files need to be +archived). We'll refer to this second shell as a subshell. + + Our example uses the '-c' option of 'sh'. Its argument is a shell +command to be executed by the subshell. Along with the rest of that +command, the $@ is enclosed by single quotes to make sure it is passed +to the subshell without being expanded by the parent shell. It is also +enclosed with double quotes so that the subshell will expand '$@' +correctly even if one of the file names contains a space or newline. + + The subshell will use any non-option arguments as positional +parameters (that is, in the expansion of '$@'). Because 'xargs' +launches the 'sh -c' subshell with a list of files, those files will end +up as the expansion of '$@'. + + You may also notice the 'move' at the end of the command line. This +is used as the value of '$0' by the subshell. We include it because +otherwise the name of the first file to be moved would be used instead. +If that happened it would not be included in the subshell's expansion of +'$@', and so it wouldn't actually get moved. + + Another reason to use the 'sh -c' construct could be to perform +redirection: + + find /usr/include -name '*.h' | xargs grep -wl mode_t | + xargs -r sh -c 'exec emacs "$@" < /dev/tty' Emacs + + Notice that we use the shell builtin 'exec' here. That's simply +because the subshell needs to do nothing once Emacs has been invoked. +Therefore instead of keeping a 'sh' process around for no reason, we +just arrange for the subshell to exec Emacs, saving an extra process +creation. + + Sometimes, though, it can be helpful to keep the shell process +around: + + find /foo -maxdepth 1 -atime +366 -print0 | + xargs -r0 sh -c 'mv "$@" /archive || exit 255' move + + Here, the shell will exit with status 255 if any 'mv' failed. This +causes 'xargs' to stop immediately. + + +File: find.info, Node: Regular Expressions, Next: Environment Variables, Prev: Invoking xargs, Up: Reference + +8.5 Regular Expressions +======================= + +The '-regex' and '-iregex' tests of 'find' allow matching by regular +expression, as does the '--regex' option of 'locate'. + + Your locale configuration affects how regular expressions are +interpreted. *Note Environment Variables::, for a description of how +your locale setup affects the interpretation of regular expressions. + + There are also several different types of regular expression, and +these are interpreted differently. Normally, the type of regular +expression used by 'find' and 'locate' is the same as is used in GNU +Emacs. Both programs provide an option which allows you to select an +alternative regular expression syntax; for 'find' this is the +'-regextype' option, and for 'locate' this is the '--regextype' option. + + These options take a single argument, which indicates the specific +regular expression syntax and behaviour that should be used. This +should be one of the following: + +* Menu: + +* findutils-default regular expression syntax:: +* awk regular expression syntax:: +* egrep regular expression syntax:: +* emacs regular expression syntax:: +* gnu-awk regular expression syntax:: +* grep regular expression syntax:: +* posix-awk regular expression syntax:: +* posix-basic regular expression syntax:: +* posix-egrep regular expression syntax:: +* posix-extended regular expression syntax:: + + +File: find.info, Node: findutils-default regular expression syntax, Next: awk regular expression syntax, Up: Regular Expressions + +8.5.1 'findutils-default' regular expression syntax +--------------------------------------------------- + +The character '.' matches any single character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +ignored. Within square brackets, '\' is taken literally. Character +classes are not supported, so for example you would need to use '[0-9]' +instead of '[[:digit:]]'. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with backslashes followed by parentheses '\(', +'\)'. A backslash followed by a digit acts as a back-reference and +matches the same thing as the previous grouped expression indicated by +that number. For example '\2' matches the second group expression. The +order of group expressions is determined by the position of their +opening parenthesis '\('. + + The alternation operator is '\|'. + + The character '^' only represents the beginning of a string when it +appears: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + + 3. After the alternation operator '\|' + + The character '$' only represents the end of a string when it +appears: + + 1. At the end of a regular expression + + 2. Before a close-group, signified by '\)' + 3. Before the alternation operator '\|' + + '*', '+' and '?' are special at any point in a regular expression +except: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + 3. After the alternation operator '\|' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: awk regular expression syntax, Next: egrep regular expression syntax, Prev: findutils-default regular expression syntax, Up: Regular Expressions + +8.5.2 'awk' regular expression syntax +------------------------------------- + +The character '.' matches any single character except the null +character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' can be used to quote the following +character. Character classes are supported; for example '[[:digit:]]' +will match a single decimal digit. + + GNU extensions are not supported and so '\w', '\W', '\<', '\>', '\b', +'\B', '\`', and '\'' match 'w', 'W', '<', '>', 'b', 'B', '`', and ''' +respectively. + + Grouping is performed with parentheses '()'. An unmatched ')' +matches just itself. A backslash followed by a digit matches that +digit. + + The alternation operator is '|'. + + The characters '^' and '$' always represent the beginning and end of +a string respectively, except within square brackets. Within brackets, +'^' can be used to invert the membership of the character class being +specified. + + '*', '+' and '?' are special at any point in a regular expression +except: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '(' + 3. After the alternation operator '|' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: egrep regular expression syntax, Next: emacs regular expression syntax, Prev: awk regular expression syntax, Up: Regular Expressions + +8.5.3 'egrep' regular expression syntax +--------------------------------------- + +The character '.' matches any single character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' is taken literally. Character +classes are supported; for example '[[:digit:]]' will match a single +decimal digit. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with parentheses '()'. An unmatched ')' +matches just itself. A backslash followed by a digit acts as a +back-reference and matches the same thing as the previous grouped +expression indicated by that number. For example '\2' matches the +second group expression. The order of group expressions is determined +by the position of their opening parenthesis '('. + + The alternation operator is '|'. + + The characters '^' and '$' always represent the beginning and end of +a string respectively, except within square brackets. Within brackets, +'^' can be used to invert the membership of the character class being +specified. + + The characters '*', '+' and '?' are special anywhere in a regular +expression. + + Intervals are specified by '{' and '}'. Invalid intervals are +treated as literals, for example 'a{1' is treated as 'a\{1' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: emacs regular expression syntax, Next: gnu-awk regular expression syntax, Prev: egrep regular expression syntax, Up: Regular Expressions + +8.5.4 'emacs' regular expression syntax +--------------------------------------- + +The character '.' matches any single character except newline. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +ignored. Within square brackets, '\' is taken literally. Character +classes are not supported, so for example you would need to use '[0-9]' +instead of '[[:digit:]]'. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with backslashes followed by parentheses '\(', +'\)'. A backslash followed by a digit acts as a back-reference and +matches the same thing as the previous grouped expression indicated by +that number. For example '\2' matches the second group expression. The +order of group expressions is determined by the position of their +opening parenthesis '\('. + + The alternation operator is '\|'. + + The character '^' only represents the beginning of a string when it +appears: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + + 3. After the alternation operator '\|' + + The character '$' only represents the end of a string when it +appears: + + 1. At the end of a regular expression + + 2. Before a close-group, signified by '\)' + 3. Before the alternation operator '\|' + + '*', '+' and '?' are special at any point in a regular expression +except: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + 3. After the alternation operator '\|' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: gnu-awk regular expression syntax, Next: grep regular expression syntax, Prev: emacs regular expression syntax, Up: Regular Expressions + +8.5.5 'gnu-awk' regular expression syntax +----------------------------------------- + +The character '.' matches any single character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' can be used to quote the following +character. Character classes are supported; for example '[[:digit:]]' +will match a single decimal digit. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with parentheses '()'. An unmatched ')' +matches just itself. A backslash followed by a digit acts as a +back-reference and matches the same thing as the previous grouped +expression indicated by that number. For example '\2' matches the +second group expression. The order of group expressions is determined +by the position of their opening parenthesis '('. + + The alternation operator is '|'. + + The characters '^' and '$' always represent the beginning and end of +a string respectively, except within square brackets. Within brackets, +'^' can be used to invert the membership of the character class being +specified. + + '*', '+' and '?' are special at any point in a regular expression +except: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '(' + 3. After the alternation operator '|' + + Intervals are specified by '{' and '}'. Invalid intervals are +treated as literals, for example 'a{1' is treated as 'a\{1' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: grep regular expression syntax, Next: posix-awk regular expression syntax, Prev: gnu-awk regular expression syntax, Up: Regular Expressions + +8.5.6 'grep' regular expression syntax +-------------------------------------- + +The character '.' matches any single character. + +'\+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'\?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'+ and ?' + match themselves. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' is taken literally. Character +classes are supported; for example '[[:digit:]]' will match a single +decimal digit. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with backslashes followed by parentheses '\(', +'\)'. A backslash followed by a digit acts as a back-reference and +matches the same thing as the previous grouped expression indicated by +that number. For example '\2' matches the second group expression. The +order of group expressions is determined by the position of their +opening parenthesis '\('. + + The alternation operator is '\|'. + + The character '^' only represents the beginning of a string when it +appears: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + + 3. After a newline + + 4. After the alternation operator '\|' + + The character '$' only represents the end of a string when it +appears: + + 1. At the end of a regular expression + + 2. Before a close-group, signified by '\)' + 3. Before a newline + + 4. Before the alternation operator '\|' + + '\*', '\+' and '\?' are special at any point in a regular expression +except: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '\(' + 3. After a newline + + 4. After the alternation operator '\|' + + Intervals are specified by '\{' and '\}'. Invalid intervals such as +'a\{1z' are not accepted. + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: posix-awk regular expression syntax, Next: posix-basic regular expression syntax, Prev: grep regular expression syntax, Up: Regular Expressions + +8.5.7 'posix-awk' regular expression syntax +------------------------------------------- + +The character '.' matches any single character except the null +character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' can be used to quote the following +character. Character classes are supported; for example '[[:digit:]]' +will match a single decimal digit. + + GNU extensions are not supported and so '\w', '\W', '\<', '\>', '\b', +'\B', '\`', and '\'' match 'w', 'W', '<', '>', 'b', 'B', '`', and ''' +respectively. + + Grouping is performed with parentheses '()'. An unmatched ')' +matches just itself. A backslash followed by a digit acts as a +back-reference and matches the same thing as the previous grouped +expression indicated by that number. For example '\2' matches the +second group expression. The order of group expressions is determined +by the position of their opening parenthesis '('. + + The alternation operator is '|'. + + The characters '^' and '$' always represent the beginning and end of +a string respectively, except within square brackets. Within brackets, +'^' can be used to invert the membership of the character class being +specified. + + '*', '+' and '?' are special at any point in a regular expression +except the following places, where they are not allowed: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '(' + 3. After the alternation operator '|' + + Intervals are specified by '{' and '}'. Invalid intervals are +treated as literals, for example 'a{1' is treated as 'a\{1' + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: posix-basic regular expression syntax, Next: posix-egrep regular expression syntax, Prev: posix-awk regular expression syntax, Up: Regular Expressions + +8.5.8 'posix-basic' regular expression syntax +--------------------------------------------- + +This is a synonym for ed. + + +File: find.info, Node: posix-egrep regular expression syntax, Next: posix-extended regular expression syntax, Prev: posix-basic regular expression syntax, Up: Regular Expressions + +8.5.9 'posix-egrep' regular expression syntax +--------------------------------------------- + +This is a synonym for egrep. + + +File: find.info, Node: posix-extended regular expression syntax, Prev: posix-egrep regular expression syntax, Up: Regular Expressions + +8.5.10 'posix-extended' regular expression syntax +------------------------------------------------- + +The character '.' matches any single character except the null +character. + +'+' + indicates that the regular expression should match one or more + occurrences of the previous atom or regexp. +'?' + indicates that the regular expression should match zero or one + occurrence of the previous atom or regexp. +'\+' + matches a '+' +'\?' + matches a '?'. + + Bracket expressions are used to match ranges of characters. Bracket +expressions where the range is backward, for example '[z-a]', are +invalid. Within square brackets, '\' is taken literally. Character +classes are supported; for example '[[:digit:]]' will match a single +decimal digit. + + GNU extensions are supported: + + 1. '\w' matches a character within a word + + 2. '\W' matches a character which is not within a word + + 3. '\<' matches the beginning of a word + + 4. '\>' matches the end of a word + + 5. '\b' matches a word boundary + + 6. '\B' matches characters which are not a word boundary + + 7. '\`' matches the beginning of the whole input + + 8. '\'' matches the end of the whole input + + Grouping is performed with parentheses '()'. An unmatched ')' +matches just itself. A backslash followed by a digit acts as a +back-reference and matches the same thing as the previous grouped +expression indicated by that number. For example '\2' matches the +second group expression. The order of group expressions is determined +by the position of their opening parenthesis '('. + + The alternation operator is '|'. + + The characters '^' and '$' always represent the beginning and end of +a string respectively, except within square brackets. Within brackets, +'^' can be used to invert the membership of the character class being +specified. + + '*', '+' and '?' are special at any point in a regular expression +except the following places, where they are not allowed: + + 1. At the beginning of a regular expression + + 2. After an open-group, signified by '(' + 3. After the alternation operator '|' + + Intervals are specified by '{' and '}'. Invalid intervals such as +'a{1z' are not accepted. + + The longest possible match is returned; this applies to the regular +expression as a whole and (subject to this constraint) to subexpressions +within groups. + + +File: find.info, Node: Environment Variables, Prev: Regular Expressions, Up: Reference + +8.6 Environment Variables +========================= + +'LANG' + Provides a default value for the internationalisation variables + that are unset or null. + +'LC_ALL' + If set to a non-empty string value, override the values of all the + other internationalisation variables. + +'LC_COLLATE' + The POSIX standard specifies that this variable affects the pattern + matching to be used for the '\-name' option. GNU find uses the GNU + version of the 'fnmatch' library function. + + This variable also affects the interpretation of the response to + '-ok'; while the 'LC_MESSAGES' variable selects the actual pattern + used to interpret the response to '-ok', the interpretation of any + bracket expressions in the pattern will be affected by the + 'LC_COLLATE' variable. + +'LC_CTYPE' + This variable affects the treatment of character classes used in + regular expression and with the '-name' test, if the 'fnmatch' + function supports this. + + This variable also affects the interpretation of any character + classes in the regular expressions used to interpret the response + to the prompt issued by '-ok'. The 'LC_CTYPE' environment variable + will also affect which characters are considered to be unprintable + when filenames are printed (*note Unusual Characters in File + Names::). + +'LC_MESSAGES' + Determines the locale to be used for internationalised messages, + including the interpretation of the response to the prompt made by + the '-ok' action. + +'NLSPATH' + Determines the location of the internationalisation message + catalogues. + +'PATH' + Affects the directories which are searched to find the executables + invoked by '-exec', '-execdir' '-ok' and '-okdir'. If the PATH + environment variable includes the current directory (by explicitly + including '.' or by having an empty element), and the find command + line includes '-execdir' or '-okdir', 'find' will refuse to run. + *Note Security Considerations::, for a more detailed discussion of + security matters. + +'POSIXLY_CORRECT' + Determines the block size used by '-ls' and '-fls'. If + 'POSIXLY_CORRECT' is set, blocks are units of 512 bytes. Otherwise + they are units of 1024 bytes. + + Setting this variable also turns off warning messages (that is, + implies '-nowarn') by default, because POSIX requires that apart + from the output for '-ok', all messages printed on stderr are + diagnostics and must result in a non-zero exit status. + + When 'POSIXLY_CORRECT' is set, the response to the prompt made by + the '-ok' action is interpreted according to the system's message + catalogue, as opposed to according to 'find''s own message + translations. + +'TZ' + Affects the time zone used for some of the time-related format + directives of '-printf' and '-fprintf'. + + +File: find.info, Node: Common Tasks, Next: Worked Examples, Prev: Reference, Up: Top + +9 Common Tasks +************** + +The sections that follow contain some extended examples that both give a +good idea of the power of these programs, and show you how to solve +common real-world problems. + +* Menu: + +* Viewing And Editing:: +* Archiving:: +* Cleaning Up:: +* Strange File Names:: +* Fixing Permissions:: +* Classifying Files:: + + +File: find.info, Node: Viewing And Editing, Next: Archiving, Up: Common Tasks + +9.1 Viewing And Editing +======================= + +To view a list of files that meet certain criteria, simply run your file +viewing program with the file names as arguments. Shells substitute a +command enclosed in backquotes with its output, so the whole command +looks like this: + + less `find /usr/include -name '*.h' | xargs grep -l mode_t` + +You can edit those files by giving an editor name instead of a file +viewing program: + + emacs `find /usr/include -name '*.h' | xargs grep -l mode_t` + + Because there is a limit to the length of any individual command +line, there is a limit to the number of files that can be handled in +this way. We can get around this difficulty by using 'xargs' like this: + + find /usr/include -name '*.h' | xargs grep -l mode_t > todo + xargs --arg-file=todo emacs + + Here, 'xargs' will run 'emacs' as many times as necessary to visit +all of the files listed in the file 'todo'. Generating a temporary file +is not always convenient, though. This command does much the same thing +without needing one: + + find /usr/include -name '*.h' | xargs grep -l mode_t | + xargs sh -c 'emacs "$@" < /dev/tty' Emacs + + The example above illustrates a useful trick; Using 'sh -c' you can +invoke a shell command from 'xargs'. The '$@' in the command line is +expanded by the shell to a list of arguments as provided by 'xargs'. +The single quotes in the command line protect the '$@' against expansion +by your interactive shell (which will normally have no arguments and +thus expand '$@' to nothing). The capitalised 'Emacs' on the command +line is used as '$0' by the shell that 'xargs' launches. + + +File: find.info, Node: Archiving, Next: Cleaning Up, Prev: Viewing And Editing, Up: Common Tasks + +9.2 Archiving +============= + +You can pass a list of files produced by 'find' to a file archiving +program. GNU 'tar' and 'cpio' can both read lists of file names from +the standard input - either delimited by nulls (the safe way) or by +blanks (the lazy, risky default way). To use null-delimited names, give +them the '--null' option. You can store a file archive in a file, write +it on a tape, or send it over a network to extract on another machine. + + One common use of 'find' to archive files is to send a list of the +files in a directory tree to 'cpio'. Use '-depth' so if a directory +does not have write permission for its owner, its contents can still be +restored from the archive since the directory's permissions are restored +after its contents. Here is an example of doing this using 'cpio'; you +could use a more complex 'find' expression to archive only certain +files. + + find . -depth -print0 | + cpio --create --null --format=crc --file=/dev/nrst0 + + You could restore that archive using this command: + + cpio --extract --null --make-dir --unconditional \ + --preserve --file=/dev/nrst0 + + Here are the commands to do the same things using 'tar': + + find . -depth -print0 | + tar --create --null --files-from=- --file=/dev/nrst0 + + tar --extract --null --preserve-perm --same-owner \ + --file=/dev/nrst0 + + Here is an example of copying a directory from one machine to +another: + + find . -depth -print0 | cpio -0o -Hnewc | + rsh OTHER-MACHINE "cd `pwd` && cpio -i0dum" + + +File: find.info, Node: Cleaning Up, Next: Strange File Names, Prev: Archiving, Up: Common Tasks + +9.3 Cleaning Up +=============== + +This section gives examples of removing unwanted files in various +situations. Here is a command to remove the CVS backup files created +when an update requires a merge: + + find . -name '.#*' -print0 | xargs -0r rm -f + + If your 'find' command removes directories, you may find that you get +a spurious error message when 'find' tries to recurse into a directory +that has now been removed. Using the '-depth' option will normally +resolve this problem. + + It is also possible to use the '-delete' action: + + find . -depth -name '.#*' -delete + + You can run this command to clean out your clutter in '/tmp'. You +might place it in the file your shell runs when you log out +('.bash_logout', '.logout', or '.zlogout', depending on which shell you +use). + + find /tmp -depth -user "$LOGNAME" -type f -delete + + To remove old Emacs backup and auto-save files, you can use a command +like the following. It is especially important in this case to use +null-terminated file names because Emacs packages like the VM mailer +often create temporary file names with spaces in them, like '#reply to +David J. MacKenzie<1>#'. + + find ~ \( -name '*~' -o -name '#*#' \) -print0 | + xargs --no-run-if-empty --null rm -vf + + Removing old files from '/tmp' is commonly done from 'cron': + + find /tmp /var/tmp -depth -not -type d -mtime +3 -delete + find /tmp /var/tmp -depth -mindepth 1 -type d -empty -delete + + The second 'find' command above cleans out empty directories +depth-first ('-delete' implies '-depth' anyway), hoping that the parents +become empty and can be removed too. It uses '-mindepth' to avoid +removing '/tmp' itself if it becomes totally empty. + + Lastly, an example of a program that almost certainly does not do +what the user intended: + + find dirname -delete -name quux + + If the user hoped to delete only files named 'quux' they will get an +unpleasant surprise; this command will attempt to delete everything at +or below the starting point 'dirname'. This is because 'find' evaluates +the items on the command line as an expression. The 'find' program will +normally execute an action if the preceding action succeeds. Here, +there is no action or test before the '-delete' so it will always be +executed. The '-name quux' test will be performed for files we +successfully deleted, but that test has no effect since '-delete' also +disables the default '-print' operation. So the above example will +probably delete a lot of files the user didn't want to delete. + + This command is also likely to do something you did not intend: + find dirname -path dirname/foo -prune -o -delete + + Because '-delete' turns on '-depth', the '-prune' action has no +effect and files in 'dirname/foo' will be deleted too. + + +File: find.info, Node: Strange File Names, Next: Fixing Permissions, Prev: Cleaning Up, Up: Common Tasks + +9.4 Strange File Names +====================== + +'find' can help you remove or rename a file with strange characters in +its name. People are sometimes stymied by files whose names contain +characters such as spaces, tabs, control characters, or characters with +the high bit set. The simplest way to remove such files is: + + rm -i SOME*PATTERN*THAT*MATCHES*THE*PROBLEM*FILE + + 'rm' asks you whether to remove each file matching the given pattern. +If you are using an old shell, this approach might not work if the file +name contains a character with the high bit set; the shell may strip it +off. A more reliable way is: + + find . -maxdepth 1 TESTS -okdir rm '{}' \; + +where TESTS uniquely identify the file. The '-maxdepth 1' option +prevents 'find' from wasting time searching for the file in any +subdirectories; if there are no subdirectories, you may omit it. A good +way to uniquely identify the problem file is to figure out its inode +number; use + + ls -i + + Suppose you have a file whose name contains control characters, and +you have found that its inode number is 12345. This command prompts you +for whether to remove it: + + find . -maxdepth 1 -inum 12345 -okdir rm -f '{}' \; + + If you don't want to be asked, perhaps because the file name may +contain a strange character sequence that will mess up your screen when +printed, then use '-execdir' instead of '-okdir'. + + If you want to rename the file instead, you can use 'mv' instead of +'rm': + + find . -maxdepth 1 -inum 12345 -okdir mv '{}' NEW-FILE-NAME \; + + +File: find.info, Node: Fixing Permissions, Next: Classifying Files, Prev: Strange File Names, Up: Common Tasks + +9.5 Fixing Permissions +====================== + +Suppose you want to make sure that everyone can write to the directories +in a certain directory tree. Here is a way to find directories lacking +either user or group write permission (or both), and fix their +permissions: + + find . -type d -not -perm -ug=w | xargs chmod ug+w + +You could also reverse the operations, if you want to make sure that +directories do _not_ have world write permission. + + +File: find.info, Node: Classifying Files, Prev: Fixing Permissions, Up: Common Tasks + +9.6 Classifying Files +===================== + +If you want to classify a set of files into several groups based on +different criteria, you can use the comma operator to perform multiple +independent tests on the files. Here is an example: + + find / -type d \( -perm -o=w -fprint allwrite , \ + -perm -o=x -fprint allexec \) + + echo "Directories that can be written to by everyone:" + cat allwrite + echo "" + echo "Directories with search permissions for everyone:" + cat allexec + + 'find' has only to make one scan through the directory tree (which is +one of the most time consuming parts of its work). + + +File: find.info, Node: Worked Examples, Next: Security Considerations, Prev: Common Tasks, Up: Top + +10 Worked Examples +****************** + +The tools in the findutils package, and in particular 'find', have a +large number of options. This means that quite often, there is more +than one way to do things. Some of the options and facilities only +exist for compatibility with other tools, and findutils provides +improved ways of doing things. + + This chapter describes a number of useful tasks that are commonly +performed, and compares the different ways of achieving them. + +* Menu: + +* Deleting Files:: +* Copying A Subset of Files:: +* Updating A Timestamp File:: +* Finding the Shallowest Instance:: + + +File: find.info, Node: Deleting Files, Next: Copying A Subset of Files, Up: Worked Examples + +10.1 Deleting Files +=================== + +One of the most common tasks that 'find' is used for is locating files +that can be deleted. This might include: + + * Files last modified more than 3 years ago which haven't been + accessed for at least 2 years + * Files belonging to a certain user + * Temporary files which are no longer required + + This example concentrates on the actual deletion task rather than on +sophisticated ways of locating the files that need to be deleted. We'll +assume that the files we want to delete are old files underneath +'/var/tmp/stuff'. + +10.1.1 The Traditional Way +-------------------------- + +The traditional way to delete files in '/var/tmp/stuff' that have not +been modified in over 90 days would have been: + + find /var/tmp/stuff -mtime +90 -exec /bin/rm {} \; + + The above command uses '-exec' to run the '/bin/rm' command to remove +each file. This approach works and in fact would have worked in Version +7 Unix in 1979. However, there are a number of problems with this +approach. + + The most obvious problem with the approach above is that it causes +'find' to fork every time it finds a file that needs to delete, and the +child process then has to use the 'exec' system call to launch +'/bin/rm'. All this is quite inefficient. If we are going to use +'/bin/rm' to do this job, it is better to make it delete more than one +file at a time. + + The most obvious way of doing this is to use the shell's command +expansion feature: + + /bin/rm `find /var/tmp/stuff -mtime +90 -print` + or you could use the more modern form + /bin/rm $(find /var/tmp/stuff -mtime +90 -print) + + The commands above are much more efficient than the first attempt. +However, there is a problem with them. The shell has a maximum command +length which is imposed by the operating system (the actual limit varies +between systems). This means that while the command expansion technique +will usually work, it will suddenly fail when there are lots of files to +delete. Since the task is to delete unwanted files, this is precisely +the time we don't want things to go wrong. + +10.1.2 Making Use of 'xargs' +---------------------------- + +So, is there a way to be more efficient in the use of 'fork()' and +'exec()' without running up against this limit? Yes, we can be almost +optimally efficient by making use of the 'xargs' command. The 'xargs' +command reads arguments from its standard input and builds them into +command lines. We can use it like this: + + find /var/tmp/stuff -mtime +90 -print | xargs /bin/rm + + For example if the files found by 'find' are '/var/tmp/stuff/A', +'/var/tmp/stuff/B' and '/var/tmp/stuff/C' then 'xargs' might issue the +commands + + /bin/rm /var/tmp/stuff/A /var/tmp/stuff/B + /bin/rm /var/tmp/stuff/C + + The above assumes that 'xargs' has a very small maximum command line +length. The real limit is much larger but the idea is that 'xargs' will +run '/bin/rm' as many times as necessary to get the job done, given the +limits on command line length. + + This usage of 'xargs' is pretty efficient, and the 'xargs' command is +widely implemented (all modern versions of Unix offer it). So far then, +the news is all good. However, there is bad news too. + +10.1.3 Unusual characters in filenames +-------------------------------------- + +Unix-like systems allow any characters to appear in file names with the +exception of the ASCII NUL character and the slash. Slashes can occur +in path names (as the directory separator) but not in the names of +actual directory entries. This means that the list of files that +'xargs' reads could in fact contain white space characters - spaces, +tabs and newline characters. Since by default, 'xargs' assumes that the +list of files it is reading uses white space as an argument separator, +it cannot correctly handle the case where a filename actually includes +white space. This makes the default behaviour of 'xargs' almost useless +for handling arbitrary data. + + To solve this problem, GNU findutils introduced the '-print0' action +for 'find'. This uses the ASCII NUL character to separate the entries +in the file list that it produces. This is the ideal choice of +separator since it is the only character that cannot appear within a +path name. The '-0' option to 'xargs' makes it assume that arguments +are separated with ASCII NUL instead of white space. It also turns off +another misfeature in the default behaviour of 'xargs', which is that it +pays attention to quote characters in its input. Some versions of +'xargs' also terminate when they see a lone '_' in the input, but GNU +'find' no longer does that (since it has become an optional behaviour in +the Unix standard). + + So, putting 'find -print0' together with 'xargs -0' we get this +command: + + find /var/tmp/stuff -mtime +90 -print0 | xargs -0 /bin/rm + + The result is an efficient way of proceeding that correctly handles +all the possible characters that could appear in the list of files to +delete. This is good news. However, there is, as I'm sure you're +expecting, also more bad news. The problem is that this is not a +portable construct; although other versions of Unix (notably BSD-derived +ones) support '-print0', it's not universal. So, is there a more +universal mechanism? + +10.1.4 Going back to '-exec' +---------------------------- + +There is indeed a more universal mechanism, which is a slight +modification to the '-exec' action. The normal '-exec' action assumes +that the command to run is terminated with a semicolon (the semicolon +normally has to be quoted in order to protect it from interpretation as +the shell command separator). The SVR4 edition of Unix introduced a +slight variation, which involves terminating the command with '+' +instead: + + find /var/tmp/stuff -mtime +90 -exec /bin/rm {} \+ + + The above use of '-exec' causes 'find' to build up a long command +line and then issue it. This can be less efficient than some uses of +'xargs'; for example 'xargs' allows new command lines to be built up +while the previous command is still executing, and allows you to specify +a number of commands to run in parallel. However, the 'find ... -exec +... +' construct has the advantage of wide portability. GNU findutils +did not support '-exec ... +' until version 4.2.12; one of the reasons +for this is that it already had the '-print0' action in any case. + +10.1.5 A more secure version of '-exec' +--------------------------------------- + +The command above seems to be efficient and portable. However, within +it lurks a security problem. The problem is shared with all the +commands we've tried in this worked example so far, too. The security +problem is a race condition; that is, if it is possible for somebody to +manipulate the filesystem that you are searching while you are searching +it, it is possible for them to persuade your 'find' command to cause the +deletion of a file that you can delete but they normally cannot. + + The problem occurs because the '-exec' action is defined by the POSIX +standard to invoke its command with the same working directory as 'find' +had when it was started. This means that the arguments which replace +the {} include a relative path from 'find''s starting point down the +file that needs to be deleted. For example, + + find /var/tmp/stuff -mtime +90 -exec /bin/rm {} \+ + + might actually issue the command: + + /bin/rm /var/tmp/stuff/A /var/tmp/stuff/B /var/tmp/stuff/passwd + + Notice the file '/var/tmp/stuff/passwd'. Likewise, the command: + + cd /var/tmp && find stuff -mtime +90 -exec /bin/rm {} \+ + + might actually issue the command: + + /bin/rm stuff/A stuff/B stuff/passwd + + If an attacker can rename 'stuff' to something else (making use of +their write permissions in '/var/tmp') they can replace it with a +symbolic link to '/etc'. That means that the '/bin/rm' command will be +invoked on '/etc/passwd'. If you are running your 'find' command as +root, the attacker has just managed to delete a vital file. All they +needed to do to achieve this was replace a subdirectory with a symbolic +link at the vital moment. + + There is however, a simple solution to the problem. This is an +action which works a lot like '-exec' but doesn't need to traverse a +chain of directories to reach the file that it needs to work on. This +is the '-execdir' action, which was introduced by the BSD family of +operating systems. The command, + + find /var/tmp/stuff -mtime +90 -execdir /bin/rm {} \+ + + might delete a set of files by performing these actions: + + 1. Change directory to /var/tmp/stuff/foo + 2. Invoke '/bin/rm ./file1 ./file2 ./file3' + 3. Change directory to /var/tmp/stuff/bar + 4. Invoke '/bin/rm ./file99 ./file100 ./file101' + + This is a much more secure method. We are no longer exposed to a +race condition. For many typical uses of 'find', this is the best +strategy. It's reasonably efficient, but the length of the command line +is limited not just by the operating system limits, but also by how many +files we actually need to delete from each directory. + + Is it possible to do any better? In the case of general file +processing, no. However, in the specific case of deleting files it is +indeed possible to do better. + +10.1.6 Using the '-delete' action +--------------------------------- + +The most efficient and secure method of solving this problem is to use +the '-delete' action: + + find /var/tmp/stuff -mtime +90 -delete + + This alternative is more efficient than any of the '-exec' or +'-execdir' actions, since it entirely avoids the overhead of forking a +new process and using 'exec' to run '/bin/rm'. It is also normally more +efficient than 'xargs' for the same reason. The file deletion is +performed from the directory containing the entry to be deleted, so the +'-delete' action has the same security advantages as the '-execdir' +action has. + + The '-delete' action was introduced by the BSD family of operating +systems. + +10.1.7 Improving things still further +------------------------------------- + +Is it possible to improve things still further? Not without either +modifying the system library to the operating system or having more +specific knowledge of the layout of the filesystem and disk I/O +subsystem, or both. + + The 'find' command traverses the filesystem, reading directories. It +then issues a separate system call for each file to be deleted. If we +could modify the operating system, there are potential gains that could +be made: + + * We could have a system call to which we pass more than one filename + for deletion + * Alternatively, we could pass in a list of inode numbers (on + GNU/Linux systems, 'readdir()' also returns the inode number of + each directory entry) to be deleted. + + The above possibilities sound interesting, but from the kernel's +point of view it is difficult to enforce standard Unix access controls +for such processing by inode number. Such a facility would probably +need to be restricted to the superuser. + + Another way of improving performance would be to increase the +parallelism of the process. For example if the directory hierarchy we +are searching is actually spread across a number of disks, we might +somehow be able to arrange for 'find' to process each disk in parallel. +In practice GNU 'find' doesn't have such an intimate understanding of +the system's filesystem layout and disk I/O subsystem. + + However, since the system administrator can have such an +understanding they can take advantage of it like so: + + find /var/tmp/stuff1 -mtime +90 -delete & + find /var/tmp/stuff2 -mtime +90 -delete & + find /var/tmp/stuff3 -mtime +90 -delete & + find /var/tmp/stuff4 -mtime +90 -delete & + wait + + In the example above, four separate instances of 'find' are used to +search four subdirectories in parallel. The 'wait' command simply waits +for all of these to complete. Whether this approach is more or less +efficient than a single instance of 'find' depends on a number of +things: + + * Are the directories being searched in parallel actually on separate + disks? If not, this parallel search might just result in a lot of + disk head movement and so the speed might even be slower. + * Other activity - are other programs also doing things on those + disks? + +10.1.8 Conclusion +----------------- + +The fastest and most secure way to delete files with the help of 'find' +is to use '-delete'. Using 'xargs -0 -P N' can also make effective use +of the disk, but it is not as secure. + + In the case where we're doing things other than deleting files, the +most secure alternative is '-execdir ... +', but this is not as portable +as the insecure action '-exec ... +'. + + The '-delete' action is not completely portable, but the only other +possibility which is as secure ('-execdir') is no more portable. The +most efficient portable alternative is '-exec ...+', but this is +insecure and isn't supported by versions of GNU findutils prior to +4.2.12. + + +File: find.info, Node: Copying A Subset of Files, Next: Updating A Timestamp File, Prev: Deleting Files, Up: Worked Examples + +10.2 Copying A Subset of Files +============================== + +Suppose you want to copy some files from '/source-dir' to '/dest-dir', +but there are a small number of files in '/source-dir' you don't want to +copy. + + One option of course is 'cp /source-dir /dest-dir' followed by +deletion of the unwanted material under '/dest-dir'. But often that can +be inconvenient, because for example we would have copied a large amount +of extraneous material, or because '/dest-dir' is too small. Naturally +there are many other possible reasons why this strategy may be +unsuitable. + + So we need to have some way of identifying which files we want to +copy, and we need to have a way of copying that file list. The second +part of this condition is met by 'cpio -p'. Of course, we can identify +the files we wish to copy by using 'find'. Here is a command that +solves our problem: + + cd /source-dir + find . -name '.snapshot' -prune -o \( \! -name '*~' -print0 \) | + cpio -pmd0 /dest-dir + + The first part of the 'find' command here identifies files or +directories named '.snapshot' and tells 'find' not to recurse into them +(since they do not need to be copied). The combination '-name +'.snapshot' -prune' yields false for anything that didn't get pruned, +but it is exactly those files we want to copy. Therefore we need to use +an OR ('-o') condition to introduce the rest of our expression. The +remainder of the expression simply arranges for the name of any file not +ending in '~' to be printed. + + Using '-print0' ensures that white space characters in file names do +not pose a problem. The 'cpio' command does the actual work of copying +files. The program as a whole fails if the 'cpio' program returns +nonzero. If the 'find' command returns non-zero on the other hand, the +Unix shell will not diagnose a problem (since 'find' is not the last +command in the pipeline). + + +File: find.info, Node: Updating A Timestamp File, Next: Finding the Shallowest Instance, Prev: Copying A Subset of Files, Up: Worked Examples + +10.3 Updating A Timestamp File +============================== + +Suppose we have a directory full of files which is maintained with a set +of automated tools; perhaps one set of tools updates them and another +set of tools uses the result. In this situation, it might be useful for +the second set of tools to know if the files have recently been changed. +It might be useful, for example, to have a 'timestamp' file which gives +the timestamp on the newest file in the collection. + + We can use 'find' to achieve this, but there are several different +ways to do it. + +10.3.1 Updating the Timestamp The Wrong Way +------------------------------------------- + +The obvious but wrong answer is just to use '-newer': + + find subdir -newer timestamp -exec touch -r {} timestamp \; + + This does the right sort of thing but has a bug. Suppose that two +files in the subdirectory have been updated, and that these are called +'file1' and 'file2'. The command above will update 'timestamp' with the +modification time of 'file1' or that of 'file2', but we don't know which +one. Since the timestamps on 'file1' and 'file2' will in general be +different, this could well be the wrong value. + + One solution to this problem is to modify 'find' to recheck the +modification time of 'timestamp' every time a file is to be compared +against it, but that will reduce the performance of 'find'. + +10.3.2 Using the test utility to compare timestamps +--------------------------------------------------- + +The 'test' command can be used to compare timestamps: + + find subdir -exec test {} -nt timestamp \; -exec touch -r {} timestamp \; + + This will ensure that any changes made to the modification time of +'timestamp' that take place during the execution of 'find' are taken +into account. This resolves our earlier problem, but unfortunately this +runs much more slowly. + +10.3.3 A combined approach +-------------------------- + +We can of course still use '-newer' to cut down on the number of calls +to 'test': + + find subdir -newer timestamp -and \ + -exec test {} -nt timestamp \; -and \ + -exec touch -r {} timestamp \; + + Here, the '-newer' test excludes all the files which are definitely +older than the timestamp, but all the files which are newer than the old +value of the timestamp are compared against the current updated +timestamp. + + This is indeed faster in general, but the speed difference will +depend on how many updated files there are. + +10.3.4 Using '-printf' and 'sort' to compare timestamps +------------------------------------------------------- + +It is possible to use the '-printf' action to abandon the use of 'test' +entirely: + + newest=$(find subdir -newer timestamp -printf "%A%p\n" | + sort -n | + tail -1 | + cut -d: -f2- ) + touch -r "${newest:-timestamp}" timestamp + + The command above works by generating a list of the timestamps and +names of all the files which are newer than the timestamp. The 'sort', +'tail' and 'cut' commands simply pull out the name of the file with the +largest timestamp value (that is, the latest file). The 'touch' command +is then used to update the timestamp, + + The '"${newest:-timestamp}"' expression simply expands to the value +of '$newest' if that variable is set, but to 'timestamp' otherwise. +This ensures that an argument is always given to the '-r' option of the +'touch' command. + + This approach seems quite efficient, but unfortunately it has a +problem. Many operating systems now keep file modification time +information at a granularity which is finer than one second. Findutils +version 4.3.3 and later will print a fractional part with %A@, but older +versions will not. + +10.3.5 Solving the problem with 'make' +-------------------------------------- + +Another tool which often works with timestamps is 'make'. We can use +'find' to generate a 'Makefile' file on the fly and then use 'make' to +update the timestamps: + + makefile=$(mktemp) + find subdir \ + \( \! -xtype l \) \ + -newer timestamp \ + -printf "timestamp:: %p\n\ttouch -r %p timestamp\n\n" > "$makefile" + make -f "$makefile" + rm -f "$makefile" + + Unfortunately although the solution above is quite elegant, it fails +to cope with white space within file names, and adjusting it to do so +would require a rather complex shell script. + +10.3.6 Coping with odd filenames too +------------------------------------ + +We can fix both of these problems (looping and problems with white +space), and do things more efficiently too. The following command works +with newlines and doesn't need to sort the list of filenames. + + find subdir -newer timestamp -printf "%A@:%p\0" | + perl -0 newest.pl | + xargs --no-run-if-empty --null -i \ + find {} -maxdepth 0 -newer timestamp -exec touch -r {} timestamp \; + + The first 'find' command generates a list of files which are newer +than the original timestamp file, and prints a list of them with their +timestamps. The 'newest.pl' script simply filters out all the filenames +which have timestamps which are older than whatever the newest file is: + + #! /usr/bin/perl -0 + my @newest = (); + my $latest_stamp = undef; + while (<>) { + my ($stamp, $name) = split(/:/); + if (!defined($latest_stamp) || ($tstamp > $latest_stamp)) { + $latest_stamp = $stamp; + @newest = (); + } + if ($tstamp >= $latest_stamp) { + push @newest, $name; + } + } + print join("\0", @newest); + + This prints a list of zero or more files, all of which are newer than +the original timestamp file, and which have the same timestamp as each +other, to the nearest second. The second 'find' command takes each +resulting file one at a time, and if that is newer than the timestamp +file, the timestamp is updated. + + +File: find.info, Node: Finding the Shallowest Instance, Prev: Updating A Timestamp File, Up: Worked Examples + +10.4 Finding the Shallowest Instance +==================================== + +Suppose you maintain local copies of sources from various projects, each +with their own choice of directory organisation and source code +management (SCM) tool. You need to periodically synchronize each +project with its upstream tree. As the number local repositories grows, +so does the work involved in maintaining synchronization. SCM utilities +typically create some sort of administrative directory: .svn for +Subversion, CVS for CVS, and so on. These directories can be used as a +key to search for the bases of the project source trees. Suppose we +have the following directory structure: + + repo/project1/CVS + repo/gnu/project2/.svn + repo/gnu/project3/.svn + repo/gnu/project3/src/.svn + repo/gnu/project3/doc/.svn + repo/project4/.git + + One would expect to update each of the 'projectX' directories, but +not their subdirectories (src, doc, etc.). To locate the project roots, +we would need to find the least deeply nested directories containing an +SCM-related subdirectory. The following command discovers those roots +efficiently. It is efficient because it avoids searching subdirectories +inside projects whose SCM directory we already found. + + find repo/ \ + -exec test -d {}/.svn \; -or \ + -exec test -d {}/.git \; -or \ + -exec test -d {}/CVS \; -print -prune + + In this example, 'test' is used to tell if we are currently examining +a directory which appears to the a project's root directory (because it +has an SCM subdirectory). When we find a project root, there is no need +to search inside it, and '-prune' makes sure that we descend no further. + + For large, complex trees like the Linux kernel, this will prevent +searching a large portion of the structure, saving a good deal of time. + + +File: find.info, Node: Security Considerations, Next: Error Messages, Prev: Worked Examples, Up: Top + +11 Security Considerations +************************** + +Security considerations are important if you are using 'find' or 'xargs' +to search for or process files that don't belong to you or which other +people have control. Security considerations relating to 'locate' may +also apply if you have files which you do not want others to see. + + The most severe forms of security problems affecting 'find' and +related programs are when third parties bring about a situation allowing +them to do something they would normally not be able to accomplish. +This is called _privilege elevation_. This might include deleting files +they would not normally be able to delete. It is common for the +operating system to periodically invoke 'find' for self-maintenance +purposes. These invocations of 'find' are particularly problematic from +a security point of view as these are often invoked by the superuser and +search the entire filesystem hierarchy. Generally, the severity of any +associated problem depends on what the system is going to do with the +files found by 'find'. + +* Menu: + +* Levels of Risk:: What is your level of exposure to security problems? +* Security Considerations for find:: Security problems with find +* Security Considerations for xargs:: Security problems with xargs +* Security Considerations for locate:: Security problems with locate +* Security Summary:: That was all very complex, what does it boil down to? +* Further Reading on Security:: + + +File: find.info, Node: Levels of Risk, Next: Security Considerations for find, Up: Security Considerations + +11.1 Levels of Risk +=================== + +There are some security risks inherent in the use of 'find', 'xargs' and +(to a lesser extent) 'locate'. The severity of these risks depends on +what sort of system you are using: + +*High risk* + Multi-user systems where you do not control (or trust) the other + users, and on which you execute 'find', including areas where those + other users can manipulate the filesystem (for example beneath + '/home' or '/tmp'). + +*Medium Risk* + Systems where the actions of other users can create file names + chosen by them, but to which they don't have access while 'find' is + being run. This access might include leaving programs running + (shell background jobs, 'at' or 'cron' tasks, for example). On + these sorts of systems, carefully written commands (avoiding use of + '-print' for example) should not expose you to a high degree of + risk. Most systems fall into this category. + +*Low Risk* + Systems to which untrusted parties do not have access, cannot + create file names of their own choice (even remotely) and which + contain no security flaws which might enable an untrusted third + party to gain access. Most systems do not fall into this category + because there are many ways in which external parties can affect + the names of files that are created on your system. The system on + which I am writing this for example automatically downloads + software updates from the Internet; the names of the files in which + these updates exist are chosen by third parties(1). + + In the discussion above, "risk" denotes the likelihood that someone +can cause 'find', 'xargs', 'locate' or some other program which is +controlled by them to do something you did not intend. The levels of +risk suggested do not take any account of the consequences of this sort +of event. That is, if you operate a "low risk" type system, but the +consequences of a security problem are disastrous, then you should still +give serious thought to all the possible security problems, many of +which of course will not be discussed here - this section of the manual +is intended to be informative but not comprehensive or exhaustive. + + If you are responsible for the operation of a system where the +consequences of a security problem could be very important, you should +do two things: + + 1. Define a security policy which defines who is allowed to do what on + your system. + 2. Seek competent advice on how to enforce your policy, detect + breaches of that policy, and take account of any potential problems + that might fall outside the scope of your policy. + + ---------- Footnotes ---------- + + (1) Of course, I trust these parties to a large extent anyway, +because I install software provided by them; I choose to trust them in +this way, and that's a deliberate choice + + +File: find.info, Node: Security Considerations for find, Next: Security Considerations for xargs, Prev: Levels of Risk, Up: Security Considerations + +11.2 Security Considerations for 'find' +======================================= + +Some of the actions 'find' might take have a direct effect; these +include '-exec' and '-delete'. However, it is also common to use +'-print' explicitly or implicitly, and so if 'find' produces the wrong +list of file names, that can also be a security problem; consider the +case for example where 'find' is producing a list of files to be +deleted. + + We normally assume that the 'find' command line expresses the file +selection criteria and actions that the user had in mind - that is, the +command line is "trusted" data. + + From a security analysis point of view, the output of 'find' should +be correct; that is, the output should contain only the names of those +files which meet the user's criteria specified on the command line. +This applies for the '-exec' and '-delete' actions; one can consider +these to be part of the output. + + On the other hand, the contents of the filesystem can be manipulated +by other people, and hence we regard this as "untrusted" data. This +implies that the 'find' command line is a filter which converts the +untrusted contents of the filesystem into a correct list of output +files. + + The filesystem will in general change while 'find' is searching it; +in fact, most of the potential security problems with 'find' relate to +this issue in some way. + + "Race conditions" are a general class of security problem where the +relative ordering of actions taken by 'find' (for example) and something +else are critically important in getting the correct and expected +result(1) . + + For 'find', an attacker might move or rename files or directories in +the hope that an action might be taken against a file which was not +normally intended to be affected. Alternatively, this sort of attack +might be intended to persuade 'find' to search part of the filesystem +which would not normally be included in the search (defeating the +'-prune' action for example). + +* Menu: + +* Problems with -exec and filenames:: +* Changing the Current Working Directory:: +* Race Conditions with -exec:: +* Race Conditions with -print and -print0:: + + ---------- Footnotes ---------- + + (1) This is more or less the definition of the term "race condition" + + +File: find.info, Node: Problems with -exec and filenames, Next: Changing the Current Working Directory, Up: Security Considerations for find + +11.2.1 Problems with '-exec' and filenames +------------------------------------------ + +It is safe in many cases to use the '-execdir' action with any file +name. Because '-execdir' prefixes the arguments it passes to programs +with './', you will not accidentally pass an argument which is +interpreted as an option. For example the file '-f' would be passed to +'rm' as './-f', which is harmless. + + However, your degree of safety does depend on the nature of the +program you are running. For example constructs such as these two +commands + + # risky + find -exec sh -c "something {}" \; + find -execdir sh -c "something {}" \; + + are very dangerous. The reason for this is that the '{}' is expanded +to a filename which might contain a semicolon or other characters +special to the shell. If for example someone creates the file +'/tmp/foo; rm -rf $HOME' then the two commands above could delete +someone's home directory. + + So for this reason do not run any command which will pass untrusted +data (such as the names of files) to commands which interpret arguments +as commands to be further interpreted (for example 'sh'). + + In the case of the shell, there is a clever workaround for this +problem: + + # safer + find -exec sh -c 'something "$@"' sh {} \; + find -execdir sh -c 'something "$@"' sh {} \; + + This approach is not guaranteed to avoid every problem, but it is +much safer than substituting data of an attacker's choice into the text +of a shell command. + + +File: find.info, Node: Changing the Current Working Directory, Next: Race Conditions with -exec, Prev: Problems with -exec and filenames, Up: Security Considerations for find + +11.2.2 Changing the Current Working Directory +--------------------------------------------- + +As 'find' searches the filesystem, it finds subdirectories and then +searches within them by changing its working directory. First, 'find' +reaches and recognises a subdirectory. It then decides if that +subdirectory meets the criteria for being searched; that is, any '-xdev' +or '-prune' expressions are taken into account. The 'find' program will +then change working directory and proceed to search the directory. + + A race condition attack might take the form that once the checks +relevant to '-xdev' and '-prune' have been done, an attacker might +rename the directory that was being considered, and put in its place a +symbolic link that actually points somewhere else. + + The idea behind this attack is to fool 'find' into going into the +wrong directory. This would leave 'find' with a working directory +chosen by an attacker, bypassing any protection apparently provided by +'-xdev' and '-prune', and any protection provided by being able to _not_ +list particular directories on the 'find' command line. This form of +attack is particularly problematic if the attacker can predict when the +'find' command will be run, as is the case with 'cron' tasks for +example. + + GNU 'find' has specific safeguards to prevent this general class of +problem. The exact form of these safeguards depends on the properties +of your system. + +* Menu: + +* O_NOFOLLOW:: Safely changing directory using 'fchdir'. +* Systems without O_NOFOLLOW:: Checking for symbolic links after 'chdir'. + + +File: find.info, Node: O_NOFOLLOW, Next: Systems without O_NOFOLLOW, Up: Changing the Current Working Directory + +11.2.2.1 'O_NOFOLLOW' +..................... + +If your system supports the 'O_NOFOLLOW' flag (1) to the 'open(2)' +system call, 'find' uses it to safely change directories. The target +directory is first opened and then 'find' changes working directory with +the 'fchdir()' system call. This ensures that symbolic links are not +followed, preventing the sort of race condition attack in which use is +made of symbolic links. + + If for any reason this approach does not work, 'find' will fall back +on the method which is normally used if 'O_NOFOLLOW' is not supported. + + You can tell if your system supports 'O_NOFOLLOW' by running + + find --version + + This will tell you the version number and which features are enabled. +For example, if I run this on my system now, this gives: + find (GNU findutils) 4.5.11-git + Copyright (C) 2012 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Written by Eric B. Decker, James Youngman, and Kevin Dalley. + Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2) + + Here, you can see that I am running a version of 'find' which was +built from the development (git) code prior to the release of +findutils-4.5.12, and that several features including 'O_NOFOLLOW' are +present. 'O_NOFOLLOW' is qualified with "enabled". This simply means +that the current system seems to support 'O_NOFOLLOW'. This check is +needed because it is possible to build 'find' on a system that defines +'O_NOFOLLOW' and then run it on a system that ignores the 'O_NOFOLLOW' +flag. We try to detect such cases at startup by checking the operating +system and version number; when this happens you will see +'O_NOFOLLOW(disabled)' instead. + + ---------- Footnotes ---------- + + (1) GNU/Linux (kernel version 2.1.126 and later) and FreeBSD +(3.0-CURRENT and later) support this + + +File: find.info, Node: Systems without O_NOFOLLOW, Prev: O_NOFOLLOW, Up: Changing the Current Working Directory + +11.2.2.2 Systems without 'O_NOFOLLOW' +..................................... + +The strategy for preventing this type of problem on systems that lack +support for the 'O_NOFOLLOW' flag is more complex. Each time 'find' +changes directory, it examines the directory it is about to move to, +issues the 'chdir()' system call, and then checks that it has ended up +in the subdirectory it expected. If all is as expected, processing +continues as normal. However, there are two main reasons why the +directory might change: the use of an automounter and the someone +removing the old directory and replacing it with something else while +'find' is trying to descend into it. + + Where a filesystem "automounter" is in use it can be the case that +the use of the 'chdir()' system call can itself cause a new filesystem +to be mounted at that point. On systems that do not support +'O_NOFOLLOW', this will cause 'find''s security check to fail. + + However, this does not normally represent a security problem, since +the automounter configuration is normally set up by the system +administrator. Therefore, if the 'chdir()' sanity check fails, 'find' +will make one more attempt(1). If that succeeds, execution carries on +as normal. This is the usual case for automounters. + + Where an attacker is trying to exploit a race condition, the problem +may not have gone away on the second attempt. If this is the case, +'find' will issue a warning message and then ignore that subdirectory. +When this happens, actions such as '-exec' or '-print' may already have +taken place for the problematic subdirectory. This is because 'find' +applies tests and actions to directories before searching within them +(unless '-depth' was specified). + + Because of the nature of the directory-change operation and security +check, in the worst case the only things that 'find' would have done +with the directory are to move into it and back out to the original +parent. No operations would have been performed within that directory. + + ---------- Footnotes ---------- + + (1) This may not be the case for the fts-based executable + + +File: find.info, Node: Race Conditions with -exec, Next: Race Conditions with -print and -print0, Prev: Changing the Current Working Directory, Up: Security Considerations for find + +11.2.3 Race Conditions with '-exec' +----------------------------------- + +The '-exec' action causes another program to be run. It passes to the +program the name of the file which is being considered at the time. The +invoked program will typically then perform some action on that file. +Once again, there is a race condition which can be exploited here. We +shall take as a specific example the command + + find /tmp -path /tmp/umsp/passwd -exec /bin/rm + + In this simple example, we are identifying just one file to be +deleted and invoking '/bin/rm' to delete it. A problem exists because +there is a time gap between the point where 'find' decides that it needs +to process the '-exec' action and the point where the '/bin/rm' command +actually issues the 'unlink()' system call to delete the file from the +filesystem. Within this time period, an attacker can rename the +'/tmp/umsp' directory, replacing it with a symbolic link to '/etc'. +There is no way for '/bin/rm' to determine that it is working on the +same file that 'find' had in mind. Once the symbolic link is in place, +the attacker has persuaded 'find' to cause the deletion of the +'/etc/passwd' file, which is not the effect intended by the command +which was actually invoked. + + One possible defence against this type of attack is to modify the +behaviour of '-exec' so that the '/bin/rm' command is run with the +argument './passwd' and a suitable choice of working directory. This +would allow the normal sanity check that 'find' performs to protect +against this form of attack too. Unfortunately, this strategy cannot be +used as the POSIX standard specifies that the current working directory +for commands invoked with '-exec' must be the same as the current +working directory from which 'find' was invoked. This means that the +'-exec' action is inherently insecure and can't be fixed. + + GNU 'find' implements a more secure variant of the '-exec' action, +'-execdir'. The '-execdir' action ensures that it is not necessary to +dereference subdirectories to process target files. The current +directory used to invoke programs is the same as the directory in which +the file to be processed exists ('/tmp/umsp' in our example, and only +the basename of the file to be processed is passed to the invoked +command, with a './' prepended (giving './passwd' in our example). + + The '-execdir' action refuses to do anything if the current directory +is included in the $PATH environment variable. This is necessary +because '-execdir' runs programs in the same directory in which it finds +files - in general, such a directory might be writable by untrusted +users. For similar reasons, '-execdir' does not allow '{}' to appear in +the name of the command to be run. + + +File: find.info, Node: Race Conditions with -print and -print0, Prev: Race Conditions with -exec, Up: Security Considerations for find + +11.2.4 Race Conditions with '-print' and '-print0' +-------------------------------------------------- + +The '-print' and '-print0' actions can be used to produce a list of +files matching some criteria, which can then be used with some other +command, perhaps with 'xargs'. Unfortunately, this means that there is +an unavoidable time gap between 'find' deciding that one or more files +meet its criteria and the relevant command being executed. For this +reason, the '-print' and '-print0' actions are just as insecure as +'-exec'. + + In fact, since the construction + + find ... -print | xargs ... + + does not cope correctly with newlines or other "white space" in file +names, and copes poorly with file names containing quotes, the '-print' +action is less secure even than '-print0'. + + +File: find.info, Node: Security Considerations for xargs, Next: Security Considerations for locate, Prev: Security Considerations for find, Up: Security Considerations + +11.3 Security Considerations for 'xargs' +======================================== + +The description of the race conditions affecting the '-print' action of +'find' shows that 'xargs' cannot be secure if it is possible for an +attacker to modify a filesystem after 'find' has started but before +'xargs' has completed all its actions. + + However, there are other security issues that exist even if it is not +possible for an attacker to have access to the filesystem in real time. +Firstly, if it is possible for an attacker to create files with names of +their choice on the filesystem, then 'xargs' is insecure unless the '-0' +option is used. If a file with the name +'/home/someuser/foo/bar\n/etc/passwd' exists (assume that '\n' stands +for a newline character), then 'find ... -print' can be persuaded to +print three separate lines: + + /home/someuser/foo/bar + + /etc/passwd + + If it finds a blank line in the input, 'xargs' will ignore it. +Therefore, if some action is to be taken on the basis of this list of +files, the '/etc/passwd' file would be included even if this was not the +intent of the person running find. There are circumstances in which an +attacker can use this to their advantage. The same consideration +applies to file names containing ordinary spaces rather than newlines, +except that of course the list of file names will no longer contain an +"extra" newline. + + This problem is an unavoidable consequence of the default behaviour +of the 'xargs' command, which is specified by the POSIX standard. The +only ways to avoid this problem are either to avoid all use of 'xargs' +in favour for example of 'find -exec' or (where available) 'find +-execdir', or to use the '-0' option, which ensures that 'xargs' +considers file names to be separated by ASCII NUL characters rather than +whitespace. However, useful as this option is, the POSIX standard does +not make it mandatory. + + POSIX also specifies that 'xargs' interprets quoting and trailing +whitespace specially in filenames, too. This means that using 'find ... +-print | xargs ...' can cause the commands run by 'xargs' to receive a +list of file names which is not the same as the list printed by 'find'. +The interpretation of quotes and trailing whitespace is turned off by +the '-0' argument to 'xargs', which is another reason to use that +option. + + +File: find.info, Node: Security Considerations for locate, Next: Security Summary, Prev: Security Considerations for xargs, Up: Security Considerations + +11.4 Security Considerations for 'locate' +========================================= + +11.4.1 Race Conditions +---------------------- + +It is fairly unusual for the output of 'locate' to be fed into another +command. However, if this were to be done, this would raise the same +set of security issues as the use of 'find ... -print'. Although the +problems relating to whitespace in file names can be resolved by using +'locate''s '-0' option, this still leaves the race condition problems +associated with 'find ... -print0'. There is no way to avoid these +problems in the case of 'locate'. + +11.4.2 Long File Name Bugs with Old-Format Databases +---------------------------------------------------- + +Old versions of 'locate' have a bug in the way that old-format databases +are read. This bug affects the following versions of 'locate': + + 1. All releases prior to 4.2.31 + 2. All 4.3.x releases prior to 4.3.7 + + The affected versions of 'locate' read file names into a fixed-length +1026 byte buffer, allocated on the heap. This buffer is not extended if +file names are too long to fit into the buffer. No range checking on +the length of the filename is performed. This could in theory lead to a +privilege escalation attack. Findutils versions 4.3.0 to 4.3.6 are also +affected. + + On systems using the old database format and affected versions of +'locate', carefully-chosen long file names could in theory allow +malicious users to run code of their choice as any user invoking locate. + + If remote users can choose the names of files stored on your system, +and these files are indexed by 'updatedb', this may be a remote security +vulnerability. Findutils version 4.2.31 and findutils version 4.3.7 +include fixes for this problem. The 'updatedb', 'bigram' and 'code' +programs do no appear to be affected. + + If you are also using GNU coreutils, you can use the following +command to determine the length of the longest file name on a given +system: + + find / -print0 | tr -c '\0' 'x' | tr '\0' '\n' | wc -L + + Although this problem is significant, the old database format is not +the default, and use of the old database format is not common. Most +installations and most users will not be affected by this problem. + + +File: find.info, Node: Security Summary, Next: Further Reading on Security, Prev: Security Considerations for locate, Up: Security Considerations + +11.5 Summary +============ + +Where untrusted parties can create files on the system, or affect the +names of files that are created, all uses for 'find', 'locate' and +'xargs' have known security problems except the following: + +Informational use only + Uses where the programs are used to prepare lists of file names + upon which no further action will ever be taken. + +'-delete' + Use of the '-delete' action with 'find' to delete files which meet + specified criteria + +'-execdir' + Use of the '-execdir' action with 'find' where the 'PATH' + environment variable contains directories which contain only + trusted programs. + + +File: find.info, Node: Further Reading on Security, Prev: Security Summary, Up: Security Considerations + +11.6 Further Reading on Security +================================ + +While there are a number of books on computer security, there are also +useful articles on the web that touch on the issues described above: + +<http://goo.gl/DAvh> + This article describes some of the unfortunate effects of allowing + free choice of file names. +<http://cwe.mitre.org/data/definitions/78.html> + Describes OS Command Injection +<https://cwe.mitre.org/data/definitions/73.html> + Describes problems arising from allowing remote computers to send + requests which specify file names of their choice +<http://cwe.mitre.org/data/definitions/116.html> + Describes problems relating to encoding file names and escaping + characters. This article is relevant to findutils because for + command lines processed via the shell, the encoding and escaping + rules are already set by the shell. For example command lines like + 'find ... -print | some-shell-script' require specific care. +<http://xkcd.com/327/> + A humorous and pithy summary of the broader problem. + + +File: find.info, Node: Error Messages, Next: GNU Free Documentation License, Prev: Security Considerations, Up: Top + +12 Error Messages +***************** + +This section describes some of the error messages sometimes made by +'find', 'xargs', or 'locate', explains them and in some cases provides +advice as to what you should do about this. + + This manual is written in English. The GNU findutils software +features translations of error messages for many languages. For this +reason the error messages produced by the programs are made to be as +self-explanatory as possible. This approach avoids leaving people to +figure out which test an English-language error message corresponds to. +Error messages which are self-explanatory will not normally be mentioned +in this document. For those messages mentioned in this document, only +the English-language version of the message will be listed. + +* Menu: + +* Error Messages From find:: +* Error Messages From xargs:: +* Error Messages From locate:: +* Error Messages From updatedb:: + + +File: find.info, Node: Error Messages From find, Next: Error Messages From xargs, Up: Error Messages + +12.1 Error Messages From 'find' +=============================== + +Most error messages produced by find are self-explanatory. Error +messages sometimes include a filename. When this happens, the filename +is quoted in order to prevent any unusual characters in the filename +making unwanted changes in the state of the terminal. + +'invalid predicate `-foo'' + This means that the 'find' command line included something that + started with a dash or other special character. The 'find' program + tried to interpret this as a test, action or option, but didn't + recognise it. If it was intended to be a test, check what was + specified against the documentation. If, on the other hand, the + string is the name of a file which has been expanded from a + wildcard (for example because you have a '*' on the command line), + consider using './*' or just '.' instead. + +'unexpected extra predicate' + This usually happens if you have an extra bracket on the command + line (for example 'find . -print \)'). + +'Warning: filesystem /path/foo has recently been mounted' +'Warning: filesystem /path/foo has recently been unmounted' + These messages might appear when 'find' moves into a directory and + finds that the device number and inode are different from what it + expected them to be. If the directory 'find' has moved into is on + a network filesystem (NFS), it will not issue this message, because + 'automount' frequently mounts new filesystems on directories as you + move into them (that is how it knows you want to use the + filesystem). So, if you do see this message, be wary - 'automount' + may not have been responsible. Consider the possibility that + someone else is manipulating the filesystem while 'find' is + running. Some people might do this in order to mislead 'find' or + persuade it to look at one set of files when it thought it was + looking at another set. + +'/path/foo changed during execution of find (old device number 12345, new device number 6789, filesystem type is <whatever>) [ref XXX]' + This message is issued when 'find' moves into a directory and ends + up somewhere it didn't expect to be. This happens in one of two + circumstances. Firstly, this happens when 'automount' intervenes + on a system where 'find' doesn't know how to determine what the + current set of mounted filesystems is. + + Secondly, this can happen when the device number of a directory + appears to change during a change of current directory, but 'find' + is moving up the filesystem hierarchy rather than down into it. In + order to prevent 'find' wandering off into some unexpected part of + the filesystem, we stop it at this point. + +'Don't know how to use getmntent() to read `/etc/mtab'. This is a bug.' + This message is issued when a problem similar to the above occurs + on a system where 'find' doesn't know how to figure out the current + list of mount points. Ask for help on <bug-findutils@gnu.org>. + +'/path/foo/bar changed during execution of find (old inode number 12345, new inode number 67893, filesystem type is <whatever>) [ref XXX]"),' + This message is issued when 'find' moves into a directory and + discovers that the inode number of that directory is different from + the inode number that it obtained when it examined the directory + previously. This usually means that while 'find' was deep in a + directory hierarchy doing a time consuming operation, somebody has + moved one of the parent directories to another location in the same + filesystem. This may or may not have been done maliciously. In + any case, 'find' stops at this point to avoid traversing parts of + the filesystem that it wasn't intended to. You can use 'ls -li' or + 'find /path -inum 12345 -o -inum 67893' to find out more about what + has happened. + +'sanity check of the fnmatch() library function failed.' + Please submit a bug report. You may well be asked questions about + your system, and if you compiled the 'findutils' code yourself, you + should keep your copy of the build tree around. The likely + explanation is that your system has a buggy implementation of + 'fnmatch' that looks enough like the GNU version to fool + 'configure', but which doesn't work properly. + +'cannot fork' + This normally happens if you use the '-exec' action or something + similar ('-ok' and so forth) but the system has run out of free + process slots. This is either because the system is very busy and + the system has reached its maximum process limit, or because you + have a resource limit in place and you've reached it. Check the + system for runaway processes (with 'ps', if possible). Some + process slots are normally reserved for use by 'root'. + +'some-program terminated by signal 99' + Some program which was launched with '-exec' or similar was killed + with a fatal signal. This is just an advisory message. + + +File: find.info, Node: Error Messages From xargs, Next: Error Messages From locate, Prev: Error Messages From find, Up: Error Messages + +12.2 Error Messages From 'xargs' +================================ + +'environment is too large for exec' + This message means that you have so many environment variables set + (or such large values for them) that there is no room within the + system-imposed limits on program command line argument length to + invoke any program. This is an unlikely situation and is more + likely result of an attempt to test the limits of 'xargs', or break + it. Please try unsetting some environment variables, or exiting + the current shell. You can also use 'xargs --show-limits' to + understand the relevant sizes. + +'argument list too long' + You are using the '-I' option and 'xargs' doesn't have enough space + to build a command line because it has read a really large item and + it doesn't fit. You may be able to work around this problem with + the '-s' option, but the default size is pretty large. This is a + rare situation and is more likely an attempt to test the limits of + 'xargs', or break it. Otherwise, you will need to try to shorten + the problematic argument or not use 'xargs'. + +'argument line too long' + You are using the '-L' or '-l' option and one of the input lines is + too long. You may be able to work around this problem with the + '-s' option, but the default size is pretty large. If you can + modify the your 'xargs' command not to use '-L' or '-l', that will + be more likely to result in success. + +'cannot fork' + See the description of the similar message for 'find'. + +'<program>: exited with status 255; aborting' + When a command run by 'xargs' exits with status 255, 'xargs' is + supposed to stop. If this is not what you intended, wrap the + program you are trying to invoke in a shell script which doesn't + return status 255. + +'<program>: terminated by signal 99' + See the description of the similar message for 'find'. + +'cannot set SIGUSR1 signal handler' + 'xargs' is having trouble preparing for you to be able to send it + signals to increase or decrease the parallelism of its processing. + If you don't plan to send it those signals, this warning can be + ignored (though if you're a programmer, you may want to help us + figure out why 'xargs' is confused by your operating system). + + +File: find.info, Node: Error Messages From locate, Next: Error Messages From updatedb, Prev: Error Messages From xargs, Up: Error Messages + +12.3 Error Messages From 'locate' +================================= + +'warning: database '/usr/local/var/locatedb' is more than 8 days old' + The 'locate' program relies on a database which is periodically + built by the 'updatedb' program. That hasn't happened in a long + time. To fix this problem, run 'updatedb' manually. This can + often happen on systems that are generally not left on, so the + periodic "cron" task which normally does this doesn't get a chance + to run. + +'locate database '/usr/local/var/locatedb' is corrupt or invalid' + This should not happen. Re-run 'updatedb'. If that works, but + 'locate' still produces this error, run 'locate --version' and + 'updatedb --version'. These should produce the same output. If + not, you are using a mixed toolset; check your '$PATH' environment + variable and your shell aliases (if you have any). If both + programs claim to be GNU versions, this is a bug; all versions of + these programs should interoperate without problem. Ask for help + on <bug-findutils@gnu.org>. + + +File: find.info, Node: Error Messages From updatedb, Prev: Error Messages From locate, Up: Error Messages + +12.4 Error Messages From 'updatedb' +=================================== + +The 'updatedb' program (and the programs it invokes) do issue error +messages, but none seem to be candidates for guidance. If you are +having a problem understanding one of these, ask for help on +<bug-findutils@gnu.org>. + + +File: find.info, Node: GNU Free Documentation License, Next: Primary Index, Prev: Error Messages, Up: Top + +Appendix A GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + <http://fsf.org/> + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled "History" in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + "History" section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + <http://www.gnu.org/copyleft/>. + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A "Massive Multiauthor Collaboration" (or "MMC") contained in the + site means any set of copyrightable works thus published on the MMC + site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + diff --git a/doc/find.info-2 b/doc/find.info-2 Binary files differnew file mode 100644 index 0000000..d0d0145 --- /dev/null +++ b/doc/find.info-2 diff --git a/doc/find.texi b/doc/find.texi new file mode 100644 index 0000000..fdeb841 --- /dev/null +++ b/doc/find.texi @@ -0,0 +1,5712 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename find.info +@settitle Finding Files +@c For double-sided printing, uncomment: +@c @setchapternewpage odd +@c %**end of header + +@include version.texi +@include dblocation.texi + +@iftex +@finalout +@end iftex + +@dircategory Basics +@direntry +* Finding files: (find). Operating on files matching certain criteria. +@end direntry + +@dircategory Individual utilities +@direntry +* find: (find)Invoking find. Finding and acting on files. +* locate: (find)Invoking locate. Finding files in a database. +* updatedb: (find)Invoking updatedb. Building the locate database. +* xargs: (find)Invoking xargs. Operating on many files. +@end direntry + +@copying + +This file documents the GNU utilities for finding files that match +certain criteria and performing various operations on them. + +Copyright @copyright{} 1994, 1996, 1998, 2000, 2001, 2003-2015 Free +Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled +``GNU Free Documentation License''. +@end copying + +@titlepage +@title Finding Files +@subtitle Edition @value{EDITION}, for GNU @code{find} version @value{VERSION} +@subtitle @value{UPDATED} +@author by David MacKenzie and James Youngman + +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top +@top GNU Findutils +@comment node-name, next, previous, up +@insertcopying + +This file documents the GNU utilities for finding files that match +certain criteria and performing various actions on them. + +This is edition @value{EDITION}, for @code{find} version @value{VERSION}. +@end ifnottex + +@c The master menu, created with texinfo-master-menu, goes here. + +@menu +* Introduction:: Summary of the tasks this manual describes. +* Finding Files:: Finding files that match certain criteria. +* Actions:: Doing things to files you have found. +* Databases:: Maintaining file name databases. +* File Permissions:: How to control access to files. +* Date input formats:: Specifying literal times. +* Configuration:: Options you can select at compile time. +* Reference:: Summary of how to invoke the programs. +* Common Tasks:: Solutions to common real-world problems. +* Worked Examples:: Examples demonstrating more complex points. +* Security Considerations:: Security issues relating to findutils. +* Error Messages:: Explanations of some messages you might see. +* GNU Free Documentation License:: Copying and sharing this manual. +* Primary Index:: The components of @code{find} expressions. +@end menu + +@node Introduction +@chapter Introduction + +This manual shows how to find files that meet criteria you specify, +and how to perform various actions on the files that you find. The +principal programs that you use to perform these tasks are +@code{find}, @code{locate}, and @code{xargs}. Some of the examples in +this manual use capabilities specific to the GNU versions of those +programs. + +GNU @code{find} was originally written by Eric Decker, with +enhancements by David MacKenzie, Jay Plett, and Tim Wood. GNU +@code{xargs} was originally written by Mike Rendell, with enhancements +by David MacKenzie. GNU @code{locate} and its associated utilities +were originally written by James Woods, with enhancements by David +MacKenzie. The idea for @samp{find -print0} and @samp{xargs -0} came +from Dan Bernstein. The current maintainer of GNU findutils (and this +manual) is James Youngman. Many other people have contributed bug +fixes, small improvements, and helpful suggestions. Thanks! + +To report a bug in GNU findutils, please use the form on the Savannah +web site at +@code{http://savannah.gnu.org/bugs/?group=findutils}. Reporting bugs +this way means that you will then be able to track progress in fixing +the problem. + +If you don't have web access, you can also just send mail to the +mailing list. The mailing list @email{bug-findutils@@gnu.org} carries +discussion of bugs in findutils, questions and answers about the +software and discussion of the development of the programs. To join +the list, send email to @email{bug-findutils-request@@gnu.org}. + +Please read any relevant sections of this manual before asking for +help on the mailing list. You may also find it helpful to read the +NON-BUGS section of the @code{find} manual page. + +If you ask for help on the mailing list, people will be able to help +you much more effectively if you include the following things: + +@itemize @bullet +@item The version of the software you are running. You can find this +out by running @samp{locate --version}. +@item What you were trying to do +@item The @emph{exact} command line you used +@item The @emph{exact} output you got (if this is very long, try to +find a smaller example which exhibits the same problem) +@item The output you expected to get +@end itemize + +It may also be the case that the bug you are describing has already +been fixed, if it is a bug. Please check the most recent findutils +releases at @url{ftp://ftp.gnu.org/gnu/findutils} and, if possible, +the development branch at @url{ftp://alpha.gnu.org/gnu/findutils}. +If you take the time to check that your bug still exists in current +releases, this will greatly help people who want to help you solve +your problem. Please also be aware that if you obtained findutils as +part of the GNU/Linux 'distribution', the distributions often lag +seriously behind findutils releases, even the stable release. Please +check the GNU FTP site. + +@menu +* Scope:: +* Overview:: +* find Expressions:: +@end menu + +@node Scope +@section Scope + +For brevity, the word @dfn{file} in this manual means a regular file, +a directory, a symbolic link, or any other kind of node that has a +directory entry. A directory entry is also called a @dfn{file name}. +A file name may contain some, all, or none of the directories in a +path that leads to the file. These are all examples of what this +manual calls ``file names'': + +@example +parser.c +README +./budget/may-94.sc +fred/.cshrc +/usr/local/include/termcap.h +@end example + +A @dfn{directory tree} is a directory and the files it contains, all +of its subdirectories and the files they contain, etc. It can also be +a single non-directory file. + +These programs enable you to find the files in one or more directory +trees that: + +@itemize @bullet +@item +have names that contain certain text or match a certain pattern; +@item +are links to certain files; +@item +were last used during a certain period of time; +@item +are within a certain size range; +@item +are of a certain type (regular file, directory, symbolic link, etc.); +@item +are owned by a certain user or group; +@item +have certain access permissions or special mode bits; +@item +contain text that matches a certain pattern; +@item +are within a certain depth in the directory tree; +@item +or some combination of the above. +@end itemize + +Once you have found the files you're looking for (or files that are +potentially the ones you're looking for), you can do more to them than +simply list their names. You can get any combination of the files' +attributes, or process the files in many ways, either individually or +in groups of various sizes. Actions that you might want to perform on +the files you have found include, but are not limited to: + +@itemize @bullet +@item +view or edit +@item +store in an archive +@item +remove or rename +@item +change access permissions +@item +classify into groups +@end itemize + +This manual describes how to perform each of those tasks, and more. + +@node Overview +@section Overview + +The principal programs used for making lists of files that match given +criteria and running commands on them are @code{find}, @code{locate}, +and @code{xargs}. An additional command, @code{updatedb}, is used by +system administrators to create databases for @code{locate} to use. + +@code{find} searches for files in a directory hierarchy and prints +information about the files it found. It is run like this: + +@example +find @r{[}@var{file}@dots{}@r{]} @r{[}@var{expression}@r{]} +@end example + +@noindent +Here is a typical use of @code{find}. This example prints the names +of all files in the directory tree rooted in @file{/usr/src} whose +name ends with @samp{.c} and that are larger than 100 Kilobytes. +@example +find /usr/src -name '*.c' -size +100k -print +@end example + +Notice that the wildcard must be enclosed in quotes in order to +protect it from expansion by the shell. + +@code{locate} searches special file name databases for file names that +match patterns. The system administrator runs the @code{updatedb} +program to create the databases. @code{locate} is run like this: + +@example +locate @r{[}@var{option}@dots{}@r{]} @var{pattern}@dots{} +@end example + +@noindent +This example prints the names of all files in the default file name +database whose name ends with @samp{Makefile} or @samp{makefile}. +Which file names are stored in the database depends on how the system +administrator ran @code{updatedb}. +@example +locate '*[Mm]akefile' +@end example + +The name @code{xargs}, pronounced EX-args, means ``combine +arguments.'' @code{xargs} builds and executes command lines by +gathering together arguments it reads on the standard input. Most +often, these arguments are lists of file names generated by +@code{find}. @code{xargs} is run like this: + +@example +xargs @r{[}@var{option}@dots{}@r{]} @r{[}@var{command} @r{[}@var{initial-arguments}@r{]}@r{]} +@end example + +@noindent +The following command searches the files listed in the file +@file{file-list} and prints all of the lines in them that contain the +word @samp{typedef}. +@example +xargs grep typedef < file-list +@end example + +@node find Expressions +@section @code{find} Expressions + +The expression that @code{find} uses to select files consists of one +or more @dfn{primaries}, each of which is a separate command line +argument to @code{find}. @code{find} evaluates the expression each +time it processes a file. An expression can contain any of the +following types of primaries: + +@table @dfn +@item options +affect overall operation rather than the processing of a specific +file; +@item tests +return a true or false value, depending on the file's attributes; +@item actions +have side effects and return a true or false value; and +@item operators +connect the other arguments and affect when and whether they are +evaluated. +@end table + +You can omit the operator between two primaries; it defaults to +@samp{-and}. @xref{Combining Primaries With Operators}, for ways to +connect primaries into more complex expressions. If the expression +contains no actions other than @samp{-prune}, @samp{-print} is +performed on all files for which the entire expression is true +(@pxref{Print File Name}). + +Options take effect immediately, rather than being evaluated for each +file when their place in the expression is reached. Therefore, for +clarity, it is best to place them at the beginning of the expression. +There are two exceptions to this; @samp{-daystart} and @samp{-follow} +have different effects depending on where in the command line they +appear. This can be confusing, so it's best to keep them at the +beginning, too. + +Many of the primaries take arguments, which immediately follow them in +the next command line argument to @code{find}. Some arguments are +file names, patterns, or other strings; others are numbers. Numeric +arguments can be specified as + +@table @code +@item +@var{n} +for greater than @var{n}, +@item -@var{n} +for less than @var{n}, +@item @var{n} +for exactly @var{n}. +@end table + +@node Finding Files +@chapter Finding Files + +By default, @code{find} prints to the standard output the names of the +files that match the given criteria. @xref{Actions}, for how to get +more information about the matching files. + + +@menu +* Name:: +* Links:: +* Time:: +* Size:: +* Type:: +* Owner:: +* Mode Bits:: +* Contents:: +* Directories:: +* Filesystems:: +* Combining Primaries With Operators:: +@end menu + +@node Name +@section Name + +Here are ways to search for files whose name matches a certain +pattern. @xref{Shell Pattern Matching}, for a description of the +@var{pattern} arguments to these tests. + +Each of these tests has a case-sensitive version and a +case-insensitive version, whose name begins with @samp{i}. In a +case-insensitive comparison, the patterns @samp{fo*} and @samp{F??} +match the file names @file{Foo}, @samp{FOO}, @samp{foo}, @samp{fOo}, +etc. + +@menu +* Base Name Patterns:: +* Full Name Patterns:: +* Fast Full Name Search:: +* Shell Pattern Matching:: Wildcards used by these programs. +@end menu + +@node Base Name Patterns +@subsection Base Name Patterns + +@deffn Test -name pattern +@deffnx Test -iname pattern +True if the base of the file name (the path with the leading +directories removed) matches shell pattern @var{pattern}. For +@samp{-iname}, the match is case-insensitive.@footnote{Because we +need to perform case-insensitive matching, the GNU fnmatch +implementation is always used; if the C library includes the GNU +implementation, we use that and otherwise we use the one from gnulib} +To ignore a whole directory tree, use @samp{-prune} +(@pxref{Directories}). As an example, to find Texinfo source files in +@file{/usr/local/doc}: + +@example +find /usr/local/doc -name '*.texi' +@end example + +Notice that the wildcard must be enclosed in quotes in order to +protect it from expansion by the shell. + +As of findutils version 4.2.2, patterns for @samp{-name} and +@samp{-iname} will match a file name with a leading @samp{.}. For +example the command @samp{find /tmp -name \*bar} will match the file +@file{/tmp/.foobar}. Braces within the pattern (@samp{@{@}}) are not +considered to be special (that is, @code{find . -name 'foo@{1,2@}'} +matches a file named @file{foo@{1,2@}}, not the files @file{foo1} and +@file{foo2}. + +Because the leading directories are removed, the file names considered +for a match with @samp{-name} will never include a slash, so +@samp{-name a/b} will never match anything (you probably need to use +@samp{-path} instead). +@end deffn + + +@node Full Name Patterns +@subsection Full Name Patterns + +@deffn Test -path pattern +@deffnx Test -wholename pattern +True if the entire file name, starting with the command line argument +under which the file was found, matches shell pattern @var{pattern}. +To ignore a whole directory tree, use @samp{-prune} rather than +checking every file in the tree (@pxref{Directories}). The ``entire +file name'' as used by @code{find} starts with the starting-point +specified on the command line, and is not converted to an absolute +pathname, so for example @code{cd /; find tmp -wholename /tmp} will +never match anything. + +Find compares the @samp{-path} argument with the concatenation of a +directory name and the base name of the file it's considering. +Since the concatenation will never end with a slash, @samp{-path} +arguments ending in @samp{/} will match nothing (except perhaps a +start point specified on the command line). + +The name @samp{-wholename} is GNU-specific, but @samp{-path} is more +portable; it is supported by HP-UX @code{find} and is part of the +POSIX 2008 standard. + +@end deffn + +@deffn Test -ipath pattern +@deffnx Test -iwholename pattern +These tests are like @samp{-wholename} and @samp{-path}, but the match +is case-insensitive. +@end deffn + + +In the context of the tests @samp{-path}, @samp{-wholename}, +@samp{-ipath} and @samp{-wholename}, a ``full path'' is the name of +all the directories traversed from @code{find}'s start point to the +file being tested, followed by the base name of the file itself. +These paths are often not absolute paths; for example + +@example +$ cd /tmp +$ mkdir -p foo/bar/baz +$ find foo -path foo/bar -print +foo/bar +$ find foo -path /tmp/foo/bar -print +$ find /tmp/foo -path /tmp/foo/bar -print +/tmp/foo/bar +@end example + +Notice that the second @code{find} command prints nothing, even though +@file{/tmp/foo/bar} exists and was examined by @code{find}. + +Unlike file name expansion on the command line, a @samp{*} in the pattern +will match both @samp{/} and leading dots in file names: + +@example +$ find . -path '*f' +./quux/bar/baz/f +$ find . -path '*/*config' +./quux/bar/baz/.config +@end example + + +@deffn Test -regex expr +@deffnx Test -iregex expr +True if the entire file name matches regular expression @var{expr}. +This is a match on the whole path, not a search. For example, to +match a file named @file{./fubar3}, you can use the regular expression +@samp{.*bar.} or @samp{.*b.*3}, but not @samp{f.*r3}. @xref{Regexps, +, Syntax of Regular Expressions, emacs, The GNU Emacs Manual}, for a +description of the syntax of regular expressions. For @samp{-iregex}, +the match is case-insensitive. + +As for @samp{-path}, the candidate file name never ends with a slash, +so regular expressions which only match something that ends in slash +will always fail. + +There are several varieties of regular expressions; by default this +test uses POSIX basic regular expressions, but this can be changed +with the option @samp{-regextype}. +@end deffn + +@deffn Option -regextype name +This option controls the variety of regular expression syntax +understood by the @samp{-regex} and @samp{-iregex} tests. This option +is positional; that is, it only affects regular expressions which +occur later in the command line. If this option is not given, GNU +Emacs regular expressions are assumed. Currently-implemented types +are + + +@table @samp +@item emacs +Regular expressions compatible with GNU Emacs; this is also the +default behaviour if this option is not used. +@item posix-awk +Regular expressions compatible with the POSIX awk command (not GNU awk) +@item posix-basic +POSIX Basic Regular Expressions. +@item posix-egrep +Regular expressions compatible with the POSIX egrep command +@item posix-extended +POSIX Extended Regular Expressions +@end table + +@ref{Regular Expressions} for more information on the regular +expression dialects understood by GNU findutils. + + +@end deffn + +@node Fast Full Name Search +@subsection Fast Full Name Search + +To search for files by name without having to actually scan the +directories on the disk (which can be slow), you can use the +@code{locate} program. For each shell pattern you give it, +@code{locate} searches one or more databases of file names and +displays the file names that contain the pattern. @xref{Shell Pattern +Matching}, for details about shell patterns. + +If a pattern is a plain string -- it contains no +metacharacters -- @code{locate} displays all file names in the database +that contain that string. If a pattern contains +metacharacters, @code{locate} only displays file names that match the +pattern exactly. As a result, patterns that contain metacharacters +should usually begin with a @samp{*}, and will most often end with one +as well. The exceptions are patterns that are intended to explicitly +match the beginning or end of a file name. + +If you only want @code{locate} to match against the last component of +the file names (the ``base name'' of the files) you can use the +@samp{--basename} option. The opposite behaviour is the default, but +can be selected explicitly by using the option @samp{--wholename}. + +The command +@example +locate @var{pattern} +@end example + +is almost equivalent to +@example +find @var{directories} -name @var{pattern} +@end example + +where @var{directories} are the directories for which the file name +databases contain information. The differences are that the +@code{locate} information might be out of date, and that @code{locate} +handles wildcards in the pattern slightly differently than @code{find} +(@pxref{Shell Pattern Matching}). + +The file name databases contain lists of files that were on the system +when the databases were last updated. The system administrator can +choose the file name of the default database, the frequency with which +the databases are updated, and the directories for which they contain +entries. + +Here is how to select which file name databases @code{locate} +searches. The default is system-dependent. At the time this document +was generated, the default was @file{@value{LOCATE_DB}}. + +@table @code +@item --database=@var{path} +@itemx -d @var{path} +Instead of searching the default file name database, search the file +name databases in @var{path}, which is a colon-separated list of +database file names. You can also use the environment variable +@code{LOCATE_PATH} to set the list of database files to search. The +option overrides the environment variable if both are used. +@end table + +GNU @code{locate} can read file name databases generated by the +@code{slocate} package. However, these generally contain a list of +all the files on the system, and so when using this database, +@code{locate} will produce output only for files which are accessible +to you. @xref{Invoking locate}, for a description of the +@samp{--existing} option which is used to do this. + +The @code{updatedb} program can also generate database in a format +compatible with @code{slocate}. @xref{Invoking updatedb}, for a +description of its @samp{--dbformat} and @samp{--output} options. + + +@node Shell Pattern Matching +@subsection Shell Pattern Matching + +@code{find} and @code{locate} can compare file names, or parts of file +names, to shell patterns. A @dfn{shell pattern} is a string that may +contain the following special characters, which are known as +@dfn{wildcards} or @dfn{metacharacters}. + +You must quote patterns that contain metacharacters to prevent the +shell from expanding them itself. Double and single quotes both work; +so does escaping with a backslash. + +@table @code +@item * +Matches any zero or more characters. + +@item ? +Matches any one character. + +@item [@var{string}] +Matches exactly one character that is a member of the string +@var{string}. This is called a @dfn{character class}. As a +shorthand, @var{string} may contain ranges, which consist of two +characters with a dash between them. For example, the class +@samp{[a-z0-9_]} matches a lowercase letter, a number, or an +underscore. You can negate a class by placing a @samp{!} or @samp{^} +immediately after the opening bracket. Thus, @samp{[^A-Z@@]} matches +any character except an uppercase letter or an at sign. + +@item \ +Removes the special meaning of the character that follows it. This +works even in character classes. +@end table + +In the @code{find} tests that do shell pattern matching (@samp{-name}, +@samp{-wholename}, etc.), wildcards in the pattern will match a +@samp{.} at the beginning of a file name. This is also the case for +@code{locate}. Thus, @samp{find -name '*macs'} will match a file +named @file{.emacs}, as will @samp{locate '*macs'}. + +Slash characters have no special significance in the shell pattern +matching that @code{find} and @code{locate} do, unlike in the shell, +in which wildcards do not match them. Therefore, a pattern +@samp{foo*bar} can match a file name @samp{foo3/bar}, and a pattern +@samp{./sr*sc} can match a file name @samp{./src/misc}. + +If you want to locate some files with the @samp{locate} command but +don't need to see the full list you can use the @samp{--limit} option +to see just a small number of results, or the @samp{--count} option to +display only the total number of matches. + +@node Links +@section Links + +There are two ways that files can be linked together. @dfn{Symbolic +links} are a special type of file whose contents are a portion of the +name of another file. @dfn{Hard links} are multiple directory entries +for one file; the file names all have the same index node +(@dfn{inode}) number on the disk. + +@menu +* Symbolic Links:: +* Hard Links:: +@end menu + +@node Symbolic Links +@subsection Symbolic Links + +Symbolic links are names that reference other files. GNU @code{find} +will handle symbolic links in one of two ways; firstly, it can +dereference the links for you - this means that if it comes across a +symbolic link, it examines the file that the link points to, in order +to see if it matches the criteria you have specified. Secondly, it +can check the link itself in case you might be looking for the actual +link. If the file that the symbolic link points to is also within the +directory hierarchy you are searching with the @code{find} command, +you may not see a great deal of difference between these two +alternatives. + +By default, @code{find} examines symbolic links themselves when it +finds them (and, if it later comes across the linked-to file, it will +examine that, too). If you would prefer @code{find} to dereference +the links and examine the file that each link points to, specify the +@samp{-L} option to @code{find}. You can explicitly specify the +default behaviour by using the @samp{-P} option. The @samp{-H} +option is a half-way-between option which ensures that any symbolic +links listed on the command line are dereferenced, but other symbolic +links are not. + +Symbolic links are different from ``hard links'' in the sense that you +need permission to search the directories +in the linked-to file name to +dereference the link. This can mean that even if you specify the +@samp{-L} option, @code{find} may not be able to determine the +properties of the file that the link points to (because you don't have +sufficient permission). In this situation, @code{find} uses the +properties of the link itself. This also occurs if a symbolic link +exists but points to a file that is missing. + +The options controlling the behaviour of @code{find} with respect to +links are as follows: + +@table @samp +@item -P +@code{find} does not dereference symbolic links at all. This is the +default behaviour. This option must be specified before any of the +file names on the command line. +@item -H +@code{find} does not dereference symbolic links (except in the case of +file names on the command line, which are dereferenced). If a +symbolic link cannot be dereferenced, the information for the symbolic +link itself is used. This option must be specified before any of the +file names on the command line. +@item -L +@code{find} dereferences symbolic links where possible, and where this +is not possible it uses the properties of the symbolic link itself. +This option must be specified before any of the file names on the +command line. Use of this option also implies the same behaviour as +the @samp{-noleaf} option. If you later use the @samp{-H} or +@samp{-P} options, this does not turn off @samp{-noleaf}. + +Actions that can cause symbolic links to become broken while +@samp{find} is executing (for example @samp{-delete}) can give rise to +confusing behaviour. Take for example the command line +@samp{find -L . -type d -delete}. This will delete empty +directories. If a subtree includes only directories and symbolic +links to directoires, this command may still not successfully delete +it, since deletion of the target of the symbolic link will cause the +symbolic link to become broken and @samp{-type d} is false for broken +symbolic links. + +@item -follow +This option forms part of the ``expression'' and must be specified +after the file names, but it is otherwise equivalent to @samp{-L}. +The @samp{-follow} option affects only those tests which appear after +it on the command line. This option is deprecated. Where possible, +you should use @samp{-L} instead. +@end table + +The following differences in behaviour occur when the @samp{-L} option +is used: + +@itemize @bullet +@item +@code{find} follows symbolic links to directories when searching +directory trees. +@item +@samp{-lname} and @samp{-ilname} always return false (unless they +happen to match broken symbolic links). +@item +@samp{-type} reports the types of the files that symbolic links point +to. This means that in combination with @samp{-L}, @samp{-type l} +will be true only for broken symbolic links. To check for symbolic +links when @samp{-L} has been specified, use @samp{-xtype l}. +@item +Implies @samp{-noleaf} (@pxref{Directories}). +@end itemize + +If the @samp{-L} option or the @samp{-H} option is used, +the file names used as arguments to @samp{-newer}, @samp{-anewer}, and +@samp{-cnewer} are dereferenced and the timestamp from the pointed-to +file is used instead (if possible -- otherwise the timestamp from the +symbolic link is used). + +@deffn Test -lname pattern +@deffnx Test -ilname pattern +True if the file is a symbolic link whose contents match shell pattern +@var{pattern}. For @samp{-ilname}, the match is case-insensitive. +@xref{Shell Pattern Matching}, for details about the @var{pattern} +argument. If the @samp{-L} option is in effect, this test will always +return false for symbolic links unless they are broken. So, to list +any symbolic links to @file{sysdep.c} in the current directory and its +subdirectories, you can do: + +@example +find . -lname '*sysdep.c' +@end example +@end deffn + +@node Hard Links +@subsection Hard Links + +Hard links allow more than one name to refer to the same file. To +find all the names which refer to the same file as @var{name}, use +@samp{-samefile NAME}. If you are not using the @samp{-L} option, you +can confine your search to one filesystem using the @samp{-xdev} +option. This is useful because hard links cannot point outside a +single filesystem, so this can cut down on needless searching. + +If the @samp{-L} option is in effect, and @var{name} is in fact a symbolic +link, the symbolic link will be dereferenced. Hence you are searching +for other links (hard or symbolic) to the file pointed to by @var{name}. If +@samp{-L} is in effect but @var{name} is not itself a symbolic link, other +symbolic links to the file @var{name} will be matched. + +You can also search for files by inode number. This can occasionally +be useful in diagnosing problems with filesystems for example, because +@code{fsck} tends to print inode numbers. Inode numbers also +occasionally turn up in log messages for some types of software, and +are used to support the @code{ftok()} library function. + +You can learn a file's inode number and the number of links to it by +running @samp{ls -li} or @samp{find -ls}. + +You can search for hard links to inode number NUM by using @samp{-inum +NUM}. If there are any filesystem mount points below the directory +where you are starting the search, use the @samp{-xdev} option unless +you are also using the @samp{-L} option. Using @samp{-xdev} this +saves needless searching, since hard links to a file must be on the +same filesystem. @xref{Filesystems}. + +@deffn Test -samefile NAME +File is a hard link to the same inode as @var{name}. If the @samp{-L} +option is in effect, symbolic links to the same file as @var{name} points to +are also matched. +@end deffn + +@deffn Test -inum n +File has inode number @var{n}. The @samp{+} and @samp{-} qualifiers +also work, though these are rarely useful. Much of the time it is +easier to use @samp{-samefile} rather than this option. +@end deffn + +You can also search for files that have a certain number of links, +with @samp{-links}. Directories normally have at least two hard +links; their @file{.} entry is the second one. If they have +subdirectories, each of those also has a hard link called @file{..} to +its parent directory. The @file{.} and @file{..} directory entries +are not normally searched unless they are mentioned on the @code{find} +command line. + +@deffn Test -links n +File has @var{n} hard links. +@end deffn + +@deffn Test -links +n +File has more than @var{n} hard links. +@end deffn + +@deffn Test -links -n +File has fewer than @var{n} hard links. +@end deffn + +@node Time +@section Time + +Each file has three time stamps, which record the last time that +certain operations were performed on the file: + +@enumerate +@item +access (read the file's contents) +@item +change the status (modify the file or its attributes) +@item +modify (change the file's contents) +@end enumerate + +Some systems also provide a timestamp that indicates when a file was +@emph{created}. For example, the UFS2 filesystem under NetBSD-3.1 +records the @emph{birth time} of each file. This information is also +available under other versions of BSD and some versions of Cygwin. +However, even on systems which support file birth time, files may +exist for which this information was not recorded (for example, UFS1 +file systems simply do not contain this information). + +You can search for files whose time stamps are within a certain age +range, or compare them to other time stamps. + +@menu +* Age Ranges:: +* Comparing Timestamps:: +@end menu + +@node Age Ranges +@subsection Age Ranges + +These tests are mainly useful with ranges (@samp{+@var{n}} and +@samp{-@var{n}}). + +@deffn Test -atime n +@deffnx Test -ctime n +@deffnx Test -mtime n +True if the file was last accessed (or its status changed, or it was +modified) @var{n}*24 hours ago. The number of 24-hour periods since +the file's timestamp is always rounded down; therefore 0 means ``less +than 24 hours ago'', 1 means ``between 24 and 48 hours ago'', and so +forth. Fractional values are supported but this only really makes +sense for the case where ranges (@samp{+@var{n}} and @samp{-@var{n}}) +are used. +@end deffn + +@deffn Test -amin n +@deffnx Test -cmin n +@deffnx Test -mmin n +True if the file was last accessed (or its status changed, or it was +modified) @var{n} minutes ago. These tests provide finer granularity +of measurement than @samp{-atime} et al., but rounding is done in a +similar way (again, fractions are supported). For example, to list +files in @file{/u/bill} that were last read from 2 to 6 minutes ago: + +@example +find /u/bill -amin +2 -amin -6 +@end example +@end deffn + +@deffn Option -daystart +Measure times from the beginning of today rather than from 24 hours +ago. So, to list the regular files in your home directory that were +modified yesterday, do + +@example +find ~/ -daystart -type f -mtime 1 +@end example + +The @samp{-daystart} option is unlike most other options in that it +has an effect on the way that other tests are performed. The affected +tests are @samp{-amin}, @samp{-cmin}, @samp{-mmin}, @samp{-atime}, +@samp{-ctime} and @samp{-mtime}. The @samp{-daystart} option only +affects the behaviour of any tests which appear after it on the +command line. +@end deffn + +@node Comparing Timestamps +@subsection Comparing Timestamps + +@deffn Test -newerXY reference +Succeeds if timestamp @samp{X} of the file being considered is newer +than timestamp @samp{Y} of the file @file{reference}. The letters +@samp{X} and @samp{Y} can be any of the following letters: + +@table @samp +@item a +Last-access time of @file{reference} +@item B +Birth time of @file{reference} (when this is not known, the test cannot succeed) +@item c +Last-change time of @file{reference} +@item m +Last-modification time of @file{reference} +@item t +The @file{reference} argument is interpreted as a literal time, rather +than the name of a file. @xref{Date input formats}, for a description +of how the timestamp is understood. Tests of the form @samp{-newerXt} +are valid but tests of the form @samp{-newertY} are not. +@end table + +For example the test @code{-newerac /tmp/foo} succeeds for all files +which have been accessed more recently than @file{/tmp/foo} was +changed. Here @samp{X} is @samp{a} and @samp{Y} is @samp{c}. + +Not all files have a known birth time. If @samp{Y} is @samp{b} and +the birth time of @file{reference} is not available, @code{find} exits +with an explanatory error message. If @samp{X} is @samp{b} and we do +not know the birth time the file currently being considered, the test +simply fails (that is, it behaves like @code{-false} does). + +Some operating systems (for example, most implementations of Unix) do +not support file birth times. Some others, for example NetBSD-3.1, +do. Even on operating systems which support file birth times, the +information may not be available for specific files. For example, +under NetBSD, file birth times are supported on UFS2 file systems, but +not UFS1 file systems. + +@end deffn + + + +There are two ways to list files in @file{/usr} modified after +February 1 of the current year. One uses @samp{-newermt}: + +@example +find /usr -newermt "Feb 1" +@end example + +The other way of doing this works on the versions of find before 4.3.3: + +@c Idea from Rick Sladkey. +@example +touch -t 02010000 /tmp/stamp$$ +find /usr -newer /tmp/stamp$$ +rm -f /tmp/stamp$$ +@end example + +@deffn Test -anewer file +@deffnx Test -cnewer file +@deffnx Test -newer file +True if the file was last accessed (or its status changed, or it was +modified) more recently than @var{file} was modified. These tests are +affected by @samp{-follow} only if @samp{-follow} comes before them on +the command line. @xref{Symbolic Links}, for more information on +@samp{-follow}. As an example, to list any files modified since +@file{/bin/sh} was last modified: + +@example +find . -newer /bin/sh +@end example +@end deffn + +@deffn Test -used n +True if the file was last accessed @var{n} days after its status was +last changed. Useful for finding files that are not being used, and +could perhaps be archived or removed to save disk space. +@end deffn + +@node Size +@section Size + +@deffn Test -size n@r{[}bckwMG@r{]} +True if the file uses @var{n} units of space, rounding up. The units +are 512-byte blocks by default, but they can be changed by adding a +one-character suffix to @var{n}: + +@table @code +@item b +512-byte blocks (never 1024) +@item c +bytes +@item k +kilobytes (1024 bytes) +@item w +2-byte words +@item M +Megabytes (units of 1048576 bytes) +@item G +Gigabytes (units of 1073741824 bytes) +@end table + +The `b' suffix always considers blocks to be 512 bytes. This is not +affected by the setting (or non-setting) of the @code{POSIXLY_CORRECT} +environment variable. This behaviour is different from the behaviour of +the @samp{-ls} action). If you want to use 1024-byte units, use the +`k' suffix instead. + +The number can be prefixed with a `+' or a `-'. A plus sign indicates +that the test should succeed if the file uses at least @var{n} units +of storage (a common use of this test) and a minus sign +indicates that the test should succeed if the file uses less than +@var{n} units of storage. There is no `=' prefix, because that's the +default anyway. + +The size does not count indirect blocks, but it does count blocks in +sparse files that are not actually allocated. In other words, it's +consistent with the result you get for @samp{ls -l} or @samp{wc -c}. +This handling of sparse files differs from the output of the @samp{%k} +and @samp{%b} format specifiers for the @samp{-printf} predicate. + +@end deffn + +@deffn Test -empty +True if the file is empty and is either a regular file or a directory. +This might help determine good candidates for deletion. This test is +useful with @samp{-depth} (@pxref{Directories}) and @samp{-delete} +(@pxref{Single File}). +@end deffn + +@node Type +@section Type + +@deffn Test -type c +True if the file is of type @var{c}: + +@table @code +@item b +block (buffered) special +@item c +character (unbuffered) special +@item d +directory +@item p +named pipe (FIFO) +@item f +regular file +@item l +symbolic link; if @samp{-L} is in effect, this is true only for broken +symbolic links. If you want to search for symbolic links when +@samp{-L} is in effect, use @samp{-xtype} instead of @samp{-type}. +@item s +socket +@item D +door (Solaris) +@end table +@end deffn + +@deffn Test -xtype c +This test behaves the same as @samp{-type} unless the file is a +symbolic link. If the file is a symbolic link, the result is as +follows (in the table below, @samp{X} should be understood to +represent any letter except @samp{l}): + +@table @samp +@item @samp{-P -xtype l} +True if the symbolic link is broken +@item @samp{-P -xtype X} +True if the (ultimate) target file is of type @samp{X}. +@item @samp{-L -xtype l} +Always true +@item @samp{-L -xtype X} +False unless the symbolic link is broken +@end table + +In other words, for symbolic links, @samp{-xtype} checks the type of +the file that @samp{-type} does not check. + +The @samp{-H} option also affects the behaviour of @samp{-xtype}. +When @samp{-H} is in effect, @samp{-xtype} behaves as if @samp{-L} had +been specified when examining files listed on the command line, and as +if @samp{-P} had been specified otherwise. If neither @samp{-H} nor +@samp{-L} was specified, @samp{-xtype} behaves as if @samp{-P} had +been specified. + +@xref{Symbolic Links}, for more information on @samp{-follow} and +@samp{-L}. +@end deffn + +@node Owner +@section Owner + +@deffn Test -user uname +@deffnx Test -group gname +True if the file is owned by user @var{uname} (belongs to group +@var{gname}). A numeric ID is allowed. +@end deffn + +@deffn Test -uid n +@deffnx Test -gid n +True if the file's numeric user ID (group ID) is @var{n}. These tests +support ranges (@samp{+@var{n}} and @samp{-@var{n}}), unlike +@samp{-user} and @samp{-group}. +@end deffn + +@deffn Test -nouser +@deffnx Test -nogroup +True if no user corresponds to the file's numeric user ID (no group +corresponds to the numeric group ID). These cases usually mean that +the files belonged to users who have since been removed from the +system. You probably should change the ownership of such files to an +existing user or group, using the @code{chown} or @code{chgrp} +program. +@end deffn + +@node Mode Bits +@section File Mode Bits + +@xref{File Permissions}, for information on how file mode bits are +structured and how to specify them. + +Four tests determine what users can do with files. These are +@samp{-readable}, @samp{-writable}, @samp{-executable} and +@samp{-perm}. The first three tests ask the operating system if the +current user can perform the relevant operation on a file, while +@samp{-perm} just examines the file's mode. The file mode may give +a misleading impression of what the user can actually do, because the +file may have an access control list, or exist on a read-only +filesystem, for example. Of these four tests though, only +@samp{-perm} is specified by the POSIX standard. + +The @samp{-readable}, @samp{-writable} and @samp{-executable} tests +are implemented via the @code{access} system call. This is +implemented within the operating system itself. If the file being +considered is on an NFS filesystem, the remote system may allow or +forbid read or write operations for reasons of which the NFS client +cannot take account. This includes user-ID mapping, either in the +general sense or the more restricted sense in which remote superusers +are treated by the NFS server as if they are the local user +@samp{nobody} on the NFS server. + +None of the tests in this section should be used to verify that a user +is authorised to perform any operation (on the file being tested or +any other file) because of the possibility of a race condition. That +is, the situation may change between the test and an action being +taken on the basis of the result of that test. + + +@deffn Test -readable +True if the file can be read by the invoking user. +@end deffn + +@deffn Test -writable +True if the file can be written by the invoking user. This is an +in-principle check, and other things may prevent a successful write +operation; for example, the filesystem might be full. +@end deffn + +@deffn Test -executable +True if the file can be executed/searched by the invoking user. +@end deffn + +@deffn Test -perm pmode + +True if the file's mode bits match @var{pmode}, which can be +either a symbolic or numeric @var{mode} (@pxref{File Permissions}) +optionally prefixed by @samp{-} or @samp{/}. + +A @var{pmode} that starts with neither @samp{-} nor @samp{/} matches +if @var{mode} exactly matches the file mode bits. +(To avoid confusion with an obsolete GNU extension, @var{mode} +must not start with a @samp{+} immediately followed by an octal digit.) + +A @var{pmode} that starts with @samp{-} matches if +@emph{all} the file mode bits set in @var{mode} are set for the file; +bits not set in @var{mode} are ignored. + +A @var{pmode} that starts with @samp{/} matches if +@emph{any} of the file mode bits set in @var{mode} are set for the file; +bits not set in @var{mode} are ignored. +This is a GNU extension. + +If you don't use the @samp{/} or @samp{-} form with a symbolic mode +string, you may have to specify a rather complex mode string. For +example @samp{-perm g=w} will only match files that have mode 0020 +(that is, ones for which group write permission is the only file mode bit +set). It is more likely that you will want to use the @samp{/} or +@samp{-} forms, for example @samp{-perm -g=w}, which matches any file +with group write permission. + + +@table @samp +@item -perm 664 +Match files that have read and write permission for their owner, +and group, but that the rest of the world can read but not write to. +Do not match files that meet these criteria but have other file mode +bits set (for example if someone can execute/search the file). + +@item -perm -664 +Match files that have read and write permission for their owner, +and group, but that the rest of the world can read but not write to, +without regard to the presence of any extra file mode bits (for +example the executable bit). This matches a file with mode +0777, for example. + +@item -perm /222 +Match files that are writable by somebody (their owner, or +their group, or anybody else). + +@item -perm /022 +Match files that are writable by either their owner or their +group. The files don't have to be writable by both the owner and +group to be matched; either will do. + +@item -perm /g+w,o+w +As above. + +@item -perm /g=w,o=w +As above. + +@item -perm -022 +Match files that are writable by both their owner and their +group. + +@item -perm -444 -perm /222 ! -perm /111 +Match files that are readable for everybody, have at least one +write bit set (i.e., somebody can write to them), but that cannot be +executed/searched by anybody. Note that in some shells the @samp{!} must be +escaped;. + +@item -perm -a+r -perm /a+w ! -perm /a+x +As above. + + +@item -perm -g+w,o+w +As above. +@end table + +@quotation Warning +If you specify @samp{-perm /000} or @samp{-perm /mode} where the +symbolic mode @samp{mode} has no bits set, the test matches all files. +Versions of GNU @code{find} prior to 4.3.3 matched no files in this +situation. +@end quotation + +@end deffn + +@deffn Test -context pattern +True if file's SELinux context matches the pattern @var{pattern}. +The pattern uses shell glob matching. + +This predicate is supported only on @code{find} versions compiled with +SELinux support and only when SELinux is enabled. +@end deffn + +@node Contents +@section Contents + +To search for files based on their contents, you can use the +@code{grep} program. For example, to find out which C source files in +the current directory contain the string @samp{thing}, you can do: + +@example +grep -l thing *.[ch] +@end example + +If you also want to search for the string in files in subdirectories, +you can combine @code{grep} with @code{find} and @code{xargs}, like +this: + +@example +find . -name '*.[ch]' | xargs grep -l thing +@end example + +The @samp{-l} option causes @code{grep} to print only the names of +files that contain the string, rather than the lines that contain it. +The string argument (@samp{thing}) is actually a regular expression, +so it can contain metacharacters. This method can be refined a little +by using the @samp{-r} option to make @code{xargs} not run @code{grep} +if @code{find} produces no output, and using the @code{find} action +@samp{-print0} and the @code{xargs} option @samp{-0} to avoid +misinterpreting files whose names contain spaces: + +@example +find . -name '*.[ch]' -print0 | xargs -r -0 grep -l thing +@end example + +For a fuller treatment of finding files whose contents match a +pattern, see the manual page for @code{grep}. + +@node Directories +@section Directories + +Here is how to control which directories @code{find} searches, and how +it searches them. These two options allow you to process a horizontal +slice of a directory tree. + +@deffn Option -maxdepth levels +Descend at most @var{levels} (a non-negative integer) levels of +directories below the command line arguments. @samp{-maxdepth 0} +means only apply the tests and actions to the command line arguments. +@end deffn + +@deffn Option -mindepth levels +Do not apply any tests or actions at levels less than @var{levels} (a +non-negative integer). @samp{-mindepth 1} means process all files +except the command line arguments. +@end deffn + +@deffn Option -depth +Process each directory's contents before the directory itself. Doing +this is a good idea when producing lists of files to archive with +@code{cpio} or @code{tar}. If a directory does not have write +permission for its owner, its contents can still be restored from the +archive since the directory's permissions are restored after its +contents. +@end deffn + +@deffn Option -d +This is a deprecated synonym for @samp{-depth}, for compatibility with +Mac OS X, FreeBSD and OpenBSD. The @samp{-depth} option is a POSIX +feature, so it is better to use that. +@end deffn + +@deffn Action -prune +If the file is a directory, do not descend into it. The result is +true. For example, to skip the directory @file{src/emacs} and all +files and directories under it, and print the names of the other files +found: + +@example +find . -wholename './src/emacs' -prune -o -print +@end example + +The above command will not print @file{./src/emacs} among its list of +results. This however is not due to the effect of the @samp{-prune} +action (which only prevents further descent, it doesn't make sure we +ignore that item). Instead, this effect is due to the use of +@samp{-o}. Since the left hand side of the ``or'' condition has +succeeded for @file{./src/emacs}, it is not necessary to evaluate the +right-hand-side (@samp{-print}) at all for this particular file. If +you wanted to print that directory name you could use either an extra +@samp{-print} action: + +@example +find . -wholename './src/emacs' -prune -print -o -print +@end example + +or use the comma operator: + +@example +find . -wholename './src/emacs' -prune , -print +@end example + +If the @samp{-depth} option is in effect, the subdirectories will have +already been visited in any case. Hence @samp{-prune} has no effect +in this case. + +Because @samp{-delete} implies @samp{-depth}, using @samp{-prune} in +combination with @samp{-delete} may well result in the deletion of +more files than you intended. +@end deffn + + +@deffn Action -quit +Exit immediately (with return value zero if no errors have occurred). +This is different to @samp{-prune} because @samp{-prune} only applies +to the contents of pruned directories, while @samp{-quit} simply makes +@code{find} stop immediately. No child processes will be left +running, but no more files specified on the command line will be +processed. For example, @code{find /tmp/foo /tmp/bar -print -quit} +will print only @samp{/tmp/foo}. Any command lines which have been +built by @samp{-exec ... \+} or @samp{-execdir ... \+} are invoked +before the program is exited. +@end deffn + +@deffn Option -noleaf +Do not optimize by assuming that directories contain 2 fewer +subdirectories than their hard link count. This option is needed when +searching filesystems that do not follow the Unix directory-link +convention, such as CD-ROM or MS-DOS filesystems or AFS volume mount +points. Each directory on a normal Unix filesystem has at least 2 +hard links: its name and its @file{.} entry. Additionally, its +subdirectories (if any) each have a @file{..} entry linked to that +directory. When @code{find} is examining a directory, after it has +statted 2 fewer subdirectories than the directory's link count, it +knows that the rest of the entries in the directory are +non-directories (@dfn{leaf} files in the directory tree). If only the +files' names need to be examined, there is no need to stat them; this +gives a significant increase in search speed. +@end deffn + +@deffn Option -ignore_readdir_race +If a file disappears after its name has been read from a directory but +before @code{find} gets around to examining the file with @code{stat}, +don't issue an error message. If you don't specify this option, an +error message will be issued. This option can be useful in system +scripts (cron scripts, for example) that examine areas of the +filesystem that change frequently (mail queues, temporary directories, +and so forth), because this scenario is common for those sorts of +directories. Completely silencing error messages from @code{find} is +undesirable, so this option neatly solves the problem. There is no +way to search one part of the filesystem with this option on and part +of it with this option off, though. When this option is turned on and +find discovers that one of the start-point files specified on the +command line does not exist, no error message will be issued. + +@end deffn + +@deffn Option -noignore_readdir_race +This option reverses the effect of the @samp{-ignore_readdir_race} +option. +@end deffn + + +@node Filesystems +@section Filesystems + +A @dfn{filesystem} is a section of a disk, either on the local host or +mounted from a remote host over a network. Searching network +filesystems can be slow, so it is common to make @code{find} avoid +them. + +There are two ways to avoid searching certain filesystems. One way is +to tell @code{find} to only search one filesystem: + +@deffn Option -xdev +@deffnx Option -mount +Don't descend directories on other filesystems. These options are +synonyms. +@end deffn + +The other way is to check the type of filesystem each file is on, and +not descend directories that are on undesirable filesystem types: + +@deffn Test -fstype type +True if the file is on a filesystem of type @var{type}. The valid +filesystem types vary among different versions of Unix; an incomplete +list of filesystem types that are accepted on some version of Unix or +another is: +@example +ext2 ext3 proc sysfs ufs 4.2 4.3 nfs tmp mfs S51K S52K +@end example +You can use @samp{-printf} with the @samp{%F} directive to see the +types of your filesystems. The @samp{%D} directive shows the device +number. @xref{Print File Information}. @samp{-fstype} is usually +used with @samp{-prune} to avoid searching remote filesystems +(@pxref{Directories}). +@end deffn + +@node Combining Primaries With Operators +@section Combining Primaries With Operators + +Operators build a complex expression from tests and actions. +The operators are, in order of decreasing precedence: + +@table @code +@item @asis{( @var{expr} )} +@findex () +Force precedence. True if @var{expr} is true. + +@item @asis{! @var{expr}} +@itemx @asis{-not @var{expr}} +@findex ! +@findex -not +True if @var{expr} is false. In some shells, it is necessary to +protect the @samp{!} from shell interpretation by quoting it. + +@item @asis{@var{expr1 expr2}} +@itemx @asis{@var{expr1} -a @var{expr2}} +@itemx @asis{@var{expr1} -and @var{expr2}} +@findex -and +@findex -a +And; @var{expr2} is not evaluated if @var{expr1} is false. + +@item @asis{@var{expr1} -o @var{expr2}} +@itemx @asis{@var{expr1} -or @var{expr2}} +@findex -or +@findex -o +Or; @var{expr2} is not evaluated if @var{expr1} is true. + +@item @asis{@var{expr1} , @var{expr2}} +@findex , +List; both @var{expr1} and @var{expr2} are always evaluated. True if +@var{expr2} is true. The value of @var{expr1} is discarded. This +operator lets you do multiple independent operations on one traversal, +without depending on whether other operations succeeded. The two +operations @var{expr1} and @var{expr2} are not always fully +independent, since @var{expr1} might have side effects like touching +or deleting files, or it might use @samp{-prune} which would also +affect @var{expr2}. +@end table + +@code{find} searches the directory tree rooted at each file name by +evaluating the expression from left to right, according to the rules +of precedence, until the outcome is known (the left hand side is false +for @samp{-and}, true for @samp{-or}), at which point @code{find} +moves on to the next file name. + +There are two other tests that can be useful in complex expressions: + +@deffn Test -true +Always true. +@end deffn + +@deffn Test -false +Always false. +@end deffn + +@node Actions +@chapter Actions + +There are several ways you can print information about the files that +match the criteria you gave in the @code{find} expression. You can +print the information either to the standard output or to a file that +you name. You can also execute commands that have the file names as +arguments. You can use those commands as further filters to select +files. + +@menu +* Print File Name:: +* Print File Information:: +* Run Commands:: +* Delete Files:: +* Adding Tests:: +@end menu + +@node Print File Name +@section Print File Name + +@deffn Action -print +True; print the entire file name on the standard output, followed by a +newline. If there is the faintest possibility that one of the files +for which you are searching might contain a newline, you should use +@samp{-print0} instead. +@end deffn + +@deffn Action -fprint file +True; print the entire file name into file @var{file}, followed by a +newline. If @var{file} does not exist when @code{find} is run, it is +created; if it does exist, it is truncated to 0 bytes. The named +output file is always created, even if no output is sent to it. The +file names @file{/dev/stdout} and @file{/dev/stderr} are handled +specially; they refer to the standard output and standard error +output, respectively. + +If there is the faintest possibility that one of the files for which +you are searching might contain a newline, you should use +@samp{-fprint0} instead. +@end deffn + + +@c @deffn Option -show-control-chars how +@c This option affects how some of @code{find}'s actions treat +@c unprintable characters in file names. If @samp{how} is +@c @samp{literal}, any subsequent actions (i.e., actions further on in the +@c command line) print file names as-is. +@c +@c If this option is not specified, it currently defaults to @samp{safe}. +@c If @samp{how} is @samp{safe}, C-like backslash escapes are used to +@c indicate the non-printable characters for @samp{-ls} and @samp{-fls}. +@c On the other hand, @samp{-print}, @samp{-fprint}, @samp{-fprintf} and +@c @code{-printf} all quote unprintable characters if the data is going +@c to a tty, and otherwise the data is emitted literally. +@c +@c @table @code +@c @item -ls +@c Escaped if @samp{how} is @samp{safe} +@c @item -fls +@c Escaped if @samp{how} is @samp{safe} +@c @item -print +@c Always quoted if stdout is a tty, +@c @samp{-show-control-chars} is ignored +@c @item -print0 +@c Always literal, never escaped +@c @item -fprint +@c Always quoted if the destination is a tty; +@c @samp{-show-control-chars} is ignored +@c @item -fprint0 +@c Always literal, never escaped +@c @item -fprintf +@c If the destination is a tty, the @samp{%f}, +@c @samp{%F}, @samp{%h}, @samp{%l}, @samp{%p}, +@c and @samp{%P} directives produce quoted +@c strings if stdout is a tty and are treated +@c literally otherwise. +@c @item -printf +@c As for @code{-fprintf}. +@c @end table +@c @end deffn + + +@node Print File Information +@section Print File Information + +@deffn Action -ls +True; list the current file in @samp{ls -dils} format on the standard +output. The output looks like this: + +@smallexample +204744 17 -rw-r--r-- 1 djm staff 17337 Nov 2 1992 ./lwall-quotes +@end smallexample + +The fields are: + +@enumerate +@item +The inode number of the file. @xref{Hard Links}, for how to find +files based on their inode number. + +@item +the number of blocks in the file. The block counts are of 1K blocks, +unless the environment variable @code{POSIXLY_CORRECT} is set, in +which case 512-byte blocks are used. @xref{Size}, for how to find +files based on their size. + +@item +The file's type and file mode bits. The type is shown as a dash for a +regular file; for other file types, a letter like for @samp{-type} is +used (@pxref{Type}). The file mode bits are read, write, and execute/search for +the file's owner, its group, and other users, respectively; a dash +means the permission is not granted. @xref{File Permissions}, for +more details about file permissions. @xref{Mode Bits}, for how to +find files based on their file mode bits. + +@item +The number of hard links to the file. + +@item +The user who owns the file. + +@item +The file's group. + +@item +The file's size in bytes. + +@item +The date the file was last modified. + +@item +The file's name. @samp{-ls} quotes non-printable characters in the +file names using C-like backslash escapes. This may change soon, as +the treatment of unprintable characters is harmonised for @samp{-ls}, +@samp{-fls}, @samp{-print}, @samp{-fprint}, @samp{-printf} and +@samp{-fprintf}. +@end enumerate +@end deffn + +@deffn Action -fls file +True; like @samp{-ls} but write to @var{file} like @samp{-fprint} +(@pxref{Print File Name}). The named output file is always created, +even if no output is sent to it. +@end deffn + +@deffn Action -printf format +True; print @var{format} on the standard output, interpreting @samp{\} +escapes and @samp{%} directives (more details in the following +sections). + +Field widths and precisions can be specified as with the @code{printf} C +function. Format flags (like @samp{#} for example) may not work as you +expect because many of the fields, even numeric ones, are printed with +%s. Numeric flags which are affected in this way include @samp{G}, +@samp{U}, @samp{b}, @samp{D}, @samp{k} and @samp{n}. This difference in +behaviour means though that the format flag @samp{-} will work; it +forces left-alignment of the field. Unlike @samp{-print}, +@samp{-printf} does not add a newline at the end of the string. If you +want a newline at the end of the string, add a @samp{\n}. + +As an example, an approximate equivalent of @samp{-ls} with +null-terminated filenames can be achieved with this @code{-printf} +format: + +@example +find -printf "%i %4k %M %3n %-8u %-8g %8s %T+ %p\n->%l\0" | cat +@end example + +A practical reason for doing this would be to get literal filenames in +the output, instead of @samp{-ls}'s backslash-escaped names. (Using +@code{cat} here prevents this happening for the @samp{%p} format +specifier; @pxref{Unusual Characters in File Names}). This format also +outputs a uniform timestamp format. + +As for symlinks, the format above outputs the symlink target on a second +line, following @samp{\n->}. There is nothing following the arrow for +non-symlinks. Another approach, for complete consistency, would be to +@code{-fprintf} the symlinks into a separate file, so they too can be +null-terminated. +@end deffn + +@deffn Action -fprintf file format +True; like @samp{-printf} but write to @var{file} like @samp{-fprint} +(@pxref{Print File Name}). The output file is always created, even if +no output is ever sent to it. +@end deffn + +@menu +* Escapes:: +* Format Directives:: +* Time Formats:: +* Formatting Flags:: +@end menu + +@node Escapes +@subsection Escapes + +The escapes that @samp{-printf} and @samp{-fprintf} recognise are: + +@table @code +@item \a +Alarm bell. +@item \b +Backspace. +@item \c +Stop printing from this format immediately and flush the output. +@item \f +Form feed. +@item \n +Newline. +@item \r +Carriage return. +@item \t +Horizontal tab. +@item \v +Vertical tab. +@item \\ +A literal backslash (@samp{\}). +@item \0 +ASCII NUL. +@item \NNN +The character whose ASCII code is NNN (octal). +@end table + +A @samp{\} character followed by any other character is treated as an +ordinary character, so they both are printed, and a warning message is +printed to the standard error output (because it was probably a typo). + +@node Format Directives +@subsection Format Directives + +@samp{-printf} and @samp{-fprintf} support the following format +directives to print information about the file being processed. The C +@code{printf} function, field width and precision specifiers are +supported, as applied to string (%s) types. That is, you can specify +"minimum field width"."maximum field width" for each directive. +Format flags (like @samp{#} for example) may not work as you expect +because many of the fields, even numeric ones, are printed with %s. +The format flag @samp{-} does work; it forces left-alignment of the +field. + +@samp{%%} is a literal percent sign. @xref{Reserved and Unknown +Directives}, for a description of how format directives not mentioned +below are handled. + +A @samp{%} at the end of the format argument causes undefined +behaviour since there is no following character. In some locales, it +may hide your door keys, while in others it may remove the final page +from the novel you are reading. + +@menu +* Name Directives:: +* Ownership Directives:: +* Size Directives:: +* Location Directives:: +* Time Directives:: +* Other Directives:: +* Reserved and Unknown Directives:: +@end menu + +@node Name Directives +@subsubsection Name Directives + +@table @code +@item %p +@c supports %-X.Yp +File's name (not the absolute path name, but the name of the file as +it was encountered by @code{find} - that is, as a relative path from +one of the starting points). +@item %f +File's name with any leading directories removed (only the last +element). +@c supports %-X.Yf +@item %h +Leading directories of file's name (all but the last element and the +slash before it). If the file's name contains no slashes (for example +because it was named on the command line and is in the current working +directory), then ``%h'' expands to ``.''. This prevents ``%h/%f'' +expanding to ``/foo'', which would be surprising and probably not +desirable. +@c supports %-X.Yh +@item %P +File's name with the name of the command line argument under which +it was found removed from the beginning. +@c supports %-X.YP +@item %H +Command line argument under which file was found. +@c supports %-X.YH +@end table + +@node Ownership Directives +@subsubsection Ownership Directives + +@table @code +@item %g +@c supports %-X.Yg +File's group name, or numeric group ID if the group has no name. +@item %G +@c supports %-X.Yg +@c TODO: Needs to support # flag and 0 flag +File's numeric group ID. +@item %u +@c supports %-X.Yu +File's user name, or numeric user ID if the user has no name. +@item %U +@c supports %-X.Yu +@c TODO: Needs to support # flag +File's numeric user ID. +@item %m +@c full support, including # and 0. +File's mode bits (in octal). If you always want to have a leading +zero on the number, use the '#' format flag, for example '%#m'. + +The file mode bit numbers used are the traditional Unix +numbers, which will be as expected on most systems, but if your +system's file mode bit layout differs from the traditional Unix +semantics, you will see a difference between the mode as printed by +@samp{%m} and the mode as it appears in @code{struct stat}. + +@item %M +File's type and mode bits (in symbolic form, as for @code{ls}). This +directive is supported in findutils 4.2.5 and later. +@end table + +@node Size Directives +@subsubsection Size Directives + +@table @code +@item %k +The amount of disk space used for this file in 1K blocks. Since disk +space is allocated in multiples of the filesystem block size this is +usually greater than %s/1024, but it can also be smaller if the file +is a sparse file (that is, it has ``holes''). +@item %b +The amount of disk space used for this file in 512-byte blocks. Since +disk space is allocated in multiples of the filesystem block size this +is usually greater than %s/512, but it can also be smaller if the +file is a sparse file (that is, it has ``holes''). +@item %s +File's size in bytes. +@item %S +File's sparseness. This is calculated as @code{(BLOCKSIZE*st_blocks / +st_size)}. The exact value you will get for an ordinary file of a +certain length is system-dependent. However, normally sparse files +will have values less than 1.0, and files which use indirect blocks +and have few holes may have a value which is greater than 1.0. The +value used for BLOCKSIZE is system-dependent, but is usually 512 +bytes. If the file size is zero, the value printed is undefined. On +systems which lack support for st_blocks, a file's sparseness is +assumed to be 1.0. +@end table + +@node Location Directives +@subsubsection Location Directives + +@table @code +@item %d +File's depth in the directory tree (depth below a file named on the +command line, not depth below the root directory). Files named on the +command line have a depth of 0. Subdirectories immediately below them +have a depth of 1, and so on. +@item %D +The device number on which the file exists (the @code{st_dev} field of +@code{struct stat}), in decimal. +@item %F +Type of the filesystem the file is on; this value can be used for +@samp{-fstype} (@pxref{Directories}). +@item %l +Object of symbolic link (empty string if file is not a symbolic link). +@item %i +File's inode number (in decimal). +@item %n +Number of hard links to file. +@item %y +Type of the file as used with @samp{-type}. If the file is a symbolic +link, @samp{l} will be printed. +@item %Y +Type of the file as used with @samp{-type}. If the file is a symbolic +link, it is dereferenced. If the file is a broken symbolic link, +@samp{N} is printed. + +@end table + +@node Time Directives +@subsubsection Time Directives + +Some of these directives use the C @code{ctime} function. Its output +depends on the current locale, but it typically looks like + +@example +Wed Nov 2 00:42:36 1994 +@end example + +@table @code +@item %a +File's last access time in the format returned by the C @code{ctime} +function. +@item %A@var{k} +File's last access time in the format specified by @var{k} +(@pxref{Time Formats}). +@item %c +File's last status change time in the format returned by the C +@code{ctime} function. +@item %C@var{k} +File's last status change time in the format specified by @var{k} +(@pxref{Time Formats}). +@item %t +File's last modification time in the format returned by the C +@code{ctime} function. +@item %T@var{k} +File's last modification time in the format specified by @var{k} +(@pxref{Time Formats}). +@end table + +@node Other Directives +@subsubsection Other Directives + +@table @code +@item %Z +File's SELinux context, or empty string if the file has no SELinux context. +@end table + +@node Reserved and Unknown Directives +@subsubsection Reserved and Unknown Directives + +The @samp{%(}, @samp{%@{} and @samp{%[} format directives, with or +without field with and precision specifications, are reserved for +future use. Don't use them and don't rely on current experiment to +predict future behaviour. To print @samp{(}, simply use @samp{(} +rather than @samp{%(}. Likewise for @samp{@{} and @samp{[}. + +Similarly, a @samp{%} character followed by any other unrecognised +character (i.e., not a known directive or @code{printf} field width +and precision specifier), is discarded (but the unrecognised character +is printed), and a warning message is printed to the standard error +output (because it was probably a typo). Don't rely on this +behaviour, because other directives may be added in the future. + + +@node Time Formats +@subsection Time Formats + +Below are the formats for the directives @samp{%A}, @samp{%C}, and +@samp{%T}, which print the file's timestamps. Some of these formats +might not be available on all systems, due to differences in the C +@code{strftime} function between systems. + +@menu +* Time Components:: +* Date Components:: +* Combined Time Formats:: +@end menu + +@node Time Components +@subsubsection Time Components + +The following format directives print single components of the time. + +@table @code +@item H +hour (00..23) +@item I +hour (01..12) +@item k +hour ( 0..23) +@item l +hour ( 1..12) +@item p +locale's AM or PM +@item Z +time zone (e.g., EDT), or nothing if no time zone is determinable +@item M +minute (00..59) +@item S +second (00..61). There is a fractional part. +@item @@ +seconds since Jan. 1, 1970, 00:00 GMT, with fractional part. +@end table + +The fractional part of the seconds field is of indeterminate length +and precision. That is, the length of the fractional part of the +seconds field will in general vary between findutils releases and +between systems. This means that it is unwise to assume that field +has any specific length. The length of this field is not usually a +guide to the precision of timestamps in the underlying file system. + + + +@node Date Components +@subsubsection Date Components + +The following format directives print single components of the date. + +@table @code +@item a +locale's abbreviated weekday name (Sun..Sat) +@item A +locale's full weekday name, variable length (Sunday..Saturday) +@item b +@itemx h +locale's abbreviated month name (Jan..Dec) +@item B +locale's full month name, variable length (January..December) +@item m +month (01..12) +@item d +day of month (01..31) +@item w +day of week (0..6) +@item j +day of year (001..366) +@item U +week number of year with Sunday as first day of week (00..53) +@item W +week number of year with Monday as first day of week (00..53) +@item Y +year (1970@dots{}) +@item y +last two digits of year (00..99) +@end table + +@node Combined Time Formats +@subsubsection Combined Time Formats + +The following format directives print combinations of time and date +components. + +@table @code +@item r +time, 12-hour (hh:mm:ss [AP]M) +@item T +time, 24-hour (hh:mm:ss) +@item X +locale's time representation (H:M:S) +@item c +locale's date and time in ctime format (Sat Nov 04 12:02:33 EST +1989). This format does not include any fractional part in the +seconds field. +@item D +date (mm/dd/yy) +@item x +locale's date representation (mm/dd/yy) +@item + +Date and time, separated by '+', for example +`2004-04-28+22:22:05.0000000000'. +The time is given in the current timezone (which may be affected by +setting the TZ environment variable). This is a GNU extension. The +seconds field includes a fractional part. +@end table + +@node Formatting Flags +@subsection Formatting Flags + +The @samp{%m} and @samp{%d} directives support the @samp{#}, @samp{0} +and @samp{+} flags, but the other directives do not, even if they +print numbers. Numeric directives that do not support these flags +include + +@samp{G}, +@samp{U}, +@samp{b}, +@samp{D}, +@samp{k} and +@samp{n}. + +All fields support the format flag @samp{-}, which makes fields +left-aligned. That is, if the field width is greater than the actual +contents of the field, the requisite number of spaces are printed +after the field content instead of before it. + +@node Run Commands +@section Run Commands + +You can use the list of file names created by @code{find} or +@code{locate} as arguments to other commands. In this way you can +perform arbitrary actions on the files. + +@menu +* Single File:: +* Multiple Files:: +* Querying:: +@end menu + +@node Single File +@subsection Single File + +Here is how to run a command on one file at a time. + +@deffn Action -execdir command ; +Execute @var{command}; true if @var{command} returns zero. @code{find} +takes all arguments after @samp{-execdir} to be part of the command until +an argument consisting of @samp{;} is reached. It replaces the string +@samp{@{@}} by the current file name being processed everywhere it +occurs in the command. Both of these constructions need to be escaped +(with a @samp{\}) or quoted to protect them from expansion by the +shell. The command is executed in the directory which @code{find} +was searching at the time the action was executed (that is, @{@} will +expand to a file in the local directory). + +For example, to compare each C header file in or below the current +directory with the file @file{/tmp/master}: + +@example +find . -name '*.h' -execdir diff -u '@{@}' /tmp/master ';' +@end example +@end deffn + +If you use @samp{-execdir}, you must ensure that the @samp{$PATH} +variable contains only absolute directory names. Having an empty +element in @samp{$PATH} or explicitly including @samp{.} (or any other +non-absolute name) is insecure. GNU find will refuse to run if you +use @samp{-execdir} and it thinks your @samp{$PATH} setting is +insecure. For example: + +@table @samp +@item /bin:/usr/bin: +Insecure; empty path element (at the end) +@item :/bin:/usr/bin:/usr/local/bin +Insecure; empty path element (at the start) +@item /bin:/usr/bin::/usr/local/bin +Insecure; empty path element (two colons in a row) +@item /bin:/usr/bin:.:/usr/local/bin +Insecure; @samp{.} is a path element (@file{.} is not an absolute file name) +@item /bin:/usr/bin:sbin:/usr/local/bin +Insecure; @samp{sbin} is not an absolute file name +@item /bin:/usr/bin:/sbin:/usr/local/bin +Secure (if you control the contents of those directories and any access to them) +@end table + +Another similar option, @samp{-exec} is supported, but is less secure. +@xref{Security Considerations}, for a discussion of the security +problems surrounding @samp{-exec}. + + +@deffn Action -exec command ; +This insecure variant of the @samp{-execdir} action is specified by +POSIX. Like @samp{-execdir command ;} it is true if zero is +returned by @var{command}. The main difference is that the command is +executed in the directory from which @code{find} was invoked, meaning +that @samp{@{@}} is expanded to a relative path starting with the name +of one of the starting directories, rather than just the basename of +the matched file. + +While some implementations of @code{find} replace the @samp{@{@}} only +where it appears on its own in an argument, GNU @code{find} replaces +@samp{@{@}} wherever it appears. +@end deffn + + +@node Multiple Files +@subsection Multiple Files + +Sometimes you need to process files one at a time. But usually this +is not necessary, and, it is faster to run a command on as many files +as possible at a time, rather than once per file. Doing this saves on +the time it takes to start up the command each time. + +The @samp{-execdir} and @samp{-exec} actions have variants that build +command lines containing as many matched files as possible. + +@deffn Action -execdir command @{@} + +This works as for @samp{-execdir command ;}, except that the result is +always true, and the @samp{@{@}} at the end of the command is expanded +to a list of names of matching files. This expansion is done in such +a way as to avoid exceeding the maximum command line length available +on the system. Only one @samp{@{@}} is allowed within the command, +and it must appear at the end, immediately before the @samp{+}. A +@samp{+} appearing in any position other than immediately after +@samp{@{@}} is not considered to be special (that is, it does not +terminate the command). +@end deffn + + +@deffn Action -exec command @{@} + +This insecure variant of the @samp{-execdir} action is specified by +POSIX. The main difference is that the command is executed in the +directory from which @code{find} was invoked, meaning that @samp{@{@}} +is expanded to a relative path starting with the name of one of the +starting directories, rather than just the basename of the matched +file. The result is always true. +@end deffn + +Before @code{find} exits, any partially-built command lines are +executed. This happens even if the exit was caused by the +@samp{-quit} action. However, some types of error (for example not +being able to invoke @code{stat()} on the current directory) can cause +an immediate fatal exit. In this situation, any partially-built +command lines will not be invoked (this prevents possible infinite +loops). + +At first sight, it looks like the list of filenames to be processed +can only be at the end of the command line, and that this might be a +problem for some commands (@code{cp} and @code{rsync} for example). + +However, there is a slightly obscure but powerful workaround for this +problem which takes advantage of the behaviour of @code{sh -c}: + +@example +find startpoint -tests @dots{} -exec sh -c 'scp "$@@" remote:/dest' sh @{@} + +@end example + +In the example above, the filenames we want to work on need to occur +on the @code{scp} command line before the name of the destination. We +use the shell to invoke the command @code{scp "$@@" remote:/dest} and +the shell expands @code{"$@@"} to the list of filenames we want to +process. + +Another, but less secure, way to run a command on more than one file +at once, is to use the @code{xargs} command, which is invoked like +this: + +@example +xargs @r{[}@var{option}@dots{}@r{]} @r{[}@var{command} @r{[}@var{initial-arguments}@r{]}@r{]} +@end example + +@code{xargs} normally reads arguments from the standard input. These +arguments are delimited by blanks (which can be protected with double +or single quotes or a backslash) or newlines. It executes the +@var{command} (the default is @file{echo}) one or more times with any +@var{initial-arguments} followed by arguments read from standard +input. Blank lines on the standard input are ignored. If the +@samp{-L} option is in use, trailing blanks indicate that @code{xargs} +should consider the following line to be part of this one. + +Instead of blank-delimited names, it is safer to use @samp{find +-print0} or @samp{find -fprint0} and process the output by giving the +@samp{-0} or @samp{--null} option to GNU @code{xargs}, GNU @code{tar}, +GNU @code{cpio}, or @code{perl}. The @code{locate} command also has a +@samp{-0} or @samp{--null} option which does the same thing. + +You can use shell command substitution (backquotes) to process a list +of arguments, like this: + +@example +grep -l sprintf `find $HOME -name '*.c' -print` +@end example + +However, that method produces an error if the length of the @samp{.c} +file names exceeds the operating system's command line length limit. +@code{xargs} avoids that problem by running the command as many times +as necessary without exceeding the limit: + +@example +find $HOME -name '*.c' -print | xargs grep -l sprintf +@end example + +However, if the command needs to have its standard input be a terminal +(@code{less}, for example), you have to use the shell command +substitution method or use the @samp{--arg-file} option of +@code{xargs}. + +The @code{xargs} command will process all its input, building command +lines and executing them, unless one of the commands exits with a +status of 255 (this will cause xargs to issue an error message and +stop) or it reads a line contains the end of file string specified +with the @samp{--eof} option. + +@menu +* Unsafe File Name Handling:: +* Safe File Name Handling:: +* Unusual Characters in File Names:: +* Limiting Command Size:: +* Controlling Parallelism:: +* Interspersing File Names:: +@end menu + +@node Unsafe File Name Handling +@subsubsection Unsafe File Name Handling + +Because file names can contain quotes, backslashes, blank characters, +and even newlines, it is not safe to process them using @code{xargs} +in its default mode of operation. But since most files' names do not +contain blanks, this problem occurs only infrequently. If you are +only searching through files that you know have safe names, then you +need not be concerned about it. + +Error messages issued by @code{find} and @code{locate} quote unusual +characters in file names in order to prevent unwanted changes in the +terminal's state. + + +@c This example is adapted from: +@c From: pfalstad@stone.Princeton.EDU (Paul John Falstad) +@c Newsgroups: comp.unix.shell +@c Subject: Re: Beware xargs security holes +@c Date: 16 Oct 90 19:12:06 GMT +@c +In many applications, if @code{xargs} botches processing a file +because its name contains special characters, some data might be lost. +The importance of this problem depends on the importance of the data +and whether anyone notices the loss soon enough to correct it. +However, here is an extreme example of the problems that using +blank-delimited names can cause. If the following command is run +daily from @code{cron}, then any user can remove any file on the +system: + +@example +find / -name '#*' -atime +7 -print | xargs rm +@end example + +For example, you could do something like this: + +@example +eg$ echo > '# +vmunix' +@end example + +@noindent +and then @code{cron} would delete @file{/vmunix}, if it ran +@code{xargs} with @file{/} as its current directory. + +To delete other files, for example @file{/u/joeuser/.plan}, you could +do this: + +@example +eg$ mkdir '# +' +eg$ cd '# +' +eg$ mkdir u u/joeuser u/joeuser/.plan' +' +eg$ echo > u/joeuser/.plan' +/#foo' +eg$ cd .. +eg$ find . -name '#*' -print | xargs echo +./# ./# /u/joeuser/.plan /#foo +@end example + +@node Safe File Name Handling +@subsubsection Safe File Name Handling + +Here is how to make @code{find} output file names so that they can be +used by other programs without being mangled or misinterpreted. You +can process file names generated this way by giving the @samp{-0} or +@samp{--null} option to GNU @code{xargs}, GNU @code{tar}, GNU +@code{cpio}, or @code{perl}. + +@deffn Action -print0 +True; print the entire file name on the standard output, followed by a +null character. +@end deffn + +@deffn Action -fprint0 file +True; like @samp{-print0} but write to @var{file} like @samp{-fprint} +(@pxref{Print File Name}). The output file is always created. +@end deffn + +As of findutils version 4.2.4, the @code{locate} program also has a +@samp{--null} option which does the same thing. For similarity with +@code{xargs}, the short form of the option @samp{-0} can also be used. + +If you want to be able to handle file names safely but need to run +commands which want to be connected to a terminal on their input, you +can use the @samp{--arg-file} option to @code{xargs} like this: + +@example +find / -name xyzzy -print0 > list +xargs --null --arg-file=list munge +@end example + +The example above runs the @code{munge} program on all the files named +@file{xyzzy} that we can find, but @code{munge}'s input will still be +the terminal (or whatever the shell was using as standard input). If +your shell has the ``process substitution'' feature @samp{<(...)}, you +can do this in just one step: + +@example +xargs --null --arg-file=<(find / -name xyzzy -print0) munge +@end example + +@node Unusual Characters in File Names +@subsubsection Unusual Characters in File Names +As discussed above, you often need to be careful about how the names +of files are handled by @code{find} and other programs. If the output +of @code{find} is not going to another program but instead is being +shown on a terminal, this can still be a problem. For example, some +character sequences can reprogram the function keys on some terminals. +@xref{Security Considerations}, for a discussion of other security +problems relating to @code{find}. + +Unusual characters are handled differently by various +actions, as described below. + +@table @samp +@item -print0 +@itemx -fprint0 +Always print the exact file name, unchanged, even if the output is +going to a terminal. +@item -ok +@itemx -okdir +Always print the exact file name, unchanged. This will probably +change in a future release. +@item -ls +@itemx -fls +Unusual characters are always escaped. White space, backslash, and +double quote characters are printed using C-style escaping (for +example @samp{\f}, @samp{\"}). Other unusual characters are printed +using an octal escape. Other printable characters (for @samp{-ls} and +@samp{-fls} these are the characters between octal 041 and 0176) are +printed as-is. +@item -printf +@itemx -fprintf +If the output is not going to a terminal, it is printed as-is. +Otherwise, the result depends on which directive is in use: + +@table @asis +@item %D, %F, %H, %Y, %y +These expand to values which are not under control of files' owners, +and so are printed as-is. +@item %a, %b, %c, %d, %g, %G, %i, %k, %m, %M, %n, %s, %t, %u, %U +These have values which are under the control of files' owners but +which cannot be used to send arbitrary data to the terminal, and so +these are printed as-is. +@item %f, %h, %l, %p, %P +The output of these directives is quoted if the output is going to a +terminal. The setting of the @code{LC_CTYPE} environment +variable is used to determine which characters need to be quoted. + +This quoting is performed in the same way as for GNU @code{ls}. This +is not the same quoting mechanism as the one used for @samp{-ls} and +@samp{fls}. If you are able to decide what format to use for the +output of @code{find} then it is normally better to use @samp{\0} as a +terminator than to use newline, as file names can contain white space +and newline characters. +@end table +@item -print +@itemx -fprint +Quoting is handled in the same way as for the @samp{%p} directive of +@samp{-printf} and @samp{-fprintf}. If you are using @code{find} in a +script or in a situation where the matched files might have arbitrary +names, you should consider using @samp{-print0} instead of +@samp{-print}. +@end table + + +The @code{locate} program quotes and escapes unusual characters in +file names in the same way as @code{find}'s @samp{-print} action. + +The behaviours described above may change soon, as the treatment of +unprintable characters is harmonised for @samp{-ls}, @samp{-fls}, +@samp{-print}, @samp{-fprint}, @samp{-printf} and @samp{-fprintf}. + +@node Limiting Command Size +@subsubsection Limiting Command Size + +@code{xargs} gives you control over how many arguments it passes to +the command each time it executes it. By default, it uses up to +@code{ARG_MAX} - 2k, or 128k, whichever is smaller, characters per +command. It uses as many lines and arguments as fit within that +limit. The following options modify those values. + +@table @code +@item --no-run-if-empty +@itemx -r +If the standard input does not contain any nonblanks, do not run the +command. By default, the command is run once even if there is no +input. This option is a GNU extension. + +@item --max-lines@r{[}=@var{max-lines}@r{]} +@itemx -L @var{max-lines} +@itemx -l@r{[}@var{max-lines}@r{]} +Use at most @var{max-lines} nonblank input lines per command line; +@var{max-lines} defaults to 1 if omitted; omitting the argument is not +allowed in the case of the @samp{-L} option. Trailing blanks cause an +input line to be logically continued on the next input line, for the +purpose of counting the lines. Implies @samp{-x}. The preferred name +for this option is @samp{-L} as this is specified by POSIX. + +@item --max-args=@var{max-args} +@itemx -n @var{max-args} +Use at most @var{max-args} arguments per command line. Fewer than +@var{max-args} arguments will be used if the size (see the @samp{-s} +option) is exceeded, unless the @samp{-x} option is given, in which +case @code{xargs} will exit. + +@item --max-chars=@var{max-chars} +@itemx -s @var{max-chars} +Use at most @var{max-chars} characters per command line, including the +command initial arguments and the terminating nulls at the ends of the +argument strings. If you specify a value for this option which is too +large or small, a warning message is printed and the appropriate upper +or lower limit is used instead. You can use @samp{--show-limits} +option to understand the command-line limits applying to @code{xargs} +and how this is affected by any other options. The POSIX limits shown +when you do this have already been adjusted to take into account the +size of your environment variables. + +The largest allowed value is system-dependent, and is calculated as +the argument length limit for exec, less the size of your environment, +less 2048 bytes of headroom. If this value is more than 128KiB, +128Kib is used as the default value; otherwise, the default value is +the maximum. +@end table + +@node Controlling Parallelism +@subsubsection Controlling Parallelism + +Normally, @code{xargs} runs one command at a time. This is called +"serial" execution; the commands happen in a series, one after another. +If you'd like @code{xargs} to do things in "parallel", you can ask it +to do so, either when you invoke it, or later while it is running. +Running several commands at one time can make the entire operation +go more quickly, if the commands are independent, and if your system +has enough resources to handle the load. When parallelism works in +your application, @code{xargs} provides an easy way to get your work +done faster. + +@table @code +@item --max-procs=@var{max-procs} +@itemx -P @var{max-procs} +Run up to @var{max-procs} processes at a time; the default is 1. If +@var{max-procs} is 0, @code{xargs} will run as many processes as +possible at a time. Use the @samp{-n}, @samp{-s}, or @samp{-L} option +with @samp{-P}; otherwise chances are that the command will be run +only once. +@end table + +For example, suppose you have a directory tree of large image files +and a @code{makeallsizes} script that takes a single file name and +creates various sized images from it (thumbnail-sized, web-page-sized, +printer-sized, and the original large file). The script is doing enough +work that it takes significant time to run, even on a single image. +You could run: + +@example +find originals -name '*.jpg' | xargs -1 makeallsizes +@end example + +This will run @code{makeallsizes @var{filename}} once for each @code{.jpg} +file in the @code{originals} directory. However, if your system has +two central processors, this script will only keep one of them busy. +Instead, you could probably finish in about half the time by running: + +@example +find originals -name '*.jpg' | xargs -1 -P 2 makeallsizes +@end example + +@code{xargs} will run the first two commands in parallel, and then +whenever one of them terminates, it will start another one, until +the entire job is done. + +The same idea can be generalized to as many processors as you have handy. +It also generalizes to other resources besides processors. For example, +if @code{xargs} is running commands that are waiting for a response from a +distant network connection, running a few in parallel may reduce the +overall latency by overlapping their waiting time. + +If you are running commands in parallel, you need to think about how +they should arbitrate access to any resources that they share. For +example, if more than one of them tries to print to stdout, the ouptut +will be produced in an indeterminate order (and very likely mixed up) +unless the processes collaborate in some way to prevent this. Using +some kind of locking scheme is one way to prevent such problems. In +general, using a locking scheme will help ensure correct output but +reduce performance. If you don't want to tolerate the performance +difference, simply arrange for each process to produce a separate output +file (or otherwise use separate resources). + +@code{xargs} also allows you to ``turn up'' or ``turn down'' its parallelism +in the middle of a run. Suppose you are keeping your four-processor +system busy for hours, processing thousands of images using @code{-P 4}. +Now, in the middle of the run, you or someone else wants you to reduce +your load on the system, so that something else will run faster. +If you interrupt @code{xargs}, your job will be half-done, and it +may take significant manual work to resume it only for the remaining +images. If you suspend @code{xargs} using your shell's job controls +(e.g. @code{control-Z}), then it will get no work done while suspended. + +Find out the process ID of the @code{xargs} process, either from your +shell or with the @code{ps} command. After you send it the signal +@code{SIGUSR2}, @code{xargs} will run one fewer command in parallel. +If you send it the signal @code{SIGUSR1}, it will run one more command +in parallel. For example: + +@example +shell$ xargs <allimages -1 -P 4 makeallsizes & +[4] 27643 + ... at some later point ... +shell$ kill -USR2 27643 +shell$ kill -USR2 %4 +@end example + +The first @code{kill} command will cause @code{xargs} to wait for +two commands to terminate before starting the next command (reducing +the parallelism from 4 to 3). The second @code{kill} will reduce it from +3 to 2. (@code{%4} works in some shells as a shorthand for the process +ID of the background job labeled @code{[4]}.) + +Similarly, if you started a long @code{xargs} job without parallelism, you +can easily switch it to start running two commands in parallel by sending +it a @code{SIGUSR1}. + +@code{xargs} will never terminate any existing commands when you ask it +to run fewer processes. It merely waits for the excess commands to +finish. If you ask it to run more commands, it will start the next +one immediately (if it has more work to do). If the degree of +parallelism is already 1, sending @code{SIGUSR2} will have no further +effect (since @code{--max-procs=0} means that there should be no limit +on the number of processes to run). + +There is an implementation-defined limit on the number of processes. +This limit is shown with @code{xargs --show-limits}. The limit is at +least 127 on all systems (and on the author's system it is +2147483647). + +If you send several identical signals quickly, the operating system +does not guarantee that each of them will be delivered to @code{xargs}. +This means that you can't rapidly increase or decrease the parallelism by +more than one command at a time. You can avoid this problem by sending +a signal, observing the result, then sending the next one; or merely by +delaying for a few seconds between signals (unless your system is very +heavily loaded). + +Whether or not parallel execution will work well for you depends on +the nature of the commmand you are running in parallel, on the +configuration of the system on which you are running the command, and +on the other work being done on the system at the time. + +@node Interspersing File Names +@subsubsection Interspersing File Names + +@code{xargs} can insert the name of the file it is processing between +arguments you give for the command. Unless you also give options to +limit the command size (@pxref{Limiting Command Size}), this mode of +operation is equivalent to @samp{find -exec} (@pxref{Single File}). + +@table @code +@item --replace@r{[}=@var{replace-str}@r{]} +@itemx -I @var{replace-str} +@itemx -i @var{replace-str} +Replace occurrences of @var{replace-str} in the initial arguments with +names read from the input. Also, unquoted blanks do not terminate +arguments; instead, the input is split at newlines only. For the +@samp{-i} option, if @var{replace-str} is omitted for @samp{--replace} +or @samp{-i}, it defaults to @samp{@{@}} (like for @samp{find -exec}). +Implies @samp{-x} and @samp{-l 1}. @samp{-i} is deprecated in favour +of @samp{-I}. As an example, to sort each file in the @file{bills} +directory, leaving the output in that file name with @file{.sorted} +appended, you could do: + +@example +find bills -type f | xargs -I XX sort -o XX.sorted XX +@end example + +@noindent +The equivalent command using @samp{find -execdir} is: + +@example +find bills -type f -execdir sort -o '@{@}.sorted' '@{@}' ';' +@end example +@end table + + +When you use the @samp{-I} option, each line read from the input is +buffered internally. This means that there is an upper limit on the +length of input line that @code{xargs} will accept when used with the +@samp{-I} option. To work around this limitation, you can use the +@samp{-s} option to increase the amount of buffer space that xargs +uses, and you can also use an extra invocation of xargs to ensure that +very long lines do not occur. For example: + +@example +somecommand | xargs -s 50000 echo | xargs -I '@{@}' -s 100000 rm '@{@}' +@end example + +Here, the first invocation of @code{xargs} has no input line length +limit because it doesn't use the @samp{-I} option. The second +invocation of @code{xargs} does have such a limit, but we have ensured +that it never encounters a line which is longer than it can +handle. + +This is not an ideal solution. Instead, the @samp{-I} option should +not impose a line length limit (apart from any limit imposed by the +operating system) and so one might consider this limitation to be a +bug. A better solution would be to allow @code{xargs -I} to +automatically move to a larger value for the @samp{-s} option when +this is needed. + +This sort of problem doesn't occur with the output of @code{find} +because it emits just one filename per line. + +@node Querying +@subsection Querying + +To ask the user whether to execute a command on a single file, you can +use the @code{find} primary @samp{-okdir} instead of @samp{-execdir}, +and the @code{find} primary @samp{-ok} instead of @samp{-exec}: + +@deffn Action -okdir command ; +Like @samp{-execdir} (@pxref{Single File}), but ask the user first. +If the user does not agree to run the command, just return false. +Otherwise, run it, with standard input redirected from +@file{/dev/null}. + +The response to the prompt is matched against a pair of regular +expressions to determine if it is a yes or no response. These regular +expressions are obtained from the system (@code{nl_langinfo} items +YESEXPR and NOEXPR are used) if the @code{POSIXLY_CORRECT} environment +variable is set and the system has such patterns available. Otherwise, +@code{find}'s message translations are used. In either case, the +@code{LC_MESSAGES} environment variable will determine the regular +expressions used to determine if the answer is affirmative or negative. +The interpretation of the regular expressions themselves will be +affected by the environment variables @code{LC_CTYPE} (character +classes) and @code{LC_COLLATE} (character ranges and equivalence +classes). +@end deffn + +@deffn Action -ok command ; +This insecure variant of the @samp{-okdir} action is specified by +POSIX. The main difference is that the command is executed in the +directory from which @code{find} was invoked, meaning that @samp{@{@}} +is expanded to a relative path starting with the name of one of the +starting directories, rather than just the basename of the matched +file. If the command is run, its standard input is redirected from +@file{/dev/null}. +@end deffn + +When processing multiple files with a single command, to query the +user you give @code{xargs} the following option. When using this +option, you might find it useful to control the number of files +processed per invocation of the command (@pxref{Limiting Command +Size}). + +@table @code +@item --interactive +@itemx -p +Prompt the user about whether to run each command line and read a line +from the terminal. Only run the command line if the response starts +with @samp{y} or @samp{Y}. Implies @samp{-t}. +@end table + +@node Delete Files +@section Delete Files + +@deffn Action -delete +Delete files or directories; true if removal succeeded. If the +removal failed, an error message is issued. + +The use of the @samp{-delete} action on the command line automatically +turns on the @samp{-depth} option (@pxref{find Expressions}). This +can be surprising if you were previously just testing with +@samp{-print}, so it is usually best to remember to use @samp{-depth} +explicitly. + +If @samp{-delete} fails, @code{find}'s exit status will be nonzero +(when it eventually exits). +@end deffn + +@node Adding Tests +@section Adding Tests + +You can test for file attributes that none of the @code{find} builtin +tests check. To do this, use @code{xargs} to run a program that +filters a list of files printed by @code{find}. If possible, use +@code{find} builtin tests to pare down the list, so the program run by +@code{xargs} has less work to do. The tests builtin to @code{find} +will likely run faster than tests that other programs perform. + +For reasons of efficiency it is often useful to limit the number of +times an external program has to be run. For this reason, it is often +a good idea to implement ``extended'' tests by using @code{xargs}. + +For example, here is a way to print the names of all of the unstripped +binaries in the @file{/usr/local} directory tree. Builtin tests avoid +running @code{file} on files that are not regular files or are not +executable. + +@example +find /usr/local -type f -perm /a=x | xargs file | + grep 'not stripped' | cut -d: -f1 +@end example + +@noindent +The @code{cut} program removes everything after the file name from the +output of @code{file}. + +However, using @code{xargs} can present important security problems +(@pxref{Security Considerations}). These can be avoided by using +@samp{-execdir}. The @samp{-execdir} action is also a useful way of +putting your own test in the middle of a set of other tests or actions +for @code{find} (for example, you might want to use @samp{-prune}). + +@c Idea from Martin Weitzel. +To place a special test somewhere in the middle of a @code{find} +expression, you can use @samp{-execdir} (or, less securely, +@samp{-exec}) to run a program that performs the test. Because +@samp{-execdir} evaluates to the exit status of the executed program, +you can use a program (which can be a shell script) that tests for a +special attribute and make it exit with a true (zero) or false +(non-zero) status. It is a good idea to place such a special test +@emph{after} the builtin tests, because it starts a new process which +could be avoided if a builtin test evaluates to false. + +Here is a shell script called @code{unstripped} that checks whether +its argument is an unstripped binary file: + +@example +#! /bin/sh +file "$1" | grep -q "not stripped" +@end example + + +This script relies on the shell exiting with the status of +the last command in the pipeline, in this case @code{grep}. The +@code{grep} command exits with a true status if it found any matches, +false if not. Here is an example of using the script (assuming it is +in your search path). It lists the stripped executables (and shell +scripts) in the file @file{sbins} and the unstripped ones in +@file{ubins}. + +@example +find /usr/local -type f -perm /a=x \ + \( -execdir unstripped '@{@}' \; -fprint ubins -o -fprint sbins \) +@end example + + +@node Databases +@chapter File Name Databases + +The file name databases used by @code{locate} contain lists of files +that were in particular directory trees when the databases were last +updated. The file name of the default database is determined when +@code{locate} and @code{updatedb} are configured and installed. The +frequency with which the databases are updated and the directories for +which they contain entries depend on how often @code{updatedb} is run, +and with which arguments. + +You can obtain some statistics about the databases by using +@samp{locate --statistics}. + +@menu +* Database Locations:: +* Database Formats:: +* Newline Handling:: +@end menu + + +@node Database Locations +@section Database Locations + +There can be multiple file name databases. Users can select which +databases @code{locate} searches using the @code{LOCATE_PATH} +environment variable or a command line option. The system +administrator can choose the file name of the default database, the +frequency with which the databases are updated, and the directories +for which they contain entries. File name databases are updated by +running the @code{updatedb} program, typically nightly. + +In networked environments, it often makes sense to build a database at +the root of each filesystem, containing the entries for that +filesystem. @code{updatedb} is then run for each filesystem on the +fileserver where that filesystem is on a local disk, to prevent +thrashing the network. + +@xref{Invoking updatedb}, for the description of the options to +@code{updatedb}. These options can be used to specify which +directories are indexed by each database file. + +The default location for the locate database depends on how findutils +is built, but the findutils installation accompanying this manual uses +the default location @file{@value{LOCATE_DB}}. + +If no database exists at @file{@value{LOCATE_DB}} but the user did not +specify where to look (by using @samp{-d} or setting +@code{LOCATE_PATH}), then @code{locate} will also check for a +``secure'' database in @file{/var/lib/slocate/slocate.db}. + +@node Database Formats +@section Database Formats + +The file name databases contain lists of files that were in particular +directory trees when the databases were last updated. The file name +database format changed starting with GNU @code{locate} version 4.0 to +allow machines with different byte orderings to share the databases. + +GNU @code{locate} can read both the old and new database formats. +However, old versions of @code{locate} (on other Unix systems, or GNU +@code{locate} before version 4.0) produce incorrect results if run +against a database in something other than the old format. + +Support for the old database format will eventually be discontinued, +first in @code{updatedb} and later in @code{locate}. + +If you run @samp{locate --statistics}, the resulting summary indicates +the type of each @code{locate} database. You select which database +format @code{updatedb} will use with the @samp{--dbformat} option. + + +@menu +* LOCATE02 Database Format:: +* Sample LOCATE02 Database:: +* slocate Database Format:: +* Old Database Format:: +@end menu + +@node LOCATE02 Database Format +@subsection LOCATE02 Database Format + +@code{updatedb} runs a program called @code{frcode} to +@dfn{front-compress} the list of file names, which reduces the +database size by a factor of 4 to 5. Front-compression (also known as +incremental encoding) works as follows. + +The database entries are a sorted list (case-insensitively, for users' +convenience). Since the list is sorted, each entry is likely to share +a prefix (initial string) with the previous entry. Each database +entry begins with an offset-differential count byte, which is the +additional number of characters of prefix of the preceding entry to +use beyond the number that the preceding entry is using of its +predecessor. (The counts can be negative.) Following the count is a +null-terminated ASCII remainder -- the part of the name that follows +the shared prefix. + +If the offset-differential count is larger than can be stored in a +byte (+/-127), the byte has the value 0x80 and the count follows in a +2-byte word, with the high byte first (network byte order). + +Every database begins with a dummy entry for a file called +@file{LOCATE02}, which @code{locate} checks for to ensure that the +database file has the correct format; it ignores the entry in doing +the search. + +Databases cannot be concatenated together, even if the first (dummy) +entry is trimmed from all but the first database. This is because the +offset-differential count in the first entry of the second and +following databases will be wrong. + +In the output of @samp{locate --statistics}, the new database format +is referred to as @samp{LOCATE02}. + +@node Sample LOCATE02 Database +@subsection Sample LOCATE02 Database + +Sample input to @code{frcode}: +@c with nulls changed to newlines: + +@example +/usr/src +/usr/src/cmd/aardvark.c +/usr/src/cmd/armadillo.c +/usr/tmp/zoo +@end example + +Length of the longest prefix of the preceding entry to share: + +@example +0 /usr/src +8 /cmd/aardvark.c +14 rmadillo.c +5 tmp/zoo +@end example + +Output from @code{frcode}, with trailing nulls changed to newlines +and count bytes made printable: + +@example +0 LOCATE02 +0 /usr/src +8 /cmd/aardvark.c +6 rmadillo.c +-9 tmp/zoo +@end example + +(6 = 14 - 8, and -9 = 5 - 14) + +@node slocate Database Format +@subsection slocate Database Format + +The @code{slocate} program uses a database format similar to, but not +quite the same as, GNU @code{locate}. The first byte of the database +specifies its @dfn{security level}. If the security level is 0, +@code{slocate} will read, match and print filenames on the basis of +the information in the database only. However, if the security level +byte is 1, @code{slocate} omits entries from its output if the +invoking user is unable to access them. The second byte of the +database is zero. The second byte is immediately followed by the +first database entry. The first entry in the database is not preceded +by any differential count or dummy entry. Instead the differential +count for the first item is assumed to be zero. + +Starting with the second entry (if any) in the database, data is +interpreted as for the GNU LOCATE02 format. + +@node Old Database Format +@subsection Old Database Format + +The old database format is used by Unix @code{locate} and @code{find} +programs and earlier releases of the GNU ones. @code{updatedb} +produces this format if given the @samp{--old-format} option. + +@code{updatedb} runs programs called @code{bigram} and @code{code} to +produce old-format databases. The old format differs from the new one +in the following ways. Instead of each entry starting with an +offset-differential count byte and ending with a null, byte values +from 0 through 28 indicate offset-differential counts from -14 through +14. The byte value indicating that a long offset-differential count +follows is 0x1e (30), not 0x80. The long counts are stored in host +byte order, which is not necessarily network byte order, and host +integer word size, which is usually 4 bytes. They also represent a +count 14 less than their value. The database lines have no +termination byte; the start of the next line is indicated by its first +byte having a value <= 30. + +In addition, instead of starting with a dummy entry, the old database +format starts with a 256 byte table containing the 128 most common +bigrams in the file list. A bigram is a pair of adjacent bytes. +Bytes in the database that have the high bit set are indexes (with the +high bit cleared) into the bigram table. The bigram and +offset-differential count coding makes these databases 20-25% smaller +than the new format, but makes them not 8-bit clean. Any byte in a +file name that is in the ranges used for the special codes is replaced +in the database by a question mark, which not coincidentally is the +shell wildcard to match a single character. + +The old format therefore cannot faithfully store entries with +non-ASCII characters. It therefore should not be used in +internationalised environments. That is, most installations should +not use it. + +Because the long counts are stored by the @code{code} program as +native-order machine words, the database format is not easily used in +environments which differ in terms of byte order. If locate databases +are to be shared between machines, the LOCATE02 database format should +be used. This has other benefits as discussed above. However, the +length of the filename currently being processed can normally be used +to place reasonable limits on the long counts and so this information +is used by locate to help it guess the byte ordering of the old format +database. Unless it finds evidence to the contrary, @code{locate} +will assume that the byte order of the database is the same as the +native byte order of the machine running @code{locate}. The output of +@samp{locate --statistics} also includes information about the byte +order of old-format databases. + +The output of @samp{locate --statistics} will give an incorrect count +of the number of file names containing newlines or high-bit characters +for old-format databases. + +Old versions of GNU @code{locate} fail to correctly handle very long +file names, possibly leading to security problems relating to a heap +buffer overrun. @xref{Security Considerations for locate}, for a +detailed explanation. + +@node Newline Handling +@section Newline Handling + +Within the database, file names are terminated with a null character. +This is the case for both the old and the new format. + +When the new database format is being used, the compression technique +used to generate the database though relies on the ability to sort the +list of files before they are presented to @code{frcode}. + +If the system's sort command allows its input list of files to be +separated with null characters via the @samp{-z} option, this option +is used and therefore @code{updatedb} and @code{locate} will both +correctly handle file names containing newlines. If the @code{sort} +command lacks support for this, the list of files is delimited with +the newline character, meaning that parts of file names containing +newlines will be incorrectly sorted. This can result in both +incorrect matches and incorrect failures to match. + +On the other hand, if you are using the old database format, file +names with embedded newlines are not correctly handled. There is no +technical limitation which enforces this, it's just that the +@code{bigram} program has not been updated to support lists of file +names separated by nulls. + +So, if you are using the new database format (this is the default) and +your system uses GNU @code{sort}, newlines will be correctly handled +at all times. Otherwise, newlines may not be correctly handled. + +@node File Permissions +@chapter File Permissions + +@include perm.texi + +@include parse-datetime.texi + +@node Configuration +@chapter Configuration + +The findutils source distribution includes a @code{configure} script +which examines the system and generates files required to build +findutils. See the files @file{README} and @file{INSTALL}. + +A number of options can be specified on the @code{configure} command +line, and many of these are straightforward, adequately documented in +the @code{--help} output, or not normally useful. Options which are +useful or which are not obvious are explained here. + +@menu +* Leaf Optimisation:: Take advantage of Unix file system semantics. +* d_type Optimisation:: Take advantage of file type information. +* fts:: A non-recursive file system search. +@end menu + +@node Leaf Optimisation +@section Leaf Optimisation + +Files in Unix file systems have a link count which indicates how many +names point to the same inode. Directories in Unix filssytems have a +@file{..} entry which functions as a hard link to the parent directory +and a @file{.} entry which functions as a link to the directory itself. +The @file{..} entry of the root directory also points to the root. +This means that @code{find} can deduce the number of subdirectories a +directory has, simply by subtracting 2 from the directory's link +count. This allows @file{find} the calls to @code{stat} which would +otherwise be needed to discover which directory entries are +subdirectories. + +File systems which don't have these semantics should simply return a +value less than 2 in the @code{st_nlinks} member of @code{struct stat} +in response to a successful call to @code{stat}. + +If you are building @code{find} for a system on which the value of +@code{st_nlinks} is unreliable, you can specify +@code{--disable-leaf-optimisation} to @code{configure} to prevent this +assumption being made. + +@node d_type Optimisation +@section d_type Optimisation + +When this feature is enabled, @code{find} takes advantage of the fact +that on some systems @code{readdir} will return the type of a file in +@code{struct dirent}. + +@node fts +@section fts + +The findutils source distribution contains two different implementations of +@code{find}. The older implementation descends the file system +recursively, while the newer one uses @code{fts}. Both are normally +installed. + +If the option @code{--without-fts} was passed to @code{configure}, the +recursive implementation is installed as @code{find} and the fts-based +implementation is installed as @code{ftsfind}. Otherwise, the +fts-based implementation is installed as @code{find} and the recursive +implementation is installed as @code{oldfind}. + + + +@node Reference +@chapter Reference + +Below are summaries of the command line syntax for the programs +discussed in this manual. + +@menu +* Invoking find:: +* Invoking locate:: +* Invoking updatedb:: +* Invoking xargs:: +* Regular Expressions:: +* Environment Variables:: +@end menu + +@node Invoking find +@section Invoking @code{find} + +@example +find @r{[-H] [-L] [-P] [-D @var{debugoptions}] [-O@var{level}]} @r{[}@var{file}@dots{}@r{]} @r{[}@var{expression}@r{]} +@end example + +@code{find} searches the directory tree rooted at each file name +@var{file} by evaluating the @var{expression} on each file it finds in +the tree. + +The command line may begin with the @samp{-H}, @samp{-L}, @samp{-P}, +@samp{-D} and @samp{-O} options. These are followed by a list of +files or directories that should be searched. If no files to search +are specified, the current directory (@file{.}) is used. + +This list of files to search is followed by a list of expressions +describing the files we wish to search for. The first part of the +expression is recognised by the fact that it begins with @samp{-} +followed by some other letters (for example @samp{-print}), or is +either @samp{(} or @samp{!}. Any arguments after it are the rest of +the expression. + +If no expression is given, the expression @samp{-print} is used. + +The @code{find} command exits with status zero if all files matched +are processed successfully, greater than zero if errors occur. + +The @code{find} program also recognises two options for administrative +use: + +@table @samp +@item --help +Print a summary of the command line usage and exit. +@item --version +Print the version number of @code{find} and exit. +@end table + +The @samp{-version} option is a synonym for @samp{--version} + + +@menu +* Filesystem Traversal Options:: +* Warning Messages:: +* Optimisation Options:: +* Debug Options:: +* Find Expressions:: +@end menu + +@node Filesystem Traversal Options +@subsection Filesystem Traversal Options + +The options @samp{-H}, @samp{-L} or @samp{-P} may be specified at the +start of the command line (if none of these is specified, @samp{-P} is +assumed). If you specify more than one of these options, the last one +specified takes effect (but note that the @samp{-follow} option is +equivalent to @samp{-L}). + +@table @code +@item -P +Never follow symbolic links (this is the default), except in the case +of the @samp{-xtype} predicate. +@item -L +Always follow symbolic links, except in the case of the @samp{-xtype} +predicate. +@item -H +Follow symbolic links specified in the list of files to search, or +which are otherwise specified on the command line. +@end table + +If @code{find} would follow a symbolic link, but cannot for any reason +(for example, because it has insufficient permissions or the link is +broken), it falls back on using the properties of the symbolic link +itself. @ref{Symbolic Links} for a more complete description of how +symbolic links are handled. + +@node Warning Messages +@subsection Warning Messages + +If there is an error on the @code{find} command line, an error message +is normally issued. However, there are some usages that are +inadvisable but which @code{find} should still accept. Under these +circumstances, @code{find} may issue a warning message. + +By default, warnings are enabled only if @code{find} is being run +interactively (specifically, if the standard input is a terminal) and +the @code{POSIXLY_CORRECT} environment variable is not set. Warning +messages can be controlled explicitly by the use of options on the +command line: + +@table @code +@item -warn +Issue warning messages where appropriate. +@item -nowarn +Do not issue warning messages. +@end table + +These options take effect at the point on the command line where they +are specified. Therefore it's not useful to specify @samp{-nowarn} at +the end of the command line. The warning messages affected by the +above options are triggered by: + +@itemize @minus +@item +Use of the @samp{-d} option which is deprecated; please use +@samp{-depth} instead, since the latter is POSIX-compliant. +@item +Use of the @samp{-ipath} option which is deprecated; please use +@samp{-iwholename} instead. +@item +Specifying an option (for example @samp{-mindepth}) after a non-option +(for example @samp{-type} or @samp{-print}) on the command line. +@item +Use of the @samp{-name} or @samp{-iname} option with a slash character +in the pattern. Since the name predicates only compare against the +basename of the visited files, the only file that can match a slash is +the root directory itself. +@end itemize + +The default behaviour above is designed to work in that way so that +existing shell scripts don't generate spurious errors, but people will +be made aware of the problem. + +Some warning messages are issued for less common or more serious +problems, and consequently cannot be turned off: + +@itemize @minus +@item +Use of an unrecognised backslash escape sequence with @samp{-fprintf} +@item +Use of an unrecognised formatting directive with @samp{-fprintf} +@end itemize + +@node Optimisation Options +@subsection Optimisation Options + +The @samp{-O@var{level}} option sets @code{find}'s optimisation level +to @var{level}. The default optimisation level is 1. + +At certain optimisation levels, @code{find} reorders tests to speed up +execution while preserving the overall effect; that is, predicates +with side effects are not reordered relative to each other. The +optimisations performed at each optimisation level are as follows. + +@table @samp +@item 0 +Currently equivalent to optimisation level 1. + +@item 1 +This is the default optimisation level and corresponds to the +traditional behaviour. Expressions are reordered so that tests based +only on the names of files (for example@samp{ -name} and +@samp{-regex}) are performed first. + +@item 2 +Any @samp{-type} or @samp{-xtype} tests are performed after any tests +based only on the names of files, but before any tests that require +information from the inode. On many modern versions of Unix, file +types are returned by @code{readdir()} and so these predicates are +faster to evaluate than predicates which need to stat the file first. + +If you use the @samp{-fstype FOO} predicate and specify a filsystem +type @samp{FOO} which is not known (that is, present in +@file{/etc/mtab}) at the time @code{find} starts, that predicate is +equivalent to @samp{-false}. + + +@item 3 +At this optimisation level, the full cost-based query optimiser is +enabled. The order of tests is modified so that cheap (i.e., fast) +tests are performed first and more expensive ones are performed later, +if necessary. Within each cost band, predicates are evaluated earlier +or later according to whether they are likely to succeed or not. For +@samp{-o}, predicates which are likely to succeed are evaluated +earlier, and for @samp{-a}, predicates which are likely to fail are +evaluated earlier. +@end table + + +@node Debug Options +@subsection Debug Options + +The @samp{-D} option makes @code{find} produce diagnostic output. +Much of the information is useful only for diagnosing problems, and so +most people will not find this option helpful. + +The list of debug options should be comma separated. Compatibility of +the debug options is not guaranteed between releases of findutils. +For a complete list of valid debug options, see the output of +@code{find -D help}. Valid debug options include: +@table @samp +@item help +Explain the debugging options. +@item tree +Show the expression tree in its original and optimised form. +@item stat +Print messages as files are examined with the stat and lstat system +calls. The find program tries to minimise such calls. +@item opt +Prints diagnostic information relating to the optimisation of the +expression tree; see the @samp{-O} option. +@item rates +Prints a summary indicating how often each predicate succeeded or +failed. +@end table + +@node Find Expressions +@subsection Find Expressions + +The final part of the @code{find} command line is a list of +expressions. @xref{Primary Index}, for a summary of all of the tests, +actions, and options that the expression can contain. If the +expression is missing, @samp{-print} is assumed. + +@node Invoking locate +@section Invoking @code{locate} + +@example +locate @r{[}@var{option}@dots{}@r{]} @var{pattern}@dots{} +@end example + +For each @var{pattern} given @code{locate} searches one or more file +name databases returning each match of @var{pattern}. + +@table @code +@item --all +@itemx -A +Print only names which match all non-option arguments, not those +matching one or more non-option arguments. + +@item --basename +@itemx -b +The specified pattern is matched against just the last component of +the name of a file in the @code{locate} database. This last +component is also called the ``base name''. For example, the base +name of @file{/tmp/mystuff/foo.old.c} is @file{foo.old.c}. If the +pattern contains metacharacters, it must match the base name exactly. +If not, it must match part of the base name. + +@item --count +@itemx -c +Instead of printing the matched file names, just print the total +number of matches found, unless @samp{--print} (@samp{-p}) is also +present. + + +@item --database=@var{path} +@itemx -d @var{path} +Instead of searching the default @code{locate} database +@file{@value{LOCATE_DB}}, @code{locate} searches the file +name databases in @var{path}, which is a colon-separated list of +database file names. You can also use the environment variable +@code{LOCATE_PATH} to set the list of database files to search. The +option overrides the environment variable if both are used. Empty +elements in @var{path} (that is, a leading or trailing colon, or two +colons in a row) are taken to stand for the default database. +A database can be supplied on stdin, using @samp{-} as an element +of @samp{path}. If more than one element of @samp{path} is @samp{-}, +later instances are ignored (but a warning message is printed). + +@item --existing +@itemx -e +Only print out such names which currently exist (instead of such names +which existed when the database was created). Note that this may slow +down the program a lot, if there are many matches in the database. +The way in which broken symbolic links are treated is affected by the +@samp{-L}, @samp{-P} and @samp{-H} options. Please note that it is +possible for the file to be deleted after @code{locate} has checked +that it exists, but before you use it. This option is automatically +turned on when reading an @code{slocate} database in secure mode +(@pxref{slocate Database Format}). + +@item --non-existing +@itemx -E +Only print out such names which currently do not exist (instead of +such names which existed when the database was created). Note that +this may slow down the program a lot, if there are many matches in the +database. The way in which broken symbolic links are treated is +affected by the @samp{-L}, @samp{-P} and @samp{-H} options. Please +note that @code{locate} checks that the file does not exist, but a +file of the same name might be created after @code{locate}'s check but +before you read @code{locate}'s output. + +@item --follow +@itemx -L +If testing for the existence of files (with the @samp{-e} or @samp{-E} +options), consider broken symbolic links to be non-existing. This is +the default behaviour. + +@item --nofollow +@itemx -P +@itemx -H +If testing for the existence of files (with the @samp{-e} or @samp{-E} +options), treat broken symbolic links as if they were existing files. +The @samp{-H} form of this option is provided purely for similarity +with @code{find}; the use of @samp{-P} is recommended over @samp{-H}. + +@item --ignore-case +@itemx -i +Ignore case distinctions in both the pattern and the file names. + +@item --limit=N +@itemx -l N +Limit the number of results printed to N. When used with the +@samp{--count} option, the value printed will never be larger than +this limit. +@item --max-database-age=D +Normally, @code{locate} will issue a warning message when it searches +a database which is more than 8 days old. This option changes that +value to something other than 8. The effect of specifying a negative +value is undefined. +@item --mmap +@itemx -m +Accepted but does nothing. The option is supported only to provide +compatibility with BSD's @code{locate}. + +@item --null +@itemx -0 +Results are separated with the ASCII NUL character rather than the +newline character. To get the full benefit of this option, +use the new @code{locate} database format (that is the default +anyway). + +@item --print +@itemx -p +Print search results when they normally would not be due to +use of @samp{--statistics} (@samp{-S}) or @samp{--count} +(@samp{-c}). + +@item --wholename +@itemx -w +The specified pattern is matched against the whole name of the file in +the @code{locate} database. If the pattern contains metacharacters, +it must match exactly. If not, it must match part of the whole file +name. This is the default behaviour. + +@item --regex +@itemx -r +Instead of using substring or shell glob matching, the pattern +specified on the command line is understood to be a regular +expression. GNU Emacs-style regular expressions are assumed unless +the @samp{--regextype} option is also given. File names from the +@code{locate} database are matched using the specified regular +expression. If the @samp{-i} flag is also given, matching is +case-insensitive. Matches are performed against the whole path name, +and so by default a pathname will be matched if any part of it matches +the specified regular expression. The regular expression may use +@samp{^} or @samp{$} to anchor a match at the beginning or end of a +pathname. + +@item --regextype +This option changes the regular expression syntax and behaviour used +by the @samp{--regex} option. @ref{Regular Expressions} for more +information on the regular expression dialects understood by GNU +findutils. + +@item --stdio +@itemx -s +Accepted but does nothing. The option is supported only to provide +compatibility with BSD's @code{locate}. + +@item --statistics +@itemx -S +Print some summary information for each @code{locate} database. No +search is performed unless non-option arguments are given. +Although the BSD version of locate also has this option, the format of the +output is different. + +@item --help +Print a summary of the command line usage for @code{locate} and exit. + +@item --version +Print the version number of @code{locate} and exit. +@end table + +@node Invoking updatedb +@section Invoking @code{updatedb} + +@example +updatedb @r{[}@var{option}@dots{}@r{]} +@end example + +@code{updatedb} creates and updates the database of file names used by +@code{locate}. @code{updatedb} generates a list of files similar to +the output of @code{find} and then uses utilities for optimizing the +database for performance. @code{updatedb} is often run periodically +as a @code{cron} job and configured with environment variables or +command options. Typically, operating systems have a shell script +that ``exports'' configurations for variable definitions and uses +another shell script that ``sources'' the configuration file into the +environment and then executes @code{updatedb} in the environment. + +@table @code +@item --findoptions='@var{OPTION}@dots{}' +Global options to pass on to @code{find}. +The environment variable @code{FINDOPTIONS} also sets this value. +Default is none. + +@item --localpaths='@var{path}@dots{}' +Non-network directories to put in the database. +Default is @file{/}. + +@item --netpaths='@var{path}@dots{}' +Network (NFS, AFS, RFS, etc.) directories to put in the database. +The environment variable @code{NETPATHS} also sets this value. +Default is none. + +@item --prunepaths='@var{path}@dots{}' +Directories to omit from the database, which would otherwise be +included. The environment variable @code{PRUNEPATHS} also sets this +value. Default is @file{/tmp /usr/tmp /var/tmp /afs}. The paths are +used as regular expressions (with @code{find ... -regex}, so you need +to specify these paths in the same way that @code{find} will encounter +them. This means for example that the paths must not include trailing +slashes. + +@item --prunefs='@var{path}@dots{}' +Filesystems to omit from the database, which would otherwise be +included. Note that files are pruned when a filesystem is reached; +Any filesystem mounted under an undesired filesystem will be ignored. +The environment variable @code{PRUNEFS} also sets this value. Default +is @file{nfs NFS proc}. + +@item --output=@var{dbfile} +The database file to build. The default is system-dependent, but +when this document was formatted it was @file{@value{LOCATE_DB}}. + +@item --localuser=@var{user} +The user to search the non-network directories as, using @code{su}. +Default is to search the non-network directories as the current user. +You can also use the environment variable @code{LOCALUSER} to set this user. + +@item --netuser=@var{user} +The user to search network directories as, using @code{su}. Default +@code{user} is @code{daemon}. You can also use the environment variable +@code{NETUSER} to set this user. + +@item --old-format +Generate a @code{locate} database in the old format, for compatibility +with versions of @code{locate} other than GNU @code{locate}. Using +this option means that @code{locate} will not be able to properly +handle non-ASCII characters in file names (that is, file names +containing characters which have the eighth bit set, such as many of +the characters from the ISO-8859-1 character set). @xref{Database +Formats}, for a detailed description of the supported database +formats. + +@item --dbformat=@var{FORMAT} +Generate the locate database in format @code{FORMAT}. Supported +database formats include @code{LOCATE02} (which is the default), +@code{old} and @code{slocate}. The @code{old} format exists for +compatibility with implementations of @code{locate} on other Unix +systems. The @code{slocate} format exists for compatibility with +@code{slocate}. @xref{Database Formats}, for a detailed description +of each format. + +@item --help +Print a summary of the command line usage and exit. +@item --version +Print the version number of @code{updatedb} and exit. +@end table + +@node Invoking xargs +@section Invoking @code{xargs} + +@example +xargs @r{[}@var{option}@dots{}@r{]} @r{[}@var{command} @r{[}@var{initial-arguments}@r{]}@r{]} +@end example + +@code{xargs} exits with the following status: + +@table @asis +@item 0 +if it succeeds +@item 123 +if any invocation of the command exited with status 1-125 +@item 124 +if the command exited with status 255 +@item 125 +if the command is killed by a signal +@item 126 +if the command cannot be run +@item 127 +if the command is not found +@item 1 +if some other error occurred. +@end table + +Exit codes greater than 128 are used by the shell to indicate that +a program died due to a fatal signal. + + +@menu +* xargs options:: +* Invoking the shell from xargs:: +@end menu + +@node xargs options +@subsection xargs options + +@table @code +@item --arg-file@r{=@var{inputfile}} +@itemx -a @r{@var{inputfile}} +Read names from the file @var{inputfile} instead of standard input. +If you use this option, the standard input stream remains unchanged +when commands are run. Otherwise, stdin is redirected from +@file{/dev/null}. + +@item --null +@itemx -0 +Input file names are terminated by a null character instead of by +whitespace, and any quotes and backslash characters are not considered +special (every character is taken literally). Disables the end of +file string, which is treated like any other argument. + +@item --delimiter @var{delim} +@itemx -d @var{delim} + +Input file names are terminated by the specified character @var{delim} +instead of by whitespace, and any quotes and backslash characters are +not considered special (every character is taken literally). Disables +the logical end of file marker string, which is treated like any other +argument. + +The specified delimiter may be a single character, a C-style character +escape such as @samp{\n}, or an octal or hexadecimal escape code. +Octal and hexadecimal escape codes are understood as for the +@code{printf} command. Multibyte characters are not supported. + +@item -E @var{eof-str} +@itemx --eof@r{[}=@var{eof-str}@r{]} +@itemx -e@r{[}@var{eof-str}@r{]} + +Set the logical end of file marker string to @var{eof-str}. If the +logical end of file marker string occurs as a line of input, the rest of +the input is ignored. If @var{eof-str} is omitted (@samp{-e}) or blank +(either @samp{-e} or @samp{-E}), there is no logical end of file marker +string. The @samp{-e} form of this option is deprecated in favour of +the POSIX-compliant @samp{-E} option, which you should use instead. As +of GNU @code{xargs} version 4.2.9, the default behaviour of @code{xargs} +is not to have a logical end of file marker string. The POSIX standard +(IEEE Std 1003.1, 2004 Edition) allows this. + +The logical end of file marker string is not treated specially if the +@samp{-d} or the @samp{-0} options are in effect. That is, when either +of these options are in effect, the whole input file will be read even +if @samp{-E} was used. + +@item --help +Print a summary of the options to @code{xargs} and exit. + +@item -I @var{replace-str} +@itemx --replace@r{[}=@var{replace-str}@r{]} +@itemx -i@r{[}@var{replace-str}@r{]} +Replace occurrences of @var{replace-str} in the initial arguments with +names read from standard input. Also, unquoted blanks do not +terminate arguments; instead, the input is split at newlines only. If +@var{replace-str} is omitted (omitting it is allowed only for +@samp{-i}), it defaults to @samp{@{@}} (like for @samp{find -exec}). +Implies @samp{-x} and @samp{-l 1}. The @samp{-i} option is deprecated +in favour of the @samp{-I} option. + +@item -L @var{max-lines} +@itemx --max-lines@r{[}=@var{max-lines}@r{]} +@itemx -l@r{[}@var{max-lines}@r{]} +Use at most @var{max-lines} non-blank input lines per command line. +For @samp{-l}, @var{max-lines} defaults to 1 if omitted. For +@samp{-L}, the argument is mandatory. Trailing blanks cause an input +line to be logically continued on the next input line, for the purpose +of counting the lines. Implies @samp{-x}. The @samp{-l} form of this +option is deprecated in favour of the POSIX-compliant @samp{-L} +option. + +@item --max-args=@var{max-args} +@itemx -n @var{max-args} +Use at most @var{max-args} arguments per command line. Fewer than +@var{max-args} arguments will be used if the size (see the @samp{-s} +option) is exceeded, unless the @samp{-x} option is given, in which +case @code{xargs} will exit. + +@item --interactive +@itemx -p +Prompt the user about whether to run each command line and read a line +from the terminal. Only run the command line if the response starts +with @samp{y} or @samp{Y}. Implies @samp{-t}. + +@item --no-run-if-empty +@itemx -r +If the standard input is completely empty, do not run the +command. By default, the command is run once even if there is no +input. + +@item --max-chars=@var{max-chars} +@itemx -s @var{max-chars} +Use at most @var{max-chars} characters per command line, including the +command, initial arguments and any terminating nulls at the ends of +the argument strings. + +@item --show-limits +Display the limits on the command-line length which are imposed by the +operating system, @code{xargs}' choice of buffer size and the +@samp{-s} option. Pipe the input from @file{/dev/null} (and perhaps +specify @samp{--no-run-if-empty}) if you don't want @code{xargs} to do +anything. + +@item --verbose +@itemx -t +Print the command line on the standard error output before executing +it. + +@item --version +Print the version number of @code{xargs} and exit. + +@item --exit +@itemx -x +Exit if the size (see the @samp{-s} option) is exceeded. + + +@item --max-procs=@var{max-procs} +@itemx -P @var{max-procs} +Run simultaneously up to @var{max-procs} processes at once; the default is 1. If +@var{max-procs} is 0, @code{xargs} will run as many processes as +possible simultaneously. @xref{Controlling Parallelism}, for +information on dynamically controlling parallelism. + +@item --process-slot-var=@var{environment-variable-name} +Set the environment variable @var{environment-variable-name} to a +unique value in each running child process. Each value is a decimal +integer. Values are reused once child processes exit. This can be +used in a rudimentary load distribution scheme, for example. +@end table + +@node Invoking the shell from xargs +@subsection Invoking the shell from xargs + +Normally, @code{xargs} will exec the command you specified directly, +without invoking a shell. This is normally the behaviour one would +want. It's somewhat more efficient and avoids problems with shell +metacharacters, for example. However, sometimes it is necessary to +manipulate the environment of a command before it is run, in a way +that @code{xargs} does not directly support. + +Invoking a shell from @code{xargs} is a good way of performing such +manipulations. However, some care must be taken to prevent problems, +for example unwanted interpretation of shell metacharacters. + +This command moves a set of files into an archive directory: + +@example +find /foo -maxdepth 1 -atime +366 -exec mv @{@} /archive \; +@end example + +However, this will only move one file at a time. We cannot in this +case use @code{-exec ... +} because the matched file names are added +at the end of the command line, while the destination directory would +need to be specified last. We also can't use @code{xargs} in the +obvious way for the same reason. One way of working around this +problem is to make use of the special properties of GNU @code{mv}; it +has a @code{-t} option that allows the target directory to be +specified before the list of files to be moved. However, while this +technique works for GNU @code{mv}, it doesn't solve the more general +problem. + +Here is a more general technique for solving this problem: + +@example +find /foo -maxdepth 1 -atime +366 -print0 | +xargs -r0 sh -c 'mv "$@@" /archive' move +@end example + +Here, a shell is being invoked. There are two shell instances to think +about. The first is the shell which launches the @code{xargs} command +(this might be the shell into which you are typing, for example). The +second is the shell launched by @code{xargs} (in fact it will probably +launch several, one after the other, depending on how many files need to +be archived). We'll refer to this second shell as a subshell. + +Our example uses the @code{-c} option of @code{sh}. Its argument is a +shell command to be executed by the subshell. Along with the rest of +that command, the $@@ is enclosed by single quotes to make sure it is +passed to the subshell without being expanded by the parent shell. It +is also enclosed with double quotes so that the subshell will expand +@code{$@@} correctly even if one of the file names contains a space or +newline. + +The subshell will use any non-option arguments as positional +parameters (that is, in the expansion of @code{$@@}). Because +@code{xargs} launches the @code{sh -c} subshell with a list of files, +those files will end up as the expansion of @code{$@@}. + +You may also notice the @samp{move} at the end of the command line. +This is used as the value of @code{$0} by the subshell. We include it +because otherwise the name of the first file to be moved would be used +instead. If that happened it would not be included in the subshell's +expansion of @code{$@@}, and so it wouldn't actually get moved. + + +Another reason to use the @code{sh -c} construct could be to +perform redirection: + +@example +find /usr/include -name '*.h' | xargs grep -wl mode_t | +xargs -r sh -c 'exec emacs "$@@" < /dev/tty' Emacs +@end example + +Notice that we use the shell builtin @code{exec} here. That's simply +because the subshell needs to do nothing once Emacs has been invoked. +Therefore instead of keeping a @code{sh} process around for no reason, +we just arrange for the subshell to exec Emacs, saving an extra +process creation. + +Sometimes, though, it can be helpful to keep the shell process around: + +@example +find /foo -maxdepth 1 -atime +366 -print0 | +xargs -r0 sh -c 'mv "$@@" /archive || exit 255' move +@end example + +Here, the shell will exit with status 255 if any @code{mv} failed. +This causes @code{xargs} to stop immediately. + + +@node Regular Expressions +@section Regular Expressions + +The @samp{-regex} and @samp{-iregex} tests of @code{find} allow +matching by regular expression, as does the @samp{--regex} option of +@code{locate}. + +Your locale configuration affects how regular expressions are +interpreted. @xref{Environment Variables}, for a description of how +your locale setup affects the interpretation of regular expressions. + +There are also several different types of regular expression, and +these are interpreted differently. Normally, the type of regular +expression used by @code{find} and @code{locate} is the same as is +used in GNU Emacs. Both programs provide an option which allows you +to select an alternative regular expression syntax; for @code{find} +this is the @samp{-regextype} option, and for @code{locate} this is +the @samp{--regextype} option. + +These options take a single argument, which indicates the specific +regular expression syntax and behaviour that should be used. This +should be one of the following: + +@include regexprops.texi + +@node Environment Variables +@section Environment Variables +@c TODO: check the variable index still contains references to these +@table @code +@item LANG +Provides a default value for the internationalisation variables that +are unset or null. + +@item LC_ALL +If set to a non-empty string value, override the values of all the +other internationalisation variables. + +@item LC_COLLATE +The POSIX standard specifies that this variable affects the pattern +matching to be used for the `\-name' option. GNU find uses the +GNU version of the @code{fnmatch} library function. + +This variable also affects the interpretation of the response to +@code{-ok}; while the @code{LC_MESSAGES} variable selects the actual +pattern used to interpret the response to @code{-ok}, the interpretation +of any bracket expressions in the pattern will be affected by the +@code{LC_COLLATE} variable. + +@item LC_CTYPE +This variable affects the treatment of character classes used in +regular expression and with +the @samp{-name} test, if the @code{fnmatch} function supports this. + +This variable also affects the interpretation of any character classes +in the regular expressions used to interpret the response to the +prompt issued by @code{-ok}. The @code{LC_CTYPE} environment variable will +also affect which characters are considered to be unprintable when +filenames are printed (@pxref{Unusual Characters in File Names}). + +@item LC_MESSAGES +Determines the locale to be used for internationalised messages, +including the interpretation of the response to the prompt made by the +@code{-ok} action. + +@item NLSPATH +Determines the location of the internationalisation message catalogues. + +@item PATH +Affects the directories which are searched to find the executables +invoked by @samp{-exec}, @samp{-execdir} @samp{-ok} and @samp{-okdir}. +If the @var{PATH} environment variable includes the current directory +(by explicitly including @samp{.} or by having an empty element), and +the find command line includes @samp{-execdir} or @samp{-okdir}, +@code{find} will refuse to run. @xref{Security Considerations}, for a +more detailed discussion of security matters. + +@item POSIXLY_CORRECT +Determines the block size used by @samp{-ls} and @samp{-fls}. If +@code{POSIXLY_CORRECT} is set, blocks are units of 512 bytes. Otherwise +they are units of 1024 bytes. + +Setting this variable also turns off warning messages (that is, implies +@samp{-nowarn}) by default, because POSIX requires that apart from +the output for @samp{-ok}, all messages printed on stderr are +diagnostics and must result in a non-zero exit status. + +When @code{POSIXLY_CORRECT} is set, the response to the prompt made by the +@code{-ok} action is interpreted according to the system's message +catalogue, as opposed to according to @code{find}'s own message +translations. + +@item TZ +Affects the time zone used for some of the time-related format +directives of @samp{-printf} and @samp{-fprintf}. +@end table + + + +@node Common Tasks +@chapter Common Tasks + +The sections that follow contain some extended examples that both give +a good idea of the power of these programs, and show you how to solve +common real-world problems. + +@menu +* Viewing And Editing:: +* Archiving:: +* Cleaning Up:: +* Strange File Names:: +* Fixing Permissions:: +* Classifying Files:: +@end menu + +@node Viewing And Editing +@section Viewing And Editing + +To view a list of files that meet certain criteria, simply run your +file viewing program with the file names as arguments. Shells +substitute a command enclosed in backquotes with its output, so the +whole command looks like this: + +@example +less `find /usr/include -name '*.h' | xargs grep -l mode_t` +@end example + +@noindent +You can edit those files by giving an editor name instead of a file +viewing program: + +@example +emacs `find /usr/include -name '*.h' | xargs grep -l mode_t` +@end example + +Because there is a limit to the length of any individual command line, +there is a limit to the number of files that can be handled in this way. +We can get around this difficulty by using @code{xargs} like this: + +@example +find /usr/include -name '*.h' | xargs grep -l mode_t > todo +xargs --arg-file=todo emacs +@end example + +Here, @code{xargs} will run @code{emacs} as many times as necessary to +visit all of the files listed in the file @file{todo}. Generating a +temporary file is not always convenient, though. This command does +much the same thing without needing one: + +@example +find /usr/include -name '*.h' | xargs grep -l mode_t | +xargs sh -c 'emacs "$@@" < /dev/tty' Emacs +@end example + +The example above illustrates a useful trick; Using @code{sh -c} you +can invoke a shell command from @code{xargs}. The @code{$@@} in the +command line is expanded by the shell to a list of arguments as +provided by @code{xargs}. The single quotes in the command line +protect the @code{$@@} against expansion by your interactive shell +(which will normally have no arguments and thus expand @code{$@@} to +nothing). The capitalised @samp{Emacs} on the command line is used as +@code{$0} by the shell that @code{xargs} launches. + +@node Archiving +@section Archiving + +You can pass a list of files produced by @code{find} to a file +archiving program. GNU @code{tar} and @code{cpio} can both read lists +of file names from the standard input -- either delimited by nulls (the +safe way) or by blanks (the lazy, risky default way). To use +null-delimited names, give them the @samp{--null} option. You can +store a file archive in a file, write it on a tape, or send it over a +network to extract on another machine. + +One common use of @code{find} to archive files is to send a list of +the files in a directory tree to @code{cpio}. Use @samp{-depth} so if +a directory does not have write permission for its owner, its contents +can still be restored from the archive since the directory's +permissions are restored after its contents. Here is an example of +doing this using @code{cpio}; you could use a more complex @code{find} +expression to archive only certain files. + +@example +find . -depth -print0 | + cpio --create --null --format=crc --file=/dev/nrst0 +@end example + +You could restore that archive using this command: + +@example +cpio --extract --null --make-dir --unconditional \ + --preserve --file=/dev/nrst0 +@end example + +Here are the commands to do the same things using @code{tar}: + +@example +find . -depth -print0 | + tar --create --null --files-from=- --file=/dev/nrst0 + +tar --extract --null --preserve-perm --same-owner \ + --file=/dev/nrst0 +@end example + +@c Idea from Rick Sladkey. +Here is an example of copying a directory from one machine to another: + +@example +find . -depth -print0 | cpio -0o -Hnewc | + rsh @var{other-machine} "cd `pwd` && cpio -i0dum" +@end example + +@node Cleaning Up +@section Cleaning Up + +@c Idea from Jim Meyering. +This section gives examples of removing unwanted files in various +situations. Here is a command to remove the CVS backup files created +when an update requires a merge: + +@example +find . -name '.#*' -print0 | xargs -0r rm -f +@end example + +If your @code{find} command removes directories, you may find that +you get a spurious error message when @code{find} tries to recurse +into a directory that has now been removed. Using the @samp{-depth} +option will normally resolve this problem. + +@c What does the following sentence mean? Why is -delete safer? --kasal +@c The command above works, but the following is safer: + +It is also possible to use the @samp{-delete} action: + +@example +find . -depth -name '.#*' -delete +@end example + +@c Idea from Franc,ois Pinard. +You can run this command to clean out your clutter in @file{/tmp}. +You might place it in the file your shell runs when you log out +(@file{.bash_logout}, @file{.logout}, or @file{.zlogout}, depending on +which shell you use). + +@example +find /tmp -depth -user "$LOGNAME" -type f -delete +@end example + +@c Idea from Noah Friedman. +To remove old Emacs backup and auto-save files, you can use a command +like the following. It is especially important in this case to use +null-terminated file names because Emacs packages like the VM mailer +often create temporary file names with spaces in them, like +@file{#reply to David J. MacKenzie<1>#}. + +@example +find ~ \( -name '*~' -o -name '#*#' \) -print0 | + xargs --no-run-if-empty --null rm -vf +@end example + +Removing old files from @file{/tmp} is commonly done from @code{cron}: + +@c Idea from Kaveh Ghazi. +@example +find /tmp /var/tmp -depth -not -type d -mtime +3 -delete +find /tmp /var/tmp -depth -mindepth 1 -type d -empty -delete +@end example + +The second @code{find} command above cleans out empty directories +depth-first (@samp{-delete} implies @samp{-depth} anyway), hoping that +the parents become empty and can be removed too. It uses +@samp{-mindepth} to avoid removing @file{/tmp} itself if it becomes +totally empty. + + +Lastly, an example of a program that almost certainly does not do what +the user intended: + +@c inspired by Savannah bug #20865 (Bruno De Fraine) +@example +find dirname -delete -name quux +@end example + +If the user hoped to delete only files named @file{quux} they will get +an unpleasant surprise; this command will attempt to delete everything +at or below the starting point @file{dirname}. This is because +@code{find} evaluates the items on the command line as an expression. +The @code{find} program will normally execute an action if the +preceding action succeeds. Here, there is no action or test before +the @samp{-delete} so it will always be executed. The @samp{-name +quux} test will be performed for files we successfully deleted, but +that test has no effect since @samp{-delete} also disables the default +@samp{-print} operation. So the above example will probably delete a +lot of files the user didn't want to delete. + +This command is also likely to do something you did not intend: +@example +find dirname -path dirname/foo -prune -o -delete +@end example + +Because @samp{-delete} turns on @samp{-depth}, the @samp{-prune} +action has no effect and files in @file{dirname/foo} will be deleted +too. + + +@node Strange File Names +@section Strange File Names + +@c Idea from: +@c From: tmatimar@isgtec.com (Ted Timar) +@c Newsgroups: comp.unix.questions,comp.unix.shell,comp.answers,news.answers +@c Subject: Unix - Frequently Asked Questions (2/7) [Frequent posting] +@c Subject: How do I remove a file with funny characters in the filename ? +@c Date: Thu Mar 18 17:16:55 EST 1993 +@code{find} can help you remove or rename a file with strange +characters in its name. People are sometimes stymied by files whose +names contain characters such as spaces, tabs, control characters, or +characters with the high bit set. The simplest way to remove such +files is: + +@example +rm -i @var{some*pattern*that*matches*the*problem*file} +@end example + +@code{rm} asks you whether to remove each file matching the given +pattern. If you are using an old shell, this approach might not work +if the file name contains a character with the high bit set; the shell +may strip it off. A more reliable way is: + +@example +find . -maxdepth 1 @var{tests} -okdir rm '@{@}' \; +@end example + +@noindent +where @var{tests} uniquely identify the file. The @samp{-maxdepth 1} +option prevents @code{find} from wasting time searching for the file +in any subdirectories; if there are no subdirectories, you may omit +it. A good way to uniquely identify the problem file is to figure out +its inode number; use + +@example +ls -i +@end example + +Suppose you have a file whose name contains control characters, and +you have found that its inode number is 12345. This command prompts +you for whether to remove it: + +@example +find . -maxdepth 1 -inum 12345 -okdir rm -f '@{@}' \; +@end example + +If you don't want to be asked, perhaps because the file name may +contain a strange character sequence that will mess up your screen +when printed, then use @samp{-execdir} instead of @samp{-okdir}. + +If you want to rename the file instead, you can use @code{mv} instead +of @code{rm}: + +@example +find . -maxdepth 1 -inum 12345 -okdir mv '@{@}' @var{new-file-name} \; +@end example + +@node Fixing Permissions +@section Fixing Permissions + +Suppose you want to make sure that everyone can write to the +directories in a certain directory tree. Here is a way to find +directories lacking either user or group write permission (or both), +and fix their permissions: + +@example +find . -type d -not -perm -ug=w | xargs chmod ug+w +@end example + +@noindent +You could also reverse the operations, if you want to make sure that +directories do @emph{not} have world write permission. + +@node Classifying Files +@section Classifying Files + +@c Idea from: +@c From: martin@mwtech.UUCP (Martin Weitzel) +@c Newsgroups: comp.unix.wizards,comp.unix.questions +@c Subject: Advanced usage of 'find' (Re: Unix security automating script) +@c Date: 22 Mar 90 15:05:19 GMT +If you want to classify a set of files into several groups based on +different criteria, you can use the comma operator to perform multiple +independent tests on the files. Here is an example: + +@example +find / -type d \( -perm -o=w -fprint allwrite , \ + -perm -o=x -fprint allexec \) + +echo "Directories that can be written to by everyone:" +cat allwrite +echo "" +echo "Directories with search permissions for everyone:" +cat allexec +@end example + +@code{find} has only to make one scan through the directory tree +(which is one of the most time consuming parts of its work). + +@node Worked Examples +@chapter Worked Examples + +The tools in the findutils package, and in particular @code{find}, +have a large number of options. This means that quite often, +there is more than one way to do things. Some of the options +and facilities only exist for compatibility with other tools, and +findutils provides improved ways of doing things. + +This chapter describes a number of useful tasks that are commonly +performed, and compares the different ways of achieving them. + +@menu +* Deleting Files:: +* Copying A Subset of Files:: +* Updating A Timestamp File:: +* Finding the Shallowest Instance:: +@end menu + +@node Deleting Files +@section Deleting Files + +One of the most common tasks that @code{find} is used for is locating +files that can be deleted. This might include: + +@itemize +@item +Files last modified more than 3 years ago which haven't been accessed +for at least 2 years +@item +Files belonging to a certain user +@item +Temporary files which are no longer required +@end itemize + +This example concentrates on the actual deletion task rather than on +sophisticated ways of locating the files that need to be deleted. +We'll assume that the files we want to delete are old files underneath +@file{/var/tmp/stuff}. + +@subsection The Traditional Way + +The traditional way to delete files in @file{/var/tmp/stuff} that have +not been modified in over 90 days would have been: + +@smallexample +find /var/tmp/stuff -mtime +90 -exec /bin/rm @{@} \; +@end smallexample + +The above command uses @samp{-exec} to run the @code{/bin/rm} command +to remove each file. This approach works and in fact would have +worked in Version 7 Unix in 1979. However, there are a number of +problems with this approach. + + +The most obvious problem with the approach above is that it causes +@code{find} to fork every time it finds a file that needs to delete, +and the child process then has to use the @code{exec} system call to +launch @code{/bin/rm}. All this is quite inefficient. If we are +going to use @code{/bin/rm} to do this job, it is better to make it +delete more than one file at a time. + +The most obvious way of doing this is to use the shell's command +expansion feature: + +@smallexample +/bin/rm `find /var/tmp/stuff -mtime +90 -print` +@end smallexample +or you could use the more modern form +@smallexample +/bin/rm $(find /var/tmp/stuff -mtime +90 -print) +@end smallexample + +The commands above are much more efficient than the first attempt. +However, there is a problem with them. The shell has a maximum +command length which is imposed by the operating system (the actual +limit varies between systems). This means that while the command +expansion technique will usually work, it will suddenly fail when +there are lots of files to delete. Since the task is to delete +unwanted files, this is precisely the time we don't want things to go +wrong. + +@subsection Making Use of @code{xargs} + +So, is there a way to be more efficient in the use of @code{fork()} +and @code{exec()} without running up against this limit? +Yes, we can be almost optimally efficient by making use +of the @code{xargs} command. The @code{xargs} command reads arguments +from its standard input and builds them into command lines. We can +use it like this: + +@smallexample +find /var/tmp/stuff -mtime +90 -print | xargs /bin/rm +@end smallexample + +For example if the files found by @code{find} are +@file{/var/tmp/stuff/A}, +@file{/var/tmp/stuff/B} and +@file{/var/tmp/stuff/C} then @code{xargs} might issue the commands + +@smallexample +/bin/rm /var/tmp/stuff/A /var/tmp/stuff/B +/bin/rm /var/tmp/stuff/C +@end smallexample + +The above assumes that @code{xargs} has a very small maximum command +line length. The real limit is much larger but the idea is that +@code{xargs} will run @code{/bin/rm} as many times as necessary to get +the job done, given the limits on command line length. + +This usage of @code{xargs} is pretty efficient, and the @code{xargs} +command is widely implemented (all modern versions of Unix offer it). +So far then, the news is all good. However, there is bad news too. + +@subsection Unusual characters in filenames + +Unix-like systems allow any characters to appear in file names with +the exception of the ASCII NUL character and the slash. +Slashes can occur in path names (as the directory separator) but +not in the names of actual directory entries. This means that the +list of files that @code{xargs} reads could in fact contain white space +characters -- spaces, tabs and newline characters. Since by default, +@code{xargs} assumes that the list of files it is reading uses white +space as an argument separator, it cannot correctly handle the case +where a filename actually includes white space. This makes the +default behaviour of @code{xargs} almost useless for handling +arbitrary data. + +To solve this problem, GNU findutils introduced the @samp{-print0} +action for @code{find}. This uses the ASCII NUL character to separate +the entries in the file list that it produces. This is the ideal +choice of separator since it is the only character that cannot appear +within a path name. The @samp{-0} option to @code{xargs} makes it +assume that arguments are separated with ASCII NUL instead of white +space. It also turns off another misfeature in the default behaviour +of @code{xargs}, which is that it pays attention to quote characters +in its input. Some versions of @code{xargs} also terminate when they +see a lone @samp{_} in the input, but GNU @code{find} no longer does +that (since it has become an optional behaviour in the Unix standard). + +So, putting @code{find -print0} together with @code{xargs -0} we get +this command: + +@smallexample +find /var/tmp/stuff -mtime +90 -print0 | xargs -0 /bin/rm +@end smallexample + +The result is an efficient way of proceeding that +correctly handles all the possible characters that could appear in the +list of files to delete. This is good news. However, there is, as +I'm sure you're expecting, also more bad news. The problem is that +this is not a portable construct; although other versions of Unix +(notably BSD-derived ones) support @samp{-print0}, it's not +universal. So, is there a more universal mechanism? + +@subsection Going back to @code{-exec} + +There is indeed a more universal mechanism, which is a slight +modification to the @samp{-exec} action. The normal @samp{-exec} +action assumes that the command to run is terminated with a semicolon +(the semicolon normally has to be quoted in order to protect it from +interpretation as the shell command separator). The SVR4 edition of +Unix introduced a slight variation, which involves terminating the +command with @samp{+} instead: + +@smallexample +find /var/tmp/stuff -mtime +90 -exec /bin/rm @{@} \+ +@end smallexample + +The above use of @samp{-exec} causes @code{find} to build up a long +command line and then issue it. This can be less efficient than some +uses of @code{xargs}; for example @code{xargs} allows new command +lines to be built up while the previous command is still executing, and +allows you to specify a number of commands to run in parallel. +However, the @code{find @dots{} -exec @dots{} +} construct has the advantage +of wide portability. GNU findutils did not support @samp{-exec @dots{} +} +until version 4.2.12; one of the reasons for this is that it already +had the @samp{-print0} action in any case. + + +@subsection A more secure version of @code{-exec} + +The command above seems to be efficient and portable. However, +within it lurks a security problem. The problem is shared with +all the commands we've tried in this worked example so far, too. The +security problem is a race condition; that is, if it is possible for +somebody to manipulate the filesystem that you are searching while you +are searching it, it is possible for them to persuade your @code{find} +command to cause the deletion of a file that you can delete but they +normally cannot. + +The problem occurs because the @samp{-exec} action is defined by the +POSIX standard to invoke its command with the same working directory +as @code{find} had when it was started. This means that the arguments +which replace the @{@} include a relative path from @code{find}'s +starting point down the file that needs to be deleted. For example, + +@smallexample +find /var/tmp/stuff -mtime +90 -exec /bin/rm @{@} \+ +@end smallexample + +might actually issue the command: + +@smallexample +/bin/rm /var/tmp/stuff/A /var/tmp/stuff/B /var/tmp/stuff/passwd +@end smallexample + +Notice the file @file{/var/tmp/stuff/passwd}. Likewise, the command: + +@smallexample +cd /var/tmp && find stuff -mtime +90 -exec /bin/rm @{@} \+ +@end smallexample + +might actually issue the command: + +@smallexample +/bin/rm stuff/A stuff/B stuff/passwd +@end smallexample + +If an attacker can rename @file{stuff} to something else (making use +of their write permissions in @file{/var/tmp}) they can replace it +with a symbolic link to @file{/etc}. That means that the +@code{/bin/rm} command will be invoked on @file{/etc/passwd}. If you +are running your @code{find} command as root, the attacker has just managed +to delete a vital file. All they needed to do to achieve this was +replace a subdirectory with a symbolic link at the vital moment. + +There is however, a simple solution to the problem. This is an action +which works a lot like @code{-exec} but doesn't need to traverse a +chain of directories to reach the file that it needs to work on. This +is the @samp{-execdir} action, which was introduced by the BSD family +of operating systems. The command, + +@smallexample +find /var/tmp/stuff -mtime +90 -execdir /bin/rm @{@} \+ +@end smallexample + +might delete a set of files by performing these actions: + +@enumerate +@item +Change directory to /var/tmp/stuff/foo +@item +Invoke @code{/bin/rm ./file1 ./file2 ./file3} +@item +Change directory to /var/tmp/stuff/bar +@item +Invoke @code{/bin/rm ./file99 ./file100 ./file101} +@end enumerate + +This is a much more secure method. We are no longer exposed to a race +condition. For many typical uses of @code{find}, this is the best +strategy. It's reasonably efficient, but the length of the command +line is limited not just by the operating system limits, but also by +how many files we actually need to delete from each directory. + +Is it possible to do any better? In the case of general file +processing, no. However, in the specific case of deleting files it is +indeed possible to do better. + +@subsection Using the @code{-delete} action + +The most efficient and secure method of solving this problem is to use +the @samp{-delete} action: + +@smallexample +find /var/tmp/stuff -mtime +90 -delete +@end smallexample + +This alternative is more efficient than any of the @samp{-exec} or +@samp{-execdir} actions, since it entirely avoids the overhead of +forking a new process and using @code{exec} to run @code{/bin/rm}. It +is also normally more efficient than @code{xargs} for the same +reason. The file deletion is performed from the directory containing +the entry to be deleted, so the @samp{-delete} action has the same +security advantages as the @samp{-execdir} action has. + +The @samp{-delete} action was introduced by the BSD family of +operating systems. + +@subsection Improving things still further + +Is it possible to improve things still further? Not without either +modifying the system library to the operating system or having more specific +knowledge of the layout of the filesystem and disk I/O subsystem, or +both. + +The @code{find} command traverses the filesystem, reading +directories. It then issues a separate system call for each file to +be deleted. If we could modify the operating system, there are +potential gains that could be made: + +@itemize +@item +We could have a system call to which we pass more than one filename +for deletion +@item +Alternatively, we could pass in a list of inode numbers (on GNU/Linux +systems, @code{readdir()} also returns the inode number of each +directory entry) to be deleted. +@end itemize + +The above possibilities sound interesting, but from the kernel's point +of view it is difficult to enforce standard Unix access controls for +such processing by inode number. Such a facility would probably +need to be restricted to the superuser. + +Another way of improving performance would be to increase the +parallelism of the process. For example if the directory hierarchy we +are searching is actually spread across a number of disks, we might +somehow be able to arrange for @code{find} to process each disk in +parallel. In practice GNU @code{find} doesn't have such an intimate +understanding of the system's filesystem layout and disk I/O +subsystem. + +However, since the system administrator can have such an understanding +they can take advantage of it like so: + +@smallexample +find /var/tmp/stuff1 -mtime +90 -delete & +find /var/tmp/stuff2 -mtime +90 -delete & +find /var/tmp/stuff3 -mtime +90 -delete & +find /var/tmp/stuff4 -mtime +90 -delete & +wait +@end smallexample + +In the example above, four separate instances of @code{find} are used +to search four subdirectories in parallel. The @code{wait} command +simply waits for all of these to complete. Whether this approach is +more or less efficient than a single instance of @code{find} depends +on a number of things: + +@itemize +@item +Are the directories being searched in parallel actually on separate +disks? If not, this parallel search might just result in a lot of +disk head movement and so the speed might even be slower. +@item +Other activity - are other programs also doing things on those disks? +@end itemize + + +@subsection Conclusion + +The fastest and most secure way to delete files with the help of +@code{find} is to use @samp{-delete}. Using @code{xargs -0 -P N} can +also make effective use of the disk, but it is not as secure. + +In the case where we're doing things other than deleting files, the +most secure alternative is @samp{-execdir @dots{} +}, but this is not as +portable as the insecure action @samp{-exec @dots{} +}. + +The @samp{-delete} action is not completely portable, but the only +other possibility which is as secure (@samp{-execdir}) is no more +portable. The most efficient portable alternative is @samp{-exec +@dots{}+}, but this is insecure and isn't supported by versions of GNU +findutils prior to 4.2.12. + +@node Copying A Subset of Files +@section Copying A Subset of Files + +Suppose you want to copy some files from @file{/source-dir} to +@file{/dest-dir}, but there are a small number of files in +@file{/source-dir} you don't want to copy. + +One option of course is @code{cp /source-dir /dest-dir} followed by +deletion of the unwanted material under @file{/dest-dir}. But often +that can be inconvenient, because for example we would have copied a +large amount of extraneous material, or because @file{/dest-dir} is +too small. Naturally there are many other possible reasons why this +strategy may be unsuitable. + +So we need to have some way of identifying which files we want to +copy, and we need to have a way of copying that file list. The second +part of this condition is met by @code{cpio -p}. Of course, we can +identify the files we wish to copy by using @code{find}. Here is a +command that solves our problem: + +@example +cd /source-dir +find . -name '.snapshot' -prune -o \( \! -name '*~' -print0 \) | +cpio -pmd0 /dest-dir +@end example + +The first part of the @code{find} command here identifies files or +directories named @file{.snapshot} and tells @code{find} not to +recurse into them (since they do not need to be copied). The +combination @code{-name '.snapshot' -prune} yields false for anything +that didn't get pruned, but it is exactly those files we want to +copy. Therefore we need to use an OR (@samp{-o}) condition to +introduce the rest of our expression. The remainder of the expression +simply arranges for the name of any file not ending in @samp{~} to be +printed. + +Using @code{-print0} ensures that white space characters in file names +do not pose a problem. The @code{cpio} command does the actual work +of copying files. The program as a whole fails if the @code{cpio} +program returns nonzero. If the @code{find} command returns non-zero +on the other hand, the Unix shell will not diagnose a problem (since +@code{find} is not the last command in the pipeline). + + +@node Updating A Timestamp File +@section Updating A Timestamp File + +Suppose we have a directory full of files which is maintained with a +set of automated tools; perhaps one set of tools updates them and +another set of tools uses the result. In this situation, it might be +useful for the second set of tools to know if the files have recently +been changed. It might be useful, for example, to have a 'timestamp' +file which gives the timestamp on the newest file in the collection. + +We can use @code{find} to achieve this, but there are several +different ways to do it. + +@subsection Updating the Timestamp The Wrong Way + +The obvious but wrong answer is just to use @samp{-newer}: + +@smallexample +find subdir -newer timestamp -exec touch -r @{@} timestamp \; +@end smallexample + +This does the right sort of thing but has a bug. Suppose that two +files in the subdirectory have been updated, and that these are called +@file{file1} and @file{file2}. The command above will update +@file{timestamp} with the modification time of @file{file1} or that of +@file{file2}, but we don't know which one. Since the timestamps on +@file{file1} and @file{file2} will in general be different, this could +well be the wrong value. + +One solution to this problem is to modify @code{find} to recheck the +modification time of @file{timestamp} every time a file is to be +compared against it, but that will reduce the performance of +@code{find}. + +@subsection Using the test utility to compare timestamps + +The @code{test} command can be used to compare timestamps: + +@smallexample +find subdir -exec test @{@} -nt timestamp \; -exec touch -r @{@} timestamp \; +@end smallexample + +This will ensure that any changes made to the modification time of +@file{timestamp} that take place during the execution of @code{find} +are taken into account. This resolves our earlier problem, but +unfortunately this runs much more slowly. + +@subsection A combined approach + +We can of course still use @samp{-newer} to cut down on the number of +calls to @code{test}: + +@smallexample +find subdir -newer timestamp -and \ + -exec test @{@} -nt timestamp \; -and \ + -exec touch -r @{@} timestamp \; +@end smallexample + +Here, the @samp{-newer} test excludes all the files which are +definitely older than the timestamp, but all the files which are newer +than the old value of the timestamp are compared against the current +updated timestamp. + +This is indeed faster in general, but the speed difference will depend +on how many updated files there are. + +@subsection Using @code{-printf} and @code{sort} to compare timestamps + +It is possible to use the @samp{-printf} action to abandon the use of +@code{test} entirely: + +@smallexample +newest=$(find subdir -newer timestamp -printf "%A@:%p\n" | + sort -n | + tail -1 | + cut -d: -f2- ) +touch -r "$@{newest:-timestamp@}" timestamp +@end smallexample + +The command above works by generating a list of the timestamps and +names of all the files which are newer than the timestamp. The +@code{sort}, @code{tail} and @code{cut} commands simply pull out the +name of the file with the largest timestamp value (that is, the latest +file). The @code{touch} command is then used to update the timestamp, + +The @code{"$@{newest:-timestamp@}"} expression simply expands to the +value of @code{$newest} if that variable is set, but to +@file{timestamp} otherwise. This ensures that an argument is always +given to the @samp{-r} option of the @code{touch} command. + +This approach seems quite efficient, but unfortunately it has a +problem. Many operating systems now keep file modification time +information at a granularity which is finer than one second. +Findutils version 4.3.3 and later will print a fractional part with +%A@@, but older versions will not. + + +@subsection Solving the problem with @code{make} + +Another tool which often works with timestamps is @code{make}. We can +use @code{find} to generate a @file{Makefile} file on the fly and then +use @code{make} to update the timestamps: + +@smallexample +makefile=$(mktemp) +find subdir \ + \( \! -xtype l \) \ + -newer timestamp \ + -printf "timestamp:: %p\n\ttouch -r %p timestamp\n\n" > "$makefile" +make -f "$makefile" +rm -f "$makefile" +@end smallexample + +Unfortunately although the solution above is quite elegant, it fails +to cope with white space within file names, and adjusting it to do so +would require a rather complex shell script. + + +@subsection Coping with odd filenames too + +We can fix both of these problems (looping and problems with white +space), and do things more efficiently too. The following command +works with newlines and doesn't need to sort the list of filenames. + +@smallexample +find subdir -newer timestamp -printf "%A@@:%p\0" | + perl -0 newest.pl | + xargs --no-run-if-empty --null -i \ + find @{@} -maxdepth 0 -newer timestamp -exec touch -r @{@} timestamp \; +@end smallexample + +The first @code{find} command generates a list of files which are +newer than the original timestamp file, and prints a list of them with +their timestamps. The @file{newest.pl} script simply filters out all +the filenames which have timestamps which are older than whatever the +newest file is: + +@smallexample +@verbatim +#! /usr/bin/perl -0 +my @newest = (); +my $latest_stamp = undef; +while (<>) { + my ($stamp, $name) = split(/:/); + if (!defined($latest_stamp) || ($tstamp > $latest_stamp)) { + $latest_stamp = $stamp; + @newest = (); + } + if ($tstamp >= $latest_stamp) { + push @newest, $name; + } +} +print join("\0", @newest); +@end verbatim +@end smallexample + +This prints a list of zero or more files, all of which are newer than +the original timestamp file, and which have the same timestamp as each +other, to the nearest second. The second @code{find} command takes +each resulting file one at a time, and if that is newer than the +timestamp file, the timestamp is updated. + +@node Finding the Shallowest Instance +@section Finding the Shallowest Instance + +Suppose you maintain local copies of sources from various projects, +each with their own choice of directory organisation and source code +management (SCM) tool. You need to periodically synchronize each +project with its upstream tree. As the number local repositories +grows, so does the work involved in maintaining synchronization. SCM +utilities typically create some sort of administrative directory: .svn +for Subversion, CVS for CVS, and so on. These directories can be used +as a key to search for the bases of the project source trees. Suppose +we have the following directory structure: + +@smallexample +repo/project1/CVS +repo/gnu/project2/.svn +repo/gnu/project3/.svn +repo/gnu/project3/src/.svn +repo/gnu/project3/doc/.svn +repo/project4/.git +@end smallexample + +One would expect to update each of the @file{projectX} directories, +but not their subdirectories (src, doc, etc.). To locate the project +roots, we would need to find the least deeply nested directories +containing an SCM-related subdirectory. The following command +discovers those roots efficiently. It is efficient because it avoids +searching subdirectories inside projects whose SCM directory we +already found. + +@smallexample +find repo/ \ +-exec test -d @{@}/.svn \; -or \ +-exec test -d @{@}/.git \; -or \ +-exec test -d @{@}/CVS \; -print -prune +@end smallexample + +In this example, @command{test} is used to tell if we are currently +examining a directory which appears to the a project's root directory +(because it has an SCM subdirectory). When we find a project root, +there is no need to search inside it, and @code{-prune} makes sure +that we descend no further. + +For large, complex trees like the Linux kernel, this will prevent +searching a large portion of the structure, saving a good deal of +time. + + +@node Security Considerations +@chapter Security Considerations + +Security considerations are important if you are using @code{find} or +@code{xargs} to search for or process files that don't belong to you +or which other people have control. Security considerations +relating to @code{locate} may also apply if you have files which you +do not want others to see. + +The most severe forms of security problems affecting +@code{find} and related programs are when third parties bring +about a situation allowing them to do something +they would normally not be able to accomplish. This is called @emph{privilege +elevation}. This might include deleting files they would not normally +be able to delete. It is common for the operating system to periodically +invoke @code{find} for self-maintenance purposes. These invocations of +@code{find} are particularly problematic from a security point of view +as these are often invoked by the superuser and search the entire +filesystem hierarchy. Generally, the severity of any associated problem depends +on what the system is going to do with the files found by @code{find}. + +@menu +* Levels of Risk:: What is your level of exposure to security problems? +* Security Considerations for find:: Security problems with find +* Security Considerations for xargs:: Security problems with xargs +* Security Considerations for locate:: Security problems with locate +* Security Summary:: That was all very complex, what does it boil down to? +* Further Reading on Security:: +@end menu + + +@node Levels of Risk +@section Levels of Risk + +There are some security risks inherent in the use of @code{find}, +@code{xargs} and (to a lesser extent) @code{locate}. The severity of +these risks depends on what sort of system you are using: + +@table @strong +@item High risk +Multi-user systems where you do not control (or trust) the other +users, and on which you execute @code{find}, including areas where +those other users can manipulate the filesystem (for example beneath +@file{/home} or @file{/tmp}). + +@item Medium Risk +Systems where the actions of other users can create file names chosen +by them, but to which they don't have access while @code{find} is +being run. This access might include leaving programs running (shell +background jobs, @code{at} or @code{cron} tasks, for example). On +these sorts of systems, carefully written commands (avoiding use of +@samp{-print} for example) should not expose you to a high degree of +risk. Most systems fall into this category. + +@item Low Risk +Systems to which untrusted parties do not have access, cannot create +file names of their own choice (even remotely) and which contain no +security flaws which might enable an untrusted third party to gain +access. Most systems do not fall into this category because there are +many ways in which external parties can affect the names of files that +are created on your system. The system on which I am writing this for +example automatically downloads software updates from the Internet; +the names of the files in which these updates exist are chosen by +third parties@footnote{Of course, I trust these parties to a large +extent anyway, because I install software provided by them; I choose +to trust them in this way, and that's a deliberate choice}. +@end table + +In the discussion above, ``risk'' denotes the likelihood that someone +can cause @code{find}, @code{xargs}, @code{locate} or some other +program which is controlled by them to do something you did not +intend. The levels of risk suggested do not take any account of the +consequences of this sort of event. That is, if you operate a ``low +risk'' type system, but the consequences of a security problem are +disastrous, then you should still give serious thought to all the +possible security problems, many of which of course will not be +discussed here -- this section of the manual is intended to be +informative but not comprehensive or exhaustive. + +If you are responsible for the operation of a system where the +consequences of a security problem could be very important, you should +do two things: + +@enumerate +@item Define a security policy which defines who is allowed to do what +on your system. +@item Seek competent advice on how to enforce your policy, detect +breaches of that policy, and take account of any potential problems +that might fall outside the scope of your policy. +@end enumerate + + +@node Security Considerations for find +@section Security Considerations for @code{find} + + +Some of the actions @code{find} might take have a direct effect; +these include @code{-exec} and @code{-delete}. However, it is also +common to use @code{-print} explicitly or implicitly, and so if +@code{find} produces the wrong list of file names, that can also be a +security problem; consider the case for example where @code{find} is +producing a list of files to be deleted. + +We normally assume that the @code{find} command line expresses the +file selection criteria and actions that the user had in mind -- that +is, the command line is ``trusted'' data. + +From a security analysis point of view, the output of @code{find} +should be correct; that is, the output should contain only the names +of those files which meet the user's criteria specified on the command +line. This applies for the @code{-exec} and @code{-delete} actions; +one can consider these to be part of the output. + +On the other hand, the contents of the filesystem can be manipulated +by other people, and hence we regard this as ``untrusted'' data. This +implies that the @code{find} command line is a filter which converts +the untrusted contents of the filesystem into a correct list of output +files. + +The filesystem will in general change while @code{find} is searching +it; in fact, most of the potential security problems with @code{find} +relate to this issue in some way. + +@dfn{Race conditions} are a general class of security problem where the +relative ordering of actions taken by @code{find} (for example) and +something else are critically important in getting the correct and expected result@footnote{This is more or less the +definition of the term ``race condition''} . + +For @code{find}, an attacker might move or rename files or directories in +the hope that an action might be taken against a file which was not +normally intended to be affected. Alternatively, this sort of attack +might be intended to persuade @code{find} to search part of the +filesystem which would not normally be included in the search +(defeating the @code{-prune} action for example). + +@menu +* Problems with -exec and filenames:: +* Changing the Current Working Directory:: +* Race Conditions with -exec:: +* Race Conditions with -print and -print0:: +@end menu + +@node Problems with -exec and filenames +@subsection Problems with @code{-exec} and filenames + +It is safe in many cases to use the @samp{-execdir} action with any +file name. Because @samp{-execdir} prefixes the arguments it passes +to programs with @samp{./}, you will not accidentally pass an argument +which is interpreted as an option. For example the file @file{-f} +would be passed to @code{rm} as @file{./-f}, which is harmless. + +However, your degree of safety does depend on the nature of the +program you are running. For example constructs such as these two commands + +@example +# risky +find -exec sh -c "something @{@}" \; +find -execdir sh -c "something @{@}" \; +@end example + +are very dangerous. The reason for this is that the @samp{@{@}} is +expanded to a filename which might contain a semicolon or other +characters special to the shell. If for example someone creates the +file @file{/tmp/foo; rm -rf $HOME} then the two commands above could +delete someone's home directory. + +So for this reason do not run any command which will pass untrusted +data (such as the names of files) to commands which interpret +arguments as commands to be further interpreted (for example +@samp{sh}). + +In the case of the shell, there is a clever workaround for this +problem: + +@example +# safer +find -exec sh -c 'something "$@@"' sh @{@} \; +find -execdir sh -c 'something "$@@"' sh @{@} \; +@end example + +This approach is not guaranteed to avoid every problem, but it is much +safer than substituting data of an attacker's choice into the text of +a shell command. + +@node Changing the Current Working Directory +@subsection Changing the Current Working Directory + +As @code{find} searches the filesystem, it finds subdirectories and +then searches within them by changing its working directory. First, +@code{find} reaches and recognises a subdirectory. It then decides if that +subdirectory meets the criteria for being searched; that is, any +@samp{-xdev} or @samp{-prune} expressions are taken into account. The +@code{find} program will then change working directory and proceed to +search the directory. + +A race condition attack might take the form that once the checks +relevant to @samp{-xdev} and @samp{-prune} have been done, an attacker +might rename the directory that was being considered, and put in its +place a symbolic link that actually points somewhere else. + +The idea behind this attack is to fool @code{find} into going into the +wrong directory. This would leave @code{find} with a working +directory chosen by an attacker, bypassing any protection apparently +provided by @samp{-xdev} and @samp{-prune}, and any protection +provided by being able to @emph{not} list particular directories on +the @code{find} command line. This form of attack is particularly +problematic if the attacker can predict when the @code{find} command +will be run, as is the case with @code{cron} tasks for example. + +GNU @code{find} has specific safeguards to prevent this general class +of problem. The exact form of these safeguards depends on the +properties of your system. + +@menu +* O_NOFOLLOW:: Safely changing directory using @code{fchdir}. +* Systems without O_NOFOLLOW:: Checking for symbolic links after @code{chdir}. +@end menu + +@node O_NOFOLLOW +@subsubsection @code{O_NOFOLLOW} + +If your system supports the @code{O_NOFOLLOW} flag @footnote{GNU/Linux +(kernel version 2.1.126 and later) and FreeBSD (3.0-CURRENT and later) +support this} to the @code{open(2)} system call, @code{find} uses it +to safely change directories. The target directory is first opened +and then @code{find} changes working directory with the +@code{fchdir()} system call. This ensures that symbolic links are not +followed, preventing the sort of race condition attack in which use +is made of symbolic links. + +If for any reason this approach does not work, @code{find} will fall +back on the method which is normally used if @code{O_NOFOLLOW} is not +supported. + +You can tell if your system supports @code{O_NOFOLLOW} by running + +@example +find --version +@end example + +This will tell you the version number and which features are enabled. +For example, if I run this on my system now, this gives: +@example +find (GNU findutils) 4.5.11-git +Copyright (C) 2012 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +Written by Eric B. Decker, James Youngman, and Kevin Dalley. +Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2) +@end example + +Here, you can see that I am running a version of @code{find} which was +built from the development (git) code prior to the release of +findutils-4.5.12, and that several features including @code{O_NOFOLLOW} are +present. @code{O_NOFOLLOW} is qualified with ``enabled''. This simply means +that the current system seems to support @code{O_NOFOLLOW}. This check is +needed because it is possible to build @code{find} on a system that +defines @code{O_NOFOLLOW} and then run it on a system that ignores the +@code{O_NOFOLLOW} flag. We try to detect such cases at startup by checking +the operating system and version number; when this happens you will +see @samp{O_NOFOLLOW(disabled)} instead. + +@node Systems without O_NOFOLLOW +@subsubsection Systems without @code{O_NOFOLLOW} + +The strategy for preventing this type of problem on systems that lack +support for the @code{O_NOFOLLOW} flag is more complex. Each time +@code{find} changes directory, it examines the directory it is about +to move to, issues the @code{chdir()} system call, and then checks +that it has ended up in the subdirectory it expected. If all is as +expected, processing continues as normal. However, there are two main +reasons why the directory might change: the use of an automounter and +the someone removing the old directory and replacing it with something +else while @code{find} is trying to descend into it. + +Where a filesystem ``automounter'' is in use it can be the case that +the use of the @code{chdir()} system call can itself cause a new +filesystem to be mounted at that point. On systems that do not +support @code{O_NOFOLLOW}, this will cause @code{find}'s security check to +fail. + +However, this does not normally represent a security problem, since +the automounter configuration is normally set up by the system +administrator. Therefore, if the @code{chdir()} sanity check fails, +@code{find} will make one more attempt@footnote{This may not be the +case for the fts-based executable}. If that succeeds, execution +carries on as normal. This is the usual case for automounters. + +Where an attacker is trying to exploit a race condition, the problem +may not have gone away on the second attempt. If this is the case, +@code{find} will issue a warning message and then ignore that +subdirectory. When this happens, actions such as @samp{-exec} or +@samp{-print} may already have taken place for the problematic +subdirectory. This is because @code{find} applies tests and actions +to directories before searching within them (unless @samp{-depth} was +specified). + +Because of the nature of the directory-change operation and security +check, in the worst case the only things that @code{find} would have +done with the directory are to move into it and back out to the +original parent. No operations would have been performed within that +directory. + +@node Race Conditions with -exec +@subsection Race Conditions with @code{-exec} + +The @samp{-exec} action causes another program to be run. It passes +to the program the name of the file which is being considered at the +time. The invoked program will typically then perform some action +on that file. Once again, there is a race condition which can be +exploited here. We shall take as a specific example the command + +@example +find /tmp -path /tmp/umsp/passwd -exec /bin/rm +@end example + +In this simple example, we are identifying just one file to be deleted +and invoking @code{/bin/rm} to delete it. A problem exists because +there is a time gap between the point where @code{find} decides that +it needs to process the @samp{-exec} action and the point where the +@code{/bin/rm} command actually issues the @code{unlink()} system +call to delete the file from the filesystem. Within this time period, an attacker can rename the +@file{/tmp/umsp} directory, replacing it with a symbolic link to +@file{/etc}. There is no way for @code{/bin/rm} to determine that it +is working on the same file that @code{find} had in mind. Once the +symbolic link is in place, the attacker has persuaded @code{find} to +cause the deletion of the @file{/etc/passwd} file, which is not the +effect intended by the command which was actually invoked. + +One possible defence against this type of attack is to modify the +behaviour of @samp{-exec} so that the @code{/bin/rm} command is run +with the argument @file{./passwd} and a suitable choice of working +directory. This would allow the normal sanity check that @code{find} +performs to protect against this form of attack too. Unfortunately, +this strategy cannot be used as the POSIX standard specifies that the +current working directory for commands invoked with @samp{-exec} must +be the same as the current working directory from which @code{find} +was invoked. This means that the @samp{-exec} action is inherently +insecure and can't be fixed. + +GNU @code{find} implements a more secure variant of the @samp{-exec} +action, @samp{-execdir}. The @samp{-execdir} action +ensures that it is not necessary to dereference subdirectories to +process target files. The current directory used to invoke programs +is the same as the directory in which the file to be processed exists +(@file{/tmp/umsp} in our example, and only the basename of the file to +be processed is passed to the invoked command, with a @samp{./} +prepended (giving @file{./passwd} in our example). + +The @samp{-execdir} action refuses to do anything if the current +directory is included in the @var{$PATH} environment variable. This +is necessary because @samp{-execdir} runs programs in the same +directory in which it finds files -- in general, such a directory +might be writable by untrusted users. For similar reasons, +@samp{-execdir} does not allow @samp{@{@}} to appear in the name of +the command to be run. + +@node Race Conditions with -print and -print0 +@subsection Race Conditions with @code{-print} and @code{-print0} + +The @samp{-print} and @samp{-print0} actions can be used to produce a +list of files matching some criteria, which can then be used with some +other command, perhaps with @code{xargs}. Unfortunately, this means +that there is an unavoidable time gap between @code{find} deciding +that one or more files meet its criteria and the relevant command +being executed. For this reason, the @samp{-print} and @samp{-print0} +actions are just as insecure as @samp{-exec}. + +In fact, since the construction + +@example +find @dots{} -print | xargs @enddots{} +@end example + +does not cope correctly with newlines or other ``white space'' in +file names, and copes poorly with file names containing quotes, the +@samp{-print} action is less secure even than @samp{-print0}. + + +@comment node-name, next, previous, up +@comment @node Security Considerations for xargs +@node Security Considerations for xargs +@section Security Considerations for @code{xargs} + +The description of the race conditions affecting the @samp{-print} +action of @code{find} shows that @code{xargs} cannot be secure if it +is possible for an attacker to modify a filesystem after @code{find} +has started but before @code{xargs} has completed all its actions. + +However, there are other security issues that exist even if it is not +possible for an attacker to have access to the filesystem in real +time. Firstly, if it is possible for an attacker to create files with +names of their choice on the filesystem, then @code{xargs} is +insecure unless the @samp{-0} option is used. If a file with the name +@file{/home/someuser/foo/bar\n/etc/passwd} exists (assume that +@samp{\n} stands for a newline character), then @code{find @dots{} -print} +can be persuaded to print three separate lines: + +@example +/home/someuser/foo/bar + +/etc/passwd +@end example + +If it finds a blank line in the input, @code{xargs} will ignore it. +Therefore, if some action is to be taken on the basis of this list of +files, the @file{/etc/passwd} file would be included even if this was +not the intent of the person running find. There are circumstances in +which an attacker can use this to their advantage. The same +consideration applies to file names containing ordinary spaces rather +than newlines, except that of course the list of file names will no +longer contain an ``extra'' newline. + +This problem is an unavoidable consequence of the default behaviour of +the @code{xargs} command, which is specified by the POSIX standard. +The only ways to avoid this problem are either to avoid all use of +@code{xargs} in favour for example of @samp{find -exec} or (where +available) @samp{find -execdir}, or to use the @samp{-0} option, which +ensures that @code{xargs} considers file names to be separated by +ASCII NUL characters rather than whitespace. However, useful as this +option is, the POSIX standard does not make it mandatory. + +POSIX also specifies that @code{xargs} interprets quoting and trailing +whitespace specially in filenames, too. This means that using +@code{find ... -print | xargs ...} can cause the commands run by +@code{xargs} to receive a list of file names which is not the same as +the list printed by @code{find}. The interpretation of quotes and +trailing whitespace is turned off by the @samp{-0} argument to +@code{xargs}, which is another reason to use that option. + +@comment node-name, next, previous, up +@node Security Considerations for locate +@section Security Considerations for @code{locate} + +@subsection Race Conditions +It is fairly unusual for the output of @code{locate} to be fed into +another command. However, if this were to be done, this would raise +the same set of security issues as the use of @samp{find @dots{} -print}. +Although the problems relating to whitespace in file names can be +resolved by using @code{locate}'s @samp{-0} option, this still leaves +the race condition problems associated with @samp{find @dots{} -print0}. +There is no way to avoid these problems in the case of @code{locate}. + +@subsection Long File Name Bugs with Old-Format Databases +Old versions of @code{locate} have a bug in the way that old-format +databases are read. This bug affects the following versions of +@code{locate}: + +@enumerate +@item All releases prior to 4.2.31 +@item All 4.3.x releases prior to 4.3.7 +@end enumerate + +The affected versions of @code{locate} read file names into a +fixed-length 1026 byte buffer, allocated on the heap. This buffer is +not extended if file names are too long to fit into the buffer. No +range checking on the length of the filename is performed. This could +in theory lead to a privilege escalation attack. Findutils versions +4.3.0 to 4.3.6 are also affected. + +On systems using the old database format and affected versions of +@code{locate}, carefully-chosen long file names could in theory allow +malicious users to run code of their choice as any user invoking +locate. + +If remote users can choose the names of files stored on your system, +and these files are indexed by @code{updatedb}, this may be a remote +security vulnerability. Findutils version 4.2.31 and findutils +version 4.3.7 include fixes for this problem. The @code{updatedb}, +@code{bigram} and @code{code} programs do no appear to be affected. + +If you are also using GNU coreutils, you can use the following command +to determine the length of the longest file name on a given system: + +@example +find / -print0 | tr -c '\0' 'x' | tr '\0' '\n' | wc -L +@end example + +Although this problem is significant, the old database format is not +the default, and use of the old database format is not common. Most +installations and most users will not be affected by this problem. + + + +@node Security Summary +@section Summary + +Where untrusted parties can create files on the system, or affect the +names of files that are created, all uses for @code{find}, +@code{locate} and @code{xargs} have known security problems except the +following: + +@table @asis +@item Informational use only +Uses where the programs are used to prepare lists of file names upon +which no further action will ever be taken. + +@item @samp{-delete} +Use of the @samp{-delete} action with @code{find} to delete files +which meet specified criteria + +@item @samp{-execdir} +Use of the @samp{-execdir} action with @code{find} where the +@env{PATH} environment variable contains directories which contain +only trusted programs. +@end table + + +@node Further Reading on Security +@section Further Reading on Security + +While there are a number of books on computer security, there are also +useful articles on the web that touch on the issues described above: + +@table @url +@item http://goo.gl/DAvh +@c https://www.securecoding.cert.org/confluence/display/seccode/MSC09-C.+Character+Encoding+-+Use+Subset+of+ASCII+for+Safety +This article describes some of the unfortunate effects of allowing +free choice of file names. +@item http://cwe.mitre.org/data/definitions/78.html +Describes OS Command Injection +@item https://cwe.mitre.org/data/definitions/73.html +Describes problems arising from allowing remote computers to send +requests which specify file names of their choice +@item http://cwe.mitre.org/data/definitions/116.html +Describes problems relating to encoding file names and escaping +characters. This article is relevant to findutils because for command +lines processed via the shell, the encoding and escaping rules are +already set by the shell. For example command lines like @code{find +... -print | some-shell-script} require specific care. +@item http://xkcd.com/327/ +A humorous and pithy summary of the broader problem. +@end table + +@comment node-name, next, previous, up +@node Error Messages +@chapter Error Messages + +This section describes some of the error messages sometimes made by +@code{find}, @code{xargs}, or @code{locate}, explains them and in some +cases provides advice as to what you should do about this. + +This manual is written in English. The GNU findutils software +features translations of error messages for many languages. For this +reason the error messages produced by the programs are made to be as +self-explanatory as possible. This approach avoids leaving people to +figure out which test an English-language error message corresponds +to. Error messages which are self-explanatory will not normally be +mentioned in this document. For those messages mentioned in this +document, only the English-language version of the message will be +listed. + +@menu +* Error Messages From find:: +* Error Messages From xargs:: +* Error Messages From locate:: +* Error Messages From updatedb:: +@end menu + +@node Error Messages From find +@section Error Messages From @code{find} + +Most error messages produced by find are self-explanatory. Error +messages sometimes include a filename. When this happens, the +filename is quoted in order to prevent any unusual characters in the +filename making unwanted changes in the state of the terminal. + +@table @samp +@item invalid predicate `-foo' +This means that the @code{find} command line included something that +started with a dash or other special character. The @code{find} +program tried to interpret this as a test, action or option, but +didn't recognise it. If it was intended to be a test, check what was +specified against the documentation. If, on the other hand, the +string is the name of a file which has been expanded from a wildcard +(for example because you have a @samp{*} on the command line), +consider using @samp{./*} or just @samp{.} instead. + +@item unexpected extra predicate +This usually happens if you have an extra bracket on the command line +(for example @samp{find . -print \)}). + +@item Warning: filesystem /path/foo has recently been mounted +@itemx Warning: filesystem /path/foo has recently been unmounted +These messages might appear when @code{find} moves into a directory +and finds that the device number and inode are different from what it +expected them to be. If the directory @code{find} has moved into is +on a network filesystem (NFS), it will not issue this message, because +@code{automount} frequently mounts new filesystems on directories as +you move into them (that is how it knows you want to use the +filesystem). So, if you do see this message, be wary -- +@code{automount} may not have been responsible. Consider the +possibility that someone else is manipulating the filesystem while +@code{find} is running. Some people might do this in order to mislead +@code{find} or persuade it to look at one set of files when it thought +it was looking at another set. + +@item /path/foo changed during execution of find (old device number 12345, new device number 6789, filesystem type is <whatever>) [ref XXX] +This message is issued when @code{find} moves into a directory and ends up +somewhere it didn't expect to be. This happens in one of two +circumstances. Firstly, this happens when @code{automount} intervenes +on a system where @code{find} doesn't know how to determine what +the current set of mounted filesystems is. + +Secondly, this can happen when the device number of a directory +appears to change during a change of current directory, but +@code{find} is moving up the filesystem hierarchy rather than down into it. +In order to prevent @code{find} wandering off into some unexpected +part of the filesystem, we stop it at this point. + +@item Don't know how to use getmntent() to read `/etc/mtab'. This is a bug. +This message is issued when a problem similar to the above occurs on a +system where @code{find} doesn't know how to figure out the current +list of mount points. Ask for help on @email{bug-findutils@@gnu.org}. + +@item /path/foo/bar changed during execution of find (old inode number 12345, new inode number 67893, filesystem type is <whatever>) [ref XXX]"), +This message is issued when @code{find} moves into a directory and +discovers that the inode number of that directory +is different from the inode number that it obtained when it examined the +directory previously. This usually means that while +@code{find} was deep in a directory hierarchy doing a +time consuming operation, somebody has moved one of the parent directories to +another location in the same filesystem. This may or may not have been done +maliciously. In any case, @code{find} stops at this point +to avoid traversing parts of the filesystem that it wasn't +intended to. You can use @code{ls -li} or @code{find /path -inum +12345 -o -inum 67893} to find out more about what has happened. + +@item sanity check of the fnmatch() library function failed. +Please submit a bug report. You may well be asked questions about +your system, and if you compiled the @code{findutils} code yourself, +you should keep your copy of the build tree around. The likely +explanation is that your system has a buggy implementation of +@code{fnmatch} that looks enough like the GNU version to fool +@code{configure}, but which doesn't work properly. + +@item cannot fork +This normally happens if you use the @code{-exec} action or +something similar (@code{-ok} and so forth) but the system has run out +of free process slots. This is either because the system is very busy +and the system has reached its maximum process limit, or because you +have a resource limit in place and you've reached it. Check the +system for runaway processes (with @code{ps}, if possible). Some process +slots are normally reserved for use by @samp{root}. + +@item some-program terminated by signal 99 +Some program which was launched with @code{-exec} or similar was killed +with a fatal signal. This is just an advisory message. +@end table + + +@node Error Messages From xargs +@section Error Messages From @code{xargs} + +@table @samp +@item environment is too large for exec +This message means that you have so many environment variables set (or +such large values for them) that there is no room within the +system-imposed limits on program command line argument length to +invoke any program. This is an unlikely situation and is more likely +result of an attempt to test the limits of @code{xargs}, or break it. +Please try unsetting some environment variables, or exiting the +current shell. You can also use @samp{xargs --show-limits} to +understand the relevant sizes. + +@item argument list too long +You are using the @samp{-I} option and @code{xargs} doesn't have +enough space to build a command line because it has read a really +large item and it doesn't fit. You may be able to work around this +problem with the @samp{-s} option, but the default size is pretty +large. This is a rare situation and is more likely an attempt to test +the limits of @code{xargs}, or break it. Otherwise, you will need to +try to shorten the problematic argument or not use @code{xargs}. + +@item argument line too long +You are using the @samp{-L} or @samp{-l} option and one of the input +lines is too long. You may be able to work around this problem with +the @samp{-s} option, but the default size is pretty large. If you +can modify the your @code{xargs} command not to use @samp{-L} or +@samp{-l}, that will be more likely to result in success. + +@item cannot fork +See the description of the similar message for @code{find}. + +@item <program>: exited with status 255; aborting +When a command run by @code{xargs} exits with status 255, @code{xargs} +is supposed to stop. If this is not what you intended, wrap the +program you are trying to invoke in a shell script which doesn't +return status 255. + +@item <program>: terminated by signal 99 +See the description of the similar message for @code{find}. + +@item cannot set SIGUSR1 signal handler +@code{xargs} is having trouble preparing for you to be able to send it +signals to increase or decrease the parallelism of its processing. +If you don't plan to send it those signals, this warning can be ignored +(though if you're a programmer, you may want to help us figure out +why @code{xargs} is confused by your operating system). +@end table + +@node Error Messages From locate +@section Error Messages From @code{locate} + +@table @samp +@item warning: database @file{@value{LOCATE_DB}} is more than 8 days old +The @code{locate} program relies on a database which is periodically +built by the @code{updatedb} program. That hasn't happened in a long +time. To fix this problem, run @code{updatedb} manually. This can +often happen on systems that are generally not left on, so the +periodic ``cron'' task which normally does this doesn't get a chance +to run. + +@item locate database @file{@value{LOCATE_DB}} is corrupt or invalid +This should not happen. Re-run @code{updatedb}. If that works, but +@code{locate} still produces this error, run @code{locate --version} +and @code{updatedb --version}. These should produce the same output. +If not, you are using a mixed toolset; check your @samp{$PATH} +environment variable and your shell aliases (if you have any). If +both programs claim to be GNU versions, this is a bug; all versions of +these programs should interoperate without problem. Ask for help on +@email{bug-findutils@@gnu.org}. +@end table + + +@node Error Messages From updatedb +@section Error Messages From @code{updatedb} + +The @code{updatedb} program (and the programs it invokes) do issue +error messages, but none seem to be candidates for guidance. If +you are having a problem understanding one of these, ask for help on +@email{bug-findutils@@gnu.org}. + +@node GNU Free Documentation License +@appendix GNU Free Documentation License +@include fdl.texi + +@node Primary Index +@unnumbered @code{find} Primary Index + +This is a list of all of the primaries (tests, actions, and options) +that make up @code{find} expressions for selecting files. @xref{find +Expressions}, for more information on expressions. + +@printindex fn + +@bye + +@comment texi related words used by Emacs' spell checker ispell.el + +@comment LocalWords: texinfo setfilename settitle setchapternewpage +@comment LocalWords: iftex finalout ifinfo DIR titlepage vskip pt +@comment LocalWords: filll dir samp dfn noindent xref pxref +@comment LocalWords: var deffn texi deffnx itemx emph asis +@comment LocalWords: findex smallexample subsubsection cindex +@comment LocalWords: dircategory direntry itemize + +@comment other words used by Emacs' spell checker ispell.el +@comment LocalWords: README fred updatedb xargs Plett Rendell akefile +@comment LocalWords: args grep Filesystems fo foo fOo wildcards iname +@comment LocalWords: ipath regex iregex expr fubar regexps +@comment LocalWords: metacharacters macs sr sc inode lname ilname +@comment LocalWords: sysdep noleaf ls inum xdev filesystems usr atime +@comment LocalWords: ctime mtime amin cmin mmin al daystart Sladkey rm +@comment LocalWords: anewer cnewer bckw rf xtype uname gname uid gid +@comment LocalWords: nouser nogroup chown chgrp perm ch maxdepth +@comment LocalWords: mindepth cpio src CD AFS statted stat fstype ufs +@comment LocalWords: nfs tmp mfs printf fprint dils rw djm Nov lwall +@comment LocalWords: POSIXLY fls fprintf strftime locale's EDT GMT AP +@comment LocalWords: EST diff perl backquotes sprintf Falstad Oct cron +@comment LocalWords: eg vmunix mkdir afs allexec allwrite ARG bigram +@comment LocalWords: bigrams cd chmod comp crc CVS dbfile eof +@comment LocalWords: fileserver filesystem fn frcode Ghazi Hnewc iXX +@comment LocalWords: joeuser Kaveh localpaths localuser LOGNAME +@comment LocalWords: Meyering mv netpaths netuser nonblank nonblanks +@comment LocalWords: ois ok Pinard printindex proc procs prunefs +@comment LocalWords: prunepaths pwd RFS rmadillo rmdir rsh sbins str +@comment LocalWords: su Timar ubins ug unstripped vf VM Weitzel +@comment LocalWords: wildcard zlogout basename execdir wholename iwholename +@comment LocalWords: timestamp timestamps Solaris FreeBSD OpenBSD POSIX diff --git a/doc/mdate-sh b/doc/mdate-sh new file mode 100755 index 0000000..7072ea9 --- /dev/null +++ b/doc/mdate-sh @@ -0,0 +1,224 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. + +scriptversion=2010-08-21.06; # UTC + +# Copyright (C) 1995-2013 Free Software Foundation, Inc. +# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995 +# +# This program 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, or (at your option) +# any later version. +# +# This program 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 <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +fi + +case $1 in + '') + echo "$0: No file. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: mdate-sh [--help] [--version] FILE + +Pretty-print the modification day of FILE, in the format: +1 January 1970 + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "mdate-sh $scriptversion" + exit $? + ;; +esac + +error () +{ + echo "$0: $1" >&2 + exit 1 +} + + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +# GNU ls changes its time format in response to the TIME_STYLE +# variable. Since we cannot assume 'unset' works, revert this +# variable to its documented default. +if test "${TIME_STYLE+set}" = set; then + TIME_STYLE=posix-long-iso + export TIME_STYLE +fi + +save_arg1=$1 + +# Find out how to get the extended ls output of a file or directory. +if ls -L /dev/null 1>/dev/null 2>&1; then + ls_command='ls -L -l -d' +else + ls_command='ls -l -d' +fi +# Avoid user/group names that might have spaces, when possible. +if ls -n /dev/null 1>/dev/null 2>&1; then + ls_command="$ls_command -n" +fi + +# A 'ls -l' line looks as follows on OS/2. +# drwxrwx--- 0 Aug 11 2001 foo +# This differs from Unix, which adds ownership information. +# drwxrwx--- 2 root root 4096 Aug 11 2001 foo +# +# To find the date, we split the line on spaces and iterate on words +# until we find a month. This cannot work with files whose owner is a +# user named "Jan", or "Feb", etc. However, it's unlikely that '/' +# will be owned by a user whose name is a month. So we first look at +# the extended ls output of the root directory to decide how many +# words should be skipped to get the date. + +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +set x`$ls_command /` + +# Find which argument is the month. +month= +command= +until test $month +do + test $# -gt 0 || error "failed parsing '$ls_command /' output" + shift + # Add another shift to the command. + command="$command shift;" + case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; + esac +done + +test -n "$month" || error "failed parsing '$ls_command /' output" + +# Get the extended ls output of the file or directory. +set dummy x`eval "$ls_command \"\\\$save_arg1\""` + +# Remove all preceding arguments +eval $command + +# Because of the dummy argument above, month is in $2. +# +# On a POSIX system, we should have +# +# $# = 5 +# $1 = file size +# $2 = month +# $3 = day +# $4 = year or time +# $5 = filename +# +# On Darwin 7.7.0 and 7.6.0, we have +# +# $# = 4 +# $1 = day +# $2 = month +# $3 = year or time +# $4 = filename + +# Get the month. +case $2 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; +esac + +case $3 in + ???*) day=$1;; + *) day=$3; shift;; +esac + +# Here we have to deal with the problem that the ls output gives either +# the time of day or the year. +case $3 in + *:*) set `date`; eval year=\$$# + case $2 in + Jan) nummonthtod=1;; + Feb) nummonthtod=2;; + Mar) nummonthtod=3;; + Apr) nummonthtod=4;; + May) nummonthtod=5;; + Jun) nummonthtod=6;; + Jul) nummonthtod=7;; + Aug) nummonthtod=8;; + Sep) nummonthtod=9;; + Oct) nummonthtod=10;; + Nov) nummonthtod=11;; + Dec) nummonthtod=12;; + esac + # For the first six month of the year the time notation can also + # be used for files modified in the last year. + if (expr $nummonth \> $nummonthtod) > /dev/null; + then + year=`expr $year - 1` + fi;; + *) year=$3;; +esac + +# The result. +echo $day $month $year + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/doc/parse-datetime.texi b/doc/parse-datetime.texi new file mode 100644 index 0000000..1083924 --- /dev/null +++ b/doc/parse-datetime.texi @@ -0,0 +1,594 @@ +@c GNU date syntax documentation + +@c Copyright (C) 1994-2006, 2009-2015 Free Software Foundation, Inc. + +@c Permission is granted to copy, distribute and/or modify this document +@c under the terms of the GNU Free Documentation License, Version 1.3 or +@c any later version published by the Free Software Foundation; with no +@c Invariant Sections, no Front-Cover Texts, and no Back-Cover +@c Texts. A copy of the license is included in the ``GNU Free +@c Documentation License'' file as part of this distribution. + +@node Date input formats +@chapter Date input formats + +@cindex date input formats +@findex parse_datetime + +First, a quote: + +@quotation +Our units of temporal measurement, from seconds on up to months, are so +complicated, asymmetrical and disjunctive so as to make coherent mental +reckoning in time all but impossible. Indeed, had some tyrannical god +contrived to enslave our minds to time, to make it all but impossible +for us to escape subjection to sodden routines and unpleasant surprises, +he could hardly have done better than handing down our present system. +It is like a set of trapezoidal building blocks, with no vertical or +horizontal surfaces, like a language in which the simplest thought +demands ornate constructions, useless particles and lengthy +circumlocutions. Unlike the more successful patterns of language and +science, which enable us to face experience boldly or at least +level-headedly, our system of temporal calculation silently and +persistently encourages our terror of time. + +@dots{} It is as though architects had to measure length in feet, width +in meters and height in ells; as though basic instruction manuals +demanded a knowledge of five different languages. It is no wonder then +that we often look into our own immediate past or future, last Tuesday +or a week from Sunday, with feelings of helpless confusion. @dots{} + +---Robert Grudin, @cite{Time and the Art of Living}. +@end quotation + +This section describes the textual date representations that GNU +programs accept. These are the strings you, as a user, can supply as +arguments to the various programs. The C interface (via the +@code{parse_datetime} function) is not described here. + +@menu +* General date syntax:: Common rules. +* Calendar date items:: 19 Dec 1994. +* Time of day items:: 9:20pm. +* Time zone items:: EST, PDT, UTC, @dots{} +* Combined date and time of day items:: 1972-09-24T20:02:00,000000-0500. +* Day of week items:: Monday and others. +* Relative items in date strings:: next tuesday, 2 years ago. +* Pure numbers in date strings:: 19931219, 1440. +* Seconds since the Epoch:: @@1078100502. +* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0". +* Authors of parse_datetime:: Bellovin, Eggert, Salz, Berets, et al. +@end menu + + +@node General date syntax +@section General date syntax + +@cindex general date syntax + +@cindex items in date strings +A @dfn{date} is a string, possibly empty, containing many items +separated by whitespace. The whitespace may be omitted when no +ambiguity arises. The empty string means the beginning of today (i.e., +midnight). Order of the items is immaterial. A date string may contain +many flavors of items: + +@itemize @bullet +@item calendar date items +@item time of day items +@item time zone items +@item combined date and time of day items +@item day of the week items +@item relative items +@item pure numbers. +@end itemize + +@noindent We describe each of these item types in turn, below. + +@cindex numbers, written-out +@cindex ordinal numbers +@findex first @r{in date strings} +@findex next @r{in date strings} +@findex last @r{in date strings} +A few ordinal numbers may be written out in words in some contexts. This is +most useful for specifying day of the week items or relative items (see +below). Among the most commonly used ordinal numbers, the word +@samp{last} stands for @math{-1}, @samp{this} stands for 0, and +@samp{first} and @samp{next} both stand for 1. Because the word +@samp{second} stands for the unit of time there is no way to write the +ordinal number 2, but for convenience @samp{third} stands for 3, +@samp{fourth} for 4, @samp{fifth} for 5, +@samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8, +@samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and +@samp{twelfth} for 12. + +@cindex months, written-out +When a month is written this way, it is still considered to be written +numerically, instead of being ``spelled in full''; this changes the +allowed strings. + +@cindex language, in dates +In the current implementation, only English is supported for words and +abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first}, +@samp{January}, @samp{Sunday}, @samp{tomorrow}, and @samp{year}. + +@cindex language, in dates +@cindex time zone item +The output of the @command{date} command +is not always acceptable as a date string, +not only because of the language problem, but also because there is no +standard meaning for time zone items like @samp{IST}@. When using +@command{date} to generate a date string intended to be parsed later, +specify a date format that is independent of language and that does not +use time zone items other than @samp{UTC} and @samp{Z}@. Here are some +ways to do this: + +@example +$ LC_ALL=C TZ=UTC0 date +Mon Mar 1 00:21:42 UTC 2004 +$ TZ=UTC0 date +'%Y-%m-%d %H:%M:%SZ' +2004-03-01 00:21:42Z +$ date --rfc-3339=ns # --rfc-3339 is a GNU extension. +2004-02-29 16:21:42.692722128-08:00 +$ date --rfc-2822 # a GNU extension +Sun, 29 Feb 2004 16:21:42 -0800 +$ date +'%Y-%m-%d %H:%M:%S %z' # %z is a GNU extension. +2004-02-29 16:21:42 -0800 +$ date +'@@%s.%N' # %s and %N are GNU extensions. +@@1078100502.692722128 +@end example + +@cindex case, ignored in dates +@cindex comments, in dates +Alphabetic case is completely ignored in dates. Comments may be introduced +between round parentheses, as long as included parentheses are properly +nested. Hyphens not followed by a digit are currently ignored. Leading +zeros on numbers are ignored. + +@cindex leap seconds +Invalid dates like @samp{2005-02-29} or times like @samp{24:00} are +rejected. In the typical case of a host that does not support leap +seconds, a time like @samp{23:59:60} is rejected even if it +corresponds to a valid leap second. + + +@node Calendar date items +@section Calendar date items + +@cindex calendar date item + +A @dfn{calendar date item} specifies a day of the year. It is +specified differently, depending on whether the month is specified +numerically or literally. All these strings specify the same calendar date: + +@example +1972-09-24 # ISO 8601. +72-9-24 # Assume 19xx for 69 through 99, + # 20xx for 00 through 68. +72-09-24 # Leading zeros are ignored. +9/24/72 # Common U.S. writing. +24 September 1972 +24 Sept 72 # September has a special abbreviation. +24 Sep 72 # Three-letter abbreviations always allowed. +Sep 24, 1972 +24-sep-72 +24sep72 +@end example + +The year can also be omitted. In this case, the last specified year is +used, or the current year if none. For example: + +@example +9/24 +sep 24 +@end example + +Here are the rules. + +@cindex ISO 8601 date format +@cindex date format, ISO 8601 +For numeric months, the ISO 8601 format +@samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is +any positive number, @var{month} is a number between 01 and 12, and +@var{day} is a number between 01 and 31. A leading zero must be present +if a number is less than ten. If @var{year} is 68 or smaller, then 2000 +is added to it; otherwise, if @var{year} is less than 100, +then 1900 is added to it. The construct +@samp{@var{month}/@var{day}/@var{year}}, popular in the United States, +is accepted. Also @samp{@var{month}/@var{day}}, omitting the year. + +@cindex month names in date strings +@cindex abbreviations for months +Literal months may be spelled out in full: @samp{January}, +@samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June}, +@samp{July}, @samp{August}, @samp{September}, @samp{October}, +@samp{November} or @samp{December}. Literal months may be abbreviated +to their first three letters, possibly followed by an abbreviating dot. +It is also permitted to write @samp{Sept} instead of @samp{September}. + +When months are written literally, the calendar date may be given as any +of the following: + +@example +@var{day} @var{month} @var{year} +@var{day} @var{month} +@var{month} @var{day} @var{year} +@var{day}-@var{month}-@var{year} +@end example + +Or, omitting the year: + +@example +@var{month} @var{day} +@end example + + +@node Time of day items +@section Time of day items + +@cindex time of day item + +A @dfn{time of day item} in date strings specifies the time on a given +day. Here are some examples, all of which represent the same time: + +@example +20:02:00.000000 +20:02 +8:02pm +20:02-0500 # In EST (U.S. Eastern Standard Time). +@end example + +@cindex leap seconds +More generally, the time of day may be given as +@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is +a number between 0 and 23, @var{minute} is a number between 0 and +59, and @var{second} is a number between 0 and 59 possibly followed by +@samp{.} or @samp{,} and a fraction containing one or more digits. +Alternatively, +@samp{:@var{second}} can be omitted, in which case it is taken to +be zero. On the rare hosts that support leap seconds, @var{second} +may be 60. + +@findex am @r{in date strings} +@findex pm @r{in date strings} +@findex midnight @r{in date strings} +@findex noon @r{in date strings} +If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.} +or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and +@samp{:@var{minute}} may be omitted (taken to be zero). @samp{am} +indicates the first half of the day, @samp{pm} indicates the second +half of the day. In this notation, 12 is the predecessor of 1: +midnight is @samp{12am} while noon is @samp{12pm}. +(This is the zero-oriented interpretation of @samp{12am} and @samp{12pm}, +as opposed to the old tradition derived from Latin +which uses @samp{12m} for noon and @samp{12pm} for midnight.) + +@cindex time zone correction +@cindex minutes, time zone correction by +The time may alternatively be followed by a time zone correction, +expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+} +or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number +of zone minutes. +The zone minutes term, @var{mm}, may be omitted, in which case +the one- or two-digit correction is interpreted as a number of hours. +You can also separate @var{hh} from @var{mm} with a colon. +When a time zone correction is given this way, it +forces interpretation of the time relative to +Coordinated Universal Time (UTC), overriding any previous +specification for the time zone or the local time zone. For example, +@samp{+0530} and @samp{+05:30} both stand for the time zone 5.5 hours +ahead of UTC (e.g., India). +This is the best way to +specify a time zone correction by fractional parts of an hour. +The maximum zone correction is 24 hours. + +Either @samp{am}/@samp{pm} or a time zone correction may be specified, +but not both. + + +@node Time zone items +@section Time zone items + +@cindex time zone item + +A @dfn{time zone item} specifies an international time zone, indicated +by a small set of letters, e.g., @samp{UTC} or @samp{Z} +for Coordinated Universal +Time. Any included periods are ignored. By following a +non-daylight-saving time zone by the string @samp{DST} in a separate +word (that is, separated by some white space), the corresponding +daylight saving time zone may be specified. +Alternatively, a non-daylight-saving time zone can be followed by a +time zone correction, to add the two values. This is normally done +only for @samp{UTC}; for example, @samp{UTC+05:30} is equivalent to +@samp{+05:30}. + +Time zone items other than @samp{UTC} and @samp{Z} +are obsolescent and are not recommended, because they +are ambiguous; for example, @samp{EST} has a different meaning in +Australia than in the United States. Instead, it's better to use +unambiguous numeric time zone corrections like @samp{-0500}, as +described in the previous section. + +If neither a time zone item nor a time zone correction is supplied, +time stamps are interpreted using the rules of the default time zone +(@pxref{Specifying time zone rules}). + + +@node Combined date and time of day items +@section Combined date and time of day items + +@cindex combined date and time of day item +@cindex ISO 8601 date and time of day format +@cindex date and time of day format, ISO 8601 + +The ISO 8601 date and time of day extended format consists of an ISO +8601 date, a @samp{T} character separator, and an ISO 8601 time of +day. This format is also recognized if the @samp{T} is replaced by a +space. + +In this format, the time of day should use 24-hour notation. +Fractional seconds are allowed, with either comma or period preceding +the fraction. ISO 8601 fractional minutes and hours are not +supported. Typically, hosts support nanosecond timestamp resolution; +excess precision is silently discarded. + +Here are some examples: + +@example +2012-09-24T20:02:00.052-05:00 +2012-12-31T23:59:59,999999999+11:00 +1970-01-01 00:00Z +@end example + +@node Day of week items +@section Day of week items + +@cindex day of week item + +The explicit mention of a day of the week will forward the date +(only if necessary) to reach that day of the week in the future. + +Days of the week may be spelled out in full: @samp{Sunday}, +@samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday}, +@samp{Friday} or @samp{Saturday}. Days may be abbreviated to their +first three letters, optionally followed by a period. The special +abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for +@samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are +also allowed. + +@findex next @var{day} +@findex last @var{day} +A number may precede a day of the week item to move forward +supplementary weeks. It is best used in expression like @samp{third +monday}. In this context, @samp{last @var{day}} or @samp{next +@var{day}} is also acceptable; they move one week before or after +the day that @var{day} by itself would represent. + +A comma following a day of the week item is ignored. + + +@node Relative items in date strings +@section Relative items in date strings + +@cindex relative items in date strings +@cindex displacement of dates + +@dfn{Relative items} adjust a date (or the current date if none) forward +or backward. The effects of relative items accumulate. Here are some +examples: + +@example +1 year +1 year ago +3 years +2 days +@end example + +@findex year @r{in date strings} +@findex month @r{in date strings} +@findex fortnight @r{in date strings} +@findex week @r{in date strings} +@findex day @r{in date strings} +@findex hour @r{in date strings} +@findex minute @r{in date strings} +The unit of time displacement may be selected by the string @samp{year} +or @samp{month} for moving by whole years or months. These are fuzzy +units, as years and months are not all of equal duration. More precise +units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7 +days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes, +@samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or +@samp{sec} worth one second. An @samp{s} suffix on these units is +accepted and ignored. + +@findex ago @r{in date strings} +The unit of time may be preceded by a multiplier, given as an optionally +signed number. Unsigned numbers are taken as positively signed. No +number at all implies 1 for a multiplier. Following a relative item by +the string @samp{ago} is equivalent to preceding the unit by a +multiplier with value @math{-1}. + +@findex day @r{in date strings} +@findex tomorrow @r{in date strings} +@findex yesterday @r{in date strings} +The string @samp{tomorrow} is worth one day in the future (equivalent +to @samp{day}), the string @samp{yesterday} is worth +one day in the past (equivalent to @samp{day ago}). + +@findex now @r{in date strings} +@findex today @r{in date strings} +@findex this @r{in date strings} +The strings @samp{now} or @samp{today} are relative items corresponding +to zero-valued time displacement, these strings come from the fact +a zero-valued time displacement represents the current time when not +otherwise changed by previous items. They may be used to stress other +items, like in @samp{12:00 today}. The string @samp{this} also has +the meaning of a zero-valued time displacement, but is preferred in +date strings like @samp{this thursday}. + +When a relative item causes the resulting date to cross a boundary +where the clocks were adjusted, typically for daylight saving time, +the resulting date and time are adjusted accordingly. + +The fuzz in units can cause problems with relative items. For +example, @samp{2003-07-31 -1 month} might evaluate to 2003-07-01, +because 2003-06-31 is an invalid date. To determine the previous +month more reliably, you can ask for the month before the 15th of the +current month. For example: + +@example +$ date -R +Thu, 31 Jul 2003 13:02:39 -0700 +$ date --date='-1 month' +'Last month was %B?' +Last month was July? +$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!' +Last month was June! +@end example + +Also, take care when manipulating dates around clock changes such as +daylight saving leaps. In a few cases these have added or subtracted +as much as 24 hours from the clock, so it is often wise to adopt +universal time by setting the @env{TZ} environment variable to +@samp{UTC0} before embarking on calendrical calculations. + +@node Pure numbers in date strings +@section Pure numbers in date strings + +@cindex pure numbers in date strings + +The precise interpretation of a pure decimal number depends +on the context in the date string. + +If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no +other calendar date item (@pxref{Calendar date items}) appears before it +in the date string, then @var{yyyy} is read as the year, @var{mm} as the +month number and @var{dd} as the day of the month, for the specified +calendar date. + +If the decimal number is of the form @var{hh}@var{mm} and no other time +of day item appears before it in the date string, then @var{hh} is read +as the hour of the day and @var{mm} as the minute of the hour, for the +specified time of day. @var{mm} can also be omitted. + +If both a calendar date and a time of day appear to the left of a number +in the date string, but no relative item, then the number overrides the +year. + + +@node Seconds since the Epoch +@section Seconds since the Epoch + +If you precede a number with @samp{@@}, it represents an internal time +stamp as a count of seconds. The number can contain an internal +decimal point (either @samp{.} or @samp{,}); any excess precision not +supported by the internal representation is truncated toward minus +infinity. Such a number cannot be combined with any other date +item, as it specifies a complete time stamp. + +@cindex beginning of time, for POSIX +@cindex epoch, for POSIX +Internally, computer times are represented as a count of seconds since +an epoch---a well-defined point of time. On GNU and +POSIX systems, the epoch is 1970-01-01 00:00:00 UTC, so +@samp{@@0} represents this time, @samp{@@1} represents 1970-01-01 +00:00:01 UTC, and so forth. GNU and most other +POSIX-compliant systems support such times as an extension +to POSIX, using negative counts, so that @samp{@@-1} +represents 1969-12-31 23:59:59 UTC. + +Traditional Unix systems count seconds with 32-bit two's-complement +integers and can represent times from 1901-12-13 20:45:52 through +2038-01-19 03:14:07 UTC@. More modern systems use 64-bit counts +of seconds with nanosecond subcounts, and can represent all the times +in the known lifetime of the universe to a resolution of 1 nanosecond. + +@cindex leap seconds +On most hosts, these counts ignore the presence of leap seconds. +For example, on most hosts @samp{@@915148799} represents 1998-12-31 +23:59:59 UTC, @samp{@@915148800} represents 1999-01-01 00:00:00 +UTC, and there is no way to represent the intervening leap second +1998-12-31 23:59:60 UTC. + +@node Specifying time zone rules +@section Specifying time zone rules + +@vindex TZ +Normally, dates are interpreted using the rules of the current time +zone, which in turn are specified by the @env{TZ} environment +variable, or by a system default if @env{TZ} is not set. To specify a +different set of default time zone rules that apply just to one date, +start the date with a string of the form @samp{TZ="@var{rule}"}. The +two quote characters (@samp{"}) must be present in the date, and any +quotes or backslashes within @var{rule} must be escaped by a +backslash. + +For example, with the GNU @command{date} command you can +answer the question ``What time is it in New York when a Paris clock +shows 6:30am on October 31, 2004?'' by using a date beginning with +@samp{TZ="Europe/Paris"} as shown in the following shell transcript: + +@example +$ export TZ="America/New_York" +$ date --date='TZ="Europe/Paris" 2004-10-31 06:30' +Sun Oct 31 01:30:00 EDT 2004 +@end example + +In this example, the @option{--date} operand begins with its own +@env{TZ} setting, so the rest of that operand is processed according +to @samp{Europe/Paris} rules, treating the string @samp{2004-10-31 +06:30} as if it were in Paris. However, since the output of the +@command{date} command is processed according to the overall time zone +rules, it uses New York time. (Paris was normally six hours ahead of +New York in 2004, but this example refers to a brief Halloween period +when the gap was five hours.) + +A @env{TZ} value is a rule that typically names a location in the +@uref{http://www.twinsun.com/tz/tz-link.htm, @samp{tz} database}. +A recent catalog of location names appears in the +@uref{http://twiki.org/cgi-bin/xtra/tzdate, TWiki Date and Time +Gateway}. A few non-GNU hosts require a colon before a +location name in a @env{TZ} setting, e.g., +@samp{TZ=":America/New_York"}. + +The @samp{tz} database includes a wide variety of locations ranging +from @samp{Arctic/Longyearbyen} to @samp{Antarctica/South_Pole}, but +if you are at sea and have your own private time zone, or if you are +using a non-GNU host that does not support the @samp{tz} +database, you may need to use a POSIX rule instead. Simple +POSIX rules like @samp{UTC0} specify a time zone without +daylight saving time; other rules can specify simple daylight saving +regimes. @xref{TZ Variable,, Specifying the Time Zone with @code{TZ}, +libc, The GNU C Library}. + +@node Authors of parse_datetime +@section Authors of @code{parse_datetime} +@c the anchor keeps the old node name, to try to avoid breaking links +@anchor{Authors of get_date} + +@cindex authors of @code{parse_datetime} + +@cindex Bellovin, Steven M. +@cindex Salz, Rich +@cindex Berets, Jim +@cindex MacKenzie, David +@cindex Meyering, Jim +@cindex Eggert, Paul +@code{parse_datetime} started life as @code{getdate}, as originally +implemented by Steven M. Bellovin +(@email{smb@@research.att.com}) while at the University of North Carolina +at Chapel Hill. The code was later tweaked by a couple of people on +Usenet, then completely overhauled by Rich $alz (@email{rsalz@@bbn.com}) +and Jim Berets (@email{jberets@@bbn.com}) in August, 1990. Various +revisions for the GNU system were made by David MacKenzie, Jim Meyering, +Paul Eggert and others, including renaming it to @code{get_date} to +avoid a conflict with the alternative Posix function @code{getdate}, +and a later rename to @code{parse_datetime}. The Posix function +@code{getdate} can parse more locale-specific dates using +@code{strptime}, but relies on an environment variable and external +file, and lacks the thread-safety of @code{parse_datetime}. + +@cindex Pinard, F. +@cindex Berry, K. +This chapter was originally produced by Fran@,{c}ois Pinard +(@email{pinard@@iro.umontreal.ca}) from the @file{parse_datetime.y} source code, +and then edited by K. Berry (@email{kb@@cs.umb.edu}). diff --git a/doc/perm.texi b/doc/perm.texi new file mode 100644 index 0000000..41b24f6 --- /dev/null +++ b/doc/perm.texi @@ -0,0 +1,508 @@ +Each file has a set of @dfn{permissions} that control the kinds of +access that users have to that file. The permissions for a file are +also called its @dfn{access mode}. They can be represented either in +symbolic form or as an octal number. + +@menu +* Mode Structure:: Structure of file permissions. +* Symbolic Modes:: Mnemonic permissions representation. +* Numeric Modes:: Permissions as octal numbers. +@end menu + +@node Mode Structure +@section Structure of File Permissions + +There are three kinds of permissions that a user can have for a file: + +@enumerate +@item +@cindex read permission +permission to read the file. For directories, this means permission to +list the contents of the directory. +@item +@cindex write permission +permission to write to (change) the file. For directories, this means +permission to create and remove files in the directory. +@item +@cindex execute permission +permission to execute the file (run it as a program). For directories, +this means permission to access files in the directory. +@end enumerate + +There are three categories of users who may have different permissions +to perform any of the above operations on a file: + +@enumerate +@item +the file's owner; +@item +other users who are in the file's group; +@item +everyone else. +@end enumerate + +@cindex owner, default +@cindex group owner, default +Files are given an owner and group when they are created. Usually the +owner is the current user and the group is the group of the directory +the file is in, but this varies with the operating system, the +file system the file is created on, and the way the file is created. You +can change the owner and group of a file by using the @command{chown} and +@command{chgrp} commands. + +In addition to the three sets of three permissions listed above, a +file's permissions have three special components, which affect only +executable files (programs) and, on some systems, directories: + +@enumerate +@item +@cindex setuid +Set the process's effective user ID to that of the file upon execution +(called the @dfn{setuid bit}). No effect on directories. +@item +@cindex setgid +Set the process's effective group ID to that of the file upon execution +(called the @dfn{setgid bit}). For directories on some systems, put +files created in the directory into the same group as the directory, no +matter what group the user who creates them is in. +@item +@cindex sticky +@cindex swap space, saving text image in +@cindex text image, saving in swap space +@cindex restricted deletion flag +prevent users from removing or renaming a file in a directory +unless they own the file or the directory; this is called the +@dfn{restricted deletion flag} for the directory. +For regular files on some systems, save the program's text image on the +swap device so it will load more quickly when run; this is called the +@dfn{sticky bit}. +@end enumerate + +In addition to the permissions listed above, there may be file attributes +specific to the file system, e.g: access control lists (ACLs), whether a +file is compressed, whether a file can be modified (immutability), whether +a file can be dumped. These are usually set using programs +specific to the file system. For example: +@c should probably say a lot more about ACLs... someday + +@table @asis +@item ext2 +On @acronym{GNU} and @acronym{GNU}/Linux the file permissions +(``attributes'') specific to +the ext2 file system are set using @command{chattr}. + +@item FFS +On FreeBSD the file permissions (``flags'') specific to the FFS +file system are set using @command{chrflags}. +@end table + +Although a file's permission ``bits'' allow an operation on that file, +that operation may still fail, because: + +@itemize +@item +the file-system-specific permissions do not permit it; + +@item +the file system is mounted as read-only. +@end itemize + +For example, if the immutable attribute is set on a file, +it cannot be modified, regardless of the fact that you +may have just run @code{chmod a+w FILE}. + +@node Symbolic Modes +@section Symbolic Modes + +@cindex symbolic modes +@dfn{Symbolic modes} represent changes to files' permissions as +operations on single-character symbols. They allow you to modify either +all or selected parts of files' permissions, optionally based on +their previous values, and perhaps on the current @code{umask} as well +(@pxref{Umask and Protection}). + +The format of symbolic modes is: + +@example +@r{[}ugoa@dots{}@r{][}+-=@r{]}@var{perms}@dots{}@r{[},@dots{}@r{]} +@end example + +@noindent +where @var{perms} is either zero or more letters from the set +@samp{rwxXst}, or a single letter from the set @samp{ugo}. + +The following sections describe the operators and other details of +symbolic modes. + +@menu +* Setting Permissions:: Basic operations on permissions. +* Copying Permissions:: Copying existing permissions. +* Changing Special Permissions:: Special permissions. +* Conditional Executability:: Conditionally affecting executability. +* Multiple Changes:: Making multiple changes. +* Umask and Protection:: The effect of the umask. +@end menu + +@node Setting Permissions +@subsection Setting Permissions + +The basic symbolic operations on a file's permissions are adding, +removing, and setting the permission that certain users have to read, +write, and execute the file. These operations have the following +format: + +@example +@var{users} @var{operation} @var{permissions} +@end example + +@noindent +The spaces between the three parts above are shown for readability only; +symbolic modes cannot contain spaces. + +The @var{users} part tells which users' access to the file is changed. +It consists of one or more of the following letters (or it can be empty; +@pxref{Umask and Protection}, for a description of what happens then). When +more than one of these letters is given, the order that they are in does +not matter. + +@table @code +@item u +@cindex owner of file, permissions for +the user who owns the file; +@item g +@cindex group, permissions for +other users who are in the file's group; +@item o +@cindex other permissions +all other users; +@item a +all users; the same as @samp{ugo}. +@end table + +The @var{operation} part tells how to change the affected users' access +to the file, and is one of the following symbols: + +@table @code +@item + +@cindex adding permissions +to add the @var{permissions} to whatever permissions the @var{users} +already have for the file; +@item - +@cindex removing permissions +@cindex subtracting permissions +to remove the @var{permissions} from whatever permissions the +@var{users} already have for the file; +@item = +@cindex setting permissions +to make the @var{permissions} the only permissions that the @var{users} +have for the file. +@end table + +The @var{permissions} part tells what kind of access to the file should +be changed; it is normally zero or more of the following letters. As with the +@var{users} part, the order does not matter when more than one letter is +given. Omitting the @var{permissions} part is useful only with the +@samp{=} operation, where it gives the specified @var{users} no access +at all to the file. + +@table @code +@item r +@cindex read permission, symbolic +the permission the @var{users} have to read the file; +@item w +@cindex write permission, symbolic +the permission the @var{users} have to write to the file; +@item x +@cindex execute permission, symbolic +the permission the @var{users} have to execute the file. +@end table + +For example, to give everyone permission to read and write a file, +but not to execute it, use: + +@example +a=rw +@end example + +To remove write permission for all users other than the file's +owner, use: + +@example +go-w +@end example + +@noindent +The above command does not affect the access that the owner of +the file has to it, nor does it affect whether other users can +read or execute the file. + +To give everyone except a file's owner no permission to do anything with +that file, use the mode below. Other users could still remove the file, +if they have write permission on the directory it is in. + +@example +go= +@end example + +@noindent +Another way to specify the same thing is: + +@example +og-rwx +@end example + +@node Copying Permissions +@subsection Copying Existing Permissions + +@cindex copying existing permissions +@cindex permissions, copying existing +You can base a file's permissions on its existing permissions. To do +this, instead of using a series of @samp{r}, @samp{w}, or @samp{x} +letters after the +operator, you use the letter @samp{u}, @samp{g}, or @samp{o}. For +example, the mode + +@example +o+g +@end example + +@noindent +adds the permissions for users who are in a file's group to the +permissions that other users have for the file. Thus, if the file +started out as mode 664 (@samp{rw-rw-r--}), the above mode would change +it to mode 666 (@samp{rw-rw-rw-}). If the file had started out as mode +741 (@samp{rwxr----x}), the above mode would change it to mode 745 +(@samp{rwxr--r-x}). The @samp{-} and @samp{=} operations work +analogously. + +@node Changing Special Permissions +@subsection Changing Special Permissions + +@cindex changing special permissions +In addition to changing a file's read, write, and execute permissions, +you can change its special permissions. @xref{Mode Structure}, for a +summary of these permissions. + +To change a file's permission to set the user ID on execution, use +@samp{u} in the @var{users} part of the symbolic mode and +@samp{s} in the @var{permissions} part. + +To change a file's permission to set the group ID on execution, use +@samp{g} in the @var{users} part of the symbolic mode and +@samp{s} in the @var{permissions} part. + +To change a file's permission to set the restricted deletion flag or sticky bit, +omit the @var{users} part of the symbolic mode (or use @samp{a}) and put +@samp{t} in the @var{permissions} part. + +For example, to add set-user-ID permission to a program, +you can use the mode: + +@example +u+s +@end example + +To remove both set-user-ID and set-group-ID permission from +it, you can use the mode: + +@example +ug-s +@end example + +To set the restricted deletion flag or sticky bit, you can use +the mode: + +@example ++t +@end example + +The combination @samp{o+s} has no effect. On @acronym{GNU} systems +the combinations @samp{u+t} and @samp{g+t} have no effect, and +@samp{o+t} acts like plain @samp{+t}. + +The @samp{=} operator is not very useful with special permissions; for +example, the mode: + +@example +o=t +@end example + +@noindent +does set the restricted deletion flag or sticky bit, but it also +removes all read, write, and execute permissions that users not in the +file's group might have had for it. + +@node Conditional Executability +@subsection Conditional Executability + +@cindex conditional executability +There is one more special type of symbolic permission: if you use +@samp{X} instead of @samp{x}, execute permission is affected only if the +file is a directory or already had execute permission. + +For example, this mode: + +@example +a+X +@end example + +@noindent +gives all users permission to search directories, or to execute files if +anyone could execute them before. + +@node Multiple Changes +@subsection Making Multiple Changes + +@cindex multiple changes to permissions +The format of symbolic modes is actually more complex than described +above (@pxref{Setting Permissions}). It provides two ways to make +multiple changes to files' permissions. + +The first way is to specify multiple @var{operation} and +@var{permissions} parts after a @var{users} part in the symbolic mode. + +For example, the mode: + +@example +og+rX-w +@end example + +@noindent +gives users other than the owner of the file read permission and, if +it is a directory or if someone already had execute permission +to it, gives them execute permission; and it also denies them write +permission to the file. It does not affect the permission that the +owner of the file has for it. The above mode is equivalent to +the two modes: + +@example +og+rX +og-w +@end example + +The second way to make multiple changes is to specify more than one +simple symbolic mode, separated by commas. For example, the mode: + +@example +a+r,go-w +@end example + +@noindent +gives everyone permission to read the file and removes write +permission on it for all users except its owner. Another example: + +@example +u=rwx,g=rx,o= +@end example + +@noindent +sets all of the non-special permissions for the file explicitly. (It +gives users who are not in the file's group no permission at all for +it.) + +The two methods can be combined. The mode: + +@example +a+r,g+x-w +@end example + +@noindent +gives all users permission to read the file, and gives users who are in +the file's group permission to execute it, as well, but not permission +to write to it. The above mode could be written in several different +ways; another is: + +@example +u+r,g+rx,o+r,g-w +@end example + +@node Umask and Protection +@subsection The Umask and Protection + +@cindex umask and modes +@cindex modes and umask +If the @var{users} part of a symbolic mode is omitted, it defaults to +@samp{a} (affect all users), except that any permissions that are +@emph{set} in the system variable @code{umask} are @emph{not affected}. +The value of @code{umask} can be set using the +@code{umask} command. Its default value varies from system to system. + +@cindex giving away permissions +Omitting the @var{users} part of a symbolic mode is generally not useful +with operations other than @samp{+}. It is useful with @samp{+} because +it allows you to use @code{umask} as an easily customizable protection +against giving away more permission to files than you intended to. + +As an example, if @code{umask} has the value 2, which removes write +permission for users who are not in the file's group, then the mode: + +@example ++w +@end example + +@noindent +adds permission to write to the file to its owner and to other users who +are in the file's group, but @emph{not} to other users. In contrast, +the mode: + +@example +a+w +@end example + +@noindent +ignores @code{umask}, and @emph{does} give write permission for +the file to all users. + +@node Numeric Modes +@section Numeric Modes + +@cindex numeric modes +@cindex file permissions, numeric +@cindex octal numbers for file modes +As an +alternative to giving a symbolic mode, you can give an octal (base 8) +number that represents the new mode. +This number is always interpreted in octal; you do not have to add a +leading 0, as you do in C. Mode 0055 is the same as mode 55. + +A numeric mode is usually shorter than the corresponding symbolic +mode, but it is limited in that it cannot take into account a file's +previous permissions; it can only set them absolutely. + +The permissions granted to the user, +to other users in the file's group, +and to other users not in the file's group each require three +bits, which are represented as one octal digit. The three special +permissions also require one bit each, and they are as a group +represented as another octal digit. Here is how the bits are arranged, +starting with the lowest valued bit: + +@example +Value in Corresponding +Mode Permission + + Other users not in the file's group: + 1 Execute + 2 Write + 4 Read + + Other users in the file's group: + 10 Execute + 20 Write + 40 Read + + The file's owner: + 100 Execute + 200 Write + 400 Read + + Special permissions: +1000 Restricted deletion flag or sticky bit +2000 Set group ID on execution +4000 Set user ID on execution +@end example + +For example, numeric mode 4755 corresponds to symbolic mode +@samp{u=rwxs,go=rx}, and numeric mode 664 corresponds to symbolic mode +@samp{ug=rw,o=r}. Numeric mode 0 corresponds to symbolic mode +@samp{a=}. diff --git a/doc/regexprops.texi b/doc/regexprops.texi new file mode 100644 index 0000000..537b64e --- /dev/null +++ b/doc/regexprops.texi @@ -0,0 +1,592 @@ +@c Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003, 2004, 2005, 2006, +@c 2007, 2009, 2010, 2011 Free Software Foundation, Inc. +@c +@c Permission is granted to copy, distribute and/or modify this document +@c under the terms of the GNU Free Documentation License, Version 1.3 or +@c any later version published by the Free Software Foundation; with no +@c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +@c A copy of the license is included in the ``GNU Free +@c Documentation License'' file as part of this distribution. + +@c this regular expression description is for: findutils + +@menu +* findutils-default regular expression syntax:: +* awk regular expression syntax:: +* egrep regular expression syntax:: +* emacs regular expression syntax:: +* gnu-awk regular expression syntax:: +* grep regular expression syntax:: +* posix-awk regular expression syntax:: +* posix-basic regular expression syntax:: +* posix-egrep regular expression syntax:: +* posix-extended regular expression syntax:: +@end menu + +@node findutils-default regular expression syntax +@subsection @samp{findutils-default} regular expression syntax + + +The character @samp{.} matches any single character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are not supported, so for example you would need to use @samp{[0-9]} instead of @samp{[[:digit:]]}. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{\(}. + +The alternation operator is @samp{\|}. + +The character @samp{^} only represents the beginning of a string when it appears: +@enumerate + +@item +At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} + +@item After the alternation operator @samp{\|} + +@end enumerate + + +The character @samp{$} only represents the end of a string when it appears: +@enumerate + +@item At the end of a regular expression + +@item Before a close-group, signified by +@samp{\)} +@item Before the alternation operator @samp{\|} + +@end enumerate + + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} +@item After the alternation operator @samp{\|} + +@end enumerate + + + + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node awk regular expression syntax +@subsection @samp{awk} regular expression syntax + + +The character @samp{.} matches any single character except the null character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} can be used to quote the following character. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are not supported and so @samp{\w}, @samp{\W}, @samp{\<}, @samp{\>}, @samp{\b}, @samp{\B}, @samp{\`}, and @samp{\'} match @samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively. + +Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit matches that digit. + +The alternation operator is @samp{|}. + +The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{(} +@item After the alternation operator @samp{|} + +@end enumerate + + + + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node egrep regular expression syntax +@subsection @samp{egrep} regular expression syntax + + +The character @samp{.} matches any single character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}. + +The alternation operator is @samp{|}. + +The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. + +The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression. + +Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1} + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node emacs regular expression syntax +@subsection @samp{emacs} regular expression syntax + + +The character @samp{.} matches any single character except newline. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are not supported, so for example you would need to use @samp{[0-9]} instead of @samp{[[:digit:]]}. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{\(}. + +The alternation operator is @samp{\|}. + +The character @samp{^} only represents the beginning of a string when it appears: +@enumerate + +@item +At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} + +@item After the alternation operator @samp{\|} + +@end enumerate + + +The character @samp{$} only represents the end of a string when it appears: +@enumerate + +@item At the end of a regular expression + +@item Before a close-group, signified by +@samp{\)} +@item Before the alternation operator @samp{\|} + +@end enumerate + + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} +@item After the alternation operator @samp{\|} + +@end enumerate + + + + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node gnu-awk regular expression syntax +@subsection @samp{gnu-awk} regular expression syntax + + +The character @samp{.} matches any single character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} can be used to quote the following character. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}. + +The alternation operator is @samp{|}. + +The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{(} +@item After the alternation operator @samp{|} + +@end enumerate + + +Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1} + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node grep regular expression syntax +@subsection @samp{grep} regular expression syntax + + +The character @samp{.} matches any single character. + + +@table @samp + +@item \+ +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item \? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item + and ? +match themselves. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{\(}. + +The alternation operator is @samp{\|}. + +The character @samp{^} only represents the beginning of a string when it appears: +@enumerate + +@item +At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} + +@item After a newline + +@item After the alternation operator @samp{\|} + +@end enumerate + + +The character @samp{$} only represents the end of a string when it appears: +@enumerate + +@item At the end of a regular expression + +@item Before a close-group, signified by +@samp{\)} +@item Before a newline + +@item Before the alternation operator @samp{\|} + +@end enumerate + + +@samp{\*}, @samp{\+} and @samp{\?} are special at any point in a regular expression except: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{\(} +@item After a newline + +@item After the alternation operator @samp{\|} + +@end enumerate + + +Intervals are specified by @samp{\@{} and @samp{\@}}. Invalid intervals such as @samp{a\@{1z} are not accepted. + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node posix-awk regular expression syntax +@subsection @samp{posix-awk} regular expression syntax + + +The character @samp{.} matches any single character except the null character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} can be used to quote the following character. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are not supported and so @samp{\w}, @samp{\W}, @samp{\<}, @samp{\>}, @samp{\b}, @samp{\B}, @samp{\`}, and @samp{\'} match @samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively. + +Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}. + +The alternation operator is @samp{|}. + +The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except the following places, where they are not allowed: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{(} +@item After the alternation operator @samp{|} + +@end enumerate + + +Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1} + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + + +@node posix-basic regular expression syntax +@subsection @samp{posix-basic} regular expression syntax +This is a synonym for ed. +@node posix-egrep regular expression syntax +@subsection @samp{posix-egrep} regular expression syntax +This is a synonym for egrep. +@node posix-extended regular expression syntax +@subsection @samp{posix-extended} regular expression syntax + + +The character @samp{.} matches any single character except the null character. + + +@table @samp + +@item + +indicates that the regular expression should match one or more occurrences of the previous atom or regexp. +@item ? +indicates that the regular expression should match zero or one occurrence of the previous atom or regexp. +@item \+ +matches a @samp{+} +@item \? +matches a @samp{?}. +@end table + + +Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit. + +GNU extensions are supported: +@enumerate + +@item @samp{\w} matches a character within a word + +@item @samp{\W} matches a character which is not within a word + +@item @samp{\<} matches the beginning of a word + +@item @samp{\>} matches the end of a word + +@item @samp{\b} matches a word boundary + +@item @samp{\B} matches characters which are not a word boundary + +@item @samp{\`} matches the beginning of the whole input + +@item @samp{\'} matches the end of the whole input + +@end enumerate + + +Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}. + +The alternation operator is @samp{|}. + +The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. + +@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except the following places, where they are not allowed: +@enumerate + +@item At the beginning of a regular expression + +@item After an open-group, signified by +@samp{(} +@item After the alternation operator @samp{|} + +@end enumerate + + +Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals such as @samp{a@{1z} are not accepted. + +The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. + diff --git a/doc/stamp-1 b/doc/stamp-1 new file mode 100644 index 0000000..5d0c32b --- /dev/null +++ b/doc/stamp-1 @@ -0,0 +1,4 @@ +@set UPDATED 28 December 2015 +@set UPDATED-MONTH December 2015 +@set EDITION 4.6.0 +@set VERSION 4.6.0 diff --git a/doc/stamp-vti b/doc/stamp-vti new file mode 100644 index 0000000..5d0c32b --- /dev/null +++ b/doc/stamp-vti @@ -0,0 +1,4 @@ +@set UPDATED 28 December 2015 +@set UPDATED-MONTH December 2015 +@set EDITION 4.6.0 +@set VERSION 4.6.0 diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..cfb5c56 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,10174 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2014-05-05.10} +% +% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +% 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. +% +% This texinfo.tex file 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. +% +% This texinfo.tex file 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 <http://www.gnu.org/licenses/>. +% +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. This Exception is an additional permission under section 7 +% of the GNU General Public License, version 3 ("GPLv3"). +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or +% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or +% http://www.gnu.org/software/texinfo/ (the Texinfo home page) +% The texinfo.tex in any given distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. + + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexfootnote=\footnote +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexinsert=\insert +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent +\let\ptexplus=+ +\let\ptexraggedright=\raggedright +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t +\let\ptextop=\top +{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{l.\the\inputlineno:\space} +\fi + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putworderror\undefined \gdef\putworderror{error}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi + +% Since the category of space is not known, we have to be careful. +\chardef\spacecat = 10 +\def\spaceisspace{\catcode`\ =\spacecat} + +% sometimes characters are active, so we need control sequences. +\chardef\ampChar = `\& +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dashChar = `\- +\chardef\dotChar = `\. +\chardef\exclamChar= `\! +\chardef\hashChar = `\# +\chardef\lquoteChar= `\` +\chardef\questChar = `\? +\chardef\rquoteChar= `\' +\chardef\semiChar = `\; +\chardef\slashChar = `\/ +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} + +% Hyphenation fixes. +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt } + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\thisisundefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines16 +}% + +% @errormsg{MSG}. Do the index-like expansions on MSG, but if things +% aren't perfect, it's not the end of the world, being an error message, +% after all. +% +\def\errormsg{\begingroup \indexnofonts \doerrormsg} +\def\doerrormsg#1{\errmessage{#1}} + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Output a mark which sets \thischapter, \thissection and \thiscolor. +% We dump everything together because we only have one kind of mark. +% This works because we only use \botmark / \topmark, not \firstmark. +% +% A mark contains a subexpression of the \ifcase ... \fi construct. +% \get*marks macros below extract the needed part using \ifcase. +% +% Another complication is to let the user choose whether \thischapter +% (\thissection) refers to the chapter (section) in effect at the top +% of a page, or that at the bottom of a page. The solution is +% described on page 260 of The TeXbook. It involves outputting two +% marks for the sectioning macros, one before the section break, and +% one after. I won't pretend I can describe this better than DEK... +\def\domark{% + \toks0=\expandafter{\lastchapterdefs}% + \toks2=\expandafter{\lastsectiondefs}% + \toks4=\expandafter{\prevchapterdefs}% + \toks6=\expandafter{\prevsectiondefs}% + \toks8=\expandafter{\lastcolordefs}% + \mark{% + \the\toks0 \the\toks2 % 0: top marks (\last...) + \noexpand\or \the\toks4 \the\toks6 % 1: bottom marks (default, \prev...) + \noexpand\else \the\toks8 % 2: color marks + }% +} +% \topmark doesn't work for the very first chapter (after the title +% page or the contents), so we use \firstmark there -- this gets us +% the mark with the chapter defs, unless the user sneaks in, e.g., +% @setcolor (or @url, or @link, etc.) between @contents and the very +% first @chapter. +\def\gettopheadingmarks{% + \ifcase0\topmark\fi + \ifx\thischapter\empty \ifcase0\firstmark\fi \fi +} +\def\getbottomheadingmarks{\ifcase1\botmark\fi} +\def\getcolormarks{\ifcase2\topmark\fi} + +% Avoid "undefined control sequence" errors. +\def\lastchapterdefs{} +\def\lastsectiondefs{} +\def\prevchapterdefs{} +\def\prevsectiondefs{} +\def\lastcolordefs{} + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \def\commmonheadfootline{\let\hsize=\pagewidth \texinfochars} + % + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi + \global\setbox\headlinebox = \vbox{\commmonheadfootline \makeheadline}% + % + \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi + \global\setbox\footlinebox = \vbox{\commmonheadfootline \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + % We don't want .vr (or whatever) entries like this: + % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} + % "\acronym" won't work when it's read back in; + % it needs to be + % {\code {{\tt \backslashcurfont }acronym} + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingyyy.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 24pt + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \indexdummies + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1\relax \unvbox#1\relax +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\argtorun{#2}% + \begingroup + \obeylines + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. +} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + \argremovecomment #1\comment\ArgTerm% + }% +} + +% First remove any @comment, then any @c comment. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} + +% Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, e.g., +% @end itemize @c foo +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. +% +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm +} + +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \argtorun. +% (Similarly, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. +% +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} + +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +% +% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my +% favourite TeX trick. --kasal, 16nov03 + +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} + +% Several utility definitions with active space: +{ + \obeyspaces + \gdef\obeyedspace{ } + + % Make each space character in the input produce a normal interword + % space in the output. Don't allow a line break at this space, as this + % is used only in environments like @example, where each line of input + % should produce a line of output anyway. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % If an index command is used in an @example environment, any spaces + % therein should become regular spaces in the raw index file, not the + % expansion of \tie (\leavevmode \penalty \@M \ ). + \gdef\unsepspaces{\let =\space} +} + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +% Define the framework for environments in texinfo.tex. It's used like this: +% +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as environments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At run-time, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp + \else + \badenverr + \fi +} + +% Environment mismatch, #1 expected: +\def\badenverr{% + \errhelp = \EMsimple + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + outside of any environment% + \else + in environment \expandafter\string#1% + \fi +} + +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv +% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal. + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi +} + +\newhelp\EMsimple{Press RETURN to continue.} + + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\unskip\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=\endofsentencespacefactor\space} + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=\endofsentencespacefactor\space} + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on|off}% + \fi\fi +} + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\envdef\group{% + \ifnum\catcode`\^^M=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + \startsavinginserts + % + \setbox\groupbox = \vtop\bgroup + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% The \vtop produces a box with normal height and large depth; thus, TeX puts +% \baselineskip glue before it, and (when the next line of text is done) +% \lineskip glue after it. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \box\groupbox + \prevdepth = \dimen1 + \checkinserts +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\parseargdef\need{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break (and is undocumented). + +\let\br = \par + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} + +% This defn is used inside nofill environments such as @example. +\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount + \leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. Not documented, written for gawk manual. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). This command +% is not documented, not supported, and doesn't work. +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% @include FILE -- \input text of FILE. +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack + \def\thisfile{#1}% + {% + \makevalueexpandable % we want to expand any @value in FILE. + \turnoffactive % and allow special characters in the expansion + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @include of #1^^J}% + \edef\temp{\noexpand\input #1 }% + % + % This trickery is to read FILE outside of a group, in case it makes + % definitions, etc. + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \catcode`-=\other + \catcode`\`=\other + \catcode`\'=\other +} + +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} +% +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\parseargdef\center{% + \ifhmode + \let\centersub\centerH + \else + \let\centersub\centerV + \fi + \centersub{\hfil \ignorespaces#1\unskip \hfil}% + \let\centersub\relax % don't let the definition persist, just in case +} +\def\centerH#1{{% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break +}} +% +\newcount\centerpenalty +\def\centerV#1{% + % The idea here is the same as in \startdefun, \cartouche, etc.: if + % @center is the first thing after a section heading, we need to wipe + % out the negative parskip inserted by \sectionheading, but still + % prevent a page break here. + \centerpenalty = \lastpenalty + \ifnum\centerpenalty>10000 \vskip\parskip \fi + \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi + \line{\kern\leftskip #1\kern\rightskip}% +} + +% @sp n outputs n lines of vertical space +% +\parseargdef\sp{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment +% +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} +% +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\parseargdef\paragraphindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\parseargdef\exampleindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indent at such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. +% We switch the definition of this back and forth according to WORD. +% By default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\def\insertword{insert} +% +\parseargdef\firstparagraphindent{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \restorefirstparagraphindent + \indent + }% + \gdef\noindent{% + \restorefirstparagraphindent + \noindent + }% + \global\everypar = {% + \kern -\parindent + \restorefirstparagraphindent + }% +} + +\gdef\restorefirstparagraphindent{% + \global \let \indent = \ptexindent + \global \let \noindent = \ptexnoindent + \global \everypar = {}% +} + + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi % \openindices needs to do some work in any case. + \openindices + \let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + \openin 1 texinfo.cnf + \ifeof 1 \else \input texinfo.cnf \fi + \closein 1 + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as being undefined. +\ifx\pdfoutput\thisisundefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% +% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and +% related messages. The final outcome is that it is up to the TeX user +% to double the backslashes and otherwise make the string valid, so +% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to +% do this reliably, so we use it. + +% #1 is a control sequence in which to do the replacements, +% which we \xdef. +\def\txiescapepdf#1{% + \ifx\pdfescapestring\thisisundefined + % No primitive available; should we give a warning or log? + % Many times it won't matter. + \else + % The expandable \pdfescapestring primitive escapes parentheses, + % backslashes, and other special chars. + \xdef#1{\pdfescapestring{#1}}% + \fi +} + +\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images +with PDF output, and none of those formats could be found. (.eps cannot +be supported due to the design of the PDF format; use regular TeX (DVI +output) for that.)} + +\ifpdf + % + % Color manipulation macros using ideas from pdfcolor.tex, + % except using rgb instead of cmyk; the latter is said to render as a + % very dark gray on-screen and a very dark halftone in print, instead + % of actual black. The dark red here is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. We use + % black by default, though. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + % k sets the color for filling (usual text, etc.); + % K sets the color for stroking (thin rules, e.g., normal _'s). + \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\rgbBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\lastcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % + \pdfcatalog{/PageMode /UseOutlines} + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\dopdfimage#1#2#3{% + \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % pdftex (and the PDF format) support .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if + % someone has a scalable image, presumably better to use that than a + % bitmap. + \let\pdfimgext=\empty + \begingroup + \openin 1 #1.pdf \ifeof 1 + \openin 1 #1.PDF \ifeof 1 + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \errhelp = \nopdfimagehelp + \errmessage{Could not find image file #1 for pdf}% + \else \gdef\pdfimgext{JPG}% + \fi + \else \gdef\pdfimgext{jpeg}% + \fi + \else \gdef\pdfimgext{jpg}% + \fi + \else \gdef\pdfimgext{png}% + \fi + \else \gdef\pdfimgext{PDF}% + \fi + \else \gdef\pdfimgext{pdf}% + \fi + \closein 1 + \endgroup + % + % without \immediate, ancient pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifdim \wd0 >0pt width \pdfimagewidth \fi + \ifdim \wd2 >0pt height \pdfimageheight \fi + \ifnum\pdftexversion<13 + #1.\pdfimgext + \else + {#1.\pdfimgext}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + % + \def\pdfmkdest#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \turnoffactive + \makevalueexpandable + \def\pdfdestname{#1}% + \txiescapepdf\pdfdestname + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + }} + % + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1} + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \def\linkcolor{\rgbBlack} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by 1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + % + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worth the trouble, since most documents are normally structured. + \edef\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty + \def\pdfoutlinedest{#4}% + \else + \txiescapepdf\pdfoutlinedest + \fi + % + % Also escape PDF chars in the display string. + \edef\pdfoutlinetext{#1}% + \txiescapepdf\pdfoutlinetext + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% + } + % + \def\pdfmakeoutlines{% + \begingroup + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\partentry##1##2##3##4{}% ignore parts in the outlines + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \def\thissubsecnum{0}% + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% + \readdatafile{toc}% + % + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. + % + % TODO this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Too + % much work for too little return. Just use the ASCII equivalents + % we use for the index sort strings. + % + \indexnofonts + \setupdatafile + % We can have normal brace characters in the PDF outlines, unlike + % Texinfo index files. So set that up. + \def\{{\lbracecharliteral}% + \def\}{\rbracecharliteral}% + \catcode`\\=\active \otherbackslash + \input \tocreadfilename + \endgroup + } + {\catcode`[=1 \catcode`]=2 + \catcode`{=\other \catcode`}=\other + \gdef\lbracecharliteral[{]% + \gdef\rbracecharliteral[}]% + ] + % + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \nextsp} + \def\getfilename#1{% + \filenamelength=0 + % If we don't expand the argument now, \skipspaces will get + % snagged on things like "@value{foo}". + \edef\temp{#1}% + \expandafter\skipspaces\temp|\relax + } + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \setcolor{\linkcolor}#1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\else + % non-pdf mode + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\setcolor = \gobble + \let\pdfsetcolor = \gobble + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput + + +\message{fonts,} + +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname ten#1\endcsname % change the current font +} + +% Select #1 fonts with the current style. +% +\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Unfortunately, we have to override this for titles and the like, since +% in those cases "rm" is bold. Sigh. +\def\rmisbold{\rm\def\curfontstyle{bf}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +% can get a sort of poor man's double spacing by redefining this. +\def\baselinefactor{1} +% +\newdimen\textleading +\def\setleading#1{% + \dimen0 = #1\relax + \normalbaselineskip = \baselinefactor\dimen0 + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% PDF CMaps. See also LaTeX's t1.cmap. +% +% do nothing with this by default. +\expandafter\let\csname cmapOT1\endcsname\gobble +\expandafter\let\csname cmapOT1IT\endcsname\gobble +\expandafter\let\csname cmapOT1TT\endcsname\gobble + +% if we are producing pdf, and we have \pdffontattr, then define cmaps. +% (\pdffontattr was introduced many years ago, but people still run +% older pdftex's; it's easy to conditionalize, so we do.) +\ifpdf \ifx\pdffontattr\thisisundefined \else + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1-0) +%%Title: (TeX-OT1-0 TeX OT1 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1) +/Supplement 0 +>> def +/CMapName /TeX-OT1-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<23> <26> <0023> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +40 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1IT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1IT-0) +%%Title: (TeX-OT1IT-0 TeX OT1IT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1IT) +/Supplement 0 +>> def +/CMapName /TeX-OT1IT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<25> <26> <0025> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +42 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<23> <0023> +<24> <00A3> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1IT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1TT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1TT-0) +%%Title: (TeX-OT1TT-0 TeX OT1TT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1TT) +/Supplement 0 +>> def +/CMapName /TeX-OT1TT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +5 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<21> <26> <0021> +<28> <5F> <0028> +<61> <7E> <0061> +endbfrange +32 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <2191> +<0C> <2193> +<0D> <0027> +<0E> <00A1> +<0F> <00BF> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<20> <2423> +<27> <2019> +<60> <2018> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1TT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +\fi\fi + + +% Set the font macro #1 to the font named \fontprefix#2. +% #3 is the font's design size, #4 is a scale factor, #5 is the CMap +% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). +% Example: +% #1 = \textrm +% #2 = \rmshape +% #3 = 10 +% #4 = \mainmagstep +% #5 = OT1 +% +\def\setfont#1#2#3#4#5{% + \font#1=\fontprefix#2#3 scaled #4 + \csname cmap#5\endcsname#1% +} +% This is what gets called when #5 of \setfont is empty. +\let\cmap\gobble +% +% (end of cmaps) + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\thisisundefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} % where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +% Definitions for a main text size of 11pt. (The default in Texinfo.) +% +\def\definetextfontsizexi{% +% Text fonts (11.2pt, magstep1). +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1095} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1}{OT1} +\setfont\deftt\ttshape{10}{\magstep1}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\titleecsize{2074} + +% Chapter (and unnumbered) fonts (17.28pt). +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2}{OT1} +\setfont\chapit\itbshape{10}{\magstep3}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep3}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} +\setfont\chapsf\sfbshape{17}{1000}{OT1} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3}{OT1} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 +\def\chapecsize{1728} + +% Section fonts (14.4pt). +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1}{OT1} +\setfont\secit\itbshape{10}{\magstep2}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep2}{OT1} +\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\secsf\sfbshape{12}{\magstep1}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2}{OT1} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 +\def\sececsize{1440} + +% Subsection fonts (13.15pt). +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} +\setfont\ssecit\itbshape{10}{1315}{OT1IT} +\setfont\ssecsl\slbshape{10}{1315}{OT1} +\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} +\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1315}{OT1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +\def\ssececsize{1200} + +% Reduced fonts for @acro in text (10pt). +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000}{OT1} +\setfont\reducedtt\ttshape{10}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{1000}{OT1} +\setfont\reducedit\itshape{10}{1000}{OT1IT} +\setfont\reducedsl\slshape{10}{1000}{OT1} +\setfont\reducedsf\sfshape{10}{1000}{OT1} +\setfont\reducedsc\scshape{10}{1000}{OT1} +\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 +\def\reducedecsize{1000} + +\textleading = 13.2pt % line spacing for 11pt CM +\textfonts % reset the current fonts +\rm +} % end of 11pt text font size definitions, \definetextfontsizexi + + +% Definitions to make the main text be 10pt Computer Modern, with +% section, chapter, etc., sizes following suit. This is for the GNU +% Press printing of the Emacs 22 manual. Maybe other manuals in the +% future. Used with @smallbook, which sets the leading to 12pt. +% +\def\definetextfontsizex{% +% Text fonts (10pt). +\def\textnominalsize{10pt} +\edef\mainmagstep{1000} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1000} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstephalf}{OT1} +\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\titleecsize{2074} + +% Chapter fonts (14.4pt). +\def\chapnominalsize{14pt} +\setfont\chaprm\rmbshape{12}{\magstep1}{OT1} +\setfont\chapit\itbshape{10}{\magstep2}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep2}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\chapsf\sfbshape{12}{\magstep1}{OT1} +\let\chapbf\chaprm +\setfont\chapsc\scbshape{10}{\magstep2}{OT1} +\font\chapi=cmmi12 scaled \magstep1 +\font\chapsy=cmsy10 scaled \magstep2 +\def\chapecsize{1440} + +% Section fonts (12pt). +\def\secnominalsize{12pt} +\setfont\secrm\rmbshape{12}{1000}{OT1} +\setfont\secit\itbshape{10}{\magstep1}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep1}{OT1} +\setfont\sectt\ttbshape{12}{1000}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} +\setfont\secsf\sfbshape{12}{1000}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep1}{OT1} +\font\seci=cmmi12 +\font\secsy=cmsy10 scaled \magstep1 +\def\sececsize{1200} + +% Subsection fonts (10pt). +\def\ssecnominalsize{10pt} +\setfont\ssecrm\rmbshape{10}{1000}{OT1} +\setfont\ssecit\itbshape{10}{1000}{OT1IT} +\setfont\ssecsl\slbshape{10}{1000}{OT1} +\setfont\ssectt\ttbshape{10}{1000}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} +\setfont\ssecsf\sfbshape{10}{1000}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1000}{OT1} +\font\sseci=cmmi10 +\font\ssecsy=cmsy10 +\def\ssececsize{1000} + +% Reduced fonts for @acro in text (9pt). +\def\reducednominalsize{9pt} +\setfont\reducedrm\rmshape{9}{1000}{OT1} +\setfont\reducedtt\ttshape{9}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{900}{OT1} +\setfont\reducedit\itshape{9}{1000}{OT1IT} +\setfont\reducedsl\slshape{9}{1000}{OT1} +\setfont\reducedsf\sfshape{9}{1000}{OT1} +\setfont\reducedsc\scshape{10}{900}{OT1} +\setfont\reducedttsl\ttslshape{10}{900}{OT1TT} +\font\reducedi=cmmi9 +\font\reducedsy=cmsy9 +\def\reducedecsize{0900} + +\divide\parskip by 2 % reduce space between paragraphs +\textleading = 12pt % line spacing for 10pt CM +\textfonts % reset the current fonts +\rm +} % end of 10pt text font size definitions, \definetextfontsizex + + +% We provide the user-level command +% @fonttextsize 10 +% (or 11) to redefine the text font size. pt is assumed. +% +\def\xiword{11} +\def\xword{10} +\def\xwordpt{10pt} +% +\parseargdef\fonttextsize{% + \def\textsizearg{#1}% + %\wlog{doing @fonttextsize \textsizearg}% + % + % Set \globaldefs so that documents can use this inside @tex, since + % makeinfo 4.8 does not support it, but we need it nonetheless. + % + \begingroup \globaldefs=1 + \ifx\textsizearg\xword \definetextfontsizex + \else \ifx\textsizearg\xiword \definetextfontsizexi + \else + \errhelp=\EMsimple + \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} + \fi\fi + \endgroup +} + + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this because \STYLE needs to also set the +% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire +% \tenSTYLE to set the current font. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used in +% the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \let\tenttsl=\textttsl + \def\curfontsize{text}% + \def\lsize{reduced}\def\lllsize{smaller}% + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \def\curfontsize{title}% + \def\lsize{chap}\def\lllsize{subsec}% + \resetmathfonts \setleading{27pt}} +\def\titlefont#1{{\titlefonts\rmisbold #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \let\tenttsl=\chapttsl + \def\curfontsize{chap}% + \def\lsize{sec}\def\lllsize{text}% + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \let\tenttsl=\secttsl + \def\curfontsize{sec}% + \def\lsize{subsec}\def\lllsize{reduced}% + \resetmathfonts \setleading{17pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \let\tenttsl=\ssecttsl + \def\curfontsize{ssec}% + \def\lsize{text}\def\lllsize{small}% + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts +\def\reducedfonts{% + \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl + \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc + \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy + \let\tenttsl=\reducedttsl + \def\curfontsize{reduced}% + \def\lsize{small}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \def\curfontsize{small}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \def\curfontsize{smaller}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{9.5pt}} + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000}{OT1} +\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000}{OT1} +\setfont\shortconttt\ttshape{12}{1000}{OT1TT} + +% Define these just so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \scriptfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% --karl, 24jan03. + +% Set up the default fonts, so we can use them for creating boxes. +% +\definetextfontsizexi + + +\message{markup,} + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will +% define and register \INITMACRO to be called on markup style changes. +% \INITMACRO can check \currentmarkupstyle for the innermost +% style and the set of \ifmarkupSTYLE switches for all styles +% currently in effect. +\newif\ifmarkupvar +\newif\ifmarkupsamp +\newif\ifmarkupkey +%\newif\ifmarkupfile % @file == @samp. +%\newif\ifmarkupoption % @option == @samp. +\newif\ifmarkupcode +\newif\ifmarkupkbd +%\newif\ifmarkupenv % @env == @code. +%\newif\ifmarkupcommand % @command == @code. +\newif\ifmarkuptex % @tex (and part of @math, for now). +\newif\ifmarkupexample +\newif\ifmarkupverb +\newif\ifmarkupverbatim + +\let\currentmarkupstyle\empty + +\def\setupmarkupstyle#1{% + \csname markup#1true\endcsname + \def\currentmarkupstyle{#1}% + \markupstylesetup +} + +\let\markupstylesetup\empty + +\def\defmarkupstylesetup#1{% + \expandafter\def\expandafter\markupstylesetup + \expandafter{\markupstylesetup #1}% + \def#1% +} + +% Markup style setup for left and right quotes. +\defmarkupstylesetup\markupsetuplq{% + \expandafter\let\expandafter \temp + \csname markupsetuplq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuplqdefault \else \temp \fi +} + +\defmarkupstylesetup\markupsetuprq{% + \expandafter\let\expandafter \temp + \csname markupsetuprq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuprqdefault \else \temp \fi +} + +{ +\catcode`\'=\active +\catcode`\`=\active + +\gdef\markupsetuplqdefault{\let`\lq} +\gdef\markupsetuprqdefault{\let'\rq} + +\gdef\markupsetcodequoteleft{\let`\codequoteleft} +\gdef\markupsetcodequoteright{\let'\codequoteright} +} + +\let\markupsetuplqcode \markupsetcodequoteleft +\let\markupsetuprqcode \markupsetcodequoteright +% +\let\markupsetuplqexample \markupsetcodequoteleft +\let\markupsetuprqexample \markupsetcodequoteright +% +\let\markupsetuplqkbd \markupsetcodequoteleft +\let\markupsetuprqkbd \markupsetcodequoteright +% +\let\markupsetuplqsamp \markupsetcodequoteleft +\let\markupsetuprqsamp \markupsetcodequoteright +% +\let\markupsetuplqverb \markupsetcodequoteleft +\let\markupsetuprqverb \markupsetcodequoteright +% +\let\markupsetuplqverbatim \markupsetcodequoteleft +\let\markupsetuprqverbatim \markupsetcodequoteright + +% Allow an option to not use regular directed right quote/apostrophe +% (char 0x27), but instead the undirected quote from cmtt (char 0x0d). +% The undirected quote is ugly, so don't make it the default, but it +% works for pasting with more pdf viewers (at least evince), the +% lilypond developers report. xpdf does work with the regular 0x27. +% +\def\codequoteright{% + \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else \char'15 \fi + \else \char'15 \fi +} +% +% and a similar option for the left quote char vs. a grave accent. +% Modern fonts display ASCII 0x60 as a grave accent, so some people like +% the code environments to do likewise. +% +\def\codequoteleft{% + \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + % [Knuth] pp. 380,381,391 + % \relax disables Spanish ligatures ?` and !` of \tt font. + \relax`% + \else \char'22 \fi + \else \char'22 \fi +} + +% Commands to set the quote options. +% +\parseargdef\codequoteundirected{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}% + \fi\fi +} +% +\parseargdef\codequotebacktick{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}% + \fi\fi +} + +% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. +\def\noligaturesquoteleft{\relax\lq} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Font commands. + +% #1 is the font command (\sl or \it), #2 is the text to slant. +% If we are in a monospaced environment, however, 1) always use \ttsl, +% and 2) do not add an italic correction. +\def\dosmartslant#1#2{% + \ifusingtt + {{\ttsl #2}\let\next=\relax}% + {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% + \next +} +\def\smartslanted{\dosmartslant\sl} +\def\smartitalic{\dosmartslant\it} + +% Output an italic correction unless \next (presumed to be the following +% character) is such as not to need one. +\def\smartitaliccorrection{% + \ifx\next,% + \else\ifx\next-% + \else\ifx\next.% + \else\ifx\next\.% + \else\ifx\next\comma% + \else\ptexslash + \fi\fi\fi\fi\fi + \aftersmartic +} + +% Unconditional use \ttsl, and no ic. @var is set to this for defuns. +\def\ttslanted#1{{\ttsl #1}} + +% @cite is like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} + +\def\aftersmartic{} +\def\var#1{% + \let\saveaftersmartic = \aftersmartic + \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% + \smartslanted{#1}% +} + +\let\i=\smartitalic +\let\slanted=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @b, explicit bold. Also @strong. +\def\b#1{{\bf #1}} +\let\strong=\b + +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\plainfrenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends + } +\catcode`@=\other +\def\endofsentencespacefactor{3000}% default + +% @t, explicit typewriter. +\def\t#1{% + {\tt \rawbackslash \plainfrenchspacing #1}% + \null +} + +% @samp. +\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} + +% @indicateurl is \samp, that is, with quotes. +\let\indicateurl=\samp + +% @code (and similar) prints in typewriter, but with spaces the same +% size as normal in the surrounding text, without hyphenation, etc. +% This is a subroutine for that. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \plainfrenchspacing + #1% + }% + \null % reset spacefactor to 1000 +} + +% We *must* turn on hyphenation at `-' and `_' in @code. +% (But see \codedashfinish below.) +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. +% +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. -- rms. +{ + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active + \global\let'=\rq \global\let`=\lq % default definitions + % + \global\def\code{\begingroup + \setupmarkupstyle{code}% + % The following should really be moved into \setupmarkupstyle handlers. + \catcode\dashChar=\active \catcode\underChar=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\normaldash + \let_\realunder + \fi + % Given -foo (with a single dash), we do not want to allow a break + % after the hyphen. + \global\let\codedashprev=\codedash + % + \codex + } + % + \gdef\codedash{\futurelet\next\codedashfinish} + \gdef\codedashfinish{% + \normaldash % always output the dash character itself. + % + % Now, output a discretionary to allow a line break, unless + % (a) the next character is a -, or + % (b) the preceding character is a -. + % E.g., given --posix, we do not want to allow a break after either -. + % Given --foo-bar, we do want to allow a break between the - and the b. + \ifx\next\codedash \else + \ifx\codedashprev\codedash + \else \discretionary{}{}{}\fi + \fi + % we need the space after the = for the case when \next itself is a + % space token; it would get swallowed otherwise. As in @code{- a}. + \global\let\codedashprev= \next + } +} +\def\normaldash{-} +% +\def\codex #1{\tclose{#1}\endgroup} + +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} + +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is bad. +% @allowcodebreaks provides a document-level way to turn breaking at - +% and _ on and off. +% +\newif\ifallowcodebreaks \allowcodebreakstrue + +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse + \else + \errhelp = \EMsimple + \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}% + \fi\fi +} + +% For @command, @env, @file, @option quotes seem unnecessary, +% so use \code rather than \samp. +\let\command=\code +\let\env=\code +\let\file=\code +\let\option=\code + +% @uref (abbreviation for `urlref') aka @url takes an optional +% (comma-separated) second argument specifying the text to display and +% an optional third arg as text to display instead of (rather than in +% addition to) the url itself. First (mandatory) arg is the url. + +% TeX-only option to allow changing PDF output to show only the second +% arg (if given), and not the url (which is then just the link target). +\newif\ifurefurlonlylink + +% The main macro is \urefbreak, which allows breaking at expected +% places within the url. (There used to be another version, which +% didn't support automatic breaking.) +\def\urefbreak{\begingroup \urefcatcodes \dourefbreak} +\let\uref=\urefbreak +% +\def\dourefbreak#1{\urefbreakfinish #1,,,\finish} +\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% look for second arg + \ifdim\wd0 > 0pt + \ifpdf + \ifurefurlonlylink + % PDF plus option to not display url, show just arg + \unhbox0 + \else + % PDF, normally display both arg and url for consistency, + % visibility, if the pdf is eventually used to print, etc. + \unhbox0\ (\urefcode{#1})% + \fi + \else + \unhbox0\ (\urefcode{#1})% DVI, always show arg and url + \fi + \else + \urefcode{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% Allow line breaks around only a few characters (only). +\def\urefcatcodes{% + \catcode\ampChar=\active \catcode\dotChar=\active + \catcode\hashChar=\active \catcode\questChar=\active + \catcode\slashChar=\active +} +{ + \urefcatcodes + % + \global\def\urefcode{\begingroup + \setupmarkupstyle{code}% + \urefcatcodes + \let&\urefcodeamp + \let.\urefcodedot + \let#\urefcodehash + \let?\urefcodequest + \let/\urefcodeslash + \codex + } + % + % By default, they are just regular characters. + \global\def&{\normalamp} + \global\def.{\normaldot} + \global\def#{\normalhash} + \global\def?{\normalquest} + \global\def/{\normalslash} +} + +% we put a little stretch before and after the breakable chars, to help +% line breaking of long url's. The unequal skips make look better in +% cmtt at least, especially for dots. +\def\urefprestretchamount{.13em} +\def\urefpoststretchamount{.1em} +\def\urefprestretch{\urefprebreak \hskip0pt plus\urefprestretchamount\relax} +\def\urefpoststretch{\urefpostbreak \hskip0pt plus\urefprestretchamount\relax} +% +\def\urefcodeamp{\urefprestretch \&\urefpoststretch} +\def\urefcodedot{\urefprestretch .\urefpoststretch} +\def\urefcodehash{\urefprestretch \#\urefpoststretch} +\def\urefcodequest{\urefprestretch ?\urefpoststretch} +\def\urefcodeslash{\futurelet\next\urefcodeslashfinish} +{ + \catcode`\/=\active + \global\def\urefcodeslashfinish{% + \urefprestretch \slashChar + % Allow line break only after the final / in a sequence of + % slashes, to avoid line break between the slashes in http://. + \ifx\next/\else \urefpoststretch \fi + } +} + +% One more complication: by default we'll break after the special +% characters, but some people like to break before the special chars, so +% allow that. Also allow no breaking at all, for manual control. +% +\parseargdef\urefbreakstyle{% + \def\txiarg{#1}% + \ifx\txiarg\wordnone + \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordbefore + \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordafter + \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak} + \else + \errhelp = \EMsimple + \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% + \fi\fi\fi +} +\def\wordafter{after} +\def\wordbefore{before} +\def\wordnone{none} + +\urefbreakstyle after + +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\txiarg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\txiarg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle setting `\txiarg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct'. +\kbdinputstyle distinct + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. +\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} + +\def\xkey{\key} +\def\kbdsub#1#2#3\par{% + \def\one{#1}\def\three{#3}\def\threex{??}% + \ifx\one\xkey\ifx\threex\three \key{#2}% + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi +} + +% definition of @key that produces a lozenge. Doesn't adjust to text size. +%\setfont\keyrm\rmshape{8}{1000}{OT1} +%\font\keysy=cmsy9 +%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% +% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% +% \vbox{\hrule\kern-0.4pt +% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% +% \kern-0.4pt\hrule}% +% \kern-.06em\raise0.4pt\hbox{\angleright}}}} + +% definition of @key with no lozenge. If the current font is already +% monospace, don't change it; that way, we respect @kbdinputstyle. But +% if it isn't monospace, then use \tt. +% +\def\key#1{{\setupmarkupstyle{key}% + \nohyphenation + \ifmonospace\else\tt\fi + #1}\null} + +% @clicksequence{File @click{} Open ...} +\def\clicksequence#1{\begingroup #1\endgroup} + +% @clickstyle @arrow (by default) +\parseargdef\clickstyle{\def\click{#1}} +\def\click{\arrow} + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\selectfonts\lsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi + \null % reset \spacefactor=1000 +} + +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\plainfrenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi + \null % reset \spacefactor=1000 +} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a math (or tt) \. +% FYI, plain.tex uses \\ as a temporary control sequence (for no +% particular reason), but this is not advertised and we don't care. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + % make the texinfo accent commands work in math mode + \let\"=\ddot + \let\'=\acute + \let\==\bar + \let\^=\hat + \let\`=\grave + \let\u=\breve + \let\v=\check + \let\~=\tilde + \let\dotaccent=\dot + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \catcode`' = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + \let' = \ptexquoteright + } +} + +% ctrl is no longer a Texinfo command, but leave this definition for fun. +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. +% Ignore unless FMTNAME == tex; then it is like @iftex and @tex, +% except specified as a normal braced arg, so no newlines to worry about. +% +\def\outfmtnametex{tex} +% +\long\def\inlinefmt#1{\doinlinefmt #1,\finish} +\long\def\doinlinefmt#1,#2,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi +} +% +% @inlinefmtifelse{FMTNAME,THEN-TEXT,ELSE-TEXT} expands THEN-TEXT if +% FMTNAME is tex, else ELSE-TEXT. +\long\def\inlinefmtifelse#1{\doinlinefmtifelse #1,,,\finish} +\long\def\doinlinefmtifelse#1,#2,#3,#4,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\else \ignorespaces #3\fi +} +% +% For raw, must switch into @tex before parsing the argument, to avoid +% setting catcodes prematurely. Doing it this way means that, for +% example, @inlineraw{html, foo{bar} gets a parse error instead of being +% ignored. But this isn't important because if people want a literal +% *right* brace they would have to use a command anyway, so they may as +% well use a command to get a left brace too. We could re-use the +% delimiter character idea from \verb, but it seems like overkill. +% +\long\def\inlineraw{\tex \doinlineraw} +\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} +\def\doinlinerawtwo#1,#2,\finish{% + \def\inlinerawname{#1}% + \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi + \endgroup % close group opened by \tex. +} + +% @inlineifset{VAR, TEXT} expands TEXT if VAR is @set. +% +\long\def\inlineifset#1{\doinlineifset #1,\finish} +\long\def\doinlineifset#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax + \else\ignorespaces#2\fi +} + +% @inlineifclear{VAR, TEXT} expands TEXT if VAR is not @set. +% +\long\def\inlineifclear#1{\doinlineifclear #1,\finish} +\long\def\doinlineifclear#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax \ignorespaces#2\fi +} + + +\message{glyphs,} +% and logos. + +% @@ prints an @, as does @atchar{}. +\def\@{\char64 } +\let\atchar=\@ + +% @{ @} @lbracechar{} @rbracechar{} all generate brace characters. +% Unless we're in typewriter, use \ecfont because the CM text fonts do +% not have braces, and we don't want to switch into math. +\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}} +\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}} +\let\{=\mylbrace \let\lbracechar=\{ +\let\}=\myrbrace \let\rbracechar=\} +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux/toc files. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \ptexc +\let\dotaccent = \ptexdot +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \ptext +\let\ubaraccent = \ptexb +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi + \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{% + \ifx\textnominalsize\xwordpt + % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX. + % Revert to plain's \scriptsize, which is 7pt. + \count255=\the\fam $\fam\count255 \scriptstyle A$% + \else + % For 11pt, we can use our lllsize. + \selectfonts\lllsize A% + \fi + }% + \vss + }}% + \kern-.15em + \TeX +} + +% Some math mode symbols. +\def\bullet{$\ptexbullet$} +\def\geq{\ifmmode \ge\else $\ge$\fi} +\def\leq{\ifmmode \le\else $\le$\fi} +\def\minus{\ifmmode -\else $-$\fi} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in the cm +% typewriter fonts as three actual period characters; on the other hand, +% in other typewriter fonts three periods are wider than 1.5em. So do +% whichever is larger. +% +\def\dots{% + \leavevmode + \setbox0=\hbox{...}% get width of three periods + \ifdim\wd0 > 1.5em + \dimen0 = \wd0 + \else + \dimen0 = 1.5em + \fi + \hbox to \dimen0{% + \hskip 0pt plus.25fil + .\hskip 0pt plus1fil + .\hskip 0pt plus1fil + .\hskip 0pt plus.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, they should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} +\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% +\def\pounds{{\it\$}} + +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% Glyphs from the EC fonts. We don't use \let for the aliases, because +% sometimes we redefine the original macro, and the alias should reflect +% the redefinition. +% +% Use LaTeX names for the Icelandic letters. +\def\DH{{\ecfont \char"D0}} % Eth +\def\dh{{\ecfont \char"F0}} % eth +\def\TH{{\ecfont \char"DE}} % Thorn +\def\th{{\ecfont \char"FE}} % thorn +% +\def\guillemetleft{{\ecfont \char"13}} +\def\guillemotleft{\guillemetleft} +\def\guillemetright{{\ecfont \char"14}} +\def\guillemotright{\guillemetright} +\def\guilsinglleft{{\ecfont \char"0E}} +\def\guilsinglright{{\ecfont \char"0F}} +\def\quotedblbase{{\ecfont \char"12}} +\def\quotesinglbase{{\ecfont \char"0D}} +% +% This positioning is not perfect (see the ogonek LaTeX package), but +% we have the precomposed glyphs for the most common cases. We put the +% tests to use those glyphs in the single \ogonek macro so we have fewer +% dummy definitions to worry about for index entries, etc. +% +% ogonek is also used with other letters in Lithuanian (IOU), but using +% the precomposed glyphs for those is not so easy since they aren't in +% the same EC font. +\def\ogonek#1{{% + \def\temp{#1}% + \ifx\temp\macrocharA\Aogonek + \else\ifx\temp\macrochara\aogonek + \else\ifx\temp\macrocharE\Eogonek + \else\ifx\temp\macrochare\eogonek + \else + \ecfont \setbox0=\hbox{#1}% + \ifdim\ht0=1ex\accent"0C #1% + \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% + \fi + \fi\fi\fi\fi + }% +} +\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} +\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} +\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} +\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} +% +% Use the ec* fonts (cm-super in outline format) for non-CM glyphs. +\def\ecfont{% + % We can't distinguish serif/sans and italic/slanted, but this + % is used for crude hacks anyway (like adding French and German + % quotes to documents typeset with CM, where we lose kerning), so + % hopefully nobody will notice/care. + \edef\ecsize{\csname\curfontsize ecsize\endcsname}% + \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% + \ifmonospace + % typewriter: + \font\thisecfont = ectt\ecsize \space at \nominalsize + \else + \ifx\curfontstyle\bfstylename + % bold: + \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize + \else + % regular: + \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \fi + \fi + \thisecfont +} + +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + \hfil\crcr\Orb}}% + }$% +} + +% @textdegree - the normal degrees sign. +% +\def\textdegree{$^\circ$} + +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\thisisundefined +\def\Orb{\mathhexbox20D} +\fi + +% Quotes. +\chardef\quotedblleft="5C +\chardef\quotedblright=`\" +\chardef\quoteleft=`\` +\chardef\quoteright=`\' + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\parseargdef\shorttitlepage{% + \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \let\page = \oldpage + \page + \null + }% +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +% Settings used for typesetting titles: no hyphenation, no indentation, +% don't worry much about spacing, ragged right. This should be used +% inside a \vbox, and fonts need to be set appropriately first. Because +% it is always used for titles, nothing else, we call \rmisbold. \par +% should be specified before the end of the \vbox, since a vbox is a group. +% +\def\raggedtitlesettings{% + \rmisbold + \hyphenpenalty=10000 + \parindent=0pt + \tolerance=5000 + \ptexraggedright +} + +% Macros to be used within @titlepage: + +\let\subtitlerm=\tenrm +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\parseargdef\title{% + \checkenv\titlepage + \vbox{\titlefonts \raggedtitlesettings #1\par}% + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\secfonts\rmisbold \leftline{#1}}% + \fi +} + + +% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make TeX use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + + +\def\evenheading{\parsearg\evenheadingxxx} +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -12pt + \global\advance\vsize by -12pt +} + +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + +% @evenheadingmarks top \thischapter <- chapter at the top of a page +% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page +% +% The same set of arguments for: +% +% @oddheadingmarks +% @evenfootingmarks +% @oddfootingmarks +% @everyheadingmarks +% @everyfootingmarks + +\def\evenheadingmarks{\headingmarks{even}{heading}} +\def\oddheadingmarks{\headingmarks{odd}{heading}} +\def\evenfootingmarks{\headingmarks{even}{footing}} +\def\oddfootingmarks{\headingmarks{odd}{footing}} +\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} + \headingmarks{odd}{heading}{#1} } +\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} + \headingmarks{odd}{footing}{#1} } +% #1 = even/odd, #2 = heading/footing, #3 = top/bottom. +\def\headingmarks#1#2#3 {% + \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname + \global\expandafter\let\csname get#1#2marks\endcsname \temp +} + +\everyheadingmarks bottom +\everyfootingmarks bottom + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\headingsoff{% non-global headings elimination + \evenheadline={\hfil}\evenfootline={\hfil}% + \oddheadline={\hfil}\oddfootline={\hfil}% +} + +\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting +\HEADINGSoff % it's the default + +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\thisisundefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg{\gdef\thistitle}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @ftable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemindicate{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil\relax + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted would + % cause the example and the item to crash together. So we use this + % bizarre value of 10001 as a signal to \aboveenvbreak to insert + % \parskip glue after all. Section titles are handled this way also. + % + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} + +% @table, @ftable, @vtable. +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% +} +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley +} +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\envdef\itemize{\parsearg\doitemize} + +\def\doitemize#1{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + % + % Try typesetting the item mark so that if the document erroneously says + % something like @itemize @samp (intending @table), there's an error + % right away at the @itemize. It's not the best error message in the + % world, but it's better than leaving it to the @item. This means if + % the user wants an empty mark, they have to say @w{} not just @w. + \def\itemcontents{#1}% + \setbox0 = \hbox{\itemcontents}% + % + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + % + \let\item=\itemizeitem +} + +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + % + \vadjust{\penalty 1200}}% not good to break after first line of item. + \flushcr +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call \doitemize, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \doitemize{#1.}\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. Assignments +% have to be global since we are inside the implicit group of an +% alignment entry. \everycr below resets \everytab so we don't have to +% undo it ourselves. +\def\headitemfont{\b}% for people to use in the template row; not changeable +\def\headitem{% + \checkenv\multitable + \crcr + \gdef\headitemcrhook{\nobreak}% attempt to avoid page break after headings + \global\everytab={\bf}% can't use \headitemfont since the parsing differs + \the\everytab % for the first item +}% +% +% default for tables with no headings. +\let\headitemcrhook=\relax +% +% A \tab used to include \hskip1sp. But then the space in a template +% line is not enough. That is bad. So let's go back to just `&' until +% we again encounter the problem the 1sp was intended to solve. +% --karl, nathan@acm.org, 20apr99. +\def\tab{\checkenv\multitable &\the\everytab}% + +% @multitable ... @end multitable definitions: +% +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% + \vskip\parskip + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + % + \everycr = {% + \noalign{% + \global\everytab={}% Reset from possible headitem. + \global\colcount=0 % Reset the column counter. + % + % Check for saved footnotes, etc.: + \checkinserts + % + % Perhaps a \nobreak, then reset: + \headitemcrhook + \global\let\headitemcrhook=\relax + }% + }% + % + \parsearg\domultitable +} +\def\domultitable#1{% + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively + % marking characters. + \noindent\ignorespaces##\unskip\multistrut + }\cr +} +\def\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse +} + +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +\fi +% Test to see if parskip is larger than space between lines of +% table. If not, do nothing. +% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. +\fi} + + +\message{conditionals,} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} +\def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% Ignore text until a line `@end #1', keeping track of nested conditionals. +% +% A count to remember the depth of nesting. +\newcount\doignorecount + +\def\doignore#1{\begingroup + % Scan in ``verbatim'' mode: + \obeylines + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \spaceisspace + % + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. + % + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next +} + +% Finish off ignored text. +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} + + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. +% +\parseargdef\set{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% +} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} + +% @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} +{ + \catcode`\-=\active \catcode`\_=\active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... + \catcode`\-=\other \catcode`\_=\other + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\normaldash \let_\normalunderscore + } +} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we call \makevalueexpandable in \indexdummies). +% The command has to be fully expandable (if the variable is set), since +% the result winds up in the index file. This means that if the +% variable's value contains other Texinfo commands, it's almost certain +% it will fail (although perhaps we could fix that with sufficient work +% to do a one-level expansion on the result, instead of complete). +% +% Unfortunately, this has the consequence that when _ is in the *value* +% of an @set, it does not print properly in the roman fonts (get the cmr +% dot accent at position 126 instead). No fix comes to mind, and it's +% been this way since 2003 or earlier, so just ignore it. +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +% To get the special treatment we need for `@end ifset,' we call +% \makecond and then redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next +} +\def\ifsetfail{\doignore{ifset}} + +% @ifclear VAR ... @end executes the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written +% without the @) is in fact defined. We can only feasibly check at the +% TeX level, so something like `mathcode' is going to considered +% defined even though it is not a Texinfo command. +% +\makecond{ifcommanddefined} +\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} +% +\def\doifcmddefined#1#2{{% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname #2\endcsname\relax + #1% If not defined, \let\next as above. + \fi + \expandafter + }\next +} +\def\ifcmddefinedfail{\doignore{ifcommanddefined}} + +% @ifcommandnotdefined CMD ... handled similar to @ifclear above. +\makecond{ifcommandnotdefined} +\def\ifcommandnotdefined{% + \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} +\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} + +% Set the `txicommandconditionals' variable, so documents have a way to +% test if the @ifcommand...defined conditionals are available. +\set txicommandconditionals + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \relax + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \escapechar = `\\ % use backslash in output files. + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % + % Need these unexpandable (because we define \tt as a dummy) + % definitions when @{ or @} appear in index entry text. Also, more + % complicated, when \tex is in effect and \{ is a \delimiter again. + % We can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. Perhaps we + % should use @lbracechar and @rbracechar? + \def\{{{\tt\char123}}% + \def\}{{\tt\char125}}% + % + % I don't entirely understand this, but when an index entry is + % generated from a macro call, the \endinput which \scanmacro inserts + % causes processing to be prematurely terminated. This is, + % apparently, because \indexsorttmp is fully expanded, and \endinput + % is an expandable command. The redefinition below makes \endinput + % disappear altogether for that purpose -- although logging shows that + % processing continues to some further point. On the other hand, it + % seems \endinput does not hurt in the printed index arg, since that + % is still getting written without apparent harm. + % + % Sample source (mac-idx3.tex, reported by Graham Percival to + % help-texinfo, 22may06): + % @macro funindex {WORD} + % @findex xyz + % @end macro + % ... + % @funindex commtest + % This is not enough to reproduce the bug, but it gives the flavor. + % + % Sample whatsit resulting: + % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} + % + % So: + \let\endinput = \empty + % + % Do the redefinitions. + \commondummies +} + +% For the aux and toc files, @ is the escape character. So we want to +% redefine everything using @ as the escape character (instead of +% \realbackslash, still used for index files). When everything uses @, +% this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % Do the redefinitions. + \commondummies + \otherbackslash +} + +% Called from \indexdummies and \atdummies. +% +\def\commondummies{% + % + % \definedummyword defines \#1 as \string\#1\space, thus effectively + % preventing its expansion. This is used only for control words, + % not control letters, because the \space would be incorrect for + % control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword ##1{\def##1{\string##1\space}}% + \def\definedummyletter##1{\def##1{\string##1}}% + \let\definedummyaccent\definedummyletter + % + \commondummiesnofonts + % + \definedummyletter\_% + \definedummyletter\-% + % + % Non-English letters. + \definedummyword\AA + \definedummyword\AE + \definedummyword\DH + \definedummyword\L + \definedummyword\O + \definedummyword\OE + \definedummyword\TH + \definedummyword\aa + \definedummyword\ae + \definedummyword\dh + \definedummyword\exclamdown + \definedummyword\l + \definedummyword\o + \definedummyword\oe + \definedummyword\ordf + \definedummyword\ordm + \definedummyword\questiondown + \definedummyword\ss + \definedummyword\th + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt + % + \definedummyword\LaTeX + \definedummyword\TeX + % + % Assorted special characters. + \definedummyword\arrow + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\entrybreak + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\expansion + \definedummyword\geq + \definedummyword\guillemetleft + \definedummyword\guillemetright + \definedummyword\guilsinglleft + \definedummyword\guilsinglright + \definedummyword\lbracechar + \definedummyword\leq + \definedummyword\minus + \definedummyword\ogonek + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\quotedblbase + \definedummyword\quotedblleft + \definedummyword\quotedblright + \definedummyword\quoteleft + \definedummyword\quoteright + \definedummyword\quotesinglbase + \definedummyword\rbracechar + \definedummyword\result + \definedummyword\textdegree + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + % + \normalturnoffactive + % + % Handle some cases of @value -- where it does not contain any + % (non-fully-expandable) commands. + \makevalueexpandable +} + +% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% +\def\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter\!% + \definedummyaccent\"% + \definedummyaccent\'% + \definedummyletter\*% + \definedummyaccent\,% + \definedummyletter\.% + \definedummyletter\/% + \definedummyletter\:% + \definedummyaccent\=% + \definedummyletter\?% + \definedummyaccent\^% + \definedummyaccent\`% + \definedummyaccent\~% + \definedummyword\u + \definedummyword\v + \definedummyword\H + \definedummyword\dotaccent + \definedummyword\ogonek + \definedummyword\ringaccent + \definedummyword\tieaccent + \definedummyword\ubaraccent + \definedummyword\udotaccent + \definedummyword\dotless + % + % Texinfo font commands. + \definedummyword\b + \definedummyword\i + \definedummyword\r + \definedummyword\sansserif + \definedummyword\sc + \definedummyword\slanted + \definedummyword\t + % + % Commands that take arguments. + \definedummyword\abbr + \definedummyword\acronym + \definedummyword\anchor + \definedummyword\cite + \definedummyword\code + \definedummyword\command + \definedummyword\dfn + \definedummyword\dmn + \definedummyword\email + \definedummyword\emph + \definedummyword\env + \definedummyword\file + \definedummyword\image + \definedummyword\indicateurl + \definedummyword\inforef + \definedummyword\kbd + \definedummyword\key + \definedummyword\math + \definedummyword\option + \definedummyword\pxref + \definedummyword\ref + \definedummyword\samp + \definedummyword\strong + \definedummyword\tie + \definedummyword\uref + \definedummyword\url + \definedummyword\var + \definedummyword\verb + \definedummyword\w + \definedummyword\xref + % + % Consider: + % @macro mkind{arg1,arg2} + % @cindex \arg2\ + % @end macro + % @mkind{foo, bar} + % The space after the comma will end up in the temporary definition + % that we make for arg2 (see \parsemargdef ff.). We want all this to be + % expanded for the sake of the index, so we end up just seeing "bar". + \let\xeatspaces = \eatspaces +} + +% For testing: output @{ and @} in index sort strings as \{ and \}. +\newif\ifusebracesinindexes + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexnofonts{% + % Accent commands should become @asis. + \def\definedummyaccent##1{\let##1\asis}% + % We can just ignore other control letters. + \def\definedummyletter##1{\let##1\empty}% + % All control words become @asis by default; overrides below. + \let\definedummyword\definedummyaccent + % + \commondummiesnofonts + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + \def\ { }% + \def\@{@}% + \def\_{\normalunderscore}% + \def\-{}% @- shouldn't affect sorting + % + % Unfortunately, texindex is not prepared to handle braces in the + % content at all. So for index sorting, we map @{ and @} to strings + % starting with |, since that ASCII character is between ASCII { and }. + \ifusebracesinindexes + \def\lbracechar{\lbracecmd}% + \def\rbracechar{\rbracecmd}% + \else + \def\lbracechar{|a}% + \def\rbracechar{|b}% + \fi + \let\{=\lbracechar + \let\}=\rbracechar + % + % + % Non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\DH{DZZ}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\TH{ZZZ}% + \def\aa{aa}% + \def\ae{ae}% + \def\dh{dzz}% + \def\exclamdown{!}% + \def\l{l}% + \def\oe{oe}% + \def\ordf{a}% + \def\ordm{o}% + \def\o{o}% + \def\questiondown{?}% + \def\ss{ss}% + \def\th{zzz}% + % + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. + % (The following {} will end up in the sort string, but that's ok.) + \def\arrow{->}% + \def\bullet{bullet}% + \def\comma{,}% + \def\copyright{copyright}% + \def\dots{...}% + \def\enddots{...}% + \def\equiv{==}% + \def\error{error}% + \def\euro{euro}% + \def\expansion{==>}% + \def\geq{>=}% + \def\guillemetleft{<<}% + \def\guillemetright{>>}% + \def\guilsinglleft{<}% + \def\guilsinglright{>}% + \def\leq{<=}% + \def\minus{-}% + \def\point{.}% + \def\pounds{pounds}% + \def\print{-|}% + \def\quotedblbase{"}% + \def\quotedblleft{"}% + \def\quotedblright{"}% + \def\quoteleft{`}% + \def\quoteright{'}% + \def\quotesinglbase{,}% + \def\registeredsymbol{R}% + \def\result{=>}% + \def\textdegree{o}% + % + \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax + \else \indexlquoteignore \fi + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist +} + +% Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us +% ignore left quotes in the sort term. +{\catcode`\`=\active + \gdef\indexlquoteignore{\let`=\empty}} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% Most index entries go through here, but \dosubind is the general case. +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{\dosubind{#1}{#2}{}} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% empty if called from \doind, as we usually are (the main exception +% is with most defuns, which call us directly). +% +\def\dosubind#1#2#3{% + \iflinks + {% + % Store the main index entry text (including the third arg). + \toks0 = {#2}% + % If third arg is present, precede it with a space. + \def\thirdarg{#3}% + \ifx\thirdarg\empty \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + \edef\writeto{\csname#1indfile\endcsname}% + % + \safewhatsit\dosubindwrite + }% + \fi +} + +% Write the entry in \toks0 to the index file: +% +\def\dosubindwrite{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% + \fi + % + % Remember, we are within a group. + \indexdummies % Must do this here, since \bf, etc expand at this stage + \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\writeto{% + \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% + }% + \temp +} + +% Take care of unwanted page breaks/skips around a whatsit: +% +% If a skip is the last thing on the list now, preserve it +% by backing up by \lastskip, doing the \write, then inserting +% the skip again. Otherwise, the whatsit generated by the +% \write or \pdfdest will make \lastskip zero. The result is that +% sequences like this: +% @end defun +% @tindex whatever +% @defun ... +% will have extra space inserted, because the \medbreak in the +% start of the @defun won't see the skip inserted by the @end of +% the previous defun. +% +% But don't do any of this if we're not in vertical mode. We +% don't want to do a \vskip and prematurely end a paragraph. +% +% Avoid page breaks due to these extra skips, too. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +\newskip\whatsitskip +\newcount\whatsitpenalty +% +% ..., ready, GO: +% +\def\safewhatsit#1{\ifhmode + #1% + \else + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \whatsitskip = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \whatsitpenalty = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\whatsitskip glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\whatsitskip + \fi + % + #1% + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\whatsitskip + \fi +\fi} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\parseargdef\printindex{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \plainfrenchspacing + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\backslashcurfont}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \nobreak + \vskip 0pt plus 3\baselineskip + \penalty 0 + \vskip 0pt plus -3\baselineskip + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + % Do our best not to break after the initial. + \nobreak + \vskip .33\baselineskip plus .1\baselineskip +}} + +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +% A straightforward implementation would start like this: +% \def\entry#1#2{... +% But this freezes the catcodes in the argument, and can cause problems to +% @code, which sets - active. This problem was fixed by a kludge--- +% ``-'' was active throughout whole index, but this isn't really right. +% The right solution is to prevent \entry from swallowing the whole text. +% --kasal, 21nov03 +\def\entry{% + \begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing + % columns. + \vskip 0pt plus1pt + % + % When reading the text of entry, convert explicit line breaks + % from @* into spaces. The user might give these in long section + % titles, for instance. + \def\*{\unskip\space\ignorespaces}% + \def\entrybreak{\hfil\break}% + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\entrybreak{\unskip\space\ignorespaces}% +\def\doentry{% + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. +} +\def\finishentry#1{% + % #1 is the page number. + % + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \setbox\boxA = \hbox{#1}% + \ifdim\wd\boxA = 0pt + \ % + \else + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#1.% + \ \the\toksA + \else + \ #1% + \fi + \fi + \par + \endgroup +} + +% Like plain.tex's \dotfill, except uses up at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + % The following penalty ensures that the page builder is exercised + % _before_ we change the output routine. This is necessary in the + % following situation: + % + % The last section of the index consists only of a single entry. + % Before this section, \pagetotal is less than \pagegoal, so no + % break occurs before the last section starts. However, the last + % section, consisting of \initial and the single \entry, does not + % fit on the page and has to be broken off. Without the following + % penalty the page builder will not be exercised until \eject + % below, and by that time we'll already have changed the output + % routine to the \balancecolumns version, so the next-to-last + % double-column page will be processed with \balancecolumns, which + % is wrong: The two columns will go to the main vertical list, with + % the broken-off section in the recent contributions. As soon as + % the output routine finishes, TeX starts reconsidering the page + % break. The two columns and the broken-off section both fit on the + % page, because the two columns now take up only half of the page + % goal. When TeX sees \eject from below which follows the final + % section, it invokes the new output routine that we've set after + % \balancecolumns below; \onepageout will try to fit the two columns + % and the final section into the vbox of \pageheight (see + % \pagebody), causing an overfull box. + % + % Note that glue won't work here, because glue does not exercise the + % page builder, unlike penalties (see The TeXbook, pp. 280-281). + \penalty0 + % + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +% Let's start with @part. +\outer\parseargdef\part{\partzzz{#1}} +\def\partzzz#1{% + \chapoddpage + \null + \vskip.3\vsize % move it down on the page a bit + \begingroup + \noindent \titlefonts\rmisbold #1\par % the text + \let\lastnode=\empty % no node to associate with + \writetocentry{part}{#1}{}% but put it in the toc + \headingsoff % no headline or footline on the part page + \chapoddpage + \endgroup +} + +% \unnumberedno is an oxymoron. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% +% \def\appendixletter{\char\the\appendixno} +% We do the following ugly conditional instead of the above simple +% construct for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +% +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines these (using marks) as the number+name, number +% and name of the chapter. Page headings and footings can use +% these. @section does likewise. +\def\thischapter{} +\def\thischapternum{} +\def\thischaptername{} +\def\thissection{} +\def\thissectionnum{} +\def\thissectionname{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achieve this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unnlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 + \else + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi + \fi + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unnlevel + \chardef\unnlevel = \absseclevel + \fi + \else + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unnlevel + \def\headtype{U}% + \else + \chardef\unnlevel = 3 + \fi + \fi + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi + \else + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi + \fi + \suppressfirstparagraphindent +} + +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + % \putwordChapter can contain complex things in translations. + \toks0=\expandafter{\putwordChapter}% + \message{\the\toks0 \space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz +% +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + % \putwordAppendix can contain complex things in translations. + \toks0=\expandafter{\putwordAppendix}% + \message{\the\toks0 \space \appendixletter}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +% normally unnmhead0 calls unnumberedzzz: +\outer\parseargdef\unnumbered{\unnmhead0{#1}} +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the<toks register> to achieve this: TeX expands \the<toks> only once, + % simply yielding the contents of <toks register>. (We also do this for + % the toc entries.) + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% + % + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\parseargdef\centerchap{% + % Well, we could do the following in a group, but that would break + % an assumption that \chapmacro is called at the outermost level. + % Thus we are safer this way: --kasal, 24feb04 + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax +} + +% @top is like @unnumbered. +\let\top\unnumbered + +% Sections. +% +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% +} + +% normally calls appendixsectionzzz: +\outer\parseargdef\appendixsection{\apphead1{#1}} +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% +} +\let\appendixsec\appendixsection + +% normally calls unnumberedseczzz: +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% +} + +% Subsections. +% +% normally calls numberedsubseczzz: +\outer\parseargdef\numberedsubsec{\numhead2{#1}} +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% +} + +% normally calls appendixsubseczzz: +\outer\parseargdef\appendixsubsec{\apphead2{#1}} +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% +} + +% normally calls unnumberedsubseczzz: +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% +} + +% Subsubsections. +% +% normally numberedsubsubseczzz: +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% normally appendixsubsubseczzz: +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% normally unnumberedsubsubseczzz: +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +\def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +} + +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% + \vbox{\chapfonts \raggedtitlesettings #1\par}% + \nobreak\bigskip \nobreak + \suppressfirstparagraphindent +} + +% @heading, @subheading, @subsubheading. +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +% Parameter controlling skip before chapter headings (if needed) +\newskip\chapheadingskip + +% Define plain chapter starts, and page on/off switching for it. +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +% Because \domark is called before \chapoddpage, the filler page will +% get the headings for the next chapter, which is wrong. But we don't +% care -- we just disable all headings on the filler page. +\def\chapoddpage{% + \chappager + \ifodd\pageno \else + \begingroup + \headingsoff + \null + \chappager + \endgroup + \fi +} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{% +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +% Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yomitfromtockeyword{Yomitfromtoc} +\def\Yappendixkeyword{Yappendix} +% +\def\chapmacro#1#2#3{% + % Insert the first mark before the heading break (see notes for \domark). + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% + \gdef\thissection{}}% + % + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{\thischaptername}}% + \else\ifx\temptype\Yomitfromtockeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{}}% + \else\ifx\temptype\Yappendixkeyword + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\appendixletter}% + % \noexpand\putwordAppendix avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordAppendix{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \else + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\the\chapno}% + % \noexpand\putwordChapter avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordChapter{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \fi\fi\fi + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert the chapter heading break. + \pchapsepmacro + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \domark + % + {% + \chapfonts \rmisbold + % + % Have to define \lastsection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\lastsection{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. + \nobreak % Avoid page breaks at the interline glue. + \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt +} + + +% I don't think this chapter style is supported any more, so I'm not +% updating it with the new noderef stuff. We'll see. --karl, 11aug03. +% +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} +% +\def\unnchfopen #1{% + \chapoddpage + \vbox{\chapfonts \raggedtitlesettings #1\par}% + \nobreak\bigskip\nobreak +} +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} +\def\centerchfopen #1{% + \chapoddpage + \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% + \nobreak\bigskip \nobreak +} +\def\CHAPFopen{% + \global\let\chapmacro=\chfopen + \global\let\centerchapmacro=\centerchfopen} + + +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} + +% Subsection titles. +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} + +% Subsubsection titles. +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} + + +% Print any size, any type, section title. +% +% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is +% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the +% section number. +% +\def\seckeyword{sec} +% +\def\sectionheading#1#2#3#4{% + {% + \checkenv{}% should not be in an environment. + % + % Switch to the right set of fonts. + \csname #2fonts\endcsname \rmisbold + % + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + % Insert first mark before the heading break (see notes for \domark). + \let\prevsectiondefs=\lastsectiondefs + \ifx\temptype\Ynothingkeyword + \ifx\sectionlevel\seckeyword + \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% + \gdef\thissection{\thissectionname}}% + \fi + \else\ifx\temptype\Yomitfromtockeyword + % Don't redefine \thissection. + \else\ifx\temptype\Yappendixkeyword + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \else + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \fi\fi\fi + % + % Go into vertical mode. Usually we'll already be there, but we + % don't want the following whatsit to end up in a preceding paragraph + % if the document didn't happen to have a blank line. + \par + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert space above the heading. + \csname #2headingbreak\endcsname + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \global\let\prevsectiondefs=\lastsectiondefs + \domark + % + % Only insert the space after the number if we have a section number. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\lastsection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \lastsection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\lastsection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\lastsection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chapmacro. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chapmacro. + \donoderef{#3}% + % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % + % Output the actual section heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% + }% + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. + \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) However, when a paragraph is not started next + % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out + % or the negative glue will cause weirdly wrong output, typically + % obscuring the section heading with something else. + \vskip-\parskip + % + % This is so the last item on the main vertical list is a known + % \penalty > 10000, so \startdefun, etc., can recognize the situation + % and do the needful. + \penalty 10001 +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. +% +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. +% +\newif\iftocfileopened +\def\omitkeyword{omit}% +% +\def\writetocentry#1#2#3{% + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% + \fi + \fi + % + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one on every page because the title pages are numbered + % 1 and 2 (the page numbers aren't printed), and so are the first + % two pages of the document. Thus, we'd have two destinations named + % `1', and two named `2'. + \ifpdf \global\pdfmakepagedesttrue \fi +} + + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \tocreadfilename +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Prepare to read what we've written to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund <tege@matematik.su.se> + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \chapmacro{#1}{Yomitfromtoc}{}% + % + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + +% redefined for the two-volume lispref. We always output on +% \jobname.toc even if this is redefined. +% +\def\tocreadfilename{\jobname.toc} + +% Normal (long) toc. +% +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\partentry = \shortpartentry + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Parts, in the main contents. Replace the part number, which doesn't +% exist, with an empty box. Let's hope all the numbers have the same width. +% Also ignore the page number, which is conventionally not printed. +\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} +\def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}} +% +% Parts, in the short toc. +\def\shortpartentry#1#2#3#4{% + \penalty-300 + \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip + \shortchapentry{{\bf #1}}{\numeralbox}{}{}% +} + +% Chapters, in the main contents. +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% +} + +% Appendices, in the main contents. +% Need the word Appendix, and a fixed-size box. +% +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} +% +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} + +% Unnumbered chapters. +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} + +% Sections. +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} + +% And subsubsections. +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} + +% This parameter controls the indentation of the various levels. +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} + + +\message{environments,} +% @foo ... @end foo. + +% @tex ... @end tex escapes into raw TeX temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain @ character. + +\envdef\tex{% + \setupmarkupstyle{tex}% + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \catcode `\`=\other + \catcode `\'=\other + \escapechar=`\\ + % + % ' is active in math mode (mathcode"8000). So reset it, and all our + % other math active characters (just in case), to plain's definitions. + \mathactive + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + \expandafter \let\csname top\endcsname=\ptextop % we've made it outer + \let\frenchspacing=\plainfrenchspacing + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +} +% There is no need to define \Etex. + +% Define @lisp ... @end lisp. +% @lisp environment forms a group so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty<10000 \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\envdef\cartouche{% + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt % we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % + % If this cartouche directly follows a sectioning command, we need the + % \parskip glue (backspaced over by default) or the cartouche can + % collide with the section heading. + \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi + % + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of def\group. +} +\def\Ecartouche{% + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \checkinserts +} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\newdimen\nonfillparindent +\def\nonfillstart{% + \aboveenvbreak + \ifdim\hfuzz < 12pt \hfuzz = 12pt \fi % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + % Turn off paragraph indentation but redefine \indent to emulate + % the normal \indent. + \nonfillparindent=\parindent + \parindent = 0pt + \let\indent\nonfillindent + % + \emergencystretch = 0pt % don't try to avoid overfull boxes + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \let\exdent=\nofillexdent +} + +\begingroup +\obeyspaces +% We want to swallow spaces (but not other tokens) after the fake +% @indent in our nonfill-environments, where spaces are normally +% active and set to @tie, resulting in them not being ignored after +% @indent. +\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}% +\gdef\nonfillindentcheck{% +\ifx\temp % +\expandafter\nonfillindentgobble% +\else% +\leavevmode\nonfillindentbox% +\fi% +}% +\endgroup +\def\nonfillindentgobble#1{\nonfillindent} +\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}} + +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp +% +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + % end paragraph for sake of leading, in case document has no blank + % line. This is redundant with what happens in \aboveenvbreak, but + % we need to do it before changing the fonts, and it's inconvenient + % to change the fonts afterward. + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm + \fi +} + +% We often define two environments, @foo and @smallfoo. +% Let's do it in one command. #1 is the env name, #2 the definition. +\def\makedispenvdef#1#2{% + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}% + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}% + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak +} + +% Define two environment synonyms (#1 and #2) for an environment. +\def\maketwodispenvdef#1#2#3{% + \makedispenvdef{#1}{#3}% + \makedispenvdef{#2}{#3}% +} +% +% @lisp: indented, narrowed, typewriter font; +% @example: same as @lisp. +% +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +% +\maketwodispenvdef{lisp}{example}{% + \nonfillstart + \tt\setupmarkupstyle{example}% + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} +% @display/@smalldisplay: same as @lisp except keep current font. +% +\makedispenvdef{display}{% + \nonfillstart + \gobble +} + +% @format/@smallformat: same as @display except don't narrow margins. +% +\makedispenvdef{format}{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} + +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} +\let\Eflushleft = \afterenvbreak + +% @flushright. +% +\envdef\flushright{% + \let\nonarrowing = t% + \nonfillstart + \advance\leftskip by 0pt plus 1fill\relax + \gobble +} +\let\Eflushright = \afterenvbreak + + +% @raggedright does more-or-less normal line breaking but no right +% justification. From plain.tex. Don't stretch around special +% characters in urls in this environment, since the stretch at the right +% should be enough. +\envdef\raggedright{% + \rightskip0pt plus2.4em \spaceskip.3333em \xspaceskip.5em\relax + \def\urefprestretchamount{0pt}% + \def\urefpoststretchamount{0pt}% +} +\let\Eraggedright\par + +\envdef\raggedleft{% + \parindent=0pt \leftskip0pt plus2em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedleft\par + +\envdef\raggedcenter{% + \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedcenter\par + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. +% +\makedispenvdef{quotation}{\quotationstart} +% +\def\quotationstart{% + \indentedblockstart % same as \indentedblock, but increase right margin too. + \ifx\nonarrowing\relax + \advance\rightskip by \lispnarrowing + \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\thisisundefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} +\def\Esmallquotation{\Equotation} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi +} + +% @indentedblock is like @quotation, but indents only on the left and +% has no optional argument. +% +\makedispenvdef{indentedblock}{\indentedblockstart} +% +\def\indentedblockstart{% + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \exdentamount = \lispnarrowing + \else + \let\nonarrowing = \relax + \fi +} + +% Keep a nonzero parskip for the environment, since we're doing normal filling. +% +\def\Eindentedblock{% + \par + {\parskip=0pt \afterenvbreak}% +} +\def\Esmallindentedblock{\Eindentedblock} + + +% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>} +% If we want to allow any <char> as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% + % Don't do the quotes -- if we do, @set txicodequoteundirected and + % @set txicodequotebacktick will not have effect on @verb and + % @verbatim, and ?` and !` ligatures won't get disabled. + %\do\`\do\'% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=\other}\dospecials} +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \setupmarkupstyle{verb}% + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion. +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +% We typeset each line of the verbatim in an \hbox, so we can handle +% tabs. The \global is in case the verbatim line starts with an accent, +% or some other command that starts with a begin-group. Otherwise, the +% entire \verbbox would disappear at the corresponding end-group, before +% it is typeset. Meanwhile, we can't have nested verbatim commands +% (can we?), so the \global won't be overwriting itself. +\newbox\verbbox +\def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} +% +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab + \divide\dimen\verbbox by\tabw + \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw + \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw + \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox + }% + } +\endgroup + +% start the verbatim environment. +\def\setupverbatim{% + \let\nonarrowing = t% + \nonfillstart + \tt % easiest (and conventionally used) font for verbatim + % The \leavevmode here is for blank lines. Otherwise, we would + % never \starttabox and the \egroup would end verbatim mode. + \def\par{\leavevmode\egroup\box\verbbox\endgraf}% + \tabexpand + \setupmarkupstyle{verbatim}% + % Respect line breaks, + % print special symbols as themselves, and + % make each space count. + % Must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'<char>#1<char>'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. +\endgroup +% +\envdef\verbatim{% + \setupverbatim\doverbatim +} +\let\Everbatim = \afterenvbreak + + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} +% +\def\doverbatiminclude#1{% + {% + \makevalueexpandable + \setupverbatim + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% + \input #1 + \afterenvbreak + }% +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\copyingtext + \endgroup +} + + +\message{defuns,} +% @defun etc. + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt +\newcount\defunpenalty + +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak + \defunpenalty=10003 % Will keep this @deffn together with the + % following @def command, see below. + \else + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \printdefunline, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + % As a further refinement, we avoid "club" headers by signalling + % with penalty of 10003 after the very first @deffn in the + % sequence (see above), and penalty of 10002 after any following + % @def command. + \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint + \fi + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% + % + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% +} +\def\gobbledefun#1\startdefun{} + +% \printdefunline \deffnheader{text} +% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil\relax + \endgraf + \nobreak\vskip -\parskip + \penalty\defunpenalty % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup +} + +\def\Edefun{\endgraf\medbreak} + +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remaining is to define \deffnheader. +% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp +} + +% \domakedefun \deffn \deffnx \deffnheader +% +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. +% +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \doingtypefnfalse % distinguish typed functions from all else + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% +} + +\newif\ifdoingtypefn % doing typed function? +\newif\ifrettypeownline % typeset return type on its own line? + +% @deftypefnnewline on|off says whether the return type of typed functions +% are printed on their own line. This affects @deftypefn, @deftypefun, +% @deftypeop, and @deftypemethod. +% +\parseargdef\deftypefnnewline{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @txideftypefnnl value `\temp', + must be on|off}% + \fi\fi +} + +% Untyped functions: + +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} + +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} + +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deffngeneral {subind}category name args +% +\def\deffngeneral#1#2 #3 #4\endheader{% + % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +} + +% Typed functions: + +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} + +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} + +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \doingtypefntrue + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +% Typed variables: + +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} + +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} + +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } + +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +% Untyped variables: + +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } + +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} + +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } + +% Types: + +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% +} + +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} + +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. +% +% We are followed by (but not passed) the arguments, if any. +% +\def\defname#1#2#3{% + \par + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % Determine if we are typesetting the return type of a typed function + % on a line by itself. + \rettypeownlinefalse + \ifdoingtypefn % doing a typed function specifically? + % then check user option for putting return type on its own line: + \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else + \rettypeownlinetrue + \fi + \fi + % + % How we'll format the category name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. We'll always have at + % least two. + \tempnum = 2 + % + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % + % If doing a return type on its own line, we'll have another line. + \ifrettypeownline + \advance\tempnum by 1 + \def\maybeshapeline{0in \hsize}% + \else + \def\maybeshapeline{}% + \fi + % + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % + % The final paragraph shape: + \parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2 + % + % Put the category name at the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% text of the return type + \ifx\temp\empty\else + \tclose{\temp}% typeset the return type + \ifrettypeownline + % put return type on its own line; prohibit line break following: + \hfil\vadjust{\nobreak}\break + \else + \space % type on same line, so just followed by a space + \fi + \fi % no return type + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \tenrm + % + \boldbrax + % arguments will be output next, if any. +} + +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. +% +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. We used to recommend @var for that, so + % leave the code in, but it's strange for @var to lead to typewriter. + % Nowadays we recommend @code, since the difference between a ttsl hyphen + % and a tt hyphen is pretty tiny. @code also disables ?` !`. + \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% + #1% + \sl\hyphenchar\font=45 +} + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& + + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} +} + +\newcount\parencount + +% If we encounter &foo, then turn on ()-hacking afterwards +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} + +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi +} +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi +} +\def\bfafterword#1 {#1 \bf} + +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword +} +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 +} + +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 +} + +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi +} +% these should not use \errmessage; the glibc manual, at least, actually +% has such constructs (when documenting function pointers). +\def\badparencount{% + \message{Warning: unbalanced parentheses in @def...}% + \global\parencount=0 +} +\def\badbrackcount{% + \message{Warning: unbalanced square brackets in @def...}% + \global\brackcount=0 +} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\thisisundefined + \newwrite\macscribble + \def\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } +\fi + +\def\scanmacro#1{\begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % + % ... and for \example: + \spaceisspace + % + % The \empty here causes a following catcode 5 newline to be eaten as + % part of reading whitespace after a control sequence. It does not + % eat a catcode 13 newline. There's no good way to handle the two + % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX + % would then have different behavior). See the Macro Details node in + % the manual for the workaround we recommend for macros and + % line-oriented commands. + % + \scantokens{#1\empty}% +\endgroup} + +\def\scanexp#1{% + \edef\temp{\noexpand\scanmacro{#1}}% + \temp +} + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? + +% List of all defined macros in the form +% \definedummyword\macro1\definedummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\definedummyword#1}% + \xdef\macrolist{\the\toks0}% +} + +% Utility routines. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% +\def\cslet#1#2{% + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \ +% to recognize macro arguments; this is the job of \mbodybackslash. +% +% Non-ASCII encodings make 8-bit characters active, so un-activate +% them to avoid their expansion. Must do this non-globally, to +% confine the change to the current group. +% +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. +% +\def\scanctxt{% used as subroutine + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\@=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\~=\other + \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi +} + +\def\scanargctxt{% used for copying and captions, not macros. + \scanctxt + \catcode`\\=\other + \catcode`\^^M=\other +} + +\def\macrobodyctxt{% used for @macro definitions + \scanctxt + \catcode`\{=\other + \catcode`\}=\other + \catcode`\^^M=\other + \usembodybackslash +} + +\def\macroargctxt{% used when scanning invocations + \scanctxt + \catcode`\\=0 +} +% why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes" +% for the single characters \ { }. Thus, we end up with the "commands" +% that would be written @\ @{ @} in a Texinfo document. +% +% We already have @{ and @}. For @\, we define it here, and only for +% this purpose, to produce a typewriter backslash (so, the @\ that we +% define for @math can't be used with @macro calls): +% +\def\\{\normalbackslash}% +% +% We would like to do this for \, too, since that is what makeinfo does. +% But it is not possible, because Texinfo already has a command @, for a +% cedilla accent. Documents must use @comma{} instead. +% +% \anythingelse will almost certainly be an error of some kind. + + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. +% +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\margbackslash#1{\char`\#1 } + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0\relax + \else + \expandafter\parsemargdef \argl;% + \if\paramno>256\relax + \ifx\eTeXversion\thisisundefined + \errhelp = \EMsimple + \errmessage{You need eTeX to compile a file with macros with more than 256 arguments} + \fi + \fi + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + \addtomacrolist{\the\macname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\parseargdef\unmacro{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\definedummyword\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx #1\relax + % remove this + \else + \noexpand\definedummyword \noexpand#1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% <parameter list> is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname#1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% For macro processing make @ a letter so that we can make Texinfo private macro names. +\edef\texiatcatcode{\the\catcode`\@} +\catcode `@=11\relax + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.BLAH for each BLAH +% in the params list to some hook where the argument is to be expanded. If +% there are less than 10 arguments that hook is to be replaced by ##N where N +% is the position in that list, that is to say the macro arguments are to be +% defined `a la TeX in the macro body. +% +% That gets used by \mbodybackslash (above). +% +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. +% +% If there are 10 or more arguments, a different technique is used, where the +% hook remains in the body, and when macro is to be expanded the body is +% processed again to replace the arguments. +% +% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the +% argument N value and then \edef the body (nothing else will expand because of +% the catcode regime underwhich the body was input). +% +% If you compile with TeX (not eTeX), and you have macros with 10 or more +% arguments, you need that no macro has more than 256 arguments, otherwise an +% error is produced. +\def\parsemargdef#1;{% + \paramno=0\def\paramlist{}% + \let\hash\relax + \let\xeatspaces\relax + \parsemargdefxxx#1,;,% + % In case that there are 10 or more arguments we parse again the arguments + % list to set new definitions for the \macarg.BLAH macros corresponding to + % each BLAH argument. It was anyhow needed to parse already once this list + % in order to count the arguments, and as macros with at most 9 arguments + % are by far more frequent than macro with 10 or more arguments, defining + % twice the \macarg.BLAH macros does not cost too much processing power. + \ifnum\paramno<10\relax\else + \paramno0\relax + \parsemmanyargdef@@#1,;,% 10 or more arguments + \fi +} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1 + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +\def\parsemmanyargdef@@#1,{% + \if#1;\let\next=\relax + \else + \let\next=\parsemmanyargdef@@ + \edef\tempb{\eatspaces{#1}}% + \expandafter\def\expandafter\tempa + \expandafter{\csname macarg.\tempb\endcsname}% + % Note that we need some extra \noexpand\noexpand, this is because we + % don't want \the to be expanded in the \parsermacbody as it uses an + % \xdef . + \expandafter\edef\tempa + {\noexpand\noexpand\noexpand\the\toks\the\paramno}% + \advance\paramno by 1\relax + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) +% + +\catcode `\@\texiatcatcode +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\catcode `\@=11\relax + +\let\endargs@\relax +\let\nil@\relax +\def\nilm@{\nil@}% +\long\def\nillm@{\nil@}% + +% This macro is expanded during the Texinfo macro expansion, not during its +% definition. It gets all the arguments values and assigns them to macros +% macarg.ARGNAME +% +% #1 is the macro name +% #2 is the list of argument names +% #3 is the list of argument values +\def\getargvals@#1#2#3{% + \def\macargdeflist@{}% + \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion. + \def\paramlist{#2,\nil@}% + \def\macroname{#1}% + \begingroup + \macroargctxt + \def\argvaluelist{#3,\nil@}% + \def\@tempa{#3}% + \ifx\@tempa\empty + \setemptyargvalues@ + \else + \getargvals@@ + \fi +} + +% +\def\getargvals@@{% + \ifx\paramlist\nilm@ + % Some sanity check needed here that \argvaluelist is also empty. + \ifx\argvaluelist\nillm@ + \else + \errhelp = \EMsimple + \errmessage{Too many arguments in macro `\macroname'!}% + \fi + \let\next\macargexpandinbody@ + \else + \ifx\argvaluelist\nillm@ + % No more arguments values passed to macro. Set remaining named-arg + % macros to empty. + \let\next\setemptyargvalues@ + \else + % pop current arg name into \@tempb + \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}% + \expandafter\@tempa\expandafter{\paramlist}% + % pop current argument value into \@tempc + \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}% + \expandafter\@tempa\expandafter{\argvaluelist}% + % Here \@tempb is the current arg name and \@tempc is the current arg value. + % First place the new argument macro definition into \@tempd + \expandafter\macname\expandafter{\@tempc}% + \expandafter\let\csname macarg.\@tempb\endcsname\relax + \expandafter\def\expandafter\@tempe\expandafter{% + \csname macarg.\@tempb\endcsname}% + \edef\@tempd{\long\def\@tempe{\the\macname}}% + \push@\@tempd\macargdeflist@ + \let\next\getargvals@@ + \fi + \fi + \next +} + +\def\push@#1#2{% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter#2% + \expandafter\expandafter\expandafter{% + \expandafter#1#2}% +} + +% Replace arguments by their values in the macro body, and place the result +% in macro \@tempa +\def\macvalstoargs@{% + % To do this we use the property that token registers that are \the'ed + % within an \edef expand only once. So we are going to place all argument + % values into respective token registers. + % + % First we save the token context, and initialize argument numbering. + \begingroup + \paramno0\relax + % Then, for each argument number #N, we place the corresponding argument + % value into a new token list register \toks#N + \expandafter\putargsintokens@\saveparamlist@,;,% + % Then, we expand the body so that argument are replaced by their + % values. The trick for values not to be expanded themselves is that they + % are within tokens and that tokens expand only once in an \edef . + \edef\@tempc{\csname mac.\macroname .body\endcsname}% + % Now we restore the token stack pointer to free the token list registers + % which we have used, but we make sure that expanded body is saved after + % group. + \expandafter + \endgroup + \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% + } + +\def\macargexpandinbody@{% + %% Define the named-macro outside of this group and then close this group. + \expandafter + \endgroup + \macargdeflist@ + % First the replace in body the macro arguments by their values, the result + % is in \@tempa . + \macvalstoargs@ + % Then we point at the \norecurse or \gobble (for recursive) macro value + % with \@tempb . + \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname + % Depending on whether it is recursive or not, we need some tailing + % \egroup . + \ifx\@tempb\gobble + \let\@tempc\relax + \else + \let\@tempc\egroup + \fi + % And now we do the real job: + \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}% + \@tempd +} + +\def\putargsintokens@#1,{% + \if#1;\let\next\relax + \else + \let\next\putargsintokens@ + % First we allocate the new token list register, and give it a temporary + % alias \@tempb . + \toksdef\@tempb\the\paramno + % Then we place the argument value into that token list register. + \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname + \expandafter\@tempb\expandafter{\@tempa}% + \advance\paramno by 1\relax + \fi + \next +} + +% Save the token stack pointer into macro #1 +\def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}} +% Restore the token stack pointer from number in macro #1 +\def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax} +% newtoks that can be used non \outer . +\def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi} + +% Tailing missing arguments are set to empty +\def\setemptyargvalues@{% + \ifx\paramlist\nilm@ + \let\next\macargexpandinbody@ + \else + \expandafter\setemptyargvaluesparser@\paramlist\endargs@ + \let\next\setemptyargvalues@ + \fi + \next +} + +\def\setemptyargvaluesparser@#1,#2\endargs@{% + \expandafter\def\expandafter\@tempa\expandafter{% + \expandafter\def\csname macarg.#1\endcsname{}}% + \push@\@tempa\macargdeflist@ + \def\paramlist{#2}% +} + +% #1 is the element target macro +% #2 is the list macro +% #3,#4\endargs@ is the list value +\def\pop@#1#2#3,#4\endargs@{% + \def#1{#3}% + \def#2{#4}% +} +\long\def\longpop@#1#2#3,#4\endargs@{% + \long\def#1{#3}% + \long\def#2{#4}% +} + +% This defines a Texinfo @macro. There are eight cases: recursive and +% nonrecursive macros of zero, one, up to nine, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +% +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else + \ifnum\paramno<10\relax % at most 9 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \else % 10 or more + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble + \fi + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % at most 9 + \ifnum\paramno<10\relax + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % 10 or more: + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse + \fi + \fi + \fi} + +\catcode `\@\texiatcatcode\relax + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg). +% +\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \macnamexxx} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Make them active and then expand them all to nothing. +% +\def\alias{\parseargusing\obeyspaces\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} + + +\message{cross references,} + +\newwrite\auxfile +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{% + \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} + +\let\nwnode=\node +\let\lastnode=\empty + +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty + \fi +} + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \lastsection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. +% +\def\setref#1#2{% + \pdfmkdest{#1}% + \iflinks + {% + \atdummies % preserve commands, but don't expand them + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\lastsection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout + }% + \fi +} + +% @xrefautosectiontitle on|off says whether @section(ing) names are used +% automatically in xrefs, if the third arg is not explicitly specified. +% This was provided as a "secret" @set xref-automatic-section-title +% variable, now it's official. +% +\parseargdef\xrefautomaticsectiontitle{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @xrefautomaticsectiontitle value `\temp', + must be on|off}% + \fi\fi +} + +% +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +% +\newbox\toprefbox +\newbox\printedrefnamebox +\newbox\infofilenamebox +\newbox\printedmanualbox +% +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + % + % Get args without leading/trailing spaces. + \def\printedrefname{\ignorespaces #3}% + \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% + % + \def\infofilename{\ignorespaces #4}% + \setbox\infofilenamebox = \hbox{\infofilename\unskip}% + % + \def\printedmanual{\ignorespaces #5}% + \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% + % + % If the printed reference name (arg #3) was not explicitly given in + % the @xref, figure out what we want to use. + \ifdim \wd\printedrefnamebox = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax + % Not auto section-title: use node name inside the square brackets. + \def\printedrefname{\ignorespaces #1}% + \else + % Auto section-title: use chapter/section title inside + % the square brackets if we have it. + \ifdim \wd\printedmanualbox > 0pt + % It is in another manual, so we don't have it; use node name. + \def\printedrefname{\ignorespaces #1}% + \else + \ifhavexrefs + % We (should) know the real title if we have the xref values. + \def\printedrefname{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printedrefname{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % Make link in pdf output. + \ifpdf + {\indexnofonts + \turnoffactive + \makevalueexpandable + % This expands tokens, so do it after making catcode changes, so _ + % etc. don't get their TeX definitions. This ignores all spaces in + % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % + % This (wrongly) does not take account of leading or trailing + % spaces in #1, which should be ignored. + \edef\pdfxrefdest{#1}% + \ifx\pdfxrefdest\empty + \def\pdfxrefdest{Top}% no empty targets + \else + \txiescapepdf\pdfxrefdest % escape PDF special chars + \fi + % + \leavevmode + \startlink attr{/Border [0 0 0]}% + \ifnum\filenamelength>0 + goto file{\the\filename.pdf} name{\pdfxrefdest}% + \else + goto name{\pdfmkpgn{\pdfxrefdest}}% + \fi + }% + \setcolor{\linkcolor}% + \fi + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". We distinguish them by the + % LABEL-title being set to a magic string. + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd\printedrefnamebox = 0pt + \refx{#1-snt}{}% + \else + \printedrefname + \fi + % + % If the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd\printedmanualbox > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. + % + % If we use \unhbox to print the node names, TeX does not insert + % empty discretionaries after hyphens, which means that it will not + % find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, + % this is a loss. Therefore, we give the text of the node name + % again, so it is as if TeX is seeing it for the first time. + % + \ifdim \wd\printedmanualbox > 0pt + % Cross-manual reference with a printed manual name. + % + \crossmanualxref{\cite{\printedmanual\unskip}}% + % + \else\ifdim \wd\infofilenamebox > 0pt + % Cross-manual reference with only an info filename (arg 4), no + % printed manual name (arg 5). This is essentially the same as + % the case above; we output the filename, since we have nothing else. + % + \crossmanualxref{\code{\infofilename\unskip}}% + % + \else + % Reference within this manual. + % + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via the macro below so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi\fi + \fi + \endlink +\endgroup} + +% Output a cross-manual xref to #1. Used just above (twice). +% +% Only include the text "Section ``foo'' in" if the foo is neither +% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply +% "see The Foo Manual", the idea being to refer to the whole manual. +% +% But, this being TeX, we can't easily compare our node name against the +% string "Top" while ignoring the possible spaces before and after in +% the input. By adding the arbitrary 7sp below, we make it much less +% likely that a real node name would have the same width as "Top" (e.g., +% in a monospaced font). Hopefully it will never happen in practice. +% +% For the same basic reason, we retypeset the "Top" at every +% reference, since the current font is indeterminate. +% +\def\crossmanualxref#1{% + \setbox\toprefbox = \hbox{Top\kern7sp}% + \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% + \ifdim \wd2 > 7sp % nonempty? + \ifdim \wd2 = \wd\toprefbox \else % same as Top? + \putwordSection{} ``\printedrefname'' \putwordin{}\space + \fi + \fi + #1% +} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since square brackets don't work well in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% Things referred to by \setref. +% +\def\Ynothing{} +\def\Yomitfromtoc{} +\def\Ynumbered{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +\def\Yappendix{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname XR#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + {\toks0 = {#1}% avoid expansion of possibly-complex value + \message{\linenumber Undefined cross reference `\the\toks0'.}}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. Usually it's +% just a \def (we prepend XR to the control sequence name to avoid +% collisions). But if this is a float type, we have more work to do. +% +\def\xrdef#1#2{% + {% The node name might contain 8-bit characters, which in our current + % implementation are changed to commands like @'e. Don't let these + % mess up the control sequence name. + \indexnofonts + \turnoffactive + \xdef\safexrefname{#1}% + }% + % + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR\safexrefname\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 + {\safexrefname}}% + \fi +} + +% Read the last existing aux file, if any. No error if none exists. +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readdatafile{aux}% + \global\havexrefstrue + \fi + \closein 1 +} + +\def\setupdatafile{% + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % This is to support \ in node names and titles, since the \ + % characters end up in a \csname. It's easier than + % leaving it active and making its active definition an actual \ + % character. What I don't understand is why it works in the *value* + % of the xrdef. Seems like it should be a catcode12 \, and that + % should not typeset properly. But it works, so I'm moving on for + % now. --karl, 15jan04. + \catcode`\\=\other + % + % Make the characters 128-255 be printing characters. + {% + \count1=128 + \def\loop{% + \catcode\count1=\other + \advance\count1 by 1 + \ifnum \count1<256 \loop \fi + }% + }% + % + % @ is our escape character in .aux files, and we need braces. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 +\endgroup} + + +\message{insertions,} +% including footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for Info output only. +\let\footnotestyle=\comment + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + % + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\gdef\dofootnote{% + \insert\footins\bgroup + % + % Nested footnotes are not supported in TeX, that would take a lot + % more work. (\startsavinginserts does not suffice.) + \let\footnote=\errfootnote + % + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + % + % Invoke rest of plain TeX footnote routine. + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +\def\errfootnote{% + \errhelp=\EMsimple + \errmessage{Nested footnotes not supported in texinfo.tex, + even though they work in makeinfo; sorry} +} + +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarly, if a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is finished. +% And the same can be done for other insert classes. --kasal, 16nov03. +% +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi +} + +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. +% +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +\closein 1 +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\thisisundefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \else \ifx\centersub\centerV + % for @center @image, we need a vbox so we can have our vertical space + \imagevmodetrue + \vbox\bgroup % vbox has better behavior than vtop herev + \fi\fi + % + \ifimagevmode + \nobreak\medskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \fi + % + % Leave vertical mode so that indentation from an enclosing + % environment such as @quotation is respected. + % However, if we're at the top level, we don't want the + % normal paragraph indentation. + % On the other hand, if we are in the case of @center @image, we don't + % want to start a paragraph, which will create a hsize-width box and + % eradicate the centering. + \ifx\centersub\centerV\else \noindent \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode + \medskip % space after a standalone image + \fi + \ifx\centersub\centerV \egroup \fi +\endgroup} + + +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \lastsection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\lastsection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \atdummies + % + % since we read the caption text in the macro world, where ^^M + % is turned into a normal character, we have to scan it back, so + % we don't write the literal three characters "^^M" into the aux file. + \scanexp{% + \xdef\noexpand\gtemp{% + \ifx\thisshortcaption\empty + \thiscaption + \else + \thisshortcaption + \fi + }% + }% + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + % place the captured inserts + % + % BEWARE: when the floats start floating, we have to issue warning + % whenever an insert appears inside a float which could possibly + % float. --kasal, 26may04 + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \lastsection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup + \fi +} + +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} + + +\message{localization,} + +% For single-language documents, @documentlanguage is usually given very +% early, just after @documentencoding. Single argument is the language +% (de) or locale (de_DE) abbreviation. +% +{ + \catcode`\_ = \active + \globaldefs=1 +\parseargdef\documentlanguage{\begingroup + \let_=\normalunderscore % normal _ character for filenames + \tex % read txi-??.tex file in plain TeX. + % Read the file by the name they passed if it exists. + \openin 1 txi-#1.tex + \ifeof 1 + \documentlanguagetrywithoutunderscore{#1_\finish}% + \else + \globaldefs = 1 % everything in the txi-LL files needs to persist + \input txi-#1.tex + \fi + \closein 1 + \endgroup % end raw TeX +\endgroup} +% +% If they passed de_DE, and txi-de_DE.tex doesn't exist, +% try txi-de.tex. +% +\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \globaldefs = 1 % everything in the txi-LL files needs to persist + \input txi-#1.tex + \fi + \closein 1 +} +}% end of special _ catcode +% +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? Putting it in the current +directory should work if nowhere else does.} + +% This macro is called from txi-??.tex files; the first argument is the +% \language name to set (without the "\lang@" prefix), the second and +% third args are \{left,right}hyphenmin. +% +% The language names to pass are determined when the format is built. +% See the etex.log file created at that time, e.g., +% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. +% +% With TeX Live 2008, etex now includes hyphenation patterns for all +% available languages. This means we can support hyphenation in +% Texinfo, at least to some extent. (This still doesn't solve the +% accented characters problem.) +% +\catcode`@=11 +\def\txisetlanguage#1#2#3{% + % do not set the language if the name is undefined in the current TeX. + \expandafter\ifx\csname lang@#1\endcsname \relax + \message{no patterns for #1}% + \else + \global\language = \csname lang@#1\endcsname + \fi + % but there is no harm in adjusting the hyphenmin values regardless. + \global\lefthyphenmin = #2\relax + \global\righthyphenmin = #3\relax +} + +% Helpers for encodings. +% Set the catcode of characters 128 through 255 to the specified number. +% +\def\setnonasciicharscatcode#1{% + \count255=128 + \loop\ifnum\count255<256 + \global\catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +\def\setnonasciicharscatcodenonglobal#1{% + \count255=128 + \loop\ifnum\count255<256 + \catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +% @documentencoding sets the definition of non-ASCII characters +% according to the specified encoding. +% +\parseargdef\documentencoding{% + % Encoding being declared for the document. + \def\declaredencoding{\csname #1.enc\endcsname}% + % + % Supported encodings: names converted to tokens in order to be able + % to compare them with \ifx. + \def\ascii{\csname US-ASCII.enc\endcsname}% + \def\latnine{\csname ISO-8859-15.enc\endcsname}% + \def\latone{\csname ISO-8859-1.enc\endcsname}% + \def\lattwo{\csname ISO-8859-2.enc\endcsname}% + \def\utfeight{\csname UTF-8.enc\endcsname}% + % + \ifx \declaredencoding \ascii + \asciichardefs + % + \else \ifx \declaredencoding \lattwo + \setnonasciicharscatcode\active + \lattwochardefs + % + \else \ifx \declaredencoding \latone + \setnonasciicharscatcode\active + \latonechardefs + % + \else \ifx \declaredencoding \latnine + \setnonasciicharscatcode\active + \latninechardefs + % + \else \ifx \declaredencoding \utfeight + \setnonasciicharscatcode\active + \utfeightchardefs + % + \else + \message{Unknown document encoding #1, ignoring.}% + % + \fi % utfeight + \fi % latnine + \fi % latone + \fi % lattwo + \fi % ascii +} + +% A message to be logged when using a character that isn't available +% the default font encoding (OT1). +% +\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} + +% Take account of \c (plain) vs. \, (Texinfo) difference. +\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} + +% First, make active non-ASCII characters in order for them to be +% correctly categorized when TeX reads the replacement text of +% macros containing the character definitions. +\setnonasciicharscatcode\active +% +% Latin1 (ISO-8859-1) character definitions. +\def\latonechardefs{% + \gdef^^a0{\tie} + \gdef^^a1{\exclamdown} + \gdef^^a2{\missingcharmsg{CENT SIGN}} + \gdef^^a3{{\pounds}} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\missingcharmsg{YEN SIGN}} + \gdef^^a6{\missingcharmsg{BROKEN BAR}} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\copyright} + \gdef^^aa{\ordf} + \gdef^^ab{\guillemetleft} + \gdef^^ac{$\lnot$} + \gdef^^ad{\-} + \gdef^^ae{\registeredsymbol} + \gdef^^af{\={}} + % + \gdef^^b0{\textdegree} + \gdef^^b1{$\pm$} + \gdef^^b2{$^2$} + \gdef^^b3{$^3$} + \gdef^^b4{\'{}} + \gdef^^b5{$\mu$} + \gdef^^b6{\P} + % + \gdef^^b7{$^.$} + \gdef^^b8{\cedilla\ } + \gdef^^b9{$^1$} + \gdef^^ba{\ordm} + % + \gdef^^bb{\guillemetright} + \gdef^^bc{$1\over4$} + \gdef^^bd{$1\over2$} + \gdef^^be{$3\over4$} + \gdef^^bf{\questiondown} + % + \gdef^^c0{\`A} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\~A} + \gdef^^c4{\"A} + \gdef^^c5{\ringaccent A} + \gdef^^c6{\AE} + \gdef^^c7{\cedilla C} + \gdef^^c8{\`E} + \gdef^^c9{\'E} + \gdef^^ca{\^E} + \gdef^^cb{\"E} + \gdef^^cc{\`I} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\"I} + % + \gdef^^d0{\DH} + \gdef^^d1{\~N} + \gdef^^d2{\`O} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\~O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\O} + \gdef^^d9{\`U} + \gdef^^da{\'U} + \gdef^^db{\^U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\TH} + \gdef^^df{\ss} + % + \gdef^^e0{\`a} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\~a} + \gdef^^e4{\"a} + \gdef^^e5{\ringaccent a} + \gdef^^e6{\ae} + \gdef^^e7{\cedilla c} + \gdef^^e8{\`e} + \gdef^^e9{\'e} + \gdef^^ea{\^e} + \gdef^^eb{\"e} + \gdef^^ec{\`{\dotless i}} + \gdef^^ed{\'{\dotless i}} + \gdef^^ee{\^{\dotless i}} + \gdef^^ef{\"{\dotless i}} + % + \gdef^^f0{\dh} + \gdef^^f1{\~n} + \gdef^^f2{\`o} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\~o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\o} + \gdef^^f9{\`u} + \gdef^^fa{\'u} + \gdef^^fb{\^u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\th} + \gdef^^ff{\"y} +} + +% Latin9 (ISO-8859-15) encoding character definitions. +\def\latninechardefs{% + % Encoding is almost identical to Latin1. + \latonechardefs + % + \gdef^^a4{\euro} + \gdef^^a6{\v S} + \gdef^^a8{\v s} + \gdef^^b4{\v Z} + \gdef^^b8{\v z} + \gdef^^bc{\OE} + \gdef^^bd{\oe} + \gdef^^be{\"Y} +} + +% Latin2 (ISO-8859-2) character definitions. +\def\lattwochardefs{% + \gdef^^a0{\tie} + \gdef^^a1{\ogonek{A}} + \gdef^^a2{\u{}} + \gdef^^a3{\L} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\v L} + \gdef^^a6{\'S} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\v S} + \gdef^^aa{\cedilla S} + \gdef^^ab{\v T} + \gdef^^ac{\'Z} + \gdef^^ad{\-} + \gdef^^ae{\v Z} + \gdef^^af{\dotaccent Z} + % + \gdef^^b0{\textdegree} + \gdef^^b1{\ogonek{a}} + \gdef^^b2{\ogonek{ }} + \gdef^^b3{\l} + \gdef^^b4{\'{}} + \gdef^^b5{\v l} + \gdef^^b6{\'s} + \gdef^^b7{\v{}} + \gdef^^b8{\cedilla\ } + \gdef^^b9{\v s} + \gdef^^ba{\cedilla s} + \gdef^^bb{\v t} + \gdef^^bc{\'z} + \gdef^^bd{\H{}} + \gdef^^be{\v z} + \gdef^^bf{\dotaccent z} + % + \gdef^^c0{\'R} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\u A} + \gdef^^c4{\"A} + \gdef^^c5{\'L} + \gdef^^c6{\'C} + \gdef^^c7{\cedilla C} + \gdef^^c8{\v C} + \gdef^^c9{\'E} + \gdef^^ca{\ogonek{E}} + \gdef^^cb{\"E} + \gdef^^cc{\v E} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\v D} + % + \gdef^^d0{\DH} + \gdef^^d1{\'N} + \gdef^^d2{\v N} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\H O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\v R} + \gdef^^d9{\ringaccent U} + \gdef^^da{\'U} + \gdef^^db{\H U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\cedilla T} + \gdef^^df{\ss} + % + \gdef^^e0{\'r} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\u a} + \gdef^^e4{\"a} + \gdef^^e5{\'l} + \gdef^^e6{\'c} + \gdef^^e7{\cedilla c} + \gdef^^e8{\v c} + \gdef^^e9{\'e} + \gdef^^ea{\ogonek{e}} + \gdef^^eb{\"e} + \gdef^^ec{\v e} + \gdef^^ed{\'{\dotless{i}}} + \gdef^^ee{\^{\dotless{i}}} + \gdef^^ef{\v d} + % + \gdef^^f0{\dh} + \gdef^^f1{\'n} + \gdef^^f2{\v n} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\H o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\v r} + \gdef^^f9{\ringaccent u} + \gdef^^fa{\'u} + \gdef^^fb{\H u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\cedilla t} + \gdef^^ff{\dotaccent{}} +} + +% UTF-8 character definitions. +% +% This code to support UTF-8 is based on LaTeX's utf8.def, with some +% changes for Texinfo conventions. It is included here under the GPL by +% permission from Frank Mittelbach and the LaTeX team. +% +\newcount\countUTFx +\newcount\countUTFy +\newcount\countUTFz + +\gdef\UTFviiiTwoOctets#1#2{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\endcsname} +% +\gdef\UTFviiiThreeOctets#1#2#3{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} +% +\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} + +\gdef\UTFviiiDefined#1{% + \ifx #1\relax + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \else + \expandafter #1% + \fi +} + +\begingroup + \catcode`\~13 + \catcode`\"12 + + \def\UTFviiiLoop{% + \global\catcode\countUTFx\active + \uccode`\~\countUTFx + \uppercase\expandafter{\UTFviiiTmp}% + \advance\countUTFx by 1 + \ifnum\countUTFx < \countUTFy + \expandafter\UTFviiiLoop + \fi} + + \countUTFx = "C2 + \countUTFy = "E0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiTwoOctets\string~}} + \UTFviiiLoop + + \countUTFx = "E0 + \countUTFy = "F0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiThreeOctets\string~}} + \UTFviiiLoop + + \countUTFx = "F0 + \countUTFy = "F4 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiFourOctets\string~}} + \UTFviiiLoop +\endgroup + +\begingroup + \catcode`\"=12 + \catcode`\<=12 + \catcode`\.=12 + \catcode`\,=12 + \catcode`\;=12 + \catcode`\!=12 + \catcode`\~=13 + + \gdef\DeclareUnicodeCharacter#1#2{% + \countUTFz = "#1\relax + %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% + \begingroup + \parseXMLCharref + \def\UTFviiiTwoOctets##1##2{% + \csname u8:##1\string ##2\endcsname}% + \def\UTFviiiThreeOctets##1##2##3{% + \csname u8:##1\string ##2\string ##3\endcsname}% + \def\UTFviiiFourOctets##1##2##3##4{% + \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \gdef\UTFviiiTmp{#2}% + \endgroup} + + \gdef\parseXMLCharref{% + \ifnum\countUTFz < "A0\relax + \errhelp = \EMsimple + \errmessage{Cannot define Unicode char value < 00A0}% + \else\ifnum\countUTFz < "800\relax + \parseUTFviiiA,% + \parseUTFviiiB C\UTFviiiTwoOctets.,% + \else\ifnum\countUTFz < "10000\relax + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% + \else + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiA!% + \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% + \fi\fi\fi + } + + \gdef\parseUTFviiiA#1{% + \countUTFx = \countUTFz + \divide\countUTFz by 64 + \countUTFy = \countUTFz + \multiply\countUTFz by 64 + \advance\countUTFx by -\countUTFz + \advance\countUTFx by 128 + \uccode `#1\countUTFx + \countUTFz = \countUTFy} + + \gdef\parseUTFviiiB#1#2#3#4{% + \advance\countUTFz by "#10\relax + \uccode `#3\countUTFz + \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} +\endgroup + +\def\utfeightchardefs{% + \DeclareUnicodeCharacter{00A0}{\tie} + \DeclareUnicodeCharacter{00A1}{\exclamdown} + \DeclareUnicodeCharacter{00A3}{\pounds} + \DeclareUnicodeCharacter{00A8}{\"{ }} + \DeclareUnicodeCharacter{00A9}{\copyright} + \DeclareUnicodeCharacter{00AA}{\ordf} + \DeclareUnicodeCharacter{00AB}{\guillemetleft} + \DeclareUnicodeCharacter{00AD}{\-} + \DeclareUnicodeCharacter{00AE}{\registeredsymbol} + \DeclareUnicodeCharacter{00AF}{\={ }} + + \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} + \DeclareUnicodeCharacter{00B4}{\'{ }} + \DeclareUnicodeCharacter{00B8}{\cedilla{ }} + \DeclareUnicodeCharacter{00BA}{\ordm} + \DeclareUnicodeCharacter{00BB}{\guillemetright} + \DeclareUnicodeCharacter{00BF}{\questiondown} + + \DeclareUnicodeCharacter{00C0}{\`A} + \DeclareUnicodeCharacter{00C1}{\'A} + \DeclareUnicodeCharacter{00C2}{\^A} + \DeclareUnicodeCharacter{00C3}{\~A} + \DeclareUnicodeCharacter{00C4}{\"A} + \DeclareUnicodeCharacter{00C5}{\AA} + \DeclareUnicodeCharacter{00C6}{\AE} + \DeclareUnicodeCharacter{00C7}{\cedilla{C}} + \DeclareUnicodeCharacter{00C8}{\`E} + \DeclareUnicodeCharacter{00C9}{\'E} + \DeclareUnicodeCharacter{00CA}{\^E} + \DeclareUnicodeCharacter{00CB}{\"E} + \DeclareUnicodeCharacter{00CC}{\`I} + \DeclareUnicodeCharacter{00CD}{\'I} + \DeclareUnicodeCharacter{00CE}{\^I} + \DeclareUnicodeCharacter{00CF}{\"I} + + \DeclareUnicodeCharacter{00D0}{\DH} + \DeclareUnicodeCharacter{00D1}{\~N} + \DeclareUnicodeCharacter{00D2}{\`O} + \DeclareUnicodeCharacter{00D3}{\'O} + \DeclareUnicodeCharacter{00D4}{\^O} + \DeclareUnicodeCharacter{00D5}{\~O} + \DeclareUnicodeCharacter{00D6}{\"O} + \DeclareUnicodeCharacter{00D8}{\O} + \DeclareUnicodeCharacter{00D9}{\`U} + \DeclareUnicodeCharacter{00DA}{\'U} + \DeclareUnicodeCharacter{00DB}{\^U} + \DeclareUnicodeCharacter{00DC}{\"U} + \DeclareUnicodeCharacter{00DD}{\'Y} + \DeclareUnicodeCharacter{00DE}{\TH} + \DeclareUnicodeCharacter{00DF}{\ss} + + \DeclareUnicodeCharacter{00E0}{\`a} + \DeclareUnicodeCharacter{00E1}{\'a} + \DeclareUnicodeCharacter{00E2}{\^a} + \DeclareUnicodeCharacter{00E3}{\~a} + \DeclareUnicodeCharacter{00E4}{\"a} + \DeclareUnicodeCharacter{00E5}{\aa} + \DeclareUnicodeCharacter{00E6}{\ae} + \DeclareUnicodeCharacter{00E7}{\cedilla{c}} + \DeclareUnicodeCharacter{00E8}{\`e} + \DeclareUnicodeCharacter{00E9}{\'e} + \DeclareUnicodeCharacter{00EA}{\^e} + \DeclareUnicodeCharacter{00EB}{\"e} + \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} + \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} + \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} + \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} + + \DeclareUnicodeCharacter{00F0}{\dh} + \DeclareUnicodeCharacter{00F1}{\~n} + \DeclareUnicodeCharacter{00F2}{\`o} + \DeclareUnicodeCharacter{00F3}{\'o} + \DeclareUnicodeCharacter{00F4}{\^o} + \DeclareUnicodeCharacter{00F5}{\~o} + \DeclareUnicodeCharacter{00F6}{\"o} + \DeclareUnicodeCharacter{00F8}{\o} + \DeclareUnicodeCharacter{00F9}{\`u} + \DeclareUnicodeCharacter{00FA}{\'u} + \DeclareUnicodeCharacter{00FB}{\^u} + \DeclareUnicodeCharacter{00FC}{\"u} + \DeclareUnicodeCharacter{00FD}{\'y} + \DeclareUnicodeCharacter{00FE}{\th} + \DeclareUnicodeCharacter{00FF}{\"y} + + \DeclareUnicodeCharacter{0100}{\=A} + \DeclareUnicodeCharacter{0101}{\=a} + \DeclareUnicodeCharacter{0102}{\u{A}} + \DeclareUnicodeCharacter{0103}{\u{a}} + \DeclareUnicodeCharacter{0104}{\ogonek{A}} + \DeclareUnicodeCharacter{0105}{\ogonek{a}} + \DeclareUnicodeCharacter{0106}{\'C} + \DeclareUnicodeCharacter{0107}{\'c} + \DeclareUnicodeCharacter{0108}{\^C} + \DeclareUnicodeCharacter{0109}{\^c} + \DeclareUnicodeCharacter{0118}{\ogonek{E}} + \DeclareUnicodeCharacter{0119}{\ogonek{e}} + \DeclareUnicodeCharacter{010A}{\dotaccent{C}} + \DeclareUnicodeCharacter{010B}{\dotaccent{c}} + \DeclareUnicodeCharacter{010C}{\v{C}} + \DeclareUnicodeCharacter{010D}{\v{c}} + \DeclareUnicodeCharacter{010E}{\v{D}} + + \DeclareUnicodeCharacter{0112}{\=E} + \DeclareUnicodeCharacter{0113}{\=e} + \DeclareUnicodeCharacter{0114}{\u{E}} + \DeclareUnicodeCharacter{0115}{\u{e}} + \DeclareUnicodeCharacter{0116}{\dotaccent{E}} + \DeclareUnicodeCharacter{0117}{\dotaccent{e}} + \DeclareUnicodeCharacter{011A}{\v{E}} + \DeclareUnicodeCharacter{011B}{\v{e}} + \DeclareUnicodeCharacter{011C}{\^G} + \DeclareUnicodeCharacter{011D}{\^g} + \DeclareUnicodeCharacter{011E}{\u{G}} + \DeclareUnicodeCharacter{011F}{\u{g}} + + \DeclareUnicodeCharacter{0120}{\dotaccent{G}} + \DeclareUnicodeCharacter{0121}{\dotaccent{g}} + \DeclareUnicodeCharacter{0124}{\^H} + \DeclareUnicodeCharacter{0125}{\^h} + \DeclareUnicodeCharacter{0128}{\~I} + \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} + \DeclareUnicodeCharacter{012A}{\=I} + \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} + \DeclareUnicodeCharacter{012C}{\u{I}} + \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} + + \DeclareUnicodeCharacter{0130}{\dotaccent{I}} + \DeclareUnicodeCharacter{0131}{\dotless{i}} + \DeclareUnicodeCharacter{0132}{IJ} + \DeclareUnicodeCharacter{0133}{ij} + \DeclareUnicodeCharacter{0134}{\^J} + \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} + \DeclareUnicodeCharacter{0139}{\'L} + \DeclareUnicodeCharacter{013A}{\'l} + + \DeclareUnicodeCharacter{0141}{\L} + \DeclareUnicodeCharacter{0142}{\l} + \DeclareUnicodeCharacter{0143}{\'N} + \DeclareUnicodeCharacter{0144}{\'n} + \DeclareUnicodeCharacter{0147}{\v{N}} + \DeclareUnicodeCharacter{0148}{\v{n}} + \DeclareUnicodeCharacter{014C}{\=O} + \DeclareUnicodeCharacter{014D}{\=o} + \DeclareUnicodeCharacter{014E}{\u{O}} + \DeclareUnicodeCharacter{014F}{\u{o}} + + \DeclareUnicodeCharacter{0150}{\H{O}} + \DeclareUnicodeCharacter{0151}{\H{o}} + \DeclareUnicodeCharacter{0152}{\OE} + \DeclareUnicodeCharacter{0153}{\oe} + \DeclareUnicodeCharacter{0154}{\'R} + \DeclareUnicodeCharacter{0155}{\'r} + \DeclareUnicodeCharacter{0158}{\v{R}} + \DeclareUnicodeCharacter{0159}{\v{r}} + \DeclareUnicodeCharacter{015A}{\'S} + \DeclareUnicodeCharacter{015B}{\'s} + \DeclareUnicodeCharacter{015C}{\^S} + \DeclareUnicodeCharacter{015D}{\^s} + \DeclareUnicodeCharacter{015E}{\cedilla{S}} + \DeclareUnicodeCharacter{015F}{\cedilla{s}} + + \DeclareUnicodeCharacter{0160}{\v{S}} + \DeclareUnicodeCharacter{0161}{\v{s}} + \DeclareUnicodeCharacter{0162}{\cedilla{t}} + \DeclareUnicodeCharacter{0163}{\cedilla{T}} + \DeclareUnicodeCharacter{0164}{\v{T}} + + \DeclareUnicodeCharacter{0168}{\~U} + \DeclareUnicodeCharacter{0169}{\~u} + \DeclareUnicodeCharacter{016A}{\=U} + \DeclareUnicodeCharacter{016B}{\=u} + \DeclareUnicodeCharacter{016C}{\u{U}} + \DeclareUnicodeCharacter{016D}{\u{u}} + \DeclareUnicodeCharacter{016E}{\ringaccent{U}} + \DeclareUnicodeCharacter{016F}{\ringaccent{u}} + + \DeclareUnicodeCharacter{0170}{\H{U}} + \DeclareUnicodeCharacter{0171}{\H{u}} + \DeclareUnicodeCharacter{0174}{\^W} + \DeclareUnicodeCharacter{0175}{\^w} + \DeclareUnicodeCharacter{0176}{\^Y} + \DeclareUnicodeCharacter{0177}{\^y} + \DeclareUnicodeCharacter{0178}{\"Y} + \DeclareUnicodeCharacter{0179}{\'Z} + \DeclareUnicodeCharacter{017A}{\'z} + \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} + \DeclareUnicodeCharacter{017C}{\dotaccent{z}} + \DeclareUnicodeCharacter{017D}{\v{Z}} + \DeclareUnicodeCharacter{017E}{\v{z}} + + \DeclareUnicodeCharacter{01C4}{D\v{Z}} + \DeclareUnicodeCharacter{01C5}{D\v{z}} + \DeclareUnicodeCharacter{01C6}{d\v{z}} + \DeclareUnicodeCharacter{01C7}{LJ} + \DeclareUnicodeCharacter{01C8}{Lj} + \DeclareUnicodeCharacter{01C9}{lj} + \DeclareUnicodeCharacter{01CA}{NJ} + \DeclareUnicodeCharacter{01CB}{Nj} + \DeclareUnicodeCharacter{01CC}{nj} + \DeclareUnicodeCharacter{01CD}{\v{A}} + \DeclareUnicodeCharacter{01CE}{\v{a}} + \DeclareUnicodeCharacter{01CF}{\v{I}} + + \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} + \DeclareUnicodeCharacter{01D1}{\v{O}} + \DeclareUnicodeCharacter{01D2}{\v{o}} + \DeclareUnicodeCharacter{01D3}{\v{U}} + \DeclareUnicodeCharacter{01D4}{\v{u}} + + \DeclareUnicodeCharacter{01E2}{\={\AE}} + \DeclareUnicodeCharacter{01E3}{\={\ae}} + \DeclareUnicodeCharacter{01E6}{\v{G}} + \DeclareUnicodeCharacter{01E7}{\v{g}} + \DeclareUnicodeCharacter{01E8}{\v{K}} + \DeclareUnicodeCharacter{01E9}{\v{k}} + + \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} + \DeclareUnicodeCharacter{01F1}{DZ} + \DeclareUnicodeCharacter{01F2}{Dz} + \DeclareUnicodeCharacter{01F3}{dz} + \DeclareUnicodeCharacter{01F4}{\'G} + \DeclareUnicodeCharacter{01F5}{\'g} + \DeclareUnicodeCharacter{01F8}{\`N} + \DeclareUnicodeCharacter{01F9}{\`n} + \DeclareUnicodeCharacter{01FC}{\'{\AE}} + \DeclareUnicodeCharacter{01FD}{\'{\ae}} + \DeclareUnicodeCharacter{01FE}{\'{\O}} + \DeclareUnicodeCharacter{01FF}{\'{\o}} + + \DeclareUnicodeCharacter{021E}{\v{H}} + \DeclareUnicodeCharacter{021F}{\v{h}} + + \DeclareUnicodeCharacter{0226}{\dotaccent{A}} + \DeclareUnicodeCharacter{0227}{\dotaccent{a}} + \DeclareUnicodeCharacter{0228}{\cedilla{E}} + \DeclareUnicodeCharacter{0229}{\cedilla{e}} + \DeclareUnicodeCharacter{022E}{\dotaccent{O}} + \DeclareUnicodeCharacter{022F}{\dotaccent{o}} + + \DeclareUnicodeCharacter{0232}{\=Y} + \DeclareUnicodeCharacter{0233}{\=y} + \DeclareUnicodeCharacter{0237}{\dotless{j}} + + \DeclareUnicodeCharacter{02DB}{\ogonek{ }} + + \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} + \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} + \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} + \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} + \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} + \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} + \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} + \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} + \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} + \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} + \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} + \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} + + \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} + \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} + + \DeclareUnicodeCharacter{1E20}{\=G} + \DeclareUnicodeCharacter{1E21}{\=g} + \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} + \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} + \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} + \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} + \DeclareUnicodeCharacter{1E26}{\"H} + \DeclareUnicodeCharacter{1E27}{\"h} + + \DeclareUnicodeCharacter{1E30}{\'K} + \DeclareUnicodeCharacter{1E31}{\'k} + \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} + \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} + \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} + \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} + \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} + \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} + \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} + \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} + \DeclareUnicodeCharacter{1E3E}{\'M} + \DeclareUnicodeCharacter{1E3F}{\'m} + + \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} + \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} + \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} + \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} + \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} + \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} + \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} + \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} + \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} + \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} + + \DeclareUnicodeCharacter{1E54}{\'P} + \DeclareUnicodeCharacter{1E55}{\'p} + \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} + \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} + \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} + \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} + \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} + \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} + \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} + \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} + + \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} + \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} + \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} + \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} + \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} + \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} + \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} + \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} + \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} + \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} + + \DeclareUnicodeCharacter{1E7C}{\~V} + \DeclareUnicodeCharacter{1E7D}{\~v} + \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} + \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} + + \DeclareUnicodeCharacter{1E80}{\`W} + \DeclareUnicodeCharacter{1E81}{\`w} + \DeclareUnicodeCharacter{1E82}{\'W} + \DeclareUnicodeCharacter{1E83}{\'w} + \DeclareUnicodeCharacter{1E84}{\"W} + \DeclareUnicodeCharacter{1E85}{\"w} + \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} + \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} + \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} + \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} + \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} + \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} + \DeclareUnicodeCharacter{1E8C}{\"X} + \DeclareUnicodeCharacter{1E8D}{\"x} + \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} + \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} + + \DeclareUnicodeCharacter{1E90}{\^Z} + \DeclareUnicodeCharacter{1E91}{\^z} + \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} + \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} + \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} + \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} + \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} + \DeclareUnicodeCharacter{1E97}{\"t} + \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} + \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} + + \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} + \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} + + \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} + \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} + \DeclareUnicodeCharacter{1EBC}{\~E} + \DeclareUnicodeCharacter{1EBD}{\~e} + + \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} + \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} + \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} + \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} + + \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} + \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} + + \DeclareUnicodeCharacter{1EF2}{\`Y} + \DeclareUnicodeCharacter{1EF3}{\`y} + \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} + + \DeclareUnicodeCharacter{1EF8}{\~Y} + \DeclareUnicodeCharacter{1EF9}{\~y} + + \DeclareUnicodeCharacter{2013}{--} + \DeclareUnicodeCharacter{2014}{---} + \DeclareUnicodeCharacter{2018}{\quoteleft} + \DeclareUnicodeCharacter{2019}{\quoteright} + \DeclareUnicodeCharacter{201A}{\quotesinglbase} + \DeclareUnicodeCharacter{201C}{\quotedblleft} + \DeclareUnicodeCharacter{201D}{\quotedblright} + \DeclareUnicodeCharacter{201E}{\quotedblbase} + \DeclareUnicodeCharacter{2022}{\bullet} + \DeclareUnicodeCharacter{2026}{\dots} + \DeclareUnicodeCharacter{2039}{\guilsinglleft} + \DeclareUnicodeCharacter{203A}{\guilsinglright} + \DeclareUnicodeCharacter{20AC}{\euro} + + \DeclareUnicodeCharacter{2192}{\expansion} + \DeclareUnicodeCharacter{21D2}{\result} + + \DeclareUnicodeCharacter{2212}{\minus} + \DeclareUnicodeCharacter{2217}{\point} + \DeclareUnicodeCharacter{2261}{\equiv} +}% end of \utfeightchardefs + + +% US-ASCII character definitions. +\def\asciichardefs{% nothing need be done + \relax +} + +% Make non-ASCII characters printable again for compatibility with +% existing Texinfo documents that may use them, even without declaring a +% document encoding. +% +\setnonasciicharscatcode \other + + +\message{formatting,} + +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be very finicky about underfull hboxes, either. +\hbadness = 6666 + +% Following George Bush, get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + % if we don't reset these, they will remain at "1 true in" of + % whatever layout pdftex was dumped with. + \pdfhorigin = 1 true in + \pdfvorigin = 1 true in + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{607.2pt}{6in}% that's 46 lines + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.25 trim size. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {-.2in}{0in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .4cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{673.2pt}{160mm}% that's 51 lines + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1\relax + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +\def^^L{\par} % remove \outer, so ^L can appear in an @comment + +% DEL is a comment character, in case @c does not suffice. +\catcode`\^^? = 14 + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other \def\normaldoublequote{"} +\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix +\catcode`\+=\other \def\normalplus{+} +\catcode`\<=\other \def\normalless{<} +\catcode`\>=\other \def\normalgreater{>} +\catcode`\^=\other \def\normalcaret{^} +\catcode`\_=\other \def\normalunderscore{_} +\catcode`\|=\other \def\normalverticalbar{|} +\catcode`\~=\other \def\normaltilde{~} + +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active \def\activetilde{{\tt\char126}} \let~ = \activetilde +\chardef\hat=`\^ +\catcode`\^=\active \def\activehat{{\tt \hat}} \let^ = \activehat + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +\let\realunder=_ +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} + +\chardef \less=`\< +\catcode`\<=\active \def\activeless{{\tt \less}}\let< = \activeless +\chardef \gtr=`\> +\catcode`\>=\active \def\activegtr{{\tt \gtr}}\let> = \activegtr +\catcode`\+=\active \def+{{\tt \char 43}} +\catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% used for headline/footline in the output routine, in case the page +% breaks in the middle of an @tex block. +\def\texinfochars{% + \let< = \activeless + \let> = \activegtr + \let~ = \activetilde + \let^ = \activehat + \markupsetuplqdefault \markupsetuprqdefault + \let\b = \strong + \let\i = \smartitalic + % in principle, all other definitions in \tex have to be undone too. +} + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} + +\catcode`\@=0 + +% \backslashcurfont outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\backslashcurfont=`\\ +\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work + +% \realbackslash is an actual character `\' with catcode other, and +% \doublebackslash is two of them (for the pdf outlines). +{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} + +% In texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active % @ for escape char from now on. + +% The story here is that in math mode, the \char of \backslashcurfont +% ends up printing the roman \ from the math symbol font (because \char +% in math mode uses the \mathcode, and plain.tex sets +% \mathcode`\\="026E). It seems better for @backslashchar{} to always +% print a typewriter backslash, hence we use an explicit \mathchar, +% which is the decimal equivalent of "715c (class 7, e.g., use \fam; +% ignored family value; char position "5C). We can't use " for the +% usual hex value because it has already been made active. +@def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} +@let@backslashchar = @normalbackslash % @backslashchar{} is for user documents. + +% On startup, @fixbackslash assigns: +% @let \ = @normalbackslash +% \rawbackslash defines an active \ to do \backslashcurfont. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. We switch back and forth between these. +@gdef@rawbackslash{@let\=@backslashcurfont} +@gdef@otherbackslash{@let\=@realbackslash} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. Also revert - to its normal character, in +% case the active - from code has slipped in. +% +{@catcode`- = @active + @gdef@normalturnoffactive{% + @let-=@normaldash + @let"=@normaldoublequote + @let$=@normaldollar %$ font-lock fix + @let+=@normalplus + @let<=@normalless + @let>=@normalgreater + @let\=@normalbackslash + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let~=@normaltilde + @markupsetuplqdefault + @markupsetuprqdefault + @unsepspaces + } +} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\' in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also turn back on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These (along with & and #) are made active for url-breaking, so need +% active definitions as the normal characters. +@def@normaldot{.} +@def@normalquest{?} +@def@normalslash{/} + +% These look ok in all fonts, so just make them not special. +% @hashchar{} gets its own user-level command, because of #line. +@catcode`@& = @other @def@normalamp{&} +@catcode`@# = @other @def@normalhash{#} +@catcode`@% = @other @def@normalpercent{%} + +@let @hashchar = @normalhash + +@c Finally, make ` and ' active, so that txicodequoteundirected and +@c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we +@c don't make ` and ' active, @code will not get them as active chars. +@c Do this last of all since we use ` in the previous @catcode assignments. +@catcode`@'=@active +@catcode`@`=@active +@markupsetuplqdefault +@markupsetuprqdefault + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: + +@c vim:sw=2: + +@ignore + arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 +@end ignore diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 0000000..5d0c32b --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,4 @@ +@set UPDATED 28 December 2015 +@set UPDATED-MONTH December 2015 +@set EDITION 4.6.0 +@set VERSION 4.6.0 diff --git a/doc/versionmaint.texi b/doc/versionmaint.texi new file mode 100644 index 0000000..5d0c32b --- /dev/null +++ b/doc/versionmaint.texi @@ -0,0 +1,4 @@ +@set UPDATED 28 December 2015 +@set UPDATED-MONTH December 2015 +@set EDITION 4.6.0 +@set VERSION 4.6.0 |