/***********************************************************************\ Filename: unfexc.c \***********************************************************************/ #include #include "thesmisc.h" #include "th.h" #define GETNIB() ((nb = ~nb) ? (bt = ctoi(*pdptr++)) >> 4 : bt & 0x0F) #define PXHEADER 8 static unfbin(); /* structure to handle the inflection exceptions processing */ static struct { int px_rev; int px_nlet; int px_wbin; int px_wlbin; int px_nbin; int px_nwords; int px_nbytes; int px_dummy; int *px_bintab; char *px_lettab; char *px_data; } Pxinfo; unfopen(ioptr) HANDLE ioptr; { char *zalloc(); long thesbit(); int i; char *strptr; int *pxptr; int offset; char str[sizeof(unsigned) * PXHEADER]; i = PXHEADER * sizeof(int); strptr = str; offset = i; while (--i >= 0) *strptr++ = thesbit(ioptr, 8); thintmv(str, (int *) &Pxinfo, PXHEADER); if ((Pxinfo.px_lettab = zalloc(_THID, (unsigned) Pxinfo.px_nlet)) == NULL || (Pxinfo.px_data = (char *) zalloc(_THID, (unsigned) Pxinfo.px_nbytes)) == NULL || (Pxinfo.px_bintab = (int *) zalloc(_THID, (unsigned) Pxinfo.px_nbin * sizeof(int))) == NULL) return (FALSE); strptr = (char *) Pxinfo.px_lettab; i = Pxinfo.px_nlet; offset += i; while (--i >= 0) *strptr++ = thesbit(ioptr, 8); offset += (i = Pxinfo.px_nbin) * sizeof(int); pxptr = Pxinfo.px_bintab; while (--i >= 0) { *pxptr = thesbit(ioptr, 8); *pxptr |= thesbit(ioptr, 8) << 8; ++pxptr; } i = Pxinfo.px_nbytes; strptr = Pxinfo.px_data; offset += i; while (--i >= 0) *strptr++ = thesbit(ioptr, 8); return (offset); } unfclose() { nzfree((char *)Pxinfo.px_data); nzfree((char *)Pxinfo.px_bintab); nzfree((char *)Pxinfo.px_lettab); } unfexc(word, excword, inftype) char *word; char *excword; int inftype; { int nb; /* flag set when nibble-getter needs a byte.*/ int c; /* index into px_lettab[] (see environ.h) */ char *pdptr; char *strptr; /* pointer to end of decompressed word */ char *saveptr; /* pointer to end of decompressed word */ int bt; /* latest byte read from corelex array */ int chind; /* index into px_lettab[] (see environ.h) */ int cmp; int bs; int bin; int binwords; int refcnt; int refindex; int refind; int refeof; int reftype; int skip; int retval; int refiarr[MAXREF]; int reftarr[MAXREF]; char clword[MAXWORD]; /* holds word during decompression */ bin = unfbin(word); binwords = bin < Pxinfo.px_nbin - 1 ? Pxinfo.px_wbin : Pxinfo.px_wlbin; pdptr = Pxinfo.px_data + Pxinfo.px_bintab[bin]; strptr = clword + 1; retval = nb = FALSE; /* decompress until the word is found. If the decompressed word is greater than word or if at the end of the bin return ERROR */ do { if (!binwords--) return (ERROR); bs = GETNIB() + 1; strptr -= bs; do { chind = 0; while ((c = GETNIB()) == 0xF) chind += 0xF; chind += c; } while (*strptr++ = Pxinfo.px_lettab[chind]); refcnt = 0; if ((cmp = strcmp(clword, word)) > 0) return (ERROR); do { refindex = GETNIB(); refeof = refindex & 0x8; if (cmp == 0) { refindex = ((refindex & 0x7) << 4) + GETNIB(); refindex = (refindex << 4) + GETNIB(); reftype = GETNIB(); reftype = ((reftype & 0x7) << 4) + GETNIB(); refiarr[refcnt] = refindex; reftarr[refcnt++] = reftype; } else { GETNIB(); GETNIB(); GETNIB(); GETNIB(); } } while (!refeof); } while (cmp); strptr = excword + 1; for (refind = 0; refind < refcnt; refind++) { refindex = refind; skip = FALSE; /* If inftype is UNF_IR retain only unflection entries. If a certain type of inflection is specified, discard elements in reftarr that do not match inftype. */ if ((inftype == UNF_IR && reftarr[refindex] & 1) || (inftype != UNF_IR && reftarr[refindex] != inftype)) continue; if (retval != 0 && retval != reftarr[refindex]) break; if ((retval = reftarr[refindex]) <= 0) return (retval); saveptr = strptr; bin = refiarr[refindex] / Pxinfo.px_wbin; binwords = refiarr[refindex] % Pxinfo.px_wbin + 1; pdptr = Pxinfo.px_data + Pxinfo.px_bintab[bin]; nb = FALSE; while (binwords--) { bs = GETNIB() + 1; strptr -= bs; do { chind = 0; while ((c = GETNIB()) == 0xF) chind += 0xF; chind += c; } while (*strptr++ = Pxinfo.px_lettab[chind]); do { refindex = GETNIB(); refeof = refindex & 0x8; GETNIB(); GETNIB(); GETNIB(); GETNIB(); } while (!refeof); } /* Take care of multiple unflections. */ if (!skip) { *(strptr - 1) = UNFSEP; *strptr++ = '\0'; } else strptr = saveptr; } if (strptr == &excword[1]) return (ERROR); *(strptr - 2) = '\0'; return (retval); } static unfbin(word0) char *word0; { char *word; /* actual word scanner */ char *pdptr; /* pointer into Pxinfo.px_data[] */ int bt; /* holds a byte read from px_data */ int bin; /* number of bin to be compared with input word */ int nb; /* nibble-getter flag */ int frindex; /* index into px_lettab[] for actual character */ int curindex; /* temporary index for processing hex-F sequences */ int minval; int maxval; minval = 0; maxval = Pxinfo.px_nbin - 1; while (minval < maxval) { bin = (minval + maxval + 1) / 2; /* px_bintab[bin] is byte offset into corelex array (px_data[]) of start of next bin to be checked. */ pdptr = Pxinfo.px_data + Pxinfo.px_bintab[bin]; /* Decompress the first word in the bin, comparing it with the input word to see if the input word is in the bin. */ nb = FALSE; /* get the backspace */ while ((curindex = GETNIB()) == 0xF) ; word = word0 - 1; do { /* read nibbles to form the character index; */ /* as in coreword(), sequence of hex-F's */ /* can be arbitrarily long */ frindex = curindex = GETNIB(); while (curindex == 0x0F) { curindex = GETNIB(); frindex += curindex; } if (*++word != Pxinfo.px_lettab[frindex]) break; } while (*word); /* update the binary search limits; test depends on */ /* string terminator ('\0') being the character with the */ /* smallest value */ if (ctoi(*word) >= ctoi(Pxinfo.px_lettab[frindex])) minval = bin; else maxval = bin - 1; } return (maxval); }