[comp.sources.games] v02i096: autopun - phonetically reparse English phrases

games-request@tekred.TEK.COM (11/25/87)

Submitted by: bradn@tekig4.TEK.COM (Bradford Needham)
Comp.sources.games: Volume 2, Issue 96
Archive-name: autopun

	[Brad originally sent this to comp.sources.unix and r$
	 forwarded it to me.  I wrote a unformatted man page from
	 Brad's original formatted man page  and compiled and ran
	 the prog on our 4.3bsd system.  Note that using the '-c'
	 option creates a large (300+Kb) file and takes awhile
	 to run.   -br]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile autopun.6 autopun.c autopun.man.orig
#   phoneme.c phoneme.h
# Wrapped by billr@tekred on Wed Nov 25 10:07:21 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(377 characters\)
sed "s/^X//" >README <<'END_OF_README'
XAutopun converts an English phrase into a table of phonetically-similar
Xwords, useful for creating rebus, punch-lines for shaggy-dog stories, and
Xother perversions of spoken English.
X
XFor more practically-minded folks, autopun includes phoneme.c, an English-
Xtext-to-phoneme translator (i.e., a text speaker) derived from an earlier
Xposting.
X
XBrad Needham
Xbradn@tekig4.TEK.COM
END_OF_README
if test 377 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(241 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
Xautopun: autopun.o phoneme.o
X	cc -o autopun autopun.o phoneme.o
Xphoneme.o: phoneme.c phoneme.h
Xautopun.o: autopun.c phoneme.h
Xclean:
X	-rm -f autopun.o phoneme.o
Xshar:
X	shar -a autopun.man autopun.c phoneme.h phoneme.c Makefile >autopun.shar
END_OF_Makefile
if test 241 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f autopun.6 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"autopun.6\"
else
echo shar: Extracting \"autopun.6\" \(2254 characters\)
sed "s/^X//" >autopun.6 <<'END_OF_autopun.6'
X.TH AUTOPUN 6
X.SH NAME
Xautopun - Phonetically Reparse an English Phrase 
X.SH SYNOPSIS
X.B autopun
X.B \-e
XEnglish_dict
X.br
X.B autopun
X.B \-p
XPhone_dict
X.br
X.B autopun
X.RB [ \-e
XEnglish_dict]
X.B \-c
X.B \-p
XPhone_dict
X.SH OPTIONS
X.TP
X.B \-e
Xspecifies which English word list to read instead of the default,
X/usr/dict/words.
X.TP
X.B \-p
Xspecifies the encoded phonetic word list to read instead of an
XEnglish word list (see
X.BR \-c )\.
X.TP
X.B \-c
Xcreates (rather than reads) the given phonetic word list.
XThe
X.B \-c
Xoption requires that the
X.B \-p
Xoption be used.
X(This is how a phonetic word list is created.)
X.SH DESCRIPTION
X.LP
XAutopun generates (to standard-out) a table of phonetic reparsings
Xof the given English phrase (from standard-in).  The table is useful
Xfor generating rebus, punch-lines for shaggy-dog stories, and other
Xperversions of spoken English.
X.LP
XFor efficiency, autopun can read from a previously-encoded phonetic
Xword list rather than an unencoded English dictionary.
X.SH EXAMPLES
X.IP ""
X$ autopun -c -p phdict
X.LP
XIf the phrase "Merry Christmas" is typed as standard-input to the
Xabove command, autopun will generate the following table and (as
Xa side-effect) create the phonetic word list, phdict, for later use.
X.LP
X.nf
X.na
X	Merry Christmas
X	00:
X	  merry:04 murre:03 moo:02
X	02:
X	  wreak:05 rick:05 reek:05 re:04
X	03:
X	  eke:05
X	04:
X	  Christmas:$  Christ:09
X	05:
X	  wrist:09 re:07
X	07:
X	  St.:09 St:09
X	09:
X	  mush:$  mouse:$  moss:$  mass:$  mash:$ 
X.ad
X.fi
X.LP
XTo (manually) generate a new phrase from the above table, start
Xat the list marked "0".  Pick an interesting word from that list,
Xsuch as "moo".  Go to the list whose number appears to the right
Xof the selected word (list 02 in this case).  Repeat the process
Xuntil the table says to go to list "$".  Following this procedure
Xmight produce the phrase "Moo wreak wrist moss".
X.SH SPECIAL\ CONSIDERATIONS
X.LP
XAutopun blindly believes that the word list contains all interesting
Xwords and that everything in the word list is interesting.  Careful
Xediting of the English word list can correct these problems.
X.LP
XAutopun doesn't know how to pronounce abbreviations, punctuation,
Xor numerals.
X.SH FILES
X.LP
X/usr/dict/words
X.SH AUTHOR
X.LP
XBrad Needham (bradn@tekig4.TEK.COM)
END_OF_autopun.6
if test 2254 -ne `wc -c <autopun.6`; then
    echo shar: \"autopun.6\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f autopun.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"autopun.c\"
else
echo shar: Extracting \"autopun.c\" \(13592 characters\)
sed "s/^X//" >autopun.c <<'END_OF_autopun.c'
X/*
X * autopun - Phrase reparser.
X *
X * Usage:
X *	autopun [-e English_dict] [-p Phone_dict]
X * or
X *	autopun [-e English_dict] -c -p Phone_dict
X *
X * Given an English phrase (as stdin), autopun prints (to stdout) a table
X * that can be used to create phonemically-similar phrases.  E.g.,
X *  "Happy Birthday" can be recast as "Hub pip Earth tee".
X */
X
X#include <stdio.h>
X#include "phoneme.h"
X#define TRUE 1
X#define FALSE 0
X
Xchar *cmd;				/* name of this program		*/
Xint phread = FALSE;			/* "read the phone dict"	*/
Xint phcreate = FALSE;			/* "create the phone dict"	*/
Xchar *engldict = "/usr/dict/words";	/* English dictionary file	*/
Xchar *phonedict;			/* phonemic dictionary file	*/
Xchar *indictname;			/* name of the dict being read	*/
XFILE *indict;				/* the open dict being read	*/
XFILE *outdict;				/* the open dict being written	*/
X					/* ...name == phonedict		*/
X
X/*
X * struct amatch - representation of the phonemic match of a word with
X * some part of the phrase.
X */
X
Xstruct amatch {
X    struct amatch *next;	/* next word matching at this position	*/
X    char *text;			/* English text of the matching word	*/
X    short nextpos;		/* position of phoneme after this word	*/
X};
X
X/*
X * struct posinfo - information about one phonemic position in the phrase.
X */
X
Xstruct posinfo {
X    struct amatch *wlist;	/* list of words that match at this point */
X    unsigned num_parents;	/* # of words leading directly to this point */
X};
X
X/*
X * posinfo[] - indexed by phoneme position in the phrase,
X */
X
X#define MAX_PHONES	300	/* Max # of phonemes in a phrase	*/
Xstruct posinfo posinfo[MAX_PHONES];
X
Xshort target[MAX_PHONES];	/* phonemes of the phrase to reparse	*/
Xint targlen;			/* # of phonemes in target[] (less P_end) */
X
X/*
X * phmap[] - phoneme map.  Maps a set of similar-sounding phonemes into one.
X *  Used in preprocessing strings before comparison.
X */
X
Xshort phmap[P_NUM] = {
X    P_end,	/* P_end */
X    P_IY,	/* P_IY */
X    P_IY,	/* P_IH */
X    P_EY,	/* P_EY */
X    P_EY,	/* P_EH */
X    P_AE,	/* P_AE */
X    P_AE,	/* P_AA */
X    P_AE,	/* P_AO */
X    P_AE,	/* P_OW */
X    P_AE,	/* P_UH */
X    P_UW,	/* P_UW */
X    P_UW,	/* P_ER */
X    P_AE,	/* P_AX */
X    P_AE,	/* P_AH */
X    P_AY,	/* P_AY */
X    P_AE,	/* P_AW */
X    P_OY,	/* P_OY */
X    P_p,	/* P_p */
X    P_p,	/* P_b */
X    P_t,	/* P_t */
X    P_t,	/* P_d */
X    P_k,	/* P_k */
X    P_g,	/* P_g */
X    P_f,	/* P_f */
X    P_f,	/* P_v */
X    P_TH,	/* P_TH */
X    P_f,	/* P_DH */
X    P_s,	/* P_s */
X    P_s,	/* P_z */
X    P_s,	/* P_SH */
X    P_s,	/* P_ZH */
X    P_HH,	/* P_HH */
X    P_m,	/* P_m */
X    P_n,	/* P_n */
X    P_n,	/* P_NG */
X    P_l,	/* P_l */
X    P_l,	/* P_w */
X    P_y,	/* P_y */
X    P_r,	/* P_r */
X    P_CH,	/* P_CH */
X    P_CH,	/* P_j */
X    P_WH,	/* P_WH */
X    P_end	/* P_PAS */
X};
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    char *cp;
X    char line[300];
X    char *strrchr();
X
X    /*
X     * get the basename of the command name,
X     * for use in error messages.
X     */
X
X    if ((cmd = strrchr(argv[0], '/'))) {
X	++cmd;
X    } else {
X	cmd = argv[0];
X    }
X
X    while (++argv, --argc > 0) {
X	cp = *argv;
X	if (*cp == '-' && *(cp + 1) != '\0') {
X	    switch(*++cp) {
X	    case 'c':	/* "create the phonemic dictionary */
X			/* (requires -p flag)		   */
X		phcreate = TRUE;
X		break;
X	    case 'p':	/* "filename of phonemic dictionary" */
X		if (++argv, --argc <= 0 ||
X		  (**argv == '-' && *(*argv + 1) != '\0')) {
X			bomb("missing -p filename");
X		}
X		phonedict = *argv;
X		break;
X	    case 'e':	/* "filename of English dictionary" */
X		if (++argv, --argc <= 0) {
X			bomb("missing -e filename");
X		}
X		engldict = *argv;
X		break;
X	    default:
X		bomb("unknown switch `%c'", *cp);
X	    }
X	} else {
X	    bomb("extra filename `%s'", *argv);
X	}
X    }
X    if (phcreate && !phonedict) {
X	bomb("missing -p flag");
X    }
X    phread = (phonedict && !phcreate);
X
X    /*
X     * open up the necessary files:
X     * Input is either an English or phonemic dictionary;
X     * Output is a phonemic dictionary (if requested).
X     */
X
X    if (phread) {
X	indictname = phonedict;
X    } else {
X	indictname = engldict;
X    }
X    if (!(indict = fopen(indictname, "r"))) {
X	fprintf(stderr, "%s: can't open \"%s\" -- ", cmd, indictname);
X	perror("");
X	exit(1);
X    }
X
X    if (phcreate) {
X	if (strcmp(indictname, phonedict) == 0) {
X	    bomb("can't overwrite `%s'", phonedict);
X	}
X	if (!(outdict = fopen(phonedict, "w"))) {
X	    fprintf(stderr, "%s: can't create \"%s\" -- ", cmd, phonedict);
X	    perror("");
X	    exit(1);
X	}
X    }
X
X    /*
X     * Grab a phrase and process it.
X     */
X
X    if (isatty(fileno(stdin))) {
X	fputs("Enter English text: ", stderr);
X	fflush(stderr);
X    }
X    if (fgets(line, 300, stdin)) {
X	line[strlen(line) - 1] = '\0';  /* removes the terminating \n */
X	reparse(line);
X    }
X
X    /*
X     * Close up shop, making sure that any I/O errors are reported
X     */
X
X    if (ferror(indict)) {
X	fprintf(stderr, "%s: problem reading \"%s\" -- ", cmd, indictname);
X	perror("");
X	exit(1);
X    }
X    (void) fclose(indict);
X    if (phcreate) {
X	if (fclose(outdict) != 0) {
X	    fprintf(stderr, "%s: problem writing \"%s\" -- ", cmd, phonedict);
X	    perror("");
X	    exit(1);
X	}
X    }
X    exit(0);
X}
X
X/*
X * reparse() - given a line of English text, 
X * Find and print the info necessary to reparse that line's phonemes
X * into other English phrases.
X */
X
Xreparse(text)
Xchar *text;
X{
X    char dictword[MAX_PHONES];	/* an English word from the dictionary	      */
X    char *textcopy;		/* dynamic copy of the text		      */
X    short phrase[MAX_PHONES];	/* the mapped, phonemic version of the phrase */
X    short testword[MAX_PHONES];	/* ditto for a word from the dictionary	*/
X    int twordlen;		/* # of phonemes in testword[] (less P_end)   */
X    register short *sp, *dp;	/* temp source and dest phoneme pointers      */
X    int idx;			/* index where a match started		      */
X    short *xlate_line();
X    short *mapphrase();
X    char *strsave();
X
X    /*
X     * Translate the input phrase and copy it to a safe place.
X     */
X
X    sp = xlate_line(text);
X    (void) mapphrase(sp);
X
X    dp = target;
X    while (*sp != P_end) {
X	*dp++ = *sp++;
X    }
X    *dp = P_end;
X    targlen = dp - &target[0];
X
X    /*
X     * For each word in the dictionary,
X     *   Convert that word into phonemic codes;
X     *   Write the converted codes to the phonemic dictionary (if necessary);
X     *   Record where that word would fit into the input phrase.
X     */
X
X    while (fgets(dictword, MAX_PHONES, indict)) {
X	dictword[strlen(dictword) - 1] = '\0';
X
X	if (phread) {
X	    twordlen = encphones(dictword, testword);
X	} else {
X	    sp = xlate_line(dictword);
X	    twordlen = mapphrase(sp) - sp;
X	    if (twordlen == 0) {
X		continue;			/* (loop leap) */
X	    }
X	    dp = testword;
X	    while (*sp != P_end) {
X		*dp++ = *sp++;
X	    }
X	    *dp = P_end;
X
X	    if (phcreate) {
X		writephones(dictword, testword);
X	    }
X	}
X
X	/*
X	 * Search for and record matches until
X	 * one can't possibly exist (too few phonemes left).
X	 */
X
X	sp = target;
X	dp = &target[targlen];
X	textcopy = (char *) 0;
X	while (dp - sp >= twordlen &&
X	  (idx = wordidx(sp, testword)) != -1) {
X	    sp += idx + 1;
X	    if (!textcopy) {
X		textcopy = strsave(dictword);
X	    }
X	    recmatch((sp - 1) - target, twordlen, textcopy);
X	}
X    }
X
X    prune();
X    saymatches(text);
X}
X
X/*
X * prune() - prune away useless matches:
X * remove potential matches that lead to unmatchable parts of the phrase;
X * remove unreachable match lists.
X */
X
Xprune()
X{
X    int pos;
X    struct amatch *prevm;
X    struct amatch *curm;
X
X    /*
X     * note and remove all the matches that lead to an unmatchable point.
X     */
X
X    for (pos = 0; pos < MAX_PHONES; ++pos) {
X	posinfo[pos].num_parents = 0;
X    }
X    for (pos = MAX_PHONES - 1; pos >= 0; --pos) {
X	prevm = (struct amatch *) 0;
X	curm = posinfo[pos].wlist;
X	while (curm) {
X
X	    /*
X	     * If this word leads us to the end, everything is o.k.
X	     * If this word leads us to a matchable point,
X	     * note that we can reach that point.
X	     * Otherwise, this word is a dead-end -- remove it.
X	     */
X
X	    if (curm->nextpos >= targlen) {
X		prevm = curm;
X	    } else if (posinfo[curm->nextpos].wlist) {
X		++posinfo[curm->nextpos].num_parents;
X		prevm = curm;
X	    } else {
X		if (!prevm) {
X		    posinfo[pos].wlist = curm->next;
X		} else {
X		    prevm->next = curm->next;
X		}
X		/* (we should free curm here if we are reclaiming space) */
X	    }
X	    curm = curm->next;
X	}
X    }
X
X    /*
X     * Find and remove each unreachable point in the phrase
X     * (except the first one).
X     * This traversal cascades forward.
X     */
X
X    for (pos = 1; pos < MAX_PHONES; ++pos) {
X	if (posinfo[pos].num_parents > 0) continue;
X	for (curm = posinfo[pos].wlist; curm; curm = curm->next) {
X	    if (curm->nextpos >= targlen) continue;
X
X	    --posinfo[curm->nextpos].num_parents;
X	}
X	posinfo[pos].wlist = (struct amatch *) 0;
X	/* (if we were reclaiming space, here's where we'd do it */
X    }
X}
X
X/*
X * saymatches() - print the phrase match information table.
X */
X
Xsaymatches(text)
Xchar *text;		/* the original text	*/
X{
X    int pos;
X    int curcol;
X    int addcols;
X    struct amatch *curm;
X
X    printf("%s\n", text);
X    for (pos = 0; pos < MAX_PHONES; ++pos) {
X	if (!posinfo[pos].wlist) continue;
X	printf("%02d:\n", pos);
X	curcol = 0;
X	for (curm = posinfo[pos].wlist; curm; curm = curm->next) {
X	    addcols = 1 + strlen(curm->text) + 1 + 2;
X	    if (curcol + addcols >= 70) {
X		printf("\n");
X		curcol = 0;
X	    }
X	    if (curcol == 0) {
X		printf(" ");
X		curcol += 1;
X	    }
X	    printf(" %s:", curm->text);
X	    if (curm->nextpos >= targlen) {
X		printf("$ ");
X	    } else {
X		printf("%02d", curm->nextpos);
X	    }
X	    curcol += addcols;
X	}
X	printf("\n");
X    }
X}
X
X/*
X * mapphrase() - given a phonetic word or phrase, map it in place via phmap[],
X * returning a pointer to the new end.
X */
X
Xshort *
Xmapphrase(pp)
Xshort *pp;	/* a P_end-terminated word/phrase to map	*/
X{
X    short *dp;	/* points to where to put the next phoneme	*/
X
X    dp = pp;
X    while (*pp != P_end) {
X	*dp = phmap[*pp];
X	if (*dp != P_end) ++dp;
X	++pp;
X    }
X    *dp = P_end;
X    return(dp);
X}
X
X/*
X * wordidx() - given a phrase and a comparison word,
X * return the index in the phrase where the word was found (-1 if not found).
X *
X * Wordidx() assumes both the phrase and the word have been mapped by phmap[].
X */
X
Xint
Xwordidx(phrase, word)
Xshort *phrase;		/* a P_end-terminated list of phonemes	*/
Xshort *word;		/* ditto				*/
X{
X    short *start;	/* the starting phoneme being compared		*/
X    register short *pp;	/* the current phrase phoneme being compared	*/
X    register short *wp;	/* the current word phoneme being compared	*/
X
X    for (start = phrase; *start != P_end; ++start) {
X	wp = word;
X	pp = start;
X	while (*wp != P_end) {
X	    if (*pp != *wp) break;
X	    ++pp, ++wp;
X	}
X	if (*wp == P_end) {
X	    return(start - phrase);
X	}
X    }
X    return(-1);
X}
X
X/*
X * recmatch() - record a match.
X */
X
Xrecmatch(pos, phlen, text)
Xint pos;		/* position of the match within the phrase	*/
Xint phlen;		/* # of phonemes matched			*/
Xchar *text;		/* text that matched				*/
X{
X    struct amatch *prevm;
X    struct amatch *newm;
X    struct amatch *nextm;
X    struct amatch *matchalloc();
X
X    newm = matchalloc();
X    newm->text = text;
X    newm->nextpos = pos + phlen;
X
X    prevm = (struct amatch *) 0;
X    for (nextm = posinfo[pos].wlist; nextm && newm->nextpos < nextm->nextpos;
X      prevm = nextm, nextm = nextm->next) {
X	/* (empty body) */
X    }
X
X    if (!prevm) {
X	newm->next = posinfo[pos].wlist;
X	posinfo[pos].wlist = newm;
X    } else {
X	newm->next = prevm->next;
X	prevm->next = newm;
X    }
X}
X
X/*
X * writephones() - write a list of phonemes to a file.
X */
X
Xwritephones(ep, sp)
Xchar *ep;		/* english text 		*/
Xshort *sp;		/* corresponding phonemes	*/
X{
X    fputs(ep, outdict);
X    putc(' ', outdict);
X    while (*sp != P_end) {
X	putc((int) *sp + (int) '!', outdict);
X	++sp;
X    }
X    putc('\n', outdict);
X    if (ferror(outdict)) {
X	fprintf(stderr, "Error: problem writing \"%s\" -- ", phonedict);
X	perror("");
X	exit(1);
X    }
X}
X
X/*
X * encphones() - encode ascii from a phoneme file into phonetic codes.
X */
X
Xint		/* returns # of phonemes in word[]		*/
Xencphones(text, word)
Xregister char *text;	/* encoded phonemes (less the newline) */
Xshort *word;		/* where to put the phonemes		*/
X{
X    register short *sp;
X    char *strchr();
X
X    /*
X     * separate the English text from its encoded form
X     */
X
X    text = strchr(text, ' ');
X    *text++ = '\0';
X
X    sp = word;
X    while (*text) {
X	*sp = (short) (*text - '!');
X	++text, ++sp;
X    }
X    *sp = P_end;
X    return(sp - word);
X}
X
X/*
X * matchalloc() - allocate a new match element.
X */
X
Xstruct amatch *
Xmatchalloc()
X{
X#define MAX_MATCHES 1000	/* max # of matches in a phrase		*/
X    static struct amatch matchpool[MAX_MATCHES];
X    static struct amatch *nextpool = matchpool;
X
X    if (nextpool >= &matchpool[MAX_MATCHES]) {
X	fprintf(stderr, "Error: too many matches (over %d)\n", MAX_MATCHES);
X	exit(1);
X    }
X    return (nextpool++);
X}
X
X/*
X * strsave() - copy the given string to a malloc'ed area,
X *  returning the resultant pointer.
X */
X
Xchar *
Xstrsave(s)
Xchar *s;
X{
X    char *ret;
X    char *malloc();
X
X    if (!(ret = malloc(strlen(s) + 1))) {
X	fprintf(stderr, "Error: out of memory saving \"%s\"\n", s);
X	exit(1);
X    }
X    (void) strcpy(ret, s);
X    return(ret);
X}
X
X/* VARARGS 1 */
Xbomb(str, a1, a2, a3)
Xchar *str;
Xint a1, a2, a3;
X{
X    fprintf(stderr, "%s: ", cmd);
X    fprintf(stderr, str, a1, a2, a3);
X    fprintf(stderr, "\n");
X    fprintf(stderr, "Usage:\n %s [-c] [-e English_dict] [-p Phone_dict]\n",
X      cmd);
X    exit(1);
X}
END_OF_autopun.c
if test 13592 -ne `wc -c <autopun.c`; then
    echo shar: \"autopun.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f autopun.man.orig -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"autopun.man.orig\"
else
echo shar: Extracting \"autopun.man.orig\" \(2420 characters\)
sed "s/^X//" >autopun.man.orig <<'END_OF_autopun.man.orig'
Xautopun - Phonetically Reparse an English Phrase 
X
XSYNTAX
X    autopun [-e English_dict] [-p Phone_dict]
X    autopun [-e English_dict] -c -p Phone_dict
X
XOPTIONS
X    -e specifies which English word list to read instead of the default,
X    /usr/dict/words.
X
X    -p specifies the encoded phonetic word list to read instead of an
X    English word list (see -c).
X
X    -c creates (rather than reads) the given phonetic word list.
X    The -c option requires that the -p option be used.
X    (this is how a phonetic word list is created.)
X
XDESCRIPTION
X    Autopun generates (to standard-out) a table of phonetic reparsings
X    of the given English phrase (from standard-in).  The table is useful
X    for generating rebus, punch-lines for shaggy-dog stories, and other
X    perversions of spoken English.
X
X    For efficiency, autopun can read from a previously-encoded phonetic
X    word list rather than an unencoded English dictionary.
X
XEXAMPLES
X	$ autopun -c -p phdict
X
X    If the phrase "Merry Christmas" is typed as standard-input to the
X    above command, autopun will generate the following table and (as
X    a side-effect) create the phonetic word list, phdict, for later use.
X
X	Merry Christmas
X	00:
X	  merry:04 murre:03 moo:02
X	02:
X	  wreak:05 rick:05 reek:05 re:04
X	03:
X	  eke:05
X	04:
X	  Christmas:$  Christ:09
X	05:
X	  wrist:09 re:07
X	07:
X	  St.:09 St:09
X	09:
X	  mush:$  mouse:$  moss:$  mass:$  mash:$ 
X
X    To (manually) generate a new phrase from the above table, start
X    at the list marked "0".  Pick an interesting word from that list,
X    such as "moo".  Go to the list whose number appears to the right
X    of the selected word (list 02 in this case).  Repeat the process
X    until the table says to go to list "$".  Following this procedure
X    might produce the phrase "Moo wreak wrist moss".
X
XSPECIAL CONSIDERATIONS
X    Autopun blindly believes that the word list contains all interesting
X    words and that everything in the word list is interesting.  Careful
X    editing of the English word list can correct these problems.
X
X    Autopun doesn't know how to pronounce abbreviations, punctuation,
X    or numerals.
X
X    This man page is not in Man format because our copy of the man macros
X    has been "improved" to the point that I cannot generate a standard
X    man page.  Credit goes to nroff for having a macro language obscure
X    enough to be a temptation to the undisciplined.
X
XFILES
X    /usr/dict/words
END_OF_autopun.man.orig
if test 2420 -ne `wc -c <autopun.man.orig`; then
    echo shar: \"autopun.man.orig\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f phoneme.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"phoneme.c\"
else
echo shar: Extracting \"phoneme.c\" \(8873 characters\)
sed "s/^X//" >phoneme.c <<'END_OF_phoneme.c'
X#include <stdio.h>
X#include <ctype.h>
X
X#define DATA
X#include "phoneme.h"
X#undef DATA
X
X/*
X * xlate_line() - given an English-text phrase or word,
X * Translate that thing into a phoneme-list.
X *
X * xlate_line() returns a pointer to the *static* resultant phoneme-list.
X */
X
Xshort *
Xxlate_line(text)
Xchar *text;	/* English text to convert */
X{
X    static short phonelist[MAXPHONES];
X    char word[1 + MAXPHONES + 1];	/* the current parsed word	*/
X    short *nxtphones;
X    char *dp;
X    short *xlate_word();
X
X    nxtphones = phonelist;
X    word[0] = ' ';
X    while (*text) {
X	while (*text && !(isalpha(*text) || *text == '\'')) {
X	    ++text;
X	}
X	dp = &word[1];
X	if (!*text) break;			/* Loop Exit */
X
X	while (isalpha(*text) || *text == '\'') {
X	    if (islower(*text)) {
X		*dp = toupper(*text);
X	    } else {
X		*dp = *text;
X	    }
X	    ++dp, ++text;
X	}
X	*dp++ = ' ';
X	*dp = '\0';
X	nxtphones = xlate_word(word, nxtphones);
X    }
X    *nxtphones = P_end;
X    return(phonelist);
X}
X
X/*
X * xlate_word() - translate the given English word into a phoneme stream.
X * The word has the following form:
X *	' [-A-Z']* '
X * That is, it begins and ends with a space and it contains only
X * upper-case letters, apostrophes, and hyphens.
X */
X
Xshort *		/* where to put any following phonemes (or a terminator) */
Xxlate_word(word, phonedst)
Xchar *word;
Xshort *phonedst;	/* where to put the new phonemes	*/
X{
X    char *apply1rule();
X    short *newphones;	/* array of phonemes to append */
X
X    ++word; /* Skip the initial blank */
X    while (*word) {
X	word = apply1rule(word, &newphones);
X	while (*newphones != P_end) {
X	    *phonedst++ = *newphones++;
X	}
X    }
X    return(phonedst);
X}
X
X/*
X * apply1rule() - apply the appropriate translation rule to the start of
X * the word provided, setting a pointer to the resultant phonemes and
X * returning a pointer to the unconverted part of the word.
X */
X
Xchar *		/* returns the place to convert next	*/
Xapply1rule(word, newphp)
Xchar *word;	/* the part of the word to start in	*/
Xshort **newphp;	/* where to put a pointer to the set of translated phonemes */
X{
X    int rtype;		/* rule type to use				*/
X    struct rule *rule;	/* the current rule being tested		*/
X    register char *cp;	/* temp pointer for matching			*/
X    register char *rem;	/* points to the first char past the match	*/
X    static short firstcall = TRUE;	/* "first call to this routine"	*/
X
X    static short nosym = P_end;	/* an empty phoneme list		*/
X
X    if (firstcall) {
X	firstcall = FALSE;
X	ruleinit();
X    }
X
X    if (isupper(*word)) {
X	rtype = (int) (*word - 'A') + RIDX_A;
X    } else {
X	rtype = RIDX_PUNC;
X    }
X    for (rule = Rules[rtype]; rule->match; ++rule) {
X	for (cp = rule->match, rem = word; *cp; cp++, rem++) {
X	    if (*cp != *rem) break;
X	}
X	if (*cp) continue; /* failed to match */
X
X	if (!leftmatch(rule->prefix, rule->preflen, word - 1)) continue;
X	if (!rightmatch(rule->suffix, rule->sufflen, rem)) continue;
X
X	*newphp = rule->outsyms;
X	return(rem);
X    }
X
X    fprintf(stderr, "Error: Can't find rule for: '%c' in \"%s\"\n",
X     *word, word);
X    *newphp = &nosym;
X    return(word + 1);	/* Skip the annoyance */
X}
X
X
Xint
Xleftmatch(pattern, patlen, context)
Xchar *pattern;	/* first char of pattern to match in text */
Xshort patlen;	/* strlen(pattern)	*/
Xchar *context;	/* last char of text to be matched */
X{
X    char *pat;
X    char *text;
X    int count;
X
X    if (!*pattern) return(TRUE);	/* null string matches any context */
X
X    /* point to last character in pattern string */
X    count = patlen;
X    pat = pattern + (count - 1);
X
X    text = context;
X
X    for (; count > 0; pat--, count--) {
X	switch (*pat) {
X	case '\'':
X	case ' ':
X	case 'A':
X	case 'B':
X	case 'C':
X	case 'D':
X	case 'E':
X	case 'F':
X	case 'G':
X	case 'H':
X	case 'I':
X	case 'J':
X	case 'K':
X	case 'L':
X	case 'M':
X	case 'N':
X	case 'O':
X	case 'P':
X	case 'Q':
X	case 'R':
X	case 'S':
X	case 'T':
X	case 'U':
X	case 'V':
X	case 'W':
X	case 'X':
X	case 'Y':
X	case 'Z':
X	    if (*pat != *text) return(FALSE);
X	    text--;
X	    continue;
X
X	case '#':	/* One or more vowels */
X	    if (!isvowel(*text)) return(FALSE);
X	    text--;
X
X	    while (isvowel(*text)) text--;
X	    break;
X
X	case ':':	/* Zero or more consonants */
X	    while (isconsonant(*text)) text--;
X	    break;
X
X	case '^':	/* One consonant */
X	    if (!isconsonant(*text)) return(FALSE);
X	    text--;
X	    break;
X
X	case '.':	/* B, D, V, G, J, L, M, N, R, W, Z */
X#ifdef NOTDEF
X	    if (*text != 'B' && *text != 'D' && *text != 'V'
X	      && *text != 'G' && *text != 'J' && *text != 'L'
X	      && *text != 'M' && *text != 'N' && *text != 'R'
X	      && *text != 'W' && *text != 'Z') {
X		return FALSE;
X	    }
X	    text--;
X#endif
X	    switch (*text) {
X	    case 'B':
X	    case 'D':
X	    case 'V':
X	    case 'G':
X	    case 'J':
X	    case 'L':
X	    case 'M':
X	    case 'N':
X	    case 'R':
X	    case 'W':
X	    case 'Z':
X		text--;
X		break;
X	    default:
X		return(FALSE);
X	    }
X	    break;
X
X	case '+':	/* E, I or Y (front vowel) */
X#ifdef NOTDEF
X	    if (*text != 'E' && *text != 'I' && *text != 'Y') return FALSE;
X	    text--;
X#endif
X	    switch(*text) {
X	    case 'E':
X	    case 'I':
X	    case 'Y':
X		text--;
X		break;
X	    default:
X		return(FALSE);
X	    }
X	    break;
X
X	default:
X	    fprintf(stderr, "Bad char in left rule: '%c'\n", *pat);
X	    return(FALSE);
X	}
X    }
X    return(TRUE);
X}
X
X
Xint
Xrightmatch(pattern, patlen, context)
Xchar *pattern;	/* first char of pattern to match in text */
Xshort patlen;	/* strlen(pattern) [ignored]		*/
Xchar *context;	/* last char of text to be matched */
X{
X    char *pat;
X    char *text;
X
X    if (!*pattern) return(TRUE);	/* null string matches any context */
X
X    pat = pattern;
X    text = context;
X
X    for (pat = pattern; *pat != '\0'; pat++) {
X	switch (*pat) {
X	case '\'':
X	case ' ':
X	case 'A':
X	case 'B':
X	case 'C':
X	case 'D':
X	case 'E':
X	case 'F':
X	case 'G':
X	case 'H':
X	case 'I':
X	case 'J':
X	case 'K':
X	case 'L':
X	case 'M':
X	case 'N':
X	case 'O':
X	case 'P':
X	case 'Q':
X	case 'R':
X	case 'S':
X	case 'T':
X	case 'U':
X	case 'V':
X	case 'W':
X	case 'X':
X	case 'Y':
X	case 'Z':
X	    if (*pat != *text) return(FALSE);
X	    text++;
X	    continue;
X
X	case '#':	/* One or more vowels */
X	    if (!isvowel(*text)) return FALSE;
X	    text++;
X
X	    while (isvowel(*text)) text++;
X	    break;
X
X	case ':':	/* Zero or more consonants */
X	    while (isconsonant(*text)) text++;
X	    break;
X
X	case '^':	/* One consonant */
X	    if (!isconsonant(*text)) return FALSE;
X	    text++;
X	    break;
X
X	case '.':	/* B, D, V, G, J, L, M, N, R, W, Z */
X#ifdef NOTDEF
X	    if (*text != 'B' && *text != 'D' && *text != 'V'
X	      && *text != 'G' && *text != 'J' && *text != 'L'
X	      && *text != 'M' && *text != 'N' && *text != 'R'
X	      && *text != 'W' && *text != 'Z') {
X		return(FALSE);
X	    }
X	    text++;
X#endif
X	    switch (*text) {
X	    case 'B':
X	    case 'D':
X	    case 'V':
X	    case 'G':
X	    case 'J':
X	    case 'L':
X	    case 'M':
X	    case 'N':
X	    case 'R':
X	    case 'W':
X	    case 'Z':
X		text++;
X		break;
X	    default:
X		return(FALSE);
X	    }
X	    break;
X
X	case '+':	/* E, I or Y (front vowel) */
X#ifdef NOTDEF
X	    if (*text != 'E' && *text != 'I' && *text != 'Y') return(FALSE);
X	    text++;
X#endif
X	    switch(*text) {
X	    case 'E':
X	    case 'I':
X	    case 'Y':
X		text++;
X		break;
X	    default:
X		return(FALSE);
X	    }
X	    break;
X
X	case '%':	/* ER, E, ES, ED, ING, ELY (a suffix) */
X	    if (*text == 'E') {
X		text++;
X		if (*text == 'L') {
X		    text++;
X		    if (*text == 'Y') {
X			text++;
X			break;
X		    } else {
X			text--; /* Don't gobble L */
X			break;
X		    }
X		} else if (*text == 'R' || *text == 'S' || *text == 'D') {
X		    text++;
X		}
X		break;
X	    } else if (*text == 'I') {
X		text++;
X		if (*text == 'N') {
X		    text++;
X		    if (*text == 'G') {
X			text++;
X			break;
X		    }
X		}
X		return(FALSE);
X	    }
X	    return(FALSE);
X
X	default:
X	    fprintf(stderr, "Bad char in right rule:'%c'\n", *pat);
X	    return(FALSE);
X	}
X    }
X    return(TRUE);
X}
X
X/*
X * ruleinit() - initialize the remaining fields of the phoneme rule table.
X */
X
Xruleinit()
X{
X    struct rule *rule;
X    int rtype;
X
X    for (rtype = 0; rtype < RULECNT; ++rtype) {
X	for (rule = Rules[rtype]; rule->match; ++rule) {
X	    rule->preflen = strlen(rule->prefix);
X	    rule->sufflen = strlen(rule->suffix);
X	}
X    }
X}
X
Xint
Xisvowel(chr)
Xchar chr;
X{
X#ifdef NOTDEF
X    return(chr == 'A' || chr == 'E' || chr == 'I' || chr == 'O' || chr == 'U');
X#endif
X    switch (chr) {
X    case 'A':
X    case 'E':
X    case 'I':
X    case 'O':
X    case 'U':
X	return(TRUE);
X    }
X    return(FALSE);
X}
X
Xint
Xisconsonant(chr)
Xchar chr;
X{
X    return(isupper(chr) && !isvowel(chr));
X}
X
X/*
X * outphonemes() - output the given P_end-terminated array of phonemes.
X */
X
Xoutphonemes(php)
Xshort *php;		/* phoneme pointer	*/
X{
X    while (*php != P_end) {
X	outstring(phochars[*php]);
X	++php;
X    }
X}
X
Xoutstring(string)
Xchar *string;
X{
X    while (*string != '\0') fputc(*string++, stderr);
X}
END_OF_phoneme.c
if test 8873 -ne `wc -c <phoneme.c`; then
    echo shar: \"phoneme.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f phoneme.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"phoneme.h\"
else
echo shar: Extracting \"phoneme.h\" \(23805 characters\)
sed "s/^X//" >phoneme.h <<'END_OF_phoneme.h'
X/*
X * phoneme.h - definitions/declarations for phonemic translation
X *
X *	Derived from: 
X *
X *	     AUTOMATIC TRANSLATION OF ENGLISH TEXT TO PHONETICS
X *	            BY MEANS OF LETTER-TO-SOUND RULES
X *
X *			NRL Report 7948
X *
X *		      January 21st, 1976
X *	    Naval Research Laboratory, Washington, D.C.
X *
X *
X *	Published by the National Technical Information Service as
X *	document "AD/A021 929".
X */
X
X#ifndef TRUE
X#define TRUE 1
X#define FALSE 0
X#endif
X
X#define MAXPHONES	301	/* max # of phonemes in a phrase (+P_end)*/
X
X/*
X * P_* - internal representation of phoneme codes.
X */
X
X#define P_end	 0	/* <<no sound>>	used as an invalid code	*/
X#define P_IY	 1	/* bEEt		*/
X#define P_IH	 2	/* bIt		*/
X#define P_EY	 3	/* gAte		*/
X#define P_EH	 4	/* gEt		*/
X#define P_AE	 5	/* fAt		*/
X#define P_AA	 6	/* fAther	*/
X#define P_AO	 7	/* lAWn		*/
X#define P_OW	 8	/* lOne		*/
X#define P_UH	 9	/* fUll		*/
X#define P_UW	10	/* fOOl		*/
X#define P_ER	11	/* mURdER	*/
X#define P_AX	12	/* About	*/
X#define P_AH	13	/* bUt		*/
X#define P_AY	14	/* hIde		*/
X#define P_AW	15	/* hOW		*/
X#define P_OY	16	/* tOY		*/
X#define P_p	17	/* Pack		*/
X#define P_b	18	/* Back		*/
X#define P_t	19	/* Time		*/
X#define P_d	20	/* Dime		*/
X#define P_k	21	/* Coat		*/
X#define P_g	22	/* Goat		*/
X#define P_f	23	/* Fault	*/
X#define P_v	24	/* Vault	*/
X#define P_TH	25	/* eTHer	*/
X#define P_DH	26	/* eiTHer	*/
X#define P_s	27	/* Sue		*/
X#define P_z	28	/* Zoo		*/
X#define P_SH	29	/* leaSH	*/
X#define P_ZH	30	/* leiSure	*/
X#define P_HH	31	/* How		*/
X#define P_m	32	/* suM		*/
X#define P_n	33	/* suN		*/
X#define P_NG	34	/* suNG		*/
X#define P_l	35	/* Laugh	*/
X#define P_w	36	/* Wear		*/
X#define P_y	37	/* Young	*/
X#define P_r	38	/* Rate		*/
X#define P_CH	39	/* CHar		*/
X#define P_j	40	/* Jar		*/
X#define P_WH	41	/* WHere	*/
X#define P_PAS	42	/* <short pause>	*/
X
X#define P_NUM	43	/* number of phonemic codes (including P_end)	*/
X
X/*
X * phochars[] - table for translating a phoneme code into ascii
X *  Indexed by a P_* code, phochars[] gives the ascii translation.
X */
X
X#ifdef DATA
Xchar *phochars[P_NUM] = {
X    "",
X    "IY", "IH", "EY", "EH", "AE", "AA", "AO", "OW", "UH",
X    "UW", "ER", "AX", "AH", "AY", "AW", "OY",
X    "p", "b", "t", "d", "k", "g", "f", "v", "TH", "DH",
X    "s", "z", "SH", "ZH", "HH", "m", "n", "NG", "l",
X    "w", "y", "r", "CH", "j", "WH",
X    " "
X};
X#else
Xextern char *phochars[];
X#endif
X
X#define MAXCOUT	6	/* max # of output phonemes in a rule (+ terminator) */
Xstruct rule {
X    char *prefix;		/* left context				    */
X    char *match;		/* characters to match			    */
X    char *suffix;		/* right context			    */
X    short outsyms[MAXCOUT];	/* P_end-terminated list of codes to output */
X    short preflen;		/* strlen() of prefix - set at runtime	    */
X    short sufflen;		/* ditto for suffix			    */
X};
X
X#ifdef DATA	/* definitions of the English rules */
X
Xstatic char Anything[] = "";	/* No context requirement */
Xstatic char Nothing[] = " ";	/* Context is beginning or end of word */
X
X/*
X *	Special Context Symbols in rules:
X *
X *		#	One or more vowels
X *		:	Zero or more consonants
X *		^	One consonant.
X *		.	One of B, D, V, G, J, L, M, N, R, W or Z (voiced 
X *			consonants)
X *		%	One of ER, E, ES, ED, ING, ELY (a suffix)
X *			(Found in right context only)
X *		+	One of E, I or Y (a "front" vowel)
X *
X */
X
Xstatic struct rule punct_rules[] = {
X    {Anything,	" ",	Anything,	{P_PAS, P_end}	},
X    {Anything,	"-",	Anything,	{P_end}		},
X    {".",	"'S",	Anything,	{P_z, P_end}	},
X    {"#:.E",	"'S",	Anything,	{P_z, P_end}	},
X    {"#",	"'S",	Anything,	{P_z, P_end}	},
X    {Anything,	"'",	Anything,	{P_end}		},
X    {Anything,	",",	Anything,	{P_PAS, P_end}	},
X    {Anything,	".",	Anything,	{P_PAS, P_end}	},
X    {Anything,	"?",	Anything,	{P_PAS, P_end}	},
X    {Anything,	"!",	Anything,	{P_PAS, P_end}	},
X    {Anything,	0,	Anything,	{P_end}		},
X};
X
Xstatic struct rule A_rules[] = {
X    {Anything,	"A",	Nothing,	{P_AX, P_end}			},
X    {Nothing,	"ARE",	Nothing,	{P_AA, P_r, P_end}		},
X    {Nothing,	"AR",	"O",		{P_AX, P_r, P_end}		},
X    {Anything,	"AR",	"#",		{P_EH, P_r, P_end}		},
X    {"^",	"AS",	"#",		{P_EY, P_s, P_end}		},
X    {Anything,	"A",	"WA",		{P_AX, P_end}			},
X    {Anything,	"AW",	Anything,	{P_AO, P_end}			},
X    {" :",	"ANY",	Anything,	{P_EH, P_n, P_IY, P_end}	},
X    {Anything,	"A",	"^+#",		{P_EY, P_end}			},
X    {"#:",	"ALLY",	Anything,	{P_AX, P_l, P_IY, P_end}	},
X    {Nothing,	"AL",	"#",		{P_AX, P_l, P_end}		},
X    {Anything,	"AGAIN",Anything,	{P_AX, P_g, P_EH, P_n, P_end}	},
X    {"#:",	"AG",	"E",		{P_IH, P_j, P_end}		},
X    {Anything,	"A",	"^+:#",		{P_AE, P_end}			},
X    {" :",	"A",	"^+ ",		{P_EY, P_end}			},
X    {Anything,	"A",	"^%",		{P_EY, P_end}			},
X    {Nothing,	"ARR",	Anything,	{P_AX, P_r, P_end}		},
X    {Anything,	"ARR",	Anything,	{P_AE, P_r, P_end}		},
X    {" :",	"AR",	Nothing,	{P_AA, P_r, P_end}		},
X    {Anything,	"AR",	Nothing,	{P_ER, P_end}			},
X    {Anything,	"AR",	Anything,	{P_AA, P_r, P_end}		},
X    {Anything,	"AIR",	Anything,	{P_EH, P_r, P_end}		},
X    {Anything,	"AI",	Anything,	{P_EY, P_end}			},
X    {Anything,	"AY",	Anything,	{P_EY, P_end}			},
X    {Anything,	"AU",	Anything,	{P_AO, P_end}			},
X    {"#:",	"AL",	Nothing,	{P_AX, P_l, P_end}		},
X    {"#:",	"ALS",	Nothing,	{P_AX, P_l, P_z, P_end}		},
X    {Anything,	"ALK",	Anything,	{P_AO, P_k, P_end}		},
X    {Anything,	"AL",	"^",		{P_AO, P_l, P_end}		},
X    {" :",	"ABLE",	Anything,	{P_EY, P_b, P_AX, P_l, P_end}	},
X    {Anything,	"ABLE",	Anything,	{P_AX, P_b, P_AX, P_l, P_end}	},
X    {Anything,	"ANG",	"+",		{P_EY, P_n, P_j, P_end}		},
X    {Anything,	"A",	Anything,	{P_AE, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule B_rules[] = {
X    {Nothing,	"BE",	"^#",		{P_b, P_IH, P_end}		},
X    {Anything,	"BEING",Anything,	{P_b, P_IY, P_IH, P_NG, P_end}	},
X    {Nothing,	"BOTH",	Nothing,	{P_b, P_OW, P_TH, P_end}	},
X    {Nothing,	"BUS",	"#",		{P_b, P_IH, P_z, P_end}		},
X    {Anything,	"BUIL",	Anything,	{P_b, P_IH, P_l, P_end}		},
X    {Anything,	"B",	Anything,	{P_b, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule C_rules[] = {
X    {Nothing,	"CH",	"^",		{P_k, P_end}			},
X    {"^E",	"CH",	Anything,	{P_k, P_end}			},
X    {Anything,	"CH",	Anything,	{P_CH, P_end}			},
X    {" S",	"CI",	"#",		{P_s, P_AY, P_end}		},
X    {Anything,	"CI",	"A",		{P_SH, P_end}			},
X    {Anything,	"CI",	"O",		{P_SH, P_end}			},
X    {Anything,	"CI",	"EN",		{P_SH, P_end}			},
X    {Anything,	"C",	"+",		{P_s, P_end}			},
X    {Anything,	"CK",	Anything,	{P_k, P_end}			},
X    {Anything,	"COM",	"%",		{P_k, P_AH, P_m, P_end}		},
X    {Anything,	"C",	Anything,	{P_k, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule D_rules[] = {
X    {"#:",	"DED",	Nothing,	{P_d, P_IH, P_d, P_end}		},
X    {".E",	"D",	Nothing,	{P_d, P_end}			},
X    {"#:^E",	"D",	Nothing,	{P_t, P_end}			},
X    {Nothing,	"DE",	"^#",		{P_d, P_IH, P_end}		},
X    {Nothing,	"DO",	Nothing,	{P_d, P_UW, P_end}		},
X    {Nothing,	"DOES",	Anything,	{P_d, P_AH, P_z, P_end}		},
X    {Nothing,	"DOING",Anything,	{P_d, P_UW, P_IH, P_NG, P_end}	},
X    {Nothing,	"DOW",	Anything,	{P_d, P_AW, P_end}		},
X    {Anything,	"DU",	"A",		{P_j, P_UW, P_end}		},
X    {Anything,	"D",	Anything,	{P_d, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule E_rules[] = {
X    {"#:",	"E",	Nothing,	{P_end}				},
X    {"':^",	"E",	Nothing,	{P_end}				},
X    {" :",	"E",	Nothing,	{P_IY, P_end}			},
X    {"#",	"ED",	Nothing,	{P_d, P_end}			},
X    {"#:",	"E",	"D ",		{P_end}				},
X    {Anything,	"EV",	"ER",		{P_EH, P_v, P_end}		},
X    {Anything,	"E",	"^%",		{P_IY, P_end}			},
X    {Anything,	"ERI",	"#",		{P_IY, P_r, P_IY, P_end}	},
X    {Anything,	"ERI",	Anything,	{P_EH, P_r, P_IH, P_end}	},
X    {"#:",	"ER",	"#",		{P_ER, P_end}			},
X    {Anything,	"ER",	"#",		{P_EH, P_r, P_end}		},
X    {Anything,	"ER",	Anything,	{P_ER, P_end}			},
X    {Nothing,	"EVEN",	Anything,	{P_IY, P_v, P_EH, P_n, P_end}	},
X    {"#:",	"E",	"W",		{P_end}				},
X    {"T",	"EW",	Anything,	{P_UW, P_end}			},
X    {"S",	"EW",	Anything,	{P_UW, P_end}			},
X    {"R",	"EW",	Anything,	{P_UW, P_end}			},
X    {"D",	"EW",	Anything,	{P_UW, P_end}			},
X    {"L",	"EW",	Anything,	{P_UW, P_end}			},
X    {"Z",	"EW",	Anything,	{P_UW, P_end}			},
X    {"N",	"EW",	Anything,	{P_UW, P_end}			},
X    {"J",	"EW",	Anything,	{P_UW, P_end}			},
X    {"TH",	"EW",	Anything,	{P_UW, P_end}			},
X    {"CH",	"EW",	Anything,	{P_UW, P_end}			},
X    {"SH",	"EW",	Anything,	{P_UW, P_end}			},
X    {Anything,	"EW",	Anything,	{P_y, P_UW, P_end}		},
X    {Anything,	"E",	"O",		{P_IY, P_end}			},
X    {"#:S",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:C",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:G",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:Z",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:X",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:J",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:CH",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:SH",	"ES",	Nothing,	{P_IH, P_z, P_end}		},
X    {"#:",	"E",	"S ",		{P_end}				},
X    {"#:",	"ELY",	Nothing,	{P_l, P_IY, P_end}		},
X    {"#:",	"EMENT",Anything,	{P_m, P_EH, P_n, P_t, P_end}	},
X    {Anything,	"EFUL",	Anything,	{P_f, P_UH, P_l, P_end}		},
X    {Anything,	"EE",	Anything,	{P_IY, P_end}			},
X    {Anything,	"EARN",	Anything,	{P_ER, P_n, P_end}		},
X    {Nothing,	"EAR",	"^",		{P_ER, P_end}			},
X    {Anything,	"EAD",	Anything,	{P_EH, P_d, P_end}		},
X    {"#:",	"EA",	Nothing,	{P_IY, P_AX, P_end}		},
X    {Anything,	"EA",	"SU",		{P_EH, P_end}			},
X    {Anything,	"EA",	Anything,	{P_IY, P_end}			},
X    {Anything,	"EIGH",	Anything,	{P_EY, P_end}			},
X    {Anything,	"EI",	Anything,	{P_IY, P_end}			},
X    {Nothing,	"EYE",	Anything,	{P_AY, P_end}			},
X    {Anything,	"EY",	Anything,	{P_IY, P_end}			},
X    {Anything,	"EU",	Anything,	{P_y, P_UW, P_end}		},
X    {Anything,	"E",	Anything,	{P_EH, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule F_rules[] = {
X    {Anything,	"FUL",	Anything,	{P_f, P_UH, P_l, P_end}		},
X    {Anything,	"F",	Anything,	{P_f, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule G_rules[] = {
X    {Anything,	"GIV",	Anything,	{P_g, P_IH, P_v, P_end}		},
X    {Nothing,	"G",	"I^",		{P_g, P_end}			},
X    {Anything,	"GE",	"T",		{P_g, P_EH, P_end}		},
X    {"SU",	"GGES",	Anything,	{P_g, P_j, P_EH, P_s, P_end}	},
X    {Anything,	"GG",	Anything,	{P_g, P_end}			},
X    {" B#",	"G",	Anything,	{P_g, P_end}			},
X    {Anything,	"G",	"+",		{P_j, P_end}			},
X    {Anything,	"GREAT",Anything,	{P_g, P_r, P_EY, P_t, P_end}	},
X    {"#",	"GH",	Anything,	{P_end}				},
X    {Anything,	"G",	Anything,	{P_g, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule H_rules[] = {
X    {Nothing,	"HAV",	Anything,	{P_HH, P_AE, P_v, P_end}	},
X    {Nothing,	"HERE",	Anything,	{P_HH, P_IY, P_r, P_end}	},
X    {Nothing,	"HOUR",	Anything,	{P_AW, P_ER, P_end}		},
X    {Anything,	"HOW",	Anything,	{P_HH, P_AW, P_end}		},
X    {Anything,	"H",	"#",		{P_HH, P_end}			},
X    {Anything,	"H",	Anything,	{P_end}				},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule I_rules[] = {
X    {Nothing,	"IN",	Anything,	{P_IH, P_n, P_end}		},
X    {Nothing,	"I",	Nothing,	{P_AY, P_end}			},
X    {Anything,	"IN",	"D",		{P_AY, P_n, P_end}		},
X    {Anything,	"IER",	Anything,	{P_IY, P_ER, P_end}		},
X    {"#:R",	"IED",	Anything,	{P_IY, P_d, P_end}		},
X    {Anything,	"IED",	Nothing,	{P_AY, P_d, P_end}		},
X    {Anything,	"IEN",	Anything,	{P_IY, P_EH, P_n, P_end}	},
X    {Anything,	"IE",	"T",		{P_AY, P_EH, P_end}		},
X    {" :",	"I",	"%",		{P_AY, P_end}			},
X    {Anything,	"I",	"%",		{P_IY, P_end}			},
X    {Anything,	"IE",	Anything,	{P_IY, P_end}			},
X    {Anything,	"I",	"^+:#",		{P_IH, P_end}			},
X    {Anything,	"IR",	"#",		{P_AY, P_r, P_end}		},
X    {Anything,	"IZ",	"%",		{P_AY, P_z, P_end}		},
X    {Anything,	"IS",	"%",		{P_AY, P_z, P_end}		},
X    {Anything,	"I",	"D%",		{P_AY, P_end}			},
X    {"+^",	"I",	"^+",		{P_IH, P_end}			},
X    {Anything,	"I",	"T%",		{P_AY, P_end}			},
X    {"#:^",	"I",	"^+",		{P_IH, P_end}			},
X    {Anything,	"I",	"^+",		{P_AY, P_end}			},
X    {Anything,	"IR",	Anything,	{P_ER, P_end}			},
X    {Anything,	"IGH",	Anything,	{P_AY, P_end}			},
X    {Anything,	"ILD",	Anything,	{P_AY, P_l, P_d, P_end}		},
X    {Anything,	"IGN",	Nothing,	{P_AY, P_n, P_end}		},
X    {Anything,	"IGN",	"^",		{P_AY, P_n, P_end}		},
X    {Anything,	"IGN",	"%",		{P_AY, P_n, P_end}		},
X    {Anything,	"IQUE",	Anything,	{P_IY, P_k, P_end}		},
X    {Anything,	"I",	Anything,	{P_IH, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule J_rules[] = {
X    {Anything,	"J",	Anything,	{P_j, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule K_rules[] = {
X    {Nothing,	"K",	"N",		{P_end}				},
X    {Anything,	"K",	Anything,	{P_k, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule L_rules[] = {
X    {Anything,	"LO",	"C#",		{P_l, P_OW, P_end}		},
X    {"L",	"L",	Anything,	{P_end}				},
X    {"#:^",	"L",	"%",		{P_AX, P_l, P_end}		},
X    {Anything,	"LEAD",	Anything,	{P_l, P_IY, P_d, P_end}		},
X    {Anything,	"L",	Anything,	{P_l, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule M_rules[] = {
X    {Anything,	"MOV",	Anything,	{P_m, P_UW, P_v, P_end}		},
X    {Anything,	"M",	Anything,	{P_m, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule N_rules[] = {
X    {"E",	"NG",	"+",		{P_n, P_j, P_end}		},
X    {Anything,	"NG",	"R",		{P_NG, P_g, P_end}		},
X    {Anything,	"NG",	"#",		{P_NG, P_g, P_end}		},
X    {Anything,	"NGL",	"%",		{P_NG, P_g, P_AX, P_l, P_end}	},
X    {Anything,	"NG",	Anything,	{P_NG, P_end}			},
X    {Anything,	"NK",	Anything,	{P_NG, P_k, P_end}		},
X    {Nothing,	"NOW",	Nothing,	{P_n, P_AW, P_end}		},
X    {Anything,	"N",	Anything,	{P_n, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule O_rules[] = {
X    {Anything,	"OF",	Nothing,	{P_AX, P_v, P_end}		},
X    {Anything,	"OROUGH",Anything,	{P_ER, P_OW, P_end}		},
X    {"#:",	"OR",	Nothing,	{P_ER, P_end}			},
X    {"#:",	"ORS",	Nothing,	{P_ER, P_z, P_end}		},
X    {Anything,	"OR",	Anything,	{P_AO, P_r, P_end}		},
X    {Nothing,	"ONE",	Anything,	{P_w, P_AH, P_n, P_end}		},
X    {Anything,	"OW",	Anything,	{P_OW, P_end}			},
X    {Nothing,	"OVER",	Anything,	{P_OW, P_v, P_ER, P_end}	},
X    {Anything,	"OV",	Anything,	{P_AH, P_v, P_end}		},
X    {Anything,	"O",	"^%",		{P_OW, P_end}			},
X    {Anything,	"O",	"^EN",		{P_OW, P_end}			},
X    {Anything,	"O",	"^I#",		{P_OW, P_end}			},
X    {Anything,	"OL",	"D",		{P_OW, P_l, P_end}		},
X    {Anything,	"OUGHT",Anything,	{P_AO, P_t, P_end}		},
X    {Anything,	"OUGH",	Anything,	{P_AH, P_f, P_end}		},
X    {Nothing,	"OU",	Anything,	{P_AW, P_end}			},
X    {"H",	"OU",	"S#",		{P_AW, P_end}			},
X    {Anything,	"OUS",	Anything,	{P_AX, P_s, P_end}		},
X    {Anything,	"OUR",	Anything,	{P_AO, P_r, P_end}		},
X    {Anything,	"OULD",	Anything,	{P_UH, P_d, P_end}		},
X    {"^",	"OU",	"^L",		{P_AH, P_end}			},
X    {Anything,	"OUP",	Anything,	{P_UW, P_p, P_end}		},
X    {Anything,	"OU",	Anything,	{P_AW, P_end}			},
X    {Anything,	"OY",	Anything,	{P_OY, P_end}			},
X    {Anything,	"OING",	Anything,	{P_OW, P_IH, P_NG, P_end}	},
X    {Anything,	"OI",	Anything,	{P_OY, P_end}			},
X    {Anything,	"OOR",	Anything,	{P_AO, P_r, P_end}		},
X    {Anything,	"OOK",	Anything,	{P_UH, P_k, P_end}		},
X    {Anything,	"OOD",	Anything,	{P_UH, P_d, P_end}		},
X    {Anything,	"OO",	Anything,	{P_UW, P_end}			},
X    {Anything,	"O",	"E",		{P_OW, P_end}			},
X    {Anything,	"O",	Nothing,	{P_OW, P_end}			},
X    {Anything,	"OA",	Anything,	{P_OW, P_end}			},
X    {Nothing,	"ONLY",	Anything,	{P_OW, P_n, P_l, P_IY, P_end}	},
X    {Nothing,	"ONCE",	Anything,	{P_w, P_AH, P_n, P_s, P_end}	},
X    {Anything,	"ON'T",	Anything,	{P_OW, P_n, P_t, P_end}		},
X    {"C",	"O",	"N",		{P_AA, P_end}			},
X    {Anything,	"O",	"NG",		{P_AO, P_end}			},
X    {" :^",	"O",	"N",		{P_AH, P_end}			},
X    {"I",	"ON",	Anything,	{P_AX, P_n, P_end}		},
X    {"#:",	"ON",	Nothing,	{P_AX, P_n, P_end}		},
X    {"#^",	"ON",	Anything,	{P_AX, P_n, P_end}		},
X    {Anything,	"O",	"ST ",		{P_OW, P_end}			},
X    {Anything,	"OF",	"^",		{P_AO, P_f, P_end}		},
X    {Anything,	"OTHER",Anything,	{P_AH, P_DH, P_ER, P_end}	},
X    {Anything,	"OSS",	Nothing,	{P_AO, P_s, P_end}		},
X    {"#:^",	"OM",	Anything,	{P_AH, P_m, P_end}		},
X    {Anything,	"O",	Anything,	{P_AA, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule P_rules[] = {
X    {Anything,	"PH",	Anything,	{P_f, P_end}			},
X    {Anything,	"PEOP",	Anything,	{P_p, P_IY, P_p, P_end}		},
X    {Anything,	"POW",	Anything,	{P_p, P_AW, P_end}		},
X    {Anything,	"PUT",	Nothing,	{P_p, P_UH, P_t, P_end}		},
X    {Anything,	"P",	Anything,	{P_p, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule Q_rules[] = {
X    {Anything,	"QUAR",	Anything,	{P_k, P_w, P_AO, P_r, P_end}	},
X    {Anything,	"QU",	Anything,	{P_k, P_w, P_end}		},
X    {Anything,	"Q",	Anything,	{P_k, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule R_rules[] = {
X    {Nothing,	"RE",	"^#",		{P_r, P_IY, P_end}		},
X    {Anything,	"R",	Anything,	{P_r, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule S_rules[] = {
X    {Anything,	"SH",	Anything,	{P_SH, P_end}			},
X    {"#",	"SION",	Anything,	{P_ZH, P_AX, P_n, P_end}	},
X    {Anything,	"SOME",	Anything,	{P_s, P_AH, P_m, P_end}		},
X    {"#",	"SUR",	"#",		{P_ZH, P_ER, P_end}		},
X    {Anything,	"SUR",	"#",		{P_SH, P_ER, P_end}		},
X    {"#",	"SU",	"#",		{P_ZH, P_UW, P_end}		},
X    {"#",	"SSU",	"#",		{P_SH, P_UW, P_end}		},
X    {"#",	"SED",	Nothing,	{P_z, P_d, P_end}		},
X    {"#",	"S",	"#",		{P_z, P_end}			},
X    {Anything,	"SAID",	Anything,	{P_s, P_EH, P_d, P_end}		},
X    {"^",	"SION",	Anything,	{P_SH, P_AX, P_n, P_end}	},
X    {Anything,	"S",	"S",		{P_end}				},
X    {".",	"S",	Nothing,	{P_z, P_end}			},
X    {"#:.E",	"S",	Nothing,	{P_z, P_end}			},
X    {"#:^##",	"S",	Nothing,	{P_z, P_end}			},
X    {"#:^#",	"S",	Nothing,	{P_s, P_end}			},
X    {"U",	"S",	Nothing,	{P_s, P_end}			},
X    {" :#",	"S",	Nothing,	{P_z, P_end}			},
X    {Nothing,	"SCH",	Anything,	{P_s, P_k, P_end}		},
X    {Anything,	"S",	"C+",		{P_end}				},
X    {"#",	"SM",	Anything,	{P_z, P_m, P_end}		},
X    {"#",	"SN",	"'",		{P_z, P_AX, P_n, P_end}		},
X    {Anything,	"S",	Anything,	{P_s, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule T_rules[] = {
X    {Nothing,	"THE",	Nothing,	{P_DH, P_AX, P_end}		},
X    {Anything,	"TO",	Nothing,	{P_t, P_UW, P_end}		},
X    {Anything,	"THAT",	Nothing,	{P_DH, P_AE, P_t, P_end}	},
X    {Nothing,	"THIS",	Nothing,	{P_DH, P_IH, P_s, P_end}	},
X    {Nothing,	"THEY",	Anything,	{P_DH, P_EY, P_end}		},
X    {Nothing,	"THERE",Anything,	{P_DH, P_EH, P_r, P_end}	},
X    {Anything,	"THER",	Anything,	{P_DH, P_ER, P_end}		},
X    {Anything,	"THEIR",Anything,	{P_DH, P_EH, P_r, P_end}	},
X    {Nothing,	"THAN",	Nothing,	{P_DH, P_AE, P_n, P_end}	},
X    {Nothing,	"THEM",	Nothing,	{P_DH, P_EH, P_m, P_end}	},
X    {Anything,	"THESE",Nothing,	{P_DH, P_IY, P_z, P_end}	},
X    {Nothing,	"THEN",	Anything,	{P_DH, P_EH, P_n, P_end}	},
X    {Anything,	"THROUGH",Anything,	{P_TH, P_r, P_UW, P_end}	},
X    {Anything,	"THOSE",Anything,	{P_DH, P_OW, P_z, P_end}	},
X    {Anything,	"THOUGH",Nothing,	{P_DH, P_OW, P_end}		},
X    {Nothing,	"THUS",	Anything,	{P_DH, P_AH, P_s, P_end}	},
X    {Anything,	"TH",	Anything,	{P_TH, P_end}			},
X    {"#:",	"TED",	Nothing,	{P_t, P_IH, P_d, P_end}		},
X    {"S",	"TI",	"#N",		{P_CH, P_end}			},
X    {Anything,	"TI",	"O",		{P_SH, P_end}			},
X    {Anything,	"TI",	"A",		{P_SH, P_end}			},
X    {Anything,	"TIEN",	Anything,	{P_SH, P_AX, P_n, P_end}	},
X    {Anything,	"TUR",	"#",		{P_CH, P_ER, P_end}		},
X    {Anything,	"TU",	"A",		{P_CH, P_UW, P_end}		},
X    {Nothing,	"TWO",	Anything,	{P_t, P_UW, P_end}		},
X    {Anything,	"T",	Anything,	{P_t, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule U_rules[] = {
X    {Nothing,	"UN",	"I",		{P_y, P_UW, P_n, P_end}		},
X    {Nothing,	"UN",	Anything,	{P_AH, P_n, P_end}		},
X    {Nothing,	"UPON",	Anything,	{P_AX, P_p, P_AO, P_n, P_end}	},
X    {"T",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"S",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"R",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"D",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"L",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"Z",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"N",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"J",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"TH",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"CH",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {"SH",	"UR",	"#",		{P_UH, P_r, P_end}		},
X    {Anything,	"UR",	"#",		{P_y, P_UH, P_r, P_end}		},
X    {Anything,	"UR",	Anything,	{P_ER, P_end}			},
X    {Anything,	"U",	"^ ",		{P_AH, P_end}			},
X    {Anything,	"U",	"^^",		{P_AH, P_end}			},
X    {Anything,	"UY",	Anything,	{P_AY, P_end}			},
X    {" G",	"U",	"#",		{P_end}				},
X    {"G",	"U",	"%",		{P_end}				},
X    {"G",	"U",	"#",		{P_w, P_end}			},
X    {"#N",	"U",	Anything,	{P_y, P_UW, P_end}		},
X    {"T",	"U",	Anything,	{P_UW, P_end}			},
X    {"S",	"U",	Anything,	{P_UW, P_end}			},
X    {"R",	"U",	Anything,	{P_UW, P_end}			},
X    {"D",	"U",	Anything,	{P_UW, P_end}			},
X    {"L",	"U",	Anything,	{P_UW, P_end}			},
X    {"Z",	"U",	Anything,	{P_UW, P_end}			},
X    {"N",	"U",	Anything,	{P_UW, P_end}			},
X    {"J",	"U",	Anything,	{P_UW, P_end}			},
X    {"TH",	"U",	Anything,	{P_UW, P_end}			},
X    {"CH",	"U",	Anything,	{P_UW, P_end}			},
X    {"SH",	"U",	Anything,	{P_UW, P_end}			},
X    {Anything,	"U",	Anything,	{P_y, P_UW, P_end}		},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule V_rules[] = {
X    {Anything,	"VIEW",	Anything,	{P_v, P_y, P_UW, P_end}		},
X    {Anything,	"V",	Anything,	{P_v, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule W_rules[] = {
X    {Nothing,	"WERE",	Anything,	{P_w, P_ER, P_end}		},
X    {Anything,	"WA",	"S",		{P_w, P_AA, P_end}		},
X    {Anything,	"WA",	"T",		{P_w, P_AA, P_end}		},
X    {Anything,	"WHERE",Anything,	{P_WH, P_EH, P_r, P_end}	},
X    {Anything,	"WHAT",	Anything,	{P_WH, P_AA, P_t, P_end}	},
X    {Anything,	"WHOL",	Anything,	{P_HH, P_OW, P_l, P_end}		},
X    {Anything,	"WHO",	Anything,	{P_HH, P_UW, P_end}		},
X    {Anything,	"WH",	Anything,	{P_WH, P_end}			},
X    {Anything,	"WAR",	Anything,	{P_w, P_AO, P_r, P_end}		},
X    {Anything,	"WOR",	"^",		{P_w, P_ER, P_end}		},
X    {Anything,	"WR",	Anything,	{P_r, P_end}			},
X    {Anything,	"W",	Anything,	{P_w, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule X_rules[] = {
X    {Anything,	"X",	Anything,	{P_k, P_s, P_end}		},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule Y_rules[] = {
X    {Anything,	"YOUNG",Anything,	{P_y, P_AH, P_NG, P_end}	},
X    {Nothing,	"YOU",	Anything,	{P_y, P_UW, P_end}		},
X    {Nothing,	"YES",	Anything,	{P_y, P_EH, P_s, P_end}		},
X    {Nothing,	"Y",	Anything,	{P_y, P_end}			},
X    {"#:^",	"Y",	Nothing,	{P_IY, P_end}			},
X    {"#:^",	"Y",	"I",		{P_IY, P_end}			},
X    {" :",	"Y",	Nothing,	{P_AY, P_end}			},
X    {" :",	"Y",	"#",		{P_AY, P_end}			},
X    {" :",	"Y",	"^+:#",		{P_IH, P_end}			},
X    {" :",	"Y",	"^#",		{P_AY, P_end}			},
X    {Anything,	"Y",	Anything,	{P_IH, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
Xstatic struct rule Z_rules[] = {
X    {Anything,	"Z",	Anything,	{P_z, P_end}			},
X    {Anything,	0,	Anything,	{P_end}				}
X};
X
X
X
Xstruct rule *Rules[] =
X	{
X	punct_rules,
X	A_rules, B_rules, C_rules, D_rules, E_rules, F_rules, G_rules, 
X	H_rules, I_rules, J_rules, K_rules, L_rules, M_rules, N_rules, 
X	O_rules, P_rules, Q_rules, R_rules, S_rules, T_rules, U_rules, 
X	V_rules, W_rules, X_rules, Y_rules, Z_rules
X	};
X
X#else /* DATA */
Xextern struct rule rules[];
X#endif
X
X#define RIDX_PUNC	0	/* Rules[] index of punctuation rules	*/
X#define RIDX_A		1	/* Rules[] index of A_rules		*/
X#define RULECNT	(sizeof(Rules) / sizeof(Rules[0])) /* # of Rule tables	*/
END_OF_phoneme.h
if test 23805 -ne `wc -c <phoneme.h`; then
    echo shar: \"phoneme.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0