home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / mkptypes / patch01 next >
Internet Message Format  |  1991-02-19  |  18KB

  1. From: ersmith@uwovax.uwo.ca (Eric R. Smith)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i008:  mkptypes - Generate prototype declarations for C, Patch01
  4. Message-ID: <1991Feb20.043027.17174@sparky.IMD.Sterling.COM>
  5. Date: 20 Feb 91 04:30:27 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 08f17442 720c6d3d 3b040275 b659a020
  8.  
  9. Submitted-by: Eric R. Smith <ersmith@uwovax.uwo.ca>
  10. Posting-number: Volume 17, Issue 8
  11. Archive-name: mkptypes/patch01
  12. Patch-To: mkptypes: Volume 16, Issue 90
  13.  
  14. Here is patch 1 for mkptypes. The biggest bug fixed is the bad default
  15. choice of guard macro; "_P" is in the reserved namespace of both ANSI C
  16. and POSIX, and conflicts with the ctypes.h header file in some versions of
  17. Unix. The default is now "P_". I also took the opportunity to add some
  18. suggested enhancements, e.g. making the parser a bit smarter, recognizing
  19. C++ style comments, and providing some new flags to print version
  20. information and to suppress the promotion of types (so C++ compilers that
  21. accept "int foo(c) char c;" and expect it to have prototype "int foo(char c)"
  22. will be happy).
  23.  
  24. Thanks to all the people who have reported bugs and suggested improvements.
  25.  
  26. Eric R. Smith                     email:
  27. Dept. of Mathematics            ersmith@uwovax.uwo.ca
  28. University of Western Ontario   ersmith@uwovax.bitnet
  29. ----
  30. #    This is a shell archive.
  31. #    Remove everything above and including the cut line.
  32. #    Then run the rest of the file through sh.
  33. #----cut here-----cut here-----cut here-----cut here----#
  34. #!/bin/sh
  35. # shar:    Shell Archiver
  36. #    Run the following text with /bin/sh to create:
  37. #    patch1
  38. # This archive created: 17 February 1991 12:31:28 AM EST
  39. # By:    eric (at home)
  40. echo shar: extracting patch1
  41. sed 's/^X//' << \SHAR_EOF > patch1
  42. X*** mkptypes/orig/Makefile    Mon Mar 26 12:12:20 1990
  43. X--- mkptypes/Makefile    Sun Feb 17 00:19:32 1991
  44. X***************
  45. X*** 2,8 ****
  46. X  # Makefile for mkptypes. Edit the lines below to suit your tastes; the default
  47. X  # is for my computer (Atari ST running the gcc 1.37); a Unix configuration is
  48. X  # also provided.
  49. X! 
  50. X  #CC = cc
  51. X  #PROG = mkptypes
  52. X  #CFLAGS = -O
  53. X--- 2,8 ----
  54. X  # Makefile for mkptypes. Edit the lines below to suit your tastes; the default
  55. X  # is for my computer (Atari ST running the gcc 1.37); a Unix configuration is
  56. X  # also provided.
  57. X! #
  58. X  #CC = cc
  59. X  #PROG = mkptypes
  60. X  #CFLAGS = -O
  61. X***************
  62. X*** 9,18 ****
  63. X  
  64. X  CC = gcc
  65. X  PROG = mkptypes.ttp
  66. X! CFLAGS = -mshort -O
  67. X  
  68. X! $(PROG) : mkptypes.c mkptypes.h
  69. X      $(CC) $(CFLAGS) -o $(PROG) mkptypes.c
  70. X  
  71. X  clean:
  72. X      rm -f mkptypes.o
  73. X--- 9,28 ----
  74. X  
  75. X  CC = gcc
  76. X  PROG = mkptypes.ttp
  77. X! CFLAGS = -mshort -O -Wall
  78. X  
  79. X! $(PROG) : mkptypes.c mkptypes.h patchlev.h
  80. X      $(CC) $(CFLAGS) -o $(PROG) mkptypes.c
  81. X+ 
  82. X+ all: $(PROG)
  83. X+ 
  84. X+ #
  85. X+ # edit the lines below if you want to be able to 'make install'
  86. X+ #
  87. X+ #DESTDIR = /usr/local/bin
  88. X+ #install: $(PROG)
  89. X+ #    install -c -o bin -g bin -m 755 $(PROG) $(DESTDIR)/$(PROG)
  90. X+ #
  91. X  
  92. X  clean:
  93. X      rm -f mkptypes.o
  94. X*** mkptypes/orig/mkptypes.1    Mon Jan 21 12:16:40 1991
  95. X--- mkptypes/mkptypes.1    Sun Feb 17 00:05:58 1991
  96. X***************
  97. X*** 19,24 ****
  98. X--- 19,28 ----
  99. X  ] [
  100. X  .B -A
  101. X  ] [
  102. X+ .B -V
  103. X+ ] [
  104. X+ .B -W
  105. X+ ] [
  106. X  .I file ...
  107. X  ]
  108. X  .SH DESCRIPTION
  109. X***************
  110. X*** 41,47 ****
  111. X  to be prepended to the prototype declaration as a comment.
  112. X  .PP
  113. X  The -p option controls the name of the macro used to guard prototype
  114. X! definitions. Normally this is ``_P'', but you can change it to any string
  115. X  you like. To eliminate the guard macro entirely, use the -A option.
  116. X  .PP
  117. X  The -s option causes prototypes to be generated for functions declared
  118. X--- 45,51 ----
  119. X  to be prepended to the prototype declaration as a comment.
  120. X  .PP
  121. X  The -p option controls the name of the macro used to guard prototype
  122. X! definitions. Normally this is ``P_'', but you can change it to any string
  123. X  you like. To eliminate the guard macro entirely, use the -A option.
  124. X  .PP
  125. X  The -s option causes prototypes to be generated for functions declared
  126. X***************
  127. X*** 63,68 ****
  128. X--- 67,79 ----
  129. X  The -A option causes the prototypes emitted to be only readable by ANSI
  130. X  compilers. Normally, the prototypes are "macro-ized" so that compilers
  131. X  with __STDC__ not defined don't see them.
  132. X+ .PP
  133. X+ The -V option prints the version number and patchlevel of mkptypes on the
  134. X+ standard error output.
  135. X+ .PP
  136. X+ The -W option supresses the default widening of types in old-style
  137. X+ declarations (e.g. char -> int); use this for C++ compilers or
  138. X+ for supposedly ANSI compilers that don't do type promotion.
  139. X  .PP
  140. X  If files are specified on the command line, then a comment specifying
  141. X  the file of origin is emitted before the prototypes constructed from
  142. X*** mkptypes/orig/mkptypes.c    Mon Mar 26 12:35:06 1990
  143. X--- mkptypes/mkptypes.c    Sun Feb 17 00:21:50 1991
  144. X***************
  145. X*** 30,37 ****
  146. X  #include <ctype.h>
  147. X  #include <string.h>
  148. X  
  149. X! /*#define DEBUG(s) (fputs(s, stderr)) /* */
  150. X! #define DEBUG(s) /* */
  151. X  
  152. X  #define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
  153. X  #define ABORTED ( (Word *) -1 )
  154. X--- 30,40 ----
  155. X  #include <ctype.h>
  156. X  #include <string.h>
  157. X  
  158. X! #if 0
  159. X! #define DEBUG(s) (fputs(s, stderr))
  160. X! #else
  161. X! #define DEBUG(s)
  162. X! #endif
  163. X  
  164. X  #define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
  165. X  #define ABORTED ( (Word *) -1 )
  166. X***************
  167. X*** 42,53 ****
  168. X  int donum    = 0;        /* print line numbers? */
  169. X  int define_macro   = 1;        /* define macro for prototypes? */
  170. X  int use_macro   = 1;        /* use a macro for prototypes? */
  171. X! char *macro_name = "_P";    /*   macro to use for prototypes */
  172. X  int no_parm_names = 0;        /* no parm names - only types */
  173. X  int print_extern = 0;        /* use "extern" before function declarations */
  174. X! #ifdef CPP
  175. X! int call_cpp = 0;        /* preprocess files */
  176. X! #endif
  177. X  
  178. X  char *ourname;            /* our name, from argv[] array */
  179. X  int inquote = 0;        /* in a quote?? */
  180. X--- 45,54 ----
  181. X  int donum    = 0;        /* print line numbers? */
  182. X  int define_macro   = 1;        /* define macro for prototypes? */
  183. X  int use_macro   = 1;        /* use a macro for prototypes? */
  184. X! char *macro_name = "P_";    /*   macro to use for prototypes */
  185. X  int no_parm_names = 0;        /* no parm names - only types */
  186. X  int print_extern = 0;        /* use "extern" before function declarations */
  187. X! int dont_promote = 0;        /* don't promote prototypes */
  188. X  
  189. X  char *ourname;            /* our name, from argv[] array */
  190. X  int inquote = 0;        /* in a quote?? */
  191. X***************
  192. X*** 164,169 ****
  193. X--- 165,173 ----
  194. X  {
  195. X      Word *oldw = 0;
  196. X  
  197. X+     if (dont_promote)
  198. X+         return;
  199. X+ 
  200. X      while (w) {
  201. X          if (*w->string) {
  202. X              if ( (!strcmp(w->string, "char") ||
  203. X***************
  204. X*** 190,196 ****
  205. X  
  206. X  /* read a character: if it's a newline, increment the line count */
  207. X  
  208. X! #ifdef __GNUC__    /* ++jrb */
  209. X  inline
  210. X  #endif
  211. X  int ngetc(f)
  212. X--- 194,200 ----
  213. X  
  214. X  /* read a character: if it's a newline, increment the line count */
  215. X  
  216. X! #if defined(__GNUC__) && !defined(__NO_INLINE__)    /* ++jrb */
  217. X  inline
  218. X  #endif
  219. X  int ngetc(f)
  220. X***************
  221. X*** 236,241 ****
  222. X--- 240,259 ----
  223. X              }
  224. X              return fnextch(f);
  225. X          }
  226. X+         else if (c == '/') {    /* C++ style comment */
  227. X+             incomment = 1;
  228. X+             c = ' ';
  229. X+ DEBUG("fnextch: C++ comment seen\n");
  230. X+             while (incomment) {
  231. X+                 lastc = c;
  232. X+                 c = ngetc(f);
  233. X+                 if (lastc != '\\' && c == '\n')
  234. X+                     incomment = 0;
  235. X+                 else if (c < 0)
  236. X+                     return c;
  237. X+             }
  238. X+             return fnextch(f);
  239. X+         }
  240. X          else {
  241. X  /* if we pre-fetched a linefeed, remember to adjust the line number */
  242. X              if (c == '\n') linenum--;
  243. X***************
  244. X*** 557,566 ****
  245. X          else if (!strcmp(buf, "{}")) break;
  246. X  /* otherwise, throw the word into the list (except for "register") */
  247. X          else if (strcmp(buf, "register")) {
  248. X-             sawsomething = 1;
  249. X              addword(plist, buf);
  250. X              if (*buf == '(') inparen++;
  251. X!             if (*buf == ')') inparen--;
  252. X          }
  253. X      }
  254. X  
  255. X--- 575,584 ----
  256. X          else if (!strcmp(buf, "{}")) break;
  257. X  /* otherwise, throw the word into the list (except for "register") */
  258. X          else if (strcmp(buf, "register")) {
  259. X              addword(plist, buf);
  260. X              if (*buf == '(') inparen++;
  261. X!             else if (*buf == ')') inparen--;
  262. X!             else sawsomething = 1;
  263. X          }
  264. X      }
  265. X  
  266. X***************
  267. X*** 682,688 ****
  268. X  /* try to guess when a declaration is not an external function definition */
  269. X          if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
  270. X              !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
  271. X!             !strcmp(buf, "extern")) {
  272. X              skipit(buf, f);
  273. X              goto again;
  274. X          }
  275. X--- 700,706 ----
  276. X  /* try to guess when a declaration is not an external function definition */
  277. X          if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
  278. X              !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
  279. X!             !strcmp(buf, "[") || !strcmp(buf, "extern")) {
  280. X              skipit(buf, f);
  281. X              goto again;
  282. X          }
  283. X***************
  284. X*** 721,738 ****
  285. X  {
  286. X      FILE *f;
  287. X      char *t, *iobuf;
  288. X      extern void Usage();
  289. X  
  290. X!     if (argv[0] && argv[0][0])
  291. X          ourname = argv[0];
  292. X      else
  293. X          ourname = "mkptypes";
  294. X  
  295. X      argv++; argc--;
  296. X  
  297. X-     if (argc < 0)        /* strange -- no args at all */
  298. X-         Usage();
  299. X- 
  300. X      iobuf = malloc(NEWBUFSIZ);
  301. X      while (*argv && **argv == '-') {
  302. X          t = *argv++; --argc; t++;
  303. X--- 739,763 ----
  304. X  {
  305. X      FILE *f;
  306. X      char *t, *iobuf;
  307. X+     int exit_if_noargs = 0;
  308. X      extern void Usage();
  309. X  
  310. X!     if (argv[0] && argv[0][0]) {
  311. X! #ifdef unix
  312. X!         ourname = strrchr(argv[0], '/');
  313. X!         if (!ourname)
  314. X! #endif
  315. X! #ifdef atarist
  316. X!         ourname = strrchr(argv[0], '\\');
  317. X!         if (!ourname)
  318. X! #endif
  319. X          ourname = argv[0];
  320. X+     }
  321. X      else
  322. X          ourname = "mkptypes";
  323. X  
  324. X      argv++; argc--;
  325. X  
  326. X      iobuf = malloc(NEWBUFSIZ);
  327. X      while (*argv && **argv == '-') {
  328. X          t = *argv++; --argc; t++;
  329. X***************
  330. X*** 758,763 ****
  331. X--- 783,794 ----
  332. X                  define_macro = 0;
  333. X              else if (*t == 'A')
  334. X                  use_macro = 0;
  335. X+             else if (*t == 'V') {
  336. X+                 exit_if_noargs = 1;
  337. X+                 Version();
  338. X+             }
  339. X+             else if (*t == 'W')
  340. X+                 dont_promote = 1;
  341. X              else
  342. X                  Usage();
  343. X              t++;
  344. X***************
  345. X*** 764,769 ****
  346. X--- 795,803 ----
  347. X          }
  348. X      }
  349. X  
  350. X+     if (argc == 0 && exit_if_noargs)
  351. X+         exit(EXIT_FAILURE);
  352. X+ 
  353. X      if (use_macro && define_macro) {
  354. X          printf("#if defined(__STDC__) || defined(__cplusplus)\n");
  355. X          printf("# define %s(s) s\n", macro_name);
  356. X***************
  357. X*** 771,778 ****
  358. X          printf("# define %s(s) ()\n", macro_name);
  359. X          printf("#endif\n\n");
  360. X      }
  361. X!     if (argc == 0)
  362. X          getdecl(stdin);
  363. X      else
  364. X          while (argc > 0 && *argv) {
  365. X  DEBUG("trying a new file\n");
  366. X--- 805,814 ----
  367. X          printf("# define %s(s) ()\n", macro_name);
  368. X          printf("#endif\n\n");
  369. X      }
  370. X! 
  371. X!     if (argc == 0) {
  372. X          getdecl(stdin);
  373. X+     }
  374. X      else
  375. X          while (argc > 0 && *argv) {
  376. X  DEBUG("trying a new file\n");
  377. X***************
  378. X*** 804,814 ****
  379. X  void Usage()
  380. X  {
  381. X      fprintf(stderr, 
  382. X!        "Usage: %s [-e][-n][-p sym][-s][-x][-z][-A][files ...]\n", ourname);
  383. X      fputs("   -e: put an explicit \"extern\" keyword in declarations\n",
  384. X         stderr);
  385. X      fputs("   -n: put line numbers of declarations as comments\n",stderr);
  386. X!     fputs("   -p nm: use \"nm\" as the prototype macro (default \"_P\")\n",
  387. X         stderr);
  388. X      fputs("   -s: include declarations for static functions\n", stderr);
  389. X      fputs("   -x: omit parameter names in prototypes\n", stderr);
  390. X--- 840,850 ----
  391. X  void Usage()
  392. X  {
  393. X      fprintf(stderr, 
  394. X!        "Usage: %s [-e][-n][-p sym][-s][-x][-z][-A][-W][files ...]\n", ourname);
  395. X      fputs("   -e: put an explicit \"extern\" keyword in declarations\n",
  396. X         stderr);
  397. X      fputs("   -n: put line numbers of declarations as comments\n",stderr);
  398. X!     fputs("   -p nm: use \"nm\" as the prototype macro (default \"P_\")\n",
  399. X         stderr);
  400. X      fputs("   -s: include declarations for static functions\n", stderr);
  401. X      fputs("   -x: omit parameter names in prototypes\n", stderr);
  402. X***************
  403. X*** 815,819 ****
  404. X--- 851,865 ----
  405. X      fputs("   -z: omit prototype macro definition\n", stderr);
  406. X      fputs("   -A: omit prototype macro; header files are strict ANSI\n",
  407. X         stderr);
  408. X+     fputs("   -V: print version number\n", stderr);
  409. X+     fputs("   -W: don't promote types in old style declarations\n", stderr);
  410. X      exit(EXIT_FAILURE);
  411. X+ }
  412. X+ 
  413. X+ #include "patchlev.h"
  414. X+ 
  415. X+ void
  416. X+ Version()
  417. X+ {
  418. X+     fprintf(stderr, "%s 1.0 patchlevel %d\n", ourname, PATCHLEVEL);
  419. X  }
  420. X*** mkptypes/orig/mkptypes.h    Thu Mar 22 08:14:40 1990
  421. X--- mkptypes/mkptypes.h    Sun Feb 17 00:08:30 1991
  422. X***************
  423. X*** 1,29 ****
  424. X  #if defined(__STDC__) || defined(__cplusplus)
  425. X! # define _P(s) s
  426. X  #else
  427. X! # define _P(s) ()
  428. X  #endif
  429. X  
  430. X  
  431. X  /* mkptypes.c */
  432. X! Word *word_alloc _P((char *s));
  433. X! void word_free _P((Word *w));
  434. X! int List_len _P((Word *w));
  435. X! Word *word_append _P((Word *w1, Word *w2));
  436. X! int foundin _P((Word *w1, Word *w2));
  437. X! void addword _P((Word *w, char *s));
  438. X! void typefixhack _P((Word *w));
  439. X! int ngetc _P((FILE *f));
  440. X! int fnextch _P((FILE *f));
  441. X! int nextch _P((FILE *f));
  442. X! int getsym _P((char *buf, FILE *f));
  443. X! int skipit _P((char *buf, FILE *f));
  444. X! int is_type_word _P((char *s));
  445. X! Word *typelist _P((Word *p));
  446. X! Word *getparamlist _P((FILE *f));
  447. X! void emit _P((Word *wlist, Word *plist, long startline));
  448. X! void getdecl _P((FILE *f));
  449. X! void main _P((int argc, char **argv));
  450. X! void Usage _P((void));
  451. X  
  452. X! #undef _P
  453. X--- 1,30 ----
  454. X  #if defined(__STDC__) || defined(__cplusplus)
  455. X! # define P_(s) s
  456. X  #else
  457. X! # define P_(s) ()
  458. X  #endif
  459. X  
  460. X  
  461. X  /* mkptypes.c */
  462. X! Word *word_alloc P_((char *s));
  463. X! void word_free P_((Word *w));
  464. X! int List_len P_((Word *w));
  465. X! Word *word_append P_((Word *w1, Word *w2));
  466. X! int foundin P_((Word *w1, Word *w2));
  467. X! void addword P_((Word *w, char *s));
  468. X! void typefixhack P_((Word *w));
  469. X! int ngetc P_((FILE *f));
  470. X! int fnextch P_((FILE *f));
  471. X! int nextch P_((FILE *f));
  472. X! int getsym P_((char *buf, FILE *f));
  473. X! int skipit P_((char *buf, FILE *f));
  474. X! int is_type_word P_((char *s));
  475. X! Word *typelist P_((Word *p));
  476. X! Word *getparamlist P_((FILE *f));
  477. X! void emit P_((Word *wlist, Word *plist, long startline));
  478. X! void getdecl P_((FILE *f));
  479. X! void main P_((int argc, char **argv));
  480. X! void Usage P_((void));
  481. X! void Version P_((void));
  482. X  
  483. X! #undef P_
  484. X*** mkptypes/orig/mkptypes.man    Mon Jan 21 12:16:38 1991
  485. X--- mkptypes/mkptypes.man    Sun Feb 17 00:05:40 1991
  486. X***************
  487. X*** 3,9 ****
  488. X  
  489. X  
  490. X  SYNOPSIS
  491. X!     mkptypes [ -e ][ -n ][ -p symbol ][ -s ][ -x ][ -z ][ -A ] [ file ... ]
  492. X  
  493. X  
  494. X  DESCRIPTION
  495. X--- 3,9 ----
  496. X  
  497. X  
  498. X  SYNOPSIS
  499. X!     mkptypes [-e][-n][-p symbol][-s][-x][-z][-A][-V][-W][ file ... ]
  500. X  
  501. X  
  502. X  DESCRIPTION
  503. X***************
  504. X*** 22,28 ****
  505. X      be prepended to the prototype declaration as a comment.
  506. X  
  507. X      The -p option controls the name of the macro used to guard prototype
  508. X!     definitions. Normally this is "_P", but you can change it to any string you
  509. X      like. To eliminate the guard macro entirely, use the -A option.
  510. X  
  511. X      The -s option causes prototypes to be generated for functions declared
  512. X--- 22,28 ----
  513. X      be prepended to the prototype declaration as a comment.
  514. X  
  515. X      The -p option controls the name of the macro used to guard prototype
  516. X!     definitions. Normally this is "P_", but you can change it to any string you
  517. X      like. To eliminate the guard macro entirely, use the -A option.
  518. X  
  519. X      The -s option causes prototypes to be generated for functions declared
  520. X***************
  521. X*** 42,47 ****
  522. X--- 42,54 ----
  523. X      The -A option causes the prototypes emitted to be only readable by ANSI
  524. X      compilers.  Normally, the prototypes are "macro-ized" so that compilers
  525. X      with __STDC__not defined don't see them.
  526. X+ 
  527. X+     The -V option prints the version number and patchlevel of mkptypes on
  528. X+     the standard error output.
  529. X+ 
  530. X+     The -W option supresses the default widening of types in old-style
  531. X+     declarations (e.g. char -> int); use this for C++ compilers or
  532. X+     for supposedly ANSI compilers that don't do type promotion.
  533. X  
  534. X      If files are specified on the command line, then a comment specifying the
  535. X      file of origin is emitted before the prototypes constructed from that file.
  536. X*** mkptypes/orig/patchlev.h    Sat Feb 16 01:14:02 1991
  537. X--- mkptypes/patchlev.h    Sun Feb 17 00:00:38 1991
  538. X***************
  539. X*** 0 ****
  540. X--- 1,16 ----
  541. X+ /*
  542. X+  * Patchlevel 1: Feb. 16, 1991
  543. X+  * changed "_P" in prototype header files to "P_" to avoid namespace conflicts
  544. X+  * with POSIX, ANSI, and some Unix header files
  545. X+  *
  546. X+  * added support C++ style comments (// to end of line)
  547. X+  * 
  548. X+  * new option (-W) to suppress promotion of prototypes in old style declarations
  549. X+  *
  550. X+  * miscellaneous bugfixes to improve probablility of parsing complicated
  551. X+  * declarations
  552. X+  *
  553. X+  * added "install" option to makefile (thanks to Blayne Puklich)
  554. X+  */
  555. X+ 
  556. X+ #define PATCHLEVEL 1
  557. SHAR_EOF
  558. if test 14624 -ne "`wc -c patch1`"
  559. then
  560. echo shar: error transmitting patch1 '(should have been 14624 characters)'
  561. fi
  562. #    End of shell archive
  563. exit 0
  564. -- 
  565. --
  566. Eric R. Smith                     email:
  567. Dept. of Mathematics            ersmith@uwovax.uwo.ca
  568. University of Western Ontario   ersmith@uwovax.bitnet
  569. London, Ont. Canada N6A 5B7
  570. ph: (519) 661-3638
  571.  
  572. exit 0 # Just in case...
  573. -- 
  574. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  575. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  576. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  577. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  578.