home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume11 / names2-2 / part01 next >
Encoding:
Text File  |  1990-03-25  |  21.0 KB  |  868 lines

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