home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1436
< 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: <554@hhb.UUCP>
Date: 8 Jun 90 20:59:11 GMT
---- Cut Here and unpack ----
#!/bin/sh
# This is part 08 of a multipart archive
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= iman/ihash.tex ==============
echo "x - extracting iman/ihash.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ihash.tex &&
X% XREF ihash ihasharg
X
X\def\name{IHASH}
X\def\IT{{\bb ihash()}}
X\def\ALT{{\bb ihasharg()}}
X
X\S{NAME}
X{\bb ihash} --- return checksum of string
X
X{\bb ihasharg} --- return checksum of upcased final component of pathname
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xihash (ptr, modval, upcase)
Xchar *ptr;
Xint modval;
Xint upcase;
X\L
Xint
Xihasharg (ptr, delim)
Xchar *ptr;
Xchar delim;
X}
X
X\S{DESCRIPTION}
X\IT\ calculates a "sum-of-bytes" value of
Xthe null terminated string at {\myit ptr\/}, and
Xreturns
Xthis value if {\myit modval\/} is zero.
XIf {\myit modval\/} is non-zero, \IT\
Xdivides the calculated sum by
X{\myit modval\/} and returns the remainder.
XIf the \IT\ {\myit upcase\/} is {\myit TRUE\/},
Xlower case alphabetic characters of the source string
Xare summed as upper case bytes.
X\L
X\ALT\ operates similarly to \IT, but computes a
Xvalue for the
Xlast component of a {\myit pathname\/} only. \ALT\ is not
Xcase sensitive:
Xeach lower case letter of the
Xexamined string is always summed as if it was upper case.
X\L
XThe primitive {\myit hash values\/} returned by \IT\ and \ALT\
Xsee use in a somewhat crude but speedy
Xalternative to repeated calls to
X{\myit strcmp()\/}. Care must be taken that differing
Xstrings contrasted this way don't produce the same sum of bytes, an
Xevent called "collision".
X\L
XIf {\myit ptr\/} is NULL or the string at {\myit ptr\/} is zero length,
X{\myit ierflag\/} is set and negative
X{\myit sys\_nerr} is returned.
X
X\S{PROGRAM EXAMPLES}
XA number of ILIB program examples such as
X{\bb nest}, {\bb ego}, {\bb rot}, as well as the
Xexample programs {\bb trunc} and {\bb lhash} listed here, decode the
Xidentity of {\myit argv[0]\/} via the \ALT\ function.
XThe single executable produced from the source text by the C~compiler
Xis given one or more alternate names with the Unix {\myit ln\/}
Xcommand. From then on, calling the command by any of its
X{\myit alias\/}es will bring the
Xsame process to life; but the process knows the name
Xthat caused its execution, and can produce different results
Xfor one name than for another.
XThe name of these example programs (stored in {\myit argv[0]\/} under
Xthe C environment) is passed to \ALT\ which then searches
Xfor the rightmost \key{/}\ {\myit delim\/} character.
X\ALT\ returns the sum of the upcased bytes past {\myit delim\/}.
XThe user program then contrasts the returned sum against a
Xlist of predefined constants, each recognized as a
X{\myit hash value\/} of a specific name among the various alternates.
X\L
X{\bb trunc} is a very simple program reading lines from \stin, and
Xwriting them to \stout, truncating (suppressing) output beyond a
Xgiven column position of each line. The maximum byte count of each
Xline (the number of the column beyond which the output is suppressed),
Xis the sole, required argument on the command line.
XLines that are shorter than or equal to the specified length are
Xoutput without change. The line terminating
X{\myit newline\/} characters do not contribute to the byte count.
XWhen called by its {\bb leftrunc} alias, the program skips over the
Xspecified number of leading bytes of each line, and prints the rest
Xof the line instead. If the line is shorter than or equal to the
Xskip length given, just a {\myit newline\/} character is printed.
X
X\S{trunc.c PROGRAM TEXT}
X\listing{../iex/trunc.c}
X
X\S{lhash PROGRAM}
X{\bb lhash} and its alias {\bb uhash} are aides in generating lines
Xfor {\myit hash tables\/} included in other user source.
XInput data to {\bb lhash} or {\bb uhash} is typically a list of tokens,
Xeach token on a line by itself.
X{\bb lhash} sums the bytes of each input line (but not the terminating
X{\myit newline\/}), and outputs each sum as an ASCII decimal string
Xon a line by itself. {\bb uhash} converts each lower case character
Xin the input to its upper case equivalent prior to summing.
X\L
XThe {\myit -m modval\/} command line option allows the specification
Xof an upper cutoff limit: each computed sum is divided by
X{\myit modval\/} and the remainder of the operation is output as the
X{\myit hash value\/}. The {\myit -p\/},
X{\myit -l\/}, or
X{\myit -t\/} options each expect a {\myit printf()\/} format string
Xto follow the option flag, and will use this string to embed the
Xcomputed hash value into a string constant of the user's choice.
XAs an example,
X\smallskip
X\I{\mytt uhash -t '\#define \%-10.10s \%d' < weekdays}
X\smallskip
Xwould produce the following output from the file {\myit weekdays\/}
Xof seven lines:
X\L
X{\obeylines \mytt
X\#define\ Sunday\ \ \ \ \ 468
X\#define\ Monday\ \ \ \ \ 456
X\#define\ Tuesday\ \ \ \ 543
X\#define\ Wednesday\ \ 676
X\#define\ Thursday\ \ \ 628
X\#define\ Friday\ \ \ \ \ 447
X\#define\ Saturday\ \ \ 621
X\smallskip}
XThe {\myit -t} format option signifies that the output value is to
Xtrail the reprint of the input token being summed; the
X{\myit printf()\/} string after the format flag contains a {\myit \%s\/}
Xformat specifier for the input token, preceding the {\myit \%d\/}
Xspecifier for the {\myit hash value\/}.
X\L
XThe {\myit -p} format option stands for ``plain'', and does not
Xreprint the original token.
XThis option only expects a
X{\myit \%d\/} format
Xspecifier for the hash value within the
X{\myit printf()\/} string.
X\L
XThe {\myit -l\/} variation indicates that the sum is to be printed
Xfirst:
X\smallskip
X\I{\mytt uhash \ -m23 \ -l'/*\%3d\ */\ \lcu"\%s"\rcu,' \ < weekdays}
X\smallskip
X{\obeylines \mytt
X/*\ \ 8\ */\ \lcu"Sunday"\rcu,
X/*\ 19\ */\ \lcu"Monday"\rcu,
X/*\ 14\ */\ \lcu"Tuesday"\rcu,
X/*\ \ 9\ */\ \lcu"Wednesday"\rcu,
X/*\ \ 7\ */\ \lcu"Thursday"\rcu,
X/*\ 10\ */\ \lcu"Friday"\rcu,
X/*\ \ 0\ */\ \lcu"Saturday"\rcu,
X\smallskip}
X
X\S{lhash.c PROGRAM TEXT}
X\listing{../iex/lhash.c}
X\eject
SHAR_EOF
$TOUCH -am 0607124590 iman/ihash.tex &&
chmod 0644 iman/ihash.tex ||
echo "restore of iman/ihash.tex failed"
set `wc -c iman/ihash.tex`;Wc_c=$1
if test "$Wc_c" != "5655"; then
echo original size 5655, current size $Wc_c
fi
# ============= iman/ihms.tex ==============
echo "x - extracting iman/ihms.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ihms.tex &&
X% XREF ihms
X
X\def\name{IHMS}
X\def\IT{{\bb ihms()}}
X
X\S{NAME}
X{\bb ihms} --- convert duration from seconds to hh:mm:ss, time events
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xchar *
Xihms (key)
Xint key;
X}
X
X\S{DESCRIPTION}
X\IT\ converts arbitrary positive
Xinteger {\myit key\/}s
Xto ``hours:minutes:seconds'' strings. Each of the three fields
Xdelimited by the \key{:} is a two digit number. The range of both
X{\myit minutes\/}
Xand {\myit seconds\/} is 0--59; {\myit hours\/} are shown
Xbetween 0 and 23 inclusive, with no provisions for multi-day overflow.
XThe returned string is null terminated, without a
X{\myit newline\/} at the end.
X\L
XIf {\myit key\/} is negative, \IT\ takes a snapshot of the
Xcurrent Unix {\myit realtime\/} kept by the operating system in a
X{\myit seconds counter\/} incremented from zero since
X00:00:00 Greenwich Mean Time, January 1 1970.
X\IT\ stores this value in a static variable for further
Xreference, and returns the NULL pointer.
X\L
XAt subsequent calls whenever 0 is passed as the {\myit key\/} value,
X\IT\ subtracts the stored reference time from the instantaneous time
Xat the call, and returns the elapsed time since the reference call,
Xformatted \dx{hh:mm:ss}.
X\L
XIn the absence of a call with a negative {\myit key\/}, calls passing
X0 values receive \dx{hh:mm:ss}\ stamps of
XGreenwhich Mean Time at the instantaneous time of the call.
X\eject
SHAR_EOF
$TOUCH -am 0530133190 iman/ihms.tex &&
chmod 0644 iman/ihms.tex ||
echo "restore of iman/ihms.tex failed"
set `wc -c iman/ihms.tex`;Wc_c=$1
if test "$Wc_c" != "1362"; then
echo original size 1362, current size $Wc_c
fi
# ============= iman/iinput.tex ==============
echo "x - extracting iman/iinput.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iinput.tex &&
X% XREF iinput
X
X\def\name{IINPUT}
X\def\IT{{\bb iinput()}}
X
X\S{NAME}
X{\bb iinput} --- get a string from \stin\ after \sterr\ prompt
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xiinput (ptr, message)
Xchar *ptr;
Xchar *message;
X}
X
X\S{DESCRIPTION}
X\IT\ writes its passed {\myit message\/} to \sterr, leaves
Xthe cursor immediately after the printed {\myit message\/}, and reads
Xthe user's response from \stin\ into the caller's buffer passed as
X{\myit ptr\/}.
X\IT\ returns the size of the user's NUL terminated response, in bytes.
XNegative {\myit sys\_nerr\/} is returned via {\myit ierror()\/} if
Xthe NULL pointer is passed as either argument.
X
X\S{inum PROGRAM EXAMPLE}
XThe {\bb inum}
Xprogram is a copy of the {\bb cnum} program described under IOPT.
XWhile functionally the two programs are nearly identical, {\bb inum}
Xconducts a dialogue with the user, prompting the user for the
Xline numbering format, instead of parsing the command line for the list
Xof specifications as {\bb cnum} does. \IT\ is a convenient vehicle
Xfor question-and-answer pairs; and the dialogue has the advantage of
Xleaving the user free from the burdens of the command line syntax,
Xas well as ensuring that all pertinent format specifiers will get
Xconsidered.
XThe disadvantage is that the dialogue monopolizes \sterr\ and \stin\
Xfor passing messages between the user and the program: unlike
X{\bb cnum}, {\bb inum} cannot be made a filter.
X
X\S{inum.c PROGRAM TEXT}
X\listing{../iex/inum.c}
X\eject
SHAR_EOF
$TOUCH -am 0512211290 iman/iinput.tex &&
chmod 0644 iman/iinput.tex ||
echo "restore of iman/iinput.tex failed"
set `wc -c iman/iinput.tex`;Wc_c=$1
if test "$Wc_c" != "1453"; then
echo original size 1453, current size $Wc_c
fi
# ============= iman/iline.tex ==============
echo "x - extracting iman/iline.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iline.tex &&
X% XREF iline
X
X\def\name{ILINE}
X\def\IT{{\bb iline()}}
X
X\S{NAME}
X{\bb iline} --- find {\myit newline\/}, null it, return line size
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xiline (start, end)
Xchar *start;
Xchar *end;
X}
X
X\S{DESCRIPTION}
X\IT\ seeks out the first {\myit unescaped newline\/} from
Xthe beginning of the buffer delimited by {\myit start\/},
X{\myit end\/}, and changes the {\myit newline\/} byte to NUL
X(ASCII 0).
XIf the {\myit end\/} is reached but a {\myit newline\/} was not
Xfound,
Xthe byte immediately before {\myit end\/} is changed into NUL.
XThe search is unhindered by other NUL bytes that may already be
Xpresent in the buffer; \IT\ will skip over these.
X\L
XThe returned value is the byte count of the string between
X{\myit start\/} and the nulled {\myit newline\/}, {\bb including}
Xthe terminating NUL byte.
X
X\S{ncat PROGRAM EXAMPLE}
XThe {\bb ncat} program produces a ``line numbered'' listing of files
Xsimilarly to the {\myit cat -n\/} command of BSD Unix (the {\myit -n\/}
Xoption is absent in System~V). The principal difference is that the
XBSD {\myit cat\/} keeps incrementing line numbers across a list of
Xfiles specified on the command line, whereas {\bb ncat\/} restarts
Xnumbering from line~1, for each file. Additionally, {\bb ncat\/}
Xtakes an optional ``separator'' or ``spooler'' line that it will
Xprepend to each file (such as {\myit formfeed\/} characters or
X{\myit page break\/} macros).
XFonetic control characters of the separator string are converted to
Xreal values by a call to {\myit ifonetic\/}; and in addition
X{\bb ncat} converts \key{\dol} characters of the separator
X(given in either the real or the phonetic form) to the
Xfile name of the next file to be spooled.
XA {\myit newline\/} is {\bb not}
Xautomatically appended to the separator string. The mechanism
Xmakes {\bb ncat} useful for
Xsetting up printer ``spooler'' queues. {\bb ncat} caters to Unix and
XC syntax by recognizing that text lines terminated with escaped
X{\myit newlines} logically belong
Xto the next line, and prepends just one line number to the first
Xline of escaped multi-line groups.
X
X\S{ncat.c PROGRAM TEXT}
X\listing{../iex/ncat.c}
X\eject
SHAR_EOF
$TOUCH -am 0529112190 iman/iline.tex &&
chmod 0644 iman/iline.tex ||
echo "restore of iman/iline.tex failed"
set `wc -c iman/iline.tex`;Wc_c=$1
if test "$Wc_c" != "2144"; then
echo original size 2144, current size $Wc_c
fi
# ============= iman/ilist.tex ==============
echo "x - extracting iman/ilist.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ilist.tex &&
X% XREF ilist ilistn illistn
X
X\def\name{ILIST}
X\def\IT{{\bb ilist()}}
X\def\ALT{{\bb illistn()}}
X
X\S{NAME}
X{\bb ilist} --- create array of pointers to non-null strings in buffer
X
X{\bb ilistn} --- create array of pointers to strings in buffer
X
X{\bb illistn} --- create array of pointers to lines in buffer
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xilist (start, end, delims, ptrlist)
Xchar *start;
Xchar *end;
Xchar *delims;
Xchar **ptrlist;
X\L
Xint
Xilistn (start, end, delims, ptrlist)
Xchar *start;
Xchar *end;
Xchar *delims;
Xchar **ptrlist;
X\L
Xint
Xillistn (start, end, ptrlist)
Xchar *start;
Xchar *end;
Xchar **ptrlist;
X}
X
X\S{DESCRIPTION}
X
XThe \IT\ functions break up text in the buffer delimited by
X{\myit start\/} and {\myit end\/} into null-terminated strings,
Xand provide a list of {\myit char pointers\/} to the caller such
Xthat successive pointers in the list will point to successive
Xnull-terminated strings of the original buffer. The pointer list
Xin all cases will contain a final {\myit sentinel\/} pointer set
Xto NULL.
X\L
XThe functions return the number of null-terminated strings counted in
Xthe buffer (the count not including the extra pointer appended to the
Xlist), and make the address of the dynamically allocated memory
Xavailable
Xvia {\myit ptrlist\/}.
XThe {\myit ptrlist\/} argument is generally of type
X{\myit (char~*)\/} passed by address.
X\L
XThe \ALT\ function assumes that data in the buffer is to be segmented
Xat every {\myit newline\/} character; and changes all
X{\myit newline\/}s
Xwithin the buffer into NUL (zero) bytes. To safeguard the caller
Xagainst accidentally
Xoverrunning an un-terminated buffer (if the byte preceding {\myit end\/}
Xwas not a {\myit newline\/}), \ALT\ automatically dubs
Xthe last byte of the buffer to be a {\myit newline\/}, and converts
Xit to NUL.
XIf the size of the passed buffer is zero, \ALT\ cannot guarantee
Xa terminal NUL byte; however the sentinel pointer will still be
Xallocated and made available to the caller.
X\L
X\IT\ and {\bb ilistn()} both segment the buffer at each byte
Xin the buffer that matches any character of the {\myit delims\/} string:
Xall characters in the buffer
Xrecognized as belonging to the delimiter character set, are
Xconverted into
XNUL bytes. \IT\ then sets successive pointers to null-terminated
Xstrings
Xthat are at least one byte long; zero-sized strings are skipped.
XThe other functions allocate pointers even to zero-sized strings;
Xin the case of \ALT\ this produces pointers to blank lines.
X\L
XPassed
X{\myit (char~*)NULL start\/}
Xaddress,
X{\myit (char~*)NULL\/} or zero-length
X{\myit delims\/}
Xtrigger
Xerror reporting via {\myit ierror()\/}, and produce return values of
X{\myit --sys\_nerr\/}.
X
X\S{lcat PROGRAM EXAMPLE}
XThe {\bb lcat} program serves to print
X(``{\myit cat\/}'' in the Unix jargon) a specific line
Xor a specific block of lines from the lines of input,
Xto \stout. {\bb lcat} is a filter. The starting
Xline number and the file name are mandatory command line parameters.
XWithout the {\myit plus option\/}
Xthe selected line of each file is printed, provided that the
Xinput has that many lines.
XThe optional solo \key{+} flag on the command line forces the
Xprinting of all remaining lines. A
X\key{+} flag immediately followed by a number, forces the printing
Xof that many successive lines after the starting line.
X({\bb lcat} does not use {\myit iopt()\/} for parsing the command
Xline options, and consequently is too myopic to correctly
Xrecognize the {\myit M\/} parameter if it is separated from its
X\key{+} flag.)
X\L
XHaving examined the command line, the process reads the input into
Xan internal buffer via {\myit ifilter()\/},
Xand sets up a pointer list to lines of
Xthe buffer with {\bb illistn()}. Because line numbering conventionally
Xbegins at 1 but C's array indices start at 0, the starting line is
Xfound by using {\myit N--1\/} as the offset into the line list.
XIf line {\myit N+M} would lie beyond the end of the input, the
Xrest of the buffer is output line-by-line; otherwise the {\myit M\/}
Xlines following line {\myit N\/} are printed. Note that the
Xrepeated calls to the {\myit puts()\/} function
Xfor printing successive lines
Xrepresent a computational
Xoverhead that is tolerated here since the use of the
X{\myit plus option\/} is expected to be minimal.
X\L
X{\bb lcat} works well in concert with the {\myit grep~--n\/}
Xcommand that produces the line number(s) of
Xregular expressions recognized in a file. Often the user wants to
Xsee the next few lines as well, but this capability is not provided
Xby {\myit grep\/}. The following one-liner shell script (named
X{\myit grep\tt+\/}) takes as its first parameter
Xthe additional number of lines that the user wants printed, followed by
Xthe searched-for word and a filename:
X\smallskip
X{\obeylines \mytt
Xlcat\ `grep -n "\$2" \$3|lcat 1|fcat 1 \ -d':' ` \ +\$1 \ \$3
X\smallskip}
X{\myit grep\/} may find more than one instance of the pattern, in
Xwhich case only the first one will pass the embedded {\bb lcat} pipe.
XFor example, the command
X\smallskip
X\I{\mytt grep+ 2 \ 'ilib.a:' \ ../i/makefile}
X\smallskip
Xsearches for the {\myit ilib.a:\/} target in {\myit makefile\/}, and
Xprints the line of the target, plus
Xthe next two lines.
X
X\S{lcat.c PROGRAM TEXT}
X\listing{../iex/lcat.c}
X
X\S{scat PROGRAM EXAMPLE}
XThe {\bb scat} program is a direct derivative of {\bb lcat},
Xreading its input as a filter and
Xprinting to \stout\ the first input line that
Xcontains a specified string.
XA string pattern and
Xa file name are positionally fixed mandatory command line parameters.
XA second string may be given after the first with the
X\dx{--s \ {\myit string}\/}\ or
X\dx{--s{\myit string\/}}\ option, and will precipitate the printing
Xof successive lines after the first line, until a text line
Xis encountered that contains the second ({\myit stop\/}) string.
X\L
XThe program structure is similar to that of {\bb lcat}, but
Xinstead of indexing into the pointer list returned by
X{\bb illistn()}, lines marked by
Xadjacent pointers of the pointer list
Xare successively passed to {\myit ianymatch()\/}
Xfor pattern matching.
X{\bb scat} puts the text ending {\myit sentinel\/} pointer returned
Xby {\bb illistn()} to good use in limiting the iteration count of
Xthe {\myit for loops\/}, and in being able to set
Xthe {\myit look-ahead\/} pointer to an address beyond the last line of
Xthe text buffer.
X
X\S{scat.c PROGRAM TEXT}
X\listing{../iex/scat.c}
X\eject
SHAR_EOF
$TOUCH -am 0607125990 iman/ilist.tex &&
chmod 0644 iman/ilist.tex ||
echo "restore of iman/ilist.tex failed"
set `wc -c iman/ilist.tex`;Wc_c=$1
if test "$Wc_c" != "6383"; then
echo original size 6383, current size $Wc_c
fi
# ============= iman/ilower.tex ==============
echo "x - extracting iman/ilower.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ilower.tex &&
X% XREF ilower iupper
X
X\def\name{ILOWER}
X\def\IT{{\bb ilower()}}
X\def\ALT{{\bb iupper()}}
X
X\S{NAME}
X{\bb ilower} --- change alphabetic characters in buffer to lower case
X
X{\bb iupper} --- change alphabetic characters in buffer to upper case
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xilower (start, end)
Xchar *start;
Xchar *end;
X\L
Xint
Xiupper (start, end)
Xchar *start;
Xchar *end;
X}
X
X\S{DESCRIPTION}
X\IT\ and \ALT\ implement table-driven, {\myit en masse\/}
Xconversion of alphabetic
Xcharacters in the buffer delimited by {\myit start\/} and
X{\myit end\/} to lower case or upper case values
Xrespectively, and return the byte length of the buffer.
XThe method is faster than the bitwise conversion implemented by
Xthe standard {\myit tolower()\/} and {\myit toupper()\/} macros,
Xbut the tables are specific to the ASCII character set.
X
X\S{up PROGRAM EXAMPLE}
XThe simplicity of the \IT, \ALT\
Xfunction interface allows fairly dense coding
Xwithout loosing readability. The {\bb up}/{\bb down}
Xprogram translates multiple files to all upper case
Xor to all lower case. The program is not a filter; it alters
Xthe source text of files.
X
X\S{up.c PROGRAM TEXT}
X\listing{../iex/up.c}
X\eject
SHAR_EOF
$TOUCH -am 0531090290 iman/ilower.tex &&
chmod 0644 iman/ilower.tex ||
echo "restore of iman/ilower.tex failed"
set `wc -c iman/ilower.tex`;Wc_c=$1
if test "$Wc_c" != "1168"; then
echo original size 1168, current size $Wc_c
fi
# ============= iman/imatch.tex ==============
echo "x - extracting iman/imatch.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/imatch.tex &&
X% XREF ianymatch imatch ixmatch
X
X\def\name{IMATCH}
X\def\IT{{\bb imatch()}}
X\def\ALT{{\bb ixmatch()}}
X
X\S{NAME}
X{\bb imatch} --- find a specific token or token head in a buffer
X
X{\bb ianymatch} --- find a specific string in a buffer
X
X{\bb ixmatch} --- find a specific token in a buffer
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xchar *
Ximatch (start, end, str)
Xchar *start;
Xchar *end;
Xchar *str;
X\L
Xchar *
Xianymatch (start, end, str)
Xchar *start;
Xchar *end, *str;
X\L
Xchar *
Xixmatch (start, end, word)
Xchar *start;
Xchar *end;
Xchar *word;
X}
X
X\S{DESCRIPTION}
X\IT\ attempts to find a byte sequence in the buffer bounded by
X{\myit start\/} and {\myit end\/}, that matches the specified
X{\myit str\/}. A comparison is performed at the first byte of
Xevery {\myit token\/} of the buffer, proceeding from left to right.
XTokens in the buffer are delimited by {\myit white space\/}.
XThe search stops as soon as {\myit str\/} can be made to exactly
Xcoincide with a buffer segment that began a token;
Xand the buffer address of this token is returned.
XThe search is case sensitive.
XIf no match is found, \IT\ returns the NULL pointer.
X\L
XThe search by \ALT\ is slightly more demanding in that
Xthe (last) token of a matching buffer segment must be a fully formed
Xtoken, terminating identically to the {\myit word\/} of the
Xcomparison.
X\L
XGiven an example buffer, containing:
X\smallskip
X\I{\dx{Heart of gold}}
X\smallskip
Xneither function would find a match to \dx{ear}\ or \dx{art}. \ALT\
Xwould produce matches to full word combinations. Various calls to
X\IT\ would produce
Xadditional matches over truncated tokens, as in \dx{He}, \dx{Hear},
X\dx{Heart o}, \dx{of go}, and so on.
X\L
X{\bb ianymatch()} finds a buffer segment that matches {\myit str\/},
Xwithout any of the token boundary restrictions of either \IT\ or
X\ALT.
X\L
XAll three functions flag invalid buffers or zero-length comparison
Xstrings by calling {\myit ierror()\/}.
X
X\S{rename EXAMPLE PROGRAM}
XWhen working with lists of related files, the {\bb rename} program
Xcan assist in making global changes to file names. The first
Xparameter given after {\bb rename} on the command line specifies
Xthe string that needs to be replaced in each of the file names
Xtrailing in the command line, with the string given as the
Xsecond parameter. For example, the command sequence
X\smallskip
X\I{\mytt split /usr/dict/words}
X\I{\mytt rename x words. *}
X\smallskip
Xfirst breaks up the word list {\myit /usr/dict/words\/} to twentyfive
Xfiles each a
Xhundred lines long, naming the new files
X{\myit xaa, xab, xac...\/} (the file naming option of {\myit split\/}
Xhas been purposely omitted from the command, to
Xdemonstrate {\bb rename}). {\bb rename} changes \key{x}\
Xto \dx{words.}\ in each of the file names, so a
Xdirectory listing
Xwill produce
X{\myit words.aa words.ab words.ac\/} and so on. To avoid
Xchanging the first
X`x' character in the names of existing files with longer names,
Xthe file list given at the end of the {\bb rename} command
Xcoulde be more restrictive:
X\smallskip
X\I{\mytt rename x words. x??}
X\L
X{\bb rename} requires at least four tokens on the command line:
Xits own name, the string to be replaced, the new replacement string,
Xand a file name. A ``usage'' message is printed if not enough
Xtokens are specified. Null strings can be specified by typing a
Xsingle \key{-} instead of a string. If the \key{-} stands
Xfor the string to be replaced, it is interpreted loosely as
X``the first nothing in the file name is to be replaced with:''
Xand the replacement string is then prepended in front of
Xthe existing file
Xname. If the \key{-} is given as the replacement string,
Xthe ``string to be replaced'' is replaced with nothing, gets
Xdeleted in effect from the file name.
X\L
X{\bb rename} prints an error message and leaves the file
Xname (and the file) intact if directory permissions prevent the
Xrenaming process, or if the newly created
Xfile name exactly matches another
Xfile name in the directory.
X
X\S{rename.c PROGRAM TEXT}
X\listing{../iex/rename.c}
X\eject
SHAR_EOF
$TOUCH -am 0607134590 iman/imatch.tex &&
chmod 0644 iman/imatch.tex ||
echo "restore of iman/imatch.tex failed"
set `wc -c iman/imatch.tex`;Wc_c=$1
if test "$Wc_c" != "3998"; then
echo original size 3998, current size $Wc_c
fi
# ============= iman/imode.tex ==============
echo "x - extracting iman/imode.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/imode.tex &&
X% XREF imode
X
X\def\name{IMODE}
X\def\IT{{\bb imode()}}
X
X\S{NAME}
X{\bb imode} --- find out if specified file permission bits are set
X
X\S{SYNOPSIS}
X\settabs\+{\bb mdefine ISUSTICKY} & 00000000000 &\cr
X\+{\bb\#define ISSOCK }&{\bb 0140000}&{\mytt/* socket */}\cr
X\+{\bb\#define ISLNK }&{\bb 0120000}&{\mytt/* symbolic link */}\cr
X\+{\bb\#define ISREG }&{\bb 0100000}&{\mytt/* regular */}\cr
X\+{\bb\#define ISBLK }&{\bb 0060000}&{\mytt/* block special */}\cr
X\+{\bb\#define ISDIR }&{\bb 0040000}&{\mytt/* directory */}\cr
X\+{\bb\#define ISCHR }&{\bb 0020000}&{\mytt/* character special */}\cr
X\+{\bb\#define ISFIFO }&{\bb 0010000}&{\mytt/* named pipe */}\cr
X\+{\bb\#define ISUID }&{\bb 0004000}&{\mytt/* set uid on execution */}\cr
X\+{\bb\#define ISGID }&{\bb 0002000}&{\mytt/* set gid on execution */}\cr
X\+{\bb\#define ISSTICK}&{\bb 0001000}&{\mytt/* keep text in memory (sticky bit) */}\cr
X\+{\bb\#define ISROWN }&{\bb 0000400}&{\mytt/* read, owner */}\cr
X\+{\bb\#define ISWOWN }&{\bb 0000200}&{\mytt/* write, owner */}\cr
X\+{\bb\#define ISXOWN }&{\bb 0000100}&{\mytt/* execute/search, owner */}\cr
X\+{\bb\#define ISRGRP }&{\bb 0000040}&{\mytt/* read, group */}\cr
X\+{\bb\#define ISWGRP }&{\bb 0000020}&{\mytt/* write, group */}\cr
X\+{\bb\#define ISXGRP }&{\bb 0000010}&{\mytt/* execute/search, group */}\cr
X\+{\bb\#define ISRALL }&{\bb 0000004}&{\mytt/* read, others */}\cr
X\+{\bb\#define ISWALL }&{\bb 0000002}&{\mytt/* write, others */}\cr
X\+{\bb\#define ISXALL }&{\bb 0000001}&{\mytt/* execute/search, others */}\cr
X\L
X{\obeylines \bb
Xint
Ximode (fname, perm)
Xchar *fname;
Xint perm;
X}
X
X\S{DESCRIPTION}
X\IT\ is a convenient {\myit shortcut\/} for querying the permission
Xmode of a file. \IT\ itself calls {\myit stat()\/}, so the user
Xcode doesn't have to. The true value of {\myit perm\/} is
Xirrelevant, except insofar as it specifies the {\myit permission bits\/}
Xsubject to the query. If {\myit file\/} has all those permission bits
Xset that are of interest to the user, \IT\ returns TRUE, else it
Xreturns FALSE. For example,
X\smallskip
X\I{\mytt imode ("/bin", ISDIR \pip\ ISWGRP);}
X\smallskip
Xwould return TRUE if the {\myit /bin\/} directory was writable by
X{\myit group\/}, but it would return FALSE if {\myit /bin\/}
Xwas not a directory or if {\myit group\/} did not have write
Xpermission. \IT\ ``knows'' how to interpret the upper four
X{\myit file type\/} permission bits, and will correctly differentiate
Xbetween a directory and a socket, for example.
XThe familiar octal permission strings may be passed as {\myit perm\/}
Xinstead of, or mixed with the symbolic constants defined in
X{\myit ilib.h\/}:
X\smallskip
X\I{\mytt imode ("../etc/motd", ISREG \pip\ 0444);}
X\smallskip
Xwould return TRUE if
X{\myit ../etc/motd\/} was a regular file writable by owner, group,
Xand others.
X\L
X\IT\ calls {\myit ierror()\/} and returns {\myit -sys\_nerr\/} if
X{\myit fname\/} is NULL or has no length, or negative {\myit errno\/} if
Xthe call to {\myit stat()\/} fails.
XIf {\myit perm\/} is zero, \IT\ returns the full permission value
Xgotten with the {\myit stat()\/} call in {\myit sbuf.st\_mode}.
X
X\S{unlink PROGRAM EXAMPLE}
XBecause the effects of the Unix {\myit rm} command are irreversible
Xin most cases, many programmers enclose the interactive form of the
X{\myit rm\/} command in a script named {\myit rm\/}, or use the
Xinteractive command as an {\myit alias\/}; in either case overlaying
Xthe original name with a duplicate command name that executes
Xdifferently.
XWhen the time comes to bypass the interactive form (to avoid
Xforever having to respond ``y''
Xwhen removing a long list of files), the programmer has to remember
Xto type the full {\myit /bin/rm\/} path to bypass the
Xinteractive version, and presumably would specify
Xthe {\myit -f\/} flag to force non-interactive removal of
X{\myit read-only\/} files. Add to this the ``solo minus'' or
X``null option'' flag
Xto be able to remove files whose names begin with \key{-},
Xand the snowballing complexity of the non-interactive remove syntax
Xmay warrant a simple, brute-force alternative: {\bb unlink}.
X\L
X{\bb unlink} removes the files (except directories)
Xin its argument list, if at all possible in the given user environment.
XIf a file
Xcannot be found or cannot be removed (because of lacking permissions
Xto {\myit write\/} the directory containing the file), {\bb unlink}
Xoutputs an error message to this effect to \sterr, and continues
Xremoving the other files in the list. The {\myit unlink()\/}
Xsystem command on which the program is based, will normally fail when
Xtrying to
Xremove directories, unless the process is executed by
Xthe {\myit super user\/}. Because removing a directory would orphan
Xany sub-file-system contained within that directory, {\bb unlink}
Xprevents even the superuser from removing a directory, by querying
Xthe status of files with \IT, and skipping directories.
X
X\S{unlink.c PROGRAM TEXT}
X\listing{../iex/unlink.c}
X\eject
SHAR_EOF
$TOUCH -am 0529112090 iman/imode.tex &&
chmod 0644 iman/imode.tex ||
echo "restore of iman/imode.tex failed"
set `wc -c iman/imode.tex`;Wc_c=$1
if test "$Wc_c" != "4921"; then
echo original size 4921, current size $Wc_c
fi
# ============= iman/inest.tex ==============
echo "x - extracting iman/inest.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/inest.tex &&
X% XREF inest
X
X\def\name{INEST}
X\def\IT{{\bb inest()}}
X
X\S{NAME}
X{\bb inest} --- create array of {\myit int\/}s to nest information
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xinest (start, end, ldelim, rdelim, infopair)
Xchar *start;
Xchar *end;
Xchar *ldelim;
Xchar *rdelim;
Xint \ **infopair;
X}
X
X\S{DESCRIPTION}
X\IT\ reads the buffer delimited by {\myit start\/} and {\myit end\/},
Xand counts the total number of distinct
X{\myit ldelim\/} and {\myit rdelim\/} strings. An integer array
Xis allocated next. The buffer is then re-parsed,
Xand for each encountered left or right delimiter
X\IT\ loads the offset from {\myit start\/} to the first
Xbyte of the delimiter into the next cell of the array, and the
X``nest-level'' of the delimiter
Xinto the cell after the cell of the offset. In this way, the array
Xis filled with integer pairs of {\myit offset, nest-level\/}.
XThe
Xnest-level of each left delimiter is stored as a positive number,
Xnest-levels of right delimiters are stored as negative numbers.
XThe internal nest-level counter gets incremented for every
Xsuccessive {\myit ldelim\/} encountered in the text,
Xand gets decremented at every {\myit rdelim\/}. If an
X{\myit rdelim\/} is found when the nest-level is zero, the counter
Xdoes not get decremented further; the nest-level of the right
Xdelimiter is recorded as zero.
X\L
X\IT\ returns the sum of {\myit ldelim\/}s and {\myit rdelim\/}s
Xfound in the buffer, and the
X{\myit malloc\/}'d buffer address via {\myit infopair\/}.
X{\myit infopair\/} is of
Xtype ``{\myit pointer to an array of ints\/}'', and will
Xnormally be an
X{\myit (int *)\/} passed by address.
X\L
XNULL or zero-length delimiters, identical left/right delimiters,
Xor ``overlapping'' delimiters trigger error returns of
X{\myit -sys\_nerr\/}. Failing {\myit malloc\/} calls produce a
Xnegative {\myit errno\/} return value, as
Xdescribed under {\myit ierror()\/}.
X\IT\ identifies an overlap condition if the two delimiters exactly
Xmatch from their beginning
X'til the end of the shorter delimiter.
XFor example, the \dx{if} \dx{ifend}\ pair or
Xthe \dx{ifstart} \dx{if}\ pair
Xare both overlapping, whereas
Xnone of the \dx{if} \dx{endif},
X\dx{startif} \dx{if},
X\dx{ifstart} \dx{ifend}\ pairs are.
X
X\S{nest PROGRAM EXAMPLE}
XThe {\bb nest} program described here
Xoutputs (to \stout) information about the distribution and relative
Xsymmetry of matched pairs of delimiters in a file. In particular,
Xthe file is assumed to be C text: one of the first actions during
Xthe process is to suppress all comment strings within the file.
XBecause of this, the {\bb nest} program is not suitable for
Xretrieving information relating to the comment delimiter pair
X\twokey{/*} and \twokey{*/}.
X\L
XThe program decodes the
Xidentity of {\myit argv[0]\/} via the {\myit ihashargv()\/} function,
Xas described under the IHASH entry.
XThe single executable produced from the source text by the C~compiler
Xis given the alternate name {\bb nestinfo} with the Unix {\myit ln\/}
Xcommand. Calling the command by either {\bb nest}
Xor {\bb nestinfo} will therefore bring the
Xsame process to life; but the process recognizes the name
Xthat caused its execution and produces different results
Xfor {\bb nest} than for {\bb nestinfo}.
X{\bb nestinfo} outputs a terse, single line summary about the delimiters
Xfound in the file. A sample command line and its output:
X\smallskip
X\I{\mytt nestinfo ifdef endif nest.c}
X\smallskip
X\I{\mytt 1 ifdef 1 endif matched}
X\L
X{\bb nest} prints a line numbered, indented
Xlist of the encountered {\myit nest levels\/}:
X\smallskip
X\I{\mytt nest \ \bsl\lcu\ \ \bsl\rcu\ \ nest.c}
X\smallskip
X{\mytt
X\I{15\ \ \lcu}
X\I{58\ \ \ \ \ \ \lcu}
X\I{69\ \ \ \ \ \ \rcu}
X\I{78\ \ \ \ \ \ \lcu}
X\I{85\ \ \ \ \ \ \rcu}
X\I{87\ \ \rcu}
X\smallskip}
X
XBecause {\myit istripcom()\/} not only suppresses comments, but also
Xalters the line numbering of the text ({\myit newline\/} characters
Xwithin comments are changed to spaces), the {\myit illistn()\/}
Xcall sets up a list of pointers to the original lines first.
XThe first {\myit int\/} of each pair of the {\myit infopairs\/} list
Xreturned from \IT\ show the offset of the given delimiter from the
Xbeginning of the text; this is converted to the actual address by
Xadding it to the base address of the text buffer. The address of the
Xdelimiter is then contrasted against the address of successive lines
X(stored via the pointers of the list returned by
X{\myit illistn()\/}) to find the original line number of the
Xdelimiter.
X
X\S{nest.c PROGRAM TEXT}
X\listing{../iex/nest.c}
X\eject
SHAR_EOF
$TOUCH -am 0529112090 iman/inest.tex &&
chmod 0644 iman/inest.tex ||
echo "restore of iman/inest.tex failed"
set `wc -c iman/inest.tex`;Wc_c=$1
if test "$Wc_c" != "4513"; then
echo original size 4513, current size $Wc_c
fi
# ============= iman/ioctal.tex ==============
echo "x - extracting iman/ioctal.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/ioctal.tex &&
X% XREF ioctal
X
X\def\name{IOCTAL}
X\def\IT{{\bb ioctal()}}
X
X\S{NAME}
X{\bb ioctal} --- convert octal digit strings to {\myit int}
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xioctal (ptr)
Xchar *ptr;
X}
X
X\S{DESCRIPTION}
X\IT\ converts a digit string to a value, and returns this value.
X\IT\ expects the passed parameter {\myit ptr\/}
Xto point to an octal string,
Xrecognizing only the digits \key{0} through \key{7}, and ignoring
Xall leading and embedded {\myit white space\/}. The conversion
Xends at the first unrecognized character, or at the NUL byte
Xterminating the string. There are no provisions for overflow.
XThe princpal use for \IT\ is in parsing the command line for
Xoctal Unix ``permission strings''.
X\L
X\IT\ calls {\myit ierror()\/} and returns {\myit -sys\_nerr\/}
Xif {\myit ptr\/} is the NULL pointer.
X\eject
SHAR_EOF
$TOUCH -am 0509104190 iman/ioctal.tex &&
chmod 0644 iman/ioctal.tex ||
echo "restore of iman/ioctal.tex failed"
set `wc -c iman/ioctal.tex`;Wc_c=$1
if test "$Wc_c" != "807"; then
echo original size 807, current size $Wc_c
fi
# ============= iman/iopt.tex ==============
echo "x - extracting iman/iopt.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iopt.tex &&
X% XREF iopt
X
X\def\name{IOPT}
X\def\IT{{\bb iopt()}}
X
X\S{NAME}
X{\bb iopt} --- command line option manager
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xiopt (ptr)
Xchar ***ptr;
X}
X
X\S{DESCRIPTION}
X\IT\ is a dynamic parser for command line options, in the genre of
Xvarious C {\myit getopt\/} routines. The main strength of
X\IT\ is its ease of use, rather than an all-encompassing
Xparser mechanism that could evaluate any possible option and flag
Xcombinations.
X\IT\ operates on the following simple types of
Xoption-flag/option-value pairs:
X\smallskip
X{\myit
X\I{{\bb--c}value}
X\I{{\bb--c} \ value}
X\I{{\bb--}}
X}
X\smallskip
XThat is, the list of options on the parsed command line must form
X{\myit flag/value\/} pairs except for the solo minus option;
Xeach {\myit flag\/}
Xis an arbitrary single character immediately
Xappended past a minus sign, and each {\myit value\/} is
Xan arbitrary token either adjoining or separate from its {\myit flag\/}.
XThe {\myit ptr\/} parameter passed to \IT\ is generally of type
X{\myit pointer to an array of strings\/} (such as the {\myit argv\/}
Xlist in {\myit main\/}) passed by address.
X\L
X\IT\ is usually called
Xrepeatedly, in a loop. The function
Xreturns the integer ASCII value of the flag character `{\bb c}'
X(but returns `{\bb--}' for the solo minus option), and
Xautomatically re-positions the passed-in pointer to the
X{\myit value\/} component of the option pair (not advancing it
Xin the case of the solo minus).
X\IT\ also remembers
Xthe location of the next, not yet evaluated argument, and will
Xautomatically continue parsing from it during the next call. In
Xthis way, the calling function has only to initialize the passed-in
Xpointer to the first command line argument; \IT\ does the rest.
XInformation passed in after the first call, will be ignored.
XOnce the flag/value list is exhausted
X(when the first character of an evaluated
Xargument pair is not `{\bb--}')
Xzero is returned instead of the
Xflag value, and at this point \IT\ has positioned
X{\myit ptr\/} to the first argument after the option list.
XThis allows easy continuation with trailing non-option items
Xon the command line, such as a list of files.
X\L
XAlternately, \IT\ may be called a selected number of times such that
Xat the last call \IT\ is not aware that the flag/value parsing is about
Xto come to an end. At the last call, \IT\ will have returned the given
Xflag character, and will have repositioned {\myit ptr\/} to point to the
X{\myit value\/} component of the flag/value pair. In order to
Xadvance the pointer to the next argument after the last {\myit value\/}
Xthe pointer should now be explicitly incremented.
X\L
XAn example of flag/value pairs in a typical option list:
X\smallskip
X\I{{\bb--A}\quad{\myit opt1\/}\quad{\bb--B}{\myit
Xopt2\/}\quad{\bb--C}\quad{\myit
Xopt3\/}\quad{\bb--}
X\quad{\bb--D}{\myit opt5\/}\quad more\_args\quad\mydots
X}
X\smallskip
XSuccessive calls to this list would return with {\myit ptr\/} pointing
Xto {\myit opt1, opt2, opt3, --, opt5\/} and finally to
X{\myit more\_args\/}; int values returned
Xwould be 65, 66, 67, 45, 68 and 0.
X\L
XIf the last argument in the command line
Xis an option flag ({\bb--c}) without a trailing
X{\myit option\/} value,
Xit is rejected from evaluation: the search stops and the option flag
Xwill be handled as the first non-option argument.
X\L
XThe \IT\ code contains
Xno system calls that could set the global
X{\myit errno\/}, and does not
Xaffect the {\myit ierflag\/} or {\myit ierbuf\/} variables used by
X{\myit ierror()\/} under
XILIB's error reporting.
X
X\S{cnum EXAMPLE PROGRAM}
XThe line numbering program {\bb cnum\/} described here calls
X\IT\ exhaustively,
Xin a loop. Another example {\bb ncat} described under ILINE,
Xcalls \IT\ only once.
X{\bb cnum\/} copies a file to \stout, annotating lines of the input
Xwith a customized number sequence.
X{\bb cnum\/} can put line
Xnumbers in front of lines, or at the end of lines; numbers can be
Xdecimal, octal, lowercase or uppercase hexadecimal. The starting
Xline number as well as the
Xincrement or decrement to the next line can be arbitrary
Xintegers. Numbers can be
Xleft or right justified in a desired field width; right
Xjustified numbers may be printed with leading zeros.
XA user-supplied string may precede the line numbers, another string
Xmay follow the line numbers, and a third
Xstring may be appended at the end of the input lines themselves.
X\L
XThe numbering format is controlled through a long but simple list of
Xcommand line options;
X\IT\ is called to evaluate the command line.
XIn the absence of command line
Xarguments, {\bb cnum} prints a ``usage'' message to \sterr, summarizing
Xthe meaning and syntax of the various options.
XAn example {\bb cnum\/} command line
X\smallskip
X\I{\mytt
Xcnum -p August -a "th was a " -s6 -t. -j3}
X\smallskip
Xtransforms the days of the week (each input on a line by itself) to:
X\smallskip
X{\mytt
X\I{August \ 6th was a Sunday.}
X\I{August \ 7th was a Monday.}
X\I{August \ 8th was a Tuesday.}
X\I{August \ 9th was a Wednesday.}
X\I{August 10th was a Thursday.}
X\I{August 11th was a Friday.}
X\I{August 12th was a Saturday.}
X}
X\L
XIf no file name is given at the end of the option list, \stin\ is
Xread. The user can also number a nonexistent file of
X{\myit N\/} lines, by using the {\bb--c N} option:
X\smallskip
X\I{\mytt
Xcnum -c 1000 -s 601}
X\smallskip
Xproduces a thousand-line sequence numbered from 601 through 1600.
X
X\S{cnum.c PROGRAM TEXT}
X\listing{../iex/cnum.c}
X\eject
SHAR_EOF
$TOUCH -am 0512211990 iman/iopt.tex &&
chmod 0644 iman/iopt.tex ||
echo "restore of iman/iopt.tex failed"
set `wc -c iman/iopt.tex`;Wc_c=$1
if test "$Wc_c" != "5407"; then
echo original size 5407, current size $Wc_c
fi
# ============= iman/iread.tex ==============
echo "x - extracting iman/iread.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/iread.tex &&
X% XREF iread
X
X\def\name{IREAD}
X\def\IT{{\bb iread()}}
X
X\S{NAME}
X{\bb iread} --- read file into buffer at mallocp, return file size
X
X\S{SYNOPSIS}
X{\obeylines \bb
Xint
Xiread (fname, mallocp)
Xchar *fname;
Xchar **mallocp;
X}
X
X\S{DESCRIPTION}
X\IT\ is a convenient subroutine for reading a file into
Xinternal space. \IT\ ascertains that the file
Xspecified by {\myit fname\/} is readable,
Xthen {\myit malloc\/}s a suitable buffer, reads
Xthe file into the buffer, closes the file, and returns the
Xfile size.
X\L
XIn somewhat more detail,
X{\myit fname\/} is opened with {\myit "r"\/} access,
Xdynamic memory is allocated (one
Xbyte greater than the size of the file) at
Xthe address of {\myit mallocp\/},
Xthe file image is transfered into the buffer, the extra byte after the
Xlast byte of the image is set to 0,
Xthe file is closed, and the byte count of the file is returned
X(not including the extra byte).
X\L
XNULL file names or zero length files trigger error returns of
X{\myit -sys\_nerr\/}. Failing system calls ({\myit read(), fstat(),
Xmalloc()\/}) produce negative {\myit errno\/} return values, as
Xdescribed under {\myit ierror()\/}.
XA valid string passed as {\myit fname\/} together with
X{\myit (char **)NULL\/} for {\myit mallocp\/},
Xreturns 0 or -1, depending on whether
X{\myit fname\/} is readable or not.
X
X\S{SEE ALSO}
X{\myit ifilter, iwrite, ierror\/}.
X
X\S{untab EXAMPLE PROGRAM}
XThe majority of example programs in this manual call \IT,
Xso the decision to list the {\bb untab} program as the
X\IT\ example is arbitrary. {\bb untab}
Xexpands tab characters to spaces in a list of files, similarly to
Xthe Unix program {\myit expand\/}, but effecting in-place
Xtransformation. That is, the source files themselves change without
X\stio. Additionally, all non-printing characters
X(tab, space, form-feed, bell, etc.) are deleted between the
Xlast printing character and the {\myit newline\/}
Xcharacter of each line.
XThe size of the required
X{\myit tab stops\/} and at least one filename
Xmust follow the command name on the command line:
X\smallskip
X\I{\mytt untab 8 *.c}
X\smallskip
Xspecifies that tabs are to be expanded to spaces assuming ``hard''
Xtabstops at every eight columns,
Xin each file whose name ends with {\myit .c\/}.
X{\bb untab} reports the number of each file's original tab characters,
Xto \stout, in the format also used by the {\myit mung\/} program
Xexample.
X
X\S{untab.c PROGRAM TEXT}
X\listing{../iex/untab.c}
X\eject
SHAR_EOF
$TOUCH -am 0513092590 iman/iread.tex &&
chmod 0644 iman/iread.tex ||
echo "restore of iman/iread.tex failed"
set `wc -c iman/iread.tex`;Wc_c=$1
if test "$Wc_c" != "2424"; then
echo original size 2424, current size $Wc_c
fi
# ============= iman/irotate.tex ==============
echo "x - extracting iman/irotate.tex (Text)"
sed 's/^X//' << 'SHAR_EOF' > iman/irotate.tex &&
X% XREF ilongest irotate itexrect
X
X\def\name{IROTATE}
X\def\IT{{\bb irotate()}}
X
X\S{NAME}
X{\bb irotate} --- rotate passed text in newly allocated buffer,
Xreturn size
X
X{\bb itexrect} --- create rectangular array from lines of varying length
X
X{\bb ilongest} --- find longest line in buffer
X
X\S{SYNOPSIS}
X{
X\settabs\+{\bb mdefine IROTOR} & mmm &\cr
X\+{\bb\#define IROTR}&\hfill {\bb1}&
X\kern 3em/* 90\deg\ to right */\cr
X\+{\bb\#define IROTL}&\hfill {\bb--1}&
X\kern 3em/* 90\deg\ to left */\cr
X\+{\bb\#define IROTOR}&\hfill {\bb3}&
X\kern 3em/* 180\deg\ over and 90\deg\ to right */\cr
X\+{\bb\#define IROTOL}&\hfill {\bb--3}&
X\kern 3em/* 180\deg\ over and 90\deg\ to left */\cr
X}
X\L
X{\obeylines \bb
Xint
Xirotate (start, llength, lcount, mallocp, type)
Xchar *start;
Xchar **mallocp;
Xint llength;
Xint lcount;
Xint type;
X\L
Xint
Xitexrect (start, end, mallocp, lcount)
Xchar *start;
Xchar *end;
Xchar **mallocp;
Xint *lcount;
X\L
Xint
Xilongest (start, end, lcount)
Xchar *start;
Xchar *end;
Xint *lcount;
X}
X
X\S{DESCRIPTION}
XThe \IT\ function rotates {\myit text rectangles\/} (twodimensional,
Xrectangular text arrays without embedded line-terminating
X{\myit newlines\/}) 90\deg\ clockwise or counterclockwise,
Xand also 180\deg\ in
Xdepth. Prior to a call to \IT, the calling process creates the
Xtext rectangle either by laying equal-sized strings end-to-end in
Xa buffer, or by calling {\bb itexrect()\/} to space fill and
Xremove newlines from arbitrary, ``straight'' text.
X\L
X\IT\ reads {\myit lcount\/} strings each {\myit llength\/} bytes,
Xfrom the passed buffer dereferenced by {\myit start\/}, interpreting
Xbuffer data as a twodimensional array of {\myit llength\/} columns and
X{\myit lcount\/} rows. To store the rotated version of this array,
X\IT\ allocates a new buffer and passes back the address of the
Xnew buffer in {\myit mallocp\/}. Either of the four rotation
X{\myit type\/}s --- {\myit IROTR, IROTL, IROTOR, IROTOL\/} ---
Xproduces a target array in which the rows of the original array
Xwill have become columns, and vice versa. To facilitate the
Xprinting of the new array, each new row (line) now ends with a
X{\myit newline\/} terminator.
XThe target array size returned by \IT\ includes the line-terminating
X{\myit newline\/}s, but does not report an available,
Xextra NUL byte appended to the end of the target array.
X\L
XBoth {\myit lcount\/} and {\myit llength\/} must be positive: zero or
Xnegative values
Xtrigger error returns of {\myit -sys\_nerr\/}. If
X{\myit malloc()\/} cannot allocate the new array, \IT\ returns
Xthe negative {\myit errno\/}, as described under {\myit ierror()\/}.
X\L
X{\bb itexrect()} is a support function for \IT, called before
Xthe \IT\ call is made, to
X``pad'' irregular lines of source text beginning at {\myit start\/}
Xand ending with the byte before {\myit end\/}.
XThe {\bb itexrect()} function itself calls {\bb ilongest()} to
Xfind out how many lines there are in the buffer delimited by
X{\myit start\/} and {\myit end\/}, and to receive the byte count of
Xthe longest line. Lines are assumed to end with either a
X{\myit newline\/} character, or with a NUL byte; the line-terminating
Xbyte is not included in the line length returned by
X{\bb ilongest()}. The number of lines is passed back from
X{\bb ilongest()} via the {\myit int *lcount\/}.
X\L
XUsing the line size and line count
Xinformation produced by {\bb ilongest()},
X{\bb itexrect()} allocates
Xa new buffer at {\myit mallocp\/}, and
Xcopies each line of the source buffer into the new buffer.
XEach line is space-filled to end flush with the longest line,
Xand line-terminating {\myit newline\/}s or NUL bytes are omitted.
X\L
X{\bb itexrect()} transfers back the buffer size information to its
Xcaller identically to
X{\bb ilongest()}: the number of lines is passed back
Xvia {\myit int *lcount\/}, and the size of the longest line of the
Xoriginal text is returned.
XAlso, {\myit mallocp\/} is pointed
Xto the address of the new buffer now containing the concatenated,
Xspace-padded list of strings.
X\L
XThe {\myit lcount\/} parameter of both
X{\bb ilongest()} and
X{\bb itexrect()}, and
Xthe {\myit mallocp\/} parameter of
X{\bb itexrect()} are used only for returning data to the calling
Xfunction. Values dereferenced by these pointers prior to the calls
Xwill be ignored and overwritten. The {\myit start, end\/}
Xparameters are tested in the customary manner.
XIf {\myit malloc()\/} fails,
X{\bb itexrect()} returns
Xthe negative {\myit errno\/}, as described under {\myit ierror()\/}.
X
X\S{rot EXAMPLE PROGRAM}
XThe obvious example for
Xillustrating calls to a function that rotates text in
Xinternal space is the {\bb rot} program, reading input and outputting
Xa rotated version.
XIn order to do away with command line options that would prescribe
Xthe direction of the rotation,
Xthe executable {\bb rot} is given alias names {\bb rotr},
X{\bb rotl},
X{\bb rotor},
X{\bb rotol},
Xvia the Unix {\myit ln\/} command in the compile script.
X{\bb rotl} will stand for ``rotate 90\deg\ to the left'',
X{\bb rotr} will stand for ``rotate 90\deg\ to the right'',
X{\bb rotol} indicates that the text is to be flipped over
X(so that the top line becomes the bottom line) and then rotated
X90\deg\ to the left, and
X{\bb rotor} would flip the text over and rotate it
X90\deg\ to the right.
X\L
XThe process adds the bytes of its own command name
X({\myit argv[0]\/}) to generate a primitive hash value stored in the
X{\myit context\/} variable.
XThis sum is used to decode which rotation {\myit type\/} the user
Xwanted. The base command name {\bb rot} does not specify
Xa rotation type; it prints a ``usage'' message instead.
XBecause there are no command line options, it is easy to implement
X{\bb rot} as a filter: if a file name follows the command, the text
Xof the file is the input; otherwise text read from \stin\ until
X{\myit EOF\/} is rotated. Results are printed to \stout.
X\L
XAs an example of using {\bb rot}, suppose one is to create
Xa ``driving~distances'' table from a list of a dozen cities. The
Xsomewhat cryptic command sequence
X\smallskip
X\I{\mytt xec echo XnewXnewXnew > head}
X\I{\mytt cat list >> head}
X\I{\mytt mung Xnew XnewXnewXnewXnew head}
X\smallskip
Xappends a copy of the
X{\myit list\/} of the cities,
Xto a new file {\myit head\/} (containing just four
X{\myit newline\/}s to start with),
Xand then adds three blank lines after each line
Xof {\myit head\/} (see
Xthe description of the {\myit mung\/} program under {\myit ierror()\/}
Xfor an explanation of the {\myit mung\/}
Xcommand syntax, or {\myit ifonetic()\/} for the phonetic control
Xcharacter codes). The next commands use {\bb rotor} to flip the
Xexpanded list of {\myit head\/} ``over and to the right'';
Xthen add the original list at the end
X\smallskip
X\I{\mytt rotor head > distances}
X\I{\mytt cat list >> distances}
X\smallskip
Xto produce the following text in the file {\myit distances\/}:
X\L
X{\obeylines \mytt
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ A\ \ \ C\ \ \ G\ \ \ M\ \ \ M\ \ \ N\ \ \ O\ \ \ S\ \ \ T\ \ \ T\ \ \ V\ \ \ Z
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ C\ \ \ A\ \ \ U\ \ \ A\ \ \ E\ \ \ O\ \ \ A\ \ \ A\ \ \ I\ \ \ O\ \ \ E\ \ \ A
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ A\ \ \ N\ \ \ A\ \ \ Z\ \ \ R\ \ \ G\ \ \ X\ \ \ L\ \ \ J\ \ \ R\ \ \ R\ \ \ C
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ P\ \ \ C\ \ \ Y\ \ \ A\ \ \ I\ \ \ A\ \ \ A\ \ \ T\ \ \ U\ \ \ R\ \ \ A\ \ \ A
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ U\ \ \ U\ \ \ A\ \ \ T\ \ \ D\ \ \ L\ \ \ C\ \ \ I\ \ \ A\ \ \ E\ \ \ C\ \ \ T
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ L\ \ \ N\ \ \ M\ \ \ L\ \ \ I\ \ \ E\ \ \ A\ \ \ L\ \ \ N\ \ \ O\ \ \ R\ \ \ E
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ C\ \ \ \ \ \ \ A\ \ \ A\ \ \ A\ \ \ S\ \ \ \ \ \ \ L\ \ \ A\ \ \ N\ \ \ U\ \ \ C
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ O\ \ \ \ \ \ \ S\ \ \ N\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ O\ \ \ \ \ \ \ \ \ \ \ Z\ \ \ A
X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ S
XACAPULCO
XCANCUN
XGUAYAMAS
XMAZATLAN
XMERIDIA
XNOGALES
XOAXACA
XSALTILLO
XTIJUANA
XTORREON
XVERACRUZ
XZACATECAS
X}
X\L
XAll that remains is to fill the table with the mileage numbers.
X
X\S{rot.c PROGRAM TEXT}
X\listing{../iex/rot.c}
X\eject
SHAR_EOF
$TOUCH -am 0608101690 iman/irotate.tex &&
chmod 0644 iman/irotate.tex ||
echo "restore of iman/irotate.tex failed"
set `wc -c iman/irotate.tex`;Wc_c=$1
if test "$Wc_c" != "8081"; then
echo original size 8081, current size $Wc_c
fi
echo "End of part 8, continue with part 9"
exit 0
--
Istvan Mohos
...uunet!pyrdc!pyrnj!hhb!istvan
RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
======================================================================