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 >
Internet Message Format  |  1990-12-28  |  55KB

  1. From: istvan@hhb.UUCP (Istvan Mohos)
  2. Newsgroups: alt.sources
  3. Subject: Subject: ILIB Unix Toolkit in C
  4. Message-ID: <554@hhb.UUCP>
  5. Date: 8 Jun 90 20:59:11 GMT
  6.  
  7.  
  8. ---- Cut Here and unpack ----
  9. #!/bin/sh
  10. # This is part 08 of a multipart archive
  11. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  12.  then TOUCH=touch
  13.  else TOUCH=true
  14. fi
  15. # ============= iman/ihash.tex ==============
  16. echo "x - extracting iman/ihash.tex (Text)"
  17. sed 's/^X//' << 'SHAR_EOF' > iman/ihash.tex &&
  18. X% XREF ihash ihasharg
  19. X
  20. X\def\name{IHASH}
  21. X\def\IT{{\bb ihash()}}
  22. X\def\ALT{{\bb ihasharg()}}
  23. X
  24. X\S{NAME}
  25. X{\bb ihash} --- return checksum of string
  26. X
  27. X{\bb ihasharg} --- return checksum of upcased final component of pathname
  28. X
  29. X\S{SYNOPSIS}
  30. X{\obeylines \bb
  31. Xint
  32. Xihash (ptr, modval, upcase)
  33. Xchar *ptr;
  34. Xint modval;
  35. Xint upcase;
  36. X\L
  37. Xint
  38. Xihasharg (ptr, delim)
  39. Xchar *ptr;
  40. Xchar delim;
  41. X}
  42. X
  43. X\S{DESCRIPTION}
  44. X\IT\ calculates a "sum-of-bytes" value of
  45. Xthe null terminated string at {\myit ptr\/}, and
  46. Xreturns
  47. Xthis value if {\myit modval\/} is zero.
  48. XIf {\myit modval\/} is non-zero, \IT\
  49. Xdivides the calculated sum by
  50. X{\myit modval\/} and returns the remainder.
  51. XIf the \IT\ {\myit upcase\/} is {\myit TRUE\/},
  52. Xlower case alphabetic characters of the source string
  53. Xare summed as upper case bytes.
  54. X\L
  55. X\ALT\ operates similarly to \IT, but computes a
  56. Xvalue for the
  57. Xlast component of a {\myit pathname\/} only.  \ALT\ is not
  58. Xcase sensitive:
  59. Xeach lower case letter of the
  60. Xexamined string is always summed as if it was upper case.
  61. X\L
  62. XThe primitive {\myit hash values\/} returned by \IT\ and \ALT\
  63. Xsee use in a somewhat crude but speedy
  64. Xalternative to repeated calls to
  65. X{\myit strcmp()\/}.  Care must be taken that differing
  66. Xstrings contrasted this way don't produce the same sum of bytes, an
  67. Xevent called "collision".
  68. X\L
  69. XIf {\myit ptr\/} is NULL or the string at {\myit ptr\/} is zero length,
  70. X{\myit ierflag\/} is set and negative
  71. X{\myit sys\_nerr} is returned.
  72. X
  73. X\S{PROGRAM EXAMPLES}
  74. XA number of ILIB program examples such as
  75. X{\bb nest}, {\bb ego}, {\bb rot}, as well as the
  76. Xexample programs {\bb trunc} and {\bb lhash} listed here, decode the
  77. Xidentity of {\myit argv[0]\/} via the \ALT\ function.
  78. XThe single executable produced from the source text by the C~compiler
  79. Xis given one or more alternate names with the Unix {\myit ln\/}
  80. Xcommand.  From then on, calling the command by any of its
  81. X{\myit alias\/}es will bring the
  82. Xsame process to life; but the process knows the name
  83. Xthat caused its execution, and can produce different results
  84. Xfor one name than for another.
  85. XThe name of these example programs (stored in {\myit argv[0]\/} under
  86. Xthe C environment) is passed to \ALT\ which then searches
  87. Xfor the rightmost \key{/}\ {\myit delim\/} character.
  88. X\ALT\  returns the sum of the upcased bytes past {\myit delim\/}.
  89. XThe user program then contrasts the returned sum against a
  90. Xlist of predefined constants, each recognized as a
  91. X{\myit hash value\/} of a specific name among the various alternates.
  92. X\L
  93. X{\bb trunc} is a very simple program reading lines from \stin, and
  94. Xwriting them to \stout, truncating (suppressing) output beyond a
  95. Xgiven column position of each line.  The maximum byte count of each
  96. Xline (the number of the column beyond which the output is suppressed),
  97. Xis the sole, required argument on the command line.
  98. XLines that are shorter than or equal to the specified length are
  99. Xoutput without change.  The line terminating
  100. X{\myit newline\/} characters do not contribute to the byte count.
  101. XWhen called by its {\bb leftrunc} alias, the program skips over the
  102. Xspecified number of leading bytes of each line, and prints the rest
  103. Xof the line instead.  If the line is shorter than or equal to the
  104. Xskip length given, just a {\myit newline\/} character is printed.
  105. X
  106. X\S{trunc.c PROGRAM TEXT}
  107. X\listing{../iex/trunc.c}
  108. X
  109. X\S{lhash PROGRAM}
  110. X{\bb lhash} and its alias {\bb uhash} are aides in generating lines
  111. Xfor {\myit hash tables\/} included in other user source.
  112. XInput data to {\bb lhash} or {\bb uhash} is typically a list of tokens,
  113. Xeach token on a line by itself.
  114. X{\bb lhash} sums the bytes of each input line (but not the terminating
  115. X{\myit newline\/}), and outputs each sum as an ASCII decimal string
  116. Xon a line by itself.  {\bb uhash} converts each lower case character
  117. Xin the input to its upper case equivalent prior to summing.
  118. X\L
  119. XThe {\myit -m modval\/} command line option allows the specification
  120. Xof an upper cutoff limit: each computed sum is divided by
  121. X{\myit modval\/} and the remainder of the operation is output as the
  122. X{\myit hash value\/}.  The {\myit -p\/},
  123. X{\myit -l\/}, or
  124. X{\myit -t\/} options each expect a {\myit printf()\/} format string
  125. Xto follow the option flag, and will use this string to embed the
  126. Xcomputed hash value into a string constant of the user's choice.
  127. XAs an example,
  128. X\smallskip
  129. X\I{\mytt uhash -t '\#define \%-10.10s \%d' < weekdays}
  130. X\smallskip
  131. Xwould produce the following output from the file {\myit weekdays\/}
  132. Xof seven lines:
  133. X\L
  134. X{\obeylines \mytt
  135. X\#define\ Sunday\ \ \ \ \ 468
  136. X\#define\ Monday\ \ \ \ \ 456
  137. X\#define\ Tuesday\ \ \ \ 543
  138. X\#define\ Wednesday\ \ 676
  139. X\#define\ Thursday\ \ \ 628
  140. X\#define\ Friday\ \ \ \ \ 447
  141. X\#define\ Saturday\ \ \ 621
  142. X\smallskip}
  143. XThe {\myit -t} format option signifies that the output value is to
  144. Xtrail the reprint of the input token being summed; the
  145. X{\myit printf()\/} string after the format flag contains a {\myit \%s\/}
  146. Xformat specifier for the input token, preceding the {\myit \%d\/}
  147. Xspecifier for the {\myit hash value\/}.
  148. X\L
  149. XThe {\myit -p} format option stands for ``plain'', and does not
  150. Xreprint the original token.
  151. XThis option only expects a
  152. X{\myit \%d\/} format
  153. Xspecifier for the hash value within the
  154. X{\myit printf()\/} string.
  155. X\L
  156. XThe {\myit -l\/} variation indicates that the sum is to be printed
  157. Xfirst:
  158. X\smallskip
  159. X\I{\mytt uhash \ -m23 \ -l'/*\%3d\ */\ \lcu"\%s"\rcu,' \ < weekdays}
  160. X\smallskip
  161. X{\obeylines \mytt
  162. X/*\ \ 8\ */\ \lcu"Sunday"\rcu,
  163. X/*\ 19\ */\ \lcu"Monday"\rcu,
  164. X/*\ 14\ */\ \lcu"Tuesday"\rcu,
  165. X/*\ \ 9\ */\ \lcu"Wednesday"\rcu,
  166. X/*\ \ 7\ */\ \lcu"Thursday"\rcu,
  167. X/*\ 10\ */\ \lcu"Friday"\rcu,
  168. X/*\ \ 0\ */\ \lcu"Saturday"\rcu,
  169. X\smallskip}
  170. X
  171. X\S{lhash.c PROGRAM TEXT}
  172. X\listing{../iex/lhash.c}
  173. X\eject
  174. SHAR_EOF
  175. $TOUCH -am 0607124590 iman/ihash.tex &&
  176. chmod 0644 iman/ihash.tex ||
  177. echo "restore of iman/ihash.tex failed"
  178. set `wc -c iman/ihash.tex`;Wc_c=$1
  179. if test "$Wc_c" != "5655"; then
  180.     echo original size 5655, current size $Wc_c
  181. fi
  182. # ============= iman/ihms.tex ==============
  183. echo "x - extracting iman/ihms.tex (Text)"
  184. sed 's/^X//' << 'SHAR_EOF' > iman/ihms.tex &&
  185. X% XREF ihms
  186. X
  187. X\def\name{IHMS}
  188. X\def\IT{{\bb ihms()}}
  189. X
  190. X\S{NAME}
  191. X{\bb ihms} --- convert duration from seconds to hh:mm:ss, time events
  192. X
  193. X\S{SYNOPSIS}
  194. X{\obeylines \bb
  195. Xchar *
  196. Xihms (key)
  197. Xint key;
  198. X}
  199. X
  200. X\S{DESCRIPTION}
  201. X\IT\ converts arbitrary positive
  202. Xinteger {\myit key\/}s
  203. Xto ``hours:minutes:seconds'' strings.  Each of the three fields
  204. Xdelimited by the \key{:} is a two digit number.  The range of both
  205. X{\myit minutes\/}
  206. Xand {\myit seconds\/} is 0--59; {\myit hours\/} are shown
  207. Xbetween 0 and 23 inclusive, with no provisions for multi-day overflow.
  208. XThe returned string is null terminated, without a
  209. X{\myit newline\/} at the end.
  210. X\L
  211. XIf {\myit key\/} is negative, \IT\ takes a snapshot of the
  212. Xcurrent Unix {\myit realtime\/} kept by the operating system in a
  213. X{\myit seconds counter\/} incremented from zero since
  214. X00:00:00 Greenwich Mean Time, January 1 1970.
  215. X\IT\ stores this value in a static variable for further
  216. Xreference, and returns the NULL pointer.
  217. X\L
  218. XAt subsequent calls whenever 0 is passed as the {\myit key\/} value,
  219. X\IT\ subtracts the stored reference time from the instantaneous time
  220. Xat the call, and returns the elapsed time since the reference call,
  221. Xformatted \dx{hh:mm:ss}.
  222. X\L
  223. XIn the absence of a call with a negative {\myit key\/}, calls passing
  224. X0 values receive \dx{hh:mm:ss}\ stamps of
  225. XGreenwhich Mean Time at the instantaneous time of the call.
  226. X\eject
  227. SHAR_EOF
  228. $TOUCH -am 0530133190 iman/ihms.tex &&
  229. chmod 0644 iman/ihms.tex ||
  230. echo "restore of iman/ihms.tex failed"
  231. set `wc -c iman/ihms.tex`;Wc_c=$1
  232. if test "$Wc_c" != "1362"; then
  233.     echo original size 1362, current size $Wc_c
  234. fi
  235. # ============= iman/iinput.tex ==============
  236. echo "x - extracting iman/iinput.tex (Text)"
  237. sed 's/^X//' << 'SHAR_EOF' > iman/iinput.tex &&
  238. X% XREF iinput
  239. X
  240. X\def\name{IINPUT}
  241. X\def\IT{{\bb iinput()}}
  242. X
  243. X\S{NAME}
  244. X{\bb iinput} --- get a string from \stin\ after \sterr\ prompt
  245. X
  246. X\S{SYNOPSIS}
  247. X{\obeylines \bb
  248. Xint
  249. Xiinput (ptr, message)
  250. Xchar *ptr;
  251. Xchar *message;
  252. X}
  253. X
  254. X\S{DESCRIPTION}
  255. X\IT\ writes its passed {\myit message\/} to \sterr, leaves
  256. Xthe cursor immediately after the printed {\myit message\/}, and reads
  257. Xthe user's response from \stin\ into the caller's buffer passed as
  258. X{\myit ptr\/}.
  259. X\IT\ returns the size of the user's NUL terminated response, in bytes.
  260. XNegative {\myit sys\_nerr\/} is returned via {\myit ierror()\/} if
  261. Xthe NULL pointer is passed as either argument.
  262. X
  263. X\S{inum PROGRAM EXAMPLE}
  264. XThe {\bb inum}
  265. Xprogram is a copy of the {\bb cnum} program described under IOPT.
  266. XWhile functionally the two programs are nearly identical, {\bb inum}
  267. Xconducts a dialogue with the user, prompting the user for the
  268. Xline numbering format, instead of parsing the command line for the list
  269. Xof specifications as {\bb cnum} does. \IT\ is a convenient vehicle
  270. Xfor question-and-answer pairs; and the dialogue has the advantage of
  271. Xleaving the user free from the burdens of the command line syntax,
  272. Xas well as ensuring that all pertinent format specifiers will get
  273. Xconsidered.
  274. XThe disadvantage is that the dialogue monopolizes \sterr\ and \stin\
  275. Xfor passing messages between the user and the program: unlike
  276. X{\bb cnum}, {\bb inum} cannot be made a filter.
  277. X
  278. X\S{inum.c PROGRAM TEXT}
  279. X\listing{../iex/inum.c}
  280. X\eject
  281. SHAR_EOF
  282. $TOUCH -am 0512211290 iman/iinput.tex &&
  283. chmod 0644 iman/iinput.tex ||
  284. echo "restore of iman/iinput.tex failed"
  285. set `wc -c iman/iinput.tex`;Wc_c=$1
  286. if test "$Wc_c" != "1453"; then
  287.     echo original size 1453, current size $Wc_c
  288. fi
  289. # ============= iman/iline.tex ==============
  290. echo "x - extracting iman/iline.tex (Text)"
  291. sed 's/^X//' << 'SHAR_EOF' > iman/iline.tex &&
  292. X% XREF iline
  293. X
  294. X\def\name{ILINE}
  295. X\def\IT{{\bb iline()}}
  296. X
  297. X\S{NAME}
  298. X{\bb iline} --- find {\myit newline\/}, null it, return line size
  299. X
  300. X\S{SYNOPSIS}
  301. X{\obeylines \bb
  302. Xint
  303. Xiline (start, end)
  304. Xchar *start;
  305. Xchar *end;
  306. X}
  307. X
  308. X\S{DESCRIPTION}
  309. X\IT\ seeks out the first {\myit unescaped newline\/} from
  310. Xthe beginning of the buffer delimited by {\myit start\/},
  311. X{\myit end\/}, and changes the {\myit newline\/} byte to NUL
  312. X(ASCII 0).
  313. XIf  the {\myit end\/} is reached but a {\myit newline\/} was not
  314. Xfound,
  315. Xthe byte immediately before {\myit end\/} is changed into NUL.
  316. XThe search is unhindered by other NUL bytes that may already be
  317. Xpresent in the buffer; \IT\ will skip over these.
  318. X\L
  319. XThe returned value is the byte count of the string between
  320. X{\myit start\/} and the nulled {\myit newline\/}, {\bb including}
  321. Xthe terminating NUL byte.
  322. X
  323. X\S{ncat PROGRAM EXAMPLE}
  324. XThe {\bb ncat} program produces a ``line numbered'' listing of files
  325. Xsimilarly to the {\myit cat -n\/} command of BSD Unix (the {\myit -n\/}
  326. Xoption is absent in System~V).  The principal difference is that the
  327. XBSD {\myit cat\/} keeps incrementing line numbers across a list of
  328. Xfiles specified on the command line, whereas {\bb ncat\/} restarts
  329. Xnumbering from line~1, for each file.  Additionally, {\bb ncat\/}
  330. Xtakes an optional ``separator'' or ``spooler'' line that it will
  331. Xprepend to each file (such as {\myit formfeed\/} characters or
  332. X{\myit page break\/} macros).
  333. XFonetic control characters of the separator string are converted to
  334. Xreal values by a call to {\myit ifonetic\/}; and in addition
  335. X{\bb ncat} converts \key{\dol} characters of the separator
  336. X(given in either the real or the phonetic form) to the
  337. Xfile name of the next file to be spooled.
  338. XA {\myit newline\/} is {\bb not}
  339. Xautomatically appended to the separator string.  The mechanism
  340. Xmakes {\bb ncat} useful for
  341. Xsetting up printer ``spooler'' queues.  {\bb ncat} caters to Unix and
  342. XC syntax by recognizing that text lines terminated with escaped
  343. X{\myit newlines} logically belong
  344. Xto the next line, and prepends just one line number to the first
  345. Xline of escaped multi-line groups.
  346. X
  347. X\S{ncat.c PROGRAM TEXT}
  348. X\listing{../iex/ncat.c}
  349. X\eject
  350. SHAR_EOF
  351. $TOUCH -am 0529112190 iman/iline.tex &&
  352. chmod 0644 iman/iline.tex ||
  353. echo "restore of iman/iline.tex failed"
  354. set `wc -c iman/iline.tex`;Wc_c=$1
  355. if test "$Wc_c" != "2144"; then
  356.     echo original size 2144, current size $Wc_c
  357. fi
  358. # ============= iman/ilist.tex ==============
  359. echo "x - extracting iman/ilist.tex (Text)"
  360. sed 's/^X//' << 'SHAR_EOF' > iman/ilist.tex &&
  361. X% XREF ilist ilistn illistn
  362. X
  363. X\def\name{ILIST}
  364. X\def\IT{{\bb ilist()}}
  365. X\def\ALT{{\bb illistn()}}
  366. X
  367. X\S{NAME}
  368. X{\bb ilist} --- create array of pointers to non-null strings in buffer
  369. X
  370. X{\bb ilistn} --- create array of pointers to strings in buffer
  371. X
  372. X{\bb illistn} --- create array of pointers to lines in buffer
  373. X
  374. X\S{SYNOPSIS}
  375. X{\obeylines \bb
  376. Xint
  377. Xilist (start, end, delims, ptrlist)
  378. Xchar *start;
  379. Xchar *end;
  380. Xchar *delims;
  381. Xchar **ptrlist;
  382. X\L
  383. Xint
  384. Xilistn (start, end, delims, ptrlist)
  385. Xchar *start;
  386. Xchar *end;
  387. Xchar *delims;
  388. Xchar **ptrlist;
  389. X\L
  390. Xint
  391. Xillistn (start, end, ptrlist)
  392. Xchar *start;
  393. Xchar *end;
  394. Xchar **ptrlist;
  395. X}
  396. X
  397. X\S{DESCRIPTION}
  398. X
  399. XThe \IT\ functions break up text in the buffer delimited by
  400. X{\myit start\/} and {\myit end\/} into null-terminated strings,
  401. Xand provide a list of {\myit char pointers\/} to the caller such
  402. Xthat successive pointers in the list will point to successive
  403. Xnull-terminated strings of the original buffer.  The pointer list
  404. Xin all cases will contain a final {\myit sentinel\/} pointer set
  405. Xto NULL.
  406. X\L
  407. XThe functions return the number of null-terminated strings counted in
  408. Xthe buffer (the count not including the extra pointer appended to the
  409. Xlist), and make the address of the dynamically allocated memory
  410. Xavailable
  411. Xvia {\myit ptrlist\/}.
  412. XThe {\myit ptrlist\/} argument is generally of type
  413. X{\myit (char~*)\/} passed by address.
  414. X\L
  415. XThe \ALT\ function assumes that data in the buffer is to be segmented
  416. Xat every {\myit newline\/} character; and changes all
  417. X{\myit newline\/}s
  418. Xwithin the buffer into NUL (zero) bytes.  To safeguard the caller
  419. Xagainst accidentally
  420. Xoverrunning an un-terminated buffer (if the byte preceding {\myit end\/}
  421. Xwas not a {\myit newline\/}), \ALT\ automatically dubs
  422. Xthe last byte of the buffer to be a {\myit newline\/}, and converts
  423. Xit to NUL.
  424. XIf the size of the passed buffer is zero, \ALT\ cannot guarantee
  425. Xa terminal NUL byte; however the sentinel pointer will still be
  426. Xallocated and made available to the caller.
  427. X\L
  428. X\IT\ and {\bb ilistn()} both segment the buffer at each byte
  429. Xin the buffer that matches any character of the {\myit delims\/} string:
  430. Xall characters in the buffer
  431. Xrecognized as belonging to the delimiter character set, are
  432. Xconverted into
  433. XNUL bytes.  \IT\ then sets successive pointers to null-terminated
  434. Xstrings
  435. Xthat are at least one byte long; zero-sized strings are skipped.
  436. XThe other functions allocate pointers even to zero-sized strings;
  437. Xin the case of \ALT\ this produces pointers to blank lines.
  438. X\L
  439. XPassed
  440. X{\myit (char~*)NULL start\/}
  441. Xaddress,
  442. X{\myit (char~*)NULL\/} or zero-length
  443. X{\myit delims\/}
  444. Xtrigger
  445. Xerror reporting via {\myit ierror()\/}, and produce return values of
  446. X{\myit --sys\_nerr\/}.
  447. X
  448. X\S{lcat PROGRAM EXAMPLE}
  449. XThe {\bb lcat} program serves to print
  450. X(``{\myit cat\/}'' in the Unix jargon) a specific line
  451. Xor a specific block of lines from the lines of input,
  452. Xto \stout.  {\bb lcat} is a filter.  The starting
  453. Xline number and the file name are mandatory command line parameters.
  454. XWithout the {\myit plus option\/}
  455. Xthe selected line of each file is printed, provided that the
  456. Xinput has that many lines.
  457. XThe optional solo \key{+} flag on the command line forces the
  458. Xprinting of all remaining lines.  A
  459. X\key{+} flag immediately followed by a number, forces the printing
  460. Xof that many successive lines after the starting line.
  461. X({\bb lcat} does not use {\myit iopt()\/} for parsing the command
  462. Xline options, and consequently is too myopic to correctly
  463. Xrecognize the {\myit M\/} parameter if it is separated from its
  464. X\key{+} flag.)
  465. X\L
  466. XHaving examined the command line, the process reads the input into
  467. Xan internal buffer via {\myit ifilter()\/},
  468. Xand sets up a pointer list to lines of
  469. Xthe buffer with {\bb illistn()}.  Because line numbering conventionally
  470. Xbegins at 1 but C's array indices start at 0, the starting line is
  471. Xfound by using {\myit N--1\/} as the offset into the line list.
  472. XIf line {\myit N+M} would lie beyond the end of the input, the
  473. Xrest of the buffer is output line-by-line; otherwise the {\myit M\/}
  474. Xlines following line {\myit N\/} are printed.  Note that the
  475. Xrepeated calls to the {\myit puts()\/} function
  476. Xfor printing successive lines
  477. Xrepresent a computational
  478. Xoverhead that is tolerated here since the use of the
  479. X{\myit plus option\/} is expected to be minimal.
  480. X\L
  481. X{\bb lcat} works well in concert with the {\myit grep~--n\/}
  482. Xcommand that produces the line number(s) of
  483. Xregular expressions recognized in a file.  Often the user wants to
  484. Xsee the next few lines as well, but this capability is not provided
  485. Xby {\myit grep\/}.  The following one-liner shell script (named
  486. X{\myit grep\tt+\/}) takes as its first parameter
  487. Xthe additional number of lines that the user wants printed, followed by
  488. Xthe searched-for word and a filename:
  489. X\smallskip
  490. X{\obeylines \mytt
  491. Xlcat\ `grep -n "\$2" \$3|lcat 1|fcat 1 \ -d':' ` \ +\$1 \ \$3
  492. X\smallskip}
  493. X{\myit grep\/} may find more than one instance of the pattern, in
  494. Xwhich case only the first one will pass the embedded {\bb lcat} pipe.
  495. XFor example, the command
  496. X\smallskip
  497. X\I{\mytt grep+ 2 \ 'ilib.a:' \ ../i/makefile}
  498. X\smallskip
  499. Xsearches for the {\myit ilib.a:\/} target in {\myit makefile\/}, and
  500. Xprints the line of the target, plus
  501. Xthe next two lines.
  502. X
  503. X\S{lcat.c PROGRAM TEXT}
  504. X\listing{../iex/lcat.c}
  505. X
  506. X\S{scat PROGRAM EXAMPLE}
  507. XThe {\bb scat} program is a direct derivative of {\bb lcat},
  508. Xreading its input as a filter and
  509. Xprinting to \stout\ the first input line that
  510. Xcontains a specified string.
  511. XA string pattern and
  512. Xa file name are positionally fixed mandatory command line parameters.
  513. XA second string may be given after the first with the
  514. X\dx{--s \ {\myit string}\/}\ or
  515. X\dx{--s{\myit string\/}}\ option, and will precipitate the printing
  516. Xof successive lines after the first line, until a text line
  517. Xis encountered that contains the second ({\myit stop\/}) string.
  518. X\L
  519. XThe program structure is similar to that of {\bb lcat}, but
  520. Xinstead of indexing into the pointer list returned by
  521. X{\bb illistn()}, lines marked by
  522. Xadjacent pointers of the pointer list
  523. Xare successively passed to {\myit ianymatch()\/}
  524. Xfor pattern matching.
  525. X{\bb scat} puts the text ending {\myit sentinel\/} pointer returned
  526. Xby {\bb illistn()} to good use in limiting the iteration count of
  527. Xthe {\myit for loops\/}, and in being able to set
  528. Xthe {\myit look-ahead\/} pointer to an address beyond the last line of
  529. Xthe text buffer.
  530. X
  531. X\S{scat.c PROGRAM TEXT}
  532. X\listing{../iex/scat.c}
  533. X\eject
  534. SHAR_EOF
  535. $TOUCH -am 0607125990 iman/ilist.tex &&
  536. chmod 0644 iman/ilist.tex ||
  537. echo "restore of iman/ilist.tex failed"
  538. set `wc -c iman/ilist.tex`;Wc_c=$1
  539. if test "$Wc_c" != "6383"; then
  540.     echo original size 6383, current size $Wc_c
  541. fi
  542. # ============= iman/ilower.tex ==============
  543. echo "x - extracting iman/ilower.tex (Text)"
  544. sed 's/^X//' << 'SHAR_EOF' > iman/ilower.tex &&
  545. X% XREF ilower iupper
  546. X
  547. X\def\name{ILOWER}
  548. X\def\IT{{\bb ilower()}}
  549. X\def\ALT{{\bb iupper()}}
  550. X
  551. X\S{NAME}
  552. X{\bb ilower} --- change alphabetic characters in buffer to lower case
  553. X
  554. X{\bb iupper} --- change alphabetic characters in buffer to upper case
  555. X
  556. X\S{SYNOPSIS}
  557. X{\obeylines \bb
  558. Xint
  559. Xilower (start, end)
  560. Xchar *start;
  561. Xchar *end;
  562. X\L
  563. Xint
  564. Xiupper (start, end)
  565. Xchar *start;
  566. Xchar *end;
  567. X}
  568. X
  569. X\S{DESCRIPTION}
  570. X\IT\ and \ALT\ implement table-driven, {\myit en masse\/}
  571. Xconversion of alphabetic
  572. Xcharacters in the buffer delimited by {\myit start\/} and
  573. X{\myit end\/} to lower case or upper case values
  574. Xrespectively, and return the byte length of the buffer.
  575. XThe method is faster than the bitwise conversion implemented by
  576. Xthe standard {\myit tolower()\/} and {\myit toupper()\/} macros,
  577. Xbut the tables are specific to the ASCII character set.
  578. X
  579. X\S{up PROGRAM EXAMPLE}
  580. XThe simplicity of the \IT, \ALT\
  581. Xfunction interface allows fairly dense coding
  582. Xwithout loosing readability.  The {\bb up}/{\bb down}
  583. Xprogram translates multiple files to all upper case
  584. Xor to all lower case.  The program is not a filter; it alters
  585. Xthe source text of files.
  586. X
  587. X\S{up.c PROGRAM TEXT}
  588. X\listing{../iex/up.c}
  589. X\eject
  590. SHAR_EOF
  591. $TOUCH -am 0531090290 iman/ilower.tex &&
  592. chmod 0644 iman/ilower.tex ||
  593. echo "restore of iman/ilower.tex failed"
  594. set `wc -c iman/ilower.tex`;Wc_c=$1
  595. if test "$Wc_c" != "1168"; then
  596.     echo original size 1168, current size $Wc_c
  597. fi
  598. # ============= iman/imatch.tex ==============
  599. echo "x - extracting iman/imatch.tex (Text)"
  600. sed 's/^X//' << 'SHAR_EOF' > iman/imatch.tex &&
  601. X% XREF ianymatch imatch ixmatch
  602. X
  603. X\def\name{IMATCH}
  604. X\def\IT{{\bb imatch()}}
  605. X\def\ALT{{\bb ixmatch()}}
  606. X
  607. X\S{NAME}
  608. X{\bb imatch} --- find a specific token or token head in a buffer
  609. X
  610. X{\bb ianymatch} --- find a specific string in a buffer
  611. X
  612. X{\bb ixmatch} --- find a specific token in a buffer
  613. X
  614. X\S{SYNOPSIS}
  615. X{\obeylines \bb
  616. Xchar *
  617. Ximatch (start, end, str)
  618. Xchar *start;
  619. Xchar *end;
  620. Xchar *str;
  621. X\L
  622. Xchar *
  623. Xianymatch (start, end, str)
  624. Xchar *start;
  625. Xchar *end, *str;
  626. X\L
  627. Xchar *
  628. Xixmatch (start, end, word)
  629. Xchar *start;
  630. Xchar *end;
  631. Xchar *word;
  632. X}
  633. X
  634. X\S{DESCRIPTION}
  635. X\IT\ attempts to find a byte sequence in the buffer bounded by
  636. X{\myit start\/} and {\myit end\/}, that matches the specified
  637. X{\myit str\/}.  A comparison is performed at the first byte of
  638. Xevery {\myit token\/} of the buffer, proceeding from left to right.
  639. XTokens in the buffer are delimited by {\myit white space\/}.
  640. XThe search stops as soon as {\myit str\/} can be made to exactly
  641. Xcoincide with a buffer segment that began a token;
  642. Xand the buffer address of this token is returned.
  643. XThe search is case sensitive.
  644. XIf no match is found, \IT\ returns the NULL pointer.
  645. X\L
  646. XThe search by \ALT\ is slightly more demanding in that
  647. Xthe (last) token of a matching buffer segment must be a fully formed
  648. Xtoken, terminating identically to the {\myit word\/} of the
  649. Xcomparison.
  650. X\L
  651. XGiven an example buffer, containing:
  652. X\smallskip
  653. X\I{\dx{Heart of gold}}
  654. X\smallskip
  655. Xneither function would find a match to \dx{ear}\ or \dx{art}.  \ALT\
  656. Xwould produce matches to full word combinations.  Various calls to
  657. X\IT\ would produce
  658. Xadditional matches over truncated tokens, as in \dx{He}, \dx{Hear},
  659. X\dx{Heart o}, \dx{of go}, and so on.
  660. X\L
  661. X{\bb ianymatch()} finds a buffer segment that matches {\myit str\/},
  662. Xwithout any of the token boundary restrictions of either \IT\ or
  663. X\ALT.
  664. X\L
  665. XAll three functions flag  invalid buffers or zero-length comparison
  666. Xstrings by calling {\myit ierror()\/}.
  667. X
  668. X\S{rename EXAMPLE PROGRAM}
  669. XWhen working with lists of related files, the {\bb rename} program
  670. Xcan assist in making global changes to file names.  The first
  671. Xparameter given after {\bb rename} on the command line specifies
  672. Xthe string that needs to be replaced in each of the file names
  673. Xtrailing in the command line, with the string given as the
  674. Xsecond parameter.  For example, the command sequence
  675. X\smallskip
  676. X\I{\mytt split /usr/dict/words}
  677. X\I{\mytt rename x words. *}
  678. X\smallskip
  679. Xfirst breaks up the word list {\myit /usr/dict/words\/} to twentyfive
  680. Xfiles each a
  681. Xhundred lines long, naming the new files
  682. X{\myit xaa, xab, xac...\/} (the file naming option of {\myit split\/}
  683. Xhas been purposely omitted from the command, to
  684. Xdemonstrate {\bb rename}).  {\bb rename} changes \key{x}\
  685. Xto \dx{words.}\ in each of the file names, so a
  686. Xdirectory listing
  687. Xwill produce
  688. X{\myit words.aa words.ab words.ac\/} and so on.  To avoid
  689. Xchanging the first
  690. X`x' character in the names of existing files with longer names,
  691. Xthe file list given at the end of the {\bb rename} command
  692. Xcoulde be more restrictive:
  693. X\smallskip
  694. X\I{\mytt rename x words. x??}
  695. X\L
  696. X{\bb rename} requires at least four tokens on the command line:
  697. Xits own name, the string to be replaced, the new replacement string,
  698. Xand a file name.  A ``usage'' message is printed if not enough
  699. Xtokens are specified.  Null strings can be specified by typing a
  700. Xsingle \key{-} instead of a string.  If the \key{-} stands
  701. Xfor the string to be replaced, it is interpreted loosely as
  702. X``the first nothing in the file name is to be replaced with:''
  703. Xand the replacement string is then prepended in front of
  704. Xthe existing file
  705. Xname.  If the \key{-} is given as the replacement string,
  706. Xthe ``string to be replaced'' is replaced with nothing, gets
  707. Xdeleted in effect from the file name.
  708. X\L
  709. X{\bb rename} prints an error message and leaves the file
  710. Xname (and the file) intact if directory permissions prevent the
  711. Xrenaming process, or if the newly created
  712. Xfile name exactly matches another
  713. Xfile name in the directory.
  714. X
  715. X\S{rename.c PROGRAM TEXT}
  716. X\listing{../iex/rename.c}
  717. X\eject
  718. SHAR_EOF
  719. $TOUCH -am 0607134590 iman/imatch.tex &&
  720. chmod 0644 iman/imatch.tex ||
  721. echo "restore of iman/imatch.tex failed"
  722. set `wc -c iman/imatch.tex`;Wc_c=$1
  723. if test "$Wc_c" != "3998"; then
  724.     echo original size 3998, current size $Wc_c
  725. fi
  726. # ============= iman/imode.tex ==============
  727. echo "x - extracting iman/imode.tex (Text)"
  728. sed 's/^X//' << 'SHAR_EOF' > iman/imode.tex &&
  729. X% XREF imode
  730. X
  731. X\def\name{IMODE}
  732. X\def\IT{{\bb imode()}}
  733. X
  734. X\S{NAME}
  735. X{\bb imode} --- find out if specified file permission bits are set
  736. X
  737. X\S{SYNOPSIS}
  738. X\settabs\+{\bb mdefine ISUSTICKY} & 00000000000 &\cr
  739. X\+{\bb\#define ISSOCK }&{\bb 0140000}&{\mytt/* socket */}\cr
  740. X\+{\bb\#define ISLNK  }&{\bb 0120000}&{\mytt/* symbolic link */}\cr
  741. X\+{\bb\#define ISREG  }&{\bb 0100000}&{\mytt/* regular */}\cr
  742. X\+{\bb\#define ISBLK  }&{\bb 0060000}&{\mytt/* block special */}\cr
  743. X\+{\bb\#define ISDIR  }&{\bb 0040000}&{\mytt/* directory */}\cr
  744. X\+{\bb\#define ISCHR  }&{\bb 0020000}&{\mytt/* character special */}\cr
  745. X\+{\bb\#define ISFIFO }&{\bb 0010000}&{\mytt/* named pipe */}\cr
  746. X\+{\bb\#define ISUID  }&{\bb 0004000}&{\mytt/* set uid on execution */}\cr
  747. X\+{\bb\#define ISGID  }&{\bb 0002000}&{\mytt/* set gid on execution */}\cr
  748. X\+{\bb\#define ISSTICK}&{\bb 0001000}&{\mytt/* keep text in memory (sticky bit) */}\cr
  749. X\+{\bb\#define ISROWN }&{\bb 0000400}&{\mytt/* read, owner */}\cr
  750. X\+{\bb\#define ISWOWN }&{\bb 0000200}&{\mytt/* write, owner */}\cr
  751. X\+{\bb\#define ISXOWN }&{\bb 0000100}&{\mytt/* execute/search, owner */}\cr
  752. X\+{\bb\#define ISRGRP }&{\bb 0000040}&{\mytt/* read, group */}\cr
  753. X\+{\bb\#define ISWGRP }&{\bb 0000020}&{\mytt/* write, group */}\cr
  754. X\+{\bb\#define ISXGRP }&{\bb 0000010}&{\mytt/* execute/search, group */}\cr
  755. X\+{\bb\#define ISRALL }&{\bb 0000004}&{\mytt/* read, others */}\cr
  756. X\+{\bb\#define ISWALL }&{\bb 0000002}&{\mytt/* write, others */}\cr
  757. X\+{\bb\#define ISXALL }&{\bb 0000001}&{\mytt/* execute/search, others */}\cr
  758. X\L
  759. X{\obeylines \bb
  760. Xint
  761. Ximode (fname, perm)
  762. Xchar *fname;
  763. Xint perm;
  764. X}
  765. X
  766. X\S{DESCRIPTION}
  767. X\IT\ is a convenient {\myit shortcut\/} for querying the permission
  768. Xmode of a file.  \IT\ itself calls {\myit stat()\/}, so the user
  769. Xcode doesn't have to.  The true value of {\myit perm\/} is
  770. Xirrelevant, except insofar as it specifies the {\myit permission bits\/}
  771. Xsubject to the query.  If {\myit file\/} has all those permission bits
  772. Xset that are of interest to the user, \IT\ returns TRUE, else it
  773. Xreturns FALSE.  For example,
  774. X\smallskip
  775. X\I{\mytt imode ("/bin", ISDIR \pip\ ISWGRP);}
  776. X\smallskip
  777. Xwould return TRUE if the {\myit /bin\/} directory was writable by
  778. X{\myit group\/}, but it would return FALSE if {\myit /bin\/}
  779. Xwas not a directory or if {\myit group\/} did not have write
  780. Xpermission.  \IT\ ``knows'' how to interpret the upper four
  781. X{\myit file type\/} permission bits, and will correctly differentiate
  782. Xbetween a directory and a socket, for example.
  783. XThe familiar octal permission strings may be passed as {\myit perm\/}
  784. Xinstead of, or mixed with the symbolic constants defined in
  785. X{\myit ilib.h\/}:
  786. X\smallskip
  787. X\I{\mytt imode ("../etc/motd", ISREG \pip\ 0444);}
  788. X\smallskip
  789. Xwould return TRUE if
  790. X{\myit ../etc/motd\/} was a regular file writable by owner, group,
  791. Xand others.
  792. X\L
  793. X\IT\ calls {\myit ierror()\/} and returns {\myit -sys\_nerr\/} if
  794. X{\myit fname\/} is NULL or has no length, or negative {\myit errno\/} if
  795. Xthe call to {\myit stat()\/} fails.
  796. XIf {\myit perm\/} is zero, \IT\ returns the full permission value
  797. Xgotten with the {\myit stat()\/} call in {\myit sbuf.st\_mode}.
  798. X
  799. X\S{unlink PROGRAM EXAMPLE}
  800. XBecause the effects of the Unix {\myit rm} command are irreversible
  801. Xin most cases, many programmers enclose the interactive form of the
  802. X{\myit rm\/} command in a script named {\myit rm\/}, or use the
  803. Xinteractive command as an {\myit alias\/}; in either case overlaying
  804. Xthe original name with a duplicate command name that executes
  805. Xdifferently.
  806. XWhen the time comes to bypass the interactive form (to avoid
  807. Xforever having to respond ``y''
  808. Xwhen removing a long list of files), the programmer has to remember
  809. Xto type the full {\myit /bin/rm\/} path to bypass the
  810. Xinteractive version, and presumably would specify
  811. Xthe {\myit -f\/} flag to force non-interactive removal of
  812. X{\myit read-only\/} files.  Add to this the ``solo minus'' or
  813. X``null option'' flag
  814. Xto be able to remove files whose names begin with \key{-},
  815. Xand the snowballing complexity of the non-interactive remove syntax
  816. Xmay warrant a simple, brute-force alternative: {\bb unlink}.
  817. X\L
  818. X{\bb unlink} removes the files (except directories)
  819. Xin its argument list, if at all possible in the given user environment.
  820. XIf a file
  821. Xcannot be found or cannot be removed (because of lacking permissions
  822. Xto {\myit write\/} the directory containing the file), {\bb unlink}
  823. Xoutputs an error message to this effect to \sterr, and continues
  824. Xremoving the other files in the list.  The {\myit unlink()\/}
  825. Xsystem command on which the program is based, will normally fail when
  826. Xtrying to
  827. Xremove directories, unless the process is executed by
  828. Xthe {\myit super user\/}.  Because removing a directory would orphan
  829. Xany sub-file-system contained within that directory, {\bb unlink}
  830. Xprevents even the superuser from removing a directory, by querying
  831. Xthe status of files with \IT, and skipping directories.
  832. X
  833. X\S{unlink.c PROGRAM TEXT}
  834. X\listing{../iex/unlink.c}
  835. X\eject
  836. SHAR_EOF
  837. $TOUCH -am 0529112090 iman/imode.tex &&
  838. chmod 0644 iman/imode.tex ||
  839. echo "restore of iman/imode.tex failed"
  840. set `wc -c iman/imode.tex`;Wc_c=$1
  841. if test "$Wc_c" != "4921"; then
  842.     echo original size 4921, current size $Wc_c
  843. fi
  844. # ============= iman/inest.tex ==============
  845. echo "x - extracting iman/inest.tex (Text)"
  846. sed 's/^X//' << 'SHAR_EOF' > iman/inest.tex &&
  847. X% XREF inest
  848. X
  849. X\def\name{INEST}
  850. X\def\IT{{\bb inest()}}
  851. X
  852. X\S{NAME}
  853. X{\bb inest} --- create array of {\myit int\/}s to nest information
  854. X
  855. X\S{SYNOPSIS}
  856. X{\obeylines \bb
  857. Xint
  858. Xinest (start, end, ldelim, rdelim, infopair)
  859. Xchar *start;
  860. Xchar *end;
  861. Xchar *ldelim;
  862. Xchar *rdelim;
  863. Xint \ **infopair;
  864. X}
  865. X
  866. X\S{DESCRIPTION}
  867. X\IT\ reads the buffer delimited by {\myit start\/} and {\myit end\/},
  868. Xand counts the total number of distinct
  869. X{\myit ldelim\/} and {\myit rdelim\/} strings.  An integer array
  870. Xis allocated next.  The buffer is then re-parsed,
  871. Xand for each encountered left or right delimiter
  872. X\IT\ loads the offset from {\myit start\/} to the first
  873. Xbyte of the delimiter into the next cell of the array, and the
  874. X``nest-level'' of the delimiter
  875. Xinto the cell after the cell of the offset.  In this way, the array
  876. Xis filled with integer pairs of {\myit offset, nest-level\/}.
  877. XThe
  878. Xnest-level of each left delimiter is stored as a positive number,
  879. Xnest-levels of right delimiters are stored as negative numbers.
  880. XThe internal nest-level counter gets incremented for every
  881. Xsuccessive {\myit ldelim\/} encountered in the text,
  882. Xand gets decremented at every {\myit rdelim\/}.  If an
  883. X{\myit rdelim\/} is found when the nest-level is zero, the counter
  884. Xdoes not get decremented further; the nest-level of the right
  885. Xdelimiter is recorded as zero.
  886. X\L
  887. X\IT\ returns the sum of {\myit ldelim\/}s and {\myit rdelim\/}s
  888. Xfound in the buffer,  and the
  889. X{\myit malloc\/}'d buffer address via {\myit infopair\/}.
  890. X{\myit infopair\/} is of
  891. Xtype ``{\myit pointer to an array of ints\/}'', and will
  892. Xnormally be an
  893. X{\myit (int *)\/} passed by address.
  894. X\L
  895. XNULL or zero-length delimiters, identical left/right delimiters,
  896. Xor ``overlapping'' delimiters trigger error returns of
  897. X{\myit -sys\_nerr\/}.  Failing {\myit malloc\/} calls produce a
  898. Xnegative {\myit errno\/} return value, as
  899. Xdescribed under {\myit ierror()\/}.
  900. X\IT\ identifies an overlap condition if the two delimiters exactly 
  901. Xmatch from their beginning
  902. X'til the end of the shorter delimiter.
  903. XFor example, the \dx{if} \dx{ifend}\ pair or
  904. Xthe \dx{ifstart} \dx{if}\ pair 
  905. Xare both overlapping, whereas
  906. Xnone of the \dx{if} \dx{endif},
  907. X\dx{startif} \dx{if},
  908. X\dx{ifstart} \dx{ifend}\ pairs are.
  909. X
  910. X\S{nest PROGRAM EXAMPLE}
  911. XThe {\bb nest} program described here
  912. Xoutputs (to \stout) information about the distribution and relative
  913. Xsymmetry of matched pairs of delimiters in a file.  In particular,
  914. Xthe file is assumed to be C text: one of the first actions during
  915. Xthe process is to suppress all comment strings within the file.
  916. XBecause of this, the {\bb nest} program is not suitable for
  917. Xretrieving information relating to the comment delimiter pair
  918. X\twokey{/*} and \twokey{*/}.
  919. X\L
  920. XThe program decodes the
  921. Xidentity of {\myit argv[0]\/} via the {\myit ihashargv()\/} function,
  922. Xas described under the IHASH entry.
  923. XThe single executable produced from the source text by the C~compiler
  924. Xis given the alternate name {\bb nestinfo} with the Unix {\myit ln\/}
  925. Xcommand.  Calling the command by either {\bb nest}
  926. Xor {\bb nestinfo} will therefore bring the
  927. Xsame process to life; but the process recognizes the name
  928. Xthat caused its execution and produces different results
  929. Xfor {\bb nest} than for {\bb nestinfo}.
  930. X{\bb nestinfo} outputs a terse, single line summary about the delimiters
  931. Xfound in the file.  A sample command line and its output:
  932. X\smallskip
  933. X\I{\mytt nestinfo ifdef endif nest.c}
  934. X\smallskip
  935. X\I{\mytt 1 ifdef 1 endif matched}
  936. X\L
  937. X{\bb nest} prints a line numbered, indented
  938. Xlist of the encountered {\myit nest levels\/}:
  939. X\smallskip
  940. X\I{\mytt nest \ \bsl\lcu\ \ \bsl\rcu\ \ nest.c}
  941. X\smallskip
  942. X{\mytt
  943. X\I{15\ \ \lcu}
  944. X\I{58\ \ \ \ \ \ \lcu}
  945. X\I{69\ \ \ \ \ \ \rcu}
  946. X\I{78\ \ \ \ \ \ \lcu}
  947. X\I{85\ \ \ \ \ \ \rcu}
  948. X\I{87\ \ \rcu}
  949. X\smallskip}
  950. X
  951. XBecause {\myit istripcom()\/} not only suppresses comments, but also
  952. Xalters the line numbering of the text ({\myit newline\/} characters
  953. Xwithin comments are changed to spaces), the {\myit illistn()\/}
  954. Xcall sets up a list of pointers to the original lines first.
  955. XThe first {\myit int\/} of each pair of the {\myit infopairs\/} list
  956. Xreturned from \IT\ show the offset of the given delimiter from the
  957. Xbeginning of the text; this is converted to the actual address by
  958. Xadding it to the base address of the text buffer.  The address of the
  959. Xdelimiter is then contrasted against the address of successive lines
  960. X(stored via the pointers of the list returned by
  961. X{\myit illistn()\/}) to find the original line number of the
  962. Xdelimiter.
  963. X
  964. X\S{nest.c PROGRAM TEXT}
  965. X\listing{../iex/nest.c}
  966. X\eject
  967. SHAR_EOF
  968. $TOUCH -am 0529112090 iman/inest.tex &&
  969. chmod 0644 iman/inest.tex ||
  970. echo "restore of iman/inest.tex failed"
  971. set `wc -c iman/inest.tex`;Wc_c=$1
  972. if test "$Wc_c" != "4513"; then
  973.     echo original size 4513, current size $Wc_c
  974. fi
  975. # ============= iman/ioctal.tex ==============
  976. echo "x - extracting iman/ioctal.tex (Text)"
  977. sed 's/^X//' << 'SHAR_EOF' > iman/ioctal.tex &&
  978. X% XREF ioctal
  979. X
  980. X\def\name{IOCTAL}
  981. X\def\IT{{\bb ioctal()}}
  982. X
  983. X\S{NAME}
  984. X{\bb ioctal} --- convert octal digit strings to {\myit int}
  985. X
  986. X\S{SYNOPSIS}
  987. X{\obeylines \bb
  988. Xint
  989. Xioctal (ptr)
  990. Xchar *ptr;
  991. X}
  992. X
  993. X\S{DESCRIPTION}
  994. X\IT\ converts a digit string to a value, and returns this value.
  995. X\IT\ expects the passed parameter {\myit ptr\/}
  996. Xto point to an octal string,
  997. Xrecognizing only the digits \key{0} through \key{7}, and ignoring
  998. Xall leading and embedded {\myit white space\/}.  The conversion
  999. Xends at the first unrecognized character, or at the NUL byte
  1000. Xterminating the string.  There are no provisions for overflow.
  1001. XThe princpal use for \IT\ is in parsing the command line for
  1002. Xoctal Unix ``permission strings''.
  1003. X\L
  1004. X\IT\ calls {\myit ierror()\/} and returns {\myit -sys\_nerr\/}
  1005. Xif {\myit ptr\/} is the NULL pointer.
  1006. X\eject
  1007. SHAR_EOF
  1008. $TOUCH -am 0509104190 iman/ioctal.tex &&
  1009. chmod 0644 iman/ioctal.tex ||
  1010. echo "restore of iman/ioctal.tex failed"
  1011. set `wc -c iman/ioctal.tex`;Wc_c=$1
  1012. if test "$Wc_c" != "807"; then
  1013.     echo original size 807, current size $Wc_c
  1014. fi
  1015. # ============= iman/iopt.tex ==============
  1016. echo "x - extracting iman/iopt.tex (Text)"
  1017. sed 's/^X//' << 'SHAR_EOF' > iman/iopt.tex &&
  1018. X% XREF iopt
  1019. X
  1020. X\def\name{IOPT}
  1021. X\def\IT{{\bb iopt()}}
  1022. X
  1023. X\S{NAME}
  1024. X{\bb iopt} --- command line option manager
  1025. X
  1026. X\S{SYNOPSIS}
  1027. X{\obeylines \bb
  1028. Xint
  1029. Xiopt (ptr)
  1030. Xchar ***ptr;
  1031. X}
  1032. X
  1033. X\S{DESCRIPTION}
  1034. X\IT\ is a dynamic parser for command line options, in the genre of
  1035. Xvarious C {\myit getopt\/} routines.  The main strength of
  1036. X\IT\ is its ease of use, rather than an all-encompassing
  1037. Xparser mechanism that could evaluate any possible option and flag
  1038. Xcombinations.
  1039. X\IT\ operates on the following simple types of
  1040. Xoption-flag/option-value pairs:
  1041. X\smallskip
  1042. X{\myit
  1043. X\I{{\bb--c}value}
  1044. X\I{{\bb--c} \ value}
  1045. X\I{{\bb--}}
  1046. X}
  1047. X\smallskip
  1048. XThat is, the list of options on the parsed command line must form
  1049. X{\myit flag/value\/} pairs except for the solo minus option;
  1050. Xeach {\myit flag\/}
  1051. Xis an arbitrary single character immediately
  1052. Xappended past a minus sign, and each {\myit value\/} is
  1053. Xan arbitrary token either adjoining or separate from its {\myit flag\/}.
  1054. XThe {\myit ptr\/} parameter passed to \IT\ is generally of type
  1055. X{\myit pointer to an array of strings\/} (such as the {\myit argv\/}
  1056. Xlist in {\myit main\/}) passed by address.
  1057. X\L
  1058. X\IT\ is usually called
  1059. Xrepeatedly, in a loop.  The function
  1060. Xreturns the integer ASCII value of the flag character `{\bb c}'
  1061. X(but returns `{\bb--}' for the solo minus option), and
  1062. Xautomatically re-positions the passed-in pointer to the
  1063. X{\myit value\/} component of the option pair (not advancing it
  1064. Xin the case of the solo minus).
  1065. X\IT\ also remembers
  1066. Xthe location of the next, not yet evaluated argument, and will
  1067. Xautomatically continue parsing from it during the next call.  In
  1068. Xthis way, the calling function has only to initialize the passed-in
  1069. Xpointer to the first command line argument; \IT\ does the rest.
  1070. XInformation passed in after the first call, will be ignored.
  1071. XOnce the flag/value list is exhausted
  1072. X(when the first character of an evaluated
  1073. Xargument pair is not `{\bb--}')
  1074. Xzero is returned instead of the
  1075. Xflag value, and at this point \IT\ has positioned
  1076. X{\myit ptr\/} to the first argument after the option list.
  1077. XThis allows easy continuation with trailing non-option items
  1078. Xon the command line, such as a list of files.
  1079. X\L
  1080. XAlternately, \IT\ may be called a selected number of times such that
  1081. Xat the last call \IT\ is not aware that the flag/value parsing is about
  1082. Xto come to an end.  At the last call, \IT\ will have returned the given
  1083. Xflag character, and will have repositioned {\myit ptr\/} to point to the
  1084. X{\myit value\/} component of the flag/value pair.  In order to
  1085. Xadvance the pointer to the next argument after the last {\myit value\/}
  1086. Xthe pointer should now be explicitly incremented.
  1087. X\L
  1088. XAn example of flag/value pairs in a typical option list:
  1089. X\smallskip
  1090. X\I{{\bb--A}\quad{\myit opt1\/}\quad{\bb--B}{\myit
  1091. Xopt2\/}\quad{\bb--C}\quad{\myit
  1092. Xopt3\/}\quad{\bb--}
  1093. X\quad{\bb--D}{\myit opt5\/}\quad more\_args\quad\mydots
  1094. X}
  1095. X\smallskip
  1096. XSuccessive calls to this list would return with {\myit ptr\/} pointing
  1097. Xto {\myit opt1, opt2, opt3, --, opt5\/} and finally to
  1098. X{\myit more\_args\/}; int values returned
  1099. Xwould be 65, 66, 67, 45, 68 and 0.
  1100. X\L
  1101. XIf the last argument in the command line
  1102. Xis an option flag ({\bb--c}) without a trailing
  1103. X{\myit option\/} value,
  1104. Xit is rejected from evaluation: the search stops and the option flag
  1105. Xwill be handled as the first non-option argument.
  1106. X\L
  1107. XThe \IT\ code contains
  1108. Xno system calls that could set the global
  1109. X{\myit errno\/}, and does not
  1110. Xaffect the {\myit ierflag\/} or {\myit ierbuf\/} variables used by
  1111. X{\myit ierror()\/} under
  1112. XILIB's error reporting.
  1113. X
  1114. X\S{cnum EXAMPLE PROGRAM}
  1115. XThe line numbering program {\bb cnum\/} described here calls
  1116. X\IT\ exhaustively,
  1117. Xin a loop.  Another example {\bb ncat} described under ILINE,
  1118. Xcalls \IT\ only once.
  1119. X{\bb cnum\/} copies a file to \stout, annotating lines of the input
  1120. Xwith a customized number sequence.
  1121. X{\bb cnum\/} can put line
  1122. Xnumbers in front of lines, or at the end of lines; numbers can be
  1123. Xdecimal, octal, lowercase or uppercase hexadecimal.  The starting
  1124. Xline number as well as the
  1125. Xincrement or decrement to the next line can be arbitrary
  1126. Xintegers.  Numbers can be
  1127. Xleft or right justified in a desired field width; right
  1128. Xjustified numbers may be printed with leading zeros.
  1129. XA user-supplied string may precede the line numbers, another string
  1130. Xmay follow the line numbers, and a third
  1131. Xstring may be appended at the end of the input lines themselves.
  1132. X\L
  1133. XThe numbering format is controlled through a long but simple list of
  1134. Xcommand line options;
  1135. X\IT\ is called to evaluate the command line.
  1136. XIn the absence of command line
  1137. Xarguments, {\bb cnum} prints a ``usage'' message to \sterr, summarizing
  1138. Xthe meaning and syntax of the various options.
  1139. XAn example {\bb cnum\/} command line
  1140. X\smallskip
  1141. X\I{\mytt
  1142. Xcnum -p August -a "th was a " -s6 -t. -j3}
  1143. X\smallskip
  1144. Xtransforms the days of the week (each input on a line by itself) to:
  1145. X\smallskip
  1146. X{\mytt
  1147. X\I{August \ 6th was a Sunday.}
  1148. X\I{August \ 7th was a Monday.}
  1149. X\I{August \ 8th was a Tuesday.}
  1150. X\I{August \ 9th was a Wednesday.}
  1151. X\I{August 10th was a Thursday.}
  1152. X\I{August 11th was a Friday.}
  1153. X\I{August 12th was a Saturday.}
  1154. X}
  1155. X\L
  1156. XIf no file name is given at the end of the option list, \stin\ is
  1157. Xread.  The user can also number a nonexistent file of
  1158. X{\myit N\/} lines, by using the {\bb--c N} option:
  1159. X\smallskip
  1160. X\I{\mytt
  1161. Xcnum -c 1000 -s 601}
  1162. X\smallskip
  1163. Xproduces a thousand-line sequence numbered from 601 through 1600.
  1164. X
  1165. X\S{cnum.c PROGRAM TEXT}
  1166. X\listing{../iex/cnum.c}
  1167. X\eject
  1168. SHAR_EOF
  1169. $TOUCH -am 0512211990 iman/iopt.tex &&
  1170. chmod 0644 iman/iopt.tex ||
  1171. echo "restore of iman/iopt.tex failed"
  1172. set `wc -c iman/iopt.tex`;Wc_c=$1
  1173. if test "$Wc_c" != "5407"; then
  1174.     echo original size 5407, current size $Wc_c
  1175. fi
  1176. # ============= iman/iread.tex ==============
  1177. echo "x - extracting iman/iread.tex (Text)"
  1178. sed 's/^X//' << 'SHAR_EOF' > iman/iread.tex &&
  1179. X% XREF iread
  1180. X
  1181. X\def\name{IREAD}
  1182. X\def\IT{{\bb iread()}}
  1183. X
  1184. X\S{NAME}
  1185. X{\bb iread} --- read file into buffer at mallocp, return file size
  1186. X
  1187. X\S{SYNOPSIS}
  1188. X{\obeylines \bb
  1189. Xint
  1190. Xiread (fname, mallocp)
  1191. Xchar *fname;
  1192. Xchar **mallocp;
  1193. X}
  1194. X
  1195. X\S{DESCRIPTION}
  1196. X\IT\ is a convenient subroutine for reading a file into
  1197. Xinternal space.  \IT\ ascertains that the file
  1198. Xspecified by {\myit fname\/} is readable,
  1199. Xthen {\myit malloc\/}s a suitable buffer, reads
  1200. Xthe file into the buffer, closes the file, and returns the
  1201. Xfile size.
  1202. X\L
  1203. XIn somewhat more detail,
  1204. X{\myit fname\/} is opened with {\myit "r"\/} access,
  1205. Xdynamic memory is allocated (one
  1206. Xbyte greater than the size of the file) at
  1207. Xthe address of {\myit mallocp\/},
  1208. Xthe file image is transfered into the buffer, the extra byte after the
  1209. Xlast byte of the image is set to 0,
  1210. Xthe file is closed, and the byte count of the file is returned
  1211. X(not including the extra byte).
  1212. X\L
  1213. XNULL file names or zero length files trigger error returns of
  1214. X{\myit -sys\_nerr\/}.  Failing system calls ({\myit read(), fstat(),
  1215. Xmalloc()\/}) produce negative {\myit errno\/} return values, as
  1216. Xdescribed under {\myit ierror()\/}.
  1217. XA valid string passed as {\myit fname\/} together with 
  1218. X{\myit (char **)NULL\/} for {\myit mallocp\/},
  1219. Xreturns 0 or -1, depending on whether
  1220. X{\myit fname\/} is readable or not.
  1221. X
  1222. X\S{SEE ALSO}
  1223. X{\myit ifilter, iwrite, ierror\/}.
  1224. X
  1225. X\S{untab EXAMPLE PROGRAM}
  1226. XThe majority of example programs in this manual call \IT,
  1227. Xso the decision to list the {\bb untab} program as the
  1228. X\IT\ example is arbitrary. {\bb untab}
  1229. Xexpands tab characters to spaces in a list of files, similarly to
  1230. Xthe Unix program {\myit expand\/}, but effecting in-place
  1231. Xtransformation.  That is, the source files themselves change without
  1232. X\stio.  Additionally, all non-printing characters
  1233. X(tab, space, form-feed, bell, etc.) are deleted between the
  1234. Xlast printing character and the {\myit newline\/}
  1235. Xcharacter of each line.
  1236. XThe size of the required
  1237. X{\myit tab stops\/} and at least one filename
  1238. Xmust follow the command name on the command line:
  1239. X\smallskip
  1240. X\I{\mytt untab 8 *.c}
  1241. X\smallskip
  1242. Xspecifies that tabs are to be expanded to spaces assuming ``hard''
  1243. Xtabstops at every eight columns,
  1244. Xin each file whose name ends with {\myit .c\/}.
  1245. X{\bb untab} reports the number of each file's original tab characters,
  1246. Xto \stout, in the format also used by the {\myit mung\/} program
  1247. Xexample.
  1248. X
  1249. X\S{untab.c PROGRAM TEXT}
  1250. X\listing{../iex/untab.c}
  1251. X\eject
  1252. SHAR_EOF
  1253. $TOUCH -am 0513092590 iman/iread.tex &&
  1254. chmod 0644 iman/iread.tex ||
  1255. echo "restore of iman/iread.tex failed"
  1256. set `wc -c iman/iread.tex`;Wc_c=$1
  1257. if test "$Wc_c" != "2424"; then
  1258.     echo original size 2424, current size $Wc_c
  1259. fi
  1260. # ============= iman/irotate.tex ==============
  1261. echo "x - extracting iman/irotate.tex (Text)"
  1262. sed 's/^X//' << 'SHAR_EOF' > iman/irotate.tex &&
  1263. X% XREF ilongest irotate itexrect
  1264. X
  1265. X\def\name{IROTATE}
  1266. X\def\IT{{\bb irotate()}}
  1267. X
  1268. X\S{NAME}
  1269. X{\bb irotate} --- rotate passed text in newly allocated buffer,
  1270. Xreturn size
  1271. X
  1272. X{\bb itexrect} --- create rectangular array from lines of varying length
  1273. X
  1274. X{\bb ilongest} --- find longest line in buffer
  1275. X
  1276. X\S{SYNOPSIS}
  1277. X{
  1278. X\settabs\+{\bb mdefine IROTOR} & mmm &\cr
  1279. X\+{\bb\#define IROTR}&\hfill    {\bb1}&
  1280. X\kern 3em/* 90\deg\ to right */\cr
  1281. X\+{\bb\#define IROTL}&\hfill  {\bb--1}&
  1282. X\kern 3em/* 90\deg\ to left */\cr
  1283. X\+{\bb\#define IROTOR}&\hfill   {\bb3}&
  1284. X\kern 3em/* 180\deg\ over and 90\deg\ to right */\cr
  1285. X\+{\bb\#define IROTOL}&\hfill {\bb--3}&
  1286. X\kern 3em/* 180\deg\ over and 90\deg\ to left */\cr
  1287. X}
  1288. X\L
  1289. X{\obeylines \bb
  1290. Xint
  1291. Xirotate (start, llength, lcount, mallocp, type)
  1292. Xchar *start;
  1293. Xchar **mallocp;
  1294. Xint llength;
  1295. Xint lcount;
  1296. Xint type;
  1297. X\L
  1298. Xint
  1299. Xitexrect (start, end, mallocp, lcount)
  1300. Xchar *start;
  1301. Xchar *end;
  1302. Xchar **mallocp;
  1303. Xint *lcount;
  1304. X\L
  1305. Xint
  1306. Xilongest (start, end, lcount)
  1307. Xchar *start;
  1308. Xchar *end;
  1309. Xint *lcount;
  1310. X}
  1311. X
  1312. X\S{DESCRIPTION}
  1313. XThe \IT\ function rotates {\myit text rectangles\/} (twodimensional,
  1314. Xrectangular text arrays without embedded line-terminating
  1315. X{\myit newlines\/}) 90\deg\ clockwise or counterclockwise,
  1316. Xand also 180\deg\ in
  1317. Xdepth.  Prior to a call to \IT, the calling process creates the
  1318. Xtext rectangle either by laying equal-sized strings end-to-end in
  1319. Xa buffer, or by calling {\bb itexrect()\/} to space fill and
  1320. Xremove newlines from arbitrary, ``straight'' text.
  1321. X\L
  1322. X\IT\ reads {\myit lcount\/} strings each {\myit llength\/} bytes,
  1323. Xfrom the passed buffer dereferenced by {\myit start\/}, interpreting
  1324. Xbuffer data as a twodimensional array of {\myit llength\/} columns and
  1325. X{\myit lcount\/} rows.  To store the rotated version of this array,
  1326. X\IT\ allocates a new buffer and passes back the address of the
  1327. Xnew buffer in {\myit mallocp\/}.  Either of the four rotation
  1328. X{\myit type\/}s --- {\myit IROTR, IROTL, IROTOR, IROTOL\/} ---
  1329. Xproduces a target array in which the rows of the original array
  1330. Xwill have become columns, and vice versa.  To facilitate the
  1331. Xprinting of the new array, each new row (line) now ends with a
  1332. X{\myit newline\/} terminator.
  1333. XThe target array size returned by \IT\ includes the line-terminating
  1334. X{\myit newline\/}s, but does not report an available,
  1335. Xextra NUL byte appended to the end of the target array.
  1336. X\L
  1337. XBoth {\myit lcount\/} and {\myit llength\/} must be positive: zero or
  1338. Xnegative values
  1339. Xtrigger error returns of {\myit -sys\_nerr\/}.  If
  1340. X{\myit malloc()\/} cannot allocate the new array, \IT\ returns
  1341. Xthe negative {\myit errno\/}, as described under {\myit ierror()\/}.
  1342. X\L
  1343. X{\bb itexrect()} is a support function for \IT, called before
  1344. Xthe \IT\ call is made, to
  1345. X``pad'' irregular lines of source text beginning at {\myit start\/}
  1346. Xand ending with the byte before {\myit end\/}.
  1347. XThe {\bb itexrect()} function itself calls {\bb ilongest()} to
  1348. Xfind out how many lines there are in the buffer delimited by
  1349. X{\myit start\/} and {\myit end\/}, and to receive the byte count of
  1350. Xthe longest line.  Lines are assumed to end with either a
  1351. X{\myit newline\/} character, or with a NUL byte; the line-terminating
  1352. Xbyte is not included in the line length returned by
  1353. X{\bb ilongest()}.  The number of lines is passed back from
  1354. X{\bb ilongest()} via the {\myit int *lcount\/}.
  1355. X\L
  1356. XUsing the line size and line count
  1357. Xinformation produced by {\bb ilongest()},
  1358. X{\bb itexrect()} allocates
  1359. Xa new buffer at {\myit mallocp\/}, and
  1360. Xcopies each line of the source buffer into the new buffer.
  1361. XEach line is space-filled to end flush with the longest line,
  1362. Xand line-terminating {\myit newline\/}s or NUL bytes are omitted.
  1363. X\L
  1364. X{\bb itexrect()} transfers back the buffer size information to its
  1365. Xcaller identically to
  1366. X{\bb ilongest()}: the number of lines is passed back
  1367. Xvia {\myit int *lcount\/}, and the size of the longest line of the
  1368. Xoriginal text is returned.
  1369. XAlso, {\myit mallocp\/} is pointed
  1370. Xto the address of the new buffer now containing the concatenated,
  1371. Xspace-padded list of strings.
  1372. X\L
  1373. XThe {\myit lcount\/} parameter of both
  1374. X{\bb ilongest()} and
  1375. X{\bb itexrect()}, and
  1376. Xthe {\myit mallocp\/} parameter of
  1377. X{\bb itexrect()} are used only for returning data to the calling
  1378. Xfunction.  Values dereferenced by these pointers prior to the calls
  1379. Xwill be ignored and overwritten.  The {\myit start, end\/}
  1380. Xparameters are tested in the customary manner.
  1381. XIf {\myit malloc()\/} fails,
  1382. X{\bb itexrect()} returns
  1383. Xthe negative {\myit errno\/}, as described under {\myit ierror()\/}.
  1384. X
  1385. X\S{rot EXAMPLE PROGRAM}
  1386. XThe obvious example for
  1387. Xillustrating calls to a function that rotates text in
  1388. Xinternal space is the {\bb rot} program, reading input and outputting
  1389. Xa rotated version.
  1390. XIn order to do away with command line options that would prescribe
  1391. Xthe direction of the rotation,
  1392. Xthe executable {\bb rot} is given alias names {\bb rotr},
  1393. X{\bb rotl},
  1394. X{\bb rotor},
  1395. X{\bb rotol},
  1396. Xvia the Unix {\myit ln\/} command in the compile script.
  1397. X{\bb rotl} will stand for ``rotate 90\deg\ to the left'',
  1398. X{\bb rotr} will stand for ``rotate 90\deg\ to the right'',
  1399. X{\bb rotol} indicates that the text is to be flipped over
  1400. X(so that the top line becomes the bottom line) and then rotated
  1401. X90\deg\ to the left, and
  1402. X{\bb rotor} would flip the text over and rotate it
  1403. X90\deg\ to the right.
  1404. X\L
  1405. XThe process adds the bytes of its own command name
  1406. X({\myit argv[0]\/}) to generate a primitive hash value stored in the
  1407. X{\myit context\/} variable.
  1408. XThis sum is used to decode which rotation {\myit type\/} the user
  1409. Xwanted.  The base command name {\bb rot} does not specify
  1410. Xa rotation type; it prints a ``usage'' message instead.
  1411. XBecause there are no command line options, it is easy to implement
  1412. X{\bb rot} as a filter: if a file name follows the command, the text
  1413. Xof the file is the input; otherwise text read from \stin\ until
  1414. X{\myit EOF\/} is rotated.  Results are printed to \stout.
  1415. X\L
  1416. XAs an example of using {\bb rot}, suppose one is to create
  1417. Xa ``driving~distances'' table from a list of a dozen cities.  The
  1418. Xsomewhat cryptic command sequence
  1419. X\smallskip
  1420. X\I{\mytt xec echo XnewXnewXnew > head}
  1421. X\I{\mytt cat list >> head}
  1422. X\I{\mytt mung Xnew XnewXnewXnewXnew head}
  1423. X\smallskip
  1424. Xappends a copy of the
  1425. X{\myit list\/} of the cities,
  1426. Xto a new file {\myit head\/} (containing just four
  1427. X{\myit newline\/}s to start with),
  1428. Xand then adds three blank lines after each line
  1429. Xof {\myit head\/} (see
  1430. Xthe description of the {\myit mung\/} program under {\myit ierror()\/}
  1431. Xfor an explanation of the {\myit mung\/}
  1432. Xcommand syntax, or {\myit ifonetic()\/} for the phonetic control
  1433. Xcharacter codes).  The next commands use {\bb rotor} to flip the
  1434. Xexpanded list of {\myit head\/} ``over and to the right'';
  1435. Xthen add the original list at the end
  1436. X\smallskip
  1437. X\I{\mytt rotor head > distances}
  1438. X\I{\mytt cat list >> distances}
  1439. X\smallskip
  1440. Xto produce the following text in the file {\myit distances\/}:
  1441. X\L
  1442. X{\obeylines \mytt
  1443. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ A\ \ \ C\ \ \ G\ \ \ M\ \ \ M\ \ \ N\ \ \ O\ \ \ S\ \ \ T\ \ \ T\ \ \ V\ \ \ Z
  1444. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ C\ \ \ A\ \ \ U\ \ \ A\ \ \ E\ \ \ O\ \ \ A\ \ \ A\ \ \ I\ \ \ O\ \ \ E\ \ \ A
  1445. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ A\ \ \ N\ \ \ A\ \ \ Z\ \ \ R\ \ \ G\ \ \ X\ \ \ L\ \ \ J\ \ \ R\ \ \ R\ \ \ C
  1446. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ P\ \ \ C\ \ \ Y\ \ \ A\ \ \ I\ \ \ A\ \ \ A\ \ \ T\ \ \ U\ \ \ R\ \ \ A\ \ \ A
  1447. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ U\ \ \ U\ \ \ A\ \ \ T\ \ \ D\ \ \ L\ \ \ C\ \ \ I\ \ \ A\ \ \ E\ \ \ C\ \ \ T
  1448. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ L\ \ \ N\ \ \ M\ \ \ L\ \ \ I\ \ \ E\ \ \ A\ \ \ L\ \ \ N\ \ \ O\ \ \ R\ \ \ E
  1449. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ C\ \ \ \ \ \ \ A\ \ \ A\ \ \ A\ \ \ S\ \ \ \ \ \ \ L\ \ \ A\ \ \ N\ \ \ U\ \ \ C
  1450. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ O\ \ \ \ \ \ \ S\ \ \ N\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ O\ \ \ \ \ \ \ \ \ \ \ Z\ \ \ A
  1451. X\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ S
  1452. XACAPULCO
  1453. XCANCUN
  1454. XGUAYAMAS
  1455. XMAZATLAN
  1456. XMERIDIA
  1457. XNOGALES
  1458. XOAXACA
  1459. XSALTILLO
  1460. XTIJUANA
  1461. XTORREON
  1462. XVERACRUZ
  1463. XZACATECAS
  1464. X}
  1465. X\L
  1466. XAll that remains is to fill the table with the mileage numbers.
  1467. X
  1468. X\S{rot.c PROGRAM TEXT}
  1469. X\listing{../iex/rot.c}
  1470. X\eject
  1471. SHAR_EOF
  1472. $TOUCH -am 0608101690 iman/irotate.tex &&
  1473. chmod 0644 iman/irotate.tex ||
  1474. echo "restore of iman/irotate.tex failed"
  1475. set `wc -c iman/irotate.tex`;Wc_c=$1
  1476. if test "$Wc_c" != "8081"; then
  1477.     echo original size 8081, current size $Wc_c
  1478. fi
  1479. echo "End of part 8, continue with part 9"
  1480. exit 0
  1481. -- 
  1482.         Istvan Mohos
  1483.         ...uunet!pyrdc!pyrnj!hhb!istvan
  1484.         RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
  1485. ======================================================================
  1486.