|
|
1.1 ! root 1: /* ! 2: * Common routines to read and write words ! 3: * in the compressed dictionary for the ! 4: * simple (but complete) version of spell. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: ! 10: /* ! 11: * The coding is as follows: ! 12: * 1-26 are letters, 27 is `-', 28 is apostrophe. ! 13: * 0 is the pad character at word's end. ! 14: * 29 is optional `s', 30-31 is unused. ! 15: * They are packed with 3 per 16 bits (canonically) ! 16: * and the 16th bit is the end-of-word marker. ! 17: * This is all done independent of byte-ordering or ! 18: * word size. All that is required is at least 8-bit ! 19: * bytes (chars) and at least 16-bit words (ints). ! 20: */ ! 21: ! 22: static char compress[256]; /* Initialised in init */ ! 23: ! 24: static char expand[] = { ! 25: '\0', ! 26: 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', ! 27: 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', ! 28: 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', ! 29: 'y', 'z', '-','\'', '#','\0','\0' ! 30: }; ! 31: ! 32: #define EWORD 0100000 /* End of word */ ! 33: #define NWORD 50 /* Length of a word */ ! 34: #define NCLONE 500 /* Number of clones to save (maximum) */ ! 35: #define NSPACE 2000 /* Size of string space for plurals */ ! 36: ! 37: static char word[NWORD]; /* Static space returned by getword() */ ! 38: static char space[NSPACE]; ! 39: static char *spacep = space; ! 40: static char *clones[NCLONE]; /* Table of saved plurals */ ! 41: static int nclone; ! 42: ! 43: /* ! 44: * Initialise the compressed table. ! 45: * This is independent of character set ! 46: * representation (e.g. ascii or ebcdic) ! 47: * and only has to be called if putword is used. ! 48: */ ! 49: init() ! 50: { ! 51: compress['-'] = 27; ! 52: compress['\'']= 28; ! 53: compress['#'] = 29; ! 54: compress['a'] = compress['A'] = 1; ! 55: compress['b'] = compress['B'] = 2; ! 56: compress['c'] = compress['C'] = 3; ! 57: compress['d'] = compress['D'] = 4; ! 58: compress['e'] = compress['E'] = 5; ! 59: compress['f'] = compress['F'] = 6; ! 60: compress['g'] = compress['G'] = 7; ! 61: compress['h'] = compress['H'] = 8; ! 62: compress['i'] = compress['I'] = 9; ! 63: compress['j'] = compress['J'] = 10; ! 64: compress['k'] = compress['K'] = 11; ! 65: compress['l'] = compress['L'] = 12; ! 66: compress['m'] = compress['M'] = 13; ! 67: compress['n'] = compress['N'] = 14; ! 68: compress['o'] = compress['O'] = 15; ! 69: compress['p'] = compress['P'] = 16; ! 70: compress['q'] = compress['Q'] = 17; ! 71: compress['r'] = compress['R'] = 18; ! 72: compress['s'] = compress['S'] = 19; ! 73: compress['t'] = compress['T'] = 20; ! 74: compress['u'] = compress['U'] = 21; ! 75: compress['v'] = compress['V'] = 22; ! 76: compress['w'] = compress['W'] = 23; ! 77: compress['x'] = compress['X'] = 24; ! 78: compress['y'] = compress['Y'] = 25; ! 79: compress['z'] = compress['Z'] = 26; ! 80: } ! 81: ! 82: /* ! 83: * Read a word from the dictionary, ! 84: * one `dfp'. Return pointer to ! 85: * word or NULL on EOF. ! 86: * `*' words are cloned into the singular ! 87: * and plural. The plural is saved until ! 88: * it comes up in collating order. ! 89: */ ! 90: char * ! 91: getword(dfp) ! 92: FILE *dfp; ! 93: { ! 94: register char *wp; ! 95: register int t = EWORD; ! 96: static int clone; ! 97: static int saved; ! 98: ! 99: if (saved) { ! 100: saved = 0; ! 101: } else { ! 102: clone = 0; ! 103: wp = word; ! 104: for (;;) { ! 105: register int c; ! 106: ! 107: if ((c = getc(dfp)) == EOF) ! 108: break; ! 109: t = c; ! 110: if ((c = getc(dfp)) == EOF) ! 111: goto bad; ! 112: t <<= 8; ! 113: t |= c; ! 114: if ((*wp++ = expand[t&037]) == '#') ! 115: clone++; ! 116: if ((*wp++ = expand[(t>>5)&037]) == '#') ! 117: clone++; ! 118: if ((*wp++ = expand[(t>>10)&037]) == '#') ! 119: clone++; ! 120: if (t & EWORD) ! 121: break; ! 122: } ! 123: if (wp == word) ! 124: return (NULL); ! 125: if ((t&EWORD) == 0) ! 126: goto bad; ! 127: if (clone) ! 128: while (wp > word) ! 129: if (*--wp == '#') ! 130: break; ! 131: *wp = '\0'; ! 132: } ! 133: if (nclone && strcmp(word, clones[nclone-1])>0) { ! 134: wp = clones[--nclone]; ! 135: saved++; ! 136: return (spacep = wp); ! 137: } else if (clone) { ! 138: plural(word); ! 139: clone = 0; ! 140: } ! 141: return (word); ! 142: bad: ! 143: fprintf(stderr, "spell: bad dictionary format\n"); ! 144: exit(1); ! 145: } ! 146: ! 147: /* ! 148: * Pluralise the word, by adding an 's' to it. ! 149: * Save a copy away in the list of pending plurals ! 150: * (`clones'). ! 151: */ ! 152: static ! 153: plural(s) ! 154: char *s; ! 155: { ! 156: register char *cp; ! 157: register char *as; ! 158: ! 159: for (cp=s; *cp++ != '\0'; ) ! 160: ; ! 161: *--cp = 's'; ! 162: cp++; ! 163: *cp++ = '\0'; ! 164: if (nclone >= NCLONE) { ! 165: fprintf(stderr, "spell: too many saved plurals\n"); ! 166: exit(1); ! 167: } ! 168: as = spacep; ! 169: if ((spacep += cp-s) >= &space[NSPACE]) { ! 170: fprintf(stderr, "spell: out of memory for plurals\n"); ! 171: exit(1); ! 172: } ! 173: strcpy(as, s); ! 174: clones[nclone++] = as; ! 175: cp[-2] = '\0'; /* Restore original word */ ! 176: } ! 177: ! 178: /* ! 179: * Put out the ascii word, onto the ! 180: * dictionary file in compressed form. ! 181: */ ! 182: putword(wp, dfp) ! 183: register char *wp; ! 184: FILE *dfp; ! 185: { ! 186: register int l; ! 187: ! 188: while ((l = compress[*wp++]) != 0) ! 189: putlet(l, dfp); ! 190: putlet(0, dfp); ! 191: } ! 192: ! 193: /* ! 194: * Put out a single compressed letter. ! 195: * 0 Marks end of word. ! 196: */ ! 197: putlet(l, fp) ! 198: register int l; ! 199: register FILE *fp; ! 200: { ! 201: static int n = 0; ! 202: static int word = 0; ! 203: ! 204: if (l != 0) { ! 205: word |= l<<(n*5); ! 206: if (++n < 3) ! 207: return; ! 208: } else ! 209: word |= EWORD; ! 210: putc(word>>8, fp); ! 211: putc(word&0377, fp); ! 212: n = word = 0; ! 213: word = 0; ! 214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.