[net.sources.games] Source for insult, flame, babble

faustus@ucbcad.UUCP (Wayne A. Christopher) (05/11/85)

I am posting the source for a few programs I wrote some time
ago to generate random insults, flames, and sentences. They
are written using a pre-processor called "kafka", which is
also included. To create them collect all the parts of this
posting, pipe them to sh, then run "make".

	Wayne

# The rest of this file is a shell script which will extract:
# READ.ME Makefile babble.k flame.k insult.k defs.h graph.h kafgraf.h dstrans.c etc.c funwords.c init.c main.c maketext.c output.c psubr.c stuff.c parse.y lexical.l
echo x - READ.ME
cat >READ.ME <<'!Funky!Stuff!'

RCS Info: $Revision: $ on $Date: $
          $Source: $
Copyright (c) 1985 Wayne A. Christopher 
	Permission is granted to do anything with this READ.ME file
	except sell it or remove this message.

Contained herein is the source for kafka, which is a program that
translates BNF grammers into C programs to generate strings in the
grammer, and files for three useful kafka programs, insult, flame,
and babble. I don't have a manual page for kafka because I have
been too lazy to write one, but if you read the .k files you will
probably be able to figure out how things work. Any improvements
anybody can make on these programs I'd be happy to hear about. The
usual disclaimer: any opinions stated in the following code, or
statements produced by the included programs, have nothing to do
with U. C. Berkeley or anybody, including me...

!Funky!Stuff!
echo x - Makefile
cat >Makefile <<'!Funky!Stuff!'

# RCS Info: $Revision: $ on $Date: $
#           $Source: $
# Copyright (c) 1985 Wayne A. Christopher 
#	Permission is granted to do anything with this code except sell it
#	or remove this message.
#
# The makefile for everything.

CFILES = dstrans.c etc.c funwords.c init.c main.c \
	maketext.c output.c psubr.c stuff.c

KFILES = babble.k flame.k insult.k

HFILES = defs.h graph.h kafgraf.h

OFILES = dstrans.o init.o main.o psubr.o stuff.o \
	lex.yy.o y.tab.o

RUNOFILES = etc.o maketext.o output.o

all: kafka insult babble flame

kafka: $(OFILES)
	cc -o kafka $(OFILES)

insult: insult.k $(RUNOFILES)
	./kafka insult.k
	cc -c kaf.spec.c kaf.text.c
	cc -o insult $(RUNOFILES) kaf.spec.o kaf.text.o

babble: babble.k $(RUNOFILES)
	./kafka babble.k
	cc -c kaf.spec.c kaf.text.c
	cc -o babble $(RUNOFILES) kaf.spec.o kaf.text.o

flame:	flame.k $(RUNOFILES)
	./kafka flame.k
	cc -c kaf.spec.c kaf.text.c
	cc -o flame $(RUNOFILES) kaf.spec.o kaf.text.o

lex.yy.c: lexical.l y.tab.h
	lex lexical.l
	egrep -v '^# define (input|unput)' < lex.yy.c > ltmp
	mv ltmp lex.yy.c

y.tab.c y.tab.h: parse.y
	yacc -d parse.y

!Funky!Stuff!
echo x - babble.k
cat >babble.k <<'!Funky!Stuff!'

# RCS Info: $Revision: $ on $Date: $
#           $Source: $
# Copyright (c) 1985 Wayne A. Christopher 
#	Permission is granted to do anything with this code except sell it
#	or remove this message.
#
# The following program is written in 'kafka', a sort of BNF with imbedded
# C code that directs the selection of rules. (CH(x,y) is a macro that
# means basically "accept this rule x out of y times".) Otherwise rules
# are checked from top to bottom.  The program that takes this specification
# and turns it into a C program (which then spits out strings) can be found
# in ~/bin/kafka, and the source and other useful things can be found in
# ~/kafka. (Some on ernie, in ~faustus/kafka.)
# The program should be pretty self-explanatory, though -- it is
# supposed to look a bit like lex and yacc specifications...
# By the way, rules are written <non-terminal> = stuff { C code } ;
# where the stuff can be any mix of non-termnals (surrounded by <>) and
# terminals. The C code should return (1) if the rule is to be used and 0
# if not. If there is no stuff, the C code can return a pointer to a string
# that is taken to be a terminal, but I'm not using this because it isn't
# very neat and is only useful when you are doing non-context free stuff...

%{

#define CH(n, o)	return ((((random() - 1313513) % o) < n) ? 1 : 0)
/* I think there used to be a reason for doing ^^^ this... */

%}

%%

<start>		= <unit> 				;

<unit>		= <s> "." 				{ CH(3, 4); } ;
<unit>		= <rnd> 				;

# We have to be explicit about what kind of nouns go with what verbs.

<s>		= <s> , <Conj> <s> 			{ CH(1, 25); } ;

# verb1 is sort of simple physical stuff (transitive), non-intentional.
<s>		= <thing> <verb1> <thing> 		{ CH(1, 20); } ;

<verb1>		= "fell	on"				{ CH(1, 20); } ;
<verb1>		= was <in-rel-to>			{ CH(1, 20); } ;
<verb1>		= hit					{ CH(1, 20); } ;
<verb1>		= "was in fact"				{ CH(1, 20); } ;
<verb1>		= "was almost as" <adj1> as		{ CH(1, 20); } ;
<verb1>		= "was as" <adj1> as			{ CH(1, 20); } ;
<verb1>		= "was more" <adj1> than		{ CH(1, 20); } ;
<verb1>		= "may have been" <in-rel-to>		{ CH(1, 20); } ;
<verb1>		= "looked like"				{ CH(1, 20); } ;
<verb1>		= reminded <agent> of			{ CH(1, 20); } ;
<verb1>		= "seemed to be"			{ CH(1, 20); } ;
<verb1>		= <verb1>				;

# verb2 is intransitive sorts of things, and complex transitive verbs.
<s>		= <agent> <verb2> 			{ CH(1, 20); } ;

<verb2>		= said "'" <s> "'"			{ CH(1, 20); } ;
<verb2>		= "said that" <s>			{ CH(1, 20); } ;
<verb2>		= ran					{ CH(1, 20); } ;
<verb2>		= died					{ CH(1, 20); } ;
<verb2>		= exploded				{ CH(1, 20); } ;
<verb2>		= ate					{ CH(1, 20); } ;
<verb2>		= became <adj1>				{ CH(1, 20); } ;
<verb2>		= was <adj1>				{ CH(1, 8); } ;
<verb2>		= seemed <adj1>				{ CH(1, 10); } ;
<verb2>		= jumped				{ CH(1, 20); } ;
<verb2>		= walked				{ CH(1, 20); } ;
<verb2>		= fell					{ CH(1, 20); } ;
<verb2>		= disappeared				{ CH(1, 20); } ;
<verb2>		= "hopped around"			{ CH(1, 20); } ;
<verb2>		= flew					{ CH(1, 20); } ;
<verb2>		= used <thing> "as a" <Inan-obj>	{ CH(1, 20); } ;
<verb2>		= gave <thing> to <agent>		{ CH(1, 20); } ;
<verb2>		= "bit the dust"			{ CH(1, 20); } ;
<verb2>		= <verb2>				;

# verb3 is transitive intentional things.
<s>		= <agent> <adv> <verb3> <thing>		{ CH(1, 5); } ;

<verb3>		= hit					{ CH(1, 20); } ;
<verb3>		= used					{ CH(1, 20); } ;
<verb3>		= "acted like"				{ CH(1, 20); } ;
<verb3>		= "thought he was"			{ CH(1, 20); } ;
<verb3>		= "looked like"				{ CH(1, 20); } ;
<verb3>		= ate					{ CH(1, 20); } ;
<verb3>		= "threw out"				{ CH(1, 20); } ;
<verb3>		= "looked at"				{ CH(1, 20); } ;
<verb3>		= disliked				{ CH(1, 20); } ;
<verb3>		= "cooked and ate"			{ CH(1, 20); } ;
<verb3>		= destroyed				{ CH(1, 20); } ;
<verb3>		= lifted				{ CH(1, 20); } ;
<verb3>		= stole					{ CH(1, 20); } ;
<verb3>		= dropped				{ CH(1, 20); } ;
<verb3>		= bought				{ CH(1, 20); } ;
<verb3>		= "heard about"				{ CH(1, 20); } ;
<verb3>		= considered				{ CH(1, 20); } ;
<verb3>		= "interacted with"			{ CH(1, 20); } ;
<verb3>		= painted				{ CH(1, 20); } ;
<verb3>		= <verb3>				;

# verb4 is agent-agent stuff.
<s>		= <agent> <verb4> <agent> 		{ CH(1, 20); } ;

<verb4>		= hated					{ CH(1, 20); } ;
<verb4>		= killed				{ CH(1, 20); } ;
<verb4>		= loved					{ CH(1, 20); } ;
<verb4>		= "disagreed with"			{ CH(1, 20); } ;
<verb4>		= imitated				{ CH(1, 20); } ;
<verb4>		= "talked to"				{ CH(1, 20); } ;
<verb4>		= <verb4>				;

# verb5 is agent-intangible stuff. (I don't know about this...)
<s>		= <agent> <verb5> <intang-obj>		{ CH(1, 20); } ;

<verb5>		= felt					{ CH(1, 20); } ;
<verb5>		= enjoyed				{ CH(1, 20); } ;
<verb5>		= <verb5>				;

# Now for some more things -- intentional statements, (some of these
# may turn out to be ungrammatical, for instance by not using the subjunctive
# mode)...

<s>		= <agent> <int-verb> <s>		{ CH(1, 20); } ;

<int-verb>	= "desired that"			{ CH(1, 20); } ;
<int-verb>	= "believed that"			{ CH(1, 20); } ;
<int-verb>	= "hoped that"				{ CH(1, 20); } ;
<int-verb>	= "thought that"			{ CH(1, 20); } ;
<int-verb>	= "wished that"				{ CH(1, 20); } ;
<int-verb>	= "feared that"				{ CH(1, 20); } ;
<int-verb>	= "wondered whether"			{ CH(1, 20); } ;
<int-verb>	= "was worried that"			{ CH(1, 20); } ;
<int-verb>	= "figured that"			{ CH(1, 20); } ;
<int-verb>	= "predicted that"			{ CH(1, 20); } ;
<int-verb>	= "was ashamed that"			{ CH(1, 20); } ;
<int-verb>	= <int-verb>				;

<s>		= <s>					;

<adv>		= ""					{ CH(4, 5); } ;
<adv>		= <Adv>					;

<in-rel-to>	= <prep>				{ CH(1, 4); } ;
<in-rel-to>	= "similar to"				{ CH(1, 20); } ;
<in-rel-to>	= "in contact with"			{ CH(1, 20); } ;
<in-rel-to>	= "not at all like"			{ CH(1, 20); } ;
<in-rel-to>	= "reminicent of"			{ CH(1, 20); } ;
<in-rel-to>	= "a part of"				{ CH(1, 20); } ;
<in-rel-to>	= "exactly like"			{ CH(1, 20); } ;
<in-rel-to>	= <in-rel-to>				;


# == NOUNS ==
# Here are the noun things -- there are agents, inanimate objects, and
# intangible objects (like concepts). Ignore pronouns for now.
# Intangible things don't have determiners, and don't have "tangible"
# adjectives attatched to them.

<thing>		= <agent>				{ CH(1, 2); } ;
<thing>		= <inan-obj>				;

<agent>		= <agent1> 				;

<agent1>	= <name-p> 				{ CH(1, 3); } ;
<agent1>	= <Det> <agent-adj> <Agent> 		;

<inan-obj>	= <A-Det> <thing-adj> <Inan-obj> 	;

<intang-obj>	= <intang-adj> <Intang-obj>		;

<name-p>	= <Name> 				;

<prep>		= "along with"   			{ CH(1, 10); } ;
<prep>		= "on top of"  				{ CH(1, 10); } ;
<prep>		= "next to"   				{ CH(1, 10); } ;
<prep>		= near   				{ CH(1, 10); } ;
<prep>		= like   				{ CH(1, 10); } ;
<prep>		= "apart from"   			{ CH(1, 10); } ;
<prep>		= "in addition to"			{ CH(1, 10); } ;
<prep>		= <prep>				;

# == ADJECTIVES == 
# Intangible adjectives -- good, bad, etc. Tangible adjectives -- red, cold,
# etc. Agent agectives -- mean, selfish, etc. Agents can have any one, things
# can have tangible and intangible, but intangibles can have only intangibles.

<intang-adj>	= ""					{ CH(4, 5); } ;
<intang-adj>	= <Intang-adj> <intang-adj>		;

<agent-adj>	= ""					{ CH(4, 5); } ;
<agent-adj>	= <adj1> <agent-adj>			;

<thing-adj>	= ""					{ CH(4, 5); } ;
<thing-adj>	= <adj2> <thing-adj> 			;

<adj1>		= <Intang-adj>				{ CH(1, 3); } ;
<adj1>		= <Agent-adj>				{ CH(1, 3); } ;
<adj1>		= <Tang-adj>				;

<adj2>		= <Intang-adj>				{ CH(1, 2); } ;
<adj2>		= <Tang-adj>				;

# Some generic words.

<Conj>		= but 					{ CH(1, 20); } ;
<Conj>		= and 					{ CH(1, 20); } ;
<Conj>		= or 					{ CH(1, 20); } ;
<Conj>		= so 					{ CH(1, 20); } ;
<Conj>		= however 				{ CH(1, 20); } ;
<Conj>		= nevertheless 				{ CH(1, 20); } ;
<Conj>		= therefore 				{ CH(1, 20); } ;
<Conj>		= <Conj> 				;

# P-Det is a posession determiner -- can't be used with an agent.

<A-Det>		= <Det>					{ CH(1, 2); } ;
<A-Det>		= <P-Det>				;

<Det>		= a 					{ CH(1, 10); } ;
<Det>		= the 					{ CH(1, 7); } ;
<Det>		= that 					{ CH(1, 15); } ;
<Det>		= "some kind of" 			{ CH(1, 20); } ;	
<Det>		= this 					{ CH(1, 15); } ;
<Det>		= some	 				{ CH(1, 20); } ;
<Det>		= <Det> 				;

<P-Det>		= my 					{ CH(1, 20); } ;
<P-Det>		= your 					{ CH(1, 20); } ;
# The # mark here ---------v means don't put a space in between...
<P-Det>		= <agent1> "#'s"			{ CH(1, 20); } ;
<P-Det>		= his 					{ CH(1, 20); } ;
<P-Det>		= her 					{ CH(1, 20); } ;
<P-Det>		= their 				{ CH(1, 20); } ;
<P-Det>		= <P-Det> 				;

<Agent>		= person				{ CH(1, 20); } ;
<Agent>		= dog 					{ CH(1, 20); } ;
<Agent>		= cat 					{ CH(1, 20); } ;
<Agent>		= duck 					{ CH(1, 20); } ;
<Agent>		= sheriff				{ CH(1, 20); } ;
<Agent>		= professor				{ CH(1, 20); } ;
<Agent>		= student				{ CH(1, 20); } ;
<Agent>		= "CS grad student"			{ CH(1, 20); } ;
<Agent>		= "disk jockey"				{ CH(1, 20); } ;
<Agent>		= hacker				{ CH(1, 20); } ;
<Agent>		= horse					{ CH(1, 20); } ;
<Agent>		= pig					{ CH(1, 20); } ;
<Agent>		= dude					{ CH(1, 20); } ;
<Agent>		= communist				{ CH(1, 20); } ;
<Agent>		= goose					{ CH(1, 20); } ;
<Agent>		= scumbag				{ CH(1, 20); } ;
<Agent>		= "scuba diver"				{ CH(1, 20); } ;
<Agent>		= "disembodied spirit"			{ CH(1, 20); } ;
<Agent>		= guy					{ CH(1, 20); } ;
<Agent>		= Australian				{ CH(1, 20); } ;
<Agent>		= aardvark				{ CH(1, 20); } ;
<Agent>		= "space alien"				{ CH(1, 20); } ;
<Agent>		= <Agent>				;

<Inan-obj>	= house 				{ CH(1, 20); } ;
<Inan-obj>	= fruit 				{ CH(1, 20); } ;
<Inan-obj>	= slime-mold 				{ CH(1, 20); } ;
<Inan-obj>	= "lisp manual" 			{ CH(1, 20); } ;
<Inan-obj>	= rock	 				{ CH(1, 20); } ;
<Inan-obj>	= terminal 				{ CH(1, 20); } ;
<Inan-obj>	= textbook 				{ CH(1, 20); } ;
<Inan-obj>	= pen	 				{ CH(1, 20); } ;
<Inan-obj>	= box 					{ CH(1, 20); } ;
<Inan-obj>	= steak 				{ CH(1, 20); } ;
<Inan-obj>	= vax	 				{ CH(1, 20); } ;
<Inan-obj>	= "salad fork" 				{ CH(1, 20); } ;
<Inan-obj>	= thingamajig 				{ CH(1, 20); } ;
<Inan-obj>	= doorknob 				{ CH(1, 20); } ;
<Inan-obj>	= axe	 				{ CH(1, 20); } ;
<Inan-obj>	= "357 magnum" 				{ CH(1, 20); } ;
<Inan-obj>	= adm3a 				{ CH(1, 20); } ;
<Inan-obj>	= saxaphone 				{ CH(1, 20); } ;
<Inan-obj>	= pineapple 				{ CH(1, 20); } ;
<Inan-obj>	= keyboard 				{ CH(1, 20); } ;
<Inan-obj>	= "baked potato"			{ CH(1, 20); } ;
<Inan-obj>	= "carpet tack"				{ CH(1, 20); } ;
<Inan-obj>	= "bottle of bee"			{ CH(1, 20); } ;
<Inan-obj>	= coathanger 				{ CH(1, 20); } ;
<Inan-obj>	= "bayobab tree"			{ CH(1, 20); } ;
<Inan-obj>	= <Inan-obj>				;

# These are all mental conditions.

<Intang-obj>	= fear					{ CH(1, 20); } ;
<Intang-obj>	= loathing				{ CH(1, 20); } ;
<Intang-obj>	= sympathy				{ CH(1, 20); } ;
<Intang-obj>	= hope					{ CH(1, 20); } ;
<Intang-obj>	= disgust				{ CH(1, 20); } ;
<Intang-obj>	= envy					{ CH(1, 20); } ;
<Intang-obj>	= distaste				{ CH(1, 20); } ;
<Intang-obj>	= excitement				{ CH(1, 20); } ;
<Intang-obj>	= <Intang-obj>				;

<Name>		= "Generic Joe" 			{ CH(1, 20); } ;
<Name>		= John 					{ CH(1, 20); } ;
<Name>		= Mary 					{ CH(1, 20); } ;
<Name>		= "Ronald Reagan" 			{ CH(1, 20); } ;
<Name>		= "Fritz Mondale" 			{ CH(1, 20); } ;
<Name>		= "Marvin Minsky" 			{ CH(1, 20); } ;
<Name>		= "Howard the Duck" 			{ CH(1, 20); } ;
<Name>		= "Doug Cooper" 			{ CH(1, 20); } ;
<Name>		= Chris 				{ CH(1, 20); } ;
<Name>		= Batman 				{ CH(1, 20); } ;
<Name>		= "Wyatt Earp" 				{ CH(1, 20); } ;
<Name>		= "Richard Nixon" 			{ CH(1, 20); } ;
<Name>		= "The Spanish Inquisition"		{ CH(1, 20); } ;
<Name>		= <Name> 				;

<Intang-adj>	= lousy 				{ CH(1, 20); } ;
<Intang-adj>	= undesirable 				{ CH(1, 20); } ;
<Intang-adj>	= bad	 				{ CH(1, 20); } ;
<Intang-adj>	= strange 				{ CH(1, 20); } ;
<Intang-adj>	= unexpected 				{ CH(1, 20); } ;
<Intang-adj>	= fascinating 				{ CH(1, 20); } ;
<Intang-adj>	= useful 				{ CH(1, 20); } ;
<Intang-adj>	= appropriate 				{ CH(1, 20); } ;
<Intang-adj>	= nice 					{ CH(1, 20); } ;
<Intang-adj>	= incredible 				{ CH(1, 20); } ;
<Intang-adj>	= bizarre 				{ CH(1, 20); } ;
<Intang-adj>	= awful	 				{ CH(1, 20); } ;
<Intang-adj>	= unnatural 				{ CH(1, 20); } ;
<Intang-adj>	= "out of place"			{ CH(1, 20); } ;
<Intang-adj>	= terrible 				{ CH(1, 20); } ;
<Intang-adj>	= <Intang-adj>				;

<Tang-adj>	= red 					{ CH(1, 20); } ;
<Tang-adj>	= green					{ CH(1, 20); } ;
<Tang-adj>	= big 					{ CH(1, 20); } ;
<Tang-adj>	= hot 					{ CH(1, 20); } ;
<Tang-adj>	= heavy					{ CH(1, 20); } ;
<Tang-adj>	= fast 					{ CH(1, 20); } ;
<Tang-adj>	= slow 					{ CH(1, 20); } ;
<Tang-adj>	= huge 					{ CH(1, 20); } ;
<Tang-adj>	= lumpy					{ CH(1, 20); } ;
<Tang-adj>	= <Agent> "#-like" 			{ CH(1, 20); } ;
<Tang-adj>	= <Inan-obj> "#-like" 			{ CH(1, 20); } ;
<Tang-adj>	= shabby 				{ CH(1, 20); } ;
<Tang-adj>	= <Tang-adj>				;

<Agent-adj>	= benevolent				{ CH(1, 20); } ;
<Agent-adj>	= nasty					{ CH(1, 20); } ;
<Agent-adj>	= misanthropic				{ CH(1, 20); } ;
<Agent-adj>	= conceited				{ CH(1, 20); } ;
<Agent-adj>	= arrogant				{ CH(1, 20); } ;
<Agent-adj>	= misguided				{ CH(1, 20); } ;
<Agent-adj>	= nervous				{ CH(1, 20); } ;
<Agent-adj>	= clever				{ CH(1, 20); } ;
<Agent-adj>	= stupid				{ CH(1, 20); } ;
<Agent-adj>	= <Agent-adj>				;

<Adv>		= quickly 				{ CH(1, 20); } ;
<Adv>		= badly 				{ CH(1, 20); } ;
<Adv>		= slowly 				{ CH(1, 20); } ;
<Adv>		= stupidly 				{ CH(1, 20); } ;
<Adv>		= selfishly 				{ CH(1, 20); } ;
<Adv>		= properly				{ CH(1, 20); } ;
<Adv>		= <Adv> 				;

<spunct>	= "."					;

# Now, just for the heck of it, some random things...

<rnd>		= "what a" <Inan-obj> "!"		{ CH(1, 20); } ;
<rnd>		= "oh no, it's" <thing>	"!"		{ CH(1, 20); } ;
<rnd>		= "NOBODY expects" <thing> "!"		{ CH(1, 20); } ;
<rnd>		= "look at" <thing> "!"			{ CH(1, 20); } ;
<rnd>		= gosh!					{ CH(1, 20); } ;
<rnd>		= yeah, <s> .				{ CH(1, 10); } ;
<rnd>		= "wouldn't ya know, " <s> "!"		{ CH(1, 20); } ;
<rnd>		= "well, shiver me timbers!"		{ CH(1, 20); } ;
<rnd>		= "lemme tell ya -" <s> "!"		{ CH(1, 20); } ;
<rnd>		= "why, you" <Inan-obj> "!"		{ CH(1, 20); } ;
<rnd>		= "look at me when I'm talking to you!"	{ CH(1, 20); } ;
<rnd>		= <thing> ... uh...			{ CH(1, 10); } ;
<rnd>		= uh...					{ CH(1, 20); } ;
<rnd>		= "hic! (excuse me...)"			{ CH(1, 20); } ;
<rnd>		= "you know," <s> .			{ CH(1, 20); } ;
<rnd>		= <agent> "said that" <s> . 		{ CH(1, 5); } ;
<rnd>		= <rnd>				;

%%

!Funky!Stuff!
echo x - flame.k
cat >flame.k <<'!Funky!Stuff!'
%{

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 */

#define CH(n, o)	return ((((random() - 1313513) % o) < n) ? 1 : 0)

char *ones;

#define YOUR	ones = "your"
#define MY	ones = "my"
#define HIS	ones = "his"

%}

%%

#  flame

<start>	=	<flame>;

<flame> =	"how can you say that " <statement> "?" { CH(1,100); } ;
<flame>	=	"I can't believe how " <adjective> " you are." { CH(1,100); } ;
<flame>	=	"only a " <der-term> " like you would say that " <statement> "." { CH(1,70); } ;
<flame>	=	<statement> ", huh?" { CH(1,80); } ;
<flame>	=	so, <statement> "?" { CH(1,80); } ;
<flame>	=	<statement> ", right?" { CH(1,80); } ;
<flame>	=	"I mean," <flame> { CH(1,80); } ;
<flame>	=	"don't you realize that" <statement> "?" { CH(1,80); } ;
<flame>	=	"I firmly believe that" <statement> "." { CH(1,80); } ;
<flame>	=	"let me tell you something, you " <der-term> "." { CH(1,80); } ;
<flame>	=	"furthermore, you " <der-term> ", " <flame> { CH(1,70); } ;
<flame>	=	"I couldn't care less about your " <thing> "." { CH(1,100); } ;
<flame>	=	"how can you be so " <adjective> "?" { CH(1,100); } ;
<flame>	=	"you make me sick." { CH(1,100); } ;
<flame>	=	"it's well known that" <statement> "."{ CH(1,70); } ;
<flame>	=	<statement> "."{ CH(1,70); } ;
<flame>	=	"it takes a" <group-adj> <der-term> "like you to say that" <statement> "." { CH(1,60); } ;
<flame>	=	"I don't want to hear about your" <thing> "." { CH(1,100); } ;
<flame>	=	"you're always totally wrong." { CH(1,100); } ;
<flame>	=	"I've never heard anything as ridiculous as the idea that " <statement> "." { CH(1,90); } ;
<flame>	=	"you must be a real" <der-term> "to think that" <statement> "." { CH(1,100); } ;
<flame>	=	you <adjective> <group-adj> <der-term> "!" { CH(1,70); } ;
<flame>	=	"you're probably" <group-adj> "yourself." { CH(1,80); } ;
<flame>	=	"you sound like a real" <der-term> "." { CH(1,100); } ;
<flame>	=	why, <statement> "!" { CH(1,100); } ;
<flame>	=	"I have many" <group-adj> "friends." { CH(1,100); } ;
<flame>	=	"save the" <thing> "#s!" { CH(1,80); } ;
<flame>	=	"no nukes!" { CH(1,100); } ;
<flame>	=	ban <thing> "#s!" { CH(1,100); } ;
<flame>	=	"mercy mercy puddin and pie!" { CH(1,100); } ;
<flame>	=	"I'll bet you think that" <thing> "#s are" <adjective> "." { CH(1,80); } ;
<flame>	=	"you know," <statement> "." { CH(1,100); } ;
<flame>	=	your <quality> "reminds me of a" <thing> "." { CH(1,80); } ;
<flame>	=	"you have the" <quality> "of a" <der-term> "." { CH(1,100); } ;
<flame>	=	<der-term> "!" { CH(1,100); } ;
<flame>	=	<adjective> <group-adj> <der-term> "!" { CH(1,80); } ;
<flame>	=	"you're a typical" <group-adj> "person, totally" <adjective> "." { CH(1,90); } ;
<flame>	=	"man, " <flame> { CH(1,100); } ;
<flame> =	<flame> ;

<quality> =	ignorance { CH(1, 100); } ;
<quality> =	stupidity { CH(1, 100); } ;
<quality> =	worthlessness { CH(1, 100); } ;
<quality> =	prejudice { CH(1, 90); } ;
<quality> =	"lack of intelligence" { CH(1, 100); } ;
<quality> =	complete <quality> { CH(1, 100); } ;
<quality> =	lousiness { CH(1, 90); } ;
<quality> =	"bad grammer" { CH(1, 70); } ;
<quality> =	"lousy spelling" { CH(1, 70); } ;
<quality> =	"lack of common decency" { CH(1, 70); } ;
<quality> =	ugliness { CH(1, 70); } ;
<quality> =	nastiness { CH(1, 70); } ;
<quality> =	pregnancy { CH(1, 70); } ;
<quality> =	<quality> ;

<adjective> =	ignorant { CH(1, 100); } ;
<adjective> =	pregnant { CH(1, 100); } ;
<adjective> =	egotistical { CH(1, 100); } ;
<adjective> =	sick { CH(1, 100); } ;
<adjective> =	perverted { CH(1, 70); } ;
<adjective> =	sadistic { CH(1, 100); } ;
<adjective> =	stupid { CH(1, 70); } ;
<adjective> =	unpleasant { CH(1, 100); } ;
<adjective> =	lousy { CH(1, 70); } ;
<adjective> =	abusive { CH(1, 70); } ;
<adjective> =	bad { CH(1, 70); } ;
<adjective> =	selfish { CH(1, 70); } ;
<adjective> =	improper { CH(1, 60); } ;
<adjective> =	nasty { CH(1, 60); } ;
<adjective> =	disgusting { CH(1, 60); } ;
<adjective> =	foul { CH(1, 60); } ;
<adjective> =	intolerable { CH(1, 60); } ;
<adjective> =	primitive { CH(1, 60); } ;
<adjective> =	depressing { CH(1, 60); } ;
<adjective> =	dumb { CH(1, 60); } ;
<adjective> =	phoney { CH(1, 60); } ;
<adjective> =	as <adjective> "as a" <thing> { CH(1, 60); } ;
<adjective> =	"hungry like a wolf" { CH(1, 60); } ;
<adjective> =	<adjective> ;

<der-term> =	<adjective> <der-term> { CH(1, 30); } ;
<der-term> =	sexist { CH(1, 100); } ;
<der-term> =	weakling { CH(1, 80); } ;
<der-term> =	coward { CH(1, 80); } ;
<der-term> =	beast { CH(1, 100); } ;
<der-term> =	racist { CH(1, 80); } ;
<der-term> =	fool { CH(1, 80); } ;
<der-term> =	jerk { CH(1, 80); } ;
<der-term> =	ignoramus { CH(1, 80); } ;
<der-term> =	idiot { CH(1, 60); } ;
<der-term> =	"macho stud" { CH(1, 60); } ;
<der-term> =	rat { CH(1, 60); } ;
<der-term> =	slimebag { CH(1, 60); } ;
<der-term> =	Neanderthal { CH(1, 60); } ;
<der-term> =	sadist { CH(1, 60); } ;
<der-term> =	drunk { CH(1, 60); } ;
<der-term> =	capitalist { CH(1, 50); } ;
<der-term> =	dogmatist { CH(1, 50); } ;
<der-term> =	sheep { CH(1, 50); } ;
<der-term> =	maniac { CH(1, 50); } ;
<der-term> =	"whimpering scumbucket" { CH(1, 50); } ;
<der-term> =	"pea brain" { CH(1, 50); } ;
<der-term> =	"Illuminati scum" { CH(1, 50); } ;
<der-term> =	"quiche - eater" { CH(1, 50); } ;
<der-term> =	"real man" { CH(1, 50); } ;
<der-term> =	goof { CH(1, 50); } ;
<der-term> =	incompetent { CH(1, 50); } ;
<der-term> =	lunkhead { CH(1, 50); } ;
<der-term> =	<der-term> ;

<thing>	=	<adjective> <thing> { CH(1,30); } ;
<thing>	=	computer { CH(1,100); } ;
<thing>	=	abortion { CH(1,100); } ;
<thing>	=	whale { CH(1,100); } ;
<thing>	=	operation { CH(1,100); } ;
<thing>	=	"sexist joke" { CH(1,100); } ;
<thing>	=	ten-incher { CH(1,100); } ;
<thing>	=	dog { CH(1,60); } ;
<thing>	=	VAX { CH(1,60); } ;
<thing>	=	"Unix license" { CH(1,60); } ;
<thing>	=	"astrological sign" { CH(1,100); } ;
<thing>	=	"mental problem" { CH(1,100); } ;
<thing>	=	"sexual fantasy" { CH(1,100); } ;
<thing>	=	"venereal disease" { CH(1,60); } ;
<thing>	=	"Jewish grandmother" { CH(1,100); } ;
<thing>	=	"royal ancestry" { CH(1,100); } ;
<thing>	=	"punk haircut" { CH(1,100); } ;
<thing>	=	surfboard { CH(1,60); } ;
<thing>	=	"system call" { CH(1,60); } ;
<thing>	=	tatoo { CH(1,100); } ;
<thing>	=	"wood-burning stove" { CH(1,60); } ;
<thing>	=	"graphics editor" { CH(1,100); } ;
<thing>	=	"right wing death squad" { CH(1,60); } ;
<thing>	=	disease { CH(1,60); } ;
<thing>	=	impotence { CH(1,60); } ;
<thing>	=	vegetable { CH(1,60); } ;
<thing>	=	religon { CH(1,60); } ;
<thing>	=	duckpond { CH(1,60); } ;
<thing>	=	"wheat germ" { CH(1,60); } ;
<thing>	=	"bug fix" { CH(1,60); } ;
<thing>	=	lawyer { CH(1,60); } ;
<thing>	=	copywrite { CH(1,60); } ;
<thing>	=	<thing> ;

<group-adj> =	gay { CH(1, 70); } ;
<group-adj> =	old { CH(1, 100); } ;
<group-adj> =	lesbian { CH(1, 100); } ;
<group-adj> =	young { CH(1, 100); } ;
<group-adj> =	black { CH(1, 70); } ;
<group-adj> =	Polish { CH(1, 70); } ;
<group-adj> =	<adjective> { CH(1, 100); } ;
<group-adj> =	white { CH(1, 70); } ;
<group-adj> =	"mentally retarded" { CH(1, 100); } ;
<group-adj> =	swinging { CH(1, 100); } ;
<group-adj> =	European { CH(1, 100); } ;
<group-adj> =	homosexual { CH(1, 70); } ;
<group-adj> =	dead { CH(1, 70); } ;
<group-adj> =	underpriveledged { CH(1, 100); } ;
<group-adj> =	religous { CH(1, 70); } ;
<group-adj> =	<thing> "#-loving" { CH(1, 100); } ;
<group-adj> =	feminist { CH(1, 70); } ;
<group-adj> =	foreign { CH(1, 100); } ;
<group-adj> =	intellectual { CH(1, 100); } ;
<group-adj> =	crazy { CH(1, 70); } ;
<group-adj> =	working { CH(1, 70); } ;
<group-adj> =	"musically inclined" { CH(1, 100); } ;
<group-adj> =	psychadelic { CH(1, 100); } ;
<group-adj> =	"disco-loving" { CH(1, 100); } ;
<group-adj> =	unborn { CH(1, 100); } ;
<group-adj> =	Asian { CH(1, 100); } ;
<group-adj> =	short { CH(1, 100); } ;
<group-adj> =	<adjective> { CH(1, 50); } ;
<group-adj> =	poor { CH(1, 100); } ;
<group-adj> =	rich { CH(1, 100); } ;
<group-adj> =	"funny-looking" { CH(1, 100); } ;
<group-adj> =	"Puerto Rican" { CH(1, 100); } ;
<group-adj> =	Mexican { CH(1, 100); } ;
<group-adj> =	Italian { CH(1, 100); } ;
<group-adj> =	communist { CH(1, 70); } ;
<group-adj> =	Iranian { CH(1, 100); } ;
<group-adj> =	<group-adj> ;

<statement> =	your <thing> "is great" { CH(1, 100); } ;
<statement> =	<thing> "#s are fun" { CH(1, 60); } ;
<statement> =	<person> "is a " <der-term> { CH(1, 60); } ;
<statement> =	<group-adj> "people are" <adjective> { CH(1, 60); } ;
<statement> =	every <group-adj> "person is a" <der-term> { CH(1, 60); } ;
<statement> =	most <group-adj> "people have" <thing> "#s" { CH(1, 60); } ;
<statement> =	all <group-adj> "dudes should get" <thing> "#s" { CH(1, 60); } ;
<statement> =	<person> "is" <group-adj> { CH(1, 60); } ;
<statement> =	"trees are" <adjective> { CH(1, 100); } ;
<statement> =	"if you've seen one" <thing> ", you've seen them all" { CH(1, 100); } ;
<statement> =	"you're" <group-adj> { CH(1, 100); } ;
<statement> =	"you have a" <thing> { CH(1, 60); } ;
<statement> =	my <thing> "is pretty good" { CH(1, 60); } ;
<statement> =	"the Martians are coming" { CH(1, 100); } ;
<statement> =	"the National Enquirer is always right" { CH(1, 100); } ;
<statement> =	<person> "was" <group-adj> { CH(1, 60); } ;
<statement> =	<person> "#'s ghost is living in your" <thing> { CH(1, 60); } ;
<statement> =	"Liz Taylor is fat" { CH(1, 100); } ;
<statement> =	"you had 90 AP units" { CH(1, 100); } ;
<statement> =	"I'm pregnant" { CH(1, 100); } ;
<statement> =	"you look like a" <thing> { CH(1, 60); } ;
<statement> =	"the plural of moose is mooses" { CH(1, 100); } ;
<statement> =	"the oceans are full of dirty fish" { CH(1, 100); } ;
<statement> =	"people are dying every day" { CH(1, 100); } ;
<statement> =	a <group-adj> "man ain't got nothin in the world these days" { CH(1, 60); } ;
<statement> =	"women are inherently superior to men" { CH(1, 100); } ;
<statement> =	"the system staff is fascist" { CH(1, 100); } ;
<statement> =	"there is life after death" { CH(1, 100); } ;
<statement> =	"the world is full of" <der-term> "#s" { CH(1, 100); } ;
<statement> =	"you remind me of" <person> { CH(1, 60); } ;
<statement> =	"technology is evil" { CH(1, 60); } ;
<statement> =	"every day ya gotta write the book" { CH(1, 100); } ;
<statement> =	<person> killed <person> { CH(1, 60); } ;
<statement> =	"the CIA killed" <person> { CH(1, 100); } ;
<statement> =	"the sexual revolution is over" { CH(1, 100); } ;
<statement> =	"disco sucks" { CH(1, 100); } ;
<statement> =	"Lassie was" <group-adj> { CH(1, 60); } ;
<statement> =	"the Hari Krishnas have really got it all together"  { CH(1, 100); } ;
<statement> =	"I was" <person> "in a previous life" { CH(1, 60); } ;
<statement> =	"breathing causes cancer" { CH(1, 100); } ;
<statement> =	"it's fun to be really" <adjective> { CH(1, 60); } ;
<statement> =	<quality> "is pretty fun" { CH(1, 50); } ;
<statement> =	"you're a" <der-term> { CH(1, 50); } ;
<statement> =	the <group-adj> "culture is fascinating" { CH(1, 50); } ;
<statement> =	"when ya gotta go, ya gotta go" { CH(1, 50); } ;
<statement> =	"girls just wanna have fun" { CH(1, 50); } ;
<statement> =	<person> is <adjective> { CH(1, 50); } ;
<statement> =	<person> "#'s" <quality> is <adjective> { CH(1, 50); } ;
<statement> =	"it's a wonderful day" { CH(1, 50); } ;
<statement> =	"everything is really a" <thing> { CH(1, 50); } ;
<statement> =	"there's a" <thing> in <person> "#'s brain" { CH(1, 50); } ;
<statement> =	<person> "is a cool dude" { CH(1, 50); } ;
<statement> =	"the more" <thing> "#s you have, the better" { CH(1, 60); } ;
<statement> =	"life is a" <thing> { CH(1, 60); } ;
<statement> =	"life is" <quality> { CH(1, 60); } ;
<statement> =	<person> is <adjective> { CH(1, 40); } ;
<statement> =	<group-adj> "people are all" <adjective> <der-term> "#s" { CH(1, 50); } ;
<statement> =	<statement> ", and" <statement> { CH(1, 50); } ;
<statement> =	<statement> ", but" <statement> { CH(1, 50); } ;
<statement> =	"I wish I had a" <thing> { CH(1, 50); } ;
<statement> =	"you should have a" <thing> { CH(1, 50); } ;
<statement> =	"you hope that" <statement> { CH(1, 50); } ;
<statement> =	<person> "is secretly" <group-adj> { CH(1, 50); } ;
<statement> =	"you wish you were" <group-adj> { CH(1, 40); } ;
<statement> =	"you wish you were a" <thing> { CH(1, 40); } ;
<statement> =	"I wish I were a" <thing> { CH(1, 40); } ;
<statement> =	"you think that" <statement> { CH(1, 40); } ;
<statement> =	<statement> ", because" <statement> { CH(1, 20); } ;
<statement> =	<group-adj> "people don't get married to" <group-adj> "people, because" <reason1> { CH(1, 5); } ;
<statement> =	<group-adj> "people are all" <adjective> because <reason1> { CH(1, 5); } ;
<statement> =	<group-adj> "people are" <adjective> ", and" <reason1> { CH(1, 40); } ;
<statement> =	<statement> ;

<person> =	Reagan { CH(1, 100); } ;
<person> =	"Old Man River" { CH(1, 100); } ;
<person> =	JFK { CH(1, 100); } ;
<person> =	"the Pope" { CH(1, 100); } ;
<person> =	Gadaffi { CH(1, 100); } ;
<person> =	Napoleon { CH(1, 100); } ;
<person> =	"Karl Marx" { CH(1, 100); } ;
<person> =	"Groucho" { CH(1, 100); } ;
<person> =	"Wierd Al" { CH(1, 100); } ;
<person> =	"Michael Jackson" { CH(1, 100); } ;
<person> =	Caesar { CH(1, 100); } ;
<person> =	"the Demolition Man" { CH(1, 100); } ;
<person> =	Nietzsche { CH(1, 100); } ;
<person> =	Heidegger { CH(1, 100); } ;
<person> =	Aqualung { CH(1, 100); } ;
<person> =	"the Sierra club" { CH(1, 100); } ;
<person> =	"Henry Kissenger" { CH(1, 100); } ;
<person> =	Nixon { CH(1, 100); } ;
<person> =	"the Boogie Man" { CH(1, 100); } ;
<person> =	Prince { CH(1, 100); } ;
<person> =	<person> ;

<reason1> =	"they don't want their children to grow up to be too lazy to steal" { CH(1, 20); } ;
<reason1> =	"they can't tell them apart from" <group-adj> "dudes" { CH(1, 20); } ;
<reason1> =	"they're too" <adjective> { CH(1, 20); } ;
<reason1> =	<person> "wouldn't have done it" { CH(1, 20); } ;
<reason1> =	"they can't spray paint that small" { CH(1, 20); } ;
<reason1> =	"they don't have" <thing> "#s" { CH(1, 20); } ;
<reason1> =	"they don't know how" { CH(1, 20); } ;
<reason1> =	<reason1> ;

!Funky!Stuff!

faustus@ucbcad.UUCP (Wayne A. Christopher) (05/11/85)

I am posting the source for a few programs I wrote some time
ago to generate random insults, flames, and sentences. They
are written using a pre-processor called "kafka", which is
also included. To create them collect all the parts of this
posting, pipe them to sh, then run "make".

	Wayne

echo x - insult.k
cat >insult.k <<'!Funky!Stuff!'
%{

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Insult -- a program to generate nasty insults. This is a kafka source file.
 *	Compile with etc.c, output.c, and maketext.c
 */

#include <stdio.h>
#include <ctype.h>

#define CH(n, o)	return (((rnum() % o) < n) ? 1 : 0)

rnum()
{
	return (random());
}

char *ones;

#define YOUR	ones = "your"
#define MY	ones = "my"
#define HIS	ones = "his"

/* Instead of defining all these words as rules, keep arrays of them. We
 * can also make the insults more interesting by using alliteration on
 * the words...
 */

char *words1[] = { 	/* Animals. */
	"aardvark",
	"amphibian",
	"animal",
	"ant",
	"apteryx",
	"bird",
	"buzzard",
	"cat",
	"cockroach",
	"cow",
	"dodo",
	"dog",
	"duck",
	"emu",
	"fish",
	"flea",
	"frog",
	"gazelle",
	"gerbil",
	"goat",
	"goose",
	"grep",
	"haddock",
	"hippotomus",
	"hog",
	"horse",
	"insect",
	"jackal",
	"kitten",
	"kobold",
	"leech",
	"louse",
	"milkweed",
	"monkey",
	"moose",
	"mouse",
	"octopus",
	"penguin",
	"pig",
	"pigeon",
	"puppy",
	"racoon",
	"rat",
	"rust monster",
	"sheep",
	"skunk",
	"slime-mold",
	"slug",
	"snail",
	"snake",
	"squid",
	"toad",
	"tuna",
	"turkey",
	"turtle",
	"weed",
	"whale",
	"wombat",
	"worm",
	"yak",
	NULL
} ;

char *words2[] = {	/* Derogatory terms. */
	"airhead",
	"axe murderer",
	"beer", 
	"bug-breath",
	"bum",
	"cookie",
	"creep",
	"cretin",
	"crud",
	"deviate",
	"dink",
	"dipstick",
	"dirt",
	"dork",
	"dude",
	"dumbbell",
	"fairy",
	"fleabag",
	"fruit",
	"garbage",
	"geek",
	"gimp",
	"glob",
	"gloop",
	"goober",
	"goof",
	"grunt",
	"gump",
	"hag",
	"idiot",
	"ignoramus",
	"inanimate object",
	"jerk",
	"lark's vomit",
	"lump",
	"lunkhead",
	"monster",
	"mudface",
	"mudpie",
	"muscle-brain",
	"nasty",
	"numskull",
	"nymphomaniac",
	"pervert",
	"pinhead",
	"plant",
	"plebe",
	"quiche-eater",
	"rat spit",
	"redneck",
	"scary dude",
	"scum that grows on the bottom of the lake",
	"scum",
	"septic tank",
	"slob",
	"super geek",
	"toady",
	"vegetable",
	"weight-lifter",
	"welfare mother",
	"wonderful, sensitive human being",
	NULL
} ;

char *words3[] = {	/* Body parts. */
	"behind",
	"brain",
	"crotch",
	"ear",
	"eye",
	"face",
	"liver",
	"nose",
	"pancreas",
	"private parts",
	"rectum",
	"stomach",
	NULL
} ;

char *words4[] = {	/* Objects. */
	"VAX",
	"baseball bat",
	"big thing",
	"boulder",
	"brick",
	"car",
	"heavy object",
	"knife",
	"manhole cover",
	"needle",
	"object",
	"rock",
	"sword",
	"terminal",
	"tree",
	"truck",
	"two by four",
	NULL
} ;

char *words5[] = {	/* Adjectives. */
	"Lovecraftian",
	"abnormal",
	"absurd",
	"awful",
	"bad",
	"bootlicking",
	"brainless",
	"cowardly",
	"crude",
	"dastardly",
	"dirty",
	"diseased",
	"disgusting",
	"disobedient",
	"dopey",
	"dumb",
	"elitist",
	"evil",
	"fat",
	"flabby",
	"foolish",
	"foul",
	"frightening",
	"funny",
	"furry",
	"green",
	"gruesome",
	"gumpy",
	"hairy",
	"hideous",
	"horrifying",
	"icky",
	"ignorant",
	"imaginary",
	"intolerable",
	"lousy",
	"ludicrous",
	"lumpy",
	"mangy",
	"muddy",
	"nauseating",
	"nauseating",
	"old",
	"pencil-necked",
	"perverted",
	"ratty",
	"religous",
	"ridiculous",
	"rotten",
	"scab-picking",
	"scummy",
	"sick",
	"silly",
	"skinny",
	"slimy",
	"slippery",
	"slobbering",
	"slow",
	"small",
	"smelly",
	"strange",
	"stupid",
	"trashy",
	"ugly",
	"undesirable",
	"unhappy",
	"unpleasant",
	"unspeakable",
	"unstructured",
	"uppity",
	"vile",
	"worthless",
	NULL
} ;

char *words6[] = {	/* Adverbs. */
	"disgustingly",
	"incredibly",
	"mega",
	"microscopically",
	"paradoxically",
	"phenomenally",
	"pseudo",
	"rather",
	"ridiculously",
	"semi",
	"slightly",
	"stupidly",
	"surprisingly",
	"terribly",
	"typically",
	"unbeliveably",
	NULL
} ;

char *words7[] = {	/* Nasty things. */
	"abuse",
	"annihilate",
	"avoid",
	"behead",
	"chop up",
	"damage",
	"destroy",
	"discriminate against",
	"disembowel",
	"dismember",
	"dissect",
	"eat",
	"flush",
	"forget about",
	"frighten",
	"hit",
	"ignore",
	"insult",
	"kick",
	"look at",
	"molest",
	"mush",
	"puree",
	"scramble",
	"shred",
	"spit on",
	"squish",
	"stab",
	"step on",
	NULL
} ;

char *words8[] = {	/* Diseases. */
	"bad breath",
	"gout",
	"leprosy",
	"malaria",
	"plague",
	NULL
} ;

char *lastchoice = NULL;

getword(type)
{
	char **wds;
	int i = 0, j = 0, k;
	int alliterate = lastchoice ? (random() % 4) : 0;

	switch (type) {
		case 1: wds = words1; break;
		case 2: wds = words2; break;
		case 3: wds = words3; break;
		case 4: wds = words4; break;
		case 5: wds = words5; break;
		case 6: wds = words6; break;
		case 7: wds = words7; break;
		case 8: wds = words8; break;
		default: fprintf(stderr, "Bad thing %d\n", type);
	}

	/* See how many words there are that we can use. */
	for (k = 0; wds[k]; k++) {
		if (alliterate && (*wds[k] == *lastchoice))
			j++;
	}
	i = k;
	if (j == 0) {
hoho:
		i = rnum() % i;
		lastchoice = wds[i];
		return ((int) wds[i]);
	} else {
		j = rnum() % j;
		for (k = 0; ; k++)
			if (*wds[k] == (isupper(*lastchoice) ?
					tolower(*lastchoice) : *lastchoice)) {
				if (wds[k] == lastchoice)
					goto hoho;
				if (j == 0) {
					lastchoice = wds[k];
					return ((int) wds[k]);
				} else
					j--;
			}
	}
}

/* Word types. */

#define ANIMAL		1
#define DER_TERM	2
#define BODYPART	3
#define OBJECT		4
#define ADJ		5
#define ADVERB		6
#define NASTY_THING	7
#define DISEASE		8

%}

%%

<start>		= <invective> ;

<invective>	= you <der-term> <ep> 	{ CH(1, 20); } ;
<invective>	= <action> <ep> 	{ YOUR; CH(1, 20); } ;
<invective>	= "why you" <der-term> , <invective> 	{ YOUR; CH(1, 20); } ;
<invective>	= "you just make me" <adj> <pp> 	{ YOUR; CH(1, 20); } ;
<invective>	= "you're a perfect example of a" <der-term> <pp> 	{ YOUR; CH(1, 20); } ;
<invective>	= "you make me want to" <action> <pp> 	{ YOUR; CH(1, 25); } ;
<invective>	= <exclam> <ep> 	{ MY; CH(1, 20); } ;
<invective>	= "you make me want to" <action> <pp> 	{ MY; CH(1, 30); } ;
<invective>	= "why don't you" <action> <qp> 	{ YOUR; CH(1, 25); } ;
<invective>	= "I'd like to" <nasty-thing> you <ep> 	{ CH(1, 30); } ;
<invective>	= "you should" <action> <pp> 	{ YOUR; CH(1, 25); } ;
<invective>	= "I wish you'd" <action> <pp> 	{ YOUR; CH(1, 25); } ;
<invective>	= "why don't you" <action> <qp> 	{ YOUR; CH(1, 25); } ;
<invective>	= "you could make a" <animalp> <action> <pp> 	{ HIS; CH(1, 40); } ;
<invective>	= go <action> <pp> 	{ YOUR; CH(1, 20); } ;
<invective>	= "do me a favor," <der-term> ", and" <action> <pp> { YOUR; CH(1, 35); } ;
<invective>	= "you resemble a" <animalp> <pp> { CH(1,25); } ;
<invective>	= "make the world a better place and" <action> <pp> { YOUR; CH(1,40); } ;
<invective>	= "why you" <der-term> , <invective>  { CH(1,30); } ;
<invective>	= "I used to know a" <der-term> "just like you" <pp> { CH(1,40); } ;
<invective>	= <der-term> <ep> { CH(1,25); } ;
<invective>	= "are you a" <der-term> ", or just a" <der-term> <qp> { CH(1, 40); } ;
<invective>	= <exclam> ", you're a" <der-term> <ep> { CH(1, 40); } ;
<invective>	= "you're just such a" <der-term> <pp> { CH(1,20); } ;
<invective>	= "you should" <nasty-thing> yourself <pp> { CH(1,35); } ;
<invective>	= "you're so" <adj> <pp> { CH(1,20); } ;
<invective>	= "oh, go" <action> <ep> { YOUR; CH(1,20) ; } ;
<invective>	= hey, <der-term> <pp> "Yeah, you!" { CH(1,20) ; } ;
<invective>	= get <disease> <pp> { CH(1, 20); } ;
<invective>	= "you look like you would" <action> <pp> { YOUR; CH(1, 20); } ;
<invective>	= "you look like you would" <action> <pp> { MY; CH(1, 20); } ;
<invective>	= "what a" <der-term> "you are" <ep> { CH(1, 20); } ;
<invective>	= "you must really be a" <animalp> <pp> { CH(1, 20); } ;
<invective>	= "even a" <animalp> "would want you to" <action> <pp> { HIS; CH(1, 20); } ;
<invective>	= "you're even more" <adj> "than a" <der-term> <ep> { CH(1, 20); } ;
<invective>	= "if I were you I'd" <action> <pp> { MY; CH(1, 30); } ;
<invective>	= "oh, I get it, you're a" <der-term> <pp> { CH(1, 30); } ;
<invective>	= "why don't you just" <action> "and get it over with" <qp> { YOUR; CH(1, 20); } ;
<invective>	= "you look like a" <thing> <pp> { CH(1, 20); } ;
<invective>	= "I don't know about you" <pp> { CH(1, 20); } ;
<invective>	= "hey," <exclam> "," <action> <ep> { YOUR; CH(1, 20); } ;
<invective>	= "whenever I" <action> "it gives me" <disease> <pp> { YOUR; CH(1, 20); } ;
<invective>	= "I wonder why" <invective> { CH(1, 20); } ;
<invective>	= "you make me want to become" <adj> ", you know" <qp> { CH(1, 20); } ;
<invective>	= <exclam> "," <invective> { CH(1, 20); } ;
<invective>	= "if only you were a" <der-term> <pp> { CH(1, 20); } ;
<invective>	= <invective> ;

<thing>		= <noun> ;

<animalp>	= <adjp> <animal> { CH(1, 3); } ;
<animalp>	= <animal> ;

<animal>	= { return (getword(ANIMAL)); } ;

<der-term>	= <adjp> <der-term-1>	{ CH(1, 3); } ;
<der-term>	= <der-term-1> ;

<der-term-1>	= <animalp> { CH(1, 4) ; } ;
<der-term-1>	= <animalp> "#'s " <bodypart> { CH(1, 10); } ;
<der-term-1>	= <adj> "#ness" { CH(1, 10) ; } ;
<der-term-1>	= <der-term> squad { CH(1, 25) ; } ;
<der-term-1>	= "son of a" <der-term> { CH(1, 25) ; } ;
<der-term-1>	= <bodypart> { CH(1, 25) ; } ;
<der-term-1>	= <der-term> "#y" <der-term> { CH(1, 25) ; } ;
<der-term-1>	= <bodypart> { CH(1, 25) ; } ;
<der-term-1>	= <adj> "#ness" { CH(1, 25) ; } ;
<der-term-1>	= <der-term-x> ;

<der-term-x>	= { return (getword(DER_TERM)); } ;

<bodypart>	= <adjp> <bodypart> { CH(1, 10) ; } ;
<bodypart>	= <bodypart-x> ;

<bodypart-x>	= { return (getword(BODYPART)); } ;

<object>	= <animalp> { CH(1, 5); } ;
<object>	= "pile of" <thing> "#s" { CH(1, 15); } ;
<object>	= "bunch of" <thing> "#s" { CH(1, 15); } ;
<object>	= <object-x> ;

<object-x>	= { return (getword(OBJECT)); } ;

<adjp>		= <adverb> <adj>	{ CH(1, 10); } ;
<adjp>		= <adj> <adj> { CH(1, 10) ; } ;
<adjp>		= <adj>	;

<adj>		= <animal> "#-infested" { CH(1, 40) ; } ;
<adj>		= <animal> "#ish" { CH(1, 40) ; } ;
<adj>		= <noun> "#-loving" { CH(1, 40) ; } ;
<adj>		= <noun> "#-eating" { CH(1, 40) ; } ;
<adj>		= <noun> "#like" { CH(1, 40) ; } ;
<adj>		= <disease> "#-infested" { CH(1, 40) ; } ;
<adj>		= <animal> <bodypart> "#ed" { CH(1, 40) ; } ;
<adj>		= <adj-x> ;

<adj-x>		= { return (getword(ADJ)); } ;

<adverb>	= <adj> "#ly" { CH(1, 50) ; } ;
<adverb>	= <adverb-x> ;

<adverb-x>	= { return (getword(ADVERB)); } ;

<nasty-thing>	= <nasty-thing-x> ;

<nasty-thing-x>	= { return (getword(NASTY_THING)); } ;

<disease>	= { return (getword(DISEASE)); } ;

<noun>		= <animal>	{ CH(2, 3); } ;
<noun>		= <object> ;

<action>	= eat a <thing>  { CH(1, 30) ; } ;
<action>	= lick a <animalp> { CH(1, 30) ; } ;
<action>	= lick a <animalp> "#'s" <bodypart> { CH(1, 30) ; } ;
<action>	= <nasty-thing> a <animalp> "#'s" <bodypart> { CH(1, 30) ; } ;
<action>	= "have sex with a" <animalp> { CH(1, 30) ; } ;
<action>	= die { CH(1, 30) ; } ;
<action>	= become a <der-term>  { CH(1, 30) ; } ;
<action>	= <nasty-thing> <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= "go out and meet a nice" <der-term> { CH(1, 30) ; } ;
<action>	= "adopt a" <animalp> { CH(1, 30) ; } ;
<action>	= become <adj> { CH(1, 30) ; } ;
<action>	= vomit { CH(1, 30) ; } ;
<action>	= "gag on a" <object> { CH(1, 30) ; } ;
<action>	= stick a <object> in <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= stick a <object> up <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= "cut off" <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= "make somebody happy and" <action> { CH(1, 30); } ;
<action>	= "live with a" <thing> { CH(1, 30) ; } ;
<action>	= put a <thing> in <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= die  { CH(1, 30) ; } ;
<action>	= "admit that you're" <adj>  { CH(1, 30) ; } ;
<action>	= "blow up" <ones> house  { CH(1, 30) ; } ;
<action>	= remove <ones> files  { CH(1, 30) ; } ;
<action>	= "sleep on the freeway"  { CH(1, 30) ; } ;
<action>	= take <adj> "lessons from a" <thing> { CH(1, 30) ; } ;
<action>	= "realize how" <adj> "you are"  { CH(1, 30) ; } ;
<action>	= relocate <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= "crawl under a" <object> { CH(1, 30) ; } ;
<action>	= pick <ones> <bodypart> { CH(1, 30) ; } ;
<action>	= "go blind" { CH(1, 30) ; } ;
<action>	= make <ones> <bodypart> <adj> { CH(1, 30) ; } ;
<action>	= "go away" { CH(1, 30) ; } ;
<action>	= "get a" <animalp> to <action> { CH(1, 30) ; } ;
<action>	= get <disease> { CH(1, 30) ; } ;
<action>	= "make a" <animalp> get <disease> { CH(1, 30) ; } ;
<action>	= stick <ones> <bodypart> "in a" <thing> { CH(1, 30) ; } ;
<action>	= <action> and <action> { CH(1, 10); } ;
<action>	= <action> ;

<exclam>	= "oh god"	{ CH(1, 10); } ;
<exclam>	= "wow, man"	{ CH(1, 10); } ;
<exclam>	= goodness	{ CH(1, 10); } ;
<exclam>	= "ah say"	{ CH(1, 10); } ;
<exclam>	= "ain't it the truth"	{ CH(1, 10); } ;
<exclam>	= <adj> <thing> "#s"	{ CH(1, 10); } ;
<exclam>	= gosh	{ CH(1, 10); } ;
<exclam>	= "land 'o goshens"	{ CH(1, 10); } ;
<exclam>	= well, <nasty-thing> <ones> <bodypart>	{ CH(1, 10); } ;
<exclam>	= "lemme tell ya" { CH(1, 10); } ;
<exclam>	= "sure as day"	{ CH(1, 10); } ;
<exclam>	= shoot	{ CH(1, 10); } ;
<exclam>	= sheeeit { CH(1, 10); } ;
<exclam>	= "hot puppies" { CH(1, 10); } ;
<exclam>	= well, <exclam> { CH(1, 10); } ;
<exclam>	= <exclam> ;

<pp>		= . { lastchoice = NULL; return (1); } ;
<ep>		= ! { lastchoice = NULL; return (1); } ;
<qp>		= ? { lastchoice = NULL; return (1); } ;

<ones>		= { return ((int) ones); } ;

!Funky!Stuff!
echo x - defs.h
cat >defs.h <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 */

#define STACKSIZE	1024
#define HASHSIZE 	256

/* Stack elements for the generator machine. */

struct kkelt {
	struct kknode *ke_node;
	struct kcarc *ke_arc;
};

!Funky!Stuff!
echo x - graph.h
cat >graph.h <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Definitions for the nodes of directed graphs used by 
 * kafka. A set of rules for a given non-term is represented 
 * as a list of rule definitions. A rule definition is
 * represented as a list of arcs to other non-terminals or
 * arcs containing terminal strings, or in the case of 
 * computed terminals, a pointer to a function that returns
 * a pointer to the computed terminal (note that the function should
 * cast the pointer to an int before returning it if it doesn't
 * want complains from the compiler) .
 * Rules are tried in turn until the kn_func of one suceeds,
 * in which case either the rule is used or the value of the
 * kn_func is used as the terminal value, if the node being left
 * is of type KTCOMP. It is an error for none of the kn_funcs
 * to succeed. Note that knode is the first form of the graph
 * nodes, used when the specification is being parsed, and
 * kknode is the final form used in the actual program generated 
 * (likewise for karc and kcarc) .
 */

#define SSIZE	100	/* Max size of terminals and nonterms.  */

struct knode {
	int kn_type;		/* See below. */
	char kn_nodename[SSIZE];/* Terminal or non-term. */
	struct karc *kn_arc;	/* Pointer to list of arcs. */
	struct knode *kn_next;	/* Next rule for this non-term. */
	struct knode *kn_nnt;	/* Next non-term. */
	int kn_fnum;		/* The id number of the function. 0 if none. */
	int kn_nodenumber;	/* The (unique) id number of this node. */
};

/* This isn't too hot, but we are lazy... */

struct kknode {
	int kk_type;		/* See below. */
	char *kk_nodename;	/* Terminal or non-term. */
	struct kcarc *kk_arc;	/* Pointer to list of arcs. */
	struct kknode *kk_next;	/* Next rule for this non-term. */
	int (*kk_func)();	/* Pointer to associated function. */
	struct kknode *kk_link;	/* Overall node list. */
};

struct karc {
	struct karc *ka_narc;	/* Link. */
	struct knode *ka_to;	/* Thing pointed to. */
	char ka_toname[SSIZE];	/* Name of node pointed to. */
	int ka_type;		/* Type of thing pointed to. */
	int ka_arcnumber;	/* The unique id of this arc. */
};

struct kcarc {
	char *kc_toname;	/* Only terminal names. */
	struct kknode *kc_to;	/* Node pointed to. */
	struct kcarc *kc_narc;	/* Link. */
};

#define KTTERM	1	/* kn_arc and kn_next will be NULL. */
#define KTNTERM	2	/* Non-terminal. */
#define KTCOMP	3	/* Computed terminal. kn_arc->ka_func will
			 * be used to decide what the value of the
			 * terminal will be.
			 */

!Funky!Stuff!
echo x - kafgraf.h
cat >kafgraf.h <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Definitions for the nodes of directed graphs used by 
 * kafka. A set of rules for a given non-term is represented 
 * as a list of rule definitions. A rule definition is
 * represented as a list of arcs to other non-terminals or
 * arcs containing terminal strings, or in the case of 
 * computed terminals, a pointer to a function that returns
 * a pointer to the computed terminal (note that the function should
 * cast the pointer to an int before returning it if it doesn't
 * want complains from the compiler) .
 * Rules are tried in turn until the kn_func of one suceeds,
 * in which case either the rule is used or the value of the
 * kn_func is used as the terminal value, if the node being left
 * is of type KTCOMP. It is an error for none of the kn_funcs
 * to succeed. Note that knode is the first form of the graph
 * nodes, used when the specification is being parsed, and
 * kknode is the final form used in the actual program generated 
 * (likewise for karc and kcarc) .
 */

#define SSIZE	100	/* Max size of terminals and nonterms.  */

struct knode {
	int kn_type;		/* See below. */
	char kn_nodename[SSIZE];/* Terminal or non-term. */
	struct karc *kn_arc;	/* Pointer to list of arcs. */
	struct knode *kn_next;	/* Next rule for this non-term. */
	struct knode *kn_nnt;	/* Next non-term. */
	int kn_fnum;		/* The id number of the function. 0 if none. */
	int kn_nodenumber;	/* The (unique) id number of this node. */
};

struct kknode {
	int kk_type;		/* See below. */
	char *kk_nodename;	/* Terminal or non-term. */
	struct kcarc *kk_arc;	/* Pointer to list of arcs. */
	struct kknode *kk_next;	/* Next rule for this non-term. */
	int (*kk_func)();	/* Pointer to associated function. */
	struct kknode *kk_link;	/* Overall node list. */
};

struct karc {
	struct karc *ka_narc;	/* Link. */
	struct knode *ka_to;	/* Thing pointed to. */
	char ka_toname[SSIZE];	/* Name of node pointed to. */
	int ka_type;		/* Type of thing pointed to. */
	int ka_arcnumber;	/* The unique id of this arc. */
};

struct kcarc {
	char *kc_toname;	/* Only terminal names. */
	struct kknode *kc_to;	/* Node pointed to. */
	struct kcarc *kc_narc;	/* Link. */
};

#define KTTERM	1	/* kn_arc and kn_next will be NULL. */
#define KTNTERM	2	/* Non-terminal. */
#define KTCOMP	3	/* Computed terminal. kn_arc->ka_func will
			 * be used to decide what the value of the
			 * terminal will be.
			 */

!Funky!Stuff!
echo x - dstrans.c
cat >dstrans.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 * This routine takes the data structures which have been created by the
 * parser and creates a file called "kaf.spec.c", with all the appropriate
 * source in it. Each node in the structure is given a unique name, and 
 * all links between these are made explicit here. Also all nodes are
 * linked together in a list, for the purpose of searching for names.
 */

#include "kafgraf.h"
#include "defs.h"
#include <stdio.h>

extern struct knode *hashtab[];
extern FILE *specp;		/* The file to output to. */
int errp = 0;

dstrans() 
{
	struct knode *nt, *wk, *lf;
	struct karc *tarc;
	int a;
	char *it;			/* Temp char *. */
	unsigned char b, phash();	/* For lookup of node names. */
	char lastnode[32];

	/* dumpdata(); Diagnostic. */

	/* First we have to resolve all references to nodes. Match
	 * ka_toname with the apropriate lists of nodes.
	 */
	
	for (a = 0; a < HASHSIZE; a++) {
	    for (nt = hashtab[a]; nt != NULL; nt = nt->kn_nnt) {
		for (wk = nt; wk != NULL; wk = wk->kn_next) {
		    for (tarc = wk->kn_arc; tarc != NULL; tarc = tarc->ka_narc) {
			if (tarc->ka_type != KTNTERM)
			    tarc->ka_to = NULL;	
			else {
			    it = tarc->ka_toname;
			    b = phash(it);
			    lf = NULL;
			    for (lf = hashtab[b]; lf != NULL; lf = lf->kn_nnt)
				if (!strcmp(it, lf->kn_nodename)) {
				    tarc->ka_to = lf;
				    break;
				}
			    if (lf == NULL) {
				fprintf(stderr, "Error: no such node: %s\n", it);
				errp = 1;
			    }
			}
		    }
		}
	    }
	}
	if (errp) {
		fprintf(stderr, "kafka aborted due to errors\n");
		exit(1);
	}

	/* All references are cool now. The working data structure is now
	 * to be built, with the difference that there is no hashing involved
	 * as everything is held together by the arcs. 
	 */

	strcpy(lastnode, "0");
	
	for (a = 0; a < HASHSIZE; a++) {
	    for (nt = hashtab[a]; nt != NULL; nt = nt->kn_nnt) {
		for (wk = nt; wk != NULL; wk = wk->kn_next) {
		    /* Write this node out. This is ugly... */
		    if (wk->kn_arc)
			fprintf(specp, "extern struct kcarc _kka%d;\n", 
			    wk->kn_arc->ka_arcnumber);
		    if (wk->kn_next)
			fprintf(specp, "extern struct kknode _kkn%d;\n",
			    wk->kn_next->kn_nodenumber);
		    if (wk->kn_fnum)
			fprintf(specp, "extern int _kkFunc%d();\n",
			    wk->kn_fnum);
		    fprintf(specp, "struct kknode _kkn%d = { ", wk->kn_nodenumber);
		    fprintf(specp, "%d, ", wk->kn_type);
		    if (wk->kn_nodename)
			fprintf(specp, "\"%s\", ",
			    wk->kn_nodename);
		    else
			fprintf(specp, "0, ");
		    if (wk->kn_arc)
		    	fprintf(specp, "&_kka%d, ", wk->kn_arc->ka_arcnumber);
		    else
			fprintf(specp, "0, ");
		    if (wk->kn_next)
		    	fprintf(specp, "&_kkn%d, ", wk->kn_next->kn_nodenumber);
		    else
			fprintf(specp, "0, ");
		    if (wk->kn_fnum)
		        fprintf(specp, "_kkFunc%d, ",
			    wk->kn_fnum);
		    else
			fprintf(specp, "0, ");
		    fprintf(specp, "%s };\n", lastnode);
		    sprintf(lastnode, "&_kkn%d", wk->kn_nodenumber);
		    if (wk->kn_arc) {
			for (tarc = wk->kn_arc; tarc != NULL; tarc = tarc->ka_narc) {
			    if (tarc->ka_to)
				fprintf(specp, "extern struct kknode _kkn%d;\n",
				    tarc->ka_to->kn_nodenumber);
			    if (tarc->ka_narc)
				fprintf(specp, "extern struct kcarc _kka%d;\n",
				    tarc->ka_narc->ka_arcnumber);
			    fprintf(specp, "struct kcarc _kka%d = { ", 
				tarc->ka_arcnumber);
			    fprintf(specp, "\"%s\", ", tarc->ka_toname);
			    if (tarc->ka_type == KTNTERM)
			    	fprintf(specp, "&_kkn%d, ",
				    tarc->ka_to->kn_nodenumber);
			    else
				fprintf(specp, "0, ");
			    if (tarc->ka_narc)
			    	fprintf(specp, "&_kka%d };\n", 
				    tarc->ka_narc->ka_arcnumber);
			    else	/* Oops { */
				fprintf(specp, "0 };\n");
			}
		    }
		}
	    }
	}
	fprintf(specp, "struct kknode *nodelist = %s;\n\n", lastnode);

	/* All the necessary information for the structure is now in place. */
}

/* Diagnostic routine. */

dumpdata()
{

	int hpos;
	struct knode *nont, *rule;
	struct karc *arc;

	for (hpos = 0; hpos < HASHSIZE; hpos++) {
		printf("Hashtab entry %d:\n", hpos);
		if (hashtab[hpos] == NULL) 
			printf("\t(empty)\n");
		else
			for (nont = hashtab[hpos]; nont != NULL; 
			    nont = nont->kn_nnt) {
				printf("\tNonterminal: %s\n", nont->kn_nodename);
				for (rule = nont; rule != NULL; 
				    rule = rule->kn_next) {
					printf("Rule: ");
					for (arc = rule->kn_arc; arc != NULL; 
					    arc = arc->ka_narc)
						printf("%s ", arc->ka_toname);
					putchar('\n');
				}
			}
	}
}

!Funky!Stuff!

faustus@ucbcad.UUCP (Wayne A. Christopher) (05/11/85)

I am posting the source for a few programs I wrote some time
ago to generate random insults, flames, and sentences. They
are written using a pre-processor called "kafka", which is
also included. To create them collect all the parts of this
posting, pipe them to sh, then run "make".

	Wayne

echo x - etc.c
cat >etc.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Some useful things.
 */

#include <stdio.h>

#define DEFAULT 3

int nflag = 0;

main(ac, av)
char **av;
{
	/* The main function for babble. */

	int i, j;
	extern int lpos;

	srandom(getpid());

	if (ac > 1) {
		j = atoi(av[1]);
		if (j < 0) {
			j = -j;
			nflag = 1;
		}
		if (j == 0) {
			for (i = 0; i < 100; i++) {
				maketext("start");
				kkoutput("@");
				lpos = 0;
				putchar('\n');
				putchar('\n');
			}
			exit(0);
		}
		for (i = 0; i < j; i++) {
			maketext("start");
			kkoutput("@");
		}
		putchar('\n');
		exit(0);
	}
	i = DEFAULT;
	while (i--) {
		srandom(random());
		maketext("start");
		kkoutput("@");
	}
	putchar('\n');
	exit(0);
}


!Funky!Stuff!
echo x - funwords.c
cat >funwords.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 */

#include <stdio.h>
#define maxlen 8

char rword[20];
char vow[] = {'a','e','i','o','u','y'};
char con[] = {'t','n','s','h','r','d','l','b','c','f','g','j','k',
                'm','p','w','v','z','x','q'};
char dip[][2] = {'t','h','s','h','s','s','r','d','q','u',
                   'l','l','r','n','s','p','s','t','r','z'};
char *fword()
{
	char nl, a, b, c, d;

	nl = (rand() % maxlen + rand() % maxlen)/2 + 1;
	for (b = 0; b < nl; ){
		switch (rand() % 8) {
			case 0 :
			case 1 :
			case 2 :
			case 3 :
			case 4 :
			case 5 :
			case 6 :
				rword[b++] = con[abs(rand() % 20 + rand() %
					20 - 20)]; 
				break;
			case 7:
				c = abs(rand() % 10 + rand() % 10 - 10);
				rword[b++] = dip[c][0];
				rword[b++] = dip[c][1];
				break;
		}
		rword[b++] = vow[abs(rand() % 6 + rand() % 6 - 6) ];
	}
	if (rand() % 10 < 7)rword[b++] = con[rand() % 20];
	rword[b++]='\0';
	return (rword);
}


main() {

	char *fword();

	srand(getpid());
	printf ("%s\n",fword());
}

!Funky!Stuff!
echo x - init.c
cat >init.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 */

#include <stdio.h>

FILE *textp, *specp, *inp;
extern char *sourcefile;

init()
{
	/* These should be only defaults here... */

	if ((textp = fopen("kaf.text.c", "w")) == NULL) {
		perror("kaf.text.c");
		exit(1);
	}
	if ((specp = fopen("kaf.spec.c", "w")) == NULL) {
		perror("kaf.spec.c");
		exit(1);
	}
	if (!sourcefile)
		inp = stdin;
	else
		if ((inp = fopen(sourcefile, "r")) == NULL) {
			perror(sourcefile);
			exit(1);
		}
	fprintf(textp, "/* The user routine file. */\n\n");
	fprintf(specp, "/* The specification file. */\n\n");
	fprintf(specp, "#include \"kafgraf.h\"\n\n");
	return (0);
}

!Funky!Stuff!
echo x - main.c
cat >main.c <<'!Funky!Stuff!'
/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * The kafka main function. Usage: kafka [sourcefile] [-v].
 */

#include <stdio.h>

#define USAGE { printf("Usage: kafka [sourcefile] [-v].\n"); exit(1); }

int vflag = 0;
char *sourcefile = NULL;

main(ac, av)
char **av;
{
	int ch;

	for (ch = 1; ch < ac; ch++) {
		if (!strcmp(av[ch], "-v")) {
			vflag++;
			continue;
		}
		if (!strcmp(av[ch], "-t")) {
			/* Do textfile option. (Unimplemented...) */
			ch++;
			continue;
		}
		if (!strcmp(av[ch], "-s")) {
			/* Do specfile option. (Unimplemented...) */
			ch++;
			continue;
		}
		/* Sourcefile. */
		if (sourcefile)
			USAGE;
		sourcefile = av[ch];
	}
	if (!sourcefile) 
		USAGE;

	/* Set up the files, */
	init();

	/* read in the information, */
	yyparse();

	/* and write it out. */
	dstrans();

	/* That's all... */
	exit(0);
}

/* The error handler. This could use work. */

yyerror()
{
	extern int lineno, errp;

	fprintf(stderr, "Syntax error in line %d.\n", lineno);
	fflush(stderr);
	errp = 1;
}

!Funky!Stuff!
echo x - maketext.c
cat >maketext.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 */

#include <stdio.h>
#include "kafgraf.h"
#include "defs.h"

struct kkelt kkstack[STACKSIZE];	/* The stack. */
struct kkelt *kksp;			/* The stack pointer. */
extern struct kknode *start;
extern struct kknode *nodelist;


/* This routine is the one that generates a string in the grammer,
 * beginning with the non-terminal s. Returns -1 if s is not the
 * name of a non-terminal.
 */

maketext(s)
char *s;
{
	struct kknode *stnode, *kknn;
	int kkcv;

	/* First find the start node. */

	/* dumpnlist();	Diagnostic. */

	for (stnode = nodelist; stnode != NULL; stnode = stnode->kk_link)
		if (!strcmp(stnode->kk_nodename, s))
			break;
	if (stnode == NULL) {
		/* Error condition. */
		return (-1);
	}

	/* Now to generate the text. The generator works like this: first
	 * select one of the rules for the given non-terminal to follow.
	 * If the non-terminal is actually a computed terminal, compute
	 * the value and output it. Otherwise, then push a pointer to the 
	 * it onto the stack along with a  pointer to the arc that we are 
	 * currently following and follow it. If it is a terminal arc, 
	 * output the terminal and return, otherwise repeat for the 
	 * new nt. When returning, pop the stack and go on to the next
	 * arc, or return if there is none.
	 */

	kksp = &kkstack[0];
	kksp->ke_node = stnode;
	kksp->ke_arc = stnode->kk_arc;
nextarc:
	if (kksp->ke_arc == NULL) {	/* We have reached the end of the 
					 * current rule.
					 */
		kksp--;
		if (kksp < &kkstack[0]) {	/* Done? */
			return (0);
		}
		/* There are more rules to go. */
		kksp->ke_arc = kksp->ke_arc->kc_narc;
		goto nextarc;
	}
	/* There are yet arcs to be followed in the current rule. */
	if (kksp->ke_arc->kc_to)	{  /* The arc is to a non-term. Follow it. */
		kknn = kksp->ke_arc->kc_to;
		if (kknn->kk_type == KTCOMP) {
			/* Compute the value of the terminal. Note that we
			 * don't bother declaring these functions to be
			 * char *.
			 */
			kkcv = (int) (*kknn->kk_func) ();
			if (kkcv == NULL) {	/* Doesn't like this rule. */
				kksp->ke_arc = kksp->ke_arc->kc_narc;
				goto nextarc;
			} else {	/* Cool. */
				kkoutput((char *) kkcv);
				kksp->ke_arc = kksp->ke_arc->kc_narc;
				goto nextarc;
			}
		}
		/* It must be a real non-terminal then. Now decide
		 * which rule to use.
		 */
		while (kknn) {
			if ((kknn->kk_func == NULL) || (*kknn->kk_func) () )
				break;
			kknn = kknn->kk_next;
		}
		if (kknn == NULL) {
			fprintf(stderr, "Error: no rules accepted for %s\n",
				kksp->ke_node->kk_nodename);
			exit(1);
		}
		kksp++;
		kksp->ke_node = kknn;
		kksp->ke_arc = kknn->kk_arc;
		goto nextarc;
	}
	/* It is a terminal. */
	kkoutput(kksp->ke_arc->kc_toname);
	kksp->ke_arc = kksp->ke_arc->kc_narc;
	goto nextarc;
}
!Funky!Stuff!
echo x - output.c
cat >output.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * The output function for babble. Well, there has to be a special control
 * character for newlines, spaces, and tabs... This is %. %n, %t, %s.
 */

#include <stdio.h>

extern int nflag;

#define vowel(c)	((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') \
				    || (c == 'u') || (c == 'A') || (c == 'E') \
				    || (c == 'I') || (c == 'O') || (c == 'U'))
#define wspace(c)	((c == ' ') || (c == '\n') || (c == '\t'))

int lpos = 0;

kkoutput(string)
char *string;
{

	static char text[BUFSIZ];
	static int tpos = 0;
	int a, b;
	int vow, x;
	char c;

	/* Save up text until it is time to write out the stuff. */

	if (*string != '@') {
		while (*string)
			text[tpos++] = *(string++);
		text[tpos++] = ' ';
		return;
	} else {
		a = 0;
		if (text[0] >= 'a' && text[0] <= 'z')
			text[0] = text[0] - 'a' + 'A';
		if (lpos > 64) {
			putchar('\n');
			lpos = 0;
		}
loop:
		if (a >= tpos) {
			tpos = 0;
			return;
		}
		if (text[a] != ' ' && text[a] != '\t' && text[a] != '!' 
		    && text[a] != '\n' && text[a] != ',' && text[a] != '.'
		    && text[a] != '?') {
			if ((text[a] == 'a') && ((a == 0) || wspace(text[a - 1]))
			    && a < tpos && wspace(text[a + 1])) {
				for (x = a + 1; x < tpos; x++)
					if (!wspace(text[x]))
						break;
				if ((x != tpos) && vowel(text[x])) {
					putchar('a');
					putchar('n');
					a++;
					lpos += 2;
					goto loop;
				}
			}
			if (text[a] == '#') {
				a++;
				goto loop;
			}
			if (text[a] == '%') {
				switch(text[++a]) {
					case 'n': {
						putchar('\n');
						lpos = 0;
						a++;
						break;
					}
					case 's': {
						putchar(' ');
						lpos++;
						a++;
						break;
					}
					case 't': {
						
						putchar('\t');
						lpos = (lpos / 8 + 1) * 8;
						a++;
						break;
					}
					default: {
						putchar(text[a++]);
						lpos++;
						break;
					}
				}
				goto loop;
			}
			putchar(text[a]);
			lpos++;
			a++;
			goto loop;
		}
		if (text[a] == '.' || text[a] == ',' || text[a] == '!' 
		    || text[a] == '?') {
			putchar(text[a++]);
			if (*(string + 1) == 'P') {
				putchar('\n');
				putchar('\t');
				lpos = 8;
				goto loop;
			}
			while (text[a] == ' ' || text[a] == '\t' || 
			    text[a] == '\n')
				a++;
			goto space;
		}
		for (b = a; b < tpos; b++) {
			if (text[b] != ' ' && text[b] != '\t' && 
			    text[b] != '\n') 
				break;
		}
		if (text[b] == '.' || text[b] == ',' || text[b] == '!'
		    || text[b] == '?') {
			a = b;
			goto loop;
		}
space:
		for (x = a + 1; x < tpos; x++) 
			if (!wspace(text[x])) {
				if (text[x] == '#') {
					a = x + 1;
					goto loop;
				}
				break;
			}
		if ((lpos > 64) && !nflag) {
			if (tpos > a) {
				putchar('\n');
				lpos = 0;
			} else {
				/*
				tpos = 1;
				lpos = 0;
				text[0] = '\n';
				return;
				*/
			}
		} else {
			putchar(' ');
			lpos++;
		}
		while (text[a] == ' ' || text[a] == '\t' || text[a] == '\n')
			a++;
		goto loop;
	}
}

!Funky!Stuff!
echo x - psubr.c
cat >psubr.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Routines for the parser. These create and maintain the graph that the
 * parser is responsible for.
 */

#include "kafgraf.h"
#include <stdio.h>
#include <strings.h>

struct knode *n;
struct knode *hashtab[256];
struct karc *avarc;
int i, c;

/* Enter a new rule. */

newrule(name)
char *name;
{
	struct knode *prev;
	unsigned char hashind, phash();

	hashind = phash(name);
	if (hashtab[hashind]) {
		for (n = hashtab[hashind]; n != NULL; n = n->kn_nnt) {
			if (!strcmp(n->kn_nodename, name)) {
				while (n->kn_next)
					n = n->kn_next;
				n->kn_next = (struct knode *)
				    malloc(sizeof (struct knode));
				n = n->kn_next;
				goto gotit;
			}
			prev = n;
		}
		if (n == NULL) {
			n = prev->kn_nnt = (struct knode *) 
			    malloc(sizeof (struct knode));
		}
	} else {
		hashtab[hashind] = (struct knode *)
				  malloc(sizeof (struct knode));
		n = hashtab[hashind];
	}
gotit:
	strcpy(n->kn_nodename, name);
	n->kn_nnt = n->kn_next = NULL;
	n->kn_type = KTNTERM;
	n->kn_nodenumber = newnum2();
	avarc = n->kn_arc = 0;	/* Set n->kn_arc to the arc when you
				 * find one.
				 */
	/* The new node is now in place. Now to collect the arcs... */
}

/* Enter a computed terminal. */


docompterm()
{
	int fnum;

	n->kn_type = KTCOMP;
	n->kn_next = n->kn_nnt = NULL;
	n->kn_arc = NULL;
	fnum = newnum();
	n->kn_fnum = fnum;
	/* Now we have to read in the actual function 
	 * definition. This is kept in "kaf.text.c", along
	 * with the rest of the user-supplied C code.
	 */
	if (transcribe(fnum)) {
		fprintf(stderr, "Premature end of file.\n");
		exit(1);
	}
}

/* Enter a nonterminal in a rule. */

dononterm(name)
char *name;
{

	/* Found a non-terminal. Note that throughout
	 * this process n will point to the main functor
	 * and avarc will point the last used arc. Thus
	 * when the end is found avarc->narc must be set = NULL.
	 * (This will also occur immediately if the rule
	 * is determined to be a computed terminal.)
	 * Also references in arcs cannot be resolved 
	 * until all rules are in...
	 */
	if (avarc) {
		avarc->ka_narc = (struct karc *) malloc(sizeof (struct karc));
		avarc = avarc->ka_narc;
	} else {	/* This is the first one. */
		avarc = (struct karc *) malloc(sizeof (struct karc));
		n->kn_arc = avarc;
	}
	strcpy(avarc->ka_toname, name);
	avarc->ka_type = KTNTERM;
	avarc->ka_arcnumber = newnum2();
}


/* Enter a terminal. */

doterm(name)
char *name;
{ 

	/* Just set ka_toname to the name of the terminal and set ka_type
	 * to be KTTERM. 
	 */

	if (avarc) {
		avarc->ka_narc = (struct karc *) malloc(sizeof (struct karc));
		avarc = avarc->ka_narc;
	} else {	/* This is the first arc. */
		avarc = (struct karc *) malloc(sizeof (struct karc));
		n->kn_arc = avarc;
	}
	strcpy(avarc->ka_toname, name);
	avarc->ka_type = KTTERM;
	avarc->ka_arcnumber = newnum2();
}

/* Copy C code in defs section. */

copyccode()
{
	int c;
	extern FILE *textp;

	for (;;) {
		while ((c = input()) != '\n') {
			if (c == '\0') {
				fprintf(stderr, "Unexpected EOF.\n");
				exit(1);
			}
			putc(c, textp);
		}
		c = input();
		if (c == '%') {
/* { boo hiss */	if ((c = input()) == '}')
				return;
			putc('\n', textp);
			putc('%', textp);
			putc(c, textp);
			continue;
		}
		putc('\n', textp);
		unput(c);
	}
}

!Funky!Stuff!
echo x - stuff.c
cat >stuff.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Assorted things.
 */

#include <stdio.h>

extern FILE *specp, *textp;

/* This should exist somewhere. It should be first in the file... */

char *itoa(num)
{
	static char buf[32];
	int p;

	p = 31;
	do {
		buf[p] = (char) num % 10 - '\0';
		num /= 10;
		p--;
	} while (num);
	return (buf + p);
}

/* The hashing function. Note that hashtables have to be of size 256. 
 * They probably don't need to be very big, and the fn is simple...
 */

phash(string)
char *string;
{
	unsigned char rv = 0;
	while (*string) 
		rv += *(string++);
	return (rv);
}


/* This function reads a C function from the input file. It is kept in
 * the file pointed to by outp. It takes the function number as an argument
 * (the function will not have arguments). Note that this will be messed
 * up by unbalanced brackets in comments.
 */ 

transcribe(num)
int num;
{

	/* Note that we must add the first bracket... */

	extern FILE *textp;
	extern char input();
	char c;
	int brct;

	fprintf(textp, "\n_kkFunc%d ()\n{\n", num);
	brct = 1;
	while (c = input()) {	/* This is the lex input function. */
		if (c == '{') brct++;
		if (c == '}') brct--;
		putc(c, textp);
		if (!brct) return (0);
	}
	/* Reached EOF. */
	return (1);
}

/* "Gensym" for user supplied C code names. */

newnum()
{
	static int n = 0;

	n++;
	return (n);
}

/* "Gensym" for arcnumbers and nodenumbers. */

newnum2()
{
	static int n = 0;

	n++;
	return (n);
}

!Funky!Stuff!
echo x - parse.y
cat >parse.y <<'!Funky!Stuff!'
%{

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * The Kafka parser. It is called once, and builds the
 * necessary data structures for the specification. 
 */

#include <stdio.h>
#include <strings.h>
#include "kafgraf.h"

char buf[BUFSIZ];
extern FILE *inp;
extern struct karc *avarc;

%}

%start spec

%token LBRACE RBRACE NONTERM TERM RULEOP SSEP KESC 
%token COPEN CCLOSE SEMI

%%

/* The following definition is much like the one for 
 * yacc itself described in the user's guide.
 */

spec	:	defs SSEP rules tail
	;

tail	:	/* Empty. */
	|	SSEP	{	/* Deal with program section here. */ 
			int n;
			extern FILE *textp;

			do {
				n = fread(buf, 1, BUFSIZ, inp);
				fwrite(buf, 1, n, textp);
			} while (n == BUFSIZ);
			}
	;

defs	:	/* Empty. */
	|	defs def
	;

def	:	KESC   { /* Deal with Kafka escape here. 
			  * (None yet implemented.) 
			  */ 
			}	
	|	COPEN	{ /* Copy C code here. */ 
			copyccode();
			}
	;

rules	:	/* Empty. */
	|	rules rule
	;

rule	:	NONTERM 
			{ 	/* Got the NT name. Create a node. */
			newrule($1);
			}
			RULEOP rtail SEMI
	;

rtail	:	LBRACE	{	/* A computed terminal. */
			docompterm();
			}
	|	stuff LBRACE 
			{	/* We have to copy the C code and clean up. */
			int fnum;
			extern struct knode *n;
			
			fnum = newnum();
			transcribe(fnum);
			n->kn_fnum = fnum;
			avarc->ka_narc = NULL;
			}
	|	stuff	{	/* Just clean up. */
			n->kn_fnum = 0;
			avarc->ka_narc = NULL;
			}
	;

stuff	:	/* Empty. */
	|	stuff thing
	;

thing	:	NONTERM {
			dononterm($1);
			}
	|	TERM
			{
			doterm($1);
			}
	;

%%

!Funky!Stuff!
echo x - lexical.l
cat >lexical.l <<'!Funky!Stuff!'
%{

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher 
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * The lexical analyzer for kafka.
 */

#include "y.tab.h"

char lookahead[100];	/* For pushback of characters. */
int nlk = 0;		/* # characters pushed back. */
extern FILE *inp;	/* The input file. */
extern int yylval;

%}

%%

\<[^ \t\n]*\>		{ /* A non-terminal. */
			yytext[yyleng - 1] = '\0';
			yylval = (int) (yytext + 1);
			return (NONTERM);
			}

[ \t\n]*		{ /* White space. */
			}

^#.*$			{ /* A comment. Ignore. */
			}

[^ \"\t\n=\<\>;\{\}\%]*	{ /* An unquoted terminal string. */
			yylval = (int) yytext;
			return (TERM);
			}

\"[^\"]*\"		{ /* A quoted terminal. */
			yytext[yyleng - 1] = '\0';
			yylval = (int) (yytext + 1);
			return (TERM);
			}

=			{ /* The rule operator. */
			return (RULEOP);
			}

^\%\%			{ /* The section seperator. */
			return (SSEP);
			}

^\%[A-Za-z].*$		{ /* A kafka escape. */
			yylval = (int) yytext[1];
			return (KESC);
			}

^\%\{			{ /* Begin def section C code. */
			return (COPEN);
			}

^\%\}			{ /* End def section C code. */
			return (CCLOSE);
			}

\{			{ /* Open brace. */
			return (LBRACE);
			}

\}			{ /* Close brace. */
			return (RBRACE);
			}

\;			{ /* Semicolon. */
			return (SEMI);
			}


%%

/* The redefined input and unput functions -- they must be usable by
 * other routines. 
 */

int lineno = 0;

char input()
{
	int c;
	if (nlk == 0) {
		c = getc(inp);
		if (c == '\n') 
			lineno++;
		if (c == EOF) 
			return (0);
		else
			return (c);
	} else {
		c = lookahead[--nlk];
		return (c);
	}
}

unput(c)
char c;
{
	lookahead[nlk++] = c;
	return;
}

/* Don't need this thing... */

yywrap()
{
	return (1);
}

!Funky!Stuff!

rafferty@cmu-cs-edu1.ARPA (Colin Rafferty) (05/18/85)

CMU seems to be lacking the include file <strings.h>, so I and many others
here would be eternally grateful if you were to post it.  Thank you.

----
            Colin Rafferty { Math Department, Carnegie-Mellon University }

"According to convention there is a sweet and a bitter, a hot and a cold,
and according to convention, there is an order.  In truth, there are atoms
and a void."
                -Democritus(400 B.C.)

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (05/19/85)

> CMU seems to be lacking the include file <strings.h>, so I and many others
> here would be eternally grateful if you were to post it.  Thank you.

Please don't; it is AT&T proprietary.
P.S. It just defines the types of the str*() functions.

faustus@ucbcad.UUCP (Wayne A. Christopher) (05/21/85)

> CMU seems to be lacking the include file <strings.h>, so I and many others
> here would be eternally grateful if you were to post it.  Thank you.

Well, it is proprietary, but here is a hint: it declares the functions
strcmp, strcpy, index, rindex, and strncat as char *, and strcmp, strlen,
and strncmp as int.

	Wayne