home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume07 / names.jrk < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  19.8 KB

  1. From decwrl!shelby!rutgers!cs.utexas.edu!uunet!allbery Sat Aug 12 15:58:47 PDT 1989
  2. Article 1025 of comp.sources.misc:
  3. Path: decwrl!shelby!rutgers!cs.utexas.edu!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v07i124: random names generator
  7. Message-ID: <62973@uunet.UU.NET>
  8. Date: 8 Aug 89 00:31:04 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Reply-To: jrk@sys.uea.ac.uk (Richard Kennaway)
  11. Organization: University of East Anglia, Norwich
  12. Lines: 741
  13. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  14.  
  15. Posting-number: Volume 7, Issue 124
  16. Submitted-by: jrk@sys.uea.ac.uk (Richard Kennaway)
  17. Archive-name: names_jrk
  18.  
  19. This is names.c, a program for generating random names for FRP characters.
  20. Unlike many other such programs, this one will generate names to match
  21. any language you like.  Feed it with text in that language, and it will
  22. generate words statistically similar to the input text.  For example,
  23. here is some of the output it gives when fed with the Sindarin words
  24. from a Sindarin-English dictionary:
  25.  
  26.     annun ossen bered lamedo tolbrandirithron meregil arad doriel
  27.     lothrond nim min rohir carch menel caradan uil las tolbrant arahad
  28.     dol egalen rhiw iath remmen celeth arveduin elwing benn min forlan
  29.     uil angborn morgai arad torn dain char thond toreth anfaladel
  30.  
  31. As you can see, not all the output is directly usable, but by
  32. exercising some selection you can obtain results like:
  33.  
  34.     Ossiriel, Eredhel, Belain, Minarwen, Gwathlain, Gundaer,
  35.     Suldor Belebrethand, Berielegor, Gwairithir, Gaurgor, Nardol,
  36.     Sammathremmir,...
  37.  
  38. For comparison, here's some output from the food-and-drink section of a
  39. German phrasebook :-):
  40.  
  41.     kursch rhampelebans prottelm tradivier en bohl sauber arnen men
  42.     rautt kabbeer banineln stetschahn blummeloneulen sarneclacher
  43.     men chwarschen aal raustdorelone en garscht karadie blat raube
  44.     sch kirschte protten flen mohl arderben audelspinguse trauchel
  45.  
  46. Runs on Macintosh (if you have MPW) and Unix.
  47. Public domain.  Share and enjoy.
  48.  
  49. --
  50. Richard Kennaway          SYS, University of East Anglia, Norwich, U.K.
  51. uucp:  ...mcvax!ukc!uea-sys!jrk        Janet:  kennaway@uk.ac.uea.sys
  52.  
  53. -----cut-----cut-----cut-----cut-----cut-----cut-----cut-----cut-----cut-----
  54. #! /bin/sh
  55. # This is a shar archive.  "sh" it to unpack.
  56. # Contents: names.1 Makefile names.c
  57. echo x - names.1
  58. sed 's/^X//' >names.1 <<'*-*-END-of-names.1-*-*'
  59. X.TH NAMES 1 "August 1989"
  60. X.UC
  61. X.SH NAME
  62. Xnames \- generate random names
  63. X.SH SYNOPSIS
  64. X.B names
  65. X[
  66. X.B \-3
  67. X] [
  68. X.BR \-w\ |\ \-s
  69. X] [
  70. X.B -l
  71. X.I nnn
  72. X] [
  73. X.I files
  74. X]
  75. X.SH DESCRIPTION
  76. X.I Names
  77. Xis a random name generator.
  78. XIt will read text from standard input or from files given on the
  79. Xcommand line, and generate a random stream of words whose statistical
  80. Xcharacteristics are similar to those of the input.
  81. XThus if you give it a database of Elvish names, it will generate Elvish-like
  82. Xnames; if a database of Orcish names, it generates Orc-like names, etc.
  83. X.PP
  84. XIt does this by counting the frequency of all 1-, 2-, 3-, and 4-character
  85. Xsequences of letters or spaces in the input.
  86. XCase is ignored, and all runs of non-letters are seen as single spaces.
  87. XThe first character to be output, say "a",
  88. Xis generated according to the relative frequencies
  89. Xwith which each character was found to follow a space in the input.
  90. XThe second, say "b", is generated according to the relative frequencies with
  91. Xwhich each character can appear following the digraph " a".
  92. XThe third is generated according to the relative frequencies with which
  93. Xeach character follows the trigraph " ab".
  94. XAnd so on ad infinitum, each new character depending on the previous three.
  95. X.PP
  96. XThe larger the input, the better.
  97. XIt needs at least a few thousand bytes of input for useful results.
  98. XIf the input is not large enough,
  99. Xyou will tend to get words from the input appearing verbatim in the
  100. Xoutput, as much of the time three consecutive characters will uniquely
  101. Xdetermine the next character.
  102. XIf more input of the desired form is not available, the program can be
  103. Xmade to use a third-order approximation instead, each character of the
  104. Xoutput depending only on the two preceding characters.  This is also
  105. Xuseful if there is not enough memory to construct the tetragraph
  106. Xtable, which occupies just over half a megabyte.
  107. X.PP
  108. XThe output is wrapped to 76 chars maximum, hyphenating any word
  109. Xthat has to be broken over a line-end.
  110. X.PP
  111. X.I Names
  112. Xwill run on Unix, and on a Macintosh as an MPW shell tool.
  113. X.SH OPTIONS
  114. X.TP
  115. X.B \-w
  116. XGenerate successive words independently,
  117. Xi.e. each word begins as if it was the beginning of the whole output,
  118. Xignoring how the preceding word ended.  (Default.)
  119. X.TP
  120. X.B \-s
  121. XNegation of
  122. X.B \-w
  123. Xoption.
  124. XThe first character of each word will depend on the last three characters
  125. Xgenerated (i.e. the last two characters of the preceding word,
  126. Xand the inter-word space).
  127. X.TP
  128. X.B \-l nnn
  129. XGenerate nnn lines of output.  Default is 20.
  130. XNo space between the \-l and the nnn.
  131. XIf \-l is given with no argument, the output will go on (nearly) forever.
  132. X.TP
  133. X.B \-3
  134. XUse trigraph frequencies instead of tetragraph frequencies.
  135. XGives better results when input data is limited.
  136. XThis option will automatically be used if there is insufficient memory
  137. Xto build the tetragraph table (a warning will be given).
  138. X.SH DIAGNOSTICS
  139. X.I Names
  140. Xgives a usage message if the arguments are bad.
  141. XExits with status 0 if all went well.
  142. XExits with status 1 if there were bad arguments (other than non-existent
  143. Xfiles), or insufficient memory for even trigraph tables.
  144. XNo names are generated.
  145. XOtherwise, exits with status 2 if any files were not found
  146. X(however, it will read all the files it could find and generate names).
  147. X.PP
  148. XWrites to stderr a count of the characters read
  149. X(i.e. letters and runs of non-letters).
  150. X.PP
  151. XIf compiled with SHOWTABLE defined,
  152. Xdumps the 0th to 3rd order tables to standard output
  153. Xbefore the random names.
  154. X.SH LIMITATIONS
  155. XThe tetragraph counts are limited to 255 maximum,
  156. Xthe trigraph and digraph counts to 65535,
  157. Xand the total number of characters read to 4294967295.
  158. X(The counts stick at their maximum values if they are reached,
  159. Xthey do not overflow.)
  160. X.SH FURTHER IDEAS
  161. XA more compact form of the tetragraph tables could be used.
  162. XThis would allow the use of a larger character set (e.g. accented letters,
  163. Xwhich play a large part in the Elvish languages).
  164. X.PP
  165. XArrange to write the tetragraph tables to a file
  166. Xand read them in again, to avoid having to reconstruct them
  167. Xevery time.  Use some sort of compression to keep the file size down.
  168. X(Run-length encoding might do - most of the entries will be zero.)
  169. X.PP
  170. XWhen insufficient input is available for good fourth-order generation,
  171. Xinstead of using trigraph statistics a better way of improving the output
  172. Xmight be to fudge the tetragraph frequencies a little.  Wherever a trigraph is
  173. Xfound with only one possible successor, choose some other letter
  174. Xand make its frequency nonzero.  Make the choice based on some
  175. Xnotion of similarity among letters.  Such a notion should not
  176. Xbe defined a priori, but based on the statistics of the input.
  177. X.SH AUTHOR
  178. XRichard Kennaway.
  179. X.PP
  180. Xjrk@uk.ac.uea.sys (JANET), ...mcvax!uea-sys!jrk (UUCP).
  181. X.PP
  182. XThis program is public domain.
  183. XDon't bother telling me the code could be improved, I know.
  184. XBy all means tell me of any improvements you make.
  185. *-*-END-of-names.1-*-*
  186. echo x - Makefile
  187. sed 's/^X//' >Makefile <<'*-*-END-of-Makefile-*-*'
  188. Xnames : names.c
  189. X    cc names.c -o names
  190. *-*-END-of-Makefile-*-*
  191. echo x - names.c
  192. sed 's/^X//' >names.c <<'*-*-END-of-names.c-*-*'
  193. X/* names.c */
  194. X/* Random name generator */
  195. X
  196. X/* Richard Kennaway */
  197. X/* JANET:  jrk@uk.ac.uea.sys */
  198. X/* UUCP:   ...mcvax!uea-sys!jrk */
  199. X
  200. X/* August 1989 */
  201. X/* Public domain! */
  202. X
  203. X
  204. X#define FALSE  0
  205. X#define TRUE   1
  206. X
  207. X/* Choose one... */
  208. X#define UNIX   TRUE    /* Version for Unix */
  209. X#define MPW    FALSE   /* Version for Apple MacIntosh (MPW C) */
  210. X
  211. X
  212. X/* System stuff */
  213. X
  214. X#include <stdio.h>
  215. X
  216. Xtypedef char int8;
  217. Xtypedef unsigned char uint8;
  218. Xtypedef short int16;
  219. Xtypedef unsigned short uint16;
  220. Xtypedef long int32;
  221. Xtypedef unsigned long uint32;
  222. X
  223. X#define MAXUINT8        ((uint8) ((int8) (-1)))
  224. X#define MAXUINT16        ((uint16) ((int16) (-1)))
  225. X#define MAXUINT32        ((uint32) ((int32) (-1)))
  226. X
  227. X#if MPW
  228. X#include <QuickDraw.h>    /* need this for random numbers */
  229. X#endif
  230. X#if UNIX
  231. X#define Boolean        int
  232. Xint32 random();
  233. X#define Random()    ((int16) (random()))
  234. X#endif
  235. X
  236. X#if MPW
  237. X#define NEWLINECHAR     '\r'
  238. X#endif
  239. X#if UNIX
  240. X#define NEWLINECHAR     '\n'
  241. X#endif
  242. X
  243. X#define EOFCHAR     (-1)
  244. X
  245. Xchar *malloc();
  246. X
  247. X
  248. X/* Parameters stuff */
  249. X
  250. Xint Argc;
  251. Xchar **Argv;
  252. Xint ExitStatus = 0;
  253. X
  254. Xint16 CurFile;
  255. XBoolean FileArgs = FALSE;
  256. X
  257. XBoolean Big = TRUE, SeparateWords = TRUE;
  258. X
  259. X#define BREAK1        60
  260. X#define BREAK2        75
  261. X
  262. Xint16 Column = 0;
  263. Xuint32 Lines = 0;
  264. X#define DEFAULTMAXLINES        20
  265. Xuint32 MaxLines = DEFAULTMAXLINES;
  266. X
  267. X
  268. X/* Tables */
  269. X
  270. X#define MAXINDEX        27
  271. X#define SPACEINDEX      26
  272. X#define T4SIZE        (MAXINDEX*MAXINDEX*MAXINDEX*MAXINDEX)
  273. X
  274. Xuint16 chartable[256];
  275. X#define indextable(c)   ((c)==(-1) ? NEWLINECHAR : \
  276. X                         (c)==SPACEINDEX ? ' ' : \
  277. X                         ((c)+'a') \
  278. X                        )
  279. X
  280. Xuint32 table0 = 0, *table1 = NULL;
  281. Xuint16 **table2 = NULL, ***table3 = NULL;
  282. Xuint8 *table4 = NULL;
  283. X
  284. X
  285. X/* Memory allocation */
  286. X
  287. Xnomemory()
  288. X{
  289. X    fprintf( stderr, "Cannot get memory!%c", NEWLINECHAR );
  290. X    ExitStatus = 1;
  291. X    exit( ExitStatus );
  292. X}  /* nomemory() */
  293. X
  294. Xgetmemory()
  295. X{
  296. Xuint32 i, j, k;
  297. Xuint16 *t2, **t3, *tt3;
  298. X
  299. X    table1 = (uint32 *) malloc( MAXINDEX * sizeof(uint32) );
  300. X    if (table1==NULL) nomemory();
  301. X    table2 = (uint16 **) malloc( MAXINDEX * sizeof(uint16 *) );
  302. X    if (table2==NULL) nomemory();
  303. X    for (i=0; i<MAXINDEX; i++) {
  304. X        table2[i] = NULL;
  305. X    }
  306. X    table3 = (uint16 ***) malloc( MAXINDEX * sizeof(uint16 **) );
  307. X    if (table3==NULL) nomemory();
  308. X    for (i=0; i<MAXINDEX; i++) {
  309. X        table3[i] = NULL;
  310. X    }
  311. X
  312. X    if (Big) {
  313. X    table4 = (uint8 *) malloc( T4SIZE * sizeof(uint8) );
  314. X    if (table4==NULL) {
  315. X        Big = FALSE;
  316. X        fprintf( stderr, "Cannot get space for 4th-order generation - using 3rd-order instead.%c",
  317. X        NEWLINECHAR );
  318. X    }
  319. X    if (Big) for (i=0; i<T4SIZE; i++) table4[i] = 0;
  320. X    }
  321. X
  322. X    for (i=0; i<MAXINDEX; i++) {
  323. X        table1[i] = 0;
  324. X
  325. X        t2 = (uint16 *) malloc( MAXINDEX * sizeof(uint16) );
  326. X        if (t2==NULL) nomemory();
  327. X        table2[i] = t2;
  328. X
  329. X        t3 = (uint16 **) malloc( MAXINDEX * sizeof(uint16 *) );
  330. X        if (t3==NULL) nomemory();
  331. X        table3[i] = t3;
  332. X        for (j=0; j<MAXINDEX; j++) {
  333. X            t3[j] = NULL;
  334. X        }
  335. X        for (j=0; j<MAXINDEX; j++) {
  336. X            t2[j] = 0;
  337. X            tt3 = (uint16 *) malloc( MAXINDEX * sizeof(uint16) );
  338. X            if (tt3==NULL) nomemory();
  339. X            t3[j] = tt3;
  340. X            for (k=0; k<MAXINDEX; k++) {
  341. X                tt3[k] = 0;
  342. X        }
  343. X        }
  344. X    }
  345. X}  /* getmemory() */
  346. X
  347. Xfreememory()
  348. X{
  349. Xuint16 i, j, k;
  350. Xuint16 *t2, **t3, *tt3;
  351. X
  352. X    if (table1 != NULL) free( table1 );
  353. X    if (table2 != NULL) {
  354. X        for (i=0; i<MAXINDEX; i++) {
  355. X            if (table2[i] != NULL) free( table2[i] );
  356. X        }
  357. X        free( table2 );
  358. X    }
  359. X    if (table3 != NULL) {
  360. X        for (i=0; i<MAXINDEX; i++) {
  361. X            t3 = table3[i];
  362. X            if (t3 != NULL) {
  363. X                for (j=0; j<MAXINDEX; j++) {
  364. X                    if (t3[j] != NULL) free( t3[j] );
  365. X                }
  366. X                free( t3 );
  367. X            }
  368. X        }
  369. X        free( table3 );
  370. X    }
  371. X    if (table4 != NULL) free( table4 );
  372. X    table1 = NULL;
  373. X    table2 = NULL;
  374. X    table3 = NULL;
  375. X    table4 = NULL;
  376. X}  /* freememory() */
  377. X
  378. X
  379. X/* Preliminary setup */
  380. X
  381. Xmaketranstable()
  382. X{
  383. Xuint16 c;
  384. X
  385. X    for (c=0; c<256; c++) chartable[c] = SPACEINDEX;
  386. X    for (c='A'; c<='Z'; c++) chartable[c] = c-'A';
  387. X    for (c='a'; c<='z'; c++) chartable[c] = c-'a';
  388. X}  /* maketranstable() */
  389. X
  390. X
  391. X/* Input */
  392. X
  393. XBoolean openfile()
  394. X{
  395. XFILE *temp;
  396. X
  397. X    temp = freopen( Argv[CurFile], "r", stdin );
  398. X    if (temp == NULL) {
  399. X        fprintf( stderr, "%s: could not open file \"%s\"%c",
  400. X        Argv[0], Argv[CurFile], NEWLINECHAR );
  401. X    ExitStatus = 2;
  402. X    }
  403. X    return( temp != NULL );
  404. X}  /* Boolean openfile() */
  405. X
  406. XBoolean getnextfile()
  407. X{
  408. XFILE *temp;
  409. X
  410. X    while (((++CurFile) < Argc) && (! openfile())) { /* nothing */ }
  411. X    return( CurFile < Argc );
  412. X}  /* Boolean getnextfile() */
  413. X
  414. Xint16 getrawchar()
  415. X{
  416. Xint16 c;
  417. X    c = getchar();
  418. X    while ((c==EOFCHAR) && getnextfile()) {
  419. X        c = getchar();
  420. X    }
  421. X    return(c);
  422. X}  /* int16 getrawchar() */
  423. X
  424. X#define WASSPACE    0
  425. X#define WASNONSPACE 1
  426. X#define END         2
  427. Xint16 Where = WASSPACE;
  428. X
  429. Xint16 nextchar()
  430. X{
  431. Xint16 c, result;
  432. X
  433. X    switch (Where) {
  434. X        case WASSPACE:
  435. X            while (((c = getrawchar()) != EOFCHAR) &&
  436. X                   (chartable[c]==SPACEINDEX)) {
  437. X                /* nothing */
  438. X            }
  439. X            if (c==EOFCHAR) {
  440. X                Where = END;
  441. X                return(-1);
  442. X            } else {
  443. X                Where = WASNONSPACE;
  444. X                return(chartable[c]);
  445. X            }
  446. X        case WASNONSPACE:
  447. X            c = getrawchar();
  448. X            if (c==EOFCHAR) {
  449. X                Where = END;
  450. X                return(SPACEINDEX);
  451. X            } else {
  452. X                result = chartable[c];
  453. X                if (result==SPACEINDEX) Where = WASSPACE;
  454. X                return(result);
  455. X            }
  456. X        case END:
  457. X            return(-1);
  458. X    }
  459. X    return(-1);    /* Never happens. */
  460. X}  /* int16 nextchar() */
  461. X
  462. Xentergroup( a, b, c, d )
  463. Xint16 a, b, c, d;
  464. X{
  465. Xuint32 ind;
  466. XBoolean do_it;
  467. X
  468. X    if (table0 >= MAXUINT32) return;
  469. X    do_it = table1[a] < MAXUINT16;
  470. X    if (Big && do_it) {
  471. X    ind = (((((a*MAXINDEX) + b)*MAXINDEX) + c)*MAXINDEX) + d;
  472. X    do_it = table4[ind] < MAXUINT8;
  473. X    if (do_it) table4[ind]++;
  474. X    }
  475. X    if (do_it) {
  476. X    table0++;
  477. X    table1[a]++;
  478. X    table2[a][b]++;
  479. X    table3[a][b][c]++;
  480. X    }
  481. X}  /* entergroup( a, b, c, d ) */
  482. X
  483. Xbuildtable()
  484. X{
  485. Xint16 a0, b0, c0, a, b, c, d;
  486. X
  487. X    a0 = nextchar();
  488. X    b0 = nextchar();
  489. X    c0 = nextchar();
  490. X    if (c0 == -1) return;
  491. X    a = a0;  b = b0;  c = c0;
  492. X    while ((d = nextchar()) != (-1)) {
  493. X        entergroup( a, b, c, d );
  494. X    a = b;  b = c;  c = d;
  495. X    }
  496. X    if (c==SPACEINDEX) {
  497. X    entergroup( a, b, c, a0 );
  498. X    entergroup( b, c, a0, b0 );
  499. X    entergroup( c, a0, b0, c0 );
  500. X    } else {
  501. X    entergroup( a, b, c, SPACEINDEX );
  502. X    entergroup( b, c, SPACEINDEX, a0 );
  503. X    entergroup( c, SPACEINDEX, a0, b0 );
  504. X    entergroup( SPACEINDEX, a0, b0, c0 );
  505. X    }
  506. X}  /* buildtable() */
  507. X
  508. X
  509. X/* Dump the 0th to 3rd order tables.  Not the 4th-order! */
  510. X/* Only called if SHOWTABLE is defined at compile time. */
  511. X
  512. Xshowtable()
  513. X{
  514. Xuint16 i, j, k;
  515. Xuint16 *t2, **t3, *tt3;
  516. X
  517. X    for (i=0; i<MAXINDEX; i++) if (table1[i] != 0) {
  518. X        printf( "%c\t%lu%c\t\ttot", i+'a', table1[i], NEWLINECHAR );
  519. X        for (k=0; k<MAXINDEX; k++) {
  520. X            printf( "\t%c", k+'a' );
  521. X        }
  522. X        putchar( NEWLINECHAR );
  523. X        t2 = table2[i];
  524. X        t3 = table3[i];
  525. X        for (j=0; j<MAXINDEX; j++) if (t2[j] != 0) {
  526. X            printf( "\t%c\t%u", j+'a', t2[j] );
  527. X            tt3 = t3[j];
  528. X            for (k=0; k<MAXINDEX; k++) {
  529. X                putchar( '\t' );
  530. X                if (tt3[k]==0) putchar( '-' );
  531. X                else printf( "%u", tt3[k] );
  532. X            }
  533. X            putchar( NEWLINECHAR );
  534. X        }
  535. X        putchar( NEWLINECHAR );
  536. X    }
  537. X}  /* showtable() */
  538. X
  539. X
  540. X/* Generation of output */
  541. X
  542. Xint16 randint( max )
  543. Xuint16 max;
  544. X{
  545. X    return( max==0 ? 0 : (int16) (((uint16) Random())%max) );
  546. X}  /* int16 randint( max ) */
  547. X
  548. Xint16 randchoice8( tot, dist )
  549. Xuint32 tot;
  550. Xuint8 *dist;
  551. X{
  552. Xint16 i, j;
  553. X
  554. X    if (tot==0) return(-1);
  555. X    i = randint( tot );
  556. X    for (j=0; j<MAXINDEX; j++) {
  557. X        i -= dist[j];
  558. X        if (i < 0) {
  559. X            return(j);
  560. X    }
  561. X    }
  562. X    return( -1 );    /* Should never happen. */
  563. X}  /* int16 randchoice8( tot, dist ) */
  564. X
  565. Xint16 randchoice16( tot, dist )
  566. Xuint32 tot;
  567. Xuint16 *dist;
  568. X{
  569. Xint16 i, j;
  570. X
  571. X    if (tot==0) return(-1);
  572. X    i = randint( tot );
  573. X    for (j=0; j<MAXINDEX; j++) {
  574. X        i -= dist[j];
  575. X        if (i < 0) {
  576. X            return(j);
  577. X    }
  578. X    }
  579. X    return( -1 );    /* Should never happen. */
  580. X}  /* int16 randchoice16( tot, dist ) */
  581. X
  582. Xint16 randchoice32( tot, dist )
  583. Xuint32 tot;
  584. Xuint32 *dist;
  585. X{
  586. Xint16 i, j;
  587. X
  588. X    if (tot==0) return(-1);
  589. X    i = randint( tot );
  590. X    for (j=0; j<MAXINDEX; j++) {
  591. X        i -= dist[j];
  592. X        if (i<0) return(j);
  593. X    }
  594. X    return( -1 );    /* Should never happen. */
  595. X}  /* int16 randchoice32( tot, dist ) */
  596. X
  597. Xoutchar( c )
  598. Xchar c;
  599. X{
  600. X    if ((c=='.') || (c==' ')) {
  601. X    if (Column > BREAK1) {
  602. X        if (c=='.') putchar('.');
  603. X        putchar( NEWLINECHAR );
  604. X        Column = 0;  Lines++;
  605. X    } else {
  606. X        if (c=='.') { putchar('.');  putchar(' ');  Column += 2; }
  607. X        putchar(' ');  Column++;
  608. X    }
  609. X    } else {
  610. X    if (Column > BREAK2) {
  611. X        putchar('-');  putchar( NEWLINECHAR );  Column = 0;  Lines++;
  612. X    }
  613. X    putchar(c);  Column++;
  614. X    }
  615. X}  /* outchar( c ) */
  616. X
  617. Xgenerateword()
  618. X{
  619. Xint16 a, b, c, d;
  620. X
  621. X    a = SPACEINDEX;
  622. X    b = randchoice16( table1[a], table2[a] );
  623. X    if (b==(-1)) return;
  624. X    outchar( indextable(b) );
  625. X    c = randchoice16( table2[a][b], table3[a][b] );
  626. X    if (c==(-1)) return;
  627. X    outchar( indextable(c) );
  628. X    while (Lines < MaxLines) {
  629. X    if (Big) {
  630. X        d = randchoice8( table3[a][b][c], &(table4[ ((((a*MAXINDEX)+b)*MAXINDEX)+c)*MAXINDEX ]) );
  631. X    } else {
  632. X        d = randchoice16( table2[b][c], table3[b][c] );
  633. X    }
  634. X    if (d==(-1)) {
  635. X        outchar( '.' );
  636. X        d = SPACEINDEX;
  637. X    } else {
  638. X        outchar( indextable(d) );
  639. X    }
  640. X    if (SeparateWords && (d==SPACEINDEX)) return;
  641. X        a = b;  b = c;  c = d;
  642. X    }
  643. X}  /* generateword() */
  644. X
  645. Xgenerate()
  646. X{
  647. X    if (table0 > 0) while (Lines < MaxLines) generateword();
  648. X}  /* generate() */
  649. X
  650. X
  651. X/* Argument parsing */
  652. X
  653. Xusageerror()
  654. X{
  655. X    fprintf( stderr, "Usage: %s [-3] [-s|-w] [-lnnn] [file]%c",
  656. X        Argv[0], NEWLINECHAR );
  657. X    fprintf( stderr, "\t-3: 3rd-order statistics (default is 4th-order)%c",
  658. X        NEWLINECHAR );
  659. X    fprintf( stderr, "\t-w: successive words are independent (default)%c",
  660. X        NEWLINECHAR );
  661. X    fprintf( stderr, "\t-s: (sentences) successive words are dependent%c",
  662. X        NEWLINECHAR );
  663. X    fprintf( stderr, "\t-lnnn: Generate nnn lines of output (default %d).%c",
  664. X        DEFAULTMAXLINES, NEWLINECHAR );
  665. X    ExitStatus = 1;
  666. X    exit( ExitStatus );
  667. X}  /* usageerror() */
  668. X
  669. Xprocessoptions()
  670. X{
  671. Xint i;
  672. X
  673. X    CurFile = Argc;
  674. X    for (i=1; i<Argc; i++) {
  675. X        if (Argv[i][0] == '-') {
  676. X        switch (Argv[i][1]) {
  677. X            case 's':
  678. X            SeparateWords = FALSE;
  679. X            break;
  680. X            case 'w':
  681. X            SeparateWords = TRUE;
  682. X            break;
  683. X        case '3':
  684. X            Big = FALSE;
  685. X            break;
  686. X        case 'l':
  687. X            if (Argv[i][2]==0) {
  688. X            MaxLines = MAXUINT32;
  689. X            } else if ((sscanf( &(Argv[i][2]), "%lu", &MaxLines ) != 1) ||
  690. X            (MaxLines < 0)) {
  691. X                usageerror();  /* exits */
  692. X            }
  693. X            break;
  694. X        default:
  695. X            usageerror();  /* exits */
  696. X        }
  697. X    } else if (Argv[i][0] == 0) {
  698. X        FileArgs = FALSE;
  699. X    } else {
  700. X        FileArgs = TRUE;
  701. X        CurFile = i-1;
  702. X        getnextfile();
  703. X        return;
  704. X    }
  705. X    }
  706. X}  /* processoptions() */
  707. X
  708. X
  709. X/* Control */
  710. X
  711. X#if UNIX
  712. Xcleanup( status, ignore )
  713. Xint status;
  714. Xchar *ignore;
  715. X#endif
  716. X#if MPW
  717. Xvoid cleanup( status )
  718. Xint status;
  719. X#endif
  720. X{
  721. X    freememory();
  722. X}  /* cleanup( status, ignore ) */
  723. X
  724. Xmain( argc, argv )
  725. Xint argc;
  726. Xchar **argv;
  727. X{
  728. X#if MPW
  729. X    InitGraf( &(qd.thePort) );  /* for random numbers */
  730. X    GetDateTime( &(qd.randSeed) );
  731. X#endif
  732. X#if UNIX
  733. X    srandom( time(0) );
  734. X#endif
  735. X
  736. X    Argc = argc;  Argv = argv;
  737. X#if UNIX
  738. X    on_exit( cleanup, NULL );    /* probably not necessary */
  739. X#endif
  740. X#if MPW
  741. X    onexit( cleanup );        /* maybe necessary */
  742. X#endif
  743. X    processoptions();
  744. X    maketranstable();
  745. X    getmemory();
  746. X    buildtable();
  747. X    fprintf( stderr, "%u characters%c", table0, NEWLINECHAR );
  748. X#ifdef SHOWTABLE
  749. X    showtable();
  750. X#endif
  751. X    generate();
  752. X    exit( ExitStatus );
  753. X}  /* main() */
  754. *-*-END-of-names.c-*-*
  755. exit
  756.  
  757.  
  758.