home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / frp / util / name2 / names2.c
C/C++ Source or Header  |  1991-03-09  |  19KB  |  838 lines

  1. /* names2.c */
  2. /* Random name generator */
  3.  
  4. /* Richard Kennaway */
  5. /* INTERNET:    jrk@uk.ac.uea.sys */
  6. /* UUCP:    ...mcvax!uea-sys!jrk */
  7.  
  8. /* Public domain! */
  9. /* August 1989:   First version. */
  10. /* January 1990:  Ported to MPW3.
  11.           Removed some untidiness (lint warnings).
  12.           Print randseed to stderr and take randseed as option
  13.           to allow reproducibility.
  14.           Better representation of tetragraph table.
  15.           Ability to specify character set.  */
  16. /* March 1990:      Additional patches by Martin J. Laubach
  17.           for Amiga compatibility, ANSI standard prototypes,
  18.           and elimination of some more lint warnings */
  19. /* March 1990:      Fixed the bug preventing it working on many cpus, due to
  20.           assumptions about byte-ordering.  Thanks to Carl Lowenstein
  21.           for finding this.  */
  22.  
  23.  
  24. #define FALSE  0
  25. #define TRUE   1
  26.  
  27. /* Choose one... */
  28. #define UNIX   TRUE   /* Version for Unix */
  29. /* #define MPW    FALSE    /* Version for Apple Macintosh (MPW C) */
  30. /* #define AMIGA    TRUE    /* Version for Commodore Amiga (Lattice C) -- automatically defined */
  31.  
  32. /* If MPW is TRUE, define one of MPW2 or MPW3 as TRUE, the other as FALSE. */
  33. #define MPW2   FALSE   /* MPW version 2 */
  34. #define MPW3   FALSE    /* MPW version 3 */
  35.  
  36.  
  37. /* System declarations */
  38.  
  39. #include <stdio.h>
  40. #if MPW
  41. #include <Memory.h>    /* For BlockMove(). */
  42. #include <QuickDraw.h>    /* For random numbers. */
  43. #include <OSUtils.h>    /* For GetDateTime(). */
  44. #endif
  45.  
  46. #define EOFCHAR     (-1)
  47.  
  48. #ifdef __STDC__
  49. #include <stdlib.h> /* for malloc(), free(), rand(), srand() */
  50. #include <string.h> /* for memcoy() */
  51. #include <time.h>      /* for time() */
  52. #else
  53. extern char *malloc();
  54. #endif
  55.  
  56.  
  57. /* Compatibility */
  58.  
  59. typedef char int8;
  60. typedef unsigned char uint8;
  61. typedef short int16;
  62. typedef unsigned short uint16;
  63. typedef unsigned long uint32;
  64. typedef long int32;
  65.  
  66. #define MAXUINT8        ((uint8) ((int8) (-1)))
  67. #define MAXUINT16        ((uint16) ((int16) (-1)))
  68. #define MAXUINT32        ((int32) ((int32) (-1)))
  69. #define NUMCHARS    256
  70. #define CHARMASK    255
  71. #define CHARBITS    8
  72. #define FIRSTCHAR(x)    ((uint8) (((x) >> CHARBITS) & CHARMASK))
  73. #define SECONDCHAR(x)    ((uint8) ((x) & CHARMASK))
  74. #define chartoint(c)    ((int16)(uint8)(c))
  75. #define A_CHAR        chartoint('A')
  76. #define Z_CHAR        chartoint('Z')
  77. #define a_CHAR        chartoint('a')
  78. #define z_CHAR        chartoint('z')
  79. #define SPACE_CHAR    chartoint(' ')
  80. #define A_TO_a        (a_CHAR-A_CHAR)
  81.  
  82. #if MPW2
  83. #define NEWLINECHAR     chartoint('\r')
  84. #endif
  85. #if UNIX || MPW3 || AMIGA
  86. #define NEWLINECHAR     chartoint('\n')
  87. /* Note: the actual value of '\n' is different in UNIX and MPW3,
  88.  and '\n' in MPW3 is the same as '\r' in MPW2. */
  89. #endif
  90.  
  91.  
  92. /* Where is the random number generator? */
  93.  
  94. #if UNIX
  95. typedef char *Ptr;
  96. #define Boolean        int
  97. #define BlockMove    bcopy
  98. int32 random();
  99. #define Random()    ((int16) (random()))
  100. #endif
  101.  
  102. #if AMIGA
  103. typedef char *Ptr;
  104. #define Boolean uint16
  105. #define BlockMove(from,to,size)    memcpy(to,from,size)
  106. #define random()    rand()
  107. #define srandom(x) srand(x)
  108. int32 random();
  109. #define Random()    ((int16) (random()))
  110.  
  111. int rand(void); /* bug in include files */
  112. void srand(unsigned int);
  113. #endif
  114.  
  115. uint32 RandSeed;
  116.  
  117.  
  118. /* Globals. */
  119.  
  120. int Argc;
  121. unsigned char **Argv;
  122. int ExitStatus = 0;
  123. Boolean FileArgs = FALSE, Big = TRUE, SeparateWords = TRUE;
  124. Boolean CaseSignificant = FALSE, Letters[NUMCHARS];
  125. int16 CurFile;
  126.  
  127.  
  128. /* Layout. */
  129.  
  130. #define BREAK1        60
  131. #define BREAK2        75
  132. int16 Column = 0;
  133. int32 Lines = 0;
  134. #define DEFAULTMAXLINES        20
  135. int32 MaxLines = DEFAULTMAXLINES;
  136.  
  137.  
  138. /* Tables */
  139.  
  140. int16 NumChars = 0;
  141. #define SPACEINDEX      0
  142. int32 t2size, t3size, t4size;
  143.  
  144. #define NOTCHOICE        MAXUINT16
  145.  
  146. int16 CharToIndex[NUMCHARS], IndexToChar[NUMCHARS];
  147.  
  148. int32    table0 = 0,
  149.     *table1 = NULL,
  150.     *table2 = NULL;
  151.  
  152. #define BLOCKSIZE(n)        (sizeof(int32) + sizeof(int32) + (n)*sizeof(uint16))
  153. #define INITSIZE        10
  154. #define GROWNUM            5
  155. #define GROWDEN            4
  156.  
  157. typedef struct DigraphBlock {
  158.     int32 size, maxsize;
  159.     uint16 data[1];
  160. } DigraphBlockRec, *DigraphBlockPtr;
  161.  
  162. DigraphBlockPtr *quadtable = NULL;
  163.  
  164.  
  165. /*-------------------------------------------------------------------------*/
  166. #ifdef __STDC__
  167. # define    P(s) s
  168. #else
  169. # define P(s) ()
  170. #endif
  171.  
  172. void SortArray P((uint16 *, int32 ));
  173. char *trymemory P((int32 bytesNeeded , Boolean mustGet ));
  174. void zero P((char *start , int32 numBytes ));
  175. void getmemory P((void ));
  176. void setchar P((uint8 c , Boolean accept ));
  177. void setchars P((uint8 *s , Boolean accept ));
  178. void maketranstable P((void ));
  179. Boolean openfile P((void ));
  180. Boolean getnextfile P((void ));
  181. int16 getrawchar P((void ));
  182. int16 nextchar P((void ));
  183. DigraphBlockPtr NewBlock P((int32 size ));
  184. Boolean insertdigraph P((DigraphBlockPtr *t , uint16 cd ));
  185. void entergroup P((int16 d ));
  186. void buildtable P((void ));
  187. void showtable P((void ));
  188. uint16 Rand16 P((void ));
  189. int32 randint P((int32 max ));
  190. uint16 randchoice32 P((int32 tot , int32 *dist ));
  191. void cleanupquads P((void ));
  192. uint16 randtrip P((uint8 a , uint8 b ));
  193. uint16 randquad P((uint8 a , uint8 b , uint8 c ));
  194. void outchar P((int16 c ));
  195. void generateword P((void ));
  196. void generate P((void ));
  197. void usageerror P((void ));
  198. void processoptions P((void ));
  199. void SeedRand P((void ));
  200. void MakeHeap P((int32 theElement, int32 numElements));
  201.  
  202. int main P((int argc , uint8 **argv ));
  203.  
  204. #undef P
  205. /*-------------------------------------------------------------------------*/
  206.  
  207. /* Memory allocation */
  208.  
  209. char *trymemory( bytesNeeded, mustGet )
  210. int32 bytesNeeded;
  211. Boolean mustGet;
  212. {
  213. char *result;
  214.  
  215.     result = (char *) malloc( bytesNeeded );
  216.     if ((result==NULL) && (mustGet)) {
  217.     fprintf( stderr, "Could not get %lu bytes - terminating.%c",
  218.          bytesNeeded, NEWLINECHAR );
  219.     ExitStatus = 1;
  220.     exit( ExitStatus );
  221.     }
  222.     return( result );
  223. }  /* char *trymemory( bytesNeeded, mustGet ) */
  224.  
  225. void zero( start, numBytes )
  226. char *start;
  227. int32 numBytes;
  228. {
  229. /* Your system may well have a faster way of zeroing memory. */
  230. /* In fact, the static arrays to which this procedure is applied */
  231. /* may be automatically initialised to zero already. */
  232. /* But portability would be impaired by asssuming that. */
  233.  
  234. int32 remainder, i, num32bits;
  235.  
  236.     remainder = numBytes % ((int32) 4);
  237.     for (i=1; i <= remainder; i++) start[numBytes-i] = 0;
  238.     num32bits = numBytes / ((int32) 4);
  239.     for (i=0; i<num32bits; i++) ((int32 *) start)[i] = 0;
  240. }  /* void zero( start, numBytes ) */
  241.  
  242. void getmemory()
  243. {
  244. int32 i;
  245.  
  246.     table1 = (int32 *) trymemory( NumChars * sizeof(int32), TRUE );
  247.     table2 = (int32 *) trymemory( t2size * sizeof(int32), TRUE );
  248.     quadtable = (DigraphBlockPtr *) trymemory( t2size * sizeof(DigraphBlockPtr), TRUE );
  249.  
  250.     zero( (char *) table1, NumChars * sizeof(int32) );
  251.     zero( (char *) table2, t2size * sizeof(int32) );
  252.     for (i=0; i<t2size; i++) quadtable[i] = NULL;
  253. }  /* void getmemory() */
  254.  
  255.  
  256. /* Preliminary setup */
  257.  
  258. void setchar( c, accept )
  259. uint8 c;
  260. Boolean accept;
  261. {
  262.     Letters[c] = accept;
  263.     if (! CaseSignificant) {
  264.     if ((A_CHAR <= c) && (c <= Z_CHAR)) Letters[c + A_TO_a] = accept;
  265.     if ((a_CHAR <= c) && (c <= z_CHAR)) Letters[c - A_TO_a] = accept;
  266.     }
  267. }  /* void setchar( c, accept ) */
  268.  
  269. void setchars( s, accept )
  270. uint8 *s;
  271. Boolean accept;
  272. {
  273. int16 i;
  274. uint8 c;
  275.  
  276.     if (s==NULL) return;
  277.     i = 0;
  278.     while ((c = s[i++]) != 0) setchar( c, accept );
  279. }  /* void setchars( s, accept ) */
  280.  
  281. void maketranstable()
  282. {
  283. int16 c;
  284.  
  285.     for (c=0; c < NUMCHARS; c++) {
  286.     CharToIndex[(uint8)c] = SPACEINDEX;
  287.     IndexToChar[(uint8)c] = SPACE_CHAR;
  288.     }
  289.     NumChars = 1;
  290.     if (!CaseSignificant) {
  291.     for (c=a_CHAR; c<= z_CHAR; c++) {
  292.         if (Letters[(uint8)(c - A_TO_a)] != Letters[(uint8)c]) {
  293.             Letters[(uint8)c] = TRUE;
  294.             Letters[(uint8)(c - A_TO_a)] = TRUE;
  295.         }
  296.     }
  297.     }
  298.     for (c=0; c < NUMCHARS; c++) {
  299.     if (Letters[(uint8)c] && (CaseSignificant || (c < A_CHAR) || (Z_CHAR < c))) {
  300.         CharToIndex[(uint8)c] = NumChars;
  301.         IndexToChar[(uint8)NumChars] = c;
  302.         NumChars++;
  303.     }
  304.     }
  305.     if (!CaseSignificant) {
  306.     for (c=a_CHAR; c<= z_CHAR; c++) {
  307.         CharToIndex[(uint8)(c - A_TO_a)] = CharToIndex[(uint8)c];
  308.     }
  309.     }
  310.     IndexToChar[(uint8)SPACEINDEX] = SPACE_CHAR;
  311.  
  312.     t2size = NumChars*NumChars;
  313.     t3size = t2size*NumChars;
  314.     t4size = t2size*t2size;
  315. }  /* void maketranstable() */
  316.  
  317.  
  318. /* Input */
  319.  
  320. Boolean openfile()
  321. {
  322. FILE *temp;
  323.  
  324.     temp = freopen( Argv[CurFile], "r", stdin );
  325.     if (temp == NULL) {
  326.     fprintf( stderr, "%s: could not open file \"%s\"%c",
  327.         Argv[0], Argv[CurFile], NEWLINECHAR );
  328.     ExitStatus = 2;
  329.     }
  330.     return( (Boolean)( temp != NULL ) );
  331. }  /* Boolean openfile() */
  332.  
  333. Boolean getnextfile()
  334. {
  335.     while (((++CurFile) < Argc) && (! openfile())) { /* nothing */ }
  336.     return( (Boolean)( CurFile < Argc ) );
  337. }  /* Boolean getnextfile() */
  338.  
  339. int16 getrawchar()
  340. {
  341. int16 c;
  342.     c = getchar();
  343.     while ((c==EOFCHAR) && getnextfile()) {
  344.     c = getchar();
  345.     }
  346.     return(c);
  347. }  /* int16 getrawchar() */
  348.  
  349. #define WASSPACE    0
  350. #define WASNONSPACE 1
  351. #define END         2
  352. int16 Where = WASSPACE;
  353.  
  354. int16 nextchar()
  355. {
  356. int16 c;
  357.  
  358.     switch (Where) {
  359.     case WASSPACE:
  360.         while (((c = getrawchar()) != EOFCHAR) &&
  361.            (!Letters[(uint8)c])) {
  362.         /* nothing */
  363.         }
  364.         if (c==EOFCHAR) {
  365.         Where = END;
  366.         return(-1);
  367.         } else {
  368.         Where = WASNONSPACE;
  369.         return(CharToIndex[(uint8)c]);
  370.         }
  371.     case WASNONSPACE:
  372.         c = getrawchar();
  373.         if (c==EOFCHAR) {
  374.         Where = END;
  375.         return(SPACEINDEX);
  376.         } else if (Letters[(uint8)c]) {
  377.         return(CharToIndex[(uint8)c]);
  378.         } else {
  379.         Where = WASSPACE;
  380.         return(SPACEINDEX);
  381.         }
  382.     case END:
  383.         return(-1);
  384.     }
  385.     return(-1);    /* Never happens. */
  386. }  /* int16 nextchar() */
  387.  
  388. DigraphBlockPtr NewBlock( size )
  389. int32 size;
  390. {
  391. DigraphBlockPtr temp;
  392.     temp = (DigraphBlockPtr) malloc( BLOCKSIZE(size) );
  393.     return( temp );
  394. }  /* DigraphBlockPtr NewBlock( size ) */
  395.  
  396. Boolean insertdigraph( t, cd )
  397. DigraphBlockPtr *t;
  398. uint16 cd;
  399. {
  400. DigraphBlockPtr temp;
  401. int32 newSize;
  402.  
  403.     if (t==NULL) return( FALSE );
  404.     if (((*t)==NULL) || ((*t)->size >= (*t)->maxsize)) {
  405.     newSize = (*t)==NULL ? INITSIZE : ((*t)->size * GROWNUM)/GROWDEN;
  406.     temp = NewBlock( newSize );
  407.     if (temp==NULL) return( FALSE );
  408.     if ((*t)==NULL) {
  409.         temp->size = 1;
  410.     } else {
  411.         BlockMove( (Ptr) (*t), (Ptr) temp, BLOCKSIZE((*t)->size) );
  412.         temp->size = (*t)->size + 1;
  413.         free( (char *) (*t) );
  414.     }
  415.     temp->maxsize = newSize;
  416.     *t = temp;
  417.     (*t)->data[(*t)->size-1] = cd;
  418.     } else {
  419.         (*t)->data[(*t)->size++] = cd;
  420.     }
  421.     return( TRUE );
  422. }  /* Boolean insertdigraph( t, cd ) */
  423.  
  424. int16 AA = 0, BB = 0, CC = 0;
  425.  
  426. void entergroup( d )
  427. int16 d;
  428. {
  429. int32 ab, cd;
  430.  
  431.     ab = AA*NumChars + BB;
  432.     cd = CC*NUMCHARS + d;
  433.     if (table2[ab] < MAXUINT16) {
  434.     if (insertdigraph( &(quadtable[ab]), (uint16) cd )) {
  435.         table0++;
  436.         table1[d]++;
  437.         table2[ab]++;
  438.     }
  439.     }
  440.     AA = BB;  BB = CC;  CC = d;
  441. }  /* void entergroup( d ) */
  442.  
  443. void buildtable()
  444. {
  445. int16 a0, b0, c0, d;
  446.  
  447.     a0 = nextchar();
  448.     if (a0==SPACEINDEX) a0 = nextchar();
  449.     b0 = nextchar();
  450.     c0 = nextchar();
  451.     if (c0 == -1) return;
  452.     AA = a0;  BB = b0;  CC = c0;
  453.     while ((d = nextchar()) != (-1)) {
  454.     entergroup( d );
  455.     }
  456.     if (CC==SPACEINDEX) {
  457.     entergroup( a0 );
  458.     entergroup( b0 );
  459.     entergroup( c0 );
  460.     } else {
  461.     entergroup( SPACEINDEX );
  462.     entergroup( a0 );
  463.     entergroup( b0 );
  464.     entergroup( c0 );
  465.     }
  466. }  /* void buildtable() */
  467.  
  468.  
  469. #ifdef SHOWTABLE
  470.  
  471. /* Dump the tables. */
  472. /* Only called if SHOWTABLE is defined at compile time. */
  473.  
  474. void showtable()
  475. {
  476. uint8 i, j, k;
  477. int32 *t2;
  478. uint16 *t4;
  479.  
  480.     for (i=0; i<NumChars; i++) if (table1[i] != 0) {
  481.     printf( "%c\t%lu%c", IndexToChar[i], table1[i], NEWLINECHAR );
  482.     t2 = table2 + i*NumChars;
  483.     for (j=0; j<NumChars; j++) if (t2[j] != 0) {
  484.         printf( "%c%c\t%u", IndexToChar[i], IndexToChar[j], t2[j] );
  485.         t4 = quadtable[i*NumChars + j]->data;
  486.         for (k=0; k<t2[j]; k++) {
  487.         if ((k%20==0) && (k>0)) { putchar( NEWLINECHAR );  putchar( '\t' ); }
  488.         putchar( ' ' );
  489.         putchar( IndexToChar[ FIRSTCHAR(t4[k]) ] );
  490.         putchar( IndexToChar[ SECONDCHAR(t4[k]) ] );
  491.         }
  492.         putchar( NEWLINECHAR );
  493.     }
  494.     putchar( NEWLINECHAR );
  495.     }
  496.     fflush( stdout );
  497. }  /* void showtable() */
  498.  
  499. #endif
  500.  
  501.  
  502. /* Generation of output */
  503.  
  504. uint16 Rand16()
  505. {
  506.     return( (uint16) Random() );
  507. }  /* uint16 Rand16() */
  508.  
  509. int32 randint( max )
  510. int32 max;
  511. {
  512.     if (max==0) return( 0 );
  513.     if (max <= MAXUINT16) return( ((int32) Rand16())%max );
  514.     return( ((((int32) Random()) << 16) + ((int32) Random())) % max );
  515. }  /* int32 randint( max ) */
  516.  
  517. uint16 randchoice32( tot, dist )
  518. int32 tot;
  519. int32 *dist;
  520. {
  521. int32 i;
  522. uint8 j;
  523.  
  524.     if (tot==0) return(NOTCHOICE);
  525.     i = randint( tot );
  526.     for (j=0; j<NumChars; j++) {
  527.         if (i < dist[j]) return( (uint16)(j) );
  528.     i -= dist[j];
  529.     }
  530.     return((uint16)( NOTCHOICE ));    /* Should never happen. */
  531. }  /* uint16 randchoice32( tot, dist ) */
  532.  
  533. void cleanupquads()
  534. {
  535. int32 i;
  536.  
  537.     for (i=0; i<t2size; i++) if (table2[i] > 0) {
  538.     SortArray( quadtable[i]->data, quadtable[i]->size );
  539.     }
  540. }  /* cleanupquads() */
  541.  
  542. uint16 randtrip( a, b )
  543. uint8 a, b;
  544. {
  545. uint16 aNb;
  546. int32 t2;
  547. uint16 *t4;
  548. int32 r;
  549.  
  550.     aNb = a*NumChars+b;
  551.     t2 = table2[ aNb ];
  552.     t4 = quadtable[ aNb ]->data;
  553.     r = randint( t2 );
  554.     return( (uint16) FIRSTCHAR(t4[r]) );
  555. }  /* uint16 randtrip( a, b ) */
  556.  
  557. uint16 randquad( a, b, c )
  558. uint8 a, b, c;
  559. {
  560. uint16 aNb;
  561. int32 t2;
  562. uint16 *t4;
  563. int32 lo, hi, i, r;
  564. uint8 c1;
  565.  
  566.     aNb = a*NumChars+b;
  567.     t2 = table2[ aNb ];
  568.     t4 = quadtable[ aNb ]->data;
  569.     lo = 0;
  570.     hi = 0;
  571.     for (i=0; i<t2; i++) {
  572.     c1 = FIRSTCHAR(t4[i]);
  573.         if (c1 <= c){
  574.         hi++;
  575.             if (c1 < c) lo++;
  576.     } else break;
  577.     }
  578.     if (lo >= hi) {
  579.         /* This should never happen. */
  580.         return( NOTCHOICE );
  581.     }
  582.     r = lo + randint( hi-lo );
  583.     return( (uint16) SECONDCHAR(t4[r]) );
  584. }  /* uint16 randquad( a, b, c ) */
  585.  
  586. void outchar( c )
  587. int16 c;
  588. {
  589.     if (Column < BREAK1) {
  590.     putchar(c);  Column++;
  591.     } else if (c==chartoint(' ')) {
  592.     putchar( NEWLINECHAR );
  593.     Column = 0;  Lines++;
  594.     } else if (Column >= BREAK2) {
  595.     putchar('-');  putchar( NEWLINECHAR );
  596.     Column = 0;  Lines++;
  597.     if (Lines < MaxLines) {
  598.         putchar(c);  Column++;
  599.     }
  600.     } else {
  601.     putchar(c);  Column++;
  602.     }
  603. }  /* void outchar( c ) */
  604.  
  605. void generateword()
  606. {
  607. uint16 a, b, c, d;
  608.  
  609.     a = (uint16)SPACEINDEX;
  610.     b = randchoice32( (int32) (table1[a]), table2 + a*NumChars );
  611.     if (b==NOTCHOICE) return;
  612.     outchar( IndexToChar[(uint8)b] );
  613.     if (SeparateWords && (b==SPACEINDEX)) return;
  614.  
  615.     c = randtrip( (uint16)SPACEINDEX, (uint8)b );
  616.     outchar( IndexToChar[(uint8)c] );
  617.     if (SeparateWords && (c==(uint16)SPACEINDEX)) return;
  618.  
  619.     while (Lines < MaxLines) {
  620.         d = Big ? randquad( (uint8)a, (uint8)b, (uint8)c )
  621.         : randtrip( (uint8)b, (uint8)c );
  622.     if (d==NOTCHOICE) {
  623.         outchar( '.' );
  624.         return;
  625.     }
  626.     outchar( IndexToChar[(uint8)d] );
  627.     if (SeparateWords && (d==(uint16)SPACEINDEX)) return;
  628.     a = b;  b = c;  c = d;
  629.     }
  630. }  /* void generateword() */
  631.  
  632. void generate()
  633. {
  634.     if (table0 > 0) while (Lines < MaxLines) generateword();
  635.     putchar('\n');
  636. }  /* void generate() */
  637.  
  638.  
  639. /* Argument parsing */
  640.  
  641. void usageerror()
  642. {
  643.     fprintf( stderr, "Usage: %s [-3] [-s|-w] [-c] [-axxxx] [-dxxxx] [-lnnn] [-rnnn] [file]%c",
  644.     Argv[0], NEWLINECHAR );
  645.     fprintf( stderr, "\t-3: 3rd-order statistics.%c",
  646.     NEWLINECHAR );
  647.     fprintf( stderr, "\t-w: Successive words are independent (default).%c",
  648.     NEWLINECHAR );
  649.     fprintf( stderr, "\t-s: (Sentences) Successive words are dependent.%c",
  650.     NEWLINECHAR );
  651.     fprintf( stderr, "\t-c: Treat case differences as significant.%c",
  652.     NEWLINECHAR );
  653.     fprintf( stderr, "\t-axxxx: Accept characters in string \"xxxx\" as 'letters'.%c",
  654.     NEWLINECHAR );
  655.     fprintf( stderr, "\t-dxxxx: Treat characters in string \"xxxx\" as spaces.%c",
  656.     NEWLINECHAR );
  657.     fprintf( stderr, "\tSuccessive -a/-d options are processed sequentially.%c",
  658.     NEWLINECHAR );
  659.     fprintf( stderr, "\t-lnnn: Generate nnn lines of output (default %d).%c",
  660.     DEFAULTMAXLINES, NEWLINECHAR );
  661.     fprintf( stderr, "\t-rnnn: Specify random generator seed.%c",
  662.     DEFAULTMAXLINES, NEWLINECHAR );
  663.     fputc( NEWLINECHAR, stderr );
  664.     ExitStatus = 1;
  665.     exit( ExitStatus );
  666. }  /* void usageerror() */
  667.  
  668. void processoptions()
  669. {
  670. int16 i;
  671.  
  672. /* getopt()?  What's that? :-) */
  673.  
  674.     CaseSignificant = FALSE;
  675.     for (i=0; i<NUMCHARS; i++) Letters[(uint8)i] = FALSE;
  676.     setchars( (uint8 *) "abcdefghijklmnopqrstuvwxyz", TRUE );
  677.  
  678.     CurFile = Argc;
  679.     for (i=1; i<Argc; i++) {
  680.     if (Argv[i][0] == '-') {
  681.         switch (Argv[i][1]) {
  682.         case 's':
  683.             SeparateWords = FALSE;
  684.             break;
  685.         case 'w':
  686.             SeparateWords = TRUE;
  687.             break;
  688.         case 'a':
  689.             setchars( &(Argv[i][1]), TRUE );
  690.             break;
  691.         case 'd':
  692.             setchars( &(Argv[i][1]), TRUE );
  693.             break;
  694.         case 'c':
  695.             CaseSignificant = TRUE;
  696.             break;
  697.         case '3':
  698.             Big = FALSE;
  699.             break;
  700.         case 'l':
  701.             if (Argv[i][2]==0) {
  702.             MaxLines = MAXUINT32;
  703.             } else if ((sscanf( &(Argv[i][2]), "%lu", &MaxLines ) != 1) ||
  704.             (MaxLines < 0)) {
  705.             usageerror();  /* exits */
  706.             }
  707.             break;
  708.         case 'r':
  709.             if ((Argv[i][2] != 0) &&
  710.             (sscanf( &(Argv[i][2]), "%lu", &RandSeed ) != 1)) {
  711.             usageerror();  /* exits */
  712.             }
  713.             break;
  714.         default:
  715.             usageerror();  /* exits */
  716.         }
  717.     } else if (Argv[i][0] == 0) {
  718.         FileArgs = FALSE;
  719.     } else {
  720.         FileArgs = TRUE;
  721.         CurFile = i-1;
  722.         (void) getnextfile();
  723.         return;
  724.     }
  725.     }
  726. }  /* void processoptions() */
  727.  
  728.  
  729. /* Control */
  730.  
  731. void SeedRand()
  732. {
  733. #if MPW
  734.     qd.randSeed = (int32) RandSeed;
  735. #endif
  736. #if UNIX || AMIGA
  737.     srandom( RandSeed );
  738. #endif
  739. }  /* void SeedRand() */
  740.  
  741. main( argc, argv )
  742. int argc;
  743. uint8 **argv;
  744. {
  745.     Argc = argc;  Argv = argv;
  746.  
  747. #if MPW
  748.     InitGraf( &(qd.thePort) );  /* for random numbers */
  749.     GetDateTime( &RandSeed );
  750. #endif
  751. #if UNIX
  752.     RandSeed = time(0);
  753. #endif
  754. #if AMIGA
  755.     RandSeed = time(0);
  756. #endif
  757.  
  758.     processoptions();
  759.  
  760.     SeedRand();
  761.     maketranstable();
  762.     getmemory();
  763.     fprintf( stderr, "Reading input...%c", NEWLINECHAR );
  764.     buildtable();
  765.     fprintf( stderr, "%d different letters, %u characters input.  Randseed = %lu%c",
  766.     NumChars-1, table0, RandSeed, NEWLINECHAR );
  767.     if (table0 > 0) {
  768. #ifdef SHOWTABLE
  769.     showtable();
  770. #endif
  771.     if (Big) cleanupquads();
  772. #ifdef SHOWTABLE
  773.     showtable();
  774. #endif
  775.     generate();
  776.     fflush( stdout );
  777.     }
  778.     exit( ExitStatus );
  779. }  /* main() */
  780.  
  781.  
  782. /* Heapsort. */
  783.  
  784. static uint16 *TheArray;
  785.  
  786. uint16 Temp;
  787.  
  788. #define SWAPITEM( i, j )    \
  789.     Temp = TheArray[(i)];    \
  790.     TheArray[(i)] = TheArray[(j)];    \
  791.     TheArray[(j)] = Temp    \
  792.  
  793. static void MakeHeap( theElement, numElements )
  794. int32 theElement, numElements;
  795. {
  796. int32 left, right;
  797.  
  798.     while ((left = theElement+theElement+1L) < numElements) {  
  799.     right = left+1L;
  800.     if (TheArray[theElement] < TheArray[left]) {
  801.         if ((right < numElements) &&
  802.         (TheArray[left] < TheArray[right])) {
  803.         /* M<L<R */
  804.         SWAPITEM( theElement, right );
  805.         theElement = right;
  806.         } else {  /* M<L, M<R<L, R<M<L */
  807.         SWAPITEM( theElement, left );
  808.         theElement = left;
  809.         }
  810.     } else if ((right < numElements) &&
  811.            (TheArray[theElement] < TheArray[right])) {
  812.         /* L<M<R */
  813.         SWAPITEM( theElement, right );
  814.         theElement = right;
  815.     } else {
  816.         /* L<M, L<R<M, R<L<M */
  817.         break;
  818.     }
  819.     }
  820. }  /* static void MakeHeap( theElement, numElements ) */
  821.  
  822. static void SortArray( theArray, length )
  823. uint16 *theArray;
  824. int32 length;
  825. {
  826. int32 i;
  827.  
  828.     TheArray = theArray;
  829.     
  830.     for (i = (length / 2L) - 1L; i >= 0L; i--) {
  831.     MakeHeap( i, length );
  832.     }
  833.     for (i = length-1L; i >= 1L; i--) {
  834.     SWAPITEM( 0L, i );
  835.     MakeHeap( 0L, i );
  836.     }
  837. }  /* static void SortArray( theArray, length ) */
  838.