home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume21 / thought / part01 next >
Text File  |  1991-07-21  |  45KB  |  1,467 lines

  1. Newsgroups: comp.sources.misc
  2. From: David F. Skoll <dfs@doe.carleton.ca>
  3. Subject:  v21i023:  thought - A replacement for 'fortune', Part01/02
  4. Message-ID: <csm-v21i023=thought.175143@sparky.imd.sterling.com>
  5. X-Md4-Signature: 00abd78133b2081edf9e6a75437f45f6
  6. Date: Sun, 21 Jul 1991 22:52:49 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: David F. Skoll <dfs@doe.carleton.ca>
  10. Posting-number: Volume 21, Issue 23
  11. Archive-name: thought/part01
  12. Environment: UNIX
  13.  
  14. Thought is a program which randomly generates sayings.  These sayings
  15. can at times be trite, are often funny, and occasionally seem profound.
  16. Thought is configurable and can produce a wide variety of sayings, with a
  17. little work.
  18.  
  19. I have supplied two grammar files - 'thought.rc' gives generally demented
  20. sayings, and 'st.rc' gives demented sayings that sound like something from
  21. Star Trek.
  22.  
  23. Many of the words in thought.rc were obtained from John Lamping's 'shop'
  24. program, posted on alt.sources.  Thanks go out to John Lamping,
  25. lamping@parc.xerox.com.
  26.  
  27. David F. Skoll (dfs@doe.carleton.ca)
  28.  
  29. ------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
  30. #!/bin/sh
  31. # This is Thought 1.0, a shell archive (shar 3.32)
  32. # made 07/17/1991 19:39 UTC by dfs@kmpec
  33. # Source directory /enterprise/transporter/dfs/work/.thought/v1.0
  34. #
  35. # existing files will NOT be overwritten
  36. #
  37. # This shar contains:
  38. # length  mode       name
  39. # ------ ---------- ------------------------------------------
  40. #   2128 -rw------- Makefile
  41. #    814 -rw------- README
  42. #    745 -rw------- examples
  43. #   2645 -rw------- protos.h
  44. #   3634 -rw------- st.rc
  45. #  26519 -rw------- thought.c
  46. #   1895 -rw------- thought.man
  47. #  22131 -rw------- thought.rc
  48. #   7061 -rw------- thoughtfile.man
  49. #   1036 -rw------- version.h
  50. #
  51. if touch 2>&1 | fgrep 'amc' > /dev/null
  52.  then TOUCH=touch
  53.  else TOUCH=true
  54. fi
  55. # ============= Makefile ==============
  56. if test X"$1" != X"-c" -a -f 'Makefile'; then
  57.     echo "File already exists: skipping 'Makefile'"
  58. else
  59. echo "x - extracting Makefile (Text)"
  60. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  61. X###############################################################
  62. X#                                                             #
  63. X#  Makefile for THOUGHT                                       #
  64. X#                                                             #
  65. X#  This file is part of THOUGHT by David F. Skoll.            #
  66. X#                                                             #
  67. X#  You can use THOUGHT in any way you see fit, but you must   #
  68. X#  fully document any changes you make to the software, and   #
  69. X#  must not remove this header from any of the files.         #
  70. X#                                                             #
  71. X#  THOUGHT is free and comes with no warranty.                #
  72. X#                                                             #
  73. X#  THOUGHT is copyright (C) 1991 by David F. Skoll            #
  74. X#                                                             #
  75. X###############################################################
  76. X
  77. X#--------------- BEGINNING OF THINGS YOU CAN CHANGE --------------
  78. X
  79. X#If you have a SYSV system, uncomment next line:
  80. X#CFLAGS= -DSYSV
  81. X
  82. X#If you want to use gcc:
  83. X#CC= gcc
  84. X
  85. X#Where do you want it installed?
  86. XBINDIR= /usr/local/bin
  87. X
  88. X#Where must the default grammar file go?
  89. XLIBDIR= /usr/share/lib
  90. X
  91. X#What should the default grammar file be called?
  92. XGRAMFILE= thought.rc
  93. X
  94. X# What program does the installation?  If you don't have 'install', use
  95. X# 'cp' instead.
  96. XINSTALL= install
  97. X#INSTALL= cp
  98. X
  99. X# Top level mandir
  100. XMANDIR= /usr/man
  101. X
  102. X# What man section for the "thought" man page? (User commands)
  103. XTMANSECT= 1
  104. X
  105. X# Whan man section for the "thoughtfile" man page? (File formats)
  106. XTFMANSECT= 5
  107. X
  108. X#--------------- SHOULDN'T CHANGE STUFF BELOW HERE ---------------
  109. X
  110. Xall: thought.c protos.h version.h
  111. X    $(CC) -DLIBPATH=\"$(LIBDIR)\" -DFILE_DEFAULT=\"$(GRAMFILE)\" -o thought thought.c
  112. X
  113. Xinstall:
  114. X    $(INSTALL) thought $(BINDIR)
  115. X    $(INSTALL) thought $(LIBDIR)/$(GRAMFILE)
  116. X
  117. Xinstall.man:
  118. X    $(INSTALL) thought.man $(MANDIR)/man$(TMANSECT)/thought.$(TMANSECT)
  119. X    $(INSTALL) thoughtfile.man $(MANDIR)/man$(TFMANSECT)/thoughtfile.$(TFMANSECT)
  120. X
  121. Xclean:
  122. X    rm -f *.o core *~
  123. X
  124. Xclobber:
  125. X    rm -f *.o core *~ thought
  126. SHAR_EOF
  127. $TOUCH -am 0704145491 Makefile &&
  128. chmod 0600 Makefile ||
  129. echo "restore of Makefile failed"
  130. set `wc -c Makefile`;Wc_c=$1
  131. if test "$Wc_c" != "2128"; then
  132.     echo original size 2128, current size $Wc_c
  133. fi
  134. fi
  135. # ============= README ==============
  136. if test X"$1" != X"-c" -a -f 'README'; then
  137.     echo "File already exists: skipping 'README'"
  138. else
  139. echo "x - extracting README (Text)"
  140. sed 's/^X//' << 'SHAR_EOF' > README &&
  141. XTHOUGHT - A replacement for fortune.
  142. X
  143. XThought is a program which randomly generates sayings.  These sayings
  144. Xcan at times be trite, are often funny, and occasionally seem profound.
  145. XThought is configurable and can produce a wide variety of sayings, with a
  146. Xlittle work.
  147. X
  148. XINSTALLING THOUGHT
  149. X
  150. X1 - Edit "Makefile" to your liking.  This involves picking installation
  151. X    directories and so on.  The grammar file "thought.rc" goes into the
  152. X    LIBDIR.
  153. X
  154. X2 - Type "make"
  155. X
  156. X3 - Type "make install"
  157. X
  158. X4 - Type "make install.man"
  159. X
  160. XAnd you're on your way!  To create your own grammar files, read the
  161. Xman page for "thoughtfile".
  162. X
  163. XI have supplied two grammar files - 'thought.rc' gives generally demented
  164. Xsayings, and 'st.rc' gives demented sayings that sound like something from
  165. XStar Trek.
  166. X
  167. X--
  168. XDavid F. Skoll (dfs@doe.carleton.ca)
  169. SHAR_EOF
  170. $TOUCH -am 0717153691 README &&
  171. chmod 0600 README ||
  172. echo "restore of README failed"
  173. set `wc -c README`;Wc_c=$1
  174. if test "$Wc_c" != "814"; then
  175.     echo original size 814, current size $Wc_c
  176. fi
  177. fi
  178. # ============= examples ==============
  179. if test X"$1" != X"-c" -a -f 'examples'; then
  180.     echo "File already exists: skipping 'examples'"
  181. else
  182. echo "x - extracting examples (Text)"
  183. sed 's/^X//' << 'SHAR_EOF' > examples &&
  184. XI'm not interested in his sickening door.  Give me a disgusting yam that
  185. Xshivers angrily any day.
  186. X
  187. XBertrand!  I told you not to anger Betty's gas tank!  Now you must berate her
  188. Xto make up for your cool behaviour.
  189. X
  190. XMy favorite eggplants are Arthur the Dismembered and Brenda the Weird.
  191. X
  192. XBats, unicorns, vampires, lend me your workstations.  I come to stab Trevor,
  193. Xnot to maim him.
  194. X
  195. XKelly is as disgusting as an icon.
  196. X
  197. XTo shiver is disgusting; to exhale, stinking.
  198. X
  199. XI'm not interested in your cool snout.  Give me a reliable dervish that kisses
  200. Xvoraciously any day.
  201. X
  202. XArnold!  I told you not to split Sylvie's window manager!  Now you must hug
  203. Xher to make up for your stinking behaviour.
  204. X
  205. XThose dismembered, leprous, weird strawberries of summer!
  206. X
  207. SHAR_EOF
  208. $TOUCH -am 0704150991 examples &&
  209. chmod 0600 examples ||
  210. echo "restore of examples failed"
  211. set `wc -c examples`;Wc_c=$1
  212. if test "$Wc_c" != "745"; then
  213.     echo original size 745, current size $Wc_c
  214. fi
  215. fi
  216. # ============= protos.h ==============
  217. if test X"$1" != X"-c" -a -f 'protos.h'; then
  218.     echo "File already exists: skipping 'protos.h'"
  219. else
  220. echo "x - extracting protos.h (Text)"
  221. sed 's/^X//' << 'SHAR_EOF' > protos.h &&
  222. X/***************************************************************/
  223. X/*                                                             */
  224. X/*  PROTOS.H                                                   */
  225. X/*                                                             */
  226. X/*  Function prototypes and certain default definitions.       */
  227. X/*                                                             */
  228. X/*  This file is part of THOUGHT by David F. Skoll.            */
  229. X/*                                                             */
  230. X/*  You can use THOUGHT in any way you see fit, but you must   */
  231. X/*  fully document any changes you make to the software, and   */
  232. X/*  must not remove this header from any of the files.         */
  233. X/*                                                             */
  234. X/*  THOUGHT is free and comes with no warranty.                */
  235. X/*                                                             */
  236. X/*  THOUGHT is copyright (C) 1991 by David F. Skoll            */
  237. X/*                                                             */
  238. X/***************************************************************/
  239. X
  240. X/* Define the structure of a word */
  241. Xtypedef struct word
  242. X{
  243. X  struct word *next;
  244. X  char *def;
  245. X} Word;
  246. X
  247. X/* Define the structure of a tag */
  248. Xtypedef struct tag
  249. X{
  250. X  struct tag *next;
  251. X  char *def;
  252. X  Word *wordlist;
  253. X  int numwords;  /* Number of words with this tag definition */
  254. X} Tag;
  255. X
  256. X/* Define the structure of a sentence */
  257. X
  258. Xtypedef struct sentence
  259. X{
  260. X  struct sentence *next;
  261. X  char *def;
  262. X} Sentence;
  263. X
  264. X/* ARGH!  Our stupid header files don't give prototype for getenv! */
  265. X#ifdef __STDC__
  266. Xchar * getenv(char *);
  267. X#else
  268. Xchar * getenv();
  269. X#endif
  270. X
  271. X#ifdef __STDC__
  272. XTag *  FindTag(char *tagname);
  273. Xchar * FindModifier(char *mod, char *srch);
  274. Xchar * NextWord(char **s);
  275. Xchar * ReadToken(const char *sep, FILE *fp, char **istream);
  276. Xchar * ResolveFilename(char *f);
  277. Xint    DefSent(FILE *fp);
  278. Xint    DefTag(FILE *fp);
  279. Xint    DefWord(Tag *tag, FILE *fp);
  280. Xint    ReadChar(FILE *fp, char **s);
  281. Xint    UnReadChar(FILE *fp, char **s, char ch);
  282. Xint    main(int argc, char **argv);
  283. Xvoid   Usage(void);
  284. Xvoid   Banner(void);
  285. Xvoid   Format(char *s, int width);
  286. Xvoid   GenerateThought(Sentence *sen);
  287. Xvoid   ReadFile (char *fname);
  288. Xvoid   WriteWord(Tag *tag, Word *w, char *mod, char **out, char upper);
  289. X#else
  290. XTag *  FindTag();
  291. Xchar * FindModifier();
  292. Xchar * NextWord();
  293. Xchar * ReadToken();
  294. Xchar * ResolveFilename();
  295. Xint    DefSent();
  296. Xint    DefTag();
  297. Xint    DefWord();
  298. Xint    ReadChar();
  299. Xint    UnReadChar();
  300. Xint    main();
  301. Xvoid   Usage();
  302. Xvoid   Banner();
  303. Xvoid   Format();
  304. Xvoid   GenerateThought();
  305. Xvoid   ReadFile ();
  306. Xvoid   WriteWord();
  307. X#endif
  308. SHAR_EOF
  309. $TOUCH -am 0704111591 protos.h &&
  310. chmod 0600 protos.h ||
  311. echo "restore of protos.h failed"
  312. set `wc -c protos.h`;Wc_c=$1
  313. if test "$Wc_c" != "2645"; then
  314.     echo original size 2645, current size $Wc_c
  315. fi
  316. fi
  317. # ============= st.rc ==============
  318. if test X"$1" != X"-c" -a -f 'st.rc'; then
  319.     echo "File already exists: skipping 'st.rc'"
  320. else
  321. echo "x - extracting st.rc (Text)"
  322. sed 's/^X//' << 'SHAR_EOF' > st.rc &&
  323. X# A star-trek like grammar file
  324. X
  325. X#--------------------------------------------------------------------------#
  326. X
  327. X# First, let's declare the parts of speech we want to use.
  328. X
  329. X{deftag art}        # Articles - "the", "a", and so on
  330. X{deftag adj}        # Adjectives
  331. X{deftag adv}        # Adverbs
  332. X{deftag vi;3s=!s}    # Intransitive verbs with mod for 3rd person singular
  333. X{deftag vt;3s=!s}    # Transitive verbs with mod for 3rd person singular
  334. X{deftag n;p=!s}        # Nouns with mod for plural
  335. X{deftag mname}        # Male's name
  336. X{deftag fname}        # Female's name
  337. X{deftag name}        # Name (either gender)
  338. X{deftag abn}        # "Abstract" nouns.
  339. X
  340. X
  341. X#--------------------------------------------------------------------------#
  342. X
  343. X# Now let's define a bunch of sentences
  344. X
  345. X{defsent These are the {n;p} of the {n} "Enterprise."  Her 5-year mission --
  346. Xto {adv} go where no {n} has gone before.}
  347. X
  348. X{defsent
  349. X{Abn}, sir, should be {adj} to all.
  350. X}
  351. X
  352. X{defsent
  353. XNo {n} is {adj}.
  354. X}
  355. X
  356. X{defsent
  357. XSuperior {abn} breeds superior {abn}.
  358. X}
  359. X
  360. X{defsent
  361. XIt's hard to believe that something which is neither {adj} nor {adj}
  362. Xcan be so {adj}.  And that's what kept the {n;p} in the {n;p} all
  363. Xthese centuries.
  364. X}
  365. X
  366. X{defsent Red alert, Mr. {mname}.  And {vt} the {n;p}.}
  367. X
  368. X{defsent Without {n;p}, {abn} cannot {vi}.}
  369. X
  370. X{defsent {N;p} don't talk {abn} unless they are ready to back it up with
  371. X{abn}.}
  372. X
  373. X{defsent {Abn} tends to {vi}.}
  374. X
  375. X{defsent Even {n;p} fail to learn from {abn}; they repeat the same {n;p}.}
  376. X
  377. X{defsent {Abn} is {adj}, like a {n} with {n;p}, {n;p} and {abn}.}
  378. X
  379. X{defsent {Abn} is the essential process of all {abn}.}
  380. X
  381. X{defsent {Abn} is {adj}, {adj}!}
  382. X
  383. X{defsent {Abn} has no purpose.  Or {abn}.  But it may have a {n}.}
  384. X
  385. X{defsent {Abn} becomes {adj} after a point. {N;p} become {adj}.}
  386. X
  387. X{defsent {Adj}.  It's not {abn} as we know it, Jim.}
  388. X
  389. X{defsent Set your {n;p} on stun!  I don't want any {abn}.}
  390. X
  391. X{defsent We come on a mission of {abn}.}
  392. X
  393. X{defsent I believe that is not {fname}.  She swapped {n;p}
  394. Xwith {mname} when we went through the {n}.}
  395. X
  396. X{defsent There are {n;p} on the {adj} {n}!}
  397. X
  398. X{defsent {Adv}!  There's no {abn} to {vt}!}
  399. X
  400. X#--------------------------------------------------------------------------#
  401. X
  402. X# Now supply some words!
  403. X
  404. X{n
  405. X mind, life form, star, galaxy;p=galaxies, man;p=men, race, crisis;p=crises,
  406. X cage, child;p=!ren, computer, crewman;p=crewmen, follower, river, current,
  407. X myth, saint, savage, woman;p=women, computer, scientist, Vulcan, Klingon,
  408. X Romulan, shield, sensor, photon torpedo;p=!es, phaser, shuttle,
  409. X Tribble, channel, screen, bridge, cabin, brig, force field, tractor beam,
  410. X trilithium crystal, warp drive, impulse engine
  411. X}
  412. X
  413. X{abn
  414. X simplicity, complexity, ability, ambition, power, danger, peace, freedom,
  415. X prejudice, creativity, suffering, purpose, reason, emotion, violence,
  416. X evil, time, killing, sentience, slavery, imprisonment, despair,
  417. X exaltation, impatience, anger, hatred, love, bravado, machismo,
  418. X disgust
  419. X}
  420. X
  421. X{adj
  422. X insoluble, superior, ultimate, hard, independent, free, self-made, stupid,
  423. X useless, wrong, ineffective, insensitive, fluid, disloyal, alien, interesting,
  424. X fascinating, logical, illogical, unacceptable, sentient
  425. X}
  426. X
  427. X{vi
  428. X spread, destroy, live, happen, kill, lead, exaggerate, worship, repeat,
  429. X exaggerate, fail, learn, repeat, know, eliminate, generate, communicate
  430. X}
  431. X
  432. X{vt
  433. X worship, kill, stun, disregard, control, arm, fire, lock, secure,
  434. X seal, beam down;s=beams down, waste, fill, destroy, stun, attack
  435. X}
  436. X
  437. X{mname
  438. X Kirk, Spock, McCoy, Worf, Picard, LaForge, Data, Scotty, Chekov
  439. X}
  440. X
  441. X{fname
  442. X Uhura, Troi, Yar, Crusher
  443. X}
  444. X
  445. X{adv
  446. X merely, forcibly, suddenly, logically, simply, philosophically,
  447. X easily, mysteriously, boldly, carefully, directly, eagerly
  448. X}
  449. SHAR_EOF
  450. $TOUCH -am 0717153491 st.rc &&
  451. chmod 0600 st.rc ||
  452. echo "restore of st.rc failed"
  453. set `wc -c st.rc`;Wc_c=$1
  454. if test "$Wc_c" != "3634"; then
  455.     echo original size 3634, current size $Wc_c
  456. fi
  457. fi
  458. # ============= thought.c ==============
  459. if test X"$1" != X"-c" -a -f 'thought.c'; then
  460.     echo "File already exists: skipping 'thought.c'"
  461. else
  462. echo "x - extracting thought.c (Text)"
  463. sed 's/^X//' << 'SHAR_EOF' > thought.c &&
  464. X/***************************************************************/
  465. X/*                                                             */
  466. X/*  THOUGHT.C                                                  */
  467. X/*                                                             */
  468. X/*  This file is part of THOUGHT by David F. Skoll.            */
  469. X/*                                                             */
  470. X/*  You can use THOUGHT in any way you see fit, but you must   */
  471. X/*  fully document any changes you make to the software, and   */
  472. X/*  must not remove this header from any of the files.         */
  473. X/*                                                             */
  474. X/*  THOUGHT is free and comes with no warranty.                */
  475. X/*                                                             */
  476. X/*  THOUGHT is copyright (C) 1991 by David F. Skoll            */
  477. X/*                                                             */
  478. X/***************************************************************/
  479. X
  480. X#include <stdio.h>
  481. X#include <string.h>
  482. X#include <ctype.h>
  483. X#include <string.h>
  484. X
  485. X#ifdef MSDOS
  486. X#include <stdlib.h>
  487. X#include <dos.h>
  488. X#include <io.h>
  489. X#include <malloc.h>
  490. X#else
  491. X#include <sys/file.h>
  492. X#include <sys/types.h>
  493. X#ifdef SYSV
  494. X#include <time.h>
  495. X#else
  496. X#include <sys/time.h>
  497. X#endif
  498. X#endif
  499. X
  500. X#include "protos.h"
  501. X#include "version.h"
  502. X
  503. X/* The next two defines are to stop my editor's bracket-matching algorithm
  504. X   from complaining later on in the program. */
  505. X
  506. X#define CLEFT '{'
  507. X#define CRIGHT '}'
  508. X
  509. X#define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - ('a' - 'A') : (c) )
  510. X
  511. Xchar *SEP1="{}=;,";
  512. Xchar *SEP2="{}=;, \n\t";
  513. X
  514. X/* The global data structures - a singly-linked list of tags
  515. X   and a singly-linked list of sentence definitions. */
  516. X
  517. XTag *TagList = NULL;
  518. Xint NumTags = 0;
  519. X
  520. XSentence *SentenceList = NULL;
  521. Xint NumSentences = 0;
  522. X
  523. Xchar Buffer[1024];  /* Temp buffer - big for sentence definitions */
  524. Xchar Mod[32];       /* Temp buffer to hold current modifier */
  525. Xchar Token[200];    /* Another temp. buffer for various stuff */
  526. Xchar FileName[256]; /* Resolved filename */
  527. X/***************************************************************/
  528. X/*                                                             */
  529. X/*  ReadChar                                                   */
  530. X/*                                                             */
  531. X/*  Read a character from a file if fp is not null; otherwise, */
  532. X/*  read from a string.                                        */
  533. X/*                                                             */
  534. X/***************************************************************/
  535. X#ifdef __STDC__
  536. Xint ReadChar(FILE *fp, char **s)
  537. X#else
  538. Xint ReadChar(fp, s)
  539. XFILE *fp;
  540. Xchar **s;
  541. X#endif
  542. X{
  543. X   if (fp) return getc(fp);
  544. X   if (!(**s)) return EOF;
  545. X   else return * (*s)++;
  546. X}
  547. X
  548. X/***************************************************************/
  549. X/*                                                             */
  550. X/*  UnReadChar                                                 */
  551. X/*                                                             */
  552. X/*  Put a character back.                                      */
  553. X/*                                                             */
  554. X/***************************************************************/
  555. X#ifdef __STDC__
  556. Xint UnReadChar(FILE *fp, char **s, char ch)
  557. X#else
  558. Xint UnReadChar(fp, s, ch)
  559. XFILE *fp;
  560. Xchar **s;
  561. Xchar ch;
  562. X#endif
  563. X{
  564. X   if (fp) return ungetc(ch, fp);
  565. X   if (!**s) return EOF;
  566. X   else *(--(*s)) = ch;
  567. X   return ch;
  568. X}
  569. X
  570. X/***************************************************************/
  571. X/*                                                             */
  572. X/*  ReadToken                                                  */
  573. X/*                                                             */
  574. X/*  Read a token from the specified input stream, with leading */
  575. X/*  and trailing whitespace stripped.  Tokens are separated by */
  576. X/*  any of the characters in 'sep'.  Tokens are stored in a    */
  577. X/*  static area and are overwritten with each call to          */
  578. X/*  ReadToken.  Returns the Null string (NOT NULL) if EOF      */
  579. X/*                                                             */
  580. X/*  If fp is not NULL, reads from file.  Otherwise, reads from */
  581. X/*  a string, adjusting the string pointer.                    */
  582. X/*                                                             */
  583. X/***************************************************************/
  584. X#ifdef __STDC__
  585. Xchar *ReadToken(const char *sep, FILE *fp, char **istream)
  586. X#else
  587. Xchar *ReadToken(sep, fp, istream)
  588. Xchar *sep;
  589. XFILE *fp;
  590. Xchar **istream;
  591. X#endif
  592. X{
  593. X   int ch;
  594. X   char read = 0;
  595. X   char *s;
  596. X   while(1) {  /* Skip comments and leading space */
  597. X      do {
  598. X         ch = ReadChar(fp, istream);
  599. X         } while (isspace (ch));
  600. X
  601. X      if (ch == '#') {
  602. X         do {ch = ReadChar(fp, istream);} while (ch != '\n' && ch != EOF);
  603. X      } else break;
  604. X   }
  605. X
  606. X   s = Token;
  607. X
  608. X   while (1) {
  609. X      if (ch == EOF) {
  610. X         if (read) break;
  611. X     else {
  612. X        *Token = 0;
  613. X        return Token;
  614. X     }
  615. X      }
  616. X      if (ch == '#') {
  617. X         UnReadChar(fp, istream, ch);
  618. X     break;
  619. X      }
  620. X      if (strchr(sep, ch)) {
  621. X         if (read) {
  622. X        UnReadChar(fp, istream, ch);
  623. X        break;
  624. X     } else {
  625. X        *Token = ch;
  626. X        *(Token + 1) = 0;
  627. X        return Token;
  628. X     }
  629. X      }
  630. X      if (ch == '\n') ch = ' ';
  631. X      *s++ = ch;
  632. X      *s = 0;
  633. X      ch = ReadChar(fp, istream);
  634. X      read = 1;
  635. X   }
  636. X
  637. X/* Strip trailing whitespace */
  638. X   s = Token + strlen(Token) - 1;
  639. X   while (s >= Token && isspace(*s)) *s-- = 0;
  640. X
  641. X   return Token;
  642. X}
  643. X
  644. X/***************************************************************/
  645. X/*                                                             */
  646. X/*  DefTag                                                     */
  647. X/*                                                             */
  648. X/*  Add a tag definition                                       */
  649. X/*                                                             */
  650. X/***************************************************************/
  651. X#ifdef __STDC__
  652. Xint DefTag(FILE *fp)
  653. X#else
  654. Xint DefTag(fp)
  655. XFILE *fp;
  656. X#endif
  657. X{
  658. X   Tag *new;
  659. X   char *s;
  660. X
  661. X/* Read the tag's name */
  662. X   s = ReadToken(SEP1, fp, NULL);
  663. X   strcpy(Buffer, s);
  664. X   if (strchr (SEP1, *s)) {
  665. X      fprintf(stderr, "Illegal tag definition: %s\n", Buffer);
  666. X      exit(1);
  667. X   }
  668. X   
  669. X/* Copy the tag name to temp. buffer */
  670. X   strcpy(Buffer, s);
  671. X/* Parse for definitions */
  672. X   while (1) {
  673. X      s = ReadToken(SEP1, fp, NULL);
  674. X      if (*s != ';' && *s != CRIGHT) {
  675. X         fprintf(stderr, "Unknown token %s in tag definition %s.\n", s, Buffer);
  676. X     exit (1);
  677. X      }
  678. X      if (*s == CRIGHT) {
  679. X         if (FindTag(Buffer)) {
  680. X        fprintf(stderr, "Ignoring duplicate definition of tag %s\n", Buffer);
  681. X           return 1;
  682. X     }
  683. X
  684. X      /* add it onto the list */
  685. X         new = (Tag *) malloc(sizeof(Tag));
  686. X         if (!new) {
  687. X            fprintf(stderr, "Memory allocation problem for tag %s.\n", s);
  688. X            exit(1);
  689. X         }
  690. X         new->next = TagList;
  691. X         new->wordlist = (Word *) NULL;
  692. X         new->numwords = 0;
  693. X         TagList = new;
  694. X         NumTags++;
  695. X     new->def = strdup(Buffer);
  696. X     if (! new->def) {
  697. X            fprintf(stderr, "Memory allocation problem for tag %s.\n", Buffer);
  698. X            exit(1);
  699. X         }
  700. X     return 0;
  701. X      }
  702. X   
  703. X
  704. X/* Must be ';' */
  705. X      strcat(Buffer, s);
  706. X
  707. X/* Get the modifier */
  708. X      s = ReadToken(SEP1, fp, NULL);
  709. X      strcat(Buffer, s);
  710. X      if (strchr (SEP1, *s)) {
  711. X         fprintf(stderr, "Illegal tag definition: %s\n", Buffer);
  712. X     exit(1);
  713. X      }
  714. X
  715. X/* Get the equals sign */
  716. X      s = ReadToken(SEP1, fp, NULL);
  717. X      strcat(Buffer, s);
  718. X      if (*s != '=') {
  719. X         fprintf(stderr, "Illegal tag definition: %s\n", Buffer);
  720. X     exit(1);
  721. X      }
  722. X
  723. X/* Get the definition */
  724. X      s = ReadToken(SEP1, fp, NULL);
  725. X      strcat(Buffer, s);
  726. X      if (strchr (SEP1, *s)) {
  727. X         fprintf(stderr, "Illegal tag definition: %s\n", Buffer);
  728. X     exit(1);
  729. X      }
  730. X   }
  731. X}
  732. X
  733. X/***************************************************************/
  734. X/*                                                             */
  735. X/*  FindTag - given a tag, find its definition.                */
  736. X/*  Return NULL if not found, else pointer to definition.      */
  737. X/*                                                             */
  738. X/***************************************************************/
  739. X#ifdef __STDC__
  740. XTag *FindTag(char *tagname)
  741. X#else
  742. XTag *FindTag(tagname)
  743. Xchar *tagname;
  744. X#endif
  745. X{
  746. X   char *s, *t;
  747. X   Tag *found = TagList;
  748. X
  749. X   while (found) {
  750. X      s = tagname;
  751. X      t = found->def;
  752. X      while (*s && *t && *s != ';' && *t != ';' && UPPER(*s) == UPPER(*t)) {
  753. X         s++;
  754. X     t++;
  755. X      }      
  756. X      if ((!*s && !*t) || (!*s && *t == ';') 
  757. X          || (*s == ';' && !*t) || (*s == ';' && *t == ';'))
  758. X           return found;
  759. X      found = found->next;
  760. X   }
  761. X   return found;
  762. X}
  763. X
  764. X/***************************************************************/
  765. X/*                                                             */
  766. X/*  DefWord                                                    */
  767. X/*                                                             */
  768. X/*  Define a list of words.  We enter with the tag found, and  */
  769. X/*  keep adding words to the tag's word list until we hit a    */
  770. X/*  closing brace.                                             */
  771. X/*                                                             */
  772. X/***************************************************************/
  773. X#ifdef __STDC__
  774. Xint DefWord(Tag *tag, FILE *fp)
  775. X#else
  776. Xint DefWord(tag, fp)
  777. XTag *tag;
  778. XFILE *fp;
  779. X#endif
  780. X{
  781. X   char *s;
  782. X   Word *new;
  783. X
  784. X   s = ReadToken(SEP1, fp, NULL);
  785. X
  786. X   while(1) {
  787. X      if (strchr(SEP1, *s)) {
  788. X         fprintf(stderr, "Illegal word definition: %s\n", s);
  789. X     exit(1);
  790. X      }
  791. X      strcpy(Buffer, s);
  792. X      s = ReadToken(SEP1, fp, NULL);
  793. X      while (*s == ';') {   /* Collect modifiers */
  794. X         strcat(Buffer, s);
  795. X         s = ReadToken(SEP1, fp, NULL);  /* Modifier name */
  796. X         strcat(Buffer, s);
  797. X         if (strchr(SEP1, *s)) {
  798. X            fprintf(stderr, "Illegal word definition: %s\n", s);
  799. X            exit(1);
  800. X         }
  801. X     s = ReadToken(SEP1, fp, NULL); /* equals sign */
  802. X     strcat(Buffer, s);
  803. X     if (*s != '=') {
  804. X            fprintf(stderr, "Illegal word definition: %s\n", s);
  805. X            exit(1);
  806. X         }
  807. X     s = ReadToken(SEP1, fp, NULL); /* Definition */
  808. X     strcat(Buffer, s);
  809. X         if (strchr(SEP1, *s)) {
  810. X            fprintf(stderr, "Illegal word definition: %s\n", s);
  811. X            exit(1);
  812. X         }
  813. X         s = ReadToken(SEP1, fp, NULL);
  814. X      }
  815. X      if (*s != ',' && *s != CRIGHT) {
  816. X         fprintf(stderr, "Illegal word definition: %s%s\n", Buffer, s);
  817. X     exit(1);
  818. X      }
  819. X      new = (Word *) malloc (sizeof(Word));
  820. X      if (!new) {
  821. X         fprintf(stderr, "Memory allocation error for word: %s\n", Buffer);
  822. X     exit(1);
  823. X      }
  824. X      new->def = strdup(Buffer);
  825. X      if (!new->def) {
  826. X         fprintf(stderr, "Memory allocation error for word: %s\n", Buffer);
  827. X     exit(1);
  828. X      }
  829. X      new->next = tag->wordlist;
  830. X      tag->wordlist = new;
  831. X      tag->numwords++;
  832. X      if (*s == CRIGHT) return 0;
  833. X      s = ReadToken(SEP1, fp, NULL);
  834. X   }
  835. X}
  836. X
  837. X/***************************************************************/
  838. X/*                                                             */
  839. X/*  DefSent                                                    */
  840. X/*                                                             */
  841. X/*  Add a sentence definition to the list.  We just slurp all  */
  842. X/*  the characters until a closing brace.                      */
  843. X/*                                                             */
  844. X/***************************************************************/
  845. X#ifdef __STDC__
  846. Xint DefSent(FILE *fp)
  847. X#else
  848. Xint DefSent(fp)
  849. XFILE *fp;
  850. X#endif
  851. X{
  852. X   Sentence *new;
  853. X   char ch;
  854. X   char *s;
  855. X   int nleft;
  856. X
  857. X   s = Buffer;
  858. X   *s = 0;
  859. X   nleft = 0;
  860. X
  861. X   do {
  862. X      ch = ReadChar(fp, NULL);
  863. X   } while (isspace(ch));
  864. X
  865. X   while (1) {
  866. X      if (ch == EOF) {
  867. X         fprintf(stderr, "Unexpected end of file!\n");
  868. X     exit(1);
  869. X      }
  870. X      if (ch == CRIGHT && !nleft) {
  871. X         s = Buffer + strlen(Buffer)-1;
  872. X     while (s >= Buffer && isspace(*s)) *s-- = 0;
  873. X         new = (Sentence *) malloc (sizeof (Sentence));
  874. X     if (!new) {
  875. X        fprintf(stderr, "Memory allocation failure during defsent!\n");
  876. X        exit(1);
  877. X     }
  878. X     new->def = strdup(Buffer);
  879. X     if (!new->def) {
  880. X        fprintf(stderr, "Memory allocation failure during defsent!\n");
  881. X        exit(1);
  882. X     }
  883. X     NumSentences++;
  884. X     new->next = SentenceList;
  885. X     SentenceList = new;
  886. X     return 0;
  887. X      }
  888. X      if (ch == '\n') ch = ' ';
  889. X      *s++ = ch;
  890. X      *s = 0;
  891. X      if (ch == CLEFT) nleft++;
  892. X      else if (ch == CRIGHT) nleft--;
  893. X      ch = ReadChar(fp, NULL);
  894. X   }
  895. X}
  896. X      
  897. X/***************************************************************/
  898. X/*                                                             */
  899. X/*  ReadFile                                                   */
  900. X/*                                                             */
  901. X/*  Read and process the grammar file, setting up all internal */
  902. X/*  data structures.                                           */
  903. X/*                                                             */
  904. X/***************************************************************/
  905. X#ifdef __STDC__
  906. Xvoid ReadFile (char *fname)
  907. X#else
  908. Xvoid ReadFile (fname)
  909. Xchar *fname;
  910. X#endif
  911. X{
  912. X   FILE *fp;
  913. X   char *s;
  914. X   Tag *t;
  915. X
  916. X   fp = fopen(fname, "r");
  917. X   if (fp == NULL) {
  918. X      perror(fname);
  919. X      exit(1);
  920. X   }
  921. X
  922. X   while(1) {
  923. X      s = ReadToken(SEP2, fp, NULL);
  924. X      if (!*s) {
  925. X         fclose(fp);
  926. X     return;
  927. X      }
  928. X      if (*s != CLEFT) {
  929. X         fprintf(stderr, "Expecting %c, found %s\n", CLEFT, s);
  930. X     fclose(fp);
  931. X     exit(1);
  932. X      }
  933. X      s = ReadToken(SEP2, fp, NULL);
  934. X      if (! stricmp(s, "deftag")) DefTag(fp);
  935. X      else if (! stricmp(s, "defsent")) DefSent(fp);
  936. X      else {
  937. X         t = FindTag(s);
  938. X     if (!t) {
  939. X        fprintf(stderr, "Unknown tag: %s\n", s);
  940. X        fclose(fp);
  941. X        exit(1);
  942. X     }
  943. X     DefWord(t, fp);
  944. X      }
  945. X   }
  946. X}
  947. X
  948. X/***************************************************************/
  949. X/*                                                             */
  950. X/*  GenerateThought                                            */
  951. X/*                                                             */
  952. X/*  This is where it all happens!  Generate a thought for the  */
  953. X/*  day and leave it in 'Buffer'                               */
  954. X/*                                                             */
  955. X/***************************************************************/
  956. X#ifdef __STDC__
  957. Xvoid GenerateThought(Sentence *sen)
  958. X#else
  959. Xvoid GenerateThought(sen)
  960. XSentence *sen;
  961. X#endif
  962. X{
  963. X   char *sd = sen->def;
  964. X   char *out, *tok;
  965. X   char *mod;
  966. X   char ch;
  967. X   Tag *tag;
  968. X   Word *w;
  969. X   int i;
  970. X   char upper;
  971. X
  972. X   out = Buffer;
  973. X   *out = 0;
  974. X
  975. X   while(*sd) {
  976. X      ch = *sd++;
  977. X      if (ch != CLEFT) {
  978. X         *out++ = ch;
  979. X     *out = 0;
  980. X     continue;
  981. X      }
  982. X      tok = ReadToken(SEP1, NULL, &sd);
  983. X      if (*tok >= 'A' && *tok <='Z') upper = 1; else upper = 0;
  984. X      tag = FindTag(tok);
  985. X      if (!tag) {
  986. X         fprintf(stderr, "Unknown tag %s in sentence definition\n%s\n", tok, sen->def);
  987. X     exit(1);
  988. X      }
  989. X      tok = ReadToken(SEP1, NULL, &sd);
  990. X      if (*tok != ';' && *tok != CRIGHT) {
  991. X         fprintf(stderr, "Illegal tag definition in %s\n", sen->def);
  992. X     exit(1);
  993. X      }
  994. X      if (*tok == ';') {
  995. X         tok = ReadToken(SEP1, NULL, &sd);
  996. X     strcpy(Mod, tok);
  997. X     mod = Mod;
  998. X     tok = ReadToken(SEP1, NULL, &sd);
  999. X         if (*tok != CRIGHT) {
  1000. X            fprintf(stderr, "Illegal tag definition in %s\n", sen->def);
  1001. X        exit(1);
  1002. X         }
  1003. X      } else mod = (char *) NULL;
  1004. X
  1005. X/* We've got the tag and the modifier - now pick a random word */
  1006. X      if (!tag->numwords) {
  1007. X         fprintf(stderr, "Tag %s has no words defined.\n", tag->def);
  1008. X     exit(1);
  1009. X      }
  1010. X      i = rand() % tag->numwords;
  1011. X
  1012. X/* Find the actual word - this is HIGHLY INEFFICIENT!! */
  1013. X      w = tag->wordlist;
  1014. X      while (i && w) {
  1015. X         w = w->next;
  1016. X     i--;
  1017. X      }
  1018. X
  1019. X      if (!w) {
  1020. X         fprintf(stderr, "Internal error!  numwords for tag %s is too high!!!\n", tag->def);
  1021. X     exit(1);
  1022. X      }
  1023. X
  1024. X/* We've got a word - emit it */
  1025. X      WriteWord(tag, w, mod, &out, upper);
  1026. X   }
  1027. X}
  1028. X/***************************************************************/
  1029. X/*                                                             */
  1030. X/*  WriteWord - Write a word, applying any modifiers.          */
  1031. X/*                                                             */
  1032. X/***************************************************************/
  1033. X#ifdef __STDC__
  1034. Xvoid WriteWord(Tag *tag, Word *w, char *mod, char **out, char upper)
  1035. X#else
  1036. Xvoid WriteWord(tag, w, mod, out, upper)
  1037. XTag *tag;
  1038. XWord *w;
  1039. Xchar *mod;
  1040. Xchar **out;
  1041. Xchar upper;
  1042. X#endif
  1043. X{
  1044. X   char *s;
  1045. X            char *OrigOut = *out;
  1046. X   char *ModDef;
  1047. X
  1048. X   if (!mod) {  /* easy case first - no modifiers */
  1049. X      s = w->def;
  1050. X      while (*s && *s != ';') {
  1051. X         *(*out)++ = *s++;
  1052. X      }
  1053. X      **out = 0;
  1054. X      if (upper) *OrigOut = UPPER(*OrigOut);
  1055. X      return;
  1056. X   }
  1057. X
  1058. X/* Grrr - Search for a modifier.  Search word description first; then search
  1059. X   tag description. */
  1060. X   ModDef = FindModifier(mod, w->def);
  1061. X   if (!ModDef) ModDef = FindModifier(mod, tag->def);
  1062. X   if (!ModDef) {
  1063. X      fprintf(stderr, "Could not find modifier %s for word %s\n", mod, w->def);
  1064. X      exit(1);
  1065. X   }
  1066. X
  1067. X/* Write out the modified word */
  1068. X   while (*ModDef && *ModDef != ';') {
  1069. X      if (*ModDef != '!') {
  1070. X         *(*out)++ = *ModDef++;
  1071. X     **out = 0;
  1072. X      } else {
  1073. X         ModDef++;
  1074. X         s = w->def;
  1075. X     while (*s && *s != ';') *(*out)++ = *s++;
  1076. X     **out = 0;
  1077. X      }
  1078. X   }
  1079. X   if (upper) *OrigOut = UPPER(*OrigOut);
  1080. X}
  1081. X
  1082. X/***************************************************************/
  1083. X/*                                                             */
  1084. X/*  FindModifier - find a modifier definition.                 */
  1085. X/*                                                             */
  1086. X/***************************************************************/
  1087. X#ifdef __STDC__
  1088. Xchar *FindModifier(char *mod, char *srch)
  1089. X#else
  1090. Xchar *FindModifier(mod, srch)
  1091. Xchar *mod, *srch;
  1092. X#endif
  1093. X{
  1094. X   /* Assumes the syntax is CORRECT and CHECKED already! */
  1095. X   char *m;
  1096. X
  1097. X   /* Skip to the modifier section - go past the first semicolon. */
  1098. X   while (*srch && *srch != ';') srch++;
  1099. X   while (*srch) {
  1100. X      srch++;      /* We're on the preceding semicolon */
  1101. X      m = mod;
  1102. X      while (*m && *srch && UPPER(*m) == UPPER(*srch)) {m++; srch++;}
  1103. X      if (!*m && *srch == '=') return srch+1;
  1104. X
  1105. X      /* Failed.  Skip to semicolon */
  1106. X      while (*srch && *srch != ';') srch++;
  1107. X   }
  1108. X   return NULL;
  1109. X}
  1110. X
  1111. X/***************************************************************/
  1112. X/*                                                             */
  1113. X/*  Format - output a string formatted for the terminal.       */
  1114. X/*                                                             */
  1115. X/*  You can specify the terminal width (min. 10).              */
  1116. X/*                                                             */
  1117. X/***************************************************************/
  1118. X#ifdef __STDC__
  1119. Xvoid Format(char *s, int width)
  1120. X#else
  1121. Xvoid Format(s, width)
  1122. Xchar *s;
  1123. Xint width;
  1124. X#endif
  1125. X{
  1126. X   int pos;
  1127. X   int len;
  1128. X   char *wd;
  1129. X
  1130. X   pos = 0;
  1131. X   while (*s) {
  1132. X      wd = NextWord(&s);  /* With leading spaces, not with trailing spaces */
  1133. X      len = strlen(wd);
  1134. X      if (pos + len > width-2) {
  1135. X         putchar('\n');
  1136. X     while (isspace(*wd)) wd++;
  1137. X     pos = strlen(wd);
  1138. X     printf("%s", wd);
  1139. X      } else {
  1140. X         pos += len;
  1141. X     printf("%s", wd);
  1142. X      }
  1143. X   }
  1144. X   putchar('\n');
  1145. X}
  1146. X
  1147. X/***************************************************************/
  1148. X/*                                                             */
  1149. X/*  NextWord - return the next word in the buffer.  Also       */
  1150. X/*  handle conversions between "a" and "an"                    */
  1151. X/*                                                             */
  1152. X/***************************************************************/
  1153. X#ifdef __STDC__
  1154. Xchar *NextWord(char **s)
  1155. X#else
  1156. Xchar *NextWord(s)
  1157. Xchar **s;
  1158. X#endif
  1159. X{
  1160. X   char *dest=Token;   /* Output goes here. */
  1161. X   char *realword;
  1162. X   char *t;
  1163. X   while (isspace(**s)) *dest++ = *(*s)++;  /* Copy leading spaces */
  1164. X
  1165. X   realword = dest;  /* Start of the real word */
  1166. X   if (**s == '-' || **s == '+') (*s)++;  /* Skip any "a/an" thing */
  1167. X   while (**s && !isspace(**s)) *dest++ = *(*s)++; /* Copy word */
  1168. X   *dest = 0;
  1169. X
  1170. X   if (stricmp(realword, "a")) return Token; /* Exit if not "a" */
  1171. X
  1172. X   /* Look for start of next word */
  1173. X   t = *s;
  1174. X   while (isspace(*t)) t++;
  1175. X   if (strchr("aeiouAEIOU+", *t)) {
  1176. X      *dest++ = 'n';
  1177. X      *dest = 0;
  1178. X   }
  1179. X   return Token;
  1180. X}
  1181. X
  1182. X/***************************************************************/
  1183. X/*                                                             */
  1184. X/*  ResolveFilename - search for the file                      */
  1185. X/*                                                             */
  1186. X/***************************************************************/
  1187. X#ifdef __STDC__
  1188. Xchar *ResolveFilename(char *f)
  1189. X#else
  1190. Xchar *ResolveFilename(f)
  1191. Xchar *f;
  1192. X#endif
  1193. X{
  1194. X   char *home;
  1195. X
  1196. X   /* If an absolute path is given, do nothing. */
  1197. X   if (*f == '/') return f;
  1198. X
  1199. X   /* If it's in the current dir, do nothing. */
  1200. X   if (!access(f, R_OK)) return f;
  1201. X
  1202. X   /* Check if it's in the home directory */
  1203. X   home = getenv("HOME");
  1204. X   if (home) {
  1205. X      strcpy(FileName, home);
  1206. X      strcat(FileName, "/");
  1207. X      strcat(FileName, f);
  1208. X      if (!access(FileName, R_OK)) return FileName;
  1209. X   }
  1210. X
  1211. X   /* Check in the library directory */
  1212. X   strcpy(FileName, LIBPATH);
  1213. X   strcat(FileName, "/");
  1214. X   strcat(FileName, f);
  1215. X   if (!access(FileName, R_OK)) return FileName;
  1216. X
  1217. X   /* Couldn't resolve it - die. */
  1218. X   return f;
  1219. X}
  1220. X
  1221. X/***************************************************************/
  1222. X/*                                                             */
  1223. X/*  Banner - print the program banner.                         */
  1224. X/*                                                             */
  1225. X/***************************************************************/
  1226. X#ifdef __STDC__
  1227. Xvoid Banner(void)
  1228. X#else
  1229. Xvoid Banner()
  1230. X#endif
  1231. X{
  1232. X   fprintf(stderr, "\nThought version %s (PL %s)\nby David F. Skoll\n\n",
  1233. X           VERSION, PATCHLEVEL);
  1234. X}
  1235. X
  1236. X/***************************************************************/
  1237. X/*                                                             */
  1238. X/*  Usage - display program usage.                             */
  1239. X/*                                                             */
  1240. X/***************************************************************/
  1241. X#ifdef __STDC__
  1242. Xvoid Usage(void)
  1243. X#else
  1244. Xvoid Usage()
  1245. X#endif
  1246. X{
  1247. X   Banner();
  1248. X   fprintf(stderr, "Usage: thought [-dvi] [-w#] [filename]\n\n");
  1249. X   fprintf(stderr, "Options: -d = Debug sentence definitions.\n");
  1250. X   fprintf(stderr, "         -v = Verbose mode.\n");
  1251. X   fprintf(stderr, "         -i = Interactive mode.\n");
  1252. X   fprintf(stderr, "         -w# = set formatted output width to # columns.\n\n");
  1253. X   fprintf(stderr, "filename is optional grammar file.  Default file is\n");
  1254. X   fprintf(stderr, "'%s'.\n\n", FILE_DEFAULT);
  1255. X   fprintf(stderr, "In interactive mode, enter 'q' to quit.\n\n");
  1256. X}
  1257. X
  1258. X/***************************************************************/
  1259. X/*                                                             */
  1260. X/* SystemTime                                                  */
  1261. X/*                                                             */
  1262. X/* Returns current system time in seconds past midnight.       */
  1263. X/*                                                             */
  1264. X/***************************************************************/
  1265. X#ifdef __STDC__
  1266. Xlong SystemTime(void)
  1267. X#else
  1268. Xlong SystemTime()
  1269. X#endif
  1270. X{
  1271. X#ifndef MSDOS
  1272. X   time_t tloc;
  1273. X   struct tm *t;
  1274. X
  1275. X   (void) time(&tloc);
  1276. X   t = localtime(&tloc);
  1277. X   return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L + (long) t->tm_sec;
  1278. X
  1279. X#else
  1280. X   struct dostime_t tloc;
  1281. X   _dos_gettime(&tloc);
  1282. X   return (long) tloc.hour * 3600L + (long) tloc.minute * 60L + (long) tloc.second;
  1283. X#endif
  1284. X}
  1285. X
  1286. X/***************************************************************/
  1287. X/*                                                             */
  1288. X/*  MAIN - Main program.                                       */
  1289. X/*                                                             */
  1290. X/***************************************************************/
  1291. X#ifdef __STDC__
  1292. Xint main (int argc, char **argv)
  1293. X#else
  1294. Xint main(argc, argv)
  1295. Xint argc;
  1296. Xchar **argv;
  1297. X#endif
  1298. X{
  1299. X   char *filename=FILE_DEFAULT;
  1300. X   char *curarg;
  1301. X   char Verbose = 0;
  1302. X   char Debug = 0;
  1303. X   char Interactive = 0;
  1304. X   int Width = 80;
  1305. X   Sentence *sent;
  1306. X   struct timeval tv;
  1307. X   int i;
  1308. X
  1309. X   while (--argc) {
  1310. X      argv++;
  1311. X      curarg = *argv;
  1312. X      if (*curarg == '-') {
  1313. X         while (*++curarg) {
  1314. X        switch(*curarg) {
  1315. X           case 'v': Verbose = 1; break;
  1316. X           case 'd': Debug   = 1; break;
  1317. X           case 'i': Interactive = 1; break;
  1318. X           case 'w': Width = atoi(curarg+1);
  1319. X                     while (*(curarg+1)) curarg++;
  1320. X             break;
  1321. X           default: Usage(); exit(1);
  1322. X        }
  1323. X     }
  1324. X      } else filename = curarg;
  1325. X   }
  1326. X   if (Verbose) Banner();
  1327. X   if (Width < 10) {
  1328. X      fprintf(stderr, "Minimum terminal width is 10.\n");
  1329. X      exit(1);
  1330. X   }
  1331. X   filename = ResolveFilename(filename);
  1332. X   if (access(filename, R_OK)) {
  1333. X      perror(filename);
  1334. X      exit(1);
  1335. X   }
  1336. X   if (Verbose) fprintf(stderr, "[Using '%s' as grammar file.]\n\n", filename);
  1337. X   ReadFile(filename);
  1338. X   if (!NumSentences) {
  1339. X      fprintf(stderr, "No sentence definitions found!\n");
  1340. X      exit(1);
  1341. X   }
  1342. X/* initialize the random seed */
  1343. X   srand( (int) SystemTime());
  1344. X   for (i=0; i<5; i++) (void) rand();
  1345. X
  1346. X/* If it's DEBUG, loop through all sentence definitions */
  1347. X   if (Debug) {
  1348. X      if (Verbose) fprintf(stderr, "Checking sentence definitions...\n");
  1349. X      sent = SentenceList;
  1350. X      while(sent) {
  1351. X         GenerateThought(sent);
  1352. X     Format(Buffer, Width);
  1353. X     putchar('\n');
  1354. X     sent = sent->next;
  1355. X      }
  1356. X      fprintf(stderr, "All sentence definitions appear to be OK.\n");
  1357. X      exit(0);
  1358. X   }
  1359. X
  1360. X/* Check that stdin, stdout is a tty if interactive mode is set */
  1361. X   if (Interactive) {
  1362. X      if (!isatty(0) || !isatty(1)) {
  1363. X         fprintf(stderr, "For interactive mode, stdin and stdout must be a tty.\n");
  1364. X     exit(1);
  1365. X      }
  1366. X   }
  1367. X
  1368. X   while(1) {
  1369. X      i = rand() % NumSentences;
  1370. X      sent = SentenceList;
  1371. X
  1372. X      while (i && sent) {
  1373. X         sent = sent->next;
  1374. X     i--;
  1375. X      }
  1376. X
  1377. X      if (!sent) {
  1378. X         fprintf(stderr, "Internal error!  NumSentences is too high!\n");
  1379. X     exit(1);
  1380. X      }
  1381. X      GenerateThought(sent);
  1382. X      Format(Buffer, Width);
  1383. X      if (!Interactive) exit(0);
  1384. X      gets(Buffer);
  1385. X      if (*Buffer == 'q' || *Buffer == 'Q') exit(0);
  1386. X   }      
  1387. X
  1388. X}
  1389. SHAR_EOF
  1390. $TOUCH -am 0717120791 thought.c &&
  1391. chmod 0600 thought.c ||
  1392. echo "restore of thought.c failed"
  1393. set `wc -c thought.c`;Wc_c=$1
  1394. if test "$Wc_c" != "26519"; then
  1395.     echo original size 26519, current size $Wc_c
  1396. fi
  1397. fi
  1398. # ============= thought.man ==============
  1399. if test X"$1" != X"-c" -a -f 'thought.man'; then
  1400.     echo "File already exists: skipping 'thought.man'"
  1401. else
  1402. echo "x - extracting thought.man (Text)"
  1403. sed 's/^X//' << 'SHAR_EOF' > thought.man &&
  1404. X.TH THOUGHT 1 "4 July 1991"
  1405. X.UC 4
  1406. X.SH NAME
  1407. Xthought \- a program to generate random (and demented) thoughts-for-today
  1408. X.SH SYNOPSIS
  1409. X.B thought
  1410. X[\fB\-dvi\fP] [\fB\-w\fP\fIn\fP] [\fIfilename\fP]
  1411. X.SH DESCRIPTION
  1412. X.B Thought
  1413. Xreads the specified \fIfilename\fP, which must contain a grammar specification,
  1414. Xand generates random thoughts.  The \fIfilename\fP defaults to \fBthought.rc\fP
  1415. Xif one is not supplied.  See the man page for \fBthoughtfile\fP(5) for
  1416. Xinformation on the format of grammar files.
  1417. X.PP
  1418. X\fBThought\fP will look for the grammar file first in the current directory;
  1419. Xnext in your home directory, and finally in a central location determined
  1420. Xby the person who built \fBthought\fP.
  1421. X.SH OPTIONS
  1422. X.TP
  1423. X.B \-d
  1424. XThe \fB\-d\fP flag causes \fBthought\fP to scan through all sentence
  1425. Xdefinitions in the grammar file to check that they are specified correctly.
  1426. XA thought-of-the-day for each type of sentence is displayed.  For this
  1427. Xreason, if you only want to check for errors, you may wish to pipe
  1428. Xstandard output to /dev/null.
  1429. XThis flag should only be of interest if you are creating grammar files.
  1430. X.TP
  1431. X.B \-i
  1432. XThe \fB\-i\fP flag causes \fBthought\fP to go into an interactive mode.
  1433. XAfter each thought has been displayed, it waits for you to press return.
  1434. XIt will keep displaying thoughts until you hit 'q' or 'Q' and press return.
  1435. X.TP
  1436. X.B \-v
  1437. XThe \fB\-v\fP causes \fBthought\fP to be slightly more verbose.
  1438. X.TP
  1439. X.B \-w
  1440. XThe \fB\-w\fP\fIn\fP option causes the output to be formatted for a terminal
  1441. Xwith \fIn\fP columns.
  1442. X.SH AUTHOR
  1443. XDavid F. Skoll (dfs@doe.carleton.ca)
  1444. X.SH BUGS
  1445. X\fBThought\fP reads the entire grammar file into memory.  This consumes lots
  1446. Xof space, and is wasteful if you only want to issue one thought for the day.
  1447. X.PP
  1448. X\fBThought\fR is quite inefficient as far as speed goes.
  1449. X.PP
  1450. XLots of silly restrictions about lengths of words, sentences, and so on.
  1451. X.SH SEE ALSO
  1452. X\fBthoughtfile\fP(5)
  1453. SHAR_EOF
  1454. $TOUCH -am 0704142291 thought.man &&
  1455. chmod 0600 thought.man ||
  1456. echo "restore of thought.man failed"
  1457. set `wc -c thought.man`;Wc_c=$1
  1458. if test "$Wc_c" != "1895"; then
  1459.     echo original size 1895, current size $Wc_c
  1460. fi
  1461. fi
  1462. echo "End of part 1, continue with part 2"
  1463. exit 0
  1464.  
  1465.  
  1466. exit 0 # Just in case...
  1467.