antoine-source/appleworksgs/Spell/Src/INFLECT.C
2023-03-04 03:45:20 +01:00

1 line
20 KiB
C
Executable File

/***********************************************************************\
Filename: inflect.c
\***********************************************************************/
#include "thesmisc.h"
#include <string.h>
#define VMASK 0x1104111
#define isvowel(c) ((1 << (c - 'a')) & VMASK) /* aeiouy */
static iplural();
static ido_ly();
static inormend();
static ido_ment();
static ido_able();
static alttry();
static ido_est();
static END *Infstgptr;
inflect(source, str, posflag, sp)
char *source; /* string to inflect */
char *str; /* inflected string */
int posflag; /* the word to be inflected is a noun or verb */
END *sp; /* inflection stage pointer. */
{
char *endptr;
char *tmpptr;
char *start;
char *endstr;
int infindex;
short unfrel;
char past[MAXWORD];
char pp[MAXWORD];
char dummy[MAXWORD];
char rtstr[MAXWORD];
if (!(Infstgptr = sp))
return (FALSE);
endstr = (char *) Infstgptr->en_end;
/* If the string is a phrase, it should be either a verb or a noun.
If it is a verb, inflect the first word
if it is a noun, inflect the last word.
*/
unfrel = Infstgptr->en_rel;
strecpy(str, source);
if (unfrel == TP_SP || unfrel == TP_FP)
return (TRUE);
endptr = start = str;
while (*endptr && *endptr != ' ')
++endptr;
*rtstr = '\0';
if (*endptr == ' ')
{
if ((infindex = unfexc(source, dummy, unfrel)) != ERROR)
{
if (infindex == 0)
return (FALSE);
strecpy(str, dummy);
return (TRUE);
}
tmpptr = endptr++;
switch (unfrel)
{
case AJ_NN:
case VB_NN:
case AJ_AV:
case VB_AJ:
return (FALSE);
default:
break;
}
if (posflag == VERB)
{
endptr = tmpptr;
strecpy(rtstr, endptr);
*endptr = '\0';
}
else if (posflag == NOUN)
{
str = tmpptr + 1;
while (*endptr)
{
if (*endptr == ' ')
str = endptr + 1;
++endptr;
}
}
else
return (FALSE);
}
/* See if it is an exception. If we have a pluralizing relation
take exceptions only if noun is indicated. */
if (posflag == NOUN || unfrel != SI_PL)
{
if (unfrel == PR_PS || unfrel == PR_PP)
{
if ((infindex = unfexc(str, str, PR_PX)) > 0)
{
appndstr(str, rtstr, INFCODE);
return (TRUE);
}
}
if ((infindex = unfexc(str, str, unfrel)) != ERROR)
{
if (infindex == 0)
return (FALSE);
appndstr(str, rtstr, INFCODE);
return (TRUE);
}
else if (unfrel == SV_PX)
{
unfrel = PR_PX;
if ((infindex = unfexc(str, str, unfrel)) > 0)
{
appndstr(str, rtstr, INFCODE);
return (TRUE);
}
}
else if (unfrel == SP_PL)
{
unfrel = SI_PL;
if ((infindex = unfexc(str, str, unfrel)) > 0)
{
appndstr(str, rtstr, INFCODE);
return (TRUE);
}
}
}
/* Take care of the ambiguous past/past participle forms */
if (unfrel == PR_PX)
{
/* Find the past tense */
endptr = strecpy(past, str);
if ((infindex = unfexc(past, dummy, PR_PS)) != ERROR)
{
if (infindex != 0)
strecpy(past, dummy);
appndstr(past, rtstr, INFCODE);
}
else
{
if (!inormend(past, endptr, endstr))
return (FALSE);
endptr = strecpy(str, past);
appndstr(str, rtstr, INFCODE);
if ((infindex = unfexc(str, dummy, UNF_IR)) == 0)
return (FALSE);
return (TRUE);
}
/* Find the past participle */
endptr = strecpy(pp, str);
if ((infindex = unfexc(pp, dummy, PR_PP)) > 0)
{
endptr = strecpy(pp, dummy);
appndstr(pp, rtstr, INFCODE);
}
else
strecpy(pp, past);
/* If the past and pp forms are different
construct <past>/<pp>. */
if (strcmp(pp, past) != 0)
{
endptr = strecpy(str, past);
*endptr++ = UNFSEP;
strecpy(endptr, pp);
return (TRUE);
}
strecpy (str, past);
return (TRUE);
}
switch (Infstgptr->en_class)
{
case 0: /* s */
if (!iplural(str, endptr, posflag))
return (FALSE);
break;
case 1:
if (!ido_ly(str, endptr, endstr))
return (FALSE);
break;
case 2:
case 3:
if (unfrel == RE_CM || unfrel == RE_SU) /* er/est */
{
if (!ido_est(str, endptr, endstr))
return (FALSE);
}
else if (!inormend(str, endptr, endstr))
return (FALSE);
break;
case 4:
if (!ido_ment(str, endptr, endstr))
return (FALSE);
break;
case 5:
if (!ido_able(str,endptr, "able") || strlen((char *) str) <
6)
return (FALSE);
break;
case 6:
case 7:
case 8:
case 9:
if (!iplural(str, endptr, posflag))
return (FALSE);
break;
default:
return (FALSE);
}
appndstr(str, rtstr, INFCODE);
if ((infindex = unfexc(start, dummy, UNF_IR)) == 0)
return (FALSE);
return (TRUE);
}
static iplural(str, endptr, pos)
char *str;
char *endptr;
int pos;
{
char end1[MAXWORD];
char end2[MAXWORD];
switch (endptr[-1]) {
case 'y': /* toy -> toys */
*endptr = 's';
endptr[1] = '\0';
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 'i'; /* candy -> candies */
*endptr++ = 'e';
break;
case 'h':
*endptr = 's'; /* bath -> baths */
endptr[1] = '\0';
if (unftry(str))
return (TRUE);
*endptr++ = 'e'; /* fish -> fishes */
break;
case 's': /* crisis -> crises */
if (endptr[-2] == 'i' && endptr[-3] == 's')
{
endptr[-2] = 'e';
*endptr = '\0';
if (unftry(str))
return (TRUE);
endptr[-2] = 'i';
}
if (endptr[-2] == 'u' && pos == NOUN) { /* focus -> foci */
endptr[-2] = 'i';
endptr[-1] = '\0';
if (unftry(str))
return (TRUE);
endptr[-2] = 'u';
endptr[-1] = 's';
}
strecpy(endptr, "ses"); /* gas -> gasses */
if (unftry(str))
return (TRUE);
*endptr++ = 'e';
break;
case 'x':
if ((endptr[-2] == 'i' || endptr[-2] == 'e') && pos == NOUN)
{
end1[0] = endptr[-2];
strecpy(&end1[1], "xes");
strecpy(end2, end1);
end2[0] = 'i';
end2[1] = 'c';
return (alttry(str, endptr-2, end1, end2));
/* vertex -> vertexes or vertices */
}
*endptr++ = 'e'; /* box -> boxes */
*endptr++ = 's';
*endptr = '\0';
if (!unftry(str))
*str = '\0';
else
return (TRUE);
case 'u': /* plateau -> plateaus or plateaux*/
end1[0] = 's';
end2[0] = 'x';
end1[1] = end2[1] = '\0';
return (alttry(str, endptr, end1, end2));
case 'z':
strecpy(endptr, "zes"); /* quiz -> quizzes */
if (unftry(str))
return (TRUE);
*endptr++ = 'e'; /* buzz -> buzzes */
break;
case 'f': /* puff -> puffs */
if (endptr[-2] != 'f') /* carafe -> carafes */
{
*endptr++ = 's';
*endptr = '\0';
if (unftry(str))
return (TRUE);
endptr -= 2; /* loaf -> loaves */
*endptr++ = 'v';
*endptr++ = 'e';
}
break;
case 'e':
if (endptr[-3] == 'e' && endptr[-2] == 's')
return (TRUE);
*endptr = 's';
endptr[1] = '\0';
if (unftry(str))
return (TRUE);
if (endptr[-2] == 'f') /* life -> lives */
{
endptr[-2] = 'v';
if (unftry(str)) {
return (TRUE);
}
}
return (FALSE);
case 'o':
if (pos == VERB && !isvowel(endptr[-2]))
{
*endptr = 'e';
endptr[1] = 's';
endptr[2] = '\0';
if (unftry(str)) /* do -> does */
return (TRUE);
}
else
{
end1[0] = 'e';
end1[1] = 's';
end2[0] = 's';
end1[2] = end2[1] = '\0';
return (alttry(str, endptr, end1, end2));
}
break;
case 'n':
if (endptr[-2] == 'a' && endptr[-3] == 'm')
{
endptr[-2] = 'e'; /* man -> men */
if (unftry(str))
return (TRUE);
endptr[-2] = 'a'; /* human -> humans */
}
break;
case 'm':
if (endptr[-2] == 'u' && pos == NOUN)
{
end1[0] = 'u';
end1[1] = 'm'; /* medium -> mediums or media */
end1[2] = 's';
end2[0] = 'a';
end1[3] = end2[1] = '\0';
return (alttry(str, endptr-2, end1, end2));
}
break;
default:
break;
}
*endptr++ = 's'; /* <word> -> <word>s */
*endptr = '\0';
return (unftry(str));
}
static ido_ly(str, endptr, ending)
char *str;
char *endptr;
char *ending;
{
switch (endptr[-1])
{
case 'y': /* ready -> readily */
endptr[-1] = 'i';
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 'y'; /* gay -> gayly */
return (unftry(str));
case 'l': /* accidental -> accidentally */
if (endptr[-2] == 'l') {
--endptr;
}
break;
case 'e':
if (endptr[-2] == 'l' && endptr[-3] == 'b') {
endptr[-1] = 'y'; /* able -> ably */
*endptr = '\0';
if (unftry(str)) {
return (TRUE);
}
}
break;
case 'c':
strecpy(endptr, ending); /* impolitic -> impoliticly */
if (unftry(str)) {
return (TRUE);
}
if (endptr[-2] == 'i' || endptr[-2] == 'a') {
strecpy(endptr, "ally");
if (unftry(str)) { /* athletic -> athletically */
return (TRUE);
}
}
return (FALSE);
default:
break;
}
strecpy(endptr, ending); /* <word> -> <word>ly */
return (unftry(str));
}
static inormend(str, endptr, ending)
char *str;
char *endptr;
char *ending;
{
char end1[MAXWORD]; /* the two endings used to generate */
char end2[MAXWORD]; /* alternative forms */
if (Infstgptr->en_rel == AJ_NN) {
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE); /* busy -> busyness */
}
if (endptr[-1] == 'y') {
endptr[-1] = 'i';
return (unftry(str));
}
return (FALSE);
}
switch (endptr[-1]) {
case 'y':
endptr[-1] = 'i';
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 'y'; /* cry -> cried */
break;
case 'e':
if (Infstgptr->en_rel == PR_PC) {
if (endptr[-2] == 'i') {
endptr -= 2;
strecpy(strecpy(end2, endptr),ending);
end1[0] = 'y';
strecpy(end1 + 1, ending);
if (alttry(str, endptr, end1, end2)) {
return (TRUE);
}
endptr += 2;
} else if (endptr[-2] == 'y') {
strecpy(endptr, ending); /* eye -> eyeing */
if (unftry(str)) {
return (TRUE);
}
}
}
endptr--; /* able -> abling */
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
*endptr++ = 'e';
break;
case 'a':
case 'i':
case 'o':
case 'u':
break;
case 'h':
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
break;
case 'c': /* panic -> panicking */
if (endptr[-2] == 'a' || endptr[-2] == 'i') {
*endptr++ = 'k';
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
}
endptr--;
break;
case 'l': /* level -> leveled or levelled */
strecpy(end1, ending);
end2[0] = endptr[-1];
strecpy(&end2[1], ending);
return (alttry(str, endptr, end1, end2));
case 's':
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
default:
*endptr = endptr[-1];
endptr++;
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
endptr--;
break;
}
strecpy(endptr, ending);
return (unftry(str));
}
static ido_ment(str, endptr, ending)
char *str;
char *endptr;
char *ending;
{
strecpy(endptr, ending); /* <word> -> <word>ment */
if (unftry(str)) {
return (TRUE);
}
*endptr = '\0'; /* acknowledge -> acknowledgment */
if (strcmp(&endptr[-3], "dge") == 0) {
strecpy(&endptr[-1], ending);
return(unftry(str));
}
return (FALSE);
}
static ido_able(str, endptr, ending)
char *str;
char *endptr;
char *ending;
{
char altend[MAXWORD];
strecpy(altend, ending);
altend[0] = 'i';
if (endptr[-1] == endptr[-2]) {
strecpy(endptr, ending);
return (unftry(str));
}
switch (endptr[-1]) {
case 'y':
endptr[-1] = 'i'; /* try -> triable */
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 'y';
break;
case 'd':
*endptr = endptr[-1];
strecpy(&endptr[1], ending);
if (unftry(str)) {
return (TRUE);
}
strecpy(endptr, altend); /* extend -> extendible */
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 's'; /* defend -> defensible */
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 'd';
strecpy(endptr, ending);
return (unftry(str));
case 't':
*endptr = endptr[-1]; /* rebut -> rebuttable */
strecpy(&endptr[1], ending);
if (unftry(str)) {
return (TRUE);
}
if (endptr[-2] == 'i') { /* permit -> permissible */
endptr[-1] = 's';
*endptr = 's';
strecpy(&endptr[1], altend);
if (unftry(str)) {
return (TRUE);
}
endptr[-1] = 't';
}
strecpy(endptr, altend);
if (unftry(str)) {
return (TRUE);
}
strecpy(endptr, ending);
return (unftry(str));
case 'b': /* recall -> recallable */
case 'f':
case 'g':
case 'l':
case 'm':
case 'n':
case 'p':
case 'r':
*endptr = endptr[-1];
strecpy(&endptr[1], ending);
if (unftry(str)) {
return (TRUE);
}
strecpy(endptr, ending);
return (unftry(str));
case 'e':
strecpy(&endptr[-1], ending); /* repute -> reputable */
if (unftry(str)) {
return (TRUE);
}
strecpy(&endptr[-1], altend);
if (unftry(str)) {
return (TRUE);
}
if (endptr[-3] == 'a' && endptr[-2] == 't') {
strecpy(&endptr[-3], ending);
if (unftry(str)) {
return (TRUE);
}
endptr[-2] = 't';
}
endptr[-1] = 'e';
strecpy(endptr, ending); /* change -> changeable */
return (unftry(str));
default:
break;
}
strecpy(endptr, ending); /* <word> -> <word>able */
if (unftry(str)) {
return (TRUE);
}
strecpy(endptr, altend); /* <word> -> <word>ible */
return (unftry(str));
}
/* Try alternative inflected forms. Return a string containing
the acceptable inflection(s) separated by UNFSEP */
static alttry(str, endptr, end1, end2)
char *str;
char *endptr;
char *end1;
char *end2;
{
char tmpstr[MAXWORD];
*endptr = '\0';
strecpy(strecpy(tmpstr, str), end2);
endptr = strecpy(endptr, end1);
if (unftry(str)) {
*endptr++ = UNFSEP;
} else {
endptr = str;
}
strecpy(endptr, tmpstr);
if (!unftry(endptr)) {
if (endptr != str) {
endptr--;
}
*endptr = '\0';
}
return (*str != '\0');
}
static ido_est(str, endptr, ending)
char *str;
char *endptr;
char *ending;
{
char end1[MAXWORD];
char end2[MAXWORD];
char altend[MAXWORD];
char prefix[MAXWORD];
if (Infstgptr->en_rel == RE_CM) {
strecpy(altend, "est");
strecpy(prefix, "more ");
} else {
strecpy(altend, "er");
strecpy(prefix, "most ");
}
switch (endptr[-1]) {
case 'y' :
endptr[-1] = 'i';
strecpy(endptr, altend);
if (unftry(str)) {
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
}
endptr[-1] = 'y';
break;
case 'e':
endptr--;
strecpy(endptr, altend);
if (unftry(str)) {
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
}
*endptr++ = 'e';
break;
case 'l':
strecpy(endptr, altend);
if (unftry(str)) {
strecpy(end1, ending);
end2[0] = 'l';
strecpy(&end2[1], ending);
return (alttry(str, endptr, end1, end2));
}
default:
*endptr = endptr[-1];
endptr++;
strecpy(endptr, altend);
if (unftry(str)) {
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
}
*--endptr = '\0';
break;
}
strecpy(endptr, altend);
if (unftry(str)) {
strecpy(endptr, ending);
if (unftry(str)) {
return (TRUE);
}
}
*endptr = '\0';
strecpy(strchr(prefix, 0), str);
strecpy(str, prefix);
return (TRUE);
}
/* Append rtstr to each word in str (separated by UNFSEP) */
appndstr(str, rtstr, code)
char *str;
char *rtstr;
int code;
{
char *tmpptr;
char *strptr;
char tmpstr[LONGWORD];
strptr = str;
tmpptr = tmpstr;
while (*strptr != '\0')
{
if (*strptr == UNFSEP)
{
if (*rtstr != '\0')
tmpptr = strecpy(tmpptr, rtstr);
if (code == INFCODE)
*strptr = INFSEP;
}
*tmpptr++ = *strptr++;
}
strecpy(tmpptr, rtstr);
strecpy(str, tmpstr);
}