[comp.sources.misc] v17i078: cproto - Generate C function prototypes from C source, Patch01

cthuang@contact.UUCP (Chin Huang) (04/04/91)

Submitted-by: Chin Huang <cthuang@contact.UUCP>
Posting-number: Volume 17, Issue 78
Archive-name: cproto/patch01
Patch-To: cproto: Volume 17, Issue 70-71

Here is patch 1 for cproto, a C function prototype generator.
It fixes a couple of bugs, cleans up some code, and includes
a formatted manual page.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  patch1 cproto.man
# Wrapped by ibmpc@laphroig.UUCP on Sat Mar 30 13:31:00 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f patch1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"patch1\"
else
echo shar: Extracting \"patch1\" \(13164 characters\)
sed "s/^X//" >patch1 <<'END_OF_patch1'
Xdiff -c old/CHANGES ./CHANGES
X*** old/CHANGES	Thu Mar 28 15:41:44 1991
X--- ./CHANGES	Sat Mar 30 13:18:50 1991
X***************
X*** 1,5 ****
X--- 1,14 ----
X  Version 2
X  
X+ Patchlevel 1
X+ 
X+ - Fix: Cproto incorrectly generated the parameter "int ..." in
X+   prototypes of functions taking variable parameters.
X+ - Fix: Function definitions can now be followed by an optional
X+   semicolon.  I found this feature in every C compiler I tried.
X+ 
X+ Patchlevel 0
X+ 
X  - Added formal parameter promotion.
X  - Added prototype style that surrounds prototypes with a guard macro.
X  - Handles C++ style comment //.
Xdiff -c old/cproto.1 ./cproto.1
X*** old/cproto.1	Thu Mar 28 15:41:44 1991
X--- ./cproto.1	Sat Mar 30 13:18:54 1991
X***************
X*** 1,4 ****
X! .\" $Id: cproto.1 2.1 91/03/25 10:13:30 cthuang Exp $
X  .\"
X  .de EX          \"Begin example
X  .ne 5
X--- 1,4 ----
X! .\" $Id: cproto.1 2.2 91/03/30 13:18:50 cthuang Exp $
X  .\"
X  .de EX          \"Begin example
X  .ne 5
X***************
X*** 140,149 ****
X  .TP
X  .B \-V
X  Print version information.
X- .SH AUTHOR
X- Chin Huang
X- cthuang@contact.uucp
X- chin.huang@canrem.uucp
X  .SH BUGS
X  When cproto finds an error, it usually outputs the not very descriptive
X  message "syntax error".
X--- 140,145 ----
X***************
X*** 154,159 ****
X--- 150,161 ----
X  \\n	newline
X  \\t	tab
X  .EE
X+ .SH AUTHOR
X+ .nf
X+ Chin Huang
X+ cthuang@contact.uucp
X+ chin.huang@canrem.uucp
X+ .fi
X  .SH "SEE ALSO"
X  cc(1),
X  cpp(1)
Xdiff -c old/cproto.c ./cproto.c
X*** old/cproto.c	Thu Mar 28 15:41:58 1991
X--- ./cproto.c	Sat Mar 30 13:19:00 1991
X***************
X*** 1,10 ****
X! /* $Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $
X   *
X   * C prototype generator
X   * Reads C source code and outputs ANSI C function prototypes.
X   */
X  #ifndef lint
X! static char *rcsid = "$Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $";
X  #endif
X  #include <stdio.h>
X  #include <ctype.h>
X--- 1,10 ----
X! /* $Id: cproto.c 2.2 91/03/30 13:18:55 cthuang Exp $
X   *
X   * C prototype generator
X   * Reads C source code and outputs ANSI C function prototypes.
X   */
X  #ifndef lint
X! static char *rcsid = "$Id: cproto.c 2.2 91/03/30 13:18:55 cthuang Exp $";
X  #endif
X  #include <stdio.h>
X  #include <ctype.h>
X***************
X*** 149,156 ****
X  static void
X  usage ()
X  {
X!     fprintf(stderr,
X! 	"usage: %s [ option ... ] [ file ... ]\n", progname);
X      fputs("  -e      output \"extern\" keyword before global declarations\n",
X  	stderr);
X      fputs("  -f n    select function prototype style (0 to 4)\n", stderr);
X--- 149,155 ----
X  static void
X  usage ()
X  {
X!     fprintf(stderr, "usage: %s [ option ... ] [ file ... ]\n", progname);
X      fputs("  -e      output \"extern\" keyword before global declarations\n",
X  	stderr);
X      fputs("  -f n    select function prototype style (0 to 4)\n", stderr);
X***************
X*** 163,175 ****
X      fputs("  -U name\n", stderr);
X      fputs("  -I directory\n", stderr);
X      fputs("          C preprocessor options\n", stderr);
X!     fputs(
X!     "  -F fmt  set prototype template in the form \"int main (a, b)\"\n",
X  	stderr);
X      fputs("  -V      print version information\n", stderr);
X      exit(1);
X  }
X  
X  main (argc, argv)
X  int argc;
X  char **argv;
X--- 162,174 ----
X      fputs("  -U name\n", stderr);
X      fputs("  -I directory\n", stderr);
X      fputs("          C preprocessor options\n", stderr);
X!     fputs("  -F fmt  set prototype template in the form \"int main (a, b)\"\n",
X  	stderr);
X      fputs("  -V      print version information\n", stderr);
X      exit(1);
X  }
X  
X+ int
X  main (argc, argv)
X  int argc;
X  char **argv;
X***************
X*** 288,294 ****
X      }
X  
X      if (optind == argc) {
X! 	printf("/* stdin */\n");
X  	parse_file();
X      } else {
X  	for (i = optind; i < argc; ++i) {
X--- 287,293 ----
X      }
X  
X      if (optind == argc) {
X! 	strcpy(cur_file, "stdin");
X  	parse_file();
X      } else {
X  	for (i = optind; i < argc; ++i) {
X***************
X*** 305,312 ****
X  	    }
X  #endif
X  	    strcpy(cur_file, argv[i]);
X- 	    line_num = 1;
X- 	    printf("/* %s */\n", cur_file);
X  	    parse_file();
X  #ifdef MSDOS
X  	    fclose(yyin);
X--- 304,309 ----
Xdiff -c old/grammar.y ./grammar.y
X*** old/grammar.y	Thu Mar 28 15:41:56 1991
X--- ./grammar.y	Sat Mar 30 13:19:04 1991
X***************
X*** 1,4 ****
X! /* $Id: grammar.y 2.1 91/02/28 11:16:07 cthuang Exp $
X   *
X   * yacc grammar for C prototype generator
X   * This was derived from the grammar given in Appendix A of
X--- 1,4 ----
X! /* $Id: grammar.y 2.2 91/03/30 13:19:00 cthuang Exp $
X   *
X   * yacc grammar for C prototype generator
X   * This was derived from the grammar given in Appendix A of
X***************
X*** 88,93 ****
X--- 88,94 ----
X  external_declaration
X  	: declaration
X  	| function_definition
X+ 	| function_definition ';'
X  	| T_EXTERN T_QUOTEC T_BRACES
X  	| error
X  	;
X***************
X*** 564,569 ****
X--- 565,572 ----
X  void
X  parse_file ()
X  {
X+     printf("/* %s */\n", cur_file);
X+     line_num = 1;
X      typedef_names = create_symbol_table();
X      yyparse();
X  }
Xdiff -c old/Makefile ./Makefile
X*** old/Makefile	Thu Mar 28 15:41:44 1991
X--- ./Makefile	Sat Mar 30 13:19:08 1991
X***************
X*** 1,4 ****
X! # $Id: makefile 2.1 91/03/25 10:56:54 cthuang Exp $
X  #
X  # MSDOS makefile for C prototype generator
X  
X--- 1,4 ----
X! # $Id: Makefile 2.2 91/03/30 13:19:06 cthuang Exp $
X  #
X  # MSDOS makefile for C prototype generator
X  
X***************
X*** 9,24 ****
X  
X  DEFINES = -DMSDOS
X  
X! DIST1 =		README CHANGES Makefile Makefile.uni cproto.1
X! DIST2 =		$(SOURCES)
X  SOURCES =	lex.l grammar.y \
X  		config.h cproto.h patchlev.h semantic.h symbol.h \
X  		cproto.c semantic.c string.c symbol.c
X  CSOURCES =	cproto.c semantic.c string.c symbol.c y_tab.c
X! OBJECTS =	cproto.obj semantic.obj getopt.obj symbol.obj \
X! 		y_tab.obj
X  
X! all: cproto.exe
X  
X  cproto.exe: $(OBJECTS)
X  	$(CC) $(CFLAGS) $(OBJECTS)
X--- 9,25 ----
X  
X  DEFINES = -DMSDOS
X  
X! DIST1 =		README CHANGES
X! DIST2 =		cproto.man
X! DIST3 =		cproto.1 Makefile Makefile.uni
X! DIST4 =		$(SOURCES)
X  SOURCES =	lex.l grammar.y \
X  		config.h cproto.h patchlev.h semantic.h symbol.h \
X  		cproto.c semantic.c string.c symbol.c
X  CSOURCES =	cproto.c semantic.c string.c symbol.c y_tab.c
X! OBJECTS =	cproto.obj semantic.obj getopt.obj symbol.obj y_tab.obj
X  
X! all: cproto.exe cproto.man
X  
X  cproto.exe: $(OBJECTS)
X  	$(CC) $(CFLAGS) $(OBJECTS)
X***************
X*** 32,37 ****
X--- 33,41 ----
X  lex_yy.c: lex.l
X  	$(LEX) lex.l
X  
X+ cproto.man: cproto.1
X+ 	cawf -man $*.1 >$@
X+ 
X  TAGS: $(SOURCES)
X  	etags -t $(SOURCES)
X  
X***************
X*** 41,47 ****
X  	erase *.log
X  	erase lex_yy.c
X  	erase y_tab.c
X! 	erase cproto1.exe
X  	
X  lint:
X  	lint -B $(DEFINES) $(CSOURCES)
X--- 45,51 ----
X  	erase *.log
X  	erase lex_yy.c
X  	erase y_tab.c
X! 	erase cproto.exe
X  	
X  lint:
X  	lint -B $(DEFINES) $(CSOURCES)
X***************
X*** 50,68 ****
X  	cpr $(SOURCES) | lpr -J'cproto'
X  
X  shar:
X! 	rmcr $(DIST1)
X! 	rmcr $(DIST2)
X! 	shar $(DIST1) >cproto.sh1
X! 	rmcr cproto.sh1
X! 	shar $(DIST2) >cproto.sh2
X! 	rmcr cproto.sh2
X  
X  zip:
X  	pkzip -u cproto README CHANGES Makefile.* *.1 *.c *.h grammar.y lex.l
X  
X  ci:
X! 	ci -r2 -u $(DIST1)
X! 	ci -r2 -u $(DIST2)
X  
X  # DO NOT DELETE THIS LINE -- make depend depends on it.
X  
X--- 54,71 ----
X  	cpr $(SOURCES) | lpr -J'cproto'
X  
X  shar:
X! 	rmcr $(DIST1) $(DIST2) $(DIST3)
X! 	rmcr $(DIST4)
X! 	shar $(DIST1) $(DIST2) $(DIST3) >cproto.sh1
X! 	shar $(DIST4) >cproto.sh2
X! 	rmcr cproto.sh1 cproto.sh2
X  
X  zip:
X  	pkzip -u cproto README CHANGES Makefile.* *.1 *.c *.h grammar.y lex.l
X  
X  ci:
X! 	ci -u2 $(DIST1) $(DIST3)
X! 	ci -u2 $(DIST4)
X  
X  # DO NOT DELETE THIS LINE -- make depend depends on it.
X  
Xdiff -c old/Makefile.uni ./Makefile.uni
X*** old/Makefile.uni	Thu Mar 28 15:41:44 1991
X--- ./Makefile.uni	Sat Mar 30 13:19:10 1991
X***************
X*** 1,4 ****
X! # $Id: Makefile.uni 2.1 91/02/28 11:15:54 cthuang Exp $
X  #
X  # UNIX makefile for C prototype generator
X  
X--- 1,4 ----
X! # $Id: Makefile.uni 2.2 91/03/30 13:19:09 cthuang Exp $
X  #
X  # UNIX makefile for C prototype generator
X  
X***************
X*** 9,16 ****
X  # Define SYSV for System V, otherwise BSD is assumed.
X  #DEFINES = -DSYSV
X  
X! DIST1 =		README CHANGES Makefile Makefile.dos cproto.1
X! DIST2 =		$(SOURCES)
X  SOURCES =	lex.l grammar.y \
X  		config.h cproto.h patchlev.h semantic.h symbol.h \
X  		cproto.c semantic.c string.c symbol.c
X--- 9,18 ----
X  # Define SYSV for System V, otherwise BSD is assumed.
X  #DEFINES = -DSYSV
X  
X! DIST1 =		README CHANGES
X! DIST2 =		cproto.man
X! DIST3 =		cproto.1 Makefile Makefile.dos
X! DIST4 =		$(SOURCES)
X  SOURCES =	lex.l grammar.y \
X  		config.h cproto.h patchlev.h semantic.h symbol.h \
X  		cproto.c semantic.c string.c symbol.c
X***************
X*** 17,23 ****
X  CSOURCES =	cproto.c semantic.c string.c symbol.c y.tab.c
X  OBJECTS =	cproto.o semantic.o string.o symbol.o y.tab.o
X  
X! all: cproto
X  
X  cproto: $(OBJECTS)
X  	$(CC) $(CFLAGS) -o $@ $(OBJECTS)
X--- 19,25 ----
X  CSOURCES =	cproto.c semantic.c string.c symbol.c y.tab.c
X  OBJECTS =	cproto.o semantic.o string.o symbol.o y.tab.o
X  
X! all: cproto cproto.man
X  
X  cproto: $(OBJECTS)
X  	$(CC) $(CFLAGS) -o $@ $(OBJECTS)
X***************
X*** 28,38 ****
X  lex.yy.c: lex.l
X  	$(LEX) lex.l
X  
X  TAGS: $(SOURCES)
X  	etags -t $(SOURCES)
X  
X  clean:
X! 	rm *.o *.bak *.log cproto1.exe
X  	
X  lint:
X  	lint -B $(DEFINES) $(CSOURCES)
X--- 30,43 ----
X  lex.yy.c: lex.l
X  	$(LEX) lex.l
X  
X+ cproto.man: cproto.1
X+ 	nroff -man $*.1 >$@
X+ 
X  TAGS: $(SOURCES)
X  	etags -t $(SOURCES)
X  
X  clean:
X! 	rm *.o *.bak *.log cproto
X  	
X  lint:
X  	lint -B $(DEFINES) $(CSOURCES)
X***************
X*** 41,51 ****
X  	cpr $(SOURCES) | lpr -J'cproto'
X  
X  shar:
X! 	shar $(DIST1) >cproto.sh1
X! 	shar $(DIST2) >cproto.sh2
X  
X  ci:
X! 	ci -u $(DIST1) $(DIST2)
X  
X  depend:
X  	makedepend $(CSOURCES)
X--- 46,56 ----
X  	cpr $(SOURCES) | lpr -J'cproto'
X  
X  shar:
X! 	shar $(DIST1) $(DIST2) $(DIST3) >cproto.sh1
X! 	shar $(DIST4) >cproto.sh2
X  
X  ci:
X! 	ci -u2 $(DIST1) $(DIST3) $(DIST4)
X  
X  depend:
X  	makedepend $(CSOURCES)
Xdiff -c old/patchlev.h ./patchlev.h
X*** old/patchlev.h	Thu Mar 28 15:41:58 1991
X--- ./patchlev.h	Sat Mar 30 13:19:38 1991
X***************
X*** 1,1 ****
X! #define PATCHLEVEL 0
X--- 1,1 ----
X! #define PATCHLEVEL 1
Xdiff -c old/semantic.c ./semantic.c
X*** old/semantic.c	Thu Mar 28 15:42:00 1991
X--- ./semantic.c	Sat Mar 30 13:19:44 1991
X***************
X*** 1,4 ****
X! /* $Id: semantic.c 2.1 91/03/25 11:40:31 cthuang Exp $
X   *
X   * C prototype generator
X   * These routines implement the semantic actions executed by the yacc parser.
X--- 1,4 ----
X! /* $Id: semantic.c 2.2 91/03/30 13:19:39 cthuang Exp $
X   *
X   * C prototype generator
X   * These routines implement the semantic actions executed by the yacc parser.
X***************
X*** 303,309 ****
X--- 303,311 ----
X  	    output_error();
X  	    fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
X  	} else {
X+ 	    free(p->declarator.text);
X  	    p->declarator.text = strdup(d->text);
X+ 
X  	    decl_spec_text = decl_spec->text;
X  	    if (promote_param && strcmp(d->text, d->name) == 0) {
X  	        s = rindex(decl_spec_text, ' ');
X***************
X*** 313,318 ****
X--- 315,321 ----
X  		else if (strcmp(s, "float") == 0)
X  		    decl_spec_text = "double";
X  	    }
X+ 	    free(p->decl_spec.text);
X  	    p->decl_spec.text = strdup(decl_spec_text);
X  	}
X      }
X***************
X*** 378,384 ****
X  	*s = *(p->declarator.name);
X      } else {
X  	if (strlen(p->declarator.text) > 0) {
X! 	    putchar(' ');
X  	    output_declarator(&(p->declarator));
X  	}
X      }
X--- 381,388 ----
X  	*s = *(p->declarator.name);
X      } else {
X  	if (strlen(p->declarator.text) > 0) {
X! 	    if (strcmp(p->declarator.text, "...") != 0)
X! 		putchar(' ');
X  	    output_declarator(&(p->declarator));
X  	}
X      }
X***************
X*** 464,470 ****
X       * part.  The default type in this cause is "int".
X       */
X      for (p = declarator->params.first; p != NULL; p = p->next) {
X! 	if (strlen(p->decl_spec.text) == 0) {
X  	    free(p->decl_spec.text);
X  	    p->decl_spec.text = strdup("int");
X  	}
X--- 468,475 ----
X       * part.  The default type in this cause is "int".
X       */
X      for (p = declarator->params.first; p != NULL; p = p->next) {
X! 	if (strlen(p->decl_spec.text) == 0 &&
X! 	    strcmp(p->declarator.text, "...") != 0) {
X  	    free(p->decl_spec.text);
X  	    p->decl_spec.text = strdup("int");
X  	}
Xdiff -c old/semantic.h ./semantic.h
X*** old/semantic.h	Thu Mar 28 15:41:58 1991
X--- ./semantic.h	Sat Mar 30 13:19:46 1991
X***************
X*** 1,6 ****
X! /* $Id: semantic.h 2.1 91/02/28 11:16:19 cthuang Exp $
X   *
X!  * Declarations for semantics action routines
X   */
X  
X  extern boolean is_typedef_name(/*
X--- 1,6 ----
X! /* $Id: semantic.h 2.2 91/03/30 13:19:44 cthuang Exp $
X   *
X!  * Declarations for semantic action routines
X   */
X  
X  extern boolean is_typedef_name(/*
X***************
X*** 9,15 ****
X  extern void new_decl_spec(/*
X  	DeclSpec *decl_spec,
X  	char *text,
X! 	unsigned short flags
X  	*/);
X  extern void join_decl_specs(/*
X  	DeclSpec *result,
X--- 9,15 ----
X  extern void new_decl_spec(/*
X  	DeclSpec *decl_spec,
X  	char *text,
X! 	int flags
X  	*/);
X  extern void join_decl_specs(/*
X  	DeclSpec *result,
END_OF_patch1
if test 13164 -ne `wc -c <patch1`; then
    echo shar: \"patch1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cproto.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cproto.man\"
else
echo shar: Extracting \"cproto.man\" \(4104 characters\)
sed "s/^X//" >cproto.man <<'END_OF_cproto.man'
X
X
XCPROTO(1)                  Unix Programmer's Manual                  CPROTO(1)
X
X
XNAME
X     cproto - generate C function prototypes from C source code
X
XSYNOPSIS
X     cproto [ option ... ] [ file ... ]
X
XDESCRIPTION
X     Cproto reads C source code files  and  outputs  function  prototypes  for
X     external  functions  defined  in  the  source  to  standard  output.  The
X     function definitions may be in the old style or ANSI style.   Optionally,
X     cproto  also  outputs  declarations for any external variables defined in
X     the file.  If no file argument is given, cproto takes its input from  the
X     standard input.
X
XOPTIONS
X
X     -e   Output the keyword extern in front of each declaration having global
X          scope.
X
X     -fn  Set the style of function prototype where n is a number from 0 to 4.
X          For example, consider the function definition
X
X                main (argc, argv)
X                int argc;
X                char *argv[];
X                {
X                 ...
X                }
X
X          If the value is 0, then no prototypes are generated.  When set to 1,
X          the output is:
X
X                int main(/*int argc, char *argv[]*/);
X
X          For a value of 2, the output has the form:
X
X                int main(int /*argc*/, char */*argv*/[]);
X
X          The default value is 3.  It produces the full function prototype:
X
X                int main(int argc, char *argv[]);
X
X          A value of 4 produces prototypes guarded by a macro:
X
X                int main P_((int argc, char *argv[]));
X
X
X     -mname
X          Set the name of the macro used to guard prototypes when  option  -f4
X          is selected.  By default it is "P_".
X
X     -d   Omit the definition of the prototype macro named by the -m option.
X
X     -p   Disable promotion of formal parameters in function  prototypes.   By
X          default,  parameters  of  type  char  or  short in traditional style
X          function definitions are  promoted  to  type  int  in  the  function
X
X
X                              February 28, 1991                              1
X
X
X
X
XCPROTO(1)                  Unix Programmer's Manual                  CPROTO(1)
X
X
X          prototype.  Parameters of type float get promoted to double as well.
X
X     -s   Also output static declarations.
X
X     -v   Also output declarations for variables defined in the file.
X
X     -Fstring
X          Set the format used to output  each  prototype.   The  string  is  a
X          template in the form
X
X                " int main ( a, b )"
X
X          where each space in the  string  may  be  replaced  with  whitespace
X          characters.  For example, the option
X
X                -F"int main(\n\ta,\n\tb\n\t)"
X
X          will produce prototypes in the format
X
X                int main(
X                        int argc,
X                        char *argv[]
X                        );
X
X
X     -Dname\[=value\]
X          This option is passed through to the preprocessor  and  is  used  to
X          define symbols for use with conditionals such as #ifdef.
X
X     -Uname
X          This option is passed through to the preprocessor  and  is  used  to
X          remove any definitions of this symbol.
X
X     -Idirectory
X          This option is passed through to the preprocessor  and  is  used  to
X          specify  a  directory  to  search for files that are referenced with
X          #include.
X
X     -V   Print version information.
X
XBUGS
X     When cproto finds an error, it usually outputs the not  very  descriptive
X     message "syntax error".
X
X     Options that take string arguments only interpret the following
X          character escape sequences:
X
X                \n   newline
X                \t   tab
X
X
XAUTHOR
X     Chin Huang
X     cthuang@contact.uucp
X     chin.huang@canrem.uucp
X
X
X
X                              February 28, 1991                              2
X
X
X
X
XCPROTO(1)                  Unix Programmer's Manual                  CPROTO(1)
X
X
XSEE ALSO
X     cc(1), cpp(1)
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X                              February 28, 1991                              3
X
X
END_OF_cproto.man
if test 4104 -ne `wc -c <cproto.man`; then
    echo shar: \"cproto.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
Chin Huang  cthuang@contact.uucp  chin.huang@canrem.uucp

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.