home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1435
< prev
next >
Wrap
Internet Message Format
|
1990-12-28
|
55KB
From: istvan@hhb.UUCP (Istvan Mohos)
Newsgroups: alt.sources
Subject: Subject: ILIB Unix Toolkit in C
Message-ID: <551@hhb.UUCP>
Date: 8 Jun 90 20:55:13 GMT
---- Cut Here and unpack ----
#!/bin/sh
# This is part 05 of a multipart archive
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= iex/untab.c ==============
echo "x - extracting iex/untab.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > iex/untab.c &&
X#ifdef NEVER
X/bin/cc -O -DIMANFMT -I../i $0 ../i/ilib.a -o $BIN/untab
Xexit 0
X#endif
X
X/* for each tab, substitute spaces until next tabstop,
X delete trailing blanks
X*/
X#include "ilib.h"
X#define SPACE 32
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X char **file;
X int tstop;
X int tcount;
X
X if (argc < 3 || (tstop = atoi (argv[1])) < 1)
X fprintf(stderr, "Usage: %s tabstopwidth files\n%s", argv[0],
X "Spacefill each tab to next tabstop, delete trailing blanks\n"),
X exit(1);
X
X for (file = &argv[2]; !NULCHARP (*file); file++) {
X tcount = untab(tstop, *file);
X if (idamage (tcount))
X fprintf (stderr, "%s %s\n%s", ierbuf, *file,
X "file damage probable ... aborting\n\n"), exit (1);
X if (tcount < 0)
X fprintf (stderr, "%s %s\n", ierbuf, *file);
X else if (tcount)
X printf("%s - %d\n", *file, tcount);
X }
X
X exit(0);
X}
X
Xint
Xuntab (tstop, file)
Xint tstop;
Xchar *file;
X{
X FILE *fopen(), *fp;
X char *realloc();
X char linebuf[BUFSIZ];
X char *lineptr, *endline;
X char *buffer, *bufptr, *tmp;
X int insiz, newsiz;
X int tcount = 0;
X int togo, lpos, fill;
X
X /* read file into buffer --- no file damage on error */
XQ if ((insiz = iread(file, &buffer)) < 0)
X return (ierflag);
X
X /* count number of tabs */
X for (bufptr = buffer + insiz; --bufptr >= buffer;)
X if (*bufptr == '\t')
X ++tcount;
X
X /* assuming maximum expansion of each tab, resize buffer */
X newsiz = insiz + tcount * (tstop - 1);
X if (newsiz != insiz) {
X tmp = buffer;
X if ((buffer = realloc (tmp, (unsigned)newsiz)) == NULL) {
X free (tmp);
X return (ierror ("while requesting expansion space"));
X }
X }
X
X /* reread file line-by-line, paste changes into buffer */
X if ((fp = fopen (file, "r")) == NULL)
X return (ierror ("while rereading line-by-line"));
X
X for (bufptr = buffer; !NULCHARP (fgets (linebuf, BUFSIZ, fp));) {
X
X /* eliminate trailing white space in linebuf */
X endline = linebuf + strlen (linebuf) - 1;
X while (WHITE (*endline))
X --endline;
X
X /* expand tabs: if tstop == 4, lpos can be 0,1,2,3; tabs become
X 4,3,2,1 spaces respectively: tstop == lpos + togo
X */
X lpos = 0;
X for (lineptr = linebuf; lineptr <= endline; lineptr++) {
X if (*lineptr == '\t') {
X togo = tstop - lpos;
X for (DOUNCOUN (togo, fill); *bufptr++ = SPACE);
X lpos = 0;
X }
X else {
X *bufptr++ = *lineptr;
X if (++lpos == tstop)
X lpos = 0;
X }
X }
X *bufptr++ = '\n';
X }
X
X fclose (fp);
X
X /* replace file with buffer contents --- error may destroy file */
XQ if (iwrite (file, buffer, bufptr) < bufptr-buffer) {
X free (buffer);
X return (ierflag);
X }
X
X free(buffer);
X return (tcount);
X}
SHAR_EOF
$TOUCH -am 0605075390 iex/untab.c &&
chmod 0755 iex/untab.c ||
echo "restore of iex/untab.c failed"
set `wc -c iex/untab.c`;Wc_c=$1
if test "$Wc_c" != "2579"; then
echo original size 2579, current size $Wc_c
fi
# ============= iex/up.c ==============
echo "x - extracting iex/up.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > iex/up.c &&
X#ifdef NEVER
X/bin/cc -O -DIMANFMT -I../i $0 ../i/ilib.a -o $BIN/up
X(/bin/rm -f $BIN/down)
Xln $BIN/up $BIN/down
Xexit 0
X#endif
X
X/* toupper/tolower entire files, in place */
X#include "ilib.h"
X#define DOWN 312
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X char *fbuf, *fend;
X char **file = &argv[1];
X int fsiz;
X int down = (ihasharg (argv[0], '/') == DOWN);
XQ static int (*cmd[])() = {iupper, ilower};
X
X if (argc < 2 )
X fprintf(stderr, "Usage: up|down files\n"), exit(0);
X
X for (; !NULCHARP (*file); file++, free (fbuf)) {
X if ((fsiz = iread (*file, &fbuf)) < 0)
X fprintf (stderr, "%s\n", ierbuf), exit (1);
X fend = fbuf + fsiz;
XQ (*cmd[down])(fbuf, fend);
X if (iwrite (*file, fbuf, fend) != fsiz)
X fprintf (stderr, "%s\n", ierbuf), exit (1);
X }
X exit(0);
X}
SHAR_EOF
$TOUCH -am 0605075390 iex/up.c &&
chmod 0755 iex/up.c ||
echo "restore of iex/up.c failed"
set `wc -c iex/up.c`;Wc_c=$1
if test "$Wc_c" != "780"; then
echo original size 780, current size $Wc_c
fi
# ============= iex/which.c ==============
echo "x - extracting iex/which.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > iex/which.c &&
X#ifdef NEVER
X/bin/cc -O -DIMANFMT -I../i $0 ../i/ilib.a -o $BIN/which
Xexit 0
X#endif
X
X/* tell if a file is readable/writable/executable/present in $PATH */
X#include "ilib.h"
X
Xmain (argc, argv)
Xchar *argv[];
Xint argc;
X{
X char buf[IONEK]; /* interactive input buffer */
X char *tokret;
X char **opt = &argv[1]; /* command line options */
X int interactive = 0;
X int access = X_OK; /* default permission */
X int optchar;
X
X if (argc < 2)
Xopterr:
X fprintf(stderr,
X"\nUsage: %s [-m r|w|f] -|file...\n%s%s%s%s%s%s\n", argv[0],
X"\tFind full path of each 'file' if it is contained in $PATH and is:\n",
X"\t-m r readable by user executing the command\n",
X"\t-m w writeable by user executing the command\n",
X"\t-m f present (irregardless of its permissions)\n",
X"\t executable (no mode option specified on the command line)\n",
X"\t- acquire file names interactively\n"), exit(0);
X
X while ((optchar = iopt (&opt)))
X switch (optchar) {
X case 'm':
X if (**opt == 'r')
X access = R_OK;
X else if (**opt == 'w')
X access = W_OK;
X else
X access = F_OK;
X break;
X case '-':
X interactive = 1;
X break;
X default:
X goto opterr;
X }
X
X if (interactive)
X while (gets (buf) != NULL)
XQ if ((tokret = iwhich (buf, access)) != NULL)
X puts (tokret);
X else
X strcat (buf, " not found"), puts (buf);
X else
X for (; !NULCHARP (*opt); opt++)
XQ if ((tokret = iwhich (*opt, access)) != NULL)
X puts (tokret);
X else
X printf ("%s not found\n", *opt);
X exit(0);
X}
SHAR_EOF
$TOUCH -am 0605075390 iex/which.c &&
chmod 0755 iex/which.c ||
echo "restore of iex/which.c failed"
set `wc -c iex/which.c`;Wc_c=$1
if test "$Wc_c" != "1516"; then
echo original size 1516, current size $Wc_c
fi
# ============= iex/xec.c ==============
echo "x - extracting iex/xec.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > iex/xec.c &&
X#ifdef NEVER
X/bin/cc -O -DIMANFMT -I../i $0 ../i/ilib.a -o $BIN/xec
Xexit 0
X#endif
X
X/* exec a command */
X#include "ilib.h"
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X char **arg = argv + 1;
X
X if (argc < 2)
X fprintf (stderr, "Usage: %s command [arg ...]\n%s%s\n", argv[0],
X"\tconvert phonetic sequences to real characters in <arg> list of\n",
X"\<command>, then 'exec' <command> with the converted <arg> list.\n"),
X exit (1);
X
X for (++arg; !NULCHARP (*arg); arg++)
XQ ifonetic (*arg);
XQ execvp (argv[1], argv+1);
X
X /* exec failed; use ierror to get system error message */
X ierror ("");
X fprintf(stderr, "%sduring execvp of '%s'\n", ierbuf, argv[1]);
X exit (1);
X}
SHAR_EOF
$TOUCH -am 0605075390 iex/xec.c &&
chmod 0755 iex/xec.c ||
echo "restore of iex/xec.c failed"
set `wc -c iex/xec.c`;Wc_c=$1
if test "$Wc_c" != "672"; then
echo original size 672, current size $Wc_c
fi
# ============= iex/iexmake ==============
echo "x - extracting iex/iexmake (Text)"
sed 's/^X//' << 'SHAR_EOF' > iex/iexmake &&
X#
Xforeach file (*.c)
X./$file
Xend
SHAR_EOF
$TOUCH -am 0529183990 iex/iexmake &&
chmod 0755 iex/iexmake ||
echo "restore of iex/iexmake failed"
set `wc -c iex/iexmake`;Wc_c=$1
if test "$Wc_c" != "33"; then
echo original size 33, current size $Wc_c
fi
# ============= iman/driver.tex ==============
if test ! -d 'iman'; then
echo "x - creating directory iman"
mkdir 'iman'
fi
echo "x - extracting iman/driver.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/driver.tex &&
X\input man
X\def\date{June, 1990}
X\def\vers{Version 1.0}
X\def\mansection{ILIB (3i)}
X
X\count0=-1
X\input ifunlines
X\input ifunclist
X\input iexamplist
X
X\count0=1
X\input i % may 10
X\input ialntok % may 10
X\input ibcmp %
X\input iblank %
X\input ibreakl %
X\input icopy %
X\input icount %
X\input icue %
X\input idate %
X\input idump %
X\input iego %
X\input ierror %
X\input iexpect %
X\input ifamily %
X\input ifilter %
X\input ifonetic %
X\input ifrombit % may 24
X\input ihash %
X\input ihms %
X\input iinput %
X\input iline %
X\input ilist % may 10
X\input ilower %
X\input imatch %
X\input imode %
X\input inest %
X\input ioctal %
X\input iopt %
X\input iread %
X\input irotate %
X\input iround %
X\input isearch %
X\input isort %
X\input istripcom %
X\input iswap %
X\input itok % may 11
X\input iuniq %
X\input iwhich %
X\input iwrite %
X
X\bye
SHAR_EOF
$TOUCH -am 0608095290 iman/driver.tex &&
chmod 0644 iman/driver.tex ||
echo "restore of iman/driver.tex failed"
set `wc -c iman/driver.tex`;Wc_c=$1
if test "$Wc_c" != "1018"; then
echo original size 1018, current size $Wc_c
fi
# ============= iman/i.tex ==============
echo "x - extracting iman/i.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/i.tex &&
X% XREF ilib
X
X\def\name{INTRO}
X\def\IT{{\bb ilib.a}}
X
X\S{INTRODUCTION}
XProgrammers with some years of experience realize that the
Xexcellent mechanism, the very robustness of ``standard I/O''
Xcreates its own programming {\myit gravity well\/} that is
Xdifficult to defy, and nearly impossible to escape.
XTwo pillars of \stio\ are the ``{\myit null terminated strings\/}''
Xand the terminal discipline of ``{\myit line buffering\/}''.
X\L
XThe idea of null terminated strings
Xenables the system to delimit character sequences
Xbetween their start address in memory and the first zero byte
Xencountered when reading the contents of byte addresses incrementally
Xfrom the start address. An unavoidable side effect of using
Xnull terminated strings is the appearance of a ``blind spot'' in
Xrecognizing the zero byte (ASCII NUL). Even the ubiquitous
X{\myit vi\/} editor---able to manipulate every ASCII
Xvalue between 1 and 127---can only report the
Xnumber of encountered NUL bytes on its {\myit ex\/} command line.
X\L
XLine buffering allows
Xediting a command or a line of input before transmitting the text
Xto a process; and encourages Unix tools to keep process size small
Xby managing only a single line of potentially huge amounts of
Xdata at any given time. The drawback of line buffering is
Xthe tools' reduced ability to process line-terminating {\myit newline\/}
Xcharacters (ASCII LF) and the total inability to handle text split
Xbetween adjacent lines. A related problem is the preponderance of
Xtools structured as a {\myit filter\/}, reading input from the terminal
X(instead of directly from a file), and writing output to the terminal
X(instead of directly to a file). This of course would create an
Xunholy mess on the interactive terminal screen, and could never work
Xsave for the {\myit redirection\/} mechanism which ``fools the system''
Xinto accepting a {\myit file\/} as ``terminal input'' and another
X{\myit file\/} as
X``output from the terminal'', and keeps the screen uncluttered.
XWhat is not so obvious is that using the same file for both input and
Xoutput would garbage the text of that file the same way concurrent
Xscreen I/O would trash the screen, and is disallowed by the system.
X\L
XIn a typical situation,
Xshould one wish to transform the text in twelve
Xdistinct files according to the same rules using the
X{\myit sed\/} text editor, the limitations inherent in the
X{\myit filter\/} structure necessitate that twelve new files be
Xcreated first to contain the respective transformed copies of the
Xoriginal files. The new files are then made to displace the
Xoriginal files in twelve separate processes!
XInterestingly, such un-automated tedium raises eyebrows of beginning
XUnix users only. The wise already know why things {\bb have to be}
Xthe way they are, and don't use {\myit sed\/} to edit twelve files
Xat once.
X\L
XThe author (who enjoys taking an opposing point of view) compiled
Xthis collection of C routines as an aid in combatting the yoke
Xof \stio. Just as mathematicians overload the ``senseless'' meaning
Xof {\myit irrational\/} to describe
Xnumbers that can not be expressed as a {\myit ratio\/} of integers,
XILIB functions are perceived to be {\myit irrational\/} because
Xthey oppose the
X{\myit rationale\/} supporting the standard C library and \stio.
XHence the {\bb i} as the name of the library and as the leading
Xcharacter of each of the function names.
X\L
XFrom an implementational perspective,
Xthe \IT\ archive is simply an extension to
Xthe standard library's string function
Xset, favoring data manipulation within
Xlarge internal character lists in order to facilitate
Xin-place, direct file transformation.
XThe majority of functions archived in \IT\ directly alter text in
Xinternal ``buffers'' passed from the calling function. The
Xcaller passes the lowest address of the buffer as the pointer
X{\myit start\/}, and the address of the byte
Ximmediately beyond the highest address of the buffer as the
Xpointer {\myit end\/}.
XThe implicit buffer size (the difference of the two addresses)
Xallows \IT\
Xfunctions to ignore or bypass notions of ``null terminated strings''
Xand handle ASCII values 0~through~127 in an equal manner.
XString size restrictions also disappear (or expand rather, to the
Xcount expressed by the system's largest positive {\myit int\/}).
X\L
XAll ILIB functions with {\myit start, end\/} parameters test against
X{\myit (char *)NULL\/} passed for {\myit start\/}, and report an
Xerror through ILIB's error function {\myit ierror()\/}.
XZero-length buffers may be passed without penalty; however the
Xcalled function is not obliged to process an empty buffer,
Xbeyond recognizing that the buffer is empty and returning zero or
XNULL.
XCallers that do not know the precise size of the buffer
Xmay pass {\myit (char *)NULL\/} as {\myit end\/}, or
Xmay first call the \IT\ function
X{\myit inull~(start)\/}.
XEither of these methods results in an attempt to find the
Xend of the buffer by reading it until the first zero byte.
XObviously, in these cases the buffer data will not include
XNUL bytes.
X\L
XBecause \IT\ functions perceive individual files as single strings,
Xprograms written with them can attempt
Xto escape stream-oriented Unix I/O and transform
Xfiles in-place instead. Most programs listed
Xin this manual directly alter file contents.
XTechnical concerns of direct file transformation are detailed
Xin the description of the {\myit mung\/} example
Xlisted along with the
Xmanual pages of the {\myit ierror()\/} function.
X\L
XAll function names archived under \IT\ begin with {\myit i\/}.
XRelated functionalities are collectively discussed in a
Xchapter titled by the name of the main function variant.
XChapters are in alphabetical order of title.
XSome functions, in spite of being behaviorally or
Xstructurally non-orthogonal to typical
X\IT\ constituents, gained a firm foothold in \IT\ because of their
Xusefulness. In selecting functions for inclusion, practicality
Xwas more of a concern than ILIB's ``purity''.
XThe functions
X{\myit iego()\/}, {\myit ihash()\/},
X{\myit imonth()\/}, {\myit iinput()\/} and {\myit iwhich()\/}
Xfor example,
Xparse environment variables delimited by null bytes, or
Xother strings whose length and range of byte values is implicit in
Xthe standard data they contain.
XThese functions operate on null terminated strings.
XSome \IT\ functions such as {\myit icount()\/}, {\myit igroup()\/},
X{\myit ihms()\/}, {\myit iopt()\/}, {\myit itok()\/},
X{\myit iuniq()\/} are ``dynamic'': they
Xmaintain primitive internal
Xstate machines. Such functions expect an initializing call, a
Xnumber of subsequent operational calls, and in most cases,
Xa single terminal call. To utilize
Xparallel instances of concurrent state machines (for example two
X{\myit icount()\/} machines for counting two
Xseparate sets of data simultaneously), clones of the function
Xwith changed function names
X(from {\myit icount() to icounta()\/})
Xshould be added to \IT.
X
X\S{MAKING ILIB}
XTo create \IT, the Unix {\myit make}
Xcommand should be executed in the directory containing the C source
Xfor the individual functions. This directory
Xis named {\myit i\/} in various example programs of this manual.
XThe directory also contains the file dependency list used by
X{\myit make\/}, in {\myit makefile\/}. In the BSD environment,
Xtype {\myit make\/} on the
Xcommand line to compile the ILIB source and to archive
Xthe individual {\myit .o\/} files as \IT.
XWhen compiling under System~V, the command line should contain
X\smallskip
X\I{\mytt make -DREALUNIX}
X\smallskip
Xto guide the preprocessor to
Xthe appropriate {\myit include files\/}, and to allow the
Xcompile-time resolution of minor incompatibilities between the
Xtwo systems.
X\L
X\IT\ is a Unix library; no provisions were made for porting to other
Xoperating systems.
XIn particular, the use of the ASCII character set is assumed, precluding
Xoperation with EBCDIC or other character arrangements.
XSystem calls are used in a transparent manner
Xbetween the System~V and Berkeley versions; some system calls
Xmay not port to other operating systems.
X
X\S{COMPILING WITH ILIB}
XTo access functions in the library, the compiler should link with
X\IT. User code should instruct the preprocessor to
X{\myit\#include~''ilib.h''\/}, containing
Xfunction declarations and constant definitions. The error routine
X{\myit ierror()\/} through which \IT\ functions report failures, also
Xdefines storage
Xfor the global {\myit ierbuf\/} string, and the
Xinteger {\myit ierflag\/}.
X\L
XSimilarly to when making
XILIB, any user code (even the example programs)
Xcompiled under System~V should define
X{\myit REALUNIX\/}
Xat compile time, to guide the preprocessor to
Xthe appropriate {\myit include files\/}.
X
X\S{FORMAT OF THE MANUAL}
XThis manual began as {\myit man pages\/} formatted as input for the
XUnix {\myit troff~-man\/} command. In spite of being renown and a
Xstandard, both the {\myit troff\/} program and the {\myit man\/}
Xformatting macros proved to be inflexible and generally an
Xencumbrance, hindering the visual precision of the descriptions,
Xand producing second-rate output.
X({\myit The soapbox, please...\/})
XThe perseverance of old standards is an unfortunate phenomenon;
Xrevolutionary, new tools find it impossible to take foothold
Xbecause of the fear of not being backward compatible with the
X``lowest common denominator'' represented by the
Xpedestrian forerunners.
X\L
XThe manual has been re-written under \TeX. The general format of
Xthe Unix {\myit man pages\/} was retained. Technical phrases,
Xfile names, function names, shell commands embedded in the manual
Xtext are in {\myit italics\/}.
XThe name of the currently described manual entry is
Xin {\bb bold}. Distinct command lines and program segments are in
X{\mytt typewriter font}.
XReferences to single key strokes and sometimes to
Xcharacter combinations are clarified by
Xsurrounding the character or the string with a \dx{rectangular border}.
X
X\S{EXAMPLE PROGRAMS}
XIn an attempt to shield readers from
Xincomplete, malformed and mis-printed example text, this manual
Xwaives a degree of visual uniformity and topical cohesion,
Xin favor of listing complete, standalone (and hopefully useful)
XC programs. The entire text of each example program is assumed to
Xreside in a single file. Since a full reproduction of program
Xtext may still
Xleave out crucial compiling and linking information, but a
Xseparate {\myit Makefile\/}
Xfor each example program would further segment the
Xmanual besides being an overkill, the simple expedient of
Xprepending example programs with their own compilation script
Xis utilized throughout this manual. It is assumed that the
X{\myit .c\/} file containing the text would be made executable;
Xand by typing the name of the file the user would execute
Xthe command script in order to compile and install the object.
X\L
XThe command structure of most example programs has been kept
Xsimple, but extendible. The goal was to provide small and
Xuncomplicated tools, and to encourage the user to upgrade the
Xexample text by adding more command line options or developing
Xalternate functionalities.
X\L
XThe command scripts listed in the manual assume compilation in the
XBerkeley environment.
XUnder System~V
Xthe {\myit -DREALUNIX\/} definition should be inserted into
Xeach compilation script. If the text of the example programs is
Xon-line, the entire set could be changed with a single
X{\myit mung\/} command ({\myit mung\/} should be made first).
XThe compiler will look for ILIB include files
X(principally for {\myit ilib.h\/}) in {\myit ../i\/}
Xand will attempt to link with {\myit ../i/ilib.a\/}.
X\L
XExample programs are in typewriter font. The text is
Xnot known to contain undocumented,
Xembedded non-printing characters, except
Xambient white space. Programs of {\myit filter\/} structure
X(reading from \stin\ or from a file, and writing to \stout)
Xwith no mandatory command line arguments
Xwill wait for input if the command name is the only word on the
Xcommand line. All other
Xprograms print a ``usage'' message to
X\stout\ and terminate without error if the program name
Xis given solo. The ``on-error'' syntax dump
Xprovides an immediate and obvious means of reviewing command
Xline particulars, with no chance of causing accidental damage
Xto files. In the absence of such review the user can infer the
Xfilter structure, and there is no potential for file damage.
X\L
XLines of program
Xlistings that contain calls to the illustrated ILIB functions
Xor that are essential in
Xthe context of the example are prepended with an arrow.
XIn order that the manual may directly include ``live'' program
Xlistings (using \TeX's {\mytt\bsl\myit input\/} construct),
Xthe arrows seen in the manual were
Xdirectly installed in the live text of the example program,
Xeach as a capital letter \key{Q}
Xin the leftmost column of a program line. The {\myit ilib.h\/}
Xinclude file makes a small concession to the manual format, with the
Xpreprocessor statements:
X\smallskip
X\I{\mytt\#ifdef\ \ IMANFMT}
X
X\I{\mytt\#define\ Q}
X
X\I{\mytt\#endif}
X\smallskip
XEach example program utilizes the construct by
Xdefining {\myit IMANFMT\/} in its
Xcompilation script, making leading \key{Q} tokens in the
XC code transparent to the compiler. At the same time
Xthe examples avoid using the capital \key{Q} for variable names,
Xdefinitions or in text strings, since any occurrence of \key{Q}
Xin the program listings would get converted to arrows by the
Xmacros that control the format of the manual.
X
X\S{CROSS REFERENCE OF PROGRAM EXAMPLES}
XThe first column of {\bb Table~3.} gives the names of
Xcomplete programs used in this manual as
Xexamples. Alternate names ({\myit aliases\/}) of a program are
Xprinted in plain font, true names of programs are in boldface.
XThe last column of each line shows the
Xmanual entry that describes and lists the text of the
Xexample program.
X
X\S{AN EXAMPLE EXAMPLE PROGRAM}
XThe following listing
Xillustrates the compile script merged with the C code, and the use of
Xthe preprocessor's {\myit \#include\/} construct for prepending the
X{\myit ilib.h\/} file to the program text.
XThe example program's name is {\bb q}, and its
Xpurpose is the automatic channeling (queuing) of data redirected from
X\stout, to temporary files.
XOn the command line, {\bb q} simply precedes the full command
Xwhose output is to be collected in a temporary file, for example:
X\smallskip
X\I{\mytt q sort -n unsorted\_file}
X\smallskip
XIn this invokation, {\bb q} {\myit exec\/}s the {\myit sort\/} command,
Xcollects the output in a file, and prints the name of the sorted
Xfile to \stout:
X\smallskip
X\I{\mytt /tmp/qtmp01478}
X\L
XThe file is created in the {\myit /tmp\/} directory. The file name
Xbegins with {\myit qtmp\/}, followed by the {\myit user~ID\/}
X(right justified and zero filled to four bytes). The last digit
Xof the name
Xrepresents a counter counting down from 9 to 0 then restarting back at
X9: the program assumes that a user never needs more than ten
Xconcurrently active temporary files. The loop provides a self-limiting
Xmechanism, automatically
Xoverriding the oldest of the user's ten temporary files
Xwith the new temporary data. To explicitly clear {\myit /tmp\/}
Xof these temporary files, the command name {\bb q} is used without
Xtrailing arguments (making this the only example
Xthat produces results with a solo token on its command line).
X\L
XUsing {\bb q} is most convenient for collecting data written to
X\stout, for further transformation by a non-filter command.
XThe Unix {\myit diff\/} is an example of a non-filter command.
XTo {\myit diff\/} two unsorted lists, the normal sequence
Xof commands would be:
X\smallskip
X\I{\mytt sort list1 > sorted\_list1}
X\I{\mytt sort list2 > sorted\_list2}
X\I{\mytt diff sorted\_list1 sorted\_list2}
X\L
XThis sequence can be
Xsimplified by queuing up the intermediate
X{\myit sort\/} outputs directly (quotes in the
Xfollowing command are {\myit back quotes\/}):
X\smallskip
X\I{\mytt diff \ `q sort list1` \ `q sort list2`}
X\L
XMore complex command strings are the norm when using {\bb q}.
XIf the token string {\bb q} is to execute contains \key{\pip}
X(pipe) or \key{\les} \key{\gre} (redirection)
Xtokens, the command should be enclosed in quotes, otherwise
Xthe shell will only pass the command fragment on the left side
Xof the pipe/redirection to {\bb q}:
X\smallskip
X\I{\mytt diff \ `q "grep '\car T' list1 | sort"` \ \ `q sort list2`}
X\smallskip
XIn this altered version of the above example, the first temporary file
Xwill contain the sorted list of only those lines of {\myit list1\/}
Xthat began with capital T.
X\L
XIn the program listing
Xthe first four lines comprise the prepended script.
XWhen executing this script, the first line will appear to the shell
Xto be a comment. The second line is the shell command for compiling
Xthe C code. The third line ends the script.
XBecasuse {\myit NEVER\/} is intentionally left undefined, the
Xpreprocessor skips the second and third lines, and the compiler
Xnever sees the shell commands.
X\L
XAdditionally,
Xthe compile-script contains the {\myit -DIMANFMT\/} definition that
Xwill render capital \key{Q} tokens of the program transparent to the
Xcompiler, while producing an arrow ($\longrightarrow$) in the listing
Xof the program. The script also contains the {\myit -I../i\/} path
Xthat lets the preprocessor find {\myit ilib.h\/} in its (assumed)
Xdirectory {\myit ../i\/} given relative to the current
Xdirectory containing the executable {\bb q.c}.
XThe {\bb q.c} program calls the {\myit ifonetic()\/} function
Xfrom {\bb ilib.a} in order to resolve ``phonetic control sequences''
X(described under the {\myit ifonetic()\/} manual entry).
XTo do this, the program has to link with {\bb ilib.a}, whose full path
X{\myit ../i/ilib.a\/} is also a part of the script,
X\L
XThe first task of the {\bb q} process is to produce a name
Xtemplate containing the target path {\myit /tmp\/}, the
Xconstant string {\myit qtmp\/} and the user's {\myit uid\/},
Xending with an extra {\myit counter\/} byte whose value can vary
Xbetween the ASCII '0' and '9'. If there were no command
Xline arguments, {\bb q} removes any existing files that match the
Xtemplate. Otherwise, if {\myit /tmp\/} does not yet contain all
Xten template variants, the new file created will end with the highest
Xunused counter byte. If all ten file name variants already exist,
Xthe ``oldest'' (least recently modified) is recycled, losing its
Xprevious data. All command line arguments that followed {\bb q}
Xare then concatenated into a space-separated list of tokens, and
Xthe {\myit system()\/} command executes the new string, redirecting
Xits \stout\ output to the selected {\myit qtmp\/} file. The
Xfull pathname of the {\myit qtmp\/} file is echoed to {\bb q}'s
X\stout.
X
X\S{q.c PROGRAM TEXT}
X\listing{../iex/q.c}
X\eject
SHAR_EOF
$TOUCH -am 0601084990 iman/i.tex &&
chmod 0644 iman/i.tex ||
echo "restore of iman/i.tex failed"
set `wc -c iman/i.tex`;Wc_c=$1
if test "$Wc_c" != "18670"; then
echo original size 18670, current size $Wc_c
fi
# ============= iman/ialntok.tex ==============
echo "x - extracting iman/ialntok.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ialntok.tex &&
X% XREF ialntok ianytok ictok
X
X\def\name{IALNTOK}
X\def\IT{{\bb ialntok()}}
X
X\S{NAME}
X{\bb ialntok} --- copy first alphanumeric token into word buffer
X
X{\bb ianytok} --- copy first token of source into word buffer
X
X{\bb ictok} --- copy first C token of source into word buffer
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xchar *
Xialntok (start, end, wbuf)
Xchar *start;
Xchar *end;
Xchar *wbuf;
X\L
Xchar *
Xianytok (start, end, wbuf)
Xchar *start;
Xchar *end;
Xchar *wbuf;
X\L
Xchar *
Xictok (start, end, wbuf)
Xchar *start;
Xchar *end;
Xchar *wbuf;
X}
X
X\S{DESCRIPTION}
XPrograms operating on text streams inevitably
Xorganize bytes into groups of
Xprinting characters or {\myit tokens\/}. Text is then handled
Xas successive tokens separated by non-printing
X{\myit white space\/} characters,
Xor made distinct by other token-forming rules. The \IT\ functions
Xrecognize and isolate the ``next token'' from {\myit start\/}.
X\L
XA pointer is advanced from {\myit start\/} to the first printing
Xcharacter in the stream. This is the beginning of the token. A
Xsecond pointer is advanced to the byte just past the token. The
Xthree functions use different character sets for mapping
Xprinting characters as part of the recognized token.
X\L
XEither of the functions return the address of
Xthe byte just past the token in the original stream.
X(This address may be {\myit end\/}, if no trailing spaces followed
Xa single token in the stream.) To get a ``next token''
X(to strip out a sequence of tokens from a stream), the caller
Xneed merely to assign the returned address as the new {\myit start\/}
Xpoint.
X\L
XThe text stream containing the token is not disturbed during parsing;
Xthe token is
Xcopied into a small buffer supplied by the caller via the pointer
X{\myit wbuf\/}, and is null terminated in {\myit wbuf\/}.
XThe caller passes a
X{\myit wbuf\/} of
Xsufficient size to hold the maximum expected token plus the
Xfinal NUL byte; for
X{\bb ictok()} a minimum of {\myit IHALFK\/} (512 bytes) is
Xrecommended.
X\L
X{\bb ianytok()} considers any printing character a legitimate member of
Xthe token byte string. The token ends when the next byte is a space,
Xa NUL byte, a ``control character'' (including {\myit newline, tab,\/}
Xetc.), or the end of the buffer
X(pointed to by {\myit end\/}). Thus, the token may contain punctuation
Xmarks, hyphenation, math symbols and special printing characters.
X\L
X\IT\ creates multi-byte tokens from alphanumeric characters only, using
Xthe 26 (upper or lower case) characters of the alphabet plus the
Xdigits 0~--~9.
XThe token ends when the next byte is a space, a non-alphanumeric
Xcharacter,
Xa NUL byte, a ``control character'', or the end of the buffer
X(pointed to by {\myit end\/}).
XIf a printing character which is recognized as the beginning
Xof a token is itself not alphanumeric, this character is interpreted
Xas a single-byte token terminating with the next byte.
X\L
X{\bb ictok()} is similar to \IT, except that
X{\bb ictok()} in the C tradition, moves
Xunderscore\key{\und} and dollar\key{\$} characters
Xinto the alphanumeric set from which
Xto build multi-byte aggregate tokens. Furthermore,
Xthe token-forming rules under
X{\bb ictok()} permit multi-byte tokens formed of adjacent
Xnon-alphanumeric printing characters, if the token thus created is a
Xvalid token in the C language. The following
Xnon-alphanumeric aggregates are recognized:
X\L
X{\obeylines
XCharacter constants
X\smallskip
X{\mytt\dx{\bsl <CR>}\ \twokey{\bsl "}\ \twokey{\bsl '}\ \dx{\bsl <octal>}\ \twokey{\bsl \bsl}\ \twokey{\bsl b}\ \twokey{\bsl f}\ \twokey{\bsl n}\ \twokey{\bsl r}\ \twokey{\bsl t}\ \twokey{\bsl v}}
X\L
XC operators
X\smallskip
X{\mytt\twokey{!=}\ \twokey{\%=}\ \twokey{\&\&}\ \twokey{\&=}\ \twokey{*=}\ \twokey{++}\ \twokey{+=}\ \twokey{--}\ \twokey{-=}\ \twokey{->}\ \twokey{/=}\ \twokey{<<}\ \dx{<<=}\ \twokey{<=}
X\smallskip
X\twokey{==}\ \twokey{>=}\ \twokey{>>}\ \twokey{>>=}\ \twokey{\cir =}\ \twokey{|=}\ \twokey{||}}
X\L
XArchaic operators
X\smallskip
X{\mytt\twokey{=*}\ \twokey{=+}\ \twokey{=-}}
X\L
XDecimal point as a part of decimal digit strings, comment delimiters
X\smallskip
X{\mytt \dx{\lsq<digits>\rsq.\lsq<digits>\rsq}\ \twokey{/*}\ \twokey{*/}}
X\smallskip
X}
X\L
XAdditionally, strings that begin with a \key{"}\ or \key{'}\
Xcharacter, force
X{\bb ictok()} to include all following bytes of the string as part of
Xthe currently evaluated token, up to and including the next
Xnot-escaped \key{"}\ or \key{'}\ byte, respectively.
XIf a matching quote character is not found by the 511th byte, parsing
Xstops, and ``{\myit runaway double quote\/}'' or
X``{\myit runaway single quote\/}'' is written into {\myit wbuf\/}
Xinstead. Parsing can then continue from the 512th byte, or the
Xcurrent 512-byte stretch of the buffer can be reexamined to
Xanalyze the failure.
X\L
X{\bb ictok()} makes no special arrangements for preprocessor syntax:
X{\myit \#include\/} for example, is seen as two separate tokens
X\key{\#}\ and \dx{\mytt include}.
X\L
XIf no token has been found on encountering {\myit end\/}, a NULL pointer
Xis returned as a sentinel. In this case, {\myit wbuf\/} is left
Xintact, potentially still
Xcontaining the token found during a previous call.
XNULL is also returned
X(immediately after a call to {\myit ierror()\/})
Xif {\myit start\/} points to NULL.
X
X\S{SEE ALSO}
X{\myit itok, iexpect\/}.
X
X\S{rewrap EXAMPLE PROGRAM}
XThe {\bb rewrap} program is a simple text formatter, producing output
Xsimilar to
Xthe Unix {\myit fold\/} or {\myit fmt\/} commands, but reorganizing
Xand changing the
Xoriginal file directly instead of filtering input to \stout.
X{\bb rewrap} demonstrates a method of in-place file transformation
Xusing a temporary target file instead of internal buffers.
XThe source is read
Xline-by-line; its tokens are extracted using
X{\bb anytok()} and are queued in an intermediate buffer,
Xseparated from the previous token by a space (two spaces if the
Xprevious token ended with a period). When the addition of
Xthe next token would bring the buffer length over
Xthe command-given limit, {\bb rewrap} appends the
Xbuffer text to the temporary file created in
X{\myit /tmp\/}, then restarts the queue with the token that would have
Xcaused the buffer overflow.
X\L
XThus, the original words are re-listed so that all new
Xlines contain the maximum number of complete words; and no
Xline exceeds the specified line width.
XBlank lines of the original text
X(lines not containing tokens)
Xsignal a new paragraph: the blank line causes an immediate flush of
Xthe queue, and the output of a linefeed.
XAt the end of the tokenizing process, the original file is removed,
Xand the target file is moved into its place.
XThe {\bb rewrap} algorithm preserves the indentation
X(from the left margin) of the old text.
XAs an example, the file {\myit quote\/}, containing
X\L
X\I{\listing{stanquote.old}}
X\L
Xcould be re-formatted as 76-column lines with the command:
X\L
X\I{\mytt rewrap 76 quote}
X\medskip
X\I{\listing{stanquote.new}}
X\L
XInstead of using {\myit fopen()\/} to gain access to the source and
Xtarget files, {\bb rewrap} calls {\myit freopen()\/}, reusing the
Xotherwise idle file pointers \stin\ and \stout.
XApart from a better use of
Xresources, this would permit the use of the more convenient
X{\myit gets(), puts()\/} calls instead of
X{\myit fgets(), fputs()\/}, although {\bb rewrap}
Xstill calls {\myit fgets()\/} because the second parameter
X(the maximum allowed line size) of this
Xfunction is a built-in
Xsafeguard against buffer overflow. Because the \stout\ stream is
Xautomatically buffered by the operating system (not written until
Xit accummulates {\myit BUFSIZ\/} bytes)
X{\bb rewrap} must explicitly flush \stout\ to
Xcomplete partial output to the temporary file.
X
X\S{rewrap.c PROGRAM TEXT}
X\listing{../iex/rewrap.c}
X\eject
SHAR_EOF
$TOUCH -am 0531155190 iman/ialntok.tex &&
chmod 0644 iman/ialntok.tex ||
echo "restore of iman/ialntok.tex failed"
set `wc -c iman/ialntok.tex`;Wc_c=$1
if test "$Wc_c" != "7693"; then
echo original size 7693, current size $Wc_c
fi
# ============= iman/ibcmp.tex ==============
echo "x - extracting iman/ibcmp.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ibcmp.tex &&
X% XREF ibcmp ibcopy ilast
X
X\def\name{IBCMP}
X\def\IT{{\bb ibcmp()}}
X
X\S{NAME}
X{\bb ibcmp} --- compare two byte strings
X
X{\bb ibcopy} --- copy bytes from one place to another
X
X{\bb ilast} --- find last occurrence of character in a string
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xibcmp (s1, s2, bytes)
Xchar *s1;
Xchar *s2;
Xint bytes;
X\L
Xvoid
Xibcopy (tobuf, frombuf, bytes)
Xchar *tobuf;
Xchar *frombuf;
Xint bytes;
X\L
Xchar *
Xilast (ptr, c)
Xchar *ptr;
Xchar c;
X}
X
X\S{DESCRIPTION}
XFrom the caller's point of view,
Xonly the names are different between System~V's {\myit memcmp()\/}
Xand the Berkeley {\myit bcmp()\/} functions. Both compare a number
Xof bytes beginning at {\myit s1\/} against the same number of bytes
Xbeginning at {\myit s2\/}, and return the difference of the byte
Xvalues at the first byte mismatch (subtracting the
X{\myit s2\/} byte from the {\myit s1\/} byte).
X{\bb ibcmp()} is a {\myit macro\/} defined in {\myit ilib.h\/},
Xmapping to {\myit memcmp()\/} or
X{\myit bcmp()\/} depending on the system under which ILIB
Xwas compiled.
X\L
XThe
XSystem~V {\myit memcpy()\/} function and the
XBerkeley {\myit bcopy()\/} function both copy a number of
Xbytes from one buffer to another. In spite the
Xidentical goal, the two functions are named differently,
Xreturn different {\myit types\/}, and use source and target
Xparameters in opposite order.
X{\myit memcpy()\/} and {\myit bcopy()\/}
Xare both standard library functions.
XOptimized ``to the hilt'', they can easily run ten (or more)
Xtimes faster than implementations
Xcopying bytes in a {\myit for loop\/}
Xin {\myit user space\/}.
X{\bb ibcopy()} is a {\myit macro\/} defined in {\myit ilib.h\/},
Xmapping to {\myit memcpy()\/} if ILIB has been compiled with the
X{\myit REALUNIX\/} flag, or to BSD's {\myit bcopy()\/} otherwise.
X{\bb ibcopy()} retains {\myit memcpy\/}'s
Xtarget--source parameter order also employed by the
Xstandard string functions {\myit strcat(), strcpy(),\/} etc..
XThere are no errors.
X\L
X{\bb ilast()} is a true function,
Xbypassing the {\myit rindex()\/} versus {\myit strrchr()\/}
Xincompatibility between Unix variants,
X{\bb ilast()}
Xfinds the last occurrence of some character ``{\myit c\/}'' in the
Xnull-terminated buffer pointed to by {\myit ptr\/}, and
Xreturns a pointer to it or a pointer to NULL on failure.
XNULL is returned and {\myit ierflag\/} is set if the passed-in
X{\myit ptr\/} is itself the NULL pointer.
X\eject
SHAR_EOF
$TOUCH -am 0601085990 iman/ibcmp.tex &&
chmod 0644 iman/ibcmp.tex ||
echo "restore of iman/ibcmp.tex failed"
set `wc -c iman/ibcmp.tex`;Wc_c=$1
if test "$Wc_c" != "2388"; then
echo original size 2388, current size $Wc_c
fi
# ============= iman/iblank.tex ==============
echo "x - extracting iman/iblank.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iblank.tex &&
X% XREF iblank itran
X
X\def\name{IBLANK}
X\def\IT{{\bb iblank()}}
X
X\S{NAME}
X{\bb iblank} --- change all bytes to spaces
X
X{\bb itran} --- change one character to another everywhere in buffer
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xvoid
Xiblank (start, end)
Xchar *start;
Xchar *end;
X\L
Xint
Xitran (start, end, fromc, toc)
Xchar *start;
Xchar *end;
Xchar fromc;
Xchar toc;
X}
X
X\S{DESCRIPTION}
X\IT\ clears an internal buffer beginning at {\myit start\/} and
Xending one byte before {\myit end\/}, by changing each byte in the
Xbuffer to the {\myit space\/} character (ASCII 32). The function is
Xemployed to ``white out'' comment fields in text,
Xso subsequent parsing would encounter meaningful tokens only.
XThe user's text is typically pre-scanned
Xto locate comments (perhaps using the
X{\myit inest()\/} function); the {\myit start\/} and {\myit end\/}
Xaddress of each comment are then passed to \IT.
X\L
XThe more selective {\bb itran()} function searches the passed buffer
Xfor {\myit fromc\/} characters; converting each
X{\myit fromc\/} value to {\myit toc\/}.
X{\bb itran()} returns the count of converted characters.
X\L
X\IT\ does not report errors.
X{\bb itran()} calls {\myit ierror()\/} if {\myit (char *)NULL\/} is
Xpassed as {\myit start\/}.
X\L
X\S{SEE ALSO}
XThe {\myit iswapstr()\/} or
X{\myit iswapw()\/} functions provide a means for transforming all
Xoccurrences of a single, multi-byte source token to a target token,
Xglobally
Xwithin the passed buffer. The {\myit idump()\/} function can be
Xused to print an image of the internal buffer to \stout.
X\eject
SHAR_EOF
$TOUCH -am 0601092690 iman/iblank.tex &&
chmod 0644 iman/iblank.tex ||
echo "restore of iman/iblank.tex failed"
set `wc -c iman/iblank.tex`;Wc_c=$1
if test "$Wc_c" != "1535"; then
echo original size 1535, current size $Wc_c
fi
# ============= iman/ibreakl.tex ==============
echo "x - extracting iman/ibreakl.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ibreakl.tex &&
X% XREF ibreakl
X
X\def\name{IBREAKL}
X\def\IT{{\bb ibreakl()}}
X
X\S{NAME}
X{\bb ibreakl} --- break long lines into shorter ones
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xibreakl (start, end, tobuf, header, ender, breakc, maxc, all)
Xchar *start;
Xchar *end;
Xchar *tobuf;
Xchar *header;
Xchar *ender;
Xchar *breakc;
Xint maxc;
Xint all;
X}
X
X\S{DESCRIPTION}
XThe \IT\ function serves as a
Xline manager of long lines that must be broken at
Xsome token boundaries, into shorter lines.
X\IT\ has the dubious distinction of featuring the longest
Xparameter list among the ILIB functions, as a
Xdirect result of the extraordinary computational complexity of even the
Xsimplest formatting requests.
X\L
XAn example source string that required re-formatting could be a
XBASIC {\myit data statement\/} automatically generated by a
Xprogram writer process:
X\L
X{\obeylines\mytt\leftskip=20pt
XDATA\ "this\ is\ string1",\ "this\ is\ string2",\ "this\ is\ string3",\ "this\ is\ st
Xring4",\ "this\ is\ string5",\ "this\ is\ string6",\ "this\ is\ string7",\ "this\ is
X\ string8",\ "this\ is\ string9",\ "this\ is\ string10",\ "this\ is\ string11",\ "th
Xis\ is\ string12"
X}
X\L
XHaving collected the necessary components of the statement,
Xthe program writer would need to {\myit output\/} the statement in a
Xvisually clear format:
X\L
X{\obeylines\mytt\leftskip=20pt
XDATA\ "this\ is\ string1",\ "this\ is\ string2",\ "this\ is\ string3",
X\ \ \ \ \ "this\ is\ string4",\ "this\ is\ string5",\ "this\ is\ string6",
X\ \ \ \ \ "this\ is\ string7",\ "this\ is\ string8",\ "this\ is\ string9",
X\ \ \ \ \ "this\ is\ string10",\ "this\ is\ string11",\ "this\ is\ string12"
X}
X\L
XA glance at the output suggests that the original string
Xwas broken up into lines by {\myit newline\/} characters placed
Ximmediately past {\myit commas\/}
Xonce the current target line was relatively full;
Xand that extra {\myit white space\/} (apparently four {\myit space\/}
Xcharacters) got inserted at the head of each new line to offset the
X``DATA'' token from the data strings.
X\L
XIn the \IT\ parameter list, {\myit start\/} and {\myit end\/}
Xdefine the limits of the buffer containing the source string.
XTypically to ILIB, {\myit end\/} is set to one byte {\bb past} the
Xlast byte of the source string.
XThe next parameter {\myit tobuf\/} is a pointer to the destination
Xstorage allocated or defined by the process that calls \IT,
Xthe buffer where \IT\ is to place the re-formatted result.
XThe caller must guarantee that {\myit tobuf\/} is of sufficient size
Xto contain the processed, enlarged target string, plus a terminating
XNUL byte.
X\L
X{\myit header\/} points to a string that \IT\ should prepend at
Xeach new line before adding more segments of the source string to
Xthe line. In the example above, the {\myit header\/} string
Xcontained four {\myit space\/} characters. Similarly,
Xthe string pointed to by {\myit ender\/}
Xis to be appended to each new line; in the above example {\myit ender\/}
Xconsisted of a single {\myit newline\/} character.
XBoth {\myit header\/} or {\myit ender\/} may be passed as
X{\myit (char~*) NULL\/}, suppressing prepended or trailing strings.
X\L
XThe {\myit breakc\/} pointer points to a string of un-ordered
Xcharacters comprising a
Xset of delimiters: when parsing the source string, a
X{\myit break point\/} is recognized immediately following
Xa character of the source string that matches any single character of
Xthe delimiter set.
XA {\myit break point\/} marks a spot at which the source line
Xcan be split. In the above example, the {\myit breakc\/} string
Xcontained a single {\myit comma\/} character.
X\L
X{\myit maxc\/} is the maximum permissible
Xbyte count of any newly made line, including {\myit newline\/}
Xor other non-printing characters that may already be present in the
Xsource string, and also including the newly prepended {\myit header\/}
Xand appended {\myit ender\/} strings.
X\L
XIf the last parameter
X{\myit all\/} is TRUE (non-zero), the {\myit header\/}
Xstring is prepended to each line of the result,
Xeven the first; and
X{\myit ender\/} is appended to each line of the result, even the last.
XOtherwise,
X{\myit header\/} is not prepended to the initial line of the result,
Xand
X{\myit ender\/} is not appended to the final line of the result.
X\L
XAtypically to ILIB, the {\myit header, ender, breakc\/} strings passed
Xto \IT\ are
Xassumed to be null terminated, normal C strings;
Xthe piecing-together operations utilize standard string functions
X{\myit strcat(), strcmp()\/}, and the like. There seemed to be
Xvery little utility in coding this function to accept arbitrary
Xstrings potentially containing embedded NUL bytes.
X
X\S{RETURN VALUES}
XThe {\myit int\/} returned from \IT\ is the byte length of the
Xprocessed, final string in {\myit tobuf\/}, not including the
Xterminal NUL byte. Error returns of
Xnegative {\myit sys\_nerr\/} indicate either
X\smallskip
X{\parindent=40pt
X\item{$\bullet$}
Xthat the sum of the lengths of {\myit header\/}
Xand {\myit ender\/}
Xis greater than the maximum specified line length {\myit maxc\/},
X\smallskip
X\item{$\bullet$}
Xor that \IT\ could not find a {\myit break point\/} within
Xthe evaluated source substring (such that the length of the current
Xtarget line,
Xwith {\myit header\/} and {\myit ender\/} included if appropriate,
Xdidn't exceed {\myit maxc\/} bytes)
Xat which the source string could have been broken. In this case,
X{\myit tobuf\/} may already contain partial results.
X\smallskip
X}
X\eject
SHAR_EOF
$TOUCH -am 0509104090 iman/ibreakl.tex &&
chmod 0644 iman/ibreakl.tex ||
echo "restore of iman/ibreakl.tex failed"
set `wc -c iman/ibreakl.tex`;Wc_c=$1
if test "$Wc_c" != "5408"; then
echo original size 5408, current size $Wc_c
fi
# ============= iman/icopy.tex ==============
echo "x - extracting iman/icopy.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/icopy.tex &&
X% XREF icopy
X
X\def\name{ICOPY}
X\def\IT{{\bb icopy()}}
X
X\S{NAME}
X{\bb icopy} --- copy buffer into dynamically allocated memory
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xchar *
Xicopy (start, end)
Xchar *start;
Xchar *end;
X}
X
X\S{DESCRIPTION}
X\IT\ is used to create a duplicate of an
Xinternal buffer by
Xdynamically allocating space for the new buffer, and then calling
X{\myit ibcopy()\/} to copy the source bytes.
XThe source buffer begins at {\myit start\/}, and ends
Xwith the byte before {\myit end\/}.
XA new buffer one
Xbyte greater than the size of the passed buffer,
Xis allocated by \IT;
Xthe source is copied into the new buffer, and
Xthe extra byte at the end of the new buffer is set to NUL.
X\IT\ returns a pointer to the allocated memory.
XIf the NULL pointer is passed as {\myit start\/} or if
X{\myit malloc()\/} fails, \IT\ calls {\myit ierror()\/} and
Xreturns {\myit (char~*) NULL\/}.
X\eject
SHAR_EOF
$TOUCH -am 0601094490 iman/icopy.tex &&
chmod 0644 iman/icopy.tex ||
echo "restore of iman/icopy.tex failed"
set `wc -c iman/icopy.tex`;Wc_c=$1
if test "$Wc_c" != "881"; then
echo original size 881, current size $Wc_c
fi
# ============= iman/icount.tex ==============
echo "x - extracting iman/icount.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/icount.tex &&
X% XREF icount
X
X\def\name{ICOUNT}
X\def\IT{{\bb icount()}}
X
X\S{NAME}
X{\bb icount} --- count how many times a specific parameter was passed
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xicount (type)
Xint type;
X}
X
X\S{DESCRIPTION}
X\IT\ is a dynamic function, expecting a setup call, zero or more
Xoperational calls, and a resetting final call.
XFor a simple example of a program that may use \IT,
Ximagine a routine for a robot arm programmed
Xto lift single pieces of fruit out of a basket, and having
Xrecognized the type of the fruit,
Xkeep separate counts of the apples, the oranges and the bananas.
XThe program could just increment
Xthree distinct variables when counting the fruit; but
Xif the number of types counted in parallel
Xwas large, or if the types varied from time to time,
Xa discreet subroutine would
Xbe defined to allocate and manage the array space
Xof the counters. \IT\ is such a subroutine.
X\L
XThe first call to \IT\ passes the number of array elements
Xthat \IT\ should allocate to store the count of
Xthe separate types during the following operational calls.
XIn the above example, three types
X(apples, oranges, bananas) would be counted, set up with
Xthe initializing call:
X\smallskip
X\I{\mytt icount (3);}
X\L
XThis first call returns zero unless the number of
X{\myit type\/}s requested was zero, or the array allocation failed.
XEither exception would call {\myit ierror()\/} and return negative,
Xleaving \IT\ ready for another initializing call.
X\L
XAt the end of each operational call, \IT\ returns
Xthe tally of previous calls in which the {\myit type\/} of the
Xcurrent call was passed. In the fruit example, the robot program
Xwould
X\smallskip
X{\mytt
X\I{\#define APPLE \ 0}
X\I{\#define BANANA 1}
X\I{\#define ORANGE 2}
X}
X\smallskip
Xand on encountering some ``orange orange banana apple orange apple apple
Xorange'' sequence, would call \IT\ eight times. The values
Xreturned from these calls are shown after each call as comments:
X\smallskip
X{\mytt
X\I{icount (ORANGE); /* 0 */}
X\I{icount (ORANGE); /* 1 */}
X\I{icount (BANANA); /* 0 */}
X\I{icount (APPLE); \ /* 0 */}
X\I{icount (ORANGE); /* 2 */}
X\I{icount (APPLE); \ /* 1 */}
X\I{icount (APPLE); \ /* 2 */}
X\I{icount (ORANGE); /* 3 */}
X}
X\L
XThe range of legitimate {\myit type\/}
Xvalues for operational calls is from zero through
Xone less than the array
Xsize specified in the initializing call, directly corresponding to
Xindices into the allocated array. Out-of-bound operational
Xparameters trigger
Xa negative return (via {\myit ierror()\/}) but do not affect
X\IT\ internal states.
XIn the fruit example, the call
X\smallskip
X{\mytt
X\I{\#define PASSIONFRUIT 3}
X\I{icount (PASSIONFRUIT);}
X}
X\smallskip
Xwould return the negative {\myit sys\_nerr\/}, but more APPLEs,
XBANANAs and ORANGEs could be counted immediately afterwards.
X\L
XThe terminating call passes a negative number, to reset
Xthe \IT\ state machine and to free dynamically allocated memory.
X
X\S{SEE ALSO}
X{\myit ierror, iuniq\/}.
X
X\S{distrib EXAMPLE PROGRAM}
XThe {\bb distrib\/} program is an aid in
Xanalyzing text distribution characteristics of selected strings, words,
Xor characters. Each parameter following {\bb distrib\/}
Xon the command line is an object on which statistical information is
Xsought. The program counts and
Xreports how many times each object occurred in the input. Text
Xis supplied to {\bb distrib\/} interactively, or by input redirection.
XThough the report is produced only after ``end of file'',
Xthe program reads a line at a time, so patterns spanning lines
Xcannot be discerned. For a given pattern, each byte
Xof the examined line is a starting point for a possible
Xmatch: in the string ``rococo'' the pattern ``oco'' is found twice.
X\L
XGiven an input file {\myit pi\/} containing the first hundred decimal
Xdigits of \char5, the following {\bb distrib} command would produce
Xa distribution of digits:
X\smallskip
X\I{\mytt distrib 0 1 2 3 4 5 6 7 8 9 \les \ pi}
X\medskip
X{\mytt \obeylines
X\ \ \ \ 0: 8
X\ \ \ \ 1: 8
X\ \ \ \ 2: 12
X\ \ \ \ 3: 12
X\ \ \ \ 4: 10
X\ \ \ \ 5: 8
X\ \ \ \ 6: 9
X\ \ \ \ 7: 8
X\ \ \ \ 8: 12
X\ \ \ \ 9: 13
X}
X\L
XAnother example checks that the input contains the same number of
Xleft and right curly braces, using phonetic control sequences
X(described under {\myit ifonetic()\/}) to
Xavoid the need to quote:
X\smallskip
X\I{\mytt distrib Xlcu Xrcu \les \ distrib.c}
X\L
XA third command produces an ``alphabetic character distribution list''
Xordered by increasing frequency of characters,
Xof {\myit /usr/dict/words\/} (the back-quotes execute the
X{\myit char\/} program that expands AZ and az to the full alphabet):
X\smallskip
X\I{\mytt (distrib `char AZ az` \les \ /usr/dict/words) \pip\ sort -n +1}
X\L
XFor each line of input the {\bb distrib} algorithm recomputes
Xthe string lenght of a search pattern specified, and attempts
Xto match the pattern at successive bytes of the input.
XThe line is then reexamined to find matches to the next search
Xpattern, then the next, until a search list is exhausted.
XA more efficient implementation of {\bb distrib}
Xcould --- at the expense of some
Xcode complexity --- dynamically allocate an array for storing the
Xlength of the patterns instead of repeatedly
Xcomputing them.
X
X\S{distrib.c PROGRAM TEXT}
X\listing{../iex/distrib.c}
X\eject
SHAR_EOF
$TOUCH -am 0601133090 iman/icount.tex &&
chmod 0644 iman/icount.tex ||
echo "restore of iman/icount.tex failed"
set `wc -c iman/icount.tex`;Wc_c=$1
if test "$Wc_c" != "5214"; then
echo original size 5214, current size $Wc_c
fi
echo "End of part 5, continue with part 6"
exit 0
--
Istvan Mohos
...uunet!pyrdc!pyrnj!hhb!istvan
RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
======================================================================