From decwrl!uunet!allbery Sun Mar 25 18:42:21 PST 1990
Article 1437 of comp.sources.misc:
Path: decwrl!uunet!allbery
From: jrk@sys.uea.ac.uk (Richard Kennaway)
Newsgroups: comp.sources.misc
Subject: v11i062: Names2 bug fix
Message-ID: <82354@uunet.UU.NET>
Date: 26 Mar 90 00:04:38 GMT
Sender: allbery@uunet.UU.NET
Organization: University of East Anglia, Norwich
Lines: 860
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

Posting-number: Volume 11, Issue 62
Submitted-by: jrk@sys.uea.ac.uk (Richard Kennaway)
Archive-name: names2-2/part01

Many users found that names2 produced garbage output full of '.' characters.
This version fixes the problem.  Thanks to Carl Lowenstein for pointing out
my unconscious assumption about byte orderings that was responsible.

Also has ANSI standard prototypes and Amiga compatibility, by Martin J.
Laubach.  (Dont worry if your C compiler doesnt accept prototypes, the
conditional compilation will automatically hide them from it.)

I took out the on_exit call, which probably never did anything useful, and
isn't in many systems' libraries.
--
Richard Kennaway          SYS, University of East Anglia, Norwich, U.K.
Internet:  jrk@sys.uea.ac.uk		uucp:  ...mcvax!ukc!uea-sys!jrk

Delete everything down to and including the cut line, feed the rest to sh.
---cut------cut------cut------cut------cut------cut------cut------cut---
echo x - names2.c
sed 's/^X//' >names2.c <<'*-*-END-of-names2.c-*-*'
X/* names2.c */
X/* Random name generator */
X
X/* Richard Kennaway */
X/* INTERNET:	jrk@uk.ac.uea.sys */
X/* UUCP:	...mcvax!uea-sys!jrk */
X
X/* Public domain! */
X/* August 1989:   First version. */
X/* January 1990:  Ported to MPW3.
X		  Removed some untidiness (lint warnings).
X		  Print randseed to stderr and take randseed as option
X		  to allow reproducibility.
X		  Better representation of tetragraph table.
X		  Ability to specify character set.  */
X/* March 1990:	  Additional patches by Martin J. Laubach
X		  for Amiga compatibility, ANSI standard prototypes,
X		  and elimination of some more lint warnings */
X/* March 1990:	  Fixed the bug preventing it working on many cpus, due to
X		  assumptions about byte-ordering.  Thanks to Carl Lowenstein
X		  for finding this.  */
X
X
X#define FALSE  0
X#define TRUE   1
X
X/* Choose one... */
X#define UNIX   TRUE   /* Version for Unix */
X#define MPW    FALSE    /* Version for Apple Macintosh (MPW C) */
X/* #define AMIGA	TRUE	/* Version for Commodore Amiga (Lattice C) -- automatically defined */
X
X/* If MPW is TRUE, define one of MPW2 or MPW3 as TRUE, the other as FALSE. */
X#define MPW2   FALSE   /* MPW version 2 */
X#define MPW3   FALSE    /* MPW version 3 */
X
X
X/* System declarations */
X
X#include <stdio.h>
X#if MPW
X#include <Memory.h>	/* For BlockMove(). */
X#include <QuickDraw.h>	/* For random numbers. */
X#include <OSUtils.h>	/* For GetDateTime(). */
X#endif
X
X#define EOFCHAR     (-1)
X
X#ifdef __STDC__
X#include <stdlib.h> /* for malloc(), free(), rand(), srand() */
X#include <string.h> /* for memcoy() */
X#include <time.h>	  /* for time() */
X#else
Xextern char *malloc();
X#endif
X
X
X/* Compatibility */
X
Xtypedef char int8;
Xtypedef unsigned char uint8;
Xtypedef short int16;
Xtypedef unsigned short uint16;
Xtypedef unsigned long uint32;
Xtypedef long int32;
X
X#define MAXUINT8		((uint8) ((int8) (-1)))
X#define MAXUINT16		((uint16) ((int16) (-1)))
X#define MAXUINT32		((int32) ((int32) (-1)))
X#define NUMCHARS	256
X#define CHARMASK	255
X#define CHARBITS	8
X#define FIRSTCHAR(x)	((uint8) (((x) >> CHARBITS) & CHARMASK))
X#define SECONDCHAR(x)	((uint8) ((x) & CHARMASK))
X#define chartoint(c)	((int16)(uint8)(c))
X#define A_CHAR		chartoint('A')
X#define Z_CHAR		chartoint('Z')
X#define a_CHAR		chartoint('a')
X#define z_CHAR		chartoint('z')
X#define SPACE_CHAR	chartoint(' ')
X#define A_TO_a		(a_CHAR-A_CHAR)
X
X#if MPW2
X#define NEWLINECHAR     chartoint('\r')
X#endif
X#if UNIX || MPW3 || AMIGA
X#define NEWLINECHAR     chartoint('\n')
X/* Note: the actual value of '\n' is different in UNIX and MPW3,
X and '\n' in MPW3 is the same as '\r' in MPW2. */
X#endif
X
X
X/* Where is the random number generator? */
X
X#if UNIX
Xtypedef char *Ptr;
X#define Boolean		int
X#define BlockMove	bcopy
Xint32 random();
X#define Random()	((int16) (random()))
X#endif
X
X#if AMIGA
Xtypedef char *Ptr;
X#define Boolean uint16
X#define BlockMove(from,to,size)	memcpy(to,from,size)
X#define random()	rand()
X#define srandom(x) srand(x)
Xint32 random();
X#define Random()	((int16) (random()))
X
Xint rand(void); /* bug in include files */
Xvoid srand(unsigned int);
X#endif
X
Xuint32 RandSeed;
X
X
X/* Globals. */
X
Xint Argc;
Xunsigned char **Argv;
Xint ExitStatus = 0;
XBoolean FileArgs = FALSE, Big = TRUE, SeparateWords = TRUE;
XBoolean CaseSignificant = FALSE, Letters[NUMCHARS];
Xint16 CurFile;
X
X
X/* Layout. */
X
X#define BREAK1		60
X#define BREAK2		75
Xint16 Column = 0;
Xint32 Lines = 0;
X#define DEFAULTMAXLINES		20
Xint32 MaxLines = DEFAULTMAXLINES;
X
X
X/* Tables */
X
Xint16 NumChars = 0;
X#define SPACEINDEX      0
Xint32 t2size, t3size, t4size;
X
X#define NOTCHOICE		MAXUINT16
X
Xint16 CharToIndex[NUMCHARS], IndexToChar[NUMCHARS];
X
Xint32	table0 = 0,
X	*table1 = NULL,
X	*table2 = NULL;
X
X#define BLOCKSIZE(n)		(sizeof(int32) + sizeof(int32) + (n)*sizeof(uint16))
X#define INITSIZE		10
X#define GROWNUM			5
X#define GROWDEN			4
X
Xtypedef struct DigraphBlock {
X	int32 size, maxsize;
X	uint16 data[1];
X} DigraphBlockRec, *DigraphBlockPtr;
X
XDigraphBlockPtr *quadtable = NULL;
X
X
X/*-------------------------------------------------------------------------*/
X#ifdef __STDC__
X# define	P(s) s
X#else
X# define P(s) ()
X#endif
X
Xvoid SortArray P((uint16 *, int32 ));
Xchar *trymemory P((int32 bytesNeeded , Boolean mustGet ));
Xvoid zero P((char *start , int32 numBytes ));
Xvoid getmemory P((void ));
Xvoid setchar P((uint8 c , Boolean accept ));
Xvoid setchars P((uint8 *s , Boolean accept ));
Xvoid maketranstable P((void ));
XBoolean openfile P((void ));
XBoolean getnextfile P((void ));
Xint16 getrawchar P((void ));
Xint16 nextchar P((void ));
XDigraphBlockPtr NewBlock P((int32 size ));
XBoolean insertdigraph P((DigraphBlockPtr *t , uint16 cd ));
Xvoid entergroup P((int16 d ));
Xvoid buildtable P((void ));
Xvoid showtable P((void ));
Xuint16 Rand16 P((void ));
Xint32 randint P((int32 max ));
Xuint16 randchoice32 P((int32 tot , int32 *dist ));
Xvoid cleanupquads P((void ));
Xuint16 randtrip P((uint8 a , uint8 b ));
Xuint16 randquad P((uint8 a , uint8 b , uint8 c ));
Xvoid outchar P((int16 c ));
Xvoid generateword P((void ));
Xvoid generate P((void ));
Xvoid usageerror P((void ));
Xvoid processoptions P((void ));
Xvoid SeedRand P((void ));
Xvoid MakeHeap P((int32 theElement, int32 numElements));
X
Xint main P((int argc , uint8 **argv ));
X
X#undef P
X/*-------------------------------------------------------------------------*/
X
X/* Memory allocation */
X
Xchar *trymemory( bytesNeeded, mustGet )
Xint32 bytesNeeded;
XBoolean mustGet;
X{
Xchar *result;
X
X    result = (char *) malloc( bytesNeeded );
X    if ((result==NULL) && (mustGet)) {
X	fprintf( stderr, "Could not get %lu bytes - terminating.%c",
X		 bytesNeeded, NEWLINECHAR );
X	ExitStatus = 1;
X	exit( ExitStatus );
X    }
X    return( result );
X}  /* char *trymemory( bytesNeeded, mustGet ) */
X
Xvoid zero( start, numBytes )
Xchar *start;
Xint32 numBytes;
X{
X/* Your system may well have a faster way of zeroing memory. */
X/* In fact, the static arrays to which this procedure is applied */
X/* may be automatically initialised to zero already. */
X/* But portability would be impaired by asssuming that. */
X
Xint32 remainder, i, num32bits;
X
X    remainder = numBytes % ((int32) 4);
X    for (i=1; i <= remainder; i++) start[numBytes-i] = 0;
X    num32bits = numBytes / ((int32) 4);
X    for (i=0; i<num32bits; i++) ((int32 *) start)[i] = 0;
X}  /* void zero( start, numBytes ) */
X
Xvoid getmemory()
X{
Xint32 i;
X
X    table1 = (int32 *) trymemory( NumChars * sizeof(int32), TRUE );
X    table2 = (int32 *) trymemory( t2size * sizeof(int32), TRUE );
X    quadtable = (DigraphBlockPtr *) trymemory( t2size * sizeof(DigraphBlockPtr), TRUE );
X
X    zero( (char *) table1, NumChars * sizeof(int32) );
X    zero( (char *) table2, t2size * sizeof(int32) );
X    for (i=0; i<t2size; i++) quadtable[i] = NULL;
X}  /* void getmemory() */
X
X
X/* Preliminary setup */
X
Xvoid setchar( c, accept )
Xuint8 c;
XBoolean accept;
X{
X    Letters[c] = accept;
X    if (! CaseSignificant) {
X	if ((A_CHAR <= c) && (c <= Z_CHAR)) Letters[c + A_TO_a] = accept;
X	if ((a_CHAR <= c) && (c <= z_CHAR)) Letters[c - A_TO_a] = accept;
X    }
X}  /* void setchar( c, accept ) */
X
Xvoid setchars( s, accept )
Xuint8 *s;
XBoolean accept;
X{
Xint16 i;
Xuint8 c;
X
X    if (s==NULL) return;
X    i = 0;
X    while ((c = s[i++]) != 0) setchar( c, accept );
X}  /* void setchars( s, accept ) */
X
Xvoid maketranstable()
X{
Xint16 c;
X
X    for (c=0; c < NUMCHARS; c++) {
X	CharToIndex[(uint8)c] = SPACEINDEX;
X	IndexToChar[(uint8)c] = SPACE_CHAR;
X    }
X    NumChars = 1;
X    if (!CaseSignificant) {
X	for (c=a_CHAR; c<= z_CHAR; c++) {
X	    if (Letters[(uint8)(c - A_TO_a)] != Letters[(uint8)c]) {
X	    	Letters[(uint8)c] = TRUE;
X	    	Letters[(uint8)(c - A_TO_a)] = TRUE;
X	    }
X	}
X    }
X    for (c=0; c < NUMCHARS; c++) {
X	if (Letters[(uint8)c] && (CaseSignificant || (c < A_CHAR) || (Z_CHAR < c))) {
X	    CharToIndex[(uint8)c] = NumChars;
X	    IndexToChar[(uint8)NumChars] = c;
X	    NumChars++;
X	}
X    }
X    if (!CaseSignificant) {
X	for (c=a_CHAR; c<= z_CHAR; c++) {
X	    CharToIndex[(uint8)(c - A_TO_a)] = CharToIndex[(uint8)c];
X	}
X    }
X    IndexToChar[(uint8)SPACEINDEX] = SPACE_CHAR;
X
X    t2size = NumChars*NumChars;
X    t3size = t2size*NumChars;
X    t4size = t2size*t2size;
X}  /* void maketranstable() */
X
X
X/* Input */
X
XBoolean openfile()
X{
XFILE *temp;
X
X    temp = freopen( Argv[CurFile], "r", stdin );
X    if (temp == NULL) {
X	fprintf( stderr, "%s: could not open file \"%s\"%c",
X	    Argv[0], Argv[CurFile], NEWLINECHAR );
X	ExitStatus = 2;
X    }
X    return( (Boolean)( temp != NULL ) );
X}  /* Boolean openfile() */
X
XBoolean getnextfile()
X{
X    while (((++CurFile) < Argc) && (! openfile())) { /* nothing */ }
X    return( (Boolean)( CurFile < Argc ) );
X}  /* Boolean getnextfile() */
X
Xint16 getrawchar()
X{
Xint16 c;
X    c = getchar();
X    while ((c==EOFCHAR) && getnextfile()) {
X	c = getchar();
X    }
X    return(c);
X}  /* int16 getrawchar() */
X
X#define WASSPACE    0
X#define WASNONSPACE 1
X#define END         2
Xint16 Where = WASSPACE;
X
Xint16 nextchar()
X{
Xint16 c;
X
X    switch (Where) {
X	case WASSPACE:
X	    while (((c = getrawchar()) != EOFCHAR) &&
X		   (!Letters[(uint8)c])) {
X		/* nothing */
X	    }
X	    if (c==EOFCHAR) {
X		Where = END;
X		return(-1);
X	    } else {
X		Where = WASNONSPACE;
X		return(CharToIndex[(uint8)c]);
X	    }
X	case WASNONSPACE:
X	    c = getrawchar();
X	    if (c==EOFCHAR) {
X		Where = END;
X		return(SPACEINDEX);
X	    } else if (Letters[(uint8)c]) {
X		return(CharToIndex[(uint8)c]);
X	    } else {
X		Where = WASSPACE;
X		return(SPACEINDEX);
X	    }
X	case END:
X	    return(-1);
X    }
X    return(-1);	/* Never happens. */
X}  /* int16 nextchar() */
X
XDigraphBlockPtr NewBlock( size )
Xint32 size;
X{
XDigraphBlockPtr temp;
X    temp = (DigraphBlockPtr) malloc( BLOCKSIZE(size) );
X    return( temp );
X}  /* DigraphBlockPtr NewBlock( size ) */
X
XBoolean insertdigraph( t, cd )
XDigraphBlockPtr *t;
Xuint16 cd;
X{
XDigraphBlockPtr temp;
Xint32 newSize;
X
X    if (t==NULL) return( FALSE );
X    if (((*t)==NULL) || ((*t)->size >= (*t)->maxsize)) {
X	newSize = (*t)==NULL ? INITSIZE : ((*t)->size * GROWNUM)/GROWDEN;
X	temp = NewBlock( newSize );
X	if (temp==NULL) return( FALSE );
X	if ((*t)==NULL) {
X	    temp->size = 1;
X	} else {
X	    BlockMove( (Ptr) (*t), (Ptr) temp, BLOCKSIZE((*t)->size) );
X	    temp->size = (*t)->size + 1;
X	    free( (char *) (*t) );
X	}
X	temp->maxsize = newSize;
X	*t = temp;
X	(*t)->data[(*t)->size-1] = cd;
X    } else {
X    	(*t)->data[(*t)->size++] = cd;
X    }
X    return( TRUE );
X}  /* Boolean insertdigraph( t, cd ) */
X
Xint16 AA = 0, BB = 0, CC = 0;
X
Xvoid entergroup( d )
Xint16 d;
X{
Xint32 ab, cd;
X
X    ab = AA*NumChars + BB;
X    cd = CC*NUMCHARS + d;
X    if (table2[ab] < MAXUINT16) {
X	if (insertdigraph( &(quadtable[ab]), (uint16) cd )) {
X	    table0++;
X	    table1[d]++;
X	    table2[ab]++;
X	}
X    }
X    AA = BB;  BB = CC;  CC = d;
X}  /* void entergroup( d ) */
X
Xvoid buildtable()
X{
Xint16 a0, b0, c0, d;
X
X    a0 = nextchar();
X    if (a0==SPACEINDEX) a0 = nextchar();
X    b0 = nextchar();
X    c0 = nextchar();
X    if (c0 == -1) return;
X    AA = a0;  BB = b0;  CC = c0;
X    while ((d = nextchar()) != (-1)) {
X	entergroup( d );
X    }
X    if (CC==SPACEINDEX) {
X	entergroup( a0 );
X	entergroup( b0 );
X	entergroup( c0 );
X    } else {
X	entergroup( SPACEINDEX );
X	entergroup( a0 );
X	entergroup( b0 );
X	entergroup( c0 );
X    }
X}  /* void buildtable() */
X
X
X#ifdef SHOWTABLE
X
X/* Dump the tables. */
X/* Only called if SHOWTABLE is defined at compile time. */
X
Xvoid showtable()
X{
Xuint8 i, j, k;
Xint32 *t2;
Xuint16 *t4;
X
X    for (i=0; i<NumChars; i++) if (table1[i] != 0) {
X	printf( "%c\t%lu%c", IndexToChar[i], table1[i], NEWLINECHAR );
X	t2 = table2 + i*NumChars;
X	for (j=0; j<NumChars; j++) if (t2[j] != 0) {
X	    printf( "%c%c\t%u", IndexToChar[i], IndexToChar[j], t2[j] );
X	    t4 = quadtable[i*NumChars + j]->data;
X	    for (k=0; k<t2[j]; k++) {
X		if ((k%20==0) && (k>0)) { putchar( NEWLINECHAR );  putchar( '\t' ); }
X		putchar( ' ' );
X		putchar( IndexToChar[ FIRSTCHAR(t4[k]) ] );
X		putchar( IndexToChar[ SECONDCHAR(t4[k]) ] );
X	    }
X	    putchar( NEWLINECHAR );
X	}
X	putchar( NEWLINECHAR );
X    }
X    fflush( stdout );
X}  /* void showtable() */
X
X#endif
X
X
X/* Generation of output */
X
Xuint16 Rand16()
X{
X    return( (uint16) Random() );
X}  /* uint16 Rand16() */
X
Xint32 randint( max )
Xint32 max;
X{
X    if (max==0) return( 0 );
X    if (max <= MAXUINT16) return( ((int32) Rand16())%max );
X    return( ((((int32) Random()) << 16) + ((int32) Random())) % max );
X}  /* int32 randint( max ) */
X
Xuint16 randchoice32( tot, dist )
Xint32 tot;
Xint32 *dist;
X{
Xint32 i;
Xuint8 j;
X
X    if (tot==0) return(NOTCHOICE);
X    i = randint( tot );
X    for (j=0; j<NumChars; j++) {
X    	if (i < dist[j]) return( (uint16)(j) );
X	i -= dist[j];
X    }
X    return((uint16)( NOTCHOICE ));	/* Should never happen. */
X}  /* uint16 randchoice32( tot, dist ) */
X
Xvoid cleanupquads()
X{
Xint32 i;
X
X    for (i=0; i<t2size; i++) if (table2[i] > 0) {
X	SortArray( quadtable[i]->data, quadtable[i]->size );
X    }
X}  /* cleanupquads() */
X
Xuint16 randtrip( a, b )
Xuint8 a, b;
X{
Xuint16 aNb;
Xint32 t2;
Xuint16 *t4;
Xint32 r;
X
X    aNb = a*NumChars+b;
X    t2 = table2[ aNb ];
X    t4 = quadtable[ aNb ]->data;
X    r = randint( t2 );
X    return( (uint16) FIRSTCHAR(t4[r]) );
X}  /* uint16 randtrip( a, b ) */
X
Xuint16 randquad( a, b, c )
Xuint8 a, b, c;
X{
Xuint16 aNb;
Xint32 t2;
Xuint16 *t4;
Xint32 lo, hi, i, r;
Xuint8 c1;
X
X    aNb = a*NumChars+b;
X    t2 = table2[ aNb ];
X    t4 = quadtable[ aNb ]->data;
X    lo = 0;
X    hi = 0;
X    for (i=0; i<t2; i++) {
X	c1 = FIRSTCHAR(t4[i]);
X    	if (c1 <= c){
X	    hi++;
X    	    if (c1 < c) lo++;
X	} else break;
X    }
X    if (lo >= hi) {
X    	/* This should never happen. */
X    	return( NOTCHOICE );
X    }
X    r = lo + randint( hi-lo );
X    return( (uint16) SECONDCHAR(t4[r]) );
X}  /* uint16 randquad( a, b, c ) */
X
Xvoid outchar( c )
Xint16 c;
X{
X    if (Column < BREAK1) {
X	putchar(c);  Column++;
X    } else if (c==chartoint(' ')) {
X	putchar( NEWLINECHAR );
X	Column = 0;  Lines++;
X    } else if (Column >= BREAK2) {
X	putchar('-');  putchar( NEWLINECHAR );
X	Column = 0;  Lines++;
X	if (Lines < MaxLines) {
X	    putchar(c);  Column++;
X	}
X    } else {
X	putchar(c);  Column++;
X    }
X}  /* void outchar( c ) */
X
Xvoid generateword()
X{
Xuint16 a, b, c, d;
X
X    a = (uint16)SPACEINDEX;
X    b = randchoice32( (int32) (table1[a]), table2 + a*NumChars );
X    if (b==NOTCHOICE) return;
X    outchar( IndexToChar[(uint8)b] );
X    if (SeparateWords && (b==SPACEINDEX)) return;
X
X    c = randtrip( (uint16)SPACEINDEX, (uint8)b );
X    outchar( IndexToChar[(uint8)c] );
X    if (SeparateWords && (c==(uint16)SPACEINDEX)) return;
X
X    while (Lines < MaxLines) {
X    	d = Big ? randquad( (uint8)a, (uint8)b, (uint8)c )
X		: randtrip( (uint8)b, (uint8)c );
X	if (d==NOTCHOICE) {
X	    outchar( '.' );
X	    return;
X	}
X	outchar( IndexToChar[(uint8)d] );
X	if (SeparateWords && (d==(uint16)SPACEINDEX)) return;
X	a = b;  b = c;  c = d;
X    }
X}  /* void generateword() */
X
Xvoid generate()
X{
X    if (table0 > 0) while (Lines < MaxLines) generateword();
X}  /* void generate() */
X
X
X/* Argument parsing */
X
Xvoid usageerror()
X{
X    fprintf( stderr, "Usage: %s [-3] [-s|-w] [-c] [-axxxx] [-dxxxx] [-lnnn] [-rnnn] [file]%c",
X	Argv[0], NEWLINECHAR );
X    fprintf( stderr, "\t-3: 3rd-order statistics.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-w: Successive words are independent (default).%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-s: (Sentences) Successive words are dependent.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-c: Treat case differences as significant.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-axxxx: Accept characters in string \"xxxx\" as 'letters'.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-dxxxx: Treat characters in string \"xxxx\" as spaces.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\tSuccessive -a/-d options are processed sequentially.%c",
X	NEWLINECHAR );
X    fprintf( stderr, "\t-lnnn: Generate nnn lines of output (default %d).%c",
X	DEFAULTMAXLINES, NEWLINECHAR );
X    fprintf( stderr, "\t-rnnn: Specify random generator seed.%c",
X	DEFAULTMAXLINES, NEWLINECHAR );
X    fputc( NEWLINECHAR, stderr );
X    ExitStatus = 1;
X    exit( ExitStatus );
X}  /* void usageerror() */
X
Xvoid processoptions()
X{
Xint16 i;
X
X/* getopt()?  What's that? :-) */
X
X    CaseSignificant = FALSE;
X    for (i=0; i<NUMCHARS; i++) Letters[(uint8)i] = FALSE;
X    setchars( (uint8 *) "abcdefghijklmnopqrstuvwxyz", TRUE );
X
X    CurFile = Argc;
X    for (i=1; i<Argc; i++) {
X	if (Argv[i][0] == '-') {
X	    switch (Argv[i][1]) {
X		case 's':
X		    SeparateWords = FALSE;
X		    break;
X		case 'w':
X		    SeparateWords = TRUE;
X		    break;
X		case 'a':
X		    setchars( &(Argv[i][1]), TRUE );
X		    break;
X		case 'd':
X		    setchars( &(Argv[i][1]), TRUE );
X		    break;
X		case 'c':
X		    CaseSignificant = TRUE;
X		    break;
X		case '3':
X		    Big = FALSE;
X		    break;
X		case 'l':
X		    if (Argv[i][2]==0) {
X			MaxLines = MAXUINT32;
X		    } else if ((sscanf( &(Argv[i][2]), "%lu", &MaxLines ) != 1) ||
X			(MaxLines < 0)) {
X			usageerror();  /* exits */
X		    }
X		    break;
X		case 'r':
X		    if ((Argv[i][2] != 0) &&
X			(sscanf( &(Argv[i][2]), "%lu", &RandSeed ) != 1)) {
X			usageerror();  /* exits */
X		    }
X		    break;
X		default:
X		    usageerror();  /* exits */
X	    }
X	} else if (Argv[i][0] == 0) {
X	    FileArgs = FALSE;
X	} else {
X	    FileArgs = TRUE;
X	    CurFile = i-1;
X	    (void) getnextfile();
X	    return;
X	}
X    }
X}  /* void processoptions() */
X
X
X/* Control */
X
Xvoid SeedRand()
X{
X#if MPW
X    qd.randSeed = (int32) RandSeed;
X#endif
X#if UNIX || AMIGA
X    srandom( RandSeed );
X#endif
X}  /* void SeedRand() */
X
Xmain( argc, argv )
Xint argc;
Xuint8 **argv;
X{
X    Argc = argc;  Argv = argv;
X
X#if MPW
X    InitGraf( &(qd.thePort) );  /* for random numbers */
X    GetDateTime( &RandSeed );
X#endif
X#if UNIX
X    RandSeed = time(0);
X#endif
X#if AMIGA
X    RandSeed = time(0);
X#endif
X
X    processoptions();
X
X    SeedRand();
X    maketranstable();
X    getmemory();
X    fprintf( stderr, "Reading input...%c", NEWLINECHAR );
X    buildtable();
X    fprintf( stderr, "%d different letters, %u characters input.  Randseed = %lu%c",
X	NumChars-1, table0, RandSeed, NEWLINECHAR );
X    if (table0 > 0) {
X#ifdef SHOWTABLE
X	showtable();
X#endif
X	if (Big) cleanupquads();
X#ifdef SHOWTABLE
X	showtable();
X#endif
X	generate();
X	fflush( stdout );
X    }
X    exit( ExitStatus );
X}  /* main() */
X
X
X/* Heapsort. */
X
Xstatic uint16 *TheArray;
X
Xuint16 Temp;
X
X#define SWAPITEM( i, j )	\
X    Temp = TheArray[(i)];	\
X    TheArray[(i)] = TheArray[(j)];	\
X    TheArray[(j)] = Temp	\
X
Xstatic void MakeHeap( theElement, numElements )
Xint32 theElement, numElements;
X{
Xint32 left, right;
X
X    while ((left = theElement+theElement+1L) < numElements) {  
X	right = left+1L;
X	if (TheArray[theElement] < TheArray[left]) {
X	    if ((right < numElements) &&
X		(TheArray[left] < TheArray[right])) {
X		/* M<L<R */
X		SWAPITEM( theElement, right );
X		theElement = right;
X	    } else {  /* M<L, M<R<L, R<M<L */
X		SWAPITEM( theElement, left );
X		theElement = left;
X	    }
X	} else if ((right < numElements) &&
X		   (TheArray[theElement] < TheArray[right])) {
X	    /* L<M<R */
X	    SWAPITEM( theElement, right );
X	    theElement = right;
X	} else {
X	    /* L<M, L<R<M, R<L<M */
X	    break;
X	}
X    }
X}  /* static void MakeHeap( theElement, numElements ) */
X
Xstatic void SortArray( theArray, length )
Xuint16 *theArray;
Xint32 length;
X{
Xint32 i;
X
X    TheArray = theArray;
X    
X    for (i = (length / 2L) - 1L; i >= 0L; i--) {
X	MakeHeap( i, length );
X    }
X    for (i = length-1L; i >= 1L; i--) {
X	SWAPITEM( 0L, i );
X	MakeHeap( 0L, i );
X    }
X}  /* static void SortArray( theArray, length ) */
*-*-END-of-names2.c-*-*
exit


