home *** CD-ROM | disk | FTP | other *** search
- 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
- ======================================================================
-