xref: /plan9/sys/src/cmd/spell/sprog.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ctype.h>
53e12c5d1SDavid du Colombier #include "code.h"
63e12c5d1SDavid du Colombier 
7219b2ee8SDavid du Colombier /* fig leaves for possibly signed char quantities */
8219b2ee8SDavid du Colombier #define ISUPPER(c)	isupper((c)&0xff)
9219b2ee8SDavid du Colombier #define ISLOWER(c)	islower((c)&0xff)
10219b2ee8SDavid du Colombier #define	ISALPHA(c)	isalpha((c)&0xff)
11219b2ee8SDavid du Colombier #define	ISDIGIT(c)	isdigit((c)&0xff)
12219b2ee8SDavid du Colombier #define ISVOWEL(c)	voweltab[(c)&0xff]
13219b2ee8SDavid du Colombier #define Tolower(c)	(ISUPPER(c)? (c)-'A'+'a': (c))
143e12c5d1SDavid du Colombier #define pair(a,b)	(((a)<<8) | (b))
153e12c5d1SDavid du Colombier #define DLEV		2
16219b2ee8SDavid du Colombier #define DSIZ		40
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier typedef	long	Bits;
193e12c5d1SDavid du Colombier #define	Set(h, f)	((long)(h) & (f))
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier Bits 	nop(char*, char*, char*, int, int);
223e12c5d1SDavid du Colombier Bits 	strip(char*, char*, char*, int, int);
233e12c5d1SDavid du Colombier Bits 	ize(char*, char*, char*, int, int);
243e12c5d1SDavid du Colombier Bits 	i_to_y(char*, char*, char*, int, int);
253e12c5d1SDavid du Colombier Bits 	ily(char*, char*, char*, int, int);
263e12c5d1SDavid du Colombier Bits 	subst(char*, char*, char*, int, int);
273e12c5d1SDavid du Colombier Bits 	CCe(char*, char*, char*, int, int);
283e12c5d1SDavid du Colombier Bits 	tion(char*, char*, char*, int, int);
293e12c5d1SDavid du Colombier Bits 	an(char*, char*, char*, int, int);
303e12c5d1SDavid du Colombier Bits 	s(char*, char*, char*, int, int);
313e12c5d1SDavid du Colombier Bits 	es(char*, char*, char*, int, int);
323e12c5d1SDavid du Colombier Bits 	bility(char*, char*, char*, int, int);
333e12c5d1SDavid du Colombier Bits 	y_to_e(char*, char*, char*, int, int);
343e12c5d1SDavid du Colombier Bits 	VCe(char*, char*, char*, int, int);
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier Bits 	trypref(char*, char*, int, int);
373e12c5d1SDavid du Colombier Bits	tryword(char*, char*, int, int);
383e12c5d1SDavid du Colombier Bits 	trysuff(char*, int, int);
393e12c5d1SDavid du Colombier Bits	dict(char*, char*);
403e12c5d1SDavid du Colombier void	typeprint(Bits);
413e12c5d1SDavid du Colombier void	pcomma(char*);
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier void	ise(void);
443e12c5d1SDavid du Colombier int	ordinal(void);
453e12c5d1SDavid du Colombier char*	skipv(char*);
463e12c5d1SDavid du Colombier int	inun(char*, Bits);
473e12c5d1SDavid du Colombier char*	ztos(char*);
483e12c5d1SDavid du Colombier void	readdict(char*);
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier typedef	struct	Ptab	Ptab;
513e12c5d1SDavid du Colombier struct	Ptab
523e12c5d1SDavid du Colombier {
533e12c5d1SDavid du Colombier 	char*	s;
543e12c5d1SDavid du Colombier 	int	flag;
553e12c5d1SDavid du Colombier };
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier typedef	struct	Suftab	Suftab;
583e12c5d1SDavid du Colombier struct	Suftab
593e12c5d1SDavid du Colombier {
603e12c5d1SDavid du Colombier 	char	*suf;
613e12c5d1SDavid du Colombier 	Bits	(*p1)(char*, char*, char*, int, int);
623e12c5d1SDavid du Colombier 	int	n1;
633e12c5d1SDavid du Colombier 	char	*d1;
643e12c5d1SDavid du Colombier 	char	*a1;
653e12c5d1SDavid du Colombier 	int	flag;
663e12c5d1SDavid du Colombier 	int	affixable;
673e12c5d1SDavid du Colombier 	Bits	(*p2)(char*, char*, char*, int, int);
683e12c5d1SDavid du Colombier 	int	n2;
693e12c5d1SDavid du Colombier 	char	*d2;
703e12c5d1SDavid du Colombier 	char	*a2;
713e12c5d1SDavid du Colombier };
723e12c5d1SDavid du Colombier 
73219b2ee8SDavid du Colombier Suftab	staba[] = {
74219b2ee8SDavid du Colombier 	{"aibohp",subst,1,"-e+ia","",NOUN, NOUN},
75219b2ee8SDavid du Colombier 	0
76219b2ee8SDavid du Colombier };
77219b2ee8SDavid du Colombier 
783e12c5d1SDavid du Colombier Suftab	stabc[] =
793e12c5d1SDavid du Colombier {
80219b2ee8SDavid du Colombier 	{"cai",strip,1,"","+c",N_AFFIX, ADJ|NOUN},
813e12c5d1SDavid du Colombier 	{"citsi",strip,2,"","+ic",N_AFFIX, ADJ | N_AFFIX | NOUN},
823e12c5d1SDavid du Colombier 	{"citi",ize,1,"-e+ic","",N_AFFIX, ADJ },
833e12c5d1SDavid du Colombier 	{"cihparg",i_to_y,1,"-y+ic","",NOUN, ADJ|NOUN },
843e12c5d1SDavid du Colombier 	{"cipocs",ize,1,"-e+ic","",NOUN, ADJ },
853e12c5d1SDavid du Colombier 	{"cirtem",i_to_y,1,"-y+ic","",NOUN, ADJ },
863e12c5d1SDavid du Colombier 	{"cigol",i_to_y,1,"-y+ic","",NOUN, ADJ },
873e12c5d1SDavid du Colombier 	{"cimono",i_to_y,1,"-y+ic","",NOUN, ADJ },
88219b2ee8SDavid du Colombier 	{"cibohp",subst,1,"-e+ic","",NOUN, ADJ },
893e12c5d1SDavid du Colombier 	0
903e12c5d1SDavid du Colombier };
913e12c5d1SDavid du Colombier Suftab	stabd[] =
923e12c5d1SDavid du Colombier {
93219b2ee8SDavid du Colombier 	{"de",strip,1,"","+d",ED,ADJ |COMP,i_to_y,2,"-y+ied","+ed"},
943e12c5d1SDavid du Colombier 	{"dooh",ily,4,"-y+ihood","+hood",NOUN | ADV, NOUN},
953e12c5d1SDavid du Colombier 	0
963e12c5d1SDavid du Colombier };
973e12c5d1SDavid du Colombier Suftab	stabe[] =
983e12c5d1SDavid du Colombier {
993e12c5d1SDavid du Colombier 	/*
1003e12c5d1SDavid du Colombier 	 * V_affix for comment ->commence->commentment??
1013e12c5d1SDavid du Colombier 	 */
102219b2ee8SDavid du Colombier 	{"ecna",subst,1,"-t+ce","",ADJ,N_AFFIX|_Y|NOUN|VERB|ACTOR|V_AFFIX},
103219b2ee8SDavid du Colombier 	{"ecne",subst,1,"-t+ce","",ADJ,N_AFFIX|_Y|NOUN|VERB|ACTOR|V_AFFIX},
1043e12c5d1SDavid du Colombier 	{"elbaif",i_to_y,4,"-y+iable","",V_IRREG,ADJ},
1053e12c5d1SDavid du Colombier 	{"elba",CCe,4,"-e+able","+able",V_AFFIX,ADJ},
1063e12c5d1SDavid du Colombier 	{"evi",subst,0,"-ion+ive","",N_AFFIX | V_AFFIX,NOUN | N_AFFIX| ADJ},
1073e12c5d1SDavid du Colombier 	{"ezi",CCe,3,"-e+ize","+ize",N_AFFIX|ADJ ,V_AFFIX | VERB |ION | COMP},
1083e12c5d1SDavid du Colombier 	{"ekil",strip,4,"","+like",N_AFFIX ,ADJ},
1093e12c5d1SDavid du Colombier 	0
1103e12c5d1SDavid du Colombier };
1113e12c5d1SDavid du Colombier Suftab	stabg[] =
1123e12c5d1SDavid du Colombier {
113219b2ee8SDavid du Colombier 	{"gniee",strip,3,"","+ing",V_IRREG ,ADJ|NOUN},
114219b2ee8SDavid du Colombier 	{"gnikam",strip,6,"","+making",NOUN,NOUN},
115219b2ee8SDavid du Colombier 	{"gnipeek",strip,7,"","+keeping",NOUN,NOUN},
1163e12c5d1SDavid du Colombier 	{"gni",CCe,3,"-e+ing","+ing",V_IRREG ,ADJ|ED|NOUN},
1173e12c5d1SDavid du Colombier 	0
1183e12c5d1SDavid du Colombier };
1193e12c5d1SDavid du Colombier Suftab	stabl[] =
1203e12c5d1SDavid du Colombier {
121219b2ee8SDavid du Colombier 	{"ladio",strip,2,"","+al",NOUN |ADJ,ADJ},
1223e12c5d1SDavid du Colombier 	{"laci",strip,2,"","+al",NOUN |ADJ,ADJ |NOUN|N_AFFIX},
1233e12c5d1SDavid du Colombier 	{"latnem",strip,2,"","+al",N_AFFIX,ADJ},
1243e12c5d1SDavid du Colombier 	{"lanoi",strip,2,"","+al",N_AFFIX,ADJ|NOUN},
1253e12c5d1SDavid du Colombier 	{"luf",ily,3,"-y+iful","+ful",N_AFFIX,ADJ | NOUN},
1263e12c5d1SDavid du Colombier 	0
1273e12c5d1SDavid du Colombier };
1283e12c5d1SDavid du Colombier Suftab	stabm[] =
1293e12c5d1SDavid du Colombier {
1303e12c5d1SDavid du Colombier 		/* congregational + ism */
1313e12c5d1SDavid du Colombier 	{"msi",CCe,3,"-e+ism","ism",N_AFFIX|ADJ,NOUN},
1323e12c5d1SDavid du Colombier 	{"margo",subst,-1,"-ph+m","",NOUN,NOUN},
1333e12c5d1SDavid du Colombier 	0
1343e12c5d1SDavid du Colombier };
1353e12c5d1SDavid du Colombier Suftab	stabn[] =
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier 	{"noitacifi",i_to_y,6,"-y+ication","",ION,NOUN | N_AFFIX},
1383e12c5d1SDavid du Colombier 	{"noitazi",ize,4,"-e+ation","",ION,NOUN| N_AFFIX},
1393e12c5d1SDavid du Colombier 	{"noit",tion,3,"-e+ion","+ion",ION,NOUN| N_AFFIX | V_AFFIX |VERB|ACTOR},
1403e12c5d1SDavid du Colombier 	{"naino",an,3,"","+ian",NOUN|PROP_COLLECT,NOUN| N_AFFIX},
1413e12c5d1SDavid du Colombier 	{"namow",strip,5,"","+woman",MAN,PROP_COLLECT|N_AFFIX},
1423e12c5d1SDavid du Colombier 	{"nam",strip,3,"","+man",MAN,PROP_COLLECT | N_AFFIX | VERB},
1433e12c5d1SDavid du Colombier 	{"na",an,1,"","+n",NOUN|PROP_COLLECT,NOUN | N_AFFIX},
1443e12c5d1SDavid du Colombier 	{"nemow",strip,5,"","+women",MAN,PROP_COLLECT},
1453e12c5d1SDavid du Colombier 	{"nem",strip,3,"","+man",MAN,PROP_COLLECT},
146219b2ee8SDavid du Colombier 	{"nosrep",strip,6,"","+person",MAN,PROP_COLLECT},
1473e12c5d1SDavid du Colombier 	0
1483e12c5d1SDavid du Colombier };
1493e12c5d1SDavid du Colombier Suftab	stabp[] =
1503e12c5d1SDavid du Colombier {
1513e12c5d1SDavid du Colombier 	{"pihs",strip,4,"","+ship",NOUN|PROP_COLLECT,NOUN| N_AFFIX},
1523e12c5d1SDavid du Colombier 	0
1533e12c5d1SDavid du Colombier };
1543e12c5d1SDavid du Colombier Suftab	stabr[] =
1553e12c5d1SDavid du Colombier {
1563e12c5d1SDavid du Colombier 	{"rehparg",subst,1,"-y+er","",ACTOR,NOUN,strip,2,"","+er"},
1573e12c5d1SDavid du Colombier 	{"reyhparg",nop,0,"","",0,NOUN},
158219b2ee8SDavid du Colombier 	{"reyl",nop,0,"","",0,NOUN},
159219b2ee8SDavid du Colombier 	{"rekam",strip,5,"","+maker",NOUN,NOUN},
160219b2ee8SDavid du Colombier 	{"repeek",strip,6,"","+keeper",NOUN,NOUN},
1613e12c5d1SDavid du Colombier 	{"re",strip,1,"","+r",ACTOR,NOUN | N_AFFIX|VERB|ADJ,	i_to_y,2,"-y+ier","+er"},
1623e12c5d1SDavid du Colombier 	{"rota",tion,2,"-e+or","",ION,NOUN| N_AFFIX|_Y},
1633e12c5d1SDavid du Colombier 	{"rotc",tion,2,"","+or",ION,NOUN| N_AFFIX},
1643e12c5d1SDavid du Colombier 	{"rotp",tion,2,"","+or",ION,NOUN| N_AFFIX},
1653e12c5d1SDavid du Colombier 	0
1663e12c5d1SDavid du Colombier };
1673e12c5d1SDavid du Colombier Suftab	stabs[] =
1683e12c5d1SDavid du Colombier {
1693e12c5d1SDavid du Colombier 	{"ssen",ily,4,"-y+iness","+ness",ADJ|ADV,NOUN| N_AFFIX},
170219b2ee8SDavid du Colombier 	{"ssel",ily,4,"-y+iless","+less",NOUN | PROP_COLLECT,ADJ },
1713e12c5d1SDavid du Colombier 	{"se",s,1,"","+s",NOUN | V_IRREG,DONT_TOUCH ,	es,2,"-y+ies","+es"},
1723e12c5d1SDavid du Colombier 	{"s'",s,2,"","+'s",PROP_COLLECT | NOUN,DONT_TOUCH },
1733e12c5d1SDavid du Colombier 	{"s",s,1,"","+s",NOUN | V_IRREG,DONT_TOUCH  },
1743e12c5d1SDavid du Colombier 	0
1753e12c5d1SDavid du Colombier };
1763e12c5d1SDavid du Colombier Suftab	stabt[] =
1773e12c5d1SDavid du Colombier {
1783e12c5d1SDavid du Colombier 	{"tnem",strip,4,"","+ment",V_AFFIX,NOUN | N_AFFIX | ADJ|VERB},
1793e12c5d1SDavid du Colombier 	{"tse",strip,2,"","+st",EST,DONT_TOUCH,	i_to_y,3,"-y+iest","+est" },
1803e12c5d1SDavid du Colombier 	{"tsigol",i_to_y,2,"-y+ist","",N_AFFIX,NOUN | N_AFFIX},
1813e12c5d1SDavid du Colombier 	{"tsi",CCe,3,"-e+ist","+ist",N_AFFIX|ADJ,NOUN | N_AFFIX|COMP},
1823e12c5d1SDavid du Colombier 	0
1833e12c5d1SDavid du Colombier };
1843e12c5d1SDavid du Colombier Suftab	staby[] =
1853e12c5d1SDavid du Colombier {
186219b2ee8SDavid du Colombier 	{"ycna",subst,1,"-t+cy","",ADJ | N_AFFIX,NOUN | N_AFFIX},
187219b2ee8SDavid du Colombier 	{"ycne",subst,1,"-t+cy","",ADJ | N_AFFIX,NOUN | N_AFFIX},
1883e12c5d1SDavid du Colombier 	{"ytilib",bility,5,"-le+ility","",ADJ | V_AFFIX,NOUN | N_AFFIX},
1893e12c5d1SDavid du Colombier 	{"ytisuo",nop,0,"","",NOUN},
190219b2ee8SDavid du Colombier 	{"ytilb",nop,0,"","",0,NOUN},
1913e12c5d1SDavid du Colombier 	{"yti",CCe,3,"-e+ity","+ity",ADJ ,NOUN | N_AFFIX },
1923e12c5d1SDavid du Colombier 	{"ylb",y_to_e,1,"-e+y","",ADJ,ADV},
1933e12c5d1SDavid du Colombier 	{"ylc",nop,0,"","",0},
194219b2ee8SDavid du Colombier 	{"ylelb",nop,0,"","",0},
195219b2ee8SDavid du Colombier 	{"ylelp",nop,0,"","",0},
1963e12c5d1SDavid du Colombier 	{"yl",ily,2,"-y+ily","+ly",ADJ,ADV|COMP},
1973e12c5d1SDavid du Colombier 	{"yrtem",subst,0,"-er+ry","",NOUN,NOUN | N_AFFIX},
1983e12c5d1SDavid du Colombier 	{"y",CCe,1,"-e+y","+y",_Y,ADJ|COMP},
1993e12c5d1SDavid du Colombier 	0
2003e12c5d1SDavid du Colombier };
2013e12c5d1SDavid du Colombier Suftab	stabz[] =
2023e12c5d1SDavid du Colombier {
2033e12c5d1SDavid du Colombier 	0
2043e12c5d1SDavid du Colombier };
2053e12c5d1SDavid du Colombier Suftab*	suftab[] =
2063e12c5d1SDavid du Colombier {
207219b2ee8SDavid du Colombier 	staba,
2083e12c5d1SDavid du Colombier 	stabz,
2093e12c5d1SDavid du Colombier 	stabc,
2103e12c5d1SDavid du Colombier 	stabd,
2113e12c5d1SDavid du Colombier 	stabe,
2123e12c5d1SDavid du Colombier 	stabz,
2133e12c5d1SDavid du Colombier 	stabg,
2143e12c5d1SDavid du Colombier 	stabz,
2153e12c5d1SDavid du Colombier 	stabz,
2163e12c5d1SDavid du Colombier 	stabz,
2173e12c5d1SDavid du Colombier 	stabz,
2183e12c5d1SDavid du Colombier 	stabl,
2193e12c5d1SDavid du Colombier 	stabm,
2203e12c5d1SDavid du Colombier 	stabn,
2213e12c5d1SDavid du Colombier 	stabz,
2223e12c5d1SDavid du Colombier 	stabp,
2233e12c5d1SDavid du Colombier 	stabz,
2243e12c5d1SDavid du Colombier 	stabr,
2253e12c5d1SDavid du Colombier 	stabs,
2263e12c5d1SDavid du Colombier 	stabt,
2273e12c5d1SDavid du Colombier 	stabz,
2283e12c5d1SDavid du Colombier 	stabz,
2293e12c5d1SDavid du Colombier 	stabz,
2303e12c5d1SDavid du Colombier 	stabz,
2313e12c5d1SDavid du Colombier 	staby,
2323e12c5d1SDavid du Colombier 	stabz,
2333e12c5d1SDavid du Colombier };
2343e12c5d1SDavid du Colombier 
2353e12c5d1SDavid du Colombier Ptab	ptaba[] =
2363e12c5d1SDavid du Colombier {
2373e12c5d1SDavid du Colombier 	"anti", 0,
2383e12c5d1SDavid du Colombier 	"auto", 0,
2393e12c5d1SDavid du Colombier 	0
2403e12c5d1SDavid du Colombier };
2413e12c5d1SDavid du Colombier Ptab	ptabb[] =
2423e12c5d1SDavid du Colombier {
2433e12c5d1SDavid du Colombier 	"bio", 0,
2443e12c5d1SDavid du Colombier 	0
2453e12c5d1SDavid du Colombier };
2463e12c5d1SDavid du Colombier Ptab	ptabc[] =
2473e12c5d1SDavid du Colombier {
2483e12c5d1SDavid du Colombier 	"counter", 0,
2493e12c5d1SDavid du Colombier 	0
2503e12c5d1SDavid du Colombier };
2513e12c5d1SDavid du Colombier Ptab	ptabd[] =
2523e12c5d1SDavid du Colombier {
2533e12c5d1SDavid du Colombier 	"dis", 0,
2543e12c5d1SDavid du Colombier 	0
2553e12c5d1SDavid du Colombier };
2563e12c5d1SDavid du Colombier Ptab	ptabe[] =
2573e12c5d1SDavid du Colombier {
2583e12c5d1SDavid du Colombier 	"electro", 0,
2593e12c5d1SDavid du Colombier 	0
2603e12c5d1SDavid du Colombier };
2613e12c5d1SDavid du Colombier Ptab	ptabf[] =
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier 	"femto", 0,
2643e12c5d1SDavid du Colombier 	0
2653e12c5d1SDavid du Colombier };
2663e12c5d1SDavid du Colombier Ptab	ptabg[] =
2673e12c5d1SDavid du Colombier {
2683e12c5d1SDavid du Colombier 	"geo", 0,
2693e12c5d1SDavid du Colombier 	"giga", 0,
2703e12c5d1SDavid du Colombier 	0
2713e12c5d1SDavid du Colombier };
2723e12c5d1SDavid du Colombier Ptab	ptabh[] =
2733e12c5d1SDavid du Colombier {
2743e12c5d1SDavid du Colombier 	"hyper", 0,
2753e12c5d1SDavid du Colombier 	0
2763e12c5d1SDavid du Colombier };
2773e12c5d1SDavid du Colombier Ptab	ptabi[] =
2783e12c5d1SDavid du Colombier {
279219b2ee8SDavid du Colombier 	"immuno", 0,
2803e12c5d1SDavid du Colombier 	"im", IN,
2813e12c5d1SDavid du Colombier 	"intra", 0,
2823e12c5d1SDavid du Colombier 	"inter", 0,
2833e12c5d1SDavid du Colombier 	"in", IN,
2843e12c5d1SDavid du Colombier 	"ir", IN,
2853e12c5d1SDavid du Colombier 	"iso", 0,
2863e12c5d1SDavid du Colombier 	0
2873e12c5d1SDavid du Colombier };
2883e12c5d1SDavid du Colombier Ptab	ptabj[] =
2893e12c5d1SDavid du Colombier {
2903e12c5d1SDavid du Colombier 	0
2913e12c5d1SDavid du Colombier };
2923e12c5d1SDavid du Colombier Ptab	ptabk[] =
2933e12c5d1SDavid du Colombier {
2943e12c5d1SDavid du Colombier 	"kilo", 0,
2953e12c5d1SDavid du Colombier 	0
2963e12c5d1SDavid du Colombier };
2973e12c5d1SDavid du Colombier Ptab	ptabl[] =
2983e12c5d1SDavid du Colombier {
2993e12c5d1SDavid du Colombier 	0
3003e12c5d1SDavid du Colombier };
3013e12c5d1SDavid du Colombier Ptab	ptabm[] =
3023e12c5d1SDavid du Colombier {
3033e12c5d1SDavid du Colombier 	"magneto", 0,
3043e12c5d1SDavid du Colombier 	"mega", 0,
3053e12c5d1SDavid du Colombier 	"meta", 0,
3063e12c5d1SDavid du Colombier 	"micro", 0,
3073e12c5d1SDavid du Colombier 	"mid", 0,
3083e12c5d1SDavid du Colombier 	"milli", 0,
309219b2ee8SDavid du Colombier 	"mini", 0,
3103e12c5d1SDavid du Colombier 	"mis", 0,
3113e12c5d1SDavid du Colombier 	"mono", 0,
3123e12c5d1SDavid du Colombier 	"multi", 0,
3133e12c5d1SDavid du Colombier 	0
3143e12c5d1SDavid du Colombier };
3153e12c5d1SDavid du Colombier Ptab	ptabn[] =
3163e12c5d1SDavid du Colombier {
3173e12c5d1SDavid du Colombier 	"nano", 0,
318219b2ee8SDavid du Colombier 	"neuro", 0,
3193e12c5d1SDavid du Colombier 	"non", 0,
3203e12c5d1SDavid du Colombier 	0
3213e12c5d1SDavid du Colombier };
3223e12c5d1SDavid du Colombier Ptab	ptabo[] =
3233e12c5d1SDavid du Colombier {
3243e12c5d1SDavid du Colombier 	"out", 0,
3253e12c5d1SDavid du Colombier 	"over", 0,
3263e12c5d1SDavid du Colombier 	0
3273e12c5d1SDavid du Colombier };
3283e12c5d1SDavid du Colombier Ptab	ptabp[] =
3293e12c5d1SDavid du Colombier {
3303e12c5d1SDavid du Colombier 	"para", 0,
3313e12c5d1SDavid du Colombier 	"photo", 0,
3323e12c5d1SDavid du Colombier 	"pico", 0,
3333e12c5d1SDavid du Colombier 	"poly", 0,
3343e12c5d1SDavid du Colombier 	"pre", 0,
3353e12c5d1SDavid du Colombier 	"pseudo", 0,
3363e12c5d1SDavid du Colombier 	"psycho", 0,
3373e12c5d1SDavid du Colombier 	0
3383e12c5d1SDavid du Colombier };
3393e12c5d1SDavid du Colombier Ptab	ptabq[] =
3403e12c5d1SDavid du Colombier {
3413e12c5d1SDavid du Colombier 	"quasi", 0,
3423e12c5d1SDavid du Colombier 	0
3433e12c5d1SDavid du Colombier };
3443e12c5d1SDavid du Colombier Ptab	ptabr[] =
3453e12c5d1SDavid du Colombier {
346219b2ee8SDavid du Colombier 	"radio", 0,
3473e12c5d1SDavid du Colombier 	"re", 0,
3483e12c5d1SDavid du Colombier 	0
3493e12c5d1SDavid du Colombier };
3503e12c5d1SDavid du Colombier Ptab	ptabs[] =
3513e12c5d1SDavid du Colombier {
3523e12c5d1SDavid du Colombier 	"semi", 0,
3533e12c5d1SDavid du Colombier 	"stereo", 0,
3543e12c5d1SDavid du Colombier 	"sub", 0,
3553e12c5d1SDavid du Colombier 	"super", 0,
3563e12c5d1SDavid du Colombier 	0
3573e12c5d1SDavid du Colombier };
3583e12c5d1SDavid du Colombier Ptab	ptabt[] =
3593e12c5d1SDavid du Colombier {
3603e12c5d1SDavid du Colombier 	"tele", 0,
361219b2ee8SDavid du Colombier 	"tera", 0,
3623e12c5d1SDavid du Colombier 	"thermo", 0,
3633e12c5d1SDavid du Colombier 	0
3643e12c5d1SDavid du Colombier };
3653e12c5d1SDavid du Colombier Ptab	ptabu[] =
3663e12c5d1SDavid du Colombier {
3673e12c5d1SDavid du Colombier 	"ultra", 0,
3683e12c5d1SDavid du Colombier 	"under", 0,	/*must precede un*/
3693e12c5d1SDavid du Colombier 	"un", IN,
3703e12c5d1SDavid du Colombier 	0
3713e12c5d1SDavid du Colombier };
3723e12c5d1SDavid du Colombier Ptab	ptabv[] =
3733e12c5d1SDavid du Colombier {
3743e12c5d1SDavid du Colombier 	0
3753e12c5d1SDavid du Colombier };
3763e12c5d1SDavid du Colombier Ptab	ptabw[] =
3773e12c5d1SDavid du Colombier {
3783e12c5d1SDavid du Colombier 	0
3793e12c5d1SDavid du Colombier };
3803e12c5d1SDavid du Colombier Ptab	ptabx[] =
3813e12c5d1SDavid du Colombier {
3823e12c5d1SDavid du Colombier 	0
3833e12c5d1SDavid du Colombier };
3843e12c5d1SDavid du Colombier Ptab	ptaby[] =
3853e12c5d1SDavid du Colombier {
3863e12c5d1SDavid du Colombier 	0
3873e12c5d1SDavid du Colombier };
3883e12c5d1SDavid du Colombier Ptab	ptabz[] =
3893e12c5d1SDavid du Colombier {
3903e12c5d1SDavid du Colombier 	0
3913e12c5d1SDavid du Colombier };
3923e12c5d1SDavid du Colombier 
3933e12c5d1SDavid du Colombier Ptab*	preftab[] =
3943e12c5d1SDavid du Colombier {
3953e12c5d1SDavid du Colombier 	ptaba,
3963e12c5d1SDavid du Colombier 	ptabb,
3973e12c5d1SDavid du Colombier 	ptabc,
3983e12c5d1SDavid du Colombier 	ptabd,
3993e12c5d1SDavid du Colombier 	ptabe,
4003e12c5d1SDavid du Colombier 	ptabf,
4013e12c5d1SDavid du Colombier 	ptabg,
4023e12c5d1SDavid du Colombier 	ptabh,
4033e12c5d1SDavid du Colombier 	ptabi,
4043e12c5d1SDavid du Colombier 	ptabj,
4053e12c5d1SDavid du Colombier 	ptabk,
4063e12c5d1SDavid du Colombier 	ptabl,
4073e12c5d1SDavid du Colombier 	ptabm,
4083e12c5d1SDavid du Colombier 	ptabn,
4093e12c5d1SDavid du Colombier 	ptabo,
4103e12c5d1SDavid du Colombier 	ptabp,
4113e12c5d1SDavid du Colombier 	ptabq,
4123e12c5d1SDavid du Colombier 	ptabr,
4133e12c5d1SDavid du Colombier 	ptabs,
4143e12c5d1SDavid du Colombier 	ptabt,
4153e12c5d1SDavid du Colombier 	ptabu,
4163e12c5d1SDavid du Colombier 	ptabv,
4173e12c5d1SDavid du Colombier 	ptabw,
4183e12c5d1SDavid du Colombier 	ptabx,
4193e12c5d1SDavid du Colombier 	ptaby,
4203e12c5d1SDavid du Colombier 	ptabz,
4213e12c5d1SDavid du Colombier };
4223e12c5d1SDavid du Colombier 
423219b2ee8SDavid du Colombier typedef struct {
424219b2ee8SDavid du Colombier 	char *mesg;
425219b2ee8SDavid du Colombier 	enum { NONE, SUFF, PREF} type;
426219b2ee8SDavid du Colombier } Deriv;
427219b2ee8SDavid du Colombier 
428219b2ee8SDavid du Colombier int	aflag;
4293e12c5d1SDavid du Colombier int	cflag;
430219b2ee8SDavid du Colombier int	fflag;
4313e12c5d1SDavid du Colombier int	vflag;
4323e12c5d1SDavid du Colombier int	xflag;
433219b2ee8SDavid du Colombier int 	nflag;
434219b2ee8SDavid du Colombier char	word[500];
4353e12c5d1SDavid du Colombier char*	original;
436219b2ee8SDavid du Colombier Deriv	emptyderiv;
437219b2ee8SDavid du Colombier Deriv	deriv[DSIZ+3];
438219b2ee8SDavid du Colombier char	affix[DSIZ*10];	/* 10 is longest affix message */
439219b2ee8SDavid du Colombier int	prefcount;
440219b2ee8SDavid du Colombier int 	suffcount;
441219b2ee8SDavid du Colombier char*	acmeid;
4423e12c5d1SDavid du Colombier char	space[300000];	/* must be as large as "words"+"space" in pcode run */
4433e12c5d1SDavid du Colombier Bits	encode[2048];	/* must be as long as "codes" in pcode run */
4443e12c5d1SDavid du Colombier int	nencode;
445219b2ee8SDavid du Colombier char	voweltab[256];
4463e12c5d1SDavid du Colombier char*	spacep[128*128+1];	/* pointer to words starting with 'xx' */
4473e12c5d1SDavid du Colombier Biobuf	bin;
448219b2ee8SDavid du Colombier Biobuf	bout;
4493e12c5d1SDavid du Colombier 
4503e12c5d1SDavid du Colombier char*	codefile = "/sys/lib/amspell";
4513e12c5d1SDavid du Colombier char*	brfile = "/sys/lib/brspell";
4523e12c5d1SDavid du Colombier char*	Usage = "usage";
4533e12c5d1SDavid du Colombier 
4543e12c5d1SDavid du Colombier void
main(int argc,char * argv[])4553e12c5d1SDavid du Colombier main(int argc, char *argv[])
4563e12c5d1SDavid du Colombier {
4573e12c5d1SDavid du Colombier 	char *ep, *cp;
4583e12c5d1SDavid du Colombier 	char *dp;
4593e12c5d1SDavid du Colombier 	int j, i, c;
4603e12c5d1SDavid du Colombier 	int low;
4613e12c5d1SDavid du Colombier 	Bits h;
4623e12c5d1SDavid du Colombier 
4633e12c5d1SDavid du Colombier 	Binit(&bin, 0, OREAD);
464219b2ee8SDavid du Colombier 	Binit(&bout, 1, OWRITE);
4653e12c5d1SDavid du Colombier 	for(i=0; c = "aeiouyAEIOUY"[i]; i++)
4663e12c5d1SDavid du Colombier 		voweltab[c] = 1;
4673e12c5d1SDavid du Colombier 	while(argc > 1) {
4683e12c5d1SDavid du Colombier 		if(argv[1][0] != '-')
4693e12c5d1SDavid du Colombier 			break;
4703e12c5d1SDavid du Colombier 		for(i=1; c = argv[1][i]; i++)
4713e12c5d1SDavid du Colombier 		switch(c) {
4723e12c5d1SDavid du Colombier 		default:
473219b2ee8SDavid du Colombier 			fprint(2, "usage: spell [-bcCvx] [-f file]\n");
4743e12c5d1SDavid du Colombier 			exits(Usage);
4753e12c5d1SDavid du Colombier 
476219b2ee8SDavid du Colombier 		case 'a':
477219b2ee8SDavid du Colombier 			aflag++;
478219b2ee8SDavid du Colombier 			continue;
479219b2ee8SDavid du Colombier 
4803e12c5d1SDavid du Colombier 		case 'b':
4813e12c5d1SDavid du Colombier 			ise();
482219b2ee8SDavid du Colombier 			if(!fflag)
4833e12c5d1SDavid du Colombier 				codefile = brfile;
4843e12c5d1SDavid du Colombier 			continue;
4853e12c5d1SDavid du Colombier 
486219b2ee8SDavid du Colombier 		case 'C':		/* for "correct" */
487219b2ee8SDavid du Colombier 			vflag++;
488219b2ee8SDavid du Colombier 		case 'c':		/* for ocr */
4893e12c5d1SDavid du Colombier 			cflag++;
4903e12c5d1SDavid du Colombier 			continue;
4913e12c5d1SDavid du Colombier 
4923e12c5d1SDavid du Colombier 		case 'v':
4933e12c5d1SDavid du Colombier 			vflag++;
4943e12c5d1SDavid du Colombier 			continue;
4953e12c5d1SDavid du Colombier 
4963e12c5d1SDavid du Colombier 		case 'x':
4973e12c5d1SDavid du Colombier 			xflag++;
4983e12c5d1SDavid du Colombier 			continue;
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier 		case 'f':
5013e12c5d1SDavid du Colombier 			if(argc <= 2) {
5023e12c5d1SDavid du Colombier 				fprint(2, "spell: -f requires another argument\n");
5033e12c5d1SDavid du Colombier 				exits(Usage);
5043e12c5d1SDavid du Colombier 			}
5053e12c5d1SDavid du Colombier 			argv++;
5063e12c5d1SDavid du Colombier 			argc--;
5073e12c5d1SDavid du Colombier 			codefile = argv[1];
508219b2ee8SDavid du Colombier 			fflag++;
5093e12c5d1SDavid du Colombier 			goto brk;
5103e12c5d1SDavid du Colombier 		}
5113e12c5d1SDavid du Colombier 	brk:
5123e12c5d1SDavid du Colombier 		argv++;
5133e12c5d1SDavid du Colombier 		argc--;
5143e12c5d1SDavid du Colombier 	}
5153e12c5d1SDavid du Colombier 	readdict(codefile);
5163e12c5d1SDavid du Colombier 	if(argc > 1) {
517219b2ee8SDavid du Colombier 		fprint(2, "usage: spell [-bcCvx] [-f file]\n");
5183e12c5d1SDavid du Colombier 		exits(Usage);
5193e12c5d1SDavid du Colombier 	}
520219b2ee8SDavid du Colombier 	if(aflag)
521219b2ee8SDavid du Colombier 		cflag = vflag = 0;
5223e12c5d1SDavid du Colombier 
5233e12c5d1SDavid du Colombier 	for(;;) {
5243e12c5d1SDavid du Colombier 		affix[0] = 0;
5253e12c5d1SDavid du Colombier 		original = Brdline(&bin, '\n');
5263e12c5d1SDavid du Colombier 		if(original == 0)
5273e12c5d1SDavid du Colombier 			exits(0);
5283e12c5d1SDavid du Colombier 		original[Blinelen(&bin)-1] = 0;
5293e12c5d1SDavid du Colombier 		low = 0;
530219b2ee8SDavid du Colombier 
531219b2ee8SDavid du Colombier 		if(aflag) {
532219b2ee8SDavid du Colombier 			acmeid = original;
533219b2ee8SDavid du Colombier 			while(*original != ':')
534219b2ee8SDavid du Colombier 				if(*original++ == 0)
535219b2ee8SDavid du Colombier 					exits(0);
536219b2ee8SDavid du Colombier 			while(*++original != ':')
537219b2ee8SDavid du Colombier 				if(*original == 0)
538219b2ee8SDavid du Colombier 					exits(0);
539219b2ee8SDavid du Colombier 			*original++ = 0;
540219b2ee8SDavid du Colombier 		}
5413e12c5d1SDavid du Colombier 		for(ep=word,dp=original; j = *dp; ep++,dp++) {
542219b2ee8SDavid du Colombier 			if(ISLOWER(j))
5433e12c5d1SDavid du Colombier 				low++;
5443e12c5d1SDavid du Colombier 			if(ep >= word+sizeof(word)-1)
5453e12c5d1SDavid du Colombier 				break;
5463e12c5d1SDavid du Colombier 			*ep = j;
5473e12c5d1SDavid du Colombier 		}
5483e12c5d1SDavid du Colombier 		*ep = 0;
5493e12c5d1SDavid du Colombier 
550219b2ee8SDavid du Colombier 		if(ISDIGIT(word[0]) && ordinal())
5513e12c5d1SDavid du Colombier 			continue;
5523e12c5d1SDavid du Colombier 
5533e12c5d1SDavid du Colombier 		h = 0;
5543e12c5d1SDavid du Colombier 		if(!low && !(h = trypref(ep,".",0,ALL|STOP|DONT_TOUCH)))
5553e12c5d1SDavid du Colombier 			for(cp=original+1,dp=word+1; dp<ep; dp++,cp++)
5563e12c5d1SDavid du Colombier 				*dp = Tolower(*cp);
5573e12c5d1SDavid du Colombier 		if(!h)
5583e12c5d1SDavid du Colombier 		for(;;) {	/* at most twice */
5593e12c5d1SDavid du Colombier 			if(h = trypref(ep,".",0,ALL|STOP|DONT_TOUCH))
5603e12c5d1SDavid du Colombier 				break;
5613e12c5d1SDavid du Colombier 			if(h = trysuff(ep,0,ALL|STOP|DONT_TOUCH))
5623e12c5d1SDavid du Colombier 				break;
563219b2ee8SDavid du Colombier 			if(!ISUPPER(word[0]))
5643e12c5d1SDavid du Colombier 				break;
5653e12c5d1SDavid du Colombier 			cp = original;
5663e12c5d1SDavid du Colombier 			dp = word;
5673e12c5d1SDavid du Colombier 			while(*dp = *cp++) {
5683e12c5d1SDavid du Colombier 					if(!low)
5693e12c5d1SDavid du Colombier 						*dp = Tolower(*dp);
5703e12c5d1SDavid du Colombier 				dp++;
5713e12c5d1SDavid du Colombier 			}
5723e12c5d1SDavid du Colombier 			word[0] = Tolower(word[0]);
5733e12c5d1SDavid du Colombier 		}
5743e12c5d1SDavid du Colombier 
5753e12c5d1SDavid du Colombier 		if(cflag) {
5763e12c5d1SDavid du Colombier 			if(!h || Set(h,STOP))
577219b2ee8SDavid du Colombier 				print("-");
578219b2ee8SDavid du Colombier 			else if(!vflag)
579219b2ee8SDavid du Colombier 				print("+");
5803e12c5d1SDavid du Colombier 			else
581219b2ee8SDavid du Colombier 				print("%c",'0' + (suffcount>0) +
582219b2ee8SDavid du Colombier 				   (prefcount>4? 8: 2*prefcount));
583219b2ee8SDavid du Colombier 		} else if(!h || Set(h,STOP)) {
584219b2ee8SDavid du Colombier 			if(aflag)
585219b2ee8SDavid du Colombier 				Bprint(&bout, "%s:%s\n", acmeid, original);
586219b2ee8SDavid du Colombier 			else
587219b2ee8SDavid du Colombier 				Bprint(&bout, "%s\n", original);
588219b2ee8SDavid du Colombier 		} else if(affix[0] != 0 && affix[0] != '.')
589219b2ee8SDavid du Colombier 			print("%s\t%s\n", affix, original);
5903e12c5d1SDavid du Colombier 	}
591*b85a8364SDavid du Colombier 	/* not reached */
5923e12c5d1SDavid du Colombier }
5933e12c5d1SDavid du Colombier 
5943e12c5d1SDavid du Colombier /*	strip exactly one suffix and do
5953e12c5d1SDavid du Colombier  *	indicated routine(s), which may recursively
5963e12c5d1SDavid du Colombier  *	strip suffixes
5973e12c5d1SDavid du Colombier  */
5983e12c5d1SDavid du Colombier Bits
trysuff(char * ep,int lev,int flag)5993e12c5d1SDavid du Colombier trysuff(char* ep, int lev, int flag)
6003e12c5d1SDavid du Colombier {
6013e12c5d1SDavid du Colombier 	Suftab *t;
6023e12c5d1SDavid du Colombier 	char *cp, *sp;
6033e12c5d1SDavid du Colombier 	Bits h = 0;
6043e12c5d1SDavid du Colombier 	int initchar = ep[-1];
6053e12c5d1SDavid du Colombier 
6063e12c5d1SDavid du Colombier 	flag &= ~MONO;
6073e12c5d1SDavid du Colombier 	lev += DLEV;
608219b2ee8SDavid du Colombier 	if(lev < DSIZ) {
609219b2ee8SDavid du Colombier 		deriv[lev]  = emptyderiv;
610219b2ee8SDavid du Colombier 		deriv[lev-1] = emptyderiv;
611219b2ee8SDavid du Colombier 	}
612219b2ee8SDavid du Colombier 	if(!ISLOWER(initchar))
6133e12c5d1SDavid du Colombier 		return h;
6143e12c5d1SDavid du Colombier 	for(t=suftab[initchar-'a']; sp=t->suf; t++) {
6153e12c5d1SDavid du Colombier 		cp = ep;
6163e12c5d1SDavid du Colombier 		while(*sp)
6173e12c5d1SDavid du Colombier 			if(*--cp != *sp++)
6183e12c5d1SDavid du Colombier 				goto next;
619219b2ee8SDavid du Colombier 		for(sp=ep-t->n1; --sp >= word && !ISVOWEL(*sp);)
6203e12c5d1SDavid du Colombier 			;
6213e12c5d1SDavid du Colombier 		if(sp < word)
622219b2ee8SDavid du Colombier 			continue;
6233e12c5d1SDavid du Colombier 		if(!(t->affixable & flag))
6243e12c5d1SDavid du Colombier 			return 0;
6253e12c5d1SDavid du Colombier 		h = (*t->p1)(ep-t->n1, t->d1, t->a1, lev+1, t->flag|STOP);
6263e12c5d1SDavid du Colombier 		if(!h && t->p2!=0) {
627219b2ee8SDavid du Colombier 			if(lev < DSIZ) {
628219b2ee8SDavid du Colombier 				deriv[lev] = emptyderiv;
629219b2ee8SDavid du Colombier 				deriv[lev+1] = emptyderiv;
630219b2ee8SDavid du Colombier 			}
6313e12c5d1SDavid du Colombier 			h = (*t->p2)(ep-t->n2, t->d2, t->a2, lev, t->flag|STOP);
6323e12c5d1SDavid du Colombier 		}
6333e12c5d1SDavid du Colombier 		break;
6343e12c5d1SDavid du Colombier 	next:;
6353e12c5d1SDavid du Colombier 	}
6363e12c5d1SDavid du Colombier 	return h;
6373e12c5d1SDavid du Colombier }
6383e12c5d1SDavid du Colombier 
6393e12c5d1SDavid du Colombier Bits
nop(char * ep,char * d,char * a,int lev,int flag)6403e12c5d1SDavid du Colombier nop(char* ep, char* d, char* a, int lev, int flag)
6413e12c5d1SDavid du Colombier {
6423e12c5d1SDavid du Colombier 	USED(ep, d, a, lev, flag);
6433e12c5d1SDavid du Colombier 	return 0;
6443e12c5d1SDavid du Colombier }
6453e12c5d1SDavid du Colombier 
6463e12c5d1SDavid du Colombier Bits
cstrip(char * ep,char * d,char * a,int lev,int flag)6473e12c5d1SDavid du Colombier cstrip(char* ep, char* d, char* a, int lev, int flag)
6483e12c5d1SDavid du Colombier {
6493e12c5d1SDavid du Colombier 	int temp = ep[0];
6503e12c5d1SDavid du Colombier 
651219b2ee8SDavid du Colombier 	if(ISVOWEL(temp) && ISVOWEL(ep[-1])) {
6523e12c5d1SDavid du Colombier 		switch(pair(ep[-1],ep[0])) {
6533e12c5d1SDavid du Colombier 		case pair('a', 'a'):
6543e12c5d1SDavid du Colombier 		case pair('a', 'e'):
6553e12c5d1SDavid du Colombier 		case pair('a', 'i'):
6563e12c5d1SDavid du Colombier 		case pair('e', 'a'):
6573e12c5d1SDavid du Colombier 		case pair('e', 'e'):
6583e12c5d1SDavid du Colombier 		case pair('e', 'i'):
6593e12c5d1SDavid du Colombier 		case pair('i', 'i'):
6603e12c5d1SDavid du Colombier 		case pair('o', 'a'):
6613e12c5d1SDavid du Colombier 			return 0;
6623e12c5d1SDavid du Colombier 		}
6633e12c5d1SDavid du Colombier 	} else
6643e12c5d1SDavid du Colombier 	if(temp==ep[-1]&&temp==ep[-2])
6653e12c5d1SDavid du Colombier 		return 0;
6663e12c5d1SDavid du Colombier 	return strip(ep,d,a,lev,flag);
6673e12c5d1SDavid du Colombier }
6683e12c5d1SDavid du Colombier 
6693e12c5d1SDavid du Colombier Bits
strip(char * ep,char * d,char * a,int lev,int flag)6703e12c5d1SDavid du Colombier strip(char* ep, char* d, char* a, int lev, int flag)
6713e12c5d1SDavid du Colombier {
6723e12c5d1SDavid du Colombier 	Bits h = trypref(ep, a, lev, flag);
6733e12c5d1SDavid du Colombier 
6743e12c5d1SDavid du Colombier 	USED(d);
675219b2ee8SDavid du Colombier 	if(Set(h,MONO) && ISVOWEL(*ep) && ISVOWEL(ep[-2]))
6763e12c5d1SDavid du Colombier 		h = 0;
6773e12c5d1SDavid du Colombier 	if(h)
6783e12c5d1SDavid du Colombier 		return h;
679219b2ee8SDavid du Colombier 	if(ISVOWEL(*ep) && !ISVOWEL(ep[-1]) && ep[-1]==ep[-2]) {
6803e12c5d1SDavid du Colombier 		h = trypref(ep-1,a,lev,flag|MONO);
6813e12c5d1SDavid du Colombier 		if(h)
6823e12c5d1SDavid du Colombier 			return h;
6833e12c5d1SDavid du Colombier 	}
6843e12c5d1SDavid du Colombier 	return trysuff(ep,lev,flag);
6853e12c5d1SDavid du Colombier }
6863e12c5d1SDavid du Colombier 
6873e12c5d1SDavid du Colombier Bits
s(char * ep,char * d,char * a,int lev,int flag)6883e12c5d1SDavid du Colombier s(char* ep, char* d, char* a, int lev, int flag)
6893e12c5d1SDavid du Colombier {
6903e12c5d1SDavid du Colombier 	if(lev > DLEV+1)
6913e12c5d1SDavid du Colombier 		return 0;
6923e12c5d1SDavid du Colombier 	if(*ep=='s') {
6933e12c5d1SDavid du Colombier 		switch(ep[-1]) {
6943e12c5d1SDavid du Colombier 		case 'y':
695219b2ee8SDavid du Colombier 			if(ISVOWEL(ep[-2])||ISUPPER(*word))
6963e12c5d1SDavid du Colombier 				break;	/*says Kennedys*/
6973e12c5d1SDavid du Colombier 		case 'x':
6983e12c5d1SDavid du Colombier 		case 'z':
6993e12c5d1SDavid du Colombier 		case 's':
7003e12c5d1SDavid du Colombier 			return 0;
7013e12c5d1SDavid du Colombier 		case 'h':
7023e12c5d1SDavid du Colombier 			switch(ep[-2]) {
7033e12c5d1SDavid du Colombier 			case 'c':
7043e12c5d1SDavid du Colombier 			case 's':
7053e12c5d1SDavid du Colombier 				return 0;
7063e12c5d1SDavid du Colombier 			}
7073e12c5d1SDavid du Colombier 		}
7083e12c5d1SDavid du Colombier 	}
7093e12c5d1SDavid du Colombier 	return strip(ep,d,a,lev,flag);
7103e12c5d1SDavid du Colombier }
7113e12c5d1SDavid du Colombier 
7123e12c5d1SDavid du Colombier Bits
an(char * ep,char * d,char * a,int lev,int flag)7133e12c5d1SDavid du Colombier an(char* ep, char* d, char* a, int lev, int flag)
7143e12c5d1SDavid du Colombier {
7153e12c5d1SDavid du Colombier 	USED(d);
716219b2ee8SDavid du Colombier 	if(!ISUPPER(*word))	/*must be proper name*/
7173e12c5d1SDavid du Colombier 		return 0;
7183e12c5d1SDavid du Colombier 	return trypref(ep,a,lev,flag);
7193e12c5d1SDavid du Colombier }
7203e12c5d1SDavid du Colombier 
7213e12c5d1SDavid du Colombier Bits
ize(char * ep,char * d,char * a,int lev,int flag)7223e12c5d1SDavid du Colombier ize(char* ep, char* d, char* a, int lev, int flag)
7233e12c5d1SDavid du Colombier {
7243e12c5d1SDavid du Colombier 	int temp = ep[-1];
7253e12c5d1SDavid du Colombier 	Bits h;
7263e12c5d1SDavid du Colombier 
7273e12c5d1SDavid du Colombier 	USED(a);
7283e12c5d1SDavid du Colombier 	ep[-1] = 'e';
7293e12c5d1SDavid du Colombier 	h = strip(ep,"",d,lev,flag);
7303e12c5d1SDavid du Colombier 	ep[-1] = temp;
7313e12c5d1SDavid du Colombier 	return h;
7323e12c5d1SDavid du Colombier }
7333e12c5d1SDavid du Colombier 
7343e12c5d1SDavid du Colombier Bits
y_to_e(char * ep,char * d,char * a,int lev,int flag)7353e12c5d1SDavid du Colombier y_to_e(char* ep, char* d, char* a, int lev, int flag)
7363e12c5d1SDavid du Colombier {
7373e12c5d1SDavid du Colombier 	Bits h;
7383e12c5d1SDavid du Colombier 	int  temp;
7393e12c5d1SDavid du Colombier 
7403e12c5d1SDavid du Colombier 	USED(a);
7413e12c5d1SDavid du Colombier 	switch(ep[-1]) {
7423e12c5d1SDavid du Colombier 	case 'a':
7433e12c5d1SDavid du Colombier 	case 'e':
7443e12c5d1SDavid du Colombier 	case 'i':
7453e12c5d1SDavid du Colombier 		return 0;
7463e12c5d1SDavid du Colombier 	}
7473e12c5d1SDavid du Colombier 	temp = *ep;
7483e12c5d1SDavid du Colombier 	*ep++ = 'e';
7493e12c5d1SDavid du Colombier 	h = strip(ep,"",d,lev,flag);
7503e12c5d1SDavid du Colombier 	ep[-1] = temp;
7513e12c5d1SDavid du Colombier 	return h;
7523e12c5d1SDavid du Colombier }
7533e12c5d1SDavid du Colombier 
7543e12c5d1SDavid du Colombier Bits
ily(char * ep,char * d,char * a,int lev,int flag)7553e12c5d1SDavid du Colombier ily(char* ep, char* d, char* a, int lev, int flag)
7563e12c5d1SDavid du Colombier {
7573e12c5d1SDavid du Colombier 	int temp = ep[0];
7583e12c5d1SDavid du Colombier 	char *cp = ep;
7593e12c5d1SDavid du Colombier 
7603e12c5d1SDavid du Colombier 	if(temp==ep[-1]&&temp==ep[-2])		/* sillly */
7613e12c5d1SDavid du Colombier 		return 0;
762219b2ee8SDavid du Colombier 	if(*--cp=='y' && !ISVOWEL(*--cp))	/* happyly */
7633e12c5d1SDavid du Colombier 		while(cp>word)
764219b2ee8SDavid du Colombier 			if(ISVOWEL(*--cp))	/* shyness */
7653e12c5d1SDavid du Colombier 				return 0;
7663e12c5d1SDavid du Colombier 	if(ep[-1]=='i')
7673e12c5d1SDavid du Colombier 		return i_to_y(ep,d,a,lev,flag);
7683e12c5d1SDavid du Colombier 	return cstrip(ep,d,a,lev,flag);
7693e12c5d1SDavid du Colombier }
7703e12c5d1SDavid du Colombier 
7713e12c5d1SDavid du Colombier Bits
bility(char * ep,char * d,char * a,int lev,int flag)7723e12c5d1SDavid du Colombier bility(char* ep, char* d, char* a, int lev, int flag)
7733e12c5d1SDavid du Colombier {
7743e12c5d1SDavid du Colombier 	*ep++ = 'l';
7753e12c5d1SDavid du Colombier 	return y_to_e(ep,d,a,lev,flag);
7763e12c5d1SDavid du Colombier }
7773e12c5d1SDavid du Colombier 
7783e12c5d1SDavid du Colombier Bits
i_to_y(char * ep,char * d,char * a,int lev,int flag)7793e12c5d1SDavid du Colombier i_to_y(char* ep, char* d, char* a, int lev, int flag)
7803e12c5d1SDavid du Colombier {
7813e12c5d1SDavid du Colombier 	Bits h;
7823e12c5d1SDavid du Colombier 	int temp;
7833e12c5d1SDavid du Colombier 
784219b2ee8SDavid du Colombier 	if(ISUPPER(*word))
7853e12c5d1SDavid du Colombier 		return 0;
786219b2ee8SDavid du Colombier 	if((temp=ep[-1])=='i' && !ISVOWEL(ep[-2])) {
7873e12c5d1SDavid du Colombier 		ep[-1] = 'y';
7883e12c5d1SDavid du Colombier 		a = d;
7893e12c5d1SDavid du Colombier 	}
7903e12c5d1SDavid du Colombier 	h = cstrip(ep,"",a,lev,flag);
7913e12c5d1SDavid du Colombier 	ep[-1] = temp;
7923e12c5d1SDavid du Colombier 	return h;
7933e12c5d1SDavid du Colombier }
7943e12c5d1SDavid du Colombier 
7953e12c5d1SDavid du Colombier Bits
es(char * ep,char * d,char * a,int lev,int flag)7963e12c5d1SDavid du Colombier es(char* ep, char* d, char* a, int lev, int flag)
7973e12c5d1SDavid du Colombier {
7983e12c5d1SDavid du Colombier 	if(lev>DLEV)
7993e12c5d1SDavid du Colombier 		return 0;
8003e12c5d1SDavid du Colombier 	switch(ep[-1]) {
8013e12c5d1SDavid du Colombier 	default:
8023e12c5d1SDavid du Colombier 		return 0;
8033e12c5d1SDavid du Colombier 	case 'i':
8043e12c5d1SDavid du Colombier 		return i_to_y(ep,d,a,lev,flag);
8053e12c5d1SDavid du Colombier 	case 'h':
8063e12c5d1SDavid du Colombier 		switch(ep[-2]) {
8073e12c5d1SDavid du Colombier 		default:
8083e12c5d1SDavid du Colombier 			return 0;
8093e12c5d1SDavid du Colombier 		case 'c':
8103e12c5d1SDavid du Colombier 		case 's':
8113e12c5d1SDavid du Colombier 			break;
8123e12c5d1SDavid du Colombier 		}
8133e12c5d1SDavid du Colombier 	case 's':
8143e12c5d1SDavid du Colombier 	case 'z':
8153e12c5d1SDavid du Colombier 	case 'x':
8163e12c5d1SDavid du Colombier 		return strip(ep,d,a,lev,flag);
8173e12c5d1SDavid du Colombier 	}
8183e12c5d1SDavid du Colombier }
8193e12c5d1SDavid du Colombier 
8203e12c5d1SDavid du Colombier Bits
subst(char * ep,char * d,char * a,int lev,int flag)8213e12c5d1SDavid du Colombier subst(char* ep, char* d, char* a, int lev, int flag)
8223e12c5d1SDavid du Colombier {
8233e12c5d1SDavid du Colombier 	char *u,*t;
8243e12c5d1SDavid du Colombier 	Bits h;
8253e12c5d1SDavid du Colombier 
8263e12c5d1SDavid du Colombier 	USED(a);
8273e12c5d1SDavid du Colombier 	if(skipv(skipv(ep-1)) < word)
8283e12c5d1SDavid du Colombier 		return 0;
8293e12c5d1SDavid du Colombier 	for(t=d; *t!='+'; t++)
8303e12c5d1SDavid du Colombier 		continue;
8313e12c5d1SDavid du Colombier 	for(u=ep; *--t!='-';)
8323e12c5d1SDavid du Colombier 		*--u = *t;
8333e12c5d1SDavid du Colombier 	h = strip(ep,"",d,lev,flag);
8343e12c5d1SDavid du Colombier 	while(*++t != '+')
8353e12c5d1SDavid du Colombier 		continue;
8363e12c5d1SDavid du Colombier 	while(*++t)
8373e12c5d1SDavid du Colombier 		*u++ = *t;
8383e12c5d1SDavid du Colombier 	return h;
8393e12c5d1SDavid du Colombier }
8403e12c5d1SDavid du Colombier 
8413e12c5d1SDavid du Colombier Bits
tion(char * ep,char * d,char * a,int lev,int flag)8423e12c5d1SDavid du Colombier tion(char* ep, char* d, char* a, int lev, int flag)
8433e12c5d1SDavid du Colombier {
8443e12c5d1SDavid du Colombier 	switch(ep[-2]) {
845219b2ee8SDavid du Colombier 	default:
8463e12c5d1SDavid du Colombier 		return trypref(ep,a,lev,flag);
8473e12c5d1SDavid du Colombier 	case 'a':
8483e12c5d1SDavid du Colombier 	case 'e':
8493e12c5d1SDavid du Colombier 	case 'i':
8503e12c5d1SDavid du Colombier 	case 'o':
8513e12c5d1SDavid du Colombier 	case 'u':
8523e12c5d1SDavid du Colombier 		return y_to_e(ep,d,a,lev,flag);
8533e12c5d1SDavid du Colombier 	}
8543e12c5d1SDavid du Colombier }
8553e12c5d1SDavid du Colombier 
8563e12c5d1SDavid du Colombier /*
8573e12c5d1SDavid du Colombier  * possible consonant-consonant-e ending
8583e12c5d1SDavid du Colombier  */
8593e12c5d1SDavid du Colombier Bits
CCe(char * ep,char * d,char * a,int lev,int flag)8603e12c5d1SDavid du Colombier CCe(char* ep, char* d, char* a, int lev, int flag)
8613e12c5d1SDavid du Colombier {
8623e12c5d1SDavid du Colombier 	Bits h;
8633e12c5d1SDavid du Colombier 
8643e12c5d1SDavid du Colombier 	switch(ep[-1]) {
8653e12c5d1SDavid du Colombier 	case 'l':
866219b2ee8SDavid du Colombier 		if(ISVOWEL(ep[-2]))
8673e12c5d1SDavid du Colombier 			break;
8683e12c5d1SDavid du Colombier 		switch(ep[-2]) {
8693e12c5d1SDavid du Colombier 		case 'l':
8703e12c5d1SDavid du Colombier 		case 'r':
8713e12c5d1SDavid du Colombier 		case 'w':
8723e12c5d1SDavid du Colombier 			break;
8733e12c5d1SDavid du Colombier 		default:
8743e12c5d1SDavid du Colombier 			return y_to_e(ep,d,a,lev,flag);
8753e12c5d1SDavid du Colombier 		}
8763e12c5d1SDavid du Colombier 		break;
8773e12c5d1SDavid du Colombier 	case 'c':
8783e12c5d1SDavid du Colombier 	case 'g':
8793e12c5d1SDavid du Colombier 		if(*ep == 'a')	/* prevent -able for -eable */
8803e12c5d1SDavid du Colombier 			return 0;
8813e12c5d1SDavid du Colombier 	case 's':
8823e12c5d1SDavid du Colombier 	case 'v':
8833e12c5d1SDavid du Colombier 	case 'z':
8843e12c5d1SDavid du Colombier 		if(ep[-2]==ep[-1])
8853e12c5d1SDavid du Colombier 			break;
886219b2ee8SDavid du Colombier 		if(ISVOWEL(ep[-2]))
8873e12c5d1SDavid du Colombier 			break;
8883e12c5d1SDavid du Colombier 	case 'u':
8893e12c5d1SDavid du Colombier 		if(h = y_to_e(ep,d,a,lev,flag))
8903e12c5d1SDavid du Colombier 			return h;
8913e12c5d1SDavid du Colombier 		if(!(ep[-2]=='n' && ep[-1]=='g'))
8923e12c5d1SDavid du Colombier 			return 0;
8933e12c5d1SDavid du Colombier 	}
8943e12c5d1SDavid du Colombier 	return VCe(ep,d,a,lev,flag);
8953e12c5d1SDavid du Colombier }
8963e12c5d1SDavid du Colombier 
8973e12c5d1SDavid du Colombier /*
8983e12c5d1SDavid du Colombier  * possible consonant-vowel-consonant-e ending
8993e12c5d1SDavid du Colombier  */
9003e12c5d1SDavid du Colombier Bits
VCe(char * ep,char * d,char * a,int lev,int flag)9013e12c5d1SDavid du Colombier VCe(char* ep, char* d, char* a, int lev, int flag)
9023e12c5d1SDavid du Colombier {
9033e12c5d1SDavid du Colombier 	int c;
9043e12c5d1SDavid du Colombier 	Bits h;
9053e12c5d1SDavid du Colombier 
9063e12c5d1SDavid du Colombier 	c = ep[-1];
9073e12c5d1SDavid du Colombier 	if(c=='e')
9083e12c5d1SDavid du Colombier 		return 0;
909219b2ee8SDavid du Colombier 	if(!ISVOWEL(c) && ISVOWEL(ep[-2])) {
9103e12c5d1SDavid du Colombier 		c = *ep;
9113e12c5d1SDavid du Colombier 		*ep++ = 'e';
9123e12c5d1SDavid du Colombier 		h = trypref(ep,d,lev,flag);
9133e12c5d1SDavid du Colombier 		if(!h)
9143e12c5d1SDavid du Colombier 			h = trysuff(ep,lev,flag);
9153e12c5d1SDavid du Colombier 		if(h)
9163e12c5d1SDavid du Colombier 			return h;
9173e12c5d1SDavid du Colombier 		ep--;
9183e12c5d1SDavid du Colombier 		*ep = c;
9193e12c5d1SDavid du Colombier 	}
9203e12c5d1SDavid du Colombier 	return cstrip(ep,d,a,lev,flag);
9213e12c5d1SDavid du Colombier }
9223e12c5d1SDavid du Colombier 
9233e12c5d1SDavid du Colombier Ptab*
lookuppref(uchar ** wp,char * ep)924219b2ee8SDavid du Colombier lookuppref(uchar** wp, char* ep)
9253e12c5d1SDavid du Colombier {
9263e12c5d1SDavid du Colombier 	Ptab *sp;
927219b2ee8SDavid du Colombier 	uchar *bp,*cp;
928219b2ee8SDavid du Colombier 	unsigned int initchar = Tolower(**wp);
9293e12c5d1SDavid du Colombier 
930219b2ee8SDavid du Colombier 	if(!ISALPHA(initchar))
9313e12c5d1SDavid du Colombier 		return 0;
9323e12c5d1SDavid du Colombier 	for(sp=preftab[initchar-'a'];sp->s;sp++) {
9333e12c5d1SDavid du Colombier 		bp = *wp;
934219b2ee8SDavid du Colombier 		for(cp= (uchar*)sp->s;*cp; )
9353e12c5d1SDavid du Colombier 			if(*bp++!=*cp++)
9363e12c5d1SDavid du Colombier 				goto next;
937219b2ee8SDavid du Colombier 		for(cp=bp;cp<(uchar*)ep;cp++)
938219b2ee8SDavid du Colombier 			if(ISVOWEL(*cp)) {
9393e12c5d1SDavid du Colombier 				*wp = bp;
9403e12c5d1SDavid du Colombier 				return sp;
9413e12c5d1SDavid du Colombier 			}
9423e12c5d1SDavid du Colombier 	next:;
9433e12c5d1SDavid du Colombier 	}
9443e12c5d1SDavid du Colombier 	return 0;
9453e12c5d1SDavid du Colombier }
9463e12c5d1SDavid du Colombier 
9473e12c5d1SDavid du Colombier /*	while word is not in dictionary try stripping
9483e12c5d1SDavid du Colombier  *	prefixes. Fail if no more prefixes.
9493e12c5d1SDavid du Colombier  */
9503e12c5d1SDavid du Colombier Bits
trypref(char * ep,char * a,int lev,int flag)9513e12c5d1SDavid du Colombier trypref(char* ep, char* a, int lev, int flag)
9523e12c5d1SDavid du Colombier {
9533e12c5d1SDavid du Colombier 	Ptab *tp;
9543e12c5d1SDavid du Colombier 	char *bp, *cp;
9553e12c5d1SDavid du Colombier 	char *pp;
9563e12c5d1SDavid du Colombier 	Bits h;
9573e12c5d1SDavid du Colombier 	char space[20];
9583e12c5d1SDavid du Colombier 
959219b2ee8SDavid du Colombier 	if(lev<DSIZ) {
960219b2ee8SDavid du Colombier 		deriv[lev].mesg = a;
961219b2ee8SDavid du Colombier 		deriv[lev].type = *a=='.'? NONE: SUFF;
962219b2ee8SDavid du Colombier 	}
9633e12c5d1SDavid du Colombier 	if(h = tryword(word,ep,lev,flag)) {
9643e12c5d1SDavid du Colombier 		if(Set(h, flag&~MONO) && (flag&MONO) <= Set(h, MONO))
9653e12c5d1SDavid du Colombier 			return h;
9663e12c5d1SDavid du Colombier 		h = 0;
9673e12c5d1SDavid du Colombier 	}
9683e12c5d1SDavid du Colombier 	bp = word;
9693e12c5d1SDavid du Colombier 	pp = space;
970219b2ee8SDavid du Colombier 	if(lev<DSIZ) {
971219b2ee8SDavid du Colombier 		deriv[lev+1].mesg = pp;
972219b2ee8SDavid du Colombier 		deriv[lev+1].type = 0;
973219b2ee8SDavid du Colombier 	}
974219b2ee8SDavid du Colombier 	while(tp=lookuppref((uchar**)&bp,ep)) {
9753e12c5d1SDavid du Colombier 		*pp++ = '+';
9763e12c5d1SDavid du Colombier 		cp = tp->s;
977219b2ee8SDavid du Colombier 		while(pp<space+sizeof(space) && (*pp = *cp++))
9783e12c5d1SDavid du Colombier 			pp++;
979219b2ee8SDavid du Colombier 		deriv[lev+1].type += PREF;
9803e12c5d1SDavid du Colombier 		h = tryword(bp,ep,lev+1,flag);
9813e12c5d1SDavid du Colombier 		if(Set(h,NOPREF) ||
9823e12c5d1SDavid du Colombier 		   ((tp->flag&IN) && inun(bp-2,h)==0)) {
9833e12c5d1SDavid du Colombier 			h = 0;
9843e12c5d1SDavid du Colombier 			break;
9853e12c5d1SDavid du Colombier 		}
9863e12c5d1SDavid du Colombier 		if(Set(h,flag&~MONO) && (flag&MONO) <= Set(h, MONO))
9873e12c5d1SDavid du Colombier 			break;
9883e12c5d1SDavid du Colombier 		h = 0;
9893e12c5d1SDavid du Colombier 	}
990219b2ee8SDavid du Colombier 	if(lev < DSIZ) {
991219b2ee8SDavid du Colombier 		deriv[lev+1] = emptyderiv;
992219b2ee8SDavid du Colombier 		deriv[lev+2] = emptyderiv;
993219b2ee8SDavid du Colombier 	}
9943e12c5d1SDavid du Colombier 	return h;
9953e12c5d1SDavid du Colombier }
9963e12c5d1SDavid du Colombier 
9973e12c5d1SDavid du Colombier Bits
tryword(char * bp,char * ep,int lev,int flag)9983e12c5d1SDavid du Colombier tryword(char* bp, char* ep, int lev, int flag)
9993e12c5d1SDavid du Colombier {
10003e12c5d1SDavid du Colombier 	int  j;
10013e12c5d1SDavid du Colombier 	Bits h = 0;
10023e12c5d1SDavid du Colombier 	char duple[3];
10033e12c5d1SDavid du Colombier 
10043e12c5d1SDavid du Colombier 	if(ep-bp <= 1)
10053e12c5d1SDavid du Colombier 		return h;
10063e12c5d1SDavid du Colombier 	if(flag&MONO) {
1007219b2ee8SDavid du Colombier 		if(lev<DSIZ) {
1008219b2ee8SDavid du Colombier 			deriv[++lev].mesg = duple;
1009219b2ee8SDavid du Colombier 			deriv[lev].type = SUFF;
1010219b2ee8SDavid du Colombier 		}
10113e12c5d1SDavid du Colombier 		duple[0] = '+';
10123e12c5d1SDavid du Colombier 		duple[1] = *ep;
10133e12c5d1SDavid du Colombier 		duple[2] = 0;
10143e12c5d1SDavid du Colombier 	}
10153e12c5d1SDavid du Colombier 	h = dict(bp, ep);
10163e12c5d1SDavid du Colombier 	if(vflag==0 || h==0)
10173e12c5d1SDavid du Colombier 		return h;
10183e12c5d1SDavid du Colombier 	/*
10193e12c5d1SDavid du Colombier 	 * when derivations are wanted, collect them
10203e12c5d1SDavid du Colombier 	 * for printing
10213e12c5d1SDavid du Colombier 	 */
10223e12c5d1SDavid du Colombier 	j = lev;
1023219b2ee8SDavid du Colombier 	prefcount = suffcount = 0;
10243e12c5d1SDavid du Colombier 	do {
1025219b2ee8SDavid du Colombier 		if(j<DSIZ && deriv[j].type) {
1026219b2ee8SDavid du Colombier 			strcat(affix, deriv[j].mesg);
1027219b2ee8SDavid du Colombier 			if(deriv[j].type == SUFF)
1028219b2ee8SDavid du Colombier 				suffcount++;
1029219b2ee8SDavid du Colombier 			else if(deriv[j].type != NONE)
1030219b2ee8SDavid du Colombier 				prefcount = deriv[j].type/PREF;
1031219b2ee8SDavid du Colombier 		}
10323e12c5d1SDavid du Colombier 	} while(--j > 0);
10333e12c5d1SDavid du Colombier 	return h;
10343e12c5d1SDavid du Colombier }
10353e12c5d1SDavid du Colombier 
10363e12c5d1SDavid du Colombier int
inun(char * bp,Bits h)10373e12c5d1SDavid du Colombier inun(char* bp, Bits h)
10383e12c5d1SDavid du Colombier {
10393e12c5d1SDavid du Colombier 	if(*bp == 'u')
10403e12c5d1SDavid du Colombier 		return Set(h, IN) == 0;
10413e12c5d1SDavid du Colombier 	/* *bp == 'i' */
10423e12c5d1SDavid du Colombier 	if(Set(h, IN) == 0)
10433e12c5d1SDavid du Colombier 		return 0;
10443e12c5d1SDavid du Colombier 	switch(bp[2]) {
10453e12c5d1SDavid du Colombier 	case 'r':
10463e12c5d1SDavid du Colombier 		return bp[1] == 'r';
10473e12c5d1SDavid du Colombier 	case 'm':
10483e12c5d1SDavid du Colombier 	case 'p':
10493e12c5d1SDavid du Colombier 		return bp[1] == 'm';
10503e12c5d1SDavid du Colombier 	}
1051219b2ee8SDavid du Colombier 	return bp[1] == 'n';
10523e12c5d1SDavid du Colombier }
10533e12c5d1SDavid du Colombier 
10543e12c5d1SDavid du Colombier char*
skipv(char * s)10553e12c5d1SDavid du Colombier skipv(char *s)
10563e12c5d1SDavid du Colombier {
1057219b2ee8SDavid du Colombier 	if(s >= word && ISVOWEL(*s))
10583e12c5d1SDavid du Colombier 		s--;
1059219b2ee8SDavid du Colombier 	while(s >= word && !ISVOWEL(*s))
10603e12c5d1SDavid du Colombier 		s--;
10613e12c5d1SDavid du Colombier 	return s;
10623e12c5d1SDavid du Colombier }
10633e12c5d1SDavid du Colombier 
10643e12c5d1SDavid du Colombier /*
10653e12c5d1SDavid du Colombier  * crummy way to Britishise
10663e12c5d1SDavid du Colombier  */
10673e12c5d1SDavid du Colombier void
ise(void)10683e12c5d1SDavid du Colombier ise(void)
10693e12c5d1SDavid du Colombier {
10703e12c5d1SDavid du Colombier 	Suftab *p;
10713e12c5d1SDavid du Colombier 	int i;
10723e12c5d1SDavid du Colombier 
10733e12c5d1SDavid du Colombier 	for(i=0; i<26; i++)
10743e12c5d1SDavid du Colombier 		for(p = suftab[i]; p->suf; p++) {
10753e12c5d1SDavid du Colombier 			p->suf = ztos(p->suf);
10763e12c5d1SDavid du Colombier 			p->d1 = ztos(p->d1);
10773e12c5d1SDavid du Colombier 			p->a1 = ztos(p->a1);
10783e12c5d1SDavid du Colombier 		}
10793e12c5d1SDavid du Colombier }
10803e12c5d1SDavid du Colombier 
10813e12c5d1SDavid du Colombier char*
ztos(char * as)10823e12c5d1SDavid du Colombier ztos(char *as)
10833e12c5d1SDavid du Colombier {
10843e12c5d1SDavid du Colombier 	char *s, *ds;
10853e12c5d1SDavid du Colombier 
10863e12c5d1SDavid du Colombier 	for(s=as; *s; s++)
10873e12c5d1SDavid du Colombier 		if(*s == 'z')
10883e12c5d1SDavid du Colombier 			goto copy;
10893e12c5d1SDavid du Colombier 	return as;
10903e12c5d1SDavid du Colombier 
10913e12c5d1SDavid du Colombier copy:
10923e12c5d1SDavid du Colombier 	ds = strdup(as);
10933e12c5d1SDavid du Colombier 	for(s=ds; *s; s++)
10943e12c5d1SDavid du Colombier 		if(*s == 'z')
10953e12c5d1SDavid du Colombier 			*s = 's';
10963e12c5d1SDavid du Colombier 	return ds;
10973e12c5d1SDavid du Colombier }
10983e12c5d1SDavid du Colombier 
10993e12c5d1SDavid du Colombier Bits
dict(char * bp,char * ep)11003e12c5d1SDavid du Colombier dict(char* bp, char* ep)
11013e12c5d1SDavid du Colombier {
11023e12c5d1SDavid du Colombier 	char *cp, *cp1, *w, *wp, *we;
11033e12c5d1SDavid du Colombier 	int n, f;
11043e12c5d1SDavid du Colombier 
11053e12c5d1SDavid du Colombier 	w = bp;
11063e12c5d1SDavid du Colombier 	we = ep;
11073e12c5d1SDavid du Colombier 	n = ep-bp;
11083e12c5d1SDavid du Colombier 	if(n <= 1)
11093e12c5d1SDavid du Colombier 		return NOUN;
11103e12c5d1SDavid du Colombier 
11113e12c5d1SDavid du Colombier 	f = w[0] & 0x7f;
11123e12c5d1SDavid du Colombier 	f *= 128;
11133e12c5d1SDavid du Colombier 	f += w[1] & 0x7f;
11143e12c5d1SDavid du Colombier 	bp = spacep[f];
11153e12c5d1SDavid du Colombier 	ep = spacep[f+1];
11163e12c5d1SDavid du Colombier 
11173e12c5d1SDavid du Colombier loop:
11183e12c5d1SDavid du Colombier 	if(bp >= ep) {
11193e12c5d1SDavid du Colombier 		if(xflag)
112059cc4ca5SDavid du Colombier 			fprint(2, "=%.*s\n", utfnlen(w, n), w);
11213e12c5d1SDavid du Colombier 		return 0;
11223e12c5d1SDavid du Colombier 	}
11233e12c5d1SDavid du Colombier 	/*
11243e12c5d1SDavid du Colombier 	 * find the beginning of some word in the middle
11253e12c5d1SDavid du Colombier 	 */
11263e12c5d1SDavid du Colombier 	cp = bp + (ep-bp)/2;
11273e12c5d1SDavid du Colombier 
11283e12c5d1SDavid du Colombier 	while(cp > bp && !(*cp & 0x80))
11293e12c5d1SDavid du Colombier 		cp--;
11303e12c5d1SDavid du Colombier 	while(cp > bp && (cp[-1] & 0x80))
11313e12c5d1SDavid du Colombier 		cp--;
11323e12c5d1SDavid du Colombier 
11333e12c5d1SDavid du Colombier 	wp = w + 2;	/* skip two letters */
1134219b2ee8SDavid du Colombier 	cp1 = cp + 2;	/* skip affix code */
11353e12c5d1SDavid du Colombier 	for(;;) {
11363e12c5d1SDavid du Colombier 		if(wp >= we) {
11373e12c5d1SDavid du Colombier 			if(*cp1 & 0x80)
11383e12c5d1SDavid du Colombier 				goto found;
1139219b2ee8SDavid du Colombier 			else
11403e12c5d1SDavid du Colombier 				f = 1;
11413e12c5d1SDavid du Colombier 			break;
11423e12c5d1SDavid du Colombier 		}
11433e12c5d1SDavid du Colombier 		if(*cp1 & 0x80) {
11443e12c5d1SDavid du Colombier 			f = -1;
11453e12c5d1SDavid du Colombier 			break;
11463e12c5d1SDavid du Colombier 		}
11473e12c5d1SDavid du Colombier 		f = *cp1++ - *wp++;
11483e12c5d1SDavid du Colombier 		if(f != 0)
11493e12c5d1SDavid du Colombier 			break;
11503e12c5d1SDavid du Colombier 	}
11513e12c5d1SDavid du Colombier 
11523e12c5d1SDavid du Colombier 	if(f < 0) {
11533e12c5d1SDavid du Colombier 		while(!(*cp1 & 0x80))
11543e12c5d1SDavid du Colombier 			cp1++;
11553e12c5d1SDavid du Colombier 		bp = cp1;
11563e12c5d1SDavid du Colombier 		goto loop;
11573e12c5d1SDavid du Colombier 	}
11583e12c5d1SDavid du Colombier 	ep = cp;
11593e12c5d1SDavid du Colombier 	goto loop;
11603e12c5d1SDavid du Colombier 
11613e12c5d1SDavid du Colombier found:
11623e12c5d1SDavid du Colombier 	f = ((cp[0] & 0x7) << 8) |
11633e12c5d1SDavid du Colombier 		(cp[1] & 0xff);
11643e12c5d1SDavid du Colombier 	if(xflag) {
116559cc4ca5SDavid du Colombier 		fprint(2, "=%.*s ", utfnlen(w, n), w);
11663e12c5d1SDavid du Colombier 		typeprint(encode[f]);
11673e12c5d1SDavid du Colombier 	}
11683e12c5d1SDavid du Colombier 	return encode[f];
11693e12c5d1SDavid du Colombier }
11703e12c5d1SDavid du Colombier 
11713e12c5d1SDavid du Colombier void
typeprint(Bits h)11723e12c5d1SDavid du Colombier typeprint(Bits h)
11733e12c5d1SDavid du Colombier {
11743e12c5d1SDavid du Colombier 
11753e12c5d1SDavid du Colombier 	pcomma("");
11763e12c5d1SDavid du Colombier 	if(h & NOUN)
11773e12c5d1SDavid du Colombier 		pcomma("n");
11783e12c5d1SDavid du Colombier 	if(h & PROP_COLLECT)
11793e12c5d1SDavid du Colombier 		pcomma("pc");
11803e12c5d1SDavid du Colombier 	if(h & VERB) {
11813e12c5d1SDavid du Colombier 		if((h & VERB) == VERB)
11823e12c5d1SDavid du Colombier 			pcomma("v");
11833e12c5d1SDavid du Colombier 		else
11843e12c5d1SDavid du Colombier 		if((h & VERB) == V_IRREG)
11853e12c5d1SDavid du Colombier 			pcomma("vi");
11863e12c5d1SDavid du Colombier 		else
11873e12c5d1SDavid du Colombier 		if(h & ED)
11883e12c5d1SDavid du Colombier 			pcomma("ed");
11893e12c5d1SDavid du Colombier 	}
11903e12c5d1SDavid du Colombier 	if(h & ADJ)
11913e12c5d1SDavid du Colombier 		pcomma("a");
11923e12c5d1SDavid du Colombier 	if(h & COMP) {
11933e12c5d1SDavid du Colombier 		if((h & COMP) == ACTOR)
11943e12c5d1SDavid du Colombier 			pcomma("er");
11953e12c5d1SDavid du Colombier 		else
11963e12c5d1SDavid du Colombier 			pcomma("comp");
11973e12c5d1SDavid du Colombier 	}
11983e12c5d1SDavid du Colombier 	if(h & DONT_TOUCH)
11993e12c5d1SDavid du Colombier 		pcomma("d");
12003e12c5d1SDavid du Colombier 	if(h & N_AFFIX)
12013e12c5d1SDavid du Colombier 		pcomma("na");
12023e12c5d1SDavid du Colombier 	if(h & ADV)
12033e12c5d1SDavid du Colombier 		pcomma("adv");
12043e12c5d1SDavid du Colombier 	if(h & ION)
12053e12c5d1SDavid du Colombier 		pcomma("ion");
12063e12c5d1SDavid du Colombier 	if(h & V_AFFIX)
12073e12c5d1SDavid du Colombier 		pcomma("va");
12083e12c5d1SDavid du Colombier 	if(h & MAN)
12093e12c5d1SDavid du Colombier 		pcomma("man");
12103e12c5d1SDavid du Colombier 	if(h & NOPREF)
12113e12c5d1SDavid du Colombier 		pcomma("nopref");
12123e12c5d1SDavid du Colombier 	if(h & MONO)
12133e12c5d1SDavid du Colombier 		pcomma("ms");
12143e12c5d1SDavid du Colombier 	if(h & IN)
12153e12c5d1SDavid du Colombier 		pcomma("in");
12163e12c5d1SDavid du Colombier 	if(h & _Y)
12173e12c5d1SDavid du Colombier 		pcomma("y");
12183e12c5d1SDavid du Colombier 	if(h & STOP)
12193e12c5d1SDavid du Colombier 		pcomma("s");
12203e12c5d1SDavid du Colombier 	fprint(2, "\n");
12213e12c5d1SDavid du Colombier }
12223e12c5d1SDavid du Colombier 
12233e12c5d1SDavid du Colombier void
pcomma(char * s)12243e12c5d1SDavid du Colombier pcomma(char *s)
12253e12c5d1SDavid du Colombier {
12263e12c5d1SDavid du Colombier 	static flag;
12273e12c5d1SDavid du Colombier 
12283e12c5d1SDavid du Colombier 	if(*s == 0) {
12293e12c5d1SDavid du Colombier 		flag = 0;
12303e12c5d1SDavid du Colombier 		return;
12313e12c5d1SDavid du Colombier 	}
12323e12c5d1SDavid du Colombier 	if(!flag) {
12333e12c5d1SDavid du Colombier 		fprint(2, "%s", s);
12343e12c5d1SDavid du Colombier 		flag = 1;
12353e12c5d1SDavid du Colombier 	} else
12363e12c5d1SDavid du Colombier 		fprint(2, ",%s", s);
12373e12c5d1SDavid du Colombier }
12383e12c5d1SDavid du Colombier 
12393e12c5d1SDavid du Colombier /*
12403e12c5d1SDavid du Colombier  * is the word on of the following
12413e12c5d1SDavid du Colombier  *	12th	teen
12423e12c5d1SDavid du Colombier  *	21st	end in 1
12433e12c5d1SDavid du Colombier  *	23rd	end in 3
12443e12c5d1SDavid du Colombier  *	77th	default
12453e12c5d1SDavid du Colombier  * called knowing word[0] is a digit
12463e12c5d1SDavid du Colombier  */
12473e12c5d1SDavid du Colombier int
ordinal(void)12483e12c5d1SDavid du Colombier ordinal(void)
12493e12c5d1SDavid du Colombier {
1250219b2ee8SDavid du Colombier 	char *cp = word;
1251219b2ee8SDavid du Colombier 	static char sp[4];
12523e12c5d1SDavid du Colombier 
1253219b2ee8SDavid du Colombier 	while(ISDIGIT(*cp))
12543e12c5d1SDavid du Colombier 		cp++;
1255219b2ee8SDavid du Colombier 	strncpy(sp,cp,3);
1256219b2ee8SDavid du Colombier 	if(ISUPPER(cp[0]) && ISUPPER(cp[1])) {
1257219b2ee8SDavid du Colombier 		sp[0] = Tolower(cp[0]);
1258219b2ee8SDavid du Colombier 		sp[1] = Tolower(cp[1]);
12593e12c5d1SDavid du Colombier 	}
1260219b2ee8SDavid du Colombier 	return 0 == strncmp(sp,
1261219b2ee8SDavid du Colombier 		cp[-2]=='1'? "th":	/* out of bounds if 1 digit */
1262219b2ee8SDavid du Colombier 		*--cp=='1'? "st":	/* harmless */
1263219b2ee8SDavid du Colombier 		*cp=='2'? "nd":
1264219b2ee8SDavid du Colombier 		*cp=='3'? "rd":
1265219b2ee8SDavid du Colombier 		"th", 3);
12663e12c5d1SDavid du Colombier }
12673e12c5d1SDavid du Colombier 
12683e12c5d1SDavid du Colombier /*
12693e12c5d1SDavid du Colombier  * read in the dictionary.
12703e12c5d1SDavid du Colombier  * format is
12713e12c5d1SDavid du Colombier  * {
12723e12c5d1SDavid du Colombier  *	short	nencode;
12733e12c5d1SDavid du Colombier  *	long	encode[nencode];
12743e12c5d1SDavid du Colombier  *	char	space[*];
12753e12c5d1SDavid du Colombier  * };
12763e12c5d1SDavid du Colombier  *
12773e12c5d1SDavid du Colombier  * the encodings are a table all different
12783e12c5d1SDavid du Colombier  * affixes.
12793e12c5d1SDavid du Colombier  * the dictionary proper has 2 bytes
12803e12c5d1SDavid du Colombier  * that demark and then the rest of the
12813e12c5d1SDavid du Colombier  * word. the 2 bytes have the following
12823e12c5d1SDavid du Colombier  *	0x80 0x00	flag
12833e12c5d1SDavid du Colombier  *	0x78 0x00	count of prefix bytes
12843e12c5d1SDavid du Colombier  *			common with prev word
12853e12c5d1SDavid du Colombier  *	0x07 0xff	affix code
12863e12c5d1SDavid du Colombier  *
12873e12c5d1SDavid du Colombier  * all ints are big endians in the file.
12883e12c5d1SDavid du Colombier  */
12893e12c5d1SDavid du Colombier void
readdict(char * file)12903e12c5d1SDavid du Colombier readdict(char *file)
12913e12c5d1SDavid du Colombier {
12923e12c5d1SDavid du Colombier 	char *s, *is, *lasts, *ls;
12933e12c5d1SDavid du Colombier 	int c, i, sp, p;
12943e12c5d1SDavid du Colombier 	int f;
12953e12c5d1SDavid du Colombier 	long l;
12963e12c5d1SDavid du Colombier 
1297219b2ee8SDavid du Colombier 	lasts = 0;
12983e12c5d1SDavid du Colombier 	f = open(file, 0);
12993e12c5d1SDavid du Colombier 	if(f == -1) {
13003e12c5d1SDavid du Colombier 		fprint(2, "cannot open %s\n", file);
13013e12c5d1SDavid du Colombier 		exits("open");
13023e12c5d1SDavid du Colombier 	}
13033e12c5d1SDavid du Colombier 	if(read(f, space, 2) != 2)
13043e12c5d1SDavid du Colombier 		goto bad;
13053e12c5d1SDavid du Colombier 	nencode = ((space[0]&0xff)<<8) | (space[1]&0xff);
13063e12c5d1SDavid du Colombier 	if(read(f, space, 4*nencode) != 4*nencode)
13073e12c5d1SDavid du Colombier 		goto bad;
13083e12c5d1SDavid du Colombier 	s = space;
13093e12c5d1SDavid du Colombier 	for(i=0; i<nencode; i++) {
13103e12c5d1SDavid du Colombier 		l = (long)(s[0] & 0xff) << 24;
13113e12c5d1SDavid du Colombier 		l |= (s[1] & 0xff) << 16;
13123e12c5d1SDavid du Colombier 		l |= (s[2] & 0xff) << 8;
13133e12c5d1SDavid du Colombier 		l |= s[3] & 0xff;
13143e12c5d1SDavid du Colombier 		encode[i] = (Bits)l;
13153e12c5d1SDavid du Colombier 		s += 4;
13163e12c5d1SDavid du Colombier 	}
13173e12c5d1SDavid du Colombier 	l = read(f, space, sizeof(space));
13183e12c5d1SDavid du Colombier 	if(l == sizeof(space))
13193e12c5d1SDavid du Colombier 		goto noroom;
13203e12c5d1SDavid du Colombier 	is = space + (sizeof(space) - l);
13213e12c5d1SDavid du Colombier 	memmove(is, space, l);
13223e12c5d1SDavid du Colombier 
13233e12c5d1SDavid du Colombier 	s = space;
13243e12c5d1SDavid du Colombier 	c = *is++ & 0xff;
13253e12c5d1SDavid du Colombier 	sp = -1;
13263e12c5d1SDavid du Colombier 	i = 0;
13273e12c5d1SDavid du Colombier 
13283e12c5d1SDavid du Colombier loop:
13293e12c5d1SDavid du Colombier 	if(s > is)
13303e12c5d1SDavid du Colombier 		goto noroom;
13313e12c5d1SDavid du Colombier 	if(c < 0) {
13323e12c5d1SDavid du Colombier 		close(f);
13333e12c5d1SDavid du Colombier 		while(sp < 128*128)
13343e12c5d1SDavid du Colombier 			spacep[++sp] = s;
13353e12c5d1SDavid du Colombier 		*s = 0x80;		/* fence */
13363e12c5d1SDavid du Colombier 		return;
13373e12c5d1SDavid du Colombier 	}
13383e12c5d1SDavid du Colombier 	p = (c>>3) & 0xf;
13393e12c5d1SDavid du Colombier 	*s++ = c;
13403e12c5d1SDavid du Colombier 	*s++ = *is++ & 0xff;
13413e12c5d1SDavid du Colombier 	if(p <= 0)
13423e12c5d1SDavid du Colombier 		i = (*is++ & 0xff)*128;
13433e12c5d1SDavid du Colombier 	if(p <= 1) {
13443e12c5d1SDavid du Colombier 		if(!(*is & 0x80))
13453e12c5d1SDavid du Colombier 			i = i/128*128 + (*is++ & 0xff);
13463e12c5d1SDavid du Colombier 		if(i <= sp) {
13473e12c5d1SDavid du Colombier 			fprint(2, "the dict isnt sorted or \n");
13483e12c5d1SDavid du Colombier 			fprint(2, "memmove didn't work\n");
13493e12c5d1SDavid du Colombier 			goto bad;
13503e12c5d1SDavid du Colombier 		}
13513e12c5d1SDavid du Colombier 		while(sp < i)
13523e12c5d1SDavid du Colombier 			spacep[++sp] = s-2;
13533e12c5d1SDavid du Colombier 	}
13543e12c5d1SDavid du Colombier 	ls = lasts;
13553e12c5d1SDavid du Colombier 	lasts = s;
13563e12c5d1SDavid du Colombier 	for(p-=2; p>0; p--)
13573e12c5d1SDavid du Colombier 		*s++ = *ls++;
13583e12c5d1SDavid du Colombier 	for(;;) {
13593e12c5d1SDavid du Colombier 		if(is >= space+sizeof(space)) {
13603e12c5d1SDavid du Colombier 			c = -1;
13613e12c5d1SDavid du Colombier 			break;
13623e12c5d1SDavid du Colombier 		}
13633e12c5d1SDavid du Colombier 		c = *is++ & 0xff;
13643e12c5d1SDavid du Colombier 		if(c & 0x80)
13653e12c5d1SDavid du Colombier 			break;
13663e12c5d1SDavid du Colombier 		*s++ = c;
13673e12c5d1SDavid du Colombier 	}
13683e12c5d1SDavid du Colombier 	*s = 0;
13693e12c5d1SDavid du Colombier 	goto loop;
13703e12c5d1SDavid du Colombier 
13713e12c5d1SDavid du Colombier bad:
13723e12c5d1SDavid du Colombier 	fprint(2, "trouble reading %s\n", file);
13733e12c5d1SDavid du Colombier 	exits("read");
13743e12c5d1SDavid du Colombier noroom:
13753e12c5d1SDavid du Colombier 	fprint(2, "not enough space for dictionary\n");
13763e12c5d1SDavid du Colombier 	exits("space");
13773e12c5d1SDavid du Colombier }
1378