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\}\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.