[comp.sources.unix] v22i023: Error table compiler and library, Part02/03

rsalz@uunet.uu.net (Rich Salz) (05/08/90)

Submitted-by: "Jonathan I. Kamens" <jik@pit-manager.mit.edu>
Posting-number: Volume 22, Issue 23
Archive-name: et/part02

[  There are a couple of control characters:
	Found 1 control char in "'com_err.texinfo'"
	Found 15 control chars in "'texinfo.tex.2'"
  --r$  ]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  com_err.texinfo texinfo.tex.2
# Wrapped by rsalz@litchi.bbn.com on Mon May  7 16:40:34 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'com_err.texinfo' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'com_err.texinfo'\"
else
echo shar: Extracting \"'com_err.texinfo'\" \(21738 characters\)
sed "s/^X//" >'com_err.texinfo' <<'END_OF_FILE'
X\input texinfo @c -*-texinfo-*-
X
X@c $Header$
X@c $Source$
X@c $Locker$
X
X@c Note that although this source file is in texinfo format (more
X@c or less), it is not yet suitable for turning into an ``info''
X@c file.  Sorry, maybe next time.
X@c
X@c In order to produce hardcopy documentation from a texinfo file,
X@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
X@c provided in this distribution.  (texinfo.tex is from the Free
X@c Software Foundation, and is under different copyright restrictions
X@c from the rest of this package.)
X
X@ifinfo
X@barfo
X@end ifinfo
X
X@iftex
X@tolerance 10000
X
X@c Mutate section headers...
X@begingroup
X  @catcode#=6
X  @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
X@endgroup
X@end iftex
X
X@setfilename com_err
X@settitle A Common Error Description Library for UNIX
X
X@ifinfo
XThis file documents the use of the Common Error Description library.
X
XCopyright (C) 1987, 1988 Student Information Processing Board of the
XMassachusetts Institute of Technology.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
Xused in advertising or publicity pertaining to distribution of the software
Xwithout specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
Xmake no representations about the suitability of this software for any
Xpurpose.  It is provided "as is" without express or implied warranty.
X
XNote that the file texinfo.tex, provided with this distribution, is from
Xthe Free Software Foundation, and is under different copyright restrictions
Xfrom the remainder of this package.
X
X@end ifinfo
X
X@ignore
XPermission is granted to process this file through Tex and print the
Xresults, provided the printed document carries copying permission
Xnotice identical to this one except for the removal of this paragraph
X(this paragraph not being relevant to the printed manual).
X
X@end ignore
X
X@setchapternewpage odd
X
X@titlepage
X@center @titlefont{A Common Error Description}
X@center @titlefont{Library for UNIX}
X@sp 2
X@center Ken Raeburn
X@center Bill Sommerfeld
X@sp 1
X@center MIT Student Information Processing Board
X@sp 3
X@center last updated 1 January 1989
X@center for version 1.2
X@center ***DRAFT COPY ONLY***
X
X@vskip 2in
X
X@center @b{Abstract}
X
XUNIX has always had a clean and simple system call interface, with a
Xstandard set of error codes passed between the kernel and user
Xprograms.  Unfortunately, the same cannot be said of many of the
Xlibraries layered on top of the primitives provided by the kernel.
XTypically, each one has used a different style of indicating errors to
Xtheir callers, leading to a total hodgepodge of error handling, and
Xconsiderable amounts of work for the programmer.  This paper describes
Xa library and associated utilities which allows a more uniform way for
Xlibraries to return errors to their callers, and for programs to
Xdescribe errors and exceptional conditions to their users.
X
X@page
X@vskip 0pt plus 1filll
X
XCopyright @copyright{} 1987, 1988 by the Student Information Processing
XBoard of the Massachusetts Institute of Technology.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
Xused in advertising or publicity pertaining to distribution of the software
Xwithout specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
Xmake no representations about the suitability of this software for any
Xpurpose.  It is provided "as is" without express or implied warranty.
X
XNote that the file texinfo.tex, provided with this distribution, is from
Xthe Free Software Foundation, and is under different copyright restrictions
Xfrom the remainder of this package.
X
X@end titlepage
X
X@ifinfo
X@c should put a menu here someday....
X@end ifinfo
X
X@page
X
X@section Why com_err?
X
XIn building application software packages, a programmer often has to
Xdeal with a number of libraries, each of which can use a different
Xerror-reporting mechanism.  Sometimes one of two values is returned,
Xindicating simply SUCCESS or FAILURE, with no description of errors
Xencountered.  Sometimes it is an index into a table of text strings,
Xwhere the name of the table used is dependent on the library being
Xused when the error is generated; since each table starts numbering at
X0 or 1, additional information as to the source of the error code is
Xneeded to determine which table to look at.  Sometimes no text messages are
Xsupplied at all, and the programmer must supply them at any point at which
Xhe may wish to report error conditions.
XOften, a global variable is assigned some value describing the error, but
Xthe programmer has to know in each case whether to look at @code{errno},
X@code{h_errno}, the return value from @code{hes_err()}, or whatever other
Xvariables or routines are specified.
XAnd what happens if something
Xin the procedure of
Xexamining or reporting the error changes the same variable?
X
XThe package we have developed is an attempt to present a common
Xerror-handling mechanism to manipulate the most common form of error code
Xin a fashion that does not have the problems listed above.
X
XA list of up to 256 text messages is supplied to a translator we have
Xwritten, along with the three- to four-character ``name'' of the error
Xtable.  The library using this error table need only call a routine
Xgenerated from this error-table source to make the table ``known'' to the
Xcom_err library, and any error code the library generates can be converted
Xto the corresponding error message.  There is also a default format for
Xerror codes accidentally returned before making the table known, which is
Xof the form @samp{unknown code foo 32}, where @samp{foo} would be the name
Xof the table.
X
X@section Error codes
X
XError codes themselves are 32 bit (signed) integers, of which the high
Xorder 24 bits are an identifier of which error table the error code is
Xfrom, and the low order 8 bits are a sequential error number within
Xthe table.  An error code may thus be easily decomposed into its component
Xparts.  Only the lowest 32 bits of an error code are considered significant
Xon systems which support wider values.
X
XError table 0 is defined to match the UNIX system call error table
X(@code{sys_errlist}); this allows @code{errno} values to be used directly
Xin the library (assuming that @code{errno} is of a type with the same width
Xas @t{long}).  Other error table numbers are formed by compacting together
Xthe first four characters of the error table name.  The mapping between
Xcharacters in the name and numeric values in the error code are defined in
Xa system-independent fashion, so that two systems that can pass integral
Xvalues between them can reliably pass error codes without loss of meaning;
Xthis should work even if the character sets used are not the same.
X(However, if this is to be done, error table 0 should be avoided, since the
Xlocal system call error tables may differ.)
X
XAny variable which is to contain an error code should be declared @t{long}.
XThe draft proposed American National Standard for C (as of May, 1988)
Xrequires that @t{long} variables be at least 32 bits; any system which does
Xnot support 32-bit @t{long} values cannot make use of this package (nor
Xmuch other software that assumes an ANSI-C environment base) without
Xsignificant effort.
X
X@section Error table source file
X
XThe error table source file begins with the declaration of the table name,
Xas
X
X@example
Xerror_table @var{tablename}
X@end example
X
XIndividual error codes are
Xspecified with
X
X@example
Xerror_code @var{ERROR_NAME}, @var{"text message"}
X@end example
X
Xwhere @samp{ec} can also be used as a short form of @samp{error_code}.  To
Xindicate the end of the table, use @samp{end}.  Thus, a (short) sample
Xerror table might be:
X
X@example
X
X        error_table     dsc
X
X        error_code      DSC_DUP_MTG_NAME,
X                        "Meeting already exists"
X
X        ec              DSC_BAD_PATH,
X                        "A bad meeting pathname was given"
X
X        ec              DSC_BAD_MODES,
X                        "Invalid mode for this access control list"
X
X        end
X
X@end example
X
X@section The error-table compiler
X
XThe error table compiler is named @code{compile_et}.  It takes one
Xargument, the pathname of a file (ending in @samp{.et}, e.g.,
X@samp{dsc_err.et}) containing an error table source file.  It parses the
Xerror table, and generates two output files -- a C header file
X(@samp{discuss_err.h}) which contains definitions of the numerical values
Xof the error codes defined in the error table, and a C source file which
Xshould be compiled and linked with the executable.  The header file must be
Xincluded in the source of a module which wishes to reference the error
Xcodes defined; the object module generated from the C code may be linked in
Xto a program which wishes to use the printed forms of the error codes.
X
XThis translator accepts a @kbd{-language @var{lang}} argument, which
Xdetermines for which language (or language variant) the output should be
Xwritten.  At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
Xand @kbd{K&R-C}, and some abbreviated forms of each.  Eventually, this will
Xbe extended to include some support for C++.  The default is currently
X@kbd{K&R-C}, though the generated sources will have ANSI-C code
Xconditionalized on the symbol @t{__STDC__}.
X
X@section Run-time support routines
X
XAny source file which uses the routines supplied with or produced by the
Xcom_err package should include the header file @file{<com_err.h>}.  It
Xcontains declarations and definitions which may be needed on some systems.
X(Some functions cannot be referenced properly without the return type
Xdeclarations in this file.  Some functions may work properly on most
Xarchitectures even without the header file, but relying on this is not
Xrecommended.)
X
XThe run-time support routines and variables provided via this package
Xinclude the following:
X
X@example
Xvoid initialize_@var{xxxx}_error_table (void);
X@end example
X
XOne of these routines is built by the error compiler for each error table.
XIt makes the @var{xxxx} error table ``known'' to the error reporting
Xsystem.  By convention, this routine should be called in the initialization
Xroutine of the @var{xxxx} library.  If the library has no initialization
Xroutine, some combination of routines which form the core of the library
Xshould ensure that this routine is called.  It is not advised to leave it
Xthe caller to make this call.
X
XThere is no harm in calling this routine more than once.
X
X@example
X#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
X@end example
X
XThis symbol contains the value of the first error code entry in the
Xspecified table.
XThis rarely needs be used by the
Xprogrammer.
X
X@example
Xconst char *error_message (long code);
X@end example
X
XThis routine returns the character string error message associated
Xwith @code{code}; if this is associated with an unknown error table, or
Xif the code is associated with a known error table but the code is not
Xin the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
Xreturned, where @var{xxxx} is the error table name produced by
Xreversing the compaction performed on the error table number implied
Xby that error code, and @var{nn} is the offset from that base value.
X
XAlthough this routine is available for use when needed, its use should be
Xleft to circumstances which render @code{com_err} (below) unusable.
X
X@example
Xvoid com_err (const char *whoami,  /* module reporting error */
X              long code,           /* error code */
X              const char *format,  /* format for additional detail */
X              ...);                /*  (extra parameters) */
X@end example
X
XThis routine provides an alternate way to print error messages to
Xstandard error; it allows the error message to be passed in as a
Xparameter, rather than in an external variable.  @emph{Provide grammatical
Xcontext for ``message.''}
X
XIf @var{format} is @code{(char *)NULL}, the formatted message will not be
Xprinted.  @var{format} may not be omitted.
X
X@example
X#include <stdarg.h>
X
Xvoid com_err_va (const char *whoami,
X                 long code,
X                 const char *format,
X                 va_list args);
X@end example
X
XThis routine provides an interface, equivalent to @code{com_err} above,
Xwhich may be used by higher-level variadic functions (functions which
Xaccept variable numbers of arguments).
X
X@example
X#include <stdarg.h>
X
Xvoid (*set_com_err_hook (void (*proc) ())) ();
X
Xvoid (*@var{proc}) (const char *whoami, long code, va_list args);
X
Xvoid reset_com_err_hook ();
X@end example
X
XThese two routines allow a routine to be dynamically substituted for
X@samp{com_err}.  After @samp{set_com_err_hook} has been called,
Xcalls to @samp{com_err} will turn into calls to the new hook routine.
X@samp{reset_com_err_hook} turns off this hook.  This may intended to
Xbe used in daemons (to use a routine which calls @var{syslog(3)}), or
Xin a window system application (which could pop up a dialogue box).
X
XIf a program is to be used in an environment in which simply printing
Xmessages to the @code{stderr} stream would be inappropriate (such as in a
Xdaemon program which runs without a terminal attached),
X@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
XThe following is an example of an error handler which uses @var{syslog(3)}
Xas supplied in BSD 4.3:
X
X@example
X#include <stdio.h>
X#include <stdarg.h>
X#include <syslog.h>
X
X/* extern openlog (const char * name, int logopt, int facility); */
X/* extern syslog (int priority, char * message, ...); */
X
Xvoid hook (const char * whoami, long code,
X           const char * format, va_list args)
X@{
X    char buffer[BUFSIZ];
X    static int initialized = 0;
X    if (!initialized) @{
X        openlog (whoami,
X                 LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
X                 LOG_DAEMON);
X        initialized = 1;
X    @}
X    vsprintf (buffer, format, args);
X    syslog (LOG_ERR, "%s %s", error_message (code), buffer);
X@}
X@end example
X
XAfter making the call
X@code{set_com_err_hook (hook);},
Xany calls to @code{com_err} will result in messages being sent to the
X@var{syslogd} daemon for logging.
XThe name of the program, @samp{whoami}, is supplied to the
X@samp{openlog()} call, and the message is formatted into a buffer and
Xpassed to @code{syslog}.
X
XNote that since the extra arguments to @code{com_err} are passed by
Xreference via the @code{va_list} value @code{args}, the hook routine may
Xplace any form of interpretation on them, including ignoring them.  For
Xconsistency, @code{printf}-style interpretation is suggested, via
X@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
Xthe ANSI C library).
X
X@section Coding Conventions
X
XThe following conventions are just some general stylistic conventions
Xto follow when writing robust libraries and programs.  Conventions
Xsimilar to this are generally followed inside the UNIX kernel and most
Xroutines in the Multics operating system.  In general, a routine
Xeither succeeds (returning a zero error code, and doing some side
Xeffects in the process), or it fails, doing minimal side effects; in
Xany event, any invariant which the library assumes must be maintained.
X
XIn general, it is not in the domain of non user-interface library
Xroutines to write error messages to the user's terminal, or halt the
Xprocess.  Such forms of ``error handling'' should be reserved for
Xfailures of internal invariants and consistancy checks only, as it
Xprovides the user of the library no way to clean up for himself in the
Xevent of total failure.
X
XLibrary routines which can fail should be set up to return an error
Xcode.  This should usually be done as the return value of the
Xfunction; if this is not acceptable, the routine should return a
X``null'' value, and put the error code into a parameter passed by
Xreference.
X
XRoutines which use the first style of interface can be used from
Xuser-interface levels of a program as follows:
X
X@example
X@{
X    if ((code = initialize_world(getuid(), random())) != 0) @{
X        com_err("demo", code,
X                "when trying to initialize world");
X        exit(1);
X    @}
X    if ((database = open_database("my_secrets", &code))==NULL) @{
X        com_err("demo", code,
X                "while opening my_secrets");
X        exit(1);
X    @}
X@}
X@end example
X
XA caller which fails to check the return status is in error.  It is
Xpossible to look for code which ignores error returns by using lint;
Xlook for error messages of the form ``foobar returns value which is
Xsometimes ignored'' or ``foobar returns value which is always
Xignored.''
X
XSince libraries may be built out of other libraries, it is often necessary
Xfor the success of one routine to depend on another.  When a lower level
Xroutine returns an error code, the middle level routine has a few possible
Xoptions.  It can simply return the error code to its caller after doing
Xsome form of cleanup, it can substitute one of its own, or it can take
Xcorrective action of its own and continue normally.  For instance, a
Xlibrary routine which makes a ``connect'' system call to make a network
Xconnection may reflect the system error code @code{ECONNREFUSED}
X(Connection refused) to its caller, or it may return a ``server not
Xavailable, try again later,'' or it may try a different server.
X
XCleanup which is typically necessary may include, but not be limited
Xto, freeing allocated memory which will not be needed any more,
Xunlocking concurrancy locks, dropping reference counts, closing file
Xdescriptors, or otherwise undoing anything which the procedure did up
Xto this point.  When there are a lot of things which can go wrong, it
Xis generally good to write one block of error-handling code which is
Xbranched to, using a goto, in the event of failure.  A common source
Xof errors in UNIX programs is failing to close file descriptors on
Xerror returns; this leaves a number of ``zombied'' file descriptors
Xopen, which eventually causes the process to run out of file
Xdescriptors and fall over.
X
X@example
X@{
X    FILE *f1=NULL, *f2=NULL, *f3=NULL;
X    int status = 0;
X
X    if ( (f1 = fopen(FILE1, "r")) == NULL) @{
X        status = errno;
X        goto error;
X    @}
X
X    /*
X     * Crunch for a while
X     */
X
X    if ( (f2 = fopen(FILE2, "w")) == NULL) @{
X        status = errno;
X        goto error;
X    @}
X
X    if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
X        status = errno;
X            goto error;
X    @}
X
X    /*
X     * Do more processing.
X     */
X    fclose(f1);
X    fclose(f2);
X    fclose(f3);
X    return 0;
X
Xerror:
X    if (f1) fclose(f1);
X    if (f2) fclose(f2);
X    if (f3) fclose(f3);
X    return status;
X@}
X@end example
X
X@section Building and Installation
X
XThe distribution of this package will probably be done as a compressed
X``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
XRetrieve @samp{pub/com_err.tar.Z} and extract the contents.  A subdirectory
X@t{profiled} should be created to hold objects compiled for profiling.
XRunning ``make all'' should then be sufficient to build the library and
Xerror-table compiler.  The files @samp{libcom_err.a},
X@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
Xinstalled for use; @samp{com_err.3} and @samp{compile_et.1} can also be
Xinstalled as manual pages.
X
XPotential problems:
X
X@itemize @bullet
X
X@item Use of @code{strcasecmp}, a routine provided in BSD for
Xcase-insensitive string comparisons.  If an equivalent routine is
Xavailable, you can modify @code{CFLAGS} in the makefile to define
X@code{strcasecmp} to the name of that routine.
X
X@item Compilers that defined @code{__STDC__} without providing the header
Xfile @code{<stdarg.h>}.  One such example is Metaware's High ``C''
Xcompiler, as provided at Project Athena on the IBM RT/PC workstation; if
X@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
Xavailable, and therefore @code{<varargs.h>} must be used.  If the symbol
X@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
Xbe used.
X
X@item If your linker rejects symbols that are simultaneously defined in two
Xlibrary files, edit @samp{Makefile} to remove @samp{perror.c} from the
Xlibrary.  This file contains a version of @var{perror(3)} which calls
X@code{com_err} instead of calling @code{write} directly.
X
X@end itemize
X
XAs I do not have access to non-BSD systems, there are probably
Xbugs present that may interfere with building or using this package on
Xother systems.  If they are reported to me, they can probably be fixed for
Xthe next version.
X
X@section Bug Reports
X
XPlease send any comments or bug reports to the principal author: Ken
XRaeburn, @t{Raeburn@@Athena.MIT.EDU}.
X
X@section Acknowledgements
X
XI would like to thank: Bill Sommerfeld, for his help with some of this
Xdocumentation, and catching some of the bugs the first time around;
XHoneywell Information Systems, for not killing off the @emph{Multics}
Xoperating system before I had an opportunity to use it; Honeywell's
Xcustomers, who persuaded them not to do so, for a while; Ted Anderson of
XCMU, for catching some problems before version 1.2 left the nest; Stan
XZanarotti and several others of MIT's Student Information Processing Board,
Xfor getting us started with ``discuss,'' for which this package was
Xoriginally written; and everyone I've talked into --- I mean, asked to read
Xthis document and the ``man'' pages.
X
X@bye
END_OF_FILE
echo shar: 1 control character may be missing from \"'com_err.texinfo'\"
if test 21738 -ne `wc -c <'com_err.texinfo'`; then
    echo shar: \"'com_err.texinfo'\" unpacked with wrong size!
fi
# end of 'com_err.texinfo'
fi
if test -f 'texinfo.tex.2' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'texinfo.tex.2'\"
else
echo shar: Extracting \"'texinfo.tex.2'\" \(15978 characters\)
sed "s/^X//" >'texinfo.tex.2' <<'END_OF_FILE'
X\def\quotation{\begingroup\inENV %This group ends at the end of the @quotation body
X{\parskip=0pt  % because we will skip by \parskip too, later
X\aboveenvbreak}%
X\singlespace
X\parindent=0pt
X\def\Equotation{\par\endgroup\afterenvbreak}%
X\advance \rightskip by \lispnarrowing 
X\advance \leftskip by \lispnarrowing}
X
X\message{defuns,}
X% Define formatter for defuns
X% First, allow user to change definition object font (\df) internally
X\def\setdeffont #1 {\csname DEF#1\endcsname}
X
X\newskip\defbodyindent \defbodyindent=36pt
X\newskip\defargsindent \defargsindent=50pt
X\newskip\deftypemargin \deftypemargin=12pt
X\newskip\deflastargmargin \deflastargmargin=18pt
X
X\newcount\parencount
X% define \functionparens, which makes ( and ) and & do special things.
X% \functionparens affects the group it is contained in.
X\def\activeparens{%
X\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
X\catcode`\[=\active \catcode`\]=\active}
X{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
X\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
X\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
X
X% Definitions of (, ) and & used in args for functions.
X% This is the definition of ( outside of all parentheses.
X\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
X\global\advance\parencount by 1 }
X%
X% This is the definition of ( when already inside a level of parens.
X\gdef\opnested{\char`\(\global\advance\parencount by 1 }
X%
X\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
X% also in that case restore the outer-level definition of (.
X\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
X\global\advance \parencount by -1 }
X% If we encounter &foo, then turn on ()-hacking afterwards
X\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
X%
X\gdef\normalparens{\boldbrax\let&=\ampnr}
X} % End of definition inside \activeparens
X%% These parens (in \boldbrax) actually are a little bolder than the
X%% contained text.  This is especially needed for [ and ]
X\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
X\def\lbrb{{\tt\char`\[}} \def\rbrb{{\tt\char`\]}}
X
X% First, defname, which formats the header line itself.
X% #1 should be the function name.
X% #2 should be the type of definition, such as "Function".
X
X\def\defname #1#2{%
X\leftskip = 0in  %
X\noindent        %
X\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
X\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
X\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
X\parshape 2 0in \dimen0 \defargsindent \dimen1     %
X% Now output arg 2 ("Function" or some such)
X% ending at \deftypemargin from the right margin,
X% but stuck inside a box of width 0 so it does not interfere with linebreaking
X\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}%
X\tolerance=10000 \hbadness=10000    % Make all lines underfull and no complaints
X{\df #1}\enskip        % Generate function name
X}
X
X% Actually process the body of a definition
X% #1 should be the terminating control sequence, such as \Edefun.
X% #2 should be the "another name" control sequence, such as \defunx.
X% #3 should be the control sequence that actually processes the header,
X%    such as \defunheader.
X
X\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
X\medbreak %
X% Define the end token that this defining construct specifies
X% so that it will exit this group.
X\def#1{\endgraf\endgroup\medbreak}%
X\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
X\parindent=0in \leftskip=\defbodyindent %
X\begingroup\obeylines\activeparens\spacesplit#3}
X
X\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
X\medbreak %
X% Define the end token that this defining construct specifies
X% so that it will exit this group.
X\def#1{\endgraf\endgroup\medbreak}%
X\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
X\parindent=0in \leftskip=\defbodyindent %
X\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
X
X% Split up #2 at the first space token.
X% call #1 with two arguments:
X%  the first is all of #2 before the space token,
X%  the second is all of #2 after that space token.
X% If #2 contains no space token, all of it is passed as the first arg
X% and the second is passed as empty.
X
X{\obeylines
X\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
X\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
X\ifx\relax #3%
X#1{#2}{}\else #1{#2}{#3#4}\fi}}
X
X% So much for the things common to all kinds of definitions.
X
X% Define @defun.
X
X% First, define the processing that is wanted for arguments of \defun
X% Use this to expand the args and terminate the paragraph they make up
X
X\def\defunargs #1{\functionparens \sl #1%
X\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
X\interlinepenalty=10000
X\endgraf\vskip -\parskip \penalty 10000}
X
X% Do complete processing of one @defun or @defunx line already parsed.
X
X% @deffn Command forward-char nchars
X
X\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
X
X\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
X\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup}
X
X% @defun == @deffn Function
X
X\def\defun{\defparsebody\Edefun\defunx\defunheader}
X
X\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
X\begingroup\defname {#1}{Function}%
X\defunargs {#2}\endgroup %
X}
X
X% @defmac == @deffn Macro
X
X\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
X
X\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
X\begingroup\defname {#1}{Macro}%
X\defunargs {#2}\endgroup %
X}
X
X% @defspec == @deffn Special Form
X
X\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
X
X\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
X\begingroup\defname {#1}{Special form}%
X\defunargs {#2}\endgroup %
X}
X
X% This definition is run if you use @defunx
X% anywhere other than immediately after a @defun or @defunx.
X
X\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
X\def\defunx #1 {\errmessage{@defunx in invalid context}}
X\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
X\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
X
X% @defmethod, and so on
X
X% @defop {Funny Method} foo-class frobnicate argument
X
X\def\defop #1 {\def\defoptype{#1}%
X\defmethparsebody\Edefop\defopx\defopheader}
X
X\def\defopheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
X\begingroup\defname {#2}{\defoptype{} on #1}%
X\defunargs {#3}\endgroup %
X}
X
X% @defmethod == @defop Method
X
X\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
X
X\def\defmethodheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% entry in function index
X\begingroup\defname {#2}{Operation on #1}%
X\defunargs {#3}\endgroup %
X}
X
X% @defcv {Class Option} foo-class foo-flag
X
X\def\defcv #1 {\def\defcvtype{#1}%
X\defmethparsebody\Edefcv\defcvx\defcvheader}
X
X\def\defcvarheader #1#2#3{%
X\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
X\begingroup\defname {#2}{\defcvtype of #1}%
X\defvarargs {#3}\endgroup %
X}
X
X% @defivar == @defcv {Instance Variable}
X
X\def\defivar{\defmethparsebody\Edefivar\defivarx\defivarheader}
X
X\def\defivarheader #1#2#3{%
X\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
X\begingroup\defname {#2}{Instance variable of #1}%
X\defvarargs {#3}\endgroup %
X}
X
X% These definitions are run if you use @defmethodx, etc.,
X% anywhere other than immediately after a @defmethod, etc.
X
X\def\defopx #1 {\errmessage{@defopx in invalid context}}
X\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
X\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
X\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
X
X% Now @defvar
X
X% First, define the processing that is wanted for arguments of @defvar.
X% This is actually simple: just print them in roman.
X% This must expand the args and terminate the paragraph they make up
X\def\defvarargs #1{\normalparens #1%
X\interlinepenalty=10000
X\endgraf\vskip -\parskip \penalty 10000}
X
X% @defvr Counter foo-count
X
X\def\defvr{\defmethparsebody\Edefvr\defvrx\defvrheader}
X
X\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
X\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
X
X% @defvar == @defvr Variable
X
X\def\defvar{\defparsebody\Edefvar\defvarx\defvarheader}
X
X\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
X\begingroup\defname {#1}{Variable}%
X\defvarargs {#2}\endgroup %
X}
X
X% @defopt == @defvr {User Option}
X
X\def\defopt{\defparsebody\Edefopt\defoptx\defoptheader}
X
X\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
X\begingroup\defname {#1}{User Option}%
X\defvarargs {#2}\endgroup %
X}
X
X% This definition is run if you use @defvarx
X% anywhere other than immediately after a @defvar or @defvarx.
X
X\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
X\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
X\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
X
X% Now define @deftp
X% Args are printed in bold, a slight difference from @defvar.
X
X\def\deftpargs #1{\bf \defvarargs{#1}}
X
X% @deftp Class window height width ...
X
X\def\deftp{\defmethparsebody\Edeftp\deftpx\deftpheader}
X
X\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
X\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
X
X% This definition is run if you use @deftpx, etc
X% anywhere other than immediately after a @deftp, etc.
X
X\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
X
X\message{cross reference,}
X% Define cross-reference macros
X\newwrite \auxfile
X
X% \setref{foo} defines a cross-reference point named foo.
X
X\def\setref#1{%
X\dosetq{#1-pg}{Ypagenumber}%
X\dosetq{#1-snt}{Ysectionnumberandtype}}
X
X\def\unnumbsetref#1{%
X\dosetq{#1-pg}{Ypagenumber}%
X\dosetq{#1-snt}{Ynothing}}
X
X% \xref and \pxref generate cross references to specified points.
X
X\def\pxref #1{see \xrefX [#1,,,,,,,]}
X\def\xref #1{See \xrefX [#1,,,,,,,]}
X\def\xrefX [#1,#2,#3,#4,#5,#6]{%
X\setbox1=\hbox{\i{\losespace#5{}}}%
X\setbox0=\hbox{\losespace#3{}}%
X\ifdim \wd0 =0pt \setbox0=\hbox{\losespace#1{}}\fi%
X\ifdim \wd1 >0pt%
Xsection \unhbox0{} in \unhbox1%
X\else%
X\refx{#1-snt} [\unhbox0], page\tie \refx{#1-pg}%
X\fi }
X
X% \dosetq is the interface for calls from other macros
X
X\def\dosetq #1#2{{\let\folio=0%
X\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
X\next}}
X
X% \internalsetq {foo}{page} expands into CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
X% When the aux file is read, ' is the escape character
X
X\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
X
X% Things to be expanded by \internalsetq
X
X\def\Ypagenumber{\folio}
X
X\def\Ynothing{}
X
X\def\Ysectionnumberandtype{%
X\ifnum\secno=0 chapter\xreftie\the\chapno %
X\else \ifnum \subsecno=0 section\xreftie\the\chapno.\the\secno %
X\else \ifnum \subsubsecno=0 %
Xsection\xreftie\the\chapno.\the\secno.\the\subsecno %
X\else %
Xsection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
X\fi \fi \fi }
X
X\gdef\xreftie{'tie}
X
X% Define @refx to reference a specific cross-reference string.
X
X\def\refx#1{%
X{%
X\expandafter\ifx\csname X#1\endcsname\relax
X% If not defined, say something at least.
X\expandafter\gdef\csname X#1\endcsname {$<$undefined$>$}%
X\message {WARNING: Cross-reference "#1" used but not yet defined}%
X\message {}%
X\fi %
X\csname X#1\endcsname %It's defined, so just use it.
X}}
X
X% Read the last existing aux file, if any.  No error if none exists.
X
X% This is the macro invoked by entries in the aux file.
X\def\xrdef #1#2{
X{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
X
X{
X\catcode `\^^@=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\^^C=\other
X\catcode `\^^D=\other
X\catcode `\^^E=\other
X\catcode `\^^F=\other
X\catcode `\^^G=\other
X\catcode `\^^H=\other
X\catcode `\=\other
X\catcode `\^^L=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\=\other
X\catcode `\^^[=\other
X\catcode `\^^\=\other
X\catcode `\^^]=\other
X\catcode `\^^^=\other
X\catcode `\^^_=\other
X\catcode `\@=\other
X\catcode `\^=\other
X\catcode `\~=\other
X\catcode `\[=\other
X\catcode `\]=\other
X\catcode`\"=\other
X\catcode`\_=\other
X\catcode`\|=\other
X\catcode`\<=\other
X\catcode`\>=\other
X\catcode `\$=\other
X\catcode `\#=\other
X\catcode `\&=\other
X
X% the aux file uses ' as the escape.
X% Turn off \ as an escape so we do not lose on
X% entries which were dumped with control sequences in their names.
X% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
X% Reference to such entries still does not work the way one would wish,
X% but at least they do not bomb out when the aux file is read in.
X
X\catcode `\{=1 \catcode `\}=2
X\catcode `\%=\other
X\catcode `\'=0
X\catcode `\\=\other
X
X'openin 1 'jobname.aux
X'ifeof 1 'else 'closein 1 'input 'jobname.aux
X'fi
X}
X
X% Open the new aux file.  Tex will close it automatically at exit.
X
X\openout \auxfile=\jobname.aux
X
X% Footnotes.
X
X\newcount \footnoteno
X
X\def\supereject{\par\penalty -20000\footnoteno =0 }
X
X\let\ptexfootnote=\footnote
X
X{\catcode `\@=11
X\gdef\footnote{\global\advance \footnoteno by \@ne
X\edef\thisfootno{$^{\the\footnoteno}$}%
X\let\@sf\empty
X\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
X\thisfootno\@sf\parsearg\footnotezzz}
X
X\gdef\footnotezzz #1{\insert\footins{
X\interlinepenalty\interfootnotelinepenalty
X\splittopskip\ht\strutbox % top baseline for broken footnotes
X\splitmaxdepth\dp\strutbox \floatingpenalty\@MM
X\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
X\footstrut\hang\textindent{\thisfootno}#1\strut}}
X
X}%end \catcode `\@=11
X
X% End of control word definitions.
X
X\message{and turning on texinfo input format.}
X
X\newindex{cp}
X\newcodeindex{fn}
X\newcodeindex{vr}
X\newcodeindex{tp}
X\newcodeindex{ky}
X\newcodeindex{pg}
X
X% Set some numeric style parameters, for 8.5 x 11 format.
X
X\hsize = 6.5in
X\parindent 15pt
X\parskip 18pt plus 1pt
X\baselineskip 15pt
X\advance\topskip by 1.2cm
X
X% Prevent underfull vbox error messages.
X\vbadness=10000
X
X% Use @smallbook to reset parameters for 7x9.5 format
X\def\smallbook{
X\global\lispnarrowing = 0.3in
X\global\baselineskip 12pt
X\global\parskip 3pt plus 1pt
X\global\hsize = 5in
X\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
X\global\vsize=7.5in
X\global\tolerance=700
X\global\hfuzz=1pt
X
X\global\pagewidth=\hsize
X\global\pageheight=\vsize
X\global\font\ninett=cmtt9
X
X\global\let\smalllisp=\smalllispx
X\global\let\smallexample=\smalllispx
X\global\def\Esmallexample{\Esmalllisp}
X}
X
X%% For a final copy, take out the rectangles
X%% that mark overfull boxes (in case you have decided
X%% that the text looks ok even though it passes the margin).
X\def\finalout{\overfullrule=0pt}
X
X% Turn off all special characters except @
X% (and those which the user can use as if they were ordinary)
X% Define certain chars to be always in tt font.
X
X\catcode`\"=\active
X\def\activedoublequote{{\tt \char '042}}
X\let"=\activedoublequote
X\catcode`\~=\active
X\def~{{\tt \char '176}}
X\chardef\hat=`\^
X\catcode`\^=\active
X\def^{{\tt \hat}}
X\catcode`\_=\active
X\def_{{\tt \char '137}}
X\catcode`\|=\active
X\def|{{\tt \char '174}}
X\chardef \less=`\<
X\catcode`\<=\active
X\def<{{\tt \less}}
X\chardef \gtr=`\>
X\catcode`\>=\active
X\def>{{\tt \gtr}}
X
X\catcode`\@=0
X
X% \rawbackslashxx output one backslash character in current font
X{\catcode`\\=\other
X@gdef@rawbackslashxx{\}}
X
X% \rawbackslash redefines \ as input to do \rawbackslashxx.
X{\catcode`\\=\active
X@gdef@rawbackslash{@let\=@rawbackslashxx }}
X
X% \normalbackslash outputs one backslash in fixed width font.
X\def\normalbackslash{{\tt\rawbackslashxx}}
X
X% Say @foo, not \foo, in error messages.
X\escapechar=`\@
X
X%% These look ok in all fonts, so just make them not special.  The @rm below
X%% makes sure that the current font starts out as the newly loaded cmr10
X\catcode`\$=\other \catcode`\%=\other \catcode`\&=\other \catcode`\#=\other
X
X\catcode 17=0   @c Define control-q
X\catcode`\\=\active
X@let\=@normalbackslash
X
X@textfonts
X@rm
END_OF_FILE
echo shar: 15 control characters may be missing from \"'texinfo.tex.2'\"
if test 15978 -ne `wc -c <'texinfo.tex.2'`; then
    echo shar: \"'texinfo.tex.2'\" unpacked with wrong size!
fi
# end of 'texinfo.tex.2'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.