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 X#if MPW X#include /* For BlockMove(). */ X#include /* For random numbers. */ X#include /* For GetDateTime(). */ X#endif X X#define EOFCHAR (-1) X X#ifdef __STDC__ X#include /* for malloc(), free(), rand(), srand() */ X#include /* for memcoy() */ X#include /* 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; isize >= (*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; idata; X for (k=0; k0)) { 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 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= 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 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= 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