home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1437
< prev
next >
Wrap
Internet Message Format
|
1990-12-28
|
48KB
From: istvan@hhb.UUCP (Istvan Mohos)
Newsgroups: alt.sources
Subject: Subject: ILIB Unix Toolkit in C
Message-ID: <552@hhb.UUCP>
Date: 8 Jun 90 20:56:30 GMT
---- Cut Here and unpack ----
#!/bin/sh
# This is part 06 of a multipart archive
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= iman/icue.tex ==============
echo "x - extracting iman/icue.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/icue.tex &&
X% XREF icue inl inull
X
X\def\name{ICUE}
X\def\IT{{\bb icue()}}
X
X\S{NAME}
X
X{\bb icue} --- buffer management
X
X{\bb inl} --- return pointer to next {\myit newline\/} or NUL byte
X
X{\bb inull} --- return pointer to next NUL byte
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xvoid
Xicue (ptr)
Xchar **ptr;
X\L
Xchar *
Xinl (start)
Xchar *start;
X\L
Xchar *
Xinull (start)
Xchar *start;
X}
X
X\S{DESCRIPTION}
XBSD's {\myit sprintf()} implementation results in
X``one of those annoying gratuitous incompatibilities among UNIX
Xvariants'' (quoting the eloquently restrained
XUSENET {\myit wizard\/} Doug Gwyn).
XUnder BSD, {\myit sprintf()} returns quite uselessly the
Xsame buffer pointer that the caller passed in;
Xline~51 of Berkeley's {\myit /usr/include/stdio.h\/} is not ashamed to
Xdeclare:
X\smallskip
X\I{\mytt /* \ats(\#)stdio.h 1.2 86/10/07 SMI; from UCB 1.4 06/30/83 */}
X\I{\mytt char *sprintf(); /* too painful to do right */}
X\smallskip
XSystem~V meanwhile, returns the number of
Xcharacters written so the user's pointer at which printing began, can
Xeasily be incremented by the returned {\myit int\/} to
Xcontinue printing at the end of the previous string.
XTo achieve the same end
Xunder BSD, the pointer would have to be incremented by the
Xoffset gotten with an extra call to {\myit strlen()\/}.
X\L
XILIB's {\bb icue()} function presents an alternative method of resetting
Xthe pointer to the end of NUL terminated strings. {\bb icue()}
Xbypasses the {\myit sprintf\/} system dependency, and
Xalso works hand-in-hand with any
Xstring function that leaves a NUL byte at the end of the
Xcaller's buffer.
X\L
X{\bb icue()} is called following
X{\myit sprintf()\/} or other string function calls, and
Xautomatically advances the passed pointer {\myit ptr\/} in the
Xbuffer to the next NUL byte.
XIn order to alter the address that the pointer dereferences,
Xthe pointer should be passed to
X{\bb icue()} by its address.
X\L
X{\bb inl()} and {\bb inull()} are two other ILIB routines
Xdedicated to search for the end of NUL terminated strings.
XSimilarly to {\myit strlen()\/}, {\bb inl()} and {\bb inull()}
Xboth report the length of a string, but by returning a pointer to the
Xend of the string rather than by the count of bytes. The pointer is
Xoften more convenient than the offset.
X{\bb inl()} finds the first {\myit unescaped\/}
Xnewline or the first NUL (ASCII zero) byte
Xfrom {\myit start\/}, and returns a pointer to it.
X{\bb inull()} finds the first NUL byte
Xfrom {\myit start\/}, and returns a pointer to it.
XNeither {\bb inl()} or {\bb inull()} ``know when to stop'' unless they
Xfound the delimiters they were searching for. If the buffer does not
Xcontain the delimiter, the search will continue into restricted
Xspace and cause a {\myit core dump\/}. {\bb inull()} is marginally
Xfaster than the standard {\myit strlen()\/}. {\bb inl} pays a speed
Xpenalty for having to match
Xeither delimiter against each byte of the string.
X
X\S{isdef EXAMPLE PROGRAM}
XMost C compilers contain a number of unadvertised internal definitions.
XInternal {\myit \#define\/}s implement system debugging parameters
Xsuch as {\myit \_\_LINE\_\_, \_\_FILE\_\_,\/} as well as
Xglobal system or machine identifiers
Xsuch as {\myit unix, pyr\/} (under the Pyramid 90x mini, for
Xexample).
XOnce in a while, identifiers of a user program will result in a
Xcollision with an internal
X{\myit \#define\/}.
XTo find out beforehand whether a word belongs in the set of
Xinternally defined tokens, one could examine the string space
Xof the programs comprising the object set of {\myit cc\/} (a few
Xelements of this list are
X{\myit /lib/cpp, /lib/ccom, /lib/c2, /lib/crt0.o, /lib/libc.a\/});
Xbut often it is simpler just to write a few-line {\myit main()\/}
Xprogram that includes the word in question --- if the program
Xcompiles, the word is already defined.
X\L
XThe {\bb isdef} program automates this process: it writes a
Xtemporary C~program for testing the defined status
Xof the command line parameters; it
Xthen proceeds with compiling, executing, and finally deleting
Xthe test program. To ascertain whether a command line parameter is
Xdefined by the C~compiler, the generated test code will contain
X\smallskip
X{\obeylines \mytt \parindent=40pt
X\#ifdef\ \dx{token}
X\ \ \ \ printf\ ("\dx{token}\ is\ defined\bsl n");
X\#else
X\ \ \ \ printf\ ("\dx{token}\ not\ defined\bsl n");
X\#endif
X\smallskip}
Xfor each token supplied to {\bb isdef} as a command line parameter.
XThe {\bb isdef} process pieces the test code together in an internal
Xbuffer {\myit fbuf\/},
Xand writes the entire buffer to a temporary file in one
Xoperation. While filling the buffer, the
Xbuffer pointer {\myit ptr\/} is moved to the
Xend of the most recently installed sub-string via {\bb icue()}, and
Xthe next sub-string is printed from this point on.
X
X\S{isdef.c PROGRAM TEXT}
X\listing{../iex/isdef.c}
X
X\S{excise EXAMPLE PROGRAM}
XWhile it is ``cleaner'' to implement algorithms for in-place
Xfile transformations by bypassing \stin\ and \stout\ (reading and
Xwriting file data through specific file descriptors instead), the
X{\bb excise} example program illustrates a method using standard
Xterminal I/O. The complaint against some
X{\myit filter\/} programs in Unix is that a filter structure is
Xoften inappropriate, and forces the user to redirect output to a
Xtemporary file that must then be followed by manually moving the
Xtemporary file to replace the source file. {\bb excise} eliminates
Xthe need for this ``manual post-processing'' by doing it within
Xthe program: it creates the temporary file of the output, and
Xmoves the temporary file to replace the source file with a call to the
X{\myit system()\/} command of the standard C library.
X\L
X{\bb excise} searches
Xfor a user-specified string (a mandatory command line
Xparameter), in the text of each file given on its command line,
XHaving found the string nearest to the beginning of the
Xfile, {\bb excise} removes the {\myit newline\/} terminated
Xline that contained the string, then goes on to
Xthe next file. The ``solo minus'' option on the command line
Xforces {\bb excise} to search each file in its entirety, and to remove
Xall those lines of the file that contained the specified string.
X\L
X{\bb excise} implements the mechanics of ``removing a line'' via
Xthe \stio\ discipline. Each source file in the queue
Xis recast as \stin\ in turn, and is read a line at a time.
XEach line of input is immediately reprinted to \stout\ unless the
Xline contains the string match and is therefore to be ``removed''.
XRemoval
Xconsists of suppressing the line from being output. Similarly to
Xrenaming source files \stin, \stout\ is attached to a
Xtemporary file in {\myit /tmp\/} collecting the altered text.
XBecause \stout\ is buffered, the system is not obliged to copy
Xfragments of output to the temporary file unless it is forced to do
Xthis by a
Xcall to {\myit fflush()\/}. After this, the temporary file is made
Xto displace the source file with the {\myit mv\/} command; and then
Xthe process repeats with the next source file in the queue.
X\L
XBecause of the line-by-line processing and because
X{\myit strcmp()\/} is used for string matching, {\bb excise}
Xwill not find the specified string in any text if the
Xstring contained {\myit newline\/}
Xor NUL (ASCII zero) characters, even though
X{\myit ifonetic()\/} pre-processes the string and converts
XILIB's phonetic control sequences to non-alphanumeric values.
X
X\S{excise.c PROGRAM TEXT}
X\listing{../iex/excise.c}
X\eject
SHAR_EOF
$TOUCH -am 0605083990 iman/icue.tex &&
chmod 0644 iman/icue.tex ||
echo "restore of iman/icue.tex failed"
set `wc -c iman/icue.tex`;Wc_c=$1
if test "$Wc_c" != "7399"; then
echo original size 7399, current size $Wc_c
fi
# ============= iman/idate.tex ==============
echo "x - extracting iman/idate.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/idate.tex &&
X% XREF idate imonth itoday itohour itomin itomonth itosec itoyear
X
X\def\name{IDATE}
X\def\IT{{\bb idate()}}
X
X\S{NAME}
X{\bb idate} --- print today's date in one of four formats
X
X{\bb imonth} --- convert month name to number 1 through 12
X
X{\bb itoday} --- integer value (1 $\ldots$\ 31) of current day of month
X
X{\bb itohour} --- integer value (0 $\ldots$\ 23) of current hour of day
X
X{\bb itomin} --- integer value (0 $\ldots$\ 59) of current minute
X
X{\bb itomonth} --- integer value (1 $\ldots$\ 12) of current month
X
X{\bb itosec} --- integer value (0 $\ldots$\ 59) of current second
X
X{\bb itoyear} --- four decimal-digit value of current year
X
X\S{SYNOPSIS}
X\settabs\+{\bb mdefine SHORTUPMO} & mmm &\cr
X\+{\bb\#define SHORTMO}&\hfill{\bb0}&\kern2em{\mytt
X/* to get: Dec 23 1990 */}\cr
X\+{\bb\#define SHORTUPMO}&\hfill{\bb1}&\kern2em{\mytt
X/* to get: DEC 23 1990 */}\cr
X\+{\bb\#define LONGMO}&\hfill{\bb2}&\kern2em{\mytt
X/* to get: December 23, 1990 */}\cr
X\+{\bb\#define LONGUPMO}&\hfill{\bb3}&\kern2em{\mytt
X/* to get: DECEMBER 23, 1990 */}\cr
X\L
X{\obeylines \bb
Xchar *
Xidate (format)
Xint format;
X\L
Xint
Ximonth (ptr)
Xchar *ptr;
X\L
Xint
Xitoday (), itohour (), itomin (), itomonth (), itosec (), itoyear ();
X}
X
X\S{DESCRIPTION}
XThe \IT\ functions provide simple and convenient ``date stamping''
Xin a variety of formats other than returned by the Unix
X{\myit ctime()\/}
Xand {\myit date()\/}. All \IT\ functions except {\bb imonth()}
Xrely on an internal, ``hidden'' function {\myit \_igetdate()\/}
Xfor consulting the system clock and storing the fields of a {\myit tm\/}
Xstructure. The current time is saved at the first
X{\myit \_igetdate()\/} call of the process; subsequent calls though
Xlater in time, do not update the originally stored values.
X\L
X\IT\ returns a pointer to a null terminated ``today's date'' string in
Xone of four {\myit format\/}s. The returned string does not contain
Xa {\myit newline\/}. Error reporting is absent.
X\L
X{\bb imonth()} understands the string passed in via
X{\myit ptr\/} to describe a month between January and December
Xor between 1 and 12, and returns the {\myit int\/} value of
Xthe month (1 through 12).
XNames may contain arbitrary upper or lower case characters,
Xbut must begin with the initial 3 characters of a month
Xto be recognized.
XIf the first character of {\myit ptr\/}
Xis a digit, {\bb imonth()} uses {\myit atoi()\/} to extract the
Xnumber. If the first character is alphabetic, two more characters
Xare read, and a hash value computed from the upcased three characters
Xis used to decode the number of the month. If the number from
Xeither evaluation lies outside the 1--12 range, 0 is returned instead.
XNegative {\myit sys\_nerr\/} is returned if
X{\myit (char *)NULL\/} is passed as {\myit ptr\/},
Xor if {\myit ptr\/} dereferences a zero length
Xstring.
X\L
XThe time stamps
X{\bb
Xitoday(),
Xitohour(),
Xitomin(),
Xitomonth(),
Xitosec(),
Xitoyear()}
Xeach return the current {\myit int\/}
Xvalue of the unit that follows {\myit ito\/} in the function name.
XError reporting is absent.
X
X\S{SEE ALSO}
X{\myit ihms\/},
Xfor converting seconds to hours:minutes:seconds; and
Xto access a continually updated time stamp for timing applications.
X
X\S{stamp EXAMPLE PROGRAM}
XAlthough the date of creation of a Unix file is evident from the
Xsystem time stamp displayed in a {\myit long listing\/} of the file,
Xoccasionally it is desirable to include the date in
Xthe file name itself. A {\myit crontab entry\/} may take regular
Xsnapshots of some system resource for example; the inclusion of
Xthe date in the snapshot file names eliminates the worry of having
Xto generate
Xfile name variants, and provides a more obvious mark of the
Xtime of creation of a file. The {\bb stamp} program prints a
Xfour-character digit string of the current month/day, easily included
Xas a file name extension:
X\smallskip
X\I{\mytt df > diskspace.`stamp`}
X\smallskip
XIn this command line, {\myit back quotes\/} surround {\bb stamp};
Xthe name of the newly written file will end in a four-digit
Xextension generated by {\bb stamp}. On January 23 for example,
Xthe new file would be named {\myit diskspace.0123\/}.
X
X\S{stamp.c PROGRAM TEXT}
X\listing{../iex/stamp.c}
X\eject
SHAR_EOF
$TOUCH -am 0607093190 iman/idate.tex &&
chmod 0644 iman/idate.tex ||
echo "restore of iman/idate.tex failed"
set `wc -c iman/idate.tex`;Wc_c=$1
if test "$Wc_c" != "4167"; then
echo original size 4167, current size $Wc_c
fi
# ============= iman/idump.tex ==============
echo "x - extracting iman/idump.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/idump.tex &&
X% XREF idump
X
X\def\name{IDUMP}
X\def\IT{{\bb idump()}}
X
X\S{NAME}
X{\bb idump} --- write a buffer to \stout,
Xtranslating NUL bytes to a different ASCII value
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xvoid
Xidump (start, end, ch)
Xchar *start;
Xchar *end;
Xchar ch;
X}
X
X\S{DESCRIPTION}
XMaking repeated calls to {\myit write()\/}, \IT\
Xprints the contents of an internal buffer
Xbegininning at {\myit start\/} and ending one byte before
X{\myit end\/}, to \stout. The most useful feature of \IT\
Xis the transformation of ASCII NUL (zero) bytes
Xto a different ASCII value in the output,
Xmaking this hard-to-handle character
Xeasily visible and identifiable.
XThe internal buffer meanwhile remains intact, and
Xprocess development can continue undisturbed by the dump.
X\L
XThe target character value (to substitute for NUL bytes in the output)
Xis passed via the {\myit char~ch\/}.
XThis character itself may be NUL
X(passed as two successive single quotes or as '\bsl0'), producing
Xan exact copy of the buffer on \stout.
X\IT\ is intended mainly as a {\myit write()\/} substitute
Xduring program development,
X
X\S{nulcat EXAMPLE PROGRAM}
XThe {\bb nulcat} program described here,
Xuses \IT\ to print a file to \stout\ with NUL bytes of the
Xfile translated to \key{\ats} characters. Alternately,
X{\bb nulcat} can be a filter, using \stin\ for input.
X\L
XThe {\bb nulcat}
Xprocess terminates immediately after \IT, and so fails to take
Xadvantage of the unchanged file image still in the internal
Xbuffer. The program aims to supplement the
Xotherwise excellent non-printing character display capabilities of
Xthe {\myit vi\/} editor. {\myit vi\/} appears to have a
X``blind spot'' when faced with NUL bytes; other solutions for displaying
XNUL characters ({\myit od~-c\/}, etc.) are visually complex and
Xhard to interpret.
X\L
XCommand line syntax is typical of filters. The
Xfollowing commands give identical results:
X\smallskip
X\I{\mytt cat sourcefile \pip \ nulcat}
X\I{\mytt nulcat sourcefile}
X
X\S{nulcat.c PROGRAM TEXT}
X\listing{../iex/nulcat.c}
X\eject
SHAR_EOF
$TOUCH -am 0607094290 iman/idump.tex &&
chmod 0644 iman/idump.tex ||
echo "restore of iman/idump.tex failed"
set `wc -c iman/idump.tex`;Wc_c=$1
if test "$Wc_c" != "2013"; then
echo original size 2013, current size $Wc_c
fi
# ============= iman/iego.tex ==============
echo "x - extracting iman/iego.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iego.tex &&
X% XREF iego
X
X\def\name{IEGO}
X\def\IT{{\bb iego()}}
X
X\S{NAME}
X{\bb iego} --- put path-less, extension-less base name into word buffer
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xiego (ptr, wbuf, delim, ext)
Xchar *ptr;
Xchar *wbuf;
Xchar delim;
Xchar ext;
X}
X
X\S{DESCRIPTION}
X\IT\ examines the null terminated
X{\myit path/filename\/} pointed to by {\myit ptr\/},
Xand removes from it
Xeither the {\myit basename.extension\/} substring
X(leaving only the {\myit path\/} component
Xin the buffer passed in via {\myit wbuf\/}),
Xor removes the {\myit path\/} and {\myit extension\/} substrings
X(leaving only the {\myit basename\/} component
Xin {\myit wbuf\/}). The original string at {\myit ptr\/} is not
Xdisturbed.
X\L
XThe {\myit path\/} substring is computed as all leading bytes to
Xand including the last {\myit delim\/} character of the name;
X{\myit delim\/} is typically --- but not necessarily --- the
Xslash \key{/} character.
XThe {\myit extension\/} substring is computed as all trailing bytes
Xincluding the first occurrence of the {\myit ext\/} character,
Xfollowing the base name. The {\myit ext\/} parameter
Xis typically the dot \key{.} character.
XThe {\myit ext\/} parameter also serves to convey the choice
Xbetween generating either the {\myit path\/} or the
X{\myit basename.extension\/} targets:
XIf {\myit ext\/} is NUL (passed as {\myit (int)0\/},
Xadjacent single quotes \dx{\mytt''}\
Xor {\mytt'\bsl0'}),
Xthe null terminated {\myit path\/} is left in {\myit wbuf\/}.
XOtherwise, the null terminated {\myit basename\/} is
Xleft in {\myit wbuf\/}.
X\L
X\IT\ returns the byte length of the target string in {\myit wbuf\/}.
XNegative {\myit sys\_nerr\/} is returned if
Xaddress~0 is passed as {\myit ptr\/},
Xor if {\myit ptr\/} dereferences a zero length string.
X
X\S{ego EXAMPLE PROGRAM}
XThe {\bb ego} program provides an
Xalternative to the Unix {\myit basename\/}
Xcommand, with
Xa shorter name and an easier syntax. Three other names {\bb path},
X{\bb ext}
Xand {\bb egoext} are {\myit links\/} of {\bb ego}, meaning that
Xthe four command names are equivalent and refer to the same object.
XExecution of the object begins with an internal examination of the
Xname by which the command was invoked;
Xthe intention of the user is inferred from the selection of the command
Xname.
X\smallskip
X\I{\mytt ego file ...}
X\smallskip
Xprints the {\myit basename\/} of the command line
Xarguments. Each name is terminated with a {\myit newline\/}.
X\smallskip
X\I{\mytt ext file ...}
X\smallskip
Xprints the {\myit extension\/} part of the file names
Xgiven as command line
Xarguments, without the period character that separates an extension
Xfrom the base name. The extension itself may contain embedded or
Xtrailing periods. Each name is terminated with a {\myit newline\/}.
XSimilarly,
X\smallskip
X\I{\mytt path file ...}
X\smallskip
Xreprints the {\myit path\/}s of
Xcommand line arguments, retaining the trailing slash \key{/}.
X\smallskip
X\I{\mytt egoext file ...}
X\smallskip
Xprints the {\myit basename.extension\/} substring of each file name
Xsupplied on the command line.
X
X\S{ego.c PROGRAM TEXT}
X\listing{../iex/ego.c}
X\eject
SHAR_EOF
$TOUCH -am 0531085290 iman/iego.tex &&
chmod 0644 iman/iego.tex ||
echo "restore of iman/iego.tex failed"
set `wc -c iman/iego.tex`;Wc_c=$1
if test "$Wc_c" != "3085"; then
echo original size 3085, current size $Wc_c
fi
# ============= iman/ierror.tex ==============
echo "x - extracting iman/ierror.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ierror.tex &&
X% XREF ierror idamage ierflag ierbuf
X
X\def\name{IERROR}
X\def\IT{{\bb ierror()}}
X
X\S{NAME}
X{\bb ierror} --- report an ILIB error or a system error
X
X{\bb idamage} --- return TRUE on possible file damage
X
X\S{SYNOPSIS}
X{\obeylines \bb
X\#define IHALFK 512
X\L
Xchar ierbuf[IHALFK];
Xint ierflag;
X\L
Xint
Xierror (ustr)
Xchar *ustr;
X\L
Xint
Xidamage (error)
Xint error;
X}
X
X\S{DESCRIPTION}
XThe \IT\ function is similar to the standard
X{\myit perror()\/}.
XILIB functions report internal failures exclusively through \IT.
XIn addition to errors during
Xsystem calls encountered within ILIB function blocks,
XILIB functions also use \IT\ to flag improper
Xparameters passed to ILIB functions that prevent normal
Xfunction execution.
X\L
XImproper parameters are typically zero-length strings, or
X{\myit start\/} pointers set to NULL instead of to some accessible
Xbuffer. Exhaustive testing of parameters would impose prohibitive
Xruntime performance penalties;
XILIB functions with {\myit start, end\/}
Xbuffer parameters are usually content to read the buffer from
X{\myit start\/} if {\myit (char *)NULL\/} is passed as
X{\myit end\/}, and assume that in these cases the caller was good
Xenough to pass
Xa null (byte) terminated string beginning at {\myit start\/}.
X\L
XIf an ILIB function makes a call to \IT\ not because of
Xsystem call failure
Xbut because the user's call to the
Xthe ILIB function
Xcontained a parameter error,
X{\myit errno\/} will be zero. In this case,
X\IT\ copies {\myit ustr\/} (or ``{\mytt Error\/}'' if
X{\myit ustr\/} is NULL)
Xinto {\bb ierbuf\/},
Xsets {\bb ierflag\/} to the negative value of the system constant
X{\myit sys\_nerr\/} (the number of error messages in
X{\myit sys\_errlist\/}), and returns this value.
X\L
XAll system calls executed by ILIB functions are tested
Xfor failing returns within the individual function blocks.
XFailing system calls
Xcause the caller ILIB function to issue a call to \IT\
Xand then to return without further processing.
XWhen called, \IT\ first examines the global
X{\myit errno\/}.
XIf {\myit errno\/} is set, an error has occurred during a previous
Xsystem call. In this case,
X\IT\ copies the {\myit sys\_errlist\/}
Xmessage indexed by {\myit errno\/}, into {\bb ierbuf\/}; appends
Xthe string ``{\mytt~---~}'' and then {\myit ustr\/}.
XIf {\myit ustr\/} is NULL, only
X{\myit sys\_errlist[errno]\/} is copied.
XNewline or white space is not added after {\myit ustr\/}. The
Xfinal {\bb ierbuf\/} message is null terminated.
XThe ILIB error flag
X{\bb ierflag\/} is assigned
Xthe negative value of {\myit errno\/} before
X\IT\ resets {\myit errno\/} to zero.
XThe {\bb ierflag\/} value is returned from the call.
X\L
XPrograms linking with ILIB may utilize \IT\ as completely distinct
Xfrom ILIB usage, for their own internal error reporting.
XThe principal benefit from this is
Xan orthogonal interpretation of errors across
Xsystem calls and user functions.
XThe \IT\ code defines
Xthe global {\bb char ierbuf[IHALFK]\/} and
X{\bb int ierflag\/} variables. The {\myit ilib.h\/} file
X{\myit \#include\/}d in the user code, declares these
Xas {\myit extern\/}.
X\L
XThe string sent to
X\IT\ from the calling ILIB function in {\myit ustr\/}
Xis a brief message noting the name of the function that recognized
Xthe error and the specific test that failed. No restrictions are
Xset for functions that call \IT\ externally to ILIB, except that
Xexcessively long
Xsystem-message/user-strings are truncated beginning at their 512th
Xcharacter in order that \IT\ can null terminate {\bb ierbuf\/}.
XBecause {\myit errno\/} is not automatically cleared by the system
Xbetween system calls, any user code that makes system calls on its
Xown (not via ILIB) and then keeps the process alive in spite of
Xa failing system call, should reset
X{\myit errno\/} on its own before subsequent calls to ILIB. This
Xwill prevent misleading error reports.
X\L
XThe {\bb idamage()\/} function makes an informed guess as to
Xwhether an error value returned by ILIB functions could have
Xbeen accompanied by file damage. A number of failing system calls
Xare benign, preventing further processing but not destroying
Xalready computed results. For example a {\myit malloc\/} error
Xsimply means that no more memory is available; existing buffer
Xcontents remain unchanged. An ``out of disk space'' error on the
Xother hand, during a {\myit write\/} could occur after a partial
Xflush of the processed buffers,
Xleaving a destroyed file image on disk. Programs that write to
Xa series of files, may be able to ignore benign errors by
Xsimply bypassing the file under whose processing the error
Xoccurred, but would
Xterminate the process when noticing apparent file damage.
X\L
XInterpreting the passed number as the negative version of a
Xsystem error constant defined in {\myit errno.h\/},
X{\bb idamage()\/} returns TRUE if the failing system call
Xhad the potential of damaging a file; and returns FALSE
Xotherwise. A {\myit -sys\_nerr\/}
Xvalue passed is assumed to be the error return from an ILIB
Xfunction failing not because of a system call error, and is
Xevaluated as having no potential for file damage.
XMore negative values, and all non-negative values are considered
Xnot in the domain of error numbers, causing FALSE returns.
X
X\S{mung EXAMPLE PROGRAM}
XThe interactive Unix interface is noted for buffering user input
Xline-by-line. Most standard tools (such as {\myit sed, grep\/})
Xthwart casual attempts at
Xstring transformations with embedded
Xline-separating {\myit newline\/} characters. The main advantage of
Xoperating on a line
Xof input at a time is that the entire input
Xcan be of unlimited length; programs aiming to transform
Xa single string can
Xallocate just enough work space to contain the
Xmaximum expected line length.
X\L
XBecause of the {\myit stream\/}
Xnature of I/O, standard transformation tools never directly
Xchange the input data. Instead, the output is generally collected
Xin a new file. If the original data is to be discarded, the user
Xwill take the extra step of moving the target file over the
Xsource file; in effect unlinking the source file and renaming the
Xtarget file with the name of the source file. This need for manually
Xreorganizing the directory tends to inhibit multiple file names
X(each requiring the same transformation) supplied as command parameters.
X\L
XThe {\bb mung\/} program finds all occurrences of the
Xstring given as the first
Xcommand line parameter, and transforms each occurrence
Xinto the string given as the second
Xcommand line parameter, in each file listed on the rest of
Xthe command line. Breaking with tradition, the files themselves
Xare transformed by the changes; each original file will be replaced
Xby its changed version without further user intervention. Both
Xthe source string and the target string may span lines; {\bb mung\/}
Xuses the easy and obvious {\myit ifonetic()\/} syntax to recognize
Xnon-printing characters specified
Xin the exchange strings.
X\L
XTrue to its name (derived from {\myit mungo\/} --- the waste of
Xmilled wool used for making cheap cloth),
X{\bb mung\/} operates in an inelegant,
Xbrute force fashion; ignoring traditional I/O blocking.
XNevertheless, its easy syntax and
Xthe convenience of arbitrary characters in the exchange strings
Xmake {\bb mung} a useful tool.
X\L
XThe following command example
Xtransforms each carriage-return/linefeed
Xline termination (endemic in files created under DOS)
Xof file1, file2 and file3, to the Unix
X``newline only'' line termination:
X\smallskip
X\I{\mytt mung \ XretXnew \ Xnew \ file1 \ file2 \ file3}
X\smallskip
XAnother example restores words broken up across consecutive lines by
Xhyphenation,
Xto whole words (at the expense of doubling the length of an
Xoccasional line), by deleting hyphen/newline pairs from
Xall files in the directory with names ending in ``text'':
X\smallskip
X\I{\mytt mung \ -Xnew \ '' \ *text}
X\smallskip
XThe two adjacent single quotes in this example indicate a zero-length
Xtarget string: occurrences of the source string are eliminated.
XZero-length strings are different from strings containing ASCII 0
X(NUL) bytes:
X\smallskip
X\I{\mytt mung \ Xnul \ '' \ *text}
X\smallskip
Xdeletes each NUL byte from *text.
X\L
XAfter updating the file, the count of
Xupdated string instances is reported to \stout, in the form
X\smallskip
X\I{\mytt file2 - 75}
X\smallskip
Xshowing that 75 instances of the source string were changed to
Xthe target string in file2.
XEach examined file is rewritten (touched) only if the source string
Xdid occur in the file; zero occurrences of the source string are
Xnot reported.
X\L
XSpecifying zero-length strings for both exchange strings, results
Xin an error message printed to \sterr. Supplying no file name
Xon the command line triggers a ``usage'' message printed to
X\sterr, summarizing command line syntax. Specifying a zero-length
Xsource string and a non-zero-length target string is interpreted
Xas a ``count~only'' option, instructing {\bb mung\/} to report
Xthe number of occurrences of the second string in each of the
Xfiles, without altering the files in any way.
XUnder this option, the count of
Xtarget string instances is reported to \stout, in the form
X\smallskip
X\I{\mytt file2: 75}
X\smallskip
Xshowing that 75 instances of the target string were encountered in
Xfile2, but file2 was not altered.
X\L
XThe main concern of designs effecting in-place file transformation
Xis the potential for damaging the file during interrupts or
Xoperating system failures. While
Xinterrupting a transform process acting on a stream
Xcannot damage the source text and may
Xat most be an inconvenience for having to restart the process,
Xa program interrupted in the midst of altering source text itself,
Xwill not be able to
Xcomplete the changes, nor could it restore the source to its original
Xcondition.
XBecause of this, the {\bb mung} process reads source text
Xinto a dynamically allocated buffer, and applies transformations
Xto the buffer image only. Afterwards,
Xthe source text is overwritten with the altered buffer text in a single
X{\myit write()\/} function call, using the maximally {\myit atomic\/}
Xoperation allowed for a user process by
Xthe multiprocessing kernel. Interrupts are guaranteed
Xto kill the process either before {\myit write()\/} or after
X{\myit write()\/} but never during {\myit write()\/}, so
Xthe file image conforms to the source text only, or to the target
Xtext only.
XBecause the system employs delayed
X{\myit write\/} operations, the buffer image will linger in
Xdynamic memory, and the disk image of the file may still get
Xcorrupted if the system crashes with the dynamic memory only
Xpartially flushed. However, unflushed crashes occur rarely.
X\L
XReading an entire file into an internal buffer has the obvious
Xadvantage of making any line boundary meaningless. The disadvantage
Xis that the file size that the program can handle is limited to
Xthe available dynamic memory. To maximize available space, the
X{\bb mung\/} program is frugal in assigning memory to anything
Xelse. The {\myit ifonetic()\/} call reuses {\myit argv[1]\/} and
X{\myit argv[2]\/} space in converting phonetic
Xcontrol sequences to true {\myit char\/}s;
Xand {\bb mung} uses just the one buffer allocated for the source text,
Xfor transforming and containing the target image as well.
XDuring the conversion, the target image
Xwill expand if the the target string is longer than the
Xsource string, but the program doesn't know the extent of the
Xexpansion unless it counts the occurrences of the source string
Xin the source text first.
XTherefore, if the target string is longer than the source string,
Xan extra parsing of the source text is necessary.
X\L
XTo be able to utilize the same transformation alogrithm regardless of
Xthe length of the exchange strings, the ``find-and-replace''
Xblock of the code proceeds from the end of the text toward the
Xbeginning. When a match to the
Xsource string is found, the source text pointer is
Xdecremented by the length of the source string, preventing
Xoverlapping pattern matching. Given the source text ``rococo''
Xfor example, the source string ``oco'' will be seen to occur only
Xonce, and if replaced with ``k'' would yield the target text
X``rock''.
X\L
XA generally overlooked
Xbenefit of in-place file transformation is that the output
Xleaves \stout\ available for status reporting, which is normally
Xdifferent from error reporting. {\bb mung} is able to flag
Xunreadable files or attempted directory writes as true errors, to
X\sterr; while summarizing the conversion count on a ``per file''
Xbasis, to \stout. It is easy to capture the summary in a pipe
Xto generate a ``total'', for example:
X\smallskip
X{\obeylines \mytt
X\ \ \ \ mung\ ''\ '\bsl listing\lcu '\ *.tex\ |\ fcat\ 2\ |\ add
X\smallskip}
XIn this command {\bb mung} counts the ``per-file''
Xoccurrences of the \dx{\mytt\bsl listing\lcu}\ token
Xin all files with the {\myit .tex\/} extension.
X(The \dx{\mytt\bsl listing\lcu}\ token is
Xdefined as a \TeX\ macro for printing this manual; and in the present
Xcontext it illustrates that the use of the phonetic control sequences
Xin specifying the {\bb mung} exchange strings is not mandatory.)
XThe second fields of the report (the actual count produced by
X{\bb mung})
Xis stripped out from the
Xoutput by {\myit fcat\/}, and is summed by {\myit add\/}.
X\L
XThe overall structure of the {\bb mung\/} program is simple.
XAfter checking and translating the command line,
Xa transform is attempted on each file of the
Xcommand line in turn: the file name is
Xpassed to the {\bb mung()\/} subroutine, and {\myit main()\/}
Xexpectantly awaits the return value. If the return is zero, the
Xfile did not contain the source string, the file has not been
Xaltered, and no reporting is done. If the return is positive, the
Xreturn
Xvalue is the number of converted strings in the file, also
Xreported to \stout.
X\L
XNegative returns signal that some error occurred, and {\myit main()\/}
Xmust now decide whether the error means potential file damage
X(in which case to notify the user and exit), or less serious trouble
X(print a warning and proceed with the next file). The {\bb mung()\/}
Xsubroutine itself relies on ILIB functions and passes
X{\bb ierflag\/} to {\myit main()\/}; but in one case it calls
X{\myit realloc()\/} directly, referring the task of building the
Xerror message after a {\myit realloc()\/} error, to \IT.
X
X\S{mung.c PROGRAM TEXT}
X\listing{../iex/mung.c}
X\eject
SHAR_EOF
$TOUCH -am 0607095490 iman/ierror.tex &&
chmod 0644 iman/ierror.tex ||
echo "restore of iman/ierror.tex failed"
set `wc -c iman/ierror.tex`;Wc_c=$1
if test "$Wc_c" != "14309"; then
echo original size 14309, current size $Wc_c
fi
# ============= iman/iexamplist.tex ==============
echo "x - extracting iman/iexamplist.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iexamplist.tex &&
X\def\name{TABLE 3}
X
X\S{Summary of Program Examples}
X{
X\settabs\+{mmmmmmmmm} &
X manage stacks of /tmp files for stdout segments, report filenames &\cr
X
X\+{\bb add}&
Xadd leading number of each line of input, print total
X&\hfill IROUND\cr
X
X\+{\bb area}&
Xarea code data base lookup
X&\hfill ISEARCH\cr
X
X\+{\bb banner}&
Xoutput command line strings in large letters
X&\hfill IFROMBIT\cr
X
X\+{\bb behead}&
Xin place, delete leading lines of files
X&\hfill IEXPECT\cr
X
X\+{\bb char}&
Xoutput space separated character lists
X&\hfill IFONETIC\cr
X
X\+{\bb cnum}&
Xcustom line numbering via command line options
X&\hfill IOPT\cr
X
X\+{\bb cweed}&
Xlist minimally spaced tokens of C text, garbage removed
X&\hfill ISTRIPCOM\cr
X
X\+{\bb defilter}&
Xreplace input file text of filter commands with their output
X&\hfill IFONETIC\cr
X
X\+{\bb distrib}&
Xcount strings in lines
X&\hfill ICOUNT\cr
X
X\+{down}&
Xtolower entire files, in place
X&\hfill ILOWER\cr
X
X\+{\bb ego}&
Xextract basename of file names
X&\hfill IEGO\cr
X
X\+{egoext}&
Xextract name.extension of file names
X&\hfill IEGO\cr
X
X\+{ext}&
Xextract extension substring of file names
X&\hfill IEGO\cr
X
X\+{\bb excise}&
Xdelete line(s) of files that contain a specified string
X&\hfill ICUE\cr
X
X\+{\bb fcat}&
Xprint fields from lines of input, concatenated by spaces
X&\hfill ITOK\cr
X
X\+{fpath}&
Xlist all files visible from \dol PATH or from given paths
X&\hfill ITOK\cr
X
X\+{\bb group}&
Xwrite alphanumerically sorted lines to \stout, in groups
X&\hfill IFAMILY\cr
X
X\+{\bb inum}&
Xinteractively specify custom line numbering sequence
X&\hfill IINPUT\cr
X
X\+{\bb isdef}&
Xfind token in list of definitions recognized by C compiler
X&\hfill ICUE\cr
X
X\+{\bb lcat}&
Xcat line {\myit N\/} or lines {\myit N\/} through {\myit N+M\/} of input to \stout
X&\hfill ILIST\cr
X
X\+{leftrunc}&
Xskipping left {\myit N\/} columns, output remaining columns of input
X&\hfill IHASH\cr
X
X\+{\bb lhash}&
Xoutput formatted sum of bytes of each line of input
X&\hfill IHASH\cr
X
X\+{\bb mung}&
Xtransform every {\myit string1\/} within files into {\myit string2\/}
X&\hfill IERROR\cr
X
X\+{\bb ncat}&
Xline number, append spooler string before each file
X&\hfill ILINE\cr
X
X\+{\bb nest}&
Xprint line-numbered list of delimiter pair contained in file
X&\hfill INEST\cr
X
X\+{nestinfo}&
Xprint nesting information for delimiter pair contained in file
X&\hfill INEST\cr
X
X\+{now}&
Xcurrent time anywhere around the world
X&\hfill ISEARCH\cr
X
X\+{\bb nulcat}&
Xwrite input to \stout, changing NUL bytes to `@'
X&\hfill IDUMP\cr
X
X\+{\bb objed}&
Xbinary file editor
X&\hfill IWRITE\cr
X
X\+{path}&
Xextract path (directory) component of file names
X&\hfill IEGO\cr
X
X\+{\bb pathfiles}&
Xprint instructions on using {\myit fpath, rpath, wpath, xpath\/}
X&\hfill ITOK\cr
X
X\+{\bb q}&
Xstack {\mytt /tmp} files for \stout\ segments, report filename
X&\hfill INTRO\cr
X
X\+{\bb rename}&
Xchange string {\myit pattern1\/} in filenames to {\myit pattern2\/}
X&\hfill IMATCH\cr
X
X\+{\bb rewrap}&
Xin place, re-list tokens of file
X&\hfill IALNTOK\cr
X
X\+{\bb rot}&
Xprint instructions on using {\myit rotl, rotol, rotor, rotr\/}
X&\hfill IROTATE\cr
X
X\+{rotl}&
Xrotate input text 90 degrees to the left (counterclockwise)
X&\hfill IROTATE\cr
X
X\+{rotol}&
Xrotate text 90 degrees to the left, and over (upside down)
X&\hfill IROTATE\cr
X
X\+{rotor}&
Xrotate text 90 degrees to the right, and over
X&\hfill IROTATE\cr
X
X\+{rotr}&
Xrotate input text 90 degrees to the right
X&\hfill IROTATE\cr
X
X\+{rpath}&
Xlist all readable files of \dol PATH or of given paths
X&\hfill ITOK\cr
X
X\+{\bb scat}&
Xreprint input from line containing {\myit string1\/}, stop at line of {\myit string2\/}
X&\hfill ILIST\cr
X
X\+{\bb stamp}&
Xprint four-digit stamp of current month/day
X&\hfill IDATE\cr
X
X\+{\bb trunc}&
Xreprint lines of input only until given column number N
X&\hfill IHASH\cr
X
X\+{uhash}&
Xoutput formatted sum of upcased bytes of each line of input
X&\hfill IHASH\cr
X
X\+{\bb unlink}&
Xbrute force file remove
X&\hfill IMODE\cr
X
X\+{\bb untab}&
Xfor each tab, substitute spaces until next {\myit tabstop\/}
X&\hfill IREAD\cr
X
X\+{\bb up}&
Xtoupper entire files, in place
X&\hfill ILOWER\cr
X
X\+{\bb which}&
Xlocate a file
X&\hfill IWHICH\cr
X
X\+{wpath}&
Xlist all writable files of \dol PATH or of given paths
X&\hfill ITOK\cr
X
X\+{\bb xec}&
Xexec a command
X&\hfill IFONETIC\cr
X
X\+{xpath}&
Xlist all executable files of \dol PATH or of given paths
X&\hfill ITOK\cr
X}
X\eject
SHAR_EOF
$TOUCH -am 0601145590 iman/iexamplist.tex &&
chmod 0644 iman/iexamplist.tex ||
echo "restore of iman/iexamplist.tex failed"
set `wc -c iman/iexamplist.tex`;Wc_c=$1
if test "$Wc_c" != "4338"; then
echo original size 4338, current size $Wc_c
fi
# ============= iman/iexpect.tex ==============
echo "x - extracting iman/iexpect.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iexpect.tex &&
X% XREF iexpect inextl istartl
X
X\def\name{IEXPECT}
X\def\IT{{\bb iexpect()}}
X
X\S{NAME}
X\hangindent=.75in \hangafter=1
X{\bb iexpect} --- confirm or deny that the first token in the nearest
Xline that does not begin with {\myit skiptok\/}, is a match for the
Xexpected {\myit word\/}
X\smallskip
X{\bb inextl} --- return location of first token in the line after the
Xcurrent line
X
X{\bb istartl} --- find nearest line that starts with a given
X{\myit word\/}
X
X\S{SYNOPSIS}
X\settabs\+{\bb mdefine SHORTUPMO} &\cr
X\+{\bb\#define IANYTOK}&\hfill{\bb0}\cr
X\+{\bb\#define IALNTOK}&\hfill{\bb1}\cr
X\+{\bb\#define ICTOK}&\hfill{\bb2}\cr
X\L
X{\obeylines \bb
Xint
Xiexpect (start, end, word, skiptok, toktype)
Xchar *start;
Xchar *end;
Xchar *word;
Xchar *skiptok;
Xint toktype;
X\L
Xchar *
Xinextl (start, end, skiptok)
Xchar *start;
Xchar *end;
Xchar *skiptok;
X\L
Xchar *
Xistartl (start, end, word)
Xchar *start;
Xchar *end;
Xchar *word;
X}
X
X\S{DESCRIPTION}
XBoth \IT\ and {\bb istartl()} are
Xused to match a chosen {\myit word\/} against the first token in
Xsuccessive lines in an internal buffer.
XDuring \IT, the search ends at the first token of the buffer
Xwhether or not the token matches the expected
X{\myit word\/}, except when the token matches {\myit skiptok\/}.
XIn this case, the entire line that began with {\myit skiptok\/} is
Xbypassed, and token-recognition continues from the next line.
X\L
XDuring {\bb istartl()}
Xthe beginning of each successive line is examined for a
Xmatch to {\myit word\/};
Xif there are no tokens in the currently examined
Xline or if the first token in the
Xcurrent line does not match the specified {\myit word\/},
Xthe line is skipped
Xand the search resumes at the start of the next line.
X\L
X{\bb inextl()} simply advances a pointer
Xpast the first {\myit newline\/},
Xand then parks it at the next printing (non-white)
Xcharacter. If this printing character leads a string that exactly
Xmatches {\myit skiptok\/}, the pointer is again advanced past the line,
Xand the process repeats in the next line, until a line is found that
Xdoesn't begin with
Xthe {\myit skiptok\/} substring.
X\L
XThe searched buffer begins at
X{\myit start\/} and ends one byte before {\myit end\/}.
XThe passed reference {\myit word\/}
Xand {\myit skiptok\/}
Xare both character strings each terminated by a NUL byte.
XIf {\myit word\/} is {\myit (char~*)NULL\/}
Xor if it is a zero-length string,
X\IT\ does no processing and returns~0.
X{\bb istartl()\/} on the other hand returns
X{\myit (char~*)NULL\/} and reports the incident via {\myit ierror()\/}.
XA {\myit (char~*)NULL\/} or a
Xzero-length string for
X{\myit skiptok\/} may be passed to \IT\ or to {\bb inextl()}
Xin a normal manner.
X\L
XThe {\myit toktype\/} parameter passed to \IT\ specifies token-forming
Xrules and character sets for tokens.
XThe ILIB {\myit include file ''ilib.h''\/} defines high level
Xconstants IANYTOK, IALNTOK, and ICTOK as possible values for
X{\myit toktype\/}.
XOther values default to IANYTOK.
XDepending on the value chosen, \IT\ calls on one of the ILIB
Xfunctions {\myit ianytok(), ialntok()\/}, or
X{\myit ictok()\/} for constructing the token.
X{\myit ianytok()\/} considers any successive
Xprinting character a legitimate member
Xof the token byte string.
X{\myit ialntok()\/} creates multi-byte tokens from
Xalphanumeric characters, or single-byte tokens from non-alphanumeric
Xprinting characters.
X{\myit ictok()\/} expands the alphanumeric character set used
Xby
X{\myit ialntok()\/} with the underscore \key{\und} and dollar
X\key{\$} characters, and also recognizes C operators and
Xcharacter constants as separate tokens.
X\L
XInteger values returned by \IT\ may be positive, negative, or zero.
XA returned zero informs the caller that the buffer contained no
Xtokens whatsoever (or that \IT\ has received an illegal {\myit word\/}
Xparameter).
XA positive return indicates that the first valid token was a match
Xfor {\myit word\/}; the integer value is the
Xoffset from {\myit start\/},
Xof the {\myit newline\/} character at the end of the line
Xin which the expected {\myit word\/} was found.
XA negative return indicates that the first valid token did not match
X{\myit word\/};
Xthe absolute value of the return is the offset from {\myit start\/},
Xof the {\myit newline\/} character at the end of the line
Xin which the valid non-matching token was found.
X\L
X\IT\ is most useful for parsing past ``comment lines'' beginning
Xwith a single-byte {\myit comment delimiter\/} and ending with
X{\myit newline\/}, or for bypassing line-starting
X``format specifications'' (for example the leading periods of
X{\myit nroff\/}).
XTo skip records with fixed {\myit header\/} keywords in various
Xfixed format text data files, {\bb istartl()} is more convenient.
X\L
X{\bb istartl()} uses a simpler algorithm for matching tokens against
Xthe specified {\myit word\/}. The byte count of {\myit word\/} is
Xstored in a temporary variable {\myit length\/}.
XThe parser is advanced to the first
Xprinting character of the examined line; a comparison
X(using the standard {\myit strncmp()\/} function)
Xis performed at this point
Xof {\myit word\/} against a {\myit length\/} number of successive
Xbytes of the line.
XThis implies that {\myit word\/} can be an arbitrary aggregate of
Xnon-NUL ASCII bytes, potentially a cluster of words; but must begin
Xwith a {\myit printing character\/}.
XAlso, a line in the buffer will match {\myit word\/} even if
X{\myit word\/} is a substring of a longer line-starting token:
Xa line beginning with ``plaintiff'' will match the {\myit word\/}
X``plain'', for example.
X\L
X{\bb istartl()} does not perform a final
Xcomparison if the length of {\myit word\/} would mean
Xcomparing past the end of the buffer.
X{\bb istartl()} returns a pointer dereferencing the leading token of the
Xfirst line that matched {\myit word\/}, or a pointer to NULL
Xif no match was found.
X\L
XThe returned pointer from the {\bb inextl()} function
Xsimply points to {\myit end\/} if a legal token
X(leading a {\myit printing\/} string in
Xthe next line) could not be found, but it will point
Xto NULL if the line does not end with a {\myit newline\/}
Xas {\myit end\/} is encountered.
X
X\S{SEE ALSO}
X{\myit imatch, ialntok.}
X
X\S{behead PROGRAM EXAMPLE}
XThe stark name of the {\bb behead} program aptly describes the
Xradical and irreversable changes it inflicts on the file in its
Xcommand line parameter list. {\bb behead} reads each file in turn,
Xinto an internal buffer; advances a pointer past an integral number of
Xbeginning text lines; then writes all text from the pointer until the
Xend of the buffer, back to the file (on disk). The net effect is to
Xdiscard of a number of leading text lines from each file.
X\L
XThe command name must be followed by a decimal
X{\myit number\/} or a {\myit string\/},
Xpreceding the list of files subjected to the operation. When a
X{\myit number\/} is given, it is taken to be the number of lines
Xthat should
Xbe removed from the beginning of files. The assumed line delimiter
Xis the {\myit newline\/} character. If the selected file has less
Xlines than (or has an equal number of lines to)
Xthe number of lines to be removed, the file is
Xtruncated to zero length.
X\L
XIf the command name is followed by a
X{\myit string\/} instead of a {\myit number\/},
Xthis {\myit string\/}
Xcorresponds to the {\myit word\/} parameter of a call to
X{\bb istartl()} described above. The text of each file in turn,
Xis searched to find
Xthe first line that begins (following optional {\myit white spaces\/})
Xwith an exact match to the specified {\myit string\/}. Lines of the
Xexamined file that preceded the line in which the match was found,
Xare removed. If lines of a file do not produce a match, the file
Xis left intact, and the incident triggers a warning message
Xprinted to \sterr.
X\L
XA minor drawback of the command line syntax is that a positive
Xinteger cannot be taken as a request to delete lines ending at
Xthe line that begins with the
Xdigit string of the integer:
X\smallskip
X\I{\mytt behead 15 foo}
X\smallskip
Xremoves the first 15 lines of {\myit foo\/} instead of searching
Xfor a line in {\myit foo\/} that begin with the bytes ``15''.
XA similar drawback inherent in the {\bb istartl()} process is that
Xa specified {\myit string\/} cannot begin with {\myit white space\/}.
X
X\S{behead.c PROGRAM TEXT}
X\listing{../iex/behead.c}
X\eject
SHAR_EOF
$TOUCH -am 0607103590 iman/iexpect.tex &&
chmod 0644 iman/iexpect.tex ||
echo "restore of iman/iexpect.tex failed"
set `wc -c iman/iexpect.tex`;Wc_c=$1
if test "$Wc_c" != "8261"; then
echo original size 8261, current size $Wc_c
fi
echo "End of part 6, continue with part 7"
exit 0
--
Istvan Mohos
...uunet!pyrdc!pyrnj!hhb!istvan
RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
======================================================================