summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/awk/Makefile.in286
-rw-r--r--contrib/awk/README_d/README.tests46
-rw-r--r--contrib/awk/aclocal.m4129
-rw-r--r--contrib/awk/alloca.c496
-rw-r--r--contrib/awk/awktab.c3983
-rw-r--r--contrib/awk/configh.in225
-rwxr-xr-xcontrib/awk/configure3685
-rw-r--r--contrib/awk/configure.in165
-rw-r--r--contrib/awk/doc/Makefile.in129
-rw-r--r--contrib/awk/doc/README.card19
-rw-r--r--contrib/awk/doc/ad.block49
-rw-r--r--contrib/awk/doc/awkcard.in1550
-rw-r--r--contrib/awk/doc/awkforai.txt150
-rw-r--r--contrib/awk/doc/cardfonts37
-rw-r--r--contrib/awk/doc/colors39
-rw-r--r--contrib/awk/doc/gawk.12657
-rw-r--r--contrib/awk/doc/igawk.173
-rw-r--r--contrib/awk/doc/macros211
-rw-r--r--contrib/awk/doc/no.colors31
-rw-r--r--contrib/awk/doc/setter.outline77
-rw-r--r--contrib/awk/doc/texinfo.tex5992
-rwxr-xr-xcontrib/awk/install-sh238
-rwxr-xr-xcontrib/awk/mkinstalldirs32
-rw-r--r--contrib/awk/protos.h128
-rw-r--r--contrib/awk/regex.c5744
-rw-r--r--contrib/awk/stamp-h.in1
-rw-r--r--contrib/awk/test/arynocls.awk95
-rw-r--r--contrib/awk/test/arynocls.in30
-rw-r--r--contrib/awk/test/arynocls.ok0
-rw-r--r--contrib/awk/test/arysubnm.awk1
-rw-r--r--contrib/awk/test/arysubnm.ok1
-rw-r--r--contrib/awk/test/fnamedat.awk1
-rw-r--r--contrib/awk/test/fnamedat.in1
-rw-r--r--contrib/awk/test/fnamedat.ok1
-rw-r--r--contrib/awk/test/fnparydl.awk31
-rw-r--r--contrib/awk/test/fnparydl.ok10
-rw-r--r--contrib/awk/test/funsmnam.awk6
-rw-r--r--contrib/awk/test/funsmnam.ok1
-rw-r--r--contrib/awk/test/getlnbuf.awk18
-rw-r--r--contrib/awk/test/getlnbuf.in1708
-rw-r--r--contrib/awk/test/getlnbuf.ok1708
-rw-r--r--contrib/awk/test/getnr2tb.awk111
-rw-r--r--contrib/awk/test/getnr2tb.in6
-rw-r--r--contrib/awk/test/getnr2tb.ok6
-rw-r--r--contrib/awk/test/getnr2tm.awk75
-rw-r--r--contrib/awk/test/getnr2tm.in1
-rw-r--r--contrib/awk/test/getnr2tm.ok1
-rw-r--r--contrib/awk/test/gtlnbufv.awk2
-rw-r--r--contrib/awk/test/igncdym.awk56
-rw-r--r--contrib/awk/test/igncdym.in2
-rw-r--r--contrib/awk/test/igncdym.ok4
-rw-r--r--contrib/awk/test/nasty.awk92
-rw-r--r--contrib/awk/test/nasty.ok2
-rw-r--r--contrib/awk/test/nlstrina.awk77
-rw-r--r--contrib/awk/test/nlstrina.ok3
-rw-r--r--contrib/awk/test/numindex.awk55
-rw-r--r--contrib/awk/test/numindex.in4
-rw-r--r--contrib/awk/test/numindex.ok1
-rw-r--r--contrib/awk/test/opasnidx.awk1
-rw-r--r--contrib/awk/test/opasnidx.ok1
-rw-r--r--contrib/awk/test/opasnslf.awk6
-rw-r--r--contrib/awk/test/opasnslf.ok3
-rw-r--r--contrib/awk/test/printf1.awk19
-rw-r--r--contrib/awk/test/printf1.ok7
-rw-r--r--contrib/awk/test/reg/Obsolete/exp.awk1
-rw-r--r--contrib/awk/test/reg/Obsolete/exp.good2
-rw-r--r--contrib/awk/test/reg/Obsolete/exp.in0
-rw-r--r--contrib/awk/test/reg/Obsolete/log.awk1
-rw-r--r--contrib/awk/test/reg/Obsolete/log.good4
-rw-r--r--contrib/awk/test/reg/Obsolete/log.in0
-rw-r--r--contrib/awk/test/strftime.awk15
-rw-r--r--contrib/awk/test/subslash.awk6
-rw-r--r--contrib/awk/test/subslash.ok1
-rw-r--r--contrib/awk/test/zeroflag.awk1
-rw-r--r--contrib/awk/test/zeroflag.ok1
-rw-r--r--contrib/nvi/catalog/uk_UA.KOI8-U317
-rw-r--r--contrib/nvi/catalog/uk_UA.KOI8-U.base307
-rw-r--r--contrib/nvi/catalog/uk_UA.KOI8-U.owner1
-rw-r--r--gnu/usr.bin/awk/config.h230
-rw-r--r--lib/libutil/login_crypt.c50
-rw-r--r--share/man/man4/mly.4256
-rw-r--r--sys/compat/linux/linux_file.c859
-rw-r--r--sys/compat/linux/linux_ipc.c447
-rw-r--r--sys/compat/linux/linux_stats.c377
-rw-r--r--sys/compat/linux/linux_util.c186
-rw-r--r--sys/dev/ed/if_ed98.h111
-rw-r--r--sys/dev/ed/if_ed_cbus.c1759
-rw-r--r--sys/dev/mly/mly_cam.c513
-rw-r--r--sys/dev/mly/mly_pci.c590
-rw-r--r--sys/dev/mly/mly_tables.h335
-rw-r--r--sys/dev/mly/mlyreg.h1270
-rw-r--r--sys/dev/mly/mlyvar.h423
-rw-r--r--sys/modules/mly/Makefile11
-rw-r--r--usr.bin/finger/finger.conf.582
-rw-r--r--usr.bin/finger/pathnames.h31
-rw-r--r--usr.sbin/pccard/pccardd/server.c187
96 files changed, 38693 insertions, 0 deletions
diff --git a/contrib/awk/Makefile.in b/contrib/awk/Makefile.in
new file mode 100644
index 000000000000..2b464168c739
--- /dev/null
+++ b/contrib/awk/Makefile.in
@@ -0,0 +1,286 @@
+# Makefile for GNU Awk.
+#
+# Copyright (C) 1986, 1988-2000 the Free Software Foundation, Inc.
+#
+# This file is part of GAWK, the GNU implementation of the
+# AWK Programming Language.
+#
+# GAWK 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 2 of the License, or
+# (at your option) any later version.
+#
+# GAWK 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+@SET_MAKE@
+
+MAKEINFO = makeinfo --no-split
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+YACC = @YACC@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+ALLOCA = @ALLOCA@
+
+LN = ln
+LN_S = @LN_S@
+
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+binprefix =
+manprefix =
+
+bindir = @bindir@
+libdir = @libdir@
+manexta = 1
+mandir = @mandir@/man$(manexta)
+manext = .$(manexta)
+infodir = @infodir@
+datadir = @datadir@/awk
+libexecdir = @libexecdir@/awk
+
+DEFPATH = ".:$(datadir)"
+
+SHELL = /bin/sh
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+COMPFLAGS = -DGAWK -I. -I$(srcdir) $(CPPFLAGS) @DEFS@ $(CFLAGS)
+
+# object files
+AWKOBJS = array.o builtin.o eval.o field.o gawkmisc.o io.o main.o \
+ missing.o msg.o node.o re.o version.o
+
+ALLOBJS = $(AWKOBJS) awktab.o
+
+# LIBOBJS
+# GNU and other stuff that gawk uses as library routines.
+LIBOBJS= getopt.o getopt1.o regex.o dfa.o random.o $(ALLOCA)
+
+# source and documentation files
+SRC = array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \
+ missing.c msg.c node.c re.c version.c
+
+ALLSRC= $(SRC) awktab.c
+
+AWKSRC= awk.h awk.y custom.h $(ALLSRC) patchlevel.h protos.h random.h
+
+LIBSRC = alloca.c dfa.c dfa.h regex.c regex.h getopt.h getopt.c getopt1.c random.c
+
+COPIES = missing/system.c missing/tzset.c \
+ missing/memcmp.c missing/memcpy.c missing/memset.c \
+ missing/strncasecmp.c missing/strchr.c \
+ missing/strerror.c missing/strtod.c \
+ missing/strftime.c missing/strftime.3
+
+DOCS= doc/gawk.1 doc/gawk.texi doc/texinfo.tex
+
+TEXFILES= doc/gawk.aux doc/gawk.cp doc/gawk.cps doc/gawk.fn doc/gawk.fns \
+ doc/gawk.ky doc/gawk.kys doc/gawk.pg doc/gawk.pgs doc/gawk.toc \
+ doc/gawk.tp doc/gawk.tps doc/gawk.vr doc/gawk.vrs
+
+MISC = NEWS COPYING FUTURES Makefile.in PROBLEMS README PORTS POSIX.STD \
+ configure configure.in acconfig.h configh.in ACKNOWLEDGMENT \
+ ChangeLog INSTALL LIMITATIONS install-sh mkinstalldirs aclocal.m4 \
+ stamp-h.in
+
+OTHERS= doc pc atari vms README_d posix awklib
+
+ALLDOC= doc/gawk.dvi $(TEXFILES) doc/gawk.info*
+
+MAKEFILEIN = Makefile.in awklib/Makefile.in doc/Makefile.in test/Makefile.in
+
+# Release of gawk. There can be no leading or trailing white space here!
+REL=3.0
+
+# clear out suffixes list
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+.c.o:
+ $(CC) -c $(COMPFLAGS) $<
+
+# rules to build gawk
+all: gawk awklib/all doc/all
+
+# stuff to make sure that configure has been run.
+$(srcdir)/configure: configure.in aclocal.m4
+ cd $(srcdir) && autoconf
+
+# autoheader might not change confh.in, so touch a stamp file
+$(srcdir)/configh.in: stamp-h.in
+$(srcdir)/stamp-h.in: configure.in aclocal.m4 acconfig.h
+ cd $(srcdir) && autoheader
+ date > $(srcdir)/stamp-h.in
+
+config.h: stamp-h
+stamp-h: configh.in config.status
+ $(SHELL) ./config.status
+
+Makefile: $(MAKEFILEIN) config.status
+ $(SHELL) ./config.status
+
+config.status: configure
+ $(SHELL) ./config.status --recheck
+
+# Note: if you need something at both compile time and link time, like -pg,
+# you will have to edit the Makefile manually to set LDFLAGS.
+gawk: $(ALLOBJS) $(LIBOBJS) $(REOBJS)
+ $(CC) -o gawk $(CFLAGS) $(LDFLAGS) $(ALLOBJS) $(LIBOBJS) $(REOBJS) $(LIBS)
+
+$(ALLOBJS): awk.h dfa.h regex.h config.h custom.h
+
+$(LIBOBJS): config.h custom.h
+
+# SunOS make's (at least) VPATH doesn't do subdirectories...
+# Solaris make doesn't allow $< in the actual rule
+gawkmisc.o: $(srcdir)/atari/gawkmisc.atr \
+ $(srcdir)/pc/gawkmisc.pc $(srcdir)/posix/gawkmisc.c \
+ $(srcdir)/vms/gawkmisc.vms
+ $(CC) -c $(COMPFLAGS) -DDEFPATH='$(DEFPATH)' $(srcdir)/gawkmisc.c
+
+getopt.o: getopt.h
+
+getopt1.o: getopt.h
+
+builtin.o: random.h
+
+main.o: patchlevel.h
+
+awktab.c: awk.y
+ $(YACC) -v $(srcdir)/awk.y && \
+ if test -f y.tab.c ; then mv y.tab.c ytab.c ; else true ; fi && \
+ sed '/^extern char .malloc(), .realloc();$$/d' ytab.c >awktab.c && \
+ rm ytab.c
+
+# VMS POSIX make won't apply the default .c.o rule to awktab.o for some reason
+awktab.o: awktab.c awk.h
+ $(CC) -c $(COMPFLAGS) $(srcdir)/awktab.c
+
+alloca.o: alloca.c
+
+install: gawk info installdirs
+ -rm -f $(bindir)/gawk
+ fullname=gawk-$(REL).`./gawk '{print $$3}' $(srcdir)/patchlevel.h` ; \
+ $(INSTALL_PROGRAM) gawk $(bindir)/$$fullname ; \
+ (cd $(bindir); $(LN) $$fullname gawk)
+ (cd $(bindir); \
+ if [ ! -f awk ]; \
+ then $(LN_S) gawk awk; \
+ fi; exit 0)
+ cd doc && $(MAKE) install
+ cd awklib && $(MAKE) install
+
+installdirs: mkinstalldirs
+ $(srcdir)/mkinstalldirs $(bindir) $(datadir) \
+ $(libdir) $(infodir) $(mandir) $(libexecdir)
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
+
+uninstall:
+ (cd $(bindir); \
+ if [ -f awk ] && cmp awk gawk > /dev/null; then rm -f awk; fi)
+ (fullname=gawk-$(REL).`gawk '{print $$3}' $(srcdir)/patchlevel.h` ; \
+ cd $(bindir); \
+ if cmp gawk $$fullname; then rm -f gawk; fi ; \
+ rm -f $(bindir)/$$fullname)
+ cd doc && $(MAKE) uninstall
+ cd awklib && $(MAKE) uninstall
+ -rmdir $(datadir) $(libexecdir)
+
+# auxiliary rules for release maintenance
+lint: $(ALLSRC)
+ lint -hcbax $(COMPFLAGS) $(ALLSRC)
+
+xref:
+ cxref -c $(COMPFLAGS) $(ALLSRC) | grep -v ' /' >xref
+
+mostlyclean:
+ : mostly clean does nothing for gawk
+ : use "make clean" to really clean things out
+
+clean:
+ rm -rf gawk *.o core */core y.output
+ cd doc && $(MAKE) clean
+ cd test && $(MAKE) clean
+ cd awklib && $(MAKE) clean
+
+local-distclean:
+ rm -f Makefile *.orig *.rej */*.orig */*.rej awk.output \
+ gmon.out make.out config.h config.status config.cache \
+ config.log stamp-h tags TAGS *~
+
+distclean: clean local-distclean
+ cd doc && $(MAKE) distclean
+ cd awklib && $(MAKE) distclean
+ cd test && $(MAKE) distclean
+
+maintainer-clean: clean local-distclean
+ @echo "This command is intended for maintainers to use; it"
+ @echo "deletes files that may require special tools to rebuild."
+ rm -f awktab.c
+ cd doc && $(MAKE) maintainer-clean
+ cd test && $(MAKE) maintainer-clean
+ cd awklib && $(MAKE) maintainer-clean
+
+clobber: maintainer-clean
+
+TAGS:
+ etags $(AWKSRC)
+
+tags:
+ ctags $(AWKSRC)
+
+dvi: $(srcdir)/doc/gawk.texi
+ cd doc && $(MAKE) dvi
+
+info: $(srcdir)/doc/gawk.texi
+ cd doc && $(MAKE) info
+
+doc/all:
+ cd doc && $(MAKE) all
+
+awklib/all: gawk
+ cd awklib && $(MAKE) CFLAGS="$(CFLAGS)" all
+
+dist: $(AWKSRC) $(LIBSRC) $(DOCS) $(MISC) $(COPIES) awklib/stamp-eg info distclean
+ -rm -rf gawk-$(REL)*
+ dir=gawk-$(REL).`gawk '{print $$3}' patchlevel.h` && \
+ mkdir $$dir && \
+ cp -pr $(AWKSRC) $(LIBSRC) $(MISC) $$dir && \
+ mkdir $$dir/missing && \
+ cp -p $(COPIES) $$dir/missing && \
+ for i in $(OTHERS); \
+ do \
+ cp -pr $$i $$dir ; \
+ done && \
+ cp -pr test $$dir && \
+ find $$dir -type d -exec chmod 777 {} ';' && \
+ find $$dir -print | doschk && \
+ tar -cf - $$dir | gzip > $$dir.tar.gz && \
+ rm -fr $$dir
+
+awklib/stamp-eg:
+ cd awklib ; $(MAKE) stamp-eg
+
+check: gawk
+ cd test; $(MAKE) -k
+
+test: check
+
diff --git a/contrib/awk/README_d/README.tests b/contrib/awk/README_d/README.tests
new file mode 100644
index 000000000000..1c969d754d4a
--- /dev/null
+++ b/contrib/awk/README_d/README.tests
@@ -0,0 +1,46 @@
+Date: Sat, 22 Apr 2000 06:07:06 -0600 (MDT)
+From: "Nelson H. F. Beebe" <beebe@math.utah.edu>
+To: arnold@gnu.org
+Cc: beebe@math.utah.edu, sysstaff@math.utah.edu, othmer@math.utah.edu
+Subject: gawk-3.0.4 and a GNU/Linux gotcha
+
+Yesterday, I was assisting a colleague install some software on his
+GNU/Linux machine for which uname -r reports 2.2.14.
+
+A (mis)feature of this system, which I've never encountered before,
+broke the build of one of my programs, and also of gawk-3.0.4.
+
+Namely, the kernel will not execute anything that resides in /tmp,
+though it will if the same script is in /usr/tmp!
+
+% cat /tmp/foo.sh
+#! /bin/sh
+echo hello
+
+ls -l /tmp/foo.sh
+-rwxr-xr-x 1 othmer math 22 Apr 21 10:34 /tmp/foo.sh*
+
+% /tmp/foo.sh
+bash: /tmp/foo.sh: Permission denied
+
+% cp /tmp/foo.sh /usr/tmp
+
+% /usr/tmp/foo.sh
+hello
+
+Thus, programs that do a temporary install in /tmp, as some of mine do
+in order to run the validation suite, will fail.
+
+gawk-3.0.4, and likely other gawk versions, hits this problem too. It
+fails because test/poundbang starts with
+
+#! /tmp/gawk -f
+
+I tracked down where it comes from:
+
+% grep /tmp /etc/fstab
+/dev/hda3 /tmp ext2 rw,nosuid,noexec,nouser,auto,async,nodev 1 1
+ !!!!!!
+
+Since this is done via a mount command, potentially ANY directory tree
+could be mounted with noexec.
diff --git a/contrib/awk/aclocal.m4 b/contrib/awk/aclocal.m4
new file mode 100644
index 000000000000..7ba39c39cdd6
--- /dev/null
+++ b/contrib/awk/aclocal.m4
@@ -0,0 +1,129 @@
+dnl
+dnl aclocal.m4 --- autoconf input file for gawk
+dnl
+dnl Copyright (C) 1995, 1996, 1998, 1999, 2000 the Free Software Foundation, Inc.
+dnl
+dnl This file is part of GAWK, the GNU implementation of the
+dnl AWK Progamming Language.
+dnl
+dnl GAWK is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl GAWK is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+dnl
+
+dnl gawk-specific macros for autoconf. one day hopefully part of autoconf
+
+AC_DEFUN(GAWK_AC_C_STRINGIZE, [
+AC_REQUIRE([AC_PROG_CPP])
+AC_MSG_CHECKING([for ANSI stringizing capability])
+AC_CACHE_VAL(gawk_cv_c_stringize,
+AC_EGREP_CPP([#teststring],[
+#define x(y) #y
+
+char *s = x(teststring);
+], gawk_cv_c_stringize=no, gawk_cv_c_stringize=yes))
+if test "${gawk_cv_c_stringize}" = yes
+then
+ AC_DEFINE(HAVE_STRINGIZE)
+fi
+AC_MSG_RESULT([${gawk_cv_c_stringize}])
+])dnl
+
+
+dnl By default, many hosts won't let programs access large files;
+dnl one must use special compiler options to get large-file access to work.
+dnl For more details about this brain damage please see:
+dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
+
+dnl Written by Paul Eggert <eggert@twinsun.com>.
+
+dnl Internal subroutine of GAWK_AC_SYS_LARGEFILE.
+dnl GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES
+AC_DEFUN(GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES,
+ [[#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+ ]])
+
+dnl Internal subroutine of GAWK_AC_SYS_LARGEFILE.
+dnl GAWK_AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE, CACHE-VAR, COMMENT, INCLUDES, FUNCTION-BODY)
+AC_DEFUN(GAWK_AC_SYS_LARGEFILE_MACRO_VALUE,
+ [AC_CACHE_CHECK([for $1 value needed for large files], $3,
+ [$3=no
+ AC_TRY_COMPILE(GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES
+$5
+ ,
+ [$6],
+ ,
+ [AC_TRY_COMPILE([#define $1 $2]
+GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES
+$5
+ ,
+ [$6],
+ [$3=$2])])])
+ if test "[$]$3" != no; then
+ AC_DEFINE_UNQUOTED([$1], [$]$3, [$4])
+ fi])
+
+AC_DEFUN(GAWK_AC_SYS_LARGEFILE,
+ [AC_ARG_ENABLE(largefile,
+ [ --disable-largefile omit support for large files])
+ if test "$enable_largefile" != no; then
+
+ AC_CACHE_CHECK([for special C compiler options needed for large files],
+ gawk_cv_sys_largefile_CC,
+ [gawk_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ AC_TRY_COMPILE(GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES, , ,
+ [ac_save_CC="$CC"
+ CC="$CC -n32"
+ AC_TRY_COMPILE(GAWK_AC_SYS_LARGEFILE_TEST_INCLUDES, ,
+ gawk_cv_sys_largefile_CC=' -n32')
+ CC="$ac_save_CC"])
+ fi])
+ if test "$gawk_cv_sys_largefile_CC" != no; then
+ CC="$CC$gawk_cv_sys_largefile_CC"
+ fi
+
+ GAWK_AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64,
+ gawk_cv_sys_file_offset_bits,
+ [Number of bits in a file offset, on hosts where this is settable.])
+ GAWK_AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE, 1,
+ gawk_cv_sys_largefile_source,
+ [Define to make ftello visible on some hosts (e.g. HP-UX 10.20).],
+ [#include <stdio.h>], [return !ftello;])
+ GAWK_AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1,
+ gawk_cv_sys_large_files,
+ [Define for large files, on AIX-style hosts.])
+ GAWK_AC_SYS_LARGEFILE_MACRO_VALUE(_XOPEN_SOURCE, 500,
+ gawk_cv_sys_xopen_source,
+ [Define to make ftello visible on some hosts (e.g. glibc 2.1.3).],
+ [#include <stdio.h>], [return !ftello;])
+ fi
+ ])
+
+dnl Check for AIX and add _XOPEN_SOURCE_EXTENDED
+AC_DEFUN(GAWK_AC_AIX_TWEAK, [
+AC_MSG_CHECKING([for AIX compilation hacks])
+AC_CACHE_VAL(gawk_cv_aix_hack, [
+if test -d /lpp/bos
+then
+ CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED=1"
+ gawk_cv_aix_hack=yes
+else
+ gawk_cv_aix_hack=no
+fi
+])dnl
+AC_MSG_RESULT([${gawk_cv_aix_hack}])
+])dnl
diff --git a/contrib/awk/alloca.c b/contrib/awk/alloca.c
new file mode 100644
index 000000000000..6bbd9839ba8b
--- /dev/null
+++ b/contrib/awk/alloca.c
@@ -0,0 +1,496 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef malloc
+/* Different portions of Emacs need to call different versions of
+ malloc. The Emacs executable needs alloca to call xmalloc, because
+ ordinary malloc isn't protected from input signals. On the other
+ hand, the utilities in lib-src need alloca to call malloc; some of
+ them are very simple, and don't have an xmalloc routine.
+
+ Non-Emacs programs expect this to call xmalloc.
+
+ Callers below should use malloc. */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+#endif /* malloc */
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* Direction unknown. */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+#else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction ()
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+pointer
+alloca (size)
+ unsigned size;
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+#ifdef emacs
+ BLOCK_INPUT;
+#endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+#ifdef emacs
+ UNBLOCK_INPUT;
+#endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = malloc (sizeof (header) + size);
+ /* Address of header. */
+
+ ((header *) new)->h.next = last_alloca_header;
+ ((header *) new)->h.deep = depth;
+
+ last_alloca_header = (header *) new;
+
+ /* User storage begins just after header. */
+
+ return (pointer) ((char *) new + sizeof (header));
+ }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
diff --git a/contrib/awk/awktab.c b/contrib/awk/awktab.c
new file mode 100644
index 000000000000..23aa4fb381e9
--- /dev/null
+++ b/contrib/awk/awktab.c
@@ -0,0 +1,3983 @@
+
+/* A Bison parser, made from ./awk.y
+ by GNU Bison version 1.25
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define FUNC_CALL 258
+#define NAME 259
+#define REGEXP 260
+#define ERROR 261
+#define YNUMBER 262
+#define YSTRING 263
+#define RELOP 264
+#define APPEND_OP 265
+#define ASSIGNOP 266
+#define MATCHOP 267
+#define NEWLINE 268
+#define CONCAT_OP 269
+#define LEX_BEGIN 270
+#define LEX_END 271
+#define LEX_IF 272
+#define LEX_ELSE 273
+#define LEX_RETURN 274
+#define LEX_DELETE 275
+#define LEX_WHILE 276
+#define LEX_DO 277
+#define LEX_FOR 278
+#define LEX_BREAK 279
+#define LEX_CONTINUE 280
+#define LEX_PRINT 281
+#define LEX_PRINTF 282
+#define LEX_NEXT 283
+#define LEX_EXIT 284
+#define LEX_FUNCTION 285
+#define LEX_GETLINE 286
+#define LEX_NEXTFILE 287
+#define LEX_IN 288
+#define LEX_AND 289
+#define LEX_OR 290
+#define INCREMENT 291
+#define DECREMENT 292
+#define LEX_BUILTIN 293
+#define LEX_LENGTH 294
+#define UNARY 295
+
+#line 26 "./awk.y"
+
+#ifdef DEBUG
+#define YYDEBUG 12
+#endif
+
+#include "awk.h"
+
+#define CAN_FREE TRUE
+#define DONT_FREE FALSE
+
+#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
+static void yyerror(const char *m, ...) ;
+#else
+static void yyerror(); /* va_alist */
+#endif
+static char *get_src_buf P((void));
+static int yylex P((void));
+static NODE *node_common P((NODETYPE op));
+static NODE *snode P((NODE *subn, NODETYPE op, int sindex));
+static NODE *mkrangenode P((NODE *cpair));
+static NODE *make_for_loop P((NODE *init, NODE *cond, NODE *incr));
+static NODE *append_right P((NODE *list, NODE *new));
+static void func_install P((NODE *params, NODE *def));
+static void pop_var P((NODE *np, int freeit));
+static void pop_params P((NODE *params));
+static NODE *make_param P((char *name));
+static NODE *mk_rexp P((NODE *exp));
+static int dup_parms P((NODE *func));
+static void param_sanity P((NODE *arglist));
+static int isnoeffect P((NODETYPE t));
+static int isassignable P((NODE *n));
+
+enum defref { FUNC_DEFINE, FUNC_USE };
+static void func_use P((char *name, enum defref how));
+static void check_funcs P((void));
+
+static int want_assign; /* lexical scanning kludge */
+static int want_regexp; /* lexical scanning kludge */
+static int can_return; /* lexical scanning kludge */
+static int io_allowed = TRUE; /* lexical scanning kludge */
+static char *lexptr; /* pointer to next char during parsing */
+static char *lexend;
+static char *lexptr_begin; /* keep track of where we were for error msgs */
+static char *lexeme; /* beginning of lexeme for debugging */
+static char *thisline = NULL;
+#define YYDEBUG_LEXER_TEXT (lexeme)
+static int param_counter;
+static char *tokstart = NULL;
+static char *tok = NULL;
+static char *tokend;
+
+#define HASHSIZE 1021 /* this constant only used here */
+NODE *variables[HASHSIZE];
+
+extern char *source;
+extern int sourceline;
+extern struct src *srcfiles;
+extern int numfiles;
+extern int errcount;
+extern NODE *begin_block;
+extern NODE *end_block;
+
+#line 89 "./awk.y"
+typedef union {
+ long lval;
+ AWKNUM fval;
+ NODE *nodeval;
+ NODETYPE nodetypeval;
+ char *sval;
+ NODE *(*ptrval)();
+} YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 312
+#define YYFLAG -32768
+#define YYNTBASE 62
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 295 ? yytranslate[x] : 107)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 51, 2, 2, 54, 50, 2, 2, 55,
+ 56, 48, 46, 42, 47, 2, 49, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 41, 61, 43,
+ 2, 44, 40, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 57, 2, 58, 53, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 59, 45, 60, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 52
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 4, 6, 9, 11, 14, 15, 16, 20, 21,
+ 25, 28, 31, 34, 36, 39, 42, 44, 46, 48,
+ 50, 52, 53, 61, 66, 71, 73, 77, 78, 83,
+ 89, 94, 96, 99, 101, 104, 106, 109, 112, 115,
+ 119, 121, 128, 137, 146, 157, 167, 170, 173, 180,
+ 185, 189, 192, 196, 197, 202, 209, 213, 216, 218,
+ 220, 227, 237, 239, 242, 243, 245, 246, 249, 250,
+ 253, 256, 259, 260, 262, 264, 268, 270, 273, 277,
+ 278, 280, 281, 283, 285, 289, 291, 294, 298, 302,
+ 303, 305, 307, 311, 313, 316, 320, 324, 325, 330,
+ 336, 341, 345, 349, 353, 357, 359, 362, 366, 370,
+ 374, 378, 384, 386, 389, 390, 395, 399, 403, 407,
+ 409, 412, 416, 420, 424, 430, 432, 435, 437, 441,
+ 445, 449, 453, 457, 461, 464, 467, 470, 474, 479,
+ 484, 486, 491, 493, 496, 499, 501, 503, 506, 509,
+ 510, 512, 514, 519, 522, 525, 528, 530, 531, 533,
+ 535
+};
+
+static const short yyrhs[] = { 83,
+ 63, 83, 0, 64, 0, 63, 64, 0, 1, 0,
+ 63, 1, 0, 0, 0, 15, 65, 75, 0, 0,
+ 16, 66, 75, 0, 15, 77, 0, 16, 77, 0,
+ 72, 75, 0, 75, 0, 72, 77, 0, 69, 71,
+ 0, 4, 0, 3, 0, 68, 0, 38, 0, 39,
+ 0, 0, 30, 70, 67, 55, 86, 103, 83, 0,
+ 101, 76, 102, 104, 0, 101, 102, 104, 83, 0,
+ 93, 0, 93, 42, 93, 0, 0, 49, 74, 5,
+ 49, 0, 101, 76, 102, 104, 83, 0, 101, 102,
+ 104, 83, 0, 78, 0, 76, 78, 0, 1, 0,
+ 76, 1, 0, 82, 0, 105, 83, 0, 105, 83,
+ 0, 101, 102, 0, 101, 76, 102, 0, 81, 0,
+ 21, 55, 93, 103, 83, 78, 0, 22, 83, 78,
+ 21, 55, 93, 103, 83, 0, 23, 55, 4, 33,
+ 4, 103, 83, 78, 0, 23, 55, 88, 105, 93,
+ 105, 88, 103, 83, 78, 0, 23, 55, 88, 105,
+ 105, 88, 103, 83, 78, 0, 24, 77, 0, 25,
+ 77, 0, 80, 55, 92, 103, 85, 77, 0, 80,
+ 89, 85, 77, 0, 28, 88, 77, 0, 32, 77,
+ 0, 29, 88, 77, 0, 0, 19, 79, 88, 77,
+ 0, 20, 4, 57, 92, 58, 77, 0, 20, 4,
+ 77, 0, 93, 77, 0, 26, 0, 27, 0, 17,
+ 55, 93, 103, 83, 78, 0, 17, 55, 93, 103,
+ 83, 78, 18, 83, 78, 0, 13, 0, 82, 13,
+ 0, 0, 82, 0, 0, 43, 97, 0, 0, 44,
+ 93, 0, 10, 93, 0, 45, 93, 0, 0, 87,
+ 0, 4, 0, 87, 106, 4, 0, 1, 0, 87,
+ 1, 0, 87, 106, 1, 0, 0, 93, 0, 0,
+ 90, 0, 95, 0, 90, 106, 95, 0, 1, 0,
+ 90, 1, 0, 90, 1, 95, 0, 90, 106, 1,
+ 0, 0, 92, 0, 93, 0, 92, 106, 93, 0,
+ 1, 0, 92, 1, 0, 92, 1, 93, 0, 92,
+ 106, 1, 0, 0, 100, 11, 94, 93, 0, 55,
+ 92, 103, 33, 4, 0, 93, 45, 31, 99, 0,
+ 31, 99, 84, 0, 93, 34, 93, 0, 93, 35,
+ 93, 0, 93, 12, 93, 0, 73, 0, 51, 73,
+ 0, 93, 33, 4, 0, 93, 9, 93, 0, 93,
+ 43, 93, 0, 93, 44, 93, 0, 93, 40, 93,
+ 41, 93, 0, 97, 0, 93, 97, 0, 0, 100,
+ 11, 96, 95, 0, 95, 34, 95, 0, 95, 35,
+ 95, 0, 31, 99, 84, 0, 73, 0, 51, 73,
+ 0, 95, 12, 95, 0, 95, 33, 4, 0, 95,
+ 9, 95, 0, 95, 40, 95, 41, 95, 0, 97,
+ 0, 95, 97, 0, 98, 0, 97, 53, 97, 0,
+ 97, 48, 97, 0, 97, 49, 97, 0, 97, 50,
+ 97, 0, 97, 46, 97, 0, 97, 47, 97, 0,
+ 100, 36, 0, 100, 37, 0, 51, 97, 0, 55,
+ 93, 103, 0, 38, 55, 91, 103, 0, 39, 55,
+ 91, 103, 0, 39, 0, 3, 55, 91, 103, 0,
+ 100, 0, 36, 100, 0, 37, 100, 0, 7, 0,
+ 8, 0, 47, 97, 0, 46, 97, 0, 0, 100,
+ 0, 4, 0, 4, 57, 92, 58, 0, 54, 98,
+ 0, 59, 83, 0, 60, 83, 0, 56, 0, 0,
+ 105, 0, 61, 0, 42, 83, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 150, 158, 166, 182, 183, 184, 188, 190, 204, 206,
+ 220, 226, 232, 234, 236, 249, 258, 260, 262, 272,
+ 273, 277, 281, 296, 301, 310, 312, 321, 323, 341,
+ 343, 348, 354, 362, 364, 369, 370, 374, 376, 378,
+ 380, 382, 384, 386, 413, 417, 422, 425, 428, 430,
+ 450, 489, 508, 510, 515, 517, 519, 533, 538, 540,
+ 545, 550, 557, 559, 563, 564, 568, 570, 575, 577,
+ 579, 581, 586, 588, 593, 595, 597, 599, 601, 607,
+ 609, 614, 616, 621, 623, 629, 631, 633, 635, 640,
+ 642, 647, 649, 655, 657, 659, 661, 666, 669, 674,
+ 676, 681, 687, 689, 691, 697, 707, 715, 717, 723,
+ 725, 727, 729, 731, 736, 739, 740, 742, 744, 750,
+ 752, 754, 756, 758, 760, 762, 764, 769, 771, 773,
+ 775, 777, 779, 781, 783, 785, 790, 792, 794, 797,
+ 799, 807, 814, 815, 817, 819, 821, 824, 832, 843,
+ 845, 850, 852, 862, 867, 871, 875, 879, 880, 884,
+ 887
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = { "$","error","$undefined.","FUNC_CALL",
+"NAME","REGEXP","ERROR","YNUMBER","YSTRING","RELOP","APPEND_OP","ASSIGNOP","MATCHOP",
+"NEWLINE","CONCAT_OP","LEX_BEGIN","LEX_END","LEX_IF","LEX_ELSE","LEX_RETURN",
+"LEX_DELETE","LEX_WHILE","LEX_DO","LEX_FOR","LEX_BREAK","LEX_CONTINUE","LEX_PRINT",
+"LEX_PRINTF","LEX_NEXT","LEX_EXIT","LEX_FUNCTION","LEX_GETLINE","LEX_NEXTFILE",
+"LEX_IN","LEX_AND","LEX_OR","INCREMENT","DECREMENT","LEX_BUILTIN","LEX_LENGTH",
+"'?'","':'","','","'<'","'>'","'|'","'+'","'-'","'*'","'/'","'%'","'!'","UNARY",
+"'^'","'$'","'('","')'","'['","']'","'{'","'}'","';'","start","program","rule",
+"@1","@2","func_name","lex_builtin","function_prologue","@3","function_body",
+"pattern","regexp","@4","action","statements","statement_term","statement","@5",
+"print","if_statement","nls","opt_nls","input_redir","output_redir","opt_param_list",
+"param_list","opt_exp","opt_rexpression_list","rexpression_list","opt_expression_list",
+"expression_list","exp","@6","rexp","@7","simp_exp","non_post_simp_exp","opt_variable",
+"variable","l_brace","r_brace","r_paren","opt_semi","semi","comma", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 62, 63, 63, 63, 63, 63, 65, 64, 66, 64,
+ 64, 64, 64, 64, 64, 64, 67, 67, 67, 68,
+ 68, 70, 69, 71, 71, 72, 72, 74, 73, 75,
+ 75, 76, 76, 76, 76, 77, 77, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 79, 78, 78, 78, 78, 80, 80,
+ 81, 81, 82, 82, 83, 83, 84, 84, 85, 85,
+ 85, 85, 86, 86, 87, 87, 87, 87, 87, 88,
+ 88, 89, 89, 90, 90, 90, 90, 90, 90, 91,
+ 91, 92, 92, 92, 92, 92, 92, 94, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 96, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 99,
+ 99, 100, 100, 100, 101, 102, 103, 104, 104, 105,
+ 106
+};
+
+static const short yyr2[] = { 0,
+ 3, 1, 2, 1, 2, 0, 0, 3, 0, 3,
+ 2, 2, 2, 1, 2, 2, 1, 1, 1, 1,
+ 1, 0, 7, 4, 4, 1, 3, 0, 4, 5,
+ 4, 1, 2, 1, 2, 1, 2, 2, 2, 3,
+ 1, 6, 8, 8, 10, 9, 2, 2, 6, 4,
+ 3, 2, 3, 0, 4, 6, 3, 2, 1, 1,
+ 6, 9, 1, 2, 0, 1, 0, 2, 0, 2,
+ 2, 2, 0, 1, 1, 3, 1, 2, 3, 0,
+ 1, 0, 1, 1, 3, 1, 2, 3, 3, 0,
+ 1, 1, 3, 1, 2, 3, 3, 0, 4, 5,
+ 4, 3, 3, 3, 3, 1, 2, 3, 3, 3,
+ 3, 5, 1, 2, 0, 4, 3, 3, 3, 1,
+ 2, 3, 3, 3, 5, 1, 2, 1, 3, 3,
+ 3, 3, 3, 3, 2, 2, 2, 3, 4, 4,
+ 1, 4, 1, 2, 2, 1, 1, 2, 2, 0,
+ 1, 1, 4, 2, 2, 2, 1, 0, 1, 1,
+ 2
+};
+
+static const short yydefact[] = { 65,
+ 63, 66, 0, 64, 4, 0, 152, 146, 147, 7,
+ 9, 22, 150, 0, 0, 0, 141, 0, 0, 28,
+ 0, 0, 0, 65, 0, 2, 0, 0, 106, 14,
+ 26, 113, 128, 143, 0, 0, 0, 160, 0, 11,
+ 36, 65, 0, 12, 0, 67, 151, 144, 145, 0,
+ 0, 0, 0, 149, 143, 148, 0, 107, 137, 154,
+ 143, 94, 0, 92, 155, 5, 3, 1, 16, 0,
+ 13, 15, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 114, 0, 0, 0, 0, 0, 0, 98,
+ 135, 136, 34, 0, 54, 0, 0, 65, 0, 0,
+ 0, 59, 60, 80, 80, 0, 65, 0, 32, 0,
+ 41, 0, 0, 158, 65, 0, 0, 92, 0, 8,
+ 37, 10, 18, 17, 20, 21, 0, 19, 0, 102,
+ 0, 0, 0, 0, 95, 65, 157, 0, 0, 138,
+ 0, 158, 109, 105, 108, 103, 104, 0, 27, 110,
+ 111, 150, 133, 134, 130, 131, 132, 129, 0, 0,
+ 80, 0, 0, 0, 80, 47, 48, 0, 81, 0,
+ 52, 156, 35, 33, 158, 86, 150, 0, 0, 120,
+ 69, 0, 84, 126, 143, 58, 0, 39, 65, 159,
+ 38, 142, 153, 0, 68, 139, 140, 29, 96, 161,
+ 0, 97, 93, 158, 65, 0, 101, 99, 0, 0,
+ 0, 57, 0, 0, 152, 0, 51, 53, 65, 67,
+ 121, 0, 0, 0, 0, 0, 87, 0, 0, 0,
+ 0, 0, 0, 0, 127, 115, 40, 31, 77, 75,
+ 0, 0, 100, 24, 25, 112, 65, 55, 0, 65,
+ 0, 0, 0, 30, 119, 69, 71, 70, 72, 50,
+ 88, 89, 85, 124, 122, 123, 117, 118, 0, 0,
+ 65, 78, 0, 0, 0, 0, 0, 0, 0, 80,
+ 0, 0, 116, 23, 79, 76, 61, 56, 42, 0,
+ 65, 80, 0, 49, 125, 65, 65, 0, 0, 65,
+ 0, 43, 44, 65, 0, 62, 0, 46, 45, 0,
+ 0, 0
+};
+
+static const short yydefgoto[] = { 310,
+ 25, 26, 39, 43, 127, 128, 27, 45, 69, 28,
+ 29, 57, 30, 108, 40, 109, 161, 110, 111, 2,
+ 3, 130, 226, 241, 242, 168, 181, 182, 116, 117,
+ 112, 159, 183, 270, 32, 33, 46, 34, 113, 114,
+ 140, 189, 42, 139
+};
+
+static const short yypact[] = { -6,
+-32768, 0, 875,-32768,-32768, -40, -38,-32768,-32768, -7,
+ -7,-32768, 10, 10, 10, -31, -26, 1735, 1735,-32768,
+ 1715, 1735, 1131, -6, 932,-32768, -24, 72,-32768,-32768,
+ 1304, 205,-32768, 5, 709, 1110, 1131,-32768, -24,-32768,
+ 0, -6, -24,-32768, 85, 3,-32768,-32768,-32768, 1110,
+ 1110, 1735, 1620, 8, 106, 8, 81,-32768, 8,-32768,
+-32768,-32768, 37, 1250,-32768,-32768,-32768,-32768,-32768, 709,
+-32768,-32768, 1620, 1620, 90, 1620, 1620, 1620, 1620, 1620,
+ 1620, 65, 205, 1735, 1735, 1735, 1735, 1735, 1735,-32768,
+-32768,-32768,-32768, 50,-32768, 111, 70, -6, 93, -7,
+ -7,-32768,-32768, 1620, 1620, -7, -6, 758,-32768, 819,
+-32768, 1040, 709, 100, -6, 99, 55, 1402, 9,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768, 109,-32768, 1735,-32768,
+ 99, 99, 1250, 119, 1620, -6,-32768, 133, 1180,-32768,
+ 758, 100, 1327, 794,-32768, 1515, 1451, 1353, 1402, 1327,
+ 1327, 10, 125, 125, 8, 8, 8, 8, 1620, 1620,
+ 1620, 42, 1620, 981, 1657,-32768,-32768, -7, 1402, -7,
+-32768,-32768,-32768,-32768, 100,-32768, 10, 1715, 1131,-32768,
+ 96, 39, 1538, 205, 117,-32768, 758,-32768, -6,-32768,
+-32768,-32768,-32768, 7, 205,-32768,-32768,-32768, 1402,-32768,
+ 166,-32768, 1402, 100, -6, 1620,-32768, 1402, 1250, -7,
+ 1131,-32768, 1250, 151, -12, 100,-32768,-32768, -6, 3,
+-32768, 37, 1620, 1620, 1620, -7, 1678, 1201, 1678, 1678,
+ 181, 1678, 1678, 1678, 205,-32768,-32768,-32768,-32768,-32768,
+ 99, 56,-32768,-32768,-32768, 1402, -6,-32768, 11, -6,
+ 131, 183, 1061,-32768,-32768, 96, 1402, 1402, 1402,-32768,
+ 1538,-32768, 1538, 635, 83,-32768, 1599, 1579, 1474, 1678,
+ -6,-32768, 103, 981, -7, 981, 1620, 99, 623, 1620,
+ -7, 1678, 1538,-32768,-32768,-32768, 170,-32768,-32768, 1250,
+ -6, 1620, 99,-32768, 1538, -6, -6, 981, 99, -6,
+ 981,-32768,-32768, -6, 981,-32768, 981,-32768,-32768, 190,
+ 191,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768, 167,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 211,-32768, 107, -53, 315, -105,-32768,-32768,-32768, 199,
+ 97, -22, -62,-32768,-32768, -103,-32768,-32768, 94, -14,
+ -3,-32768, -202,-32768, 318, 177, -134, 95, 124, -69,
+ 407, -138, 420, -177
+};
+
+
+#define YYLAST 1790
+
+
+static const short yytable[] = { 31,
+ 142, 170, 174, 205, 228, 1, 1, 239, 63, 135,
+ 240, 135, 4, 7, 36, 90, 141, 207, 37, 64,
+ 252, 31, 119, 50, 261, 263, 264, 265, 51, 267,
+ 268, 269, 118, 118, 24, 174, 219, 135, 175, 227,
+ 91, 92, 220, 188, 37, 129, 118, 118, -83, 133,
+ 136, -83, 136, 38, 1, 135, 272, 210, 214, 187,
+ 89, 216, -73, 22, 273, 244, 193, 283, 275, 143,
+ 144, 204, 146, 147, 148, 149, 150, 151, 136, 295,
+ 136, 174, -83, -83, 1, 134, 7, 123, 124, 8,
+ 9, 229, 137, 145,-32768, 152, 136, 136, 211, -83,
+ 169, 169, 38, 285, 160, 223, 286, 47, 48, 49,
+ -91, -74, 55, 55, 162, 55, 61, 237, 14, 15,
+ 65, 68, 125, 126, 163, 55, 35, 236, 18, 19,
+ 24, 199, 38, 52, 71, 203, 22, 53, 121, 224,
+ 225, 91, 92, 131, 132, 120, 55, 165, 35, 122,
+ 70, 35, 91, 92, 137, 208, 209, 169, 55, 213,
+ 38, 169, 35, 194, 222, 201, 35, 198, 287, 243,
+ 289, 251, 86, 87, 88, 64, 293, 89, 55, 55,
+ 55, 55, 55, 55, 266, 277, 278, 296, 299, 311,
+ 312, 67, 303, 281, 164, 306, 249, 255, 60, 308,
+ 0, 309, 246, 172, 185, 0, 55, 118, 41, 41,
+ 0, 191, 55, 0, 0, 0, 0, 0, 0, 257,
+ 258, 259, 0, 55, 0, 0, 41, 55, 0, 0,
+ 0, 58, 200, 0, 0, 0, 0, 55, 55, 0,
+ 55, 55, 55, 55, 55, 55, 47, 0, 0, 279,
+ 84, 85, 86, 87, 88, 0, 0, 89, 0, 0,
+ 0, 0, 0, 55, 0, 0, 0, 0, 0, 0,
+ 0, 47, 55, 290, 0, 0, 169, 55, 0, 0,
+ 0, 0, 0, 0, 0, 238, 0, 0, 169, 0,
+ 0, 0, 0, 55, 0, 0, 0, 55, 41, 41,
+ 0, 245, 55, 55, 41, 0, 0, 55, 0, 0,
+ 41, 0, 0, 0, 0, 254, 0, 0, 0, 0,
+ 180, 185, 185, 185, 185, 44, 185, 185, 185, 0,
+ 0, 0, 0, 0, 0, 54, 56, 0, 59, 0,
+ 55, 0, 72, 274, 0, 0, 276, 0, 83, 0,
+ 0, 55, 55, 55, 0, 55, 0, 55, 55, 55,
+ 41, 55, 55, 55, 185, 0, 41, 284, 41, 59,
+ 0, 0, 0, 55, 0, 0, 185, 55, 0, 0,
+ 0, 83, 0, 0, 55, 0, 0, 298, 221, 55,
+ 0, 0, 301, 302, 0, 0, 305, 0, 0, 0,
+ 307, 153, 154, 155, 156, 157, 158, 0, 41, 0,
+ 0, 0, 0, 0, 166, 167, 0, 0, 0, 0,
+ 171, 0, 0, 0, 41, 0, 186, 184, 0, 83,
+ 0, 0, 0, 0, 0, 83, 0, 180, 180, 180,
+ 180, 0, 180, 180, 180, 0, 195, 0, 0, 0,
+ 83, 0, 0, 0, 115, 0, 0, 0, 0, 0,
+ 83, 83, 0, 83, 83, 83, 83, 83, 83, 138,
+ 0, 0, 0, 41, 0, 0, 212, 0, 0, 41,
+ 180, 0, 217, 0, 218, 0, 83, 0, 0, 115,
+ 0, 0, 180, 0, 0, 59, 0, 0, 0, 0,
+ 235, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 83, 0, 0, 0,
+ 83, 0, 192, 0, 248, 83, 83, 115, 0, 0,
+ 83, 0, 115, 190, 0, 0, 0, 196, 197, 0,
+ 260, 0, 0, 0, 184, 184, 184, 184, 0, 184,
+ 184, 184, 0, 0, 0, 0, 0, 0, 0, 0,
+ 115, 190, 0, 83, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 83, 83, 0, 235, 0,
+ 235, 235, 235, 115, 235, 235, 235, 184, 0, 288,
+ 0, 0, 0, 0, 190, 294, 83, 0, 0, 184,
+ 235, 0, 0, 0, 0, 0, 115, 83, 0, 0,
+ 0, 0, 235, 0, 0, 247, 0, 0, 0, 250,
+ 0, 0, 0, 190, 0, 6, 7, 0, 256, 8,
+ 9, 73, 0, 0, 74, 253, 0, 0, 7, 0,
+ 0, 8, 9,-32768, 0, 0, 0, 271, 0, 0,
+ 0, 0, 0, 0, 0, 75, 76, 77, 14, 15,
+ 16, 17, 78, 0, 0, 80, 81, 82, 18, 19,
+ 14, 15, 280, 52, 0, 0, 22, 53, 0, 0,
+ 18, 19, 0, 38, 291, 52, 0, 0, 22, 53,
+ 0, 0, 0, 115, 0, 115, 297, 0, 292, 300,
+ 0, 0, 0, 0, 0, 304, 0, 0, 0, 93,
+ 0, 6, 7, 0, 0, 8, 9, 115, 0, 0,
+ 115, 0, 0, 0, 115, 94, 115, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 0, 13,
+ 106, 0, 0, 0, 14, 15, 16, 17, 0, 0,
+ 0, 0, 0, 0, 18, 19, 0, 20, 173, 21,
+ 6, 7, 22, 23, 8, 9, 0, 24, 107, 38,
+ 0, 0, 0, 0, 94, 0, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 0, 13, 106,
+ 0, 0, 0, 14, 15, 16, 17, 7, 0, 0,
+ 8, 9, 73, 18, 19,-32768, 20, 0, 21, 0,
+ 0, 22, 23, 0, 0, 0, 24, 107, 38, 176,
+ 0, 6, 7, 0, 0, 8, 9, 0, -82, 14,
+ 15, -82, 0, 0, 0, 0, 80, 81, 82, 18,
+ 19, 0, 0, 0, 52, 0, 0, 22, 53, 177,
+ 0, 0, 0, 0, 14, 15, 16, 17, 0, 0,
+ 0, 0, -82, -82, 18, 19, 0, 20, 0, 178,
+ 0, 0, 22, 179, -6, 5, 0, 6, 7, -82,
+ 0, 8, 9, 0, 0, 0, 0, -6, 0, 10,
+ 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 12, 13, 0, 0, 0, 0,
+ 14, 15, 16, 17, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 20, 0, 21, 0, 0, 22, 23,
+ 0, -65, 66, 24, 6, 7, 0, 0, 8, 9,
+ 0, 0, 0, 0, 1, 0, 10, 11, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 12, 13, 0, 0, 0, 0, 14, 15, 16,
+ 17, 0, 0, 0, 0, 0, 0, 18, 19, 0,
+ 20, 0, 21, 6, 7, 22, 23, 8, 9, 0,
+ 24, 0, 0, 0, 0, 0, 0, 94, 0, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 0, 13, 106, 0, 0, 0, 14, 15, 16, 17,
+ 0, 0, 0, 0, 0, 0, 18, 19, 0, 20,
+ 0, 21, 0, 0, 22, 23, 0, 0, 0, 24,
+ 0, 38, 6, 7, 0, 0, 8, 9, 73, 0,
+ 0, 74, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 7, 0, 0, 8, 9, 0,
+ 0, 0, 75, 76, 77, 14, 15, 16, 17, 78,
+ 0, 0, 80, 81, 82, 18, 19, 0, 0, 0,
+ 52, 13, 0, 22, 53, 0, 14, 15, 16, 17,
+ 38, 0, 0, 0, 0, 0, 18, 19, 0, 20,
+ 62, 21, 6, 7, 22, 23, 8, 9, 0, 0,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 62, 0, 6, 7, 0, 0, 8, 9, 0,
+ 13, 0, 0, 0, 0, 14, 15, 16, 17, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 13, 0, 22, 23, -90, 14, 15, 16, 17,
+ 0, 0, 0, 0, 0, 0, 18, 19, 0, 20,
+ 202, 21, 6, 7, 22, 23, 8, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 262, 0, 6, 7, 0, 0, 8, 9, 0,
+ 13, 0, 0, 0, 0, 14, 15, 16, 17, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 177, 0, 22, 23, 0, 14, 15, 16, 17,
+ 0, 0, 0, 0, 0, 0, 18, 19, 0, 20,
+ 0, 178, 6, 7, 22, 53, 8, 9, 73, 0,
+ 0, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 75, 76, 77, 14, 15, 16, 17, 78,
+ 0, 0, 80, 81, 82, 18, 19, 0, 0, 0,
+ 52, 0, 0, 22, 53, 137, 6, 7, 0, 0,
+ 8, 9, 73, 0, 0, 74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 7, 0, 0, 8, 9,-32768, 75, 76, 77, 14,
+ 15, 16, 17, 78, 0, 79, 80, 81, 82, 18,
+ 19, 0, 0, 0, 52, 6, 7, 22, 53, 8,
+ 9, 73, 14, 15, 74, 0, 0, 0, 0,-32768,
+-32768,-32768, 18, 19, 0, 0, 0, 52, 0, 0,
+ 22, 53, 0, 0, 0, 75, 76, 77, 14, 15,
+ 16, 17, 78, 206, 0, 80, 81, 82, 18, 19,
+ 0, 0, 0, 52, 6, 7, 22, 53, 8, 9,
+ 73, 0, 0, 74, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 75, 76, 77, 14, 15, 16,
+ 17, 78, 0, 0, 80, 81, 82, 18, 19, 0,
+ 0, 0, 52, 6, 7, 22, 53, 8, 9, 73,
+ 0, 0, 74, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 6, 7, 0, 0,
+ 8, 9, 229, 75, 76, 230, 14, 15, 16, 17,
+ 0, 0, 0, 80, 81, 82, 18, 19, 0, 0,
+ 0, 52, 0, 0, 22, 53, 231, 232, 233, 14,
+ 15, 16, 17, 234, 282, 0, 0, 6, 7, 18,
+ 19, 8, 9, 73, 52, 0, 74, 22, 53, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 7, 0, 0, 8, 9, 229, 75, 0, 230,
+ 14, 15, 16, 17, 0, 0, 0, 80, 81, 82,
+ 18, 19, 0, 0, 0, 52, 0, 0, 22, 53,
+ 231, 232, 233, 14, 15, 16, 17, 234, 0, 0,
+ 0, 6, 7, 18, 19, 8, 9, 229, 52, 0,
+ 230, 22, 53, 0, 0, 0, 0, 0, 0, 0,
+ 0, 6, 7, 0, 0, 8, 9, 229, 0, 0,
+ 230, 231, 232, 0, 14, 15, 16, 17, 0, 0,
+ 0, 0, 6, 7, 18, 19, 8, 9, 0, 52,
+ 0, 231, 22, 53, 14, 15, 16, 17, 0, 0,
+ 0, 0, 0, 0, 18, 19, 0, 0, 0, 52,
+ 13, 0, 22, 53, 0, 14, 15, 16, 17, 6,
+ 215, 0, 0, 8, 9, 18, 19, 0, 20, 0,
+ 21, 0, 0, 22, 23, 0, 0, 0, 0, 0,
+ 6, 7, 0, 0, 8, 9, 0, 13, 0, 0,
+ 0, 0, 14, 15, 16, 17, 0, 0, 0, 0,
+ 0, 0, 18, 19, 0, 20, 0, 21, 177, 0,
+ 22, 23, 0, 14, 15, 16, 17, 6, 7, 0,
+ 0, 8, 9, 18, 19, 0, 20, 0, 178, 0,
+ 0, 22, 53, 0, 0, 0, 0, 6, 7, 0,
+ 0, 8, 9, 0, 0, 0, 0, 0, 0, 0,
+ 14, 15, 16, 17, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 20, 0, 52, 0, 0, 22, 53,
+ 14, 15, 16, 17, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 0, 0, 52, 0, 0, 22, 53
+};
+
+static const short yycheck[] = { 3,
+ 70, 105, 108, 142, 182, 13, 13, 1, 23, 1,
+ 4, 1, 13, 4, 55, 11, 70, 152, 57, 23,
+ 33, 25, 37, 55, 227, 228, 229, 230, 55, 232,
+ 233, 234, 36, 37, 59, 141, 175, 1, 108, 1,
+ 36, 37, 177, 113, 57, 43, 50, 51, 10, 53,
+ 42, 13, 42, 61, 13, 1, 1, 161, 164, 113,
+ 53, 165, 56, 54, 242, 204, 58, 270, 58, 73,
+ 74, 141, 76, 77, 78, 79, 80, 81, 42, 282,
+ 42, 187, 44, 45, 13, 5, 4, 3, 4, 7,
+ 8, 9, 56, 4, 12, 31, 42, 42, 57, 61,
+ 104, 105, 61, 1, 55, 10, 4, 13, 14, 15,
+ 56, 56, 18, 19, 4, 21, 22, 187, 36, 37,
+ 24, 25, 38, 39, 55, 31, 3, 11, 46, 47,
+ 59, 135, 61, 51, 28, 139, 54, 55, 42, 44,
+ 45, 36, 37, 50, 51, 39, 52, 55, 25, 43,
+ 27, 28, 36, 37, 56, 159, 160, 161, 64, 163,
+ 61, 165, 39, 55, 179, 33, 43, 49, 274, 4,
+ 276, 21, 48, 49, 50, 179, 280, 53, 84, 85,
+ 86, 87, 88, 89, 4, 55, 4, 18, 292, 0,
+ 0, 25, 298, 256, 98, 301, 211, 220, 22, 305,
+ -1, 307, 206, 107, 110, -1, 112, 211, 10, 11,
+ -1, 115, 118, -1, -1, -1, -1, -1, -1, 223,
+ 224, 225, -1, 129, -1, -1, 28, 133, -1, -1,
+ -1, 21, 136, -1, -1, -1, -1, 143, 144, -1,
+ 146, 147, 148, 149, 150, 151, 152, -1, -1, 253,
+ 46, 47, 48, 49, 50, -1, -1, 53, -1, -1,
+ -1, -1, -1, 169, -1, -1, -1, -1, -1, -1,
+ -1, 177, 178, 277, -1, -1, 280, 183, -1, -1,
+ -1, -1, -1, -1, -1, 189, -1, -1, 292, -1,
+ -1, -1, -1, 199, -1, -1, -1, 203, 100, 101,
+ -1, 205, 208, 209, 106, -1, -1, 213, -1, -1,
+ 112, -1, -1, -1, -1, 219, -1, -1, -1, -1,
+ 110, 227, 228, 229, 230, 11, 232, 233, 234, -1,
+ -1, -1, -1, -1, -1, 18, 19, -1, 21, -1,
+ 246, -1, 28, 247, -1, -1, 250, -1, 31, -1,
+ -1, 257, 258, 259, -1, 261, -1, 263, 264, 265,
+ 162, 267, 268, 269, 270, -1, 168, 271, 170, 52,
+ -1, -1, -1, 279, -1, -1, 282, 283, -1, -1,
+ -1, 64, -1, -1, 290, -1, -1, 291, 178, 295,
+ -1, -1, 296, 297, -1, -1, 300, -1, -1, -1,
+ 304, 84, 85, 86, 87, 88, 89, -1, 210, -1,
+ -1, -1, -1, -1, 100, 101, -1, -1, -1, -1,
+ 106, -1, -1, -1, 226, -1, 112, 110, -1, 112,
+ -1, -1, -1, -1, -1, 118, -1, 227, 228, 229,
+ 230, -1, 232, 233, 234, -1, 129, -1, -1, -1,
+ 133, -1, -1, -1, 35, -1, -1, -1, -1, -1,
+ 143, 144, -1, 146, 147, 148, 149, 150, 151, 63,
+ -1, -1, -1, 275, -1, -1, 162, -1, -1, 281,
+ 270, -1, 168, -1, 170, -1, 169, -1, -1, 70,
+ -1, -1, 282, -1, -1, 178, -1, -1, -1, -1,
+ 183, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 199, -1, -1, -1,
+ 203, -1, 116, -1, 210, 208, 209, 108, -1, -1,
+ 213, -1, 113, 114, -1, -1, -1, 131, 132, -1,
+ 226, -1, -1, -1, 227, 228, 229, 230, -1, 232,
+ 233, 234, -1, -1, -1, -1, -1, -1, -1, -1,
+ 141, 142, -1, 246, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 257, 258, 259, -1, 261, -1,
+ 263, 264, 265, 164, 267, 268, 269, 270, -1, 275,
+ -1, -1, -1, -1, 175, 281, 279, -1, -1, 282,
+ 283, -1, -1, -1, -1, -1, 187, 290, -1, -1,
+ -1, -1, 295, -1, -1, 209, -1, -1, -1, 213,
+ -1, -1, -1, 204, -1, 3, 4, -1, 222, 7,
+ 8, 9, -1, -1, 12, 216, -1, -1, 4, -1,
+ -1, 7, 8, 9, -1, -1, -1, 241, -1, -1,
+ -1, -1, -1, -1, -1, 33, 34, 35, 36, 37,
+ 38, 39, 40, -1, -1, 43, 44, 45, 46, 47,
+ 36, 37, 253, 51, -1, -1, 54, 55, -1, -1,
+ 46, 47, -1, 61, 278, 51, -1, -1, 54, 55,
+ -1, -1, -1, 274, -1, 276, 290, -1, 279, 293,
+ -1, -1, -1, -1, -1, 299, -1, -1, -1, 1,
+ -1, 3, 4, -1, -1, 7, 8, 298, -1, -1,
+ 301, -1, -1, -1, 305, 17, 307, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, -1, 31,
+ 32, -1, -1, -1, 36, 37, 38, 39, -1, -1,
+ -1, -1, -1, -1, 46, 47, -1, 49, 1, 51,
+ 3, 4, 54, 55, 7, 8, -1, 59, 60, 61,
+ -1, -1, -1, -1, 17, -1, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, -1, 31, 32,
+ -1, -1, -1, 36, 37, 38, 39, 4, -1, -1,
+ 7, 8, 9, 46, 47, 12, 49, -1, 51, -1,
+ -1, 54, 55, -1, -1, -1, 59, 60, 61, 1,
+ -1, 3, 4, -1, -1, 7, 8, -1, 10, 36,
+ 37, 13, -1, -1, -1, -1, 43, 44, 45, 46,
+ 47, -1, -1, -1, 51, -1, -1, 54, 55, 31,
+ -1, -1, -1, -1, 36, 37, 38, 39, -1, -1,
+ -1, -1, 44, 45, 46, 47, -1, 49, -1, 51,
+ -1, -1, 54, 55, 0, 1, -1, 3, 4, 61,
+ -1, 7, 8, -1, -1, -1, -1, 13, -1, 15,
+ 16, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 30, 31, -1, -1, -1, -1,
+ 36, 37, 38, 39, -1, -1, -1, -1, -1, -1,
+ 46, 47, -1, 49, -1, 51, -1, -1, 54, 55,
+ -1, 0, 1, 59, 3, 4, -1, -1, 7, 8,
+ -1, -1, -1, -1, 13, -1, 15, 16, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 30, 31, -1, -1, -1, -1, 36, 37, 38,
+ 39, -1, -1, -1, -1, -1, -1, 46, 47, -1,
+ 49, -1, 51, 3, 4, 54, 55, 7, 8, -1,
+ 59, -1, -1, -1, -1, -1, -1, 17, -1, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ -1, 31, 32, -1, -1, -1, 36, 37, 38, 39,
+ -1, -1, -1, -1, -1, -1, 46, 47, -1, 49,
+ -1, 51, -1, -1, 54, 55, -1, -1, -1, 59,
+ -1, 61, 3, 4, -1, -1, 7, 8, 9, -1,
+ -1, 12, 13, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3, 4, -1, -1, 7, 8, -1,
+ -1, -1, 33, 34, 35, 36, 37, 38, 39, 40,
+ -1, -1, 43, 44, 45, 46, 47, -1, -1, -1,
+ 51, 31, -1, 54, 55, -1, 36, 37, 38, 39,
+ 61, -1, -1, -1, -1, -1, 46, 47, -1, 49,
+ 1, 51, 3, 4, 54, 55, 7, 8, -1, -1,
+ -1, 61, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1, -1, 3, 4, -1, -1, 7, 8, -1,
+ 31, -1, -1, -1, -1, 36, 37, 38, 39, -1,
+ -1, -1, -1, -1, -1, 46, 47, -1, 49, -1,
+ 51, 31, -1, 54, 55, 56, 36, 37, 38, 39,
+ -1, -1, -1, -1, -1, -1, 46, 47, -1, 49,
+ 1, 51, 3, 4, 54, 55, 7, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1, -1, 3, 4, -1, -1, 7, 8, -1,
+ 31, -1, -1, -1, -1, 36, 37, 38, 39, -1,
+ -1, -1, -1, -1, -1, 46, 47, -1, 49, -1,
+ 51, 31, -1, 54, 55, -1, 36, 37, 38, 39,
+ -1, -1, -1, -1, -1, -1, 46, 47, -1, 49,
+ -1, 51, 3, 4, 54, 55, 7, 8, 9, -1,
+ -1, 12, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 33, 34, 35, 36, 37, 38, 39, 40,
+ -1, -1, 43, 44, 45, 46, 47, -1, -1, -1,
+ 51, -1, -1, 54, 55, 56, 3, 4, -1, -1,
+ 7, 8, 9, -1, -1, 12, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 4, -1, -1, 7, 8, 9, 33, 34, 35, 36,
+ 37, 38, 39, 40, -1, 42, 43, 44, 45, 46,
+ 47, -1, -1, -1, 51, 3, 4, 54, 55, 7,
+ 8, 9, 36, 37, 12, -1, -1, -1, -1, 43,
+ 44, 45, 46, 47, -1, -1, -1, 51, -1, -1,
+ 54, 55, -1, -1, -1, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, -1, 43, 44, 45, 46, 47,
+ -1, -1, -1, 51, 3, 4, 54, 55, 7, 8,
+ 9, -1, -1, 12, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 33, 34, 35, 36, 37, 38,
+ 39, 40, -1, -1, 43, 44, 45, 46, 47, -1,
+ -1, -1, 51, 3, 4, 54, 55, 7, 8, 9,
+ -1, -1, 12, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3, 4, -1, -1,
+ 7, 8, 9, 33, 34, 12, 36, 37, 38, 39,
+ -1, -1, -1, 43, 44, 45, 46, 47, -1, -1,
+ -1, 51, -1, -1, 54, 55, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, -1, -1, 3, 4, 46,
+ 47, 7, 8, 9, 51, -1, 12, 54, 55, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 3, 4, -1, -1, 7, 8, 9, 33, -1, 12,
+ 36, 37, 38, 39, -1, -1, -1, 43, 44, 45,
+ 46, 47, -1, -1, -1, 51, -1, -1, 54, 55,
+ 33, 34, 35, 36, 37, 38, 39, 40, -1, -1,
+ -1, 3, 4, 46, 47, 7, 8, 9, 51, -1,
+ 12, 54, 55, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3, 4, -1, -1, 7, 8, 9, -1, -1,
+ 12, 33, 34, -1, 36, 37, 38, 39, -1, -1,
+ -1, -1, 3, 4, 46, 47, 7, 8, -1, 51,
+ -1, 33, 54, 55, 36, 37, 38, 39, -1, -1,
+ -1, -1, -1, -1, 46, 47, -1, -1, -1, 51,
+ 31, -1, 54, 55, -1, 36, 37, 38, 39, 3,
+ 4, -1, -1, 7, 8, 46, 47, -1, 49, -1,
+ 51, -1, -1, 54, 55, -1, -1, -1, -1, -1,
+ 3, 4, -1, -1, 7, 8, -1, 31, -1, -1,
+ -1, -1, 36, 37, 38, 39, -1, -1, -1, -1,
+ -1, -1, 46, 47, -1, 49, -1, 51, 31, -1,
+ 54, 55, -1, 36, 37, 38, 39, 3, 4, -1,
+ -1, 7, 8, 46, 47, -1, 49, -1, 51, -1,
+ -1, 54, 55, -1, -1, -1, -1, 3, 4, -1,
+ -1, 7, 8, -1, -1, -1, -1, -1, -1, -1,
+ 36, 37, 38, 39, -1, -1, -1, -1, -1, -1,
+ 46, 47, -1, 49, -1, 51, -1, -1, 54, 55,
+ 36, 37, 38, 39, -1, -1, -1, -1, -1, -1,
+ 46, 47, -1, -1, -1, 51, -1, -1, 54, 55
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+#ifndef YYPARSE_RETURN_TYPE
+#define YYPARSE_RETURN_TYPE int
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+YYPARSE_RETURN_TYPE yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 196 "/usr/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+YYPARSE_RETURN_TYPE
+yyparse(YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 1:
+#line 151 "./awk.y"
+{
+ expression_value = yyvsp[-1].nodeval;
+ check_funcs();
+ ;
+ break;}
+case 2:
+#line 159 "./awk.y"
+{
+ if (yyvsp[0].nodeval != NULL)
+ yyval.nodeval = yyvsp[0].nodeval;
+ else
+ yyval.nodeval = NULL;
+ yyerrok;
+ ;
+ break;}
+case 3:
+#line 168 "./awk.y"
+{
+ if (yyvsp[0].nodeval == NULL)
+ yyval.nodeval = yyvsp[-1].nodeval;
+ else if (yyvsp[-1].nodeval == NULL)
+ yyval.nodeval = yyvsp[0].nodeval;
+ else {
+ if (yyvsp[-1].nodeval->type != Node_rule_list)
+ yyvsp[-1].nodeval = node(yyvsp[-1].nodeval, Node_rule_list,
+ (NODE*) NULL);
+ yyval.nodeval = append_right(yyvsp[-1].nodeval,
+ node(yyvsp[0].nodeval, Node_rule_list, (NODE *) NULL));
+ }
+ yyerrok;
+ ;
+ break;}
+case 4:
+#line 182 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 5:
+#line 183 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 6:
+#line 184 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 7:
+#line 188 "./awk.y"
+{ io_allowed = FALSE; ;
+ break;}
+case 8:
+#line 190 "./awk.y"
+{
+ if (begin_block != NULL) {
+ if (begin_block->type != Node_rule_list)
+ begin_block = node(begin_block, Node_rule_list,
+ (NODE *) NULL);
+ (void) append_right(begin_block, node(
+ node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval),
+ Node_rule_list, (NODE *) NULL) );
+ } else
+ begin_block = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval);
+ yyval.nodeval = NULL;
+ io_allowed = TRUE;
+ yyerrok;
+ ;
+ break;}
+case 9:
+#line 204 "./awk.y"
+{ io_allowed = FALSE; ;
+ break;}
+case 10:
+#line 206 "./awk.y"
+{
+ if (end_block != NULL) {
+ if (end_block->type != Node_rule_list)
+ end_block = node(end_block, Node_rule_list,
+ (NODE *) NULL);
+ (void) append_right (end_block, node(
+ node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval),
+ Node_rule_list, (NODE *) NULL));
+ } else
+ end_block = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval);
+ yyval.nodeval = NULL;
+ io_allowed = TRUE;
+ yyerrok;
+ ;
+ break;}
+case 11:
+#line 221 "./awk.y"
+{
+ warning("BEGIN blocks must have an action part");
+ errcount++;
+ yyerrok;
+ ;
+ break;}
+case 12:
+#line 227 "./awk.y"
+{
+ warning("END blocks must have an action part");
+ errcount++;
+ yyerrok;
+ ;
+ break;}
+case 13:
+#line 233 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_rule_node, yyvsp[0].nodeval); yyerrok; ;
+ break;}
+case 14:
+#line 235 "./awk.y"
+{ yyval.nodeval = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval); yyerrok; ;
+ break;}
+case 15:
+#line 237 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[-1].nodeval,
+ Node_rule_node,
+ node(node(node(make_number(0.0),
+ Node_field_spec,
+ (NODE *) NULL),
+ Node_expression_list,
+ (NODE *) NULL),
+ Node_K_print,
+ (NODE *) NULL));
+ yyerrok;
+ ;
+ break;}
+case 16:
+#line 250 "./awk.y"
+{
+ func_install(yyvsp[-1].nodeval, yyvsp[0].nodeval);
+ yyval.nodeval = NULL;
+ yyerrok;
+ ;
+ break;}
+case 17:
+#line 259 "./awk.y"
+{ yyval.sval = yyvsp[0].sval; ;
+ break;}
+case 18:
+#line 261 "./awk.y"
+{ yyval.sval = yyvsp[0].sval; ;
+ break;}
+case 19:
+#line 263 "./awk.y"
+{
+ yyerror("%s() is a built-in function, it cannot be redefined",
+ tokstart);
+ errcount++;
+ /* yyerrok; */
+ ;
+ break;}
+case 22:
+#line 278 "./awk.y"
+{
+ param_counter = 0;
+ ;
+ break;}
+case 23:
+#line 282 "./awk.y"
+{
+ NODE *t;
+
+ t = make_param(yyvsp[-4].sval);
+ t->flags |= FUNC;
+ yyval.nodeval = append_right(t, yyvsp[-2].nodeval);
+ can_return = TRUE;
+ /* check for duplicate parameter names */
+ if (dup_parms(yyval.nodeval))
+ errcount++;
+ ;
+ break;}
+case 24:
+#line 297 "./awk.y"
+{
+ yyval.nodeval = yyvsp[-2].nodeval;
+ can_return = FALSE;
+ ;
+ break;}
+case 25:
+#line 302 "./awk.y"
+{
+ yyval.nodeval = node((NODE *) NULL, Node_K_return, (NODE *) NULL);
+ can_return = FALSE;
+ ;
+ break;}
+case 26:
+#line 311 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 27:
+#line 313 "./awk.y"
+{ yyval.nodeval = mkrangenode(node(yyvsp[-2].nodeval, Node_cond_pair, yyvsp[0].nodeval)); ;
+ break;}
+case 28:
+#line 322 "./awk.y"
+{ ++want_regexp; ;
+ break;}
+case 29:
+#line 324 "./awk.y"
+{
+ NODE *n;
+ size_t len;
+
+ getnode(n);
+ n->type = Node_regex;
+ len = strlen(yyvsp[-1].sval);
+ n->re_exp = make_string(yyvsp[-1].sval, len);
+ n->re_reg = make_regexp(yyvsp[-1].sval, len, FALSE, TRUE);
+ n->re_text = NULL;
+ n->re_flags = CONST;
+ n->re_cnt = 1;
+ yyval.nodeval = n;
+ ;
+ break;}
+case 30:
+#line 342 "./awk.y"
+{ yyval.nodeval = yyvsp[-3].nodeval; ;
+ break;}
+case 31:
+#line 344 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 32:
+#line 349 "./awk.y"
+{
+ yyval.nodeval = yyvsp[0].nodeval;
+ if (do_lint && isnoeffect(yyval.nodeval->type))
+ warning("statement may have no effect");
+ ;
+ break;}
+case 33:
+#line 355 "./awk.y"
+{
+ if (yyvsp[-1].nodeval == NULL || yyvsp[-1].nodeval->type != Node_statement_list)
+ yyvsp[-1].nodeval = node(yyvsp[-1].nodeval, Node_statement_list, (NODE *) NULL);
+ yyval.nodeval = append_right(yyvsp[-1].nodeval,
+ node(yyvsp[0].nodeval, Node_statement_list, (NODE *) NULL));
+ yyerrok;
+ ;
+ break;}
+case 34:
+#line 363 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 35:
+#line 365 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 38:
+#line 375 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 39:
+#line 377 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 40:
+#line 379 "./awk.y"
+{ yyval.nodeval = yyvsp[-1].nodeval; ;
+ break;}
+case 41:
+#line 381 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 42:
+#line 383 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-3].nodeval, Node_K_while, yyvsp[0].nodeval); ;
+ break;}
+case 43:
+#line 385 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_K_do, yyvsp[-5].nodeval); ;
+ break;}
+case 44:
+#line 387 "./awk.y"
+{
+ /*
+ * Efficiency hack. Recognize the special case of
+ *
+ * for (iggy in foo)
+ * delete foo[iggy]
+ *
+ * and treat it as if it were
+ *
+ * delete foo
+ *
+ * Check that the body is a `delete a[i]' statement,
+ * and that both the loop var and array names match.
+ */
+ if (yyvsp[0].nodeval->type == Node_K_delete
+ && yyvsp[0].nodeval->rnode != NULL
+ && strcmp(yyvsp[-5].sval, yyvsp[0].nodeval->rnode->var_value->vname) == 0
+ && strcmp(yyvsp[-3].sval, yyvsp[0].nodeval->lnode->vname) == 0) {
+ yyvsp[0].nodeval->type = Node_K_delete_loop;
+ yyval.nodeval = yyvsp[0].nodeval;
+ } else {
+ yyval.nodeval = node(yyvsp[0].nodeval, Node_K_arrayfor,
+ make_for_loop(variable(yyvsp[-5].sval, CAN_FREE, Node_var),
+ (NODE *) NULL, variable(yyvsp[-3].sval, CAN_FREE, Node_var_array)));
+ }
+ ;
+ break;}
+case 45:
+#line 414 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[0].nodeval, Node_K_for, (NODE *) make_for_loop(yyvsp[-7].nodeval, yyvsp[-5].nodeval, yyvsp[-3].nodeval));
+ ;
+ break;}
+case 46:
+#line 418 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[0].nodeval, Node_K_for,
+ (NODE *) make_for_loop(yyvsp[-6].nodeval, (NODE *) NULL, yyvsp[-3].nodeval));
+ ;
+ break;}
+case 47:
+#line 424 "./awk.y"
+{ yyval.nodeval = node((NODE *) NULL, Node_K_break, (NODE *) NULL); ;
+ break;}
+case 48:
+#line 427 "./awk.y"
+{ yyval.nodeval = node((NODE *) NULL, Node_K_continue, (NODE *) NULL); ;
+ break;}
+case 49:
+#line 429 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-5].nodetypeval, yyvsp[-1].nodeval); ;
+ break;}
+case 50:
+#line 431 "./awk.y"
+{
+ if (yyvsp[-3].nodetypeval == Node_K_print && yyvsp[-2].nodeval == NULL) {
+ static int warned = FALSE;
+
+ yyvsp[-2].nodeval = node(node(make_number(0.0),
+ Node_field_spec,
+ (NODE *) NULL),
+ Node_expression_list,
+ (NODE *) NULL);
+
+ if (do_lint && ! io_allowed && ! warned) {
+ warned = TRUE;
+ warning(
+ "plain `print' in BEGIN or END rule should probably be `print \"\"'");
+ }
+ }
+
+ yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-3].nodetypeval, yyvsp[-1].nodeval);
+ ;
+ break;}
+case 51:
+#line 451 "./awk.y"
+{ NODETYPE type;
+
+ if (yyvsp[-1].nodeval) {
+ if (yyvsp[-1].nodeval == lookup("file")) {
+ static int warned = FALSE;
+
+ if (! warned) {
+ warned = TRUE;
+ warning("`next file' is obsolete; use `nextfile'");
+ }
+ if (do_lint)
+ warning("`next file' is a gawk extension");
+ if (do_traditional) {
+ /*
+ * can't use yyerror, since may have overshot
+ * the source line
+ */
+ errcount++;
+ error("`next file' is a gawk extension");
+ }
+ if (! io_allowed) {
+ /* same thing */
+ errcount++;
+ error("`next file' used in BEGIN or END action");
+ }
+ type = Node_K_nextfile;
+ } else {
+ errcount++;
+ error("illegal expression after `next'");
+ type = Node_K_next; /* sanity */
+ }
+ } else {
+ if (! io_allowed)
+ yyerror("`next' used in BEGIN or END action");
+ type = Node_K_next;
+ }
+ yyval.nodeval = node((NODE *) NULL, type, (NODE *) NULL);
+ ;
+ break;}
+case 52:
+#line 490 "./awk.y"
+{
+ if (do_lint)
+ warning("`nextfile' is a gawk extension");
+ if (do_traditional) {
+ /*
+ * can't use yyerror, since may have overshot
+ * the source line
+ */
+ errcount++;
+ error("`nextfile' is a gawk extension");
+ }
+ if (! io_allowed) {
+ /* same thing */
+ errcount++;
+ error("`nextfile' used in BEGIN or END action");
+ }
+ yyval.nodeval = node((NODE *) NULL, Node_K_nextfile, (NODE *) NULL);
+ ;
+ break;}
+case 53:
+#line 509 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_exit, (NODE *) NULL); ;
+ break;}
+case 54:
+#line 511 "./awk.y"
+{
+ if (! can_return)
+ yyerror("`return' used outside function context");
+ ;
+ break;}
+case 55:
+#line 516 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_return, (NODE *) NULL); ;
+ break;}
+case 56:
+#line 518 "./awk.y"
+{ yyval.nodeval = node(variable(yyvsp[-4].sval, CAN_FREE, Node_var_array), Node_K_delete, yyvsp[-2].nodeval); ;
+ break;}
+case 57:
+#line 520 "./awk.y"
+{
+ if (do_lint)
+ warning("`delete array' is a gawk extension");
+ if (do_traditional) {
+ /*
+ * can't use yyerror, since may have overshot
+ * the source line
+ */
+ errcount++;
+ error("`delete array' is a gawk extension");
+ }
+ yyval.nodeval = node(variable(yyvsp[-1].sval, CAN_FREE, Node_var_array), Node_K_delete, (NODE *) NULL);
+ ;
+ break;}
+case 58:
+#line 534 "./awk.y"
+{ yyval.nodeval = yyvsp[-1].nodeval; ;
+ break;}
+case 59:
+#line 539 "./awk.y"
+{ yyval.nodetypeval = yyvsp[0].nodetypeval; ;
+ break;}
+case 60:
+#line 541 "./awk.y"
+{ yyval.nodetypeval = yyvsp[0].nodetypeval; ;
+ break;}
+case 61:
+#line 546 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[-3].nodeval, Node_K_if,
+ node(yyvsp[0].nodeval, Node_if_branches, (NODE *) NULL));
+ ;
+ break;}
+case 62:
+#line 552 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-6].nodeval, Node_K_if,
+ node(yyvsp[-3].nodeval, Node_if_branches, yyvsp[0].nodeval)); ;
+ break;}
+case 63:
+#line 558 "./awk.y"
+{ want_assign = FALSE; ;
+ break;}
+case 67:
+#line 569 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 68:
+#line 571 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_input, (NODE *) NULL); ;
+ break;}
+case 69:
+#line 576 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 70:
+#line 578 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_output, (NODE *) NULL); ;
+ break;}
+case 71:
+#line 580 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_append, (NODE *) NULL); ;
+ break;}
+case 72:
+#line 582 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_pipe, (NODE *) NULL); ;
+ break;}
+case 73:
+#line 587 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 74:
+#line 589 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 75:
+#line 594 "./awk.y"
+{ yyval.nodeval = make_param(yyvsp[0].sval); ;
+ break;}
+case 76:
+#line 596 "./awk.y"
+{ yyval.nodeval = append_right(yyvsp[-2].nodeval, make_param(yyvsp[0].sval)); yyerrok; ;
+ break;}
+case 77:
+#line 598 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 78:
+#line 600 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 79:
+#line 602 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 80:
+#line 608 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 81:
+#line 610 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 82:
+#line 615 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 83:
+#line 617 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 84:
+#line 622 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL); ;
+ break;}
+case 85:
+#line 624 "./awk.y"
+{
+ yyval.nodeval = append_right(yyvsp[-2].nodeval,
+ node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL));
+ yyerrok;
+ ;
+ break;}
+case 86:
+#line 630 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 87:
+#line 632 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 88:
+#line 634 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 89:
+#line 636 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 90:
+#line 641 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 91:
+#line 643 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 92:
+#line 648 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL); ;
+ break;}
+case 93:
+#line 650 "./awk.y"
+{
+ yyval.nodeval = append_right(yyvsp[-2].nodeval,
+ node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL));
+ yyerrok;
+ ;
+ break;}
+case 94:
+#line 656 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 95:
+#line 658 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 96:
+#line 660 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 97:
+#line 662 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 98:
+#line 667 "./awk.y"
+{ want_assign = FALSE; ;
+ break;}
+case 99:
+#line 669 "./awk.y"
+{
+ if (do_lint && yyvsp[0].nodeval->type == Node_regex)
+ warning("Regular expression on left of assignment.");
+ yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-2].nodetypeval, yyvsp[0].nodeval);
+ ;
+ break;}
+case 100:
+#line 675 "./awk.y"
+{ yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-3].nodeval); ;
+ break;}
+case 101:
+#line 677 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[0].nodeval, Node_K_getline,
+ node(yyvsp[-3].nodeval, Node_redirect_pipein, (NODE *) NULL));
+ ;
+ break;}
+case 102:
+#line 682 "./awk.y"
+{
+ if (do_lint && ! io_allowed && yyvsp[0].nodeval == NULL)
+ warning("non-redirected getline undefined inside BEGIN or END action");
+ yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_getline, yyvsp[0].nodeval);
+ ;
+ break;}
+case 103:
+#line 688 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_and, yyvsp[0].nodeval); ;
+ break;}
+case 104:
+#line 690 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_or, yyvsp[0].nodeval); ;
+ break;}
+case 105:
+#line 692 "./awk.y"
+{
+ if (yyvsp[-2].nodeval->type == Node_regex)
+ warning("Regular expression on left of MATCH operator.");
+ yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, mk_rexp(yyvsp[0].nodeval));
+ ;
+ break;}
+case 106:
+#line 698 "./awk.y"
+{
+ yyval.nodeval = yyvsp[0].nodeval;
+ if (do_lint && tokstart[0] == '*') {
+ /* possible C comment */
+ int n = strlen(tokstart) - 1;
+ if (tokstart[n] == '*')
+ warning("regexp looks like a C comment, but is not");
+ }
+ ;
+ break;}
+case 107:
+#line 708 "./awk.y"
+{
+ yyval.nodeval = node(node(make_number(0.0),
+ Node_field_spec,
+ (NODE *) NULL),
+ Node_nomatch,
+ yyvsp[0].nodeval);
+ ;
+ break;}
+case 108:
+#line 716 "./awk.y"
+{ yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-2].nodeval); ;
+ break;}
+case 109:
+#line 718 "./awk.y"
+{
+ if (do_lint && yyvsp[0].nodeval->type == Node_regex)
+ warning("Regular expression on left of comparison.");
+ yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, yyvsp[0].nodeval);
+ ;
+ break;}
+case 110:
+#line 724 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_less, yyvsp[0].nodeval); ;
+ break;}
+case 111:
+#line 726 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_greater, yyvsp[0].nodeval); ;
+ break;}
+case 112:
+#line 728 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-4].nodeval, Node_cond_exp, node(yyvsp[-2].nodeval, Node_if_branches, yyvsp[0].nodeval));;
+ break;}
+case 113:
+#line 730 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 114:
+#line 732 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_concat, yyvsp[0].nodeval); ;
+ break;}
+case 115:
+#line 737 "./awk.y"
+{ want_assign = FALSE; ;
+ break;}
+case 116:
+#line 739 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-2].nodetypeval, yyvsp[0].nodeval); ;
+ break;}
+case 117:
+#line 741 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_and, yyvsp[0].nodeval); ;
+ break;}
+case 118:
+#line 743 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_or, yyvsp[0].nodeval); ;
+ break;}
+case 119:
+#line 745 "./awk.y"
+{
+ if (do_lint && ! io_allowed && yyvsp[0].nodeval == NULL)
+ warning("non-redirected getline undefined inside BEGIN or END action");
+ yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_getline, yyvsp[0].nodeval);
+ ;
+ break;}
+case 120:
+#line 751 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 121:
+#line 753 "./awk.y"
+{ yyval.nodeval = node((NODE *) NULL, Node_nomatch, yyvsp[0].nodeval); ;
+ break;}
+case 122:
+#line 755 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, mk_rexp(yyvsp[0].nodeval)); ;
+ break;}
+case 123:
+#line 757 "./awk.y"
+{ yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-2].nodeval); ;
+ break;}
+case 124:
+#line 759 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, yyvsp[0].nodeval); ;
+ break;}
+case 125:
+#line 761 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-4].nodeval, Node_cond_exp, node(yyvsp[-2].nodeval, Node_if_branches, yyvsp[0].nodeval));;
+ break;}
+case 126:
+#line 763 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 127:
+#line 765 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_concat, yyvsp[0].nodeval); ;
+ break;}
+case 129:
+#line 772 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_exp, yyvsp[0].nodeval); ;
+ break;}
+case 130:
+#line 774 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_times, yyvsp[0].nodeval); ;
+ break;}
+case 131:
+#line 776 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_quotient, yyvsp[0].nodeval); ;
+ break;}
+case 132:
+#line 778 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_mod, yyvsp[0].nodeval); ;
+ break;}
+case 133:
+#line 780 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_plus, yyvsp[0].nodeval); ;
+ break;}
+case 134:
+#line 782 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-2].nodeval, Node_minus, yyvsp[0].nodeval); ;
+ break;}
+case 135:
+#line 784 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_postincrement, (NODE *) NULL); ;
+ break;}
+case 136:
+#line 786 "./awk.y"
+{ yyval.nodeval = node(yyvsp[-1].nodeval, Node_postdecrement, (NODE *) NULL); ;
+ break;}
+case 137:
+#line 791 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_not, (NODE *) NULL); ;
+ break;}
+case 138:
+#line 793 "./awk.y"
+{ yyval.nodeval = yyvsp[-1].nodeval; ;
+ break;}
+case 139:
+#line 796 "./awk.y"
+{ yyval.nodeval = snode(yyvsp[-1].nodeval, Node_builtin, (int) yyvsp[-3].lval); ;
+ break;}
+case 140:
+#line 798 "./awk.y"
+{ yyval.nodeval = snode(yyvsp[-1].nodeval, Node_builtin, (int) yyvsp[-3].lval); ;
+ break;}
+case 141:
+#line 800 "./awk.y"
+{
+ if (do_lint)
+ warning("call of `length' without parentheses is not portable");
+ yyval.nodeval = snode((NODE *) NULL, Node_builtin, (int) yyvsp[0].lval);
+ if (do_posix)
+ warning("call of `length' without parentheses is deprecated by POSIX");
+ ;
+ break;}
+case 142:
+#line 808 "./awk.y"
+{
+ yyval.nodeval = node(yyvsp[-1].nodeval, Node_func_call, make_string(yyvsp[-3].sval, strlen(yyvsp[-3].sval)));
+ func_use(yyvsp[-3].sval, FUNC_USE);
+ param_sanity(yyvsp[-1].nodeval);
+ free(yyvsp[-3].sval);
+ ;
+ break;}
+case 144:
+#line 816 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_preincrement, (NODE *) NULL); ;
+ break;}
+case 145:
+#line 818 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_predecrement, (NODE *) NULL); ;
+ break;}
+case 146:
+#line 820 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 147:
+#line 822 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 148:
+#line 825 "./awk.y"
+{
+ if (yyvsp[0].nodeval->type == Node_val) {
+ yyvsp[0].nodeval->numbr = -(force_number(yyvsp[0].nodeval));
+ yyval.nodeval = yyvsp[0].nodeval;
+ } else
+ yyval.nodeval = node(yyvsp[0].nodeval, Node_unary_minus, (NODE *) NULL);
+ ;
+ break;}
+case 149:
+#line 833 "./awk.y"
+{
+ /*
+ * was: $$ = $2
+ * POSIX semantics: force a conversion to numeric type
+ */
+ yyval.nodeval = node (make_number(0.0), Node_plus, yyvsp[0].nodeval);
+ ;
+ break;}
+case 150:
+#line 844 "./awk.y"
+{ yyval.nodeval = NULL; ;
+ break;}
+case 151:
+#line 846 "./awk.y"
+{ yyval.nodeval = yyvsp[0].nodeval; ;
+ break;}
+case 152:
+#line 851 "./awk.y"
+{ yyval.nodeval = variable(yyvsp[0].sval, CAN_FREE, Node_var); ;
+ break;}
+case 153:
+#line 853 "./awk.y"
+{
+ if (yyvsp[-1].nodeval == NULL) {
+ fatal("invalid subscript expression");
+ } else if (yyvsp[-1].nodeval->rnode == NULL) {
+ yyval.nodeval = node(variable(yyvsp[-3].sval, CAN_FREE, Node_var_array), Node_subscript, yyvsp[-1].nodeval->lnode);
+ freenode(yyvsp[-1].nodeval);
+ } else
+ yyval.nodeval = node(variable(yyvsp[-3].sval, CAN_FREE, Node_var_array), Node_subscript, yyvsp[-1].nodeval);
+ ;
+ break;}
+case 154:
+#line 863 "./awk.y"
+{ yyval.nodeval = node(yyvsp[0].nodeval, Node_field_spec, (NODE *) NULL); ;
+ break;}
+case 156:
+#line 871 "./awk.y"
+{ yyerrok; ;
+ break;}
+case 157:
+#line 875 "./awk.y"
+{ yyerrok; ;
+ break;}
+case 160:
+#line 884 "./awk.y"
+{ yyerrok; want_assign = FALSE; ;
+ break;}
+case 161:
+#line 887 "./awk.y"
+{ yyerrok; ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 498 "/usr/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 890 "./awk.y"
+
+
+struct token {
+ const char *operator; /* text to match */
+ NODETYPE value; /* node type */
+ int class; /* lexical class */
+ unsigned flags; /* # of args. allowed and compatability */
+# define ARGS 0xFF /* 0, 1, 2, 3 args allowed (any combination */
+# define A(n) (1<<(n))
+# define VERSION 0xFF00 /* old awk is zero */
+# define NOT_OLD 0x0100 /* feature not in old awk */
+# define NOT_POSIX 0x0200 /* feature not in POSIX */
+# define GAWKX 0x0400 /* gawk extension */
+# define RESX 0x0800 /* Bell Labs Research extension */
+ NODE *(*ptr)(); /* function that implements this keyword */
+};
+
+
+/* Tokentab is sorted ascii ascending order, so it can be binary searched. */
+/* Function pointers come from declarations in awk.h. */
+
+static struct token tokentab[] = {
+{"BEGIN", Node_illegal, LEX_BEGIN, 0, 0},
+{"END", Node_illegal, LEX_END, 0, 0},
+#ifdef ARRAYDEBUG
+{"adump", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_adump},
+#endif
+#ifdef BITOPS
+{"and", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_and},
+#endif /* BITOPS */
+{"atan2", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2), do_atan2},
+{"break", Node_K_break, LEX_BREAK, 0, 0},
+{"close", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_close},
+#ifdef BITOPS
+{"compl", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_compl},
+#endif /* BITOPS */
+{"continue", Node_K_continue, LEX_CONTINUE, 0, 0},
+{"cos", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_cos},
+{"delete", Node_K_delete, LEX_DELETE, NOT_OLD, 0},
+{"do", Node_K_do, LEX_DO, NOT_OLD, 0},
+{"else", Node_illegal, LEX_ELSE, 0, 0},
+{"exit", Node_K_exit, LEX_EXIT, 0, 0},
+{"exp", Node_builtin, LEX_BUILTIN, A(1), do_exp},
+{"fflush", Node_builtin, LEX_BUILTIN, RESX|A(0)|A(1), do_fflush},
+{"for", Node_K_for, LEX_FOR, 0, 0},
+{"func", Node_K_function, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0},
+{"function", Node_K_function, LEX_FUNCTION, NOT_OLD, 0},
+{"gensub", Node_builtin, LEX_BUILTIN, GAWKX|A(3)|A(4), do_gensub},
+{"getline", Node_K_getline, LEX_GETLINE, NOT_OLD, 0},
+{"gsub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_gsub},
+{"if", Node_K_if, LEX_IF, 0, 0},
+{"in", Node_illegal, LEX_IN, 0, 0},
+{"index", Node_builtin, LEX_BUILTIN, A(2), do_index},
+{"int", Node_builtin, LEX_BUILTIN, A(1), do_int},
+{"length", Node_builtin, LEX_LENGTH, A(0)|A(1), do_length},
+{"log", Node_builtin, LEX_BUILTIN, A(1), do_log},
+#ifdef BITOPS
+{"lshift", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_lshift},
+#endif /* BITOPS */
+{"match", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2), do_match},
+{"next", Node_K_next, LEX_NEXT, 0, 0},
+{"nextfile", Node_K_nextfile, LEX_NEXTFILE, GAWKX, 0},
+#ifdef BITOPS
+{"or", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_or},
+#endif /* BITOPS */
+{"print", Node_K_print, LEX_PRINT, 0, 0},
+{"printf", Node_K_printf, LEX_PRINTF, 0, 0},
+{"rand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0), do_rand},
+{"return", Node_K_return, LEX_RETURN, NOT_OLD, 0},
+#ifdef BITOPS
+{"rshift", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_rshift},
+#endif /* BITOPS */
+{"sin", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_sin},
+{"split", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_split},
+{"sprintf", Node_builtin, LEX_BUILTIN, 0, do_sprintf},
+{"sqrt", Node_builtin, LEX_BUILTIN, A(1), do_sqrt},
+{"srand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0)|A(1), do_srand},
+#ifdef ARRAYDEBUG
+{"stopme", Node_builtin, LEX_BUILTIN, GAWKX|A(0), stopme},
+#endif
+{"strftime", Node_builtin, LEX_BUILTIN, GAWKX|A(0)|A(1)|A(2), do_strftime},
+#ifdef BITOPS
+{"strtonum", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_strtonum},
+#endif /* BITOPS */
+{"sub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_sub},
+{"substr", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_substr},
+{"system", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_system},
+{"systime", Node_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime},
+{"tolower", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower},
+{"toupper", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper},
+{"while", Node_K_while, LEX_WHILE, 0, 0},
+#ifdef BITOPS
+{"xor", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_xor},
+#endif /* BITOPS */
+};
+
+/* yyerror --- print a syntax error message, show where */
+
+#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
+static void
+yyerror(const char *m, ...)
+#else
+/* VARARGS0 */
+static void
+yyerror(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ const char *mesg = NULL;
+ register char *bp, *cp;
+ char *scan;
+ char buf[120];
+ static char end_of_file_line[] = "(END OF FILE)";
+
+ errcount++;
+ /* Find the current line in the input file */
+ if (lexptr && lexeme) {
+ if (thisline == NULL) {
+ cp = lexeme;
+ if (*cp == '\n') {
+ cp--;
+ mesg = "unexpected newline";
+ }
+ for (; cp != lexptr_begin && *cp != '\n'; --cp)
+ continue;
+ if (*cp == '\n')
+ cp++;
+ thisline = cp;
+ }
+ /* NL isn't guaranteed */
+ bp = lexeme;
+ while (bp < lexend && *bp && *bp != '\n')
+ bp++;
+ } else {
+ thisline = end_of_file_line;
+ bp = thisline + strlen(thisline);
+ }
+ msg("%.*s", (int) (bp - thisline), thisline);
+ bp = buf;
+ cp = buf + sizeof(buf) - 24; /* 24 more than longest msg. input */
+ if (lexptr != NULL) {
+ scan = thisline;
+ while (bp < cp && scan < lexeme)
+ if (*scan++ == '\t')
+ *bp++ = '\t';
+ else
+ *bp++ = ' ';
+ *bp++ = '^';
+ *bp++ = ' ';
+ }
+#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
+ va_start(args, m);
+ if (mesg == NULL)
+ mesg = m;
+#else
+ va_start(args);
+ if (mesg == NULL)
+ mesg = va_arg(args, char *);
+#endif
+ strcpy(bp, mesg);
+ err("", buf, args);
+ va_end(args);
+}
+
+/* get_src_buf --- read the next buffer of source program */
+
+static char *
+get_src_buf()
+{
+ static int samefile = FALSE;
+ static int nextfile = 0;
+ static char *buf = NULL;
+ static int fd;
+ int n;
+ register char *scan;
+ static int len = 0;
+ static int did_newline = FALSE;
+ int newfile;
+ struct stat sbuf;
+
+# define SLOP 128 /* enough space to hold most source lines */
+
+again:
+ newfile = FALSE;
+ if (nextfile > numfiles)
+ return NULL;
+
+ if (srcfiles[nextfile].stype == CMDLINE) {
+ if (len == 0) {
+ len = strlen(srcfiles[nextfile].val);
+ if (len == 0) {
+ /*
+ * Yet Another Special case:
+ * gawk '' /path/name
+ * Sigh.
+ */
+ static int warned = FALSE;
+
+ if (do_lint && ! warned) {
+ warned = TRUE;
+ warning("empty program text on command line");
+ }
+ ++nextfile;
+ goto again;
+ }
+ sourceline = 1;
+ lexptr = lexptr_begin = srcfiles[nextfile].val;
+ lexend = lexptr + len;
+ } else if (! did_newline && *(lexptr-1) != '\n') {
+ /*
+ * The following goop is to ensure that the source
+ * ends with a newline and that the entire current
+ * line is available for error messages.
+ */
+ int offset;
+
+ did_newline = TRUE;
+ offset = lexptr - lexeme;
+ for (scan = lexeme; scan > lexptr_begin; scan--)
+ if (*scan == '\n') {
+ scan++;
+ break;
+ }
+ len = lexptr - scan;
+ emalloc(buf, char *, len+1, "get_src_buf");
+ memcpy(buf, scan, len);
+ thisline = buf;
+ lexptr = buf + len;
+ *lexptr = '\n';
+ lexeme = lexptr - offset;
+ lexptr_begin = buf;
+ lexend = lexptr + 1;
+ } else {
+ len = 0;
+ lexeme = lexptr = lexptr_begin = NULL;
+ }
+ if (lexptr == NULL && ++nextfile <= numfiles)
+ goto again;
+ return lexptr;
+ }
+ if (! samefile) {
+ source = srcfiles[nextfile].val;
+ if (source == NULL) {
+ if (buf != NULL) {
+ free(buf);
+ buf = NULL;
+ }
+ len = 0;
+ return lexeme = lexptr = lexptr_begin = NULL;
+ }
+ fd = pathopen(source);
+ if (fd <= INVALID_HANDLE) {
+ char *in;
+
+ /* suppress file name and line no. in error mesg */
+ in = source;
+ source = NULL;
+ fatal("can't open source file \"%s\" for reading (%s)",
+ in, strerror(errno));
+ }
+ len = optimal_bufsize(fd, & sbuf);
+ newfile = TRUE;
+ if (buf != NULL)
+ free(buf);
+ emalloc(buf, char *, len + SLOP, "get_src_buf");
+ lexptr_begin = buf + SLOP;
+ samefile = TRUE;
+ sourceline = 1;
+ } else {
+ /*
+ * Here, we retain the current source line (up to length SLOP)
+ * in the beginning of the buffer that was overallocated above
+ */
+ int offset;
+ int linelen;
+
+ offset = lexptr - lexeme;
+ for (scan = lexeme; scan > lexptr_begin; scan--)
+ if (*scan == '\n') {
+ scan++;
+ break;
+ }
+ linelen = lexptr - scan;
+ if (linelen > SLOP)
+ linelen = SLOP;
+ thisline = buf + SLOP - linelen;
+ memcpy(thisline, scan, linelen);
+ lexeme = buf + SLOP - offset;
+ lexptr_begin = thisline;
+ }
+ n = read(fd, buf + SLOP, len);
+ if (n == -1)
+ fatal("can't read sourcefile \"%s\" (%s)",
+ source, strerror(errno));
+ if (n == 0) {
+ if (newfile) {
+ static int warned = FALSE;
+
+ if (do_lint && ! warned) {
+ warned = TRUE;
+ warning("source file `%s' is empty", source);
+ }
+ }
+ if (fileno(stdin) != fd) /* safety */
+ close(fd);
+ samefile = FALSE;
+ nextfile++;
+ if (lexeme)
+ *lexeme = '\0';
+ len = 0;
+ goto again;
+ }
+ lexptr = buf + SLOP;
+ lexend = lexptr + n;
+ return buf;
+}
+
+/* tokadd --- add a character to the token buffer */
+
+#define tokadd(x) (*tok++ = (x), tok == tokend ? tokexpand() : tok)
+
+/* tokexpand --- grow the token buffer */
+
+char *
+tokexpand()
+{
+ static int toksize = 60;
+ int tokoffset;
+
+ tokoffset = tok - tokstart;
+ toksize *= 2;
+ if (tokstart != NULL)
+ erealloc(tokstart, char *, toksize, "tokexpand");
+ else
+ emalloc(tokstart, char *, toksize, "tokexpand");
+ tokend = tokstart + toksize;
+ tok = tokstart + tokoffset;
+ return tok;
+}
+
+/* nextc --- get the next input character */
+
+#if DEBUG
+int
+nextc()
+{
+ int c;
+
+ if (lexptr && lexptr < lexend)
+ c = (int) (unsigned char) *lexptr++;
+ else if (get_src_buf())
+ c = (int) (unsigned char) *lexptr++;
+ else
+ c = EOF;
+
+ return c;
+}
+#else
+#define nextc() ((lexptr && lexptr < lexend) ? \
+ ((int) (unsigned char) *lexptr++) : \
+ (get_src_buf() ? ((int) (unsigned char) *lexptr++) : EOF) \
+ )
+#endif
+
+/* pushback --- push a character back on the input */
+
+#define pushback() (lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr)
+
+/* allow_newline --- allow newline after &&, ||, ? and : */
+
+static void
+allow_newline()
+{
+ int c;
+
+ for (;;) {
+ c = nextc();
+ if (c == EOF)
+ break;
+ if (c == '#') {
+ while ((c = nextc()) != '\n' && c != EOF)
+ continue;
+ if (c == EOF)
+ break;
+ }
+ if (c == '\n')
+ sourceline++;
+ if (! isspace(c)) {
+ pushback();
+ break;
+ }
+ }
+}
+
+/* yylex --- Read the input and turn it into tokens. */
+
+static int
+yylex()
+{
+ register int c, c1;
+ int seen_e = FALSE; /* These are for numbers */
+ int seen_point = FALSE;
+ int esc_seen; /* for literal strings */
+ int low, mid, high;
+ static int did_newline = FALSE;
+ char *tokkey;
+ static int lasttok = 0, eof_warned = FALSE;
+ int inhex = FALSE;
+
+ if (nextc() == EOF) {
+ if (lasttok != NEWLINE) {
+ lasttok = NEWLINE;
+ if (do_lint && ! eof_warned) {
+ warning("source file does not end in newline");
+ eof_warned = TRUE;
+ }
+ return NEWLINE; /* fake it */
+ }
+ return 0;
+ }
+ pushback();
+#ifdef OS2
+ /*
+ * added for OS/2's extproc feature of cmd.exe
+ * (like #! in BSD sh)
+ */
+ if (strncasecmp(lexptr, "extproc ", 8) == 0) {
+ while (*lexptr && *lexptr != '\n')
+ lexptr++;
+ }
+#endif
+ lexeme = lexptr;
+ thisline = NULL;
+ if (want_regexp) {
+ int in_brack = 0; /* count brackets, [[:alnum:]] allowed */
+ /*
+ * Counting brackets is non-trivial. [[] is ok,
+ * and so is [\]], with a point being that /[/]/ as a regexp
+ * constant has to work.
+ *
+ * Do not count [ or ] if either one is preceded by a \.
+ * A `[' should be counted if
+ * a) it is the first one so far (in_brack == 0)
+ * b) it is the `[' in `[:'
+ * A ']' should be counted if not preceded by a \, since
+ * it is either closing `:]' or just a plain list.
+ * According to POSIX, []] is how you put a ] into a set.
+ * Try to handle that too.
+ *
+ * The code for \ handles \[ and \].
+ */
+
+ want_regexp = FALSE;
+ tok = tokstart;
+ for (;;) {
+ c = nextc();
+ switch (c) {
+ case '[':
+ /* one day check for `.' and `=' too */
+ if ((c1 = nextc()) == ':' || in_brack == 0)
+ in_brack++;
+ pushback();
+ break;
+ case ']':
+ if (tokstart[0] == '['
+ && (tok == tokstart + 1
+ || (tok == tokstart + 2
+ && tokstart[1] == '^')))
+ /* do nothing */;
+ else
+ in_brack--;
+ break;
+ case '\\':
+ if ((c = nextc()) == EOF) {
+ yyerror("unterminated regexp ends with \\ at end of file");
+ return lasttok = REGEXP; /* kludge */
+ } else if (c == '\n') {
+ sourceline++;
+ continue;
+ } else {
+ tokadd('\\');
+ tokadd(c);
+ continue;
+ }
+ break;
+ case '/': /* end of the regexp */
+ if (in_brack > 0)
+ break;
+
+ pushback();
+ tokadd('\0');
+ yylval.sval = tokstart;
+ return lasttok = REGEXP;
+ case '\n':
+ pushback();
+ yyerror("unterminated regexp");
+ return lasttok = REGEXP; /* kludge */
+ case EOF:
+ yyerror("unterminated regexp at end of file");
+ return lasttok = REGEXP; /* kludge */
+ }
+ tokadd(c);
+ }
+ }
+retry:
+ while ((c = nextc()) == ' ' || c == '\t')
+ continue;
+
+ lexeme = lexptr ? lexptr - 1 : lexptr;
+ thisline = NULL;
+ tok = tokstart;
+ yylval.nodetypeval = Node_illegal;
+
+ switch (c) {
+ case EOF:
+ if (lasttok != NEWLINE) {
+ lasttok = NEWLINE;
+ if (do_lint && ! eof_warned) {
+ warning("source file does not end in newline");
+ eof_warned = TRUE;
+ }
+ return NEWLINE; /* fake it */
+ }
+ return 0;
+
+ case '\n':
+ sourceline++;
+ return lasttok = NEWLINE;
+
+ case '#': /* it's a comment */
+ while ((c = nextc()) != '\n') {
+ if (c == EOF) {
+ if (lasttok != NEWLINE) {
+ lasttok = NEWLINE;
+ if (do_lint && ! eof_warned) {
+ warning(
+ "source file does not end in newline");
+ eof_warned = TRUE;
+ }
+ return NEWLINE; /* fake it */
+ }
+ return 0;
+ }
+ }
+ sourceline++;
+ return lasttok = NEWLINE;
+
+ case '\\':
+#ifdef RELAXED_CONTINUATION
+ /*
+ * This code puports to allow comments and/or whitespace
+ * after the `\' at the end of a line used for continuation.
+ * Use it at your own risk. We think it's a bad idea, which
+ * is why it's not on by default.
+ */
+ if (! do_traditional) {
+ /* strip trailing white-space and/or comment */
+ while ((c = nextc()) == ' ' || c == '\t')
+ continue;
+ if (c == '#') {
+ if (do_lint)
+ warning(
+ "use of `\\ #...' line continuation is not portable");
+ while ((c = nextc()) != '\n')
+ if (c == EOF)
+ break;
+ }
+ pushback();
+ }
+#endif /* RELAXED_CONTINUATION */
+ if (nextc() == '\n') {
+ sourceline++;
+ goto retry;
+ } else {
+ yyerror("backslash not last character on line");
+ exit(1);
+ }
+ break;
+
+ case '$':
+ want_assign = TRUE;
+ return lasttok = '$';
+
+ case ':':
+ case '?':
+ allow_newline();
+ return lasttok = c;
+
+ case ')':
+ case '(':
+ case ';':
+ case '{':
+ case ',':
+ want_assign = FALSE;
+ /* fall through */
+ case '[':
+ case ']':
+ return lasttok = c;
+
+ case '*':
+ if ((c = nextc()) == '=') {
+ yylval.nodetypeval = Node_assign_times;
+ return lasttok = ASSIGNOP;
+ } else if (do_posix) {
+ pushback();
+ return lasttok = '*';
+ } else if (c == '*') {
+ /* make ** and **= aliases for ^ and ^= */
+ static int did_warn_op = FALSE, did_warn_assgn = FALSE;
+
+ if (nextc() == '=') {
+ if (do_lint && ! did_warn_assgn) {
+ did_warn_assgn = TRUE;
+ warning("**= is not allowed by POSIX");
+ warning("operator `**=' is not supported in old awk");
+ }
+ yylval.nodetypeval = Node_assign_exp;
+ return ASSIGNOP;
+ } else {
+ pushback();
+ if (do_lint && ! did_warn_op) {
+ did_warn_op = TRUE;
+ warning("** is not allowed by POSIX");
+ warning("operator `**' is not supported in old awk");
+ }
+ return lasttok = '^';
+ }
+ }
+ pushback();
+ return lasttok = '*';
+
+ case '/':
+ if (want_assign) {
+ if (nextc() == '=') {
+ yylval.nodetypeval = Node_assign_quotient;
+ return lasttok = ASSIGNOP;
+ }
+ pushback();
+ }
+ return lasttok = '/';
+
+ case '%':
+ if (nextc() == '=') {
+ yylval.nodetypeval = Node_assign_mod;
+ return lasttok = ASSIGNOP;
+ }
+ pushback();
+ return lasttok = '%';
+
+ case '^':
+ {
+ static int did_warn_op = FALSE, did_warn_assgn = FALSE;
+
+ if (nextc() == '=') {
+ if (do_lint && ! did_warn_assgn) {
+ did_warn_assgn = TRUE;
+ warning("operator `^=' is not supported in old awk");
+ }
+ yylval.nodetypeval = Node_assign_exp;
+ return lasttok = ASSIGNOP;
+ }
+ pushback();
+ if (do_lint && ! did_warn_op) {
+ did_warn_op = TRUE;
+ warning("operator `^' is not supported in old awk");
+ }
+ return lasttok = '^';
+ }
+
+ case '+':
+ if ((c = nextc()) == '=') {
+ yylval.nodetypeval = Node_assign_plus;
+ return lasttok = ASSIGNOP;
+ }
+ if (c == '+')
+ return lasttok = INCREMENT;
+ pushback();
+ return lasttok = '+';
+
+ case '!':
+ if ((c = nextc()) == '=') {
+ yylval.nodetypeval = Node_notequal;
+ return lasttok = RELOP;
+ }
+ if (c == '~') {
+ yylval.nodetypeval = Node_nomatch;
+ want_assign = FALSE;
+ return lasttok = MATCHOP;
+ }
+ pushback();
+ return lasttok = '!';
+
+ case '<':
+ if (nextc() == '=') {
+ yylval.nodetypeval = Node_leq;
+ return lasttok = RELOP;
+ }
+ yylval.nodetypeval = Node_less;
+ pushback();
+ return lasttok = '<';
+
+ case '=':
+ if (nextc() == '=') {
+ yylval.nodetypeval = Node_equal;
+ return lasttok = RELOP;
+ }
+ yylval.nodetypeval = Node_assign;
+ pushback();
+ return lasttok = ASSIGNOP;
+
+ case '>':
+ if ((c = nextc()) == '=') {
+ yylval.nodetypeval = Node_geq;
+ return lasttok = RELOP;
+ } else if (c == '>') {
+ yylval.nodetypeval = Node_redirect_append;
+ return lasttok = APPEND_OP;
+ }
+ yylval.nodetypeval = Node_greater;
+ pushback();
+ return lasttok = '>';
+
+ case '~':
+ yylval.nodetypeval = Node_match;
+ want_assign = FALSE;
+ return lasttok = MATCHOP;
+
+ case '}':
+ /*
+ * Added did newline stuff. Easier than
+ * hacking the grammar.
+ */
+ if (did_newline) {
+ did_newline = FALSE;
+ return lasttok = c;
+ }
+ did_newline++;
+ --lexptr; /* pick up } next time */
+ return lasttok = NEWLINE;
+
+ case '"':
+ esc_seen = FALSE;
+ while ((c = nextc()) != '"') {
+ if (c == '\n') {
+ pushback();
+ yyerror("unterminated string");
+ exit(1);
+ }
+ if (c == '\\') {
+ c = nextc();
+ if (c == '\n') {
+ sourceline++;
+ continue;
+ }
+ esc_seen = TRUE;
+ tokadd('\\');
+ }
+ if (c == EOF) {
+ pushback();
+ yyerror("unterminated string");
+ exit(1);
+ }
+ tokadd(c);
+ }
+ yylval.nodeval = make_str_node(tokstart,
+ tok - tokstart, esc_seen ? SCAN : 0);
+ yylval.nodeval->flags |= PERM;
+ return lasttok = YSTRING;
+
+ case '-':
+ if ((c = nextc()) == '=') {
+ yylval.nodetypeval = Node_assign_minus;
+ return lasttok = ASSIGNOP;
+ }
+ if (c == '-')
+ return lasttok = DECREMENT;
+ pushback();
+ return lasttok = '-';
+
+ case '.':
+ c = nextc();
+ pushback();
+ if (! isdigit(c))
+ return lasttok = '.';
+ else
+ c = '.';
+ /* FALL THROUGH */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* It's a number */
+ for (;;) {
+ int gotnumber = FALSE;
+
+ tokadd(c);
+ switch (c) {
+#ifdef BITOPS
+ case 'x':
+ case 'X':
+ if (do_traditional)
+ goto done;
+ if (tok == tokstart + 2)
+ inhex = TRUE;
+ break;
+#endif /* BITOTS */
+ case '.':
+ if (seen_point) {
+ gotnumber = TRUE;
+ break;
+ }
+ seen_point = TRUE;
+ break;
+ case 'e':
+ case 'E':
+ if (inhex)
+ break;
+ if (seen_e) {
+ gotnumber = TRUE;
+ break;
+ }
+ seen_e = TRUE;
+ if ((c = nextc()) == '-' || c == '+')
+ tokadd(c);
+ else
+ pushback();
+ break;
+#ifdef BITOPS
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'C':
+ case 'D':
+ case 'd':
+ case 'f':
+ case 'F':
+ if (do_traditional || ! inhex)
+ goto done;
+ /* fall through */
+#endif
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+ default:
+ done:
+ gotnumber = TRUE;
+ }
+ if (gotnumber)
+ break;
+ c = nextc();
+ }
+ if (c != EOF)
+ pushback();
+ else if (do_lint && ! eof_warned) {
+ warning("source file does not end in newline");
+ eof_warned = TRUE;
+ }
+ tokadd('\0');
+#ifdef BITOPS
+ if (! do_traditional && isnondecimal(tokstart))
+ yylval.nodeval = make_number(nondec2awknum(tokstart, strlen(tokstart)));
+ else
+#endif /* BITOPS */
+ yylval.nodeval = make_number(atof(tokstart));
+ yylval.nodeval->flags |= PERM;
+ return lasttok = YNUMBER;
+
+ case '&':
+ if ((c = nextc()) == '&') {
+ yylval.nodetypeval = Node_and;
+ allow_newline();
+ want_assign = FALSE;
+ return lasttok = LEX_AND;
+ }
+ pushback();
+ return lasttok = '&';
+
+ case '|':
+ if ((c = nextc()) == '|') {
+ yylval.nodetypeval = Node_or;
+ allow_newline();
+ want_assign = FALSE;
+ return lasttok = LEX_OR;
+ }
+ pushback();
+ return lasttok = '|';
+ }
+
+ if (c != '_' && ! isalpha(c)) {
+ yyerror("Invalid char '%c' in expression\n", c);
+ exit(1);
+ }
+
+ /* it's some type of name-type-thing. Find its length. */
+ tok = tokstart;
+ while (is_identchar(c)) {
+ tokadd(c);
+ c = nextc();
+ }
+ tokadd('\0');
+ emalloc(tokkey, char *, tok - tokstart, "yylex");
+ memcpy(tokkey, tokstart, tok - tokstart);
+ if (c != EOF)
+ pushback();
+ else if (do_lint && ! eof_warned) {
+ warning("source file does not end in newline");
+ eof_warned = TRUE;
+ }
+
+ /* See if it is a special token. */
+ low = 0;
+ high = (sizeof(tokentab) / sizeof(tokentab[0])) - 1;
+ while (low <= high) {
+ int i;
+
+ mid = (low + high) / 2;
+ c = *tokstart - tokentab[mid].operator[0];
+ i = c ? c : strcmp(tokstart, tokentab[mid].operator);
+
+ if (i < 0) /* token < mid */
+ high = mid - 1;
+ else if (i > 0) /* token > mid */
+ low = mid + 1;
+ else {
+ if (do_lint) {
+ if (tokentab[mid].flags & GAWKX)
+ warning("%s() is a gawk extension",
+ tokentab[mid].operator);
+ if (tokentab[mid].flags & RESX)
+ warning("%s() is a Bell Labs extension",
+ tokentab[mid].operator);
+ if (tokentab[mid].flags & NOT_POSIX)
+ warning("POSIX does not allow %s",
+ tokentab[mid].operator);
+ }
+ if (do_lint_old && (tokentab[mid].flags & NOT_OLD))
+ warning("%s is not supported in old awk",
+ tokentab[mid].operator);
+ if ((do_traditional && (tokentab[mid].flags & GAWKX))
+ || (do_posix && (tokentab[mid].flags & NOT_POSIX)))
+ break;
+ if (tokentab[mid].class == LEX_BUILTIN
+ || tokentab[mid].class == LEX_LENGTH
+ )
+ yylval.lval = mid;
+ else
+ yylval.nodetypeval = tokentab[mid].value;
+
+ free(tokkey);
+ return lasttok = tokentab[mid].class;
+ }
+ }
+
+ yylval.sval = tokkey;
+ if (*lexptr == '(')
+ return lasttok = FUNC_CALL;
+ else {
+ want_assign = TRUE;
+ return lasttok = NAME;
+ }
+}
+
+/* node_common --- common code for allocating a new node */
+
+static NODE *
+node_common(op)
+NODETYPE op;
+{
+ register NODE *r;
+
+ getnode(r);
+ r->type = op;
+ r->flags = MALLOC;
+ /* if lookahead is NL, lineno is 1 too high */
+ if (lexeme && *lexeme == '\n')
+ r->source_line = sourceline - 1;
+ else
+ r->source_line = sourceline;
+ r->source_file = source;
+ return r;
+}
+
+/* node --- allocates a node with defined lnode and rnode. */
+
+NODE *
+node(left, op, right)
+NODE *left, *right;
+NODETYPE op;
+{
+ register NODE *r;
+
+ r = node_common(op);
+ r->lnode = left;
+ r->rnode = right;
+ return r;
+}
+
+/* snode --- allocate a node with defined subnode and proc for builtin
+ functions. Checks for arg. count and supplies defaults where
+ possible. */
+
+static NODE *
+snode(subn, op, idx)
+NODETYPE op;
+int idx;
+NODE *subn;
+{
+ register NODE *r;
+ register NODE *n;
+ int nexp = 0;
+ int args_allowed;
+
+ r = node_common(op);
+
+ /* traverse expression list to see how many args. given */
+ for (n = subn; n != NULL; n = n->rnode) {
+ nexp++;
+ if (nexp > 3)
+ break;
+ }
+
+ /* check against how many args. are allowed for this builtin */
+ args_allowed = tokentab[idx].flags & ARGS;
+ if (args_allowed && (args_allowed & A(nexp)) == 0)
+ fatal("%s() cannot have %d argument%c",
+ tokentab[idx].operator, nexp, nexp == 1 ? ' ' : 's');
+
+ r->proc = tokentab[idx].ptr;
+
+ /* special case processing for a few builtins */
+ /*
+ * FIXME: go through these to make sure that everything done
+ * here is really right. Move anything that's not into
+ * the corresponding routine.
+ */
+ if (nexp == 0 && r->proc == do_length) {
+ subn = node(node(make_number(0.0), Node_field_spec, (NODE *) NULL),
+ Node_expression_list,
+ (NODE *) NULL);
+ } else if (r->proc == do_match) {
+ if (subn->rnode->lnode->type != Node_regex)
+ subn->rnode->lnode = mk_rexp(subn->rnode->lnode);
+ } else if (r->proc == do_sub || r->proc == do_gsub) {
+ if (subn->lnode->type != Node_regex)
+ subn->lnode = mk_rexp(subn->lnode);
+ if (nexp == 2)
+ append_right(subn, node(node(make_number(0.0),
+ Node_field_spec,
+ (NODE *) NULL),
+ Node_expression_list,
+ (NODE *) NULL));
+ else if (subn->rnode->rnode->lnode->type == Node_val) {
+ if (do_lint)
+ warning("string literal as last arg of substitute");
+ } else if (! isassignable(subn->rnode->rnode->lnode))
+ yyerror("%s third parameter is not a changeable object",
+ r->proc == do_sub ? "sub" : "gsub");
+ } else if (r->proc == do_gensub) {
+ if (subn->lnode->type != Node_regex)
+ subn->lnode = mk_rexp(subn->lnode);
+ if (nexp == 3)
+ append_right(subn, node(node(make_number(0.0),
+ Node_field_spec,
+ (NODE *) NULL),
+ Node_expression_list,
+ (NODE *) NULL));
+ } else if (r->proc == do_split) {
+ if (nexp == 2)
+ append_right(subn,
+ node(FS_node, Node_expression_list, (NODE *) NULL));
+ n = subn->rnode->rnode->lnode;
+ if (n->type != Node_regex)
+ subn->rnode->rnode->lnode = mk_rexp(n);
+ if (nexp == 2)
+ subn->rnode->rnode->lnode->re_flags |= FS_DFLT;
+ }
+
+ r->subnode = subn;
+ return r;
+}
+
+/*
+ * mkrangenode:
+ * This allocates a Node_line_range node with defined condpair and
+ * zeroes the trigger word to avoid the temptation of assuming that calling
+ * 'node( foo, Node_line_range, 0)' will properly initialize 'triggered'.
+ * Otherwise like node().
+ */
+
+static NODE *
+mkrangenode(cpair)
+NODE *cpair;
+{
+ register NODE *r;
+
+ getnode(r);
+ r->type = Node_line_range;
+ r->condpair = cpair;
+ r->triggered = FALSE;
+ return r;
+}
+
+/* make_for_loop --- build a for loop */
+
+static NODE *
+make_for_loop(init, cond, incr)
+NODE *init, *cond, *incr;
+{
+ register FOR_LOOP_HEADER *r;
+ NODE *n;
+
+ emalloc(r, FOR_LOOP_HEADER *, sizeof(FOR_LOOP_HEADER), "make_for_loop");
+ getnode(n);
+ n->type = Node_illegal;
+ r->init = init;
+ r->cond = cond;
+ r->incr = incr;
+ n->sub.nodep.r.hd = r;
+ return n;
+}
+
+/* dup_parms --- return TRUE if there are duplicate parameters */
+
+static int
+dup_parms(func)
+NODE *func;
+{
+ register NODE *np;
+ char *fname, **names;
+ int count, i, j, dups;
+ NODE *params;
+
+ if (func == NULL) /* error earlier */
+ return TRUE;
+
+ fname = func->param;
+ count = func->param_cnt;
+ params = func->rnode;
+
+ if (count == 0) /* no args, no problem */
+ return FALSE;
+
+ if (params == NULL) /* error earlier */
+ return TRUE;
+
+ emalloc(names, char **, count * sizeof(char *), "dup_parms");
+
+ i = 0;
+ for (np = params; np != NULL; np = np->rnode) {
+ if (np->param == NULL) { /* error earlier, give up, go home */
+ free(names);
+ return TRUE;
+ }
+ names[i++] = np->param;
+ }
+
+ dups = 0;
+ for (i = 1; i < count; i++) {
+ for (j = 0; j < i; j++) {
+ if (strcmp(names[i], names[j]) == 0) {
+ dups++;
+ error(
+ "function `%s': parameter #%d, `%s', duplicates parameter #%d",
+ fname, i+1, names[j], j+1);
+ }
+ }
+ }
+
+ free(names);
+ return (dups > 0 ? TRUE : FALSE);
+}
+
+/*
+ * install:
+ * Install a name in the symbol table, even if it is already there.
+ * Caller must check against redefinition if that is desired.
+ */
+
+NODE *
+install(name, value)
+char *name;
+NODE *value;
+{
+ register NODE *hp;
+ register size_t len;
+ register int bucket;
+
+ len = strlen(name);
+ bucket = hash(name, len, (unsigned long) HASHSIZE);
+ getnode(hp);
+ hp->type = Node_hashnode;
+ hp->hnext = variables[bucket];
+ variables[bucket] = hp;
+ hp->hlength = len;
+ hp->hvalue = value;
+ hp->hname = name;
+ hp->hvalue->vname = name;
+ return hp->hvalue;
+}
+
+/* lookup --- find the most recent hash node for name installed by install */
+
+NODE *
+lookup(name)
+const char *name;
+{
+ register NODE *bucket;
+ register size_t len;
+
+ len = strlen(name);
+ for (bucket = variables[hash(name, len, (unsigned long) HASHSIZE)];
+ bucket != NULL; bucket = bucket->hnext)
+ if (bucket->hlength == len && STREQN(bucket->hname, name, len))
+ return bucket->hvalue;
+
+ return NULL;
+}
+
+/*
+ * append_right:
+ * Add new to the rightmost branch of LIST. This uses n^2 time, so we make
+ * a simple attempt at optimizing it.
+ */
+
+static NODE *
+append_right(list, new)
+NODE *list, *new;
+{
+ register NODE *oldlist;
+ static NODE *savefront = NULL, *savetail = NULL;
+
+ if (list == NULL || new == NULL)
+ return list;
+
+ oldlist = list;
+ if (savefront == oldlist) {
+ savetail = savetail->rnode = new;
+ return oldlist;
+ } else
+ savefront = oldlist;
+ while (list->rnode != NULL)
+ list = list->rnode;
+ savetail = list->rnode = new;
+ return oldlist;
+}
+
+/*
+ * func_install:
+ * check if name is already installed; if so, it had better have Null value,
+ * in which case def is added as the value. Otherwise, install name with def
+ * as value.
+ */
+
+static void
+func_install(params, def)
+NODE *params;
+NODE *def;
+{
+ NODE *r;
+ NODE *n;
+
+ /* check for function foo(foo) { ... }. bleh. */
+ for (n = params->rnode; n != NULL; n = n->rnode) {
+ if (strcmp(n->param, params->param) == 0)
+ fatal("function `%s': can't use function name as parameter name",
+ params->param);
+ }
+
+ pop_params(params->rnode);
+ pop_var(params, FALSE);
+ r = lookup(params->param);
+ if (r != NULL) {
+ fatal("function name `%s' previously defined", params->param);
+ } else
+ (void) install(params->param, node(params, Node_func, def));
+
+ func_use(params->param, FUNC_DEFINE);
+}
+
+/* pop_var --- remove a variable from the symbol table */
+
+static void
+pop_var(np, freeit)
+NODE *np;
+int freeit;
+{
+ register NODE *bucket, **save;
+ register size_t len;
+ char *name;
+
+ name = np->param;
+ len = strlen(name);
+ save = &(variables[hash(name, len, (unsigned long) HASHSIZE)]);
+ for (bucket = *save; bucket != NULL; bucket = bucket->hnext) {
+ if (len == bucket->hlength && STREQN(bucket->hname, name, len)) {
+ *save = bucket->hnext;
+ freenode(bucket);
+ if (freeit)
+ free(np->param);
+ return;
+ }
+ save = &(bucket->hnext);
+ }
+}
+
+/* pop_params --- remove list of function parameters from symbol table */
+
+/*
+ * pop parameters out of the symbol table. do this in reverse order to
+ * avoid reading freed memory if there were duplicated parameters.
+ */
+static void
+pop_params(params)
+NODE *params;
+{
+ if (params == NULL)
+ return;
+ pop_params(params->rnode);
+ pop_var(params, TRUE);
+}
+
+/* make_param --- make NAME into a function parameter */
+
+static NODE *
+make_param(name)
+char *name;
+{
+ NODE *r;
+
+ getnode(r);
+ r->type = Node_param_list;
+ r->rnode = NULL;
+ r->param = name;
+ r->param_cnt = param_counter++;
+ return (install(name, r));
+}
+
+static struct fdesc {
+ char *name;
+ short used;
+ short defined;
+ struct fdesc *next;
+} *ftable[HASHSIZE];
+
+/* func_use --- track uses and definitions of functions */
+
+static void
+func_use(name, how)
+char *name;
+enum defref how;
+{
+ struct fdesc *fp;
+ int len;
+ int ind;
+
+ len = strlen(name);
+ ind = hash(name, len, HASHSIZE);
+
+ for (fp = ftable[ind]; fp != NULL; fp = fp->next) {
+ if (strcmp(fp->name, name) == 0) {
+ if (how == FUNC_DEFINE)
+ fp->defined++;
+ else
+ fp->used++;
+ return;
+ }
+ }
+
+ /* not in the table, fall through to allocate a new one */
+
+ emalloc(fp, struct fdesc *, sizeof(struct fdesc), "func_use");
+ memset(fp, '\0', sizeof(struct fdesc));
+ emalloc(fp->name, char *, len + 1, "func_use");
+ strcpy(fp->name, name);
+ if (how == FUNC_DEFINE)
+ fp->defined++;
+ else
+ fp->used++;
+ fp->next = ftable[ind];
+ ftable[ind] = fp;
+}
+
+/* check_funcs --- verify functions that are called but not defined */
+
+static void
+check_funcs()
+{
+ struct fdesc *fp, *next;
+ int i;
+
+ for (i = 0; i < HASHSIZE; i++) {
+ for (fp = ftable[i]; fp != NULL; fp = fp->next) {
+#ifdef REALLYMEAN
+ /* making this the default breaks old code. sigh. */
+ if (fp->defined == 0) {
+ error(
+ "function `%s' called but never defined", fp->name);
+ errcount++;
+ }
+#else
+ if (do_lint && fp->defined == 0)
+ warning(
+ "function `%s' called but never defined", fp->name);
+#endif
+ if (do_lint && fp->used == 0) {
+ warning("function `%s' defined but never called",
+ fp->name);
+ }
+ }
+ }
+
+ /* now let's free all the memory */
+ for (i = 0; i < HASHSIZE; i++) {
+ for (fp = ftable[i]; fp != NULL; fp = next) {
+ next = fp->next;
+ free(fp->name);
+ free(fp);
+ }
+ }
+}
+
+/* param_sanity --- look for parameters that are regexp constants */
+
+static void
+param_sanity(arglist)
+NODE *arglist;
+{
+ NODE *argp, *arg;
+ int i;
+
+ for (i = 1, argp = arglist; argp != NULL; argp = argp->rnode, i++) {
+ arg = argp->lnode;
+ if (arg->type == Node_regex)
+ warning("regexp constant for parameter #%d yields boolean value", i);
+ }
+}
+
+/* variable --- make sure NAME is in the symbol table */
+
+NODE *
+variable(name, can_free, type)
+char *name;
+int can_free;
+NODETYPE type;
+{
+ register NODE *r;
+ static int env_loaded = FALSE;
+
+ if (! env_loaded && STREQ(name, "ENVIRON")) {
+ load_environ();
+ env_loaded = TRUE;
+ }
+ if ((r = lookup(name)) == NULL)
+ r = install(name, node(Nnull_string, type, (NODE *) NULL));
+ else if (can_free)
+ free(name);
+ return r;
+}
+
+/* mk_rexp --- make a regular expression constant */
+
+static NODE *
+mk_rexp(exp)
+NODE *exp;
+{
+ NODE *n;
+
+ if (exp->type == Node_regex)
+ return exp;
+
+ getnode(n);
+ n->type = Node_regex;
+ n->re_exp = exp;
+ n->re_text = NULL;
+ n->re_reg = NULL;
+ n->re_flags = 0;
+ n->re_cnt = 1;
+ return n;
+}
+
+/* isnoeffect --- when used as a statement, has no side effects */
+
+/*
+ * To be completely general, we should recursively walk the parse
+ * tree, to make sure that all the subexpressions also have no effect.
+ * Instead, we just weaken the actual warning that's printed, up above
+ * in the grammar.
+ */
+
+static int
+isnoeffect(type)
+NODETYPE type;
+{
+ switch (type) {
+ case Node_times:
+ case Node_quotient:
+ case Node_mod:
+ case Node_plus:
+ case Node_minus:
+ case Node_subscript:
+ case Node_concat:
+ case Node_exp:
+ case Node_unary_minus:
+ case Node_field_spec:
+ case Node_and:
+ case Node_or:
+ case Node_equal:
+ case Node_notequal:
+ case Node_less:
+ case Node_greater:
+ case Node_leq:
+ case Node_geq:
+ case Node_match:
+ case Node_nomatch:
+ case Node_not:
+ case Node_val:
+ case Node_in_array:
+ case Node_NF:
+ case Node_NR:
+ case Node_FNR:
+ case Node_FS:
+ case Node_RS:
+ case Node_FIELDWIDTHS:
+ case Node_IGNORECASE:
+ case Node_OFS:
+ case Node_ORS:
+ case Node_OFMT:
+ case Node_CONVFMT:
+ return TRUE;
+ default:
+ break; /* keeps gcc -Wall happy */
+ }
+
+ return FALSE;
+}
+
+/* isassignable --- can this node be assigned to? */
+
+static int
+isassignable(n)
+register NODE *n;
+{
+ switch (n->type) {
+ case Node_var:
+ case Node_FIELDWIDTHS:
+ case Node_RS:
+ case Node_FS:
+ case Node_FNR:
+ case Node_NR:
+ case Node_NF:
+ case Node_IGNORECASE:
+ case Node_OFMT:
+ case Node_CONVFMT:
+ case Node_ORS:
+ case Node_OFS:
+ case Node_field_spec:
+ case Node_subscript:
+ return TRUE;
+ case Node_param_list:
+ return ((n->flags & FUNC) == 0); /* ok if not func name */
+ default:
+ break; /* keeps gcc -Wall happy */
+ }
+ return FALSE;
+}
+
+/* for debugging */
+NODE *
+stopme(tree)
+NODE *tree;
+{
+ return tmp_number((AWKNUM) 0.0);
+}
diff --git a/contrib/awk/configh.in b/contrib/awk/configh.in
new file mode 100644
index 000000000000..f423d4aac894
--- /dev/null
+++ b/contrib/awk/configh.in
@@ -0,0 +1,225 @@
+/* configh.in. Generated automatically from configure.in by autoheader. */
+/*
+ * acconfig.h -- configuration definitions for gawk.
+ */
+
+/*
+ * Copyright (C) 1995-2000 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define if type char is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define to the type of elements in the array set by `getgroups'.
+ Usually this is either `int' or `gid_t'. */
+#undef GETGROUPS_T
+
+/* Define if the `getpgrp' function takes no argument. */
+#undef GETPGRP_VOID
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if you don't have vprintf but do have _doprnt. */
+#undef HAVE_DOPRNT
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if your struct stat has st_blksize. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#undef HAVE_STRINGIZE
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if your struct tm has tm_zone. */
+#undef HAVE_TM_ZONE
+
+/* Define if you don't have tm_zone but do have the external array
+ tzname. */
+#undef HAVE_TZNAME
+
+/* Define if you have the vprintf function. */
+#undef HAVE_VPRINTF
+
+/* Define if on MINIX. */
+#undef _MINIX
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm. */
+#undef TM_IN_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+#undef HAVE_STRINGIZE /* can use ANSI # operator in cpp */
+#undef REGEX_MALLOC /* use malloc instead of alloca in regex.c */
+#undef SPRINTF_RET /* return type of sprintf */
+#undef BITOPS /* bitwise ops (undocumented feature) */
+#undef NONDECDATA /* non-decimal input data (undocumented feature) */
+#undef _FILE_OFFSET_BITS /* bits in a file offset, where this matters */
+#undef _LARGEFILE_SOURCE /* makes fseeko etc. visible on some hosts */
+#undef _LARGE_FILES /* emables large files on AIX-style hosts */
+
+/* Define if you have the fmod function. */
+#undef HAVE_FMOD
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the madvise function. */
+#undef HAVE_MADVISE
+
+/* Define if you have the memcmp function. */
+#undef HAVE_MEMCMP
+
+/* Define if you have the memcpy function. */
+#undef HAVE_MEMCPY
+
+/* Define if you have the memset function. */
+#undef HAVE_MEMSET
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the strchr function. */
+#undef HAVE_STRCHR
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have the strncasecmp function. */
+#undef HAVE_STRNCASECMP
+
+/* Define if you have the strtod function. */
+#undef HAVE_STRTOD
+
+/* Define if you have the system function. */
+#undef HAVE_SYSTEM
+
+/* Define if you have the tzset function. */
+#undef HAVE_TZSET
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <signum.h> header file. */
+#undef HAVE_SIGNUM_H
+
+/* Define if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the m library (-lm). */
+#undef HAVE_LIBM
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to make ftello visible on some hosts (e.g. HP-UX 10.20). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to make ftello visible on some hosts (e.g. glibc 2.1.3). */
+#undef _XOPEN_SOURCE
+
+
+#include <custom.h> /* overrides for stuff autoconf can't deal with */
diff --git a/contrib/awk/configure b/contrib/awk/configure
new file mode 100755
index 000000000000..b4ba9dc3dd80
--- /dev/null
+++ b/contrib/awk/configure
@@ -0,0 +1,3685 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-bitops Enable Octal and Hex constants and bit functions"
+ac_help="$ac_help
+ --enable-non-decimal-data Enable Octal and Hex constants as valid input data"
+ac_help="$ac_help
+ --disable-largefile omit support for large files"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=awk.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+# Check whether --enable-bitops or --disable-bitops was given.
+if test "${enable_bitops+set}" = set; then
+ enableval="$enable_bitops"
+ cat >> confdefs.h <<\EOF
+#define BITOPS 1
+EOF
+
+fi
+
+# Check whether --enable-non-decimal-data or --disable-non-decimal-data was given.
+if test "${enable_non_decimal_data+set}" = set; then
+ enableval="$enable_non_decimal_data"
+ cat >> confdefs.h <<\EOF
+#define NONDECDATA 1
+EOF
+
+fi
+
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:558: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:589: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:612: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:642: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:693: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:725: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 736 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:741: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:767: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:772: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:781: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:800: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:832: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 847 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:853: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 864 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:870: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 881 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+# This is a hack. Different versions of install on different systems
+# are just too different. Chuck it and use install-sh.
+INSTALL="$srcdir/install-sh -c"; export INSTALL
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:946: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1000: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+if test "$CFLAGS" = ""
+then
+ if test "$GCC" = yes
+ then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+fi
+
+# This is mainly for my use during testing and development.
+# Yes, it's a bit of a hack.
+if test -f $srcdir/.developing
+then
+ cat >> confdefs.h <<\EOF
+#define BITOPS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NONDECDATA 1
+EOF
+
+ CFLAGS="$CFLAGS -DARRAYDEBUG"
+fi
+
+
+
+echo $ac_n "checking for AIX""... $ac_c" 1>&6
+echo "configure:1055: checking for AIX" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1057 "configure"
+#include "confdefs.h"
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:1079: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+echo "configure:1101: checking for minix/config.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1106 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ MINIX=yes
+else
+ echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+# Check whether --enable-largefile or --disable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval="$enable_largefile"
+ :
+fi
+
+ if test "$enable_largefile" != no; then
+
+ echo $ac_n "checking for special C compiler options needed for large files""... $ac_c" 1>&6
+echo "configure:1157: checking for special C compiler options needed for large files" >&5
+if eval "test \"`echo '$''{'gawk_cv_sys_largefile_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ gawk_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat > conftest.$ac_ext <<EOF
+#line 1166 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_save_CC="$CC"
+ CC="$CC -n32"
+ cat > conftest.$ac_ext <<EOF
+#line 1184 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gawk_cv_sys_largefile_CC=' -n32'
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+ CC="$ac_save_CC"
+fi
+rm -f conftest*
+ fi
+fi
+
+echo "$ac_t""$gawk_cv_sys_largefile_CC" 1>&6
+ if test "$gawk_cv_sys_largefile_CC" != no; then
+ CC="$CC$gawk_cv_sys_largefile_CC"
+ fi
+
+ echo $ac_n "checking for _FILE_OFFSET_BITS value needed for large files""... $ac_c" 1>&6
+echo "configure:1213: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+if eval "test \"`echo '$''{'gawk_cv_sys_file_offset_bits'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ gawk_cv_sys_file_offset_bits=no
+ cat > conftest.$ac_ext <<EOF
+#line 1219 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1230: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 1237 "configure"
+#include "confdefs.h"
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1249: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gawk_cv_sys_file_offset_bits=64
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gawk_cv_sys_file_offset_bits" 1>&6
+ if test "$gawk_cv_sys_file_offset_bits" != no; then
+ cat >> confdefs.h <<EOF
+#define _FILE_OFFSET_BITS $gawk_cv_sys_file_offset_bits
+EOF
+
+ fi
+ echo $ac_n "checking for _LARGEFILE_SOURCE value needed for large files""... $ac_c" 1>&6
+echo "configure:1269: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+if eval "test \"`echo '$''{'gawk_cv_sys_largefile_source'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ gawk_cv_sys_largefile_source=no
+ cat > conftest.$ac_ext <<EOF
+#line 1275 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+#include <stdio.h>
+
+int main() {
+return !ftello;
+; return 0; }
+EOF
+if { (eval echo configure:1286: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 1293 "configure"
+#include "confdefs.h"
+#define _LARGEFILE_SOURCE 1
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+#include <stdio.h>
+
+int main() {
+return !ftello;
+; return 0; }
+EOF
+if { (eval echo configure:1305: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gawk_cv_sys_largefile_source=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gawk_cv_sys_largefile_source" 1>&6
+ if test "$gawk_cv_sys_largefile_source" != no; then
+ cat >> confdefs.h <<EOF
+#define _LARGEFILE_SOURCE $gawk_cv_sys_largefile_source
+EOF
+
+ fi
+ echo $ac_n "checking for _LARGE_FILES value needed for large files""... $ac_c" 1>&6
+echo "configure:1325: checking for _LARGE_FILES value needed for large files" >&5
+if eval "test \"`echo '$''{'gawk_cv_sys_large_files'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ gawk_cv_sys_large_files=no
+ cat > conftest.$ac_ext <<EOF
+#line 1331 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 1349 "configure"
+#include "confdefs.h"
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1361: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gawk_cv_sys_large_files=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gawk_cv_sys_large_files" 1>&6
+ if test "$gawk_cv_sys_large_files" != no; then
+ cat >> confdefs.h <<EOF
+#define _LARGE_FILES $gawk_cv_sys_large_files
+EOF
+
+ fi
+ echo $ac_n "checking for _XOPEN_SOURCE value needed for large files""... $ac_c" 1>&6
+echo "configure:1381: checking for _XOPEN_SOURCE value needed for large files" >&5
+if eval "test \"`echo '$''{'gawk_cv_sys_xopen_source'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ gawk_cv_sys_xopen_source=no
+ cat > conftest.$ac_ext <<EOF
+#line 1387 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+#include <stdio.h>
+
+int main() {
+return !ftello;
+; return 0; }
+EOF
+if { (eval echo configure:1398: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 1405 "configure"
+#include "confdefs.h"
+#define _XOPEN_SOURCE 500
+#include <sys/types.h>
+ int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1];
+
+#include <stdio.h>
+
+int main() {
+return !ftello;
+; return 0; }
+EOF
+if { (eval echo configure:1417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gawk_cv_sys_xopen_source=500
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gawk_cv_sys_xopen_source" 1>&6
+ if test "$gawk_cv_sys_xopen_source" != no; then
+ cat >> confdefs.h <<EOF
+#define _XOPEN_SOURCE $gawk_cv_sys_xopen_source
+EOF
+
+ fi
+ fi
+
+
+echo $ac_n "checking for AIX compilation hacks""... $ac_c" 1>&6
+echo "configure:1440: checking for AIX compilation hacks" >&5
+if eval "test \"`echo '$''{'gawk_cv_aix_hack'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+if test -d /lpp/bos
+then
+ CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED=1"
+ gawk_cv_aix_hack=yes
+else
+ gawk_cv_aix_hack=no
+fi
+
+fi
+echo "$ac_t""${gawk_cv_aix_hack}" 1>&6
+
+
+if test "$ISC" = 1 # will be set by test for ISC
+then
+ CFLAGS="$CFLAGS -D_SYSV3"
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1463: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1468 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1476: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1493 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1511 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1532 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:1567: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1572 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:1588: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in limits.h locale.h stdarg.h unistd.h signum.h sys/param.h string.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1612: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1617 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1622: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+if test "$ac_cv_header_string_h" = yes
+then
+ for ac_hdr in memory.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1654: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1659 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1664: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+else
+ for ac_hdr in strings.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1695: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1700 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:1734: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1739 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1767: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1772 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1789: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1808: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1813 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:1841: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1846 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
+echo "configure:1875: checking type of array argument to getgroups" >&5
+if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_type_getgroups=cross
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1883 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Rendell for this test. */
+#include <sys/types.h>
+#define NGID 256
+#undef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+main()
+{
+ gid_t gidset[NGID];
+ int i, n;
+ union { gid_t gval; long lval; } val;
+
+ val.lval = -1;
+ for (i = 0; i < NGID; i++)
+ gidset[i] = val.gval;
+ n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1,
+ gidset);
+ /* Exit non-zero if getgroups seems to require an array of ints. This
+ happens when gid_t is short but getgroups modifies an array of ints. */
+ exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0);
+}
+
+EOF
+if { (eval echo configure:1908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_type_getgroups=gid_t
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_type_getgroups=int
+fi
+rm -fr conftest*
+fi
+
+if test $ac_cv_type_getgroups = cross; then
+ cat > conftest.$ac_ext <<EOF
+#line 1922 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_getgroups=gid_t
+else
+ rm -rf conftest*
+ ac_cv_type_getgroups=int
+fi
+rm -f conftest*
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_type_getgroups" 1>&6
+cat >> confdefs.h <<EOF
+#define GETGROUPS_T $ac_cv_type_getgroups
+EOF
+
+
+cat > conftest.$ac_ext <<EOF
+#line 1946 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "int.*sprintf" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define SPRINTF_RET int
+EOF
+
+else
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define SPRINTF_RET char *
+EOF
+
+fi
+rm -f conftest*
+
+
+if test "$YACC" = "bison -y" ||
+ { test -f $srcdir/awktab.c && grep 'alloca *(' $srcdir/awktab.c > /dev/null; }
+then
+ # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:1973: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1978 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:1985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:2006: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2011 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:2071: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2076 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2101: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2106 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2129: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:2156: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2164 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:2183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+fi
+cat >> confdefs.h <<\EOF
+#define REGEX_MALLOC 1
+EOF
+
+echo $ac_n "checking for vprintf""... $ac_c" 1>&6
+echo "configure:2210: checking for vprintf" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2215 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vprintf(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vprintf();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vprintf) || defined (__stub___vprintf)
+choke me
+#else
+vprintf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VPRINTF 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$ac_cv_func_vprintf" != yes; then
+echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
+echo "configure:2262: checking for _doprnt" >&5
+if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2267 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+_doprnt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+echo $ac_n "checking for fmod in -lm""... $ac_c" 1>&6
+echo "configure:2316: checking for fmod in -lm" >&5
+ac_lib_var=`echo m'_'fmod | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2324 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fmod();
+
+int main() {
+fmod()
+; return 0; }
+EOF
+if { (eval echo configure:2335: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lm $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+for ac_func in madvise memset memcpy memcmp fmod setlocale strchr strerror \
+ strftime strncasecmp strtod system tzset
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2366: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2371 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2423: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2428 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2433: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2462: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2467 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2490: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:2515: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2523 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:2663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+if (uname) > /dev/null 2>&1
+then
+ case `uname` in
+ *VMS*|*BeOS*)
+ cat >> confdefs.h <<\EOF
+#define GETPGRP_VOID 1
+EOF
+
+ ;;
+ *HP-UX*) # not getpgrp related
+ if test "$GCC" = yes
+ then
+ :
+ else
+ # stupid HP linker leaves the output file
+ # around even when a link fails. This confuses
+ # the alloca tests, so we have to do this
+ # manually. Sucks big time.
+ LIBS="$LIBS -lPW"
+ fi
+
+ # have to do the getpgrp test since won't
+ # fall into the default
+ echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:2710: checking whether getpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check getpgrp if cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2718 "configure"
+#include "confdefs.h"
+
+/*
+ * If this system has a BSD-style getpgrp(),
+ * which takes a pid argument, exit unsuccessfully.
+ *
+ * Snarfed from Chet Ramey's bash pgrp.c test program
+ */
+#include <stdio.h>
+#include <sys/types.h>
+
+int pid;
+int pg1, pg2, pg3, pg4;
+int ng, np, s, child;
+
+main()
+{
+ pid = getpid();
+ pg1 = getpgrp(0);
+ pg2 = getpgrp();
+ pg3 = getpgrp(pid);
+ pg4 = getpgrp(1);
+
+ /*
+ * If all of these values are the same, it's pretty sure that
+ * we're on a system that ignores getpgrp's first argument.
+ */
+ if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3)
+ exit(0);
+
+ child = fork();
+ if (child < 0)
+ exit(1);
+ else if (child == 0) {
+ np = getpid();
+ /*
+ * If this is Sys V, this will not work; pgrp will be
+ * set to np because setpgrp just changes a pgrp to be
+ * the same as the pid.
+ */
+ setpgrp(np, pg1);
+ ng = getpgrp(0); /* Same result for Sys V and BSD */
+ if (ng == pg1) {
+ exit(1);
+ } else {
+ exit(0);
+ }
+ } else {
+ wait(&s);
+ exit(s>>8);
+ }
+}
+
+EOF
+if { (eval echo configure:2773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_getpgrp_void=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_getpgrp_void=no
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$ac_cv_func_getpgrp_void" 1>&6
+if test $ac_cv_func_getpgrp_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define GETPGRP_VOID 1
+EOF
+
+fi
+
+ ;;
+ *) echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:2798: checking whether getpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check getpgrp if cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2806 "configure"
+#include "confdefs.h"
+
+/*
+ * If this system has a BSD-style getpgrp(),
+ * which takes a pid argument, exit unsuccessfully.
+ *
+ * Snarfed from Chet Ramey's bash pgrp.c test program
+ */
+#include <stdio.h>
+#include <sys/types.h>
+
+int pid;
+int pg1, pg2, pg3, pg4;
+int ng, np, s, child;
+
+main()
+{
+ pid = getpid();
+ pg1 = getpgrp(0);
+ pg2 = getpgrp();
+ pg3 = getpgrp(pid);
+ pg4 = getpgrp(1);
+
+ /*
+ * If all of these values are the same, it's pretty sure that
+ * we're on a system that ignores getpgrp's first argument.
+ */
+ if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3)
+ exit(0);
+
+ child = fork();
+ if (child < 0)
+ exit(1);
+ else if (child == 0) {
+ np = getpid();
+ /*
+ * If this is Sys V, this will not work; pgrp will be
+ * set to np because setpgrp just changes a pgrp to be
+ * the same as the pid.
+ */
+ setpgrp(np, pg1);
+ ng = getpgrp(0); /* Same result for Sys V and BSD */
+ if (ng == pg1) {
+ exit(1);
+ } else {
+ exit(0);
+ }
+ } else {
+ wait(&s);
+ exit(s>>8);
+ }
+}
+
+EOF
+if { (eval echo configure:2861: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_getpgrp_void=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_getpgrp_void=no
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$ac_cv_func_getpgrp_void" 1>&6
+if test $ac_cv_func_getpgrp_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define GETPGRP_VOID 1
+EOF
+
+fi
+
+ ;;
+ esac
+else
+ echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:2888: checking whether getpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check getpgrp if cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2896 "configure"
+#include "confdefs.h"
+
+/*
+ * If this system has a BSD-style getpgrp(),
+ * which takes a pid argument, exit unsuccessfully.
+ *
+ * Snarfed from Chet Ramey's bash pgrp.c test program
+ */
+#include <stdio.h>
+#include <sys/types.h>
+
+int pid;
+int pg1, pg2, pg3, pg4;
+int ng, np, s, child;
+
+main()
+{
+ pid = getpid();
+ pg1 = getpgrp(0);
+ pg2 = getpgrp();
+ pg3 = getpgrp(pid);
+ pg4 = getpgrp(1);
+
+ /*
+ * If all of these values are the same, it's pretty sure that
+ * we're on a system that ignores getpgrp's first argument.
+ */
+ if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3)
+ exit(0);
+
+ child = fork();
+ if (child < 0)
+ exit(1);
+ else if (child == 0) {
+ np = getpid();
+ /*
+ * If this is Sys V, this will not work; pgrp will be
+ * set to np because setpgrp just changes a pgrp to be
+ * the same as the pid.
+ */
+ setpgrp(np, pg1);
+ ng = getpgrp(0); /* Same result for Sys V and BSD */
+ if (ng == pg1) {
+ exit(1);
+ } else {
+ exit(0);
+ }
+ } else {
+ wait(&s);
+ exit(s>>8);
+ }
+}
+
+EOF
+if { (eval echo configure:2951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_getpgrp_void=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_getpgrp_void=no
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$ac_cv_func_getpgrp_void" 1>&6
+if test $ac_cv_func_getpgrp_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define GETPGRP_VOID 1
+EOF
+
+fi
+
+fi
+
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:2977: checking for st_blksize in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2982 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_blksize;
+; return 0; }
+EOF
+if { (eval echo configure:2990: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
+if test $ac_cv_struct_st_blksize = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:3011: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3016 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:3025: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:3046: checking whether struct tm is in sys/time.h or time.h" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3051 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:3059: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
+echo "configure:3080: checking for tm_zone in struct tm" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3085 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+int main() {
+struct tm tm; tm.tm_zone;
+; return 0; }
+EOF
+if { (eval echo configure:3093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm_zone=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm_zone=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6
+if test "$ac_cv_struct_tm_zone" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TM_ZONE 1
+EOF
+
+else
+ echo $ac_n "checking for tzname""... $ac_c" 1>&6
+echo "configure:3113: checking for tzname" >&5
+if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3118 "configure"
+#include "confdefs.h"
+#include <time.h>
+#ifndef tzname /* For SGI. */
+extern char *tzname[]; /* RS6000 and others reject char **tzname. */
+#endif
+int main() {
+atoi(*tzname);
+; return 0; }
+EOF
+if { (eval echo configure:3128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_var_tzname=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_var_tzname=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_var_tzname" 1>&6
+ if test $ac_cv_var_tzname = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TZNAME 1
+EOF
+
+ fi
+fi
+
+
+echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
+echo "configure:3151: checking whether char is unsigned" >&5
+if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$GCC" = yes; then
+ # GCC predefines this symbol on systems where it applies.
+cat > conftest.$ac_ext <<EOF
+#line 3158 "configure"
+#include "confdefs.h"
+#ifdef __CHAR_UNSIGNED__
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_c_char_unsigned=yes
+else
+ rm -rf conftest*
+ ac_cv_c_char_unsigned=no
+fi
+rm -f conftest*
+
+else
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3180 "configure"
+#include "confdefs.h"
+/* volatile prevents gcc2 from optimizing the test away on sparcs. */
+#if !defined(__STDC__) || __STDC__ != 1
+#define volatile
+#endif
+main() {
+ volatile char c = 255; exit(c < 0);
+}
+EOF
+if { (eval echo configure:3190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_char_unsigned=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_char_unsigned=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+ cat >> confdefs.h <<\EOF
+#define __CHAR_UNSIGNED__ 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:3214: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3219 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:3268: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+
+
+echo $ac_n "checking for ANSI stringizing capability""... $ac_c" 1>&6
+echo "configure:3291: checking for ANSI stringizing capability" >&5
+if eval "test \"`echo '$''{'gawk_cv_c_stringize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3296 "configure"
+#include "confdefs.h"
+
+#define x(y) #y
+
+char *s = x(teststring);
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "#teststring" >/dev/null 2>&1; then
+ rm -rf conftest*
+ gawk_cv_c_stringize=no
+else
+ rm -rf conftest*
+ gawk_cv_c_stringize=yes
+fi
+rm -f conftest*
+
+fi
+
+if test "${gawk_cv_c_stringize}" = yes
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRINGIZE 1
+EOF
+
+fi
+echo "$ac_t""${gawk_cv_c_stringize}" 1>&6
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile doc/Makefile test/Makefile awklib/Makefile config.h:configh.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@YACC@%$YACC%g
+s%@LN_S@%$LN_S%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@ALLOCA@%$ALLOCA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile test/Makefile awklib/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h:configh.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+date > stamp-h
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/awk/configure.in b/contrib/awk/configure.in
new file mode 100644
index 000000000000..7867034fb76b
--- /dev/null
+++ b/contrib/awk/configure.in
@@ -0,0 +1,165 @@
+dnl
+dnl configure.in --- autoconf input file for gawk
+dnl
+dnl Copyright (C) 1995-2000 the Free Software Foundation, Inc.
+dnl
+dnl This file is part of GAWK, the GNU implementation of the
+dnl AWK Programming Language.
+dnl
+dnl GAWK is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl GAWK is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+dnl
+
+dnl Process this file with autoconf to produce a configure script.
+
+dnl this makes sure that the local install-sh gets found
+dnl define(AC_CONFIG_AUX_DIR,)
+
+dnl This is the configure.in script proper
+AC_INIT(awk.h)
+AC_PREREQ(2.12)
+AC_CONFIG_HEADER(config.h:configh.in)
+
+dnl Additional argument stuff
+AC_ARG_ENABLE(bitops, [ --enable-bitops Enable Octal and Hex constants and bit functions], AC_DEFINE(BITOPS))
+AC_ARG_ENABLE(non-decimal-data, [ --enable-non-decimal-data Enable Octal and Hex constants as valid input data], AC_DEFINE(NONDECDATA))
+
+dnl checks for programs
+AC_PROG_YACC
+AC_PROG_LN_S
+AC_PROG_CC
+AC_PROG_CPP
+
+# This is a hack. Different versions of install on different systems
+# are just too different. Chuck it and use install-sh.
+INSTALL="$srcdir/install-sh -c"; export INSTALL
+AC_PROG_INSTALL
+
+AC_PROG_MAKE_SET
+
+if test "$CFLAGS" = ""
+then
+dnl no user provided CFLAGS, feel free to do this our way
+ if test "$GCC" = yes
+ then
+ CFLAGS="-g -O"
+ else
+dnl go for speed, not debugging. :-)
+ CFLAGS="-O"
+ fi
+fi
+
+# This is mainly for my use during testing and development.
+# Yes, it's a bit of a hack.
+if test -f $srcdir/.developing
+then
+ AC_DEFINE(BITOPS)
+ AC_DEFINE(NONDECDATA)
+ CFLAGS="$CFLAGS -DARRAYDEBUG"
+fi
+
+AC_SUBST(CFLAGS)
+
+dnl checks for systems
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+GAWK_AC_SYS_LARGEFILE
+GAWK_AC_AIX_TWEAK
+
+if test "$ISC" = 1 # will be set by test for ISC
+then
+dnl need -D_SYSV3 for ISC
+ CFLAGS="$CFLAGS -D_SYSV3"
+fi
+
+dnl checks for header files
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(limits.h locale.h stdarg.h unistd.h signum.h sys/param.h string.h)
+if test "$ac_cv_header_string_h" = yes
+then
+ AC_CHECK_HEADERS(memory.h)
+else
+ AC_CHECK_HEADERS(strings.h)
+fi
+
+dnl checks for typedefs
+AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+AC_SIZE_T
+AC_TYPE_GETGROUPS
+AC_EGREP_HEADER([int.*sprintf], stdio.h,
+ AC_DEFINE(SPRINTF_RET, int),
+ AC_DEFINE(SPRINTF_RET, char *))
+
+dnl checks for functions
+if test "$YACC" = "bison -y" ||
+ { test -f $srcdir/awktab.c && grep 'alloca *(' $srcdir/awktab.c > /dev/null; }
+then
+ AC_FUNC_ALLOCA
+fi
+AC_DEFINE(REGEX_MALLOC)
+AC_FUNC_VPRINTF
+
+AC_CHECK_LIB(m, fmod)
+AC_CHECK_FUNCS(madvise memset memcpy memcmp fmod setlocale strchr strerror \
+ strftime strncasecmp strtod system tzset)
+
+dnl see if we have mmap
+AC_FUNC_MMAP
+
+dnl check for how to use getpgrp
+dnl have to hardwire it for VMS POSIX. Sigh.
+if (uname) > /dev/null 2>&1
+then
+ case `uname` in
+ *VMS*|*BeOS*)
+ AC_DEFINE(GETPGRP_VOID)
+ ;;
+ *HP-UX*) # not getpgrp related
+ if test "$GCC" = yes
+ then
+ :
+ else
+ # stupid HP linker leaves the output file
+ # around even when a link fails. This confuses
+ # the alloca tests, so we have to do this
+ # manually. Sucks big time.
+ LIBS="$LIBS -lPW"
+ fi
+
+ # have to do the getpgrp test since won't
+ # fall into the default
+ AC_FUNC_GETPGRP
+ ;;
+ *) AC_FUNC_GETPGRP
+ ;;
+ esac
+else
+ AC_FUNC_GETPGRP
+fi
+
+dnl checks for structure members
+AC_STRUCT_ST_BLKSIZE
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_STRUCT_TIMEZONE
+
+dnl checks for compiler characteristics
+AC_C_CHAR_UNSIGNED
+AC_C_CONST
+GAWK_AC_C_STRINGIZE
+
+AC_OUTPUT(Makefile doc/Makefile test/Makefile awklib/Makefile, [date > stamp-h])
diff --git a/contrib/awk/doc/Makefile.in b/contrib/awk/doc/Makefile.in
new file mode 100644
index 000000000000..edcf40465602
--- /dev/null
+++ b/contrib/awk/doc/Makefile.in
@@ -0,0 +1,129 @@
+# Makefile for GNU Awk documentation.
+#
+# Copyright (C) 1993-2000 the Free Software Foundation, Inc.
+#
+# This file is part of GAWK, the GNU implementation of the
+# AWK Programming Language.
+#
+# GAWK 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 2 of the License, or
+# (at your option) any later version.
+#
+# GAWK 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+binprefix =
+manprefix =
+
+bindir = @bindir@
+libdir = @libdir@
+mandir = @mandir@/man1
+manext = .1
+infodir = @infodir@
+datadir = @datadir@/awk
+
+TEXI2DVI = texi2dvi
+TEX = tex
+MAKEINFO = makeinfo --no-split
+TROFF = groff -t -Tps
+SEDME = sed -e "s/^level0 restore/level0 restore flashme 100 72 moveto (Copyright `date '+%m-%d-%y %T'`, FSF, Inc. (all)) show/" \
+ -e "s/^\/level0 save def/\/level0 save def 30 -48 translate/"
+
+DOCS= gawk.1 igawk.1 gawk.texi
+
+TEXFILES= gawk.aux gawk.cp gawk.cps gawk.fn gawk.fns gawk.ky gawk.kys \
+ gawk.pg gawk.pgs gawk.toc gawk.tp gawk.tps gawk.vr gawk.vrs
+
+ALLDOC= gawk.dvi $(TEXFILES) gawk.log awkcard.tr
+
+CARDSRC = $(srcdir)/macros $(srcdir)/cardfonts $(srcdir)/colors awkcard.tr
+CARDSRC_N = $(srcdir)/macros $(srcdir)/cardfonts $(srcdir)/no.colors awkcard.tr
+CARDFILES= $(CARDSRC) ad.block awkcard.in setter.outline
+
+# Use this if your troff can correctly handle macros from 'colors' file
+AWKCARD = awkcard.ps
+
+# Uncomment the following definition of AWKCARD if your troff can produce
+# Postscript but still has troubles with macros from 'colors'. As this
+# is not groff you will have to change TROFF macro as well. Do not forget
+# to ensure that awkcard.tr is processed by tbl.
+#AWKCARD = awkcard.nc
+
+all: $(DOCS) info
+
+install: $(mandir)/gawk$(manext) $(mandir)/igawk$(manext) $(infodir)/gawk.info
+
+$(infodir)/gawk.info::
+ -if test -f gawk.info; then d=.; \
+ else d=$(srcdir); fi; \
+ if [ -f $(infodir)/dir -a -f $(infodir)/gawk.info ] \
+ && cmp $$d/gawk.info $(infodir)/gawk.info > /dev/null \
+ && grep '(gawk)' $(infodir)/dir > /dev/null; then \
+ exit 0; \
+ fi; \
+ $(INSTALL_DATA) $$d/gawk.info $(infodir)/gawk.info ; \
+ if $(SHELL) -c 'install-info --version' > /dev/null 2>&1 ; \
+ then install-info --info-dir=$(infodir) gawk.info ; \
+ else true ; fi; exit 0
+
+$(mandir)/gawk$(manext):: gawk.1
+ $(INSTALL_DATA) $(srcdir)/gawk.1 $(mandir)/gawk$(manext)
+
+$(mandir)/igawk$(manext):: igawk.1
+ $(INSTALL_DATA) $(srcdir)/igawk.1 $(mandir)/igawk$(manext)
+
+uninstall:
+ rm -f $(mandir)/gawk$(manext) $(mandir)/igawk$(manext) $(infodir)/gawk.info*
+
+dvi: gawk.dvi
+
+gawk.dvi: gawk.texi
+ -TEXINPUTS=$(srcdir):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/gawk.texi
+
+info: gawk.info
+
+gawk.info: gawk.texi
+ $(MAKEINFO) $(srcdir)/gawk.texi
+
+postscript: dvi gawk.1 igawk.1 $(AWKCARD)
+ -groff -man $(srcdir)/gawk.1 > gawk.1.ps
+ -groff -man $(srcdir)/igawk.1 > igawk.1.ps
+ dvips -o gawk.ps gawk.dvi
+
+awkcard.tr: awkcard.in
+ sed 's:SRCDIR:$(srcdir):' < $(srcdir)/awkcard.in > awkcard.tr
+
+awkcard.ps: $(CARDFILES)
+ $(TROFF) $(CARDSRC) | $(SEDME) | cat $(srcdir)/setter.outline - > awkcard.ps
+
+awkcard.nc: $(CARDFILES)
+ $(TROFF) $(CARDSRC_N) | $(SEDME) | cat $(srcdir)/setter.outline - > awkcard.ps && touch awkcard.nc
+
+clean:
+ rm -f *.ps $(ALLDOC) *~ awkcard.nc
+
+distclean: clean
+ rm -f Makefile
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use; it"
+ @echo "deletes files that may require special tools to rebuild."
+ rm -f gawk.info
diff --git a/contrib/awk/doc/README.card b/contrib/awk/doc/README.card
new file mode 100644
index 000000000000..ef77cdacec7b
--- /dev/null
+++ b/contrib/awk/doc/README.card
@@ -0,0 +1,19 @@
+Mon Dec 9 12:45:48 EST 1996
+
+The AWK reference card included here requires a modern version of troff
+(ditroff). GNU Troff (groff) is known to work.
+
+If your troff is able to produce Postscript but does not know how to
+properly use the macros from `colors' file then try to uncomment in
+Makefile the defintion which sets AWKCARD to awkcard.nc (no colors).
+This will definitely require changes to the TROFF macro and you have to
+ensure that the tbl preprocessor is called. For example, the following
+modifications on NeXT:
+
+TROFF = tbl
+SEDME = ptroff -t | sed -e \
+ "s/^level0 restore/level0 restore flashme 100 72 moveto\
+ (Copyright `date`, FSF, Inc. (all)) show/" \
+ -e "s/^\/level0 save def/\/level0 save def 30 -48 translate/"
+
+will produce a correctly formatted, albeit monochromatic, reference card.
diff --git a/contrib/awk/doc/ad.block b/contrib/awk/doc/ad.block
new file mode 100644
index 000000000000..d31f5d50a043
--- /dev/null
+++ b/contrib/awk/doc/ad.block
@@ -0,0 +1,49 @@
+.\" AWK Reference Card --- Arnold Robbins, arnold@gnu.org
+.\" This file is the Ad block (included in cover)
+.\"
+.\" Copyright (C) 1996, 98 Free Software Foundation, Inc.
+.\"
+.\" Permission is granted to make and distribute verbatim copies of
+.\" this reference card provided the copyright notice and this permission
+.\" notice are preserved on all copies.
+.\"
+.\" Permission is granted to process this file through troff and print the
+.\" results, provided the printed document carries copying permission
+.\" notice identical to this one except for the removal of this paragraph
+.\" (this paragraph not being relevant to the printed reference card).
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" reference card under the conditions for verbatim copying, provided that
+.\" the entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Permission is granted to copy and distribute translations of this
+.\" reference card into another language, under the above conditions for
+.\" modified versions, except that this permission notice may be stated in
+.\" a translation approved by the Foundation.
+.\"
+.ft HB
+.ps 10
+.vs 12
+.ES
+.nf
+.ce 7
+\*(CBFree Software Foundation, Inc.
+.ft H
+59 Temple Place \(em Suite 330
+Boston, MA 02111-1307 USA
+Phone: +1-617-542-5942
+Fax (including Japan): +1-617-542-2652
+E-mail: gnu@gnu.org
+URL: http://www.gnu.org
+
+.ce 7
+.ft HB
+\*(CGFree Software
+Source Distributions on CD-ROM
+Deluxe Distributions
+Emacs, Gawk, Make and GDB Manuals
+Emacs and GDB References\*(CX
+.EB "\f(HBOTHER FSF PRODUCTS:\*(FR"
+.ps
+.vs
diff --git a/contrib/awk/doc/awkcard.in b/contrib/awk/doc/awkcard.in
new file mode 100644
index 000000000000..ac1e8e56c74c
--- /dev/null
+++ b/contrib/awk/doc/awkcard.in
@@ -0,0 +1,1550 @@
+.\" AWK Reference Card --- Arnold Robbins, arnold@gnu.org
+.\"
+.\" Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+.\"
+.\" Permission is granted to make and distribute verbatim copies of
+.\" this reference card provided the copyright notice and this permission
+.\" notice are preserved on all copies.
+.\"
+.\" Permission is granted to process this file through troff and print the
+.\" results, provided the printed document carries copying permission
+.\" notice identical to this one except for the removal of this paragraph
+.\" (this paragraph not being relevant to the printed reference card).
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" reference card under the conditions for verbatim copying, provided that
+.\" the entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Permission is granted to copy and distribute translations of this
+.\" reference card into another language, under the above conditions for
+.\" modified versions, except that this permission notice may be stated in
+.\" a translation approved by the Foundation.
+.\"
+.\" Strings to save typing
+.ds AK \*(FCawk\*(FR
+.ds GK \*(FCgawk\*(FR
+.ds NK Bell Labs \*(FCawk\*(FR
+.ds MK \*(FCmawk\*(FR
+.\"
+.\"
+.de TD\" tab defaults
+.ta .2i .78i 1i 1.2i 1.4i 1.7i
+..
+.de TE
+.TD
+..
+
+.sp
+.ce
+\*(CD\f(HB\s+8AWK REFERENCE\s0\*(FR
+.sp
+.\" --- Table Of Contents
+.ta 2.4i 2.6iR
+.lc .
+.ES
+.in +.2i
+.nf
+\*(FRAWK Program Execution 4
+Action Statements 7
+Arrays 9
+Bug Reports 15
+Command Line Arguments (standard) 2
+Command Line Arguments (\*(GK) 3
+Command Line Arguments (\*(MK) 4
+Conversions And Comparisons 10
+Copying Permissions 16
+Definitions 2
+Environment Variables 16
+Escape Sequences 7
+Expressions 9
+Fields 6
+FTP Information 16
+Historical Features (\*(GK) 16
+Input Control 11
+Lines And Statements 5
+.ig
+Localization 10
+..
+Numeric Functions 13
+Output Control 11
+Pattern Elements 7
+POSIX Character Classes (\*(GK) 6
+Printf Formats 12
+Records 6
+Regular Expressions 5
+Special Filenames 13
+String Functions 14
+Time Functions (\*(GK) 15
+User-defined Functions 15
+Variables 8\*(CX
+.in -.2i
+.EB "\s+2\f(HBCONTENTS\*(FR\s0"
+.sp
+.TD
+.fi
+\*(CD\*(FRThis reference card was written by Arnold Robbins.
+Brian Kernighan and Michael Brennan reviewed it; we thank them
+for their help.
+.sp
+.SL
+.sp
+.so SRCDIR/ad.block
+.\" a subtlety here; this line changes color. We rely on it
+.\" also to provide a blank line.
+\*(CD
+.SL
+.nf
+\*(FR\(co Copyright 1996-2000, Free Software Foundation
+59 Temple Place \(em Suite 330
+Boston, MA 02111-1307 USA
+.nf
+.BT
+
+
+.\"
+.\"
+.\" --- Definitions
+.fi
+.ES
+\*(CDThis card describes POSIX AWK, as well as the three
+freely available \*(AK implementations
+(see \fHFTP Information\fP below).
+\*(CLCommon extensions (in two or more versions) are printed in light blue.
+\*(CBFeatures specific to just one version\(emusually GNU AWK (\*(GK)\(emare
+printed in dark blue.
+\*(CRExceptions and deprecated features are printed in red.
+\*(CDFeatures mandated by POSIX are printed in black.
+.sp .5
+Several type faces are used to clarify the meaning:
+.br
+.nr IN \w'\(bu '
+\(bu \*(FC\*(CN\fP is used for computer input.
+.br
+.fi
+.in +\n(INu
+.ti -\n(INu
+\(bu\|\^\*(FI\*(IN\fP is used to indicate user input and for syntactic
+placeholders, such as \*(FIvariable\fP or \*(FIaction\fP.
+.in -\n(INu
+.br
+\(bu \*(RN is used for explanatory text.
+.sp .5
+\*(FInumber\fP \- a floating point number as in ANSI C, such as
+\*(FC3\*(FR,
+\*(FC2.3\*(FR,
+\*(FC.4\*(FR,
+\*(FC1.4e2\*(FR
+or
+\*(FC4.1E5\*(FR.
+.sp .5
+\*(FIescape sequences\fP \- a special sequence of characters beginning
+with a backslash, used to describe otherwise unprintable characters.
+(See \fHEscape Sequences\fP below.)
+.sp .5
+\*(FIstring\fP \- a group of characters enclosed in double quotes.
+Strings may contain \*(FIescape sequences\*(FR.
+.sp .5
+\*(FIregexp\fP \- a regular expression, either a regexp constant
+enclosed in forward slashes, or a dynamic regexp computed at run-time.
+Regexp constants may contain \*(FIescape sequences\*(FR.
+.sp .5
+\*(FIname\fP \- a variable, array or function name.
+.sp .5
+\*(FIentry\fP(\*(FIN\fP) \- entry \*(FIentry\fP in section \*(FIN\fP of the
+UNIX reference manual.
+.sp .5
+\*(FIpattern\fP \- an expression describing an input record to be matched.
+.sp .5
+\*(FIaction\fP \- statements to execute when an input record is matched.
+.sp .5
+\*(FIrule\fP \- a pattern-action pair, where the pattern or action may
+be missing.\*(CX
+.EB \s+2\f(HBDEFINITIONS\*(FR\s0
+
+.\" --- Command Line Arguments
+.ES
+.fi
+\*(CDCommand line arguments control setting the field separator,
+setting variables before the \*(FCBEGIN\fP rule is run, and
+the location of AWK program source code.
+Implementation-specific command line arguments change
+the behavior of the running interpreter.
+.sp .5
+.TS
+expand;
+l lw(2.2i).
+\*(FC\-F \*(FIfs\*(FR use \*(FIfs\fP for the input field separator.
+\*(FC\-v\*(FI var\*(FC\^=\^\*(FIval\*(FR T{
+assign the value \*(FIval\*(FR, to the variable \*(FIvar\*(FR,
+before execution of the program begins. Such
+variable values are available to the \*(FCBEGIN\fP rule.
+T}
+\*(FC\-f \*(FIprog-file\*(FR T{
+read the AWK program source from the file
+\*(FIprog-file\*(FR, instead of from the first command
+line argument. Multiple \*(FC\-f\*(FR options may be used.
+T}
+\*(FC\-\^\-\*(FR signal the end of options.
+.TE
+.sp .5
+.fi
+\*(CLThe following options are accepted by both \*(NK and \*(GK
+\*(CR(ignored by \*(GK, not in \*(MK).\*(CL
+.sp .5
+.nf
+.TS
+expand, tab(%);
+l lw(2.2i).
+\*(FC\-mf \*(FIval\*(FR%set the maximum number of fields to \*(FIval\fP
+\*(FC\-mr \*(FIval\*(FR%set the maximum record size to \*(FIval\fP\*(CX
+.TE
+.EB "\s+2\f(HBCOMMAND LINE ARGUMENTS (standard)\*(FR\s0"
+
+.BT
+
+.ES
+.fi
+\*(CDThe following options are specific to \*(GK. The \*(FC\-W\*(FR
+forms are for full POSIX compliance.
+.sp .5
+.ig
+.\" This option is left undocumented, on purpose.
+\*(FC\-\^\-nostalgia\*(FR
+\*(FC\-W nostalgia\*(FR%T{
+provide a moment of nostalgia for
+long time \*(AK users.
+T}
+..
+.TS
+expand, tab(%);
+ls
+l lw(1.8i).
+\*(FC\-\^\-field-separator \*(FIfs\*(FR
+%just like \*(FC\-F\fP
+\*(FC\-\^\-assign \*(FIvar\*(FC\^=\^\*(FIval\*(FR%just like \*(FC\-v\fP
+\*(FC\-\^\-file \*(FIprog-file%\*(FRjust like \*(FC\-f\fP
+\*(FC\-\^\-traditional\*(FR
+\*(FC\-\^\-compat\*(FR
+\*(FC\-W compat\*(FR
+\*(FC\-W traditional\*(FR%T{
+turn off \*(GK-specific extensions
+(\*(FC\-\^\-traditional\*(FR preferred).
+T}
+\*(FC\-\^\-copyleft\*(FR
+\*(FC\-\^\-copyright\*(FR
+\*(FC\-W copyleft\*(FR
+\*(FC\-W copyright\*(FR%T{
+print the short version of the GNU
+copyright information on \*(FCstdout\*(FR.
+T}
+\*(FC\-\^\-help\*(FR
+\*(FC\-\^\-usage\*(FR
+\*(FC\-W help\*(FR
+\*(FC\-W usage\*(FR%T{
+print a short summary of the available
+options on \*(FCstdout\*(FR, then exit zero.
+T}
+\*(FC\-\^\-lint\*(FR
+\*(FC\-W lint\*(FR%T{
+warn about constructs that are dubious
+or non-portable to other \*(AKs.
+T}
+\*(FC\-\^\-lint\-old\*(FR
+\*(FC\-W lint\-old\*(FR%T{
+warn about constructs that are not
+portable to the original version of
+Unix \*(AK.
+T}
+\*(FC\-\^\-posix\*(FR
+\*(FC\-W posix\*(FR%T{
+disable common and GNU extensions.
+Enable \*(FIinterval expressions\*(FR in regular
+expression matching (see \fHRegular
+Expressions\fP below).
+T}
+\*(FC\-\^\-re\-interval\*(FR
+\*(FC\-W re\-interval\*(FR%T{
+enable \*(FIinterval expressions\*(FR in regular
+expression matching (see \fHRegular
+Expressions\fP below). Useful if
+\*(FC\-\^\-posix\*(FR is not specified.
+T}
+\*(FC\-\^\-source '\*(FItext\*(FC'\*(FR
+\*(FC\-W source '\*(FItext\*(FC'\*(FR%use \*(FItext\*(FR as AWK program source code.
+\*(FC\-\^\-version\*(FR
+\*(FC\-W version\*(FR%T{
+print version information on \*(FCstdout\fP
+and exit zero.
+T}
+.TE
+.sp .5
+.fi
+In compatibility mode,
+any other options are flagged as illegal, but are otherwise ignored.
+In normal operation, as long as program text has been supplied, unknown
+options are passed on to the AWK program in
+\*(FCARGV\*(FR
+for processing. This is most useful for running AWK
+programs via the \*(FC#!\*(FR executable interpreter mechanism.\*(CB
+.EB "\s+2\f(HBCOMMAND LINE ARGUMENTS (\*(GK\f(HB)\*(FR\s0"
+
+.BT
+
+.ES
+.fi
+\*(CDThe following options are specific to \*(MK.
+.sp .5
+.fi
+.TS
+expand;
+l lw(1.8i).
+\*(FC\-W dump\*(FR T{
+print an assembly listing of the program to
+\*(FCstdout\fP and exit zero.
+T}
+\*(FC\-W exec \*(FIfile\*(FR T{
+read program text from \*(FIfile\fP. No other
+options are processed. Useful with \*(FC#!\fP.
+T}
+\*(FC\-W interactive\*(FR T{
+unbuffer \*(FCstdout\fP and line buffer \*(FCstdin\fP.
+Lines are always records, ignoring \*(FCRS\fP
+T}
+\*(FC\-W posix_space\*(FR T{
+\*(FC\en\*(FR separates fields when \*(FCRS = "\^"\fP.
+T}
+\*(FC\-W sprintf=\*(FInum\*(FR T{
+adjust the size of \*(MK's internal
+\*(FCsprintf\*(FR buffer.
+T}
+\*(FC\-W version\*(FR T{
+print version and copyright on
+\*(FCstdout\fP and limit information on \*(FCstderr\fP
+and exit zero.
+T}
+.TE
+.sp .5
+.fi
+The options may be abbreviated using just the first letter, e.g.,
+\*(FC\-We\*(FR,
+\*(FC\-Wv\*(FR
+and so on.\*(CB
+.EB "\s+2\f(HBCOMMAND LINE ARGUMENTS (\*(MK\f(HB)\*(FR\s0"
+
+.\" --- Awk Program Execution
+.ES
+.fi
+\*(CDAWK programs are a sequence of pattern-action statements
+and optional function definitions.
+.sp .5
+ \*(FIpattern\*(FC { \*(FIaction statements\*(FC }\*(FR
+.br
+ \*(FCfunction \*(FIname\*(FC(\*(FIparameter list\*(FC) { \*(FIstatements\*(FC }\*(FR
+.sp .5
+\*(AK first reads the program source from the
+\*(FIprog-file\*(FR(s), if specified,
+\*(CBfrom arguments to \*(FC\-\^\-source\*(FR,\*(CD
+or from the first non-option argument on the command line.
+The program text is read as if all the \*(FIprog-file\*(FR(s)
+\*(CBand command line
+source texts\*(CD had been concatenated.
+.sp .5
+AWK programs execute in the following order.
+First, all variable assignments specified via the \*(FC\-v\fP
+option are performed.
+Next, \*(AK executes the code in the
+\*(FCBEGIN\fP rules(s), if any, and then proceeds to read
+the files \*(FC1\fP through \*(FCARGC \- 1\fP in the \*(FCARGV\fP array.
+(Adjusting \*(FCARGC\fP and \*(FCARGV\fP thus provides control over
+the input files that will be processed.)
+If there are no files named on the command line,
+\*(AK reads the standard input.
+.sp .5
+If a command line argument has the form
+\*(FIvar\*(FC=\*(FIval\*(FR,
+it is treated as a variable assignment. The variable
+\*(FIvar\fP will be assigned the value \*(FIval\*(FR.
+(This happens after any \*(FCBEGIN\fP rule(s) have been run.)
+... delete this paragraph if no space
+Command line variable assignment
+is most useful for dynamically assigning values to the variables
+\*(AK uses to control how input is broken into fields and records. It
+is also useful for controlling state if multiple passes are needed over
+a single data file.
+.sp .5
+If the value of a particular element of \*(FCARGV\fP is empty
+(\*(FC"\^"\*(FR), \*(AK skips over it.
+.sp .5
+For each record in the input, \*(AK tests to see if it matches any
+\*(FIpattern\fP in the AWK program.
+For each pattern that the record matches, the associated
+\*(FIaction\fP is executed.
+The patterns are tested in the order they occur in the program.
+.sp .5
+Finally, after all the input is exhausted,
+\*(AK executes the code in the \*(FCEND\fP rule(s), if any.
+.sp .5
+If a program only has a \*(FCBEGIN\fP rule, no input files are processed.
+If a program only has an \*(FCEND\fP rule, the input will be read.
+\*(CX
+.EB "\s+2\f(HBAWK PROGRAM EXECUTION\*(FR\s0"
+
+
+.BT
+
+.\" --- Lines And Statements
+.ES
+.fi
+\*(CDAWK is a line oriented language. The pattern comes first, and then the
+action. Action statements are enclosed in \*(FC{\fP and \*(FC}\*(FR.
+Either the pattern or the action may be missing, but
+not both. If the pattern is missing, the action will be
+executed for every input record.
+A missing action is equivalent to
+.sp .5
+ \*(FC{ print }\fP
+.sp .5
+which prints the entire record.
+.sp .5
+Comments begin with the \*(FC#\*(FR character, and continue until the
+end of the line.
+Normally, a statement ends with a newline, but lines ending in
+a ``,'',
+\*(FC{\*(FR,
+\*(CB\*(FC?\*(FR,
+\*(FC:\*(FR,\*(CD
+\*(FC&&\*(FR
+or
+\*(FC||\*(FR
+are automatically continued.
+Lines ending in \*(FCdo\fP or \*(FCelse\fP
+also have their statements automatically continued on the following line.
+In other cases, a line can be continued by ending it with a ``\e'',
+in which case the newline will be ignored. However, a ``\e'' after a
+\*(FC#\*(FR is not special.
+.sp .5
+Multiple statements may be put on one line by separating them with a ``;''.
+This applies to both the statements within the action part of a
+pattern-action pair (the usual case)
+and to the pattern-action statements themselves.\*(CX
+.EB "\s+2\f(HBLINES AND STATEMENTS\*(FR\s0"
+
+
+
+.\" --- Regular Expressions
+.ES
+.fi
+\*(CDRegular expressions are the extended kind originally defined by
+\*(FCegrep\fP.
+\*(CBAdditional GNU regexp operators are supported by \*(GK.
+A \*(FIword-constituent\fP character is a letter, digit, or
+underscore (\*(FC_\fP).\*(CD
+.sp .5
+.TS
+center, tab(~);
+cp8 sp8
+cp8 sp8
+lp8|lp8.
+.\" .vs 10
+_
+Summary of Regular Expressions
+In Decreasing Precedence
+_
+\*(FC(\^\*(FIr\*(FC)\*(FR~regular expression (for grouping)
+\*(FIc\*(FR~if non-special char, matches itself
+\*(FC\e\*(FI\^c\*(FR~turn off special meaning of \*(FIc\fP
+\*(FC^\*(FR~beginning of string (note: \*(FInot\fP line)
+\*(FC$\*(FR~end of string (note: \*(FInot\fP line)
+\*(FC.\*(FR~any single character, including newline
+\*(FC[\*(FR...\*(FC]\*(FR~any one character in ... or range
+\*(FC[^\*(FR...\*(FC]\*(FR~any one character not in ... or range
+\*(CB\*(FC\ey\*(FR~word boundary
+\*(FC\eB\*(FR~middle of a word
+\*(FC\e<\*(FR~beginning of a word
+\*(FC\e>\*(FR~end of a word
+\*(FC\ew\*(FR~any word-constituent character
+\*(FC\eW\*(FR~any non-word-constituent character
+\*(FC\e`\*(FR~beginning of a buffer (string)
+\*(FC\e'\*(FR~end of a buffer (string)\*(CD
+\*(FIr\*(FC*\*(FR~zero or more occurrences of \*(FIr\*(FR
+\*(FIr\*(FC+\*(FR~one or more occurrences of \*(FIr\*(FR
+\*(FIr\*(FC?\*(FR~zero or one occurrences of \*(FIr\*(FR
+\*(FIr\*(FC{\*(FIn\*(FC,\*(FIm\*(FC}\*(FR~\*(FIn\fP to \*(FIm\fP occurrences of \*(FIr\*(FR \*(CR(POSIX: see note below)\*(CD
+\*(FIr1\*(FC|\|\*(FIr2\*(FR~\*(FIr1\*(FR or \*(FIr2\*(FR
+.TE
+.sp .5
+.fi
+\*(CRThe \*(FIr\*(FC{\*(FIn\*(FC,\*(FIm\*(FC}\*(FR notation is called an
+\*(FIinterval expression\fP. POSIX mandates it for AWK regexps, but
+most \*(AKs don't implement it. \*(CBUse \*(FC\-\^\-re\-interval\*(FR
+or \*(FC\-\^\-posix\*(FR to enable
+this feature in \*(GK.\*(CX
+.EB "\s+2\f(HBREGULAR EXPRESSIONS\*(FR\s0"
+
+
+.BT
+
+.\" --- POSIX Character Classes (gawk)
+.ES
+.fi
+\*(CDIn regular expressions, within character ranges
+(\*(FC[\*(FR...\*(FC]\*(FR),
+the notation \*(FC[[:\*(FIclass\*(FC:]]\*(FR defines characters classes:
+.sp .5
+.TS
+center, tab(~);
+lp8 lp8 lp8 lp8.
+\*(FCalnum\*(FR~alphanumeric~\*(FClower\*(FR~lower-case
+\*(FCalpha\*(FR~alphabetic~\*(FCprint\*(FR~printable
+\*(FCblank\*(FR~space or tab~\*(FCpunct\*(FR~punctuation
+\*(FCcntrl\*(FR~control~\*(FCspace\*(FR~whitespace
+\*(FCdigit\*(FR~decimal~\*(FCupper\*(FR~upper-case
+\*(FCgraph\*(FR~non-spaces~\*(FCxdigit\*(FR~hexadecimal\*(CB
+.TE
+.fi
+.EB "\s+2\f(HBPOSIX CHARACTER CLASSES (\*(GK\f(HB)\*(FR\s0"
+
+.\" --- Records
+.ES
+.fi
+\*(CDNormally, records are separated by newline characters.
+Assigning values to the built-in variable \*(FCRS\*(FR
+controls how records are separated.
+If \*(FCRS\fP is any single character, that character separates records.
+\*(CLOtherwise, \*(FCRS\fP is a regular expression.
+\*(CR(Not \*(NK.)\*(CL
+Text in the input that matches this
+regular expression will separate the record.
+\*(CB\*(GK sets \*(FCRT\*(FR to the value of the
+input text that matched the regular expression.
+The value of \*(FCIGNORECASE\fP
+will also affect how records are separated when
+\*(FCRS\fP is a regular expression.\*(CD
+If \*(FCRS\fP is set to the null string,
+then records are separated by one or more blank lines.
+When \*(FCRS\fP is set to the null string,
+the newline character always acts as
+a field separator, in addition to whatever value
+\*(FCFS\fP may have.
+\*(CB\*(MK does not apply exceptional rules to \*(FCFS\fP
+when \*(FCRS = "\^"\fP.\*(CX
+.EB \s+2\f(HBRECORDS\*(FR\s0
+
+.\" --- Fields
+.ES
+.fi
+\*(CDAs each input record is read, \*(AK splits the record into
+\*(FIfields\*(FR, using the value of the \*(FCFS\fP
+variable as the field separator.
+If \*(FCFS\fP is a single character,
+fields are separated by that character.
+\*(CLIf \*(FCFS\fP is the null string,
+then each individual character becomes a separate field.\*(CD
+Otherwise, \*(FCFS\fP is expected to be a full regular expression.
+In the special case that \*(FCFS\fP
+is a single space, fields are separated
+by runs of spaces and/or tabs
+\*(CLand/or newlines\*(CD.
+Leading and trailing whitespace are ignored.
+\*(CBThe value of \*(FCIGNORECASE\fP
+will also affect how fields are split when
+\*(FCFS\fP is a regular expression.\*(CD
+.sp .5
+\*(CBIf the \*(FCFIELDWIDTHS\fP
+variable is set to a space separated list of numbers, each field is
+expected to have a fixed width, and \*(GK
+will split up the record using the specified widths.
+The value of \*(FCFS\fP is ignored.
+Assigning a new value to \*(FCFS\fP
+overrides the use of \*(FCFIELDWIDTHS\*(FR,
+and restores the default behavior.\*(CD
+.sp .5
+Each field in the input record may be referenced by its position,
+\*(FC$1\*(FR, \*(FC$2\*(FR and so on.
+\*(FC$0\fP is the whole record.
+Fields may also be assigned new values.
+.sp .5
+The variable \*(FCNF\fP
+is set to the total number of fields in the input record.
+.sp .5
+References to non-existent fields (i.e., fields after \*(FC$NF\*(FR)
+produce the null-string. However, assigning to a non-existent field
+(e.g., \*(FC$(NF+2) = 5\*(FR) will increase the value of
+\*(FCNF\*(FR, create any intervening fields with the null string as their value,
+and cause the value of \*(FC$0\fP
+to be recomputed with the fields being separated by the
+value of \*(FCOFS\*(FR.
+References to negative numbered fields cause a fatal error.
+Decreasing the value of \*(FCNF\fP causes the trailing fields to be lost
+\*(CR(not \*(NK).\*(CX
+.EB \s+2\f(HBFIELDS\*(FR\s0
+
+.BT
+
+.\" --- Pattern Elements
+.ES
+.fi
+\*(CDAWK patterns may be one of the following.
+.sp .5
+.nf
+ \*(FCBEGIN
+ END
+ \*(FIexpression
+ pat1\*(FC,\*(FIpat2\*(FR
+.sp .5
+.fi
+\*(FCBEGIN\fP and \*(FCEND\fP are special patterns that provide start-up
+and clean-up actions respectively. They must have actions. There can
+be multiple \*(FCBEGIN\fP and \*(FCEND\fP rules; they are merged and
+executed as if there had just been one large rule. They may occur anywhere
+in a program, including different source files.
+.sp .5
+Expression patterns can be any expression, as described
+under \fHExpressions\fP.
+.sp .5
+The \*(FIpat1\*(FC,\*(FIpat2\*(FR pattern
+is called a \*(FIrange pattern\*(FR.
+It matches all input records starting with a record that matches
+\*(FIpat1\*(FR, and continuing until a record that matches
+\*(FIpat2\*(FR, inclusive.
+It does not combine with any other pattern expression.\*(CX
+.EB "\s+2\f(HBPATTERN ELEMENTS\*(FR\s0"
+
+
+.\" --- Action Statements
+.ES
+.nf
+\*(CD\*(FCif (\*(FIcondition\*(FC) \*(FIstatement\*(FR [ \*(FCelse\*(FI statement \*(FR]
+\*(FCwhile (\*(FIcondition\*(FC) \*(FIstatement \*(FR
+\*(FCdo \*(FIstatement \*(FCwhile (\*(FIcondition\*(FC)\*(FR
+\*(FCfor (\*(FIexpr1\*(FC; \*(FIexpr2\*(FC; \*(FIexpr3\*(FC) \*(FIstatement\*(FR
+\*(FCfor (\*(FIvar \*(FCin\*(FI array\*(FC) \*(FIstatement\*(FR
+.ig
+\*(CB\*(FCabort\*(FR [ \*(FIexpression\*(FR ]\*(CD
+..
+\*(FCbreak\*(FR
+\*(FCcontinue\*(FR
+\*(FCdelete \*(FIarray\^\*(FC[\^\*(FIindex\^\*(FC]\*(FR
+\*(CL\*(FCdelete \*(FIarray\^\*(FR\*(CD
+\*(FCexit\*(FR [ \*(FIexpression\*(FR ]
+\*(FCnext\*(FR
+\*(CL\*(FCnextfile\*(FR \*(CR(not \*(MK)\*(CD
+\*(FC{ \*(FIstatements \*(FC}\*(CX
+.EB "\s+2\f(HBACTION STATEMENTS\*(FR\s0"
+
+
+
+.\" --- Escape Sequences
+.ES
+.fi
+\*(CDWithin strings constants (\*(FC"..."\fP) and regexp
+constants (\*(FC/.../\fP), escape sequences may be used to
+generate otherwise unprintable characters. This table lists
+the available escape sequences.
+.sp .5
+.ig
+\*(CB\*(FCPROCINFO\fP T{
+elements of this array provide access to info
+about the running AWK program. See
+\*(AM for details.\*(CD
+T}
+..
+.TS
+center, tab(~);
+lp8 lp8 lp8 lp8.
+\*(FC\ea\fP~alert (bell)~\*(FC\er\fP~carriage return
+\*(FC\eb\fP~backspace~\*(FC\et\fP~horizontal tab
+\*(FC\ef\fP~form feed~\*(FC\ev\fP~vertical tab
+\*(FC\en\fP~newline~\*(FC\e\e\fP~backslash
+\*(FC\e\*(FIddd\*(FR~octal value \*(FIddd\fP~\*(CL\*(FC\ex\*(FIhh\*(FR~hex value \*(FIhh\fP\*(CD
+\*(FC\e"\fP~double quote~\*(FC\e/\fP~forward slash\*(CX
+.TE
+.EB "\s+2\f(HBESCAPE SEQUENCES\*(FR\s0"
+
+
+.BT
+
+.\" --- Variables
+.ES
+.fi
+.TS
+expand;
+l lw(2i).
+\*(FCARGC\fP T{
+number of command line arguments.
+T}
+\*(CB\*(FCARGIND\fP T{
+index in \*(FCARGV\fP of current data file.\*(CD
+T}
+\*(FCARGV\fP T{
+array of command line arguments. Indexed from
+0 to \*(FCARGC\fP \- 1. Dynamically changing the
+contents of \*(FCARGV\fP can control the files used
+for data.
+T}
+\*(FCCONVFMT\fP T{
+conversion format for numbers, default value
+is \*(FC"%.6g"\*(FR.
+T}
+\*(FCENVIRON\fP T{
+array containing the the current environment.
+The array is indexed by the environment
+variables, each element being the value of
+that variable.
+T}
+\*(CB\*(FCERRNO\fP T{
+contains a string describing the error when a
+redirection or read for \*(FCgetline\*(FR fails, or if
+\*(FCclose()\*(FR fails.
+T}
+\*(FCFIELDWIDTHS\fP T{
+white-space separated list of fieldwidths. Used
+to parse the input into fields of fixed width,
+instead of the value of \*(FCFS\fP.\*(CD
+T}
+\*(FCFILENAME\fP T{
+name of the current input file. If no files given
+on the command line, \*(FCFILENAME\fP is ``\-''.
+\*(FCFILENAME\fP is undefined inside the \*(FCBEGIN\fP rule
+(unless set by \*(FCgetline\fP).
+T}
+\*(FCFNR\fP T{
+number of the input record in current input file.
+T}
+\*(FCFS\fP T{
+input field separator, a space by default
+(see \fHFields\fP above).
+T}
+\*(CB\*(FCIGNORECASE\fP T{
+if non-zero, all regular expression and string
+operations ignore case. \*(CRIn versions of \*(GK
+prior to 3.0, \*(FCIGNORECASE\fP only affected
+regular expression operations and \*(FCindex()\*(FR.\*(CD
+T}
+\*(FCNF\fP T{
+number of fields in the current input record.
+T}
+\*(FCNR\fP T{
+total number of input records seen so far.
+T}
+\*(FCOFMT\fP T{
+output format for numbers, \*(FC"%.6g"\*(FR, by default.
+\*(CROld versions of \*(AK also used this for number
+to string conversion instead of \*(FCCONVFMT\fP.\*(CD
+T}
+\*(FCOFS\fP T{
+output field separator, a space by default.
+T}
+\*(FCORS\fP T{
+output record separator, a newline by default.
+T}
+\*(FCRS\fP T{
+input record separator, a newline by default
+(see \fHRecords\fP above).
+T}
+\*(CB\*(FCRT\fP T{
+record terminator. \*(GK sets \*(FCRT\fP to the input
+text that matched the character or regular
+expression specified by \*(FCRS\*(FR.\*(CD
+T}
+\*(FCRSTART\fP T{
+index of the first character matched by
+\*(FCmatch()\*(FR; 0 if no match.
+T}
+\*(FCRLENGTH\fP T{
+length of the string matched by \*(FCmatch()\*(FR;
+\-1 if no match.
+T}
+\*(FCSUBSEP\fP T{
+character(s) used to separate multiple subscripts
+in array elements, by default \*(FC"\e034"\*(FR. (see
+\fHArrays\fP below).\*(CX
+T}
+.TE
+.EB \s+2\f(HBVARIABLES\*(FR\s0
+
+.BT
+
+.\" --- Arrays
+.ES
+.fi
+\*(CDAn arrays subscript is an expression between square brackets
+(\*(FC[ \*(FRand \*(FC]\*(FR).
+If the expression is a list
+\*(FC(\*(FIexpr\*(FC, \*(FIexpr \*(FC...)\*(FR,
+then the subscript is a string consisting of the
+concatenation of the (string) value of each expression,
+separated by the value of the \*(FCSUBSEP\fP variable.
+This simulates multi-dimensional
+arrays. For example:
+.nf
+.sp .5
+ \*(FCi = "A";\^ j = "B";\^ k = "C"
+ x[i, j, k] = "hello, world\en"\*(FR
+.sp .5
+.fi
+assigns \*(FC"hello, world\en"\*(FR to the element of the array
+\*(FCx\fP
+indexed by the string \*(FC"A\e034B\e034C"\*(FR. All arrays in AWK
+are associative, i.e., indexed by string values.
+.sp .5
+Use the special operator \*(FCin\fP in an \*(FCif\fP
+or \*(FCwhile\fP statement to see if a particular value is
+an array index.
+.sp .5
+.nf
+ \*(FCif (val in array)
+ print array[val]\*(FR
+.sp .5
+.fi
+If the array has multiple subscripts, use
+\*(FC(i, j) in array\*(FR.
+.sp .5
+Use the \*(FCin\fP construct in a \*(FCfor\fP
+loop to iterate over all the elements of an array.
+.sp .5
+Use the \*(FCdelete\fP statement to delete an
+element from an array.
+\*(CLSpecifying just the array name without a subscript in
+the \*(FCdelete\fP
+statement deletes the entire contents of an array.\*(CX
+.EB \s+2\f(HBARRAYS\*(FR\s0
+
+.\" --- Expressions
+.ES
+.fi
+\*(CDExpressions are used as patterns, for controlling conditional action
+statements, and to produce parameter values when calling functions.
+Expressions may also be used as simple statements,
+particularly if they have side-effects such as assignment.
+Expressions mix \*(FIoperands\fP and \*(FIoperators\fP. Operands are
+constants, fields, variables, array elements, and the return
+values from function calls (both built-in and user-defined).
+.sp .5
+Regexp constants (\*(FC/\*(FIpat\*(FC/\*(FR), when used as simple expressions,
+i.e., not used on the right-hand side of
+\*(FC~\fP and \*(FC!~\fP, or as arguments to the
+\*(CB\*(FCgensub()\fP,\*(CD
+\*(FCgsub()\fP,
+\*(FCmatch()\fP,
+\*(FCsplit()\fP,
+and
+\*(FCsub()\fP,
+functions, mean \*(FC$0 ~ /\*(FIpat\*(FC/\*(FR.
+.sp .5
+The AWK operators, in order of decreasing precedence, are
+.sp .5
+.fi
+.TS
+expand;
+l lw(1.8i).
+\*(FC(\&...)\*(FR grouping
+\*(FC$\fP field reference
+\*(FC++ \-\^\-\fP T{
+increment and decrement,
+prefix and postfix
+T}
+\*(FC^\fP \*(CL\*(FC**\*(FR\*(CD exponentiation
+\*(FC+ \- !\fP unary plus, unary minus, and logical negation
+\*(FC* / %\fP multiplication, division, and modulus
+\*(FC+ \-\fP addition and subtraction
+\*(FIspace\fP string concatenation
+\*(FC< >\fP less than, greater than
+\*(FC<= >=\fP less than or equal, greater than or equal
+\*(FC!= ==\fP not equal, equal
+\*(FC~ !~\fP regular expression match, negated match
+\*(FCin\fP array membership
+\*(FC&&\fP logical AND, short circuit
+\*(FC||\fP logical OR, short circuit
+\*(FC?\^:\fP in-line conditional expression
+.T&
+l s
+l lw(1.8i).
+\*(FC=\0+=\0\-=\0*=\0/=\0%=\0^=\0\*(CL**=\*(CD\fP
+ assignment operators\*(CX
+.TE
+.EB \s+2\f(HBEXPRESSIONS\*(FR\s0
+
+
+.BT
+
+.\" --- Conversions and Comparisons
+.ES
+.fi
+\*(CDVariables and fields may be (floating point) numbers, strings or both.
+Context determines how the value of a variable is interpreted. If used in
+a numeric expression, it will be treated as a number, if used as a string
+it will be treated as a string.
+.sp .5
+To force a variable to be treated as a number, add 0 to it; to force it
+to be treated as a string, concatenate it with the null string.
+.sp .5
+When a string must be converted to a number, the conversion is accomplished
+using \*(FIatof\*(FR(3).
+A number is converted to a string by using the value of \*(FCCONVFMT\fP
+as a format string for \*(FIsprintf\*(FR(3),
+with the numeric value of the variable as the argument.
+However, even though all numbers in AWK are floating-point,
+integral values are \*(FIalways\fP converted as integers.
+.sp .5
+Comparisons are performed as follows:
+If two variables are numeric, they are compared numerically.
+If one value is numeric and the other has a string value that is a
+``numeric string,'' then comparisons are also done numerically.
+Otherwise, the numeric value is converted to a string, and a string
+comparison is performed.
+Two strings are compared, of course, as strings.
+\*(CRAccording to the POSIX standard, even if two strings are
+numeric strings, a numeric comparison is performed. However, this is
+clearly incorrect, and none of the three free \*(AK\*(FRs do this.\*(CD
+.sp .5
+Note that string constants, such as \*(FC"57"\fP, are \*(FInot\fP
+numeric strings, they are string constants. The idea of ``numeric string''
+only applies to fields, \*(FCgetline\fP input,
+\*(FCFILENAME\*(FR, \*(FCARGV\fP elements, \*(FCENVIRON\fP
+elements and the elements of an array created by
+\*(FCsplit()\fP that are numeric strings.
+The basic idea is that \*(FIuser input\*(FR,
+and only user input, that looks numeric,
+should be treated that way.
+.sp .5
+Uninitialized variables have the numeric value 0 and the string value
+\*(FC"\^"\fP
+(the null, or empty, string).\*(CX
+.EB "\s+2\f(HBCONVERSIONS AND COMPARISONS\*(FR\s0"
+
+.ig
+.\" --- Localization
+.ES
+.nf
+.ce 100
+\*(CDThis
+section
+is
+under
+construction.
+.sp .5
+This
+section
+is
+under
+construction.\*(CB
+.ce 0
+.EB "\s+2\f(HBLOCALIZATION\*(FR\s0"
+..
+
+.ig
+.ps +2
+.ce 1
+\*(CD\fHISBN: 0-916151-97-2\*(FR
+.ps -2
+..
+
+.BT
+
+
+.\" --- Input Control
+.ES
+.fi
+.TS
+expand;
+l lw(1.8i).
+\*(CD\*(FCclose(\*(FIfile\*(FC)\*(FR close input file or pipe.
+\*(FCgetline\fP T{
+set \*(FC$0\fP from next input record;
+set \*(FCNF\*(FR, \*(FCNR\*(FR, \*(FCFNR\*(FR.
+T}
+\*(FCgetline < \*(FIfile\*(FR set \*(FC$0\fP from next record of \*(FIfile\*(FR; set \*(FCNF\*(FR.
+\*(FCgetline \*(FIv\*(FR T{
+set \*(FIv\fP from next input record;
+set \*(FCNR\*(FR, \*(FCFNR\*(FR.
+T}
+\*(FCgetline \*(FIv \*(FC< \*(FIfile\*(FR set \*(FIv\fP from next record of \*(FIfile\*(FR.
+\*(FIcmd \*(FC| getline\*(FR pipe into \*(FCgetline\*(FR; set \*(FC$0\*(FR, \*(FCNF\*(FR.
+\*(FIcmd \*(FC| getline \*(FIv\*(FR pipe into \*(FCgetline\*(FR; set \*(FIv\*(FR.
+.TE
+.fi
+.in +.2i
+.ti -.2i
+\*(FCnext\fP
+.br
+stop processing the current input
+record. Read next input record and
+start over with the first pattern in the
+program. Upon end of the input data,
+execute any \*(FCEND\fP rule(s).
+.br
+.ti -.2i
+\*(CL\*(FCnextfile\fP
+.br
+stop processing the current input file.
+The next input record comes from the
+next input file. \*(FCFILENAME\fP \*(CBand
+\*(FCARGIND\fP\*(CL are updated, \*(FCFNR\fP is reset to 1,
+and processing starts over with the first
+pattern in the AWK program. Upon end
+of input data, execute any \*(FCEND\fP rule(s).
+\*(CREarlier versions of \*(GK used
+\*(FCnext file\*(FR, as two words. This
+generates a warning message and will
+eventually be removed. \*(CR\*(MK does not
+currently support \*(FCnextfile\*(FR.\*(CD
+.in -.2i
+.sp .5
+.fi
+\*(FCgetline\*(FR returns 0 on end of file, and \-1 on an
+error.\*(CX
+.EB "\s+2\f(HBINPUT CONTROL\*(FR\s0"
+
+.\" --- Output Control
+.ES
+.fi
+.in +.2i
+.ti -.2i
+\*(CD\*(FCclose(\*(FIfile\*(FC)\*(FR
+.br
+close output file or pipe.
+.ti -.2i
+\*(CL\*(FCfflush(\*(FR[\*(FIfile\^\*(FR]\*(FC)\*(FR
+.br
+flush any buffers associated
+with the open output file or pipe \*(FIfile\*(FR.\*(CD
+\*(CBIf \*(FIfile\fP is missing, then standard output is flushed.
+If \*(FIfile\fP is the null string, then all open output files and pipes
+are flushed \*(CR(not \*(NK)\*(CD.
+.ti -.2i
+\*(FCprint\fP
+.br
+print the current record. The output record is terminated
+with the value of \*(FCORS\fP.
+.ti -.2i
+\*(FCprint \*(FIexpr-list\*(FR
+.br
+print expressions. Each expression is separated
+by the value of \*(FCOFS\fP. The output record is
+terminated with the value of \*(FCORS\fP.
+.ti -.2i
+\*(FCprintf \*(FIfmt\*(FC, \*(FIexpr-list\*(FR
+.br
+format and print (see \fHPrintf Formats\fP below).
+.ti -.2i
+\*(FCsystem(\*(FIcmd\*(FC)\*(FR
+.br
+execute the command \*(FIcmd\*(FR,
+and return the exit status
+\*(CR(may not be available on non-POSIX systems)\*(CD.
+.sp .5
+.in -.2i
+I/O redirections may be used with both \*(FCprint\fP and \*(FCprintf\fP.
+.sp .5
+.in +.2i
+.ti -.2i
+\*(CD\*(FCprint "hello" > \*(FIfile\*(FR
+.br
+Print data to \*(FIfile\fP. The first time the file is written to, it
+will be truncated. Subsequent commands append data.
+.ti -.2i
+\*(FCprint "hello" >> \*(FIfile\*(FR
+.br
+Append data to \*(FIfile\fP. The previous contents of the file are not lost.
+.ti -.2i
+\*(FCprint "hello" | \*(FIcmd\*(FR
+.br
+Print data down a pipeline to \*(FIcmd\*(FR.\*(CX
+.in -.2i
+.EB "\s+2\f(HBOUTPUT CONTROL\*(FR\s0"
+
+.BT
+
+
+.\" --- Printf Formats
+.ES
+.fi
+\*(CDThe \*(FCprintf\fP statement and
+\*(FCsprintf()\fP function
+accept the following conversion specification formats:
+.sp .5
+.nf
+\*(FC%c\fP an \s-1ASCII\s+1 character
+\*(FC%d\fP a decimal number (the integer part)
+\*(FC%i\fP a decimal number (the integer part)
+\*(FC%e\fP a floating point number of the form
+ \*(FC[\-]d.dddddde[+\^\-]dd\*(FR
+\*(FC%E\fP like \*(FC%e\fP, but use \*(FCE\fP instead of \*(FCe\*(FR
+\*(FC%f\fP a floating point number of the form
+ \*(FC[\-]ddd.dddddd\*(FR
+\*(FC%g\fP use \*(FC%e\fP or \*(FC%f\fP, whichever is shorter, with
+ nonsignificant zeros suppressed
+\*(FC%G\fP like \*(FC%g\fP, but use \*(FC%E\fP instead of \*(FC%e\*(FR
+\*(FC%o\fP an unsigned octal integer
+\*(FC%u\fP an unsigned decimal integer
+\*(FC%s\fP a character string
+\*(FC%x\fP an unsigned hexadecimal integer
+\*(FC%X\fP like \*(FC%x\fP, but use \*(FCABCDEF\fP for 10\(en15
+\*(FC%%\fP A literal \*(FC%\fP; no argument is converted
+.sp .5
+.fi
+Optional, additional parameters may lie between the \*(FC%\fP
+and the control letter:
+.sp .5
+.TS
+expand;
+l lw(2.2i).
+\*(FC\-\fP T{
+left-justify the expression within its field.
+T}
+\*(FIspace\fP T{
+for numeric conversions, prefix positive values
+with a space and negative values with a
+minus sign.
+T}
+\*(FC+\fP T{
+used before the \*(FIwidth\fP modifier means to always
+supply a sign for numeric conversions, even if
+the data to be formatted is positive. The \*(FC+\fP
+overrides the space modifier.
+T}
+\*(FC#\fP T{
+use an ``alternate form'' for some control letters.
+T}
+ \*(FC%o\*(FR T{
+supply a leading zero.
+T}
+ \*(FC%x\*(FR, \*(FC%X\*(FR T{
+supply a leading \*(FC0x\*(FR or \*(FC0X\*(FR for a nonzero result.
+T}
+ \*(FC%e\*(FR, \*(FC%E\*(FR, \*(FC%f\*(FR T{
+the result always has a decimal point.
+T}
+ \*(FC%g\*(FR, \*(FC%G\*(FR T{
+trailing zeros are not removed.
+T}
+\*(FC0\fP T{
+a leading zero acts as a flag, indicating output
+should be padded with zeroes instead of spaces.
+This applies even to non-numeric output formats.
+Only has an effect when the field width is wider
+than the value to be printed.
+T}
+\*(FIwidth\fP T{
+pad the field to this width. The field is normally
+padded with spaces. If the \*(FC0\fP flag has been used,
+pad with zeroes.
+T}
+\*(FC.\fP\*(FIprec\fP T{
+precision.
+The meaning varies by control letter:
+T}
+ \*(FC%d\*(FR, \*(FC%o\*(FR, \*(FC%i\*(FR,
+ \*(FC%u\*(FR, \*(FC%x\*(FR, \*(FC%X\fP T{
+the minimum number of digits to print.
+T}
+ \*(FC%e\*(FR, \*(FC%E\*(FR, \*(FC%f\*(FR T{
+the number of digits to print to the right of the decimal point.
+T}
+ \*(FC%g\*(FR, \*(FC%G\fP T{
+the maximum number of significant digits.
+T}
+ \*(FC%s\fP T{
+the maximum number of characters to print.
+T}
+.TE
+.sp .5
+.fi
+The dynamic \*(FIwidth\fP and \*(FIprec\fP capabilities of the ANSI C
+\*(FCprintf()\fP routines are supported.
+A \*(FC*\fP in place of either the \*(FIwidth\fP or \*(FIprec\fP
+specifications will cause their values to be taken from
+the argument list to \*(FCprintf\fP or \*(FCsprintf()\*(FR.\*(CX
+.EB "\s+2\f(HBPRINTF FORMATS\*(FR\s0"
+
+
+
+.BT
+
+.\" --- Special Filenames
+.ES
+.fi
+\*(CDWhen doing I/O redirection from either \*(FCprint\fP
+or \*(FCprintf\fP into a file or via \*(FCgetline\fP
+from a file, all three implementations of \*(FCawk\fP
+recognize certain special filenames internally. These filenames
+allow access to open file descriptors inherited from the
+parent process (usually the shell).
+These filenames may also be used on the command line to name data files.
+The filenames are:
+.sp .5
+.TS
+expand;
+l lw(2i).
+\*(FC"\-"\fP standard input
+\*(FC/dev/stdin\fP standard input \*(CR(not \*(MK)\*(CD
+\*(FC/dev/stdout\fP standard output
+\*(FC/dev/stderr\fP standard error output
+.TE
+.sp .5
+.fi
+\*(CBThe following names are specific to \*(GK.
+.sp .5
+.TS
+expand;
+l lw(2i).
+\*(FC/dev/fd/\^\*(FIn\*(FR T{
+file associated with the open file descriptor \*(FIn\*(FR
+T}
+.TE
+.sp .5
+.fi
+Other special filenames provide access to information about the running
+\*(FCgawk\fP process.
+Reading from these files returns a single record.
+The filenames and what they return are:\*(FR
+.sp .5
+.TS
+expand;
+l lw(2i).
+\*(FC/dev/pid\fP process ID of current process
+\*(FC/dev/ppid\fP parent process ID of current process
+\*(FC/dev/pgrpid\fP process group ID of current process
+\*(FC/dev/user\fP T{
+.nf
+a single newline-terminated record.
+The fields are separated with spaces.
+\*(FC$1\fP is the return value of \*(FIgetuid\*(FR(2),
+\*(FC$2\fP is the return value of \*(FIgeteuid\*(FR(2),
+\*(FC$3\fP is the return value of \*(FIgetgid\*(FR(2) , and
+\*(FC$4\fP is the return value of \*(FIgetegid\*(FR(2).
+.fi
+Any additional fields are the group IDs returned
+by \*(FIgetgroups\*(FR(2). Multiple groups may not be
+supported on all systems.
+T}
+.TE
+.sp .5
+.fi
+.ig
+\*(CRThese filenames are now obsolete.
+Use the \*(FCPROCINFO\fP array to obtain the information they provide.\*(CL
+..
+.\" BEGIN FOR 3.0.x
+\*(CRThese filenames will become obsolete in \*(GK 3.1.
+Be aware that you will have to change your programs.\*(CL
+.\" END FOR 3.0.x
+.EB "\s+2\f(HBSPECIAL FILENAMES\*(FR\s0"
+
+
+
+
+.\" --- Builtin Numeric Functions
+.ES
+.fi
+.TS
+expand;
+l lw(2i).
+\*(CD\*(FCatan2(\*(FIy\*(FC, \*(FIx\*(FC)\*(FR the arctangent of \*(FIy/x\fP in radians.
+\*(FCcos(\*(FIexpr\*(FC)\*(FR the cosine of \*(FIexpr\fP, which is in radians.
+\*(FCexp(\*(FIexpr\*(FC)\*(FR the exponential function (\*(FIe \*(FC^ \*(FIx\*(FR).
+\*(FCint(\*(FIexpr\*(FC)\*(FR truncates to integer.
+\*(FClog(\*(FIexpr\*(FC)\*(FR the natural logarithm function (base \*(FIe\^\*(FR).
+\*(FCrand()\fP a random number between 0 and 1.
+\*(FCsin(\*(FIexpr\*(FC)\*(FR the sine of \*(FIexpr\fP, which is in radians.
+\*(FCsqrt(\*(FIexpr\*(FC)\*(FR the square root function.
+\&\*(FCsrand(\*(FR[\*(FIexpr\^\*(FR]\*(FC)\*(FR T{
+uses \*(FIexpr\fP as a new seed for the random number
+generator. If no \*(FIexpr\fP, the time of day is used.
+Returns previous seed for the random number
+generator.\*(CX
+T}
+.TE
+.EB "\s+2\f(HBNUMERIC FUNCTIONS\*(FR\s0"
+
+
+.BT
+
+
+.\" --- Builtin String Functions
+.ES
+.fi
+.in +.2i
+.ti -.2i
+\*(CB\*(FCgensub(\*(FIr\*(FC, \*(FIs\*(FC, \*(FIh \*(FR[\*(FC, \*(FIt\*(FR]\*(FC)\*(FR
+.br
+search the target string
+\*(FIt\fP for matches of the regular expression \*(FIr\*(FR. If
+\*(FIh\fP is a string beginning with \*(FCg\fP or \*(FCG\*(FR,
+replace all matches of \*(FIr\fP with \*(FIs\*(FR. Otherwise, \*(FIh\fP
+is a number indicating which match of \*(FIr\fP to replace. If no
+\*(FIt\fP is supplied, \*(FC$0\fP is used instead. Within the
+replacement text \*(FIs\*(FR, the sequence \*(FC\e\*(FIn\*(FR,
+where \*(FIn\fP is a digit from 1 to 9, may be used to indicate just
+the text that matched the \*(FIn\*(FRth parenthesized subexpression.
+The sequence \*(FC\e0\fP represents the entire matched text, as does
+the character \*(FC&\*(FR. Unlike \*(FCsub()\fP and \*(FCgsub()\*(FR,
+the modified string is returned as the result of the function,
+and the original target string is \*(FInot\fP changed.\*(CD
+.ti -.2i
+\*(FCgsub(\*(FIr\*(FC, \*(FIs \*(FR[\*(FC, \*(FIt\*(FR]\*(FC)\*(FR
+.br
+for each substring matching the
+regular expression \*(FIr\fP in the string \*(FIt\*(FR, substitute the
+string \*(FIs\*(FR, and return the number of substitutions. If
+\*(FIt\fP is not supplied, use \*(FC$0\*(FR. An \*(FC&\fP in the
+replacement text is replaced with the text that was actually matched.
+Use \*(FC\e&\fP to get a literal \*(FC&\*(FR. See \*(AM
+for a fuller discussion of the rules for \*(FC&\*(FR's and backslashes
+in the replacement text of \*(CB\*(FCgensub()\*(FR,\*(CD \*(FCsub()\*(FR
+and \*(FCgsub()\*(FR
+.ti -.2i
+\*(FCindex(\*(FIs\*(FC, \*(FIt\*(FC)\*(FR
+.br
+returns the index of the string
+\*(FIt\fP in the string \*(FIs\*(FR, or 0 if \*(FIt\fP is not present.
+.ti -.2i
+\*(FClength(\*(FR[\*(FIs\*(FR]\*(FC)\*(FR
+.br
+returns the length of the string
+\*(FIs\*(FR, or the length of \*(FC$0\fP if \*(FIs\fP is not supplied.
+.ti -.2i
+\*(FCmatch(\*(FIs\*(FC, \*(FIr\*(FC)\*(FR
+.br
+returns the position in
+\*(FIs\fP where the regular expression \*(FIr\fP occurs, or 0 if
+\*(FIr\fP is not present, and sets the values of variables
+\*(FCRSTART\fP
+and \*(FCRLENGTH\*(FR.
+.ti -.2i
+\*(FCsplit(\*(FIs\*(FC, \*(FIa \*(FR[\*(FC, \*(FIr\*(FR]\*(FC)\*(FR
+.br
+splits the string
+\*(FIs\fP into the array \*(FIa\fP using the regular expression \*(FIr\*(FR,
+and returns the number of fields. If \*(FIr\fP is omitted, \*(FCFS\fP
+is used instead. The array \*(FIa\fP is cleared first.
+Splitting behaves identically to field splitting.
+(See \fHFields\fP, above.)
+.ti -.2i
+\*(FCsprintf(\*(FIfmt\*(FC, \*(FIexpr-list\*(FC)\*(FR
+.br
+prints \*(FIexpr-list\fP
+according to \*(FIfmt\*(FR, and returns the resulting string.
+.ti -.2i
+\*(FCsub(\*(FIr\*(FC, \*(FIs \*(FR[\*(FC, \*(FIt\*(FR]\*(FC)\*(FR
+.br
+just like
+\*(FCgsub()\*(FR, but only the first matching substring is replaced.
+.ti -.2i
+\*(FCsubstr(\*(FIs\*(FC, \*(FIi \*(FR[\*(FC, \*(FIn\*(FR]\*(FC)\*(FR
+.br
+returns the at most
+\*(FIn\*(FR-character substring of \*(FIs\fP starting at \*(FIi\*(FR.
+If \*(FIn\fP is omitted, the rest of \*(FIs\fP is used.
+.ti -.2i
+\*(FCtolower(\*(FIstr\*(FC)\*(FR
+.br
+returns a copy of the string \*(FIstr\*(FR,
+with all the upper-case characters in \*(FIstr\fP translated to their
+corresponding lower-case counterparts. Non-alphabetic characters are
+left unchanged.
+.ti -.2i
+\*(FCtoupper(\*(FIstr\*(FC)\*(FR
+.br
+returns a copy of the string \*(FIstr\*(FR,
+with all the lower-case characters in \*(FIstr\fP translated to their
+corresponding upper-case counterparts. Non-alphabetic characters are
+left unchanged.\*(CX
+.in -.2i
+.EB "\s+2\f(HBSTRING FUNCTIONS\*(FR\s0"
+
+
+
+.BT
+
+
+.\" --- Builtin Time Functions
+.ES
+.fi
+\*(CD\*(GK
+provides the following functions for obtaining time stamps and
+formatting them.
+.sp .5
+.fi
+.in +.2i
+.ig
+.ti -.2i
+\*(FCmktime(\*(FIdatespec\*(FC)\*(FR
+.br
+turns \*(FIdatespec\fP into a time
+stamp of the same form as returned by \*(FCsystime()\*(FR.
+The \*(FIdatespec\fP is a string of the form
+\*(FC"\*(FIYYYY MM DD HH MM SS\*(FC"\*(FR.
+..
+.ti -.2i
+\*(FCstrftime(\*(FR[\*(FIformat \*(FR[\*(FC, \*(FItimestamp\*(FR]]\*(FC)\*(FR
+.br
+formats \*(FItimestamp\fP
+according to the specification in \*(FIformat\*(FR. The
+\*(FItimestamp\fP should be of the same form as returned by
+\*(FCsystime()\*(FR.
+If \*(FItimestamp\fP is missing, the current time of day is used. If
+\*(FIformat\fP is missing, a default format equivalent to the output
+of \*(FIdate\*(FR(1) will be used.
+.ti -.2i
+\*(FCsystime()\fP
+.br
+returns the current time of day as the number of
+seconds since the Epoch.\*(CB
+.in -.2i
+.EB "\s+2\f(HBTIME FUNCTIONS (\*(GK\f(HB)\*(FR\s0"
+
+
+
+.\" --- User-defined Functions
+.ES
+.fi
+\*(CDFunctions in AWK are defined as follows:
+.sp .5
+.nf
+ \*(FCfunction \*(FIname\*(FC(\*(FIparameter list\*(FC)
+ {
+ \*(FIstatements
+ \*(FC}\*(FR
+.sp .5
+.fi
+Functions are executed when they are called from within expressions
+in either patterns or actions. Actual parameters supplied in the function
+call instantiate the formal parameters declared in the function.
+Arrays are passed by reference, other variables are passed by value.
+.sp .5
+Local variables are declared as extra parameters
+in the parameter list. The convention is to separate local variables from
+real parameters by extra spaces in the parameter list. For example:
+.sp .5
+.nf
+ \*(FC# a & b are local
+ function f(p, q, a, b)
+ {
+ \&.....
+ }
+.sp .3
+ /abc/ { ... ; f(1, 2) ; ... }\*(FR
+.fi
+.sp .5
+The left parenthesis in a function call is required
+to immediately follow the function name
+without any intervening white space.
+This is to avoid a syntactic ambiguity with the concatenation operator.
+This restriction does not apply to the built-in functions.
+.sp .5
+Functions may call each other and may be recursive.
+Function parameters used as local variables are initialized
+to the null string and the number zero upon function invocation.
+.sp .5
+Use \*(FCreturn\fP to return a value from a function. The return value
+is undefined if no value is provided, or if the function returns by
+``falling off'' the end.
+.sp .5
+\*(CLThe word
+\*(FCfunc\fP
+may be used in place of
+\*(FCfunction\*(FR.
+\*(CRNote: This usage is deprecated.\*(CX
+.EB "\s+2\f(HBUSER-DEFINED FUNCTIONS\*(FR\s0"
+
+
+
+.\" --- Bug Reports
+.ES
+.fi
+\*(CDIf you find a bug in this reference card, please report it via electronic
+mail to \*(FCarnold@gnu.org\*(FR.\*(CX
+.EB "\s+2\f(HBBUG REPORTS\*(FR\s0"
+
+.BT
+
+.\" --- Environment Variables
+.ES
+.fi
+\*(CDThe environment variable \*(FCAWKPATH\fP specifies a search path to use
+when finding source files named with the \*(FC\-f\fP
+option.
+The default path is
+\*(FC".:/usr/local/share/awk"\*(FR,
+if this variable does not exist.
+(The actual directory may vary,
+depending upon how \*(GK was built and installed.)
+If a file name given to the \*(FC\-f\fP option contains a ``/'' character,
+no path search is performed.
+.sp .5
+If \*(FCPOSIXLY_CORRECT\fP exists in the environment, then \*(GK
+behaves exactly as if \*(FC\-\^\-posix\fP had been specified on the
+command line.\*(CB
+.EB "\s+2\f(HBENVIRONMENT VARIABLES (\*(GK\f(HB)\*(FR\s0"
+
+.\" --- Historical Features
+.ES
+.fi
+\*(CD\*(GK supports two features of historical AWK implementations.
+First, it is possible to call the \*(FClength()\fP
+built-in function not only with no argument, but even without parentheses.
+This feature is marked as ``deprecated'' in the POSIX standard, and \*(GK
+will issue a warning about its use if \*(FC\-\^\-lint\fP
+is specified on the command line.
+.sp .5
+The other feature is the use of \*(FCcontinue\fP
+or \*(FCbreak\fP statements outside the body of a
+\*(FCwhile\*(FR, \*(FCfor\*(FR, or \*(FCdo\fP loop.
+Historical AWK implementations have treated such usage as
+equivalent to the \*(FCnext\fP statement.
+\*(GK will support this usage if \*(FC\-\^\-traditional\fP
+has been specified.\*(CB
+.EB "\s+2\f(HBHISTORICAL FEATURES (\*(GK\f(HB)\*(FR\s0"
+
+
+.\" --- FTP Information
+.ES
+.nf
+\*(CDHost: \*(FCgnudist.gnu.org\*(FR
+File: \*(FC/gnu/gawk/gawk-3.0.6.tar.gz\fP
+.in +.2i
+.fi
+GNU \*(AK (\*(GK). There may be a later version.
+.in -.2i
+.nf
+.sp .5
+Host: \*(FCnetlib.bell-labs.com\*(FR
+File: \*(FC/netlib/research/awk.bundle.gz\fP
+.in +.2i
+.fi
+\*(NK. This version requires an ANSI C compiler;
+GCC (the GNU C compiler) works well.
+.in -.2i
+.nf
+.sp .5
+Host: \*(FCftp.whidbey.net\*(FR
+File: \*(FC/pub/brennan/mawk1.3.3.tar.gz\fP
+.in +.2i
+.fi
+Michael Brennan's \*(MK. There may be a newer version.\*(CX
+.in -.2i
+.EB "\s+2\f(HBFTP INFORMATION\*(FR\s0"
+
+.\" --- Copying Permissions
+.ES
+.fi
+\*(CDCopyright \(co 1996-2000 Free Software Foundation, Inc.
+.sp .5
+Permission is granted to make and distribute verbatim copies of this
+reference card provided the copyright notice and this permission notice
+are preserved on all copies.
+.sp .5
+Permission is granted to copy and distribute modified versions of this
+reference card under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.sp .5
+Permission is granted to copy and distribute translations of this
+reference card into another language, under the above conditions for
+modified versions, except that this permission notice may be stated in a
+translation approved by the Foundation.\*(CX
+.EB "\s+2\f(HBCOPYING PERMISSIONS\*(FR\s0"
+.BT
diff --git a/contrib/awk/doc/awkforai.txt b/contrib/awk/doc/awkforai.txt
new file mode 100644
index 000000000000..3fca3204324f
--- /dev/null
+++ b/contrib/awk/doc/awkforai.txt
@@ -0,0 +1,150 @@
+Draft for ACM SIGPLAN Patterns (Language Trends)
+
+1996
+
+Why GAWK for AI?
+
+Ronald P. Loui
+
+Most people are surprised when I tell them what language we use in our
+undergraduate AI programming class. That's understandable. We use
+GAWK. GAWK, Gnu's version of Aho, Weinberger, and Kernighan's old
+pattern scanning language isn't even viewed as a programming language by
+most people. Like PERL and TCL, most prefer to view it as a "scripting
+language." It has no objects; it is not functional; it does no built-in
+logic programming. Their surprise turns to puzzlement when I confide
+that (a) while the students are allowed to use any language they want;
+(b) with a single exception, the best work consistently results from
+those working in GAWK. (footnote: The exception was a PASCAL
+programmer who is now an NSF graduate fellow getting a Ph.D. in
+mathematics at Harvard.) Programmers in C, C++, and LISP haven't even
+been close (we have not seen work in PROLOG or JAVA).
+
+Why GAWK?
+
+There are some quick answers that have to do with the pragmatics of
+undergraduate programming. Then there are more instructive answers that
+might be valuable to those who debate programming paradigms or to those
+who study the history of AI languages. And there are some deep
+philosophical answers that expose the nature of reasoning and symbolic
+AI. I think the answers, especially the last ones, can be even more
+surprising than the observed effectiveness of GAWK for AI.
+
+First it must be confessed that PERL programmers can cobble together AI
+projects well, too. Most of GAWK's attractiveness is reproduced in
+PERL, and the success of PERL forebodes some of the success of GAWK.
+Both are powerful string-processing languages that allow the programmer
+to exploit many of the features of a UNIX environment. Both provide
+powerful constructions for manipulating a wide variety of data in
+reasonably efficient ways. Both are interpreted, which can reduce
+development time. Both have short learning curves. The GAWK manual can
+be consumed in a single lab session and the language can be mastered by
+the next morning by the average student. GAWK's automatic
+initialization, implicit coercion, I/O support and lack of pointers
+forgive many of the mistakes that young programmers are likely to make.
+Those who have seen C but not mastered it are happy to see that GAWK
+retains some of the same sensibilities while adding what must be
+regarded as spoonsful of syntactic sugar. Some will argue that
+PERL has superior functionality, but for quick AI applications, the
+additional functionality is rarely missed. In fact, PERL's terse syntax
+is not friendly when regular expressions begin to proliferate and
+strings contain fragments of HTML, WWW addresses, or shell commands.
+PERL provides new ways of doing things, but not necessarily ways of
+doing new things.
+
+In the end, despite minor difference, both PERL and GAWK minimize
+programmer time. Neither really provides the programmer the setting in
+which to worry about minimizing run-time.
+
+There are further simple answers. Probably the best is the fact that
+increasingly, undergraduate AI programming is involving the Web. Oren
+Etzioni (University of Washington, Seattle) has for a while been arguing
+that the "softbot" is replacing the mechanical engineers' robot as the
+most glamorous AI testbed. If the artifact whose behavior needs to be
+controlled in an intelligent way is the software agent, then a language
+that is well-suited to controlling the software environment is the
+appropriate language. That would imply a scripting language. If the
+robot is KAREL, then the right language is "turn left; turn right." If
+the robot is Netscape, then the right language is something that can
+generate "netscape -remote 'openURL(http://cs.wustl.edu/~loui)'" with
+elan.
+
+Of course, there are deeper answers. Jon Bentley found two pearls in
+GAWK: its regular expressions and its associative arrays. GAWK asks
+the programmer to use the file system for data organization and the
+operating system for debugging tools and subroutine libraries. There is
+no issue of user-interface. This forces the programmer to return to the
+question of what the program does, not how it looks. There is no time
+spent programming a binsort when the data can be shipped to /bin/sort
+in no time. (footnote: I am reminded of my IBM colleague Ben Grosof's
+advice for Palo Alto: Don't worry about whether it's highway 101 or 280.
+Don't worry if you have to head south for an entrance to go north. Just
+get on the highway as quickly as possible.)
+
+There are some similarities between GAWK and LISP that are illuminating.
+Both provided a powerful uniform data structure (the associative array
+implemented as a hash table for GAWK and the S-expression, or list of
+lists, for LISP). Both were well-supported in their environments (GAWK
+being a child of UNIX, and LISP being the heart of lisp machines). Both
+have trivial syntax and find their power in the programmer's willingness
+to use the simple blocks to build a complex approach.
+
+Deeper still, is the nature of AI programming. AI is about
+functionality and exploratory programming. It is about bottom-up design
+and the building of ambitions as greater behaviors can be demonstrated.
+Woe be to the top-down AI programmer who finds that the bottom-level
+refinements, "this subroutine parses the sentence," cannot actually be
+implemented. Woe be to the programmer who perfects the data structures
+for that heapsort when the whole approach to the high-level problem
+needs to be rethought, and the code is sent to the junkheap the next day.
+
+AI programming requires high-level thinking. There have always been a few
+gifted programmers who can write high-level programs in assembly language.
+Most however need the ambient abstraction to have a higher floor.
+
+Now for the surprising philosophical answers. First, AI has discovered
+that brute-force combinatorics, as an approach to generating intelligent
+behavior, does not often provide the solution. Chess, neural nets, and
+genetic programming show the limits of brute computation. The
+alternative is clever program organization. (footnote: One might add
+that the former are the AI approaches that work, but that is easily
+dismissed: those are the AI approaches that work in general, precisely
+because cleverness is problem-specific.) So AI programmers always want
+to maximize the content of their program, not optimize the efficiency
+of an approach. They want minds, not insects. Instead of enumerating
+large search spaces, they define ways of reducing search, ways of
+bringing different knowledge to the task. A language that maximizes
+what the programmer can attempt rather than one that provides tremendous
+control over how to attempt it, will be the AI choice in the end.
+
+Second, inference is merely the expansion of notation. No matter whether
+the logic that underlies an AI program is fuzzy, probabilistic, deontic,
+defeasible, or deductive, the logic merely defines how strings can be
+transformed into other strings. A language that provides the best
+support for string processing in the end provides the best support for
+logic, for the exploration of various logics, and for most forms of
+symbolic processing that AI might choose to call "reasoning" instead of
+"logic." The implication is that PROLOG, which saves the AI programmer
+from having to write a unifier, saves perhaps two dozen lines of GAWK
+code at the expense of strongly biasing the logic and representational
+expressiveness of any approach.
+
+I view these last two points as news not only to the programming language
+community, but also to much of the AI community that has not reflected on
+the past decade's lessons.
+
+In the puny language, GAWK, which Aho, Weinberger, and Kernighan thought
+not much more important than grep or sed, I find lessons in AI's trends,
+AI's history, and the foundations of AI. What I have found not only
+surprising but also hopeful, is that when I have approached the AI
+people who still enjoy programming, some of them are not the least bit
+surprised.
+
+
+R. Loui (loui@ai.wustl.edu) is Associate Professor of Computer Science,
+at Washington University in St. Louis. He has published in AI Journal,
+Computational Intelligence, ACM SIGART, AI Magazine, AI and Law, the ACM
+Computing Surveys Symposium on AI, Cognitive Science, Minds and
+Machines, Journal of Philosophy, and is on this year's program
+committees for AAAI (National AI conference) and KR (Knowledge
+Representation and Reasoning).
diff --git a/contrib/awk/doc/cardfonts b/contrib/awk/doc/cardfonts
new file mode 100644
index 000000000000..5529ba9891aa
--- /dev/null
+++ b/contrib/awk/doc/cardfonts
@@ -0,0 +1,37 @@
+.\" AWK Reference Card --- Arnold Robbins, arnold@gnu.org
+.\" cardfonts --- this file sets the fonts to use for the reference card
+.\"
+.\" Copyright (C) 1996 Free Software Foundation, Inc.
+.\"
+.\" Permission is granted to make and distribute verbatim copies of
+.\" this reference card provided the copyright notice and this permission
+.\" notice are preserved on all copies.
+.\"
+.\" Permission is granted to process this file through troff and print the
+.\" results, provided the printed document carries copying permission
+.\" notice identical to this one except for the removal of this paragraph
+.\" (this paragraph not being relevant to the printed reference card).
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" reference card under the conditions for verbatim copying, provided that
+.\" the entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Permission is granted to copy and distribute translations of this
+.\" reference card into another language, under the above conditions for
+.\" modified versions, except that this permission notice may be stated in
+.\" a translation approved by the Foundation.
+.\"
+.ig
+Strings for inline font change.
+FR - font roman
+FI - font italic
+FC - font courier
+..
+.ds FR \fR
+.ds FI \fI
+.ds FC \f(CB
+.ds RN Times Roman
+.ds IN Times Italic
+.ds CN Courier Bold
+.ds AM \fIThe GNU Awk User's Guide\fP
diff --git a/contrib/awk/doc/colors b/contrib/awk/doc/colors
new file mode 100644
index 000000000000..933d25efedfc
--- /dev/null
+++ b/contrib/awk/doc/colors
@@ -0,0 +1,39 @@
+.\" AWK Reference Card --- Arnold Robbins, arnold@gnu.org
+.\" This file sets the colors to use.
+.\"
+.\" Copyright (C) 1996,97,99 Free Software Foundation, Inc.
+.\"
+.\" Permission is granted to make and distribute verbatim copies of
+.\" this reference card provided the copyright notice and this permission
+.\" notice are preserved on all copies.
+.\"
+.\" Permission is granted to process this file through troff and print the
+.\" results, provided the printed document carries copying permission
+.\" notice identical to this one except for the removal of this paragraph
+.\" (this paragraph not being relevant to the printed reference card).
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" reference card under the conditions for verbatim copying, provided that
+.\" the entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Permission is granted to copy and distribute translations of this
+.\" reference card into another language, under the above conditions for
+.\" modified versions, except that this permission notice may be stated in
+.\" a translation approved by the Foundation.
+.\"
+.ig
+Strings for inline color change.
+CR - color red
+CG - color green
+CL - color light blue
+CB - color blue
+CD - color dark, i.e. black
+CX - color boX, i.e. for the surrounding boxes (red for now)
+..
+.ds CR \X'ps: exec 0 .96 .65 0 setcmykcolor'
+.ds CG \X'ps: exec 1.0 0 .51 .43 setcmykcolor'
+.ds CL \X'ps: exec .69 .34 0 0 setcmykcolor'
+.ds CB \X'ps: exec 1 .72 0 .06 setcmykcolor'
+.ds CD \X'ps: exec 1 1 1 1 setcmykcolor'
+.ds CX \*(CG
diff --git a/contrib/awk/doc/gawk.1 b/contrib/awk/doc/gawk.1
new file mode 100644
index 000000000000..6f07cfab136e
--- /dev/null
+++ b/contrib/awk/doc/gawk.1
@@ -0,0 +1,2657 @@
+.ds PX \s-1POSIX\s+1
+.ds UX \s-1UNIX\s+1
+.ds AN \s-1ANSI\s+1
+.ds GN \s-1GNU\s+1
+.ds AK \s-1AWK\s+1
+.if !\n(.g \{\
+. if !\w|\*(lq| \{\
+. ds lq ``
+. if \w'\(lq' .ds lq "\(lq
+. \}
+. if !\w|\*(rq| \{\
+. ds rq ''
+. if \w'\(rq' .ds rq "\(rq
+. \}
+.\}
+.TH GAWK 1 "May 17 2000" "Free Software Foundation" "Utility Commands"
+.SH NAME
+gawk \- pattern scanning and processing language
+.SH SYNOPSIS
+.B gawk
+[ \*(PX or \*(GN style options ]
+.B \-f
+.I program-file
+[
+.B \-\^\-
+] file .\|.\|.
+.br
+.B gawk
+[ \*(PX or \*(GN style options ]
+[
+.B \-\^\-
+]
+.I program-text
+file .\|.\|.
+.SH DESCRIPTION
+.I Gawk
+is the \*(GN Project's implementation of the \*(AK programming language.
+It conforms to the definition of the language in
+the \*(PX 1003.2 Command Language And Utilities Standard.
+This version in turn is based on the description in
+.IR "The AWK Programming Language" ,
+by Aho, Kernighan, and Weinberger,
+with the additional features found in the System V Release 4 version
+of \*(UX
+.IR awk .
+.I Gawk
+also provides more recent Bell Labs
+.I awk
+extensions, and some \*(GN-specific extensions.
+.PP
+The command line consists of options to
+.I gawk
+itself, the \*(AK program text (if not supplied via the
+.B \-f
+or
+.B \-\^\-file
+options), and values to be made
+available in the
+.B ARGC
+and
+.B ARGV
+pre-defined \*(AK variables.
+.SH OPTION FORMAT
+.PP
+.I Gawk
+options may be either the traditional \*(PX one letter options,
+or the \*(GN style long options. \*(PX options start with a single \*(lq\-\*(rq,
+while long options start with \*(lq\-\^\-\*(rq.
+Long options are provided for both \*(GN-specific features and
+for \*(PX mandated features.
+.PP
+Following the \*(PX standard,
+.IR gawk -specific
+options are supplied via arguments to the
+.B \-W
+option. Multiple
+.B \-W
+options may be supplied
+Each
+.B \-W
+option has a corresponding long option, as detailed below.
+Arguments to long options are either joined with the option
+by an
+.B =
+sign, with no intervening spaces, or they may be provided in the
+next command line argument.
+Long options may be abbreviated, as long as the abbreviation
+remains unique.
+.SH OPTIONS
+.PP
+.I Gawk
+accepts the following options.
+.TP
+.PD 0
+.BI \-F " fs"
+.TP
+.PD
+.BI \-\^\-field-separator " fs"
+Use
+.I fs
+for the input field separator (the value of the
+.B FS
+predefined
+variable).
+.TP
+.PD 0
+\fB\-v\fI var\fB\^=\^\fIval\fR
+.TP
+.PD
+\fB\-\^\-assign \fIvar\fB\^=\^\fIval\fR
+Assign the value
+.IR val ,
+to the variable
+.IR var ,
+before execution of the program begins.
+Such variable values are available to the
+.B BEGIN
+block of an \*(AK program.
+.TP
+.PD 0
+.BI \-f " program-file"
+.TP
+.PD
+.BI \-\^\-file " program-file"
+Read the \*(AK program source from the file
+.IR program-file ,
+instead of from the first command line argument.
+Multiple
+.B \-f
+(or
+.BR \-\^\-file )
+options may be used.
+.TP
+.PD 0
+.BI \-mf " NNN"
+.TP
+.PD
+.BI \-mr " NNN"
+Set various memory limits to the value
+.IR NNN .
+The
+.B f
+flag sets the maximum number of fields, and the
+.B r
+flag sets the maximum record size. These two flags and the
+.B \-m
+option are from the Bell Labs research version of \*(UX
+.IR awk .
+They are ignored by
+.IR gawk ,
+since
+.I gawk
+has no pre-defined limits.
+.TP
+.PD 0
+.B "\-W traditional"
+.TP
+.PD 0
+.B "\-W compat"
+.TP
+.PD 0
+.B \-\^\-traditional
+.TP
+.PD
+.B \-\^\-compat
+Run in
+.I compatibility
+mode. In compatibility mode,
+.I gawk
+behaves identically to \*(UX
+.IR awk ;
+none of the \*(GN-specific extensions are recognized.
+The use of
+.B \-\^\-traditional
+is preferred over the other forms of this option.
+See
+.BR "GNU EXTENSIONS" ,
+below, for more information.
+.TP
+.PD 0
+.B "\-W copyleft"
+.TP
+.PD 0
+.B "\-W copyright"
+.TP
+.PD 0
+.B \-\^\-copyleft
+.TP
+.PD
+.B \-\^\-copyright
+Print the short version of the \*(GN copyright information message on
+the standard output, and exits successfully.
+.TP
+.PD 0
+.B "\-W help"
+.TP
+.PD 0
+.B "\-W usage"
+.TP
+.PD 0
+.B \-\^\-help
+.TP
+.PD
+.B \-\^\-usage
+Print a relatively short summary of the available options on
+the standard output.
+(Per the
+.IR "GNU Coding Standards" ,
+these options cause an immediate, successful exit.)
+.TP
+.PD 0
+.B "\-W lint"
+.TP
+.PD
+.B \-\^\-lint
+Provide warnings about constructs that are
+dubious or non-portable to other \*(AK implementations.
+.TP
+.PD 0
+.B "\-W lint\-old"
+.TP
+.PD
+.B \-\^\-lint\-old
+Provide warnings about constructs that are
+not portable to the original version of Unix
+.IR awk .
+.ig
+.\" This option is left undocumented, on purpose.
+.TP
+.PD 0
+.B "\-W nostalgia"
+.TP
+.PD
+.B \-\^\-nostalgia
+Provide a moment of nostalgia for long time
+.I awk
+users.
+..
+.TP
+.PD 0
+.B "\-W posix"
+.TP
+.PD
+.B \-\^\-posix
+This turns on
+.I compatibility
+mode, with the following additional restrictions:
+.RS
+.TP \w'\(bu'u+1n
+\(bu
+.B \ex
+escape sequences are not recognized.
+.TP
+\(bu
+Only space and tab act as field separators when
+.B FS
+is set to a single space, newline does not.
+.TP
+\(bu
+The synonym
+.B func
+for the keyword
+.B function
+is not recognized.
+.TP
+\(bu
+The operators
+.B **
+and
+.B **=
+cannot be used in place of
+.B ^
+and
+.BR ^= .
+.TP
+\(bu
+The
+.B fflush()
+function is not available.
+.RE
+.TP
+.PD 0
+.B "\-W re\-interval"
+.TP
+.PD
+.B \-\^\-re\-interval
+Enable the use of
+.I "interval expressions"
+in regular expression matching
+(see
+.BR "Regular Expressions" ,
+below).
+Interval expressions were not traditionally available in the
+\*(AK language. The \*(PX standard added them, to make
+.I awk
+and
+.I egrep
+consistent with each other.
+However, their use is likely
+to break old \*(AK programs, so
+.I gawk
+only provides them if they are requested with this option, or when
+.B \-\^\-posix
+is specified.
+.TP
+.PD 0
+.BI "\-W source " program-text
+.TP
+.PD
+.BI \-\^\-source " program-text"
+Use
+.I program-text
+as \*(AK program source code.
+This option allows the easy intermixing of library functions (used via the
+.B \-f
+and
+.B \-\^\-file
+options) with source code entered on the command line.
+It is intended primarily for medium to large \*(AK programs used
+in shell scripts.
+.TP
+.PD 0
+.B "\-W version"
+.TP
+.PD
+.B \-\^\-version
+Print version information for this particular copy of
+.I gawk
+on the standard output.
+This is useful mainly for knowing if the current copy of
+.I gawk
+on your system
+is up to date with respect to whatever the Free Software Foundation
+is distributing.
+This is also useful when reporting bugs.
+(Per the
+.IR "GNU Coding Standards" ,
+these options cause an immediate, successful exit.)
+.TP
+.B \-\^\-
+Signal the end of options. This is useful to allow further arguments to the
+\*(AK program itself to start with a \*(lq\-\*(rq.
+This is mainly for consistency with the argument parsing convention used
+by most other \*(PX programs.
+.PP
+In compatibility mode,
+any other options are flagged as illegal, but are otherwise ignored.
+In normal operation, as long as program text has been supplied, unknown
+options are passed on to the \*(AK program in the
+.B ARGV
+array for processing. This is particularly useful for running \*(AK
+programs via the \*(lq#!\*(rq executable interpreter mechanism.
+.SH AWK PROGRAM EXECUTION
+.PP
+An \*(AK program consists of a sequence of pattern-action statements
+and optional function definitions.
+.RS
+.PP
+\fIpattern\fB { \fIaction statements\fB }\fR
+.br
+\fBfunction \fIname\fB(\fIparameter list\fB) { \fIstatements\fB }\fR
+.RE
+.PP
+.I Gawk
+first reads the program source from the
+.IR program-file (s)
+if specified,
+from arguments to
+.BR \-\^\-source ,
+or from the first non-option argument on the command line.
+The
+.B \-f
+and
+.B \-\^\-source
+options may be used multiple times on the command line.
+.I Gawk
+will read the program text as if all the
+.IR program-file s
+and command line source texts
+had been concatenated together. This is useful for building libraries
+of \*(AK functions, without having to include them in each new \*(AK
+program that uses them. It also provides the ability to mix library
+functions with command line programs.
+.PP
+The environment variable
+.B AWKPATH
+specifies a search path to use when finding source files named with
+the
+.B \-f
+option. If this variable does not exist, the default path is
+\fB".:/usr/local/share/awk"\fR.
+(The actual directory may vary, depending upon how
+.I gawk
+was built and installed.)
+If a file name given to the
+.B \-f
+option contains a \*(lq/\*(rq character, no path search is performed.
+.PP
+.I Gawk
+executes \*(AK programs in the following order.
+First,
+all variable assignments specified via the
+.B \-v
+option are performed.
+Next,
+.I gawk
+compiles the program into an internal form.
+Then,
+.I gawk
+executes the code in the
+.B BEGIN
+block(s) (if any),
+and then proceeds to read
+each file named in the
+.B ARGV
+array.
+If there are no files named on the command line,
+.I gawk
+reads the standard input.
+.PP
+If a filename on the command line has the form
+.IB var = val
+it is treated as a variable assignment. The variable
+.I var
+will be assigned the value
+.IR val .
+(This happens after any
+.B BEGIN
+block(s) have been run.)
+Command line variable assignment
+is most useful for dynamically assigning values to the variables
+\*(AK uses to control how input is broken into fields and records.
+It is also useful for controlling state if multiple passes are needed over
+a single data file.
+.PP
+If the value of a particular element of
+.B ARGV
+is empty (\fB""\fR),
+.I gawk
+skips over it.
+.PP
+For each record in the input,
+.I gawk
+tests to see if it matches any
+.I pattern
+in the \*(AK program.
+For each pattern that the record matches, the associated
+.I action
+is executed.
+The patterns are tested in the order they occur in the program.
+.PP
+Finally, after all the input is exhausted,
+.I gawk
+executes the code in the
+.B END
+block(s) (if any).
+.SH VARIABLES, RECORDS AND FIELDS
+\*(AK variables are dynamic; they come into existence when they are
+first used. Their values are either floating-point numbers or strings,
+or both,
+depending upon how they are used. \*(AK also has one dimensional
+arrays; arrays with multiple dimensions may be simulated.
+Several pre-defined variables are set as a program
+runs; these will be described as needed and summarized below.
+.SS Records
+Normally, records are separated by newline characters. You can control how
+records are separated by assigning values to the built-in variable
+.BR RS .
+If
+.B RS
+is any single character, that character separates records.
+Otherwise,
+.B RS
+is a regular expression. Text in the input that matches this
+regular expression will separate the record.
+However, in compatibility mode,
+only the first character of its string
+value is used for separating records.
+If
+.B RS
+is set to the null string, then records are separated by
+blank lines.
+When
+.B RS
+is set to the null string, the newline character always acts as
+a field separator, in addition to whatever value
+.B FS
+may have.
+.SS Fields
+.PP
+As each input record is read,
+.I gawk
+splits the record into
+.IR fields ,
+using the value of the
+.B FS
+variable as the field separator.
+If
+.B FS
+is a single character, fields are separated by that character.
+If
+.B FS
+is the null string, then each individual character becomes a
+separate field.
+Otherwise,
+.B FS
+is expected to be a full regular expression.
+In the special case that
+.B FS
+is a single space, fields are separated
+by runs of spaces and/or tabs and/or newlines.
+(But see the discussion of
+.BR \-\^\-posix ,
+below).
+Note that the value of
+.B IGNORECASE
+(see below) will also affect how fields are split when
+.B FS
+is a regular expression, and how records are separated when
+.B RS
+is a regular expression.
+.PP
+If the
+.B FIELDWIDTHS
+variable is set to a space separated list of numbers, each field is
+expected to have fixed width, and
+.I gawk
+will split up the record using the specified widths. The value of
+.B FS
+is ignored.
+Assigning a new value to
+.B FS
+overrides the use of
+.BR FIELDWIDTHS ,
+and restores the default behavior.
+.PP
+Each field in the input record may be referenced by its position,
+.BR $1 ,
+.BR $2 ,
+and so on.
+.B $0
+is the whole record. The value of a field may be assigned to as well.
+Fields need not be referenced by constants:
+.RS
+.PP
+.ft B
+n = 5
+.br
+print $n
+.ft R
+.RE
+.PP
+prints the fifth field in the input record.
+The variable
+.B NF
+is set to the total number of fields in the input record.
+.PP
+References to non-existent fields (i.e. fields after
+.BR $NF )
+produce the null-string. However, assigning to a non-existent field
+(e.g.,
+.BR "$(NF+2) = 5" )
+will increase the value of
+.BR NF ,
+create any intervening fields with the null string as their value, and
+cause the value of
+.B $0
+to be recomputed, with the fields being separated by the value of
+.BR OFS .
+References to negative numbered fields cause a fatal error.
+Decrementing
+.B NF
+causes the values of fields past the new value to be lost, and the value of
+.B $0
+to be recomputed, with the fields being separated by the value of
+.BR OFS .
+.SS Built-in Variables
+.PP
+.IR Gawk 's
+built-in variables are:
+.PP
+.TP \w'\fBFIELDWIDTHS\fR'u+1n
+.B ARGC
+The number of command line arguments (does not include options to
+.IR gawk ,
+or the program source).
+.TP
+.B ARGIND
+The index in
+.B ARGV
+of the current file being processed.
+.TP
+.B ARGV
+Array of command line arguments. The array is indexed from
+0 to
+.B ARGC
+\- 1.
+Dynamically changing the contents of
+.B ARGV
+can control the files used for data.
+.TP
+.B CONVFMT
+The conversion format for numbers, \fB"%.6g"\fR, by default.
+.TP
+.B ENVIRON
+An array containing the values of the current environment.
+The array is indexed by the environment variables, each element being
+the value of that variable (e.g., \fBENVIRON["HOME"]\fP might be
+.BR /home/arnold ).
+Changing this array does not affect the environment seen by programs which
+.I gawk
+spawns via redirection or the
+.B system()
+function.
+(This may change in a future version of
+.IR gawk .)
+.\" but don't hold your breath...
+.TP
+.B ERRNO
+If a system error occurs either doing a redirection for
+.BR getline ,
+during a read for
+.BR getline ,
+or during a
+.BR close() ,
+then
+.B ERRNO
+will contain
+a string describing the error.
+.TP
+.B FIELDWIDTHS
+A white-space separated list of fieldwidths. When set,
+.I gawk
+parses the input into fields of fixed width, instead of using the
+value of the
+.B FS
+variable as the field separator.
+The fixed field width facility is still experimental; the
+semantics may change as
+.I gawk
+evolves over time.
+.TP
+.B FILENAME
+The name of the current input file.
+If no files are specified on the command line, the value of
+.B FILENAME
+is \*(lq\-\*(rq.
+However,
+.B FILENAME
+is undefined inside the
+.B BEGIN
+block.
+.TP
+.B FNR
+The input record number in the current input file.
+.TP
+.B FS
+The input field separator, a space by default. See
+.BR Fields ,
+above.
+.TP
+.B IGNORECASE
+Controls the case-sensitivity of all regular expression
+and string operations. If
+.B IGNORECASE
+has a non-zero value, then string comparisons and
+pattern matching in rules,
+field splitting with
+.BR FS ,
+record separating with
+.BR RS ,
+regular expression
+matching with
+.B ~
+and
+.BR !~ ,
+and the
+.BR gensub() ,
+.BR gsub() ,
+.BR index() ,
+.BR match() ,
+.BR split() ,
+and
+.B sub()
+pre-defined functions will all ignore case when doing regular expression
+operations. Thus, if
+.B IGNORECASE
+is not equal to zero,
+.B /aB/
+matches all of the strings \fB"ab"\fP, \fB"aB"\fP, \fB"Ab"\fP,
+and \fB"AB"\fP.
+As with all \*(AK variables, the initial value of
+.B IGNORECASE
+is zero, so all regular expression and string
+operations are normally case-sensitive.
+Under Unix, the full ISO 8859-1 Latin-1 character set is used
+when ignoring case.
+.B NOTE:
+In versions of
+.I gawk
+prior to 3.0,
+.B IGNORECASE
+only affected regular expression operations. It now affects string
+comparisons as well.
+.TP
+.B NF
+The number of fields in the current input record.
+.TP
+.B NR
+The total number of input records seen so far.
+.TP
+.B OFMT
+The output format for numbers, \fB"%.6g"\fR, by default.
+.TP
+.B OFS
+The output field separator, a space by default.
+.TP
+.B ORS
+The output record separator, by default a newline.
+.TP
+.B RS
+The input record separator, by default a newline.
+.TP
+.B RT
+The record terminator.
+.I Gawk
+sets
+.B RT
+to the input text that matched the character or regular expression
+specified by
+.BR RS .
+.TP
+.B RSTART
+The index of the first character matched by
+.BR match() ;
+0 if no match.
+.TP
+.B RLENGTH
+The length of the string matched by
+.BR match() ;
+\-1 if no match.
+.TP
+.B SUBSEP
+The character used to separate multiple subscripts in array
+elements, by default \fB"\e034"\fR.
+.SS Arrays
+.PP
+Arrays are subscripted with an expression between square brackets
+.RB ( [ " and " ] ).
+If the expression is an expression list
+.RI ( expr ", " expr " .\|.\|.)"
+then the array subscript is a string consisting of the
+concatenation of the (string) value of each expression,
+separated by the value of the
+.B SUBSEP
+variable.
+This facility is used to simulate multiply dimensioned
+arrays. For example:
+.PP
+.RS
+.ft B
+i = "A";\^ j = "B";\^ k = "C"
+.br
+x[i, j, k] = "hello, world\en"
+.ft R
+.RE
+.PP
+assigns the string \fB"hello, world\en"\fR to the element of the array
+.B x
+which is indexed by the string \fB"A\e034B\e034C"\fR. All arrays in \*(AK
+are associative, i.e. indexed by string values.
+.PP
+The special operator
+.B in
+may be used in an
+.B if
+or
+.B while
+statement to see if an array has an index consisting of a particular
+value.
+.PP
+.RS
+.ft B
+.nf
+if (val in array)
+ print array[val]
+.fi
+.ft
+.RE
+.PP
+If the array has multiple subscripts, use
+.BR "(i, j) in array" .
+.PP
+The
+.B in
+construct may also be used in a
+.B for
+loop to iterate over all the elements of an array.
+.PP
+An element may be deleted from an array using the
+.B delete
+statement.
+The
+.B delete
+statement may also be used to delete the entire contents of an array,
+just by specifying the array name without a subscript.
+.SS Variable Typing And Conversion
+.PP
+Variables and fields
+may be (floating point) numbers, or strings, or both. How the
+value of a variable is interpreted depends upon its context. If used in
+a numeric expression, it will be treated as a number, if used as a string
+it will be treated as a string.
+.PP
+To force a variable to be treated as a number, add 0 to it; to force it
+to be treated as a string, concatenate it with the null string.
+.PP
+When a string must be converted to a number, the conversion is accomplished
+using
+.IR atof (3).
+A number is converted to a string by using the value of
+.B CONVFMT
+as a format string for
+.IR sprintf (3),
+with the numeric value of the variable as the argument.
+However, even though all numbers in \*(AK are floating-point,
+integral values are
+.I always
+converted as integers. Thus, given
+.PP
+.RS
+.ft B
+.nf
+CONVFMT = "%2.2f"
+a = 12
+b = a ""
+.fi
+.ft R
+.RE
+.PP
+the variable
+.B b
+has a string value of \fB"12"\fR and not \fB"12.00"\fR.
+.PP
+.I Gawk
+performs comparisons as follows:
+If two variables are numeric, they are compared numerically.
+If one value is numeric and the other has a string value that is a
+\*(lqnumeric string,\*(rq then comparisons are also done numerically.
+Otherwise, the numeric value is converted to a string and a string
+comparison is performed.
+Two strings are compared, of course, as strings.
+According to the \*(PX standard, even if two strings are
+numeric strings, a numeric comparison is performed. However, this is
+clearly incorrect, and
+.I gawk
+does not do this.
+.PP
+Note that string constants, such as \fB"57"\fP, are
+.I not
+numeric strings, they are string constants.
+The idea of \*(lqnumeric string\*(rq
+only applies to fields,
+.B getline
+input,
+.BR FILENAME ,
+.B ARGV
+elements,
+.B ENVIRON
+elements and the elements of an array created by
+.B split()
+that are numeric strings.
+The basic idea is that
+.IR "user input" ,
+and only user input, that looks numeric,
+should be treated that way.
+.PP
+Uninitialized variables have the numeric value 0 and the string value ""
+(the null, or empty, string).
+.SH PATTERNS AND ACTIONS
+\*(AK is a line-oriented language. The pattern comes first, and then the
+action. Action statements are enclosed in
+.B {
+and
+.BR } .
+Either the pattern may be missing, or the action may be missing, but,
+of course, not both. If the pattern is missing, the action will be
+executed for every single record of input.
+A missing action is equivalent to
+.RS
+.PP
+.B "{ print }"
+.RE
+.PP
+which prints the entire record.
+.PP
+Comments begin with the \*(lq#\*(rq character, and continue until the
+end of the line.
+Blank lines may be used to separate statements.
+Normally, a statement ends with a newline, however, this is not the
+case for lines ending in
+a \*(lq,\*(rq,
+.BR { ,
+.BR ? ,
+.BR : ,
+.BR && ,
+or
+.BR || .
+Lines ending in
+.B do
+or
+.B else
+also have their statements automatically continued on the following line.
+In other cases, a line can be continued by ending it with a \*(lq\e\*(rq,
+in which case the newline will be ignored.
+.PP
+Multiple statements may
+be put on one line by separating them with a \*(lq;\*(rq.
+This applies to both the statements within the action part of a
+pattern-action pair (the usual case),
+and to the pattern-action statements themselves.
+.SS Patterns
+\*(AK patterns may be one of the following:
+.PP
+.RS
+.nf
+.B BEGIN
+.B END
+.BI / "regular expression" /
+.I "relational expression"
+.IB pattern " && " pattern
+.IB pattern " || " pattern
+.IB pattern " ? " pattern " : " pattern
+.BI ( pattern )
+.BI ! " pattern"
+.IB pattern1 ", " pattern2
+.fi
+.RE
+.PP
+.B BEGIN
+and
+.B END
+are two special kinds of patterns which are not tested against
+the input.
+The action parts of all
+.B BEGIN
+patterns are merged as if all the statements had
+been written in a single
+.B BEGIN
+block. They are executed before any
+of the input is read. Similarly, all the
+.B END
+blocks are merged,
+and executed when all the input is exhausted (or when an
+.B exit
+statement is executed).
+.B BEGIN
+and
+.B END
+patterns cannot be combined with other patterns in pattern expressions.
+.B BEGIN
+and
+.B END
+patterns cannot have missing action parts.
+.PP
+For
+.BI / "regular expression" /
+patterns, the associated statement is executed for each input record that matches
+the regular expression.
+Regular expressions are the same as those in
+.IR egrep (1),
+and are summarized below.
+.PP
+A
+.I "relational expression"
+may use any of the operators defined below in the section on actions.
+These generally test whether certain fields match certain regular expressions.
+.PP
+The
+.BR && ,
+.BR || ,
+and
+.B !
+operators are logical AND, logical OR, and logical NOT, respectively, as in C.
+They do short-circuit evaluation, also as in C, and are used for combining
+more primitive pattern expressions. As in most languages, parentheses
+may be used to change the order of evaluation.
+.PP
+The
+.B ?\^:
+operator is like the same operator in C. If the first pattern is true
+then the pattern used for testing is the second pattern, otherwise it is
+the third. Only one of the second and third patterns is evaluated.
+.PP
+The
+.IB pattern1 ", " pattern2
+form of an expression is called a
+.IR "range pattern" .
+It matches all input records starting with a record that matches
+.IR pattern1 ,
+and continuing until a record that matches
+.IR pattern2 ,
+inclusive. It does not combine with any other sort of pattern expression.
+.SS Regular Expressions
+Regular expressions are the extended kind found in
+.IR egrep .
+They are composed of characters as follows:
+.TP \w'\fB[^\fIabc.\|.\|.\fB]\fR'u+2n
+.I c
+matches the non-metacharacter
+.IR c .
+.TP
+.I \ec
+matches the literal character
+.IR c .
+.TP
+.B .
+matches any character
+.I including
+newline.
+.TP
+.B ^
+matches the beginning of a string.
+.TP
+.B $
+matches the end of a string.
+.TP
+.BI [ abc.\|.\|. ]
+character list, matches any of the characters
+.IR abc.\|.\|. .
+.TP
+.BI [^ abc.\|.\|. ]
+negated character list, matches any character except
+.IR abc.\|.\|. .
+.TP
+.IB r1 | r2
+alternation: matches either
+.I r1
+or
+.IR r2 .
+.TP
+.I r1r2
+concatenation: matches
+.IR r1 ,
+and then
+.IR r2 .
+.TP
+.IB r +
+matches one or more
+.IR r 's.
+.TP
+.IB r *
+matches zero or more
+.IR r 's.
+.TP
+.IB r ?
+matches zero or one
+.IR r 's.
+.TP
+.BI ( r )
+grouping: matches
+.IR r .
+.TP
+.PD 0
+.IB r { n }
+.TP
+.PD 0
+.IB r { n ,}
+.TP
+.PD
+.IB r { n , m }
+One or two numbers inside braces denote an
+.IR "interval expression" .
+If there is one number in the braces, the preceding regexp
+.I r
+is repeated
+.I n
+times. If there are two numbers separated by a comma,
+.I r
+is repeated
+.I n
+to
+.I m
+times.
+If there is one number followed by a comma, then
+.I r
+is repeated at least
+.I n
+times.
+.sp .5
+Interval expressions are only available if either
+.B \-\^\-posix
+or
+.B \-\^\-re\-interval
+is specified on the command line.
+.TP
+.B \ey
+matches the empty string at either the beginning or the
+end of a word.
+.TP
+.B \eB
+matches the empty string within a word.
+.TP
+.B \e<
+matches the empty string at the beginning of a word.
+.TP
+.B \e>
+matches the empty string at the end of a word.
+.TP
+.B \ew
+matches any word-constituent character (letter, digit, or underscore).
+.TP
+.B \eW
+matches any character that is not word-constituent.
+.TP
+.B \e`
+matches the empty string at the beginning of a buffer (string).
+.TP
+.B \e'
+matches the empty string at the end of a buffer.
+.PP
+The escape sequences that are valid in string constants (see below)
+are also legal in regular expressions.
+.PP
+.I "Character classes"
+are a new feature introduced in the \*(PX standard.
+A character class is a special notation for describing
+lists of characters that have a specific attribute, but where the
+actual characters themselves can vary from country to country and/or
+from character set to character set. For example, the notion of what
+is an alphabetic character differs in the USA and in France.
+.PP
+A character class is only valid in a regexp
+.I inside
+the brackets of a character list. Character classes consist of
+.BR [: ,
+a keyword denoting the class, and
+.BR :] .
+Here are the character
+classes defined by the \*(PX standard.
+.TP
+.B [:alnum:]
+Alphanumeric characters.
+.TP
+.B [:alpha:]
+Alphabetic characters.
+.TP
+.B [:blank:]
+Space or tab characters.
+.TP
+.B [:cntrl:]
+Control characters.
+.TP
+.B [:digit:]
+Numeric characters.
+.TP
+.B [:graph:]
+Characters that are both printable and visible.
+(A space is printable, but not visible, while an
+.B a
+is both.)
+.TP
+.B [:lower:]
+Lower-case alphabetic characters.
+.TP
+.B [:print:]
+Printable characters (characters that are not control characters.)
+.TP
+.B [:punct:]
+Punctuation characters (characters that are not letter, digits,
+control characters, or space characters).
+.TP
+.B [:space:]
+Space characters (such as space, tab, and formfeed, to name a few).
+.TP
+.B [:upper:]
+Upper-case alphabetic characters.
+.TP
+.B [:xdigit:]
+Characters that are hexadecimal digits.
+.PP
+For example, before the \*(PX standard, to match alphanumeric
+characters, you would have had to write
+.BR /[A\-Za\-z0\-9]/ .
+If your character set had other alphabetic characters in it, this would not
+match them. With the \*(PX character classes, you can write
+.BR /[[:alnum:]]/ ,
+and this will match
+.I all
+the alphabetic and numeric characters in your character set.
+.PP
+Two additional special sequences can appear in character lists.
+These apply to non-ASCII character sets, which can have single symbols
+(called
+.IR "collating elements" )
+that are represented with more than one
+character, as well as several characters that are equivalent for
+.IR collating ,
+or sorting, purposes. (E.g., in French, a plain \*(lqe\*(rq
+and a grave-accented e\` are equivalent.)
+.TP
+Collating Symbols
+A collating symbols is a multi-character collating element enclosed in
+.B [.
+and
+.BR .] .
+For example, if
+.B ch
+is a collating element, then
+.B [[.ch.]]
+is a regexp that matches this collating element, while
+.B [ch]
+is a regexp that matches either
+.B c
+or
+.BR h .
+.TP
+Equivalence Classes
+An equivalence class is a locale-specific name for a list of
+characters that are equivalent. The name is enclosed in
+.B [=
+and
+.BR =] .
+For example, the name
+.B e
+might be used to represent all of
+\*(lqe,\*(rq \*(lqe\`,\*(rq and \*(lqe\`.\*(rq
+In this case,
+.B [[=e]]
+is a regexp
+that matches any of
+ .BR e ,
+ .BR e\' ,
+or
+ .BR e\` .
+.PP
+These features are very valuable in non-English speaking locales.
+The library functions that
+.I gawk
+uses for regular expression matching
+currently only recognize \*(PX character classes; they do not recognize
+collating symbols or equivalence classes.
+.PP
+The
+.BR \ey ,
+.BR \eB ,
+.BR \e< ,
+.BR \e> ,
+.BR \ew ,
+.BR \eW ,
+.BR \e` ,
+and
+.B \e'
+operators are specific to
+.IR gawk ;
+they are extensions based on facilities in the \*(GN regexp libraries.
+.PP
+The various command line options
+control how
+.I gawk
+interprets characters in regexps.
+.TP
+No options
+In the default case,
+.I gawk
+provide all the facilities of
+\*(PX regexps and the \*(GN regexp operators described above.
+However, interval expressions are not supported.
+.TP
+.B \-\^\-posix
+Only \*(PX regexps are supported, the \*(GN operators are not special.
+(E.g.,
+.B \ew
+matches a literal
+.BR w ).
+Interval expressions are allowed.
+.TP
+.B \-\^\-traditional
+Traditional Unix
+.I awk
+regexps are matched. The \*(GN operators
+are not special, interval expressions are not available, and neither
+are the \*(PX character classes
+.RB ( [[:alnum:]]
+and so on).
+Characters described by octal and hexadecimal escape sequences are
+treated literally, even if they represent regexp metacharacters.
+.TP
+.B \-\^\-re\-interval
+Allow interval expressions in regexps, even if
+.B \-\^\-traditional
+has been provided.
+.SS Actions
+Action statements are enclosed in braces,
+.B {
+and
+.BR } .
+Action statements consist of the usual assignment, conditional, and looping
+statements found in most languages. The operators, control statements,
+and input/output statements
+available are patterned after those in C.
+.SS Operators
+.PP
+The operators in \*(AK, in order of decreasing precedence, are
+.PP
+.TP "\w'\fB*= /= %= ^=\fR'u+1n"
+.BR ( \&.\|.\|. )
+Grouping
+.TP
+.B $
+Field reference.
+.TP
+.B "++ \-\^\-"
+Increment and decrement, both prefix and postfix.
+.TP
+.B ^
+Exponentiation (\fB**\fR may also be used, and \fB**=\fR for
+the assignment operator).
+.TP
+.B "+ \- !"
+Unary plus, unary minus, and logical negation.
+.TP
+.B "* / %"
+Multiplication, division, and modulus.
+.TP
+.B "+ \-"
+Addition and subtraction.
+.TP
+.I space
+String concatenation.
+.TP
+.PD 0
+.B "< >"
+.TP
+.PD 0
+.B "<= >="
+.TP
+.PD
+.B "!= =="
+The regular relational operators.
+.TP
+.B "~ !~"
+Regular expression match, negated match.
+.B NOTE:
+Do not use a constant regular expression
+.RB ( /foo/ )
+on the left-hand side of a
+.B ~
+or
+.BR !~ .
+Only use one on the right-hand side. The expression
+.BI "/foo/ ~ " exp
+has the same meaning as \fB(($0 ~ /foo/) ~ \fIexp\fB)\fR.
+This is usually
+.I not
+what was intended.
+.TP
+.B in
+Array membership.
+.TP
+.B &&
+Logical AND.
+.TP
+.B ||
+Logical OR.
+.TP
+.B ?:
+The C conditional expression. This has the form
+.IB expr1 " ? " expr2 " : " expr3\c
+\&.
+If
+.I expr1
+is true, the value of the expression is
+.IR expr2 ,
+otherwise it is
+.IR expr3 .
+Only one of
+.I expr2
+and
+.I expr3
+is evaluated.
+.TP
+.PD 0
+.B "= += \-="
+.TP
+.PD
+.B "*= /= %= ^="
+Assignment. Both absolute assignment
+.BI ( var " = " value )
+and operator-assignment (the other forms) are supported.
+.SS Control Statements
+.PP
+The control statements are
+as follows:
+.PP
+.RS
+.nf
+\fBif (\fIcondition\fB) \fIstatement\fR [ \fBelse\fI statement \fR]
+\fBwhile (\fIcondition\fB) \fIstatement \fR
+\fBdo \fIstatement \fBwhile (\fIcondition\fB)\fR
+\fBfor (\fIexpr1\fB; \fIexpr2\fB; \fIexpr3\fB) \fIstatement\fR
+\fBfor (\fIvar \fBin\fI array\fB) \fIstatement\fR
+\fBbreak\fR
+\fBcontinue\fR
+\fBdelete \fIarray\^\fB[\^\fIindex\^\fB]\fR
+\fBdelete \fIarray\^\fR
+\fBexit\fR [ \fIexpression\fR ]
+\fB{ \fIstatements \fB}
+.fi
+.RE
+.SS "I/O Statements"
+.PP
+The input/output statements are as follows:
+.PP
+.TP "\w'\fBprintf \fIfmt, expr-list\fR'u+1n"
+.BI close( file )
+Close file (or pipe, see below).
+.TP
+.B getline
+Set
+.B $0
+from next input record; set
+.BR NF ,
+.BR NR ,
+.BR FNR .
+.TP
+.BI "getline <" file
+Set
+.B $0
+from next record of
+.IR file ;
+set
+.BR NF .
+.TP
+.BI getline " var"
+Set
+.I var
+from next input record; set
+.BR NR ,
+.BR FNR .
+.TP
+.BI getline " var" " <" file
+Set
+.I var
+from next record of
+.IR file .
+.TP
+.B next
+Stop processing the current input record. The next input record
+is read and processing starts over with the first pattern in the
+\*(AK program. If the end of the input data is reached, the
+.B END
+block(s), if any, are executed.
+.TP
+.B "nextfile"
+Stop processing the current input file. The next input record read
+comes from the next input file.
+.B FILENAME
+and
+.B ARGIND
+are updated,
+.B FNR
+is reset to 1, and processing starts over with the first pattern in the
+\*(AK program. If the end of the input data is reached, the
+.B END
+block(s), if any, are executed.
+.B NOTE:
+Earlier versions of gawk used
+.BR "next file" ,
+as two words. While this usage is still recognized, it generates a
+warning message and will eventually be removed.
+.TP
+.B print
+Prints the current record.
+The output record is terminated with the value of the
+.B ORS
+variable.
+.TP
+.BI print " expr-list"
+Prints expressions.
+Each expression is separated by the value of the
+.B OFS
+variable.
+The output record is terminated with the value of the
+.B ORS
+variable.
+.TP
+.BI print " expr-list" " >" file
+Prints expressions on
+.IR file .
+Each expression is separated by the value of the
+.B OFS
+variable. The output record is terminated with the value of the
+.B ORS
+variable.
+.TP
+.BI printf " fmt, expr-list"
+Format and print.
+.TP
+.BI printf " fmt, expr-list" " >" file
+Format and print on
+.IR file .
+.TP
+.BI system( cmd-line )
+Execute the command
+.IR cmd-line ,
+and return the exit status.
+(This may not be available on non-\*(PX systems.)
+.TP
+\&\fBfflush(\fR[\fIfile\^\fR]\fB)\fR
+Flush any buffers associated with the open output file or pipe
+.IR file .
+If
+.I file
+is missing, then standard output is flushed.
+If
+.I file
+is the null string,
+then all open output files and pipes
+have their buffers flushed.
+.PP
+Other input/output redirections are also allowed. For
+.B print
+and
+.BR printf ,
+.BI >> " file"
+appends output to the
+.IR file ,
+while
+.BI | " command"
+writes on a pipe.
+In a similar fashion,
+.IB command " | getline"
+pipes into
+.BR getline .
+The
+.BR getline
+command will return 0 on end of file, and \-1 on an error.
+.PP
+NOTE: If using a pipe to
+.BR getline ,
+or from
+.B print
+or
+.BR printf
+within a loop, you
+.I must
+use
+.B close()
+to create new instances of the command.
+AWK does not automatically close pipes when
+they return EOF.
+.SS The \fIprintf\fP\^ Statement
+.PP
+The \*(AK versions of the
+.B printf
+statement and
+.B sprintf()
+function
+(see below)
+accept the following conversion specification formats:
+.TP
+.B %c
+An \s-1ASCII\s+1 character.
+If the argument used for
+.B %c
+is numeric, it is treated as a character and printed.
+Otherwise, the argument is assumed to be a string, and the only first
+character of that string is printed.
+.TP
+.PD 0
+.B %d
+.TP
+.PD
+.B %i
+A decimal number (the integer part).
+.TP
+.PD 0
+.B %e
+.TP
+.PD
+.B %E
+A floating point number of the form
+.BR [\-]d.dddddde[+\^\-]dd .
+The
+.B %E
+format uses
+.B E
+instead of
+.BR e .
+.TP
+.B %f
+A floating point number of the form
+.BR [\-]ddd.dddddd .
+.TP
+.PD 0
+.B %g
+.TP
+.PD
+.B %G
+Use
+.B %e
+or
+.B %f
+conversion, whichever is shorter, with nonsignificant zeros suppressed.
+The
+.B %G
+format uses
+.B %E
+instead of
+.BR %e .
+.TP
+.B %o
+An unsigned octal number (also an integer).
+.TP
+.PD
+.B %u
+An unsigned decimal number (again, an integer).
+.TP
+.B %s
+A character string.
+.TP
+.PD 0
+.B %x
+.TP
+.PD
+.B %X
+An unsigned hexadecimal number (an integer).
+The
+.B %X
+format uses
+.B ABCDEF
+instead of
+.BR abcdef .
+.TP
+.B %%
+A single
+.B %
+character; no argument is converted.
+.PP
+There are optional, additional parameters that may lie between the
+.B %
+and the control letter:
+.TP
+.B \-
+The expression should be left-justified within its field.
+.TP
+.I space
+For numeric conversions, prefix positive values with a space, and
+negative values with a minus sign.
+.TP
+.B +
+The plus sign, used before the width modifier (see below),
+says to always supply a sign for numeric conversions, even if the data
+to be formatted is positive. The
+.B +
+overrides the space modifier.
+.TP
+.B #
+Use an \*(lqalternate form\*(rq for certain control letters.
+For
+.BR %o ,
+supply a leading zero.
+For
+.BR %x ,
+and
+.BR %X ,
+supply a leading
+.BR 0x
+or
+.BR 0X
+for
+a nonzero result.
+For
+.BR %e ,
+.BR %E ,
+and
+.BR %f ,
+the result will always contain a
+decimal point.
+For
+.BR %g ,
+and
+.BR %G ,
+trailing zeros are not removed from the result.
+.TP
+.B 0
+A leading
+.B 0
+(zero) acts as a flag, that indicates output should be
+padded with zeroes instead of spaces.
+This applies even to non-numeric output formats.
+This flag only has an effect when the field width is wider than the
+value to be printed.
+.TP
+.I width
+The field should be padded to this width. The field is normally padded
+with spaces. If the
+.B 0
+flag has been used, it is padded with zeroes.
+.TP
+.BI \&. prec
+A number that specifies the precision to use when printing.
+For the
+.BR %e ,
+.BR %E ,
+and
+.BR %f
+formats, this specifies the
+number of digits you want printed to the right of the decimal point.
+For the
+.BR %g ,
+and
+.B %G
+formats, it specifies the maximum number
+of significant digits. For the
+.BR %d ,
+.BR %o ,
+.BR %i ,
+.BR %u ,
+.BR %x ,
+and
+.B %X
+formats, it specifies the minimum number of
+digits to print. For a string, it specifies the maximum number of
+characters from the string that should be printed.
+.PP
+The dynamic
+.I width
+and
+.I prec
+capabilities of the \*(AN C
+.B printf()
+routines are supported.
+A
+.B *
+in place of either the
+.B width
+or
+.B prec
+specifications will cause their values to be taken from
+the argument list to
+.B printf
+or
+.BR sprintf() .
+.SS Special File Names
+.PP
+When doing I/O redirection from either
+.B print
+or
+.B printf
+into a file,
+or via
+.B getline
+from a file,
+.I gawk
+recognizes certain special filenames internally. These filenames
+allow access to open file descriptors inherited from
+.IR gawk 's
+parent process (usually the shell).
+Other special filenames provide access to information about the running
+.B gawk
+process.
+The filenames are:
+.TP \w'\fB/dev/stdout\fR'u+1n
+.B /dev/pid
+Reading this file returns the process ID of the current process,
+in decimal, terminated with a newline.
+.TP
+.B /dev/ppid
+Reading this file returns the parent process ID of the current process,
+in decimal, terminated with a newline.
+.TP
+.B /dev/pgrpid
+Reading this file returns the process group ID of the current process,
+in decimal, terminated with a newline.
+.TP
+.B /dev/user
+Reading this file returns a single record terminated with a newline.
+The fields are separated with spaces.
+.B $1
+is the value of the
+.IR getuid (2)
+system call,
+.B $2
+is the value of the
+.IR geteuid (2)
+system call,
+.B $3
+is the value of the
+.IR getgid (2)
+system call, and
+.B $4
+is the value of the
+.IR getegid (2)
+system call.
+If there are any additional fields, they are the group IDs returned by
+.IR getgroups (2).
+Multiple groups may not be supported on all systems.
+.TP
+.B /dev/stdin
+The standard input.
+.TP
+.B /dev/stdout
+The standard output.
+.TP
+.B /dev/stderr
+The standard error output.
+.TP
+.BI /dev/fd/\^ n
+The file associated with the open file descriptor
+.IR n .
+.PP
+These are particularly useful for error messages. For example:
+.PP
+.RS
+.ft B
+print "You blew it!" > "/dev/stderr"
+.ft R
+.RE
+.PP
+whereas you would otherwise have to use
+.PP
+.RS
+.ft B
+print "You blew it!" | "cat 1>&2"
+.ft R
+.RE
+.PP
+These file names may also be used on the command line to name data files.
+.SS Numeric Functions
+.PP
+\*(AK has the following pre-defined arithmetic functions:
+.PP
+.TP \w'\fBsrand(\fR[\fIexpr\^\fR]\fB)\fR'u+1n
+.BI atan2( y , " x" )
+returns the arctangent of
+.I y/x
+in radians.
+.TP
+.BI cos( expr )
+returns the cosine of
+.IR expr ,
+which is in radians.
+.TP
+.BI exp( expr )
+the exponential function.
+.TP
+.BI int( expr )
+truncates to integer.
+.TP
+.BI log( expr )
+the natural logarithm function.
+.TP
+.B rand()
+returns a random number between 0 and 1.
+.TP
+.BI sin( expr )
+returns the sine of
+.IR expr ,
+which is in radians.
+.TP
+.BI sqrt( expr )
+the square root function.
+.TP
+\&\fBsrand(\fR[\fIexpr\^\fR]\fB)\fR
+uses
+.I expr
+as a new seed for the random number generator. If no
+.I expr
+is provided, the time of day will be used.
+The return value is the previous seed for the random
+number generator.
+.SS String Functions
+.PP
+.I Gawk
+has the following pre-defined string functions:
+.PP
+.TP "\w'\fBsprintf(\^\fIfmt\fB\^, \fIexpr-list\^\fB)\fR'u+1n"
+\fBgensub(\fIr\fB, \fIs\fB, \fIh \fR[\fB, \fIt\fR]\fB)\fR
+search the target string
+.I t
+for matches of the regular expression
+.IR r .
+If
+.I h
+is a string beginning with
+.B g
+or
+.BR G ,
+then replace all matches of
+.I r
+with
+.IR s .
+Otherwise,
+.I h
+is a number indicating which match of
+.I r
+to replace.
+If no
+.I t
+is supplied,
+.B $0
+is used instead.
+Within the replacement text
+.IR s ,
+the sequence
+.BI \e n\fR,
+where
+.I n
+is a digit from 1 to 9, may be used to indicate just the text that
+matched the
+.IR n 'th
+parenthesized subexpression. The sequence
+.B \e0
+represents the entire matched text, as does the character
+.BR & .
+Unlike
+.B sub()
+and
+.BR gsub() ,
+the modified string is returned as the result of the function,
+and the original target string is
+.I not
+changed.
+.TP "\w'\fBsprintf(\^\fIfmt\fB\^, \fIexpr-list\^\fB)\fR'u+1n"
+\fBgsub(\fIr\fB, \fIs \fR[\fB, \fIt\fR]\fB)\fR
+for each substring matching the regular expression
+.I r
+in the string
+.IR t ,
+substitute the string
+.IR s ,
+and return the number of substitutions.
+If
+.I t
+is not supplied, use
+.BR $0 .
+An
+.B &
+in the replacement text is replaced with the text that was actually matched.
+Use
+.B \e&
+to get a literal
+.BR & .
+See
+.I "Effective AWK Programming"
+for a fuller discussion of the rules for
+.BR &'s
+and backslashes in the replacement text of
+.BR sub() ,
+.BR gsub() ,
+and
+.BR gensub() .
+.TP
+.BI index( s , " t" )
+returns the index of the string
+.I t
+in the string
+.IR s ,
+or 0 if
+.I t
+is not present.
+.TP
+\fBlength(\fR[\fIs\fR]\fB)
+returns the length of the string
+.IR s ,
+or the length of
+.B $0
+if
+.I s
+is not supplied.
+.TP
+.BI match( s , " r" )
+returns the position in
+.I s
+where the regular expression
+.I r
+occurs, or 0 if
+.I r
+is not present, and sets the values of
+.B RSTART
+and
+.BR RLENGTH .
+.TP
+\fBsplit(\fIs\fB, \fIa \fR[\fB, \fIr\fR]\fB)\fR
+splits the string
+.I s
+into the array
+.I a
+on the regular expression
+.IR r ,
+and returns the number of fields. If
+.I r
+is omitted,
+.B FS
+is used instead.
+The array
+.I a
+is cleared first.
+Splitting behaves identically to field splitting, described above.
+.TP
+.BI sprintf( fmt , " expr-list" )
+prints
+.I expr-list
+according to
+.IR fmt ,
+and returns the resulting string.
+.TP
+\fBsub(\fIr\fB, \fIs \fR[\fB, \fIt\fR]\fB)\fR
+just like
+.BR gsub() ,
+but only the first matching substring is replaced.
+.TP
+\fBsubstr(\fIs\fB, \fIi \fR[\fB, \fIn\fR]\fB)\fR
+returns the at most
+.IR n -character
+substring of
+.I s
+starting at
+.IR i .
+If
+.I n
+is omitted, the rest of
+.I s
+is used.
+.TP
+.BI tolower( str )
+returns a copy of the string
+.IR str ,
+with all the upper-case characters in
+.I str
+translated to their corresponding lower-case counterparts.
+Non-alphabetic characters are left unchanged.
+.TP
+.BI toupper( str )
+returns a copy of the string
+.IR str ,
+with all the lower-case characters in
+.I str
+translated to their corresponding upper-case counterparts.
+Non-alphabetic characters are left unchanged.
+.SS Time Functions
+.PP
+Since one of the primary uses of \*(AK programs is processing log files
+that contain time stamp information,
+.I gawk
+provides the following two functions for obtaining time stamps and
+formatting them.
+.PP
+.TP "\w'\fBsystime()\fR'u+1n"
+.B systime()
+returns the current time of day as the number of seconds since the Epoch
+(Midnight UTC, January 1, 1970 on \*(PX systems).
+.TP
+\fBstrftime(\fR[\fIformat \fR[\fB, \fItimestamp\fR]]\fB)\fR
+formats
+.I timestamp
+according to the specification in
+.IR format.
+The
+.I timestamp
+should be of the same form as returned by
+.BR systime() .
+If
+.I timestamp
+is missing, the current time of day is used.
+If
+.I format
+is missing, a default format equivalent to the output of
+.IR date (1)
+will be used.
+See the specification for the
+.B strftime()
+function in \*(AN C for the format conversions that are
+guaranteed to be available.
+A public-domain version of
+.IR strftime (3)
+and a man page for it come with
+.IR gawk ;
+if that version was used to build
+.IR gawk ,
+then all of the conversions described in that man page are available to
+.IR gawk.
+.SS String Constants
+.PP
+String constants in \*(AK are sequences of characters enclosed
+between double quotes (\fB"\fR). Within strings, certain
+.I "escape sequences"
+are recognized, as in C. These are:
+.PP
+.TP \w'\fB\e\^\fIddd\fR'u+1n
+.B \e\e
+A literal backslash.
+.TP
+.B \ea
+The \*(lqalert\*(rq character; usually the \s-1ASCII\s+1 \s-1BEL\s+1 character.
+.TP
+.B \eb
+backspace.
+.TP
+.B \ef
+form-feed.
+.TP
+.B \en
+newline.
+.TP
+.B \er
+carriage return.
+.TP
+.B \et
+horizontal tab.
+.TP
+.B \ev
+vertical tab.
+.TP
+.BI \ex "\^hex digits"
+The character represented by the string of hexadecimal digits following
+the
+.BR \ex .
+As in \*(AN C, all following hexadecimal digits are considered part of
+the escape sequence.
+(This feature should tell us something about language design by committee.)
+E.g., \fB"\ex1B"\fR is the \s-1ASCII\s+1 \s-1ESC\s+1 (escape) character.
+.TP
+.BI \e ddd
+The character represented by the 1-, 2-, or 3-digit sequence of octal
+digits.
+E.g., \fB"\e033"\fR is the \s-1ASCII\s+1 \s-1ESC\s+1 (escape) character.
+.TP
+.BI \e c
+The literal character
+.IR c\^ .
+.PP
+The escape sequences may also be used inside constant regular expressions
+(e.g.,
+.B "/[\ \et\ef\en\er\ev]/"
+matches whitespace characters).
+.PP
+In compatibility mode, the characters represented by octal and
+hexadecimal escape sequences are treated literally when used in
+regexp constants. Thus,
+.B /a\e52b/
+is equivalent to
+.BR /a\e*b/ .
+.SH FUNCTIONS
+Functions in \*(AK are defined as follows:
+.PP
+.RS
+\fBfunction \fIname\fB(\fIparameter list\fB) { \fIstatements \fB}\fR
+.RE
+.PP
+Functions are executed when they are called from within expressions
+in either patterns or actions. Actual parameters supplied in the function
+call are used to instantiate the formal parameters declared in the function.
+Arrays are passed by reference, other variables are passed by value.
+.PP
+Since functions were not originally part of the \*(AK language, the provision
+for local variables is rather clumsy: They are declared as extra parameters
+in the parameter list. The convention is to separate local variables from
+real parameters by extra spaces in the parameter list. For example:
+.PP
+.RS
+.ft B
+.nf
+function f(p, q, a, b) # a & b are local
+{
+ \&.\|.\|.
+}
+
+/abc/ { .\|.\|. ; f(1, 2) ; .\|.\|. }
+.fi
+.ft R
+.RE
+.PP
+The left parenthesis in a function call is required
+to immediately follow the function name,
+without any intervening white space.
+This is to avoid a syntactic ambiguity with the concatenation operator.
+This restriction does not apply to the built-in functions listed above.
+.PP
+Functions may call each other and may be recursive.
+Function parameters used as local variables are initialized
+to the null string and the number zero upon function invocation.
+.PP
+Use
+.BI return " expr"
+to return a value from a function. The return value is undefined if no
+value is provided, or if the function returns by \*(lqfalling off\*(rq the
+end.
+.PP
+If
+.B \-\^\-lint
+has been provided,
+.I gawk
+will warn about calls to undefined functions at parse time,
+instead of at run time.
+Calling an undefined function at run time is a fatal error.
+.PP
+The word
+.B func
+may be used in place of
+.BR function .
+.SH EXAMPLES
+.nf
+Print and sort the login names of all users:
+
+.ft B
+ BEGIN { FS = ":" }
+ { print $1 | "sort" }
+
+.ft R
+Count lines in a file:
+
+.ft B
+ { nlines++ }
+ END { print nlines }
+
+.ft R
+Precede each line by its number in the file:
+
+.ft B
+ { print FNR, $0 }
+
+.ft R
+Concatenate and line number (a variation on a theme):
+
+.ft B
+ { print NR, $0 }
+.ft R
+.fi
+.SH SEE ALSO
+.IR egrep (1),
+.IR getpid (2),
+.IR getppid (2),
+.IR getpgrp (2),
+.IR getuid (2),
+.IR geteuid (2),
+.IR getgid (2),
+.IR getegid (2),
+.IR getgroups (2)
+.PP
+.IR "The AWK Programming Language" ,
+Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger,
+Addison-Wesley, 1988. ISBN 0-201-07981-X.
+.PP
+.IR "Effective AWK Programming" ,
+Edition 1.0, published by the Free Software Foundation, 1995.
+.SH POSIX COMPATIBILITY
+A primary goal for
+.I gawk
+is compatibility with the \*(PX standard, as well as with the
+latest version of \*(UX
+.IR awk .
+To this end,
+.I gawk
+incorporates the following user visible
+features which are not described in the \*(AK book,
+but are part of the Bell Labs version of
+.IR awk ,
+and are in the \*(PX standard.
+.PP
+The
+.B \-v
+option for assigning variables before program execution starts is new.
+The book indicates that command line variable assignment happens when
+.I awk
+would otherwise open the argument as a file, which is after the
+.B BEGIN
+block is executed. However, in earlier implementations, when such an
+assignment appeared before any file names, the assignment would happen
+.I before
+the
+.B BEGIN
+block was run. Applications came to depend on this \*(lqfeature.\*(rq
+When
+.I awk
+was changed to match its documentation, this option was added to
+accommodate applications that depended upon the old behavior.
+(This feature was agreed upon by both the AT&T and \*(GN developers.)
+.PP
+The
+.B \-W
+option for implementation specific features is from the \*(PX standard.
+.PP
+When processing arguments,
+.I gawk
+uses the special option \*(lq\-\^\-\*(rq to signal the end of
+arguments.
+In compatibility mode, it will warn about, but otherwise ignore,
+undefined options.
+In normal operation, such arguments are passed on to the \*(AK program for
+it to process.
+.PP
+The \*(AK book does not define the return value of
+.BR srand() .
+The \*(PX standard
+has it return the seed it was using, to allow keeping track
+of random number sequences. Therefore
+.B srand()
+in
+.I gawk
+also returns its current seed.
+.PP
+Other new features are:
+The use of multiple
+.B \-f
+options (from MKS
+.IR awk );
+the
+.B ENVIRON
+array; the
+.BR \ea ,
+and
+.BR \ev
+escape sequences (done originally in
+.I gawk
+and fed back into AT&T's); the
+.B tolower()
+and
+.B toupper()
+built-in functions (from AT&T); and the \*(AN C conversion specifications in
+.B printf
+(done first in AT&T's version).
+.SH GNU EXTENSIONS
+.I Gawk
+has a number of extensions to \*(PX
+.IR awk .
+They are described in this section. All the extensions described here
+can be disabled by
+invoking
+.I gawk
+with the
+.B \-\^\-traditional
+option.
+.PP
+The following features of
+.I gawk
+are not available in
+\*(PX
+.IR awk .
+.RS
+.TP \w'\(bu'u+1n
+\(bu
+The
+.B \ex
+escape sequence.
+(Disabled with
+.BR \-\^\-posix .)
+.TP \w'\(bu'u+1n
+\(bu
+The
+.B fflush()
+function.
+(Disabled with
+.BR \-\^\-posix .)
+.TP
+\(bu
+The
+.BR systime(),
+.BR strftime(),
+and
+.B gensub()
+functions.
+.TP
+\(bu
+The special file names available for I/O redirection are not recognized.
+.TP
+\(bu
+The
+.BR ARGIND ,
+.BR ERRNO ,
+and
+.B RT
+variables are not special.
+.TP
+\(bu
+The
+.B IGNORECASE
+variable and its side-effects are not available.
+.TP
+\(bu
+The
+.B FIELDWIDTHS
+variable and fixed-width field splitting.
+.TP
+\(bu
+The use of
+.B RS
+as a regular expression.
+.TP
+\(bu
+The ability to split out individual characters using the null string
+as the value of
+.BR FS ,
+and as the third argument to
+.BR split() .
+.TP
+\(bu
+No path search is performed for files named via the
+.B \-f
+option. Therefore the
+.B AWKPATH
+environment variable is not special.
+.TP
+\(bu
+The use of
+.B "nextfile"
+to abandon processing of the current input file.
+.TP
+\(bu
+The use of
+.BI delete " array"
+to delete the entire contents of an array.
+.RE
+.PP
+The AWK book does not define the return value of the
+.B close()
+function.
+.IR Gawk\^ 's
+.B close()
+returns the value from
+.IR fclose (3),
+or
+.IR pclose (3),
+when closing a file or pipe, respectively.
+.PP
+When
+.I gawk
+is invoked with the
+.B \-\^\-traditional
+option,
+if the
+.I fs
+argument to the
+.B \-F
+option is \*(lqt\*(rq, then
+.B FS
+will be set to the tab character.
+Note that typing
+.B "gawk \-F\et \&.\|.\|."
+simply causes the shell to quote the \*(lqt,\*(rq, and does not pass
+\*(lq\et\*(rq to the
+.B \-F
+option.
+Since this is a rather ugly special case, it is not the default behavior.
+This behavior also does not occur if
+.B \-\^\-posix
+has been specified.
+To really get a tab character as the field separator, it is best to use
+quotes:
+.BR "gawk \-F'\et' \&.\|.\|." .
+.ig
+.PP
+If
+.I gawk
+was compiled for debugging, it will
+accept the following additional options:
+.TP
+.PD 0
+.B \-Wparsedebug
+.TP
+.PD
+.B \-\^\-parsedebug
+Turn on
+.IR yacc (1)
+or
+.IR bison (1)
+debugging output during program parsing.
+This option should only be of interest to the
+.I gawk
+maintainers, and may not even be compiled into
+.IR gawk .
+..
+.SH HISTORICAL FEATURES
+There are two features of historical \*(AK implementations that
+.I gawk
+supports.
+First, it is possible to call the
+.B length()
+built-in function not only with no argument, but even without parentheses!
+Thus,
+.RS
+.PP
+.ft B
+a = length # Holy Algol 60, Batman!
+.ft R
+.RE
+.PP
+is the same as either of
+.RS
+.PP
+.ft B
+a = length()
+.br
+a = length($0)
+.ft R
+.RE
+.PP
+This feature is marked as \*(lqdeprecated\*(rq in the \*(PX standard, and
+.I gawk
+will issue a warning about its use if
+.B \-\^\-lint
+is specified on the command line.
+.PP
+The other feature is the use of either the
+.B continue
+or the
+.B break
+statements outside the body of a
+.BR while ,
+.BR for ,
+or
+.B do
+loop. Traditional \*(AK implementations have treated such usage as
+equivalent to the
+.B next
+statement.
+.I Gawk
+will support this usage if
+.B \-\^\-traditional
+has been specified.
+.SH ENVIRONMENT VARIABLES
+If
+.B POSIXLY_CORRECT
+exists in the environment, then
+.I gawk
+behaves exactly as if
+.B \-\^\-posix
+had been specified on the command line.
+If
+.B \-\^\-lint
+has been specified,
+.I gawk
+will issue a warning message to this effect.
+.PP
+The
+.B AWKPATH
+environment variable can be used to provide a list of directories that
+.I gawk
+will search when looking for files named via the
+.B \-f
+and
+.B \-\^\-file
+options.
+.SH BUGS
+The
+.B \-F
+option is not necessary given the command line variable assignment feature;
+it remains only for backwards compatibility.
+.PP
+If your system actually has support for
+.B /dev/fd
+and the associated
+.BR /dev/stdin ,
+.BR /dev/stdout ,
+and
+.B /dev/stderr
+files, you may get different output from
+.I gawk
+than you would get on a system without those files. When
+.I gawk
+interprets these files internally, it synchronizes output to the standard
+output with output to
+.BR /dev/stdout ,
+while on a system with those files, the output is actually to different
+open files.
+Caveat Emptor.
+.PP
+Syntactically invalid single character programs tend to overflow
+the parse stack, generating a rather unhelpful message. Such programs
+are surprisingly difficult to diagnose in the completely general case,
+and the effort to do so really is not worth it.
+.SH VERSION INFORMATION
+This man page documents
+.IR gawk ,
+version 3.0.6.
+.SH AUTHORS
+The original version of \*(UX
+.I awk
+was designed and implemented by Alfred Aho,
+Peter Weinberger, and Brian Kernighan of AT&T Bell Labs. Brian Kernighan
+continues to maintain and enhance it.
+.PP
+Paul Rubin and Jay Fenlason,
+of the Free Software Foundation, wrote
+.IR gawk ,
+to be compatible with the original version of
+.I awk
+distributed in Seventh Edition \*(UX.
+John Woods contributed a number of bug fixes.
+David Trueman, with contributions
+from Arnold Robbins, made
+.I gawk
+compatible with the new version of \*(UX
+.IR awk .
+Arnold Robbins is the current maintainer.
+.PP
+The initial DOS port was done by Conrad Kwok and Scott Garfinkle.
+Scott Deifik is the current DOS maintainer. Pat Rankin did the
+port to VMS, and Michal Jaegermann did the port to the Atari ST.
+The port to OS/2 was done by Kai Uwe Rommel, with contributions and
+help from Darrel Hankerson. Fred Fish supplied support for the Amiga.
+.SH BUG REPORTS
+If you find a bug in
+.IR gawk ,
+please send electronic mail to
+.BR bug-gawk@gnu.org .
+Please include your operating system and its revision, the version of
+.IR gawk ,
+what C compiler you used to compile it, and a test program
+and data that are as small as possible for reproducing the problem.
+.PP
+Before sending a bug report, please do two things. First, verify that
+you have the latest version of
+.IR gawk .
+Many bugs (usually subtle ones) are fixed at each release, and if
+yours is out of date, the problem may already have been solved.
+Second, please read this man page and the reference manual carefully to
+be sure that what you think is a bug really is, instead of just a quirk
+in the language.
+.PP
+Whatever you do, do
+.B NOT
+post a bug report in
+.BR comp.lang.awk .
+While the
+.I gawk
+developers occasionally read this newsgroup, posting bug reports there
+is an unreliable way to report bugs. Instead, please use the electronic mail
+addresses given above.
+.SH ACKNOWLEDGEMENTS
+Brian Kernighan of Bell Labs
+provided valuable assistance during testing and debugging.
+We thank him.
+.SH COPYING PERMISSIONS
+Copyright \(co 1996\-2000 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual page provided the copyright notice and this permission
+notice are preserved on all copies.
+.ig
+Permission is granted to process this file through troff and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual page).
+..
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual page under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual page into another language, under the above conditions for
+modified versions, except that this permission notice may be stated in
+a translation approved by the Foundation.
diff --git a/contrib/awk/doc/igawk.1 b/contrib/awk/doc/igawk.1
new file mode 100644
index 000000000000..08173ec182ff
--- /dev/null
+++ b/contrib/awk/doc/igawk.1
@@ -0,0 +1,73 @@
+.TH IGAWK 1 "Nov 3 1999" "Free Software Foundation" "Utility Commands"
+.SH NAME
+igawk \- gawk with include files
+.SH SYNOPSIS
+.B igawk
+[ all
+.I gawk
+options ]
+.B \-f
+.I program-file
+[
+.B \-\^\-
+] file .\^.\^.
+.br
+.B igawk
+[ all
+.I gawk
+options ]
+[
+.B \-\^\-
+]
+.I program-text
+file .\^.\^.
+.SH DESCRIPTION
+.I Igawk
+is a simple shell script that adds the ability to have ``include files'' to
+.IR gawk (1).
+.PP
+AWK programs for
+.I igawk
+are the same as for
+.IR gawk ,
+except that, in addition, you may have lines like
+.RS
+.sp
+.ft B
+@include getopt.awk
+.ft R
+.sp
+.RE
+in your program to include the file
+.B getopt.awk
+from either the current directory or one of the other directories
+in the search path.
+.SH OPTIONS
+See
+.IR gawk (1)
+for a full description of the AWK language and the options that
+.I gawk
+supports.
+.SH EXAMPLES
+.nf
+.ft B
+cat << EOF > test.awk
+@include getopt.awk
+.sp
+BEGIN {
+ while (getopt(ARGC, ARGV, "am:q") != \-1)
+ \&.\^.\^.
+}
+EOF
+.sp
+igawk \-f test.awk
+.ft R
+.fi
+.SH SEE ALSO
+.IR gawk (1)
+.PP
+.IR "Effective AWK Programming" ,
+Edition 1.0, published by the Free Software Foundation, 1995.
+.SH AUTHOR
+Arnold Robbins
+.RB ( arnold@skeeve.com ).
diff --git a/contrib/awk/doc/macros b/contrib/awk/doc/macros
new file mode 100644
index 000000000000..bdfc5c8cbf69
--- /dev/null
+++ b/contrib/awk/doc/macros
@@ -0,0 +1,211 @@
+.\" SSC Reference card macros
+.\"
+.\" Copyright (C) 1996, Specialized System Consultants Inc. (SSC)
+.\"
+.\" These macros are free software; you can redistribute them and/or modify
+.\" them under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" These macros are 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, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+.\"
+.\" Generic SSC "card" macros
+.\" based on lots of other macros
+.\" Last update: 4-25-91 ph
+.\" attempting to get margins in the boxes Aug 3 09:43:48 PDT 1994
+.ll 3i \" length of text line
+.lt 3.2i \" length of title line
+.de BT \" bottom of page trap
+.sp |8.2i \" go to where we put footer
+.ie \\n(CL=1 \{\
+. nr CL 2
+.tl ''\\*(CD\\n+(PN'' \" footer is just page number
+. po 4i \" go to second column
+.TP \" print header if any
+\}
+.el \{\
+. nr CL 1
+.tl ''\\*(CD\\n+(PN'' \" footer is just page number
+. po .5i \" go to first column
+. bp \" force a new page (which will force header)
+. TP
+\}
+..
+.de TP \" top of page
+.\" .sp |.2i
+.sp |0
+.\" put page header stuff here
+.\" for example: .tl ''WOW!''
+.\".sp
+..
+.\" .wh 8.1i BT \" set bottom of column trap
+.nf \" don't fill lines
+.nh \" no hyphenation
+.nr CL 1 \" start with column = 1
+.po .5i \" offset for first column
+.vs 9 \" line spacing
+.ps 8 \" point size
+.de ST \" set tabs to normal places
+.ta .2i .78i 1.2i 1.7i \" set tabs
+..
+.ig
+ From: bryang@chinet.chi.il.us (Bryan Glennon)
+ Box macro. Do a .mk z where the box is to start, and a .eb
+ where it is to end. Optional argument is a title to be centered
+ within the top box line.
+
+ Usage:
+
+ .mk z
+ Text, etc to be boxed...
+ .eb "Optional title goes here"
+
+ ~or~
+
+ .mk z
+ Text, etc to be boxed...
+ .eb
+
+
+ Some explanation:
+ The macro name is eb <.de eb>. First thing we do is to go up on line
+ <.sp -1> and turn off fill mode <.nf>. Now it gets interesting: the
+ .ie is the if/else construct. We check the number of arguments provided
+ to the macro <\\n(.$> and if it is greater than 0 (meaning we have a title),
+ we do the rest of the .ie line, as follows:
+
+ \h'-.5n' - move left one-half of an n
+ \L'|\\nzu-1' - draw a vertical line <\L> to the
+ absolute position (|) given by \\nzu-1,
+ which is the position set with the .mk
+ command into register z <\\nz> in base
+ units <u> minus 1.
+ \l'(\\n(.lu+1n-\w'\\$1'u/2u)\(ul' - Draw a horizontal line <\l> with length
+ equal to the current line length
+ <\\n(.l> in base units <u> plus the
+ space required for an 'n' <1n>, minus
+ the width <\w> of the title string
+ <\\$1> in base units <u> divided by 2
+ <in base units <u>>. Draw the line
+ using the underline character, <\(ul>.
+ \v'.3m'\|\\$1\|\v'-.3m' - Move down the page 3/10 of an m,
+ <\v'.3m'>, output a 1/6 of an m space
+ <\|>, output the title <\\$1>, another
+ 1/6 of an m space <\|>, and then move
+ up the page 3/10 of an m <\v'-.3m'>.
+ \l'...\(ul' - Draw the second part of the line, just
+ like the corresponding left half done
+ before.
+ \L'-|\\nzu+1' - Draw a verticle line <\L> going down
+ the absolute distance <-|> from where
+ the macro was given to where the start
+ point was marked <\\nz> in base units
+ <u> plus one line <+1>
+ \l'|0u-.5n\(ul' - Draw a horizontal line to the absolute
+ position (|0) when the macro was
+ invoked, minus half an n <-.5n> using
+ the underline character <\(ul>.
+
+ The .el beings the else part, which is identical to the above, except
+ the string dosen't get printed. This makes the printing of the top
+ line much easier: just draw a line <\l> with width equal to the
+ current line plus the witdh of an n <\\n(.l+1n> using the underline
+ character <.\(ul>.
+..
+.de ES \" start "text in a box"
+.mk z
+.in +.5n
+.ll -.5n
+.sp 1.3
+..
+.de EB \" end "text in a box" -- optional box title as argument
+.sp -.6
+.nf
+.in -.5n
+.ll +.5n
+.ie \\n(.$\
+\L'|\\nzu'\
+\l'(\\n(.lu-\w'\\$1'u)/2u-.33m\(ul'\
+\v'.3m'\|\\$1\|\v'-.3m'\
+\l'(\\n(.lu-\w'\\$1'u)/2u\(ul'\
+\L'-|\\nzu'\
+\l'|0u\(ul'
+.el \h'-.5n'\L'|\\nzu-1'\l'\\n(.lu+1n\(ul'\L'-|\\nzu+1'\l'|0u-.5n\(ul'
+.in 0
+..
+.de SL \" draw single line (works in non-fill mode only)
+.sp -.8
+.ti 0
+\l'\\n(.lu\(ul'
+..
+.de Hl \" draw horizontal line
+.br
+.ti 0
+\l'\\n(.lu-\\n(.iu'
+.br
+..
+.de DL \" draw double line (works in non-fill mode only)
+.sp -.8
+.ti 0
+\l'\\n(.lu\(ul'
+.sp -.8
+.ti 0
+\l'\\n(.lu\(ul'
+..
+.ST
+.nr PN 0 1 \" sets starting page number and auto-increment
+.\" must define page header (if any) before here
+.TP
+.ds 3) \|\v'3p'\s+5\z\(sq\s0\v'-3p'\h'1.25p'\v'-.5p'3\v'.5p'\h'2p'
+.\" old one .ds 2) \h'-1.5p'\v'1p'\s+4\z\(ci\s0\v'-1p'\h'3.25p'2
+.ds 2) \|\v'-2.4p'\D'c.095id'\h'-5.15p'\v'2.4p'2\h'1.9p'
+.ds dC \v'1p'\s+5\(bu\s0\v'-1p'\" for development commands
+.ds tC \s+2\(dm\s0\" (for DWB) should be a triangle
+.ds tP \s+2\(dm\s0\" (for other text processing) should be a triangle
+.\" various trademark symbols
+.ds Tm \v'-0.5m'\s8TM\s0\v'0.5m'
+.ds Ts \v'-0.5m'\s4TM\s0\v'0.5m'
+.ig ++
+.\" mount Serifa fonts
+.fp 5 SR
+.fp 6 SB
+.fp 4 Si
+.++
+.\" other assorted junk
+.lg 0
+.\" Fl requires extended version of troff
+.de Fl \" draw fat horizontal line
+.br
+.ti 0
+.ruw 1.5p
+\l'\\n(.lu-\\n(.iu'
+.br
+.ruw
+..
+.de Bx \" box for keys in text
+\\$3\&\|\&\c
+\s-3\(br\|\fH\v'.18n'\\$1\v'-.18n\fP\|\(br\l'|0\(rn'\l'|0\(ul'\&\s0\|\\$2
+..
+.de Fn \" function name - left justified, gray background
+.\" bold with gray for function name
+.ns
+.br
+\
+.ns
+.br
+\!! gsave ( ) stringwidth neg 0 rmoveto
+\!! /Serifa-Bold findfont 8 scalefont setfont
+\!! (\\$1) dup stringwidth pop 6 gsave dup 0 exch rlineto neg exch 0 rlineto
+\!! 0 exch rlineto closepath .9 setgray fill grestore show
+\!! grestore
+.nf
+.rs
+..
+.rs
diff --git a/contrib/awk/doc/no.colors b/contrib/awk/doc/no.colors
new file mode 100644
index 000000000000..974f985b349d
--- /dev/null
+++ b/contrib/awk/doc/no.colors
@@ -0,0 +1,31 @@
+.\" AWK Reference Card --- Arnold Robbins, arnold@gnu.org
+.\" This file is for troff which does not know what to do
+.\" with a literal Poscript and cannot use macros from 'colors'.
+.\"
+.\" Copyright (C) 1996 Free Software Foundation, Inc.
+.\"
+.\" Permission is granted to make and distribute verbatim copies of
+.\" this reference card provided the copyright notice and this permission
+.\" notice are preserved on all copies.
+.\"
+.\" Permission is granted to process this file through troff and print the
+.\" results, provided the printed document carries copying permission
+.\" notice identical to this one except for the removal of this paragraph
+.\" (this paragraph not being relevant to the printed reference card).
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" reference card under the conditions for verbatim copying, provided that
+.\" the entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Permission is granted to copy and distribute translations of this
+.\" reference card into another language, under the above conditions for
+.\" modified versions, except that this permission notice may be stated in
+.\" a translation approved by the Foundation.
+.\"
+.ds CR
+.ds CG
+.ds CL
+.ds CB
+.ds CD
+.ds CX
diff --git a/contrib/awk/doc/setter.outline b/contrib/awk/doc/setter.outline
new file mode 100644
index 000000000000..67ade73a178a
--- /dev/null
+++ b/contrib/awk/doc/setter.outline
@@ -0,0 +1,77 @@
+%!PS-Adobe-3.0
+% SSC Reference card typesetter outline / cut marks
+%
+% Copyright (C) 1996, Specialized System Consultants Inc. (SSC)
+%
+% This 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 2 of the License, or
+% (at your option) any later version.
+%
+% This 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, write to the Free Software
+% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+%
+%! page cut marks and stuff for Pocket References - 10-26-88 - ph
+%! modified to move the cut marks onto the page
+%! center a string
+/inch {72 mul} def
+/cshow % stk: string
+ % center string in space (space us variable)
+ {
+ dup stringwidth pop % get length of string
+ space exch sub 2 div % compute initial space needed
+ 0 rmoveto % move over
+ show
+ } def
+
+/flashme
+{ /space 612 def
+ 0 0 0 setrgbcolor % always print this stuff
+
+ /Helvetica findfont 12 scalefont setfont
+ gsave
+% for groff (I hope)
+ -6 -6 translate
+ 0.2 setlinewidth
+
+ 0.25 inch 10.5 inch moveto
+ 0.5 inch 10.5 inch lineto
+ .75 inch 10.75 inch moveto
+ .75 inch 11 inch lineto
+ stroke
+
+ 0.25 inch 2 inch moveto
+ 0.5 inch 2 inch lineto
+ .75 inch 1.75 inch moveto
+ .75 inch 1.50 inch lineto
+ stroke
+ 4.25 inch 11 inch moveto
+ 4.25 inch 10.75 inch lineto
+ stroke
+
+ 4.25 inch 1.75 inch moveto
+ 4.25 inch 1.5 inch lineto
+ stroke
+
+ 7.75 inch 1.5 inch moveto
+ 7.75 inch 1.75 inch lineto
+ 8 inch 2 inch moveto
+ 8.25 inch 2 inch lineto
+ stroke
+
+ 7.75 inch 11 inch moveto
+ 7.75 inch 10.75 inch lineto
+ 8 inch 10.5 inch moveto
+ 8.25 inch 10.5 inch lineto
+ stroke
+ grestore
+ } def
+
+% actually do something
+
diff --git a/contrib/awk/doc/texinfo.tex b/contrib/awk/doc/texinfo.tex
new file mode 100644
index 000000000000..ebf58d8e8345
--- /dev/null
+++ b/contrib/awk/doc/texinfo.tex
@@ -0,0 +1,5992 @@
+% 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{1999-10-01.07}
+%
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+% 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 2, 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 texinfo.tex file; see the file COPYING. If not, write
+% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+% Boston, MA 02111-1307, USA.
+%
+% In other words, you are welcome to use, share and improve this program.
+% You are forbidden to forbid anyone else to use, share and improve
+% what you give them. Help stamp out software-hoarding!
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+% ftp://ftp.gnu.org/gnu/texinfo.tex
+% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+% ftp://texinfo.org/tex/texinfo.tex
+% ftp://us.ctan.org/macros/texinfo/texinfo.tex
+% (and all CTAN mirrors, finger ctan@us.ctan.org for a list).
+% /home/gd/gnu/doc/texinfo.tex on the GNU machines.
+% The texinfo.tex in any given Texinfo distribution could well be out
+% of date, so if that's what you're using, please check.
+% Texinfo has a small home page at http://texinfo.org/.
+%
+% 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, to process the dvi file; this makes foo.ps.
+% The extra runs of TeX 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. You can get
+% the existing language-specific files from ftp://ftp.gnu.org/gnu/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}
+
+% Save some parts of plain tex 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\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
+\let\ptext=\t
+
+% We never want plain's outer \+ definition in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% 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\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\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi
+\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi
+\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+\hyphenation{white-space}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset
+\newdimen \normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% 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.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\ifx\eTeXversion\undefined
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\else
+\def\loggingall{\tracingcommands3 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \tracingscantokens1 \tracingassigns1 \tracingifs1
+ \tracinggroups1 \tracingnesting2
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\fi
+
+% For @cropmarks command.
+% 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
+
+% 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).
+ \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \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.
+ %
+ \escapechar = `\\ % use backslash in output files.
+ \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.
+ \shipout\vbox{%
+ \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 \oddfootingxxx.)
+ % The \baselineskip=24pt in plain's \makefootline has no effect.
+ \vskip 2\baselineskip
+ \unvbox\footlinebox
+ \fi
+ %
+ \ifpdfmakepagedest \pdfmkdest{\the\pageno} \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 \turnoffactive
+ \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 \unvbox#1
+\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#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment; press RETURN to continue}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Press RETURN to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef@lbracecmd[\{]%
+ @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
+
+% 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\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=3000 }
+
+% @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.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below 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. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % 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
+}
+%
+% 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
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % 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
+
+\let\br = \par
+
+% @dots{} output an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+ \leavevmode
+ \hbox to 1.5em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+ \leavevmode
+ \hbox to 2em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+ \spacefactor=3000
+}
+
+
+% @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.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\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.
+% We cannot implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\def\paragraphindent{\parsearg\doparagraphindent}
+\def\doparagraphindent#1{%
+ \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.
+\def\exampleindent{\parsearg\doexampleindent}
+\def\doexampleindent#1{%
+ \def\temp{#1}%
+ \ifx\temp\asisword
+ \else
+ \ifx\temp\noneword
+ \lispnarrowing = 0pt
+ \else
+ \lispnarrowing = #1em
+ \fi
+ \fi
+}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+% @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{%
+ \iflinks
+ \readauxfile
+ \fi % \openindices needs to do some work in any case.
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ %
+ % If texinfo.cnf is present on the system, read it.
+ % Useful for site-wide @afourpaper, etc.
+ % Just to be on the safe side, close the input stream before the \input.
+ \openin 1 texinfo.cnf
+ \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+ \closein1
+ \temp
+ %
+ \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
+
+\ifx\pdfoutput\undefined
+ \pdffalse
+ \let\pdfmkdest = \gobble
+ \let\pdfurl = \gobble
+ \let\endlink = \relax
+ \let\linkcolor = \relax
+ \let\pdfmakeoutlines = \relax
+\else
+ \pdftrue
+ \pdfoutput = 1
+ \input pdfcolor
+ \def\dopdfimage#1#2#3{%
+ \def\imagewidth{#2}%
+ \def\imageheight{#3}%
+ \ifnum\pdftexversion < 14
+ \pdfimage
+ \else
+ \pdfximage
+ \fi
+ \ifx\empty\imagewidth\else width \imagewidth \fi
+ \ifx\empty\imageheight\else height \imageheight \fi
+ {#1.pdf}%
+ \ifnum\pdftexversion < 14 \else
+ \pdfrefximage \pdflastximage
+ \fi}
+ \def\pdfmkdest#1{\pdfdest name{#1@} xyz}
+ \def\pdfmkpgn#1{#1@}
+ \let\linkcolor = \Cyan
+ \def\endlink{\Black\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 by1
+ \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+ \def\pdfmakeoutlines{{%
+ \openin 1 \jobname.toc
+ \ifeof 1\else\bgroup
+ \closein 1
+ \indexnofonts
+ \def\tt{}
+ % thanh's hack / proper braces in bookmarks
+ \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+ \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+ %
+ \def\chapentry ##1##2##3{}
+ \def\unnumbchapentry ##1##2{}
+ \def\secentry ##1##2##3##4{\advancenumber{chap##2}}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \def\chapentry ##1##2##3{%
+ \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}}
+ \def\unnumbchapentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\secentry ##1##2##3##4{%
+ \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}}
+ \def\unnumbsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\subsecentry ##1##2##3##4##5{%
+ \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}}
+ \def\unnumbsubsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\subsubsecentry ##1##2##3##4##5##6{%
+ \pdfoutline goto name{\pdfmkpgn{##6}}{##1}}
+ \def\unnumbsubsubsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \input \jobname.toc
+ \egroup\fi
+ }}
+ \def\makelinks #1,{%
+ \def\params{#1}\def\E{END}%
+ \ifx\params\E
+ \let\nextmakelinks=\relax
+ \else
+ \let\nextmakelinks=\makelinks
+ \ifnum\lnkcount>0,\fi
+ \picknum{#1}%
+ \startlink attr{/Border [0 0 0]}
+ goto name{\pdfmkpgn{\the\pgn}}%
+ \linkcolor #1%
+ \advance\lnkcount by 1%
+ \endlink
+ \fi
+ \nextmakelinks
+ }
+ \def\picknum#1{\expandafter\pn#1}
+ \def\pn#1{%
+ \def\p{#1}%
+ \ifx\p\lbrace
+ \let\nextpn=\ppn
+ \else
+ \let\nextpn=\ppnn
+ \def\first{#1}
+ \fi
+ \nextpn
+ }
+ \def\ppn#1{\pgn=#1\gobble}
+ \def\ppnn{\pgn=\first}
+ \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,}
+ \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+ \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+ \ifx\PP\D\let\nextsp\relax
+ \else\let\nextsp\skipspaces
+ \ifx\p\space\else\addtokens{\filename}{\PP}%
+ \advance\filenamelength by 1
+ \fi
+ \fi
+ \nextsp}
+ \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+ \ifnum\pdftexversion < 14
+ \let \startlink \pdfannotlink
+ \else
+ \let \startlink \pdfstartlink
+ \fi
+ \def\pdfurl#1{%
+ \begingroup
+ \normalturnoffactive\def\@{@}%
+ \leavevmode\Red
+ \startlink attr{/Border [0 0 0]}%
+ user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+ % #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|
+ \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{\mkpgn{#1}}
+ \linkcolor #1\endlink}
+ \def\mkpgn#1{#1@}
+ \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\fi % \ifx\pdfoutput
+
+
+\message{fonts,}
+% Font-change commands.
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+% Use Computer Modern fonts at \magstephalf (11pt).
+\newcount\mainmagstep
+\mainmagstep=\magstephalf
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\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}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\setfont\smallrm\rmshape{9}{1000}
+\setfont\smalltt\ttshape{9}{1000}
+\setfont\smallbf\bfshape{10}{900}
+\setfont\smallit\itshape{9}{1000}
+\setfont\smallsl\slshape{9}{1000}
+\setfont\smallsf\sfshape{9}{1000}
+\setfont\smallsc\scshape{10}{900}
+\setfont\smallttsl\ttslshape{10}{900}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% 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, 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 so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\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
+ \resetmathfonts}
+\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
+ \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #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
+ \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
+ \resetmathfonts \setleading{16pt}}
+\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
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\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
+ \resetmathfonts \setleading{11pt}}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+\let\cite=\smartslanted
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% 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 = `- }
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont=\t
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}
+\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}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\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
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% 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
+ %
+ \global\def\code{\begingroup
+ \catcode`\-=\active \let-\codedash
+ \catcode`\_=\active \let_\codeunder
+ \codex
+ }
+ %
+ % If we end up with any active - characters when handling the index,
+ % just treat them as a normal -.
+ \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @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).
+\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+\def\kbdinputstylexxx#1{%
+ \def\arg{#1}%
+ \ifx\arg\worddistinct
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+ \else\ifx\arg\wordexample
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+ \else\ifx\arg\wordcode
+ \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+ \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is kbdinputdistinct. (Too much of a hassle to call the macro,
+% the catcodes are wrong for parsearg to work.)
+\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @url, @env, @command quotes seem unnecessary, so use \code.
+\let\url=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') 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. Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+ \unsepspaces
+ \pdfurl{#1}%
+ \setbox0 = \hbox{\ignorespaces #3}%
+ \ifdim\wd0 > 0pt
+ \unhbox0 % third arg given, show only that
+ \else
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \ifpdf
+ \unhbox0 % PDF: 2nd arg given, show only it
+ \else
+ \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+ \fi
+ \else
+ \code{#1}% only url given, so show it
+ \fi
+ \fi
+ \endlink
+\endgroup}
+
+% 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
+
+% 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 }
+
+% 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}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @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}
+
+% 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
+
+% @acronym downcases the argument and prints in smallcaps.
+\def\acronym#1{{\smallcaps \lowercase{#1}}}
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+
+\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
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % 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
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\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
+ %
+ % 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
+ %
+ \ifpdf \pdfmakepagedesttrue \fi
+ %
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% 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\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\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 -\baselineskip
+ \global\advance\vsize by -\baselineskip
+}
+
+\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+%
+}% unbind the catcode of @.
+
+% @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{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% 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
+% Produces Day Month Year style of output.
+\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}
+
+% @settitle line... specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(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, @vtable, 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\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#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
+ \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. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \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 table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+% Contains a kludge to get @end[description] to work.
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+% @table, @ftable, @vtable.
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \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'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % 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 itemizey, 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
+ \itemizey{#1.}\Eenumerate\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}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{In hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @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.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
+
+% 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, @multitable or @end multitable 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 part of the @columnfraction before the decimal point, which
+% is presumably either 0 or the empty string (but we don't check, we
+% just throw it away). #2 is the decimal part, which we use as the
+% percent of \hsize for this column.
+\def\pickupwholefraction#1.#2 {%
+ \global\advance\colcount by 1
+ \expandafter\xdef\csname col\the\colcount\endcsname{.#2\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 }% 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
+}
+
+% This used to have \hskip1sp. But then the space in a template line is
+% not enough. That is bad. So let's go back to just & until we
+% encounter the problem it was intended to solve again.
+% --karl, nathan@acm.org, 20apr99.
+\def\tab{&}
+
+% @multitable ... @end multitable definitions:
+%
+\def\multitable{\parsearg\dotable}
+\def\dotable#1{\bgroup
+ \vskip\parskip
+ \let\item\crcr
+ \tolerance=9500
+ \hbadness=9500
+ \setmultitablespacing
+ \parskip=\multitableparskip
+ \parindent=\multitableparindent
+ \overfullrule=0pt
+ \global\colcount=0
+ \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}%
+ %
+ % To parse everything between @multitable and @item:
+ \setuptable#1 \endsetuptable
+ %
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+ \everycr{\noalign{%
+ %
+ % \filbreak%% keeps underfull box messages off when table breaks over pages.
+ % Maybe so, but it also creates really weird page breaks when the table
+ % breaks over pages. Wouldn't \vfil be better? Wait until the problem
+ % manifests itself, so it can be fixed for real --karl.
+ \global\colcount=0\relax}}%
+ %
+ % 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\relax
+ \multistrut\vtop{\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\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+\else
+%% FIXME: what is \box0 supposed to be?
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \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,}
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+ \let\chapter=\relax
+ \let\unnumbered=\relax
+ \let\top=\relax
+ \let\unnumberedsec=\relax
+ \let\unnumberedsection=\relax
+ \let\unnumberedsubsec=\relax
+ \let\unnumberedsubsection=\relax
+ \let\unnumberedsubsubsec=\relax
+ \let\unnumberedsubsubsection=\relax
+ \let\section=\relax
+ \let\subsec=\relax
+ \let\subsubsec=\relax
+ \let\subsection=\relax
+ \let\subsubsection=\relax
+ \let\appendix=\relax
+ \let\appendixsec=\relax
+ \let\appendixsection=\relax
+ \let\appendixsubsec=\relax
+ \let\appendixsubsection=\relax
+ \let\appendixsubsubsec=\relax
+ \let\appendixsubsubsection=\relax
+ \let\contents=\relax
+ \let\smallbook=\relax
+ \let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcodeindex = \relax
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypeivar = \relax
+ \let\deftypeop = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ % This @ is a catcode 12 token (that is the normal catcode of @ in
+ % this texinfo.tex file). We change the catcode of @ below to match.
+ \long\def\doignoretext##1@end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % Ignore braces, too, so mismatched braces don't cause trouble.
+ \catcode`\{ = 9
+ \catcode`\} = 9
+ %
+ % We must not have @c interpreted as a control sequence.
+ \catcode`\@ = 12
+ %
+ % Make the letter c a comment character so that the rest of the line
+ % will be ignored. This way, the document can have (for example)
+ % @c @end ifinfo
+ % and the @end ifinfo will be properly ignored.
+ % (We've just changed @ to catcode 12.)
+ \catcode`\c = 14
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{WARNING: for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont
+ \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont
+ \let\tensf=\nullfont
+ % Similarly for index fonts (mostly for their use in smallexample).
+ \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont
+ \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont
+ \let\smallsf=\nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}%
+ % Do not execute macro definitions.
+ % `c' is a comment character, so the word `macro' will get cut off.
+ \def\macro{\doignore{ma}}%
+}
+
+% @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. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10
+ \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+ \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+{
+ \catcode`\_ = \active
+ %
+ % We might end up with active _ or - characters in the argument if
+ % we're called from @code, as @code{@value{foo-bar_}}. So \let any
+ % such active characters to their normal equivalents.
+ \gdef\value{\begingroup
+ \catcode`\-=12 \catcode`\_=12
+ \indexbreaks \let_\normalunderscore
+ \valuexxx}
+}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we \let\value to this in \indexdummies). Ones
+% whose names contain - or _ still won't work, but we can't do anything
+% about that. The command has to be fully expandable, 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).
+%
+\def\expandablevalue#1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ {[No value for ``#1'']}%
+ \else
+ \csname SET#1\endcsname
+ \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
+% following, through the first @end iftex (etc.). Make `@end iftex'
+% (etc.) valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\def\ifnothtml{\conditionalsucceed{ifnothtml}}
+\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
+\defineunmatchedend{iftex}
+\defineunmatchedend{ifnothtml}
+\defineunmatchedend{ifnotinfo}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @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 \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \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\newcodeindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{%
+ \noexpand\docodeindex{#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @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.
+% The \closeout helps reduce unnecessary open files; the limit on the
+% Acorn RISC OS is a mere 16 files.
+\def\synindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\doindex{#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\docodeindex{#2}}%
+}
+
+% 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}}}
+
+\def\indexdummies{%
+\def\ { }%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+% Need these in case \tex is in effect and \{ is a \delimiter again.
+% But can't use \lbracecmd and \rbracecmd because texindex assumes
+% braces and backslashes are used only as delimiters.
+\let\{ = \mylbrace
+\let\} = \myrbrace
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+%\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\result{\realbackslash result}%
+\def\equiv{\realbackslash equiv}%
+\def\expansion{\realbackslash expansion}%
+\def\print{\realbackslash print}%
+\def\error{\realbackslash error}%
+\def\point{\realbackslash point}%
+\def\copyright{\realbackslash copyright}%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\uref##1{\realbackslash uref {##1}}%
+\def\url##1{\realbackslash url {##1}}%
+\def\env##1{\realbackslash env {##1}}%
+\def\command##1{\realbackslash command {##1}}%
+\def\option##1{\realbackslash option {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\sc##1{\realbackslash sc {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\def\acronym##1{\realbackslash acronym {##1}}%
+%
+% Handle some cases of @value -- where the variable name does not
+% contain - or _, and the value does not contain any
+% (non-fully-expandable) commands.
+\let\value = \expandablevalue
+%
+\unsepspaces
+% Turn off macro expansion
+\turnoffmacros
+}
+
+% 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 \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\,=\indexdummyfont
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\url=\indexdummyfont
+\let\uref=\indexdummyfont
+\let\env=\indexdummyfont
+\let\acronym=\indexdummyfont
+\let\command=\indexdummyfont
+\let\option=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+\def\@{@}%
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+ @gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% For \ifx comparisons.
+\def\emptymacro{\empty}
+
+% Most index entries go through here, but \dosubind is the general case.
+%
+\def\doind#1#2{\dosubind{#1}{#2}\empty}
+
+% 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 defuns, which call us directly.
+%
+\def\dosubind#1#2#3{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio = 0% We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ \def\thirdarg{#3}%
+ %
+ % If third arg is present, precede it with space in sort key.
+ \ifx\thirdarg\emptymacro
+ \let\subentry = \empty
+ \else
+ \def\subentry{ #3}%
+ \fi
+ %
+ % First process the index entry with all font commands turned
+ % off to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2\subentry}}%
+ %
+ % Now the real index entry with the fonts.
+ \toks0 = {#2}%
+ %
+ % If third (subentry) arg is present, add it to the index
+ % string. And include a space.
+ \ifx\thirdarg\emptymacro \else
+ \toks0 = \expandafter{\the\toks0 \space #3}%
+ \fi
+ %
+ % 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, texindex reduces to
+ % two when writing the .??s sorted result.
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ %
+ % 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 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.
+ %
+ \iflinks
+ \ifvmode
+ \skip0 = \lastskip
+ \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi
+ \fi
+ %
+ \temp % do the write
+ %
+ %
+ \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi
+ \fi
+ }%
+ }%
+ \penalty\count255
+ }%
+}
+
+% 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).
+%
+\def\printindex{\parsearg\doprintindex}
+\def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \smallfonts \rm
+ \tolerance = 9500
+ \indexbreaks
+ %
+ % 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{\rawbackslashxx}%
+ \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.
+ \penalty -300
+ %
+ % 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}%
+ \vskip .33\baselineskip plus .1\baselineskip
+ %
+ % Do our best not to break after the initial.
+ \nobreak
+}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry#1#2{\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
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % 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.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \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#2.\ \the\toksA % The page number ends the paragraph.
+ \else
+ \ #2% The page number ends the paragraph.
+ \fi
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \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 #2\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.)
+ \advance\vsize by -\ht\partialpage
+ \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
+ %
+ % box0 will be the left-hand column, box2 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255
+ \penalty\outputpenalty
+}
+\def\pagesofar{%
+ % Re-output the contents of the output page -- any previous material,
+ % followed by the two boxes we just split, in box0 and box2.
+ \unvbox\partialpage
+ %
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize
+ \hbox to\pagewidth{\box0\hfil\box2}%
+}
+\def\enddoublecolumns{%
+ \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
+}
+\def\balancecolumns{%
+ % Called at the end of the double column material.
+ \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.
+
+\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 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 this as the name of the chapter.
+% page headings and footings can use it. @section does likewise.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/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
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% @chapter, @appendix, @unnumbered.
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\the\chapno}}}%
+\temp
+\donoderef
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1
+\message{\putwordAppendix\space \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\putwordAppendix{} \appendixletter}}}%
+\temp
+\appendixnoderef
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+% @top is like @unnumbered.
+\outer\def\top{\parsearg\unnumberedyyy}
+
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% 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)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% Sections.
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\the\chapno}{\the\secno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\appendixletter}{\the\secno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsections.
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
+ {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsubsections.
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
+ {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% 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.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
+
+% 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}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\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
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+}
+
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+}}
+
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\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 {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+% Subsection titles.
+\newskip \subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc. We supply {\folio} at the end of the
+% argument, which will end up as the last argument to the \...entry macro.
+%
+% We open the .toc file here instead of at @setfilename or any other
+% given time so that @contents can be put in the document anywhere.
+%
+\newif\iftocfileopened
+\def\writetocentry#1{%
+ \iftocfileopened\else
+ \immediate\openout\tocfile = \jobname.toc
+ \global\tocfileopenedtrue
+ \fi
+ \iflinks \write\tocfile{#1{\folio}}\fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Finish up the main text and 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.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \savepageno = \pageno
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ % We can't do this, because then an actual ^ in a section
+ % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97.
+ %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \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 \pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+ \startcontents{\putwordTOC}%
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \pdfmakeoutlines
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+ \startcontents{\putwordShortTOC}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+\ifpdf
+ \pdfcatalog{/PageMode /UseOutlines}%
+\fi
+
+% 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, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+%
+\newdimen\shortappendixwidth
+%
+\def\shortchaplabel#1{%
+ % Compute width of word "Appendix", may change with language.
+ \setbox0 = \hbox{\shortcontrm \putwordAppendix}%
+ \shortappendixwidth = \wd0
+ %
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno\bgroup#2\egroup}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% 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}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+\def\tocentry#1#2{\begingroup
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+ % Do not use \turnoffactive in these arguments. Since the toc is
+ % typeset in cmr, so characters such as _ would come out wrong; we
+ % have to do the usual translation tricks.
+ \entry{#1}{#2}%
+\endgroup}
+
+% 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}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\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 \tensf error\kern-1.5pt}
+
+\global\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}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @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 tex @ character.
+
+\def\tex{\begingroup
+ \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+ \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+ \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+ \catcode `\%=14
+ \catcode 43=12 % plus
+ \catcode`\"=12
+ \catcode`\==12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \escapechar=`\\
+ %
+ \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\{=\ptexlbrace
+ \let\+=\tabalign
+ \let\}=\ptexrbrace
+ \let\*=\ptexstar
+ \let\t=\ptext
+ %
+ \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+ \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+ \def\@{@}%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (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}
+
+% 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.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% 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{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\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
+
+\long\def\cartouche{%
+\begingroup
+ \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
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% Define the \E... control sequence only if we are inside the particular
+% environment, so the error checking in \end will work.
+%
+% To end an @example-like environment, we first end the paragraph (via
+% \afterenvbreak's vertical glue), and then the group. That way we keep
+% the zero \parskip that the environments set -- \parskip glue will be
+% inserted at the beginning of the next paragraph in the document, after
+% the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}
+
+% @lisp: indented, narrowed, typewriter font.
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+ \gobble % eat return
+}
+
+% @example: Same as @lisp.
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+
+% @small... is usually equivalent to the non-small (@smallbook
+% redefines). We must call \example (or whatever) last in the
+% definition, since it reads the return following the @example (or
+% whatever) command.
+%
+% This actually allows (for example) @end display inside an
+% @smalldisplay. Too bad, but makeinfo will catch the error anyway.
+%
+\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display}
+\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format}
+\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts.
+% Originally contributed by Pavel@xerox.
+\def\smalllispx{\begingroup
+ \def\Esmalllisp{\nonfillfinish\endgroup}%
+ \def\Esmallexample{\nonfillfinish\endgroup}%
+ \smallfonts
+ \lisp
+}
+
+% @display: same as @lisp except keep current font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% @smalldisplay (when @smallbook): @display plus smaller fonts.
+%
+\def\smalldisplayx{\begingroup
+ \def\Esmalldisplay{\nonfillfinish\endgroup}%
+ \smallfonts \rm
+ \display
+}
+
+% @format: same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @smallformat (when @smallbook): @format plus smaller fonts.
+%
+\def\smallformatx{\begingroup
+ \def\Esmallformat{\nonfillfinish\endgroup}%
+ \smallfonts \rm
+ \format
+}
+
+% @flushleft (same as @format).
+%
+\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+
+% @flushright.
+%
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble
+}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+}
+
+
+\message{defuns,}
+% @defun etc.
+
+% Allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\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 = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% 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.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+ \global\advance\parencount by 1
+}
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+ % also in that case restore the outer-level definition of (.
+ \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+ \global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+\let\ampnr = \&
+\def\lbrb{{\bf\char`\[}}
+\def\rbrb{{\bf\char`\]}}
+
+% Active &'s sneak into the index arguments, so make sure it's defined.
+{
+ \catcode`& = 13
+ \global\let& = \ampnr
+}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\noindent
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2
+\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by the space, is the class name.
+%
+\def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+% Used for @deftypemethod and @deftypeivar.
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by a space, is the class name.
+% #5 is the method's return type.
+%
+\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV
+ \medbreak
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
+
+% Used for @deftypeop. The change from \deftypemethparsebody is an
+% extra argument at the beginning which is the `category', instead of it
+% being the hardwired string `Method' or `Instance Variable'. We have
+% to account for this both in the \...x definition and in parsing the
+% input at hand. Thus also need a control sequence (passed as #5) for
+% the \E... definition to assign the category name to.
+%
+\def\deftypeopparsebody#1#2#3#4#5 #6 {\begingroup\inENV
+ \medbreak
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 ##2 ##3 {%
+ \def#4{##1}%
+ \begingroup\obeylines\activeparens\spacesplit{#3{##2}{##3}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\activeparens\spacesplit{#3{#5}{#6}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does.
+%
+\def\removeemptybraces\empty#1\relax{#1}
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ #1{\removeemptybraces#2\relax}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs#1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Set the font temporarily and use \font in case \setfont made \tensl a macro.
+{\tensl\hyphenchar\font=0}%
+#1%
+{\tensl\hyphenchar\font=45}%
+\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDeffunc}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypefun}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefmac}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefspec}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defop CATEGORY CLASS OPERATION ARG...
+%
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+%
+\def\defopheader#1#2#3{%
+\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype\ \putwordon\ #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @deftypeop CATEGORY CLASS TYPE OPERATION ARG...
+%
+\def\deftypeop #1 {\def\deftypeopcategory{#1}%
+ \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader
+ \deftypeopcategory}
+%
+% #1 is the class name, #2 the data type, #3 the operation name, #4 the args.
+\def\deftypeopheader#1#2#3#4{%
+ \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{\defheaderxcond#2\relax$$$#3}
+ {\deftypeopcategory\ \putwordon\ \code{#1}}%
+ \deftypefunargs{#4}%
+ \endgroup
+}
+
+% @deftypemethod CLASS TYPE METHOD ARG...
+%
+\def\deftypemethod{%
+ \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+%
+% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+\def\deftypemethodheader#1#2#3#4{%
+ \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}%
+ \deftypefunargs{#4}%
+ \endgroup
+}
+
+% @deftypeivar CLASS TYPE VARNAME
+%
+\def\deftypeivar{%
+ \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader}
+%
+% #1 is the class name, #2 the data type, #3 the variable name.
+\def\deftypeivarheader#1#2#3{%
+ \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index
+ \begingroup
+ \defname{#3}{\putwordInstanceVariableof\ \code{#1}}%
+ \defvarargs{#3}%
+ \endgroup
+}
+
+% @defmethod == @defop Method
+%
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+%
+% #1 is the class name, #2 the method name, #3 the args.
+\def\defmethodheader#1#2#3{%
+ \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{#2}{\putwordMethodon\ \code{#1}}%
+ \defunargs{#3}%
+ \endgroup
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype\ \putwordof\ #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME
+%
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+%
+\def\defivarheader#1#2#3{%
+ \dosubind {vr}{\code{#2}}{\putwordof\ #1}% entry in var index
+ \begingroup
+ \defname{#2}{\putwordInstanceVariableof\ #1}%
+ \defvarargs{#3}%
+ \endgroup
+}
+
+% @defvar
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefvar}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefopt}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name, perhaps followed by text that
+% is actually part of the data type, which should not be put into the index.
+\def\deftypevarheader #1#2{%
+\dovarind#2 \relax% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypevar}%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% These definitions are used if you use @defunx (etc.)
+% anywhere other than immediately after a @defun or @defunx.
+%
+\def\defcvx#1 {\errmessage{@defcvx in invalid context}}
+\def\deffnx#1 {\errmessage{@deffnx in invalid context}}
+\def\defivarx#1 {\errmessage{@defivarx in invalid context}}
+\def\defmacx#1 {\errmessage{@defmacx in invalid context}}
+\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\defopx#1 {\errmessage{@defopx in invalid context}}
+\def\defspecx#1 {\errmessage{@defspecx in invalid context}}
+\def\deftpx#1 {\errmessage{@deftpx in invalid context}}
+\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}}
+\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}}
+\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}}
+\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}}
+\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}}
+\def\defunx#1 {\errmessage{@defunx in invalid context}}
+\def\defvarx#1 {\errmessage{@defvarx in invalid context}}
+\def\defvrx#1 {\errmessage{@defvrx in invalid context}}
+
+
+\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\undefined
+ \newwrite\macscribble
+ \def\scanmacro#1{%
+ \begingroup \newlinechar`\^^M
+ % Undo catcode changes of \startcontents and \doprintindex
+ \catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+ % Append \endinput to make sure that TeX does not see the ending newline.
+ \toks0={#1\endinput}%
+ \immediate\openout\macscribble=\jobname.tmp
+ \immediate\write\macscribble{\the\toks0}%
+ \immediate\closeout\macscribble
+ \let\xeatspaces\eatspaces
+ \input \jobname.tmp
+ \endgroup
+}
+\else
+\def\scanmacro#1{%
+\begingroup \newlinechar`\^^M
+% Undo catcode changes of \startcontents and \doprintindex
+\catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup}
+\fi
+
+\newcount\paramno % Count of parameters
+\newtoks\macname % Macro name
+\newif\ifrecursive % Is it recursive?
+\def\macrolist{} % List of all defined macros in the form
+ % \do\macro1\do\macro2...
+
+% Utility routines.
+% Thisdoes \let #1 = #2, except with \csnames.
+\def\cslet#1#2{%
+\expandafter\expandafter
+\expandafter\let
+\expandafter\expandafter
+\csname#1\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=12\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 \.
+
+% 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\macrobodyctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\{=12
+ \catcode`\}=12
+ \catcode`\@=12
+ \catcode`\^^M=12
+ \usembodybackslash}
+
+\def\macroargctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\@=12
+ \catcode`\\=12}
+
+% \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\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%
+ \else
+ \expandafter\parsemargdef \argl;%
+ \fi
+ \if1\csname ismacro.\the\macname\endcsname
+ \message{Warning: redefining \the\macname}%
+ \else
+ \expandafter\ifx\csname \the\macname\endcsname \relax
+ \else \errmessage{The name \the\macname\space is reserved}\fi
+ \global\cslet{macsave.\the\macname}{\the\macname}%
+ \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+ % Add the macroname to \macrolist
+ \toks0 = \expandafter{\macrolist\do}%
+ \xdef\macrolist{\the\toks0
+ \expandafter\noexpand\csname\the\macname\endcsname}%
+ \fi
+ \begingroup \macrobodyctxt
+ \ifrecursive \expandafter\parsermacbody
+ \else \expandafter\parsemacbody
+ \fi}
+
+\def\unmacro{\parsearg\unmacroxxx}
+\def\unmacroxxx#1{%
+ \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
+ \edef\tempa{\expandafter\noexpand\csname#1\endcsname}%
+ \def\do##1{%
+ \def\tempb{##1}%
+ \ifx\tempa\tempb
+ % remove this
+ \else
+ \toks0 = \expandafter{\newmacrolist\do}%
+ \edef\newmacrolist{\the\toks0\expandafter\noexpand\tempa}%
+ \fi}%
+ \def\newmacrolist{}%
+ % Execute macro list to define \newmacrolist
+ \macrolist
+ \global\let\macrolist\newmacrolist
+ \endgroup
+ \else
+ \errmessage{Macro #1 not defined}%
+ \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}}
+
+% 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 be ##N where N is the position in that list.
+% 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.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+ \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\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}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, 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 % many
+ \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}}%
+ \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 % many
+ \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}%
+ \fi
+ \fi}
+
+\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\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+ \ifx\nchar\bgroup\else
+ \expandafter\parsearg
+ \fi \next}
+
+% We mant to disable all macros during \shipout so that they are not
+% expanded by \write.
+\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}%
+ \edef\next{\macrolist}\expandafter\endgroup\next}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign. Just make them active and then expand them all to nothing.
+\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{\ignoreactivespaces
+\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=%
+ \expandafter\noexpand\csname#2\endcsname}%
+\expandafter\endgroup\next}
+
+
+\message{cross references,}
+% @xref etc.
+
+\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 job is to define \lastnode.
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+% The sectioning commands (@chapter, etc.) call these.
+\def\donoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Ysectionnumberandtype}%
+ \global\let\lastnode=\relax
+ \fi
+}
+\def\unnumbnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}%
+ \global\let\lastnode=\relax
+ \fi
+}
+\def\appendixnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Yappendixletterandtype}%
+ \global\let\lastnode=\relax
+ \fi
+}
+
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME, namely
+% NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have
+% to set \indexdummies so commands such as @code in a section title
+% aren't expanded. It would be nicer not to expand the titles in the
+% first place, but there's so many layers that that is hard to do.
+%
+\def\setref#1#2{{%
+ \indexdummies
+ \pdfmkdest{#1}%
+ \dosetq{#1-title}{Ytitle}%
+ \dosetq{#1-pg}{Ypagenumber}%
+ \dosetq{#1-snt}{#2}%
+}}
+
+% @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,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \unsepspaces
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1 > 0pt
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 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.
+ \ifpdf
+ \leavevmode
+ \getfilename{#4}%
+ \ifnum\filenamelength>0
+ \startlink attr{/Border [0 0 0]}%
+ goto file{\the\filename.pdf} name{#1@}%
+ \else
+ \startlink attr{/Border [0 0 0]}%
+ goto name{#1@}%
+ \fi
+ \linkcolor
+ \fi
+ %
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}%
+ \else
+ % _ (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.
+ {\normalturnoffactive
+ % 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
+ }%
+ % [mynode],
+ [\printednodename],\space
+ % page 3
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+ \endlink
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \normalturnoffactive so that punctuation chars such as underscore
+% and backslash work in node names. (\turnoffactive doesn't do \.)
+\def\dosetq#1#2{%
+ {\let\folio=0%
+ \normalturnoffactive
+ \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}%
+ \iflinks
+ \next
+ \fi
+ }%
+}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% 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 % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\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{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ \angleleft un\-de\-fined\angleright
+ \iflinks
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \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.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.
+%
+\def\xrdef#1{\begingroup
+ % Reenable \ as an escape while reading the second argument.
+ \catcode`\\ = 0
+ \afterassignment\endgroup
+ \expandafter\gdef\csname X#1\endcsname
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+\def\readauxfile{\begingroup
+ \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
+ \catcode`\@=\other
+ \catcode`\^=\other
+ % It was suggested to define this as 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
+ \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
+ % Make the characters 128-255 be printing characters
+ {%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+ }%
+ % The aux file uses ' as the escape (for now).
+ % Turn off \ as an escape so we do not lose on
+ % entries which were dumped with control sequences in their names.
+ % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+ % Reference to such entries still does not work the way one would wish,
+ % but at least they do not bomb out when the aux file is read in.
+ \catcode`\{=1
+ \catcode`\}=2
+ \catcode`\%=\other
+ \catcode`\'=0
+ \catcode`\\=\other
+ %
+ \openin 1 \jobname.aux
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.aux
+ \global\havexrefstrue
+ \global\warnedobstrue
+ \fi
+ % Open the new aux file. TeX will close it automatically at exit.
+ \openout\auxfile=\jobname.aux
+\endgroup}
+
+
+% 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
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \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}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% 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 fail inside footnotes because the tokens are fixed when
+% the footnote is read. --karl, 16nov96.
+%
+\long\gdef\footnotezzz{\insert\footins\bgroup
+ % 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.
+ \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
+ %
+ % Hang the footnote text off the number.
+ \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
+ \futurelet\next\fo@t
+}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\par\egroup}
+
+}%end \catcode `\@=11
+
+% 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}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| 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).
+%
+\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
+ }%
+ }%
+}
+
+% 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}
+
+% @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
+ \closein 1
+ % Do not bother showing banner with post-v2.7 epsf.tex (available in
+ % doc/epsf.tex until it shows up on ctan).
+ \def\epsfannounce{\toks0 = }%
+ \input epsf.tex
+\fi
+%
+% 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\undefined
+ \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 just the usual extra ignored arg for parsing this stuff.
+\def\imagexxx#1,#2,#3,#4\finish{%
+ \ifpdf
+ \centerline{\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
+ \begingroup
+ \catcode`\^^M = 5 % in case we're inside an example
+ % If the image is by itself, center it.
+ \ifvmode
+ \nobreak\bigskip
+ % 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
+ \centerline{\epsfbox{#1.eps}}%
+ \bigbreak
+ \else
+ % In the middle of a paragraph, no extra space.
+ \epsfbox{#1.eps}%
+ \fi
+ \endgroup
+ \fi
+}
+
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename. If done too late, it may not override everything
+% properly. Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\def\documentlanguage{\parsearg\dodocumentlanguage}
+\def\dodocumentlanguage#1{%
+ \tex % read txi-??.tex file in plain TeX.
+ % Read the file if it exists.
+ \openin 1 txi-#1.tex
+ \ifeof1
+ \errhelp = \nolanghelp
+ \errmessage{Cannot read language file txi-#1.tex}%
+ \let\temp = \relax
+ \else
+ \def\temp{\input txi-#1.tex }%
+ \fi
+ \temp
+ \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty. Maybe you need to install it? In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\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 so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just 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. Then whoever calls us can
+% set \parskip and call \setleading for \baselineskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6{%
+ \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
+ %
+ \parindent = \defaultparindent
+ \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{13.2pt}%
+ %
+ % If page is nothing but text, make it come out even.
+ \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+ \parskip = 2pt plus 1pt
+ \setleading{12pt}%
+ %
+ \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+ %
+ \lispnarrowing = 0.3in
+ \tolerance = 700
+ \hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \deftypemargin = 0pt
+ \defbodyindent = .5cm
+ %
+ \let\smalldisplay = \smalldisplayx
+ \let\smallexample = \smalllispx
+ \let\smallformat = \smallformatx
+ \let\smalllisp = \smalllispx
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+ \setleading{12pt}%
+ \parskip = 3pt plus 2pt minus 1pt
+ %
+ \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+ %
+ \tolerance = 700
+ \hfuzz = 1pt
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex{{\globaldefs = 1
+ \setleading{13.6pt}%
+ %
+ \afourpaper
+ \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}%
+ %
+ \globaldefs = 0
+}}
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{%
+ \afourpaper
+ \internalpagesizes{6.5in}{9.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
+ %
+ \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.
+%
+\def\pagesizes{\parsearg\pagesizesxxx}
+\def\pagesizesxxx#1{\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{13.2pt}%
+ %
+ \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, 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~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% 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}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{@let"=@normaldoublequote
+@let\=@realbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus
+@let$=@normaldollar}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus
+@let$=@normaldollar}
+
+% 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 back turn 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 look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+@c Set initial fonts.
+@textfonts
+@rm
+
+
+@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:
diff --git a/contrib/awk/install-sh b/contrib/awk/install-sh
new file mode 100755
index 000000000000..ab74c882e923
--- /dev/null
+++ b/contrib/awk/install-sh
@@ -0,0 +1,238 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/awk/mkinstalldirs b/contrib/awk/mkinstalldirs
new file mode 100755
index 000000000000..0801ec2c9661
--- /dev/null
+++ b/contrib/awk/mkinstalldirs
@@ -0,0 +1,32 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" || errstatus=$?
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/contrib/awk/protos.h b/contrib/awk/protos.h
new file mode 100644
index 000000000000..3ed55c5e9602
--- /dev/null
+++ b/contrib/awk/protos.h
@@ -0,0 +1,128 @@
+/*
+ * protos.h -- function prototypes for when the headers don't have them.
+ */
+
+/*
+ * Copyright (C) 1991 - 2000 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef __STDC__
+#define aptr_t void * /* arbitrary pointer type */
+#else
+#define aptr_t char *
+#endif
+extern aptr_t malloc P((MALLOC_ARG_T));
+extern aptr_t realloc P((aptr_t, MALLOC_ARG_T));
+extern aptr_t calloc P((MALLOC_ARG_T, MALLOC_ARG_T));
+
+extern void free P((aptr_t));
+extern char *getenv P((const char *));
+
+#if ! defined(HAVE_STRING_H) && ! defined(HAVE_STRINGS_H)
+extern char *strcpy P((char *, const char *));
+extern char *strcat P((char *, const char *));
+extern char *strncpy P((char *, const char *, size_t));
+extern int strcmp P((const char *, const char *));
+extern int strncmp P((const char *, const char *, size_t));
+extern char *strchr P((const char *, int));
+extern char *strrchr P((const char *, int));
+extern char *strstr P((const char *s1, const char *s2));
+extern size_t strlen P((const char *));
+extern long strtol P((const char *, char **, int));
+
+extern aptr_t memset P((aptr_t, int, size_t));
+extern aptr_t memcpy P((aptr_t, const aptr_t, size_t));
+extern aptr_t memmove P((aptr_t, const aptr_t, size_t));
+extern aptr_t memchr P((const aptr_t, int, size_t));
+extern int memcmp P((const aptr_t, const aptr_t, size_t));
+#endif /* ! defined(HAVE_STRING_H) && ! defined(HAVE_STRINGS_H) */
+
+#ifndef VMS
+extern char *strerror P((int));
+#else
+extern char *strerror P((int,...));
+#endif
+
+#if ! defined(_MSC_VER) && ! defined(__GNU_LIBRARY__)
+extern size_t strftime P((char *, size_t, const char *, const struct tm *));
+#endif
+#ifdef __STDC__
+extern time_t time P((time_t *));
+#else
+extern long time();
+#endif
+
+extern FILE *fdopen P((int, const char *));
+extern int fprintf P((FILE *, const char *, ...));
+#if ! defined(MSDOS) && ! defined(__GNU_LIBRARY__)
+#ifdef __STDC__
+extern size_t fwrite P((const aptr_t, size_t, size_t, FILE *));
+#else
+extern int fwrite();
+#endif
+extern int fputs P((const char *, FILE *));
+extern int unlink P((const char *));
+#endif
+extern int fflush P((FILE *));
+extern int fclose P((FILE *));
+extern FILE *popen P((const char *, const char *));
+extern int pclose P((FILE *));
+extern void abort P(());
+extern int isatty P((int));
+extern void exit P((int));
+extern int system P((const char *));
+extern int sscanf P((const char *, const char *, ...));
+#ifndef toupper
+extern int toupper P((int));
+#endif
+#ifndef tolower
+extern int tolower P((int));
+#endif
+
+extern double pow P((double x, double y));
+extern double atof P((const char *));
+extern double strtod P((const char *, char **));
+extern int fstat P((int, struct stat *));
+extern int stat P((const char *, struct stat *));
+extern off_t lseek P((int, off_t, int));
+extern int fseek P((FILE *, long, int));
+extern int close P((int));
+extern int creat P((const char *, mode_t));
+extern int open P((const char *, int, ...));
+extern int pipe P((int *));
+extern int dup P((int));
+extern int dup2 P((int,int));
+extern int fork P(());
+extern int execl P((const char *, const char *, ...));
+#ifndef __STDC__
+extern int read P((int, void *, unsigned int));
+#endif
+#ifndef HAVE_SYS_WAIT_H
+extern int wait P((int *));
+#endif
+extern void _exit P((int));
+
+#ifndef __STDC__
+extern long time P((long *));
+#endif
+
+extern SPRINTF_RET sprintf P((char *, const char *, ...));
+
+#undef aptr_t
diff --git a/contrib/awk/regex.c b/contrib/awk/regex.c
new file mode 100644
index 000000000000..8c7f4fe2c8c3
--- /dev/null
+++ b/contrib/awk/regex.c
@@ -0,0 +1,5744 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P1003.2/D11.2, except for some of the
+ internationalization features.)
+
+ Copyright (C) 1993,1994,1995,1996,1997,1999,2000 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 2, 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+ #pragma alloca
+#endif
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(STDC_HEADERS) && !defined(emacs)
+#include <stddef.h>
+#else
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+#include <sys/types.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+# include <wctype.h>
+# include <wchar.h>
+#endif
+
+/* This is for other GNU distributions with internationalized messages. */
+#if HAVE_LIBINTL_H || defined (_LIBC)
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+ strings. */
+#define gettext_noop(String) String
+#endif
+
+/* The `emacs' switch turns on certain matching commands
+ that make sense only in Emacs. */
+#ifdef emacs
+
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else /* not emacs */
+
+/* If we are not linking with Emacs proper,
+ we can't use the relocating allocator
+ even if config.h says that we can. */
+#undef REL_ALLOC
+
+#if defined (STDC_HEADERS) || defined (_LIBC)
+#include <stdlib.h>
+#else
+char *malloc ();
+char *realloc ();
+#endif
+
+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
+ If nothing else has been done, use the method below. */
+#ifdef INHIBIT_STRING_HEADER
+#if !(defined (HAVE_BZERO) && defined (HAVE_BCOPY))
+#if !defined (bzero) && !defined (bcopy)
+#undef INHIBIT_STRING_HEADER
+#endif
+#endif
+#endif
+
+/* This is the normal way of making sure we have a bcopy and a bzero.
+ This is used in most programs--a few other programs avoid this
+ by defining INHIBIT_STRING_HEADER. */
+#ifndef INHIBIT_STRING_HEADER
+#if defined (HAVE_STRING_H) || defined (STDC_HEADERS) || defined (_LIBC)
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n) memset ((s), 0, (n))
+#endif
+#else
+#include <strings.h>
+#endif
+#endif
+
+/* Define the syntax stuff for \<, \>, etc. */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+ commands in re_match_2. */
+#ifndef Sword
+#define Sword 1
+#endif
+
+#ifdef SWITCH_ENUM_BUG
+#define SWITCH_ENUM_CAST(x) ((int)(x))
+#else
+#define SWITCH_ENUM_CAST(x) (x)
+#endif
+
+#endif /* not emacs */
+
+/* Get the interface, including the syntax bits. */
+#include "regex.h"
+
+/* isalpha etc. are used for the character classes. */
+#include <ctype.h>
+
+/* Jim Meyering writes:
+
+ "... Some ctype macros are valid only for character codes that
+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ using /bin/cc or gcc but without giving an ansi option). So, all
+ ctype uses should be through macros like ISPRINT... If
+ STDC_HEADERS is defined, then autoconf has verified that the ctype
+ macros don't need to be guarded with references to isascii. ...
+ Defining isascii to 1 should let any compiler worth its salt
+ eliminate the && through constant folding." */
+
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+#define ISASCII(c) 1
+#else
+#define ISASCII(c) isascii(c)
+#endif
+
+#ifdef isblank
+#define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+#define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+ since ours (we hope) works properly with all combinations of
+ machines, compilers, `char' and `unsigned char' argument types.
+ (Per Bothner suggested the basic approach.) */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+
+#ifndef emacs
+/* How many characters in the character set. */
+#define CHAR_SET_SIZE 256
+
+#ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 0; c < CHAR_SET_SIZE; c++)
+ if (ISALNUM (c))
+ re_syntax_table[c] = Sword;
+
+ re_syntax_table['_'] = Sword;
+
+ done = 1;
+}
+
+#endif /* not SYNTAX_TABLE */
+
+#define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
+
+#endif /* emacs */
+
+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
+ use `alloca' instead of `malloc'. This is because using malloc in
+ re_search* or re_match* could cause memory leaks when C-g is used in
+ Emacs; also, malloc is slower and causes storage fragmentation. On
+ the other hand, malloc is more portable, and easier to debug.
+
+ Because we sometimes use alloca, some routines have to be macros,
+ not functions -- `alloca'-allocated space disappears at the end of the
+ function it is called in. */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE malloc
+#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+#define REGEX_FREE free
+
+#else /* not REGEX_MALLOC */
+
+/* Emacs already defines alloca, sometimes. */
+#ifndef alloca
+
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#if 0 /* It is a bad idea to declare alloca. We always cast the result. */
+#ifndef _AIX /* Already did AIX, up at the top. */
+char *alloca ();
+#endif /* not _AIX */
+#endif
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUC__ */
+
+#endif /* not alloca */
+
+#define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable. */
+#define REGEX_REALLOCATE(source, osize, nsize) \
+ (destination = (char *) alloca (nsize), \
+ bcopy (source, destination, osize), \
+ destination)
+
+/* No need to do anything to free, after alloca. */
+#define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
+
+#endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack. */
+
+#if defined (REL_ALLOC) && defined (REGEX_MALLOC)
+
+#define REGEX_ALLOCATE_STACK(size) \
+ r_alloc (&failure_stack_ptr, (size))
+#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ r_re_alloc (&failure_stack_ptr, (nsize))
+#define REGEX_FREE_STACK(ptr) \
+ r_alloc_free (&failure_stack_ptr)
+
+#else /* not using relocating allocator */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE_STACK malloc
+#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+#define REGEX_FREE_STACK free
+
+#else /* not REGEX_MALLOC */
+
+#define REGEX_ALLOCATE_STACK alloca
+
+#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything. */
+#define REGEX_FREE_STACK(arg)
+
+#endif /* not REGEX_MALLOC */
+#endif /* not using relocating allocator */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+ `string1' or just past its end. This works if PTR is NULL, which is
+ a good thing. */
+#define FIRST_STRING_P(ptr) \
+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail. */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define RETALLOC_IF(addr, n, t) \
+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits. */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+static int re_match_2_internal ();
+
+/* These are the command codes that appear in compiled regular
+ expressions. Some opcodes are followed by argument bytes. A
+ command code can specify any interpretation whatsoever for its
+ arguments. Zero bytes may appear in the compiled regular expression. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Succeed right away--no more backtracking. */
+ succeed,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn,
+
+ /* Matches any (more or less) character. */
+ anychar,
+
+ /* Matches any one char belonging to specified set. First
+ following byte is number of bitmap bytes. Then come bytes
+ for a bitmap saying which chars are in. Bits in each byte
+ are ordered low-bit-first. A character is in the set if its
+ bit is 1. A character too large to have a bit in the map is
+ automatically not in the set. */
+ charset,
+
+ /* Same parameters as charset, but match any character that is
+ not one of those specified. */
+ charset_not,
+
+ /* Start remembering the text that is matched, for storing in a
+ register. Followed by one byte with the register number, in
+ the range 0 to one less than the pattern buffer's re_nsub
+ field. Then followed by one byte with the number of groups
+ inner to this one. (This last has to be part of the
+ start_memory only because we need it in the on_failure_jump
+ of re_match_2.) */
+ start_memory,
+
+ /* Stop remembering the text that is matched and store it in a
+ memory register. Followed by one byte with the register
+ number, in the range 0 to one less than `re_nsub' in the
+ pattern buffer, and one byte with the number of inner groups,
+ just like `start_memory'. (We need the number of inner
+ groups here because we don't have any easy way of finding the
+ corresponding start_memory when we're at a stop_memory.) */
+ stop_memory,
+
+ /* Match a duplicate of something remembered. Followed by one
+ byte containing the register number. */
+ duplicate,
+
+ /* Fail unless at beginning of line. */
+ begline,
+
+ /* Fail unless at end of line. */
+ endline,
+
+ /* Succeeds if at beginning of buffer (if emacs) or at beginning
+ of string to be matched (if not). */
+ begbuf,
+
+ /* Analogously, for end of buffer/string. */
+ endbuf,
+
+ /* Followed by two byte relative address to which to jump. */
+ jump,
+
+ /* Same as jump, but marks the end of an alternative. */
+ jump_past_alt,
+
+ /* Followed by two-byte relative address of place to resume at
+ in case of failure. */
+ on_failure_jump,
+
+ /* Like on_failure_jump, but pushes a placeholder instead of the
+ current string position when executed. */
+ on_failure_keep_string_jump,
+
+ /* Throw away latest failure point and then jump to following
+ two-byte relative address. */
+ pop_failure_jump,
+
+ /* Change to pop_failure_jump if know won't have to backtrack to
+ match; otherwise change to jump. This is used to jump
+ back to the beginning of a repeat. If what follows this jump
+ clearly won't match what the repeat does, such that we can be
+ sure that there is no use backtracking out of repetitions
+ already matched, then we change it to a pop_failure_jump.
+ Followed by two-byte address. */
+ maybe_pop_jump,
+
+ /* Jump to following two-byte address, and push a dummy failure
+ point. This failure point will be thrown away if an attempt
+ is made to use it for a failure. A `+' construct makes this
+ before the first repeat. Also used as an intermediary kind
+ of jump when compiling an alternative. */
+ dummy_failure_jump,
+
+ /* Push a dummy failure point and continue. Used at the end of
+ alternatives. */
+ push_dummy_failure,
+
+ /* Followed by two-byte relative address and two-byte number n.
+ After matching N times, jump to the address upon failure. */
+ succeed_n,
+
+ /* Followed by two-byte relative address, and two-byte number n.
+ Jump to the address N times, then fail. */
+ jump_n,
+
+ /* Set the following two-byte relative address to the
+ subsequent two-byte number. The address *includes* the two
+ bytes of number. */
+ set_number_at,
+
+ wordchar, /* Matches any word-constituent character. */
+ notwordchar, /* Matches any char that is not a word-constituent. */
+
+ wordbeg, /* Succeeds if at word beginning. */
+ wordend, /* Succeeds if at word end. */
+
+ wordbound, /* Succeeds if at a word boundary. */
+ notwordbound /* Succeeds if not at a word boundary. */
+
+#ifdef emacs
+ ,before_dot, /* Succeeds if before point. */
+ at_dot, /* Succeeds if at point. */
+ after_dot, /* Succeeds if after point. */
+
+ /* Matches any character whose syntax is specified. Followed by
+ a byte which contains a syntax code, e.g., Sword. */
+ syntaxspec,
+
+ /* Matches any character whose syntax is not that specified. */
+ notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+
+/* Common operations on the compiled pattern. */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
+
+#define STORE_NUMBER(destination, number) \
+ do { \
+ (destination)[0] = (number) & 0377; \
+ (destination)[1] = (number) >> 8; \
+ } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+ the byte after where the number is stored. Therefore, DESTINATION
+ must be an lvalue. */
+
+#define STORE_NUMBER_AND_INCR(destination, number) \
+ do { \
+ STORE_NUMBER (destination, number); \
+ (destination) += 2; \
+ } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+ at SOURCE. */
+
+#define EXTRACT_NUMBER(destination, source) \
+ do { \
+ (destination) = *(source) & 0377; \
+ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number _RE_ARGS ((int *dest, unsigned char *source));
+static void
+extract_number (dest, source)
+ int *dest;
+ unsigned char *source;
+{
+ int temp = SIGN_EXTEND_CHAR (*(source + 1));
+ *dest = *source & 0377;
+ *dest += temp << 8;
+}
+
+#ifndef EXTRACT_MACROS /* To debug the macros. */
+#undef EXTRACT_NUMBER
+#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+ SOURCE must be an lvalue. */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source) \
+ do { \
+ EXTRACT_NUMBER (destination, source); \
+ (source) += 2; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number_and_incr _RE_ARGS ((int *destination,
+ unsigned char **source));
+static void
+extract_number_and_incr (destination, source)
+ int *destination;
+ unsigned char **source;
+{
+ extract_number (destination, *source);
+ *source += 2;
+}
+
+#ifndef EXTRACT_MACROS
+#undef EXTRACT_NUMBER_AND_INCR
+#define EXTRACT_NUMBER_AND_INCR(dest, src) \
+ extract_number_and_incr (&dest, &src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+ it is doing (if the variable `debug' is nonzero). If linked with the
+ main program in `iregex.c', you can enter patterns and strings
+ interactively. And if linked with the main program in `main.c' and
+ the other test files, you can run the already-written tests. */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging. */
+#include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging. */
+#include <assert.h>
+
+static int debug = 0;
+
+#define DEBUG_STATEMENT(e) e
+#define DEBUG_PRINT1(x) if (debug) printf (x)
+#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
+ if (debug) print_partial_compiled_pattern (s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
+ if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form. */
+
+void
+print_fastmap (fastmap)
+ char *fastmap;
+{
+ unsigned was_a_range = 0;
+ unsigned i = 0;
+
+ while (i < (1 << BYTEWIDTH))
+ {
+ if (fastmap[i++])
+ {
+ was_a_range = 0;
+ putchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ putchar (i - 1);
+ }
+ }
+ }
+ putchar ('\n');
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+ the START pointer into it and ending just before the pointer END. */
+
+void
+print_partial_compiled_pattern (start, end)
+ unsigned char *start;
+ unsigned char *end;
+{
+ int mcnt, mcnt2;
+ unsigned char *p1;
+ unsigned char *p = start;
+ unsigned char *pend = end;
+
+ if (start == NULL)
+ {
+ printf ("(null)\n");
+ return;
+ }
+
+ /* Loop over pattern commands. */
+ while (p < pend)
+ {
+ printf ("%d:\t", p - start);
+
+ switch ((re_opcode_t) *p++)
+ {
+ case no_op:
+ printf ("/no_op");
+ break;
+
+ case exactn:
+ mcnt = *p++;
+ printf ("/exactn/%d", mcnt);
+ do
+ {
+ putchar ('/');
+ putchar (*p++);
+ }
+ while (--mcnt);
+ break;
+
+ case start_memory:
+ mcnt = *p++;
+ printf ("/start_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case stop_memory:
+ mcnt = *p++;
+ printf ("/stop_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case duplicate:
+ printf ("/duplicate/%d", *p++);
+ break;
+
+ case anychar:
+ printf ("/anychar");
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ register int c, last = -100;
+ register int in_range = 0;
+
+ printf ("/charset [%s",
+ (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+
+ assert (p + *p < pend);
+
+ for (c = 0; c < 256; c++)
+ if (c / 8 < *p
+ && (p[1 + (c/8)] & (1 << (c % 8))))
+ {
+ /* Are we starting a range? */
+ if (last + 1 == c && ! in_range)
+ {
+ putchar ('-');
+ in_range = 1;
+ }
+ /* Have we broken a range? */
+ else if (last + 1 != c && in_range)
+ {
+ putchar (last);
+ in_range = 0;
+ }
+
+ if (! in_range)
+ putchar (c);
+
+ last = c;
+ }
+
+ if (in_range)
+ putchar (last);
+
+ putchar (']');
+
+ p += 1 + *p;
+ }
+ break;
+
+ case begline:
+ printf ("/begline");
+ break;
+
+ case endline:
+ printf ("/endline");
+ break;
+
+ case on_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case on_failure_keep_string_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+ break;
+
+ case dummy_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/dummy_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case push_dummy_failure:
+ printf ("/push_dummy_failure");
+ break;
+
+ case maybe_pop_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/maybe_pop_jump to %d", p + mcnt - start);
+ break;
+
+ case pop_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/pop_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case jump_past_alt:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump_past_alt to %d", p + mcnt - start);
+ break;
+
+ case jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump to %d", p + mcnt - start);
+ break;
+
+ case succeed_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/succeed_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case jump_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case set_number_at:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/set_number_at location %d to %d", p1 - start, mcnt2);
+ break;
+
+ case wordbound:
+ printf ("/wordbound");
+ break;
+
+ case notwordbound:
+ printf ("/notwordbound");
+ break;
+
+ case wordbeg:
+ printf ("/wordbeg");
+ break;
+
+ case wordend:
+ printf ("/wordend");
+
+#ifdef emacs
+ case before_dot:
+ printf ("/before_dot");
+ break;
+
+ case at_dot:
+ printf ("/at_dot");
+ break;
+
+ case after_dot:
+ printf ("/after_dot");
+ break;
+
+ case syntaxspec:
+ printf ("/syntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+
+ case notsyntaxspec:
+ printf ("/notsyntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+#endif /* emacs */
+
+ case wordchar:
+ printf ("/wordchar");
+ break;
+
+ case notwordchar:
+ printf ("/notwordchar");
+ break;
+
+ case begbuf:
+ printf ("/begbuf");
+ break;
+
+ case endbuf:
+ printf ("/endbuf");
+ break;
+
+ default:
+ printf ("?%d", *(p-1));
+ }
+
+ putchar ('\n');
+ }
+
+ printf ("%d:\tend of pattern.\n", p - start);
+}
+
+
+void
+print_compiled_pattern (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *buffer = bufp->buffer;
+
+ print_partial_compiled_pattern (buffer, buffer + bufp->used);
+ printf ("%ld bytes used/%ld bytes allocated.\n",
+ bufp->used, bufp->allocated);
+
+ if (bufp->fastmap_accurate && bufp->fastmap)
+ {
+ printf ("fastmap: ");
+ print_fastmap (bufp->fastmap);
+ }
+
+ printf ("re_nsub: %d\t", bufp->re_nsub);
+ printf ("regs_alloc: %d\t", bufp->regs_allocated);
+ printf ("can_be_null: %d\t", bufp->can_be_null);
+ printf ("newline_anchor: %d\n", bufp->newline_anchor);
+ printf ("no_sub: %d\t", bufp->no_sub);
+ printf ("not_bol: %d\t", bufp->not_bol);
+ printf ("not_eol: %d\t", bufp->not_eol);
+ printf ("syntax: %lx\n", bufp->syntax);
+ /* Perhaps we should print the translate table? */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+ const char *where;
+ const char *string1;
+ const char *string2;
+ int size1;
+ int size2;
+{
+ int this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ putchar (string1[this_char]);
+
+ where = string2;
+ }
+
+ for (this_char = where - string2; this_char < size2; this_char++)
+ putchar (string2[this_char]);
+ }
+}
+
+void
+printchar (c)
+ int c;
+{
+ putc (c, stderr);
+}
+
+#else /* not DEBUG */
+
+#undef assert
+#define assert(e)
+
+#define DEBUG_STATEMENT(e)
+#define DEBUG_PRINT1(x)
+#define DEBUG_PRINT2(x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
+ also be assigned to arbitrarily: each pattern buffer stores its own
+ syntax, so it can be changed between regex compilations. */
+/* This has no initializer because initialized variables in Emacs
+ become read-only after dumping. */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation. This provides
+ for compatibility for various utilities which historically have
+ different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit mask comprised of the various bits
+ defined in regex.h. We return the old syntax. */
+
+reg_syntax_t
+re_set_syntax (syntax)
+ reg_syntax_t syntax;
+{
+ reg_syntax_t ret = re_syntax_options;
+
+ re_syntax_options = syntax;
+#ifdef DEBUG
+ if (syntax & RE_DEBUG)
+ debug = 1;
+ else if (debug) /* was on but now is not */
+ debug = 0;
+#endif /* DEBUG */
+ return ret;
+}
+
+/* This table gives an error message for each of the error codes listed
+ in regex.h. Obviously the order here has to be same as there.
+ POSIX doesn't require that we do anything for REG_NOERROR,
+ but why not be nice? */
+
+static const char *re_error_msgid[] =
+ {
+ gettext_noop ("Success"), /* REG_NOERROR */
+ gettext_noop ("No match"), /* REG_NOMATCH */
+ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
+ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
+ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
+ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
+ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
+ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */
+ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
+ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
+ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
+ gettext_noop ("Invalid range end"), /* REG_ERANGE */
+ gettext_noop ("Memory exhausted"), /* REG_ESPACE */
+ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
+ gettext_noop ("Premature end of regular expression"), /* REG_EEND */
+ gettext_noop ("Regular expression too big"), /* REG_ESIZE */
+ gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */
+ };
+
+/* Avoiding alloca during matching, to placate r_alloc. */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+ searching and matching functions should not call alloca. On some
+ systems, alloca is implemented in terms of malloc, and if we're
+ using the relocating allocator routines, then malloc could cause a
+ relocation, which might (if the strings being searched are in the
+ ralloc heap) shift the data out from underneath the regexp
+ routines.
+
+ Here's another reason to avoid allocation: Emacs
+ processes input from X in a signal handler; processing X input may
+ call malloc; if input arrives while a matching routine is calling
+ malloc, then we're scrod. But Emacs can't just block input while
+ calling matching routines; then we don't notice interrupts when
+ they come in. So, Emacs blocks input around all regexp calls
+ except the matching calls, which it leaves unprotected, in the
+ faith that they will not malloc. */
+
+/* Normally, this is fine. */
+#define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+ what config.h may say. So don't take precautions for it. */
+#ifdef __GNUC__
+#undef C_ALLOCA
+#endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+ and (2) it's not safe for them to use malloc.
+ Note that if REL_ALLOC is defined, matching would not use malloc for the
+ failure stack, but we would still use it for the register vectors;
+ so REL_ALLOC should not affect this. */
+#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (emacs)
+#undef MATCH_MAY_ALLOCATE
+#endif
+
+
+/* Failure stack declarations and macros; both re_compile_fastmap and
+ re_match_2 use a failure stack. These have to be macros because of
+ REGEX_ALLOCATE_STACK. */
+
+
+/* Number of failure points for which to initially allocate space
+ when matching. If this number is exceeded, we allocate more
+ space, so it is not a hard limit. */
+#ifndef INIT_FAILURE_ALLOC
+#define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack. Would be
+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+
+#ifdef INT_IS_16BIT
+
+#if defined (MATCH_MAY_ALLOCATE)
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+long int re_max_failures = 4000;
+#else
+long int re_max_failures = 2000;
+#endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ long int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned long int size;
+ unsigned long int avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#else /* not INT_IS_16BIT */
+
+#if defined (MATCH_MAY_ALLOCATE)
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+int re_max_failures = 20000;
+#else
+int re_max_failures = 2000;
+#endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#endif /* INT_IS_16BIT */
+
+#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
+
+
+/* Define macros to initialize and free the failure stack.
+ Do `return -2' if the alloc fails. */
+
+#ifdef MATCH_MAY_ALLOCATE
+#define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (fail_stack_elt_t *) \
+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
+ \
+ if (fail_stack.stack == NULL) \
+ return -2; \
+ \
+ fail_stack.size = INIT_FAILURE_ALLOC; \
+ fail_stack.avail = 0; \
+ } while (0)
+
+#define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
+#else
+#define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.avail = 0; \
+ } while (0)
+
+#define RESET_FAIL_STACK()
+#endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+ Return 1 if succeeds, and 0 if either ran out of memory
+ allocating space for it or it was already too large.
+
+ REGEX_REALLOCATE_STACK requires `destination' be declared. */
+
+#define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \
+ ? 0 \
+ : ((fail_stack).stack = (fail_stack_elt_t *) \
+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \
+ (fail_stack).size * sizeof (fail_stack_elt_t), \
+ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
+ \
+ (fail_stack).stack == NULL \
+ ? 0 \
+ : ((fail_stack).size <<= 1, \
+ 1)))
+
+
+/* Push pointer POINTER on FAIL_STACK.
+ Return 1 if was able to do so and 0 if ran out of memory allocating
+ space to do so. */
+#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
+ ? 0 \
+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
+ 1))
+
+/* Push a pointer value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_POINTER(item) \
+ fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_INT(item) \
+ fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_ELT(item) \
+ fail_stack.stack[fail_stack.avail++] = (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+ All assume that `fail_stack' is nonempty. */
+#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging. */
+#ifdef DEBUG
+#define DEBUG_PUSH PUSH_FAILURE_INT
+#define DEBUG_POP(item_addr) (item_addr)->integer = POP_FAILURE_INT ()
+#else
+#define DEBUG_PUSH(item)
+#define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+ if we ever fail back to it.
+
+ Requires variables fail_stack, regstart, regend, reg_info, and
+ num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be
+ declared.
+
+ Does `return FAILURE_CODE' if runs out of memory. */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
+ do { \
+ char *destination; \
+ /* Must be int, so when we don't save any registers, the arithmetic \
+ of 0 + -1 isn't done as unsigned. */ \
+ /* Can't be int, since there is not a shred of a guarantee that int \
+ is wide enough to hold a value of something to which pointer can \
+ be assigned */ \
+ s_reg_t this_reg; \
+ \
+ DEBUG_STATEMENT (failure_id++); \
+ DEBUG_STATEMENT (nfailure_points_pushed++); \
+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
+ \
+ DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \
+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
+ \
+ /* Ensure we have enough space allocated for what we will push. */ \
+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
+ { \
+ if (!DOUBLE_FAIL_STACK (fail_stack)) \
+ return failure_code; \
+ \
+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
+ (fail_stack).size); \
+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+ } \
+ \
+ /* Push the info, starting with the registers. */ \
+ DEBUG_PRINT1 ("\n"); \
+ \
+ if (1) \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ PUSH_FAILURE_POINTER (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ PUSH_FAILURE_POINTER (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
+ DEBUG_PRINT2 (" match_null=%d", \
+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" matched_something=%d", \
+ MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" ever_matched=%d", \
+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT1 ("\n"); \
+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \
+ } \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
+ PUSH_FAILURE_INT (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
+ PUSH_FAILURE_INT (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern 0x%x:\n", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_POINTER (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_POINTER (string_place); \
+ \
+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
+ DEBUG_PUSH (failure_id); \
+ } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+ for each register. */
+#define NUM_REG_ITEMS 3
+
+/* Individual items aside from the registers. */
+#ifdef DEBUG
+#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
+#else
+#define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack. */
+/* We used to use (num_regs - 1), which is the number of registers
+ this regexp will save; but that was changed to 5
+ to avoid stack overflow for a regexp with lots of parens. */
+#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+#define NUM_FAILURE_ITEMS \
+ (((0 \
+ ? 0 : highest_active_reg - lowest_active_reg + 1) \
+ * NUM_REG_ITEMS) \
+ + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it. */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+ We restore into the parameters, all of which should be lvalues:
+ STR -- the saved data position.
+ PAT -- the saved pattern position.
+ LOW_REG, HIGH_REG -- the highest and lowest active registers.
+ REGSTART, REGEND -- arrays of string positions.
+ REG_INFO -- array of information about each subexpression.
+
+ Also assumes the variables `fail_stack' and (if debugging), `bufp',
+ `pend', `string1', `size1', `string2', and `size2'. */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{ \
+ DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \
+ s_reg_t this_reg; \
+ const unsigned char *string_temp; \
+ \
+ assert (!FAIL_STACK_EMPTY ()); \
+ \
+ /* Remove failure points and point to how many regs pushed. */ \
+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
+ \
+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
+ \
+ DEBUG_POP (&failure_id); \
+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
+ \
+ /* If the saved string location is NULL, it came from an \
+ on_failure_keep_string_jump opcode, and we want to throw away the \
+ saved NULL, thus retaining our current position in the string. */ \
+ string_temp = POP_FAILURE_POINTER (); \
+ if (string_temp != NULL) \
+ str = (const char *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (unsigned char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" Popping pattern 0x%x:\n", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ /* Restore register info. */ \
+ high_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
+ \
+ low_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
+ \
+ if (1) \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ELT (); \
+ DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
+ \
+ regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ } \
+ else \
+ { \
+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
+ { \
+ reg_info[this_reg].word.integer = 0; \
+ regend[this_reg] = 0; \
+ regstart[this_reg] = 0; \
+ } \
+ highest_active_reg = high_reg; \
+ } \
+ \
+ set_regs_matched_done = 0; \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+
+
+/* Structure for per-register (a.k.a. per-group) information.
+ Other register information, such as the
+ starting and ending positions (which are addresses), and the list of
+ inner groups (which is a bits list) are maintained in separate
+ variables.
+
+ We are making a (strictly speaking) nonportable assumption here: that
+ the compiler will pack our bit fields into something that fits into
+ the type of `word', i.e., is something that fits into one item on the
+ failure stack. */
+
+
+/* Declarations and macros for re_match_2. */
+
+typedef union
+{
+ fail_stack_elt_t word;
+ struct
+ {
+ /* This field is one if this group can match the empty string,
+ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
+#define MATCH_NULL_UNSET_VALUE 3
+ unsigned match_null_string_p : 2;
+ unsigned is_active : 1;
+ unsigned matched_something : 1;
+ unsigned ever_matched_something : 1;
+ } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R) ((R).bits.is_active)
+#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+ for the subexpressions which we are currently inside. Also records
+ that those subexprs have matched. */
+#define SET_REGS_MATCHED() \
+ do \
+ { \
+ if (!set_regs_matched_done) \
+ { \
+ active_reg_t r; \
+ set_regs_matched_done = 1; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+static char reg_unset_dummy;
+#define REG_UNSET_VALUE (&reg_unset_dummy)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+/* Subroutine declarations and macros for regex_compile. */
+
+static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size,
+ reg_syntax_t syntax,
+ struct re_pattern_buffer *bufp));
+static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg));
+static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2));
+static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg, unsigned char *end));
+static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2, unsigned char *end));
+static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p,
+ reg_syntax_t syntax));
+static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend,
+ reg_syntax_t syntax));
+static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr,
+ const char *pend,
+ char *translate,
+ reg_syntax_t syntax,
+ unsigned char *b));
+
+/* Fetch the next character in the uncompiled pattern---translating it
+ if necessary. Also cast from a signed character in the constant
+ string passed to us by the user to an unsigned char that we can use
+ as an array index (in, e.g., `translate'). */
+#ifndef PATFETCH
+#define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = (unsigned char) translate[c]; \
+ } while (0)
+#endif
+
+/* Fetch the next character in the uncompiled pattern, with no
+ translation. */
+#define PATFETCH_RAW(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ } while (0)
+
+/* Go backwards one character in the pattern. */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D. We
+ cast the subscript to translate because some data is declared as
+ `char *', to avoid warnings when a string constant is passed. But
+ when we use a character as a subscript we must make it unsigned. */
+#ifndef TRANSLATE
+#define TRANSLATE(d) \
+ (translate ? (char) translate[(unsigned char) (d)] : (d))
+#endif
+
+
+/* Macros for outputting the compiled pattern into `buffer'. */
+
+/* If the buffer isn't allocated when it comes in, use this. */
+#define INIT_BUF_SIZE 32
+
+/* Make sure we have at least N more bytes of space in buffer. */
+#define GET_BUFFER_SPACE(n) \
+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
+ EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it. */
+#define BUF_PUSH(c) \
+ do { \
+ GET_BUFFER_SPACE (1); \
+ *b++ = (unsigned char) (c); \
+ } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
+#define BUF_PUSH_2(c1, c2) \
+ do { \
+ GET_BUFFER_SPACE (2); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes. */
+#define BUF_PUSH_3(c1, c2, c3) \
+ do { \
+ GET_BUFFER_SPACE (3); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ *b++ = (unsigned char) (c3); \
+ } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO. We store a
+ relative address offset by the three bytes the jump itself occupies. */
+#define STORE_JUMP(op, loc, to) \
+ store_op1 (op, loc, (int) ((to) - (loc) - 3))
+
+/* Likewise, for a two-argument jump. */
+#define STORE_JUMP2(op, loc, to, arg) \
+ store_op2 (op, loc, (int) ((to) - (loc) - 3), arg)
+
+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP(op, loc, to) \
+ insert_op1 (op, loc, (int) ((to) - (loc) - 3), b)
+
+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP2(op, loc, to, arg) \
+ insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+ into the pattern are two bytes long. So if 2^16 bytes turns out to
+ be too small, many things would have to change. */
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+ bytes will have to use approach similar to what was done below for
+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up
+ reallocating to 0 bytes. Such thing is not going to work too well.
+ You have been warned!! */
+#if defined(_MSC_VER) && !defined(WIN32)
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+ The REALLOC define eliminates a flurry of conversion warnings,
+ but is not required. */
+#define MAX_BUF_SIZE 65500L
+#define REALLOC(p,s) realloc ((p), (size_t) (s))
+#else
+#define MAX_BUF_SIZE (1L << 16)
+#define REALLOC(p,s) realloc ((p), (s))
+#endif
+
+/* Extend the buffer by twice its current size via realloc and
+ reset the pointers that pointed into the old block to point to the
+ correct places in the new one. If extending the buffer results in it
+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */
+#if __BOUNDED_POINTERS__
+# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
+# define MOVE_BUFFER_POINTER(P) \
+ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND \
+ else \
+ { \
+ SET_HIGH_BOUND (b); \
+ SET_HIGH_BOUND (begalt); \
+ if (fixup_alt_jump) \
+ SET_HIGH_BOUND (fixup_alt_jump); \
+ if (laststart) \
+ SET_HIGH_BOUND (laststart); \
+ if (pending_exact) \
+ SET_HIGH_BOUND (pending_exact); \
+ }
+#else
+# define MOVE_BUFFER_POINTER(P) (P) += incr
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND
+#endif
+#define EXTEND_BUFFER() \
+ do { \
+ unsigned char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == MAX_BUF_SIZE) \
+ return REG_ESIZE; \
+ bufp->allocated <<= 1; \
+ if (bufp->allocated > MAX_BUF_SIZE) \
+ bufp->allocated = MAX_BUF_SIZE; \
+ bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\
+ if (bufp->buffer == NULL) \
+ return REG_ESPACE; \
+ /* If the buffer moved, move all the pointers into it. */ \
+ if (old_buffer != bufp->buffer) \
+ { \
+ int incr = bufp->buffer - old_buffer; \
+ MOVE_BUFFER_POINTER (b); \
+ MOVE_BUFFER_POINTER (begalt); \
+ if (fixup_alt_jump) \
+ MOVE_BUFFER_POINTER (fixup_alt_jump); \
+ if (laststart) \
+ MOVE_BUFFER_POINTER (laststart); \
+ if (pending_exact) \
+ MOVE_BUFFER_POINTER (pending_exact); \
+ } \
+ ELSE_EXTEND_BUFFER_HIGH_BOUND \
+ } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+ {start,stop}_memory, the maximum number of groups we can report
+ things about is what fits in that byte. */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers. We just
+ ignore the excess. */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack. */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
+/* int may be not enough when sizeof(int) == 2. */
+typedef long pattern_offset_t;
+
+typedef struct
+{
+ pattern_offset_t begalt_offset;
+ pattern_offset_t fixup_alt_jump;
+ pattern_offset_t inner_group_offset;
+ pattern_offset_t laststart_offset;
+ regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+ compile_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
+
+/* The next available element. */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list. */
+#define SET_LIST_BIT(c) \
+ (b[((unsigned char) (c)) / BYTEWIDTH] \
+ |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern. */
+#define GET_UNSIGNED_NUMBER(num) \
+ { if (p != pend) \
+ { \
+ PATFETCH (c); \
+ while (ISDIGIT (c)) \
+ { \
+ if (num < 0) \
+ num = 0; \
+ num = num * 10 + c - '0'; \
+ if (p == pend) \
+ break; \
+ PATFETCH (c); \
+ } \
+ } \
+ }
+
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# define IS_CHAR_CLASS(string) wctype (string)
+#else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+#endif
+
+#ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+ we make the fail stack and register vectors global.
+ The fail stack, we grow to the maximum size when a regexp
+ is compiled.
+ The register vectors, we adjust in size each time we
+ compile a regexp, according to the number of registers it needs. */
+
+static fail_stack_type fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+ That is so we can make them bigger as needed,
+ but never make them smaller. */
+static int regs_allocated_size;
+
+static const char ** regstart, ** regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static register_info_type *reg_info;
+static const char **reg_dummy;
+static register_info_type *reg_info_dummy;
+
+/* Make the register vectors big enough for NUM_REGS registers,
+ but don't make them smaller. */
+
+static
+regex_grow_registers (num_regs)
+ int num_regs;
+{
+ if (num_regs > regs_allocated_size)
+ {
+ RETALLOC_IF (regstart, num_regs, const char *);
+ RETALLOC_IF (regend, num_regs, const char *);
+ RETALLOC_IF (old_regstart, num_regs, const char *);
+ RETALLOC_IF (old_regend, num_regs, const char *);
+ RETALLOC_IF (best_regstart, num_regs, const char *);
+ RETALLOC_IF (best_regend, num_regs, const char *);
+ RETALLOC_IF (reg_info, num_regs, register_info_type);
+ RETALLOC_IF (reg_dummy, num_regs, const char *);
+ RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
+
+ regs_allocated_size = num_regs;
+ }
+}
+
+#endif /* not MATCH_MAY_ALLOCATE */
+
+static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type
+ compile_stack,
+ regnum_t regnum));
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+ Returns one of error codes defined in `regex.h', or zero for success.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate'
+ fields are set in BUFP on entry.
+
+ If it succeeds, results are put in BUFP (if it returns an error, the
+ contents of BUFP are undefined):
+ `buffer' is the compiled pattern;
+ `syntax' is set to SYNTAX;
+ `used' is set to the length of the compiled pattern;
+ `fastmap_accurate' is zero;
+ `re_nsub' is the number of subexpressions in PATTERN;
+ `not_bol' and `not_eol' are zero;
+
+ The `fastmap' and `newline_anchor' fields are neither
+ examined nor set. */
+
+/* Return, freeing storage we allocated. */
+#define FREE_STACK_RETURN(value) \
+ return (free (compile_stack.stack), value)
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+ const char *pattern;
+ size_t size;
+ reg_syntax_t syntax;
+ struct re_pattern_buffer *bufp;
+{
+ /* We fetch characters from PATTERN here. Even though PATTERN is
+ `char *' (i.e., signed), we declare these variables as unsigned, so
+ they can be reliably used as array indices. */
+ register unsigned char c, c1;
+
+ /* A random temporary spot in PATTERN. */
+ const char *p1;
+
+ /* Points to the end of the buffer, where we should append. */
+ register unsigned char *b;
+
+ /* Keeps track of unclosed groups. */
+ compile_stack_type compile_stack;
+
+ /* Points to the current (ending) position in the pattern. */
+ const char *p = pattern;
+ const char *pend = pattern + size;
+
+ /* How to translate the characters in the pattern. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell if a new exact-match
+ character can be added to that command or if the character requires
+ a new `exactn' command. */
+ unsigned char *pending_exact = 0;
+
+ /* Address of start of the most recently finished expression.
+ This tells, e.g., postfix * where to find the start of its
+ operand. Reset at the beginning of groups and alternatives. */
+ unsigned char *laststart = 0;
+
+ /* Address of beginning of regexp, or inside of last group. */
+ unsigned char *begalt;
+
+ /* Place in the uncompiled pattern (i.e., the {) to
+ which to go back if the interval is invalid. */
+ const char *beg_interval;
+
+ /* Address of the place where a forward jump should go to the end of
+ the containing expression. Each alternative of an `or' -- except the
+ last -- ends with a forward jump of this sort. */
+ unsigned char *fixup_alt_jump = 0;
+
+ /* Counts open-groups as they are encountered. Remembered for the
+ matching close-group on the compile stack, so the same register
+ number is put in the stop_memory as the start_memory. */
+ regnum_t regnum = 0;
+
+#ifdef DEBUG
+ DEBUG_PRINT1 ("\nCompiling pattern: ");
+ if (debug)
+ {
+ unsigned debug_count;
+
+ for (debug_count = 0; debug_count < size; debug_count++)
+ putchar (pattern[debug_count]);
+ putchar ('\n');
+ }
+#endif /* DEBUG */
+
+ /* Initialize the compile stack. */
+ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+ if (compile_stack.stack == NULL)
+ return REG_ESPACE;
+
+ compile_stack.size = INIT_COMPILE_STACK_SIZE;
+ compile_stack.avail = 0;
+
+ /* Initialize the pattern buffer. */
+ bufp->syntax = syntax;
+ bufp->fastmap_accurate = 0;
+ bufp->not_bol = bufp->not_eol = 0;
+
+ /* Set `used' to zero, so that if we return an error, the pattern
+ printer (for debugging) will think there's no pattern. We reset it
+ at the end. */
+ bufp->used = 0;
+
+ /* Always count groups, whether or not bufp->no_sub is set. */
+ bufp->re_nsub = 0;
+
+#if !defined (emacs) && !defined (SYNTAX_TABLE)
+ /* Initialize the syntax table. */
+ init_syntax_once ();
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ if (bufp->buffer)
+ { /* If zero allocated, but buffer is non-null, try to realloc
+ enough space. This loses if buffer's address is bogus, but
+ that is the user's responsibility. */
+ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+ }
+ else
+ { /* Caller did not allocate a buffer. Do it for them. */
+ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+ }
+ if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
+
+ bufp->allocated = INIT_BUF_SIZE;
+ }
+
+ begalt = b = bufp->buffer;
+
+ /* Loop through the uncompiled pattern until we're at the end. */
+ while (p != pend)
+ {
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '^':
+ {
+ if ( /* If at start of pattern, it's an operator. */
+ p == pattern + 1
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's come before. */
+ || at_begline_loc_p (pattern, p, syntax))
+ BUF_PUSH (begline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '$':
+ {
+ if ( /* If at end of pattern, it's an operator. */
+ p == pend
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's next. */
+ || at_endline_loc_p (p, pend, syntax))
+ BUF_PUSH (endline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '+':
+ case '?':
+ if ((syntax & RE_BK_PLUS_QM)
+ || (syntax & RE_LIMITED_OPS))
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern... */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ }
+
+ {
+ /* Are we optimizing this jump? */
+ boolean keep_string_p = false;
+
+ /* 1 means zero (many) matches is allowed. */
+ char zero_times_ok = 0, many_times_ok = 0;
+
+ /* If there is a sequence of repetition chars, collapse it
+ down to just one (the right one). We can't combine
+ interval operators with these because of, e.g., `a{2}*',
+ which should only match an even number of `a's. */
+
+ for (;;)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+
+ if (p == pend)
+ break;
+
+ PATFETCH (c);
+
+ if (c == '*'
+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+ ;
+
+ else if (syntax & RE_BK_PLUS_QM && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+
+ /* If we get here, we found another repeat character. */
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether or not zero matches is allowed
+ and also whether or not two or more matches is allowed. */
+ if (many_times_ok)
+ { /* More than one repetition is allowed, so put in at the
+ end a backward relative jump from `b' to before the next
+ jump we're going to put in below (which jumps from
+ laststart to after this jump).
+
+ But if we are at the `*' in the exact sequence `.*\n',
+ insert an unconditional jump backwards to the .,
+ instead of the beginning of the loop. This way we only
+ push a failure point once, instead of every time
+ through the loop. */
+ assert (p - 1 > pattern);
+
+ /* Allocate the space for the jump. */
+ GET_BUFFER_SPACE (3);
+
+ /* We know we are not at the first character of the pattern,
+ because laststart was nonzero. And we've already
+ incremented `p', by the way, to be the character after
+ the `*'. Do we have to do something analogous here
+ for null bytes, because of RE_DOT_NOT_NULL? */
+ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+ && zero_times_ok
+ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+ && !(syntax & RE_DOT_NEWLINE))
+ { /* We have .*\n. */
+ STORE_JUMP (jump, b, laststart);
+ keep_string_p = true;
+ }
+ else
+ /* Anything else. */
+ STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+ /* We've added more stuff to the buffer. */
+ b += 3;
+ }
+
+ /* On failure, jump from laststart to b + 3, which will be the
+ end of the buffer after this jump is inserted. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+ : on_failure_jump,
+ laststart, b + 3);
+ pending_exact = 0;
+ b += 3;
+
+ if (!zero_times_ok)
+ {
+ /* At least one repetition is required, so insert a
+ `dummy_failure_jump' before the initial
+ `on_failure_jump' instruction of the loop. This
+ effects a skip over that instruction the first time
+ we hit that loop. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+ b += 3;
+ }
+ }
+ break;
+
+
+ case '.':
+ laststart = b;
+ BUF_PUSH (anychar);
+ break;
+
+
+ case '[':
+ {
+ boolean had_char_class = false;
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ /* Ensure that we have enough space to push a charset: the
+ opcode, the length count, and the bitset; 34 bytes in all. */
+ GET_BUFFER_SPACE (34);
+
+ laststart = b;
+
+ /* We test `*p == '^' twice, instead of using an if
+ statement, so we only need one BUF_PUSH. */
+ BUF_PUSH (*p == '^' ? charset_not : charset);
+ if (*p == '^')
+ p++;
+
+ /* Remember the first position in the bracket expression. */
+ p1 = p;
+
+ /* Push the number of bytes in the bitmap. */
+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* Clear the whole map. */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* charset_not matches newline according to a syntax bit. */
+ if ((re_opcode_t) b[-2] == charset_not
+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+ SET_LIST_BIT ('\n');
+
+ /* Read in characters and ranges, setting map bits. */
+ for (;;)
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ SET_LIST_BIT (c1);
+ continue;
+ }
+
+ /* Could be the end of the bracket expression. If it's
+ not (i.e., when the bracket expression is `[]' so
+ far), the ']' character bit gets set way below. */
+ if (c == ']' && p != p1 + 1)
+ break;
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ FREE_STACK_RETURN (REG_ERANGE);
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character: if this is a hyphen not at the
+ beginning or the end of a list, then it's the range
+ operator. */
+ if (c == '-'
+ && !(p - 2 >= pattern && p[-2] == '[')
+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+ && *p != ']')
+ {
+ reg_errcode_t ret
+ = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ else if (p[0] == '-' && p[1] != ']')
+ { /* This handles ranges made up of characters only. */
+ reg_errcode_t ret;
+
+ /* Move past the `-'. */
+ PATFETCH (c1);
+
+ ret = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ /* See if we're at the beginning of a possible character
+ class. */
+
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+ { /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[:'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if (c == ':' || c == ']' || p == pend
+ || c1 == CHAR_CLASS_MAX_LENGTH)
+ break;
+ str[c1++] = c;
+ }
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and:`]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but set bits for them). */
+ if (c == ':' && *p == ']')
+ {
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_upper = STREQ (str, "upper");
+ wctype_t wt;
+ int ch;
+
+ wt = wctype (str);
+ if (wt == 0)
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+ {
+ if (iswctype (btowc (ch), wt))
+ SET_LIST_BIT (ch);
+
+ if (translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+
+ had_char_class = true;
+#else
+ int ch;
+ boolean is_alnum = STREQ (str, "alnum");
+ boolean is_alpha = STREQ (str, "alpha");
+ boolean is_blank = STREQ (str, "blank");
+ boolean is_cntrl = STREQ (str, "cntrl");
+ boolean is_digit = STREQ (str, "digit");
+ boolean is_graph = STREQ (str, "graph");
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_print = STREQ (str, "print");
+ boolean is_punct = STREQ (str, "punct");
+ boolean is_space = STREQ (str, "space");
+ boolean is_upper = STREQ (str, "upper");
+ boolean is_xdigit = STREQ (str, "xdigit");
+
+ if (!IS_CHAR_CLASS (str))
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ /* This was split into 3 if's to
+ avoid an arbitrary limit in some compiler. */
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ if ( translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+#endif /* libc || wctype.h */
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT (':');
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ had_char_class = false;
+ SET_LIST_BIT (c);
+ }
+ }
+
+ /* Discard any (non)matching list bytes that are all 0 at the
+ end of the map. Decrease the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ }
+ break;
+
+
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_open;
+ else
+ goto normal_char;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_close;
+ else
+ goto normal_char;
+
+
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '|':
+ if (syntax & RE_NO_BK_VBAR)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '{':
+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+ goto handle_interval;
+ else
+ goto normal_char;
+
+
+ case '\\':
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW (c);
+
+ switch (c)
+ {
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto normal_backslash;
+
+ handle_open:
+ bufp->re_nsub++;
+ regnum++;
+
+ if (COMPILE_STACK_FULL)
+ {
+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
+ compile_stack_elt_t);
+ if (compile_stack.stack == NULL) return REG_ESPACE;
+
+ compile_stack.size <<= 1;
+ }
+
+ /* These are the values to restore when we hit end of this
+ group. They are all relative offsets, so that if the
+ whole pattern moves because of realloc, they will still
+ be valid. */
+ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+ COMPILE_STACK_TOP.fixup_alt_jump
+ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+ COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+ COMPILE_STACK_TOP.regnum = regnum;
+
+ /* We will eventually replace the 0 with the number of
+ groups inner to this one. But do not push a
+ start_memory for groups beyond the last one we can
+ represent in the compiled pattern. */
+ if (regnum <= MAX_REGNUM)
+ {
+ COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+ BUF_PUSH_3 (start_memory, regnum, 0);
+ }
+
+ compile_stack.avail++;
+
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+ break;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+ if (COMPILE_STACK_EMPTY)
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_backslash;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+
+ handle_close:
+ if (fixup_alt_jump)
+ { /* Push a dummy failure point at the end of the
+ alternative for a possible future
+ `pop_failure_jump' to pop. See comments at
+ `push_dummy_failure' in `re_match_2'. */
+ BUF_PUSH (push_dummy_failure);
+
+ /* We allocated space for this jump when we assigned
+ to `fixup_alt_jump', in the `handle_alt' case below. */
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+ }
+
+ /* See similar code for backslashed left paren above. */
+ if (COMPILE_STACK_EMPTY)
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+
+ /* Since we just checked for an empty stack above, this
+ ``can't happen''. */
+ assert (compile_stack.avail != 0);
+ {
+ /* We don't just want to restore into `regnum', because
+ later groups should continue to be numbered higher,
+ as in `(ab)c(de)' -- the second group is #2. */
+ regnum_t this_group_regnum;
+
+ compile_stack.avail--;
+ begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+ fixup_alt_jump
+ = COMPILE_STACK_TOP.fixup_alt_jump
+ ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+ : 0;
+ laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+ this_group_regnum = COMPILE_STACK_TOP.regnum;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+
+ /* We're at the end of the group, so now we know how many
+ groups were inside this one. */
+ if (this_group_regnum <= MAX_REGNUM)
+ {
+ unsigned char *inner_group_loc
+ = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+
+ *inner_group_loc = regnum - this_group_regnum;
+ BUF_PUSH_3 (stop_memory, this_group_regnum,
+ regnum - this_group_regnum);
+ }
+ }
+ break;
+
+
+ case '|': /* `\|'. */
+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+ goto normal_backslash;
+ handle_alt:
+ if (syntax & RE_LIMITED_OPS)
+ goto normal_char;
+
+ /* Insert before the previous alternative a jump which
+ jumps to this alternative if the former fails. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (on_failure_jump, begalt, b + 6);
+ pending_exact = 0;
+ b += 3;
+
+ /* The alternative before this one has a jump after it
+ which gets executed if it gets matched. Adjust that
+ jump so it will jump to this alternative's analogous
+ jump (put in below, which in turn will jump to the next
+ (if any) alternative's such jump, etc.). The last such
+ jump jumps to the correct final destination. A picture:
+ _____ _____
+ | | | |
+ | v | v
+ a | b | c
+
+ If we are at `b', then fixup_alt_jump right now points to a
+ three-byte space after `a'. We'll put in the jump, set
+ fixup_alt_jump to right after `b', and leave behind three
+ bytes which we'll fill in when we get to after `c'. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ /* Mark and leave space for a jump after this alternative,
+ to be filled in later either by next alternative or
+ when know we're at the end of a series of alternatives. */
+ fixup_alt_jump = b;
+ GET_BUFFER_SPACE (3);
+ b += 3;
+
+ laststart = 0;
+ begalt = b;
+ break;
+
+
+ case '{':
+ /* If \{ is a literal. */
+ if (!(syntax & RE_INTERVALS)
+ /* If we're at `\{' and it's not the open-interval
+ operator. */
+ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+ || (p - 2 == pattern && p == pend))
+ goto normal_backslash;
+
+ handle_interval:
+ {
+ /* If got here, then the syntax allows intervals. */
+
+ /* At least (most) this many matches must be made. */
+ int lower_bound = -1, upper_bound = -1;
+
+ beg_interval = p - 1;
+
+ if (p == pend)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_EBRACE);
+ }
+
+ GET_UNSIGNED_NUMBER (lower_bound);
+
+ if (c == ',')
+ {
+ GET_UNSIGNED_NUMBER (upper_bound);
+ if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+ }
+ else
+ /* Interval such as `{1}' => match exactly once. */
+ upper_bound = lower_bound;
+
+ if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+ || lower_bound > upper_bound)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
+
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ /* We just parsed a valid interval. */
+
+ /* If it's invalid to have no preceding re. */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (syntax & RE_CONTEXT_INDEP_OPS)
+ laststart = b;
+ else
+ goto unfetch_interval;
+ }
+
+ /* If the upper bound is zero, don't want to succeed at
+ all; jump from `laststart' to `b + 3', which will be
+ the end of the buffer after we insert the jump. */
+ if (upper_bound == 0)
+ {
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (jump, laststart, b + 3);
+ b += 3;
+ }
+
+ /* Otherwise, we have a nontrivial interval. When
+ we're all done, the pattern will look like:
+ set_number_at <jump count> <upper bound>
+ set_number_at <succeed_n count> <lower bound>
+ succeed_n <after jump addr> <succeed_n count>
+ <body of loop>
+ jump_n <succeed_n addr> <jump count>
+ (The upper bound and `jump_n' are omitted if
+ `upper_bound' is 1, though.) */
+ else
+ { /* If the upper bound is > 1, we need to insert
+ more at the end of the loop. */
+ unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+ GET_BUFFER_SPACE (nbytes);
+
+ /* Initialize lower bound of the `succeed_n', even
+ though it will be set during matching by its
+ attendant `set_number_at' (inserted next),
+ because `re_compile_fastmap' needs to know.
+ Jump to the `jump_n' we might insert below. */
+ INSERT_JUMP2 (succeed_n, laststart,
+ b + 5 + (upper_bound > 1) * 5,
+ lower_bound);
+ b += 5;
+
+ /* Code to initialize the lower bound. Insert
+ before the `succeed_n'. The `5' is the last two
+ bytes of this `set_number_at', plus 3 bytes of
+ the following `succeed_n'. */
+ insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+ b += 5;
+
+ if (upper_bound > 1)
+ { /* More than one repetition is allowed, so
+ append a backward jump to the `succeed_n'
+ that starts this interval.
+
+ When we've reached this during matching,
+ we'll have matched the interval once, so
+ jump back only `upper_bound - 1' times. */
+ STORE_JUMP2 (jump_n, b, laststart + 5,
+ upper_bound - 1);
+ b += 5;
+
+ /* The location we want to set is the second
+ parameter of the `jump_n'; that is `b-2' as
+ an absolute address. `laststart' will be
+ the `set_number_at' we're about to insert;
+ `laststart+3' the number to set, the source
+ for the relative address. But we are
+ inserting into the middle of the pattern --
+ so everything is getting moved up by 5.
+ Conclusion: (b - 2) - (laststart + 3) + 5,
+ i.e., b - laststart.
+
+ We insert this at the beginning of the loop
+ so that if we fail during matching, we'll
+ reinitialize the bounds. */
+ insert_op2 (set_number_at, laststart, b - laststart,
+ upper_bound - 1, b);
+ b += 5;
+ }
+ }
+ pending_exact = 0;
+ beg_interval = NULL;
+ }
+ break;
+
+ unfetch_interval:
+ /* If an invalid interval, match the characters as literals. */
+ assert (beg_interval);
+ p = beg_interval;
+ beg_interval = NULL;
+
+ /* normal_char and normal_backslash need `c'. */
+ PATFETCH (c);
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (p > pattern && p[-1] == '\\')
+ goto normal_backslash;
+ }
+ goto normal_char;
+
+#ifdef emacs
+ /* There is no way to specify the before_dot and after_dot
+ operators. rms says this is ok. --karl */
+ case '=':
+ BUF_PUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+
+ case 'w':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (endbuf);
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (syntax & RE_NO_BK_REFS)
+ goto normal_char;
+
+ c1 = c - '0';
+
+ if (c1 > regnum)
+ FREE_STACK_RETURN (REG_ESUBREG);
+
+ /* Can't back reference to a subexpression if inside of it. */
+ if (group_in_compile_stack (compile_stack, (regnum_t) c1))
+ goto normal_char;
+
+ laststart = b;
+ BUF_PUSH_2 (duplicate, c1);
+ break;
+
+
+ case '+':
+ case '?':
+ if (syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+ else
+ goto normal_backslash;
+
+ default:
+ normal_backslash:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ c = TRANSLATE (c);
+ goto normal_char;
+ }
+ break;
+
+
+ default:
+ /* Expects the character in `c'. */
+ normal_char:
+ /* If no exactn currently being built. */
+ if (!pending_exact
+
+ /* If last exactn not at current position. */
+ || pending_exact + *pending_exact + 1 != b
+
+ /* We have only one byte following the exactn for the count. */
+ || *pending_exact == (1 << BYTEWIDTH) - 1
+
+ /* If followed by a repetition operator. */
+ || *p == '*' || *p == '^'
+ || ((syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?'))
+ || ((syntax & RE_INTERVALS)
+ && ((syntax & RE_NO_BK_BRACES)
+ ? *p == '{'
+ : (p[0] == '\\' && p[1] == '{'))))
+ {
+ /* Start building a new exactn. */
+
+ laststart = b;
+
+ BUF_PUSH_2 (exactn, 0);
+ pending_exact = b - 1;
+ }
+
+ BUF_PUSH (c);
+ (*pending_exact)++;
+ break;
+ } /* switch (c) */
+ } /* while p != pend */
+
+
+ /* Through the pattern now. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ if (!COMPILE_STACK_EMPTY)
+ FREE_STACK_RETURN (REG_EPAREN);
+
+ /* If we don't want backtracking, force success
+ the first time we reach the end of the compiled pattern. */
+ if (syntax & RE_NO_POSIX_BACKTRACKING)
+ BUF_PUSH (succeed);
+
+ free (compile_stack.stack);
+
+ /* We have succeeded; set the length of the buffer. */
+ bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+ if (debug)
+ {
+ DEBUG_PRINT1 ("\nCompiled pattern: \n");
+ print_compiled_pattern (bufp);
+ }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+ /* Initialize the failure stack to the largest possible stack. This
+ isn't necessary unless we're trying to avoid calling alloca in
+ the search and match routines. */
+ {
+ int num_regs = bufp->re_nsub + 1;
+
+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+ is strictly greater than re_max_failures, the largest possible stack
+ is 2 * re_max_failures failure points. */
+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+ {
+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+#ifdef emacs
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) xmalloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+#else /* not emacs */
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) malloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) realloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+#endif /* not emacs */
+ }
+
+ regex_grow_registers (num_regs);
+ }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+ return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'. */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG. */
+
+static void
+store_op1 (op, loc, arg)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg1);
+ STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+ for OP followed by two-byte integer parameter ARG. */
+
+static void
+insert_op1 (op, loc, arg, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 3;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 5;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN. Return true if that ^ comes
+ after an alternative or a begin-subexpression. We assume there is at
+ least one character before the ^. */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+ const char *pattern, *p;
+ reg_syntax_t syntax;
+{
+ const char *prev = p - 2;
+ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+ return
+ /* After a subexpression? */
+ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+ /* After an alternative? */
+ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p. This one is for $. We assume there is
+ at least one character after the $, i.e., `P < PEND'. */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+ const char *p, *pend;
+ reg_syntax_t syntax;
+{
+ const char *next = p;
+ boolean next_backslash = *next == '\\';
+ const char *next_next = p + 1 < pend ? p + 1 : 0;
+
+ return
+ /* Before a subexpression? */
+ (syntax & RE_NO_BK_PARENS ? *next == ')'
+ : next_backslash && next_next && *next_next == ')')
+ /* Before an alternative? */
+ || (syntax & RE_NO_BK_VBAR ? *next == '|'
+ : next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+ false if it's not. */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+ compile_stack_type compile_stack;
+ regnum_t regnum;
+{
+ int this_element;
+
+ for (this_element = compile_stack.avail - 1;
+ this_element >= 0;
+ this_element--)
+ if (compile_stack.stack[this_element].regnum == regnum)
+ return true;
+
+ return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+ uncompiled pattern *P_PTR (which ends at PEND). We assume the
+ starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
+ Then we set the translation of all bits between the starting and
+ ending characters (inclusive) in the compiled pattern B.
+
+ Return an error code.
+
+ We use these short variable names so we can use the same macros as
+ `regex_compile' itself. */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+ const char **p_ptr, *pend;
+ RE_TRANSLATE_TYPE translate;
+ reg_syntax_t syntax;
+ unsigned char *b;
+{
+ unsigned this_char;
+
+ const char *p = *p_ptr;
+ unsigned int range_start, range_end;
+
+ if (p == pend)
+ return REG_ERANGE;
+
+ /* Even though the pattern is a signed `char *', we need to fetch
+ with unsigned char *'s; if the high bit of the pattern character
+ is set, the range endpoints will be negative if we fetch using a
+ signed char *.
+
+ We also want to fetch the endpoints without translating them; the
+ appropriate translation is done in the bit-setting loop below. */
+ /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */
+ range_start = ((const unsigned char *) p)[-2];
+ range_end = ((const unsigned char *) p)[0];
+
+ /* Have to increment the pointer into the pattern string, so the
+ caller isn't still at the ending character. */
+ (*p_ptr)++;
+
+ /* If the start is after the end, the range is empty. */
+ if (range_start > range_end)
+ return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+ /* Here we see why `this_char' has to be larger than an `unsigned
+ char' -- the range is inclusive, so if `range_end' == 0xff
+ (assuming 8-bit characters), we would otherwise go into an infinite
+ loop, since all characters <= 0xff. */
+ for (this_char = range_start; this_char <= range_end; this_char++)
+ {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ }
+
+ return REG_NOERROR;
+}
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
+ characters can start a string that matches the pattern. This fastmap
+ is used by re_search to skip quickly over impossible starting points.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+ area as BUFP->fastmap.
+
+ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+ the pattern buffer.
+
+ Returns 0 if we succeed, -2 if an internal error. */
+
+int
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+ fail_stack_type fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+
+ register char *fastmap = bufp->fastmap;
+ unsigned char *pattern = bufp->buffer;
+ unsigned char *p = pattern;
+ register unsigned char *pend = pattern + bufp->used;
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* Assume that each path through the pattern can be null until
+ proven otherwise. We set this false at the bottom of switch
+ statement, to which we get only if a particular path doesn't
+ match the empty string. */
+ boolean path_can_be_null = true;
+
+ /* We aren't doing a `succeed_n' to begin with. */
+ boolean succeed_n_p = false;
+
+ assert (fastmap != NULL && p != NULL);
+
+ INIT_FAIL_STACK ();
+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
+ bufp->fastmap_accurate = 1; /* It will be when we're done. */
+ bufp->can_be_null = 0;
+
+ while (1)
+ {
+ if (p == pend || *p == succeed)
+ {
+ /* We have reached the (effective) end of pattern. */
+ if (!FAIL_STACK_EMPTY ())
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail].pointer;
+
+ continue;
+ }
+ else
+ break;
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+
+ /* I guess the idea here is to simply not bother with a fastmap
+ if a backreference is used, since it's too hard to figure out
+ the fastmap for the corresponding group. Setting
+ `can_be_null' stops `re_search_2' from using the fastmap, so
+ that is all we do. */
+ case duplicate:
+ bufp->can_be_null = 1;
+ goto done;
+
+
+ /* Following are the cases which match a character. These end
+ with `break'. */
+
+ case exactn:
+ fastmap[p[1]] = 1;
+ break;
+
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ fastmap[j] = 1;
+ break;
+
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed. */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ fastmap[j] = 1;
+ break;
+
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case anychar:
+ {
+ int fastmap_newline = fastmap['\n'];
+
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = fastmap_newline;
+
+ /* Return if we have already set `can_be_null'; if we have,
+ then the fastmap is irrelevant. Something's wrong here. */
+ else if (bufp->can_be_null)
+ goto done;
+
+ /* Otherwise, have to check alternative paths. */
+ break;
+ }
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ /* All cases after this match the empty string. These end with
+ `continue'. */
+
+
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ continue;
+#endif /* emacs */
+
+
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case push_dummy_failure:
+ continue;
+
+
+ case jump_n:
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+ if (j > 0)
+ continue;
+
+ /* Jump backward implies we just went through the body of a
+ loop and matched nothing. Opcode jumped to should be
+ `on_failure_jump' or `succeed_n'. Just treat it like an
+ ordinary jump. For a * loop, it has pushed its failure
+ point already; if so, discard that as redundant. */
+ if ((re_opcode_t) *p != on_failure_jump
+ && (re_opcode_t) *p != succeed_n)
+ continue;
+
+ p++;
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+
+ /* If what's on the stack is where we are now, pop it. */
+ if (!FAIL_STACK_EMPTY ()
+ && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+ fail_stack.avail--;
+
+ continue;
+
+
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ handle_on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+
+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+ end of the pattern. We don't want to push such a point,
+ since when we restore it above, entering the switch will
+ increment `p' past the end of the pattern. We don't need
+ to push such a point since we obviously won't find any more
+ fastmap entries beyond `pend'. Such a pattern can match
+ the null string, though. */
+ if (p + j < pend)
+ {
+ if (!PUSH_PATTERN_OP (p + j, fail_stack))
+ {
+ RESET_FAIL_STACK ();
+ return -2;
+ }
+ }
+ else
+ bufp->can_be_null = 1;
+
+ if (succeed_n_p)
+ {
+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
+ succeed_n_p = false;
+ }
+
+ continue;
+
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p += 2;
+
+ /* Increment p past the n for when k != 0. */
+ EXTRACT_NUMBER_AND_INCR (k, p);
+ if (k == 0)
+ {
+ p -= 4;
+ succeed_n_p = true; /* Spaghetti code alert. */
+ goto handle_on_failure_jump;
+ }
+ continue;
+
+
+ case set_number_at:
+ p += 4;
+ continue;
+
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+
+ default:
+ abort (); /* We have listed all the cases. */
+ } /* switch *p++ */
+
+ /* Getting here means we have found the possible starting
+ characters for one path of the pattern -- and that the empty
+ string does not match. We need not follow this path further.
+ Instead, look at the next alternative (remembered on the
+ stack), or quit if no more. The test at the top of the loop
+ does these things. */
+ path_can_be_null = false;
+ p = pend;
+ } /* while p */
+
+ /* Set `can_be_null' for the last path (also the first path, if the
+ pattern is empty). */
+ bufp->can_be_null |= path_can_be_null;
+
+ done:
+ RESET_FAIL_STACK ();
+ return 0;
+} /* re_compile_fastmap */
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
+ this memory for recording register information. STARTS and ENDS
+ must be allocated using the malloc library routine, and must each
+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+ struct re_pattern_buffer *bufp;
+ struct re_registers *regs;
+ unsigned num_regs;
+ regoff_t *starts, *ends;
+{
+ if (num_regs)
+ {
+ bufp->regs_allocated = REGS_REALLOCATE;
+ regs->num_regs = num_regs;
+ regs->start = starts;
+ regs->end = ends;
+ }
+ else
+ {
+ bufp->regs_allocated = REGS_UNALLOCATED;
+ regs->num_regs = 0;
+ regs->start = regs->end = (regoff_t *) 0;
+ }
+}
+
+/* Searching routines. */
+
+/* Like re_search_2, below, but only one string is specified, and
+ doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+ regs, size);
+}
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+ virtual concatenation of STRING1 and STRING2, starting first at index
+ STARTPOS, then at STARTPOS + 1, and so on.
+
+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+ RANGE is how far to scan while trying to match. RANGE = 0 means try
+ only at STARTPOS; in general, the last start tried is STARTPOS +
+ RANGE.
+
+ In REGS, return the indices of the virtual concatenation of STRING1
+ and STRING2 that matched the entire BUFP->buffer and its contained
+ subexpressions.
+
+ Do not consider matching one past the index STOP in the virtual
+ concatenation of STRING1 and STRING2.
+
+ We return either the position in the strings at which the match was
+ found, -1 if no match, or -2 if error (such as failure
+ stack overflow). */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ int range;
+ struct re_registers *regs;
+ int stop;
+{
+ int val;
+ register char *fastmap = bufp->fastmap;
+ register RE_TRANSLATE_TYPE translate = bufp->translate;
+ int total_size = size1 + size2;
+ int endpos = startpos + range;
+
+ /* Check for out-of-range STARTPOS. */
+ if (startpos < 0 || startpos > total_size)
+ return -1;
+
+ /* Fix up RANGE if it might eventually take us outside
+ the virtual concatenation of STRING1 and STRING2.
+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
+ if (endpos < 0)
+ range = 0 - startpos;
+ else if (endpos > total_size)
+ range = total_size - startpos;
+
+ /* If the search isn't to be a backwards one, don't waste time in a
+ search for a pattern that must be anchored. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+#ifdef emacs
+ /* In a forward search for something that starts with \=.
+ don't keep searching past point. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+ {
+ range = PT - startpos;
+ if (range <= 0)
+ return -1;
+ }
+#endif /* emacs */
+
+ /* Update the fastmap now if not correct already. */
+ if (fastmap && !bufp->fastmap_accurate)
+ if (re_compile_fastmap (bufp) == -2)
+ return -2;
+
+ /* Loop through the string, looking for a place to start matching. */
+ for (;;)
+ {
+ /* If a fastmap is supplied, skip quickly over characters that
+ cannot be the start of a match. If the pattern can match the
+ null string, however, we don't need to skip characters; we want
+ the first null string. */
+ if (fastmap && startpos < total_size && !bufp->can_be_null)
+ {
+ if (range > 0) /* Searching forwards. */
+ {
+ register const char *d;
+ register int lim = 0;
+ int irange = range;
+
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+ /* Written out as an if-else to avoid testing `translate'
+ inside the loop. */
+ if (translate)
+ while (range > lim
+ && !fastmap[(unsigned char)
+ translate[(unsigned char) *d++]])
+ range--;
+ else
+ while (range > lim && !fastmap[(unsigned char) *d++])
+ range--;
+
+ startpos += irange - range;
+ }
+ else /* Searching backwards. */
+ {
+ register char c = (size1 == 0 || startpos >= size1
+ ? string2[startpos - size1]
+ : string1[startpos]);
+
+ if (!fastmap[(unsigned char) TRANSLATE (c)])
+ goto advance;
+ }
+ }
+
+ /* If can't match the null string, and that's all we have left, fail. */
+ if (range >= 0 && startpos == total_size && fastmap
+ && !bufp->can_be_null)
+ return -1;
+
+ val = re_match_2_internal (bufp, string1, size1, string2, size2,
+ startpos, regs, stop);
+#ifndef REGEX_MALLOC
+#ifdef C_ALLOCA
+ alloca (0);
+#endif
+#endif
+
+ if (val >= 0)
+ return startpos;
+
+ if (val == -2)
+ return -2;
+
+ advance:
+ if (!range)
+ break;
+ else if (range > 0)
+ {
+ range--;
+ startpos++;
+ }
+ else
+ {
+ range++;
+ startpos--;
+ }
+ }
+ return -1;
+} /* re_search_2 */
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+ and `string2' into an offset from the beginning of that string. */
+#define POINTER_TO_OFFSET(ptr) \
+ (FIRST_STRING_P (ptr) \
+ ? ((regoff_t) ((ptr) - string1)) \
+ : ((regoff_t) ((ptr) - string2 + size1)))
+
+/* Macros for dealing with the split strings in re_match_2. */
+
+#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
+
+/* Call before fetching a character with *d. This switches over to
+ string2 if necessary. */
+#define PREFETCH() \
+ while (d == dend) \
+ { \
+ /* End of string2 => fail. */ \
+ if (dend == end_match_2) \
+ goto fail; \
+ /* End of string1 => advance to string2. */ \
+ d = string2; \
+ dend = end_match_2; \
+ }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+ of `string1' and `string2'. If only one string, it's `string2'. */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent. We have
+ two special cases to check for: if past the end of string1, look at
+ the first character in string2; and if before the beginning of
+ string2, look at the last character in string1. */
+#define WORDCHAR_P(d) \
+ (SYNTAX ((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
+ == Sword)
+
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
+/* Test if the character before D and the one at D differ with respect
+ to being word-constituent. */
+#define AT_WORD_BOUNDARY(d) \
+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+#endif
+
+/* Free everything we malloc. */
+#ifdef MATCH_MAY_ALLOCATE
+#define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+#define FREE_VARIABLES() \
+ do { \
+ REGEX_FREE_STACK (fail_stack.stack); \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (old_regstart); \
+ FREE_VAR (old_regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ FREE_VAR (reg_dummy); \
+ FREE_VAR (reg_info_dummy); \
+ } while (0)
+#else
+#define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints. They must not be valid
+ register values; since we have a limit of 255 registers (because
+ we use only one byte in the pattern for the register number), we can
+ use numbers larger than 255. They must differ by 1, because of
+ NUM_FAILURE_ITEMS above. And the value for the lowest register must
+ be larger than the value for the highest register, so we do not try
+ to actually save any registers when none are active. */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+/* Matching routines. */
+
+#ifndef emacs /* Emacs never uses this. */
+/* re_match is like re_match_2 except it takes only a single string. */
+
+int
+re_match (bufp, string, size, pos, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ int result = re_match_2_internal (bufp, NULL, 0, string, size,
+ pos, regs, size);
+#ifndef REGEX_MALLOC
+#ifdef C_ALLOCA
+ alloca (0);
+#endif
+#endif
+ return result;
+}
+#endif /* not emacs */
+
+static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2,
+ int len, char *translate));
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+ and SIZE2, respectively). We start matching at POS, and stop
+ matching at STOP.
+
+ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+ store offsets for the substring each group matched in REGS. See the
+ documentation for exactly how many groups we fill.
+
+ We return -1 if no match, -2 if an internal error (such as the
+ failure stack overflowing). Otherwise, we return the length of the
+ matched substring. */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ int result = re_match_2_internal (bufp, string1, size1, string2, size2,
+ pos, regs, stop);
+#ifndef REGEX_MALLOC
+#ifdef C_ALLOCA
+ alloca (0);
+#endif
+#endif
+ return result;
+}
+
+/* This is a separate function so that we can force an alloca cleanup
+ afterwards. */
+static int
+re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ /* General temporaries. */
+ int mcnt;
+ unsigned char *p1;
+
+ /* Just past the end of the corresponding string. */
+ const char *end1, *end2;
+
+ /* Pointers into string1 and string2, just past the last characters in
+ each to consider matching. */
+ const char *end_match_1, *end_match_2;
+
+ /* Where we are in the data, and the end of the current string. */
+ const char *d, *dend;
+
+ /* Where we are in the pattern, and the end of the pattern. */
+ unsigned char *p = bufp->buffer;
+ register unsigned char *pend = p + bufp->used;
+
+ /* Mark the opcode just after a start_memory, so we can test for an
+ empty subpattern when we get to the stop_memory. */
+ unsigned char *just_past_start_mem = 0;
+
+ /* We use this to map every character in the string. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further
+ down the line pushes a failure point on this stack. It consists of
+ restart, regend, and reg_info for all registers corresponding to
+ the subexpressions we're currently inside, plus the number of such
+ registers, and, finally, two char *'s. The first char * is where
+ to resume scanning the pattern; the second one is where to resume
+ scanning the strings. If the latter is zero, the failure point is
+ a ``dummy''; if a failure happens and the failure point is a dummy,
+ it gets discarded and the next next one is tried. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ fail_stack_type fail_stack;
+#endif
+#ifdef DEBUG
+ static unsigned failure_id = 0;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* We fill all the registers internally, independent of what we
+ return, for use in backreferences. The number here includes
+ an element for register zero. */
+ size_t num_regs = bufp->re_nsub + 1;
+
+ /* The currently active registers. */
+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+ /* Information on the contents of registers. These are pointers into
+ the input strings; they record just what was matched (on this
+ attempt) by a subexpression part of the pattern, that is, the
+ regnum-th regstart pointer points to where in the pattern we began
+ matching and the regnum-th regend points to right after where we
+ stopped matching the regnum-th subexpression. (The zeroth register
+ keeps track of what the whole pattern matches.) */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **regstart, **regend;
+#endif
+
+ /* If a group that's operated upon by a repetition operator fails to
+ match anything, then the register for its start will need to be
+ restored because it will have been set to wherever in the string we
+ are when we last see its open-group operator. Similarly for a
+ register's end. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **old_regstart, **old_regend;
+#endif
+
+ /* The is_active field of reg_info helps us keep track of which (possibly
+ nested) subexpressions we are currently in. The matched_something
+ field of reg_info[reg_num] helps us tell whether or not we have
+ matched any of the pattern so far this time through the reg_num-th
+ subexpression. These two fields get reset each time through any
+ loop their register is in. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ register_info_type *reg_info;
+#endif
+
+ /* The following record the register info as found in the above
+ variables when we find a match better than any we've seen before.
+ This happens as we backtrack through the failure points, which in
+ turn happens only if we have not yet matched the entire string. */
+ unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **best_regstart, **best_regend;
+#endif
+
+ /* Logically, this is `best_regend[0]'. But we don't want to have to
+ allocate space for that if we're not allocating space for anything
+ else (see below). Also, we never need info about register 0 for
+ any of the other register vectors, and it seems rather a kludge to
+ treat `best_regend' differently than the rest. So we keep track of
+ the end of the best match so far in a separate variable. We
+ initialize this to NULL so that when we backtrack the first time
+ and need to test it, it's not garbage. */
+ const char *match_end = NULL;
+
+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */
+ int set_regs_matched_done = 0;
+
+ /* Used when we pop values we don't care about. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **reg_dummy;
+ register_info_type *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+ /* Counts the total number of registers pushed. */
+ unsigned num_regs_pushed = 0;
+#endif
+
+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+ INIT_FAIL_STACK ();
+
+#ifdef MATCH_MAY_ALLOCATE
+ /* Do not bother to initialize all the register variables if there are
+ no groups in the pattern, as it takes a fair amount of time. If
+ there are groups, we include space for register 0 (the whole
+ pattern), even though we never use it, since it simplifies the
+ array indexing. We should fix this. */
+ if (bufp->re_nsub)
+ {
+ regstart = REGEX_TALLOC (num_regs, const char *);
+ regend = REGEX_TALLOC (num_regs, const char *);
+ old_regstart = REGEX_TALLOC (num_regs, const char *);
+ old_regend = REGEX_TALLOC (num_regs, const char *);
+ best_regstart = REGEX_TALLOC (num_regs, const char *);
+ best_regend = REGEX_TALLOC (num_regs, const char *);
+ reg_info = REGEX_TALLOC (num_regs, register_info_type);
+ reg_dummy = REGEX_TALLOC (num_regs, const char *);
+ reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+ if (!(regstart && regend && old_regstart && old_regend && reg_info
+ && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ else
+ {
+ /* We must initialize all our variables to NULL, so that
+ `FREE_VARIABLES' doesn't try to free them. */
+ regstart = regend = old_regstart = old_regend = best_regstart
+ = best_regend = reg_dummy = NULL;
+ reg_info = reg_info_dummy = (register_info_type *) NULL;
+ }
+#endif /* MATCH_MAY_ALLOCATE */
+
+ /* The starting position is bogus. */
+ if (pos < 0 || pos > size1 + size2)
+ {
+ FREE_VARIABLES ();
+ return -1;
+ }
+
+ /* Initialize subexpression text positions to -1 to mark ones that no
+ start_memory/stop_memory has been seen for. Also initialize the
+ register information struct. */
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = regend[mcnt]
+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+ IS_ACTIVE (reg_info[mcnt]) = 0;
+ MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ }
+
+ /* We move `string1' into `string2' if the latter's empty -- but not if
+ `string1' is null. */
+ if (size2 == 0 && string1 != NULL)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings. */
+ if (stop <= size1)
+ {
+ end_match_1 = string1 + stop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + stop - size1;
+ }
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within. `d'
+ is advanced into the following input string whenever necessary, but
+ this happens before fetching; therefore, at the beginning of the
+ loop, `d' can be pointing at the end of a string, but it cannot
+ equal `string2'. */
+ if (size1 > 0 && pos <= size1)
+ {
+ d = string1 + pos;
+ dend = end_match_1;
+ }
+ else
+ {
+ d = string2 + pos - size1;
+ dend = end_match_2;
+ }
+
+ DEBUG_PRINT1 ("The compiled pattern is:\n");
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+ DEBUG_PRINT1 ("The string to match is: `");
+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+ DEBUG_PRINT1 ("'\n");
+
+ /* This loops over pattern commands. It exits by returning from the
+ function if the match is complete, or it drops through if the match
+ fails at this starting point in the input data. */
+ for (;;)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+
+ if (p == pend)
+ { /* End of pattern means we might have succeeded. */
+ DEBUG_PRINT1 ("end of pattern ... ");
+
+ /* If we haven't matched the entire string, and we want the
+ longest match, try backtracking. */
+ if (d != end_match_2)
+ {
+ /* 1 if this match ends in the same string (string1 or string2)
+ as the best previous match. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+ /* 1 if this match is the best seen so far. */
+ boolean best_match_p;
+
+ /* AIX compiler got confused when this was combined
+ with the previous declaration. */
+ if (same_str_p)
+ best_match_p = d > match_end;
+ else
+ best_match_p = !MATCHING_IN_FIRST_STRING;
+
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set || best_match_p)
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. And if
+ last match is real best match, don't restore second
+ best one. */
+ else if (best_regs_set && !best_match_p)
+ {
+ restore_best_regs:
+ /* Restore best match. It may happen that `dend ==
+ end_match_1' while the restored d is in string2.
+ For example, the pattern `x.*y.*z' against the
+ strings `x-' and `y-z-', if the two strings are
+ not consecutive in memory. */
+ DEBUG_PRINT1 ("Restoring best registers.\n");
+
+ d = match_end;
+ dend = ((d >= string1 && d <= end1)
+ ? end_match_1 : end_match_2);
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ succeed_label:
+ DEBUG_PRINT1 ("Accepting match.\n");
+
+ /* If caller wants register contents data back, do it. */
+ if (regs && !bufp->no_sub)
+ {
+ /* Have the register data arrays been allocated? */
+ if (bufp->regs_allocated == REGS_UNALLOCATED)
+ { /* No. So allocate them with malloc. We need one
+ extra element beyond `num_regs' for the `-1' marker
+ GNU code uses. */
+ regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+ regs->start = TALLOC (regs->num_regs, regoff_t);
+ regs->end = TALLOC (regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ bufp->regs_allocated = REGS_REALLOCATE;
+ }
+ else if (bufp->regs_allocated == REGS_REALLOCATE)
+ { /* Yes. If we need more elements than were already
+ allocated, reallocate them. If we need fewer, just
+ leave it alone. */
+ if (regs->num_regs < num_regs + 1)
+ {
+ regs->num_regs = num_regs + 1;
+ RETALLOC (regs->start, regs->num_regs, regoff_t);
+ RETALLOC (regs->end, regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ }
+ else
+ {
+ /* These braces fend off a "empty body in an else-statement"
+ warning under GCC when assert expands to nothing. */
+ assert (bufp->regs_allocated == REGS_FIXED);
+ }
+
+ /* Convert the pointer data in `regstart' and `regend' to
+ indices. Register zero has to be set differently,
+ since we haven't kept track of any info for it. */
+ if (regs->num_regs > 0)
+ {
+ regs->start[0] = pos;
+ regs->end[0] = (MATCHING_IN_FIRST_STRING
+ ? ((regoff_t) (d - string1))
+ : ((regoff_t) (d - string2 + size1)));
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+ mcnt++)
+ {
+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ else
+ {
+ regs->start[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+ }
+ }
+
+ /* If the regs structure we return has more elements than
+ were in the pattern, set the extra elements to -1. If
+ we (re)allocated the registers, this is the case,
+ because we always allocate enough to have at least one
+ -1 at the end. */
+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+ nfailure_points_pushed, nfailure_points_popped,
+ nfailure_points_pushed - nfailure_points_popped);
+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+ ? string1
+ : string2 - size1);
+
+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+ FREE_VARIABLES ();
+ return mcnt;
+ }
+
+ /* Otherwise match next pattern command. */
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+ /* Ignore these. Used to ignore the n of succeed_n's which
+ currently have n == 0. */
+ case no_op:
+ DEBUG_PRINT1 ("EXECUTING no_op.\n");
+ break;
+
+ case succeed:
+ DEBUG_PRINT1 ("EXECUTING succeed.\n");
+ goto succeed_label;
+
+ /* Match the next n pattern characters exactly. The following
+ byte in the pattern defines n, and the n bytes after that
+ are the characters to match. */
+ case exactn:
+ mcnt = *p++;
+ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+ /* This is written out as an if-else so we don't waste time
+ testing `translate' inside the loop. */
+ if (translate)
+ {
+ do
+ {
+ PREFETCH ();
+ if ((unsigned char) translate[(unsigned char) *d++]
+ != (unsigned char) *p++)
+ goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH ();
+ if (*d++ != (char) *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ SET_REGS_MATCHED ();
+ break;
+
+
+ /* Match any character except possibly a newline or a null. */
+ case anychar:
+ DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+ PREFETCH ();
+
+ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+ goto fail;
+
+ SET_REGS_MATCHED ();
+ DEBUG_PRINT2 (" Matched `%d'.\n", *d);
+ d++;
+ break;
+
+
+ case charset:
+ case charset_not:
+ {
+ register unsigned char c;
+ boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+ DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+ PREFETCH ();
+ c = TRANSLATE (*d); /* The character to match. */
+
+ /* Cast to `unsigned' instead of `unsigned char' in case the
+ bit list is a full 32 bytes long. */
+ if (c < (unsigned) (*p * BYTEWIDTH)
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+ }
+
+
+ /* The beginning of a group is represented by start_memory.
+ The arguments are the register number in the next byte, and the
+ number of groups inner to this one in the next. The text
+ matched within the group is recorded (in the internal
+ registers data structure) under the register number. */
+ case start_memory:
+ DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+ /* Find out if this group can match the empty string. */
+ p1 = p; /* To send to group_match_null_string_p. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[*p])
+ = group_match_null_string_p (&p1, pend, reg_info);
+
+ /* Save the position in the string where we were the last time
+ we were at this open-group operator in case the group is
+ operated upon by a repetition operator, e.g., with `(a*)*b'
+ against `ab'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+ : regstart[*p];
+ DEBUG_PRINT2 (" old_regstart: %d\n",
+ POINTER_TO_OFFSET (old_regstart[*p]));
+
+ regstart[*p] = d;
+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+ IS_ACTIVE (reg_info[*p]) = 1;
+ MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* This is the new highest active register. */
+ highest_active_reg = *p;
+
+ /* If nothing was active before, this is the new lowest active
+ register. */
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *p;
+
+ /* Move past the register number and inner group count. */
+ p += 2;
+ just_past_start_mem = p;
+
+ break;
+
+
+ /* The stop_memory opcode represents the end of a group. Its
+ arguments are the same as start_memory's: the register
+ number, and the number of inner groups. */
+ case stop_memory:
+ DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+
+ /* We need to save the string position the last time we were at
+ this close-group operator in case the group is operated
+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+ against `aba'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regend[*p]) ? d : regend[*p]
+ : regend[*p];
+ DEBUG_PRINT2 (" old_regend: %d\n",
+ POINTER_TO_OFFSET (old_regend[*p]));
+
+ regend[*p] = d;
+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+ /* This register isn't active anymore. */
+ IS_ACTIVE (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* If this was the only register active, nothing is active
+ anymore. */
+ if (lowest_active_reg == highest_active_reg)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ { /* We must scan for the new highest active register, since
+ it isn't necessarily one less than now: consider
+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the
+ new highest active register is 1. */
+ unsigned char r = *p - 1;
+ while (r > 0 && !IS_ACTIVE (reg_info[r]))
+ r--;
+
+ /* If we end up at register zero, that means that we saved
+ the registers as the result of an `on_failure_jump', not
+ a `start_memory', and we jumped to past the innermost
+ `stop_memory'. For example, in ((.)*) we save
+ registers 1 and 2 as a result of the *, but when we pop
+ back to the second ), we are at the stop_memory 1.
+ Thus, nothing is active. */
+ if (r == 0)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ highest_active_reg = r;
+ }
+
+ /* If just failed to match something this time around with a
+ group that's operated on by a repetition operator, try to
+ force exit from the ``loop'', and restore the register
+ information for this group that we had before trying this
+ last match. */
+ if ((!MATCHED_SOMETHING (reg_info[*p])
+ || just_past_start_mem == p - 1)
+ && (p + 2) < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ p1 = p + 2;
+ mcnt = 0;
+ switch ((re_opcode_t) *p1++)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (is_a_jump_n)
+ p1 += 2;
+ break;
+
+ default:
+ /* do nothing */ ;
+ }
+ p1 += mcnt;
+
+ /* If the next operation is a jump backwards in the pattern
+ to an on_failure_jump right before the start_memory
+ corresponding to this stop_memory, exit from the loop
+ by forcing a failure after pushing on the stack the
+ on_failure_jump's jump in the pattern, and d. */
+ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+ && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+ {
+ /* If this group ever matched anything, then restore
+ what its registers were before trying this last
+ failed match, e.g., with `(a*)*b' against `ab' for
+ regstart[1], and, e.g., with `((a*)*(b*)*)*'
+ against `aba' for regend[3].
+
+ Also restore the registers for inner groups for,
+ e.g., `((a*)(b*))*' against `aba' (register 3 would
+ otherwise get trashed). */
+
+ if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+ {
+ unsigned r;
+
+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Restore this and inner groups' (if any) registers. */
+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+ r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if (old_regend[r] >= regstart[r])
+ regend[r] = old_regend[r];
+ }
+ }
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+ goto fail;
+ }
+ }
+
+ /* Move past the register number and the inner group count. */
+ p += 2;
+ break;
+
+
+ /* \<digit> has been turned into a `duplicate' command which is
+ followed by the numeric value of <digit> as the register number. */
+ case duplicate:
+ {
+ register const char *d2, *dend2;
+ int regno = *p++; /* Get which register to match against. */
+ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+ /* Can't back reference a group which we've never matched. */
+ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+ goto fail;
+
+ /* Where in input to try to start matching. */
+ d2 = regstart[regno];
+
+ /* Where to stop matching; if both the place to start and
+ the place to stop matching are in the same string, then
+ set to the place to stop, otherwise, for now have to use
+ the end of the first string. */
+
+ dend2 = ((FIRST_STRING_P (regstart[regno])
+ == FIRST_STRING_P (regend[regno]))
+ ? regend[regno] : end_match_1);
+ for (;;)
+ {
+ /* If necessary, advance to next segment in register
+ contents. */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+
+ /* End of string1 => advance to string2. */
+ d2 = string2;
+ dend2 = regend[regno];
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* If necessary, advance to next segment in data. */
+ PREFETCH ();
+
+ /* How many characters left in this segment to match. */
+ mcnt = dend - d;
+
+ /* Want how many consecutive characters we can match in
+ one shot, so, if necessary, adjust the count. */
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+
+ /* Compare that many; failure if mismatch, else move
+ past them. */
+ if (translate
+ ? bcmp_translate (d, d2, mcnt, translate)
+ : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+
+ /* Do this because we've match some characters. */
+ SET_REGS_MATCHED ();
+ }
+ }
+ break;
+
+
+ /* begline matches the empty string at the beginning of the string
+ (unless `not_bol' is set in `bufp'), and, if
+ `newline_anchor' is set, after newlines. */
+ case begline:
+ DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+ if (AT_STRINGS_BEG (d))
+ {
+ if (!bufp->not_bol) break;
+ }
+ else if (d[-1] == '\n' && bufp->newline_anchor)
+ {
+ break;
+ }
+ /* In all other cases, we fail. */
+ goto fail;
+
+
+ /* endline is the dual of begline. */
+ case endline:
+ DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+ if (AT_STRINGS_END (d))
+ {
+ if (!bufp->not_eol) break;
+ }
+
+ /* We have to ``prefetch'' the next character. */
+ else if ((d == end1 ? *string2 : *d) == '\n'
+ && bufp->newline_anchor)
+ {
+ break;
+ }
+ goto fail;
+
+
+ /* Match at the very beginning of the data. */
+ case begbuf:
+ DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+ if (AT_STRINGS_BEG (d))
+ break;
+ goto fail;
+
+
+ /* Match at the very end of the data. */
+ case endbuf:
+ DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+ if (AT_STRINGS_END (d))
+ break;
+ goto fail;
+
+
+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It
+ pushes NULL as the value for the string on the stack. Then
+ `pop_failure_point' will keep the current value for the
+ string, instead of restoring it. To see why, consider
+ matching `foo\nbar' against `.*\n'. The .* matches the foo;
+ then the . fails against the \n. But the next thing we want
+ to do is match the \n against the \n; if we restored the
+ string value, we would be back at the foo.
+
+ Because this is used only in specific cases, we don't need to
+ check all the things that `on_failure_jump' does, to make
+ sure the right things get saved on the stack. Hence we don't
+ share its code. The only reason to push anything on the
+ stack at all is that otherwise we would have to change
+ `anychar's code to do something besides goto fail in this
+ case; that seems worse than this. */
+ case on_failure_keep_string_jump:
+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
+
+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+ break;
+
+
+ /* Uses of on_failure_jump:
+
+ Each alternative starts with an on_failure_jump that points
+ to the beginning of the next alternative. Each alternative
+ except the last ends with a jump that in effect jumps past
+ the rest of the alternatives. (They really jump to the
+ ending jump of the following alternative, because tensioning
+ these jumps is a hassle.)
+
+ Repeats start with an on_failure_jump that points past both
+ the repetition text and either the following jump or
+ pop_failure_jump back to this on_failure_jump. */
+ case on_failure_jump:
+ on_failure:
+ DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
+
+ /* If this on_failure_jump comes right before a group (i.e.,
+ the original * applied to a group), save the information
+ for that group and all inner ones, so that if we fail back
+ to this point, the group's information will be correct.
+ For example, in \(a*\)*\1, we need the preceding group,
+ and in \(zz\(a*\)b*\)\2, we need the inner group. */
+
+ /* We can't use `p' to check ahead because we push
+ a failure point to `p + mcnt' after we do this. */
+ p1 = p;
+
+ /* We need to skip no_op's before we look for the
+ start_memory in case this on_failure_jump is happening as
+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+ against aba. */
+ while (p1 < pend && (re_opcode_t) *p1 == no_op)
+ p1++;
+
+ if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+ {
+ /* We have a new highest active register now. This will
+ get reset at the start_memory we are about to get to,
+ but we will have saved all the registers relevant to
+ this repetition op, as described above. */
+ highest_active_reg = *(p1 + 1) + *(p1 + 2);
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *(p1 + 1);
+ }
+
+ DEBUG_PRINT1 (":\n");
+ PUSH_FAILURE_POINT (p + mcnt, d, -2);
+ break;
+
+
+ /* A smart repeat ends with `maybe_pop_jump'.
+ We change it to either `pop_failure_jump' or `jump'. */
+ case maybe_pop_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+ {
+ register unsigned char *p2 = p;
+
+ /* Compare the beginning of the repeat with what in the
+ pattern follows its end. If we can establish that there
+ is nothing that they would both match, i.e., that we
+ would have to backtrack because of (as in, e.g., `a*a')
+ then we can change to pop_failure_jump, because we'll
+ never have to backtrack.
+
+ This is not true in the case of alternatives: in
+ `(a|ab)*' we do need to backtrack to the `ab' alternative
+ (e.g., if the string was `ab'). But instead of trying to
+ detect that here, the alternative has put on a dummy
+ failure point which is what we will end up popping. */
+
+ /* Skip over open/close-group commands.
+ If what follows this loop is a ...+ construct,
+ look at what begins its body, since we will have to
+ match at least one of that. */
+ while (1)
+ {
+ if (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3;
+ else if (p2 + 6 < pend
+ && (re_opcode_t) *p2 == dummy_failure_jump)
+ p2 += 6;
+ else
+ break;
+ }
+
+ p1 = p + mcnt;
+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+ to the `maybe_finalize_jump' of this case. Examine what
+ follows. */
+
+ /* If we're at the end of the pattern, we can change. */
+ if (p2 == pend)
+ {
+ /* Consider what happens when matching ":\(.*\)"
+ against ":/". I don't really understand this code
+ yet. */
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1
+ (" End of pattern: change to `pop_failure_jump'.\n");
+ }
+
+ else if ((re_opcode_t) *p2 == exactn
+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+ {
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+
+ if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset
+ || (re_opcode_t) p1[3] == charset_not)
+ {
+ int not = (re_opcode_t) p1[3] == charset_not;
+
+ if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ /* `not' is equal to 1 if c would match, which means
+ that we can't change to pop_failure_jump. */
+ if (!not)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ else if ((re_opcode_t) *p2 == charset)
+ {
+#ifdef DEBUG
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+#endif
+
+#if 0
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+ && (p2[2 + p1[5] / BYTEWIDTH]
+ & (1 << (p1[5] % BYTEWIDTH)))))
+#else
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
+ && (p2[2 + p1[4] / BYTEWIDTH]
+ & (1 << (p1[4] % BYTEWIDTH)))))
+#endif
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset_not)
+ {
+ int idx;
+ /* We win if the charset_not inside the loop
+ lists every character listed in the charset after. */
+ for (idx = 0; idx < (int) p2[1]; idx++)
+ if (! (p2[2 + idx] == 0
+ || (idx < (int) p1[4]
+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+ break;
+
+ if (idx == p2[1])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ else if ((re_opcode_t) p1[3] == charset)
+ {
+ int idx;
+ /* We win if the charset inside the loop
+ has no overlap with the one after the loop. */
+ for (idx = 0;
+ idx < (int) p2[1] && idx < (int) p1[4];
+ idx++)
+ if ((p2[2 + idx] & p1[5 + idx]) != 0)
+ break;
+
+ if (idx == p2[1] || idx == p1[4])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ }
+ p -= 2; /* Point at relative address again. */
+ if ((re_opcode_t) p[-1] != pop_failure_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ DEBUG_PRINT1 (" Match => jump.\n");
+ goto unconditional_jump;
+ }
+ /* Note fall through. */
+
+
+ /* The end of a simple repeat has a pop_failure_jump back to
+ its matching on_failure_jump, where the latter will push a
+ failure point. The pop_failure_jump takes off failure
+ points put on by this pop_failure_jump's matching
+ on_failure_jump; we got through the pattern to here from the
+ matching on_failure_jump, so didn't fail. */
+ case pop_failure_jump:
+ {
+ /* We need to pass separate storage for the lowest and
+ highest registers, even though we don't care about the
+ actual values. Otherwise, we will restore only one
+ register from the stack, since lowest will == highest in
+ `pop_failure_point'. */
+ active_reg_t dummy_low_reg, dummy_high_reg;
+ unsigned char *pdummy;
+ const char *sdummy;
+
+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+ POP_FAILURE_POINT (sdummy, pdummy,
+ dummy_low_reg, dummy_high_reg,
+ reg_dummy, reg_dummy, reg_info_dummy);
+ }
+ /* Note fall through. */
+
+ unconditional_jump:
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+ /* Note fall through. */
+
+ /* Unconditionally jump (without popping any failure points). */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+#ifdef _LIBC
+ DEBUG_PRINT2 ("(to %p).\n", p);
+#else
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
+ break;
+
+
+ /* We need this opcode so we can detect where alternatives end
+ in `group_match_null_string_p' et al. */
+ case jump_past_alt:
+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+ goto unconditional_jump;
+
+
+ /* Normally, the on_failure_jump pushes a failure point, which
+ then gets popped at pop_failure_jump. We will end up at
+ pop_failure_jump, also, and with a pattern of, say, `a+', we
+ are skipping over the on_failure_jump, so we have to push
+ something meaningless for pop_failure_jump to pop. */
+ case dummy_failure_jump:
+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+ /* It doesn't matter what we push for the string here. What
+ the code at `fail' tests is the value for the pattern. */
+ PUSH_FAILURE_POINT (0, 0, -2);
+ goto unconditional_jump;
+
+
+ /* At the end of an alternative, we need to push a dummy failure
+ point in case we are followed by a `pop_failure_jump', because
+ we don't want the failure point for the alternative to be
+ popped. For example, matching `(a|ab)*' against `aab'
+ requires that we match the `ab' alternative. */
+ case push_dummy_failure:
+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+ /* See comments just above at `dummy_failure_jump' about the
+ two zeroes. */
+ PUSH_FAILURE_POINT (0, 0, -2);
+ break;
+
+ /* Have to succeed matching what follows at least n times.
+ After that, handle like `on_failure_jump'. */
+ case succeed_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+ assert (mcnt >= 0);
+ /* Originally, this is how many times we HAVE to succeed. */
+ if (mcnt > 0)
+ {
+ mcnt--;
+ p += 2;
+ STORE_NUMBER_AND_INCR (p, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt);
+#endif
+ }
+ else if (mcnt == 0)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2);
+#else
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
+#endif
+ p[2] = (unsigned char) no_op;
+ p[3] = (unsigned char) no_op;
+ goto on_failure;
+ }
+ break;
+
+ case jump_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt)
+ {
+ mcnt--;
+ STORE_NUMBER (p + 2, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt);
+#endif
+ goto unconditional_jump;
+ }
+ /* If don't have to jump any more, skip over the rest of command. */
+ else
+ p += 4;
+ break;
+
+ case set_number_at:
+ {
+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ p1 = p + mcnt;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+#endif
+ STORE_NUMBER (p1, mcnt);
+ break;
+ }
+
+#if 0
+ /* The DEC Alpha C compiler 3.x generates incorrect code for the
+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the
+ macro and introducing temporary variables works around the bug. */
+
+ case wordbound:
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ break;
+ goto fail;
+
+ case notwordbound:
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ goto fail;
+ break;
+#else
+ case wordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ break;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ break;
+ goto fail;
+ }
+
+ case notwordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ goto fail;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ goto fail;
+ break;
+ }
+#endif
+
+ case wordbeg:
+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+ if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+ break;
+ goto fail;
+
+ case wordend:
+ DEBUG_PRINT1 ("EXECUTING wordend.\n");
+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+ && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) != point)
+ goto fail;
+ break;
+
+ case after_dot:
+ DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+ goto fail;
+ break;
+
+ case syntaxspec:
+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchsyntax;
+
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+ mcnt = (int) Sword;
+ matchsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+ case notsyntaxspec:
+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchnotsyntax;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+ mcnt = (int) Sword;
+ matchnotsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+#else /* not emacs */
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+ PREFETCH ();
+ if (!WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+ PREFETCH ();
+ if (WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+#endif /* not emacs */
+
+ default:
+ abort ();
+ }
+ continue; /* Successfully executed one pattern command; keep going. */
+
+
+ /* We goto here if a matching operation fails. */
+ fail:
+ if (!FAIL_STACK_EMPTY ())
+ { /* A restart point is known. Restore to that state. */
+ DEBUG_PRINT1 ("\nFAIL:\n");
+ POP_FAILURE_POINT (d, p,
+ lowest_active_reg, highest_active_reg,
+ regstart, regend, reg_info);
+
+ /* If this failure point is a dummy, try the next one. */
+ if (!p)
+ goto fail;
+
+ /* If we failed to the end of the pattern, don't examine *p. */
+ assert (p <= pend);
+ if (p < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ /* If failed to a backwards jump that's part of a repetition
+ loop, need to pop this failure point and use the next one. */
+ switch ((re_opcode_t) *p)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case maybe_pop_jump:
+ case pop_failure_jump:
+ case jump:
+ p1 = p + 1;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+
+ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+ || (!is_a_jump_n
+ && (re_opcode_t) *p1 == on_failure_jump))
+ goto fail;
+ break;
+ default:
+ /* do nothing */ ;
+ }
+ }
+
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else
+ break; /* Matching at this starting point really fails. */
+ } /* for (;;) */
+
+ if (best_regs_set)
+ goto restore_best_regs;
+
+ FREE_VARIABLES ();
+
+ return -1; /* Failure to match. */
+} /* re_match_2 */
+
+/* Subroutine definitions for re_match_2. */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+ Return true if the pattern up to the corresponding stop_memory can
+ match the empty string, and false otherwise.
+
+ If we find the matching stop_memory, sets P to point to one past its number.
+ Otherwise, sets P to an undefined byte less than or equal to END.
+
+ We don't handle duplicates properly (yet). */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ /* Point to after the args to the start_memory. */
+ unsigned char *p1 = *p + 2;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and return true or
+ false, as appropriate, when we get to one that can't, or to the
+ matching stop_memory. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* Could be either a loop or a series of alternatives. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ /* If the next operation is not a jump backwards in the
+ pattern. */
+
+ if (mcnt >= 0)
+ {
+ /* Go through the on_failure_jumps of the alternatives,
+ seeing if any of the alternatives cannot match nothing.
+ The last alternative starts with only a jump,
+ whereas the rest start with on_failure_jump and end
+ with a jump, e.g., here is the pattern for `a|b|c':
+
+ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+ /exactn/1/c
+
+ So, we have to first go through the first (n-1)
+ alternatives and then deal with the last one separately. */
+
+
+ /* Deal with the first (n-1) alternatives, which start
+ with an on_failure_jump (see above) that jumps to right
+ past a jump_past_alt. */
+
+ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+ {
+ /* `mcnt' holds how many bytes long the alternative
+ is, including the ending `jump_past_alt' and
+ its number. */
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
+ reg_info))
+ return false;
+
+ /* Move to right after this alternative, including the
+ jump_past_alt. */
+ p1 += mcnt;
+
+ /* Break if it's the beginning of an n-th alternative
+ that doesn't begin with an on_failure_jump. */
+ if ((re_opcode_t) *p1 != on_failure_jump)
+ break;
+
+ /* Still have to check that it's not an n-th
+ alternative that starts with an on_failure_jump. */
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+ {
+ /* Get to the beginning of the n-th alternative. */
+ p1 -= 3;
+ break;
+ }
+ }
+
+ /* Deal with the last alternative: go back and get number
+ of the `jump_past_alt' just before it. `mcnt' contains
+ the length of the alternative. */
+ EXTRACT_NUMBER (mcnt, p1 - 2);
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+ return false;
+
+ p1 += mcnt; /* Get past the n-th alternative. */
+ } /* if mcnt > 0 */
+ break;
+
+
+ case stop_memory:
+ assert (p1[1] == **p);
+ *p = p1 + 2;
+ return true;
+
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+ It expects P to be the first byte of a single alternative and END one
+ byte past the last. The alternative can contain groups. */
+
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+ unsigned char *p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ unsigned char *p1 = p;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and break when we get
+ to one that can't. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* It's a loop. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ break;
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+ alt_match_null_string_p.
+
+ Sets P to one after the op and its arguments, if any. */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ boolean ret;
+ int reg_no;
+ unsigned char *p1 = *p;
+
+ switch ((re_opcode_t) *p1++)
+ {
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case wordbound:
+ case notwordbound:
+#ifdef emacs
+ case before_dot:
+ case at_dot:
+ case after_dot:
+#endif
+ break;
+
+ case start_memory:
+ reg_no = *p1;
+ assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+ ret = group_match_null_string_p (&p1, end, reg_info);
+
+ /* Have to set this here in case we're checking a group which
+ contains a group and a back reference to it. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+ if (!ret)
+ return false;
+ break;
+
+ /* If this is an optimized succeed_n for zero times, make the jump. */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (mcnt >= 0)
+ p1 += mcnt;
+ else
+ return false;
+ break;
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p1 += 2;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ if (mcnt == 0)
+ {
+ p1 -= 4;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ }
+ else
+ return false;
+ break;
+
+ case duplicate:
+ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+ return false;
+ break;
+
+ case set_number_at:
+ p1 += 4;
+
+ default:
+ /* All other opcodes mean we cannot match the empty string. */
+ return false;
+ }
+
+ *p = p1;
+ return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+ bytes; nonzero otherwise. */
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ const char *s1, *s2;
+ register int len;
+ RE_TRANSLATE_TYPE translate;
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ while (len)
+ {
+ if (translate[*p1++] != translate[*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points for GNU code. */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+ compiles PATTERN (of length SIZE) and puts the result in BUFP.
+ Returns 0 if the pattern was valid, otherwise an error string.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+ are set in BUFP on entry.
+
+ We call regex_compile to do the actual compilation. */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+ const char *pattern;
+ size_t length;
+ struct re_pattern_buffer *bufp;
+{
+ reg_errcode_t ret;
+
+ /* GNU code is written to assume at least RE_NREGS registers will be set
+ (and at least one extra will be -1). */
+ bufp->regs_allocated = REGS_UNALLOCATED;
+
+ /* And GNU code determines whether or not to get register information
+ by passing null for the REGS argument to re_match, etc., not by
+ setting no_sub. */
+ bufp->no_sub = 0;
+
+ /* Match anchors at newline. */
+ bufp->newline_anchor = 1;
+
+ ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+ if (!ret)
+ return NULL;
+ return gettext (re_error_msgid[(int) ret]);
+}
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined (_REGEX_RE_COMP) || defined (_LIBC)
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+#ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+ these names if they don't use our functions, and still use
+ regcomp/regexec below without link errors. */
+weak_function
+#endif
+re_comp (s)
+ const char *s;
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return gettext ("No previous regular expression");
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ re_comp_buf.buffer = (unsigned char *) malloc (200);
+ if (re_comp_buf.buffer == NULL)
+ return gettext (re_error_msgid[(int) REG_ESPACE]);
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return gettext (re_error_msgid[(int) REG_ESPACE]);
+ }
+
+ /* Since `re_exec' always passes NULL for the `regs' argument, we
+ don't need to initialize the pattern buffer fields which affect it. */
+
+ /* Match anchors at newlines. */
+ re_comp_buf.newline_anchor = 1;
+
+ ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+ if (!ret)
+ return NULL;
+
+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
+ return (char *) gettext (re_error_msgid[(int) ret]);
+}
+
+
+int
+#ifdef _LIBC
+weak_function
+#endif
+re_exec (s)
+ const char *s;
+{
+ const int len = strlen (s);
+ return
+ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+
+#endif /* _REGEX_RE_COMP */
+
+/* POSIX.2 functions. Don't define these for Emacs. */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+ PREG is a regex_t *. We do not expect any fields to be initialized,
+ since POSIX says we shouldn't. Thus, we set
+
+ `buffer' to the compiled pattern;
+ `used' to the length of the compiled pattern;
+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
+ RE_SYNTAX_POSIX_BASIC;
+ `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+ `fastmap' and `fastmap_accurate' to zero;
+ `re_nsub' to the number of subexpressions in PATTERN.
+
+ PATTERN is the address of the pattern string.
+
+ CFLAGS is a series of bits which affect compilation.
+
+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+ use POSIX basic syntax.
+
+ If REG_NEWLINE is set, then . and [^...] don't match newline.
+ Also, regexec will try a match beginning after every newline.
+
+ If REG_ICASE is set, then we considers upper- and lowercase
+ versions of letters to be equivalent when matching.
+
+ If REG_NOSUB is set, then when PREG is passed to regexec, that
+ routine will report only success or failure, and nothing about the
+ registers.
+
+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
+ the return codes and their meanings.) */
+
+#ifdef __APPLE__
+__private_extern__
+#endif
+int
+regcomp (preg, pattern, cflags)
+ regex_t *preg;
+ const char *pattern;
+ int cflags;
+{
+ reg_errcode_t ret;
+ reg_syntax_t syntax
+ = (cflags & REG_EXTENDED) ?
+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+ /* regex_compile will allocate the space for the compiled pattern. */
+ preg->buffer = 0;
+ preg->allocated = 0;
+ preg->used = 0;
+
+ /* Don't bother to use a fastmap when searching. This simplifies the
+ REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+ characters after newlines into the fastmap. This way, we just try
+ every character. */
+ preg->fastmap = 0;
+
+ if (cflags & REG_ICASE)
+ {
+ unsigned i;
+
+ preg->translate
+ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
+ * sizeof (*(RE_TRANSLATE_TYPE)0));
+ if (preg->translate == NULL)
+ return (int) REG_ESPACE;
+
+ /* Map uppercase characters to corresponding lowercase ones. */
+ for (i = 0; i < CHAR_SET_SIZE; i++)
+ preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+ }
+ else
+ preg->translate = NULL;
+
+ /* If REG_NEWLINE is set, newlines are treated differently. */
+ if (cflags & REG_NEWLINE)
+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
+ syntax &= ~RE_DOT_NEWLINE;
+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+ /* It also changes the matching behavior. */
+ preg->newline_anchor = 1;
+ }
+ else
+ preg->newline_anchor = 0;
+
+ preg->no_sub = !!(cflags & REG_NOSUB);
+
+ /* POSIX says a null character in the pattern terminates it, so we
+ can use strlen here in compiling the pattern. */
+ ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+
+ /* POSIX doesn't distinguish between an unmatched open-group and an
+ unmatched close-group: both are REG_EPAREN. */
+ if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+ return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+ string STRING.
+
+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ least NMATCH elements, and we set them to the offsets of the
+ corresponding matched substrings.
+
+ EFLAGS specifies `execution flags' which affect matching: if
+ REG_NOTBOL is set, then ^ does not match at the beginning of the
+ string; if REG_NOTEOL is set, then $ does not match at the end.
+
+ We return 0 if we find a match and REG_NOMATCH if not. */
+
+#ifdef __APPLE__
+__private_extern__
+#endif
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+ const regex_t *preg;
+ const char *string;
+ size_t nmatch;
+ regmatch_t pmatch[];
+ int eflags;
+{
+ int ret;
+ struct re_registers regs;
+ regex_t private_preg;
+ int len = strlen (string);
+ boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+ private_preg = *preg;
+
+ private_preg.not_bol = !!(eflags & REG_NOTBOL);
+ private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+ /* The user has told us exactly how many registers to return
+ information about, via `nmatch'. We have to pass that on to the
+ matching routines. */
+ private_preg.regs_allocated = REGS_FIXED;
+
+ if (want_reg_info)
+ {
+ regs.num_regs = nmatch;
+ regs.start = TALLOC (nmatch, regoff_t);
+ regs.end = TALLOC (nmatch, regoff_t);
+ if (regs.start == NULL || regs.end == NULL)
+ return (int) REG_NOMATCH;
+ }
+
+ /* Perform the searching operation. */
+ ret = re_search (&private_preg, string, len,
+ /* start: */ 0, /* range: */ len,
+ want_reg_info ? &regs : (struct re_registers *) 0);
+
+ /* Copy the register information to the POSIX structure. */
+ if (want_reg_info)
+ {
+ if (ret >= 0)
+ {
+ unsigned r;
+
+ for (r = 0; r < nmatch; r++)
+ {
+ pmatch[r].rm_so = regs.start[r];
+ pmatch[r].rm_eo = regs.end[r];
+ }
+ }
+
+ /* If we needed the temporary register info, free the space now. */
+ free (regs.start);
+ free (regs.end);
+ }
+
+ /* We want zero return to mean success, unlike `re_search'. */
+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+ from either regcomp or regexec. We don't use PREG here. */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+ int errcode;
+ const regex_t *preg;
+ char *errbuf;
+ size_t errbuf_size;
+{
+ const char *msg;
+ size_t msg_size;
+
+ if (errcode < 0
+ || errcode >= (int) (sizeof (re_error_msgid)
+ / sizeof (re_error_msgid[0])))
+ /* Only error codes returned by the rest of the code should be passed
+ to this routine. If we are given anything else, or if other regex
+ code generates an invalid error code, then the program has a bug.
+ Dump core so we can fix it. */
+ abort ();
+
+ msg = gettext (re_error_msgid[errcode]);
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+ strncpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+ }
+ else
+ strcpy (errbuf, msg);
+ }
+
+ return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG. */
+
+#ifdef __APPLE__
+__private_extern__
+#endif
+void
+regfree (preg)
+ regex_t *preg;
+{
+ if (preg->buffer != NULL)
+ free (preg->buffer);
+ preg->buffer = NULL;
+
+ preg->allocated = 0;
+ preg->used = 0;
+
+ if (preg->fastmap != NULL)
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ preg->fastmap_accurate = 0;
+
+ if (preg->translate != NULL)
+ free (preg->translate);
+ preg->translate = NULL;
+}
+
+#endif /* not emacs */
diff --git a/contrib/awk/stamp-h.in b/contrib/awk/stamp-h.in
new file mode 100644
index 000000000000..232f054cb9fe
--- /dev/null
+++ b/contrib/awk/stamp-h.in
@@ -0,0 +1 @@
+Mon Jun 12 15:56:11 IDT 2000
diff --git a/contrib/awk/test/arynocls.awk b/contrib/awk/test/arynocls.awk
new file mode 100644
index 000000000000..724c9ac87ed3
--- /dev/null
+++ b/contrib/awk/test/arynocls.awk
@@ -0,0 +1,95 @@
+#To: bug-gnu-utils@gnu.org
+#From: Kristján Jónasson <kristjan@decode.is>
+#Subject: Gawk bug
+#Cc: arnold@gnu.org
+#
+#Hi!
+#
+#The following seems to be a bug in gawk. I have tried as I could to
+#minimize the bug-causing program, so of course it does not seem to do
+#anything useful in its present form. The error message received is:
+#
+#gawk: test.awk:15: fatal error: internal error
+#Aborted
+#
+#Note that there is an attached file that the program reads, called "a". I
+#played with the program a fair bit and my feeling is that the error is
+#related with the delete statement, and not the reading of the file and the
+#close statement. At one point I was able to remove the file reading and
+#still obtain the error. If, for example, I remove the close statement and
+#make two copies of the file instead, (reading one copy in sub1 and the
+#other in sub2), the error still occurs.
+#
+#The operating system is Red Hat Linux, version 6.0, the gawk is version
+#3.0.4, and the gawk was obtained from an rpm file gawk-3.0.4-1.i386.rpm.
+#
+#The program is:
+#
+
+# Wed Mar 8 13:41:34 IST 2000
+# ADR: modified to use INPUT, so can set it from command line.
+# When run, no output is produced, but it shouldn't core
+# dump, either.
+#
+# The program bug is to not close the file in sub2.
+
+function sub1(x) {
+# while (getline < "a" == 1) i++
+ while (getline < INPUT == 1) i++
+# close("a")
+ close(INPUT)
+}
+
+function sub2(x) {
+ i=0
+ delete y
+# while (getline < "a" == 1) z[++i] = $1
+ while (getline < INPUT == 1) z[++i] = $1
+ for(i in z) y[i] = x[i] + z[i]
+}
+
+function sub3(x, y, z) {
+ sub2(x)
+ for(i=1; i<=4; i++) z[i] = y[i]
+}
+
+BEGIN {
+ sub1(x)
+ sub2(x)
+ sub3(x, y, z)
+}
+#
+#And the data file is:
+#
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+# 32.440 3.830 3.383700000000000 10.08 298 865
+#
+#
diff --git a/contrib/awk/test/arynocls.in b/contrib/awk/test/arynocls.in
new file mode 100644
index 000000000000..8f4712c5c28b
--- /dev/null
+++ b/contrib/awk/test/arynocls.in
@@ -0,0 +1,30 @@
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
+ 32.440 3.830 3.383700000000000 10.08 298 865
diff --git a/contrib/awk/test/arynocls.ok b/contrib/awk/test/arynocls.ok
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/contrib/awk/test/arynocls.ok
diff --git a/contrib/awk/test/arysubnm.awk b/contrib/awk/test/arysubnm.awk
new file mode 100644
index 000000000000..961b54abf530
--- /dev/null
+++ b/contrib/awk/test/arysubnm.awk
@@ -0,0 +1 @@
+BEGIN { n = 11 ; foo[n] = n; print (2 <= n) }
diff --git a/contrib/awk/test/arysubnm.ok b/contrib/awk/test/arysubnm.ok
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/contrib/awk/test/arysubnm.ok
@@ -0,0 +1 @@
+1
diff --git a/contrib/awk/test/fnamedat.awk b/contrib/awk/test/fnamedat.awk
new file mode 100644
index 000000000000..33a07049cda0
--- /dev/null
+++ b/contrib/awk/test/fnamedat.awk
@@ -0,0 +1 @@
+function foo() { print foo } {foo()}
diff --git a/contrib/awk/test/fnamedat.in b/contrib/awk/test/fnamedat.in
new file mode 100644
index 000000000000..257cc5642cb1
--- /dev/null
+++ b/contrib/awk/test/fnamedat.in
@@ -0,0 +1 @@
+foo
diff --git a/contrib/awk/test/fnamedat.ok b/contrib/awk/test/fnamedat.ok
new file mode 100644
index 000000000000..0dd0ae5ad8e9
--- /dev/null
+++ b/contrib/awk/test/fnamedat.ok
@@ -0,0 +1 @@
+gawk: fnamedat.awk:1: (FILENAME=- FNR=1) fatal: can't use function name `foo' as variable or array
diff --git a/contrib/awk/test/fnparydl.awk b/contrib/awk/test/fnparydl.awk
new file mode 100644
index 000000000000..ef3a82255b35
--- /dev/null
+++ b/contrib/awk/test/fnparydl.awk
@@ -0,0 +1,31 @@
+# fnparydl.awk --- check that deleting works with arrays
+# that are parameters.
+#
+# Tue Jul 11 14:20:58 EDT 2000
+
+function delit(a, k)
+{
+ print "BEFORE LOOP"
+ for (k in a) {
+ print "DELETING KEY", k
+ delete a[k]
+ }
+ print "AFTER LOOP"
+}
+
+BEGIN {
+ for (i = 1 ; i <= 7; i++) {
+ q[i] = sprintf("element %d", i)
+ x[i] = i
+ y[i] = q[i]
+ }
+# adump(q)
+ delit(q)
+# for (i in q)
+# delete q[i]
+ j = 0;
+ for (i in q)
+ j++
+ print j, "elements still in q[]"
+# adump(q)
+}
diff --git a/contrib/awk/test/fnparydl.ok b/contrib/awk/test/fnparydl.ok
new file mode 100644
index 000000000000..26a5c3902c86
--- /dev/null
+++ b/contrib/awk/test/fnparydl.ok
@@ -0,0 +1,10 @@
+BEFORE LOOP
+DELETING KEY 4
+DELETING KEY 5
+DELETING KEY 6
+DELETING KEY 7
+DELETING KEY 1
+DELETING KEY 2
+DELETING KEY 3
+AFTER LOOP
+0 elements still in q[]
diff --git a/contrib/awk/test/funsmnam.awk b/contrib/awk/test/funsmnam.awk
new file mode 100644
index 000000000000..1e8ca50650c0
--- /dev/null
+++ b/contrib/awk/test/funsmnam.awk
@@ -0,0 +1,6 @@
+function foo( \
+ foo)
+{
+ print foo
+}
+{ foo() }
diff --git a/contrib/awk/test/funsmnam.ok b/contrib/awk/test/funsmnam.ok
new file mode 100644
index 000000000000..bc68a2f3bab7
--- /dev/null
+++ b/contrib/awk/test/funsmnam.ok
@@ -0,0 +1 @@
+gawk: funsmnam.awk:6: fatal: function `foo': can't use function name as parameter name
diff --git a/contrib/awk/test/getlnbuf.awk b/contrib/awk/test/getlnbuf.awk
new file mode 100644
index 000000000000..8a4483ef46ca
--- /dev/null
+++ b/contrib/awk/test/getlnbuf.awk
@@ -0,0 +1,18 @@
+#Date: Tue, 21 Dec 1999 16:11:07 +0100
+#From: Daniel Schnell <Daniel.Schnell.GP@icn.siemens.de>
+#To: bug-gnu-utils@gnu.org
+#CC: arnold@gnu.org
+#Subject: BUG in gawk (version 3.0.4 linux, windows): Text mangeling in between
+
+# search for "@K@CODE" segment
+
+$0 ~ /@K@CODE/ {
+ # get next record
+ getline temp
+ printf ("@K@CODE\n")
+ printf ("%s\n",temp)
+ }
+
+$0 !~ /@K@CODE/ {
+ printf ("%s\n", $0)
+ }
diff --git a/contrib/awk/test/getlnbuf.in b/contrib/awk/test/getlnbuf.in
new file mode 100644
index 000000000000..062b377f282b
--- /dev/null
+++ b/contrib/awk/test/getlnbuf.in
@@ -0,0 +1,1708 @@
+EXTRA_INFO.TYP3.EC := EC;
+EXTRA_INFO.TYP3.TEXT:= 'CONNECT_SERVICE TO OAM FAILED';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C003', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_SWERR, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+917596041
+@K@NAME
+T_ERR4_1
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+MP/NSEI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: MP/NSEI-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903219
+@K@NAME
+T_ERR4_2
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+MP/NSVCI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: MP/NSVCI-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903222
+@K@NAME
+T_ERR4_3
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+NSEI/NSVCI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: NSEI/NSVC-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903226
+@K@NAME
+TR_RESET
+@K@INSCRIPT
+RESTART_
+TNS_RESET_
+TIMER
+@K@CODE
+/* TIMER EVENT DESCRIPTOR STILL THERE */
+
+/* INITIALIZATION OF THE TIMER-EVENT-DESCRIPTOR STILL VALID */
+NSVCI_CON_PTR->.TIM_EVD_PTR->.TIMER:= TNS_RESET_MAP;
+
+/* START TIMER */
+G9PX508_START_TIMER_P
+(
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+@K@FREEZE
+924684867
+@K@NAME
+TX_AUDIT
+@K@INSCRIPT
+FOR
+AUDIT
+
+@K@NAME
+M_BLKOACKM
+@K@INSCRIPT
+NS_
+BLOCK_ACK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+
+IF
+/* 'OTHER' ALIVE NSVC TO THIS NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+THEN
+/* USE THIS 'OTHER' FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+/* NSEI TO BE USED FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+/* NSVCI TO BE USED FOR TRANSPORT */
+ELSE
+/* USE AFFECTED NSVC AGAIN FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+FI;
+
+
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D3);
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR2_NS_BLOCK_ACK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D3.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938805885
+@K@NAME
+T_RCTRUE
+@K@INSCRIPT
+RC
+=
+TRUE
+@K@CODE
+RC:= TRUE;
+
+@K@FREEZE
+922176328
+@K@NAME
+M_AC_SBVCN
+@K@INSCRIPT
+G9IBME0_
+ACT_
+SIGN_BVC_C
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME0_ACT_SIGN_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):= EVD_PTR->.KEYS.INT_ARR(0);
+TX_EVD_PTR->.KEYS.INT_ARR(1):= SIGN_BVCI;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938788211
+@K@NAME
+T_RC_EOD
+@K@INSCRIPT
+RC
+=
+END OF DATA
+
+@K@CODE
+RC:= G9IBSM4_RC_END_OF_DATA;
+
+@K@FREEZE
+921083785
+@K@NAME
+T_RC_EMP
+@K@INSCRIPT
+RC
+=
+EMPTY
+
+@K@CODE
+RC:= G9IBSM4_RC_EMPTY;
+
+@K@FREEZE
+921083757
+@K@NAME
+T_RC_ERR
+@K@INSCRIPT
+RC
+=
+ERROR
+
+@K@CODE
+RC:= G9IBSM4_RC_ERROR;
+
+@K@FREEZE
+921083731
+@K@NAME
+S_UNUSED
+@K@INSCRIPT
+G9IBSM0_
+UNUSED
+@K@CODE
+
+
+@K@FREEZE
+919416670
+@K@NAME
+TA_UNBLOCK
+@K@INSCRIPT
+START_
+TNS_UNBLOCK_
+TIMER
+@K@CODE
+/* GET TIMER-EVENT DESCRIPTOR */
+G9PB513_GET_TIMER_EV_DESCR_P
+(
+SID_GBNSVC,
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+/* INITIALIZATION OF THE TIMER-EVENT-DESCRIPTOR */
+NSVCI_CON_PTR->.TIM_EVD_PTR->.EVENT_CMD:= G9IBSE4_TO_TNS_C;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.EVENT_DESTINATION:= GBNSVC_HANDLE;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.TIMER:= TNS_UNBLOCK_MAP;
+
+/* START TIMER */
+G9PX508_START_TIMER_P
+(
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+@K@FREEZE
+924686210
+@K@NAME
+M_BLK_ACKM
+@K@INSCRIPT
+NS_
+BLOCK_ACK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D3);
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR2_NS_BLOCK_ACK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D3.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+926348442
+@K@NAME
+TA_NXTALIV
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+ALIVE'
+@K@CODE
+IF
+/* ALIVE NSVC TO THE NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+
+THEN
+/* TAKE NEXT ELEMENT IN THE LINKED LIST AS THE NEXT ALIVE NSVC */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR:=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.NEXT_ALV_NSVCI_CON_PTR;
+
+FI;
+
+@K@FREEZE
+938801086
+@K@NAME
+M_DE_CBVCN
+@K@INSCRIPT
+G9IBME2_
+DEACT_
+CELL_BVC_C
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME2_DEACT_CELL_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+TX_EVD_PTR->.KEYS.INT_ARR(1):= EVD_PTR->.ADD_DATA(3);
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+933318270
+@K@NAME
+TA_NXTRESP
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+RESPONSIBLE'
+@K@CODE
+NSEI_CON_PTR->.NEXT_RESP_NSVCI_CON_PTR:=
+ NSEI_CON_PTR->.NEXT_RESP_NSVCI_CON_PTR->.NEXT_LSP_NSVCI_CON_PTR;
+
+
+@K@FREEZE
+938005006
+@K@NAME
+TA_NXTSUBS
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+SUBSTITUTE'
+@K@CODE
+NSEI_CON_PTR->.NEXT_SUBS_NSVCI_CON_PTR:=
+ NSEI_CON_PTR->.NEXT_SUBS_NSVCI_CON_PTR->.NEXT_UBL_NSVCI_CON_PTR;
+
+@K@NAME
+M_BLK_O__M
+@K@INSCRIPT
+NS_
+BLOCK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+
+IF
+/* 'OTHER' ALIVE NSVC TO THIS NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+THEN
+/* USE THIS 'OTHER' FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+/* NSEI TO BE USED FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+/* NSVCI TO BE USED FOR TRANSPORT */
+ELSE
+/* USE AFFECTED NSVC AGAIN FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+FI;
+
+
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D2);
+
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR1_NS_BLOCK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D2.CAUSE_TLV.CAUSE_VAL:=
+ G9IBBA2_NS_TRANSIT_NETWORK_FAILURE; /* CAUSE FOR BLOCK */
+NS_PDU_PTR->.D2.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+GSM 8.16 CHAP. 7.2:
+THE NS-BLOCK-PDU MAY BE SENT IN ANY ALIVE
+(BLOCKED OR UNBLOCKED) NS-VC...
+@K@FREEZE
+938803215
+@K@NAME
+M_DE_SBVCN
+@K@INSCRIPT
+G9IBME1_
+DEACT_
+SIGN_BVC_C
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME1_DEACT_SIGN_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):= EVD_PTR->.KEYS.INT_ARR(0);
+TX_EVD_PTR->.KEYS.INT_ARR(1):= SIGN_BVCI;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938788201
+@K@NAME
+M_OAME401M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSE */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSE;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSE_ID:= EVD_PTR->.KEYS.INT_ARR(0); /*
+USED NSEI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935766108
+@K@NAME
+M_OAME402M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.KEYS.INT_ARR(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935766407
+@K@NAME
+M_OAME411M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_ACK_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSE */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSE;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSE_ID:= EVD_PTR->.KEYS.INT_ARR(0); /*
+USED NSEI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935767332
+@K@NAME
+M_OAME412M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_ACK_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.KEYS.INT_ARR(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935767189
+@K@NAME
+C_CON
+@K@INSCRIPT
+RC_DB
+@K@CODE
+RC_DB
+
+@K@FREEZE
+922176673
+@K@NAME
+M_BLK____M
+@K@INSCRIPT
+NS_
+BLOCK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D2);
+
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR1_NS_BLOCK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D2.CAUSE_TLV.CAUSE_VAL:=
+ G9IBBA2_NS_OAM_INTERVENTION; /* CAUSE FOR BLOCK */
+NS_PDU_PTR->.D2.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+GSM 8.16 CHAP. 7.2:
+THE NS-BLOCK-PDU MAY BE SENT IN ANY ALIVE
+(BLOCKED OR UNBLOCKED) NS-VC...
+@K@FREEZE
+926348613
+@K@NAME
+S_BLOCKED
+@K@INSCRIPT
+G9IBSM0_
+BLOCKED
+@K@CODE
+
+
+@K@FREEZE
+922176496
+@K@NAME
+D_CON
+@K@INSCRIPT
+CONTEXT
+GOT
+@K@CODE
+RC_DB = G9IBSR0_RC_OK
+
+@K@FREEZE
+921772339
+@K@NAME
+M_OAME901M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+UBL->BLK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_ENABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970975
+@K@NAME
+M_OAME902M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+UBL->BLK
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_DISABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970987
+@K@NAME
+M_OAME10SM
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@NAME
+M_OAME911M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+BLK->UBL
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_ENABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970996
+@K@NAME
+M_OAME20SM
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@NAME
+M_OAME10_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443813
+@K@NAME
+D_SEM
+@K@INSCRIPT
+CALL_SEM
+=
+TRUE
+@K@CODE
+CALL_SEM = TRUE
+
+@K@FREEZE
+922176624
+@K@NAME
+D_N_0
+@K@INSCRIPT
+N = 0
+
+@K@CODE
+NSVCI_CON_PTR->.N = 0
+
+@K@FREEZE
+921511000
+@K@NAME
+M_OAME12_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443829
+@K@NAME
+M_OAME21_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ FALSE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443856
+@K@NAME
+M_OAME13_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443838
+@K@NAME
+M_OAME22_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443864
+@K@NAME
+M_OAME30_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FORM_BSS
+RESET_PROCEDURE
+
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_RESET_PROCEDURE;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175973
+@K@NAME
+M_OAME31_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FROM_BSS
+BLOCK_PROCEDURE
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_BLOCK_PROCEDURE;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175976
+@K@NAME
+M_OAME32_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FROM_BSS
+UNBLOCK_PROCEDURE
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_UNBLOCK_PROCEDURE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175980
+@K@NAME
+M_OAME42_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+BLOCK_PDU
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.ADD_DATA(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_BLOCK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.KEYS.INT_ARR(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.KEYS.INT_ARR(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+934296141
+@K@NAME
+M_OAME50_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+STATUS_PDU_CONTAINS_ERROR_INFO
+RECEIVED
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR-CAUSE = STATUS_PDU_CONTAINS_ERROR_INFO */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_STATUS_PDU_CONTAINS_ERROR_INFO;
+/* ADDITIONAL_STATUS_PDU_INFO */
+INT_CAUSE_PTR.INT_PTR:= ADDR(EVD_PTR->.ADD_DATA(2));
+OAM_MSG_PTR->.ADDITIONAL_STATUS_PDU_INFO:=
+ INT_CAUSE_PTR.CAUSE_PTR->; /* CAUSE */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+NICHT OK
+
+@K@FREEZE
+934298924
+@K@NAME
+M_OAME43_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+BLOCK_ACK_PDU
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.ADD_DATA(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_BLOCK_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.KEYS.INT_ARR(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.KEYS.INT_ARR(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+934297710
diff --git a/contrib/awk/test/getlnbuf.ok b/contrib/awk/test/getlnbuf.ok
new file mode 100644
index 000000000000..062b377f282b
--- /dev/null
+++ b/contrib/awk/test/getlnbuf.ok
@@ -0,0 +1,1708 @@
+EXTRA_INFO.TYP3.EC := EC;
+EXTRA_INFO.TYP3.TEXT:= 'CONNECT_SERVICE TO OAM FAILED';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C003', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_SWERR, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+917596041
+@K@NAME
+T_ERR4_1
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+MP/NSEI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: MP/NSEI-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903219
+@K@NAME
+T_ERR4_2
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+MP/NSVCI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: MP/NSVCI-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903222
+@K@NAME
+T_ERR4_3
+@K@INSCRIPT
+ERROR_HANDLING:
+DB_OVERFLOW
+NSEI/NSVCI
+@K@CODE
+/***@@@ ERROR ***/
+/*@@ERRORTEXT
+*@ DB-OVERFLOW
+*@
+*@
+*@@DESCRIPTION
+*@ THE INSTANCE-CREATION WAS NOT POSSIBLE
+*@ BECAUSE THE DATABASE WOULD OVERFLOW
+*@
+*@@EXTRA INFO
+*@ (EXTRA_INFO_4_STRUCT)
+*@ NSEI
+*@ NSVCI
+*@ TEXT
+*@
+*/
+
+EXTRA_INFO.TYP4.NSEI := EVD_PTR->.KEYS.INT_ARR(0);
+EXTRA_INFO.TYP4.NSVCI:= EVD_PTR->.KEYS.INT_ARR(1);
+EXTRA_INFO.TYP4.TEXT := 'NSVC-HAND.: NSEI/NSVC-OVERFLOW';
+
+G9PXYA1S!G9TE500_EHP_P(
+'G9IBSA1C004', /*@@ID*/
+G9PXYA1S!G9TE102_ERR_CLASS_ESC_MAX_ANY, /*@@CLASS*/
+ADDR(EXTRA_INFO.ERROR_HANDLER), /* EXTRA-INFO ADDR */
+G9PXYA1S!G9TE100_GB_LM, /* USER-ID */
+NULL /* OPTIONAL-SWET-INFO ADDR */
+);
+/***@@@ END OF ERROR ***/
+
+@K@FREEZE
+920903226
+@K@NAME
+TR_RESET
+@K@INSCRIPT
+RESTART_
+TNS_RESET_
+TIMER
+@K@CODE
+/* TIMER EVENT DESCRIPTOR STILL THERE */
+
+/* INITIALIZATION OF THE TIMER-EVENT-DESCRIPTOR STILL VALID */
+NSVCI_CON_PTR->.TIM_EVD_PTR->.TIMER:= TNS_RESET_MAP;
+
+/* START TIMER */
+G9PX508_START_TIMER_P
+(
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+@K@FREEZE
+924684867
+@K@NAME
+TX_AUDIT
+@K@INSCRIPT
+FOR
+AUDIT
+
+@K@NAME
+M_BLKOACKM
+@K@INSCRIPT
+NS_
+BLOCK_ACK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+
+IF
+/* 'OTHER' ALIVE NSVC TO THIS NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+THEN
+/* USE THIS 'OTHER' FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+/* NSEI TO BE USED FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+/* NSVCI TO BE USED FOR TRANSPORT */
+ELSE
+/* USE AFFECTED NSVC AGAIN FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+FI;
+
+
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D3);
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR2_NS_BLOCK_ACK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D3.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938805885
+@K@NAME
+T_RCTRUE
+@K@INSCRIPT
+RC
+=
+TRUE
+@K@CODE
+RC:= TRUE;
+
+@K@FREEZE
+922176328
+@K@NAME
+M_AC_SBVCN
+@K@INSCRIPT
+G9IBME0_
+ACT_
+SIGN_BVC_C
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME0_ACT_SIGN_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):= EVD_PTR->.KEYS.INT_ARR(0);
+TX_EVD_PTR->.KEYS.INT_ARR(1):= SIGN_BVCI;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938788211
+@K@NAME
+T_RC_EOD
+@K@INSCRIPT
+RC
+=
+END OF DATA
+
+@K@CODE
+RC:= G9IBSM4_RC_END_OF_DATA;
+
+@K@FREEZE
+921083785
+@K@NAME
+T_RC_EMP
+@K@INSCRIPT
+RC
+=
+EMPTY
+
+@K@CODE
+RC:= G9IBSM4_RC_EMPTY;
+
+@K@FREEZE
+921083757
+@K@NAME
+T_RC_ERR
+@K@INSCRIPT
+RC
+=
+ERROR
+
+@K@CODE
+RC:= G9IBSM4_RC_ERROR;
+
+@K@FREEZE
+921083731
+@K@NAME
+S_UNUSED
+@K@INSCRIPT
+G9IBSM0_
+UNUSED
+@K@CODE
+
+
+@K@FREEZE
+919416670
+@K@NAME
+TA_UNBLOCK
+@K@INSCRIPT
+START_
+TNS_UNBLOCK_
+TIMER
+@K@CODE
+/* GET TIMER-EVENT DESCRIPTOR */
+G9PB513_GET_TIMER_EV_DESCR_P
+(
+SID_GBNSVC,
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+/* INITIALIZATION OF THE TIMER-EVENT-DESCRIPTOR */
+NSVCI_CON_PTR->.TIM_EVD_PTR->.EVENT_CMD:= G9IBSE4_TO_TNS_C;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.EVENT_DESTINATION:= GBNSVC_HANDLE;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+NSVCI_CON_PTR->.TIM_EVD_PTR->.TIMER:= TNS_UNBLOCK_MAP;
+
+/* START TIMER */
+G9PX508_START_TIMER_P
+(
+NSVCI_CON_PTR->.TIM_EVD_PTR
+);
+
+@K@FREEZE
+924686210
+@K@NAME
+M_BLK_ACKM
+@K@INSCRIPT
+NS_
+BLOCK_ACK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D3);
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR2_NS_BLOCK_ACK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D3.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+926348442
+@K@NAME
+TA_NXTALIV
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+ALIVE'
+@K@CODE
+IF
+/* ALIVE NSVC TO THE NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+
+THEN
+/* TAKE NEXT ELEMENT IN THE LINKED LIST AS THE NEXT ALIVE NSVC */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR:=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.NEXT_ALV_NSVCI_CON_PTR;
+
+FI;
+
+@K@FREEZE
+938801086
+@K@NAME
+M_DE_CBVCN
+@K@INSCRIPT
+G9IBME2_
+DEACT_
+CELL_BVC_C
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME2_DEACT_CELL_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+TX_EVD_PTR->.KEYS.INT_ARR(1):= EVD_PTR->.ADD_DATA(3);
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+933318270
+@K@NAME
+TA_NXTRESP
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+RESPONSIBLE'
+@K@CODE
+NSEI_CON_PTR->.NEXT_RESP_NSVCI_CON_PTR:=
+ NSEI_CON_PTR->.NEXT_RESP_NSVCI_CON_PTR->.NEXT_LSP_NSVCI_CON_PTR;
+
+
+@K@FREEZE
+938005006
+@K@NAME
+TA_NXTSUBS
+@K@INSCRIPT
+DEFINE
+NEW 'NEXT_
+SUBSTITUTE'
+@K@CODE
+NSEI_CON_PTR->.NEXT_SUBS_NSVCI_CON_PTR:=
+ NSEI_CON_PTR->.NEXT_SUBS_NSVCI_CON_PTR->.NEXT_UBL_NSVCI_CON_PTR;
+
+@K@NAME
+M_BLK_O__M
+@K@INSCRIPT
+NS_
+BLOCK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+
+IF
+/* 'OTHER' ALIVE NSVC TO THIS NSEI EXISTING? */
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR /= NULL
+THEN
+/* USE THIS 'OTHER' FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI;
+/* NSEI TO BE USED FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+
+NSVCI_CON_PTR->.OWN_NSEI_CON_PTR->.NEXT_ALIV_NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+/* NSVCI TO BE USED FOR TRANSPORT */
+ELSE
+/* USE AFFECTED NSVC AGAIN FOR TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+FI;
+
+
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D2);
+
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR1_NS_BLOCK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D2.CAUSE_TLV.CAUSE_VAL:=
+ G9IBBA2_NS_TRANSIT_NETWORK_FAILURE; /* CAUSE FOR BLOCK */
+NS_PDU_PTR->.D2.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+GSM 8.16 CHAP. 7.2:
+THE NS-BLOCK-PDU MAY BE SENT IN ANY ALIVE
+(BLOCKED OR UNBLOCKED) NS-VC...
+@K@FREEZE
+938803215
+@K@NAME
+M_DE_SBVCN
+@K@INSCRIPT
+G9IBME1_
+DEACT_
+SIGN_BVC_C
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB512_GET_MSG_LESS_EV_DESCR_P
+(
+SID_GBNSVC,
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+TX_EVD_PTR->.EVENT_CMD:= G9IBME1_DEACT_SIGN_BVC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBBVC_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):= EVD_PTR->.KEYS.INT_ARR(0);
+TX_EVD_PTR->.KEYS.INT_ARR(1):= SIGN_BVCI;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+938788201
+@K@NAME
+M_OAME401M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSE */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSE;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSE_ID:= EVD_PTR->.KEYS.INT_ARR(0); /*
+USED NSEI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935766108
+@K@NAME
+M_OAME402M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.KEYS.INT_ARR(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935766407
+@K@NAME
+M_OAME411M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_ACK_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSE */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSE;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSE_ID:= EVD_PTR->.KEYS.INT_ARR(0); /*
+USED NSEI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935767332
+@K@NAME
+M_OAME412M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+RESET_ACK_PDU
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.KEYS.INT_ARR(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_RESET_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.ADD_DATA(0); /* NSEI FROM PDU */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.ADD_DATA(1); /* NSVCI FROM PDU */
+
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+935767189
+@K@NAME
+C_CON
+@K@INSCRIPT
+RC_DB
+@K@CODE
+RC_DB
+
+@K@FREEZE
+922176673
+@K@NAME
+M_BLK____M
+@K@INSCRIPT
+NS_
+BLOCK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9IBDF4_NS_LM_M) + G9IBD44_NS_PDU_DATA_OFFSET_C),
+TX_EVD_PTR
+);
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9IBD40_NS_LM_PDU_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= GBDL_HANDLE;
+TX_EVD_PTR->.KEYS.INT_ARR(0):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSEI; /* NSEI TO BE USED FOR
+TRANSPORT */
+TX_EVD_PTR->.KEYS.INT_ARR(1):=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVCI TO BE USED FOR
+TRANSPORT */
+/* POINTER TO PDU IN POOL-ELEMENT */
+NS_PDU_PTR:= NS_PDU_REF_M (INT(TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT)
+ + G9IBD44_NS_PDU_DATA_OFFSET_C);
+/* OFFSET OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= G9IBD44_NS_PDU_DATA_OFFSET_C;
+/* LENGTH OF THE PDU IN POOL-ELEMENT */
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(NS_PDU_PTR->.G9IBDF4_PDU_TYPE) +
+SIZE(NS_PDU_PTR->.D2);
+
+
+/* NOW THE POOL-ELEMENT */
+NS_PDU_PTR->.G9IBDF4_PDU_TYPE:= G9IBDR1_NS_BLOCK_C; /* PDU-TYPE */
+
+NS_PDU_PTR->.D2.CAUSE_TLV.CAUSE_VAL:=
+ G9IBBA2_NS_OAM_INTERVENTION; /* CAUSE FOR BLOCK */
+NS_PDU_PTR->.D2.NSVCI_TLV.NSVCI_VAL :=
+ NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI; /* NSVC TO BE BLOCKED */
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+GSM 8.16 CHAP. 7.2:
+THE NS-BLOCK-PDU MAY BE SENT IN ANY ALIVE
+(BLOCKED OR UNBLOCKED) NS-VC...
+@K@FREEZE
+926348613
+@K@NAME
+S_BLOCKED
+@K@INSCRIPT
+G9IBSM0_
+BLOCKED
+@K@CODE
+
+
+@K@FREEZE
+922176496
+@K@NAME
+D_CON
+@K@INSCRIPT
+CONTEXT
+GOT
+@K@CODE
+RC_DB = G9IBSR0_RC_OK
+
+@K@FREEZE
+921772339
+@K@NAME
+M_OAME901M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+UBL->BLK
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_ENABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970975
+@K@NAME
+M_OAME902M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+UBL->BLK
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_DISABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970987
+@K@NAME
+M_OAME10SM
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@NAME
+M_OAME911M
+@K@INSCRIPT
+ERROR_MESSAGE:
+OPERATIONAL_STATE_CHANGE
+BLK->UBL
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = OPERATIONAL_STATE_CHANGE */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_OPERATIONAL_STATE_CHANGE;
+/* ADDITIONAL_OPERATIONAL_STATE_INFO */
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.OPER_STATE_NEW:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_OLD:=
+ G9OC102_ENABLED;
+OAM_MSG_PTR->.ADDITIONAL_OPERATIONAL_STATE_INFO.ADMIN_STATE_NEW:=
+ G9OC102_ENABLED;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+925970996
+@K@NAME
+M_OAME20SM
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@NAME
+M_OAME10_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443813
+@K@NAME
+D_SEM
+@K@INSCRIPT
+CALL_SEM
+=
+TRUE
+@K@CODE
+CALL_SEM = TRUE
+
+@K@FREEZE
+922176624
+@K@NAME
+D_N_0
+@K@INSCRIPT
+N = 0
+
+@K@CODE
+NSVCI_CON_PTR->.N = 0
+
+@K@FREEZE
+921511000
+@K@NAME
+M_OAME12_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443829
+@K@NAME
+M_OAME21_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ TRUE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ FALSE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443856
+@K@NAME
+M_OAME13_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_BEGIN_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_BEGIN_NS_ALIVE_TEST*/
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_BEGIN_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_UNBLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443838
+@K@NAME
+M_OAME22_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ALARM_END_NS_ALIVE_TEST
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = ALARM_END_NS_ALIVE_TEST */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ALARM_END_NS_ALIVE_TEST;
+/* ADDITIONAL_ALARM_INFO */
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.ADMINISTRATIVE_STATE_CHANGED:=
+ FALSE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_OLD:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.OPER_STATE_NEW:=
+ G9OC101_BLOCKED;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_OLD:=
+ G9OC103_DEAD;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.AVAIL_STATE_NEW:=
+ G9OC103_ALIVE;
+OAM_MSG_PTR->.ADDITIONAL_ALARM_INFO.CONFIGURATION_OF_NSVC:=
+ TRUE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922443864
+@K@NAME
+M_OAME30_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FORM_BSS
+RESET_PROCEDURE
+
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_RESET_PROCEDURE;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175973
+@K@NAME
+M_OAME31_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FROM_BSS
+BLOCK_PROCEDURE
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_BLOCK_PROCEDURE;
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175976
+@K@NAME
+M_OAME32_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+NO_ANSWER_FROM_BSS
+UNBLOCK_PROCEDURE
+
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR_CAUSE = NO_ANSWER_FROM_BSS */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_NO_ANSWER_FROM_BSS;
+/* INITIATED_PROCEDURE */
+OAM_MSG_PTR->.INITIATED_PROCEDURE:=
+ G9OC123_UNBLOCK_PROCEDURE;
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+922175980
+@K@NAME
+M_OAME42_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+BLOCK_PDU
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.ADD_DATA(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_BLOCK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.KEYS.INT_ARR(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.KEYS.INT_ARR(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+934296141
+@K@NAME
+M_OAME50_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+STATUS_PDU_CONTAINS_ERROR_INFO
+RECEIVED
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:=
+NSVCI_CON_PTR->.DBMS.NSVC_INSTANCE.NSVCI;
+
+/* ERROR-CAUSE = STATUS_PDU_CONTAINS_ERROR_INFO */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_STATUS_PDU_CONTAINS_ERROR_INFO;
+/* ADDITIONAL_STATUS_PDU_INFO */
+INT_CAUSE_PTR.INT_PTR:= ADDR(EVD_PTR->.ADD_DATA(2));
+OAM_MSG_PTR->.ADDITIONAL_STATUS_PDU_INFO:=
+ INT_CAUSE_PTR.CAUSE_PTR->; /* CAUSE */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@TEXT
+NICHT OK
+
+@K@FREEZE
+934298924
+@K@NAME
+M_OAME43_M
+@K@INSCRIPT
+ERROR_MESSAGE:
+ERRONOUS_PDU
+BLOCK_ACK_PDU
+@K@CODE
+/* GETTING THE EVENT DESCRIPTOR */
+G9PB511_GET_MSG_BOUND_EV_DESCR_P
+(
+SID_GBNSVC,
+(SIZE(G9OC109_REPORTED_EVENT_STR_M)),
+TX_EVD_PTR
+);
+
+
+/* COMPOSING THE EVENT */
+/* FIRST THE DESCRIPTOR */
+TX_EVD_PTR->.EVENT_CMD:= G9PX040_SEND_MBC_C;
+TX_EVD_PTR->.EVENT_DESTINATION:= RXTX_HANDLE;
+TX_EVD_PTR->.KEYS.UBI_INDEX:= OAM_UBI_INDEX;
+TX_EVD_PTR->.BOUND.DATA_OFFSET:= 0;
+TX_EVD_PTR->.BOUND.DATA_LENGTH:= SIZE(G9OC109_REPORTED_EVENT_STR_M);
+
+/* NOW THE POOL-ELEMENT */
+/* INITIALIZATION OF THE POINTER WITH THE POOL-ELEMENT-START */
+OAM_MSG_PTR:= OAM_MSG_PTR_M (TX_EVD_PTR->.BOUND.PTR_TO_POOL_ELEMENT);
+
+/* COMPOSING THE MESSAGE */
+/* HANDLED OBJECT = AFFECTED INSTANCE, TYPE NSVC */
+OAM_MSG_PTR->.HANDLED_OBJECT.OBJECT_TYPE:= G9OC104_NSVC;
+OAM_MSG_PTR->.HANDLED_OBJECT.NSVC_ID:= EVD_PTR->.ADD_DATA(1); /*
+USED NSVCI (FROM ECI) */
+
+/* ERROR-CAUSE = ERRONEOUS_PDU */
+OAM_MSG_PTR->.ERROR_CAUSE:= G9OC108_ERRONEOUS_PDU;
+/* ADDITIONAL_PDU_INFO */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_PDU_TYPE:=
+ G9OC124_BLOCK_ACK_PDU;
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSEI:=
+ EVD_PTR->.KEYS.INT_ARR(0); /* AFFECTED NSEI (FROM PDU) */
+OAM_MSG_PTR->.ADDITIONAL_PDU_INFO.G9OC120_REPORTED_NSVC:=
+ EVD_PTR->.KEYS.INT_ARR(1); /* AFFECTED NSVCI (FROM PDU) */
+
+
+
+/* SENDING */
+G9PX503_POST_EVENT_P(TX_EVD_PTR);
+
+@K@FREEZE
+934297710
diff --git a/contrib/awk/test/getnr2tb.awk b/contrib/awk/test/getnr2tb.awk
new file mode 100644
index 000000000000..204acf463e35
--- /dev/null
+++ b/contrib/awk/test/getnr2tb.awk
@@ -0,0 +1,111 @@
+#From vp@dmat.uevora.pt Thu Jun 18 09:10 EDT 1998
+#Received: from mescaline.gnu.org (we-refuse-to-spy-on-our-users@mescaline.gnu.org [158.121.106.21]) by cssun.mathcs.emory.edu (8.7.5/8.6.9-940818.01cssun) with ESMTP id JAA23649 for <arnold@mathcs.emory.edu>; Thu, 18 Jun 1998 09:10:54 -0400 (EDT)
+#Received: from khromeleque.dmat.uevora.pt by mescaline.gnu.org (8.8.5/8.6.12GNU) with ESMTP id JAA21732 for <arnold@gnu.ai.mit.edu>; Thu, 18 Jun 1998 09:11:19 -0400
+#Received: from khromeleque.dmat.uevora.pt (vp@localhost [127.0.0.1])
+# by khromeleque.dmat.uevora.pt (8.8.8/8.8.8/Debian/GNU) with ESMTP id OAA11817
+# for <arnold@gnu.ai.mit.edu>; Thu, 18 Jun 1998 14:13:57 +0100
+#Message-Id: <199806181313.OAA11817@khromeleque.dmat.uevora.pt>
+#To: arnold@gnu.org
+#Subject: concatenation bug in gawk 3.0.3
+#Date: Thu, 18 Jun 1998 14:13:57 +0200
+#From: Vasco Pedro <vp@dmat.uevora.pt>
+#Content-Type: text
+#Content-Length: 2285
+#Status: RO
+#
+#Hi,
+#
+#The gawk program '{print NR " " 10/NR}' will print:
+#
+#1 10
+#5 5
+#3 3.33333
+#2 2.5
+#2 2
+#1 1.66667
+#
+#instead of the correct:
+#
+#1 10
+#2 5
+#3 3.33333
+#4 2.5
+#5 2
+#6 1.66667
+#
+#You'll notice, on the incorrect output, that the first column is
+#the first digit of the second.
+#
+#I think the problem comes from the way builtin variables are handled.
+#Since the items to be concatenated are processed in reverse order and
+#the return value of tree_eval(``NR'') is a pointer to the value part
+#of `NR_node', the `unref()' of `NR_node' due to its second occurrence
+#will leave a dangling pointer in `strlist'. The reason that it doesn't
+#reuse the freed space with objects of the same type. (Using Electric
+#Fence with EF_PROTECT_FREE set confirms that freed space is being
+#accessed.)
+#
+#The enclosed patch (hack would be a better word to describe it) is
+#all I could come up with. With it installed, things seem to work ok,
+#but I doubt this is the correct way to do it. (If I treated the
+#case for `Node_field_spec' as the I did others, `make check' would
+#fail in several places.)
+#
+#Regards,
+#vasco
+#
+#*** eval.c~ Tue May 6 21:39:55 1997
+#--- eval.c Thu Jun 18 13:39:25 1998
+#***************
+#*** 685,697 ****
+# return func_call(tree->rnode, tree->lnode);
+#
+# /* unary operations */
+# case Node_NR:
+# case Node_FNR:
+# case Node_NF:
+# case Node_FIELDWIDTHS:
+# case Node_FS:
+# case Node_RS:
+#- case Node_field_spec:
+# case Node_subscript:
+# case Node_IGNORECASE:
+# case Node_OFS:
+#--- 685,700 ----
+# return func_call(tree->rnode, tree->lnode);
+#
+# /* unary operations */
+#+ case Node_field_spec:
+#+ lhs = get_lhs(tree, (Func_ptr *) NULL);
+#+ return *lhs;
+#+
+# case Node_NR:
+# case Node_FNR:
+# case Node_NF:
+# case Node_FIELDWIDTHS:
+# case Node_FS:
+# case Node_RS:
+# case Node_subscript:
+# case Node_IGNORECASE:
+# case Node_OFS:
+#***************
+#*** 699,705 ****
+# case Node_OFMT:
+# case Node_CONVFMT:
+# lhs = get_lhs(tree, (Func_ptr *) NULL);
+#! return *lhs;
+#
+# case Node_var_array:
+# fatal("attempt to use array `%s' in a scalar context",
+#--- 702,710 ----
+# case Node_OFMT:
+# case Node_CONVFMT:
+# lhs = get_lhs(tree, (Func_ptr *) NULL);
+#! r = dupnode(*lhs);
+#! r->flags |= TEMP;
+#! return r;
+#
+# case Node_var_array:
+# fatal("attempt to use array `%s' in a scalar context",
+#
+{ print NR " " 10/NR }
diff --git a/contrib/awk/test/getnr2tb.in b/contrib/awk/test/getnr2tb.in
new file mode 100644
index 000000000000..f98585722413
--- /dev/null
+++ b/contrib/awk/test/getnr2tb.in
@@ -0,0 +1,6 @@
+line 1
+line 2
+line 3
+line 4
+line 5
+line 6
diff --git a/contrib/awk/test/getnr2tb.ok b/contrib/awk/test/getnr2tb.ok
new file mode 100644
index 000000000000..7b40e8d7519c
--- /dev/null
+++ b/contrib/awk/test/getnr2tb.ok
@@ -0,0 +1,6 @@
+1 10
+2 5
+3 3.33333
+4 2.5
+5 2
+6 1.66667
diff --git a/contrib/awk/test/getnr2tm.awk b/contrib/awk/test/getnr2tm.awk
new file mode 100644
index 000000000000..dfe377a84887
--- /dev/null
+++ b/contrib/awk/test/getnr2tm.awk
@@ -0,0 +1,75 @@
+#From dhw@gamgee.acad.emich.edu Sat Oct 31 22:54:07 1998
+#Return-Path: <dhw@gamgee.acad.emich.edu>
+#Received: from cssun.mathcs.emory.edu (cssun.mathcs.emory.edu [170.140.150.1])
+# by amx.netvision.net.il (8.9.0.Beta5/8.8.6) with ESMTP id HAA08891
+# for <arobbins@netvision.net.il>; Sat, 31 Oct 1998 07:14:07 +0200 (IST)
+#Received: from mescaline.gnu.org (we-refuse-to-spy-on-our-users@mescaline.gnu.org [158.121.106.21]) by cssun.mathcs.emory.edu (8.7.5/8.6.9-940818.01cssun) with ESMTP id AAA14947 for <arnold@mathcs.emory.edu>; Sat, 31 Oct 1998 00:14:32 -0500 (EST)
+#Received: from gamgee.acad.emich.edu (gamgee.acad.emich.edu [164.76.102.76])
+# by mescaline.gnu.org (8.9.1a/8.9.1) with SMTP id AAA20645
+# for <arnold@gnu.ai.mit.edu>; Sat, 31 Oct 1998 00:17:54 -0500
+#Received: by gamgee.acad.emich.edu (Smail3.1.29.1 #57)
+# id m0zZUKY-000IDSC; Sat, 31 Oct 98 00:16 CST
+#Message-Id: <m0zZUKY-000IDSC@gamgee.acad.emich.edu>
+#Date: Sat, 31 Oct 98 00:16 CST
+#From: dhw@gamgee.acad.emich.edu (David H. West)
+#To: bug-gnu-utils@gnu.org
+#Subject: gawk 3.0.3 bug report
+#Cc: arnold@gnu.org
+#X-UIDL: 7474b825cff989adf38f13883d84fdd7
+#Status: RO
+#
+#gawk version: 3.03
+#System used: Linux, kernel 2.0.28, libc 5.4.33, AMD K5PR133 (i586 clone)
+#Remark: There seems to be at least one bug shown by the demo below.
+# There may also be a Dark Corner involving the value of NR in an
+# END block, a topic on which the info file is silent. In gawk
+# 3.0.3, NR often seems to have the least-surprise value in an
+# END block, but sometimes it doesn't - see example below.
+#Problem descr: the log below shows a case where:
+# a) (this may be a red herring) the output of the gawk script
+# is different depending on whether its input file is named on
+# the command line or catted to stdin, without any use of the
+# legitimate means which could produce this effect.
+# b) NR is clearly getting clobbered; I have tried to simplify
+# the 19-line script "awkerr1" below, but seemingly unrelated
+# changes, like shortening constant strings which appear only in
+# print statements, or removing unexecuted or irrelevant code,
+# cause the clobbering to go away. Some previous (larger)
+# versions of this code would clobber NR also when reading from
+# stdin, but I thought you'd prefer a shorter example :-).
+#Reproduce-By: using the gawk script "awkerr1", the contents of
+# which appear in the transcript below as the output of the
+# command "cat awkerr1". Comments following # were added
+# to the transcript later as explanation.
+#---------------------------------------------- Script started on Fri
+#Oct 30 20:04:16 1998 chipmunk:/ram0# ls -l a1 awkerr1 -rw-r--r-- 1
+#root root 2 Oct 30 18:42 a1 -rwxr-xr-x 1 root root
+#389 Oct 30 19:54 awkerr1 chipmunk:/ram0# cat a1 #a1 contains
+#one printable char and a newline a chipmunk:/ram0# od -c xc a1
+#0000000 0a61
+# a \n
+#0000002 chipmunk:/ram0# cat a1 | awkerr1 #no surprises here
+#1 lines in 1 sec: 1 lines/sec; nlines=1 chipmunk:/ram0# awkerr1 a1 È
+#lines in 1 sec: 1 lines/sec; nlines=1 #?! first char is an uppercase
+#E-grave chipmunk:/ram0# awkerr1 a1 | od -N1 -xc 0000000 00c8
+# 310 \0
+#0000001 chipmunk:/ram0# cat awkerr1 #the apparent ^M's are not
+#actually in the file
+#!/usr/bin/awk -f
+function process(w) {
+ if(w in ws) {
+ printf " : found\n"; lc[p " " w]++; rc[w " " n]++; }
+ }
+BEGIN {IGNORECASE=1;
+ }
+/^/ {if(NR % 10 ==0)print "processing line " NR;
+ process($1); nlines++;
+ }
+END {p=w; w=n; n="";
+ if(w)process(w); t=1; print NR " lines in " t " sec: " NR+0 " lines/sec; nlines=" nlines;
+ }
+#chipmunk:/ram0# exit Script done on Fri Oct 30 20:07:31 1998
+#---------------------------------------------
+#
+#-David West dhw@gamgee.acad.emich.edu
+#
diff --git a/contrib/awk/test/getnr2tm.in b/contrib/awk/test/getnr2tm.in
new file mode 100644
index 000000000000..78981922613b
--- /dev/null
+++ b/contrib/awk/test/getnr2tm.in
@@ -0,0 +1 @@
+a
diff --git a/contrib/awk/test/getnr2tm.ok b/contrib/awk/test/getnr2tm.ok
new file mode 100644
index 000000000000..d63fca0990e7
--- /dev/null
+++ b/contrib/awk/test/getnr2tm.ok
@@ -0,0 +1 @@
+1 lines in 1 sec: 1 lines/sec; nlines=1
diff --git a/contrib/awk/test/gtlnbufv.awk b/contrib/awk/test/gtlnbufv.awk
new file mode 100644
index 000000000000..ce7d243c9c70
--- /dev/null
+++ b/contrib/awk/test/gtlnbufv.awk
@@ -0,0 +1,2 @@
+/@K@CODE/ { print ; getline temp ; print temp ;next }
+{print}
diff --git a/contrib/awk/test/igncdym.awk b/contrib/awk/test/igncdym.awk
new file mode 100644
index 000000000000..3119c3e9c36e
--- /dev/null
+++ b/contrib/awk/test/igncdym.awk
@@ -0,0 +1,56 @@
+#From Jeffrey.B.Woodward@Hitchcock.ORG Mon Feb 21 09:33:32 2000
+#Message-id: <12901034@mailbox2.Hitchcock.ORG>
+#Date: 20 Feb 2000 18:14:11 EST
+#From: Jeffrey.B.Woodward@Hitchcock.ORG (Jeffrey B. Woodward)
+#Subject: gawk 3.0.4 bug
+#To: bug-gnu-utils@gnu.org
+#Cc: arnold@gnu.org
+#
+#O/S: Digital UNIX 4.0D
+#
+#C Compiler: DEC C
+#
+#gawk version: 3.0.4
+#
+#Sample Program:
+#gawk '
+ BEGIN {
+ pattern[1] = "bar" ; ignore[1] = 1
+ pattern[2] = "foo" ; ignore[2] = 0
+ }
+
+ {
+ for (i = 1 ; i <= 2 ; i++) {
+ IGNORECASE = ignore[i]
+ print match($0, pattern[i]) " " pattern[i] ":" $0
+ }
+ }
+#' << -EOF-
+#This is foo
+#This is bar
+#-EOF-
+#
+#Program Output:
+#0 bar:This is foo
+#0 foo:This is foo
+#9 bar:This is bar
+#9 foo:This is bar
+#
+#
+#**Expected** Output:
+#0 bar:This is foo
+#9 foo:This is foo
+#9 bar:This is bar
+#0 foo:This is bar
+#
+#
+#This problem appears to be directly related to IGNORECASE. If
+#IGNORECASE remains constant, the program behaves as expected;
+#however, switching IGNORECASE seems to causes problems - it is
+#almost as though the pattern stored in the variable is treated
+#as a constant and the regexp() is not recompiled(?) - just a
+#guess...
+#
+#
+#Thanks,
+#-Jeff Woodward
diff --git a/contrib/awk/test/igncdym.in b/contrib/awk/test/igncdym.in
new file mode 100644
index 000000000000..43e361aa6480
--- /dev/null
+++ b/contrib/awk/test/igncdym.in
@@ -0,0 +1,2 @@
+This is foo
+This is bar
diff --git a/contrib/awk/test/igncdym.ok b/contrib/awk/test/igncdym.ok
new file mode 100644
index 000000000000..e715a6de5c21
--- /dev/null
+++ b/contrib/awk/test/igncdym.ok
@@ -0,0 +1,4 @@
+0 bar:This is foo
+9 foo:This is foo
+9 bar:This is bar
+0 foo:This is bar
diff --git a/contrib/awk/test/nasty.awk b/contrib/awk/test/nasty.awk
new file mode 100644
index 000000000000..b9c20c8b6cb3
--- /dev/null
+++ b/contrib/awk/test/nasty.awk
@@ -0,0 +1,92 @@
+#From hankedr@manatee.dms.auburn.edu Tue Oct 13 22:15:59 1998
+#Return-Path: <hankedr@manatee.dms.auburn.edu>
+#Received: from cssun.mathcs.emory.edu (cssun.mathcs.emory.edu [170.140.150.1])
+# by dmx.netvision.net.il (8.9.0.Beta5/8.8.6) with ESMTP id PAA03924
+# for <arobbins@netvision.net.il>; Tue, 13 Oct 1998 15:32:13 +0200 (IST)
+#Received: from mescaline.gnu.org (we-refuse-to-spy-on-our-users@mescaline.gnu.org [158.121.106.21]) by cssun.mathcs.emory.edu (8.7.5/8.6.9-940818.01cssun) with ESMTP id KAA11644 for <arnold@mathcs.emory.edu>; Tue, 13 Oct 1998 10:22:32 -0400 (EDT)
+#Received: from manatee.dms.auburn.edu (manatee.dms.auburn.edu [131.204.53.104])
+# by mescaline.gnu.org (8.9.1a/8.9.1) with ESMTP id KAA03250
+# for <arnold@gnu.org>; Tue, 13 Oct 1998 10:25:32 -0400
+#Received: (from hankedr@localhost)
+# by manatee.dms.auburn.edu (8.9.1a/8.9.1) id JAA13348;
+# Tue, 13 Oct 1998 09:22:29 -0500 (CDT)
+#Date: Tue, 13 Oct 1998 09:22:29 -0500 (CDT)
+#Message-Id: <199810131422.JAA13348@manatee.dms.auburn.edu>
+#From: Darrel Hankerson <hankedr@dms.auburn.edu>
+#To: arnold@gnu.org
+#In-reply-to: <199810131313.QAA31784@alpha.netvision.net.il> (message from
+# Aharon Robbins on Tue, 13 Oct 1998 16:10:36 +0200)
+#Subject: Re: full text of bug report?
+#Mime-Version: 1.0
+#Content-Type: text/plain; charset=US-ASCII
+#X-UIDL: bf3fce492dad4ab030c561e7b2f27d0a
+#Status: RO
+#
+# Do you have the full text of the a = a "\n" f() bug report?
+# I can't find it.... I'm not sure there really is a bug.
+#
+#Yes, see below.
+#
+#His example has unnecessary fragments (in particular, the use of
+#gensub is irrelevant). As I wrote to you earlier, the interesting
+#question for me is:
+#
+# Is the concatenation result undefined? If the result is defined or
+# implementation-dependent, then gawk has a bug.
+#
+#
+#=== Original report =====================================================
+#From: Attila Torcsvari <arcdev@mail.matav.hu>
+#To: "'bug-gnu-utils@prep.ai.mit.edu'" <bug-gnu-utils@gnu.org>
+#Subject: gawk 3.0.3 bug
+#Date: Thu, 17 Sep 1998 18:12:13 +0200
+#MIME-Version: 1.0
+#Content-Transfer-Encoding: 7bit
+#Resent-From: bug-gnu-utils@gnu.org
+#X-Mailing-List: <bug-gnu-utils@gnu.org> archive/latest/3396
+#X-Loop: bug-gnu-utils@gnu.org
+#Precedence: list
+#Resent-Sender: bug-gnu-utils-request@gnu.org
+#Content-Transfer-Encoding: 7bit
+#Content-Type: text/plain; charset="us-ascii"
+#Content-Length: 618
+#
+#Bug-gnuers,
+#please pass it to the responsible.
+#
+#The following generates something interesting:
+#
+BEGIN{
+a="aaaaa"
+a=a a #10
+a=a a #20
+a=a a #40
+a=a a #80
+a=a a #160
+a=a a # i.e. a is long enough
+
+a=a"\n"f() # this causes the trouble
+print a # guess the result
+}
+
+function f()
+{
+#print "a before: ", a
+#a=gensub("a","123,","g",a) # 'a' will be just a bit longer (4 times, but still should fit: 4*160=640)
+gsub(/a/, "123", a)
+#print "a after: ", a
+return "X"
+}
+#
+#Possible reason:
+#during f the a is modified,
+#it can be even freed, because gensub modifies its size
+#the printout contains trash.
+#
+#Used version: VC compiled WinNT 32 bit Intel.
+#
+#Regards,
+#
+#Attila Torcsvari
+#Arcanum Development
+#
diff --git a/contrib/awk/test/nasty.ok b/contrib/awk/test/nasty.ok
new file mode 100644
index 000000000000..5189cf8167c8
--- /dev/null
+++ b/contrib/awk/test/nasty.ok
@@ -0,0 +1,2 @@
+123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123
+X
diff --git a/contrib/awk/test/nlstrina.awk b/contrib/awk/test/nlstrina.awk
new file mode 100644
index 000000000000..41dbd5f1230a
--- /dev/null
+++ b/contrib/awk/test/nlstrina.awk
@@ -0,0 +1,77 @@
+# From E.Ab@chem.rug.nl Wed Aug 2 13:16:53 2000
+# Received: from mail.actcom.co.il
+# by localhost with POP3 (fetchmail-5.1.2)
+# for arnold@localhost (single-drop); Wed, 02 Aug 2000 13:16:53 -0400 (EDT)
+# Received: from lmail.actcom.co.il by actcom.co.il with ESMTP
+# (8.9.1a/actcom-0.2) id MAA21699 for <arobbins@actcom.co.il>;
+# Wed, 2 Aug 2000 12:20:38 +0300 (EET DST)
+# (rfc931-sender: lmail.actcom.co.il [192.114.47.13])
+# Received: from freefriends.org (freefriends.org [63.85.55.109])
+# by lmail.actcom.co.il (8.9.3/8.9.1) with ESMTP id LAA22723
+# for <arobbins@actcom.co.il>; Wed, 2 Aug 2000 11:23:22 +0300
+# Received: from mescaline.gnu.org (mescaline.gnu.org [158.121.106.21])
+# by freefriends.org (8.9.3/8.9.3) with ESMTP id FAA23582
+# for <arnold@skeeve.com>; Wed, 2 Aug 2000 05:18:59 -0400
+# Received: from dep.chem.rug.nl (dep.chem.rug.nl [129.125.7.81])
+# by mescaline.gnu.org (8.9.1a/8.9.1) with ESMTP id FAA30670;
+# Wed, 2 Aug 2000 05:20:24 -0400
+# Received: from rugmd34.chem.rug.nl (rugmd34.chem.rug.nl [129.125.42.34])
+# by dep.chem.rug.nl (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id LAA17089;
+# Wed, 2 Aug 2000 11:20:23 +0200
+# Received: from chem.rug.nl (localhost [127.0.0.1]) by rugmd34.chem.rug.nl (980427.SGI.8.8.8/980728.SGI.AUTOCF) via ESMTP id LAA25392; Wed, 2 Aug 2000 11:20:22 +0200 (MDT)
+# Sender: E.Ab@chem.rug.nl
+# Message-ID: <3987E7D5.2BDC5FD3@chem.rug.nl>
+# Date: Wed, 02 Aug 2000 11:20:21 +0200
+# From: Eiso AB <E.Ab@chem.rug.nl>
+# X-Mailer: Mozilla 4.72C-SGI [en] (X11; I; IRIX 6.5 IP32)
+# X-Accept-Language: en
+# MIME-Version: 1.0
+# To: bug-gnu-utils@gnu.org, arnold@gnu.org
+# Subject: bug? [GNU Awk 3.0.5]
+#
+# Content-Type: text/plain; charset=us-ascii
+# Content-Transfer-Encoding: 7bit
+# X-UIDL: \f8"!(8G!!ZL$#!h>X!!
+# Status: R
+#
+# hi Arnold,
+#
+#
+# Please try the script beneath...
+# I'm not sure if this is a bug or not, but I would expect
+# the empty string as an array index just to be treated
+# like any other string
+#
+# so if ("" in ta) would be true, and for ( i in ta ) should loop only once.
+#
+BEGIN {
+ v=""
+ ta[v]++
+ if ( v in ta) print "a",v,++ta[v],ta[v]
+ print "b",v,++ta[v],ta[v]
+ for( i in ta) print "c",++c,i,ta[i]
+}
+#
+# goodluck, Eiso
+#
+# --
+# _________
+# _______________________________/ Eiso AB \_________________________
+#
+# o
+#
+# o Dept. of Biochemistry
+# University of Groningen
+# The Netherlands
+# o
+# . .
+# o ^ mailto:eiso@chem.rug.nl
+# | - _ mailto:eiso@dds.nl
+# \__|__/ http://md.chem.rug.nl/~eiso
+# | tel 4326
+# |
+# / \
+# / \
+# | |
+# ________ ._| |_. ________________________________________________
+#
diff --git a/contrib/awk/test/nlstrina.ok b/contrib/awk/test/nlstrina.ok
new file mode 100644
index 000000000000..690f1a2fac73
--- /dev/null
+++ b/contrib/awk/test/nlstrina.ok
@@ -0,0 +1,3 @@
+a 2 2
+b 3 3
+c 1 3
diff --git a/contrib/awk/test/numindex.awk b/contrib/awk/test/numindex.awk
new file mode 100644
index 000000000000..1762e456f2b2
--- /dev/null
+++ b/contrib/awk/test/numindex.awk
@@ -0,0 +1,55 @@
+#To: bug-gnu-utils@gnu.org
+#cc: arnold@gnu.org
+#Subject: Possible bug in GNU Awk 3.0.4
+#Date: Wed, 24 Nov 1999 21:47:24 +0000
+#From: Daniel Elphick <de397@ecs.soton.ac.uk>
+#Message-Id: <E11qkG4-0000l0-00@cameron>
+#
+#This is a multipart MIME message.
+#
+#--==_Exmh_-11192982200
+#Content-Type: text/plain; charset=us-ascii
+#
+#
+#When I use the attached awk script unique on the attached data file, it
+#reports that all 4 lines of the data are the same. Using mawk it correctly
+#reports that there are no repeats.
+#
+#I don't know if there are limits on the size of associative array keys for the
+#purposes of reliable indexing but if there is then it is not (obviously)
+#documented.
+#
+#
+#--==_Exmh_-11192982200
+#Content-Type: text/plain ; name="data"; charset=us-ascii
+#Content-Description: data
+#Content-Disposition: attachment; filename="data"
+#
+#322322111111112232231111
+#322322111111112213223111
+#322322111111112211132231
+#322322111111112211113223
+#
+#--==_Exmh_-11192982200
+#Content-Type: text/plain ; name="unique"; charset=us-ascii
+#Content-Description: unique
+#Content-Disposition: attachment; filename="unique"
+#
+{
+ if($0 in a)
+ {
+ printf("line %d has been seen before at line %d\n", NR, a[$0])
+ repeat_count += 1
+ }
+ else
+ {
+ a[$0] = NR
+ }
+ count += 1
+}
+END {
+# printf("%d %f%%\n", repeat_count, (float)repeat_count / count * 100)
+ printf("%d %f%%\n", repeat_count, repeat_count / count * 100)
+}
+#
+#--==_Exmh_-11192982200--
diff --git a/contrib/awk/test/numindex.in b/contrib/awk/test/numindex.in
new file mode 100644
index 000000000000..3852058d5848
--- /dev/null
+++ b/contrib/awk/test/numindex.in
@@ -0,0 +1,4 @@
+322322111111112232231111
+322322111111112213223111
+322322111111112211132231
+322322111111112211113223
diff --git a/contrib/awk/test/numindex.ok b/contrib/awk/test/numindex.ok
new file mode 100644
index 000000000000..8e086f62a65a
--- /dev/null
+++ b/contrib/awk/test/numindex.ok
@@ -0,0 +1 @@
+0 0.000000%
diff --git a/contrib/awk/test/opasnidx.awk b/contrib/awk/test/opasnidx.awk
new file mode 100644
index 000000000000..e39886004acb
--- /dev/null
+++ b/contrib/awk/test/opasnidx.awk
@@ -0,0 +1 @@
+BEGIN { b = 1; a[b] = 2; a[b++] += 1; print b,a[1] }
diff --git a/contrib/awk/test/opasnidx.ok b/contrib/awk/test/opasnidx.ok
new file mode 100644
index 000000000000..654d526942ad
--- /dev/null
+++ b/contrib/awk/test/opasnidx.ok
@@ -0,0 +1 @@
+2 3
diff --git a/contrib/awk/test/opasnslf.awk b/contrib/awk/test/opasnslf.awk
new file mode 100644
index 000000000000..46cd2b8176dd
--- /dev/null
+++ b/contrib/awk/test/opasnslf.awk
@@ -0,0 +1,6 @@
+BEGIN {
+ print b += b += 1
+ b = 6
+ print b += b++
+ print b
+}
diff --git a/contrib/awk/test/opasnslf.ok b/contrib/awk/test/opasnslf.ok
new file mode 100644
index 000000000000..2fa9fd51a97e
--- /dev/null
+++ b/contrib/awk/test/opasnslf.ok
@@ -0,0 +1,3 @@
+2
+13
+13
diff --git a/contrib/awk/test/printf1.awk b/contrib/awk/test/printf1.awk
new file mode 100644
index 000000000000..1cd7b99fff7f
--- /dev/null
+++ b/contrib/awk/test/printf1.awk
@@ -0,0 +1,19 @@
+# Tue May 25 16:36:16 IDT 1999
+#
+# Test cases based on email from Andreas Schwab, schwab@gnu.org
+
+BEGIN {
+ fmt[1] = "%8.5d"; data[1] = 100
+ fmt[2] = "%#o"; data[2] = 0
+ fmt[3] = "%#.1o"; data[3] = 0
+ fmt[4] = "%#.0o"; data[4] = 0
+ fmt[5] = "%#x"; data[5] = 0
+ fmt[6] = "%.0d"; data[6] = 0
+ fmt[7] = "%5.0d"; data[7] = 0
+
+ for (i = 1; i <= 7; i++) {
+ format = "%s, %d --- |" fmt[i] "|\n"
+ printf(format, fmt[i], data[i], data[i])
+ }
+
+}
diff --git a/contrib/awk/test/printf1.ok b/contrib/awk/test/printf1.ok
new file mode 100644
index 000000000000..32b3a7d87a0d
--- /dev/null
+++ b/contrib/awk/test/printf1.ok
@@ -0,0 +1,7 @@
+%8.5d, 100 --- | 00100|
+%#o, 0 --- |0|
+%#.1o, 0 --- |0|
+%#.0o, 0 --- |0|
+%#x, 0 --- |0|
+%.0d, 0 --- ||
+%5.0d, 0 --- | |
diff --git a/contrib/awk/test/reg/Obsolete/exp.awk b/contrib/awk/test/reg/Obsolete/exp.awk
new file mode 100644
index 000000000000..4e707f891a77
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/exp.awk
@@ -0,0 +1 @@
+BEGIN { print exp(0), exp(1000000), exp(0.5) }
diff --git a/contrib/awk/test/reg/Obsolete/exp.good b/contrib/awk/test/reg/Obsolete/exp.good
new file mode 100644
index 000000000000..07b88537dd81
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/exp.good
@@ -0,0 +1,2 @@
+1 gawk: reg/exp.awk:1: warning: exp argument 1e+06 is out of range
+Inf 1.64872
diff --git a/contrib/awk/test/reg/Obsolete/exp.in b/contrib/awk/test/reg/Obsolete/exp.in
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/exp.in
diff --git a/contrib/awk/test/reg/Obsolete/log.awk b/contrib/awk/test/reg/Obsolete/log.awk
new file mode 100644
index 000000000000..bcae90b8132d
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/log.awk
@@ -0,0 +1 @@
+BEGIN { print log(0), log(-1), log(100) }
diff --git a/contrib/awk/test/reg/Obsolete/log.good b/contrib/awk/test/reg/Obsolete/log.good
new file mode 100644
index 000000000000..857ab7703650
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/log.good
@@ -0,0 +1,4 @@
+log: SING error
+-Inf gawk: reg/log.awk:1: warning: log called with negative argument -1
+log: DOMAIN error
+NaN 4.60517
diff --git a/contrib/awk/test/reg/Obsolete/log.in b/contrib/awk/test/reg/Obsolete/log.in
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/contrib/awk/test/reg/Obsolete/log.in
diff --git a/contrib/awk/test/strftime.awk b/contrib/awk/test/strftime.awk
new file mode 100644
index 000000000000..8c1f401acc75
--- /dev/null
+++ b/contrib/awk/test/strftime.awk
@@ -0,0 +1,15 @@
+# strftime.awk ; test the strftime code
+#
+# input is the output of `date', see Makefile.in
+#
+# The mucking about with $0 and $N is to avoid problems
+# on cygwin, where the timezone field is empty and there
+# are two consecutive blanks.
+
+{
+ $3 = sprintf("%02d", $3 + 0)
+ print > "strftime.ok"
+ $0 = strftime()
+ $NF = $NF
+ print > OUTPUT
+}
diff --git a/contrib/awk/test/subslash.awk b/contrib/awk/test/subslash.awk
new file mode 100644
index 000000000000..87ab02991a9b
--- /dev/null
+++ b/contrib/awk/test/subslash.awk
@@ -0,0 +1,6 @@
+BEGIN {
+ i = 2
+ a[i] = 5
+ a[i] /= 2
+ printf "a[%s] = %f\n", i, a[i]
+}
diff --git a/contrib/awk/test/subslash.ok b/contrib/awk/test/subslash.ok
new file mode 100644
index 000000000000..4f3beffb42cf
--- /dev/null
+++ b/contrib/awk/test/subslash.ok
@@ -0,0 +1 @@
+a[2] = 2.500000
diff --git a/contrib/awk/test/zeroflag.awk b/contrib/awk/test/zeroflag.awk
new file mode 100644
index 000000000000..526ed0e89a7d
--- /dev/null
+++ b/contrib/awk/test/zeroflag.awk
@@ -0,0 +1 @@
+BEGIN { printf("%2.1d---%02.1d\n", 2, 2) }
diff --git a/contrib/awk/test/zeroflag.ok b/contrib/awk/test/zeroflag.ok
new file mode 100644
index 000000000000..937c0ede098a
--- /dev/null
+++ b/contrib/awk/test/zeroflag.ok
@@ -0,0 +1 @@
+ 2--- 2
diff --git a/contrib/nvi/catalog/uk_UA.KOI8-U b/contrib/nvi/catalog/uk_UA.KOI8-U
new file mode 100644
index 000000000000..2d561c953c4e
--- /dev/null
+++ b/contrib/nvi/catalog/uk_UA.KOI8-U
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+ðÅÒÅÐÏ×ÎÅÎÎÑ ÚÎÁÞÅÎÎÑ Äo×ÖuÎu pÑÄËyX
+ÎÅÍÏÖÌÉ×Ï ÓÔÅÒÔÉ ÒÑÄÏË %luX
+ÎÅÍÏÖÌÉ×Ï ÄÏÄÁÔÉ ÄÏ ÒÑÄËÕ %luX
+ÎÅÍÏÖÌÉ×Ï ×ÓÔÁ×ÉÔÉ × ÒÑÄÏË %luX
+ÎÅÍÏÖÌÉ×Ï poÚÍiÓÔÉÔÉ ÒÑÄÏË %luX
+ÎÅÍÏÖÌÉ×Ï ÄiÓÔÁÔu ÏÓÔÁÎÎiÊ ÒÑÄÏËX
+ðÏÍÉÌËÁ: ÎÅÍÏÖÌÉ×Ï oÔpuÍaÔÉ ÒÑÄÏË %luX
+æÁÊÌ ÚÁÐÉÓi×X
+úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ×iÄÍiÎÉÔÉ ÏÓÔÁÎÎÀ ËÏÍÁÎÄÕX
+îÅÍÁ ÞÏÇÏ ×iÄÍiÎÑÔÉX
+úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ×iÄÍiÎÉÔÉ ÏÓÔÁÎÎÀ ËÏÍÁÎÄÕX
+úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ÐÒÏÄÉ×ÉÔÉÓÑ ×ÐÅÒÅÄX
+îÅÍÁ ÞÏÇÏ ÐÏ×ÔÏÒÀ×ÁÔÉX
+%s/%d: ÐÏÍÉÌËÁ ÚaÐÉÓy ÐÒÏÔÏËÏÌyX
+CÔÁÎÄÁÒÔÎÉÍ ××ÅÄÅÎÎÑÍ/×É×ÅÄÅÎÎÑÍ ÄÌÑ vi ÍÁ¤ ÂÕÔu ÔÅÒÍiÎÁÌX
+MiÔËÁ %s: ÎÅ ×ÓÔÁÎÏ×ÌÅÎÏX
+MiÔËÁ %s: ÒÑÄÏË ÓÔÅÒÔoX
+MiÔËÁ %s: ÐÏÚÉÃi§ ËÕÒÓÏÒy ÂiÌØÛÅ ÎÅ icÎÕ¤X
+ðÏÍÉÌËÁ: X
+Ho×uÊ ÆaÊÌX
+IÍ'Ñ ÚÍiÎuÌocØX
+ÚÍiÎÅÎÉÊX
+Îe ÚÍiÎÅÎÉÊX
+PO3âìOKOBAHOX
+ÔiÌØËu ÄÌÑ ÞÉÔÁÎÎÑX
+pÑÄoË %lu Ú %lu [%ld%%]X
+ÐycÔuÊ ÆaÊÌX
+pÑÄoË %luX
+æaÊÌ %s ÎÅ ¤ ÆaÊÌoÍ ÐÏ×iÄÏÍÌÅÎÎØX
+îeÍÏÖÌÉ×Ï ×ÓÔÁÎÏ×ÉÔÉ oÐÃiÀ %s ÚÁ ÚÍÏ×ÞÁÎÎÑÍX
+BuËopucÔaÎÎÑ: %sX
+ïÐÃi§ %s ÎÅÍa: 'set all' ÐÏËÁÚy¤ ×Ói ÍÏÖÌÉ×i ÏÐÃi§X
+set: [no]%s ÎÅ ÎÁÂÕ×Á¤ ÔÁËÏÇÏ ÚÎÁÞÅÎÎÑX
+set: %s ÏÐÃiÑ ÎÅ ¤ ÌÏÇiÞÎÏÀX
+set: ÏÐÃiÑ %s: %sX
+set: ÏÐÃiÑ %s: %s: ÐÅÒÅÐÏ×ÎÅÎÎÑX
+set: ÎÅÐÒÁ×ÉÌØÎÅ ÚÎÁÞÅÎÎÑ %sX
+set: %s ÏÐÃiÑ ÎÅ ¤ ÌÏÇiÞÎÏÀX
+ëiÌØËicÔØ ËÏÌÏÎÏË Îa ÜËÒÁÎi ÎÁÄÔÏ ÍÁÌa, ÍÅÎÛÅ ÎiÖ %dX
+ëiÌØËicÔØ ËÏÌÏÎÏË Îa ÜËÒÁÎi ÎÁÄÔÏ ×eÌuËa, ÂiÌØÛe ÎiÖ %dX
+ëiÌØËicÔØ pÑÄËi× Îa ÜËÒÁÎi ÎÁÄÔÏ ÍÁÌa, ÍÅÎÛÅ ÎiÖ %dX
+ëiÌØËicÔØ pÑÄËi× Îa ÜËÒÁÎi ÎÁÄÔÏ ×eÌuËa, ÂiÌØÛe ÎiÖ %dX
+ïÐÃiÑ lisp ×iÄcyÔÎÑX
+ðÏ×iÄÏÍÌÅÎÎÑ ÎÅ ×uÍËÎÅÎi: %sX
+ðÏ×iÄÏÍÌÅÎÎÑ ÎÅ ××iÍËÎÅÎi: %sX
+
+ïÐÃiÑ paragraph ÐÏ×ÉÎÎÁ ÍiÓÔÉÔÉ ÇpyÐÉ Ú Ä×ÏÈ ÓÉÍ×oÌi×X
+ïÐÃiÑ section ÐÏ×ÉÎÎÁ ÍiÓÔÉÔÉ ÇpyÐÉ Ú Ä×ÏÈ ÓÉÍ×oÌi×X
+
+
+
+óÔÁÒÔÏ×uÊ ÂÕÆÅÒ ÐopoÖÎiÊX
+âÕÆÅÒ %s ÐopoÖÎiÊX
+îeÍÏÖÌÉ×Ï ×iÄÎÏ×uÔÉ ÆÁÊÌ, ÝÏ ÍiÓÔÉÔØ × iÍÅÎi ÓÉÍ×oÌÉ ÐÅÒÅ×eÄeÎÎÑ ËÁÒÅÔËÉX
+úÍiÎÉ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ×iÄÎÏ×uÔÉ ÐicÌÑ Ëpaxy ceci§X
+KoÐiÀ×ÁÎÎÑ ÆÁÊÌÕ ÄÌÑ ×iÄÎÏ×ÌÅÎÎÑ...X
+úÂÅÒÅÖÅÎÎÑ ÎÅ ×ÄÁÌÏÓØ: %sX
+úÍiÎÉ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ×iÄÎÏ×uÔÉ ÐicÌÑ Ëpaxy ceci§X
+úÂÅÒÅÖÅÎÎÑ ËÏÐi§ ÆÁÊÌy ÎÅ ×ÄÁÌÏÓØ: %sX
+KoÐiÀ×ÁÎÎÑ ÆÁÊÌÕ ÄÌÑ ×iÄÎÏ×ÌÅÎÎÑ...X
+IÎÆÏÒÍÁÃiÀ ÐÒÏ ËopucÔÕ×ÁÞa %u ÎÅ ÚÎÁÊÄÅÎÏX
+úÁÂÌÏËÕ×ÁÔÉ ×iÄÎÏ×ÌÅÎÎuÊ ÆÁÊÌ ÎeÍÏÖÌÉ×ÏX
+âÕÆÅÒ ×iÄÎÏ×ÌÅÎoÇo ÆÁÊÌy ÐÅÒÅÐÏ×ÎÅÎoX
+÷iÄÎÏ×ÌÅÎÎuÊ ÆÁÊÌX
+%s: ÆÁÊÌ ×iÄÎÏ×ÌÅÎÎuÊ ÎÅ ÄÏ ËiÎÃÑX
+%s: ÆÁÊÌ ×iÄÎÏ×ÌÅÎÎuÊ ÎÅ ÄÏ ËiÎÃÑX
+He icÎyÀ¤ ÆÁÊÌi× Ú iÍÅÎÅÍ %s, ÑËi ÷u ÍÏÖÅÔÅ ÐÒÏÞÉÔÁÔuX
+IcÎyÀÔØ ÓÔÁÒi ×ÅÒÓi§ ÆÁÊÌy, ÑËi ÍÏÖÎÁ ×iÄÎÏ×ÉÔÉX
+IcÎyÀÔØ iÎÛi ÆÁÊÌu, ÑËi ÍÏÖÎÁ ×iÄÎÏ×ÉÔÉX
+Å-mail ÎÅ ×iÄicÌaÎo: %sX
+æÁÊÌ ÐÕÓÔuÊ - ÎeÍÁ ÞÏÇo ÛyËaÔÉX
+äÏÓÑÎÕÔo ËiÎÃÑ ÆÁÊÌy ÂÅÚ ÚÎÁÈÏÖÄÅÎÎÑ ÚpÁÚËy ÐÏÛÕËyX
+îÅ ÚÁÄÁÎo ÚpaÚoË ÐÏÛÕËyX
+úpaÚoË ÐÏÛÕËy ÎÅ ÚÎÁÊÄÅÎoX
+äÏÓÑÎÕÔo ÐÏÞÁÔËy ÆÁÊÌy ÂÅÚ ÚÎÁÈÏÖÄÅÎÎÑ ÚpÁÚËy ÐÏÛÕËyX
+ðÏÛyË ÚÁÃÉËÌÅÎoX
+ðÏÛyË...X
+îÅÐÅÞÁÔÎuÈ ÓÉÍ×ÏÌi× ÎÅ ÚÎÁÊÄÅÎÏX
+îÅ×iÄoÍa ËÏÍÁÎÄÁX
+
+%s: ËÏÍÁÎÄÁ ÎÅ ÄÏÓÔÕÐÎÁ × ÒÅÖÉÍi exX
+ìiÞÉÌØÎÉË ÎÅ ÍÏÖÅ ÂyÔu ÎÕÌÅÍX
+%s: ÎÅÐÒÁ×ÉÌØÎÅ ×uÚÎÁÞÅÎÎÑ pÑÄËÕX
+÷ÎÕÔÒiÛÎÑ ÐÏÍÉÌËÁ × ÓÉÎÔÁËÓÉÓi (%s: %s)X
+BuËopucÔaÎÎÑ: %sX
+%s: ÔÉÍÞÁÓÏ×ÉÊ ÂÕÆÅÒ ÎÅ ×uËÏpÉÓÔÁÎÏX
+MiÔËy ÐÏÓÔÁ×ÌÅÎo ÐÅÒÅÄ ÐÅÒÛÉÍ ÒÑÄËÏÍX
+MiÔËy ÐÏÓÔÁ×ÌÅÎo ÐicÌÑ ËiÎÃÑ ÆÁÊÌÕX
+@ Ú ÄiÁÐÁÚÏÎÏÍ ÐÒÁÃÀ¤ ËÏÌÉ ÚÍiÎÅÎÏ ÆÁÊÌ/×iËÎÏX
+ëÏÍÁÎÄÁ Global/v ÐÒÁÃÀ¤ ËÏÌÉ ÚÍiÎÅÎÏ ÆÁÊÌ/×iËÎÏX
+ëÏÍÁÎÄÁ ex ÎÅ ×ÄÁÌÁÓØ: ÎÁÓÔÕÐÎi ËÏÍÁÎÄÉ Ú'iÇÎÏÒÏ×ÁÎÏX
+ëÏÍÁÎÄÁ ex ÎÅ ×ÄÁÌÁÓØ: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏX
+äpyÇÁ ÁÄÒÅÓa ÍÅÎÛÅ ÎiÖ ÐÅÒÛaX
+He ×ËÁÚÁÎÏ iÍ'Ñ ÍiÔËÉX
+\\ ÎÅ ÚÁËiÎÞÕ¤ÔØÓÑ / Þu ?X
+ðoÓÉÌÁÎÎÑ ÎÁ pÑÄÏË Ú ÎoÍÅpoÍ, ÍÅÎÛÉÍ ÎiÖ 0X
+ëÏÍÁÎÄÁ %s ÎÅ×iÄÏÍaX
+ðÅÒÅÐÏ×ÎÅÎÎÑ ÌiÞuÌØÎÉËÁ aÄpecX
+îÅÄÏÂiÒ ÌiÞuÌØÎÉËÁ aÄpecX
+îÅÄÏÐÕÓÔÉÍÁ ËÏÍÂiÎÁÃiÑ × ÁÄÒÅÓiX
+îÅÐÒÁ×ÉÌØÎa ÁÄÒÅÓa: ×ÓØoÇÏ %lu pÑÄËi× y ÆÁÊÌiX
+îÅÐÒÁ×ÉÌØÎa ÁÄÒÅÓa: ÆÁÊÌ ÐÕÓÔuÊX
+ëÏÍÁÎÄÁ %s ÎÅ ÍÏÖÅ ×ÉËopucÔo×Õ×ÁÔu ÁÄÒÅÓy 0X
+îÅÍÁ¤ ÁÂÒÅ×iÁÔÕÒX
+áÂÒÅ×iÁÔÕÒu ÐÏ×ÉÎÎi ÚÁËiÎÞÕ×ÁÔÉÓÑ ÓÉÍ×ÏÌÏÍ "word"X
+B ÁÂÒÅ×iÁÔÕÒi ÎÅ ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÉÍ×ÏÌÉ ÔÁÂÕÌÑÃi§ ÔÁ ÐÒÏÂiÌÉX
+áÂÒÅ×iÁÔÕÒu ÎÅ ÍÏÖyÔØ ÚÍiÛÕ×ÁÔÉ ÓÉÍ×ÏÌÉ ÓÌi×/ÎÅ-ÓÌi×, xiÂÁ Ýo × ËiÎÃi pÑÄËÕX
+"%s" ÎÅ ÁÂÒÅ×iÁÔÕÒaX
+ëÏÍÁÎÄÁ Vi ÎÅ ×ÄÁÌÁÓØ: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏX
+æÁÊÌi× ÄÌÑ ÒÅÄÁÇy×aÎÎÑ ÂiÌØÛÅ ÎÅÍa¤X
+ðÏÐÅÒÅÄÎØÏÇÏ ÆaÊÌy ÄÌÑ ÒÅÄÁÇy×aÎÎÑ ÎÅÍa¤X
+ðÏÐÅÒÅÄÎØÏÇÏ ÆaÊÌy ÄÌÑ ÐÅÒeÇÌÑÄy ÎÅÍa¤X
+îÅÍa¤ ÆÁÊÌi×X
+HeÍÁ¤ ÐÏÐÅÒÅÄÎØÏ§ ËÏÍÁÎÄÉ ÄÌÑ ÚÁÍiÎÉ "!"X
+÷iÄÓyÔΤ iÍ'Ñ ÆÁÊÌÕ ÄÌÑ ÐiÄÍiÎÉ %%X
+÷iÄÓyÔΤ iÍ'Ñ ÆÁÊÌÕ ÄÌÑ ÐiÄÍiÎÉ #X
+ðÏÍÉÌËÁ: execl: %sX
+ðÏÍÉÌËÁ ××ÅÄÅÎÎÑ/×É×ÅÄÅÎÎÑ: %sX
+æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÐÏ×ÎÏÇÏ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+îÅÍÏÖÌu×Ï ÚÎÁÊÔÉ ÄÏÍÁÛÎiÊ ËÁÔÁÌÏÇX
+îÏ×uÊ ËÁÔÁÌÏÇ: %sX
+HeÍÁ¤ ÎÁÐÏ×ÎÅÎÉÈ ÂÕÆÅÒi×X
+KoÍÁÎÄa %s ÎÅ ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ ÑË ÞÁÓÔÉÎÁ ËÏÍÁÎÄÉ global ÞÉ vX
+%s/%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ ÞÉ aÄÍiÎicÔpaÔopÕX
+%s/%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍX
+%s/%s: ÎÅ ×iÄËpuÔo: ÍÏÖÌu×iÓÔØ ÚÁÐÉÓy ËopucÔÕ×ÁÞÅÍ, ÑËÉÊ ÎÅ ¤ ×ÌÁÓÎÉËÏÍX
+%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ ÞÉ aÄÍiÎicÔpaÔopÕX
+%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍX
+%s: ÎÅ ×iÄËpuÔo: ÍÏÖÌu×iÓÔØ ÚÁÐÉÓy ËopucÔÕ×ÁÞÅÍ, ÑËÉÊ ÎÅ ¤ ×ÌÁÓÎÉËÏÍX
+HeÍÁ¤ ÂiÌØÛÅ pÑÄËi× ÄÌÑ ÏÂ'¤ÄÎÁÎÎÑX
+HeÍÁ¤ ÐÁÒÁÍÅÔÒi× ××eÄeÎÎÑX
+HeÍÁ¤ ÐÁÒÁÍÅÔÒi× ËÏÍÁÎÄuX
+óÉÍ×ÏÌ %s ÎÅ ÍÏÖÎÁ ÐÅÒÅÎÁÚÎÁÞuÔÉX
+"%s" ÚÁÒÁÚ ÎÅ ÐÅÒÅÎÁÚÎÁÞeÎoX
+IÍ'Ñ ÍiÔËÉ -- ÏÄÉÎ ÓÉÍ×ÏÌX
+%s icÎÕ¤, ÎÅ ÚÁÐÉÓÁÎo; ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+îÏ×uÊ ÆÁÊÌ exrc: %sX
+PÑÄÏË ÐÒÉÚÎÁÞÅÎÎÑ ÚÁÚÎÁÞÅÎÏ ×ÓÅÒÅÄÉÎi ÄiÁÐÁÚÏÎy ÐÅÒÅÍiÝÅÎÎÑX
+ëÏÍÁÎÄa open ×ÉÍÁÇÁ¤ ×ÓÔÁÎÏ×ÌÅÎÎÑ oÐÃi§ openX
+ëÏÍÁÎÄy open ÝÅ ÎÅ ÒÅÁÌiÚÏ×ÁÎÏX
+úÁxÉcÔ ÆÁÊÌy ÎÅÍÏÖÌu×uÊX
+æÁÊÌ ÚÁxÉÝÅÎoX
+%s ÒoÚÛÉÒÉ×ÓÑ × ÎÁÄÔÏ ×ÅÌÉËÕ ËiÌØËiÓÔØ iÍÅÎ ÆÁÊÌi×X
+ðÒÏÞÉÔÁÔÉ ÍÏÖÎÁ ÔiÌØËÉ ÐÒÏÓÔÉÊ ÆÁÊÌ ÞÉ iÍÅÎÏ×ÁÎÉÊ ËÁÎÁÌ(pipe)X
+%s: ÂÌÏËÕ×ÁÎÎÑ ×iÄ ÞÉÔÁÎÎÑ ÎÅÍÏÖÌÉ×ÅX
+úÞuÔyÀ...X
+%s: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×X
+îÅÍÁ¤ ÔiÎØo×uÈ ×iËÏÎX
+ëÏÍÁÎÄa script ÄÏÓÔÕÐÎÁ ÌÉÛÅ × peÖÉÍi viX
+îÅÍÁ ËÏÍÁÎÄu ÄÌÑ ×ÉËoÎaÎÎÑX
+ïÐÃiÀ shiftwidth ×ÓÔÁÎÏ×ÌÅÎo × 0X
+ðÅÒÅÐÏ×ÎÅÎÎÑ ÌiÞuÌØÎÉËÁX
+ãÉËÌ ×uËoÎaÎo ÎÅ ÄÏ ËiÎÃÑX
+BËÁÚÁÎÏ peÇyÌÑÒÎÉÊ ×ÉÒÁÚ; ÐÁÒÁÍÅÔÒ 'r' ÎÅ ÍÁ¤ ÓÅÎÓÕX
+ðÁÒÁÍÅÔÒu #, l Ôa p ÎÅ ÍÏÖÎÁ ËÏÍÂiÎÕ×ÁÔÉ Ú ÐÁÒÁÍÅÔÒÏÍ 'c' × peÖÉÍi viX
+CÐi×ÐÁÄaÎØ ÎÅÍa¤X
+TeÇ ×iÄÓÕÔÎiÊX
+MeÎÛÅ ÎiÖ %s ÚÁÐÉÓi× Õ ÓÔÅËÕ ÔÅÇi×; ×uËopucÔaÊÔÅ :display t[ags]X
+HeÍÁ¤ ÆÁÊÌÕ %s × ÓÔÅËÕ ÔÅÇi× ÄÌÑ ÐÏ×ÅÒÎÅÎÎÑ; ×uËopucÔaÊÔÅ :display t[ags]X
+HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ: X
+%s: ÔeÇ ÎÅ ÚÎÁÊÄÅÎoX
+%s: ÚiÐÓo×ÁÎÉÊ ÔÅÇ × %sX
+%s: ÎÏÍÅÒ ÒÑÄËÕ ÔÅÇÁ ÚÎÁÈÏÄÉÔØÓÑ ÚÁ ËiÎÃÅÍ ÆÁÊÌÕX
+CÔÅË ÔeÇi× ÐÏÒÏÖÎiÊX
+%s: ÚpaÚoË ÐÏÛÕËy ÎÅ ÚÎÁÊÄÅÎoX
+úaÌÉÛÉÌÏÓØ %d ÆÁÊÌi× ÄÌÑ ÒÅÄÁÇÕ×ÁÎÎÑX
+âÕÆÅÒ %s ÐopoÖÎiÊX
+úÍiÎuÔu? [n]X
+ðeÒÅÒ×ÁÎÏX
+HeÍa¤ ÂÕÆÅÒy ÄÌÑ ×uËopucÔaÎÎÑX
+îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×uÒÁÚyX
+ëÏÍÁÎÄa %s ×ÉÍÁÇÁ¤ ×ÖÅ ÐÒÏÞÉÔÁÎÉÊ ÆÁÊÌX
+BuËopucÔaÎÎÑ: %sX
+ëÏÍÁÎÄa visual ×ÉÍÁÇÁ¤ ×ÓÔÁÎÏ×ÌÅÎÎÑ oÐÃi§ openX
+
+ðÕÓÔuÊ ÆÁÊÌX
+îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÐÏÛyËy F, f, T, ÞÉ tX
+%s ÎÅ ÚÎÁÊÄÅÎÏX
+îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÆÁÊÌy ÄÌÑ ÒÅÄÁÇy×ÁÎÎÑX
+Kypcop cÔÏ§ÔØ Îe ÎÁ ÃuÆpiX
+OÔÒÉÍÁÎÅ ÞÉÓÌÏ ÎÁÄÔÏ ×ÅÌÉËeX
+OÔÒÉÍÁÎÅ ÞÉÓÌÏ ÎÁÄÔÏ ÍaÌeX
+HeÍa¤ ×iÄÐo×iÄÎoÇo cÉÍ×ÏÌÕ × ÃØÏÍÕ ÒÑÄËÕX
+÷iÄÐo×iÄÎuÊ cÉÍ×ÏÌ Îe ÚÎÁÊÄÅÎÏX
+îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ÚaÍiÎuX
+îÅÍa¤ iÎÛoÇo ×iËÎÁX
+óÉÍ×ÏÌu ÐiÓÌÑ pÑÄËÕ ÄÌÑ ÐÏÛÕËÕ, ÚÍiÝÅÎÎÑ pÑÄËÕ ÔÁ/ÞÉ ËÏÍÁÎÄÉ zX
+îÅÍa¤ ÐÏÐÅÒÅÄÎØÏÇÏ ÚpaÚËy ÐÏÛÕËyX
+ðÏÛÕË ÚÁËiÎÞÉ×ÓÑ ÎÁ ÐÏÞÁÔËÏ×iÊ ÐÏÚÉÃi§X
+áÂÒÅ×iÁÔÕÒa ÐÅÒÅ×ÉÝÉÌÁ ÌiÍiÔ ÒÏÚÛÉÒÅÎÎÑ: ÓÉÍ×ÏÌu Ú'iÇÎÏÒÏ×ÁÎÏX
+HeÄÏÚ×ÏÌÅÎÉÊ ÓÉÍ×ÏÌ: ÚÁÄÁÊÔÅ × ÄÕÖËÁÈX
+BÖÅ ÎÁ ÐÏÞÁÔËÕ ×ÓÔÁ×ËÉX
+îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ×uÄaÌeÎÎÑX
+Pyx ÚÁ ËiÎÅÃØ ÆÁÊÌyX
+Pyx ÚÁ ËiÎÅÃØ ÒÑÄËyX
+Kypcop ÎÅ ÐÅÒÅÍiÝÕ×Á×ÓÑX
+BÖÅ ÎÁ ÐÏÞaÔËÕ ÆÁÊÌyX
+Pyx ËÕÒÓÏÒy ÚÁ ÐÏÞaÔoË ÆÁÊÌyX
+BÖÅ × ÐÅpÛiÊ ËÏÌÏÎÃiX
+âÕÆÅÒ ÔÒÅÂÁ ×ËÁÚÕ×ÁÔÉ ÐÅÒÅÄ ËÏÍÁÎÄÏÀX
+BÖÅ ÎÁ ËiÎÃi ÆÁÊÌyX
+BÖÅ ÎÁ ËiÎÃi ÒÑÄËyX
+%s ÎÅ ËÏÍÁÎÄa ViX
+BuËopucÔaÎÎÑ: %sX
+îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ×uÄaÌeÎÎÑX
+ëÏÍÁÎÄa Q ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ exX
+îÅÍÁ¤ ËÏÍÁÎÄu ÄÌÑ ÐÏ×ÔÏÒÅÎÎÑX
+æaÊÌ ÐÕÓÔÉÊX
+ëÏÍÁÎÄy %s ÎÅ ÍÏÖÎa ×ÉËÏÒÉÓÔÁÔÉ ÄÌÑ ÐÅÒÅÍiÝÅÎÎÑX
+BÖÅ × ËÏÍÁÎÄÎÏÍy ÒÅÖÉÍiX
+Kypcop cÔÏ§ÔØ Îe ÎÁ cÌo×iX
+
+úÎÁÞÎÅÎÎÑ ÏÐÃi§ Windows ÎÁÄÔÏ ×ÅÌÉËÅ, ÍÁËÓÉÍÕÍ = %uX
+äoÐucaÔuX
+úÍiÎuÔuX
+KoÍaÎÄaX
+BcÔa×uÔuX
+úaÍiÎuÔuX
+Pyx ËÕÒÓÏÒy ÚÁ ËiÎÅÃØ ÜËÒÁÎyX
+Pyx ËÕÒÓÏÒy ÚÁ ÐÏÞaÔoË ÜËÒÁÎyX
+äÌÑ ÒÏÚÂÉÔÔÑ ×iËÎo ÍÁ¤ ÍiÓÔÉÔÉ ÂiÌØÛÅ ÎiÖ %d pÑÄËi×X
+ôiÎØo×uÈ ×iËÏÎ ÎÅÍÁ¤X
+HeÍa¤ ÔiÎØo×oÇo ×iËÎa Ú peÄÁÇÕ×ÁÎÎÑÍ ÆÁÊÌÕ %sX
+He ÍÏÖÎÁ ÚpoÂÉÔÉ ÔiÎØÏ×uÍ ¤ÄÉÎÅ ×iËÎÏX
+÷iËÎÏ ÍÏÖÎÁ ÓÔÉÓÎÕÔÉ ÌÉÛÅ ÄÏ %d pÑÄËi×X
+÷iËÎÏ ÎÅ ÍÏÖÎÁ ÓÔÉÓÎÕÔÉX
+÷iËÎÏ ÎÅ ÍÏÖÎÁ poÚÛÉÒÉÔÉX
+
+ãe ×iËÎÏ ÎÅ ÍÏÖÎÁ ÐÒÉÚÕÐÉÎÉÔÉX
+ðÅÒÅÒ×ÁÎo: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏX
+vi: ÔÉÍÞÁÓÏ×ÉÊ ÂÕÆÕÒ ÎÅ ×É×iÌØÎÅÎÏX
+ãeÊ ÔÉÐ ÔÅÒÍiÎÁÌy ÎÅÍa¤ ËÌÁ×iÛi %sX
+MoÖÎÁ ×ËÁÚÁÔÉ ÌÉÛÅ ÏÄÉÎ ÂÕÆÅÒX
+þÉÓÌÏ ÂiÌØÛÅ, ÎiÖ %luX
+ðÅÒÅÒ×ÁÎoX
+îÅÍÏÖÌy cÔ×ÏÒÉÔÉ ÔÉÍÞÁÓÏ×ÉÊ ÆÁÊÌX
+õBAçA: %s ÓÐÅÃiÁÌØÎuÊ ÆÁÊÌX
+%s ×ÖÅ ÚÁÂÌÏËo×ÁÎo, ÄÏÓÔÕÐÎuÊ ÔiÌØËu ÄÌÑ ÞÉÔÁÎÎÑX
+%s: cÔepÔoX
+%s: ÚÁËÒuÔoX
+%s: cÔepÔoX
+%s: cÔepÔoX
+æÁÊÌ ÔiÌØËu ÄÌÑ ÞuÔaÎÎÑ, ÎÅ ÚÁÐÉÓÁÎo: BuËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+æÁÊÌ ÔiÌØËu ÄÌÑ ÞuÔaÎÎÑ, ÎÅ ÚÁÐÉÓÁÎoX
+%s icÎy¤, ÎÅ ÚÁÐÉÓÁÎo; ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+%s icÎy¤, ÎÅ ÚÁÐÉÓÁÎoX
+BuËopucÔaÊÔÅ ! ÄÌÑ ÞÁÓÔËÏ×oÇo ÚÁÐÉÓy ÆÁÊÌyX
+þÁÓÔuÎa ÆÁÊÌy, ÆÁÊÌ ÎÅ ÚÁÐÉÓÁÎoX
+%s: æÁÊÌ ÚÍiÎÀ×Á×ÓÑ ÐiÚÎiÛÅ, ÎiÖ ÃÑ ËÏÐiÑ: ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+%s: æÁÊÌ ÚÍiÎÀ×Á×ÓÑ ÐiÚÎiÛÅ, ÎiÖ ÃÑ ËÏÐiÑX
+%s: ÚÁxÉcÔ ×iÄ ÚÁÐÉÓy ÎÅÄÏÓÔÕÐÎuÊX
+úaÐÉÓ...X
+%s: õBAçA: ÆÁÊÌ oÂpiÚaÎoX
+BÖÅ ÎÁ ÐÅÒÛÏÍÕ ÔÅÇÕ × ÃiÊ ÇÒÕÐiX
+%s: ÎÏ×uÊ ÆÁÊÌ: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×X
+%s: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×X
+%s ÒoÚÛÉÒÉ×ÓÑ × ÎÁÄÔÏ ×ÅÌÉËÕ ËiÌØËiÓÔØ iÍÅÎ ÆÁÊÌi×X
+%s: ÓÐÅÃiÁÌØÎuÊ ÆÁÊÌX
+%s: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍX
+%s: ÄÏÓÔÕÐÎuÊ ÎÅ ÌuÛe ÷ÁÍ
+æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ :edit ÄÌÑ ÏÂÈÏÄyX
+æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄyX
+ôÉÍÞÁÓÏ×ÉÊ ÆÁÊÌ: ×uÈiÄ ÚiÔÒÅ ÚÍiÎÉX
+æÁÊÌ ÔiÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ, ÚÍiÎÉ ÎÅ ÚÁÐÉÛÕÔØÓÑ Á×ÔÏÍÁÔÉÞÎÏX
+úÁÐÉÓÉ ÐÏÞÁÔi ÚÁÎÏ×ÏX
+ðiÄÔ×ÅÒÄÖÕ¤ÔÅ? [ynq]X
+HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ: X
+HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ [: ÄÌÑ iÎÛux ËoÍÁÎÄ] X
+HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ [q ÄÌÑ ×uxoÄy]: X
+TaËÁ ÆÏÒÍÁ %s ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ exX
+BxoÄÉÍ × peÖÉÍ ××ÅÄÅÎÎÑ exX
+úÂiÊ ËÏÍÁÎÄÉ, ÆÁÊÌ ÎÅ ÐÒÏÞÉÔÁÎÏX
+ðÒÏÄÏ×ÖÉÔÉ?X
+HeoÞiËÕ×ÁÎÁ cuÍ×ÏÌØÎÁ ÐÏÄiÑX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ËiÎÃÑ ÆÁÊÌÕX
+HeÍÁ¤ ÓÐi×ÐÁÄÁÎØ ÚÁ ÚÁÐÉÔÏÍX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÐÅÒÅÒÉ×ÁÎÎÑX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ×uxoÄyX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÐÅÒÅÒÉÓo×ËuX
+BÖÅ ÎÁ ÏÓÔÁÎÎØÍÕ ôÅÇÕ × ÃiÊ ÇpyÐiX
+KoÍÁÎÄÁ %s ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ exX
+TaËÁ ÆÏÒÍÁ %s ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure editX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ pÑÄËyX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÔÁÊÍ-ÁÕÔÕX
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÚaÐucyX
+
+Shell'i×ÓËÅ ÄÏÐÏ×ÎÅÎÎÑ ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure editX
+KoÍÁÎÄÁ %s ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure editX
+set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ ×uÍËÎÅÎÏÀX
+åËÒÁÎ ÎÁÄÔÏ ÍÁÌuÊ.X
+ÄÏÄÁÎÏX
+ÚÍiÎÅÎoX
+ÓÔÅÒÔÏX
+oÂ'¤ÄÎÁÎÏX
+ÐÅÒÅÍiÝÅÎÏX
+ÚÄ×ÉÎÕÔÏX
+×cÔÁ×ÌÅÎÏX
+pÑÄÏËX
+pÑÄËi×X
+Vi ÚÁ×ÁÎÔÁÖÅÎÏ ÂÅÚ iÎÔÅÒÐÒÅÔÁÔÏÒa TclX
+æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy.X
+îÅ×ÄÁÞÁ shell'i×ÓØËÏÇÏ ÄÏÐÏ×ÎÅÎÎÑX
+OÐÃi§ peÄÁÇÕ×ÁÎÎÑ %s ÎÅ ×ËÁÚÁÎÏX
+Vi ÚÁ×ÁÎÔÁÖÅÎÏ ÂÅÚ iÎÔÅÒÐÒÅÔÁÔÏÒa PerlX
+HeÍÁ¤ ËÏÍÁÎÄÉ ex ÄÌÑ ×uËÏÎÁÎÎÑX
+HaÔÉÓÎiÔØ ENTER ÝÏ ×uËÏÎÁÔÉ ËÏÍÁÎÄÕ, q ÝÏ ×ÉÊÔÉX
+÷×ÅÄiÔØ 'cscope help' ÄÌÑ iÎÆÏÒÍÁÃi§X
+HeÍÁ¤ cscope Ú'¤ÄÎÁÎÎØX
+%s: ÎÅ×iÄÏÍÉÊ ÔÉÐ ÐÏÛÕËÕ: ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ ÏÄÉÎ Ú %sX
+%d: ÎÅÍÁ¤ ÔÁËϧ ceci§ cscopeX
+set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ y×iÍËÎÅÎÏÀX
+set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ × 0X
+%s: ÄÏÄÁÎÏ: %lu pÑÄËi×, %lu cuÍ×ÏÌi×X
+HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÚÍiÎÉ ÒÏÚÍipyX
+%d ÆÁÊÌi× ÄÌÑ ÒÅÄÁÇÕ×ÁÎÎÑX
diff --git a/contrib/nvi/catalog/uk_UA.KOI8-U.base b/contrib/nvi/catalog/uk_UA.KOI8-U.base
new file mode 100644
index 000000000000..fd5da67c3cb9
--- /dev/null
+++ b/contrib/nvi/catalog/uk_UA.KOI8-U.base
@@ -0,0 +1,307 @@
+002 "ðÅÒÅÐÏ×ÎÅÎÎÑ ÚÎÁÞÅÎÎÑ Äo×ÖuÎu pÑÄËy"
+003 "ÎÅÍÏÖÌÉ×Ï ÓÔÅÒÔÉ ÒÑÄÏË %lu"
+004 "ÎÅÍÏÖÌÉ×Ï ÄÏÄÁÔÉ ÄÏ ÒÑÄËÕ %lu"
+005 "ÎÅÍÏÖÌÉ×Ï ×ÓÔÁ×ÉÔÉ × ÒÑÄÏË %lu"
+006 "ÎÅÍÏÖÌÉ×Ï poÚÍiÓÔÉÔÉ ÒÑÄÏË %lu"
+007 "ÎÅÍÏÖÌÉ×Ï ÄiÓÔÁÔu ÏÓÔÁÎÎiÊ ÒÑÄÏË"
+008 "ðÏÍÉÌËÁ: ÎÅÍÏÖÌÉ×Ï oÔpuÍaÔÉ ÒÑÄÏË %lu"
+009 "æÁÊÌ ÚÁÐÉÓi×"
+010 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ×iÄÍiÎÉÔÉ ÏÓÔÁÎÎÀ ËÏÍÁÎÄÕ"
+011 "îÅÍÁ ÞÏÇÏ ×iÄÍiÎÑÔÉ"
+012 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ×iÄÍiÎÉÔÉ ÏÓÔÁÎÎÀ ËÏÍÁÎÄÕ"
+013 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎeÍÏÖÌÉ×Ï ÐÒÏÄÉ×ÉÔÉÓÑ ×ÐÅÒÅÄ"
+014 "îÅÍÁ ÞÏÇÏ ÐÏ×ÔÏÒÀ×ÁÔÉ"
+015 "%s/%d: ÐÏÍÉÌËÁ ÚaÐÉÓy ÐÒÏÔÏËÏÌy"
+016 "CÔÁÎÄÁÒÔÎÉÍ ××ÅÄÅÎÎÑÍ/×É×ÅÄÅÎÎÑÍ ÄÌÑ vi ÍÁ¤ ÂÕÔu ÔÅÒÍiÎÁÌ"
+017 "MiÔËÁ %s: ÎÅ ×ÓÔÁÎÏ×ÌÅÎÏ"
+018 "MiÔËÁ %s: ÒÑÄÏË ÓÔÅÒÔo"
+019 "MiÔËÁ %s: ÐÏÚÉÃi§ ËÕÒÓÏÒy ÂiÌØÛÅ ÎÅ icÎÕ¤"
+020 "ðÏÍÉÌËÁ: "
+021 "Ho×uÊ ÆaÊÌ"
+022 "IÍ'Ñ ÚÍiÎuÌocØ"
+023 "ÚÍiÎÅÎÉÊ"
+024 "Îe ÚÍiÎÅÎÉÊ"
+025 "PO3âìOKOBAHO"
+026 "ÔiÌØËu ÄÌÑ ÞÉÔÁÎÎÑ"
+027 "pÑÄoË %lu Ú %lu [%ld%%]"
+028 "ÐycÔuÊ ÆaÊÌ"
+029 "pÑÄoË %lu"
+030 "æaÊÌ %s ÎÅ ¤ ÆaÊÌoÍ ÐÏ×iÄÏÍÌÅÎÎØ"
+031 "îeÍÏÖÌÉ×Ï ×ÓÔÁÎÏ×ÉÔÉ oÐÃiÀ %s ÚÁ ÚÍÏ×ÞÁÎÎÑÍ"
+032 "BuËopucÔaÎÎÑ: %s"
+033 "ïÐÃi§ %s ÎÅÍa: 'set all' ÐÏËÁÚy¤ ×Ói ÍÏÖÌÉ×i ÏÐÃi§"
+034 "set: [no]%s ÎÅ ÎÁÂÕ×Á¤ ÔÁËÏÇÏ ÚÎÁÞÅÎÎÑ"
+035 "set: %s ÏÐÃiÑ ÎÅ ¤ ÌÏÇiÞÎÏÀ"
+036 "set: ÏÐÃiÑ %s: %s"
+037 "set: ÏÐÃiÑ %s: %s: ÐÅÒÅÐÏ×ÎÅÎÎÑ"
+038 "set: ÎÅÐÒÁ×ÉÌØÎÅ ÚÎÁÞÅÎÎÑ %s"
+039 "set: %s ÏÐÃiÑ ÎÅ ¤ ÌÏÇiÞÎÏÀ"
+040 "ëiÌØËicÔØ ËÏÌÏÎÏË Îa ÜËÒÁÎi ÎÁÄÔÏ ÍÁÌa, ÍÅÎÛÅ ÎiÖ %d"
+041 "ëiÌØËicÔØ ËÏÌÏÎÏË Îa ÜËÒÁÎi ÎÁÄÔÏ ×eÌuËa, ÂiÌØÛe ÎiÖ %d"
+042 "ëiÌØËicÔØ pÑÄËi× Îa ÜËÒÁÎi ÎÁÄÔÏ ÍÁÌa, ÍÅÎÛÅ ÎiÖ %d"
+043 "ëiÌØËicÔØ pÑÄËi× Îa ÜËÒÁÎi ÎÁÄÔÏ ×eÌuËa, ÂiÌØÛe ÎiÖ %d"
+044 "ïÐÃiÑ lisp ×iÄcyÔÎÑ"
+045 "ðÏ×iÄÏÍÌÅÎÎÑ ÎÅ ×uÍËÎÅÎi: %s"
+046 "ðÏ×iÄÏÍÌÅÎÎÑ ÎÅ ××iÍËÎÅÎi: %s"
+048 "ïÐÃiÑ paragraph ÐÏ×ÉÎÎÁ ÍiÓÔÉÔÉ ÇpyÐÉ Ú Ä×ÏÈ ÓÉÍ×oÌi×"
+049 "ïÐÃiÑ section ÐÏ×ÉÎÎÁ ÍiÓÔÉÔÉ ÇpyÐÉ Ú Ä×ÏÈ ÓÉÍ×oÌi×"
+053 "óÔÁÒÔÏ×uÊ ÂÕÆÅÒ ÐopoÖÎiÊ"
+054 "âÕÆÅÒ %s ÐopoÖÎiÊ"
+055 "îeÍÏÖÌÉ×Ï ×iÄÎÏ×uÔÉ ÆÁÊÌ, ÝÏ ÍiÓÔÉÔØ × iÍÅÎi ÓÉÍ×oÌÉ ÐÅÒÅ×eÄeÎÎÑ ËÁÒÅÔËÉ"
+056 "úÍiÎÉ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ×iÄÎÏ×uÔÉ ÐicÌÑ Ëpaxy ceci§"
+057 "KoÐiÀ×ÁÎÎÑ ÆÁÊÌÕ ÄÌÑ ×iÄÎÏ×ÌÅÎÎÑ..."
+058 "úÂÅÒÅÖÅÎÎÑ ÎÅ ×ÄÁÌÏÓØ: %s"
+059 "úÍiÎÉ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ×iÄÎÏ×uÔÉ ÐicÌÑ Ëpaxy ceci§"
+060 "úÂÅÒÅÖÅÎÎÑ ËÏÐi§ ÆÁÊÌy ÎÅ ×ÄÁÌÏÓØ: %s"
+061 "KoÐiÀ×ÁÎÎÑ ÆÁÊÌÕ ÄÌÑ ×iÄÎÏ×ÌÅÎÎÑ..."
+062 "IÎÆÏÒÍÁÃiÀ ÐÒÏ ËopucÔÕ×ÁÞa %u ÎÅ ÚÎÁÊÄÅÎÏ"
+063 "úÁÂÌÏËÕ×ÁÔÉ ×iÄÎÏ×ÌÅÎÎuÊ ÆÁÊÌ ÎeÍÏÖÌÉ×Ï"
+064 "âÕÆÅÒ ×iÄÎÏ×ÌÅÎoÇo ÆÁÊÌy ÐÅÒÅÐÏ×ÎÅÎo"
+065 "÷iÄÎÏ×ÌÅÎÎuÊ ÆÁÊÌ"
+066 "%s: ÆÁÊÌ ×iÄÎÏ×ÌÅÎÎuÊ ÎÅ ÄÏ ËiÎÃÑ"
+067 "%s: ÆÁÊÌ ×iÄÎÏ×ÌÅÎÎuÊ ÎÅ ÄÏ ËiÎÃÑ"
+068 "He icÎyÀ¤ ÆÁÊÌi× Ú iÍÅÎÅÍ %s, ÑËi ÷u ÍÏÖÅÔÅ ÐÒÏÞÉÔÁÔu"
+069 "IcÎyÀÔØ ÓÔÁÒi ×ÅÒÓi§ ÆÁÊÌy, ÑËi ÍÏÖÎÁ ×iÄÎÏ×ÉÔÉ"
+070 "IcÎyÀÔØ iÎÛi ÆÁÊÌu, ÑËi ÍÏÖÎÁ ×iÄÎÏ×ÉÔÉ"
+071 "Å-mail ÎÅ ×iÄicÌaÎo: %s"
+072 "æÁÊÌ ÐÕÓÔuÊ - ÎeÍÁ ÞÏÇo ÛyËaÔÉ"
+073 "äÏÓÑÎÕÔo ËiÎÃÑ ÆÁÊÌy ÂÅÚ ÚÎÁÈÏÖÄÅÎÎÑ ÚpÁÚËy ÐÏÛÕËy"
+074 "îÅ ÚÁÄÁÎo ÚpaÚoË ÐÏÛÕËy"
+075 "úpaÚoË ÐÏÛÕËy ÎÅ ÚÎÁÊÄÅÎo"
+076 "äÏÓÑÎÕÔo ÐÏÞÁÔËy ÆÁÊÌy ÂÅÚ ÚÎÁÈÏÖÄÅÎÎÑ ÚpÁÚËy ÐÏÛÕËy"
+077 "ðÏÛyË ÚÁÃÉËÌÅÎo"
+078 "ðÏÛyË..."
+079 "îÅÐÅÞÁÔÎuÈ ÓÉÍ×ÏÌi× ÎÅ ÚÎÁÊÄÅÎÏ"
+080 "îÅ×iÄoÍa ËÏÍÁÎÄÁ"
+082 "%s: ËÏÍÁÎÄÁ ÎÅ ÄÏÓÔÕÐÎÁ × ÒÅÖÉÍi ex"
+083 "ìiÞÉÌØÎÉË ÎÅ ÍÏÖÅ ÂyÔu ÎÕÌÅÍ"
+084 "%s: ÎÅÐÒÁ×ÉÌØÎÅ ×uÚÎÁÞÅÎÎÑ pÑÄËÕ"
+085 "÷ÎÕÔÒiÛÎÑ ÐÏÍÉÌËÁ × ÓÉÎÔÁËÓÉÓi (%s: %s)"
+086 "BuËopucÔaÎÎÑ: %s"
+087 "%s: ÔÉÍÞÁÓÏ×ÉÊ ÂÕÆÅÒ ÎÅ ×uËÏpÉÓÔÁÎÏ"
+088 "MiÔËy ÐÏÓÔÁ×ÌÅÎo ÐÅÒÅÄ ÐÅÒÛÉÍ ÒÑÄËÏÍ"
+089 "MiÔËy ÐÏÓÔÁ×ÌÅÎo ÐicÌÑ ËiÎÃÑ ÆÁÊÌÕ"
+090 "@ Ú ÄiÁÐÁÚÏÎÏÍ ÐÒÁÃÀ¤ ËÏÌÉ ÚÍiÎÅÎÏ ÆÁÊÌ/×iËÎÏ"
+091 "ëÏÍÁÎÄÁ Global/v ÐÒÁÃÀ¤ ËÏÌÉ ÚÍiÎÅÎÏ ÆÁÊÌ/×iËÎÏ"
+092 "ëÏÍÁÎÄÁ ex ÎÅ ×ÄÁÌÁÓØ: ÎÁÓÔÕÐÎi ËÏÍÁÎÄÉ Ú'iÇÎÏÒÏ×ÁÎÏ"
+093 "ëÏÍÁÎÄÁ ex ÎÅ ×ÄÁÌÁÓØ: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏ"
+094 "äpyÇÁ ÁÄÒÅÓa ÍÅÎÛÅ ÎiÖ ÐÅÒÛa"
+095 "He ×ËÁÚÁÎÏ iÍ'Ñ ÍiÔËÉ"
+096 "\\ ÎÅ ÚÁËiÎÞÕ¤ÔØÓÑ / Þu ?"
+097 "ðoÓÉÌÁÎÎÑ ÎÁ pÑÄÏË Ú ÎoÍÅpoÍ, ÍÅÎÛÉÍ ÎiÖ 0"
+098 "ëÏÍÁÎÄÁ %s ÎÅ×iÄÏÍa"
+099 "ðÅÒÅÐÏ×ÎÅÎÎÑ ÌiÞuÌØÎÉËÁ aÄpec"
+100 "îÅÄÏÂiÒ ÌiÞuÌØÎÉËÁ aÄpec"
+101 "îÅÄÏÐÕÓÔÉÍÁ ËÏÍÂiÎÁÃiÑ × ÁÄÒÅÓi"
+102 "îÅÐÒÁ×ÉÌØÎa ÁÄÒÅÓa: ×ÓØoÇÏ %lu pÑÄËi× y ÆÁÊÌi"
+103 "îÅÐÒÁ×ÉÌØÎa ÁÄÒÅÓa: ÆÁÊÌ ÐÕÓÔuÊ"
+104 "ëÏÍÁÎÄÁ %s ÎÅ ÍÏÖÅ ×ÉËopucÔo×Õ×ÁÔu ÁÄÒÅÓy 0"
+105 "îÅÍÁ¤ ÁÂÒÅ×iÁÔÕÒ"
+106 "áÂÒÅ×iÁÔÕÒu ÐÏ×ÉÎÎi ÚÁËiÎÞÕ×ÁÔÉÓÑ ÓÉÍ×ÏÌÏÍ "word""
+107 "B ÁÂÒÅ×iÁÔÕÒi ÎÅ ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÉÍ×ÏÌÉ ÔÁÂÕÌÑÃi§ ÔÁ ÐÒÏÂiÌÉ"
+108 "áÂÒÅ×iÁÔÕÒu ÎÅ ÍÏÖyÔØ ÚÍiÛÕ×ÁÔÉ ÓÉÍ×ÏÌÉ ÓÌi×/ÎÅ-ÓÌi×, xiÂÁ Ýo × ËiÎÃi pÑÄËÕ"
+109 ""%s" ÎÅ ÁÂÒÅ×iÁÔÕÒa"
+110 "ëÏÍÁÎÄÁ Vi ÎÅ ×ÄÁÌÁÓØ: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏ"
+111 "æÁÊÌi× ÄÌÑ ÒÅÄÁÇy×aÎÎÑ ÂiÌØÛÅ ÎÅÍa¤"
+112 "ðÏÐÅÒÅÄÎØÏÇÏ ÆaÊÌy ÄÌÑ ÒÅÄÁÇy×aÎÎÑ ÎÅÍa¤"
+113 "ðÏÐÅÒÅÄÎØÏÇÏ ÆaÊÌy ÄÌÑ ÐÅÒeÇÌÑÄy ÎÅÍa¤"
+114 "îÅÍa¤ ÆÁÊÌi×"
+115 "HeÍÁ¤ ÐÏÐÅÒÅÄÎØÏ§ ËÏÍÁÎÄÉ ÄÌÑ ÚÁÍiÎÉ "!""
+116 "÷iÄÓyÔΤ iÍ'Ñ ÆÁÊÌÕ ÄÌÑ ÐiÄÍiÎÉ %%"
+117 "÷iÄÓyÔΤ iÍ'Ñ ÆÁÊÌÕ ÄÌÑ ÐiÄÍiÎÉ #"
+118 "ðÏÍÉÌËÁ: execl: %s"
+119 "ðÏÍÉÌËÁ ××ÅÄÅÎÎÑ/×É×ÅÄÅÎÎÑ: %s"
+120 "æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÐÏ×ÎÏÇÏ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+121 "îÅÍÏÖÌu×Ï ÚÎÁÊÔÉ ÄÏÍÁÛÎiÊ ËÁÔÁÌÏÇ"
+122 "îÏ×uÊ ËÁÔÁÌÏÇ: %s"
+123 "HeÍÁ¤ ÎÁÐÏ×ÎÅÎÉÈ ÂÕÆÅÒi×"
+124 "KoÍÁÎÄa %s ÎÅ ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ ÑË ÞÁÓÔÉÎÁ ËÏÍÁÎÄÉ global ÞÉ v"
+125 "%s/%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ ÞÉ aÄÍiÎicÔpaÔopÕ"
+126 "%s/%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ"
+127 "%s/%s: ÎÅ ×iÄËpuÔo: ÍÏÖÌu×iÓÔØ ÚÁÐÉÓy ËopucÔÕ×ÁÞÅÍ, ÑËÉÊ ÎÅ ¤ ×ÌÁÓÎÉËÏÍ"
+128 "%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ ÞÉ aÄÍiÎicÔpaÔopÕ"
+129 "%s: ÎÅ ×iÄËpuÔo: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ"
+130 "%s: ÎÅ ×iÄËpuÔo: ÍÏÖÌu×iÓÔØ ÚÁÐÉÓy ËopucÔÕ×ÁÞÅÍ, ÑËÉÊ ÎÅ ¤ ×ÌÁÓÎÉËÏÍ"
+131 "HeÍÁ¤ ÂiÌØÛÅ pÑÄËi× ÄÌÑ ÏÂ'¤ÄÎÁÎÎÑ"
+132 "HeÍÁ¤ ÐÁÒÁÍÅÔÒi× ××eÄeÎÎÑ"
+133 "HeÍÁ¤ ÐÁÒÁÍÅÔÒi× ËÏÍÁÎÄu"
+134 "óÉÍ×ÏÌ %s ÎÅ ÍÏÖÎÁ ÐÅÒÅÎÁÚÎÁÞuÔÉ"
+135 ""%s" ÚÁÒÁÚ ÎÅ ÐÅÒÅÎÁÚÎÁÞeÎo"
+136 "IÍ'Ñ ÍiÔËÉ -- ÏÄÉÎ ÓÉÍ×ÏÌ"
+137 "%s icÎÕ¤, ÎÅ ÚÁÐÉÓÁÎo; ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+138 "îÏ×uÊ ÆÁÊÌ exrc: %s"
+139 "PÑÄÏË ÐÒÉÚÎÁÞÅÎÎÑ ÚÁÚÎÁÞÅÎÏ ×ÓÅÒÅÄÉÎi ÄiÁÐÁÚÏÎy ÐÅÒÅÍiÝÅÎÎÑ"
+140 "ëÏÍÁÎÄa open ×ÉÍÁÇÁ¤ ×ÓÔÁÎÏ×ÌÅÎÎÑ oÐÃi§ open"
+141 "ëÏÍÁÎÄy open ÝÅ ÎÅ ÒÅÁÌiÚÏ×ÁÎÏ"
+142 "úÁxÉcÔ ÆÁÊÌy ÎÅÍÏÖÌu×uÊ"
+143 "æÁÊÌ ÚÁxÉÝÅÎo"
+144 "%s ÒoÚÛÉÒÉ×ÓÑ × ÎÁÄÔÏ ×ÅÌÉËÕ ËiÌØËiÓÔØ iÍÅÎ ÆÁÊÌi×"
+145 "ðÒÏÞÉÔÁÔÉ ÍÏÖÎÁ ÔiÌØËÉ ÐÒÏÓÔÉÊ ÆÁÊÌ ÞÉ iÍÅÎÏ×ÁÎÉÊ ËÁÎÁÌ(pipe)"
+146 "%s: ÂÌÏËÕ×ÁÎÎÑ ×iÄ ÞÉÔÁÎÎÑ ÎÅÍÏÖÌÉ×Å"
+147 "úÞuÔyÀ..."
+148 "%s: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×"
+149 "îÅÍÁ¤ ÔiÎØo×uÈ ×iËÏÎ"
+150 "ëÏÍÁÎÄa script ÄÏÓÔÕÐÎÁ ÌÉÛÅ × peÖÉÍi vi"
+151 "îÅÍÁ ËÏÍÁÎÄu ÄÌÑ ×ÉËoÎaÎÎÑ"
+152 "ïÐÃiÀ shiftwidth ×ÓÔÁÎÏ×ÌÅÎo × 0"
+153 "ðÅÒÅÐÏ×ÎÅÎÎÑ ÌiÞuÌØÎÉËÁ"
+154 "ãÉËÌ ×uËoÎaÎo ÎÅ ÄÏ ËiÎÃÑ"
+155 "BËÁÚÁÎÏ peÇyÌÑÒÎÉÊ ×ÉÒÁÚ; ÐÁÒÁÍÅÔÒ 'r' ÎÅ ÍÁ¤ ÓÅÎÓÕ"
+156 "ðÁÒÁÍÅÔÒu #, l Ôa p ÎÅ ÍÏÖÎÁ ËÏÍÂiÎÕ×ÁÔÉ Ú ÐÁÒÁÍÅÔÒÏÍ 'c' × peÖÉÍi vi"
+157 "CÐi×ÐÁÄaÎØ ÎÅÍa¤"
+158 "TeÇ ×iÄÓÕÔÎiÊ"
+159 "MeÎÛÅ ÎiÖ %s ÚÁÐÉÓi× Õ ÓÔÅËÕ ÔÅÇi×; ×uËopucÔaÊÔÅ :display t[ags]"
+160 "HeÍÁ¤ ÆÁÊÌÕ %s × ÓÔÅËÕ ÔÅÇi× ÄÌÑ ÐÏ×ÅÒÎÅÎÎÑ; ×uËopucÔaÊÔÅ :display t[ags]"
+161 "HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ: "
+162 "%s: ÔeÇ ÎÅ ÚÎÁÊÄÅÎo"
+163 "%s: ÚiÐÓo×ÁÎÉÊ ÔÅÇ × %s"
+164 "%s: ÎÏÍÅÒ ÒÑÄËÕ ÔÅÇÁ ÚÎÁÈÏÄÉÔØÓÑ ÚÁ ËiÎÃÅÍ ÆÁÊÌÕ"
+165 "CÔÅË ÔeÇi× ÐÏÒÏÖÎiÊ"
+166 "%s: ÚpaÚoË ÐÏÛÕËy ÎÅ ÚÎÁÊÄÅÎo"
+167 "úaÌÉÛÉÌÏÓØ %d ÆÁÊÌi× ÄÌÑ ÒÅÄÁÇÕ×ÁÎÎÑ"
+168 "âÕÆÅÒ %s ÐopoÖÎiÊ"
+169 "úÍiÎuÔu? [n]"
+170 "ðeÒÅÒ×ÁÎÏ"
+171 "HeÍa¤ ÂÕÆÅÒy ÄÌÑ ×uËopucÔaÎÎÑ"
+172 "îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×uÒÁÚy"
+173 "ëÏÍÁÎÄa %s ×ÉÍÁÇÁ¤ ×ÖÅ ÐÒÏÞÉÔÁÎÉÊ ÆÁÊÌ"
+174 "BuËopucÔaÎÎÑ: %s"
+175 "ëÏÍÁÎÄa visual ×ÉÍÁÇÁ¤ ×ÓÔÁÎÏ×ÌÅÎÎÑ oÐÃi§ open"
+177 "ðÕÓÔuÊ ÆÁÊÌ"
+178 "îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÐÏÛyËy F, f, T, ÞÉ t"
+179 "%s ÎÅ ÚÎÁÊÄÅÎÏ"
+180 "îÅÍÁ¤ ÐÏÐÅÒÅÄÎØoÇÏ ÆÁÊÌy ÄÌÑ ÒÅÄÁÇy×ÁÎÎÑ"
+181 "Kypcop cÔÏ§ÔØ Îe ÎÁ ÃuÆpi"
+182 "OÔÒÉÍÁÎÅ ÞÉÓÌÏ ÎÁÄÔÏ ×ÅÌÉËe"
+183 "OÔÒÉÍÁÎÅ ÞÉÓÌÏ ÎÁÄÔÏ ÍaÌe"
+184 "HeÍa¤ ×iÄÐo×iÄÎoÇo cÉÍ×ÏÌÕ × ÃØÏÍÕ ÒÑÄËÕ"
+185 "÷iÄÐo×iÄÎuÊ cÉÍ×ÏÌ Îe ÚÎÁÊÄÅÎÏ"
+186 "îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ÚaÍiÎu"
+187 "îÅÍa¤ iÎÛoÇo ×iËÎÁ"
+188 "óÉÍ×ÏÌu ÐiÓÌÑ pÑÄËÕ ÄÌÑ ÐÏÛÕËÕ, ÚÍiÝÅÎÎÑ pÑÄËÕ ÔÁ/ÞÉ ËÏÍÁÎÄÉ z"
+189 "îÅÍa¤ ÐÏÐÅÒÅÄÎØÏÇÏ ÚpaÚËy ÐÏÛÕËy"
+190 "ðÏÛÕË ÚÁËiÎÞÉ×ÓÑ ÎÁ ÐÏÞÁÔËÏ×iÊ ÐÏÚÉÃi§"
+191 "áÂÒÅ×iÁÔÕÒa ÐÅÒÅ×ÉÝÉÌÁ ÌiÍiÔ ÒÏÚÛÉÒÅÎÎÑ: ÓÉÍ×ÏÌu Ú'iÇÎÏÒÏ×ÁÎÏ"
+192 "HeÄÏÚ×ÏÌÅÎÉÊ ÓÉÍ×ÏÌ: ÚÁÄÁÊÔÅ × ÄÕÖËÁÈ"
+193 "BÖÅ ÎÁ ÐÏÞÁÔËÕ ×ÓÔÁ×ËÉ"
+194 "îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ×uÄaÌeÎÎÑ"
+195 "Pyx ÚÁ ËiÎÅÃØ ÆÁÊÌy"
+196 "Pyx ÚÁ ËiÎÅÃØ ÒÑÄËy"
+197 "Kypcop ÎÅ ÐÅÒÅÍiÝÕ×Á×ÓÑ"
+198 "BÖÅ ÎÁ ÐÏÞaÔËÕ ÆÁÊÌy"
+199 "Pyx ËÕÒÓÏÒy ÚÁ ÐÏÞaÔoË ÆÁÊÌy"
+200 "BÖÅ × ÐÅpÛiÊ ËÏÌÏÎÃi"
+201 "âÕÆÅÒ ÔÒÅÂÁ ×ËÁÚÕ×ÁÔÉ ÐÅÒÅÄ ËÏÍÁÎÄÏÀ"
+202 "BÖÅ ÎÁ ËiÎÃi ÆÁÊÌy"
+203 "BÖÅ ÎÁ ËiÎÃi ÒÑÄËy"
+204 "%s ÎÅ ËÏÍÁÎÄa Vi"
+205 "BuËopucÔaÎÎÑ: %s"
+206 "îÅÍa¤ ÓÉÍ×ÏÌi× ÄÌÑ ×uÄaÌeÎÎÑ"
+207 "ëÏÍÁÎÄa Q ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ ex"
+208 "îÅÍÁ¤ ËÏÍÁÎÄu ÄÌÑ ÐÏ×ÔÏÒÅÎÎÑ"
+209 "æaÊÌ ÐÕÓÔÉÊ"
+210 "ëÏÍÁÎÄy %s ÎÅ ÍÏÖÎa ×ÉËÏÒÉÓÔÁÔÉ ÄÌÑ ÐÅÒÅÍiÝÅÎÎÑ"
+211 "BÖÅ × ËÏÍÁÎÄÎÏÍy ÒÅÖÉÍi"
+212 "Kypcop cÔÏ§ÔØ Îe ÎÁ cÌo×i"
+214 "úÎÁÞÎÅÎÎÑ ÏÐÃi§ Windows ÎÁÄÔÏ ×ÅÌÉËÅ, ÍÁËÓÉÍÕÍ = %u"
+215 "äoÐucaÔu"
+216 "úÍiÎuÔu"
+217 "KoÍaÎÄa"
+218 "BcÔa×uÔu"
+219 "úaÍiÎuÔu"
+220 "Pyx ËÕÒÓÏÒy ÚÁ ËiÎÅÃØ ÜËÒÁÎy"
+221 "Pyx ËÕÒÓÏÒy ÚÁ ÐÏÞaÔoË ÜËÒÁÎy"
+222 "äÌÑ ÒÏÚÂÉÔÔÑ ×iËÎo ÍÁ¤ ÍiÓÔÉÔÉ ÂiÌØÛÅ ÎiÖ %d pÑÄËi×"
+223 "ôiÎØo×uÈ ×iËÏÎ ÎÅÍÁ¤"
+224 "HeÍa¤ ÔiÎØo×oÇo ×iËÎa Ú peÄÁÇÕ×ÁÎÎÑÍ ÆÁÊÌÕ %s"
+225 "He ÍÏÖÎÁ ÚpoÂÉÔÉ ÔiÎØÏ×uÍ ¤ÄÉÎÅ ×iËÎÏ"
+226 "÷iËÎÏ ÍÏÖÎÁ ÓÔÉÓÎÕÔÉ ÌÉÛÅ ÄÏ %d pÑÄËi×"
+227 "÷iËÎÏ ÎÅ ÍÏÖÎÁ ÓÔÉÓÎÕÔÉ"
+228 "÷iËÎÏ ÎÅ ÍÏÖÎÁ poÚÛÉÒÉÔÉ"
+230 "ãe ×iËÎÏ ÎÅ ÍÏÖÎÁ ÐÒÉÚÕÐÉÎÉÔÉ"
+231 "ðÅÒÅÒ×ÁÎo: ×iÄÏÂÒÁÖÅÎi ËÌÁ×iÛi Ú'iÇÎÏÒÏ×ÁÎÏ"
+232 "vi: ÔÉÍÞÁÓÏ×ÉÊ ÂÕÆÕÒ ÎÅ ×É×iÌØÎÅÎÏ"
+233 "ãeÊ ÔÉÐ ÔÅÒÍiÎÁÌy ÎÅÍa¤ ËÌÁ×iÛi %s"
+234 "MoÖÎÁ ×ËÁÚÁÔÉ ÌÉÛÅ ÏÄÉÎ ÂÕÆÅÒ"
+235 "þÉÓÌÏ ÂiÌØÛÅ, ÎiÖ %lu"
+236 "ðÅÒÅÒ×ÁÎo"
+237 "îÅÍÏÖÌy cÔ×ÏÒÉÔÉ ÔÉÍÞÁÓÏ×ÉÊ ÆÁÊÌ"
+238 "õBAçA: %s ÓÐÅÃiÁÌØÎuÊ ÆÁÊÌ"
+239 "%s ×ÖÅ ÚÁÂÌÏËo×ÁÎo, ÄÏÓÔÕÐÎuÊ ÔiÌØËu ÄÌÑ ÞÉÔÁÎÎÑ"
+240 "%s: cÔepÔo"
+241 "%s: ÚÁËÒuÔo"
+242 "%s: cÔepÔo"
+243 "%s: cÔepÔo"
+244 "æÁÊÌ ÔiÌØËu ÄÌÑ ÞuÔaÎÎÑ, ÎÅ ÚÁÐÉÓÁÎo: BuËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+245 "æÁÊÌ ÔiÌØËu ÄÌÑ ÞuÔaÎÎÑ, ÎÅ ÚÁÐÉÓÁÎo"
+246 "%s icÎy¤, ÎÅ ÚÁÐÉÓÁÎo; ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+247 "%s icÎy¤, ÎÅ ÚÁÐÉÓÁÎo"
+248 "BuËopucÔaÊÔÅ ! ÄÌÑ ÞÁÓÔËÏ×oÇo ÚÁÐÉÓy ÆÁÊÌy"
+249 "þÁÓÔuÎa ÆÁÊÌy, ÆÁÊÌ ÎÅ ÚÁÐÉÓÁÎo"
+250 "%s: æÁÊÌ ÚÍiÎÀ×Á×ÓÑ ÐiÚÎiÛÅ, ÎiÖ ÃÑ ËÏÐiÑ: ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+251 "%s: æÁÊÌ ÚÍiÎÀ×Á×ÓÑ ÐiÚÎiÛÅ, ÎiÖ ÃÑ ËÏÐiÑ"
+252 "%s: ÚÁxÉcÔ ×iÄ ÚÁÐÉÓy ÎÅÄÏÓÔÕÐÎuÊ"
+253 "úaÐÉÓ..."
+254 "%s: õBAçA: ÆÁÊÌ oÂpiÚaÎo"
+255 "BÖÅ ÎÁ ÐÅÒÛÏÍÕ ÔÅÇÕ × ÃiÊ ÇÒÕÐi"
+256 "%s: ÎÏ×uÊ ÆÁÊÌ: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×"
+257 "%s: %lu ÒÑÄËi×, %lu ÓÉÍ×ÏÌi×"
+258 "%s ÒoÚÛÉÒÉ×ÓÑ × ÎÁÄÔÏ ×ÅÌÉËÕ ËiÌØËiÓÔØ iÍÅÎ ÆÁÊÌi×"
+259 "%s: ÓÐÅÃiÁÌØÎuÊ ÆÁÊÌ"
+260 "%s: ÎÅ ÎÁÌÅÖÉÔØ ÷ÁÍ"
+261 "%s: ÄÏÓÔÕÐÎuÊ ÎÅ ÌuÛe ÷ÁÍ
+262 "æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+263 "æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ :edit ÄÌÑ ÏÂÈÏÄy"
+264 "æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy: ÚÂepeÖiÔØ ÞÉ ×uËopucÔaÊÔÅ ! ÄÌÑ ÏÂÈÏÄy"
+265 "ôÉÍÞÁÓÏ×ÉÊ ÆÁÊÌ: ×uÈiÄ ÚiÔÒÅ ÚÍiÎÉ"
+266 "æÁÊÌ ÔiÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ, ÚÍiÎÉ ÎÅ ÚÁÐÉÛÕÔØÓÑ Á×ÔÏÍÁÔÉÞÎÏ"
+267 "úÁÐÉÓÉ ÐÏÞÁÔi ÚÁÎÏ×Ï"
+268 "ðiÄÔ×ÅÒÄÖÕ¤ÔÅ? [ynq]"
+269 "HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ: "
+270 "HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ [: ÄÌÑ iÎÛux ËoÍÁÎÄ] "
+271 "HaÔÉÓÎiÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ [q ÄÌÑ ×uxoÄy]: "
+272 "TaËÁ ÆÏÒÍÁ %s ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ ex"
+273 "BxoÄÉÍ × peÖÉÍ ××ÅÄÅÎÎÑ ex"
+274 "úÂiÊ ËÏÍÁÎÄÉ, ÆÁÊÌ ÎÅ ÐÒÏÞÉÔÁÎÏ"
+275 "ðÒÏÄÏ×ÖÉÔÉ?"
+276 "HeoÞiËÕ×ÁÎÁ cuÍ×ÏÌØÎÁ ÐÏÄiÑ"
+277 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ËiÎÃÑ ÆÁÊÌÕ"
+278 "HeÍÁ¤ ÓÐi×ÐÁÄÁÎØ ÚÁ ÚÁÐÉÔÏÍ"
+279 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÐÅÒÅÒÉ×ÁÎÎÑ"
+280 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ×uxoÄy"
+281 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÐÅÒÅÒÉÓo×Ëu"
+282 "BÖÅ ÎÁ ÏÓÔÁÎÎØÍÕ ôÅÇÕ × ÃiÊ ÇpyÐi"
+283 "KoÍÁÎÄÁ %s ×ÉÍÁÇÁ¤ iÎÔÅÒÆÅÊÓÕ ex"
+284 "TaËÁ ÆÏÒÍÁ %s ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure edit"
+285 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ pÑÄËy"
+286 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÔÁÊÍ-ÁÕÔÕ"
+287 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÚaÐucy"
+289 "Shell'i×ÓËÅ ÄÏÐÏ×ÎÅÎÎÑ ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure edit"
+290 "KoÍÁÎÄÁ %s ÎÅ ÄÏÚ×ÏÌÑ¤ÔØÓÑ ÐÒÉ ×ÓÔÁÎÏ×ÌÅÎiÊ ÏÐÃi§ secure edit"
+291 "set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ ×uÍËÎÅÎÏÀ"
+292 "åËÒÁÎ ÎÁÄÔÏ ÍÁÌuÊ."
+293 "ÄÏÄÁÎÏ"
+294 "ÚÍiÎÅÎo"
+295 "ÓÔÅÒÔÏ"
+296 "oÂ'¤ÄÎÁÎÏ"
+297 "ÐÅÒÅÍiÝÅÎÏ"
+298 "ÚÄ×ÉÎÕÔÏ"
+299 "×cÔÁ×ÌÅÎÏ"
+300 "pÑÄÏË"
+301 "pÑÄËi×"
+302 "Vi ÚÁ×ÁÎÔÁÖÅÎÏ ÂÅÚ iÎÔÅÒÐÒÅÔÁÔÏÒa Tcl"
+303 "æÁÊÌ ÍÏÄÉÆiËÏ×ÁÎÏ ÐiÓÌÑ ÏÓÔÁÎÎØÏ§ ËoÍÁÎÄÉ ÚÁÐÉÓy."
+304 "îÅ×ÄÁÞÁ shell'i×ÓØËÏÇÏ ÄÏÐÏ×ÎÅÎÎÑ"
+305 "OÐÃi§ peÄÁÇÕ×ÁÎÎÑ %s ÎÅ ×ËÁÚÁÎÏ"
+306 "Vi ÚÁ×ÁÎÔÁÖÅÎÏ ÂÅÚ iÎÔÅÒÐÒÅÔÁÔÏÒa Perl"
+307 "HeÍÁ¤ ËÏÍÁÎÄÉ ex ÄÌÑ ×uËÏÎÁÎÎÑ"
+308 "HaÔÉÓÎiÔØ ENTER ÝÏ ×uËÏÎÁÔÉ ËÏÍÁÎÄÕ, q ÝÏ ×ÉÊÔÉ"
+309 "÷×ÅÄiÔØ 'cscope help' ÄÌÑ iÎÆÏÒÍÁÃi§"
+310 "HeÍÁ¤ cscope Ú'¤ÄÎÁÎÎØ"
+311 "%s: ÎÅ×iÄÏÍÉÊ ÔÉÐ ÐÏÛÕËÕ: ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ ÏÄÉÎ Ú %s"
+312 "%d: ÎÅÍÁ¤ ÔÁËϧ ceci§ cscope"
+313 "set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ y×iÍËÎÅÎÏÀ"
+314 "set: oÐÃiÀ %s ÎÅÍÏÖÎa ×ÉÓÔÁ×uÔÉ × 0"
+315 "%s: ÄÏÄÁÎÏ: %lu pÑÄËi×, %lu cuÍ×ÏÌi×"
+316 "HeoÞiËÕ×ÁÎÁ ÐÏÄiÑ ÚÍiÎÉ ÒÏÚÍipy"
+317 "%d ÆÁÊÌi× ÄÌÑ ÒÅÄÁÇÕ×ÁÎÎÑ"
diff --git a/contrib/nvi/catalog/uk_UA.KOI8-U.owner b/contrib/nvi/catalog/uk_UA.KOI8-U.owner
new file mode 100644
index 000000000000..11719baa95ff
--- /dev/null
+++ b/contrib/nvi/catalog/uk_UA.KOI8-U.owner
@@ -0,0 +1 @@
+Olexander Kunytsa aka Cawko Xakep <xakep@snark.ukma.kiev.ua>
diff --git a/gnu/usr.bin/awk/config.h b/gnu/usr.bin/awk/config.h
new file mode 100644
index 000000000000..df6c5f057891
--- /dev/null
+++ b/gnu/usr.bin/awk/config.h
@@ -0,0 +1,230 @@
+/* config.h. Generated automatically by configure. */
+/* configh.in. Generated automatically from configure.in by autoheader. */
+/*
+ * acconfig.h -- configuration definitions for gawk.
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright (C) 1995-2000 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define if type char is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+/* #undef __CHAR_UNSIGNED__ */
+#endif
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to the type of elements in the array set by `getgroups'.
+ Usually this is either `int' or `gid_t'. */
+#define GETGROUPS_T gid_t
+
+/* Define if the `getpgrp' function takes no argument. */
+#define GETPGRP_VOID 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#define HAVE_STRINGIZE 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if your struct tm has tm_zone. */
+#define HAVE_TM_ZONE 1
+
+/* Define if you don't have tm_zone but do have the external array
+ tzname. */
+/* #undef HAVE_TZNAME */
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your <sys/time.h> declares struct tm. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+#define HAVE_STRINGIZE 1 /* can use ANSI # operator in cpp */
+#define REGEX_MALLOC 1 /* use malloc instead of alloca in regex.c */
+#define SPRINTF_RET int /* return type of sprintf */
+/* #undef BITOPS */ /* bitwise ops (undocumented feature) */
+/* #undef NONDECDATA */ /* non-decimal input data (undocumented feature) */
+/* #undef _FILE_OFFSET_BITS */ /* bits in a file offset, where this matters */
+/* #undef _LARGEFILE_SOURCE */ /* makes fseeko etc. visible on some hosts */
+/* #undef _LARGE_FILES */ /* emables large files on AIX-style hosts */
+
+/* Define if you have the fmod function. */
+#define HAVE_FMOD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the madvise function. */
+#define HAVE_MADVISE 1
+
+/* Define if you have the memcmp function. */
+#define HAVE_MEMCMP 1
+
+/* Define if you have the memcpy function. */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memset function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the strtod function. */
+#define HAVE_STRTOD 1
+
+/* Define if you have the system function. */
+#define HAVE_SYSTEM 1
+
+/* Define if you have the tzset function. */
+#define HAVE_TZSET 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <signum.h> header file. */
+/* #undef HAVE_SIGNUM_H */
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+/* #undef HAVE_STRINGS_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the m library (-lm). */
+#define HAVE_LIBM 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to make ftello visible on some hosts (e.g. HP-UX 10.20). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to make ftello visible on some hosts (e.g. glibc 2.1.3). */
+/* #undef _XOPEN_SOURCE */
+
+
+#include <custom.h> /* overrides for stuff autoconf can't deal with */
diff --git a/lib/libutil/login_crypt.c b/lib/libutil/login_crypt.c
new file mode 100644
index 000000000000..b291100e335d
--- /dev/null
+++ b/lib/libutil/login_crypt.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2000 Brian Fundakowski Feldman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <login_cap.h>
+#include <unistd.h>
+
+#pragma weak crypt_set_format
+int
+crypt_set_format(const char *f) {
+ return (0);
+}
+
+const char *
+login_setcryptfmt(login_cap_t *lc, const char *def, const char *error) {
+ const char *cipher;
+
+ cipher = login_getcapstr(lc, "passwd_format", def, NULL);
+ if (cipher == NULL)
+ return (error);
+ if (!crypt_set_format(cipher))
+ return (error);
+ return (cipher);
+}
diff --git a/share/man/man4/mly.4 b/share/man/man4/mly.4
new file mode 100644
index 000000000000..40e6e4bbe032
--- /dev/null
+++ b/share/man/man4/mly.4
@@ -0,0 +1,256 @@
+.\"
+.\" Copyright (c) 2000 Michael Smith
+.\" Copyright (c) 2000 BSDi
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 22, 2000
+.Dt MLY 4
+.Os
+.Sh NAME
+.Nm mly
+.Nd Mylex AcceleRAID/eXtremeRAID family driver
+.Sh SYNOPSIS
+.Cd device pci
+.Cd device mly
+.Cd device scbus
+.Cd device da
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for Mylex AcceleRAID and eXtremeRAID-family
+PCI to SCSI RAID controllers with version 6.00 and later
+firmware.
+Supported controllers include:
+.Bl -bullet
+.It
+AcceleRAID 160
+.It
+AcceleRAID 170
+.It
+AcceleRAID 352
+.It
+eXtremeRAID 2000
+.It
+eXtremeRAID 3000
+.El
+.Pp
+Compatible Mylex controllers not listed should work, but have not been
+verified.
+.Pp
+Logical devices (array drives) attached to the controller are presented
+to the SCSI subsystem as though they were direct-access devices on a
+virtual SCSI bus.
+Physical devices which are not claimed by a logical
+device are presented on SCSI channels which match the physical channels
+on the controller.
+.Sh DIAGNOSTICS
+.Ss Controller initialisation phase
+.Bl -diag
+.It "mly%d: controller initialisation started"
+.It "mly%d: initialisation complete"
+.Pp
+The controller firmware has started initialisation.
+Normally this process is performed by the controller BIOS,
+but the driver may need
+to do this in cases where the BIOS has failed, or is not compatible
+(e.g. on non-x86 systems).
+.It "mly%d: drive spinup in progress"
+.Pp
+Drive startup is in progress; this may take several minutes.
+.It "mly%d: mirror race recovery failed, one or more drives offline"
+.It "mly%d: mirror race recovery in progress"
+.It "mly%d: mirror race recovery on a critical drive"
+.Pp
+These error codes are undocumented.
+.It "mly%d: FATAL MEMORY PARITY ERROR"
+.Pp
+Firmware detected a fatal memory error; the driver will not attempt to
+attach to this controller.
+.It "mly%d: unknown initialisation code %x"
+.Pp
+An unknown error occurred during initialisation; it will be ignored.
+.El
+.Ss Driver initialisation/shutdown phase
+.Bl -diag
+.It "mly%d: can't enable busmaster feature"
+.It "mly%d: memory window not available"
+.It "mly%d: can't allocate register window"
+.It "mly%d: can't allocate interrupt"
+.It "mly%d: can't set up interrupt"
+.Pp
+The system's PCI BIOS has not correctly configured the controller's
+PCI interface; initialisation has failed and the driver will not
+attach to this controller.
+.It "mly%d: can't allocate parent DMA tag"
+.It "mly%d: can't allocate buffer DMA tag"
+.It "mly%d: can't allocate command packet DMA tag"
+.It "mly%d: can't allocate scatter/gather DMA tag"
+.It "mly%d: can't allocate s/g table"
+.It "mly%d: can't allocate memory mailbox DMA tag"
+.It "mly%d: can't allocate memory mailbox"
+.Pp
+A resource allocation error occurred while initialising the driver;
+initialisation has failed and the driver will not attach to this
+controller.
+.It "mly%d: BTL rescan result corrupted"
+.Pp
+The results of a scan for an attached device were corrupted.
+One or more devices may not be correctly reported.
+.It "mly%d: flushing cache..."
+.Pp
+The controller cache is being flushed prior to detach or shutdown.
+.El
+.Ss Operational diagnostics
+.Bl -diag
+.It "mly%d: physical device %d:%d online"
+.It "mly%d: physical device %d:%d standby"
+.It "mly%d: physical device %d:%d automatic rebuild started"
+.It "mly%d: physical device %d:%d manual rebuild started"
+.It "mly%d: physical device %d:%d rebuild completed"
+.It "mly%d: physical device %d:%d rebuild cancelled"
+.It "mly%d: physical device %d:%d rebuild failed for unknown reasons"
+.It "mly%d: physical device %d:%d rebuild failed due to new physical device"
+.It "mly%d: physical device %d:%d rebuild failed due to logical drive failure"
+.It "mly%d: physical device %d:%d found"
+.It "mly%d: physical device %d:%d gone"
+.It "mly%d: physical device %d:%d unconfigured"
+.It "mly%d: physical device %d:%d expand capacity started"
+.It "mly%d: physical device %d:%d expand capacity completed"
+.It "mly%d: physical device %d:%d expand capacity failed"
+.It "mly%d: physical device %d:%d parity error"
+.It "mly%d: physical device %d:%d soft error"
+.It "mly%d: physical device %d:%d miscellaneous error"
+.It "mly%d: physical device %d:%d reset"
+.It "mly%d: physical device %d:%d active spare found"
+.It "mly%d: physical device %d:%d warm spare found"
+.It "mly%d: physical device %d:%d initialization started"
+.It "mly%d: physical device %d:%d initialization completed"
+.It "mly%d: physical device %d:%d initialization failed"
+.It "mly%d: physical device %d:%d initialization cancelled"
+.It "mly%d: physical device %d:%d write recovery failed"
+.It "mly%d: physical device %d:%d scsi bus reset failed"
+.It "mly%d: physical device %d:%d double check condition"
+.It "mly%d: physical device %d:%d device cannot be accessed"
+.It "mly%d: physical device %d:%d gross error on scsi processor"
+.It "mly%d: physical device %d:%d bad tag from device"
+.It "mly%d: physical device %d:%d command timeout"
+.It "mly%d: physical device %d:%d system reset"
+.It "mly%d: physical device %d:%d busy status or parity error"
+.It "mly%d: physical device %d:%d host set device to failed state"
+.It "mly%d: physical device %d:%d selection timeout"
+.It "mly%d: physical device %d:%d scsi bus phase error"
+.It "mly%d: physical device %d:%d device returned unknown status"
+.It "mly%d: physical device %d:%d device not ready"
+.It "mly%d: physical device %d:%d device not found at startup"
+.It "mly%d: physical device %d:%d COD write operation failed"
+.It "mly%d: physical device %d:%d BDT write operation failed"
+.It "mly%d: physical device %d:%d missing at startup"
+.It "mly%d: physical device %d:%d start rebuild failed due to physical drive too small"
+.It "mly%d: physical device %d:%d sense data received"
+.It "mly%d: sense key %d asc %02x ascq %02x"
+.It "mly%d: info %4D csi %4D"
+.It "mly%d: physical device %d:%d offline"
+.It "mly%d: sense key %d asc %02x ascq %02x"
+.It "mly%d: info %4D csi %4D"
+.Pp
+The reported event refers to the physical device at the given channel:target
+address.
+.It "mly%d: logical device %d (%s) consistency check started"
+.It "mly%d: logical device %d (%s) consistency check completed"
+.It "mly%d: logical device %d (%s) consistency check cancelled"
+.It "mly%d: logical device %d (%s) consistency check completed with errors"
+.It "mly%d: logical device %d (%s) consistency check failed due to logical drive failure"
+.It "mly%d: logical device %d (%s) consistency check failed due to physical device failure"
+.It "mly%d: logical device %d (%s) automatic rebuild started"
+.It "mly%d: logical device %d (%s) manual rebuild started"
+.It "mly%d: logical device %d (%s) rebuild completed"
+.It "mly%d: logical device %d (%s) rebuild cancelled"
+.It "mly%d: logical device %d (%s) rebuild failed for unknown reasons"
+.It "mly%d: logical device %d (%s) rebuild failed due to new physical device"
+.It "mly%d: logical device %d (%s) rebuild failed due to logical drive failure"
+.It "mly%d: logical device %d (%s) offline"
+.It "mly%d: logical device %d (%s) critical"
+.It "mly%d: logical device %d (%s) online"
+.It "mly%d: logical device %d (%s) initialization started"
+.It "mly%d: logical device %d (%s) initialization completed"
+.It "mly%d: logical device %d (%s) initialization cancelled"
+.It "mly%d: logical device %d (%s) initialization failed"
+.It "mly%d: logical device %d (%s) found"
+.It "mly%d: logical device %d (%s) gone"
+.It "mly%d: logical device %d (%s) expand capacity started"
+.It "mly%d: logical device %d (%s) expand capacity completed"
+.It "mly%d: logical device %d (%s) expand capacity failed"
+.It "mly%d: logical device %d (%s) bad block found"
+.It "mly%d: logical device %d (%s) size changed"
+.It "mly%d: logical device %d (%s) type changed"
+.It "mly%d: logical device %d (%s) bad data block found"
+.It "mly%d: logical device %d (%s) read of data block in bdt"
+.It "mly%d: logical device %d (%s) write back data for disk block lost"
+.Pp
+The event report will include the name of the SCSI device which has
+attached to the device if possible.
+.It "mly%d: enclosure %d fan %d failed"
+.It "mly%d: enclosure %d fan %d ok"
+.It "mly%d: enclosure %d fan %d not present"
+.It "mly%d: enclosure %d power supply %d failed"
+.It "mly%d: enclosure %d power supply %d ok"
+.It "mly%d: enclosure %d power supply %d not present"
+.It "mly%d: enclosure %d temperature sensor %d failed"
+.It "mly%d: enclosure %d temperature sensor %d critical"
+.It "mly%d: enclosure %d temperature sensor %d ok"
+.It "mly%d: enclosure %d temperature sensor %d not present"
+.It "mly%d: enclosure %d unit %d access critical"
+.It "mly%d: enclosure %d unit %d access ok"
+.It "mly%d: enclosure %d unit %d access offline"
+.Pp
+These events refer to external enclosures by number.
+The driver does not attempt to name the enclosures.
+.It "mly%d: controller cache write back error"
+.It "mly%d: controller battery backup unit found"
+.It "mly%d: controller battery backup unit charge level low"
+.It "mly%d: controller battery backup unit charge level ok"
+.It "mly%d: controller installation aborted"
+.It "mly%d: controller mirror race recovery in progress"
+.It "mly%d: controller mirror race on critical drive"
+.It "mly%d: controller memory soft ecc error"
+.It "mly%d: controller memory hard ecc error"
+.It "mly%d: controller battery backup unit failed"
+.Pp
+These events report controller status changes.
+.El
+.Sh BUGS
+The driver does not yet provide an external management interface.
+.Pp
+Enclosures are not named or otherwise identified in event messages.
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Michael Smith
+.Aq msmith@FreeBSD.org .
+.Pp
+This manual page was written by
+.An Michael Smith
+.Aq msmith@FreeBSD.org .
+
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
new file mode 100644
index 000000000000..66e80c60a68b
--- /dev/null
+++ b/sys/compat/linux/linux_file.c
@@ -0,0 +1,859 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+int
+linux_creat(struct proc *p, struct linux_creat_args *args)
+{
+ struct open_args /* {
+ char *path;
+ int flags;
+ int mode;
+ } */ bsd_open_args;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): creat(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+ bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
+ return open(p, &bsd_open_args);
+}
+
+int
+linux_open(struct proc *p, struct linux_open_args *args)
+{
+ struct open_args /* {
+ char *path;
+ int flags;
+ int mode;
+ } */ bsd_open_args;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+
+ if (args->flags & LINUX_O_CREAT)
+ CHECKALTCREAT(p, &sg, args->path);
+ else
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
+ p->p_pid, args->path, args->flags, args->mode);
+#endif
+ bsd_open_args.flags = 0;
+ if (args->flags & LINUX_O_RDONLY)
+ bsd_open_args.flags |= O_RDONLY;
+ if (args->flags & LINUX_O_WRONLY)
+ bsd_open_args.flags |= O_WRONLY;
+ if (args->flags & LINUX_O_RDWR)
+ bsd_open_args.flags |= O_RDWR;
+ if (args->flags & LINUX_O_NDELAY)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_O_APPEND)
+ bsd_open_args.flags |= O_APPEND;
+ if (args->flags & LINUX_O_SYNC)
+ bsd_open_args.flags |= O_FSYNC;
+ if (args->flags & LINUX_O_NONBLOCK)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_FASYNC)
+ bsd_open_args.flags |= O_ASYNC;
+ if (args->flags & LINUX_O_CREAT)
+ bsd_open_args.flags |= O_CREAT;
+ if (args->flags & LINUX_O_TRUNC)
+ bsd_open_args.flags |= O_TRUNC;
+ if (args->flags & LINUX_O_EXCL)
+ bsd_open_args.flags |= O_EXCL;
+ if (args->flags & LINUX_O_NOCTTY)
+ bsd_open_args.flags |= O_NOCTTY;
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+
+ error = open(p, &bsd_open_args);
+ if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp = fdp->fd_ofiles[p->p_retval[0]];
+
+ if (fp->f_type == DTYPE_VNODE)
+ fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, p);
+ }
+#ifdef DEBUG
+ printf("Linux-emul(%d): open returns error %d\n",
+ p->p_pid, error);
+#endif
+ return error;
+}
+
+struct linux_flock {
+ short l_type;
+ short l_whence;
+ linux_off_t l_start;
+ linux_off_t l_len;
+ linux_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ default:
+ bsd_flock->l_type = -1;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
+}
+
+int
+linux_fcntl(struct proc *p, struct linux_fcntl_args *args)
+{
+ int error, result;
+ struct fcntl_args /* {
+ int fd;
+ int cmd;
+ int arg;
+ } */ fcntl_args;
+ struct linux_flock linux_flock;
+ struct flock *bsd_flock;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ fcntl_args.fd = args->fd;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ fcntl_args.cmd = F_DUPFD;
+ fcntl_args.arg = args->arg;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_GETFD:
+ fcntl_args.cmd = F_GETFD;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_SETFD:
+ fcntl_args.cmd = F_SETFD;
+ fcntl_args.arg = args->arg;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_GETFL:
+ fcntl_args.cmd = F_GETFL;
+ error = fcntl(p, &fcntl_args);
+ result = p->p_retval[0];
+ p->p_retval[0] = 0;
+ if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY;
+ if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY;
+ if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR;
+ if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND;
+ if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC;
+ if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC;
+ return error;
+
+ case LINUX_F_SETFL:
+ fcntl_args.arg = 0;
+ if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
+ if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC;
+ fcntl_args.cmd = F_SETFL;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_GETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ error = fcntl(p, &fcntl_args);
+ if (error)
+ return error;
+ bsd_to_linux_flock(bsd_flock, &linux_flock);
+ return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
+ sizeof(struct linux_flock));
+
+ case LINUX_F_SETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_SETLKW:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_GETOWN:
+ fcntl_args.cmd = F_GETOWN;
+ return fcntl(p, &fcntl_args);
+
+ case LINUX_F_SETOWN:
+ fcntl_args.cmd = F_SETOWN;
+ fcntl_args.arg = args->arg;
+ return fcntl(p, &fcntl_args);
+ }
+ return EINVAL;
+}
+
+int
+linux_lseek(struct proc *p, struct linux_lseek_args *args)
+{
+
+ struct lseek_args /* {
+ int fd;
+ int pad;
+ off_t offset;
+ int whence;
+ } */ tmp_args;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): lseek(%d, %ld, %d)\n",
+ (long)p->p_pid, args->fdes, args->off, args->whence);
+#endif
+ tmp_args.fd = args->fdes;
+ tmp_args.offset = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = lseek(p, &tmp_args);
+ return error;
+}
+
+int
+linux_llseek(struct proc *p, struct linux_llseek_args *args)
+{
+ struct lseek_args bsd_args;
+ int error;
+ off_t off;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
+ p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
+#endif
+ off = (args->olow) | (((off_t) args->ohigh) << 32);
+
+ bsd_args.fd = args->fd;
+ bsd_args.offset = off;
+ bsd_args.whence = args->whence;
+
+ if ((error = lseek(p, &bsd_args)))
+ return error;
+
+ if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t))))
+ return error;
+
+ p->p_retval[0] = 0;
+ return 0;
+}
+
+
+struct linux_dirent {
+ long dino;
+ linux_off_t doff;
+ unsigned short dreclen;
+ char dname[LINUX_NAME_MAX + 1];
+};
+
+#define LINUX_RECLEN(de,namlen) \
+ ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
+
+int
+linux_readdir(struct proc *p, struct linux_readdir_args *args)
+{
+ struct linux_getdents_args lda;
+
+ lda.fd = args->fd;
+ lda.dent = args->dent;
+ lda.count = 1;
+ return linux_getdents(p, &lda);
+}
+
+int
+linux_getdents(struct proc *p, struct linux_getdents_args *args)
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct linux_dirent linux_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+ u_long *cookies = NULL, *cookiep;
+ int ncookies;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): getdents(%d, *, %d)\n",
+ p->p_pid, args->fd, args->count);
+#endif
+ if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
+ return (error);
+ }
+
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) {
+ return error;
+ }
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ nbytes = sizeof (struct linux_dirent);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ off = fp->f_offset;
+#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
+ buflen = max(DIRBLKSIZ, nbytes);
+ buflen = min(buflen, MAXBSIZE);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = p;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+ if (cookies) {
+ free(cookies, M_TEMP);
+ cookies = NULL;
+ }
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies);
+ if (error) {
+ goto out;
+ }
+
+ inp = buf;
+ outp = (caddr_t) args->dent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) <= 0) {
+ goto eof;
+ }
+
+ cookiep = cookies;
+
+ if (cookies) {
+ /*
+ * When using cookies, the vfs has the option of reading from
+ * a different offset than that supplied (UFS truncates the
+ * offset to a block boundary to make sure that it never reads
+ * partway through a directory entry, even if the directory
+ * has been compacted).
+ */
+ while (len > 0 && ncookies > 0 && *cookiep <= off) {
+ bdp = (struct dirent *) inp;
+ len -= bdp->d_reclen;
+ inp += bdp->d_reclen;
+ cookiep++;
+ ncookies--;
+ }
+ }
+
+ while (len > 0) {
+ if (cookiep && ncookies == 0)
+ break;
+ bdp = (struct dirent *) inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3) {
+ printf("linux_readdir: reclen=%d\n", reclen);
+ error = EFAULT;
+ goto out;
+ }
+
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ len -= reclen;
+ continue;
+ }
+ linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+ linux_dirent.dino = (long) bdp->d_fileno;
+ if (justone) {
+ /*
+ * old linux-style readdir usage.
+ */
+ linux_dirent.doff = (linux_off_t) linuxreclen;
+ linux_dirent.dreclen = (u_short) bdp->d_namlen;
+ } else {
+ linux_dirent.doff = (linux_off_t)(off + reclen);
+ linux_dirent.dreclen = (u_short) linuxreclen;
+ }
+ strcpy(linux_dirent.dname, bdp->d_name);
+ if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
+ goto out;
+ }
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) args->dent)
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + linuxreclen;
+
+eof:
+ p->p_retval[0] = nbytes - resid;
+out:
+ if (cookies)
+ free(cookies, M_TEMP);
+ VOP_UNLOCK(vp, 0, p);
+ free(buf, M_TEMP);
+ return error;
+}
+
+/*
+ * These exist mainly for hooks for doing /compat/linux translation.
+ */
+
+int
+linux_access(struct proc *p, struct linux_access_args *args)
+{
+ struct access_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): access(%s, %d)\n",
+ p->p_pid, args->path, args->flags);
+#endif
+ bsd.path = args->path;
+ bsd.flags = args->flags;
+
+ return access(p, &bsd);
+}
+
+int
+linux_unlink(struct proc *p, struct linux_unlink_args *args)
+{
+ struct unlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): unlink(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return unlink(p, &bsd);
+}
+
+int
+linux_chdir(struct proc *p, struct linux_chdir_args *args)
+{
+ struct chdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return chdir(p, &bsd);
+}
+
+int
+linux_chmod(struct proc *p, struct linux_chmod_args *args)
+{
+ struct chmod_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chmod(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return chmod(p, &bsd);
+}
+
+int
+linux_chown(struct proc *p, struct linux_chown_args *args)
+{
+ struct chown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chown(%s, %d, %d)\n",
+ p->p_pid, args->path, args->uid, args->gid);
+#endif
+ bsd.path = args->path;
+ /* XXX size casts here */
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+
+ return chown(p, &bsd);
+}
+
+int
+linux_lchown(struct proc *p, struct linux_lchown_args *args)
+{
+ struct lchown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): lchown(%s, %d, %d)\n",
+ p->p_pid, args->path, args->uid, args->gid);
+#endif
+ bsd.path = args->path;
+ /* XXX size casts here */
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+
+ return lchown(p, &bsd);
+}
+
+int
+linux_mkdir(struct proc *p, struct linux_mkdir_args *args)
+{
+ struct mkdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): mkdir(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return mkdir(p, &bsd);
+}
+
+int
+linux_rmdir(struct proc *p, struct linux_rmdir_args *args)
+{
+ struct rmdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rmdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return rmdir(p, &bsd);
+}
+
+int
+linux_rename(struct proc *p, struct linux_rename_args *args)
+{
+ struct rename_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->from);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rename(%s, %s)\n",
+ p->p_pid, args->from, args->to);
+#endif
+ bsd.from = args->from;
+ bsd.to = args->to;
+
+ return rename(p, &bsd);
+}
+
+int
+linux_symlink(struct proc *p, struct linux_symlink_args *args)
+{
+ struct symlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): symlink(%s, %s)\n",
+ p->p_pid, args->path, args->to);
+#endif
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return symlink(p, &bsd);
+}
+
+int
+linux_readlink(struct proc *p, struct linux_readlink_args *args)
+{
+ struct readlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->name);
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): readlink(%s, %p, %d)\n",
+ (long)p->p_pid, args->name, (void *)args->buf, args->count);
+#endif
+ bsd.path = args->name;
+ bsd.buf = args->buf;
+ bsd.count = args->count;
+
+ return readlink(p, &bsd);
+}
+
+int
+linux_truncate(struct proc *p, struct linux_truncate_args *args)
+{
+ struct truncate_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): truncate(%s, %ld)\n",
+ p->p_pid, args->path, args->length);
+#endif
+ bsd.path = args->path;
+ bsd.length = args->length;
+
+ return truncate(p, &bsd);
+}
+
+int
+linux_link(struct proc *p, struct linux_link_args *args)
+{
+ struct link_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): link(%s, %s)\n", p->p_pid, args->path, args->to);
+#endif
+
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return link(p, &bsd);
+}
+
+int
+linux_getcwd(struct proc *p, struct linux_getcwd_args *args)
+{
+ struct __getcwd_args bsd;
+ caddr_t sg;
+ int error, len;
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)p->p_pid,
+ args->buf, args->bufsize);
+#endif
+
+ sg = stackgap_init();
+ bsd.buf = stackgap_alloc(&sg, SPARE_USRSPACE);
+ bsd.buflen = SPARE_USRSPACE;
+ error = __getcwd(p, &bsd);
+ if (!error) {
+ len = strlen(bsd.buf) + 1;
+ if (len <= args->bufsize) {
+ p->p_retval[0] = len;
+ error = copyout(bsd.buf, args->buf, len);
+ }
+ else
+ error = ERANGE;
+ }
+ return (error);
+}
+
+int
+linux_fdatasync(p, uap)
+ struct proc *p;
+ struct linux_fdatasync_args *uap;
+{
+ struct fsync_args bsd;
+
+ bsd.fd = uap->fd;
+ return fsync(p, &bsd);
+}
+
+int
+linux_pread(p, uap)
+ struct proc *p;
+ struct linux_pread_args *uap;
+{
+ struct pread_args bsd;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+ return pread(p, &bsd);
+}
+
+int
+linux_pwrite(p, uap)
+ struct proc *p;
+ struct linux_pwrite_args *uap;
+{
+ struct pwrite_args bsd;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+ return pwrite(p, &bsd);
+}
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
new file mode 100644
index 000000000000..48e13d578277
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.c
@@ -0,0 +1,447 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_util.h>
+
+struct linux_ipc_perm {
+ linux_key_t key;
+ unsigned short uid;
+ unsigned short gid;
+ unsigned short cuid;
+ unsigned short cgid;
+ unsigned short mode;
+ unsigned short seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
+{
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct linux_semid_ds {
+ struct linux_ipc_perm sem_perm;
+ linux_time_t sem_otime;
+ linux_time_t sem_ctime;
+ void *sem_base;
+ void *sem_pending;
+ void *sem_pending_last;
+ void *undo;
+ ushort sem_nsems;
+};
+
+struct linux_shmid_ds {
+ struct linux_ipc_perm shm_perm;
+ int shm_segsz;
+ linux_time_t shm_atime;
+ linux_time_t shm_dtime;
+ linux_time_t shm_ctime;
+ ushort shm_cpid;
+ ushort shm_lpid;
+ short shm_nattch;
+ ushort private1;
+ void *private2;
+ void *private3;
+};
+
+static void
+linux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
+ bsp->sem_otime = lsp->sem_otime;
+ bsp->sem_ctime = lsp->sem_ctime;
+ bsp->sem_nsems = lsp->sem_nsems;
+ bsp->sem_base = lsp->sem_base;
+}
+
+static void
+bsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
+ lsp->sem_otime = bsp->sem_otime;
+ lsp->sem_ctime = bsp->sem_ctime;
+ lsp->sem_nsems = bsp->sem_nsems;
+ lsp->sem_base = bsp->sem_base;
+}
+
+static void
+linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
+}
+
+int
+linux_semop(struct proc *p, struct linux_ipc_args *args)
+{
+ struct semop_args /* {
+ int semid;
+ struct sembuf *sops;
+ int nsops;
+ } */ bsd_args;
+
+ bsd_args.semid = args->arg1;
+ bsd_args.sops = (struct sembuf *)args->ptr;
+ bsd_args.nsops = args->arg2;
+ return semop(p, &bsd_args);
+}
+
+int
+linux_semget(struct proc *p, struct linux_ipc_args *args)
+{
+ struct semget_args /* {
+ key_t key;
+ int nsems;
+ int semflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.nsems = args->arg2;
+ bsd_args.semflg = args->arg3;
+ return semget(p, &bsd_args);
+}
+
+int
+linux_semctl(struct proc *p, struct linux_ipc_args *args)
+{
+ struct linux_semid_ds linux_semid;
+ struct semid_ds bsd_semid;
+ struct __semctl_args /* {
+ int semid;
+ int semnum;
+ int cmd;
+ union semun *arg;
+ } */ bsd_args;
+ int error;
+ caddr_t sg, unptr, dsp, ldsp;
+
+ sg = stackgap_init();
+ bsd_args.semid = args->arg1;
+ bsd_args.semnum = args->arg2;
+ bsd_args.cmd = args->arg3;
+ bsd_args.arg = (union semun *)args->ptr;
+
+ switch (args->arg3) {
+ case LINUX_IPC_RMID:
+ bsd_args.cmd = IPC_RMID;
+ break;
+ case LINUX_GETNCNT:
+ bsd_args.cmd = GETNCNT;
+ break;
+ case LINUX_GETPID:
+ bsd_args.cmd = GETPID;
+ break;
+ case LINUX_GETVAL:
+ bsd_args.cmd = GETVAL;
+ break;
+ case LINUX_GETZCNT:
+ bsd_args.cmd = GETZCNT;
+ break;
+ case LINUX_SETVAL:
+ bsd_args.cmd = SETVAL;
+ break;
+ case LINUX_IPC_SET:
+ bsd_args.cmd = IPC_SET;
+ error = copyin(args->ptr, &ldsp, sizeof(ldsp));
+ if (error)
+ return error;
+ error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid));
+ if (error)
+ return error;
+ linux_to_bsd_semid_ds(&linux_semid, &bsd_semid);
+ unptr = stackgap_alloc(&sg, sizeof(union semun));
+ dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
+ error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid));
+ if (error)
+ return error;
+ error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
+ if (error)
+ return error;
+ bsd_args.arg = (union semun *)unptr;
+ return __semctl(p, &bsd_args);
+ case LINUX_IPC_STAT:
+ bsd_args.cmd = IPC_STAT;
+ unptr = stackgap_alloc(&sg, sizeof(union semun *));
+ dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
+ error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
+ if (error)
+ return error;
+ bsd_args.arg = (union semun *)unptr;
+ error = __semctl(p, &bsd_args);
+ if (error)
+ return error;
+ error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid));
+ if (error)
+ return error;
+ bsd_to_linux_semid_ds(&bsd_semid, &linux_semid);
+ error = copyin(args->ptr, &ldsp, sizeof(ldsp));
+ if (error)
+ return error;
+ return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid));
+ case LINUX_GETALL:
+ /* FALLTHROUGH */
+ case LINUX_SETALL:
+ /* FALLTHROUGH */
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return EINVAL;
+ }
+ return __semctl(p, &bsd_args);
+}
+
+int
+linux_msgsnd(struct proc *p, struct linux_ipc_args *args)
+{
+ struct msgsnd_args /* {
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.msqid = args->arg1;
+ bsd_args.msgp = args->ptr;
+ bsd_args.msgsz = args->arg2;
+ bsd_args.msgflg = args->arg3;
+ return msgsnd(p, &bsd_args);
+}
+
+int
+linux_msgrcv(struct proc *p, struct linux_ipc_args *args)
+{
+ struct msgrcv_args /* {
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ long msgtyp;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.msqid = args->arg1;
+ bsd_args.msgp = args->ptr;
+ bsd_args.msgsz = args->arg2;
+ bsd_args.msgtyp = 0;
+ bsd_args.msgflg = args->arg3;
+ return msgrcv(p, &bsd_args);
+}
+
+int
+linux_msgget(struct proc *p, struct linux_ipc_args *args)
+{
+ struct msgget_args /* {
+ key_t key;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.msgflg = args->arg2;
+ return msgget(p, &bsd_args);
+}
+
+int
+linux_msgctl(struct proc *p, struct linux_ipc_args *args)
+{
+ struct msgctl_args /* {
+ int msqid;
+ int cmd;
+ struct msqid_ds *buf;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.msqid = args->arg1;
+ bsd_args.cmd = args->arg2;
+ bsd_args.buf = (struct msqid_ds *)args->ptr;
+ error = msgctl(p, &bsd_args);
+ return ((args->arg2 == LINUX_IPC_RMID && error == EINVAL) ? 0 : error);
+}
+
+int
+linux_shmat(struct proc *p, struct linux_ipc_args *args)
+{
+ struct shmat_args /* {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.shmid = args->arg1;
+ bsd_args.shmaddr = args->ptr;
+ bsd_args.shmflg = args->arg2;
+ if ((error = shmat(p, &bsd_args)))
+ return error;
+ if ((error = copyout(p->p_retval, (caddr_t)args->arg3, sizeof(int))))
+ return error;
+ p->p_retval[0] = 0;
+ return 0;
+}
+
+int
+linux_shmdt(struct proc *p, struct linux_ipc_args *args)
+{
+ struct shmdt_args /* {
+ void *shmaddr;
+ } */ bsd_args;
+
+ bsd_args.shmaddr = args->ptr;
+ return shmdt(p, &bsd_args);
+}
+
+int
+linux_shmget(struct proc *p, struct linux_ipc_args *args)
+{
+ struct shmget_args /* {
+ key_t key;
+ int size;
+ int shmflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.size = args->arg2;
+ bsd_args.shmflg = args->arg3;
+ return shmget(p, &bsd_args);
+}
+
+int
+linux_shmctl(struct proc *p, struct linux_ipc_args *args)
+{
+ struct shmid_ds bsd_shmid;
+ struct linux_shmid_ds linux_shmid;
+ struct shmctl_args /* {
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+ } */ bsd_args;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ switch (args->arg2) {
+ case LINUX_IPC_STAT:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_STAT;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = shmctl(p, &bsd_args)))
+ return error;
+ if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+ return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
+
+ case LINUX_IPC_SET:
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_SET;
+ return shmctl(p, &bsd_args);
+
+ case LINUX_IPC_RMID:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_RMID;
+ if (NULL == args->ptr)
+ bsd_args.buf = NULL;
+ else {
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ }
+ return shmctl(p, &bsd_args);
+
+ case LINUX_IPC_INFO:
+ case LINUX_SHM_STAT:
+ case LINUX_SHM_INFO:
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return EINVAL;
+ }
+}
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
new file mode 100644
index 000000000000..573cd74d251d
--- /dev/null
+++ b/sys/compat/linux/linux_stats.c
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+struct linux_newstat {
+ u_short stat_dev;
+ u_short __pad1;
+ u_long stat_ino;
+ u_short stat_mode;
+ u_short stat_nlink;
+ u_short stat_uid;
+ u_short stat_gid;
+ u_short stat_rdev;
+ u_short __pad2;
+ u_long stat_size;
+ u_long stat_blksize;
+ u_long stat_blocks;
+ u_long stat_atime;
+ u_long __unused1;
+ u_long stat_mtime;
+ u_long __unused2;
+ u_long stat_ctime;
+ u_long __unused3;
+ u_long __unused4;
+ u_long __unused5;
+};
+
+struct linux_ustat
+{
+ int f_tfree;
+ u_long f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct linux_newstat tbuf;
+
+ tbuf.stat_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
+ tbuf.stat_ino = buf->st_ino;
+ tbuf.stat_mode = buf->st_mode;
+ tbuf.stat_nlink = buf->st_nlink;
+ tbuf.stat_uid = buf->st_uid;
+ tbuf.stat_gid = buf->st_gid;
+ tbuf.stat_rdev = buf->st_rdev;
+ tbuf.stat_size = buf->st_size;
+ tbuf.stat_atime = buf->st_atime;
+ tbuf.stat_mtime = buf->st_mtime;
+ tbuf.stat_ctime = buf->st_ctime;
+ tbuf.stat_blksize = buf->st_blksize;
+ tbuf.stat_blocks = buf->st_blocks;
+
+ return (copyout(&tbuf, ubuf, sizeof(tbuf)));
+}
+
+int
+linux_newstat(struct proc *p, struct linux_newstat_args *args)
+{
+ struct stat buf;
+ struct nameidata nd;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): newstat(%s, *)\n", (long)p->p_pid,
+ args->path);
+#endif
+
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ args->path, p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ if (error)
+ return (error);
+
+ return (newstat_copyout(&buf, args->buf));
+}
+
+/*
+ * Get file status; this version does not follow links.
+ */
+int
+linux_newlstat(p, uap)
+ struct proc *p;
+ struct linux_newlstat_args *uap;
+{
+ int error;
+ struct vnode *vp;
+ struct stat sb;
+ struct nameidata nd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, uap->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): newlstat(%s, *)\n", (long)p->p_pid,
+ uap->path);
+#endif
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ uap->path, p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ vp = nd.ni_vp;
+ error = vn_stat(vp, &sb, p);
+ vput(vp);
+ if (error)
+ return (error);
+
+ return (newstat_copyout(&sb, uap->buf));
+}
+
+int
+linux_newfstat(struct proc *p, struct linux_newfstat_args *args)
+{
+ struct filedesc *fdp;
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+ fdp = p->p_fd;
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): newfstat(%d, *)\n", (long)p->p_pid, args->fd);
+#endif
+
+ if ((unsigned)args->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return (EBADF);
+
+ error = fo_stat(fp, &buf, p);
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+
+ return (error);
+}
+
+struct linux_statfs_buf {
+ long ftype;
+ long fbsize;
+ long fblocks;
+ long fbfree;
+ long fbavail;
+ long ffiles;
+ long fffree;
+ linux_fsid_t ffsid;
+ long fnamelen;
+ long fspare[6];
+};
+
+#ifndef VT_NWFS
+#define VT_NWFS VT_TFS /* XXX - bug compatibility with sys/nwfs/nwfs_node.h */
+#endif
+
+#define LINUX_CODA_SUPER_MAGIC 0x73757245L
+#define LINUX_EXT2_SUPER_MAGIC 0xEF53L
+#define LINUX_HPFS_SUPER_MAGIC 0xf995e849L
+#define LINUX_ISOFS_SUPER_MAGIC 0x9660L
+#define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
+#define LINUX_NCP_SUPER_MAGIC 0x564cL
+#define LINUX_NFS_SUPER_MAGIC 0x6969L
+#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
+#define LINUX_PROC_SUPER_MAGIC 0x9fa0L
+#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
+
+/*
+ * ext2fs uses the VT_UFS tag. A mounted ext2 filesystem will therefore
+ * be seen as an ufs/mfs filesystem.
+ */
+static long
+bsd_to_linux_ftype(int tag)
+{
+
+ switch (tag) {
+ case VT_CODA:
+ return (LINUX_CODA_SUPER_MAGIC);
+ case VT_HPFS:
+ return (LINUX_HPFS_SUPER_MAGIC);
+ case VT_ISOFS:
+ return (LINUX_ISOFS_SUPER_MAGIC);
+ case VT_MFS:
+ return (LINUX_UFS_SUPER_MAGIC);
+ case VT_MSDOSFS:
+ return (LINUX_MSDOS_SUPER_MAGIC);
+ case VT_NFS:
+ return (LINUX_NFS_SUPER_MAGIC);
+ case VT_NTFS:
+ return (LINUX_NTFS_SUPER_MAGIC);
+ case VT_NWFS:
+ return (LINUX_NCP_SUPER_MAGIC);
+ case VT_PROCFS:
+ return (LINUX_PROC_SUPER_MAGIC);
+ case VT_UFS:
+ return (LINUX_UFS_SUPER_MAGIC);
+ }
+
+ return (0L);
+}
+
+int
+linux_statfs(struct proc *p, struct linux_statfs_args *args)
+{
+ struct mount *mp;
+ struct nameidata *ndp;
+ struct statfs *bsd_statfs;
+ struct nameidata nd;
+ struct linux_statfs_buf linux_statfs_buf;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
+#endif
+ ndp = &nd;
+ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curproc);
+ error = namei(ndp);
+ if (error)
+ return error;
+ NDFREE(ndp, NDF_ONLY_PNBUF);
+ mp = ndp->ni_vp->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ vrele(ndp->ni_vp);
+ error = VFS_STATFS(mp, bsd_statfs, p);
+ if (error)
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs_buf.ftype = bsd_to_linux_ftype(bsd_statfs->f_type);
+ linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
+ linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
+ linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
+ linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
+ linux_statfs_buf.fffree = bsd_statfs->f_ffree;
+ linux_statfs_buf.ffiles = bsd_statfs->f_files;
+ linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs_buf.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
+ sizeof(struct linux_statfs_buf));
+}
+
+int
+linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args)
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *bsd_statfs;
+ struct linux_statfs_buf linux_statfs_buf;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd);
+#endif
+ error = getvnode(p->p_fd, args->fd, &fp);
+ if (error)
+ return error;
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ error = VFS_STATFS(mp, bsd_statfs, p);
+ if (error)
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs_buf.ftype = bsd_to_linux_ftype(bsd_statfs->f_type);
+ linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
+ linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
+ linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
+ linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
+ linux_statfs_buf.fffree = bsd_statfs->f_ffree;
+ linux_statfs_buf.ffiles = bsd_statfs->f_files;
+ linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs_buf.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
+ sizeof(struct linux_statfs_buf));
+}
+
+int
+linux_ustat(p, uap)
+ struct proc *p;
+ struct linux_ustat_args *uap;
+{
+ struct linux_ustat lu;
+ dev_t dev;
+ struct vnode *vp;
+ struct statfs *stat;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): ustat(%d, *)\n", (long)p->p_pid, uap->dev);
+#endif
+
+ /*
+ * lu.f_fname and lu.f_fpack are not used. They are always zeroed.
+ * lu.f_tinode and lu.f_tfree are set from the device's super block.
+ */
+ bzero(&lu, sizeof(lu));
+
+ /*
+ * XXX - Don't return an error if we can't find a vnode for the
+ * device. Our dev_t is 32-bits whereas Linux only has a 16-bits
+ * dev_t. The dev_t that is used now may as well be a truncated
+ * dev_t returned from previous syscalls. Just return a bzeroed
+ * ustat in that case.
+ */
+ dev = makebdev(uap->dev >> 8, uap->dev & 0xFF);
+ if (vfinddev(dev, VBLK, &vp)) {
+ if (vp->v_mount == NULL)
+ return (EINVAL);
+ stat = &(vp->v_mount->mnt_stat);
+ error = VFS_STATFS(vp->v_mount, stat, p);
+ if (error)
+ return (error);
+
+ lu.f_tfree = stat->f_bfree;
+ lu.f_tinode = stat->f_ffree;
+ }
+
+ return (copyout(&lu, uap->ubuf, sizeof(lu)));
+}
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
new file mode 100644
index 000000000000..6399805a3037
--- /dev/null
+++ b/sys/compat/linux/linux_util.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include <compat/linux/linux_util.h>
+
+const char linux_emul_path[] = "/compat/linux";
+
+/*
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a seperate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+linux_emul_find(p, sgp, prefix, path, pbuf, cflag)
+ struct proc *p;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+ int error;
+ char *ptr, *buf, *cp;
+ size_t sz, len;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--);
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ }
+ else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the linux_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path,
+ p);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p))
+ != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ if (*pbuf != NULL)
+ error = copyout(buf, *pbuf, sz);
+ else
+ error = ENAMETOOLONG;
+ free(buf, M_TEMP);
+ }
+
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ if (!cflag) {
+ NDFREE(&ndroot, NDF_ONLY_PNBUF);
+ vrele(ndroot.ni_vp);
+ }
+ return error;
+
+bad:
+ NDFREE(&ndroot, NDF_ONLY_PNBUF);
+ vrele(ndroot.ni_vp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
diff --git a/sys/dev/ed/if_ed98.h b/sys/dev/ed/if_ed98.h
new file mode 100644
index 000000000000..22bbf78be0e6
--- /dev/null
+++ b/sys/dev/ed/if_ed98.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) KATO Takenori, 1996. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * PC-9801 specific definitions for DP8390/SMC8216 NICs.
+ */
+#ifndef PC98
+#error Why you include if_ed98.h?
+#endif
+
+/*
+ * Vendor types
+ */
+#define ED_VENDOR_MISC 0xf0 /* others */
+
+/*
+ * Card types.
+ *
+ * Type Card
+ * 0x00 Allied Telesis CenterCom LA-98-T / SMC EtherEZ98.
+ * 0x10 ** RESERVED **
+ * 0x20 PLANET SMART COM 98 EN-2298 / ELECOM LANEED LD-BDN[123]A.
+ * 0x30 MELCO EGY-98 / Contec C-NET(98)E-A/L-A.
+ * 0x40 MELCO LGY-98, IND-SP, IND-SS / MACNICA NE2098(XXX).
+ * 0x50 ICM DT-ET-25, DT-ET-T5, IF-2766ET, IF-2771ET /
+ * D-Link DE-298P{T,CAT}, DE-298{T,TP,CAT}.
+ * 0x60 Allied Telesis SIC-98.
+ * 0x70 ** RESERVED **
+ * 0x80 NEC PC-9801-108.
+ * 0x90 IO-DATA LA-98 / NEC PC-9801-77.
+ * 0xa0 Contec C-NET(98).
+ * 0xb0 Contec C-NET(98)E/L.
+ * 0xc0 ** RESERVED **
+ * 0xd0 Networld EC/EP-98X.
+ * 0xe0 Soliton SB-9801 / Fujikura FN-9801 / Networld EC/EP-98S.
+ * 0xf0 NextCom NC5098.
+ */
+#define ED_TYPE98_BASE 0x80
+
+#define ED_TYPE98_GENERIC 0x80
+#define ED_TYPE98_BDN 0x82
+#define ED_TYPE98_EGY 0x83
+#define ED_TYPE98_LGY 0x84
+#define ED_TYPE98_ICM 0x85
+#define ED_TYPE98_SIC 0x86
+#define ED_TYPE98_108 0x88
+#define ED_TYPE98_LA98 0x89
+#define ED_TYPE98_CNET98 0x8a
+#define ED_TYPE98_CNET98EL 0x8b
+#define ED_TYPE98_NW98X 0x8d
+#define ED_TYPE98_SB98 0x8e
+#define ED_TYPE98_NC5098 0x8f
+
+#define ED_TYPE98(x) (((x & 0xffff0000) >> 20) | ED_TYPE98_BASE)
+#define ED_TYPE98SUB(x) ((x & 0xf0000) >> 16)
+
+/*
+ * Definitions for C-NET(98) serise
+ */
+/*
+ * Initial Register(on board JP1)
+ */
+#define ED_CNET98_INIT 0xaaed /* default */
+#define ED_CNET98_INIT2 0x55ed /* another setting */
+
+#define ED_CNET98EL_PAGE_OFFSET 0x0000 /* Page offset for NIC access to mem */
+
+/*
+ * Definitions for Soliton SB-9801
+ */
+/*
+ * I/O port select register
+ */
+#define ED_SB98_IO_INHIBIT 0x0040 /* XXX - shares printer port! */
+
+/*
+ * Definitions for SMC EtherEZ98(SMC8498BTA)
+ */
+#define ED_EZ98_NIC_OFFSET 0x100 /* I/O base offset to NIC */
+#define ED_EZ98_ASIC_OFFSET 0 /* I/O base offset to ASIC */
+/*
+ * XXX - The I/O address range is fragmented in the EtherEZ98;
+ * it occupies 16*2 I/O addresses, by the way.
+ */
+#define ED_EZ98_IO_PORTS 16 /* # of i/o addresses used */
diff --git a/sys/dev/ed/if_ed_cbus.c b/sys/dev/ed/if_ed_cbus.c
new file mode 100644
index 000000000000..68f6f88c2e42
--- /dev/null
+++ b/sys/dev/ed/if_ed_cbus.c
@@ -0,0 +1,1759 @@
+/*
+ * Copyright (c) 1995, David Greenman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#ifdef PC98
+#include <sys/rman.h>
+#include <machine/resource.h>
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#endif
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_mib.h>
+
+#include <isa/isavar.h>
+#include <isa/pnpvar.h>
+
+#include <dev/ed/if_edvar.h>
+#ifdef PC98
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_ed98.h>
+
+static int ed98_alloc_port __P((device_t, int));
+static int ed98_alloc_memory __P((device_t, int));
+static int ed_pio_testmem __P((struct ed_softc *, int, int, int));
+static int ed_probe_SIC98 __P((device_t, int, int));
+static int ed_probe_CNET98 __P((device_t, int, int));
+static int ed_probe_CNET98EL __P((device_t, int, int));
+static int ed_probe_NEC77 __P((device_t, int, int));
+static int ed_probe_NW98X __P((device_t, int, int));
+static int ed_probe_SB98 __P((device_t, int, int));
+static int ed_probe_EZ98 __P((device_t, int, int));
+static int ed98_probe_Novell __P((device_t, int, int));
+static int ed98_probe_generic8390 __P((struct ed_softc *));
+static void ed_reset_CNET98 __P((struct ed_softc *, int));
+static void ed_winsel_CNET98 __P((struct ed_softc *, u_short));
+static void ed_get_SB98 __P((struct ed_softc *));
+#endif
+
+static int ed_isa_probe __P((device_t));
+static int ed_isa_attach __P((device_t));
+
+static struct isa_pnp_id ed_ids[] = {
+#ifdef PC98
+/* TODO - list up PnP boards for PC-98 */
+ { 0, NULL }
+#endif
+};
+
+static int
+ed_isa_probe(dev)
+ device_t dev;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int flags = device_get_flags(dev);
+ int error = 0;
+
+ bzero(sc, sizeof(struct ed_softc));
+#ifdef PC98
+ sc->type = ED_TYPE98(flags);
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_isa_probe: sc->type=%x\n", sc->type);
+#endif
+#endif
+
+ /* Check isapnp ids */
+ error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids);
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_isa_probe: ISA_PNP_PROBE returns %d\n", error);
+#endif
+
+ /* If the card had a PnP ID that didn't match any we know about */
+ if (error == ENXIO) {
+ goto end;
+ }
+
+ /* If we had some other problem. */
+ if (!(error == 0 || error == ENOENT)) {
+ goto end;
+ }
+
+ /* Heuristic probes */
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_isa_probe: Heuristic probes start\n");
+#endif
+#ifdef PC98
+ switch (sc->type) {
+ case ED_TYPE98_GENERIC:
+ /*
+ * CAUTION!
+ * sc->type of these boards are overwritten by PC/AT's value.
+ */
+
+ /*
+ * SMC EtherEZ98
+ */
+ error = ed_probe_EZ98(dev, 0, flags);
+ if (error == 0) {
+ goto end;
+ }
+
+ ed_release_resources(dev);
+
+ /*
+ * Allied Telesis CenterCom LA-98-T
+ */
+ error = ed_probe_Novell(dev, 0, flags);
+ if (error == 0) {
+ goto end;
+ }
+
+ break;
+
+ /*
+ * NE2000-like boards probe routine
+ */
+ case ED_TYPE98_BDN:
+ /*
+ * ELECOM LANEED LD-BDN
+ * PLANET SMART COM 98 EN-2298
+ */
+ case ED_TYPE98_LGY:
+ /*
+ * MELCO LGY-98, IND-SP, IND-SS
+ * MACNICA NE2098
+ */
+ case ED_TYPE98_ICM:
+ /*
+ * ICM DT-ET-25, DT-ET-T5, IF-2766ET, IF-2771ET
+ * D-Link DE-298P, DE-298
+ */
+ case ED_TYPE98_EGY:
+ /*
+ * MELCO EGY-98
+ * Contec C-NET(98)E-A, C-NET(98)L-A
+ */
+ case ED_TYPE98_108:
+ /*
+ * NEC PC-9801-107,108
+ */
+ case ED_TYPE98_NC5098:
+ /*
+ * NextCom NC5098
+ */
+
+ error = ed98_probe_Novell(dev, 0, flags);
+
+ break;
+
+ /*
+ * other boards with special probe routine
+ */
+ case ED_TYPE98_SIC:
+ /*
+ * Allied Telesis SIC-98
+ */
+ error = ed_probe_SIC98(dev, 0, flags);
+
+ break;
+
+ case ED_TYPE98_CNET98EL:
+ /*
+ * Contec C-NET(98)E/L
+ */
+ error = ed_probe_CNET98EL(dev, 0, flags);
+
+ break;
+
+ case ED_TYPE98_CNET98:
+ /*
+ * Contec C-NET(98)
+ */
+ error = ed_probe_CNET98(dev, 0, flags);
+
+ break;
+
+ case ED_TYPE98_LA98:
+ /*
+ * IO-DATA LA/T-98
+ * NEC PC-9801-77,78
+ */
+ error = ed_probe_NEC77(dev, 0, flags);
+
+ break;
+
+ case ED_TYPE98_NW98X:
+ /*
+ * Networld EC/EP-98X
+ */
+ error = ed_probe_NW98X(dev, 0, flags);
+
+ break;
+
+ case ED_TYPE98_SB98:
+ /*
+ * Soliton SB-9801
+ * Fujikura FN-9801
+ */
+
+ error = ed_probe_SB98(dev, 0, flags);
+
+ break;
+ }
+#endif
+
+end:
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_isa_probe: end, error=%d\n", error);
+#endif
+ if (error == 0)
+ error = ed_alloc_irq(dev, 0, 0);
+
+ ed_release_resources(dev);
+ return (error);
+}
+
+static int
+ed_isa_attach(dev)
+ device_t dev;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int flags = device_get_flags(dev);
+ int error;
+
+ if (sc->port_used > 0) {
+#ifdef PC98
+ if (ED_TYPE98(flags) == ED_TYPE98_GENERIC) {
+ ed_alloc_port(dev, sc->port_rid, sc->port_used);
+ } else {
+ ed98_alloc_port(dev, sc->port_rid);
+ }
+#endif
+ }
+ if (sc->mem_used)
+ ed_alloc_memory(dev, sc->mem_rid, sc->mem_used);
+
+ ed_alloc_irq(dev, sc->irq_rid, 0);
+
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
+ edintr, sc, &sc->irq_handle);
+ if (error) {
+ ed_release_resources(dev);
+ return (error);
+ }
+
+ return ed_attach(sc, device_get_unit(dev), flags);
+}
+
+static device_method_t ed_isa_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ed_isa_probe),
+ DEVMETHOD(device_attach, ed_isa_attach),
+
+ { 0, 0 }
+};
+
+static driver_t ed_isa_driver = {
+ "ed",
+ ed_isa_methods,
+ sizeof(struct ed_softc)
+};
+
+static devclass_t ed_isa_devclass;
+
+DRIVER_MODULE(ed, isa, ed_isa_driver, ed_isa_devclass, 0, 0);
+
+#ifdef PC98
+/*
+ * Interrupt conversion table for EtherEZ98
+ */
+static unsigned short ed_EZ98_intr_val[] = {
+ 0,
+ 3,
+ 5,
+ 6,
+ 0,
+ 9,
+ 12,
+ 13
+};
+
+static int
+ed_probe_EZ98(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ static unsigned short *intr_vals[] = {NULL, ed_EZ98_intr_val};
+
+ error = ed_alloc_port(dev, port_rid, ED_EZ98_IO_PORTS);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_EZ98_ASIC_OFFSET;
+ sc->nic_offset = ED_EZ98_NIC_OFFSET;
+
+ return ed_probe_WD80x3_generic(dev, flags, intr_vals);
+}
+
+/*
+ * I/O conversion tables
+ */
+
+/* LGY-98, ICM, C-NET(98)E/L */
+static bus_addr_t ed98_ioaddr_generic[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+/*
+ * Definitions for Contec C-NET(98)E/L
+ */
+#define ED_CNET98EL_ICR 2 /* Interrupt Configuration Register */
+
+#define ED_CNET98EL_ICR_IRQ3 0x01
+#define ED_CNET98EL_ICR_IRQ5 0x02
+#define ED_CNET98EL_ICR_IRQ6 0x04
+#define ED_CNET98EL_ICR_IRQ12 0x20
+
+#define ED_CNET98EL_IMR 4 /* Interrupt Mask Register */
+#define ED_CNET98EL_ISR 5 /* Interrupt Status Register */
+
+/* EGY-98 */
+static bus_addr_t ed98_ioaddr_egy98[] = {
+ 0, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e
+};
+
+/* SIC-98 */
+static bus_addr_t ed98_ioaddr_sic98[] = {
+ 0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00, 0x0c00, 0x0e00,
+ 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00
+};
+
+/* LA/T-98, LD-BDN, PC-9801-77, SB-9801 */
+static bus_addr_t ed98_ioaddr_la98[] = {
+ 0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000,
+ 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0xf000,
+ 0x0100 /* for NEC 77(see below) */
+};
+
+/*
+ * Definitions for NEC PC-9801-77
+ */
+#define ED_NEC77_IRQ 16 /* Interrupt Configuration Register */
+
+#define ED_NEC77_IRQ3 0x04
+#define ED_NEC77_IRQ5 0x06
+#define ED_NEC77_IRQ6 0x08
+#define ED_NEC77_IRQ12 0x0a
+#define ED_NEC77_IRQ13 0x02
+
+/*
+ * Definitions for Soliton SB-9801
+ */
+#define ED_SB98_CFG 1 /* Board configuration */
+
+#define ED_SB98_CFG_IRQ3 0x00
+#define ED_SB98_CFG_IRQ5 0x04
+#define ED_SB98_CFG_IRQ6 0x08
+#define ED_SB98_CFG_IRQ12 0x0c
+#define ED_SB98_CFG_ALTPORT 0x40 /* use EXTERNAL media */
+#define ED_SB98_CFG_ENABLE 0xa0 /* enable configuration */
+
+#define ED_SB98_EEPENA 2 /* EEPROM access enable */
+
+#define ED_SB98_EEPENA_DISABLE 0x00
+#define ED_SB98_EEPENA_ENABLE 0x01
+
+#define ED_SB98_EEP 3 /* EEPROM access */
+
+#define ED_SB98_EEP_SDA 0x01 /* Serial Data */
+#define ED_SB98_EEP_SCL 0x02 /* Serial Clock */
+#define ED_SB98_EEP_READ 0x01 /* Read Command */
+
+#define ED_SB98_EEP_DELAY 300
+
+#define ED_SB98_ADDRESS 0x01 /* Station Address(1-6) */
+
+#define ED_SB98_POLARITY 4 /* Polarity */
+
+/* PC-9801-108 */
+static bus_addr_t ed98_ioaddr_nec108[] = {
+ 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
+ 0x1000, 0x1002, 0x1004, 0x1006, 0x1008, 0x100a, 0x100c, 0x100e
+};
+
+/* C-NET(98) */
+static bus_addr_t ed98_ioaddr_cnet98[] = {
+ 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
+ 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e
+};
+
+/*
+ * Definitions for Contec C-NET(98)
+ */
+#define ED_CNET98_MAP_REG0L 0 /* MAPPING register0 Low */
+#define ED_CNET98_MAP_REG1L 1 /* MAPPING register1 Low */
+#define ED_CNET98_MAP_REG2L 2 /* MAPPING register2 Low */
+#define ED_CNET98_MAP_REG3L 3 /* MAPPING register3 Low */
+#define ED_CNET98_MAP_REG0H 4 /* MAPPING register0 Hi */
+#define ED_CNET98_MAP_REG1H 5 /* MAPPING register1 Hi */
+#define ED_CNET98_MAP_REG2H 6 /* MAPPING register2 Hi */
+#define ED_CNET98_MAP_REG3H 7 /* MAPPING register3 Hi */
+#define ED_CNET98_WIN_REG 8 /* Window register */
+#define ED_CNET98_INT_LEV 9 /* Init level register */
+
+#define ED_CNET98_INT_IRQ3 0x01 /* INT 0 */
+#define ED_CNET98_INT_IRQ5 0x02 /* INT 1 */
+#define ED_CNET98_INT_IRQ6 0x04 /* INT 2 */
+#define ED_CNET98_INT_IRQ9 0x08 /* INT 3 */
+#define ED_CNET98_INT_IRQ12 0x20 /* INT 5 */
+#define ED_CNET98_INT_IRQ13 0x40 /* INT 6 */
+
+#define ED_CNET98_INT_REQ 10 /* Init request register */
+#define ED_CNET98_INT_MASK 11 /* Init mask register */
+#define ED_CNET98_INT_STAT 12 /* Init status register */
+#define ED_CNET98_INT_CLR 12 /* Init clear register */
+#define ED_CNET98_RESERVE1 13
+#define ED_CNET98_RESERVE2 14
+#define ED_CNET98_RESERVE3 15
+
+/* EC/EP-98X, NC5098 */
+static bus_addr_t ed98_ioaddr_nw98x[] = {
+ 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700,
+ 0x0800, 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00,
+ 0x1000 /* for EC/EP-98X(see below) */
+};
+
+/*
+ * Definitions for Networld EC/EP-98X
+ */
+#define ED_NW98X_IRQ 16 /* Interrupt Configuration Register */
+
+#define ED_NW98X_IRQ3 0x04
+#define ED_NW98X_IRQ5 0x06
+#define ED_NW98X_IRQ6 0x08
+#define ED_NW98X_IRQ12 0x0a
+#define ED_NW98X_IRQ13 0x02
+
+/* NC5098 ASIC */
+static bus_addr_t ed98_asic_nc5098[] = {
+/* DATA ENADDR RESET */
+ 0x0000, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x4000,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Definitions for NextCom NC5098
+ */
+#define ED_NC5098_ENADDR 1 /* Station Address(1-6) */
+
+/*
+ * Allocate a port resource with the given resource id.
+ */
+static int
+ed98_alloc_port(dev, rid)
+ device_t dev;
+ int rid;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ struct resource *res;
+ int error;
+ bus_addr_t *io_nic, *io_asic, adj;
+ static bus_addr_t io_res[ED_NOVELL_IO_PORTS + 1];
+ int i, n;
+ int offset, reset, data;
+
+ /* Set i/o table for resource manager */
+ io_nic = io_asic = ed98_ioaddr_generic;
+ offset = ED_NOVELL_ASIC_OFFSET;
+ reset = ED_NOVELL_RESET;
+ data = ED_NOVELL_DATA;
+ n = ED_NOVELL_IO_PORTS;
+
+ switch (sc->type) {
+ case ED_TYPE98_LGY:
+ io_asic = ed98_ioaddr_egy98; /* XXX - Yes, we use egy98 */
+ offset = 0x0200;
+ reset = 8;
+ break;
+
+ case ED_TYPE98_EGY:
+ io_nic = io_asic = ed98_ioaddr_egy98;
+ offset = 0x0200;
+ reset = 8;
+ break;
+
+ case ED_TYPE98_ICM:
+ offset = 0x0100;
+ break;
+
+ case ED_TYPE98_BDN:
+ io_nic = io_asic = ed98_ioaddr_la98;
+ offset = 0x0100;
+ reset = 0x0c;
+ break;
+
+ case ED_TYPE98_SIC:
+ io_nic = io_asic = ed98_ioaddr_sic98;
+ offset = 0x2000;
+ n = 16+1;
+ break;
+
+ case ED_TYPE98_108:
+ io_nic = io_asic = ed98_ioaddr_nec108;
+ offset = 0x0888; /* XXX - overwritten after */
+ reset = 1;
+ n = 16; /* XXX - does not set ASIC i/o here */
+ break;
+
+ case ED_TYPE98_LA98:
+ io_nic = io_asic = ed98_ioaddr_la98;
+ offset = 0x0100;
+ break;
+
+ case ED_TYPE98_CNET98EL:
+ offset = 0x0400;
+ data = 0x0e;
+ break;
+
+ case ED_TYPE98_CNET98:
+ /* XXX - Yes, we use generic i/o here */
+ offset = 0x0400;
+ break;
+
+ case ED_TYPE98_NW98X:
+ io_nic = io_asic = ed98_ioaddr_nw98x;
+ offset = 0x1000;
+ break;
+
+ case ED_TYPE98_SB98:
+ io_nic = io_asic = ed98_ioaddr_la98;
+ offset = 0x0400;
+ reset = 7;
+ break;
+
+ case ED_TYPE98_NC5098:
+ io_nic = ed98_ioaddr_nw98x;
+ io_asic = ed98_asic_nc5098;
+ offset = 0x2000;
+ reset = 7;
+ n = 16+8; /* XXX */
+ break;
+ }
+
+ bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET);
+ for (i = ED_NOVELL_ASIC_OFFSET; i < ED_NOVELL_IO_PORTS; i++) {
+ io_res[i] = io_asic[i - ED_NOVELL_ASIC_OFFSET] + offset;
+ }
+
+ res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
+ io_res, n, RF_ACTIVE);
+ if (!res) {
+ return (ENOENT);
+ }
+
+ sc->port_rid = rid;
+ sc->port_res = res;
+ sc->port_used = n;
+
+ /* Re-map i/o table if needed */
+ switch (sc->type) {
+ case ED_TYPE98_LA98:
+ case ED_TYPE98_NW98X:
+ io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
+ n++;
+ break;
+
+ case ED_TYPE98_108:
+ adj = (rman_get_start(res) & 0xf000) / 2;
+ offset = (offset | adj) - rman_get_start(res);
+
+ for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) {
+ io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
+ }
+ break;
+
+ case ED_TYPE98_CNET98:
+ io_nic = io_asic = ed98_ioaddr_cnet98;
+ offset = 1;
+
+ bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET);
+ for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) {
+ io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
+ }
+ break;
+
+ case ED_TYPE98_NC5098:
+ n = ED_NOVELL_IO_PORTS;
+ break;
+ }
+
+ if (reset != ED_NOVELL_RESET) {
+ io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_RESET] =
+ io_res[ED_NOVELL_ASIC_OFFSET + reset];
+ }
+ if (data != ED_NOVELL_DATA) {
+ io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA] =
+ io_res[ED_NOVELL_ASIC_OFFSET + data];
+#if 0
+ io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA + 1] =
+ io_res[ED_NOVELL_ASIC_OFFSET + data + 1];
+#endif
+ }
+
+ error = isa_load_resourcev(res, io_res, n);
+ if (error != 0) {
+ return (ENOENT);
+ }
+#ifdef ED_DEBUG
+ device_printf(dev, "ed98_alloc_port: i/o ports = %d\n", n);
+ for (i = 0; i < n; i++) {
+ printf("%x,", io_res[i]);
+ }
+ printf("\n");
+#endif
+ return (0);
+}
+
+static int
+ed98_alloc_memory(dev, rid)
+ device_t dev;
+ int rid;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ u_long conf_maddr, conf_msize;
+
+ error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
+ &conf_maddr, &conf_msize);
+ if (error) {
+ return (error);
+ }
+
+ if ((conf_maddr == 0) || (conf_msize == 0)) {
+ return (ENXIO);
+ }
+
+ error = ed_alloc_memory(dev, rid, (int) conf_msize);
+ if (error) {
+ return (error);
+ }
+
+ sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_size = conf_msize;
+
+ return (0);
+}
+
+/*
+ * Generic probe routine for testing for the existance of a DS8390.
+ * Must be called after the NIC has just been reset. This routine
+ * works by looking at certain register values that are guaranteed
+ * to be initialized a certain way after power-up or reset. Seems
+ * not to currently work on the 83C690.
+ *
+ * Specifically:
+ *
+ * Register reset bits set bits
+ * Command Register (CR) TXP, STA RD2, STP
+ * Interrupt Status (ISR) RST
+ * Interrupt Mask (IMR) All bits
+ * Data Control (DCR) LAS
+ * Transmit Config. (TCR) LB1, LB0
+ *
+ * XXX - We only check the CR register.
+ *
+ * Return 1 if 8390 was found, 0 if not.
+ */
+
+static int
+ed98_probe_generic8390(sc)
+ struct ed_softc *sc;
+{
+ u_char tmp = ed_nic_inb(sc, ED_P0_CR);
+#ifdef DIAGNOSTIC
+ printf("ed?: inb(ED_P0_CR)=%x\n", tmp);
+#endif
+ if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
+ (ED_CR_RD2 | ED_CR_STP)) {
+ return (0);
+ }
+
+ (void) ed_nic_inb(sc, ED_P0_ISR);
+
+ return (1);
+}
+
+static int
+ed98_probe_Novell(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int n;
+ u_char romdata[ETHER_ADDR_LEN * 2], tmp;
+
+#ifdef ED_DEBUG
+ device_printf(dev, "ed98_probe_Novell: start\n");
+#endif
+ error = ed98_alloc_port(dev, port_rid);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ /* Reset the board */
+#ifdef ED_DEBUG
+ device_printf(dev, "ed98_probe_Novell: reset\n");
+#endif
+ switch (sc->type) {
+#if 1 /* XXX - I'm not sure this is really necessary... */
+ case ED_TYPE98_BDN:
+ tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
+ ed_asic_outb(sc, ED_NOVELL_RESET, (tmp & 0xf0) | 0x08);
+ ed_nic_outb(sc, 0x04, tmp);
+ (void) ed_asic_inb(sc, 0x08);
+ ed_asic_outb(sc, 0x08, tmp);
+ ed_asic_outb(sc, 0x08, tmp & 0x7f);
+ break;
+#endif
+ case ED_TYPE98_NC5098:
+ ed_asic_outb(sc, ED_NOVELL_RESET, 0x00);
+ DELAY(5000);
+ ed_asic_outb(sc, ED_NOVELL_RESET, 0x01);
+ break;
+
+ default:
+ tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
+
+ /*
+ * I don't know if this is necessary; probably cruft leftover from
+ * Clarkson packet driver code. Doesn't do a thing on the boards I've
+ * tested. -DG [note that a outb(0x84, 0) seems to work here, and is
+ * non-invasive...but some boards don't seem to reset and I don't have
+ * complete documentation on what the 'right' thing to do is...so we
+ * do the invasive thing for now. Yuck.]
+ */
+ ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
+ break;
+ }
+ DELAY(5000);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ DELAY(5000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed98_probe_generic8390(sc)) {
+ return (ENXIO);
+ }
+
+ /* Test memory via PIO */
+#ifdef ED_DEBUG
+ device_printf(dev, "ed98_probe_Novell: test memory\n");
+#endif
+ sc->cr_proto = ED_CR_RD2;
+ if (!ed_pio_testmem(sc, 8192, 0, flags)
+ && !ed_pio_testmem(sc, 16384, 1, flags)) {
+ return (ENXIO);
+ }
+
+ /* Setup the board type */
+#ifdef ED_DEBUG
+ device_printf(dev, "ed98_probe_Novell: board type\n");
+#endif
+ switch (sc->type) {
+ case ED_TYPE98_BDN:
+ sc->type_str = "LD-BDN";
+ break;
+ case ED_TYPE98_EGY:
+ sc->type_str = "EGY-98";
+ break;
+ case ED_TYPE98_LGY:
+ sc->type_str = "LGY-98";
+ break;
+ case ED_TYPE98_ICM:
+ sc->type_str = "ICM";
+ break;
+ case ED_TYPE98_108:
+ sc->type_str = "PC-9801-108";
+ break;
+ case ED_TYPE98_LA98:
+ sc->type_str = "LA-98";
+ break;
+ case ED_TYPE98_NW98X:
+ sc->type_str = "NW98X";
+ break;
+ case ED_TYPE98_NC5098:
+ sc->type_str = "NC5098";
+ break;
+ default:
+ sc->type_str = NULL;
+ break;
+ }
+
+ /* Get station address */
+ switch (sc->type) {
+ case ED_TYPE98_NC5098:
+ for (n = 0; n < ETHER_ADDR_LEN; n++) {
+ sc->arpcom.ac_enaddr[n] =
+ ed_asic_inb(sc, ED_NC5098_ENADDR + n);
+ }
+ break;
+
+ default:
+ ed_pio_readmem(sc, 0, romdata, sizeof(romdata));
+ for (n = 0; n < ETHER_ADDR_LEN; n++) {
+ sc->arpcom.ac_enaddr[n] =
+ romdata[n * (sc->isa16bit + 1)];
+ }
+ break;
+ }
+
+ /* clear any pending interrupts that might have occurred above */
+ ed_nic_outb(sc, ED_P0_ISR, 0xff);
+
+ return (0);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for SIC-98 boards
+ */
+static int
+ed_probe_SIC98(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int i;
+ u_char sum;
+
+ /*
+ * Setup card RAM and I/O address
+ * Kernel Virtual to segment C0000-DFFFF????
+ */
+ error = ed98_alloc_port(dev, port_rid);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ error = ed98_alloc_memory(dev, 0);
+ if (error) {
+ return (error);
+ }
+
+ /* Reset card to force it into a known state. */
+ ed_asic_outb(sc, 0, 0x00);
+ DELAY(100);
+ if (ED_TYPE98SUB(flags) == 0) {
+ /* SIC-98/SIU-98 */
+ ed_asic_outb(sc, 0, 0x94);
+ DELAY(100);
+ ed_asic_outb(sc, 0, 0x94);
+ } else {
+ /* SIU-98-D */
+ ed_asic_outb(sc, 0, 0x80);
+ DELAY(100);
+ ed_asic_outb(sc, 0, 0x94);
+ DELAY(100);
+ ed_asic_outb(sc, 0, 0x9e);
+ }
+ DELAY(100);
+
+ /*
+ * Here we check the card ROM, if the checksum passes, and the
+ * type code and ethernet address check out, then we know we have
+ * an SIC card.
+ */
+ sum = sc->mem_start[6 * 2];
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ sum ^= (sc->arpcom.ac_enaddr[i] = sc->mem_start[i * 2]);
+ }
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_probe_sic98: got address %6D\n",
+ sc->arpcom.ac_enaddr, ":");
+#endif
+ if (sum != 0) {
+ return (ENXIO);
+ }
+ if ((sc->arpcom.ac_enaddr[0] | sc->arpcom.ac_enaddr[1] |
+ sc->arpcom.ac_enaddr[2]) == 0) {
+ return (ENXIO);
+ }
+
+ sc->vendor = ED_VENDOR_MISC;
+ sc->type_str = "SIC98";
+ sc->isa16bit = 1;
+ sc->cr_proto = 0;
+
+ /*
+ * SIC RAM page 0x0000-0x3fff(or 0x7fff)
+ */
+ if (ED_TYPE98SUB(flags) == 0) {
+ ed_asic_outb(sc, 0, 0x90);
+ } else {
+ ed_asic_outb(sc, 0, 0x8e);
+ }
+ DELAY(100);
+
+ /*
+ * clear interface memory, then sum to make sure its valid
+ */
+ bzero(sc->mem_start, sc->mem_size);
+
+ for (i = 0; i < sc->mem_size; i++) {
+ if (sc->mem_start[i]) {
+ device_printf(dev, "failed to clear shared memory "
+ "at %lx - check configuration\n",
+ kvtop(sc->mem_start + i));
+
+ return (ENXIO);
+ }
+ }
+
+ sc->mem_shared = 1;
+ sc->mem_end = sc->mem_start + sc->mem_size;
+
+ /*
+ * allocate one xmit buffer if < 16k, two buffers otherwise
+ */
+ if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
+ sc->txb_cnt = 1;
+ } else {
+ sc->txb_cnt = 2;
+ }
+ sc->tx_page_start = 0;
+
+ sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
+ sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ return (0);
+}
+
+/*
+ * Contec C-NET(98) series support routines
+ */
+static void
+ed_reset_CNET98(sc, flags)
+ struct ed_softc *sc;
+ int flags;
+{
+ u_short init_addr = ED_CNET98_INIT;
+ u_char tmp;
+
+ /* Choose initial register address */
+ if (ED_TYPE98SUB(flags) != 0) {
+ init_addr = ED_CNET98_INIT2;
+ }
+#ifdef ED_DEBUG
+ printf("ed?: initial register=%x\n", init_addr);
+#endif
+ /*
+ * Reset the board to force it into a known state.
+ */
+ outb(init_addr, 0x00); /* request */
+ DELAY(5000);
+ outb(init_addr, 0x01); /* cancel */
+ DELAY(5000);
+
+ /*
+ * Set I/O address(A15-12) and cpu type
+ *
+ * AAAAIXXC(8bit)
+ * AAAA: A15-A12, I: I/O enable, XX: reserved, C: CPU type
+ *
+ * CPU type is 1:80286 or higher, 0:not.
+ * But FreeBSD runs under i386 or higher, thus it must be 1.
+ */
+ tmp = (rman_get_start(sc->port_res) & 0xf000) >> 8;
+ tmp |= (0x08 | 0x01);
+#ifdef ED_DEBUG
+ printf("ed?: outb(%x, %x)\n", init_addr + 2, tmp);
+#endif
+ outb(init_addr + 2, tmp);
+ DELAY(5000);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ DELAY(5000);
+}
+
+static void
+ed_winsel_CNET98(sc, bank)
+ struct ed_softc *sc;
+ u_short bank;
+{
+ u_char mem = (kvtop(sc->mem_start) >> 12) & 0xff;
+
+ /*
+ * Disable window memory
+ * bit7 is 0:disable
+ */
+ ed_asic_outb(sc, ED_CNET98_WIN_REG, mem & 0x7f);
+ DELAY(10);
+
+ /*
+ * Select window address
+ * FreeBSD address 0xf00xxxxx
+ */
+ ed_asic_outb(sc, ED_CNET98_MAP_REG0L, bank & 0xff);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG0H, (bank >> 8) & 0xff);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG1L, 0x00);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG1H, 0x41);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG2L, 0x00);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG2H, 0x42);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG3L, 0x00);
+ DELAY(10);
+ ed_asic_outb(sc, ED_CNET98_MAP_REG3H, 0x43);
+ DELAY(10);
+
+ /*
+ * Enable window memory(16Kbyte)
+ * bit7 is 1:enable
+ */
+#ifdef ED_DEBUG
+ printf("ed?: window start address=%x\n", mem);
+#endif
+ ed_asic_outb(sc, ED_CNET98_WIN_REG, mem);
+ DELAY(10);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for C-NET(98) boards
+ */
+static int
+ed_probe_CNET98(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ u_char tmp;
+ u_long conf_irq, junk;
+ int i;
+#ifdef DIAGNOSTIC
+ u_char tmp_s;
+#endif
+
+ error = ed98_alloc_port(dev, port_rid);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ error = ed98_alloc_memory(dev, 0);
+ if (error) {
+ return (error);
+ }
+
+ /* Check I/O address. 0x[a-f]3d0 are allowed. */
+ if (((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0)
+ || ((rman_get_start(sc->port_res) & 0xf000) < (u_short) 0xa000)) {
+#ifdef DIAGNOSTIC
+ device_printf(dev, "Invalid i/o port configuration (0x%x) "
+ "must be %s for %s\n", rman_get_start(sc->port_res),
+ "0x[a-f]3d0", "CNET98");
+#endif
+ return (ENXIO);
+ }
+
+#ifdef DIAGNOSTIC
+ /* Check window area address */
+ tmp_s = kvtop(sc->mem_start) >> 12;
+ if (tmp_s < 0x80) {
+ device_printf(dev, "Please change window address(0x%x)\n",
+ kvtop(sc->mem_start));
+ return (ENXIO);
+ }
+
+ tmp_s &= 0x0f;
+ tmp = rman_get_start(sc->port_res) >> 12;
+ if ((tmp_s <= tmp) && (tmp < (tmp_s + 4))) {
+ device_printf(dev, "Please change iobase address(0x%x) "
+ "or window address(0x%x)\n",
+ rman_get_start(sc->port_res), kvtop(sc->mem_start));
+ return (ENXIO);
+ }
+#endif
+ /* Reset the board */
+ ed_reset_CNET98(sc, flags);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ DELAY(5000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed98_probe_generic8390(sc)) {
+ return (ENXIO);
+ }
+
+ /*
+ * Set window ethernet address area
+ * board memory base 0x480000 data 256byte
+ */
+ ed_winsel_CNET98(sc, 0x4800);
+
+ /*
+ * Get station address from on-board ROM
+ */
+ bcopy(sc->mem_start, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
+
+ sc->vendor = ED_VENDOR_MISC;
+ sc->type_str = "CNET98";
+ sc->isa16bit = 0;
+ sc->cr_proto = ED_CR_RD2;
+
+ /*
+ * Set window buffer memory area
+ * board memory base 0x400000 data 16kbyte
+ */
+ ed_winsel_CNET98(sc, 0x4000);
+
+ /*
+ * clear interface memory, then sum to make sure its valid
+ */
+ bzero(sc->mem_start, sc->mem_size);
+
+ for (i = 0; i < sc->mem_size; i++) {
+ if (sc->mem_start[i]) {
+ device_printf(dev, "failed to clear shared memory "
+ "at %lx - check configuration\n",
+ kvtop(sc->mem_start + i));
+
+ return (ENXIO);
+ }
+ }
+
+ sc->mem_shared = 1;
+ sc->mem_end = sc->mem_start + sc->mem_size;
+
+ sc->txb_cnt = 1; /* XXX */
+ sc->tx_page_start = 0;
+
+ sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE;
+ sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ /*
+ * Set interrupt level
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0,
+ &conf_irq, &junk);
+ if (error)
+ return (error);
+
+ switch (conf_irq) {
+ case 3:
+ tmp = ED_CNET98_INT_IRQ3;
+ break;
+ case 5:
+ tmp = ED_CNET98_INT_IRQ5;
+ break;
+ case 6:
+ tmp = ED_CNET98_INT_IRQ6;
+ break;
+ case 9:
+ tmp = ED_CNET98_INT_IRQ9;
+ break;
+ case 12:
+ tmp = ED_CNET98_INT_IRQ12;
+ break;
+ case 13:
+ tmp = ED_CNET98_INT_IRQ13;
+ break;
+ default:
+ device_printf(dev, "Invalid irq configuration (%ld) must be "
+ "%s for %s\n", conf_irq, "3,5,6,9,12,13", "CNET98");
+ return (ENXIO);
+ }
+ ed_asic_outb(sc, ED_CNET98_INT_LEV, tmp);
+ DELAY(1000);
+ /*
+ * Set interrupt mask.
+ * bit7:1 all interrupt mask
+ * bit1:1 timer interrupt mask
+ * bit0:0 NS controler interrupt enable
+ */
+ ed_asic_outb(sc, ED_CNET98_INT_MASK, 0x7e);
+ DELAY(1000);
+
+ return (0);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for C-NET(98)E/L boards
+ */
+static int
+ed_probe_CNET98EL(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int i;
+ u_char romdata[ETHER_ADDR_LEN * 2], tmp;
+ u_long conf_irq, junk;
+
+ error = ed98_alloc_port(dev, port_rid);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ /* Check I/O address. 0x[0-f]3d0 are allowed. */
+ if ((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) {
+#ifdef DIAGNOSTIC
+ device_printf(dev, "Invalid i/o port configuration (0x%x) "
+ "must be %s for %s\n", rman_get_start(sc->port_res),
+ "0x?3d0", "CNET98E/L");
+#endif
+ return (ENXIO);
+ }
+
+ /* Reset the board */
+ ed_reset_CNET98(sc, flags);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ DELAY(5000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed98_probe_generic8390(sc)) {
+ return (ENXIO);
+ }
+
+ /* Test memory via PIO */
+ sc->cr_proto = ED_CR_RD2;
+ if (!ed_pio_testmem(sc, ED_CNET98EL_PAGE_OFFSET, 1, flags)) {
+ return (ENXIO);
+ }
+
+ /* This looks like a C-NET(98)E/L board. */
+ sc->type_str = "CNET98E/L";
+
+ /*
+ * Set IRQ. C-NET(98)E/L only allows a choice of irq 3,5,6.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0,
+ &conf_irq, &junk);
+ if (error) {
+ return (error);
+ }
+
+ switch (conf_irq) {
+ case 3:
+ tmp = ED_CNET98EL_ICR_IRQ3;
+ break;
+ case 5:
+ tmp = ED_CNET98EL_ICR_IRQ5;
+ break;
+ case 6:
+ tmp = ED_CNET98EL_ICR_IRQ6;
+ break;
+#if 0
+ case 12:
+ tmp = ED_CNET98EL_ICR_IRQ12;
+ break;
+#endif
+ default:
+ device_printf(dev, "Invalid irq configuration (%ld) must be "
+ "%s for %s\n", conf_irq, "3,5,6", "CNET98E/L");
+ return (ENXIO);
+ }
+ ed_asic_outb(sc, ED_CNET98EL_ICR, tmp);
+ ed_asic_outb(sc, ED_CNET98EL_IMR, 0x7e);
+
+ /* Get station address from on-board ROM */
+ ed_pio_readmem(sc, 16384, romdata, sizeof(romdata));
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ sc->arpcom.ac_enaddr[i] = romdata[i * 2];
+ }
+
+ /* clear any pending interrupts that might have occurred above */
+ ed_nic_outb(sc, ED_P0_ISR, 0xff);
+
+ return (0);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for PC-9801-77 boards
+ */
+static int
+ed_probe_NEC77(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ u_char tmp;
+ u_long conf_irq, junk;
+
+ error = ed98_probe_Novell(dev, port_rid, flags);
+ if (error) {
+ return (error);
+ }
+
+ /* LA/T-98 does not need IRQ setting. */
+ if (ED_TYPE98SUB(flags) == 0) {
+ return (0);
+ }
+
+ /*
+ * Set IRQ. PC-9801-77 only allows a choice of irq 3,5,6,12,13.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0,
+ &conf_irq, &junk);
+ if (error) {
+ return (error);
+ }
+
+ switch (conf_irq) {
+ case 3:
+ tmp = ED_NEC77_IRQ3;
+ break;
+ case 5:
+ tmp = ED_NEC77_IRQ5;
+ break;
+ case 6:
+ tmp = ED_NEC77_IRQ6;
+ break;
+ case 12:
+ tmp = ED_NEC77_IRQ12;
+ break;
+ case 13:
+ tmp = ED_NEC77_IRQ13;
+ break;
+ default:
+ device_printf(dev, "Invalid irq configuration (%ld) must be "
+ "%s for %s\n", conf_irq, "3,5,6,12,13", "PC-9801-77");
+ return (ENXIO);
+ }
+ ed_asic_outb(sc, ED_NEC77_IRQ, tmp);
+
+ return (0);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for EC/EP-98X boards
+ */
+static int
+ed_probe_NW98X(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ u_char tmp;
+ u_long conf_irq, junk;
+
+ error = ed98_probe_Novell(dev, port_rid, flags);
+ if (error) {
+ return (error);
+ }
+
+ /* Networld 98X3 does not need IRQ setting. */
+ if (ED_TYPE98SUB(flags) == 0) {
+ return (0);
+ }
+
+ /*
+ * Set IRQ. EC/EP-98X only allows a choice of irq 3,5,6,12,13.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0,
+ &conf_irq, &junk);
+ if (error) {
+ return (error);
+ }
+
+ switch (conf_irq) {
+ case 3:
+ tmp = ED_NW98X_IRQ3;
+ break;
+ case 5:
+ tmp = ED_NW98X_IRQ5;
+ break;
+ case 6:
+ tmp = ED_NW98X_IRQ6;
+ break;
+ case 12:
+ tmp = ED_NW98X_IRQ12;
+ break;
+ case 13:
+ tmp = ED_NW98X_IRQ13;
+ break;
+ default:
+ device_printf(dev, "Invalid irq configuration (%ld) must be "
+ "%s for %s\n", conf_irq, "3,5,6,12,13", "EC/EP-98X");
+ return (ENXIO);
+ }
+ ed_asic_outb(sc, ED_NW98X_IRQ, tmp);
+
+ return (0);
+}
+
+/*
+ * Read SB-9801 station address from Serial Two-Wire EEPROM
+ */
+static void
+ed_get_SB98(sc)
+ struct ed_softc *sc;
+{
+ int i, j;
+ u_char mask, val;
+
+ /* enable EEPROM acceess */
+ ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_ENABLE);
+
+ /* output start command */
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+
+ /* output address (7bit) */
+ for (mask = 0x40; mask != 0; mask >>= 1) {
+ val = 0;
+ if (ED_SB98_ADDRESS & mask)
+ val = ED_SB98_EEP_SDA;
+ ed_asic_outb(sc, ED_SB98_EEP, val);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, val | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+ }
+
+ /* output READ command */
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+
+ /* read station address */
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ /* output ACK */
+ ed_asic_outb(sc, ED_SB98_EEP, 0);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+
+ val = 0;
+ for (j = 0; j < 8; j++) {
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+ val <<= 1;
+ val |= (ed_asic_inb(sc, ED_SB98_EEP) & ED_SB98_EEP_SDA);
+ DELAY(ED_SB98_EEP_DELAY);
+ }
+ sc->arpcom.ac_enaddr[i] = val;
+ }
+
+ /* output Last ACK */
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+
+ /* output stop command */
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+ ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
+ DELAY(ED_SB98_EEP_DELAY);
+
+ /* disable EEPROM access */
+ ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_DISABLE);
+}
+
+/*
+ * Probe and vendor-specific initialization routine for SB-9801 boards
+ */
+static int
+ed_probe_SB98(dev, port_rid, flags)
+ device_t dev;
+ int port_rid;
+ int flags;
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ u_char tmp;
+ u_long conf_irq, junk;
+
+ error = ed98_alloc_port(dev, port_rid);
+ if (error) {
+ return (error);
+ }
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ /* Check I/O address. 00d[02468ace] are allowed. */
+ if ((rman_get_start(sc->port_res) & ~0x000e) != 0x00d0) {
+#ifdef DIAGNOSTIC
+ device_printf(dev, "Invalid i/o port configuration (0x%x) "
+ "must be %s for %s\n", rman_get_start(sc->port_res),
+ "0xd?", "SB9801");
+#endif
+ return (ENXIO);
+ }
+
+ /* Write I/O port address and read 4 times */
+ outb(ED_SB98_IO_INHIBIT, rman_get_start(sc->port_res) & 0xff);
+ (void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
+ (void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
+ (void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
+ (void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
+
+ /*
+ * Check IRQ. Soliton SB-9801 only allows a choice of
+ * irq 3,5,6,12
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0,
+ &conf_irq, &junk);
+ if (error) {
+ return (error);
+ }
+
+ switch (conf_irq) {
+ case 3:
+ tmp = ED_SB98_CFG_IRQ3;
+ break;
+ case 5:
+ tmp = ED_SB98_CFG_IRQ5;
+ break;
+ case 6:
+ tmp = ED_SB98_CFG_IRQ6;
+ break;
+ case 12:
+ tmp = ED_SB98_CFG_IRQ12;
+ break;
+ default:
+ device_printf(dev, "Invalid irq configuration (%ld) must be "
+ "%s for %s\n", conf_irq, "3,5,6,12", "SB9801");
+ return (ENXIO);
+ }
+
+ if (flags & ED_FLAGS_DISABLE_TRANCEIVER) {
+ tmp |= ED_SB98_CFG_ALTPORT;
+ }
+ ed_asic_outb(sc, ED_SB98_CFG, ED_SB98_CFG_ENABLE | tmp);
+ ed_asic_outb(sc, ED_SB98_POLARITY, 0x01);
+
+ /* Reset the board. */
+ ed_asic_outb(sc, ED_NOVELL_RESET, 0x7a);
+ DELAY(300);
+ ed_asic_outb(sc, ED_NOVELL_RESET, 0x79);
+ DELAY(300);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ DELAY(5000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed98_probe_generic8390(sc)) {
+ return (ENXIO);
+ }
+
+ /* Test memory via PIO */
+ sc->cr_proto = ED_CR_RD2;
+ if (!ed_pio_testmem(sc, 16384, 1, flags)) {
+ return (ENXIO);
+ }
+
+ /* This looks like an SB9801 board. */
+ sc->type_str = "SB9801";
+
+ /* Get station address */
+ ed_get_SB98(sc);
+
+ /* clear any pending interrupts that might have occurred above */
+ ed_nic_outb(sc, ED_P0_ISR, 0xff);
+
+ return (0);
+}
+
+/*
+ * Test the ability to read and write to the NIC memory.
+ */
+static int
+ed_pio_testmem(sc, page_offset, isa16bit, flags)
+ struct ed_softc *sc;
+ int page_offset;
+ int isa16bit;
+ int flags;
+{
+ u_long memsize;
+ static char test_pattern[32] = "THIS is A memory TEST pattern";
+ char test_buffer[32];
+#ifdef DIAGNOSTIC
+ int page_end;
+#endif
+
+ sc->vendor = ED_VENDOR_NOVELL;
+ sc->mem_shared = 0;
+ sc->isa16bit = isa16bit;
+
+ /* 8k of memory plus an additional 8k if 16bit */
+ memsize = (isa16bit ? 16384 : 8192);
+
+ /*
+ * This prevents packets from being stored in the NIC memory when the
+ * readmem routine turns on the start bit in the CR.
+ */
+ ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
+
+ /* Initialize DCR for byte/word operations */
+ if (isa16bit) {
+ ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
+ } else {
+ ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+ }
+ ed_nic_outb(sc, ED_P0_PSTART, page_offset / ED_PAGE_SIZE);
+ ed_nic_outb(sc, ED_P0_PSTOP, (page_offset + memsize) / ED_PAGE_SIZE);
+#ifdef ED_DEBUG
+ printf("ed?: ed_pio_testmem: page start=%x, end=%x",
+ page_offset, page_offset + memsize);
+#endif
+
+ /*
+ * Write a test pattern. If this fails, then we don't know
+ * what this board is.
+ */
+ ed_pio_writemem(sc, test_pattern, page_offset, sizeof(test_pattern));
+ ed_pio_readmem(sc, page_offset, test_buffer, sizeof(test_pattern));
+
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
+#ifdef ED_DEBUG
+ printf("ed?: ed_pio_testmem: bcmp(page %x) NG",
+ page_offset);
+#endif
+ return (0);
+ }
+
+#ifdef DIAGNOSTIC
+ /* Check the bottom. */
+ page_end = page_offset + memsize - ED_PAGE_SIZE;
+ ed_pio_writemem(sc, test_pattern, page_end, sizeof(test_pattern));
+ ed_pio_readmem(sc, page_end, test_buffer, sizeof(test_pattern));
+
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
+#ifdef ED_DEBUG
+ printf("ed?: ed_pio_testmem: bcmp(page %x) NG",
+ page_end);
+#endif
+ return (0);
+ }
+#endif
+ sc->mem_size = memsize;
+ sc->mem_start = (char *) page_offset;
+ sc->mem_end = sc->mem_start + memsize;
+ sc->tx_page_start = page_offset / ED_PAGE_SIZE;
+
+ /*
+ * Use one xmit buffer if < 16k, two buffers otherwise (if not told
+ * otherwise).
+ */
+ if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
+ sc->txb_cnt = 1;
+ } else {
+ sc->txb_cnt = 2;
+ }
+
+ sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
+ sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ return (1);
+}
+#endif /* PC98 */
diff --git a/sys/dev/mly/mly_cam.c b/sys/dev/mly/mly_cam.c
new file mode 100644
index 000000000000..9175b276616d
--- /dev/null
+++ b/sys/dev/mly/mly_cam.c
@@ -0,0 +1,513 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * CAM interface for FreeBSD
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/devicestat.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/scsi/scsi_all.h>
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+
+#include <dev/mly/mlyreg.h>
+#include <dev/mly/mlyvar.h>
+#include <dev/mly/mly_tables.h>
+
+static void mly_cam_poll(struct cam_sim *sim);
+static void mly_cam_action(struct cam_sim *sim, union ccb *ccb);
+static void mly_cam_complete(struct mly_command *mc);
+static struct cam_periph *mly_find_periph(struct mly_softc *sc, int bus, int target);
+
+/********************************************************************************
+ * CAM-specific queue primitives
+ */
+static __inline void
+mly_enqueue_ccb(struct mly_softc *sc, union ccb *ccb)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_TAIL(&sc->mly_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
+ splx(s);
+}
+
+static __inline void
+mly_requeue_ccb(struct mly_softc *sc, union ccb *ccb)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_HEAD(&sc->mly_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
+ splx(s);
+}
+
+static __inline union ccb *
+mly_dequeue_ccb(struct mly_softc *sc)
+{
+ union ccb *ccb;
+ int s;
+
+ s = splcam();
+ if ((ccb = (union ccb *)TAILQ_FIRST(&sc->mly_cam_ccbq)) != NULL)
+ TAILQ_REMOVE(&sc->mly_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
+ splx(s);
+ return(ccb);
+}
+
+/********************************************************************************
+ * space-fill a character string
+ */
+static __inline void
+padstr(char *targ, char *src, int len)
+{
+ while (len-- > 0) {
+ if (*src != 0) {
+ *targ++ = *src++;
+ } else {
+ *targ++ = ' ';
+ }
+ }
+}
+
+/********************************************************************************
+ * Attach the real and virtual SCSI busses to CAM
+ */
+int
+mly_cam_attach(struct mly_softc *sc)
+{
+ struct cam_devq *devq;
+ int chn, nchn;
+
+ debug_called(1);
+
+ /* initialise the CCB queue */
+ TAILQ_INIT(&sc->mly_cam_ccbq);
+
+ /*
+ * Allocate a devq for all our channels combined.
+ */
+ if ((devq = cam_simq_alloc(sc->mly_controllerinfo->maximum_parallel_commands)) == NULL) {
+ mly_printf(sc, "can't allocate CAM SIM\n");
+ return(ENOMEM);
+ }
+
+ /*
+ * Iterate over channels, registering them with CAM.
+ */
+ nchn = sc->mly_controllerinfo->physical_channels_present +
+ sc->mly_controllerinfo->virtual_channels_present;
+ for (chn = 0; chn < nchn; chn++) {
+
+ /* allocate a sim */
+ if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action,
+ mly_cam_poll,
+ "mly",
+ sc,
+ device_get_unit(sc->mly_dev),
+ 1,
+ sc->mly_controllerinfo->maximum_parallel_commands,
+ devq)) == NULL) {
+ cam_simq_free(devq);
+ mly_printf(sc, "CAM SIM attach failed\n");
+ return(ENOMEM);
+ }
+
+ /* register the bus ID so we can get it later */
+ if (xpt_bus_register(sc->mly_cam_sim[chn], chn)) {
+ mly_printf(sc, "CAM XPT bus registration failed\n");
+ return(ENXIO);
+ }
+ debug(1, "registered sim %p bus %d", sc->mly_cam_sim[chn], chn);
+
+ }
+
+ return(0);
+}
+
+/********************************************************************************
+ * Detach from CAM
+ */
+void
+mly_cam_detach(struct mly_softc *sc)
+{
+ int chn, nchn, first;
+
+ debug_called(1);
+
+ nchn = sc->mly_controllerinfo->physical_channels_present +
+ sc->mly_controllerinfo->virtual_channels_present;
+
+ /*
+ * Iterate over channels, deregistering as we go.
+ */
+ nchn = sc->mly_controllerinfo->physical_channels_present +
+ sc->mly_controllerinfo->virtual_channels_present;
+ for (chn = 0, first = 1; chn < nchn; chn++) {
+
+ /*
+ * If a sim was registered for this channel, free it.
+ */
+ if (sc->mly_cam_sim[chn] != NULL) {
+ debug(1, "deregister bus %d", chn);
+ xpt_bus_deregister(cam_sim_path(sc->mly_cam_sim[chn]));
+ debug(1, "free sim for channel %d (%sfree queue)", chn, first ? "" : "don't ");
+ cam_sim_free(sc->mly_cam_sim[chn], first ? TRUE : FALSE);
+ first = 0;
+ }
+ }
+}
+
+/********************************************************************************
+ * Handle an action requested by CAM
+ */
+static void
+mly_cam_action(struct cam_sim *sim, union ccb *ccb)
+{
+ struct mly_softc *sc = cam_sim_softc(sim);
+
+ debug_called(2);
+
+ switch (ccb->ccb_h.func_code) {
+
+ /* perform SCSI I/O */
+ case XPT_SCSI_IO:
+ {
+ struct ccb_scsiio *csio = &ccb->csio;
+ int bus, target;
+
+ bus = cam_sim_bus(sim);
+ target = csio->ccb_h.target_id;
+
+ debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, ccb->ccb_h.target_lun);
+
+ /* check for I/O attempt to a protected device */
+ if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PROTECTED) {
+ debug(2, " device protected");
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+
+ /* check for I/O attempt to nonexistent device */
+ if (!(sc->mly_btl[bus][target].mb_flags & (MLY_BTL_LOGICAL | MLY_BTL_PHYSICAL))) {
+ debug(2, " device does not exist");
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+
+ /* XXX increase if/when we support large SCSI commands */
+ if (csio->cdb_len > MLY_CMD_SCSI_SMALL_CDB) {
+ debug(2, " command too large (%d > %d)", csio->cdb_len, MLY_CMD_SCSI_SMALL_CDB);
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+
+ /* check that the CDB pointer is not to a physical address */
+ if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) {
+ debug(2, " CDB pointer is to physical address");
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+
+ /* if there is data transfer, it must be to/from a virtual address */
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ if (csio->ccb_h.flags & CAM_DATA_PHYS) { /* we can't map it */
+ debug(2, " data pointer is to physical address");
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+ if (csio->ccb_h.flags & CAM_SCATTER_VALID) { /* we want to do the s/g setup */
+ debug(2, " data has premature s/g setup");
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ }
+ }
+
+ /* abandon aborted ccbs or those that have failed validation */
+ if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
+ debug(2, "abandoning CCB due to abort/validation failure");
+ break;
+ }
+
+ /* save the channel number in the ccb */
+ csio->ccb_h.sim_priv.entries[0].field = bus;
+
+ /* enqueue the ccb and start I/O */
+ mly_enqueue_ccb(sc, ccb);
+ mly_startio(sc);
+ return;
+ }
+
+ /* perform geometry calculations */
+ case XPT_CALC_GEOMETRY:
+ {
+ struct ccb_calc_geometry *ccg = &ccb->ccg;
+ u_int32_t secs_per_cylinder;
+
+ debug(2, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
+
+ if (sc->mly_controllerparam->bios_geometry == MLY_BIOSGEOM_8G) {
+ ccg->heads = 255;
+ ccg->secs_per_track = 63;
+ } else { /* MLY_BIOSGEOM_2G */
+ ccg->heads = 128;
+ ccg->secs_per_track = 32;
+ }
+ secs_per_cylinder = ccg->heads * ccg->secs_per_track;
+ ccg->cylinders = ccg->volume_size / secs_per_cylinder;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+
+ /* handle path attribute inquiry */
+ case XPT_PATH_INQ:
+ {
+ struct ccb_pathinq *cpi = &ccb->cpi;
+
+ debug(2, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
+
+ cpi->version_num = 1;
+ cpi->hba_inquiry = PI_TAG_ABLE; /* XXX extra flags for physical channels? */
+ cpi->target_sprt = 0;
+ cpi->hba_misc = 0;
+ cpi->max_target = MLY_MAX_TARGETS - 1;
+ cpi->max_lun = MLY_MAX_LUNS - 1;
+ cpi->initiator_id = sc->mly_controllerparam->initiator_id;
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "BSDi", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->unit_number = cam_sim_unit(sim);
+ cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 132 * 1024; /* XXX what to set this to? */
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+
+ default: /* we can't do this */
+ debug(2, "unspported func_code = 0x%x", ccb->ccb_h.func_code);
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
+
+ xpt_done(ccb);
+}
+
+/********************************************************************************
+ * Check for possibly-completed commands.
+ */
+static void
+mly_cam_poll(struct cam_sim *sim)
+{
+ struct mly_softc *sc = cam_sim_softc(sim);
+
+ debug_called(2);
+
+ mly_done(sc);
+}
+
+/********************************************************************************
+ * Pull a CCB off the work queue and turn it into a command.
+ */
+int
+mly_cam_command(struct mly_softc *sc, struct mly_command **mcp)
+{
+ struct mly_command *mc;
+ struct mly_command_scsi_small *ss;
+ struct ccb_scsiio *csio;
+ int error;
+
+ debug_called(2);
+
+ error = 0;
+ mc = NULL;
+ csio = NULL;
+
+ /* check for a CCB */
+ if (!(csio = (struct ccb_scsiio *)mly_dequeue_ccb(sc)))
+ goto out;
+
+ /* get a command to back it */
+ if (mly_alloc_command(sc, &mc)) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ /* build the command */
+ MLY_CMD_SETSTATE(mc, MLY_CMD_SETUP);
+ mc->mc_data = csio->data_ptr;
+ mc->mc_length = csio->dxfer_len;
+ mc->mc_complete = mly_cam_complete;
+ mc->mc_private = csio;
+
+ /* build the packet for the controller */
+ ss = &mc->mc_packet->scsi_small;
+ ss->opcode = MDACMD_SCSI;
+ if (csio->ccb_h.flags * CAM_DIS_DISCONNECT)
+ ss->command_control.disable_disconnect = 1;
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
+ ss->command_control.data_direction = MLY_CCB_WRITE;
+ ss->data_size = csio->dxfer_len;
+ ss->addr.phys.lun = csio->ccb_h.target_lun;
+ ss->addr.phys.target = csio->ccb_h.target_id;
+ ss->addr.phys.channel = csio->ccb_h.sim_priv.entries[0].field;
+ if (csio->ccb_h.timeout < (60 * 1000)) {
+ ss->timeout.value = csio->ccb_h.timeout / 1000;
+ ss->timeout.scale = MLY_TIMEOUT_SECONDS;
+ } else if (csio->ccb_h.timeout < (60 * 60 * 1000)) {
+ ss->timeout.value = csio->ccb_h.timeout / (60 * 1000);
+ ss->timeout.scale = MLY_TIMEOUT_MINUTES;
+ } else {
+ ss->timeout.value = csio->ccb_h.timeout / (60 * 60 * 1000); /* overflow? */
+ ss->timeout.scale = MLY_TIMEOUT_HOURS;
+ }
+ ss->maximum_sense_size = csio->sense_len;
+ ss->cdb_length = csio->cdb_len;
+ if (csio->ccb_h.flags & CAM_CDB_POINTER) {
+ bcopy(csio->cdb_io.cdb_ptr, ss->cdb, csio->cdb_len);
+ } else {
+ bcopy(csio->cdb_io.cdb_bytes, ss->cdb, csio->cdb_len);
+ }
+
+out:
+ if (error != 0) {
+ if (mc != NULL) {
+ mly_release_command(mc);
+ mc = NULL;
+ }
+ if (csio != NULL)
+ mly_requeue_ccb(sc, (union ccb *)csio);
+ }
+ *mcp = mc;
+ return(error);
+}
+
+/********************************************************************************
+ * Handle completion of a command - pass results back through the CCB
+ */
+static void
+mly_cam_complete(struct mly_command *mc)
+{
+ struct mly_softc *sc = mc->mc_sc;
+ struct ccb_scsiio *csio = (struct ccb_scsiio *)mc->mc_private;
+ struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)csio->data_ptr;
+ struct mly_btl *btl;
+ u_int8_t cmd;
+ int bus, target;
+
+ debug_called(2);
+
+ csio->scsi_status = mc->mc_status;
+ switch(mc->mc_status) {
+ case SCSI_STATUS_OK:
+ /*
+ * In order to report logical device type and status, we overwrite
+ * the result of the INQUIRY command to logical devices.
+ */
+ bus = csio->ccb_h.sim_priv.entries[0].field;
+ if (bus >= sc->mly_controllerinfo->physical_channels_present) {
+ if (csio->ccb_h.flags & CAM_CDB_POINTER) {
+ cmd = *csio->cdb_io.cdb_ptr;
+ } else {
+ cmd = csio->cdb_io.cdb_bytes[0];
+ }
+ if (cmd == INQUIRY) {
+ target = csio->ccb_h.target_id;
+ btl = &sc->mly_btl[bus][target];
+ padstr(inq->vendor, mly_describe_code(mly_table_device_type, btl->mb_type), 8);
+ padstr(inq->product, mly_describe_code(mly_table_device_state, btl->mb_state), 16);
+ padstr(inq->revision, "", 4);
+ }
+ }
+
+ debug(2, "SCSI_STATUS_OK");
+ csio->ccb_h.status = CAM_REQ_CMP;
+ break;
+
+ case SCSI_STATUS_CHECK_COND:
+ debug(2, "SCSI_STATUS_CHECK_COND sense %d resid %d", mc->mc_sense, mc->mc_resid);
+ csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ bzero(&csio->sense_data, SSD_FULL_SIZE);
+ bcopy(mc->mc_packet, &csio->sense_data, mc->mc_sense);
+ csio->sense_len = mc->mc_sense;
+ csio->ccb_h.status |= CAM_AUTOSNS_VALID;
+ csio->resid = mc->mc_resid; /* XXX this is a signed value... */
+ break;
+
+ case SCSI_STATUS_BUSY:
+ debug(2, "SCSI_STATUS_BUSY");
+ csio->ccb_h.status = CAM_SCSI_BUSY;
+ break;
+
+ default:
+ debug(2, "unknown status 0x%x", csio->scsi_status);
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ break;
+ }
+ xpt_done((union ccb *)csio);
+ mly_release_command(mc);
+}
+
+/********************************************************************************
+ * Find a peripheral attahed at (bus),(target)
+ */
+static struct cam_periph *
+mly_find_periph(struct mly_softc *sc, int bus, int target)
+{
+ struct cam_periph *periph;
+ struct cam_path *path;
+ int status;
+
+ status = xpt_create_path(&path, NULL, cam_sim_path(sc->mly_cam_sim[bus]), target, 0);
+ if (status == CAM_REQ_CMP) {
+ periph = cam_periph_find(path, NULL);
+ xpt_free_path(path);
+ } else {
+ periph = NULL;
+ }
+ return(periph);
+}
+
+/********************************************************************************
+ * Name the device at (bus)(target)
+ */
+int
+mly_name_device(struct mly_softc *sc, int bus, int target)
+{
+ struct cam_periph *periph;
+
+ if ((periph = mly_find_periph(sc, bus, target)) != NULL) {
+ sprintf(sc->mly_btl[bus][target].mb_name, "%s%d", periph->periph_name, periph->unit_number);
+ return(0);
+ }
+ sc->mly_btl[bus][target].mb_name[0] = 0;
+ return(ENOENT);
+}
diff --git a/sys/dev/mly/mly_pci.c b/sys/dev/mly/mly_pci.c
new file mode 100644
index 000000000000..c0dbd457ed88
--- /dev/null
+++ b/sys/dev/mly/mly_pci.c
@@ -0,0 +1,590 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/devicestat.h>
+#include <sys/disk.h>
+
+#include <machine/bus_memio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <dev/mly/mlyreg.h>
+#include <dev/mly/mlyvar.h>
+
+static int mly_pci_probe(device_t dev);
+static int mly_pci_attach(device_t dev);
+static int mly_pci_detach(device_t dev);
+static int mly_pci_shutdown(device_t dev);
+static int mly_pci_suspend(device_t dev);
+static int mly_pci_resume(device_t dev);
+static void mly_pci_intr(void *arg);
+
+static int mly_sg_map(struct mly_softc *sc);
+static void mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
+static int mly_mmbox_map(struct mly_softc *sc);
+static void mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
+static void mly_free_command_cluster(struct mly_command_cluster *mcc);
+
+static device_method_t mly_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mly_pci_probe),
+ DEVMETHOD(device_attach, mly_pci_attach),
+ DEVMETHOD(device_detach, mly_pci_detach),
+ DEVMETHOD(device_shutdown, mly_pci_shutdown),
+ DEVMETHOD(device_suspend, mly_pci_suspend),
+ DEVMETHOD(device_resume, mly_pci_resume),
+ { 0, 0 }
+};
+
+static driver_t mly_pci_driver = {
+ "mly",
+ mly_methods,
+ sizeof(struct mly_softc)
+};
+
+static devclass_t mly_devclass;
+DRIVER_MODULE(mly, pci, mly_pci_driver, mly_devclass, 0, 0);
+
+struct mly_ident
+{
+ u_int16_t vendor;
+ u_int16_t device;
+ u_int16_t subvendor;
+ u_int16_t subdevice;
+ int hwif;
+ char *desc;
+} mly_identifiers[] = {
+ {0x1069, 0xba56, 0x1069, 0x0040, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 2000"},
+ {0x1069, 0xba56, 0x1069, 0x0030, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 3000"},
+ {0x1069, 0x0050, 0x1069, 0x0050, MLY_HWIF_I960RX, "Mylex AcceleRAID 352"},
+ {0x1069, 0x0050, 0x1069, 0x0052, MLY_HWIF_I960RX, "Mylex AcceleRAID 170"},
+ {0x1069, 0x0050, 0x1069, 0x0054, MLY_HWIF_I960RX, "Mylex AcceleRAID 160"},
+ {0, 0, 0, 0, 0, 0}
+};
+
+/********************************************************************************
+ ********************************************************************************
+ Bus Interface
+ ********************************************************************************
+ ********************************************************************************/
+
+static int
+mly_pci_probe(device_t dev)
+{
+ struct mly_ident *m;
+
+ debug_called(1);
+
+ for (m = mly_identifiers; m->vendor != 0; m++) {
+ if ((m->vendor == pci_get_vendor(dev)) &&
+ (m->device == pci_get_device(dev)) &&
+ ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) &&
+ (m->subdevice == pci_get_subdevice(dev))))) {
+
+ device_set_desc(dev, m->desc);
+ return(-10); /* allow room to be overridden */
+ }
+ }
+ return(ENXIO);
+}
+
+static int
+mly_pci_attach(device_t dev)
+{
+ struct mly_softc *sc;
+ int i, error;
+ u_int32_t command;
+
+ debug_called(1);
+
+ /*
+ * Initialise softc.
+ */
+ sc = device_get_softc(dev);
+ bzero(sc, sizeof(*sc));
+ sc->mly_dev = dev;
+
+#ifdef MLY_DEBUG
+ if (device_get_unit(sc->mly_dev) == 0)
+ mly_softc0 = sc;
+#endif
+
+ /* assume failure is 'not configured' */
+ error = ENXIO;
+
+ /*
+ * Verify that the adapter is correctly set up in PCI space.
+ */
+ command = pci_read_config(sc->mly_dev, PCIR_COMMAND, 2);
+ command |= PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, command, 2);
+ command = pci_read_config(sc->mly_dev, PCIR_COMMAND, 2);
+ if (!(command & PCIM_CMD_BUSMASTEREN)) {
+ mly_printf(sc, "can't enable busmaster feature\n");
+ goto fail;
+ }
+ if ((command & PCIM_CMD_MEMEN) == 0) {
+ mly_printf(sc, "memory window not available\n");
+ goto fail;
+ }
+
+ /*
+ * Allocate the PCI register window.
+ */
+ sc->mly_regs_rid = PCIR_MAPS; /* first base address register */
+ if ((sc->mly_regs_resource = bus_alloc_resource(sc->mly_dev, SYS_RES_MEMORY, &sc->mly_regs_rid,
+ 0, ~0, 1, RF_ACTIVE)) == NULL) {
+ mly_printf(sc, "can't allocate register window\n");
+ goto fail;
+ }
+ sc->mly_btag = rman_get_bustag(sc->mly_regs_resource);
+ sc->mly_bhandle = rman_get_bushandle(sc->mly_regs_resource);
+
+ /*
+ * Allocate and connect our interrupt.
+ */
+ sc->mly_irq_rid = 0;
+ if ((sc->mly_irq = bus_alloc_resource(sc->mly_dev, SYS_RES_IRQ, &sc->mly_irq_rid,
+ 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+ mly_printf(sc, "can't allocate interrupt\n");
+ goto fail;
+ }
+ if (bus_setup_intr(sc->mly_dev, sc->mly_irq, INTR_TYPE_CAM, mly_pci_intr, sc, &sc->mly_intr)) {
+ mly_printf(sc, "can't set up interrupt\n");
+ goto fail;
+ }
+
+ /* assume failure is 'out of memory' */
+ error = ENOMEM;
+
+ /*
+ * Allocate the parent bus DMA tag appropriate for our PCI interface.
+ *
+ * Note that all of these controllers are 64-bit capable.
+ */
+ if (bus_dma_tag_create(NULL, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAXBSIZE, MLY_MAXSGENTRIES, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ &sc->mly_parent_dmat)) {
+ mly_printf(sc, "can't allocate parent DMA tag\n");
+ goto fail;
+ }
+
+ /*
+ * Create DMA tag for mapping buffers into controller-addressable space.
+ */
+ if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAXBSIZE, MLY_MAXSGENTRIES, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->mly_buffer_dmat)) {
+ mly_printf(sc, "can't allocate buffer DMA tag\n");
+ goto fail;
+ }
+
+ /*
+ * Initialise the DMA tag for command packets.
+ */
+ if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sizeof(union mly_command_packet) * MLY_CMD_CLUSTERCOUNT, 1, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->mly_packet_dmat)) {
+ mly_printf(sc, "can't allocate command packet DMA tag\n");
+ goto fail;
+ }
+
+ /*
+ * Detect the hardware interface version
+ */
+ for (i = 0; mly_identifiers[i].vendor != 0; i++) {
+ if ((mly_identifiers[i].vendor == pci_get_vendor(dev)) &&
+ (mly_identifiers[i].device == pci_get_device(dev))) {
+ sc->mly_hwif = mly_identifiers[i].hwif;
+ switch(sc->mly_hwif) {
+ case MLY_HWIF_I960RX:
+ debug(2, "set hardware up for i960RX");
+ sc->mly_doorbell_true = 0x00;
+ sc->mly_command_mailbox = MLY_I960RX_COMMAND_MAILBOX;
+ sc->mly_status_mailbox = MLY_I960RX_STATUS_MAILBOX;
+ sc->mly_idbr = MLY_I960RX_IDBR;
+ sc->mly_odbr = MLY_I960RX_ODBR;
+ sc->mly_error_status = MLY_I960RX_ERROR_STATUS;
+ sc->mly_interrupt_status = MLY_I960RX_INTERRUPT_STATUS;
+ sc->mly_interrupt_mask = MLY_I960RX_INTERRUPT_MASK;
+ break;
+ case MLY_HWIF_STRONGARM:
+ debug(2, "set hardware up for StrongARM");
+ sc->mly_doorbell_true = 0xff; /* doorbell 'true' is 0 */
+ sc->mly_command_mailbox = MLY_STRONGARM_COMMAND_MAILBOX;
+ sc->mly_status_mailbox = MLY_STRONGARM_STATUS_MAILBOX;
+ sc->mly_idbr = MLY_STRONGARM_IDBR;
+ sc->mly_odbr = MLY_STRONGARM_ODBR;
+ sc->mly_error_status = MLY_STRONGARM_ERROR_STATUS;
+ sc->mly_interrupt_status = MLY_STRONGARM_INTERRUPT_STATUS;
+ sc->mly_interrupt_mask = MLY_STRONGARM_INTERRUPT_MASK;
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Create the scatter/gather mappings.
+ */
+ if ((error = mly_sg_map(sc)))
+ goto fail;
+
+ /*
+ * Allocate and map the memory mailbox
+ */
+ if ((error = mly_mmbox_map(sc)))
+ goto fail;
+
+ /*
+ * Do bus-independent initialisation.
+ */
+ if ((error = mly_attach(sc)))
+ goto fail;
+
+ return(0);
+
+fail:
+ mly_free(sc);
+ return(error);
+}
+
+/********************************************************************************
+ * Disconnect from the controller completely, in preparation for unload.
+ */
+static int
+mly_pci_detach(device_t dev)
+{
+ struct mly_softc *sc = device_get_softc(dev);
+ int error;
+
+ debug_called(1);
+
+ if (sc->mly_state & MLY_STATE_OPEN)
+ return(EBUSY);
+
+ if ((error = mly_pci_shutdown(dev)))
+ return(error);
+
+ mly_free(sc);
+
+ return(0);
+}
+
+/********************************************************************************
+ * Bring the controller down to a dormant state and detach all child devices.
+ *
+ * This function is called before detach or system shutdown.
+ *
+ * Note that we can assume that the camq on the controller is empty, as we won't
+ * allow shutdown if any device is open.
+ */
+static int
+mly_pci_shutdown(device_t dev)
+{
+ struct mly_softc *sc = device_get_softc(dev);
+
+ debug_called(1);
+
+ mly_detach(sc);
+ return(0);
+}
+
+/********************************************************************************
+ * Bring the controller to a quiescent state, ready for system suspend.
+ *
+ * We can't assume that the controller is not active at this point, so we need
+ * to mask interrupts.
+ */
+static int
+mly_pci_suspend(device_t dev)
+{
+ struct mly_softc *sc = device_get_softc(dev);
+ int s;
+
+ debug_called(1);
+ s = splcam();
+ mly_detach(sc);
+ splx(s);
+ return(0);
+}
+
+/********************************************************************************
+ * Bring the controller back to a state ready for operation.
+ */
+static int
+mly_pci_resume(device_t dev)
+{
+ struct mly_softc *sc = device_get_softc(dev);
+
+ debug_called(1);
+ sc->mly_state &= ~MLY_STATE_SUSPEND;
+ MLY_UNMASK_INTERRUPTS(sc);
+ return(0);
+}
+
+/*******************************************************************************
+ * Take an interrupt, or be poked by other code to look for interrupt-worthy
+ * status.
+ */
+static void
+mly_pci_intr(void *arg)
+{
+ struct mly_softc *sc = (struct mly_softc *)arg;
+
+ debug_called(3);
+
+ /* collect finished commands, queue anything waiting */
+ mly_done(sc);
+};
+
+/********************************************************************************
+ ********************************************************************************
+ Bus-dependant Resource Management
+ ********************************************************************************
+ ********************************************************************************/
+
+/********************************************************************************
+ * Allocate memory for the scatter/gather tables
+ */
+static int
+mly_sg_map(struct mly_softc *sc)
+{
+ size_t segsize;
+
+ debug_called(1);
+
+ /*
+ * Create a single tag describing a region large enough to hold all of
+ * the s/g lists we will need.
+ */
+ segsize = sizeof(struct mly_sg_entry) * MLY_MAXCOMMANDS * MLY_MAXSGENTRIES;
+ if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ segsize, 1, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->mly_sg_dmat)) {
+ mly_printf(sc, "can't allocate scatter/gather DMA tag\n");
+ return(ENOMEM);
+ }
+
+ /*
+ * Allocate enough s/g maps for all commands and permanently map them into
+ * controller-visible space.
+ *
+ * XXX this assumes we can get enough space for all the s/g maps in one
+ * contiguous slab.
+ */
+ if (bus_dmamem_alloc(sc->mly_sg_dmat, (void **)&sc->mly_sg_table, BUS_DMA_NOWAIT, &sc->mly_sg_dmamap)) {
+ mly_printf(sc, "can't allocate s/g table\n");
+ return(ENOMEM);
+ }
+ bus_dmamap_load(sc->mly_sg_dmat, sc->mly_sg_dmamap, sc->mly_sg_table, segsize, mly_sg_map_helper, sc, 0);
+ return(0);
+}
+
+/********************************************************************************
+ * Save the physical address of the base of the s/g table.
+ */
+static void
+mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ struct mly_softc *sc = (struct mly_softc *)arg;
+
+ debug_called(2);
+
+ /* save base of s/g table's address in bus space */
+ sc->mly_sg_busaddr = segs->ds_addr;
+}
+
+/********************************************************************************
+ * Allocate memory for the memory-mailbox interface
+ */
+static int
+mly_mmbox_map(struct mly_softc *sc)
+{
+
+ /*
+ * Create a DMA tag for a single contiguous region large enough for the
+ * memory mailbox structure.
+ */
+ if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sizeof(struct mly_mmbox), 1, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->mly_mmbox_dmat)) {
+ mly_printf(sc, "can't allocate memory mailbox DMA tag\n");
+ return(ENOMEM);
+ }
+
+ /*
+ * Allocate the buffer
+ */
+ if (bus_dmamem_alloc(sc->mly_mmbox_dmat, (void **)&sc->mly_mmbox, BUS_DMA_NOWAIT, &sc->mly_mmbox_dmamap)) {
+ mly_printf(sc, "can't allocate memory mailbox\n");
+ return(ENOMEM);
+ }
+ bus_dmamap_load(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap, sc->mly_mmbox, sizeof(struct mly_mmbox),
+ mly_mmbox_map_helper, sc, 0);
+ bzero(sc->mly_mmbox, sizeof(*sc->mly_mmbox));
+ return(0);
+
+}
+
+/********************************************************************************
+ * Save the physical address of the memory mailbox
+ */
+static void
+mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ struct mly_softc *sc = (struct mly_softc *)arg;
+
+ debug_called(2);
+
+ sc->mly_mmbox_busaddr = segs->ds_addr;
+}
+
+/********************************************************************************
+ * Free all of the resources associated with (sc)
+ *
+ * Should not be called if the controller is active.
+ */
+void
+mly_free(struct mly_softc *sc)
+{
+ struct mly_command_cluster *mcc;
+
+ debug_called(1);
+
+ /* detach from CAM */
+ mly_cam_detach(sc);
+
+ /* throw away any command buffers */
+ while ((mcc = mly_dequeue_cluster(sc)) != NULL)
+ mly_free_command_cluster(mcc);
+
+ /* throw away the controllerinfo structure */
+ if (sc->mly_controllerinfo != NULL)
+ free(sc->mly_controllerinfo, M_DEVBUF);
+
+ /* throw away the controllerparam structure */
+ if (sc->mly_controllerparam != NULL)
+ free(sc->mly_controllerparam, M_DEVBUF);
+
+ /* destroy data-transfer DMA tag */
+ if (sc->mly_buffer_dmat)
+ bus_dma_tag_destroy(sc->mly_buffer_dmat);
+
+ /* free and destroy DMA memory and tag for s/g lists */
+ if (sc->mly_sg_table) {
+ bus_dmamap_unload(sc->mly_sg_dmat, sc->mly_sg_dmamap);
+ bus_dmamem_free(sc->mly_sg_dmat, sc->mly_sg_table, sc->mly_sg_dmamap);
+ }
+ if (sc->mly_sg_dmat)
+ bus_dma_tag_destroy(sc->mly_sg_dmat);
+
+ /* free and destroy DMA memory and tag for memory mailbox */
+ if (sc->mly_mmbox) {
+ bus_dmamap_unload(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap);
+ bus_dmamem_free(sc->mly_mmbox_dmat, sc->mly_mmbox, sc->mly_mmbox_dmamap);
+ }
+ if (sc->mly_mmbox_dmat)
+ bus_dma_tag_destroy(sc->mly_mmbox_dmat);
+
+ /* disconnect the interrupt handler */
+ if (sc->mly_intr)
+ bus_teardown_intr(sc->mly_dev, sc->mly_irq, sc->mly_intr);
+ if (sc->mly_irq != NULL)
+ bus_release_resource(sc->mly_dev, SYS_RES_IRQ, sc->mly_irq_rid, sc->mly_irq);
+
+ /* destroy the parent DMA tag */
+ if (sc->mly_parent_dmat)
+ bus_dma_tag_destroy(sc->mly_parent_dmat);
+
+ /* release the register window mapping */
+ if (sc->mly_regs_resource != NULL)
+ bus_release_resource(sc->mly_dev, SYS_RES_MEMORY, sc->mly_regs_rid, sc->mly_regs_resource);
+}
+
+/********************************************************************************
+ * Free a command cluster.
+ */
+static void
+mly_free_command_cluster(struct mly_command_cluster *mcc)
+{
+ struct mly_softc *sc = mcc->mcc_command[0].mc_sc;
+ int i;
+
+ debug_called(1);
+
+ for (i = 0; i < MLY_CMD_CLUSTERCOUNT; i++)
+ bus_dmamap_destroy(sc->mly_buffer_dmat, mcc->mcc_command[i].mc_datamap);
+
+ bus_dmamap_unload(sc->mly_packet_dmat, mcc->mcc_packetmap);
+ bus_dmamem_free(sc->mly_packet_dmat, mcc->mcc_packet, mcc->mcc_packetmap);
+ free(mcc, M_DEVBUF);
+}
+
diff --git a/sys/dev/mly/mly_tables.h b/sys/dev/mly/mly_tables.h
new file mode 100644
index 000000000000..5a83f1767353
--- /dev/null
+++ b/sys/dev/mly/mly_tables.h
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Lookup table for code-to-text translations.
+ */
+struct mly_code_lookup {
+ char *string;
+ u_int32_t code;
+};
+
+extern char *mly_describe_code(struct mly_code_lookup *table, u_int32_t code);
+
+#ifndef MLY_DEFINE_TABLES
+extern struct mly_code_lookup mly_table_bustype[];
+extern struct mly_code_lookup mly_table_controllertype[];
+extern struct mly_code_lookup mly_table_oemname[];
+extern struct mly_code_lookup mly_table_memorytype[];
+extern struct mly_code_lookup mly_table_cputype[];
+extern struct mly_code_lookup mly_table_event[];
+extern struct mly_code_lookup mly_table_device_state[];
+extern struct mly_code_lookup mly_table_device_type[];
+extern struct mly_code_lookup mly_table_stripe_size[];
+extern struct mly_code_lookup mly_table_cacheline_size[];
+
+#else /* MLY_DEFINE_TABLES */
+
+/********************************************************************************
+ * Look up a text description of a numeric code and return a pointer to same.
+ */
+char *
+mly_describe_code(struct mly_code_lookup *table, u_int32_t code)
+{
+ int i;
+
+ for (i = 0; table[i].string != NULL; i++)
+ if (table[i].code == code)
+ return(table[i].string);
+ return(table[i+1].string);
+}
+
+struct mly_code_lookup mly_table_bustype[] = {
+ {"SCSI", 0x00},
+ {"FC-AL", 0x01},
+ {"PCI", 0x03},
+ {NULL, 0},
+ {"unknown bus", 0}
+};
+
+struct mly_code_lookup mly_table_controllertype[] = {
+#if 0 /* not supported by this driver */
+ {"DAC960E", 0x01}, /* EISA */
+ {"DAC960M", 0x08}, /* MCA */
+ {"DAC960PD", 0x10}, /* PCI Dual */
+ {"DAC960PL", 0x11}, /* PCU low-cost */
+ {"DAC960PDU", 0x12}, /* PD Ultra */
+ {"DAC960PE", 0x13}, /* Peregrine low-cost */
+ {"DAC960PG", 0x14}, /* Peregrine high-performance */
+ {"DAC960PJ", 0x15}, /* Road Runner */
+ {"DAC960PTL0", 0x16}, /* Jaguar */
+ {"DAC960PR", 0x17}, /* Road Runner (again?) */
+ {"DAC960PRL", 0x18}, /* Tomcat */
+ {"DAC960PT", 0x19}, /* Road Runner (yet again?) */
+ {"DAC1164P", 0x1a}, /* Little Apple */
+ {"DAC960PTL1", 0x1b}, /* Jaguar+ */
+#endif
+ {"EXR2000P", 0x1c}, /* Big Apple */
+ {"EXR3000P", 0x1d}, /* Fibre Apple */
+ {"AcceleRAID 352", 0x1e}, /* Leopard */
+ {"AcceleRAID 170", 0x1f}, /* Lynx */
+ {"AcceleRAID 160", 0x20}, /* Bobcat */
+ {NULL, 0},
+ {"unknown adapter", 0}
+};
+
+struct mly_code_lookup mly_table_oemname[] = {
+ {"Mylex", MLY_OEM_MYLEX},
+ {"IBM", MLY_OEM_IBM},
+ {"Hewlett-Packard", MLY_OEM_HP},
+ {"DEC/Compaq", MLY_OEM_DEC},
+ {"Siemens", MLY_OEM_SIEMENS},
+ {"Intel", MLY_OEM_INTEL},
+ {NULL, 0},
+ {"unknown OEM", 0}
+};
+
+struct mly_code_lookup mly_table_memorytype[] = {
+ {"DRAM", 0x01},
+ {"EDRAM", 0x02},
+ {"EDO RAM", 0x03},
+ {"SDRAM", 0x04},
+ {NULL, 0},
+ {"unknown memory", 0}
+};
+
+struct mly_code_lookup mly_table_cputype[] = {
+ {"i960CA", 0x01},
+ {"i960RD", 0x02},
+ {"i960RN", 0x03},
+ {"i960RP", 0x04},
+ {"NorthBay(?)", 0x05},
+ {"StrongArm", 0x06},
+ {"i960RM", 0x07},
+ {NULL, 0},
+ {"unknown CPU", 0}
+};
+
+/*
+ * This table is directly derived from the corresponding table in the
+ * Linux driver, and uses a derivative encoding for simplicity's sake.
+ *
+ * The first character of the string determines the format of the message.
+ *
+ * p "physical device <channel>:<target> <text>" (physical device status)
+ * s "physical device <channel>:<target> <text>" (scsi message or error)
+ * " sense key <key> asc <asc> ascq <ascq>"
+ * " info <info> csi <csi>"
+ * l "logical drive <unit>: <text>" (logical device status)
+ * m "logical drive <unit>: <text>" (logical device message)
+ *
+ * Messages which are typically suppressed have the first character capitalised.
+ * These messages will only be printed if bootverbose is set.
+ *
+ * The second character in the string indicates an action to be taken as a
+ * result of the event.
+ *
+ * r rescan the device for possible state change
+ *
+ */
+struct mly_code_lookup mly_table_event[] = {
+ /* physical device events (0x0000 - 0x007f) */
+ {"pr online", 0x0001},
+ {"pr standby", 0x0002},
+ {"p automatic rebuild started", 0x0005},
+ {"p manual rebuild started", 0x0006},
+ {"pr rebuild completed", 0x0007},
+ {"pr rebuild cancelled", 0x0008},
+ {"pr rebuild failed for unknown reasons", 0x0009},
+ {"pr rebuild failed due to new physical device", 0x000a},
+ {"pr rebuild failed due to logical drive failure", 0x000b},
+ {"sr offline", 0x000c},
+ {"pr found", 0x000d},
+ {"pr gone", 0x000e},
+ {"p unconfigured", 0x000f},
+ {"p expand capacity started", 0x0010},
+ {"pr expand capacity completed", 0x0011},
+ {"pr expand capacity failed", 0x0012},
+ {"p parity error", 0x0016},
+ {"p soft error", 0x0017},
+ {"p miscellaneous error", 0x0018},
+ {"p reset", 0x0019},
+ {"p active spare found", 0x001a},
+ {"p warm spare found", 0x001b},
+ {"s sense data received", 0x001c},
+ {"p initialization started", 0x001d},
+ {"pr initialization completed", 0x001e},
+ {"pr initialization failed", 0x001f},
+ {"pr initialization cancelled", 0x0020},
+ {"P write recovery failed", 0x0021},
+ {"p scsi bus reset failed", 0x0022},
+ {"p double check condition", 0x0023},
+ {"p device cannot be accessed", 0x0024},
+ {"p gross error on scsi processor", 0x0025},
+ {"p bad tag from device", 0x0026},
+ {"p command timeout", 0x0027},
+ {"pr system reset", 0x0028},
+ {"p busy status or parity error", 0x0029},
+ {"pr host set device to failed state", 0x002a},
+ {"pr selection timeout", 0x002b},
+ {"p scsi bus phase error", 0x002c},
+ {"pr device returned unknown status", 0x002d},
+ {"pr device not ready", 0x002e},
+ {"p device not found at startup", 0x002f},
+ {"p COD write operation failed", 0x0030},
+ {"p BDT write operation failed", 0x0031},
+ {"p missing at startup", 0x0039},
+ {"p start rebuild failed due to physical drive too small", 0x003a},
+ /* logical device events (0x0080 - 0x00ff) */
+ {"m consistency check started", 0x0080},
+ {"mr consistency check completed", 0x0081},
+ {"mr consistency check cancelled", 0x0082},
+ {"mr consistency check completed with errors", 0x0083},
+ {"mr consistency check failed due to logical drive failure", 0x0084},
+ {"mr consistency check failed due to physical device failure", 0x0085},
+ {"lr offline", 0x0086},
+ {"lr critical", 0x0087},
+ {"lr online", 0x0088},
+ {"m automatic rebuild started", 0x0089},
+ {"m manual rebuild started", 0x008a},
+ {"mr rebuild completed", 0x008b},
+ {"mr rebuild cancelled", 0x008c},
+ {"mr rebuild failed for unknown reasons", 0x008d},
+ {"mr rebuild failed due to new physical device", 0x008e},
+ {"mr rebuild failed due to logical drive failure", 0x008f},
+ {"l initialization started", 0x0090},
+ {"lr initialization completed", 0x0091},
+ {"lr initialization cancelled", 0x0092},
+ {"lr initialization failed", 0x0093},
+ {"lr found", 0x0094},
+ {"lr gone", 0x0095},
+ {"l expand capacity started", 0x0096},
+ {"lr expand capacity completed", 0x0097},
+ {"lr expand capacity failed", 0x0098},
+ {"l bad block found", 0x0099},
+ {"lr size changed", 0x009a},
+ {"lr type changed", 0x009b},
+ {"l bad data block found", 0x009c},
+ {"l read of data block in bdt", 0x009e},
+ {"l write back data for disk block lost", 0x009f},
+ /* enclosure management events (0x0100 - 0x017f) */
+ {"e enclosure %d fan %d failed", 0x0140},
+ {"e enclosure %d fan %d ok", 0x0141},
+ {"e enclosure %d fan %d not present", 0x0142},
+ {"e enclosure %d power supply %d failed", 0x0143},
+ {"e enclosure %d power supply %d ok", 0x0144},
+ {"e enclosure %d power supply %d not present", 0x0145},
+ {"e enclosure %d temperature sensor %d failed", 0x0146},
+ {"e enclosure %d temperature sensor %d critical", 0x0147},
+ {"e enclosure %d temperature sensor %d ok", 0x0148},
+ {"e enclosure %d temperature sensor %d not present", 0x0149},
+ {"e enclosure %d unit %d access critical", 0x014a},
+ {"e enclosure %d unit %d access ok", 0x014b},
+ {"e enclosure %d unit %d access offline", 0x014c},
+ /* controller events (0x0180 - 0x01ff) */
+ {"c cache write back error", 0x0181},
+ {"c battery backup unit found", 0x0188},
+ {"c battery backup unit charge level low", 0x0189},
+ {"c battery backup unit charge level ok", 0x018a},
+ {"c installation aborted", 0x0193},
+ {"c mirror race recovery in progress", 0x0195},
+ {"c mirror race on critical drive", 0x0196},
+ {"c memory soft ecc error", 0x019e},
+ {"c memory hard ecc error", 0x019f},
+ {"c battery backup unit failed", 0x01a2},
+ {NULL, 0},
+ {"? unknown event code", 0}
+};
+
+/*
+ * Values here must be 16 characters or less, as they are packed into
+ * the 'product' field in the SCSI inquiry data.
+ */
+struct mly_code_lookup mly_table_device_state[] = {
+ {"offline", MLY_DEVICE_STATE_OFFLINE},
+ {"unconfigured", MLY_DEVICE_STATE_UNCONFIGURED},
+ {"online", MLY_DEVICE_STATE_ONLINE},
+ {"critical", MLY_DEVICE_STATE_CRITICAL},
+ {"writeonly", MLY_DEVICE_STATE_WRITEONLY},
+ {"standby", MLY_DEVICE_STATE_STANDBY},
+ {"missing", MLY_DEVICE_STATE_MISSING},
+ {NULL, 0},
+ {"unknown state", 0}
+};
+
+/*
+ * Values here must be 8 characters or less, as they are packed into
+ * the 'vendor' field in the SCSI inquiry data.
+ */
+struct mly_code_lookup mly_table_device_type[] = {
+ {"RAID 0", MLY_DEVICE_TYPE_RAID0},
+ {"RAID 1", MLY_DEVICE_TYPE_RAID1},
+ {"RAID 3", MLY_DEVICE_TYPE_RAID3}, /* right asymmetric parity */
+ {"RAID 5", MLY_DEVICE_TYPE_RAID5}, /* right asymmetric parity */
+ {"RAID 6", MLY_DEVICE_TYPE_RAID6}, /* Mylex RAID 6 */
+ {"RAID 7", MLY_DEVICE_TYPE_RAID7}, /* JBOD */
+ {"SPAN", MLY_DEVICE_TYPE_NEWSPAN}, /* New Mylex SPAN */
+ {"RAID 3", MLY_DEVICE_TYPE_RAID3F}, /* fixed parity */
+ {"RAID 3", MLY_DEVICE_TYPE_RAID3L}, /* left symmetric parity */
+ {"SPAN", MLY_DEVICE_TYPE_SPAN}, /* current spanning implementation */
+ {"RAID 5", MLY_DEVICE_TYPE_RAID5L}, /* left symmetric parity */
+ {"RAID E", MLY_DEVICE_TYPE_RAIDE}, /* concatenation */
+ {"PHYSICAL", MLY_DEVICE_TYPE_PHYSICAL}, /* physical device */
+ {NULL, 0},
+ {"UNKNOWN", 0}
+};
+
+struct mly_code_lookup mly_table_stripe_size[] = {
+ {"NONE", MLY_STRIPE_ZERO},
+ {"512B", MLY_STRIPE_512b},
+ {"1k", MLY_STRIPE_1k},
+ {"2k", MLY_STRIPE_2k},
+ {"4k", MLY_STRIPE_4k},
+ {"8k", MLY_STRIPE_8k},
+ {"16k", MLY_STRIPE_16k},
+ {"32k", MLY_STRIPE_32k},
+ {"64k", MLY_STRIPE_64k},
+ {"128k", MLY_STRIPE_128k},
+ {"256k", MLY_STRIPE_256k},
+ {"512k", MLY_STRIPE_512k},
+ {"1M", MLY_STRIPE_1m},
+ {NULL, 0},
+ {"unknown", 0}
+};
+
+struct mly_code_lookup mly_table_cacheline_size[] = {
+ {"NONE", MLY_CACHELINE_ZERO},
+ {"512B", MLY_CACHELINE_512b},
+ {"1k", MLY_CACHELINE_1k},
+ {"2k", MLY_CACHELINE_2k},
+ {"4k", MLY_CACHELINE_4k},
+ {"8k", MLY_CACHELINE_8k},
+ {"16k", MLY_CACHELINE_16k},
+ {"32k", MLY_CACHELINE_32k},
+ {"64k", MLY_CACHELINE_64k},
+ {NULL, 0},
+ {"unknown", 0}
+};
+
+#endif /* MLY_DEFINE_TABLES */
diff --git a/sys/dev/mly/mlyreg.h b/sys/dev/mly/mlyreg.h
new file mode 100644
index 000000000000..2809eb58714c
--- /dev/null
+++ b/sys/dev/mly/mlyreg.h
@@ -0,0 +1,1270 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Section numbers in this document refer to the Mylex "Firmware Software Interface"
+ * document ('FSI'), revision 0.11 04/11/00 unless otherwise qualified.
+ *
+ * Reference is made to the Mylex "Programming Guide for 6.x Controllers" document
+ * ('PG6'), document #771242 revision 0.02, 04/11/00
+ *
+ * Note that fields marked N/A are not supported by the PCI controllers, but are
+ * defined here to hold place in datastructures that are shared with the SCSI
+ * controllers. Items not relevant to PCI controllers are not described here.
+ *
+ * Ordering of items in this file is a little odd due to the constraints of
+ * nested declarations.
+ */
+
+/*
+ * 2.1 (Scatter Gather List Format)
+ */
+struct mly_sg_entry {
+ u_int64_t physaddr;
+ u_int64_t length;
+} __attribute__ ((packed));
+
+/*
+ * 5.2 System Device Access
+ *
+ * This is corroborated by the layout of the MDACIOCTL_GETCONTROLLERINFO data
+ * in 21.8
+ */
+#define MLY_MAX_CHANNELS 6
+#define MLY_MAX_TARGETS 16
+#define MLY_MAX_LUNS 1
+
+/*
+ * 8.1 Different Device States
+ */
+#define MLY_DEVICE_STATE_OFFLINE 0x08 /* DEAD/OFFLINE */
+#define MLY_DEVICE_STATE_UNCONFIGURED 0x00
+#define MLY_DEVICE_STATE_ONLINE 0x01
+#define MLY_DEVICE_STATE_CRITICAL 0x09
+#define MLY_DEVICE_STATE_WRITEONLY 0x03
+#define MLY_DEVICE_STATE_STANDBY 0x21
+#define MLY_DEVICE_STATE_MISSING 0x04 /* or-ed with (ONLINE or WRITEONLY or STANDBY) */
+
+/*
+ * 8.2 Device Type Field definitions
+ */
+#define MLY_DEVICE_TYPE_RAID0 0x0 /* RAID 0 */
+#define MLY_DEVICE_TYPE_RAID1 0x1 /* RAID 1 */
+#define MLY_DEVICE_TYPE_RAID3 0x3 /* RAID 3 right asymmetric parity */
+#define MLY_DEVICE_TYPE_RAID5 0x5 /* RAID 5 right asymmetric parity */
+#define MLY_DEVICE_TYPE_RAID6 0x6 /* RAID 6 (Mylex RAID 6) */
+#define MLY_DEVICE_TYPE_RAID7 0x7 /* RAID 7 (JBOD) */
+#define MLY_DEVICE_TYPE_NEWSPAN 0x8 /* New Mylex SPAN */
+#define MLY_DEVICE_TYPE_RAID3F 0x9 /* RAID 3 fixed parity */
+#define MLY_DEVICE_TYPE_RAID3L 0xb /* RAID 3 left symmetric parity */
+#define MLY_DEVICE_TYPE_SPAN 0xc /* current spanning implementation */
+#define MLY_DEVICE_TYPE_RAID5L 0xd /* RAID 5 left symmetric parity */
+#define MLY_DEVICE_TYPE_RAIDE 0xe /* RAID E (concatenation) */
+#define MLY_DEVICE_TYPE_PHYSICAL 0xf /* physical device */
+
+/*
+ * 8.3 Stripe Size
+ */
+#define MLY_STRIPE_ZERO 0x0 /* no stripe (RAID 1, RAID 7, etc) */
+#define MLY_STRIPE_512b 0x1
+#define MLY_STRIPE_1k 0x2
+#define MLY_STRIPE_2k 0x3
+#define MLY_STRIPE_4k 0x4
+#define MLY_STRIPE_8k 0x5
+#define MLY_STRIPE_16k 0x6
+#define MLY_STRIPE_32k 0x7
+#define MLY_STRIPE_64k 0x8
+#define MLY_STRIPE_128k 0x9
+#define MLY_STRIPE_256k 0xa
+#define MLY_STRIPE_512k 0xb
+#define MLY_STRIPE_1m 0xc
+
+/*
+ * 8.4 Cacheline Size
+ */
+#define MLY_CACHELINE_ZERO 0x0 /* caching cannot be enabled */
+#define MLY_CACHELINE_512b 0x1
+#define MLY_CACHELINE_1k 0x2
+#define MLY_CACHELINE_2k 0x3
+#define MLY_CACHELINE_4k 0x4
+#define MLY_CACHELINE_8k 0x5
+#define MLY_CACHELINE_16k 0x6
+#define MLY_CACHELINE_32k 0x7
+#define MLY_CACHELINE_64k 0x8
+
+/*
+ * 8.5 Read/Write control
+ */
+#define MLY_RWCtl_INITTED (1<<7) /* if set, the logical device is initialised */
+ /* write control */
+#define MLY_RWCtl_WCD (0) /* write cache disabled */
+#define MLY_RWCtl_WDISABLE (1<<3) /* writing disabled */
+#define MLY_RWCtl_WCE (2<<3) /* write cache enabled */
+#define MLY_RWCtl_IWCE (3<<3) /* intelligent write cache enabled */
+ /* read control */
+#define MLY_RWCtl_RCD (0) /* read cache is disabled */
+#define MLY_RWCtl_RCE (1) /* read cache enabled */
+#define MLY_RWCtl_RAHEAD (2) /* readahead enabled */
+#define MLY_RWCtl_IRAHEAD (3) /* intelligent readahead enabled */
+
+/*
+ * 9.0 LUN Map Format
+ */
+struct mly_lun_map {
+ u_int8_t res1:4;
+ u_int8_t host_port_mapped:1; /* this system drive visibile to host on this controller/port combination */
+ u_int8_t tid_valid:1; /* target ID valid */
+ u_int8_t hid_valid:1; /* host ID valid */
+ u_int8_t lun_valid:1; /* LUN valid */
+ u_int8_t res2;
+ u_int8_t lun; /* LUN */
+ u_int8_t tid; /* TID */
+ u_int8_t hid[32]; /* HID (one bit for each host) */
+} __attribute__ ((packed));
+
+/*
+ * 10.1 Controller Parameters
+ */
+struct mly_param_controller {
+ u_int8_t rdahen:1; /* N/A */
+ u_int8_t bilodly:1; /* N/A */
+ u_int8_t fua_disable:1;
+ u_int8_t reass1s:1; /* N/A */
+ u_int8_t truvrfy:1; /* N/A */
+ u_int8_t dwtvrfy:1; /* N/A */
+ u_int8_t background_initialisation:1;
+ u_int8_t clustering:1; /* N/A */
+
+ u_int8_t bios_disable:1;
+ u_int8_t boot_from_cdrom:1;
+ u_int8_t drive_coercion:1;
+ u_int8_t write_same_disable:1;
+ u_int8_t hba_mode:1; /* N/A */
+ u_int8_t bios_geometry:2;
+#define MLY_BIOSGEOM_2G 0x0
+#define MLY_BIOSGEOM_8G 0x1
+ u_int8_t res1:1; /* N/A */
+
+ u_int8_t res2[2]; /* N/A */
+
+ u_int8_t v_dec:1;
+ u_int8_t safte:1; /* N/A */
+ u_int8_t ses:1; /* N/A */
+ u_int8_t res3:2; /* N/A */
+ u_int8_t v_arm:1;
+ u_int8_t v_ofm:1;
+ u_int8_t res4:1; /* N/A */
+
+ u_int8_t rebuild_check_rate;
+ u_int8_t cache_line_size; /* see 8.4 */
+ u_int8_t oem_code;
+#define MLY_OEM_MYLEX 0x00
+#define MLY_OEM_IBM 0x08
+#define MLY_OEM_HP 0x0a
+#define MLY_OEM_DEC 0x0c
+#define MLY_OEM_SIEMENS 0x10
+#define MLY_OEM_INTEL 0x12
+ u_int8_t spinup_mode;
+#define MLY_SPIN_AUTO 0
+#define MLY_SPIN_PWRSPIN 1
+#define MLY_SPIN_WSSUSPIN 2
+ u_int8_t spinup_devices;
+ u_int8_t spinup_interval;
+ u_int8_t spinup_wait_time;
+
+ u_int8_t res5:3; /* N/A */
+ u_int8_t vutursns:1; /* N/A */
+ u_int8_t dccfil:1; /* N/A */
+ u_int8_t nopause:1; /* N/A */
+ u_int8_t disqfull:1; /* N/A */
+ u_int8_t disbusy:1; /* N/A */
+
+ u_int8_t res6:2; /* N/A */
+ u_int8_t failover_node_name; /* N/A */
+ u_int8_t res7:1; /* N/A */
+ u_int8_t ftopo:3; /* N/A */
+ u_int8_t disable_ups:1; /* N/A */
+
+ u_int8_t res8:1; /* N/A */
+ u_int8_t propagate_reset:1; /* N/A */
+ u_int8_t nonstd_mp_reset:1; /* N/A */
+ u_int8_t res9:5; /* N/A */
+
+ u_int8_t res10; /* N/A */
+ u_int8_t serial_port_baud_rate; /* N/A */
+ u_int8_t serial_port_control; /* N/A */
+ u_int8_t change_stripe_ok_developer_flag_only; /* N/A */
+
+ u_int8_t small_large_host_transfers:2; /* N/A */
+ u_int8_t frame_control:2; /* N/A */
+ u_int8_t pci_latency_control:2; /* N/A */
+ u_int8_t treat_lip_as_reset:1; /* N/A */
+ u_int8_t res11:1; /* N/A */
+
+ u_int8_t ms_autorest:1; /* N/A */
+ u_int8_t res12:7; /* N/A */
+
+ u_int8_t ms_aa_fsim:1; /* N/A */
+ u_int8_t ms_aa_ccach:1; /* N/A */
+ u_int8_t ms_aa_fault_signals:1; /* N/A */
+ u_int8_t ms_aa_c4_faults:1; /* N/A */
+ u_int8_t ms_aa_host_reset_delay_mask:4; /* N/A */
+
+ u_int8_t ms_flg_simplex_no_rstcom:1; /* N/A */
+ u_int8_t res13:7; /* N/A */
+
+ u_int8_t res14; /* N/A */
+ u_int8_t hardloopid[2][2]; /* N/A */
+ u_int8_t ctrlname[2][16+1]; /* N/A */
+ u_int8_t initiator_id;
+ u_int8_t startup_option;
+#define MLY_STARTUP_IF_NO_CHANGE 0x0
+#define MLY_STARTUP_IF_NO_LUN_CHANGE 0x1
+#define MLY_STARTUP_IF_NO_LUN_OFFLINE 0x2
+#define MLY_STARTUP_IF_LUN0_NO_CHANGE 0x3
+#define MLY_STARTUP_IF_LUN0_NOT_OFFLINE 0x4
+#define MLY_STARTUP_ALWAYS 0x5
+
+ u_int8_t res15[62];
+} __attribute__ ((packed));
+
+/*
+ * 10.2 Physical Device Parameters
+ */
+struct mly_param_physical_device {
+ u_int16_t tags;
+ u_int16_t speed;
+ u_int8_t width;
+ u_int8_t combing:1;
+ u_int8_t res1:7;
+ u_int8_t res2[3];
+} __attribute__ ((packed));
+
+/*
+ * 10.3 Logical Device Parameters
+ */
+struct mly_param_logical_device {
+ u_int8_t type; /* see 8.2 */
+ u_int8_t state; /* see 8.1 */
+ u_int16_t raid_device;
+ u_int8_t res1;
+ u_int8_t bios_geometry; /* BIOS control word? */
+ u_int8_t stripe_size; /* see 8.3 */
+ u_int8_t read_write_control; /* see 8.5 */
+ u_int8_t res2[8];
+} __attribute__ ((packed));
+
+/*
+ * 12.3 Health Status Buffer
+ *
+ * Pad to 128 bytes.
+ */
+struct mly_health_status {
+ u_int32_t uptime_us; /* N/A */
+ u_int32_t uptime_ms; /* N/A */
+ u_int32_t realtime; /* N/A */
+ u_int32_t res1; /* N/A */
+ u_int32_t change_counter;
+ u_int32_t res2; /* N/A */
+ u_int32_t debug_message_index; /* N/A */
+ u_int32_t bios_message_index; /* N/A */
+ u_int32_t trace_page; /* N/A */
+ u_int32_t profiler_page; /* N/A */
+ u_int32_t next_event;
+ u_int8_t res3[4 + 16 + 64]; /* N/A */
+} __attribute__ ((packed));
+
+/*
+ * 14.2 Timeout Bit Format
+ */
+struct mly_timeout {
+ u_int8_t value:6;
+ u_int8_t scale:2;
+#define MLY_TIMEOUT_SECONDS 0x0
+#define MLY_TIMEOUT_MINUTES 0x1
+#define MLY_TIMEOUT_HOURS 0x2
+} __attribute__ ((packed));
+
+/*
+ * 14.3 Operation Device
+ */
+#define MLY_OPDEVICE_PHYSICAL_DEVICE 0x0
+#define MLY_OPDEVICE_RAID_DEVICE 0x1
+#define MLY_OPDEVICE_PHYSICAL_CHANNEL 0x2
+#define MLY_OPDEVICE_RAID_CHANNEL 0x3
+#define MLY_OPDEVICE_PHYSICAL_CONTROLLER 0x4
+#define MLY_OPDEVICE_RAID_CONTROLLER 0x5
+#define MLY_OPDEVICE_CONFIGURATION_GROUP 0x10
+
+/*
+ * 14.4 Status Bit Format
+ *
+ * AKA Status Mailbox Format
+ *
+ * XXX format conflict between FSI and PG6 over the ordering of the
+ * status and sense length fields.
+ */
+struct mly_status {
+ u_int16_t command_id;
+ u_int8_t status;
+ u_int8_t sense_length;
+ int32_t residue;
+} __attribute__ ((packed));
+
+/*
+ * 14.5 Command Control Bit (CCB) format
+ *
+ * This byte is unfortunately named.
+ */
+struct mly_command_control {
+ u_int8_t force_unit_access:1;
+ u_int8_t disable_page_out:1;
+ u_int8_t res1:1;
+ u_int8_t extended_sg_table:1;
+ u_int8_t data_direction:1;
+#define MLY_CCB_WRITE 1
+#define MLY_CCB_READ 0
+ u_int8_t res2:1;
+ u_int8_t no_auto_sense:1;
+ u_int8_t disable_disconnect:1;
+} __attribute__ ((packed));
+
+/*
+ * 15.0 Commands
+ *
+ * We use the command names as given by Mylex
+ */
+#define MDACMD_MEMCOPY 0x1 /* memory to memory copy */
+#define MDACMD_SCSIPT 0x2 /* SCSI passthrough (small command) */
+#define MDACMD_SCSILCPT 0x3 /* SCSI passthrough (large command) */
+#define MDACMD_SCSI 0x4 /* SCSI command for logical/phyiscal device (small command) */
+#define MDACMD_SCSILC 0x5 /* SCSI command for logical/phyiscal device (large command) */
+#define MDACMD_IOCTL 0x20 /* Management command */
+#define MDACMD_IOCTLCHECK 0x23 /* Validate management command (not implemented) */
+
+/*
+ * 16.0 IOCTL command
+ *
+ * We use the IOCTL names as given by Mylex
+ * Note that only ioctls supported by the PCI controller family are listed
+ */
+#define MDACIOCTL_GETCONTROLLERINFO 0x1
+#define MDACIOCTL_GETLOGDEVINFOVALID 0x3
+#define MDACIOCTL_GETPHYSDEVINFOVALID 0x5
+#define MDACIOCTL_GETCONTROLLERSTATISTICS 0xb
+#define MDACIOCTL_GETLOGDEVSTATISTICS 0xd
+#define MDACIOCTL_GETPHYSDEVSTATISTICS 0xf
+#define MDACIOCTL_GETHEALTHSTATUS 0x11
+#define MDACIOCTL_GETEVENT 0x15
+/* flash update */
+#define MDACIOCTL_STOREIMAGE 0x2c
+#define MDACIOCTL_READIMAGE 0x2d
+#define MDACIOCTL_FLASHIMAGES 0x2e
+/* battery backup unit */
+#define MDACIOCTL_GET_SUBSYSTEM_DATA 0x70
+#define MDACIOCTL_SET_SUBSYSTEM_DATA 0x71
+/* non-data commands */
+#define MDACIOCTL_STARTDISOCVERY 0x81
+#define MDACIOCTL_SETRAIDDEVSTATE 0x82
+#define MDACIOCTL_INITPHYSDEVSTART 0x84
+#define MDACIOCTL_INITPHYSDEVSTOP 0x85
+#define MDACIOCTL_INITRAIDDEVSTART 0x86
+#define MDACIOCTL_INITRAIDDEVSTOP 0x87
+#define MDACIOCTL_REBUILDRAIDDEVSTART 0x88
+#define MDACIOCTL_REBUILDRAIDDEVSTOP 0x89
+#define MDACIOCTL_MAKECONSISTENTDATASTART 0x8a
+#define MDACIOCTL_MAKECONSISTENTDATASTOP 0x8b
+#define MDACIOCTL_CONSISTENCYCHECKSTART 0x8c
+#define MDACIOCTL_CONSISTENCYCHECKSTOP 0x8d
+#define MDACIOCTL_SETMEMORYMAILBOX 0x8e
+#define MDACIOCTL_RESETDEVICE 0x90
+#define MDACIOCTL_FLUSHDEVICEDATA 0x91
+#define MDACIOCTL_PAUSEDEVICE 0x92
+#define MDACIOCTL_UNPAUSEDEVICE 0x93
+#define MDACIOCTL_LOCATEDEVICE 0x94
+#define MDACIOCTL_SETMASTERSLAVEMODE 0x95
+#define MDACIOCTL_SETREALTIMECLOCK 0xac
+/* RAID configuration */
+#define MDACIOCTL_CREATENEWCONF 0xc0
+#define MDACIOCTL_DELETERAIDDEV 0xc1
+#define MDACIOCTL_REPLACEINTERNALDEV 0xc2
+#define MDACIOCTL_RENAMERAIDDEV 0xc3
+#define MDACIOCTL_ADDNEWCONF 0xc4
+#define MDACIOCTL_XLATEPHYSDEVTORAIDDEV 0xc5
+#define MDACIOCTL_MORE 0xc6
+#define MDACIOCTL_SETPHYSDEVPARAMETER 0xc8
+#define MDACIOCTL_GETPHYSDEVPARAMETER 0xc9
+#define MDACIOCTL_CLEARCONF 0xca
+#define MDACIOCTL_GETDEVCONFINFO 0xcb
+#define MDACIOCTL_GETGROUPCONFINFO 0xcc
+#define MDACIOCTL_GETFREESPACELIST 0xcd
+#define MDACIOCTL_GETLOGDEVPARAMETER 0xce
+#define MDACIOCTL_SETLOGDEVPARAMETER 0xcf
+#define MDACIOCTL_GETCONTROLLERPARAMETER 0xd0
+#define MDACIOCTL_SETCONTRLLERPARAMETER 0xd1
+#define MDACIOCTL_CLEARCONFSUSPMODE 0xd2
+#define MDACIOCTL_GETBDT_FOR_SYSDRIVE 0xe0
+
+/*
+ * 17.1.4 Data Transfer Memory Address Without SG List
+ */
+struct mly_short_transfer {
+ struct mly_sg_entry sg[2];
+} __attribute__ ((packed));
+
+/*
+ * 17.1.5 Data Transfer Memory Address With SG List
+ *
+ * Note that only the first s/g table is currently used.
+ */
+struct mly_sg_transfer {
+ u_int16_t entries[3];
+ u_int16_t res1;
+ u_int64_t table_physaddr[3];
+} __attribute__ ((packed));
+
+/*
+ * 17.1.3 Data Transfer Memory Address Format
+ */
+union mly_command_transfer {
+ struct mly_short_transfer direct;
+ struct mly_sg_transfer indirect;
+};
+
+/*
+ * 21.1 MDACIOCTL_SETREALTIMECLOCK
+ * 21.7 MDACIOCTL_GETHEALTHSTATUS
+ * 21.8 MDACIOCTL_GETCONTROLLERINFO
+ * 21.9 MDACIOCTL_GETLOGDEVINFOVALID
+ * 21.10 MDACIOCTL_GETPHYSDEVINFOVALID
+ * 21.11 MDACIOCTL_GETPHYSDEVSTATISTICS
+ * 21.12 MDACIOCTL_GETLOGDEVSTATISTICS
+ * 21.13 MDACIOCTL_GETCONTROLLERSTATISTICS
+ * 21.27 MDACIOCTL_GETBDT_FOR_SYSDRIVE
+ * 23.4 MDACIOCTL_CREATENEWCONF
+ * 23.5 MDACIOCTL_ADDNEWCONF
+ * 23.8 MDACIOCTL_GETDEVCONFINFO
+ * 23.9 MDACIOCTL_GETFREESPACELIST
+ * 24.1 MDACIOCTL_MORE
+ * 25.1 MDACIOCTL_GETPHYSDEVPARAMETER
+ * 25.2 MDACIOCTL_SETPHYSDEVPARAMETER
+ * 25.3 MDACIOCTL_GETLOGDEVPARAMETER
+ * 25.4 MDACIOCTL_SETLOGDEVPARAMETER
+ * 25.5 MDACIOCTL_GETCONTROLLERPARAMETER
+ * 25.6 MDACIOCTL_SETCONTROLLERPARAMETER
+ *
+ * These commands just transfer data
+ */
+struct mly_ioctl_param_data {
+ u_int8_t param[10];
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+/*
+ * 21.2 MDACIOCTL_SETMEMORYMAILBOX
+ */
+struct mly_ioctl_param_setmemorymailbox {
+ u_int8_t health_buffer_size;
+ u_int8_t res1;
+ u_int64_t health_buffer_physaddr;
+ u_int64_t command_mailbox_physaddr;
+ u_int64_t status_mailbox_physaddr;
+ u_int64_t res2[2];
+} __attribute__ ((packed));
+
+/*
+ * 21.8.2 MDACIOCTL_GETCONTROLLERINFO: Data Format
+ */
+struct mly_ioctl_getcontrollerinfo {
+ u_int8_t res1; /* N/A */
+ u_int8_t interface_type;
+ u_int8_t controller_type;
+ u_int8_t res2; /* N/A */
+ u_int16_t interface_speed;
+ u_int8_t interface_width;
+ u_int8_t res3[9]; /* N/A */
+ char interface_name[16];
+ char controller_name[16];
+ u_int8_t res4[16]; /* N/A */
+ /* firmware release information */
+ u_int8_t fw_major;
+ u_int8_t fw_minor;
+ u_int8_t fw_turn;
+ u_int8_t fw_build;
+ u_int8_t fw_day;
+ u_int8_t fw_month;
+ u_int8_t fw_century;
+ u_int8_t fw_year;
+ /* hardware release information */
+ u_int8_t hw_revision; /* N/A */
+ u_int8_t res5[3]; /* N/A */
+ u_int8_t hw_release_day; /* N/A */
+ u_int8_t hw_release_month; /* N/A */
+ u_int8_t hw_release_century; /* N/A */
+ u_int8_t hw_release_year; /* N/A */
+ /* hardware manufacturing information */
+ u_int8_t batch_number; /* N/A */
+ u_int8_t res6; /* N/A */
+ u_int8_t plant_number;
+ u_int8_t res7;
+ u_int8_t hw_manuf_day;
+ u_int8_t hw_manuf_month;
+ u_int8_t hw_manuf_century;
+ u_int8_t hw_manuf_year;
+ u_int8_t max_pdd_per_xldd;
+ u_int8_t max_ildd_per_xldd;
+ u_int16_t nvram_size;
+ u_int8_t max_number_of_xld; /* N/A */
+ u_int8_t res8[3]; /* N/A */
+ /* unique information per controller */
+ char serial_number[16];
+ u_int8_t res9[16]; /* N/A */
+ /* vendor information */
+ u_int8_t res10[3]; /* N/A */
+ u_int8_t oem_information;
+ char vendor_name[16]; /* N/A */
+ /* other physical/controller/operation information */
+ u_int8_t bbu_present:1;
+ u_int8_t active_clustering:1;
+ u_int8_t res11:6; /* N/A */
+ u_int8_t res12[3]; /* N/A */
+ /* physical device scan information */
+ u_int8_t physical_scan_active:1;
+ u_int8_t res13:7; /* N/A */
+ u_int8_t physical_scan_channel;
+ u_int8_t physical_scan_target;
+ u_int8_t physical_scan_lun;
+ /* maximum command data transfer size */
+ u_int16_t maximum_block_count;
+ u_int16_t maximum_sg_entries;
+ /* logical/physical device counts */
+ u_int16_t logical_devices_present;
+ u_int16_t logical_devices_critical;
+ u_int16_t logical_devices_offline;
+ u_int16_t physical_devices_present;
+ u_int16_t physical_disks_present;
+ u_int16_t physical_disks_critical; /* N/A */
+ u_int16_t physical_disks_offline;
+ u_int16_t maximum_parallel_commands;
+ /* channel and target ID information */
+ u_int8_t physical_channels_present;
+ u_int8_t virtual_channels_present;
+ u_int8_t physical_channels_possible;
+ u_int8_t virtual_channels_possible;
+ u_int8_t maximum_targets_possible[16]; /* N/A (6 and up) */
+ u_int8_t res14[12]; /* N/A */
+ /* memory/cache information */
+ u_int16_t memory_size;
+ u_int16_t cache_size;
+ u_int32_t valid_cache_size; /* N/A */
+ u_int32_t dirty_cache_size; /* N/A */
+ u_int16_t memory_speed;
+ u_int8_t memory_width;
+ u_int8_t memory_type:5;
+ u_int8_t res15:1; /* N/A */
+ u_int8_t memory_parity:1;
+ u_int8_t memory_ecc:1;
+ char memory_information[16]; /* N/A */
+ /* execution memory information */
+ u_int16_t exmemory_size;
+ u_int16_t l2cache_size; /* N/A */
+ u_int8_t res16[8]; /* N/A */
+ u_int16_t exmemory_speed;
+ u_int8_t exmemory_width;
+ u_int8_t exmemory_type:5;
+ u_int8_t res17:1; /* N/A */
+ u_int8_t exmemory_parity:1;
+ u_int8_t exmemory_ecc:1;
+ char exmemory_name[16]; /* N/A */
+ /* CPU information */
+ struct {
+ u_int16_t speed;
+ u_int8_t type;
+ u_int8_t number;
+ u_int8_t res1[12]; /* N/A */
+ char name[16]; /* N/A */
+ } cpu[2] __attribute__ ((packed));
+ /* debugging/profiling/command time tracing information */
+ u_int16_t profiling_page; /* N/A */
+ u_int16_t profiling_programs; /* N/A */
+ u_int16_t time_trace_page; /* N/A */
+ u_int16_t time_trace_programs; /* N/A */
+ u_int8_t res18[8]; /* N/A */
+ /* error counters on physical devices */
+ u_int16_t physical_device_bus_resets; /* N/A */
+ u_int16_t physical_device_parity_errors; /* N/A */
+ u_int16_t physical_device_soft_errors; /* N/A */
+ u_int16_t physical_device_commands_failed; /* N/A */
+ u_int16_t physical_device_miscellaneous_errors; /* N/A */
+ u_int16_t physical_device_command_timeouts; /* N/A */
+ u_int16_t physical_device_selection_timeouts; /* N/A */
+ u_int16_t physical_device_retries; /* N/A */
+ u_int16_t physical_device_aborts; /* N/A */
+ u_int16_t physical_device_host_command_aborts; /* N/A */
+ u_int16_t physical_device_PFAs_detected; /* N/A */
+ u_int16_t physical_device_host_commands_failed; /* N/A */
+ u_int8_t res19[8]; /* N/A */
+ /* error counters on logical devices */
+ u_int16_t logical_device_soft_errors; /* N/A */
+ u_int16_t logical_device_commands_failed; /* N/A */
+ u_int16_t logical_device_host_command_aborts; /* N/A */
+ u_int16_t res20; /* N/A */
+ /* error counters on controller */
+ u_int16_t controller_parity_ecc_errors;
+ u_int16_t controller_host_command_aborts; /* N/A */
+ u_int8_t res21[4]; /* N/A */
+ /* long duration activity information */
+ u_int16_t background_inits_active;
+ u_int16_t logical_inits_active;
+ u_int16_t physical_inits_active;
+ u_int16_t consistency_checks_active;
+ u_int16_t rebuilds_active;
+ u_int16_t MORE_active;
+ u_int16_t patrol_active; /* N/A */
+ u_int8_t long_operation_status; /* N/A */
+ u_int8_t res22; /* N/A */
+ /* flash ROM information */
+ u_int8_t flash_type; /* N/A */
+ u_int8_t res23; /* N/A */
+ u_int16_t flash_size;
+ u_int32_t flash_maximum_age;
+ u_int32_t flash_age;
+ u_int8_t res24[4]; /* N/A */
+ char flash_name[16]; /* N/A */
+ /* firmware runtime information */
+ u_int8_t rebuild_rate;
+ u_int8_t background_init_rate;
+ u_int8_t init_rate;
+ u_int8_t consistency_check_rate;
+ u_int8_t res25[4]; /* N/A */
+ u_int32_t maximum_dp;
+ u_int32_t free_dp;
+ u_int32_t maximum_iop;
+ u_int32_t free_iop;
+ u_int16_t maximum_comb_length;
+ u_int16_t maximum_configuration_groups;
+ u_int8_t installation_abort:1;
+ u_int8_t maintenance:1;
+ u_int8_t res26:6; /* N/A */
+ u_int8_t res27[3]; /* N/A */
+ u_int8_t res28[32 + 512]; /* N/A */
+} __attribute__ ((packed));
+
+/*
+ * 21.9.2 MDACIOCTL_GETLOGDEVINFOVALID
+ */
+struct mly_ioctl_getlogdevinfovalid {
+ u_int8_t res1; /* N/A */
+ u_int8_t channel;
+ u_int8_t target;
+ u_int8_t lun;
+ u_int8_t state; /* see 8.1 */
+ u_int8_t raid_level; /* see 8.2 */
+ u_int8_t stripe_size; /* see 8.3 */
+ u_int8_t cache_line_size; /* see 8.4 */
+ u_int8_t read_write_control; /* see 8.5 */
+ u_int8_t consistency_check:1;
+ u_int8_t rebuild:1;
+ u_int8_t make_consistent:1;
+ u_int8_t initialisation:1;
+ u_int8_t migration:1;
+ u_int8_t patrol:1;
+ u_int8_t res2:2; /* N/A */
+ u_int8_t ar5_limit;
+ u_int8_t ar5_algo;
+ u_int16_t logical_device_number;
+ u_int16_t bios_control;
+ /* erorr counters */
+ u_int16_t soft_errors; /* N/A */
+ u_int16_t commands_failed; /* N/A */
+ u_int16_t host_command_aborts; /* N/A */
+ u_int16_t deferred_write_errors; /* N/A */
+ u_int8_t res3[8]; /* N/A */
+ /* device size information */
+ u_int8_t res4[2]; /* N/A */
+ u_int16_t device_block_size;
+ u_int32_t original_device_size; /* N/A */
+ u_int32_t device_size; /* XXX "blocks or MB" Huh? */
+ u_int8_t res5[4]; /* N/A */
+ char device_name[32]; /* N/A */
+ u_int8_t inquiry[36];
+ u_int8_t res6[12]; /* N/A */
+ u_int64_t last_read_block; /* N/A */
+ u_int64_t last_written_block; /* N/A */
+ u_int64_t consistency_check_block;
+ u_int64_t rebuild_block;
+ u_int64_t make_consistent_block;
+ u_int64_t initialisation_block;
+ u_int64_t migration_block;
+ u_int64_t patrol_block; /* N/A */
+ u_int8_t res7[64]; /* N/A */
+} __attribute__ ((packed));
+
+/*
+ * 21.10.2 MDACIOCTL_GETPHYSDEVINFOVALID: Data Format
+ */
+struct mly_ioctl_getphysdevinfovalid {
+ u_int8_t res1;
+ u_int8_t channel;
+ u_int8_t target;
+ u_int8_t lun;
+ u_int8_t raid_ft:1; /* configuration status */
+ u_int8_t res2:1; /* N/A */
+ u_int8_t local:1;
+ u_int8_t res3:5;
+ u_int8_t host_dead:1; /* multiple host/controller status *//* N/A */
+ u_int8_t host_connection_dead:1; /* N/A */
+ u_int8_t res4:6; /* N/A */
+ u_int8_t state; /* see 8.1 */
+ u_int8_t width;
+ u_int16_t speed;
+ /* multiported physical device information */
+ u_int8_t ports_available; /* N/A */
+ u_int8_t ports_inuse; /* N/A */
+ u_int8_t res5[4];
+ u_int8_t ether_address[16]; /* N/A */
+ u_int16_t command_tags;
+ u_int8_t consistency_check:1; /* N/A */
+ u_int8_t rebuild:1; /* N/A */
+ u_int8_t make_consistent:1; /* N/A */
+ u_int8_t initialisation:1;
+ u_int8_t migration:1; /* N/A */
+ u_int8_t patrol:1; /* N/A */
+ u_int8_t res6:2;
+ u_int8_t long_operation_status; /* N/A */
+ u_int8_t parity_errors;
+ u_int8_t soft_errors;
+ u_int8_t hard_errors;
+ u_int8_t miscellaneous_errors;
+ u_int8_t command_timeouts; /* N/A */
+ u_int8_t retries; /* N/A */
+ u_int8_t aborts; /* N/A */
+ u_int8_t PFAs_detected; /* N/A */
+ u_int8_t res7[6];
+ u_int16_t block_size;
+ u_int32_t original_device_size; /* XXX "blocks or MB" Huh? */
+ u_int32_t device_size; /* XXX "blocks or MB" Huh? */
+ u_int8_t res8[4];
+ char name[16]; /* N/A */
+ u_int8_t res9[16 + 32];
+ u_int8_t inquiry[36];
+ u_int8_t res10[12 + 16];
+ u_int64_t last_read_block; /* N/A */
+ u_int64_t last_written_block; /* N/A */
+ u_int64_t consistency_check_block; /* N/A */
+ u_int64_t rebuild_block; /* N/A */
+ u_int64_t make_consistent_block; /* N/A */
+ u_int64_t initialisation_block; /* N/A */
+ u_int64_t migration_block; /* N/A */
+ u_int64_t patrol_block; /* N/A */
+ u_int8_t res11[256];
+} __attribute__ ((packed));
+
+union mly_devinfo {
+ struct mly_ioctl_getlogdevinfovalid logdev;
+ struct mly_ioctl_getphysdevinfovalid physdev;
+};
+
+/*
+ * 21.11.2 MDACIOCTL_GETPHYSDEVSTATISTICS: Data Format
+ * 21.12.2 MDACIOCTL_GETLOGDEVSTATISTICS: Data Format
+ */
+struct mly_ioctl_getdevstatistics {
+ u_int32_t uptime_ms; /* getphysedevstatistics only */
+ u_int8_t res1[5]; /* N/A */
+ u_int8_t channel;
+ u_int8_t target;
+ u_int8_t lun;
+ u_int16_t raid_device; /* getlogdevstatistics only */
+ u_int8_t res2[2]; /* N/A */
+ /* total read/write performance including cache data */
+ u_int32_t total_reads;
+ u_int32_t total_writes;
+ u_int32_t total_read_size;
+ u_int32_t total_write_size;
+ /* cache read/write performance */
+ u_int32_t cache_reads; /* N/A */
+ u_int32_t cache_writes; /* N/A */
+ u_int32_t cache_read_size; /* N/A */
+ u_int32_t cache_write_size; /* N/A */
+ /* commands active/wait information */
+ u_int32_t command_waits_done; /* N/A */
+ u_int16_t active_commands; /* N/A */
+ u_int16_t waiting_commands; /* N/A */
+ u_int8_t res3[8]; /* N/A */
+} __attribute__ ((packed));
+
+/*
+ * 21.13.2 MDACIOCTL_GETCONTROLLERSTATISTICS: Data Format
+ */
+struct mly_ioctl_getcontrollerstatistics {
+ u_int32_t uptime_ms; /* N/A */
+ u_int8_t res1[12]; /* N/A */
+ /* target physical device performance data information */
+ u_int32_t target_physical_device_interrupts; /* N/A */
+ u_int32_t target_physical_device_stray_interrupts; /* N/A */
+ u_int8_t res2[8]; /* N/A */
+ u_int32_t target_physical_device_reads; /* N/A */
+ u_int32_t target_physical_device_writes; /* N/A */
+ u_int32_t target_physical_device_read_size; /* N/A */
+ u_int32_t target_physical_device_write_size; /* N/A */
+ /* host system performance data information */
+ u_int32_t host_system_interrupts; /* N/A */
+ u_int32_t host_system_stray_interrupts; /* N/A */
+ u_int32_t host_system_sent_interrupts; /* N/A */
+ u_int8_t res3[4]; /* N/A */
+ u_int32_t physical_device_reads; /* N/A */
+ u_int32_t physical_device_writes; /* N/A */
+ u_int32_t physical_device_read_size; /* N/A */
+ u_int32_t physical_device_write_size; /* N/A */
+ u_int32_t physical_device_cache_reads; /* N/A */
+ u_int32_t physical_device_cache_writes; /* N/A */
+ u_int32_t physical_device_cache_read_size; /* N/A */
+ u_int32_t physical_device_cache_write_size; /* N/A */
+ u_int32_t logical_device_reads; /* N/A */
+ u_int32_t logical_device_writes; /* N/A */
+ u_int32_t logical_device_read_size; /* N/A */
+ u_int32_t logical_device_write_size; /* N/A */
+ u_int32_t logical_device_cache_reads; /* N/A */
+ u_int32_t logical_device_cache_writes; /* N/A */
+ u_int32_t logical_device_cache_read_size; /* N/A */
+ u_int32_t logical_device_cache_write_size; /* N/A */
+ u_int16_t target_physical_device_commands_active; /* N/A */
+ u_int16_t target_physical_device_commands_waiting; /* N/A */
+ u_int16_t host_system_commands_active; /* N/A */
+ u_int16_t host_system_commands_waiting; /* N/A */
+ u_int8_t res4[48 + 64]; /* N/A */
+} __attribute__ ((packed));
+
+/*
+ * 21.2 MDACIOCTL_SETRAIDDEVSTATE
+ */
+struct mly_ioctl_param_setraiddevstate {
+ u_int8_t state;
+} __attribute__ ((packed));
+
+/*
+ * 21.27.2 MDACIOCTL_GETBDT_FOR_SYSDRIVE: Data Format
+ */
+#define MLY_MAX_BDT_ENTRIES 1022
+struct mly_ioctl_getbdt_for_sysdrive {
+ u_int32_t num_of_bdt_entries;
+ u_int32_t bad_data_block_address[MLY_MAX_BDT_ENTRIES];
+} __attribute__ ((packed));
+
+/*
+ * 22.1 Physical Device Definition (PDD)
+ */
+struct mly_pdd {
+ u_int8_t type; /* see 8.2 */
+ u_int8_t state; /* see 8.1 */
+ u_int16_t raid_device;
+ u_int32_t device_size; /* XXX "block or MB" Huh? */
+ u_int8_t controller;
+ u_int8_t channel;
+ u_int8_t target;
+ u_int8_t lun;
+ u_int32_t start_address;
+} __attribute__ ((packed));
+
+/*
+ * 22.2 RAID Device Use Definition (UDD)
+ */
+struct mly_udd {
+ u_int8_t res1;
+ u_int8_t state; /* see 8.1 */
+ u_int16_t raid_device;
+ u_int32_t start_address;
+} __attribute__ ((packed));
+
+/*
+ * RAID Device Definition (LDD)
+ */
+struct mly_ldd {
+ u_int8_t type; /* see 8.2 */
+ u_int8_t state; /* see 8.1 */
+ u_int16_t raid_device;
+ u_int32_t device_size; /* XXX "block or MB" Huh? */
+ u_int8_t devices_used_count;
+ u_int8_t stripe_size; /* see 8.3 */
+ u_int8_t cache_line_size; /* see 8.4 */
+ u_int8_t read_write_control; /* see 8.5 */
+ u_int32_t devices_used_size; /* XXX "block or MB" Huh? */
+ u_int16_t devices_used[32]; /* XXX actual size of this field unknown! */
+} __attribute__ ((packed));
+
+/*
+ * Define a datastructure giving the smallest allocation that will hold
+ * a PDD, UDD or LDD for MDACIOCTL_GETDEVCONFINFO.
+ */
+struct mly_devconf_hdr {
+ u_int8_t type; /* see 8.2 */
+ u_int8_t state; /* see 8.1 */
+ u_int16_t raid_device;
+};
+
+union mly_ioctl_devconfinfo {
+ struct mly_pdd pdd;
+ struct mly_udd udd;
+ struct mly_ldd ldd;
+ struct mly_devconf_hdr hdr;
+};
+
+/*
+ * 22.3 MDACIOCTL_RENAMERAIDDEV
+ *
+ * XXX this command is listed as transferring data, but does not define the data.
+ */
+struct mly_ioctl_param_renameraiddev {
+ u_int8_t new_raid_device;
+} __attribute__ ((packed));
+
+/*
+ * 23.6.2 MDACIOCTL_XLATEPHYSDEVTORAIDDEV
+ *
+ * XXX documentation suggests this format will change
+ */
+struct mly_ioctl_param_xlatephysdevtoraiddev {
+ u_int16_t raid_device;
+ u_int8_t res1[2];
+ u_int8_t controller;
+ u_int8_t channel;
+ u_int8_t target;
+ u_int8_t lun;
+} __attribute__ ((packed));
+
+/*
+ * 23.7 MDACIOCTL_GETGROUPCONFINFO
+ */
+struct mly_ioctl_param_getgroupconfinfo {
+ u_int16_t group;
+ u_int8_t res1[8];
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+/*
+ * 23.9.2 MDACIOCTL_GETFREESPACELIST: Data Format
+ *
+ * The controller will populate as much of this structure as is provided,
+ * or as is required to fully list the free space available.
+ */
+struct mly_ioctl_getfreespacelist_entry {
+ u_int16_t raid_device;
+ u_int8_t res1[6];
+ u_int32_t address; /* XXX "blocks or MB" Huh? */
+ u_int32_t size; /* XXX "blocks or MB" Huh? */
+} __attribute__ ((packed));
+
+struct mly_ioctl_getfrespacelist {
+ u_int16_t returned_entries;
+ u_int16_t total_entries;
+ u_int8_t res1[12];
+ struct mly_ioctl_getfreespacelist_entry space[0]; /* expand to suit */
+} __attribute__ ((packed));
+
+/*
+ * 27.1 MDACIOCTL_GETSUBSYSTEMDATA
+ * 27.2 MDACIOCTL_SETSUBSYSTEMDATA
+ *
+ * PCI controller only supports a limited subset of the possible operations.
+ *
+ * XXX where does the status end up? (the command transfers no data)
+ */
+struct mly_ioctl_param_subsystemdata {
+ u_int8_t operation:4;
+#define MLY_BBU_GETSTATUS 0x00
+#define MLY_BBU_SET_THRESHOLD 0x00 /* minutes in param[0,1] */
+ u_int8_t subsystem:4;
+#define MLY_SUBSYSTEM_BBU 0x01
+ u_int parameter[3]; /* only for SETSUBSYSTEMDATA */
+} __attribute__ ((packed));
+
+struct mly_ioctl_getsubsystemdata_bbustatus {
+ u_int16_t current_power;
+ u_int16_t maximum_power;
+ u_int16_t power_threshold;
+ u_int8_t charge_level;
+ u_int8_t hardware_version;
+ u_int8_t battery_type;
+#define MLY_BBU_TYPE_UNKNOWN 0x00
+#define MLY_BBU_TYPE_NICAD 0x01
+#define MLY_BBU_TYPE_MISSING 0xfe
+ u_int8_t res1;
+ u_int8_t operation_status;
+#define MLY_BBU_STATUS_NO_SYNC 0x01
+#define MLY_BBU_STATUS_OUT_OF_SYNC 0x02
+#define MLY_BBU_STATUS_FIRST_WARNING 0x04
+#define MLY_BBU_STATUS_SECOND_WARNING 0x08
+#define MLY_BBU_STATUS_RECONDITIONING 0x10
+#define MLY_BBU_STATUS_DISCHARGING 0x20
+#define MLY_BBU_STATUS_FASTCHARGING 0x40
+ u_int8_t res2;
+} __attribute__ ((packed));
+
+/*
+ * 28.9 MDACIOCTL_RESETDEVICE
+ * 28.10 MDACIOCTL_FLUSHDEVICEDATA
+ * 28.11 MDACIOCTL_PAUSEDEVICE
+ * 28.12 MDACIOCTL_UNPAUSEDEVICE
+ */
+struct mly_ioctl_param_deviceoperation {
+ u_int8_t operation_device; /* see 14.3 */
+} __attribute__ ((packed));
+
+/*
+ * 31.1 Event Data Format
+ */
+struct mly_event {
+ u_int32_t sequence_number;
+ u_int32_t timestamp;
+ u_int32_t code;
+ u_int8_t controller;
+ u_int8_t channel;
+ u_int8_t target; /* also enclosure */
+ u_int8_t lun; /* also enclosure unit */
+ u_int8_t res1[4];
+ u_int32_t param;
+ u_int8_t sense[40];
+} __attribute__ ((packed));
+
+/*
+ * 31.2 MDACIOCTL_GETEVENT
+ */
+struct mly_ioctl_param_getevent {
+ u_int16_t sequence_number_low;
+ u_int8_t res1[8];
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+union mly_ioctl_param {
+ struct mly_ioctl_param_data data;
+ struct mly_ioctl_param_setmemorymailbox setmemorymailbox;
+ struct mly_ioctl_param_setraiddevstate setraiddevstate;
+ struct mly_ioctl_param_renameraiddev renameraiddev;
+ struct mly_ioctl_param_xlatephysdevtoraiddev xlatephysdevtoraiddev;
+ struct mly_ioctl_param_getgroupconfinfo getgroupconfinfo;
+ struct mly_ioctl_param_subsystemdata subsystemdata;
+ struct mly_ioctl_param_deviceoperation deviceoperation;
+ struct mly_ioctl_param_getevent getevent;
+};
+
+/*
+ * 19 SCSI Command Format
+ */
+struct mly_command_address_physical {
+ u_int8_t lun;
+ u_int8_t target;
+ u_int8_t channel:3;
+ u_int8_t controller:5;
+} __attribute__ ((packed));
+
+struct mly_command_address_logical {
+ u_int16_t logdev;
+ u_int8_t res1:3;
+ u_int8_t controller:5;
+} __attribute__ ((packed));
+
+union mly_command_address {
+ struct mly_command_address_physical phys;
+ struct mly_command_address_logical log;
+};
+
+struct mly_command_generic {
+ u_int16_t command_id;
+ u_int8_t opcode;
+ struct mly_command_control command_control;
+ u_int32_t data_size;
+ u_int64_t sense_buffer_address;
+ union mly_command_address addr;
+ struct mly_timeout timeout;
+ u_int8_t maximum_sense_size;
+ u_int8_t res1[11];
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+
+/*
+ * 19.1 MDACMD_SCSI & MDACMD_SCSIPT
+ */
+#define MLY_CMD_SCSI_SMALL_CDB 10
+struct mly_command_scsi_small {
+ u_int16_t command_id;
+ u_int8_t opcode;
+ struct mly_command_control command_control;
+ u_int32_t data_size;
+ u_int64_t sense_buffer_address;
+ union mly_command_address addr;
+ struct mly_timeout timeout;
+ u_int8_t maximum_sense_size;
+ u_int8_t cdb_length;
+ u_int8_t cdb[MLY_CMD_SCSI_SMALL_CDB];
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+/*
+ * 19.2 MDACMD_SCSILC & MDACMD_SCSILCPT
+ */
+struct mly_command_scsi_large {
+ u_int16_t command_id;
+ u_int8_t opcode;
+ struct mly_command_control command_control;
+ u_int32_t data_size;
+ u_int64_t sense_buffer_address;
+ union mly_command_address addr;
+ struct mly_timeout timeout;
+ u_int8_t maximum_sense_size;
+ u_int8_t cdb_length;
+ u_int16_t res1;
+ u_int64_t cdb_physaddr;
+ union mly_command_transfer transfer;
+} __attribute__ ((packed));
+
+/*
+ * 20.1 IOCTL Command Format: Internal Bus
+ */
+struct mly_command_ioctl {
+ u_int16_t command_id;
+ u_int8_t opcode;
+ struct mly_command_control command_control;
+ u_int32_t data_size;
+ u_int64_t sense_buffer_address;
+ union mly_command_address addr;
+ struct mly_timeout timeout;
+ u_int8_t maximum_sense_size;
+ u_int8_t sub_ioctl;
+ union mly_ioctl_param param;
+} __attribute__ ((packed));
+
+/*
+ * PG6: 8.2.2
+ */
+struct mly_command_mmbox {
+ u_int32_t flag;
+ u_int8_t data[60];
+} __attribute__ ((packed));
+
+union mly_command_packet {
+ struct mly_command_generic generic;
+ struct mly_command_scsi_small scsi_small;
+ struct mly_command_scsi_large scsi_large;
+ struct mly_command_ioctl ioctl;
+ struct mly_command_mmbox mmbox;
+};
+
+/*
+ * PG6: 5.3
+ */
+#define MLY_I960RX_COMMAND_MAILBOX 0x10
+#define MLY_I960RX_STATUS_MAILBOX 0x18
+#define MLY_I960RX_IDBR 0x20
+#define MLY_I960RX_ODBR 0x2c
+#define MLY_I960RX_ERROR_STATUS 0x2e
+#define MLY_I960RX_INTERRUPT_STATUS 0x30
+#define MLY_I960RX_INTERRUPT_MASK 0x34
+
+#define MLY_STRONGARM_COMMAND_MAILBOX 0x50
+#define MLY_STRONGARM_STATUS_MAILBOX 0x58
+#define MLY_STRONGARM_IDBR 0x60
+#define MLY_STRONGARM_ODBR 0x61
+#define MLY_STRONGARM_ERROR_STATUS 0x63
+#define MLY_STRONGARM_INTERRUPT_STATUS 0x30
+#define MLY_STRONGARM_INTERRUPT_MASK 0x34
+
+/*
+ * PG6: 5.4.3 Doorbell 0
+ */
+#define MLY_HM_CMDSENT (1<<0)
+#define MLY_HM_STSACK (1<<1)
+#define MLY_SOFT_RST (1<<3)
+#define MLY_AM_CMDSENT (1<<4)
+
+/*
+ * PG6: 5.4.4 Doorbell 1
+ *
+ * Note that the documentation claims that these bits are set when the
+ * status queue(s) are empty, wheras the Linux driver and experience
+ * suggest they are set when there is status available.
+ */
+#define MLY_HM_STSREADY (1<<0)
+#define MLY_AM_STSREADY (1<<1)
+
+/*
+ * PG6: 5.4.6 Doorbell 3
+ */
+#define MLY_MSG_EMPTY (1<<3)
+#define MLY_MSG_SPINUP 0x08
+#define MLY_MSG_RACE_RECOVERY_FAIL 0x60
+#define MLY_MSG_RACE_IN_PROGRESS 0x70
+#define MLY_MSG_RACE_ON_CRITICAL 0xb0
+#define MLY_MSG_PARITY_ERROR 0xf0
+
+/*
+ * PG6: 5.4.8 Outbound Interrupt Mask
+ */
+#define MLY_INTERRUPT_MASK_DISABLE 0xff
+#define MLY_INTERRUPT_MASK_ENABLE (0xff & ~(1<<2))
+
+/*
+ * PG6: 8.2 Advanced Mailbox Scheme
+ *
+ * Note that this must be allocated on a 4k boundary, and all internal
+ * fields must also reside on a 4k boundary.
+ * We could dynamically size this structure, but the extra effort
+ * is probably unjustified. Note that these buffers do not need to be
+ * adjacent - we just group them to simplify allocation of the bus-visible
+ * buffer.
+ *
+ * XXX Note that for some reason, if MLY_MMBOX_COMMANDS is > 64, the controller
+ * fails to respond to the command at (MLY_MMBOX_COMMANDS - 64). It's not
+ * wrapping to 0 at this point (determined by experimentation). This is not
+ * consistent with the Linux driver's implementation.
+ * Whilst it's handy to have lots of room for status returns in case we end up
+ * being slow getting back to completed commands, it seems unlikely that we
+ * would get 64 commands ahead of the controller on the submissions side, so
+ * the current workaround is to simply limit the command ring to 64 entries.
+ */
+union mly_status_packet {
+ struct mly_status status;
+ struct {
+ u_int32_t flag;
+ u_int8_t data[4];
+ } __attribute__ ((packed)) mmbox;
+};
+union mly_health_region {
+ struct mly_health_status status;
+ u_int8_t pad[1024];
+};
+
+#define MLY_MMBOX_COMMANDS 64
+#define MLY_MMBOX_STATUS 512
+struct mly_mmbox {
+ union mly_command_packet mmm_command[MLY_MMBOX_COMMANDS];
+ union mly_status_packet mmm_status[MLY_MMBOX_STATUS];
+ union mly_health_region mmm_health;
+} __attribute__ ((packed));
diff --git a/sys/dev/mly/mlyvar.h b/sys/dev/mly/mlyvar.h
new file mode 100644
index 000000000000..00a9c9be1d3c
--- /dev/null
+++ b/sys/dev/mly/mlyvar.h
@@ -0,0 +1,423 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/********************************************************************************
+ ********************************************************************************
+ Driver Parameter Definitions
+ ********************************************************************************
+ ********************************************************************************/
+
+/*
+ * The firmware interface allows for a 16-bit command identifier. A lookup
+ * table this size (256k) would be too expensive, so we cap ourselves at a
+ * reasonable limit.
+ */
+#define MLY_MAXCOMMANDS 256 /* max outstanding commands per controller, limit 65535 */
+
+/*
+ * The firmware interface allows for a 16-bit s/g list length. We limit
+ * ourselves to a reasonable maximum and ensure alignment.
+ */
+#define MLY_MAXSGENTRIES 64 /* max S/G entries, limit 65535 */
+
+/********************************************************************************
+ ********************************************************************************
+ Driver Variable Definitions
+ ********************************************************************************
+ ********************************************************************************/
+
+#if __FreeBSD_version >= 500005
+# include <sys/taskqueue.h>
+#endif
+
+/*
+ * Debugging levels:
+ * 0 - quiet, only emit warnings
+ * 1 - noisy, emit major function points and things done
+ * 2 - extremely noisy, emit trace items in loops, etc.
+ */
+#ifdef MLY_DEBUG
+# define debug(level, fmt, args...) do { if (level <= MLY_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args); } while(0)
+# define debug_called(level) do { if (level <= MLY_DEBUG) printf(__FUNCTION__ ": called\n"); } while(0)
+# define debug_struct(s) printf(" SIZE %s: %d\n", #s, sizeof(struct s))
+# define debug_union(s) printf(" SIZE %s: %d\n", #s, sizeof(union s))
+# define debug_field(s, f) printf(" OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
+extern void mly_printstate0(void);
+extern struct mly_softc *mly_softc0;
+#else
+# define debug(level, fmt, args...)
+# define debug_called(level)
+# define debug_struct(s)
+#endif
+
+#define mly_printf(sc, fmt, args...) device_printf(sc->mly_dev, fmt , ##args)
+
+/*
+ * Per-device structure, used to save persistent state on devices.
+ *
+ * Note that this isn't really Bus/Target/Lun since we don't support
+ * lun != 0 at this time.
+ */
+struct mly_btl {
+ int mb_flags;
+#define MLY_BTL_PHYSICAL (1<<0) /* physical device */
+#define MLY_BTL_LOGICAL (1<<1) /* logical device */
+#define MLY_BTL_PROTECTED (1<<2) /* device is protected - I/O not allowed */
+#define MLY_BTL_RESCAN (1<<3) /* device needs to be rescanned */
+ char mb_name[16]; /* peripheral attached to this device */
+ int mb_state; /* see 8.1 */
+ int mb_type; /* see 8.2 */
+};
+
+/*
+ * Per-command control structure.
+ */
+struct mly_command {
+ TAILQ_ENTRY(mly_command) mc_link; /* list linkage */
+
+ struct mly_softc *mc_sc; /* controller that owns us */
+ u_int16_t mc_slot; /* command slot we occupy */
+ int mc_flags;
+#define MLY_CMD_STATEMASK ((1<<8)-1)
+#define MLY_CMD_STATE(mc) ((mc)->mc_flags & MLY_CMD_STATEMASK)
+#define MLY_CMD_SETSTATE(mc, s) ((mc)->mc_flags = ((mc)->mc_flags &= ~MLY_CMD_STATEMASK) | (s))
+#define MLY_CMD_FREE 0 /* command is on the free list */
+#define MLY_CMD_SETUP 1 /* command is being built */
+#define MLY_CMD_BUSY 2 /* command is being run, or ready to run, or not completed */
+#define MLY_CMD_COMPLETE 3 /* command has been completed */
+#define MLY_CMD_SLOTTED (1<<8) /* command has a slot number */
+#define MLY_CMD_MAPPED (1<<9) /* command has had its data mapped */
+#define MLY_CMD_PRIORITY (1<<10) /* allow use of "priority" slots */
+#define MLY_CMD_DATAIN (1<<11) /* data moves controller->system */
+#define MLY_CMD_DATAOUT (1<<12) /* data moves system->controller */
+ u_int16_t mc_status; /* command completion status */
+ u_int8_t mc_sense; /* sense data length */
+ int32_t mc_resid; /* I/O residual count */
+
+ union mly_command_packet *mc_packet; /* our controller command */
+ u_int64_t mc_packetphys; /* physical address of the mapped packet */
+
+ void *mc_data; /* data buffer */
+ size_t mc_length; /* data length */
+ bus_dmamap_t mc_datamap; /* DMA map for data */
+
+ void (* mc_complete)(struct mly_command *mc); /* completion handler */
+ void *mc_private; /* caller-private data */
+
+};
+
+/*
+ * Command slot regulation.
+ *
+ * We can't use slot 0 due to the memory mailbox implementation.
+ */
+#define MLY_SLOT_START 1
+#define MLY_SLOT_MAX (MLY_SLOT_START + MLY_MAXCOMMANDS)
+
+/*
+ * Command/command packet cluster.
+ *
+ * Due to the difficulty of using the zone allocator to create a new
+ * zone from within a module, we use our own clustering to reduce
+ * memory wastage caused by allocating lots of these small structures.
+ *
+ * Note that it is possible to require more than MLY_MAXCOMMANDS
+ * command structures.
+ *
+ * Since we may need to allocate extra clusters at any time, and since this
+ * process needs to allocate a physically contiguous slab of controller
+ * addressible memory in which to place the command packets, do not allow more
+ * command packets in a cluster than will fit in a page.
+ */
+#define MLY_CMD_CLUSTERCOUNT (PAGE_SIZE / sizeof(union mly_command_packet))
+
+struct mly_command_cluster {
+ TAILQ_ENTRY(mly_command_cluster) mcc_link;
+ union mly_command_packet *mcc_packet;
+ bus_dmamap_t mcc_packetmap;
+ u_int64_t mcc_packetphys;
+ struct mly_command mcc_command[MLY_CMD_CLUSTERCOUNT];
+};
+
+/*
+ * Per-controller structure.
+ */
+struct mly_softc {
+ /* bus connections */
+ device_t mly_dev;
+ struct resource *mly_regs_resource; /* register interface window */
+ int mly_regs_rid; /* resource ID */
+ bus_space_handle_t mly_bhandle; /* bus space handle */
+ bus_space_tag_t mly_btag; /* bus space tag */
+ bus_dma_tag_t mly_parent_dmat; /* parent DMA tag */
+ bus_dma_tag_t mly_buffer_dmat; /* data buffer/command DMA tag */
+ struct resource *mly_irq; /* interrupt */
+ int mly_irq_rid;
+ void *mly_intr; /* interrupt handle */
+
+ /* scatter/gather lists and their controller-visible mappings */
+ struct mly_sg_entry *mly_sg_table; /* s/g lists */
+ u_int32_t mly_sg_busaddr; /* s/g table base address in bus space */
+ bus_dma_tag_t mly_sg_dmat; /* s/g buffer DMA tag */
+ bus_dmamap_t mly_sg_dmamap; /* map for s/g buffers */
+
+ /* controller hardware interface */
+ int mly_hwif;
+#define MLY_HWIF_I960RX 0
+#define MLY_HWIF_STRONGARM 1
+ u_int8_t mly_doorbell_true; /* xor map to make hardware doorbell 'true' bits into 1s */
+ u_int8_t mly_command_mailbox; /* register offsets */
+ u_int8_t mly_status_mailbox;
+ u_int8_t mly_idbr;
+ u_int8_t mly_odbr;
+ u_int8_t mly_error_status;
+ u_int8_t mly_interrupt_status;
+ u_int8_t mly_interrupt_mask;
+ struct mly_mmbox *mly_mmbox; /* kernel-space address of memory mailbox */
+ u_int64_t mly_mmbox_busaddr; /* bus-space address of memory mailbox */
+ bus_dma_tag_t mly_mmbox_dmat; /* memory mailbox DMA tag */
+ bus_dmamap_t mly_mmbox_dmamap; /* memory mailbox DMA map */
+ u_int32_t mly_mmbox_command_index; /* next slot to use */
+ u_int32_t mly_mmbox_status_index; /* slot we next expect status in */
+
+ /* controller features, limits and status */
+ int mly_state;
+#define MLY_STATE_SUSPEND (1<<0)
+#define MLY_STATE_OPEN (1<<1)
+#define MLY_STATE_INTERRUPTS_ON (1<<2)
+#define MLY_STATE_MMBOX_ACTIVE (1<<3)
+ int mly_max_commands; /* max parallel commands we allow */
+ struct mly_ioctl_getcontrollerinfo *mly_controllerinfo;
+ struct mly_param_controller *mly_controllerparam;
+ struct mly_btl mly_btl[MLY_MAX_CHANNELS][MLY_MAX_TARGETS];
+
+ /* command management */
+ struct mly_command *mly_busycmds[MLY_SLOT_MAX]; /* busy commands */
+ int mly_busy_count;
+ int mly_last_slot;
+ TAILQ_HEAD(,mly_command) mly_freecmds; /* commands available for reuse */
+ TAILQ_HEAD(,mly_command) mly_ready; /* commands ready to be submitted */
+ TAILQ_HEAD(,mly_command) mly_completed; /* commands which have been returned by the controller */
+ TAILQ_HEAD(,mly_command_cluster) mly_clusters; /* command memory blocks */
+ bus_dma_tag_t mly_packet_dmat; /* command packet DMA tag */
+
+ /* health monitoring */
+ u_int32_t mly_event_change; /* event status change indicator */
+ u_int32_t mly_event_counter; /* next event for which we anticpiate status */
+ u_int32_t mly_event_waiting; /* next event the controller will post status for */
+ struct callout_handle mly_periodic; /* periodic event handling */
+
+ /* CAM connection */
+ TAILQ_HEAD(,ccb_hdr) mly_cam_ccbq; /* outstanding I/O from CAM */
+ struct cam_sim *mly_cam_sim[MLY_MAX_CHANNELS];
+ int mly_cam_lowbus;
+
+#if __FreeBSD_version >= 500005
+ /* command-completion task */
+ struct task mly_task_complete; /* deferred-completion task */
+#endif
+};
+
+/*
+ * Register access helpers.
+ */
+#define MLY_SET_REG(sc, reg, val) bus_space_write_1(sc->mly_btag, sc->mly_bhandle, reg, val)
+#define MLY_GET_REG(sc, reg) bus_space_read_1 (sc->mly_btag, sc->mly_bhandle, reg)
+#define MLY_GET_REG2(sc, reg) bus_space_read_2 (sc->mly_btag, sc->mly_bhandle, reg)
+#define MLY_GET_REG4(sc, reg) bus_space_read_4 (sc->mly_btag, sc->mly_bhandle, reg)
+
+#define MLY_SET_MBOX(sc, mbox, ptr) \
+ do { \
+ bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox, *((u_int32_t *)ptr)); \
+ bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 4, *((u_int32_t *)ptr + 1)); \
+ bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 8, *((u_int32_t *)ptr + 2)); \
+ bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 12, *((u_int32_t *)ptr + 3)); \
+ } while(0);
+#define MLY_GET_MBOX(sc, mbox, ptr) \
+ do { \
+ *((u_int32_t *)ptr) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox); \
+ *((u_int32_t *)ptr + 1) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 4); \
+ *((u_int32_t *)ptr + 2) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 8); \
+ *((u_int32_t *)ptr + 3) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 12); \
+ } while(0);
+
+#define MLY_IDBR_TRUE(sc, mask) \
+ ((((MLY_GET_REG((sc), (sc)->mly_idbr)) ^ (sc)->mly_doorbell_true) & (mask)) == (mask))
+#define MLY_ODBR_TRUE(sc, mask) \
+ ((MLY_GET_REG((sc), (sc)->mly_odbr) & (mask)) == (mask))
+#define MLY_ERROR_VALID(sc) \
+ ((((MLY_GET_REG((sc), (sc)->mly_error_status)) ^ (sc)->mly_doorbell_true) & (MLY_MSG_EMPTY)) == 0)
+
+#define MLY_MASK_INTERRUPTS(sc) \
+ do { \
+ MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_DISABLE); \
+ sc->mly_state &= ~MLY_STATE_INTERRUPTS_ON; \
+ } while(0);
+#define MLY_UNMASK_INTERRUPTS(sc) \
+ do { \
+ MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_ENABLE); \
+ sc->mly_state |= MLY_STATE_INTERRUPTS_ON; \
+ } while(0);
+
+/*
+ * Logical device number -> bus/target translation
+ */
+#define MLY_LOGDEV_BUS(sc, x) (((x) / MLY_MAX_TARGETS) + (sc)->mly_controllerinfo->physical_channels_present)
+#define MLY_LOGDEV_TARGET(x) ((x) % MLY_MAX_TARGETS)
+
+/*
+ * Public functions/variables
+ */
+/* mly.c */
+extern int mly_attach(struct mly_softc *sc);
+extern void mly_detach(struct mly_softc *sc);
+extern void mly_free(struct mly_softc *sc);
+extern void mly_startio(struct mly_softc *sc);
+extern void mly_done(struct mly_softc *sc);
+extern int mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp);
+extern void mly_release_command(struct mly_command *mc);
+
+/* mly_cam.c */
+extern int mly_cam_attach(struct mly_softc *sc);
+extern void mly_cam_detach(struct mly_softc *sc);
+extern int mly_cam_command(struct mly_softc *sc, struct mly_command **mcp);
+extern int mly_name_device(struct mly_softc *sc, int bus, int target);
+
+/********************************************************************************
+ * Queue primitives
+ *
+ * These are broken out individually to make statistics gathering easier.
+ */
+
+static __inline void
+mly_enqueue_ready(struct mly_command *mc)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_TAIL(&mc->mc_sc->mly_ready, mc, mc_link);
+ MLY_CMD_SETSTATE(mc, MLY_CMD_BUSY);
+ splx(s);
+}
+
+static __inline void
+mly_requeue_ready(struct mly_command *mc)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_HEAD(&mc->mc_sc->mly_ready, mc, mc_link);
+ splx(s);
+}
+
+static __inline struct mly_command *
+mly_dequeue_ready(struct mly_softc *sc)
+{
+ struct mly_command *mc;
+ int s;
+
+ s = splcam();
+ if ((mc = TAILQ_FIRST(&sc->mly_ready)) != NULL)
+ TAILQ_REMOVE(&sc->mly_ready, mc, mc_link);
+ splx(s);
+ return(mc);
+}
+
+static __inline void
+mly_enqueue_completed(struct mly_command *mc)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_TAIL(&mc->mc_sc->mly_completed, mc, mc_link);
+ /* don't set MLY_CMD_COMPLETE here to avoid wakeup race */
+ splx(s);
+}
+
+static __inline struct mly_command *
+mly_dequeue_completed(struct mly_softc *sc)
+{
+ struct mly_command *mc;
+ int s;
+
+ s = splcam();
+ if ((mc = TAILQ_FIRST(&sc->mly_completed)) != NULL)
+ TAILQ_REMOVE(&sc->mly_completed, mc, mc_link);
+ splx(s);
+ return(mc);
+}
+
+static __inline void
+mly_enqueue_free(struct mly_command *mc)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_HEAD(&mc->mc_sc->mly_freecmds, mc, mc_link);
+ MLY_CMD_SETSTATE(mc, MLY_CMD_FREE);
+ splx(s);
+}
+
+static __inline struct mly_command *
+mly_dequeue_free(struct mly_softc *sc)
+{
+ struct mly_command *mc;
+ int s;
+
+ s = splcam();
+ if ((mc = TAILQ_FIRST(&sc->mly_freecmds)) != NULL)
+ TAILQ_REMOVE(&sc->mly_freecmds, mc, mc_link);
+ splx(s);
+ return(mc);
+}
+
+static __inline void
+mly_enqueue_cluster(struct mly_softc *sc, struct mly_command_cluster *mcc)
+{
+ int s;
+
+ s = splcam();
+ TAILQ_INSERT_HEAD(&sc->mly_clusters, mcc, mcc_link);
+ splx(s);
+}
+
+static __inline struct mly_command_cluster *
+mly_dequeue_cluster(struct mly_softc *sc)
+{
+ struct mly_command_cluster *mcc;
+ int s;
+
+ s = splcam();
+ if ((mcc = TAILQ_FIRST(&sc->mly_clusters)) != NULL)
+ TAILQ_REMOVE(&sc->mly_clusters, mcc, mcc_link);
+ splx(s);
+ return(mcc);
+}
+
+
diff --git a/sys/modules/mly/Makefile b/sys/modules/mly/Makefile
new file mode 100644
index 000000000000..1f8abe828496
--- /dev/null
+++ b/sys/modules/mly/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/mly
+KMOD = mly
+SRCS = mly.c mly_pci.c mly_cam.c
+SRCS += opt_scsi.h opt_cam.h
+SRCS += device_if.h bus_if.h pci_if.h
+
+#CFLAGS+= -DMLY_DEBUG=1
+
+.include <bsd.kmod.mk>
diff --git a/usr.bin/finger/finger.conf.5 b/usr.bin/finger/finger.conf.5
new file mode 100644
index 000000000000..a339b0c71ee0
--- /dev/null
+++ b/usr.bin/finger/finger.conf.5
@@ -0,0 +1,82 @@
+.\"Copyright (c) 2000 Mark Knight <markk@knigma.org>
+.\"All rights reserved.
+.\"
+.\"Redistribution and use in source and binary forms, with or without
+.\"modification, are permitted provided that the following conditions
+.\"are met:
+.\"1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\"THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\"ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\"IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\"ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\"FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\"DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\"OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\"HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\"LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\"OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\"SUCH DAMAGE.
+.\"
+.\"$FreeBSD$
+.\"
+.Dd August 16, 2000
+.Dt FINGER.CONF 5
+.Os
+.Sh NAME
+.Nm finger.conf
+.Nd
+.Xr finger 1
+alias configuration file
+.Sh DESCRIPTION
+The optional
+.Nm
+file is used to provide aliases that can be fingered by local
+and network users.
+This may be useful where a user's login name is not the same
+as their preferred mail address.
+.Pp
+Lines beginning with ``#'' are comments.
+Other lines must consist of an
+alias name and a target name separated by a colon.
+A target name should be either a user, or a forward
+reference to another alias.
+.Sh EXAMPLES
+.Bd -literal
+# /etc/finger.conf alias definition file
+#
+# Format alias:(user|alias)
+#
+# Individual aliases
+#
+markk:mkn
+john.smith:dev329
+john:dev329
+#
+# Administrative redirects
+#
+root:admin
+postmaster:admin
+abuse:admin
+#
+# For the time being, 'sod' is sysadmin.
+#
+admin:sod
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/finger.conf -compact
+.It Pa /etc/finger.conf
+.Xr finger 1
+alias definition data base
+.El
+.Sh SEE ALSO
+.Xr finger 1
+.Sh HISTORY
+Support for the
+.Nm
+file was submitted by Mark Knight <markk@knigma.org> and first appeared in
+.Fx 5.0 .
diff --git a/usr.bin/finger/pathnames.h b/usr.bin/finger/pathnames.h
new file mode 100644
index 000000000000..6839159ade67
--- /dev/null
+++ b/usr.bin/finger/pathnames.h
@@ -0,0 +1,31 @@
+/*-
+ * Copyright (c) 2000 Mark Knight <markk@knigma.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _PATH_FINGERCONF
+#define _PATH_FINGERCONF "/etc/finger.conf"
+#endif /* _PATH_FINGERCONF */
diff --git a/usr.sbin/pccard/pccardd/server.c b/usr.sbin/pccard/pccardd/server.c
new file mode 100644
index 000000000000..d5a271fb5e42
--- /dev/null
+++ b/usr.sbin/pccard/pccardd/server.c
@@ -0,0 +1,187 @@
+/*
+ * pccardd UNIX-domain socket interface
+ * Copyright (C) 1996 by Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * $Id: server.c,v 1.3 1999/02/07 08:02:44 kuriyama Exp $
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include "cardd.h"
+
+static void
+cardnum(char *buf)
+{
+ int i = 0;
+ struct slot *sp;
+
+ for (sp = slots; sp; sp = sp->next)
+ i++;
+ if (i > MAXSLOT)
+ i = MAXSLOT;
+ sprintf(buf, "%2d", i);
+}
+
+static struct slot *
+find_slot(int slot)
+{
+ struct slot *sp;
+
+ /* Search the list until we find the slot or get to the end */
+ for (sp = slots; sp && sp->slot != slot; sp = sp->next)
+ continue;
+
+ return ( sp );
+}
+
+static void
+cardname(char *buf, int slot)
+{
+ struct slot *sp;
+ char *manuf, *vers, *drv, *stat;
+
+ /* Look for the slot */
+ if ( (sp = find_slot(slot)) == NULL)
+ return;
+
+ /* Fill in the information in the buff */
+ if (sp->cis) {
+
+ manuf = sp->cis->manuf;
+ vers = sp->cis->vers;
+ if (sp->config && sp->config->driver &&
+ sp->config->driver->name)
+ drv = sp->config->driver->name;
+ else
+ drv = "";
+ } else
+ manuf = vers = drv = "";
+
+ switch (sp->state) {
+ case empty:
+ stat = "0";
+ break;
+ case filled:
+ stat = "1";
+ break;
+ case inactive:
+ stat = "2";
+ break;
+ default:
+ stat = "9";
+ }
+ sprintf(buf, "%d~%s~%s~%s~%s", slot, manuf, vers, drv, stat);
+}
+
+static void
+cardpwr(int slot, int pwon)
+{
+ struct slot *sp;
+
+ /* Look for the slot */
+ if ( (sp = find_slot(slot)) == NULL)
+ return;
+
+ if (ioctl(sp->fd, PIOCSVIR, &pwon) < 0)
+ logerr("invaild arguments for cardpwr");
+}
+
+static int sock = 0;
+static int slen = 0;
+static struct sockaddr_un sun;
+
+void
+set_socket(int s)
+{
+ sock = s;
+}
+
+void
+stat_changed(struct slot *sp)
+{
+ int len;
+ char buf[512];
+
+ if (!slen)
+ return;
+
+ cardname(buf, sp->slot);
+ len = strlen(buf);
+ if (sendto(sock, buf, len, 0, (struct sockaddr *) & sun, slen) != len) {
+ logerr("sendto failed");
+ slen = 0;
+ }
+}
+
+void
+process_client(void)
+{
+ char buf[512], obuf[512];
+ int len;
+ int snum;
+
+ if (!sock)
+ return;
+ slen = sizeof(sun);
+ len = recvfrom(sock, buf, sizeof(buf),
+ 0, (struct sockaddr *)&sun, &slen);
+ if (len < 0)
+ logerr("recvfrom failed");
+ buf[len] = '\0';
+ obuf[0] = '\0';
+ switch (buf[0]) { /* Protocol implementation */
+ case 'S': /* How many slots? */
+ cardnum(obuf);
+ break;
+ case 'N': /* Card name request */
+ sscanf(buf + 1, "%d", &snum);
+ if (snum >= 0 && snum <= MAXSLOT)
+ cardname(obuf, snum);
+ else
+ logerr("Illegal slot requests for N command");
+ break;
+ case 'P': /* Virtual insertion request */
+ sscanf(buf + 1, "%d", &snum);
+ if (snum >= 0 && snum <= MAXSLOT) {
+ logmsg("slot %d: spring has come", snum);
+ cardpwr(snum, 1);
+ } else
+ logerr("Illegal slot requests for P command");
+ break;
+ case 'Q': /* Virtual removal request */
+ sscanf(buf + 1, "%d", &snum);
+ if (snum >= 0 && snum <= MAXSLOT) {
+ logmsg("slot %d: hibernation", snum);
+ cardpwr(snum, 0);
+ } else
+ logerr("Illegal slot requests for Q command");
+ break;
+ default:
+ logerr("Unknown control message from socket");
+ break;
+ }
+ len = strlen(obuf);
+ if (len) {
+ if (sendto(sock, obuf, len, 0, (struct sockaddr *)&sun, slen)
+ != len) {
+ logerr("sendto failed");
+ slen = 0;
+ }
+ } else if (sendto(sock, 0, 0, 0, (struct sockaddr *)&sun, slen)
+ != len) {
+ logerr("sendto failed");
+ slen = 0;
+ }
+}