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: <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
- ======================================================================
-