home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode:Text -*- */
- #ifndef lint
- static char Rcs_Id[] =
- "$Id: tgood.c,v 1.18 91/09/11 23:23:00 geoff Exp $";
- #endif
-
- /*
- * Copyright 1987, 1988, 1989, by Geoff Kuenning, Manhattan Beach, CA
- * Permission for non-profit use is hereby granted.
- * All other rights reserved.
- * See "version.h" for a more complete copyright notice.
- */
-
- /*
- * $Log: tgood.c,v $
- * Revision 1.18 91/09/11 23:23:00 geoff
- * Make sure that pure-deletion suffixes operate correctly, by adding the
- * necessary null byte after the strip portion.
- *
- * Revision 1.17 91/07/11 19:52:27 geoff
- * Remove the include of stdio.h, since ispell.h now does this.
- *
- * Revision 1.16 91/05/27 21:48:12 geoff
- * When checking affixes, remember to check for the case of affixes that
- * strip nothing and only add characters.
- *
- * Revision 1.15 90/12/31 01:04:16 geoff
- * Add a text-mode line so emacs will edit consistently.
- *
- * Revision 1.14 90/04/26 22:44:28 geoff
- * Add the canonicalize parameter to calls to ichartosstr.
- *
- * Revision 1.13 89/06/09 15:56:32 geoff
- * Add support for the internal "character" type, ichar_t.
- *
- * Revision 1.12 89/04/27 23:34:27 geoff
- * In suf_list_chk, call setfindlast just before the condition check, because
- * the word changes on each pass through the loop. Also call findlastchar
- * with the correct parameters.
- *
- * Revision 1.11 89/04/03 01:58:53 geoff
- * Fix a bunch of lint complaints. Add (partial) support for string
- * characters.
- *
- * Revision 1.10 88/12/26 02:33:04 geoff
- * Update the copyright notice.
- *
- * Revision 1.9 88/11/25 19:54:28 geoff
- * Fix some inconsistencies in the formatting of curly braces.
- *
- * Revision 1.8 88/04/30 22:16:04 geoff
- * Fix some lint complaints.
- *
- * Revision 1.7 88/02/20 23:14:44 geoff
- * Support the new capitalization handling. Add the "allhits" parameter to
- * chk_aff and its descendents.
- *
- * Revision 1.6 87/10/02 22:38:11 geoff
- * Modify expansion routines to exactly duplicate the capitalization
- * rules implemented by ins_cap and cap_ok.
- *
- * Revision 1.5 87/09/30 23:31:48 geoff
- * Move some globals to ispell.h. Add support for ignoreflagbits.
- * Rationalize some array sizes. Get rid of the checkbit calls and
- * replace them with a macro call.
- *
- * Revision 1.4 87/09/26 15:41:25 geoff
- * Make the sizes of the word buffers consistent.
- *
- * Revision 1.3 87/09/14 22:39:19 geoff
- * Add copyright comments
- *
- * Revision 1.2 87/09/09 00:19:43 geoff
- * Replace a lot of #ifdef's on NO8BIT with use of SET_SIZE and NOPARITY.
- *
- * Revision 1.1 87/07/20 22:56:14 geoff
- * Initial revision
- *
- */
-
- /*
- * Table-driven version of good.c.
- *
- * Geoff Kuenning, July 1987
- */
-
- #include <ctype.h>
- #include "config.h"
- #include "ispell.h"
-
- extern struct dent * lookup (); /* Look up a dictionary entry */
-
- extern char * strcpy ();
-
- /* Check possible affixes */
- chk_aff (word, ucword, len, ignoreflagbits, allhits)
- ichar_t * word; /* Word to be checked */
- ichar_t * ucword; /* Upper-case-only copy of word */
- int len; /* The length of word/ucword */
- int ignoreflagbits; /* Ignore whether affix is legal */
- int allhits; /* Keep going after first hit */
- {
- register ichar_t * cp; /* Pointer to char to index on */
- struct flagptr * ind; /* Flag index table to test */
-
- pfx_list_chk (word, ucword, len, &pflagindex[0], ignoreflagbits, allhits);
- cp = ucword;
- ind = &pflagindex[*cp++];
- while (ind->numents == 0 && ind->pu.fp != NULL)
- {
- if (*cp == 0)
- return;
- if (ind->pu.fp[0].numents)
- {
- pfx_list_chk (word, ucword, len, &ind->pu.fp[0],
- ignoreflagbits, allhits);
- if (numhits && !allhits && !cflag && !ignoreflagbits)
- return;
- }
- ind = &ind->pu.fp[*cp++];
- }
- pfx_list_chk (word, ucword, len, ind, ignoreflagbits, allhits);
- if (numhits && !allhits && !cflag && !ignoreflagbits)
- return;
- chk_suf (word, ucword, len, 0, (struct flagent *) NULL,
- ignoreflagbits, allhits);
- }
-
- /* Check some prefix flags */
- pfx_list_chk (word, ucword, len, ind, ignoreflagbits, allhits)
- ichar_t * word; /* Word to be checked */
- ichar_t * ucword; /* Upper-case-only word */
- int len; /* The length of ucword */
- struct flagptr * ind; /* Flag index table */
- int ignoreflagbits; /* Ignore whether affix is legal */
- int allhits; /* Keep going after first hit */
- {
- int cond; /* Condition number */
- register ichar_t * cp; /* Pointer into end of ucword */
- struct dent * dent; /* Dictionary entry we found */
- int entcount; /* Number of entries to process */
- register struct flagent *
- flent; /* Current table entry */
- int preadd; /* Length added to tword2 as prefix */
- register int tlen; /* Length of tword */
- ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */
- ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */
-
- for (flent = ind->pu.ent, entcount = ind->numents;
- entcount > 0;
- flent++, entcount--)
- {
- /*
- * See if the prefix matches.
- */
- tlen = len - flent->affl + flent->stripl;
- if (tlen > 0 && icharncmp (flent->affix, ucword, flent->affl) == 0
- && tlen >= flent->numconds)
- {
- /*
- * The prefix matches. Remove it, replace it by the "strip"
- * string (if any), and check the original conditions.
- */
- if (flent->stripl)
- (void) icharcpy (tword, flent->strip);
- (void) icharcpy (tword + flent->stripl, ucword + flent->affl);
- cp = tword;
- for (cond = 0; cond < flent->numconds; cond++)
- {
- if ((flent->conds[*cp++] & (1 << cond)) == 0)
- break;
- }
- if (cond >= flent->numconds)
- {
- /*
- * The conditions match. See if the word is in the
- * dictionary.
- */
- if (cflag)
- flagpr (tword, BITTOCHAR (flent->flagbit), flent->stripl,
- flent->affl, -1, 0);
- else if (ignoreflagbits)
- {
- if ((dent = lookup (tword, 1)) != NULL)
- {
- cp = tword2;
- if (flent->affl)
- {
- (void) icharcpy (cp, flent->affix);
- cp += flent->affl;
- *cp++ = '+';
- }
- preadd = cp - tword2;
- (void) icharcpy (cp, tword);
- cp += tlen;
- if (flent->stripl)
- {
- *cp++ = '-';
- (void) icharcpy (cp, flent->strip);
- }
- (void) ins_root_cap (tword2, word,
- flent->stripl, preadd,
- 0, (cp - tword2) - tlen - preadd,
- dent, flent, (struct flagent *) NULL);
- }
- }
- else if ((dent = lookup (tword, 1)) != NULL
- && TSTMASKBIT (dent->mask, flent->flagbit))
- {
- if (numhits < MAX_HITS)
- {
- hits[numhits].dictent = dent;
- hits[numhits].prefix = flent;
- hits[numhits].suffix = NULL;
- numhits++;
- }
- if (!allhits)
- return;
- }
- /*
- * Handle cross-products.
- */
- if (flent->flagflags & FF_CROSSPRODUCT)
- chk_suf (word, tword, tlen, 1, flent,
- ignoreflagbits, allhits);
- }
- }
- }
- }
-
- /* Check possible suffixes */
- chk_suf (word, ucword, len, crossonly, pfxent, ignoreflagbits, allhits)
- ichar_t * word; /* Word to be checked */
- ichar_t * ucword; /* Upper-case-only word */
- int len; /* The length of ucword */
- int crossonly; /* NZ to do only cross-products */
- struct flagent * pfxent; /* Prefix flag entry if crossonly */
- int ignoreflagbits; /* Ignore whether affix is legal */
- int allhits; /* Keep going after first hit */
- {
- register ichar_t * cp; /* Pointer to char to index on */
- struct flagptr * ind; /* Flag index table to test */
-
- suf_list_chk (word, ucword, len, &sflagindex[0], crossonly, pfxent,
- ignoreflagbits, allhits);
- cp = ucword + len - 1;
- ind = &sflagindex[*cp];
- while (ind->numents == 0 && ind->pu.fp != NULL)
- {
- if (cp == ucword)
- return;
- if (ind->pu.fp[0].numents)
- {
- suf_list_chk (word, ucword, len, &ind->pu.fp[0],
- crossonly, pfxent, ignoreflagbits, allhits);
- if (numhits != 0 && !allhits && !cflag && !ignoreflagbits)
- return;
- }
- ind = &ind->pu.fp[*--cp];
- }
- suf_list_chk (word, ucword, len, ind, crossonly, pfxent,
- ignoreflagbits, allhits);
- }
-
- suf_list_chk (word, ucword, len, ind, crossonly, pfxent,
- ignoreflagbits, allhits)
- ichar_t * word; /* Word to be checked */
- ichar_t * ucword; /* Upper-case-only word */
- int len; /* The length of ucword */
- struct flagptr * ind; /* Flag index table */
- int crossonly; /* NZ to do only cross-products */
- struct flagent * pfxent; /* Prefix flag entry if crossonly */
- int ignoreflagbits; /* Ignore whether affix is legal */
- int allhits; /* Keep going after first hit */
- {
- register ichar_t * cp; /* Pointer into end of ucword */
- int cond; /* Condition number */
- struct dent * dent; /* Dictionary entry we found */
- int entcount; /* Number of entries to process */
- register struct flagent *
- flent; /* Current table entry */
- int preadd; /* Length added to tword2 as prefix */
- register int tlen; /* Length of tword */
- ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */
- ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */
-
- (void) icharcpy (tword, ucword);
- for (flent = ind->pu.ent, entcount = ind->numents;
- entcount > 0;
- flent++, entcount--)
- {
- if (crossonly && (flent->flagflags & FF_CROSSPRODUCT) == 0)
- continue;
- /*
- * See if the suffix matches.
- */
- tlen = len - flent->affl;
- if (tlen > 0
- && tlen + flent->stripl > 1
- && (flent->affl == 0
- || icharcmp (flent->affix, ucword + tlen) == 0)
- && tlen + flent->stripl >= flent->numconds)
- {
- /*
- * The suffix matches. Remove it, replace it by the "strip"
- * string (if any), and check the original conditions.
- */
- (void) icharcpy (tword, ucword);
- cp = tword + tlen;
- if (flent->stripl)
- {
- (void) icharcpy (cp, flent->strip);
- tlen += flent->stripl;
- cp = tword + tlen;
- }
- else
- *cp = '\0';
- for (cond = flent->numconds; --cond >= 0; )
- {
- if ((flent->conds[*--cp] & (1 << cond)) == 0)
- break;
- }
- if (cond < 0)
- {
- /*
- * The conditions match. See if the word is in the
- * dictionary.
- */
- if (cflag)
- {
- if (crossonly)
- flagpr (tword, BITTOCHAR (pfxent->flagbit),
- pfxent->stripl, pfxent->affl,
- BITTOCHAR (flent->flagbit), flent->affl);
- else
- flagpr (tword, -1, 0, 0,
- BITTOCHAR (flent->flagbit), flent->affl);
- }
- else if (ignoreflagbits)
- {
- if ((dent = lookup (tword, 1)) != NULL)
- {
- cp = tword2;
- if (crossonly && pfxent->affl != 0)
- {
- (void) icharcpy (cp, pfxent->affix);
- cp += pfxent->affl;
- *cp++ = '+';
- }
- preadd = cp - tword2;
- (void) icharcpy (cp, tword);
- cp += tlen;
- if (crossonly && pfxent->stripl != 0)
- {
- *cp++ = '-';
- (void) icharcpy (cp, pfxent->strip);
- cp += pfxent->stripl;
- }
- if (flent->stripl)
- {
- *cp++ = '-';
- (void) icharcpy (cp, flent->strip);
- cp += flent->stripl;
- }
- if (flent->affl)
- {
- *cp++ = '+';
- (void) icharcpy (cp, flent->affix);
- cp += flent->affl;
- }
- (void) ins_root_cap (tword2, word,
- crossonly ? pfxent->stripl : 0, preadd,
- flent->stripl, (cp - tword2) - tlen - preadd,
- dent, pfxent, flent);
- }
- }
- else if ((dent = lookup (tword, 1)) != NULL
- && TSTMASKBIT (dent->mask, flent->flagbit)
- && (!crossonly || TSTMASKBIT (dent->mask, pfxent->flagbit)))
- {
- if (numhits < MAX_HITS)
- {
- hits[numhits].dictent = dent;
- hits[numhits].prefix = pfxent;
- hits[numhits].suffix = flent;
- numhits++;
- }
- if (!allhits)
- return;
- }
- }
- }
- }
- }
-
- /*
- * Expand a dictionary prefix entry
- */
- expand_pre (rootword, mask)
- ichar_t * rootword; /* Root word to expand */
- register MASKTYPE mask[]; /* Mask bits to expand on */
- {
- int entcount; /* No. of entries to process */
- register struct flagent *
- flent; /* Current table entry */
-
- for (flent = pflaglist, entcount = numpflags;
- entcount > 0;
- flent++, entcount--)
- {
- if (TSTMASKBIT (mask, flent->flagbit))
- pr_pre_expansion (rootword, flent, mask);
- }
- }
-
- pr_pre_expansion (rootword, flent, mask) /* Print a prefix expansion */
- register ichar_t * rootword; /* Root word to expand */
- register struct flagent * flent; /* Current table entry */
- MASKTYPE mask[]; /* Mask bits to expand on */
- {
- int cond; /* Current condition number */
- register ichar_t * nextc; /* Next case choice */
- int tlen; /* Length of tword */
- ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Tmp cpy */
-
- tlen = icharlen (rootword);
- if (flent->numconds > tlen)
- return;
- if (tlen - flent->stripl + flent->affl <= 0)
- return;
- for (cond = 0, nextc = rootword; cond < flent->numconds; cond++)
- {
- if ((flent->conds[mytoupper (*nextc++)] & (1 << cond)) == 0)
- return;
- }
- /*
- * The conditions are satisfied. Copy the word, add the prefix,
- * and make it the proper case. This code is carefully written
- * to match that ins_cap and cap_ok. Note that the affix, as
- * inserted, is uppercase.
- *
- * There is a tricky bit here: if the root is capitalized, we
- * want a capitalized result. If the root is followcase, however,
- * we want to duplicate the case of the first remaining letter
- * of the root. In other words, "Loved/U" should generate "Unloved",
- * but "LOved/U" should generate "UNLOved" and "lOved/U" should
- * produce "unlOved".
- */
- if (flent->affl)
- {
- (void) icharcpy (tword, flent->affix);
- nextc = tword + flent->affl;
- }
- (void) icharcpy (nextc, rootword + flent->stripl);
- if (myupper (rootword[0]))
- {
- /* We must distinguish followcase from capitalized */
- for (nextc = rootword + 1; *nextc; )
- {
- if (!myupper (*nextc++))
- break;
- }
- if (*nextc)
- {
- /* It's a followcase or all-upper word. We don't care which. */
- if (!myupper (tword[flent->affl]));
- forcelc (tword, flent->affl);
- }
- else
- {
- /* It's capitalized */
- forcelc (tword + 1, tlen + flent->affl - flent->stripl);
- }
- }
- else
- {
- /* Followcase or all-lower, we don't care which */
- if (!myupper (*nextc));
- forcelc (tword, flent->affl);
- }
- (void) printf (" %s", ichartosstr (tword, 1));
- if (flent->flagflags & FF_CROSSPRODUCT)
- expand_suf (tword, mask, 1);
- }
-
- /*
- * Expand a dictionary suffix entry
- */
- expand_suf (rootword, mask, crossonly)
- ichar_t * rootword; /* Root word to expand */
- register MASKTYPE mask[]; /* Mask bits to expand on */
- int crossonly; /* NZ for cross-products only */
- {
- int entcount; /* No. of entries to process */
- register struct flagent *
- flent; /* Current table entry */
-
- for (flent = sflaglist, entcount = numsflags;
- entcount > 0;
- flent++, entcount--)
- {
- if (TSTMASKBIT (mask, flent->flagbit))
- {
- if (!crossonly || (flent->flagflags & FF_CROSSPRODUCT))
- pr_suf_expansion (rootword, flent);
- }
- }
- }
-
- pr_suf_expansion (rootword, flent) /* Print a suffix expansion */
- register ichar_t * rootword; /* Root word to expand */
- register struct flagent * flent; /* Current table entry */
- {
- int cond; /* Current condition number */
- register ichar_t * nextc; /* Next case choice */
- int tlen; /* Length of tword */
- ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Tmp cpy */
-
- tlen = icharlen (rootword);
- cond = flent->numconds;
- if (cond > tlen)
- return;
- if (tlen - flent->stripl + flent->affl <= 0)
- return;
- for (nextc = rootword + tlen; --cond >= 0; )
- {
- if ((flent->conds[mytoupper (*--nextc)] & (1 << cond)) == 0)
- return;
- }
- /*
- * The conditions are satisfied. Copy the word, add the suffix,
- * and make it match the case of the last remaining character of the
- * root. Again, this code carefully matches ins_cap and cap_ok.
- */
- (void) icharcpy (tword, rootword);
- nextc = tword + tlen - flent->stripl;
- if (flent->affl)
- {
- (void) icharcpy (nextc, flent->affix);
- if (!myupper (nextc[-1]))
- forcelc (nextc, flent->affl);
- }
- else
- *nextc = 0;
- (void) printf (" %s", ichartosstr (tword, 1));
- }
-
- forcelc (dst, len) /* Force to lowercase */
- register ichar_t * dst; /* Destination to modify */
- register int len; /* Length to copy */
- {
-
- for ( ; --len >= 0; dst++)
- *dst = mytolower (*dst);
- }
-