[net.sources] ncode -- source, man page and sample input files

good@pixar.UUCP (12/23/86)

Here it is: the new, improved ncode.c along with new, improved sample
files which help you appreciate all the wonderful features of the program.
To unwrap your kit, save it in a file called "ncode.shar".

To assemble your kit, delete everything in the file above (and including)
this "cut here" line, and delete everything below (and including) the
other "cut here" line near the bottom of the file.  Then give the command

	sh ncode.shar

and start by reading the README file.  Cheers.
----------------------------- cut here --------------------------------
echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
XYou should now have README, ncode.c, ncode.1 ncode.sample.1 and ncode.sample.2.
X
XThe program will now handle arbitrarily large files (you can even #include
X/usr/dict/words) and runs much quicker than the first one I posted.
X
XThis source is known to compile and run on 4.3 BSD and on Sun 3.0.  I
Xunderstand that it compiles fine on sysV if you replace the calls to random()
Xand srandom() with calls to rand() and srand().  Non 4.3 users will probably
Xalso have to replace the innards of a_random_number() with something that
Xworks on your system.  You basically want some number to seed the random
Xnumber generator.  A getpid() doesn't change very quickly but will work;
Xcalls to the real-time clock work better.  This version of a_random_number()
Xwas written by pixar!brighton who insists that all the baroque bit twiddling
Xhelps.  I just know that it works.
X
XCompile it "cc ncode.c -O -o ncode" and then try
X
X	ncode ncode.sample.1
X
XFor more fun, try
X
X	ncode -n 5 ncode.sample.1
X
XAnd for a good education say
X
X	ncode -g "I had a date with FOX\" ncode.sample.1
X
XThen you might want to read the man page, ncode.1, to learn about how it
Xworks.  You can make it pretty with "nroff -man ncode.1".  If all of this
Xleaves you hopelessly confused, send mail to {sun,ucbvax}!pixar!good and
XI'll send you more confusing sample files.  If I feel like it.
X
X
X		--Craig
X		...{ucbvax,sun}!pixar!good
X
*-*-END-of-README-*-*
echo x - ncode.c
sed 's/^X//' >ncode.c <<'*-*-END-of-ncode.c-*-*'
X/*
X *	ncode.c --  a random text constructor
X *	pixar!good
X *	based on a program by pixar!mark
X */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#define DATALUMP	8192	/* increment size of data[] by this as needed */
X#define BIGBUF		4096	/* nice, roomy buffer for group name checks */
X
Xchar **data;	/* array of pointers to elements in bucket */
Xint dindex;	/* number of elements in data */
Xint datasize;	/* how many elements would fit in data[] is right now */
X
Xchar *malloc();
Xchar *realloc();
Xchar *rindex();
Xchar *fgets();
Xlong random();
X
Xstruct gstruct {
X	char *name;	/* points to name of a group in data[] */
X	int count;	/* how many elements of data belong to this group */
X	int index;	/* index of element of data where group starts */
X};
Xstruct gstruct *groups; /* where the group structs live, or is that obvious? */
Xint ngroups;		/* number of elements in groups */
X
Xmain (ac,av)
Xint ac;
Xchar *av[];
X{
X	char *prog;		/* name of this program */
X	char *fname = 0;
X	int loopcnt = 1;	/* times through main loop */
X 	char *groupname = "CODE";
X
X	prog = rindex(*av,'/');
X	prog = ( prog == NULL ) ? *av : ++prog ;
X	ac--;av++;
X	while(ac && **av == '-'){
X		if (strcmp(*av,"-n") == 0){
X			ac--;av++;
X			loopcnt = atoi(*av);
X			if (loopcnt <= 0){
X				fprintf(stderr,
X					"%s: -n: need positive integer\n",prog);
X				exit(1);
X			}
X			ac--;av++;
X		} else if (strcmp(*av,"-g") == 0){
X			ac--;av++;
X			groupname = *av;	/* use instead of "CODE" */
X			if (! groupname ){
X				fprintf(stderr,
X					"%s: -g: need group name\n",prog);
X				exit(1);
X			}
X			ac--;av++;
X		} else {
X			printf(
X			"Usage %s [-n n ] [-g groupname] codefile\n",prog);
X			exit(0);
X		}
X	}
X	if (!ac){
X		fprintf(stderr,
X			"Usage %s [-n n ] [-g groupname] codefile\n",prog);
X		exit(1);
X	}
X	fname = *av;
X
X	/*
X	 *	Make some room to start, and increment by DATALUMP as needed
X	 */
X	datasize = DATALUMP;
X	if ((data = (char **) malloc(datasize * sizeof(char *))) == NULL ){
X		perror("main: could not malloc for data[]");
X		exit(1);
X	}
X	dindex = 0;
X	if( init(fname) != 0 ){	
X		fprintf(stderr,"%s: init error\n",prog);
X		exit(1);
X	}
X	/*
X	 * This should be more than enough room for worst-case
X	 */
X	groups = (struct gstruct *) malloc(dindex * sizeof(struct gstruct));
X	if (groups == NULL){
X		perror("main: could not malloc for groups[]");
X		exit(1);
X	}
X	if ( scan() != 0 ){
X		fprintf(stderr,"%s: scan error\n",prog);
X		exit(1);
X	}
X	srandom(a_random_number());	/* seed the number generator */
X	while ( loopcnt ){
X		expand(groupname,strlen(groupname));
X		loopcnt--;
X	}
X	exit(0);
X}
X
Xinit(fname)
Xchar *fname;
X{
X	char *bucket;	/* big array where data lives */
X	char *bptr;	/* points into bucket */
X	int fd;
X	struct stat sbuf;
X	char *s, *t;
X
X	fd = open(fname,O_RDONLY,0);
X	if ( fd < 0 ) {
X		perror(fname);
X		return 1;
X	}
X	if ( fstat(fd,&sbuf) != 0 ){
X		perror(fname);
X		return 1;
X	}
X	if ((bucket = (char *) malloc( sbuf.st_size + 1)) == NULL ){
X		perror("init(): malloc() trouble");
X		return 1;
X	}
X	/*
X	 *	Read entire file into bucket[]
X	 */
X	if ((read(fd,bucket,sbuf.st_size)) != sbuf.st_size){
X		perror("init: read error");
X		return 1;
X	}
X	close(fd);
X	/*
X	 * Make first pass through memory, pointing data[] the right way
X	 * and recursing as needed on #include files.
X	 */
X	bptr = bucket;
X	while ( *bptr && (bptr <= bucket + sbuf.st_size) ){
X		s = bptr; 
X		while ( *s != '\0' ){
X			if(*s == '\n' )
X				*s = '\0';	/* nuke newline */
X			else
X				s++;
X		}
X		if( strncmp(bptr, "#include", 8) == 0 ){
X			for(t = bptr + 8; *t!='\0' && (*t==' '||*t=='\t');t++)
X				;	/* skipping white space */
X			if (init(t) != 0){	/* RECURSES HERE */
X				return 1;
X			}
X			bptr = t +strlen(t) + 1; /* skip the #include line */
X			continue;	/* back to the top of the while loop */
X		}
X		/*
X		 *	Make sure data[] is still big enough
X		 */
X		if ( dindex >= datasize){
X			datasize += DATALUMP;
X			if((data=(char **) realloc(data,
X					datasize*sizeof(char *)))==NULL){
X				perror("init: could not realloc for data[]");
X				return(1);
X			}
X		}
X		data[dindex] = bptr;	/* point it at the data */
X		bptr = s + 1;	/* move bptr to the next location to fill */
X		dindex++;
X	}
X	return 0;
X}
X
X/*
X *	Scan data[] marking and counting groups
X */
Xscan()
X{
X	register i, gcnt, gindex;
X
X	/*
X	 * special case: first line always a group name 
X	 */
X	groups[0].name = data[0];
X	groups[0].index = 0;
X	ngroups = 1;
X	i = 1;
X	gindex = 0;
X	gcnt = 0;
X	while ( i < dindex ){
X		if ( data[i][0] == '%' ){
X			groups[gindex].count = gcnt;
X			gcnt = 0;		/* close out prev group */
X			ngroups++;
X			i++;			/* start next group */
X			/*
X			 *	If a #included file has any blank lines after
X			 *	the last '%' then the group name would wind
X			 *	up being '\0'.  So the first group name after
X			 *	the #include won't be marked as a group name
X			 *	and will thus never be expanded.  We could
X			 *	cluck our tongues at the user and say he has
X			 *	a bogus file and thus deserves what he gets.
X			 *	But hopefully this check will just make the
X			 *	program more robust.
X			 */
X			while ((i < dindex) && (data[i][0] == '\0')){
X					i++;
X			}
X			gindex++;
X			groups[gindex].name = data[i];
X			groups[gindex].index = i;
X		}else{
X			gcnt++;
X		}
X		i++;
X	}
X	ngroups--;	/* The last % in the file doesn't start a new group */
X	return 0;
X}
X
X/*
X *	This is where we finally do the deed.  If a string is a group name
X *	then expand() will randomly select a member of that group to
X *	replace it.  Through the miracle of recursion, a whole sentence
X *	may be passed to expand() and each word (anything bounded by what
X *	we call "white space" gets expanded.  Anything that cannot be
X *	expanded gets printed out.
X */
Xexpand(s,lim)
Xchar s[];
Xint lim;
X{
X	register i, j, k, done, n, r;
X
X	i = j = 0;
X	while ( s[i] != 0 && i < lim ){
X		done = 0;
X		while ( ! done && j <= lim ){
X			if ( isawhite(s[j]) ){
X				/* chase down remaining white space */
X				for (k=j; k<=lim && s[k] && isawhite(s[k]);k++){
X					;
X				}
X				n = isagroup(&s[i], j-i);
X				if ( n >= 0 ){
X					r = (groups[n].index + 1
X						+ rnd(groups[n].count));
X					expand( data[r], strlen(data[r]));
X					outstring(&s[j], k-j);
X				} else {
X					outstring(&s[i], k-i);
X				}
X				done++;
X				i = j = k; /* should be on next word, if any */
X			}
X			j++;
X		}
X	}
X
X
X}
X
X/*
X *	Return index into groups[] array if a group name, -1 if just a word.
X *	We have to use gbuf, a seperate place, so that we can null-terminate
X *	the string where we want.  Otherwise it wouldn't know santa from
X *	santana.
X */
Xisagroup(s,lim)
Xchar s[];
Xint lim;
X{
X	register i;
X	static char gbuf[BIGBUF];
X
X	strncpy(gbuf,s,lim);
X	gbuf[lim] = '\0';	/* strncpy might not do this */
X	for(i=0; i<ngroups; i++ ){
X		if (groups[i].name && strcmp(gbuf,groups[i].name) == 0){
X			return i;	/* hit */
X		}
X	}
X	return -1;	/* fail */
X}
X
X/*
X * 	Output string, handling splices
X */
Xoutstring(s,lim)
Xchar s[];
Xint lim;
X{
X	register i = 0;
X
X	while ( s[i] != '\0' && i < lim ){
X		switch (s[i]){
X		case '|':
X				break;	/* splice: no output */
X		case '\\':
X				putchar('\n');
X				break;
X		default:
X				putchar(s[i]);
X				break;
X		}
X		i++;
X	}
X}
X
X/*
X *     Return random number 0 to limit
X */
Xrnd(limit)
Xint limit;
X{
X	if (limit > 0){
X		return (random() % limit);
X	}
X	return 0;	/* better than a floating exception if lim == 0 */
X}
X
Xa_random_number()
X{
X	struct timeval tp;
X	struct timezone tzp;
X
X	gettimeofday (&tp, &tzp);
X
X	return((getpid() ^ tp.tv_usec) % 123456);
X}
X
X/*
X *	Return 1 if one of our "white" characters.  A white character is
X *	any character which can bound a group name, so punctuation marks
X *	are included.
X */
Xisawhite(c)
Xchar c;
X{
X	if (	c == '\0' ||		/* traditional white space */
X		c == ' '  ||
X		c == '\t' ||
X		c == '|'  ||		/* "splice" character */
X		c == '\\' ||		/* becomes a newline */
X		c == '.'  ||		/* common punctuation */
X		c == '-'  ||
X		c == ':'  ||
X		c == ';'  ||
X		c == ','  ||
X		c == '!'  ||
X		c == '?'  ||
X		c == '['  ||
X		c == ']'  ||
X		c == '{'  ||
X		c == '}'  ||
X		c == '('  ||
X		c == ')'  ||
X		c == '\'' ||
X		c == '\"' ||
X		c == '`'
X	)
X		return 1;
X	return 0;
X}
*-*-END-of-ncode.c-*-*
echo x - ncode.1
sed 's/^X//' >ncode.1 <<'*-*-END-of-ncode.1-*-*'
X.TH NCODE 1 "Pixar"	
X.SH NAME
Xncode  - stochastic text construction
X.SH SYNOPSIS
X.B ncode [-n number] [-g groupname] codefile
X.SH DESCRIPTION
X.I Ncode
Xreads in a file of a certain format and randomly constructs text based on
Xthe organization of the file.  Other files may be recursively included by
Xputting
X
X#include pathname
X
Xon any line of the file.  This is useful when
Xyou want to use a file of basic definitions, or groups, in different
Xconfigurations.
X
XThe -n flag is used to run the program through the main loop multiple times.
X
XA "group" name is defined as the word on the first line of the file and, more
Xcommonly, the word on each line following a line starting with "%".  The members
Xof a group are all lines between the group name and the next "%".  When a
Xgroup name is encountered, surrounded by any of a set of characters called
X"white space" in this context, it is randomly expanded into one of its members.
XGroup names are not allowed to contain any white space, to prevent terminal
Xconfusion on the part of the program.
X
XThe -g flag allows you to start the expanding process on a group name other
Xthan the default, which is "CODE".  The argument may be a group name, or an
Xentire string including group names, just as if it were a line in the file.
XIt is legal to start on any group in the file, and groups may be referenced
Xbefore or after the place in the file where they are defined.  In the case of
Xduplicate group definitions, the first one occurring is the only one used.
X
XFor example, here is a sample group definition:
X
X.nf
X	NOUN
X	lamp
X	house
X	car
X	%
X.fi
X
XThe line "See the NOUN." could be randomly expanded to say "See the lamp."
X
XThe characters considered "white" for the purpose of bounding a group name,
Xbesides what is normally considered white space, are currently: 
X
X	| \\ .  - : ; , ! ? [ ] { } () ' " `
X
XTwo of those characters have special meanings to
X.I ncode.
XThe "|" symbol allows you to "splice" things to a group name.  When it is
Xencountered, no character is printed on output.  The "\\" causes a newline
Xto be printed on output.
X
XThe simplest application would be for a "fortune" program, but
X.I ncode
Xcould also be used for more complex things such as a rumor generating file.
XThe group definitions will be left as an exercise for the reader, but the
Xfollowing example should prove illuminating:
X
X.nf
XCODE
XIt was rumored today that COMPANY will be bought by COMPANY for PRICE\\.
XPERSON, POSITION of COMPANY, said that PRODUCT will be announced DATE\\.
X.fi
X
XNote that every string to be expanded must be on only one line of the file.
XThe program now dynamically allocates memory in a very general way, so the
Xtotal size of your input files and the length of the lines in the files is
Xlimited only by how much memory you can get.  The only hard limit is that
Xa group name can't be over 4096 characters long.  If you can't come up
Xwith a unique group name in fewer characters then don't blame me.
X.SH BUGS
XNo bugs.  Only features that you haven't figured out how to use yet.
XA recent improvement makes it tolerant of blank lines following the last %
Xin a #include file.
X.SH DIAGNOSTICS
XStandard perror() stuff.  Pretty self explanatory.  A bogus input file might
Xbenignly yield cryptic results.
X.SH AUTHOR
XCraig Good
*-*-END-of-ncode.1-*-*
echo x - ncode.sample.1
sed 's/^X//' >ncode.sample.1 <<'*-*-END-of-ncode.sample.1-*-*'
XNOUN
XNorth
XSouth
XEast
XWest
XTruth
Xgrass
Xdesk
Xwall
Xwindow
Xceiling
Xfloor
Xcar
Xsign
X%
XNUMBER
Xone
Xtwo
Xtwo
X3.1415927
Xthree
Xeleven
Xa googol
X%
XVERB
Xmeet
Xknock
Xkiss
Xhug
Xtrot
Xmiss
Xnod
Xwink
Xhit
Xwalk
Xfly
Xzip
Xsmash
Xsniff
X%
XFLOWERS
XRoses
XViolets
XChrysanthemums
XDaisies
XGardenias
XStinkweeds
XPetunias
X%
XCOLOR
Xpuce
Xinvisible
Xred
Xtan
Xwhite
Xblue
Xgreen
Xmuave
Xpurple
Xchartreuse
Xblack
Xyellow
X%
XSOMETHING
XI am
XSugar is
XRadiation is
XComputing is
XNitrous Oxide is
XANIMALS are
XAUTHOR_ANY is
XYou are
X%
XPROPERTY
Xfearful
Xliberal
Xconservative
Xsexy
Xschizophrenic
Xsweet
Xbitter
Xstupid
Xugly
Xhilarious
Xslow
Xmiserable
X%
XISYOU
Xare you.
Xis this.
Xam I.
Xis Maple Surple.
Xis it.
Xit is.
Xare they.
X...who cares?
X%
XHAND
Xmouth
Xhand
Xhand
Xeye
Xeye
Xnose
Xear
Xtooth
Xfoot
X%
XAUTHOR_A
XCraig Good
XMichael Jackson
XWally
XBeaver
XSpock
XGidget
XBambi
XDracula
XSuperman
XKahn
XBullwinkle
XBo Derek
XKoo Stark
XLady Diana
XSteve Jobs
XRoy Rogers
XBugs Bunny
XJames Bond
XGodzilla
XKilroy
XThe Emperor
XSweeny Todd
XKate Bush
X%
XAUTHOR_AN
XAnonymous
XAndre
XOliver North
XEd Catmull
X%
XAUTHOR_ANY
XAUTHOR_AN
XAUTHOR_A
XAUTHOR_A
XFOX
XFOX
XFOX
X%
XANIMAL_A
XBird
XSnail
XPanda
XFishy
XDoggy
XPuppy
XTiger
XKitty
XWorm
XKangaroo
XWart Hog
XPenguin
XPolar Bear
XParakeet
XCat
XMountain Goat
XMoose
XMouse
X%
XANIMAL_AN
XEgret
XAardvark
XEmu
XElephant
X%
XANIMAL_ANY
XANIMAL_AN
XANIMAL_A
XANIMAL_A
XANIMAL_A
X%
XANIMALS
XBirds
XSnails
XPandas
XFish
XDogs
XPuppies
XTigers
XKittens
XAardvarks
XWorms
XKangaroos
XWart Hogs
XPenguins
XPolar Bears
XParakeets
XCats
XMountain Goats
XMooses
XMice
X%
XROYALTY
XPrince
XKing
XBoss
XProgrammer
XHacker
XSalesman
XHead Hunter
X%
XMITS
Xknickers
Xarm bands
Xmittens
Xsunglasses
Xcowboy boots
Xgaloshes
X%
XHURT
Xhurt
Xhurt
Xkill
Xslap
Xdeoderize
Xbreak
Xzap
Xvaporize
Xirradiate
Xbother
X%
XSTICKS
XSticks
XStones
XBullets
XBombs
XCroissants
XKeyboards
X%
XFOREST
Xball park
Xforest
Xswamp land
Xjungle
Xghetto
Xdrug store
Xoffice
X%
XPLACE
Xgarage
Xoven
Xbush
Xbush
XFOREST
X%
XTREE
Xa tree
XFOX's knee
XFOX's knee
XFOX's knee
XFOX's knee
X%
XPROVERB
XNOUN is NOUN, and NOUN is NOUN,\and never the twain shall meet.\
XNOUN is NOUN, and NOUN is NOUN,\and never the twain shall VERB.\
XNOUN is NOUN, and NOUN is NOUN,\and never the twain shall VERB.\
XNOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\
XNOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\
XNOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\
XA ANIMAL_A is as good as a FOREST to AUTHOR_ANY.\
XA ANIMAL_A is as good as a FOREST to AUTHOR_ANY.\
XAn ANIMAL_AN is as good as a FOREST to AUTHOR_ANY.\
XA HURT is as good as a VERB to a ANIMAL_A.\
XA HURT is as good as a VERB to an ANIMAL_AN.\
XA HURT is as good as a VERB to a ANIMAL_A.\
XA HURT is as good as a VERB to an ANIMAL_AN.\
XA VERB is as good as a HURT to AUTHOR_ANY.\
XA VERB is as good as a HURT to AUTHOR_ANY.\
XFLOWERS and MITS\May HURT my bones,\But AUTHOR_ANY will never VERB me.\
XSTICKS and ANIMALS\May HURT my bones,\But FLOWERS will never HURT me.\
XFLOWERS and STICKS\May HURT my bones,\But MITS will never HURT me.\
XSTICKS and STICKS\May HURT my bones,\But ANIMALS will never VERB me.\
XNever VERB today what you can HURT tomorrow.
XNever VERB today what you can HURT tomorrow.
XNever HURT today what you can VERB tomorrow.
XA ANIMAL_A in the HAND is worth NUMBER in the PLACE.
XAn ANIMAL_AN in the HAND is worth NUMBER in the PLACE.
XA ANIMAL_A in the HAND is worth NUMBER in the PLACE.
XAn ANIMAL_AN in the HAND is worth NUMBER in the PLACE.
XA AUTHOR_A in the HAND is worth NUMBER in the PLACE.
XAn AUTHOR_AN in the HAND is worth NUMBER in the PLACE.
XNever look a gift ANIMAL_ANY in the mouth.
XDead ANIMALS aren't much fun.
X%
XVERSE
XANIMAL_ANY, ANIMAL_ANY, burning bright\In the FOREST of the night\What immortal HAND or HAND\Dare frame thy PROPERTY symmetry?\
XFLOWERS are COLOR,\FLOWERS are COLOR,\SOMETHING PROPERTY,\And so ISYOU\
XHark!  Hark!\The ANIMALS do bark!\The ROYALTY is fond of ANIMALS\He likes to take their insides out\And wear them as his MITS.\
XI think that I shall never see\A thing as lovely\As TREE.\
X%
XTITLE
X		"Why AUTHOR_ANY tried to HURT the ANIMAL_ANY"
X		"The day AUTHOR_ANY wanted to HURT the ANIMAL_ANY"
X			"ANIMALS"
X			"FLOWERS"
X		"The PROPERTY ANIMAL_ANY"
X		"The PROPERTY FLOWERS"
X		"Ode to AUTHOR_ANY"
X		"I'm so COLOR without my ANIMAL_ANY"
X		"Ode to the ANIMAL_ANY"
X		"I'm dreaming of a COLOR Christmas"
X		"I Love The FLOWERS"
X			"Dead ANIMALS"
X%
X#include ncode.sample.2
XCODE
X\PROVERB\\			--AUTHOR_ANY\
X\PROVERB\\			--AUTHOR_ANY\
X\VERSE\\			--AUTHOR_ANY\
X\VERSE\\			--AUTHOR_ANY\
X\TITLE\\VERSE\\			--AUTHOR_ANY\
X%
*-*-END-of-ncode.sample.1-*-*
echo x - ncode.sample.2
sed 's/^X//' >ncode.sample.2 <<'*-*-END-of-ncode.sample.2-*-*'
XFOX
XAppollonia
XApril Wayne
XBarbara Hershey
XBo Derek
XBrooke Adams
XCarly Simon
XCarol Alt
XCatherine Mary Stewart
XCheryl Tiegs
XChristie Brinkley
XCoco Mitchell
XCybill Shepherd
XDarryl Hannah
XErin Grey
XFarrah Fawcett Majors
XHeather Thomas
XJaclyn Smith
XJamie Lee Curtis
XJane Seymour
XJanet Jones
XJennifer Beales
XJenny Seagrove
XJohann Carlo
XKate Capshaw
XKate Jackson
XKathy Ireland
XKelly Emberg
XKelly LeBrock
XKim Basinger
XLauren Hutton
XLea Thompson
XLisa Bonet
XLisa Hartman
XMarkie Post
XMarlee Matlin
XMelanie Griffith
XMichelle Pfieffer
XNastasia Kinski
XOla Ray
XOlivia Newton John
XPamela Sue Martin
XPaulina Porizkova
XRachel Ward
XRosanna Arquette
XSheila E
XShelly Hack
XSigney Coleman
XStevie Nicks
XTahnee Welch
XTanya Roberts
XVictoria Principal
XVivian Ruiz
XWhitney Houston
X%
*-*-END-of-ncode.sample.2-*-*
exit
----------------------------- cut here --------------------------------
(delete from here down)
-- 
		--Craig
		...{ucbvax,sun}!pixar!good