diff options
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\}\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 (®_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 ? ®s : (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; + } +} |
